From 9607db6e294099d53792e4e674ae88215a386ce8 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 8 Jul 2016 08:43:17 +0900 Subject: [PATCH 01/30] Bug 1283052 - Remove some of the magic around mozconfig detection. r=gps The mozconfig detection logic has bitten us on many occasions in the past. The following changes are made to tentatively improve the situation: - The API is modified such that autodetection of the mozconfig has to be a conscious decision made by the caller, and not triggered any time there is no mozconfig given, which could be a conscious decision of the opposite. - mozinfo.json now stores the actual mozconfig (or lack thereof) used during configure. --HG-- extra : rebase_source : c7a632afd414f25daf7bbe7e1a66c3736c26e039 --- build/moz.configure/init.configure | 2 ++ configure.py | 3 ++- .../mozbuild/backend/configenvironment.py | 4 +++- python/mozbuild/mozbuild/base.py | 18 +++++++++--------- python/mozbuild/mozbuild/config_status.py | 6 ++++-- python/mozbuild/mozbuild/mozconfig.py | 8 +++++--- python/mozbuild/mozbuild/mozinfo.py | 7 +++---- python/mozbuild/mozbuild/test/test_mozinfo.py | 3 ++- 8 files changed, 30 insertions(+), 21 deletions(-) diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure index 27e92c03470b..a1aaaed0aeae 100644 --- a/build/moz.configure/init.configure +++ b/build/moz.configure/init.configure @@ -115,6 +115,8 @@ def mozconfig(current_project, mozconfig, old_configure, build_env, help): return mozconfig +set_config('MOZCONFIG', depends(mozconfig)(lambda m: m['path'])) + # Hacks related to old-configure # ============================== diff --git a/configure.py b/configure.py index 9a0d532b22aa..0ba626f99d9d 100644 --- a/configure.py +++ b/configure.py @@ -50,6 +50,7 @@ def config_status(config): sanitized_config['non_global_defines'] = config['non_global_defines'] sanitized_config['topsrcdir'] = config['TOPSRCDIR'] sanitized_config['topobjdir'] = config['TOPOBJDIR'] + sanitized_config['mozconfig'] = config.get('MOZCONFIG') # Create config.status. Eventually, we'll want to just do the work it does # here, when we're able to skip configure tests/use cached results/not rely @@ -68,7 +69,7 @@ def config_status(config): json.dump(v, fh, sort_keys=True, indent=4, ensure_ascii=False) fh.write('\n') fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', " - "'non_global_defines', 'substs']") + "'non_global_defines', 'substs', 'mozconfig']") if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): fh.write(''' diff --git a/python/mozbuild/mozbuild/backend/configenvironment.py b/python/mozbuild/mozbuild/backend/configenvironment.py index 3142c272d7f2..94e322013b23 100644 --- a/python/mozbuild/mozbuild/backend/configenvironment.py +++ b/python/mozbuild/mozbuild/backend/configenvironment.py @@ -34,6 +34,7 @@ class BuildConfig(object): self.non_global_defines = [] self.substs = {} self.files = [] + self.mozconfig = None @classmethod def from_config_status(cls, path): @@ -106,7 +107,7 @@ class ConfigEnvironment(object): """ def __init__(self, topsrcdir, topobjdir, defines=None, - non_global_defines=None, substs=None, source=None): + non_global_defines=None, substs=None, source=None, mozconfig=None): if not source: source = mozpath.join(topobjdir, 'config.status') @@ -116,6 +117,7 @@ class ConfigEnvironment(object): self.substs = dict(substs or {}) self.topsrcdir = mozpath.abspath(topsrcdir) self.topobjdir = mozpath.abspath(topobjdir) + self.mozconfig = mozpath.abspath(mozconfig) if mozconfig else None self.lib_prefix = self.substs.get('LIB_PREFIX', '') if 'LIB_SUFFIX' in self.substs: self.lib_suffix = '.%s' % self.substs['LIB_SUFFIX'] diff --git a/python/mozbuild/mozbuild/base.py b/python/mozbuild/mozbuild/base.py index 947d0767ee18..21ac92f14ad7 100644 --- a/python/mozbuild/mozbuild/base.py +++ b/python/mozbuild/mozbuild/base.py @@ -73,7 +73,8 @@ class MozbuildObject(ProcessExecutionMixin): running processes, etc. This classes provides that functionality. Other modules can inherit from this class to obtain this functionality easily. """ - def __init__(self, topsrcdir, settings, log_manager, topobjdir=None): + def __init__(self, topsrcdir, settings, log_manager, topobjdir=None, + mozconfig=MozconfigLoader.AUTODETECT): """Create a new Mozbuild object instance. Instances are bound to a source directory, a ConfigSettings instance, @@ -88,7 +89,7 @@ class MozbuildObject(ProcessExecutionMixin): self._make = None self._topobjdir = mozpath.normsep(topobjdir) if topobjdir else topobjdir - self._mozconfig = None + self._mozconfig = mozconfig self._config_guess_output = None self._config_environment = None self._virtualenv_manager = None @@ -104,9 +105,7 @@ class MozbuildObject(ProcessExecutionMixin): mozconfig file. If the current working directory is inside a known objdir, we always - use the topsrcdir and mozconfig associated with that objdir. If no - mozconfig is associated with that objdir, we fall back to looking for - the mozconfig in the usual places. + use the topsrcdir and mozconfig associated with that objdir. If the current working directory is inside a known srcdir, we use that topsrcdir and look for mozconfigs using the default mechanism, which @@ -126,7 +125,7 @@ class MozbuildObject(ProcessExecutionMixin): cwd = cwd or os.getcwd() topsrcdir = None topobjdir = None - mozconfig = None + mozconfig = MozconfigLoader.AUTODETECT def load_mozinfo(path): info = json.load(open(path, 'rt')) @@ -196,7 +195,8 @@ class MozbuildObject(ProcessExecutionMixin): # If we can't resolve topobjdir, oh well. The constructor will figure # it out via config.guess. - return cls(topsrcdir, None, None, topobjdir=topobjdir) + return cls(topsrcdir, None, None, topobjdir=topobjdir, + mozconfig=mozconfig) @staticmethod def resolve_mozconfig_topobjdir(topsrcdir, mozconfig, default=None): @@ -237,9 +237,9 @@ class MozbuildObject(ProcessExecutionMixin): This a dict as returned by MozconfigLoader.read_mozconfig() """ - if self._mozconfig is None: + if self._mozconfig is MozconfigLoader.AUTODETECT: loader = MozconfigLoader(self.topsrcdir) - self._mozconfig = loader.read_mozconfig( + self._mozconfig = loader.read_mozconfig(path=self._mozconfig, moz_build_app=os.environ.get('MOZ_CURRENT_PROJECT')) return self._mozconfig diff --git a/python/mozbuild/mozbuild/config_status.py b/python/mozbuild/mozbuild/config_status.py index 4fb7b0e3c1ad..467876058b36 100644 --- a/python/mozbuild/mozbuild/config_status.py +++ b/python/mozbuild/mozbuild/config_status.py @@ -62,7 +62,8 @@ files by running: def config_status(topobjdir='.', topsrcdir='.', defines=None, - non_global_defines=None, substs=None, source=None): + non_global_defines=None, substs=None, source=None, + mozconfig=None): '''Main function, providing config.status functionality. Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS @@ -113,7 +114,8 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None, topobjdir = os.path.abspath('.') env = ConfigEnvironment(topsrcdir, topobjdir, defines=defines, - non_global_defines=non_global_defines, substs=substs, source=source) + non_global_defines=non_global_defines, substs=substs, + source=source, mozconfig=mozconfig) # mozinfo.json only needs written if configure changes and configure always # passes this environment variable. diff --git a/python/mozbuild/mozbuild/mozconfig.py b/python/mozbuild/mozbuild/mozconfig.py index b4aaf6ec5ceb..219545cab989 100644 --- a/python/mozbuild/mozbuild/mozconfig.py +++ b/python/mozbuild/mozbuild/mozconfig.py @@ -80,6 +80,8 @@ class MozconfigLoader(object): 'CC', 'CXX', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS', 'MOZ_OBJDIR', } + AUTODETECT = object() + def __init__(self, topsrcdir): self.topsrcdir = topsrcdir @@ -190,8 +192,8 @@ class MozconfigLoader(object): def read_mozconfig(self, path=None, moz_build_app=None): """Read the contents of a mozconfig into a data structure. - This takes the path to a mozconfig to load. If it is not defined, we - will try to find a mozconfig from the environment using + This takes the path to a mozconfig to load. If the given path is + AUTODETECT, will try to find a mozconfig from the environment using find_mozconfig(). mozconfig files are shell scripts. So, we can't just parse them. @@ -199,7 +201,7 @@ class MozconfigLoader(object): state from execution. Thus, the output from a mozconfig is a friendly static data structure. """ - if path is None: + if path is self.AUTODETECT: path = self.find_mozconfig() result = { diff --git a/python/mozbuild/mozbuild/mozinfo.py b/python/mozbuild/mozbuild/mozinfo.py index 61286f355c92..c6bb9b2de872 100755 --- a/python/mozbuild/mozbuild/mozinfo.py +++ b/python/mozbuild/mozbuild/mozinfo.py @@ -10,7 +10,7 @@ from __future__ import absolute_import import os import re import json -import mozbuild.mozconfig as mozconfig + def build_dict(config, env=os.environ): """ @@ -29,9 +29,8 @@ def build_dict(config, env=os.environ): d = {} d['topsrcdir'] = config.topsrcdir - the_mozconfig = mozconfig.MozconfigLoader(config.topsrcdir).find_mozconfig(env) - if the_mozconfig: - d['mozconfig'] = the_mozconfig + if config.mozconfig: + d['mozconfig'] = config.mozconfig # os o = substs["OS_TARGET"] diff --git a/python/mozbuild/mozbuild/test/test_mozinfo.py b/python/mozbuild/mozbuild/test/test_mozinfo.py index f95bf1770fdf..1a4194cb503e 100755 --- a/python/mozbuild/mozbuild/test/test_mozinfo.py +++ b/python/mozbuild/mozbuild/test/test_mozinfo.py @@ -245,7 +245,8 @@ class TestWriteMozinfo(unittest.TestCase, Base): with NamedTemporaryFile(dir=os.path.normpath(c.topsrcdir)) as mozconfig: mozconfig.write('unused contents') mozconfig.flush() - write_mozinfo(self.f, c, {'MOZCONFIG': mozconfig.name}) + c.mozconfig = mozconfig.name + write_mozinfo(self.f, c) with open(self.f) as f: d = json.load(f) self.assertEqual('win', d['os']) From 8df5750b1c682b090c4193bbea3a8242c2f48204 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Fri, 8 Jul 2016 08:34:14 +0800 Subject: [PATCH 02/30] Bug 1285248. Part 1 - the value of aSeekJob.mTarget.IsVideoOnly() is wrong because the members are reset in the move constructor. r=gerald mDoneAudioSeeking should be true for video-only seek. Otherwise we might request audio while a pending request is already in progress and hit the assertion. MozReview-Commit-ID: IeVjoEChLAR --HG-- extra : rebase_source : 88ab010934579d2b9517a77e2080ada6159d2968 --- dom/media/AccurateSeekTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/media/AccurateSeekTask.cpp b/dom/media/AccurateSeekTask.cpp index 94a3f471feae..a1bb244e7f49 100644 --- a/dom/media/AccurateSeekTask.cpp +++ b/dom/media/AccurateSeekTask.cpp @@ -45,7 +45,7 @@ AccurateSeekTask::AccurateSeekTask(const void* aDecoderID, : SeekTask(aDecoderID, aThread, aReader, Move(aSeekJob)) , mCurrentTimeBeforeSeek(media::TimeUnit::FromMicroseconds(aCurrentMediaTime)) , mAudioRate(aInfo.mAudio.mRate) - , mDoneAudioSeeking(!aInfo.HasAudio() || aSeekJob.mTarget.IsVideoOnly()) + , mDoneAudioSeeking(!aInfo.HasAudio() || mSeekJob.mTarget.IsVideoOnly()) , mDoneVideoSeeking(!aInfo.HasVideo()) { AssertOwnerThread(); From 297c1dbf96299d60ab22f018852a81ca969428c2 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Fri, 8 Jul 2016 11:52:40 +0800 Subject: [PATCH 03/30] Bug 1285248. Part 2 - fix logic for video-only seek. r=gerald MozReview-Commit-ID: lopt6zxC5f --HG-- extra : rebase_source : 880663980f5b813caeddfd3cbc8d77907ee393f5 --- dom/media/AccurateSeekTask.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/dom/media/AccurateSeekTask.cpp b/dom/media/AccurateSeekTask.cpp index a1bb244e7f49..92cdac05d2f7 100644 --- a/dom/media/AccurateSeekTask.cpp +++ b/dom/media/AccurateSeekTask.cpp @@ -309,6 +309,14 @@ AccurateSeekTask::OnAudioDecoded(MediaData* aAudioSample) SAMPLE_LOG("OnAudioDecoded [%lld,%lld] disc=%d", audio->mTime, audio->GetEndTime(), audio->mDiscontinuity); + // Video-only seek doesn't reset audio decoder. There might be pending audio + // requests when AccurateSeekTask::Seek() begins. We will just store the data + // without checking |mDiscontinuity| or calling DropAudioUpToSeekTarget(). + if (mSeekJob.mTarget.IsVideoOnly()) { + mSeekedAudioData = audio.forget(); + return; + } + if (mFirstAudioSample) { mFirstAudioSample = false; MOZ_ASSERT(audio->mDiscontinuity); @@ -341,6 +349,11 @@ AccurateSeekTask::OnNotDecoded(MediaData::Type aType, SAMPLE_LOG("OnNotDecoded type=%d reason=%u", aType, aReason); + // Ignore pending requests from video-only seek. + if (aType == MediaData::AUDIO_DATA && mSeekJob.mTarget.IsVideoOnly()) { + return; + } + if (aReason == MediaDecoderReader::DECODE_ERROR) { // If this is a decode error, delegate to the generic error path. RejectIfExist(__func__); @@ -446,6 +459,10 @@ AccurateSeekTask::SetCallbacks() mAudioWaitCallback = mReader->AudioWaitCallback().Connect( OwnerThread(), [this] (WaitCallbackData aData) { + // Ignore pending requests from video-only seek. + if (mSeekJob.mTarget.IsVideoOnly()) { + return; + } if (aData.is()) { RequestAudioData(); } From 7cc7e32a9b0f48d54225b9305018253c7626852f Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 8 Jul 2016 13:01:31 +0900 Subject: [PATCH 04/30] Bug 1278136 - Part 0: Clean up frame->StyleDisplay()->BackfaceIsHidden() usage. r=mattwoodrow We already have a wrapper named nsIFrame::BackfaceIsHidden(). MozReview-Commit-ID: 5L49W6wtXs1 --HG-- extra : rebase_source : d3be8d028453e63fb2d3d96b5956262d352385ef --- dom/animation/KeyframeEffect.cpp | 2 +- layout/base/nsDisplayList.cpp | 7 +++---- layout/base/nsDisplayList.h | 2 +- layout/generic/nsFrame.cpp | 4 ++-- layout/generic/nsIFrame.h | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index bc72632dea03..62b05074b275 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -1405,7 +1405,7 @@ KeyframeEffectReadOnly::CanAnimateTransformOnCompositor( // what we need for animating backface-visibility correctly if we // remove the above test for Extend3DContext(); that would require // looking at backface-visibility on descendants as well. See bug 1186204. - if (aFrame->StyleDisplay()->BackfaceIsHidden()) { + if (aFrame->BackfaceIsHidden()) { aPerformanceWarning = AnimationPerformanceWarning::Type::TransformBackfaceVisibilityHidden; return false; diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index badc1cdbab6a..ebf3f5022202 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -5482,7 +5482,7 @@ nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame, { NS_PRECONDITION(aFrame, "Can't get delta for a null frame!"); NS_PRECONDITION(aFrame->IsTransformed() || - aFrame->StyleDisplay()->BackfaceIsHidden() || + aFrame->BackfaceIsHidden() || aFrame->Combines3DTransformWithAncestors(), "Shouldn't get a delta for an untransformed frame!"); @@ -5555,7 +5555,7 @@ nsDisplayTransform::ComputePerspectiveMatrix(const nsIFrame* aFrame, { NS_PRECONDITION(aFrame, "Can't get delta for a null frame!"); NS_PRECONDITION(aFrame->IsTransformed() || - aFrame->StyleDisplay()->BackfaceIsHidden() || + aFrame->BackfaceIsHidden() || aFrame->Combines3DTransformWithAncestors(), "Shouldn't get a delta for an untransformed frame!"); NS_PRECONDITION(aOutMatrix.IsIdentity(), "Must have a blank output matrix"); @@ -5889,8 +5889,7 @@ static bool IsFrameVisible(nsIFrame* aFrame, const Matrix4x4& aMatrix) if (aMatrix.IsSingular()) { return false; } - if (aFrame->StyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN && - aMatrix.IsBackfaceVisible()) { + if (aFrame->BackfaceIsHidden() && aMatrix.IsBackfaceVisible()) { return false; } return true; diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 79af1c4060bb..a9d4d57b14cb 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1854,7 +1854,7 @@ public: const DisplayItemScrollClip* ScrollClip() const { return mScrollClip; } bool BackfaceIsHidden() { - return mFrame->StyleDisplay()->BackfaceIsHidden(); + return mFrame->BackfaceIsHidden(); } protected: diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 6e2d70055a39..352e4bdd65bf 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1206,13 +1206,13 @@ nsIFrame::Combines3DTransformWithAncestors() const if (!GetParent() || !GetParent()->Extend3DContext()) { return false; } - return StyleDisplay()->HasTransform(this) || StyleDisplay()->BackfaceIsHidden(); + return StyleDisplay()->HasTransform(this) || BackfaceIsHidden(); } bool nsIFrame::In3DContextAndBackfaceIsHidden() const { - return Combines3DTransformWithAncestors() && StyleDisplay()->BackfaceIsHidden(); + return Combines3DTransformWithAncestors() && BackfaceIsHidden(); } bool diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index cf8862675c67..9f54d4b9a519 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -3260,7 +3260,7 @@ public: virtual mozilla::dom::Element* GetPseudoElement(mozilla::CSSPseudoElementType aType); - bool BackfaceIsHidden() { + bool BackfaceIsHidden() const { return StyleDisplay()->BackfaceIsHidden(); } From e7a860ecf8736423ff84e81bec1edb987318beb2 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 8 Jul 2016 13:01:31 +0900 Subject: [PATCH 05/30] Bug 1278136 - Part 1: Add nsLayoutUtils::HasRelevantAnimationOfProperty. r=birtles We want to know that an nsIFrame has a transform or opacity animations regardless of its state, e.g., running on the main-thead, paused or finished but in fill:forwards state, to create a stacking context for the animation. MozReview-Commit-ID: mNYsd5RO3u --HG-- extra : rebase_source : 19f88d9f77f3c329f36a6505c6335bae64050a22 --- layout/base/nsLayoutUtils.cpp | 32 +++++++++++++++++++++----------- layout/base/nsLayoutUtils.h | 8 ++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 1455815a6770..cfbaffa1ceec 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -454,7 +454,7 @@ BackgroundClipTextEnabledPrefChangeCallback(const char* aPrefName, template static bool -HasMatchingCurrentAnimations(const nsIFrame* aFrame, TestType&& aTest) +HasMatchingAnimations(const nsIFrame* aFrame, TestType&& aTest) { EffectSet* effects = EffectSet::GetEffectSet(aFrame); if (!effects) { @@ -462,10 +462,6 @@ HasMatchingCurrentAnimations(const nsIFrame* aFrame, TestType&& aTest) } for (KeyframeEffectReadOnly* effect : *effects) { - if (!effect->IsCurrent()) { - continue; - } - if (aTest(*effect)) { return true; } @@ -478,10 +474,10 @@ bool nsLayoutUtils::HasCurrentAnimationOfProperty(const nsIFrame* aFrame, nsCSSProperty aProperty) { - return HasMatchingCurrentAnimations(aFrame, + return HasMatchingAnimations(aFrame, [&aProperty](KeyframeEffectReadOnly& aEffect) { - return aEffect.HasAnimationOfProperty(aProperty); + return aEffect.IsCurrent() && aEffect.HasAnimationOfProperty(aProperty); } ); } @@ -489,12 +485,12 @@ nsLayoutUtils::HasCurrentAnimationOfProperty(const nsIFrame* aFrame, bool nsLayoutUtils::HasCurrentTransitions(const nsIFrame* aFrame) { - return HasMatchingCurrentAnimations(aFrame, + return HasMatchingAnimations(aFrame, [](KeyframeEffectReadOnly& aEffect) { // Since |aEffect| is current, it must have an associated Animation // so we don't need to null-check the result of GetAnimation(). - return aEffect.GetAnimation()->AsCSSTransition(); + return aEffect.IsCurrent() && aEffect.GetAnimation()->AsCSSTransition(); } ); } @@ -504,10 +500,24 @@ nsLayoutUtils::HasCurrentAnimationsForProperties(const nsIFrame* aFrame, const nsCSSProperty* aProperties, size_t aPropertyCount) { - return HasMatchingCurrentAnimations(aFrame, + return HasMatchingAnimations(aFrame, [&aProperties, &aPropertyCount](KeyframeEffectReadOnly& aEffect) { - return aEffect.HasAnimationOfProperties(aProperties, aPropertyCount); + return aEffect.IsCurrent() && + aEffect.HasAnimationOfProperties(aProperties, aPropertyCount); + } + ); +} + +bool +nsLayoutUtils::HasRelevantAnimationOfProperty(const nsIFrame* aFrame, + nsCSSProperty aProperty) +{ + return HasMatchingAnimations(aFrame, + [&aProperty](KeyframeEffectReadOnly& aEffect) + { + return (aEffect.IsInEffect() || aEffect.IsCurrent()) && + aEffect.HasAnimationOfProperty(aProperty); } ); } diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 17245fdf4ecc..009dd07d984b 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -2253,6 +2253,14 @@ public: const nsCSSProperty* aProperties, size_t aPropertyCount); + /** + * Returns true if the frame has current or in-effect (i.e. in before phase, + * running or filling) animations or transitions for the + * property. + */ + static bool HasRelevantAnimationOfProperty(const nsIFrame* aFrame, + nsCSSProperty aProperty); + /** * Checks if off-main-thread animations are enabled. */ From d6944d301d9212038065c146f254eeec11fa6d02 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 27 Jun 2016 12:52:53 +0900 Subject: [PATCH 06/30] Bug 1278136 - Part 2: We should not check whether the animation can run on the compositor or it's paused when determining if we should create a stacking context. r=birtles,mattwoodrow We should create a stacking context for any transform or opacity animations that are either "in effect" (what we currently do) OR "current", i.e. scheduled to run or running. *BUT* for now, we don't create any stacking context in before phase without fill:backwards or fill:both because the property never wins in cascade until the animation gets "in effect". This restriction will be removed in a subsequent patch in this bug after landing bug 1279403. MozReview-Commit-ID: 8RyLJNPtoKI --HG-- rename : layout/reftests/css-animations/stacking-context-transform-animation-ref.html => layout/reftests/css-animations/stacking-context-animation-ref.html extra : rebase_source : 0d9c8d9e03ca0d400e9b376b9416fbabffd10034 --- layout/generic/nsFrame.cpp | 8 +++--- layout/generic/nsIFrame.h | 7 ++--- .../no-stacking-context-animation-ref.html | 20 ++++++++++++++ layout/reftests/css-animations/reftest.list | 22 +++++++++++++--- ...ml => stacking-context-animation-ref.html} | 0 .../stacking-context-lose-opacity-1.html | 24 +++++++++++++++++ .../stacking-context-lose-transform-none.html | 24 +++++++++++++++++ .../stacking-context-opacity-1-animation.html | 24 +++++++++++++++++ .../stacking-context-opacity-1-in-delay.html | 23 ++++++++++++++++ ...context-opacity-1-with-fill-backwards.html | 24 +++++++++++++++++ ...-context-opacity-1-with-fill-forwards.html | 24 +++++++++++++++++ .../stacking-context-paused-on-opacity-1.html | 24 +++++++++++++++++ ...king-context-paused-on-transform-none.html | 24 +++++++++++++++++ ...ne-animation-with-backface-visibility.html | 26 +++++++++++++++++++ ...king-context-transform-none-animation.html | 5 +++- ...cking-context-transform-none-in-delay.html | 23 ++++++++++++++++ ...xt-transform-none-with-fill-backwards.html | 24 +++++++++++++++++ ...ext-transform-none-with-fill-forwards.html | 24 +++++++++++++++++ 18 files changed, 339 insertions(+), 11 deletions(-) create mode 100644 layout/reftests/css-animations/no-stacking-context-animation-ref.html rename layout/reftests/css-animations/{stacking-context-transform-animation-ref.html => stacking-context-animation-ref.html} (100%) create mode 100644 layout/reftests/css-animations/stacking-context-lose-opacity-1.html create mode 100644 layout/reftests/css-animations/stacking-context-lose-transform-none.html create mode 100644 layout/reftests/css-animations/stacking-context-opacity-1-animation.html create mode 100644 layout/reftests/css-animations/stacking-context-opacity-1-in-delay.html create mode 100644 layout/reftests/css-animations/stacking-context-opacity-1-with-fill-backwards.html create mode 100644 layout/reftests/css-animations/stacking-context-opacity-1-with-fill-forwards.html create mode 100644 layout/reftests/css-animations/stacking-context-paused-on-opacity-1.html create mode 100644 layout/reftests/css-animations/stacking-context-paused-on-transform-none.html create mode 100644 layout/reftests/css-animations/stacking-context-transform-none-animation-with-backface-visibility.html create mode 100644 layout/reftests/css-animations/stacking-context-transform-none-in-delay.html create mode 100644 layout/reftests/css-animations/stacking-context-transform-none-with-fill-backwards.html create mode 100644 layout/reftests/css-animations/stacking-context-transform-none-with-fill-forwards.html diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 352e4bdd65bf..c28fba81cc5b 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -559,8 +559,8 @@ nsFrame::Init(nsIContent* aContent, } const nsStyleDisplay *disp = StyleDisplay(); if (disp->HasTransform(this) || - nsLayoutUtils::HasCurrentAnimationOfProperty(this, - eCSSProperty_transform)) { + nsLayoutUtils::HasRelevantAnimationOfProperty(this, + eCSSProperty_transform)) { // The frame gets reconstructed if we toggle the -moz-transform // property, so we can set this bit here and then ignore it. mState |= NS_FRAME_MAY_BE_TRANSFORMED; @@ -1150,7 +1150,7 @@ nsIFrame::IsTransformed() const (StyleDisplay()->HasTransform(this) || IsSVGTransformed() || (mContent && - EffectCompositor::HasAnimationsForCompositor( + nsLayoutUtils::HasRelevantAnimationOfProperty( this, eCSSProperty_transform) && IsFrameOfType(eSupportsCSSTransforms) && mContent->GetPrimaryFrame() == this))); @@ -1163,7 +1163,7 @@ nsIFrame::HasOpacityInternal(float aThreshold) const return StyleEffects()->mOpacity < aThreshold || (StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) || (mContent && - EffectCompositor::HasAnimationsForCompositor( + nsLayoutUtils::HasRelevantAnimationOfProperty( this, eCSSProperty_opacity) && mContent->GetPrimaryFrame() == this); } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 9f54d4b9a519..aae87662ae3b 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1361,13 +1361,14 @@ public: /** * Returns true if this frame is transformed (e.g. has CSS or SVG transforms) * or if its parent is an SVG frame that has children-only transforms (e.g. - * an SVG viewBox attribute) or if its transform-style is preserve-3d. + * an SVG viewBox attribute) or if its transform-style is preserve-3d or + * the frame has transform animations. */ bool IsTransformed() const; /** - * Returns true if the frame is translucent for the purposes of creating a - * stacking context. + * Returns true if the frame is translucent or the frame has opacity + * animations for the purposes of creating a stacking context. */ bool HasOpacity() const { diff --git a/layout/reftests/css-animations/no-stacking-context-animation-ref.html b/layout/reftests/css-animations/no-stacking-context-animation-ref.html new file mode 100644 index 000000000000..efc029d03e1e --- /dev/null +++ b/layout/reftests/css-animations/no-stacking-context-animation-ref.html @@ -0,0 +1,20 @@ + + +Reference of testcases which don't create a stacking context for bug 1278136 + + + +
diff --git a/layout/reftests/css-animations/reftest.list b/layout/reftests/css-animations/reftest.list index b98b7e6a36b8..954d360a2a00 100644 --- a/layout/reftests/css-animations/reftest.list +++ b/layout/reftests/css-animations/reftest.list @@ -8,6 +8,22 @@ fails != print-no-animations.html print-no-animations-notref.html # reftest harn == in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element-ref.html == partially-out-of-view-animation.html partially-out-of-view-animation-ref.html == animate-display-table-opacity.html animate-display-table-opacity-ref.html -== stacking-context-transform-none-animation.html stacking-context-transform-animation-ref.html -== stacking-context-transform-none-animation-on-svg.html stacking-context-transform-animation-ref.html -== stacking-context-transform-none-animation-with-preserve-3d.html stacking-context-transform-animation-ref.html +# We need to run 100% opacity test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor +test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-opacity-1-animation.html stacking-context-animation-ref.html +# We need to run transform:none test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor +test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-transform-none-animation.html stacking-context-animation-ref.html +== stacking-context-lose-opacity-1.html no-stacking-context-animation-ref.html +== stacking-context-lose-transform-none.html no-stacking-context-animation-ref.html +== stacking-context-opacity-1-animation.html stacking-context-animation-ref.html +== stacking-context-opacity-1-with-fill-backwards.html stacking-context-animation-ref.html +== stacking-context-opacity-1-with-fill-forwards.html stacking-context-animation-ref.html +== stacking-context-paused-on-opacity-1.html stacking-context-animation-ref.html +== stacking-context-paused-on-transform-none.html stacking-context-animation-ref.html +== stacking-context-transform-none-animation.html stacking-context-animation-ref.html +== stacking-context-transform-none-animation-on-svg.html stacking-context-animation-ref.html +== stacking-context-transform-none-animation-with-backface-visibility.html stacking-context-animation-ref.html +== stacking-context-transform-none-animation-with-preserve-3d.html stacking-context-animation-ref.html +== stacking-context-transform-none-with-fill-backwards.html stacking-context-animation-ref.html +== stacking-context-transform-none-with-fill-forwards.html stacking-context-animation-ref.html +fails == stacking-context-opacity-1-in-delay.html stacking-context-animation-ref.html # bug 1278136 and bug 1279403 +fails == stacking-context-transform-none-in-delay.html stacking-context-animation-ref.html # bug 1278136 and bug 1279403 diff --git a/layout/reftests/css-animations/stacking-context-transform-animation-ref.html b/layout/reftests/css-animations/stacking-context-animation-ref.html similarity index 100% rename from layout/reftests/css-animations/stacking-context-transform-animation-ref.html rename to layout/reftests/css-animations/stacking-context-animation-ref.html diff --git a/layout/reftests/css-animations/stacking-context-lose-opacity-1.html b/layout/reftests/css-animations/stacking-context-lose-opacity-1.html new file mode 100644 index 000000000000..a3b72a6b873e --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-lose-opacity-1.html @@ -0,0 +1,24 @@ + + +Opacity animation losing in cascade doesn't create stacking context + + + +
diff --git a/layout/reftests/css-animations/stacking-context-lose-transform-none.html b/layout/reftests/css-animations/stacking-context-lose-transform-none.html new file mode 100644 index 000000000000..b5effa3c849b --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-lose-transform-none.html @@ -0,0 +1,24 @@ + + +Transform animation losing in cascade doesn't create stacking context + + + +
diff --git a/layout/reftests/css-animations/stacking-context-opacity-1-animation.html b/layout/reftests/css-animations/stacking-context-opacity-1-animation.html new file mode 100644 index 000000000000..3a4fe7bf4589 --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-opacity-1-animation.html @@ -0,0 +1,24 @@ + + +Opacity animation creates a stacking context even if it has only 100% opacity +in its keyframes + + + +
diff --git a/layout/reftests/css-animations/stacking-context-opacity-1-in-delay.html b/layout/reftests/css-animations/stacking-context-opacity-1-in-delay.html new file mode 100644 index 000000000000..4e441397c807 --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-opacity-1-in-delay.html @@ -0,0 +1,23 @@ + + +Opacity animation creates stacking context in delay phase + + + +
diff --git a/layout/reftests/css-animations/stacking-context-opacity-1-with-fill-backwards.html b/layout/reftests/css-animations/stacking-context-opacity-1-with-fill-backwards.html new file mode 100644 index 000000000000..484da2979d34 --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-opacity-1-with-fill-backwards.html @@ -0,0 +1,24 @@ + + +Opacity animation does not destroy stacking context when the animation +has finished but has fill:backwards + + + +
diff --git a/layout/reftests/css-animations/stacking-context-opacity-1-with-fill-forwards.html b/layout/reftests/css-animations/stacking-context-opacity-1-with-fill-forwards.html new file mode 100644 index 000000000000..5fdda4f9dd89 --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-opacity-1-with-fill-forwards.html @@ -0,0 +1,24 @@ + + +Opacity animation does not destroy stacking context when the animation +has finished but has fill:forwards + + + +
diff --git a/layout/reftests/css-animations/stacking-context-paused-on-opacity-1.html b/layout/reftests/css-animations/stacking-context-paused-on-opacity-1.html new file mode 100644 index 000000000000..b27985a6ca60 --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-paused-on-opacity-1.html @@ -0,0 +1,24 @@ + + +Transform animation creates a stacking context even though it's paused on +a 100% opacity keyframe + + + +
diff --git a/layout/reftests/css-animations/stacking-context-paused-on-transform-none.html b/layout/reftests/css-animations/stacking-context-paused-on-transform-none.html new file mode 100644 index 000000000000..cd0290849899 --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-paused-on-transform-none.html @@ -0,0 +1,24 @@ + + +Transform animation creates a stacking context even though it's paused on +a 'transform:none' keyframe + + + +
diff --git a/layout/reftests/css-animations/stacking-context-transform-none-animation-with-backface-visibility.html b/layout/reftests/css-animations/stacking-context-transform-none-animation-with-backface-visibility.html new file mode 100644 index 000000000000..c96be7d4cc3f --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-transform-none-animation-with-backface-visibility.html @@ -0,0 +1,26 @@ + + +Transform animation creates a stacking context even though it has only +'transform:none' keyframes and with a style which prevents performning +the animation on the compositor. + + + +
diff --git a/layout/reftests/css-animations/stacking-context-transform-none-animation.html b/layout/reftests/css-animations/stacking-context-transform-none-animation.html index 13b360466131..53213b452d32 100644 --- a/layout/reftests/css-animations/stacking-context-transform-none-animation.html +++ b/layout/reftests/css-animations/stacking-context-transform-none-animation.html @@ -1,5 +1,8 @@ -Transform animation creates a stacking context even though it has only 'transform:none' keyframes + +Transform animation creates a stacking context even though it has only +'transform:none' keyframes + + +
diff --git a/layout/reftests/css-animations/stacking-context-transform-none-with-fill-backwards.html b/layout/reftests/css-animations/stacking-context-transform-none-with-fill-backwards.html new file mode 100644 index 000000000000..d0515c294552 --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-transform-none-with-fill-backwards.html @@ -0,0 +1,24 @@ + + +Transform animation does not destroy stacking context when the animation +has finished but has fill:backwards + + + +
diff --git a/layout/reftests/css-animations/stacking-context-transform-none-with-fill-forwards.html b/layout/reftests/css-animations/stacking-context-transform-none-with-fill-forwards.html new file mode 100644 index 000000000000..2d9610232c7c --- /dev/null +++ b/layout/reftests/css-animations/stacking-context-transform-none-with-fill-forwards.html @@ -0,0 +1,24 @@ + + +Transform animation does not destroy stacking context when the animation +has finished but has fill:forwards + + + +
From e5daa34c2a8a80226152ea17971e566714435b09 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 8 Jul 2016 13:02:44 +0900 Subject: [PATCH 07/30] Bug 1278136 - Part 3: Test that animations with fill:backwards consumes the main-thread while it's in delay phase. r=birtles MozReview-Commit-ID: 3dDGPfgOvJl --HG-- extra : rebase_source : 2b3edce74e3a1b60598752c3a1727d77e55b7c8e --- .../chrome/test_running_on_compositor.html | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/dom/animation/test/chrome/test_running_on_compositor.html b/dom/animation/test/chrome/test_running_on_compositor.html index 38790c549357..d2b07546c76e 100644 --- a/dom/animation/test/chrome/test_running_on_compositor.html +++ b/dom/animation/test/chrome/test_running_on_compositor.html @@ -447,6 +447,28 @@ promise_test(function(t) { }); }, 'animation is removed from the compositor when setting null target'); +promise_test(function(t) { + var div = addDiv(t); + var animation = div.animate({ opacity: [ 0, 1 ] }, + { duration: 100 * MS_PER_SEC, + delay: 100 * MS_PER_SEC, + fill: 'backwards' }); + + return animation.ready.then(function() { + // Will be fixed in bug 1223658. + assert_equals(animation.isRunningOnCompositor, false, + 'Animation with fill:backwards in delay phase reports ' + + 'that it is NOT running on the compositor'); + + animation.currentTime = 100 * MS_PER_SEC; + return waitForFrame(); + }).then(function() { + assert_equals(animation.isRunningOnCompositor, omtaEnabled, + 'Animation with fill:backwards in delay phase reports ' + + 'that it is running on the compositor after delay phase'); + }); +}, 'animation with fill:backwards in delay phase is running on the ' + + ' main-thread while it is in delay phase'); From d96ced9ff8f2e256b9edd8df176b27cc6b6bf92b Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Thu, 7 Jul 2016 16:50:14 +0100 Subject: [PATCH 08/30] Bug 1206842 - check we have a failedChannel and securityInfo before serializing, extract to helper, original patch by YF (Yang), r=fkiefer MozReview-Commit-ID: 9isfRHExX4H --HG-- extra : rebase_source : b3b0959f1e59edaddb26a5982c8a15cf174d0a9a --- browser/base/content/content.js | 41 ++++++++++++++------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/browser/base/content/content.js b/browser/base/content/content.js index f2168246b0de..3dee1f631431 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -276,6 +276,20 @@ const PREF_SSL_IMPACT = PREF_SSL_IMPACT_ROOTS.reduce((prefs, root) => { }, []); +function getSerializedSecurityInfo(docShell) { + let serhelper = Cc["@mozilla.org/network/serialization-helper;1"] + .getService(Ci.nsISerializationHelper); + + let securityInfo = docShell.failedChannel && docShell.failedChannel.securityInfo; + if (!securityInfo) { + return ""; + } + securityInfo.QueryInterface(Ci.nsITransportSecurityInfo) + .QueryInterface(Ci.nsISerializable); + + return serhelper.serializeToString(securityInfo); +} + var AboutNetAndCertErrorListener = { init: function(chromeGlobal) { addMessageListener("CertErrorDetails", this); @@ -417,19 +431,10 @@ var AboutNetAndCertErrorListener = { // if we're enabling reports, send a report for this failure if (evt.detail) { - let serhelper = Cc["@mozilla.org/network/serialization-helper;1"] - .getService(Ci.nsISerializationHelper); - - let serializable = docShell.failedChannel.securityInfo - .QueryInterface(Ci.nsITransportSecurityInfo) - .QueryInterface(Ci.nsISerializable); - - let serializedSecurityInfo = serhelper.serializeToString(serializable); - let {host, port} = content.document.mozDocumentURIIfNotForErrorPages; sendAsyncMessage("Browser:SendSSLErrorReport", { uri: { host, port }, - securityInfo: serializedSecurityInfo + securityInfo: getSerializedSecurityInfo(docShell), }); } @@ -542,26 +547,14 @@ var ClickEventHandler = { }, onCertError: function (targetElement, ownerDoc) { - let docshell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor) + let docShell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShell); - let serhelper = Cc["@mozilla.org/network/serialization-helper;1"] - .getService(Ci.nsISerializationHelper); - let serializedSecurityInfo = ""; - - try { - let serializable = docShell.failedChannel.securityInfo - .QueryInterface(Ci.nsITransportSecurityInfo) - .QueryInterface(Ci.nsISerializable); - - serializedSecurityInfo = serhelper.serializeToString(serializable); - } catch (e) { } - sendAsyncMessage("Browser:CertExceptionError", { location: ownerDoc.location.href, elementId: targetElement.getAttribute("id"), isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView), - securityInfoAsString: serializedSecurityInfo + securityInfoAsString: getSerializedSecurityInfo(docShell), }); }, From 2302a9db3b119a232256b4861c048d0b37bfe8c5 Mon Sep 17 00:00:00 2001 From: David Burns Date: Thu, 7 Jul 2016 23:06:17 +0100 Subject: [PATCH 09/30] Bug 1285240: Trim leading and trailing space when finding elements by link text r=ato This gives up parity with the WebDriver project and brings us in line with the current specification http://w3c.github.io/webdriver/webdriver-spec.html#dfn-link-text MozReview-Commit-ID: 9OD6B2pKTfx --HG-- extra : rebase_source : 075fe800d1a82593ebb55987a2eccb2d318e0c5f --- testing/marionette/element.js | 4 ++-- .../tests/unit/test_element_retrieval.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/testing/marionette/element.js b/testing/marionette/element.js index 8cb8becc1de2..369da01d789e 100644 --- a/testing/marionette/element.js +++ b/testing/marionette/element.js @@ -351,7 +351,7 @@ element.findByXPathAll = function(root, startNode, expr) { * Sequence of link elements which text is |s|. */ element.findByLinkText = function(node, s) { - return filterLinks(node, link => link.text === s); + return filterLinks(node, link => link.text.trim() === s); }; /** @@ -438,7 +438,7 @@ function findElement(using, value, rootNode, startNode) { case element.Strategy.LinkText: for (let link of startNode.getElementsByTagName("a")) { - if (link.text === value) { + if (link.text.trim() === value) { return link; } } diff --git a/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py b/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py index d8557ace8454..42d3c0c1f16a 100644 --- a/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py +++ b/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py @@ -40,6 +40,7 @@ class_xhtml = inline('

', doctype="xhtml") name_html = inline("

", doctype="html") name_xhtml = inline('

', doctype="xhtml") link_html = inline("

foo bar", doctype="html") +link_html_with_trailing_space = inline("

a link with a trailing space ") link_xhtml = inline('

foo bar

', doctype="xhtml") @@ -103,6 +104,13 @@ class TestFindElementHTML(MarionetteTestCase): self.assertIsInstance(found, HTMLElement) self.assertEqual(el, found) + def test_link_text_with_trailing_space(self): + self.marionette.navigate(link_html_with_trailing_space) + el = self.marionette.execute_script("return document.querySelector('a')") + found = self.marionette.find_element(By.LINK_TEXT, "a link with a trailing space") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + def test_partial_link_text(self): self.marionette.navigate(link_html) el = self.marionette.execute_script("return document.querySelector('a')") @@ -343,6 +351,14 @@ class TestFindElementsHTML(MarionetteTestCase): self.assertItemsIsInstance(found, HTMLElement) self.assertSequenceEqual(els, found) + def test_link_text_with_trailing_space(self): + self.marionette.navigate(link_html_with_trailing_space) + els = self.marionette.execute_script("return document.querySelectorAll('a')") + found = self.marionette.find_elements(By.LINK_TEXT, "a link with a trailing space") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_partial_link_text(self): self.marionette.navigate(link_html) els = self.marionette.execute_script("return document.querySelectorAll('a')") From 011ccb6f4b7e7ad02767a2045d9bf4ad56febf79 Mon Sep 17 00:00:00 2001 From: David Burns Date: Thu, 7 Jul 2016 22:20:32 +0100 Subject: [PATCH 10/30] Bug 1285240: Update tests to prevent redefinitions r=ato The tests had the same name which caused a redefinition meaning only one of the tests was run. MozReview-Commit-ID: LuflhcD4wKl --HG-- extra : rebase_source : 09b233c42cd0dba4437f51dc63986c119711cd70 --- .../harness/marionette/tests/unit/test_element_retrieval.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py b/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py index 42d3c0c1f16a..d1065b16cb76 100644 --- a/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py +++ b/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py @@ -147,7 +147,7 @@ class TestFindElementHTML(MarionetteTestCase): self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese") self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese") - def test_not_found(self): + def test_not_found_from_element(self): self.marionette.set_search_timeout(0) self.marionette.navigate(id_html) el = self.marionette.find_element(By.ID, "foo") @@ -160,7 +160,7 @@ class TestFindElementHTML(MarionetteTestCase): self.assertRaises(NoSuchElementException, el.find_element, By.TAG_NAME, "cheese") self.assertRaises(NoSuchElementException, el.find_element, By.XPATH, "cheese") - def test_not_found_implicit_wait(self): + def test_not_found_implicit_wait_from_element(self): self.marionette.set_search_timeout(50) self.marionette.navigate(id_html) el = self.marionette.find_element(By.ID, "foo") From ee77e301ddcf52eea24e902db2bc8ed8967de083 Mon Sep 17 00:00:00 2001 From: Alexandre Lissy Date: Wed, 16 Mar 2016 17:11:12 +0100 Subject: [PATCH 11/30] Bug 1285170 - Remove app:// protocol r=valentin MozReview-Commit-ID: 4cnLrqqyP35 --HG-- extra : rebase_source : 424b63df547308033fc960632c5ef5939e3d8d85 --- addon-sdk/source/test/test-url.js | 2 +- .../test/unit/test_frame-utils-01.js | 2 - devtools/shared/apps/moz.build | 2 - devtools/shared/apps/tests/unit/.eslintrc | 4 - .../apps/tests/unit/data/app-engineering.zip | Bin 895 -> 0 bytes devtools/shared/apps/tests/unit/data/app.zip | Bin 1139 -> 0 bytes devtools/shared/apps/tests/unit/head_apps.js | 123 ----- devtools/shared/apps/tests/unit/tail_apps.js | 6 - .../apps/tests/unit/test_webappsActor.js | 311 ----------- devtools/shared/apps/tests/unit/xpcshell.ini | 12 - .../unit/defaultStorageUpgrade_profile.zip | Bin 78093 -> 71933 bytes .../test/unit/idbSubdirUpgrade1_profile.zip | Bin 8066 -> 5530 bytes .../test/unit/idbSubdirUpgrade2_profile.zip | Bin 8398 -> 5809 bytes .../test/unit/schema23upgrade_profile.zip | Bin 8309 -> 5735 bytes .../unit/storagePersistentUpgrade_profile.zip | Bin 9480 -> 6469 bytes .../test/unit/test_defaultStorageUpgrade.js | 8 - .../test/unit/test_idbSubdirUpgrade.js | 4 - .../test/unit/test_schema23upgrade.js | 4 - .../unit/test_storagePersistentUpgrade.js | 4 - netwerk/build/moz.build | 1 - netwerk/build/nsNetCID.h | 12 - netwerk/build/nsNetModule.cpp | 4 - netwerk/ipc/NeckoParent.cpp | 107 ---- netwerk/ipc/NeckoParent.h | 2 - netwerk/protocol/app/AppProtocolHandler.cpp | 513 ------------------ netwerk/protocol/app/AppProtocolHandler.h | 35 -- netwerk/protocol/app/moz.build | 16 - old-configure.in | 2 +- 28 files changed, 2 insertions(+), 1172 deletions(-) delete mode 100644 devtools/shared/apps/tests/unit/.eslintrc delete mode 100644 devtools/shared/apps/tests/unit/data/app-engineering.zip delete mode 100644 devtools/shared/apps/tests/unit/data/app.zip delete mode 100644 devtools/shared/apps/tests/unit/head_apps.js delete mode 100644 devtools/shared/apps/tests/unit/tail_apps.js delete mode 100644 devtools/shared/apps/tests/unit/test_webappsActor.js delete mode 100644 devtools/shared/apps/tests/unit/xpcshell.ini delete mode 100644 netwerk/protocol/app/AppProtocolHandler.cpp delete mode 100644 netwerk/protocol/app/AppProtocolHandler.h delete mode 100644 netwerk/protocol/app/moz.build diff --git a/addon-sdk/source/test/test-url.js b/addon-sdk/source/test/test-url.js index 7c81a07f5a25..9f2df0917625 100644 --- a/addon-sdk/source/test/test-url.js +++ b/addon-sdk/source/test/test-url.js @@ -396,7 +396,7 @@ exports.testLocalURLwithInvalidURL = function(assert) { exports.testFileName = function(assert) { let urls = [ ['https://foo/bar.js', 'bar.js'], - ['app://myfxosapp/file.js', 'file.js'], + ['chrome://gaia/content/myfxosapp/file.js', 'file.js'], ['http://localhost:8888/file.js', 'file.js'], ['http://foo/bar.js#hash', 'bar.js'], ['http://foo/bar.js?q=go&query=yeah', 'bar.js'], diff --git a/devtools/client/performance/test/unit/test_frame-utils-01.js b/devtools/client/performance/test/unit/test_frame-utils-01.js index 3d3ed1bac27d..a1b31796f935 100644 --- a/devtools/client/performance/test/unit/test_frame-utils-01.js +++ b/devtools/client/performance/test/unit/test_frame-utils-01.js @@ -14,7 +14,6 @@ const CONTENT_LOCATIONS = [ "hello/<.world (http://foo/bar.js?myquery=params&search=1:123:987)", "hello/<.world (http://foo/#bar:123:987)", "hello/<.world (http://foo/:123:987)", - "hello/<.world (app://myfxosapp/file.js:100:1)", // Test scripts with port numbers (bug 1164131) "hello/<.world (http://localhost:8888/file.js:100:1)", @@ -72,7 +71,6 @@ add_task(function () { ["hello/<.world", "bar.js", "foo", "http://foo/bar.js?myquery=params&search=1", 123, 987, "foo", null], ["hello/<.world", "/", "foo", "http://foo/#bar", 123, 987, "foo", null], ["hello/<.world", "/", "foo", "http://foo/", 123, 987, "foo", null], - ["hello/<.world", "file.js", "myfxosapp", "app://myfxosapp/file.js", 100, 1, "myfxosapp", null], ["hello/<.world", "file.js", "localhost:8888", "http://localhost:8888/file.js", 100, 1, "localhost:8888", 8888], ["hello/<.world", "file.js", "localhost:8888", "http://localhost:8888/file.js", 100, null, "localhost:8888", 8888], ["hello/<.world", "file.js (eval:1)", "localhost:8888", "http://localhost:8888/file.js", 65, null, "localhost:8888", 8888], diff --git a/devtools/shared/apps/moz.build b/devtools/shared/apps/moz.build index 6f22be8bf061..b1d889b7529f 100644 --- a/devtools/shared/apps/moz.build +++ b/devtools/shared/apps/moz.build @@ -16,8 +16,6 @@ TEST_HARNESS_FILES.testing.mochitest.tests.devtools.shared.apps.tests.data += [ 'tests/data/app.zip', ] -XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini'] - DevToolsModules( 'app-actor-front.js', 'Devices.jsm', diff --git a/devtools/shared/apps/tests/unit/.eslintrc b/devtools/shared/apps/tests/unit/.eslintrc deleted file mode 100644 index 3fe48b834e19..000000000000 --- a/devtools/shared/apps/tests/unit/.eslintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - // Extend from the common devtools xpcshell eslintrc config. - "extends": "../../../../.eslintrc.xpcshell" -} \ No newline at end of file diff --git a/devtools/shared/apps/tests/unit/data/app-engineering.zip b/devtools/shared/apps/tests/unit/data/app-engineering.zip deleted file mode 100644 index cb3c7ffd2a53c249dbcab8cc851a0c4f4354a053..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 895 zcmWIWW@Zs#U}E54IFdTgi7D`)iW>t1Lo5(;0dZztN@|5(MoDhY=0Km5{(38QJVH-s zoIJbn@utSWm7SVpW~wt)EmxMA{W6eJ;hN%e%75jS$3X!FK6)qhgETyK^#VO~G%h^e zbdmiuLuQ92Ljc@1htydfi|+>{tN_{~#mKx{;R3aV$wyYc&bzn$)a^|yiV@B! z|GqWMP0UnDdbh1)^Q~3<5Kl1xgYfpGzfPGdhfT%TM&$Ns>917}X0P$=A9 z&Kxl3;N`35Q|AUd2_prc;N-tfe#b6|*h6jNhS_9hLcB%1K{_`iC4wa-=S+{RFlK06 zzIy&?tK}_fV0%E(4~!O|k0cbMgE)X}5Qh86$kYsE5s<0?Vy*yhMkYCC+zAO}7BH3> zwlsoRh-8JV4_lG|sfOsw1G3N(2uw4spa*FNfp3k@Kr@gd0;Us`?y&_WL?1}!T9{5q lz(O?Q4jYh0hP%J3m1SnX45V~UrB0qQ zKPdC~(ghD@#7v4`5-=$$X3>O*fCa}>7xPbK)MA;<#1H^?N`Akl>x7-bm!|=p@fL{r zflkRy%*#wmEiTb3PfbcJC;+>sa1nn92&1{j_naeFvw=YC!@bKTHm&nI>h)3P?sSu7 zY6~VG^vQJGQ?1^XG(CTx{G_c60V~p1R|S|$OPWlyTKYO+aiq;g{vXc$%6r~APvW>$ z5K(0LQe3KB{jA>9t;Y}6X&wJObF1;MvG>kk_sT^3h-uRl4Hh|h$TSQFfan~mPQZ@IZ3lZk~EsR z$mU_DL}c^2f#zYPOQ4}x(j>B>nDGxW6y&^bjafjqqNWC*iJ;Vg$C;RMiEQErn2E5M t1sVv7S*!-)iWg*mmoh<}2#+P8iCAJNz?+o~ gClient.listTabs()) - .then(aResponse => { - gActor = aResponse.webappsActor; - gActorFront = new AppActorFront(gClient, aResponse); - onDone(); - }); -} - -function webappActorRequest(request, onResponse) { - if (!gActor) { - connect(webappActorRequest.bind(null, request, onResponse)); - return; - } - - request.to = gActor; - gClient.request(request, onResponse); -} - -// Install a test packaged webapp from data folder -function installTestApp(zipName, appId, onDone) { - // Copy our package to tmp folder, where the actor retrieves it - let zip = do_get_file("data/" + zipName); - let appDir = FileUtils.getDir("TmpD", ["b2g", appId], true, true); - zip.copyTo(appDir, "application.zip"); - - let request = {type: "install", appId: appId}; - webappActorRequest(request, function (aResponse) { - do_check_eq(aResponse.appId, appId); - if ("error" in aResponse) { - do_throw("Error: " + aResponse.error); - } - if ("message" in aResponse) { - do_throw("Error message: " + aResponse.message); - } - do_check_false("error" in aResponse); - - onDone(); - }); -} - -function setup() { - // We have to setup a profile, otherwise indexed db used by webapps - // will throw random exception when trying to get profile folder - do_get_profile(); - - // The webapps dir isn't registered on b2g xpcshell tests, - // we have to manually set it to the directory service. - do_get_webappsdir(); - - // We also need a valid nsIXulAppInfo service as Webapps.jsm is querying it - Components.utils.import("resource://testing-common/AppInfo.jsm"); - updateAppInfo(); - - Components.utils.import("resource://gre/modules/Webapps.jsm"); - - // Enable launch/close method of the webapps actor - let {WebappsActor} = require("devtools/server/actors/webapps"); - WebappsActor.prototype.supportsLaunch = true; -} - -function do_get_webappsdir() { - var webappsDir = Services.dirsvc.get("ProfD", Ci.nsILocalFile); - webappsDir.append("test_webapps"); - if (!webappsDir.exists()) - webappsDir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("755", 8)); - - var coreAppsDir = Services.dirsvc.get("ProfD", Ci.nsILocalFile); - coreAppsDir.append("test_coreapps"); - if (!coreAppsDir.exists()) - coreAppsDir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("755", 8)); - - // Register our own provider for the profile directory. - // It will return our special docshell profile directory. - var provider = { - getFile: function (prop, persistent) { - persistent.value = true; - if (prop == "webappsDir") { - return webappsDir.clone(); - } - else if (prop == "coreAppsDir") { - return coreAppsDir.clone(); - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function (iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } - }; - Services.dirsvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); -} diff --git a/devtools/shared/apps/tests/unit/tail_apps.js b/devtools/shared/apps/tests/unit/tail_apps.js deleted file mode 100644 index 0a5fb4b50d9e..000000000000 --- a/devtools/shared/apps/tests/unit/tail_apps.js +++ /dev/null @@ -1,6 +0,0 @@ -if (gClient) { - // Close the test remote connection before leaving this test - gClient.close(function () { - run_next_test(); - }); -} diff --git a/devtools/shared/apps/tests/unit/test_webappsActor.js b/devtools/shared/apps/tests/unit/test_webappsActor.js deleted file mode 100644 index 1bc2f250f733..000000000000 --- a/devtools/shared/apps/tests/unit/test_webappsActor.js +++ /dev/null @@ -1,311 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -const promise = require("promise"); -const defer = require("devtools/shared/defer"); - -var gAppId = "actor-test"; -const APP_ORIGIN = "app://" + gAppId; - -add_test(function testLaunchInexistantApp() { - let request = {type: "launch", manifestURL: "http://foo.com"}; - webappActorRequest(request, function (aResponse) { - do_check_eq(aResponse.error, "NO_SUCH_APP"); - run_next_test(); - }); -}); - -add_test(function testCloseInexistantApp() { - let request = {type: "close", manifestURL: "http://foo.com"}; - webappActorRequest(request, function (aResponse) { - do_check_eq(aResponse.error, "missingParameter"); - do_check_eq(aResponse.message, "No application for http://foo.com"); - run_next_test(); - }); -}); - -// Install a test app -add_test(function testInstallPackaged() { - installTestApp("app.zip", gAppId, function () { - run_next_test(); - }); -}); - -// Now check that the app appear in getAll -add_test(function testGetAll() { - let request = {type: "getAll"}; - webappActorRequest(request, function (aResponse) { - do_check_true("apps" in aResponse); - let apps = aResponse.apps; - do_check_true(apps.length > 0); - for (let i = 0; i < apps.length; i++) { - let app = apps[i]; - if (app.id == gAppId) { - do_check_eq(app.name, "Test app"); - do_check_eq(app.manifest.description, "Testing webapps actor"); - do_check_eq(app.manifest.launch_path, "/index.html"); - do_check_eq(app.origin, APP_ORIGIN); - do_check_eq(app.installOrigin, app.origin); - do_check_eq(app.manifestURL, app.origin + "/manifest.webapp"); - do_check_eq(app.csp, "script-src: http://foo.com"); - run_next_test(); - return; - } - } - do_throw("Unable to find the test app by its id"); - }); -}); - -add_test(function testGetApp() { - let manifestURL = APP_ORIGIN + "/manifest.webapp"; - let request = {type: "getApp", manifestURL: manifestURL}; - webappActorRequest(request, function (aResponse) { - do_check_true("app" in aResponse); - let app = aResponse.app; - do_check_eq(app.id, gAppId); - do_check_eq(app.name, "Test app"); - do_check_eq(app.manifest.description, "Testing webapps actor"); - do_check_eq(app.manifest.launch_path, "/index.html"); - do_check_eq(app.origin, APP_ORIGIN); - do_check_eq(app.installOrigin, app.origin); - do_check_eq(app.manifestURL, app.origin + "/manifest.webapp"); - run_next_test(); - }); -}); - -add_test(function testLaunchApp() { - let manifestURL = APP_ORIGIN + "/manifest.webapp"; - let startPoint = "/index.html"; - let request = { - type: "launch", - manifestURL: manifestURL, - startPoint: startPoint - }; - Services.obs.addObserver(function observer(subject, topic, data) { - Services.obs.removeObserver(observer, topic); - let json = JSON.parse(data); - do_check_eq(json.manifestURL, manifestURL); - do_check_eq(json.startPoint, startPoint); - run_next_test(); - }, "webapps-launch", false); - - webappActorRequest(request, function (aResponse) { - do_check_false("error" in aResponse); - }); -}); - -add_test(function testCloseApp() { - let manifestURL = APP_ORIGIN + "/manifest.webapp"; - let request = { - type: "close", - manifestURL: manifestURL - }; - Services.obs.addObserver(function observer(subject, topic, data) { - Services.obs.removeObserver(observer, topic); - let json = JSON.parse(data); - do_check_eq(json.manifestURL, manifestURL); - - }, "webapps-close", false); - - webappActorRequest(request, function (aResponse) { - do_check_false("error" in aResponse); - run_next_test(); - }); -}); - -// The 128px icon is a single red pixel and the 64px one is a blue one -// bug 899177: there is a bug with xhr and app:// and jar:// uris -// that ends up forcing the content type to application/xml -var red1px = "data:application/xml;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4z8AAAAMBAQAY3Y2wAAAAAElFTkSuQmCC"; -var blue1px = "data:application/xml;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12MwZDgHAAFlAQBDpjhLAAAAAElFTkSuQmCC"; - -add_test(function testGetIcon() { - let manifestURL = APP_ORIGIN + "/manifest.webapp"; - let request = { - type: "getIconAsDataURL", - manifestURL: manifestURL - }; - - webappActorRequest(request, function (aResponse) { - do_check_false("error" in aResponse); - - // By default, getIconAsDataURL return the 128x128 icon - do_check_eq(aResponse.url, red1px); - run_next_test(); - }); -}); - -add_test(function testGetIconWithCustomSize() { - let manifestURL = APP_ORIGIN + "/manifest.webapp"; - let request = { - type: "getIconAsDataURL", - manifestURL: manifestURL, - size: 64 - }; - - webappActorRequest(request, function (aResponse) { - do_check_false("error" in aResponse); - - do_check_eq(aResponse.url, blue1px); - run_next_test(); - }); -}); - -add_test(function testUninstall() { - let manifestURL = APP_ORIGIN + "/manifest.webapp"; - let request = { - type: "uninstall", - manifestURL: manifestURL - }; - - Services.obs.addObserver(function observer(subject, topic, data) { - Services.obs.removeObserver(observer, topic); - let json = JSON.parse(data); - do_check_eq(json.manifestURL, manifestURL); - do_check_eq(json.origin, APP_ORIGIN); - do_check_eq(json.id, gAppId); - run_next_test(); - }, "webapps-uninstall", false); - - webappActorRequest(request, function (aResponse) { - do_check_false("error" in aResponse); - }); -}); - -add_test(function testFileUploadInstall() { - let packageFile = do_get_file("data/app.zip"); - - // Disable the bulk trait temporarily to test the JSON upload path - gClient.traits.bulk = false; - - let progressDeferred = defer(); - // Ensure we get at least one progress event at the end - gActorFront.on("install-progress", function onProgress(e, progress) { - if (progress.bytesSent == progress.totalBytes) { - gActorFront.off("install-progress", onProgress); - progressDeferred.resolve(); - } - }); - - let installed = - gActorFront.installPackaged(packageFile.path, gAppId) - .then(function ({ appId }) { - do_check_eq(appId, gAppId); - }, function (e) { - do_throw("Failed install uploaded packaged app: " + e.error + ": " + e.message); - }); - - promise.all([progressDeferred.promise, installed]) - .then(() => { - // Restore default bulk trait value - gClient.traits.bulk = true; - run_next_test(); - }); -}); - -add_test(function testBulkUploadInstall() { - let packageFile = do_get_file("data/app.zip"); - do_check_true(gClient.traits.bulk); - - let progressDeferred = defer(); - // Ensure we get at least one progress event at the end - gActorFront.on("install-progress", function onProgress(e, progress) { - if (progress.bytesSent == progress.totalBytes) { - gActorFront.off("install-progress", onProgress); - progressDeferred.resolve(); - } - }); - - let installed = - gActorFront.installPackaged(packageFile.path, gAppId) - .then(function ({ appId }) { - do_check_eq(appId, gAppId); - }, function (e) { - do_throw("Failed bulk install uploaded packaged app: " + e.error + ": " + e.message); - }); - - promise.all([progressDeferred.promise, installed]) - .then(run_next_test); -}); - -add_test(function testInstallHosted() { - gAppId = "hosted-app"; - let metadata = { - origin: "http://foo.com", - installOrigin: "http://metadata.foo.com", - manifestURL: "http://foo.com/metadata/manifest.webapp" - }; - let manifest = { - name: "My hosted app", - csp: "script-src: http://foo.com" - }; - gActorFront.installHosted(gAppId, metadata, manifest) - .then(function ({ appId }) { - do_check_eq(appId, gAppId); - run_next_test(); - }, - function (e) { - do_throw("Failed installing hosted app: " + e.error + ": " + e.message); - }); -}); - -add_test(function testCheckHostedApp() { - let request = {type: "getAll"}; - webappActorRequest(request, function (aResponse) { - do_check_true("apps" in aResponse); - let apps = aResponse.apps; - do_check_true(apps.length > 0); - for (let i = 0; i < apps.length; i++) { - let app = apps[i]; - if (app.id == gAppId) { - do_check_eq(app.name, "My hosted app"); - do_check_eq(app.origin, "http://foo.com"); - do_check_eq(app.installOrigin, "http://metadata.foo.com"); - do_check_eq(app.manifestURL, "http://foo.com/metadata/manifest.webapp"); - do_check_eq(app.csp, "script-src: http://foo.com"); - run_next_test(); - return; - } - } - do_throw("Unable to find the test app by its id"); - }); -}); - -add_test(function testInstallOverrideSystem() { - let appId = "actor-test"; // Match app.zip id - - // Make the test app non-removable, like system apps - DOMApplicationRegistry.webapps[appId].removable = false; - - let packageFile = do_get_file("data/app.zip"); - gActorFront.installPackaged(packageFile.path, appId) - .then(function ({ appId }) { - do_throw("Override of a non-removable app has been accepted."); - }, function (e) { - do_check_eq(e.message, "The application " + appId + " can't be overridden."); - - // Then make it removable again... - DOMApplicationRegistry.webapps[appId].removable = true; - run_next_test(); - }); -}); - -add_test(function testInstallEngineeringMode() { - let appId = "actor-test"; // Match app.zip id - - let packageFile = do_get_file("data/app-engineering.zip"); - gActorFront.installPackaged(packageFile.path, appId) - .then(function ({ appId }) { - do_throw("App with engineering mode permission was accepted."); - }, function (e) { - do_check_eq(e.message, "Installing apps with any of these permissions is forbidden: " + - Services.prefs.getCharPref("devtools.apps.forbidden-permissions")); - run_next_test(); - }); -}); - -function run_test() { - setup(); - - run_next_test(); -} diff --git a/devtools/shared/apps/tests/unit/xpcshell.ini b/devtools/shared/apps/tests/unit/xpcshell.ini deleted file mode 100644 index cf2372f1c4e4..000000000000 --- a/devtools/shared/apps/tests/unit/xpcshell.ini +++ /dev/null @@ -1,12 +0,0 @@ -[DEFAULT] -tags = devtools -head = head_apps.js -tail = tail_apps.js -firefox-appdir = browser -skip-if = toolkit == 'android' || (toolkit == 'gonk' && debug) # Bug 1206586 -support-files = - data/app.zip - data/app-engineering.zip - -[test_webappsActor.js] -skip-if = buildapp == "b2g" diff --git a/dom/indexedDB/test/unit/defaultStorageUpgrade_profile.zip b/dom/indexedDB/test/unit/defaultStorageUpgrade_profile.zip index 588a9970597a5e1e1b84915b9ead980253288a00..68bb4749f527fbf71c5b509b6614c69ea8b37284 100644 GIT binary patch delta 3790 zcmZ`*30RXy6V5IPge!y)jwFz9Lr@UG0~7^<;sLfGqK{g|gUf?9A_^)ssIB)=S#W9< zuYyVy(MBuY+IoQph$t$Bs%^C*3MyVG@bCA9AoTzL!1L_R`_9bn%+Ah!>mG7j4{!E^M?a#_8*Uz7$ zTX*5en)!($uBOG# zNSL0oI{(X*1+#w04E>QT2#RozP74~JGiF5linWS?xjf_SjLcKYDT8ayq`rPBA5t;X zSsmUp!N&Wqdz?#K`(~fb?zcZAx&Bw*^=tBDzR&2rMG|dQ@zcd0vzq+f6nC@d6|IQS z^ckBxug`|Jc*AvB?#5Z1n|q(EpY^W(G-vagr6JXOxB33&Wjd^BF@Bco+O$h-b6Dls zXM$sEZC?JH`b|;M50l)@!V3M}BT@<#t=1VWD`PV_=<{OUiRUk3A6KHQ57N?8oytl} zM||<5mulpr$BS3a`#NI3TJuY=4AQ zj~os=So7mlpZv=|+q-P4U;gXpaRJ=p{?Z)NRXa~io=|PGxXMm2=lPdQZeCAnh`Azs zQFn3W-9MI|IO9;Y{m(_d(jRgkt&M%5KKv%LUyZ5qpXiy@ili@!j&4y&cLhsF zHTqY7d^uSYGY%^>=;mKe@UUB`#a>XGUb1wcY+^QDFY}vzA3^H4RohzVUkKlpc5F`QQVs z$&2o{Y?@V`zUcAE2lq~KK6{WhI|SOj9sSmo+2!@mudcBu97Psfo~ihL()emC+sK0> z_oyC@U$MP^d+8z5M~z2o(i?+TJWIDt{q0I-K*Pxwyvt*pLu+qw2ecQe?kp)D6#JL2 z`R$2)IXic>UEuBr{#cuEQod-_j3i@}yo}01pX>vbsYmWOzu;{QEA&hgP zNUe!AX_E0t`9VuiI3WSqSmOTkp)ez|FXsfS6)&M$XZkyk@~weH9b>4So!iHVT=*!` zzV^P!CtG%ZNfzx{K;jAviSeFPGPF30)oR%jVWhp>&&HSt^2U=7`7=pU-Z<7F$f(2P zZjR6(MONge0(Vybd|rPeZK+Hu(x$Je<7?}J2ODemMT?Aymzz-AbA*OZPEAPAo|sM@ zQiO!3*b>K)+)c(vOeTyFY3EKH&ez_U-Nq*a&Iz^GN<7&RiQ_RY8GKI7uJGYluo1Wl z>Ea(WCM0scLTfU=h)*8;y`Gpg0yf~nWFKTlvavNieiW*$e$Vk#j(&8X;@~Tkl zaz$-SZWml2vH&5m(hOswAr-YkVq5E}y;3E#)K1W3^9LXtZ1Dfv8|`rP=a`kXgc-Xx zJF>IU3r{g1*BT@7E(5ajjWzLYa-~No$BnGG@hp$1O z@`CdUq{6#81f?7aAjA<3!q&D7?E}RQhzCDAA_+P8jxAX^Uc^#Cpmjp7&}4}WiQyp; zjBr6__%%xU6V458Y!JBn*`BolWq&(}8R<|6#(i1W`DM9wEPpD^H zOm$>kly9{n2XgtKk|1YV`f{A>L84ndiFvCEzh$P*tcqsF5#&;Oo=O=7Bw-9dybH`=o{Xj`DNiK$REcLp zm$5u7lOh*3HrfW{_`VKgIsw$nI*t?eODPpSgk6AAgGl*XIbIn-WiKLm7lxnerkOrw zY~7Pz-pO%XBtvJvABHb>%y{IKgE{&3eHb1%O2;vX4Y6nm!I@(yl8&D+Ltk>g-JA6M zKrJtii7-@224k5W8tY=@d9X>vE#ul+@$wPF(ti(=s zhXGyC)(XiXii>Q(79#h*BH?Z2uWm-y5uZb=8oJT3v?Z%VQAofwIVm%z8C)S1sxy&lC}bq(0lj4Bs) zB_u$jGlpemG#R$bx>!ia^#n`cnbY)=f8$cNrq}=j1vJ2WtM!H*?;RUt2##8#$6<;I zvSWhe0pEl!b*vkcjD6R3)pP^CDGj&8obGlmVHl{ep!Pfgjq6SqV7`DJ*Jn9;4SQ&2 zG>&!xN| zl5R#HC?&L5A}JQ_=~QDFYu!aI^QLa24zK~y&wvD&;!Ao zSg#ri_k8Gr76&^4GUKrr*7l;6R@?M!8mGolVF6iEQ zADv^}lh1b>!RPi!g#ux!8?vUd2#(q7He%t@?XzK@PD7n#$@UbsVQ*0)IpV{8##Egp zgg=xh93^+kr2Q5jV!WvPt6ec#T3)n72A|jMff`apIgIOpLQp0w@#t`Nst0xUd#6nD zYAqn3C(Yc@tDT0httT3Z3%dXUZ!``|uYJ;>fEc!W(>ICvE`WhnNP(*Kv?b6682L%I rhBsCy4BgW6ZcK-V&0-|`ggL`gF>(^~44DtAujyawKn|z=cSiaTIZC>_ delta 6605 zcmb7J2UHZ<(w=V85QHH~bU;>=Bsqwnq!m;QfC{c;NrL2{7+^s3@hbvqt+ogfWKj$x zXIaUJhzg6MtB8S&M2Sj{fA^5|?RoCmIcHAa`fk;C>vq?zt~x!F!yMhp3=T|jsJ;gj zx=Dj1GmEsVyrZwLyu5tCv4B7qFGV*;cSkRugYKR#ia!2sO8fS*lbFUgfH{i<_%Krt zJqTwJ6ZxMuK#dYYq@j7m8s1d_{#!`j{5BGnGXK+(v6{Q{!TA+$0}`Q(Y$Z$-|Jg)M zQ%iM&y1KTeit|oD4k>U>&RrUQ!b&Vo1{%w%e@o$aNC}kQiXuB;wXQCxtX{98Z5}*% ztNQZWCbivj)3x?VvmLPmAtT)wZKC|>)ZFBkwwaCrw=vpugMP@W1(i&C1UjA{^z}{J1!_GuoDm(aZ`_W#&tC87P>RUjNXworua9r9jEekR z?0&RA%zn_trA0bXLgPsov?$htMhG%-|7^ z(d2iTO&>iTdkuB^>y3ZuwFn+2@7Qvy)WUW}Tkc7-yY;elZzDdoOa}T+PY+v9A(y!` zixcHDo2sePck+whk010YoS3jv4>}q0Yh-wWr}z2(5o4t*+k-Yw%WTm7DCxH{@;K|B z2wPM8xvpB9p^oRh4|ocrBnlkUTXVyIKYz8kYvaY+p^7&n){SHo8!H$7t{b1egLODN zXAbr&C_z}PoOem>`CWk_S;YYYO@rp+m1eb{+v`f2C~8Lg&O~@_wkitQbVB)k#>p42 zblgLOnwt|_9&c_-r*1B}DsNYsI5V2jZ@#Jfn17Iav+u0Z^(yS>=uP|9mck(S8+pMY z^_APGaqxM%rdRy1aQYOua1xXD>){_?OT|tA5T= zok##ge>KZg#*@@1V8$<{P~CB^F4Ki)dxP{-_dKhnO|v214!37Mq@LaVbo{qhAH4cK z^_;xY4Aq@RyN`l$>WStxMbhzm}>5rf`GlAtfkN_Tj3o=jt679dU(X-D|utuyAU z*6T2lNORmI5;sYl`ttzk84MM6VCYHvQ`_GcZYj_DHsV`(c)aiP0XEAI?u=b994Ddx@F$y zUy8C{iNt4j1iGF2K;GBSUB0u%;8vSzP9W*H&1hX$^QA_8N114reU8T-smpWqKEfth z^##fb6HcXWKfQxj>D*4!b$1eioN|7@7`#@9%^a#v0|#mUgKqx#)<}myAvi>G8(XX|&0?+b_4YeYH_fh|AJhA@*Q=m?nLo3XThzcPqtL9w^Kq z{hz>On*X_Q( zKkRh!ox(Ai@gE|_H$GeRByq;?VagaYa~!?PVNrQs!%Fo8e<-4onx!_`^jn`MGs!uiP4K}Uyxx~&=QWc^T95O+l*6sSW=x0Ogi|0 zN752rma{^Y;V*DzfDe+4wlEZ|f7W6HAso;!+7CTOhZ#zPWfgE**&F;+{Nao8F}jng zIUBU8gb|bU?JG49hUuKpCN?-D6v#kNBy5;R)e`mC;6wriDz7^;$b9oCaG-W2=oPU1 z!@Hi5BT}i`tWq&Q3L*f5EM(q$YDHV+ysf@y;d#ac|8IuyJW<+@3jjqgmq15n$3Vwr zLY(x!l8%#uMoCg?Q9H`S6p@}19-e>X+L7Z2T@QMPTDb1IV;5?^(aext?&5wkhqNqv zn_p}$UAr53hl6Bh%EZh80tJGIHsOiFk3CtcUcT8?vnv_!dxDq{_8b4%UR6U=OG8CV zSykD2|3WSF4cp>9+O>MmwuSnJw3A@g|Ch{)0e+tDfiBCp40sAxBi4}eTo_@8rpMB& zTyJOI3{4trnM??%nYiAhJ+@YXmi^9C>(tc8j7V5rA*J0>S|gM=Egg_QQd143p(A7K zXyadX>_aBon`Va_8fhid!C4beBtI+^4X?HB8Kcxo`$W~l0NZ)i?&=utZF zgNh_mlQPV0WqG-YgX+ea%O0D~*L?}i_+pp;hiE;A)vZ%)ot^0;GRc3<*3zs3Dr&{v z&opT~&=j@r_14g9ioO|>#q;$g2GO}K#de=7EN;IzbMzE_1)rN=vYYbzrrhC?8oL*Q zKK0K+r;-cD!^K$T?7B_=yui+##UHn^s$%b8a7e%d-f9KK=WFBu*>tFPQ^v8bBrd6jD5+kL@~H2*r|EjR=e0}-I-Jnuc7v}6`K`5g-_KYat@IP^&m0h+3%%`g z+ax!VKPhI&FE#gdedF<}58KZideRF6s;_uRB+#&+a&(<{d#Y$(pLgOGJ?F?O6r~}+ zQy@wY%kyQ&o(dp*aP`l%^zG#oUdYsDg#(!}^vJC1Wa!Go;9!%e2$>{|r#|9GA@vy$ z*MLADe@8bL@EwNP<_bf{@#=hG^u1C&ba%c?9q0e)@4H*teI3#00OH`7bLY z;uO85rAVaT!snJqR{f9!Qic>I|JL3uQ4wB;Aq)?3e`J41r8J*2ai4B)1;6f9U^Y#m zZ2gXEc!}!YwsASra^l}~f}~wbyu@ygpo=d4OI}O@MHJvY{u~~&FHp#XcB4MJk%J*# zXbeQl=7*BZvha|F8MZbVqB@)l$^;|;jZOM!`L_@+_%v@rSMoEoYVe`Q{7|XI0J zL;C2I1%wZ%UkuTi1xW%DzZjwZtLC*2q4YJx2$J^+L(*46R8pETG3@FgI9C7@|xD3tD3Ee8LC~SQMSnOg!di72x3{gOsB7U3~IwV@zhxn4*!y zP#MNZhj*If}(vKB1rVLRIi$(Er46+{Trl{!YMTi3w zrVY`dMNtUuPaC10dln2NF%6*zHu1;)&Z^PE}&R$>=e5h+ZV9Ve;?!VK7uHPC#M1#@J_$<`iO241k^ zgjbgUc5EvLt}!zYVA&kVe$?maqPiev#ECFs3wywg-^Ywl%zzgWz&>&#Yp^gre65Lj z1bl0GiD;u@11k_#Ojrn!KxhnIVrD7Y@F2ym2_ZbobAs4wA;bs?Thx`t%!CnxWmyV) zCXB4U)Xky&_bz_^wS)KRq_FUwNYdYWdOS-LJw2E=i9zEC74?e3AB8xC+H=5~QA704 zWie*d6y11!VU`u&vJx(+l3})kAM_;2kkla# z&5f*Zzn_XSUuT^8fqoghC!(UZ^J0+^2UHJ;&l4WT(`CUTPKNBk4S2UiMTdT4SneHA zfqq=HPGg8gMuY}8DE&-^ZG((;uzX(p8CIvwKh-{7WE(1Rb4g$W-$$I79Up$cV!Em5 z#hVP8WEBzk)V&6xdZ_5!A|wHwJ$N#~A-`KoT6R6_=G~0{OhpG5@l~Lt$_-4ta=?zm zI#~3K{?SQPfQ zOMwRtY3DK2bcFff$tV06G_qn`WIPFu4{|X-G@$1Z(Jhb7u;OvQGM^BRpywD@dGJkS z#=6)R!Wh&Nm!C2bWJ60@BG@PyKW;cJ6;&={5aPDH*da1;?(hZYxDg6PV<|yWNDmF} z;Cj4>$eJG)7>t64(P9cSHi?DtAk5<5HJMASgij)m7_94m%=%5!iJuAvy&^?>iHLCT z**wudbiqsY&jN?ZcN{w93}-Zd>yRLC*9b(f(^XusT%XOBz$i>wZ zF&-W~t+D?}xV;Ip;lV>9bY6f`W=^b&2hZTz)x@j;c9??C-e(9qv1tmPem6WPW`eP9 zA`_l{LkI$RzN294`SBM@_c8#XkI7gHKVpdN#4ZZs9~?p-3u06OJn@w-%2X^(0AFmT zewl?+5NEM%SOP%2ng{!jAg=Xf8N_-8k?p8ls2|3j46vEAUmZPKH5qwl#K!8;^c6 jVSo-SvVd6@Cw7(#5f)%!e9DLejsIl=n4KGs;>zb diff --git a/dom/indexedDB/test/unit/idbSubdirUpgrade1_profile.zip b/dom/indexedDB/test/unit/idbSubdirUpgrade1_profile.zip index 1f8066a4a032a181e308dc5c74203287c0e01115..b7e434171df3d80dc91cf7ddf684188b8723d468 100644 GIT binary patch delta 604 zcmZp&pQT+N;LXe;!py+H!H_lQnn$8Ura=oM1H*JC1_nL`28QIK)Wnk1_>?5QjFQ}( z-budMj|~Lc-v1MQ|7*&GBVFHvJmwsjb}9Mg!Z)cmn{#}VbhjPzc)TR@Wqtf@uDh+@ z0uCyqec?M_v*O3LDAfb}<&H=19=)BcyMeK-XYG~=jRs59>TSNICTrg*T)p;m+mxs! zw>3g5FD3bh6yDy%E%|%#E48&Vm%M7VS#1-&I%VrEbywY7Ub^tFvuVNm zzBuVa2aCIZSJ#|3Eau7fYT0LUt-W&LB0I@o=cl>q6TIDbhrEcqB42ySaF^{w{%Lph z&gWecEO`;D>ddgOeDlwGfeKlk6*qWO-kq?`T7SDiwoY|MUr@!WTn6hy6E%A#Z#Z|s zc;@bC({1}Bbk035zV@j*SITx*tx|_4>;3EBKlvG> z-{xR01py0tX53K+j6EPwXlQ5z(WntQ`LL803$?v~tgi?AOD5m_#y5w<0>v`(Cy6ZJiG%B2f6 zk~1|#*y>j*$&g!!VUhdDQpV=scX^!i`#pYt^!R-qkI&=t{@k9Q&*Sm_JYKKQ4a|8Q z-NQvzP6Yq}1z@9p)#1lwwI2C0005N*fDM2qaN;x}IGzv`8iEavkB-87!vNVPEjyo@ zm6||>12S@7Ru-@AzkBuJsa^xbMT%8D9#rZs?AUouPa_-=O3d6o>KT9Q1^D97j&+|y z9buoRciL-DWkS}OBjhrc>9YblrGq(jK=xb6$?!>2i;gdHZy0vP>NYwldp$B{Ogk8n z1H8!F>*2aqtyQ0DV|5PaJ$&frFSwqdg;p&MC|p{XH@vfVHmb&ofOk(!(@;F4$nq`> zf7*sjJRdQco2gLBR-YCQ#=$TrY#P*;yj_Nuo(wtNtoP=d?pJQHqz@VHPTD2)%C*0Q z;*Him8u5LUV|l)(!B_<{u#4@N`jqI4aLqYbseQw7@WOn|1!3bl;L}Wds;4ibUe*ZzabOr$Px-La5y#eM18S6U<3Wa7+va zgNZv67f*=Bh6P6iN0UM#q6k>h=`j7ZC&0mht%_Sg0%VJo#rFb?4w&pSH8wUoU>NEK zav*!1FuB(xuc50qQUGlJFB%qZWZ9|n**0s;K}X|n5nkDDZN~VV6nMoUSK@KqvpNaq z+n#LCR0lUF5Tkmmg~2^@g|w@*i?j<)AGZ!rELhyKr;+l6;*f_4_Tc|4-mBll zJx1p*5fIs*dM8+6{W?biEq#S9+^VfCZ})F=Hh%jdvZb+Y@D5WfyfH1(kMAVMjLGL!&?M=b zh#Ic*-JRrdsGgkT72L9ULH=yA^p)8tU8A6-_fwbt!a{{(!*{#`VVIKU zz~#A8!)e3FXf90;zjSslx{i+hbO{qzzYr5sgw#bF9{*sRSa`_LZI1ffi;!b~4BH9Huu zRE-uUy4v`hZnOKZtTI?wB~9M)U9W{9UcU%#ne-Uz_ED9UVPPh5q>p?vKRYvPw+m+k zO7AT?Z@qlBYL`(N>G_m^U(295PQ4(1IjZNYgbSD|Nk7e*t?F44h0>Ovp$*#$>Pk=6 zRrWhkO&nSjpU-}p-&PiIf zuJ?aWS$J2JH)iG8Ot0G+D_+chvJi8-sxtmPRYbAs&l$UA)b$gS6m>rXn*3}*+U7X~~mg=$jv@^WkWrNn}Q(wzMzy*ER}o2GHDH z9_J0m;c!>DG=VFVI1q3wO}cz~FxVXAlJ)wq@!6Wp!EJ#FUq`=Ir`$z#l6PBg6@Y#x z9&^~VH$95g;V(sPLQk-Hqb_W&KQCbEZdQx|Xahro?J#$lN1#w)7Zi*2gUQRR4VuGp z!P^RMYZGp=_4XJrWs^2^8M^AM-~(kfHUhE%aS$c@zg$*rO^sK46gZc%8vdu}u3Ph5 za3fL^3{ghOjDRW1hWP&$@_%3e00B(d?12E^E9)z#a6ly_*2Mz&GwI6rlK!IaKO^@9 z{Z-%p#Rh=Fl+{nhcbU(h*&*1t*rOJeKj+G0GcWeDF6Tf diff --git a/dom/indexedDB/test/unit/idbSubdirUpgrade2_profile.zip b/dom/indexedDB/test/unit/idbSubdirUpgrade2_profile.zip index bbebcc12c7dce08d41fc6d0a84dffe7714d179af..264c68d866d55dfc3739fc8e85302677e0b57a74 100644 GIT binary patch delta 642 zcmX@-xKX!0z?+#xgqeYXgP~#0HIKXH9ud8a3=Auo7#R2%7#Na^QWHy3<5QCKGD>oD zrcOGT_1Hk5?R{NWEQFm%R$DS763zIlgHf6k9I(c!s?Vr;LaZU%E*V|5Te8Ev$a>&^7 z=E4mdccq)?EaGqnF{KBoD7@{-+{?(i4e#!0D{C1_W%F@ delta 2353 zcmbVNdpOhkAOEf~*-|vuT*j&6(rk!GVJde?7t$|MJ8l`;hHZ|_5+}te)%U0)QBkRu zMlKPXZbX=CE5vfiow+PBHitU(d(Q9o{Lb^7-yfgP^Lf9Y*X#9pf1dZ}dA;*7-0h4# zu23mO00343&;Yg*nLKjy4g>&npa8HM&;b0x1MranNBn=n9*YbM_4JShps-giUTI5< z5`_RDQlFN8gv&ahEO7;M6=p>f@|ZEb6$n&WMCym#xLT-A7TV$0_2&~C0i zmZIhZ`=Ko80j1hGGk>#-+L&u^bf8M^!CRx!8F0n=#VR5@#0g*~Gfl30V|v^<>e-Z4a$9x(B8pPgSktZYnvf7sBYH33|Oz zDRotYnR}4Qbp52B@Y3I2msgYf@@3wtvb3+tJS43tJ$8KBElT2acI@V<$8Iyk2ZYCE z22W0PI0+++?>`z~Ttc^0D=b!tC5#e}m;3122&-Pz=>FFS250YYZVnPAx)1IZj$F7j z_-p)|Gg9VqPa{!P`JD5zwuHC_{qf_qpUYf&Hj&LIB<10}#L6*@YffM=`gvEYVXp51 z3x~R!6HO#?-Id%eeK}X{BbqVkBAMle!$bBj$|%*-s!P5j+JXM~{~`q~w7HEg+pm4M6tBT|Ae_2cPJ?MxkV&{sbYy#KOW ziy>|%&|M?zrQ z!#m>G=ZPZ`T^%s;9d?x zG;HL~m`- z$s@y+@gemNV$hv%PUcf?dsSC&J)xku$!oKhY%&v{cgO&PJ)L^gj&-9XZ(Y#?HV#Ge z!O}!hh}u+bLoQpz*&~ zp*dur@q75ciVThFD-JXG3jy+%2RcSrL0$U0eXR}(+{z*Z1?}Q~2SsO!UqP|ww$*o8 zAMJ#_f+0+n%C5pQoQLaqYh`%O_Vfq~{amS!AK%<4FD`8LZgDZIdrxSrZRyU+5ecr2 z3ymUqRML=4MiE_{tPrBUYo?7y9fo0~953P)w`ONf#!6mU4l>lU8#@MSduK~IZ0``W ziX&K&6?7dJLqZ&h|8jRYk*xxi{ zlZhbI4W+MM`+W= z7r^>+O>AGrNaenb4T&gNkopF0&z^>(guIaM5ftZI4Zl21GJ_AA+-b4OvwYKq%L>Ry z*8C>Q@5w_SoGBqJZ;kDYaBW&C(Iyp1xgdvK}zz!s#BP!=eq`OE1l*!TeX3@8H zm{?pqQkJ%x64)V*VQOUz4*N#rsPiZGey-W`hFR&w;me!u^em-rO|Ri|GLO4cH(nJ+ENmq_WqTz*v@ zsk1Wv9wKd_&tH@tvuIQ4{f;)*d^cmrdS3&B{Ucd4pZR2tbhD&5@?DgWX5E!Obi?%R z*&Jf%{S;X2vpGqdD{`*6&vdGjE-&KjDr7`s!3y$v`b2*t*vO#Ajt-%&_eISdLkTPh zDTMWsPV#RpH0}hTp;s8;fxzK#7c1z!yK+K4_#8eXSq$&SZv`u;m`-fuWsRKfAABjZ zgR`Y^x3zdwJsY)N@Q~kQP67ROJG}H*m9RyyuW1cPhNBb~_-RhpE5d`PyE1$hZl{ur z!ML?Lpgr6T@(A>m)rDfQhd`G629POx6_l6#nst+|v`2SqFY{Mw;}>DeZVR46suuXK zu#>mZg8r{jtNO)ymxd{DGH&_!pMzI=Y4C!^P({!f2?s~lYC*<91kw#^yaE98;ff#; zxk2Z@Tpai+3IOuJ*mnA#$R$_b@b}K_>9KSf2Rx^QRj~Vu#Mr+j{(-q)Qr@Wf7jOTr z2>`d^LZDwCuvFGR&;-{g8G;~E3;G!Tjcx!=B6mPBh;OkaD5b0m-cwu$&HtV=2j!KV up-|*91_Pc|vV{hHIio>agxnI|7Rvh`!@(G3z16FLRlsd&06?lQH{}ni=^t?b diff --git a/dom/indexedDB/test/unit/schema23upgrade_profile.zip b/dom/indexedDB/test/unit/schema23upgrade_profile.zip index fec7aa8307525b00956f7e45104c18bc1a2ec858..888d24434525d9cf041733de62061b853c773899 100644 GIT binary patch delta 687 zcmezB@LZ=pz?+#xgqeYXgJI^JYaUHXiQ!Wj85njmF);8kFfb$+r6!i7#-}9dWt8OR zObt4iciVtx?{963`9c=k9=)BQTgasIV&{v*8>u%Ow@E}d>q-gDHPQX`e)E!T8W-ZU z945Hf?RB@=^lQ>{&IA6%t!>9vU(G$fKvpAU*Tf#K84cDg^}AQTD`hq}@yP9BS&%HZ z-N{5u^|i5?2~SFl<2KRc1FINB`7=DH9F0<`tn*ma*M3i4<7#5s%826r_QzM8cK-YK z_V{()Cju6NQ&J+m+xh%b93Oi6*)}I{+T=Rp*fp=#sU19>>czcRm6_w+?=0{6uJiBY z=AMgpCD&d~`IfrTb8r2ZOe5a&j2k9L>O4R2cn_nLQD38*N%^Hy2M@~qQxTXZ@L~03 zz7q;tTKHzfof2G}Uf$EzTCR3_)9I%{JYN?4j;jivXDR1+b$ihP-6gB+maYEz(^_m> ztI)i#lh3!D`dT%)@R{n}H7h^#*q;5lDDYY6U4{B3b-&|m5Bz)QBzW+vYrhLmvPqL) zeokc7?n9T{9@?&&o&0cfH;3M$b6oT0ueUlK`{Ub`Be9(~=I*SY`oa03zUfNs2`@cY z)k^K!?9D&*!^4Jd<1g})zcWtTypvOk&%&M=cU%Ia69^O<8X7?~YRpbnme686IN49a zmyvn$90~Ku>C$pczD$z^WvwS4l6GP`0AW^gaZmP<~;_{C<(ltgoA~q^bb{%iA;MLlAXTv;A=O;ASC#Y`z(BJ{A1HaeS(s$wF{(DcLkBs^)mA(AP5<Zd{-&`8~+VH!r6G}ajTC_+A2y)Bhf;D-nOA6!uOqm z`AcymLe#`v{kv!j2Q6a|-@lxwz3sggW%MCMu?2QvkCjG`(j#yEyFuRB~&z^RX@rm>I9u}aiw#j665d6Y#uJ$Yr9TCG~ z#Ap}w<|!6w`l3zMggYSyCSy+rUrvyGXLogdEx92zlck(0x zfrur=67i8bA-GUnBq1;~0su-0N`aM!%JmH?3ZbwxY9KKURr2y;8tqIHk{Pt!A)TqK5H&c z=bv$gNR)x`zI`T0{a^>s9;PJ{zFrB>hjO$u0f61VAsK|4kl|rBilC3J=`>r|I8-%_ zsSwh^yt!Au?Wn)k9I>#@HbvK9KC$4KY~7&j>vo+L?fAx^7VL(M;B1NXI{Q+}#QUF{ zNz@j{pw9Xb0cOwBBZc0s4wVe%7=uxxD>!1T^T@w@u*o3F!MLTDL`|-r-c-_jbYPuz zTRvXTu;B%h{Bf=R{WZ*D_3aE=Kw*KPuBt3ZwilMvM?z0_S0@}l$GZ09#MGt!o~$hT z@v(P`Wf8fWCB?a#KJJEemy^M+Me^q*tX~i!k6hbcU}<1-ULZI$wel2}n4a@7Qd6Qh z+wWjksSmb7Zg=BhE9}ldn)A1cM1*e60c5P}&N4})B^hBvFN`U4M@cStYoHI-IzEYD zwV>mXA+bCAjl+Erii=8Wd86HTq;)53$YXu2_BoeqRs%5MeG1IEgrf9SmkLFn?g#!W zZ%iClNYPoXwkH^D9RxyEEAO!DqmT6d6Sw>9l6nT*K?fByydq)6>gUkyE4X&$^-#_QG;CIuTlonT!73YQ1N~0xcd~okSPREMH!+EG;MZ z1@?QjFvA+$O6RQTM?6YjteLe{gZBPyUHk^E5+3_gjdP}zXDL$APFT`^S!MAv+tu=a z7^E$1(lJ@WOJ$@6!;p%kw->gZb)^QEw~e+(vdMEn<`-{wZ&>%ciIw_X_f3_gy)mNn zt2fQ!;zu|q2dlJ(@t0EH*t!Qvz4T-njeMfM}ZK#(YEpoI=0p?hJ*8Bdit@qsA z?kJLV3l6aKR3A@Gtz|6EPj0_#YJ53yU@71O&WlnJ)osLr-|2M-wO2FIcq}Ws_C9Nl zQ8QU5DnJPL-E{}$DQkF>e{)r+P%-;ftv#&+HpAXk*ulTYdJZKrw4YjZZtrQ5QTj^r z!nsC|07t>4SMHmqhx`zpth5l-UnsExUb3s?>&MH9hiYwS!yKwI#(@HlI2;ea{?a8}>Zn13?t4+40?PKKLk%ob0Hb-RY^1W;kXG*qlMa z%FnmYEXTN((l#Ld%N4a0@tJFLZJ9z#wI-XV8E=Z?u*xNe*i+{c((AinyGMKm27*_} zBi0ox@>{#I(CN(eTX|(A7oJ5?V@ll-*Y+RXXgx+R_izdb-E|0Ur?_7FJT3YDQ_lzR zg8Yer=sMG0k%)T60Xz-kx90-Al-=3JMuRKOtp5!0ZYKa3K2*7he92@rCU8uY*9cuw zNlOXjsn@cf79LEHm0>ET8P+$(D9y}Q6iSO&mU4-jTEVSuMlmjoJ`v>Z8J=lbU!slr zsbz57C*p0zT0qUvyH)ZQK}rHZWq)Fi!pySSV{0l~UxwqG-($AIrup=#KlTrZy<~qn z`@RYn3jZ|Q8loD=RrZiQq8MfVuRR*%cssdgrlfMiKR+P^xK9YMQ)&lDhb!}~f<15t zJ`+$?9QEyAYzWxm0yrY(&Cf!>6badXbR`Zw$CVnScPf41N}s6!;AZMO9+mu8Z*=g1 zl!3}$+~YF^S4}=hmXJeym4RoGTVBEuRBRLO2ELP21OueuaO*F4M4{ZQ{$F!(l+;xE z!dyOca?{KFSDgAXs-Tm&I;28~qX-RFi(5ccg?XW&gdJpn8>T{BV4ML1c0ffyCrL|4 z-yc&M5G^CefeV8$DP;)1I7pV(0Ntc4Ai-PVLn%ARDmT;y(b5(WUkOf_2x;RED6k$T T#DOb|N&pf-wjcn!LgP1r>0 diff --git a/dom/indexedDB/test/unit/storagePersistentUpgrade_profile.zip b/dom/indexedDB/test/unit/storagePersistentUpgrade_profile.zip index ecdb0e5ee0022e174560074b36e97dd6c22f13c7..b1082106b218c990ecabc23a4d1dc1637f5b2085 100644 GIT binary patch delta 664 zcmeD1I%-rO;LXe;!py+H!LWGFH4p3Ljm`ax3=Aun7#R2%7#Na^QWHy3<5QCKGD>oD zdM6#sdTb!j_P(wwa=y@NQ6=@@pWMFx4Kr0aeB!og$oxuRTAX^}*y65-h4(sQ7IQw4-oM-R#62{0`st-|FOGiM>k}6f9PcPE_oP8u{i${OzPXp~b=gQwtQOpTwc`uZr6&$mESqdS_i8VX%Q;=E z98_`XDf?&s$sZW~CYvb;Z4Tf*B4}aHj5{WQkqHC}4GoPT8Z}-gr^sqC?w;H)YX~$; zj_E(+TT;a)gROI-07$SQ!{@ I3xga70CYbRw*UYD delta 2901 zcmbuBc{E%57RL{1QS%&Xs=6p4iWpkgkQhqMuWEjcC^fVQqGqS4w(F^@dKMjV#Z)yF zrREgX(O9LoQ9@C}eTJGM3Gsx!yKcMQ`=j^%an9Pm{rjEI*=O&4)^~SmT{{UnSi|;- z0sz1T$a~aVjywNS`G5@o;4lE-2c&_sVZJzmFV@E!=}!o{aN6kr09%kTa~ayXBBFQz zwtZ_mhj*VZyxA5!e3bXfVgh$h@jkmUpQjFoLfOlX#CY_ZR=w#<_U^CawnqJ=RN}EZ zqU?r#V#>)ogBCOcGd5r5mbI$gl6)FzfU)hEAq;E!3vg#vDCV;(jq#5&qh=!b^n42H ze7RrQF%^`8-?E8h6{3i z+R|5ttWx^)weYb#SW;V;aFmj=hbZiLrD49W0~sgNHPI{#s-VTgY2?|Ll$0oE> zm7{OIYBcP`S2smOXPyWPf2_j^tIyBwP9E2h=2HF5ft$~Nu@HLR!Jl9&2VkC>!XL}0 z_6gIEq}6ffI*xdzJ~-hhI=#|>S|u{hSg0fODu3mVd^^Sw7E#{=AE#*#)+FjQt5N}MW2=?)f^7S#p zXlNcis)sm-z~S)-1R^{-oZuUT^uq<}BtuaLBL^|bU+sAIaC zKDN+RUNu_<8LOn{9IV7~0p@?3_=Q&q?6>!LF9UcPScQHX3aUG@Y??W1aYV#9;8d3F z0P6I;M4noV&G}zd;w2)I1{&pW9E8Lo&R-xKE#k;41zT1Oo}&5a#rTgcb!<|@m(Sg) zC`!m(8mHe6@1F;KH3P(5nk{;<(gB{#jr9Q^%sc}v%EqJ7n zlNkoF!`)-qWAk3Ro@$xNG`!071&;@6l-W_qh>FYTc{RFOHK79( zk7!hKOw|?^j^1@9;yybkpUL5e8xDf+3B_PuOv zFy{sd29&bV;fI|;U#6FFOPwDIA2GOW%!^4*XZR*+n_W~!RGf#BhsWsz{OYE3oh*lw zKQ>ke!jkR;Zx^+;xG}s#nwYdRsED|c?hX?>T|EnG3|J1gF8Nt5LE?VU4gFM8!{m~- zij+!lIZO#$IY%G9n%yZda@6U|YZG@1o4%HXH}7!BqGaX4@)q}_O^<&bcKIOJ*Fk0m zbSrSq4_}*j6&uc%cIGz!(Cb3#`}VvFM{7b)`&;j5d;!Mc0Gz0YjYfJNlMZ^)FfgMY zqqYH2hE!_q^XAI3ap$ENA>#PMDK`EVgU15^E1KET$jG zQh#o3MB(+fbM2;54Ppm0mX<~uQ5o1~qlL*;Iq=TJ@BeOlA#!K4%Z7e$0pY8^Fn+h| zX)E88bZ~`#U8YuKc<@B6m(C`>wi5Z8_Ix66WdK^+;sl>Lq_5ZAT_aztsWK*hS!xM8 zObiB;BR9;7tE3FiVLxk$(3-R-)_wIsDeaC3xIhuoXBmQKLzcG~q9HiSly&~aBC4e! zNX>dSyBIt7xg+Hh`7LgupRyJeQk2}|shrbVRbq5-WB)V*u3}!z9-dn)=+r?q4|^J2;Y0ndZofaUIUy@VRaum^MQ1Sywram?TOL z*psZyjdy-iIiaOw?F=Ju>h0$igN6-j#JCsB%W(+zq26B+x*?*-Rt_Z!D{%Nu5Hs}Sm@kfWFk)X65y zw|5!<1c7<<5`+=eJpH}8r~`jKgJK7MR0nrncoss#L?L4dZYUToXr%iG5daDj@BJVV zG7&?%eIKOeA4t}R@a&9gKP1+Bg7~LE584}lL%jG`h~EgKgSe{4x5D_}w6c=0__z52 zl85&aEG8(V{Y~sB9st6_P|! proto = do_GetService("@mozilla.org/network/protocol;1?name=http"); - if (UsingNeckoIPCSecurity()) { - // cache values for core/packaged apps basepaths - nsAutoString corePath, webPath; - nsCOMPtr appsService = do_GetService(APPS_SERVICE_CONTRACTID); - if (appsService) { - appsService->GetCoreAppsBasePath(corePath); - appsService->GetWebAppsBasePath(webPath); - } - // corePath may be empty: we don't use it for all build types - MOZ_ASSERT(!webPath.IsEmpty()); - - LossyCopyUTF16toASCII(corePath, mCoreAppsBasePath); - LossyCopyUTF16toASCII(webPath, mWebAppsBasePath); - } - mObserver = new OfflineObserver(this); gNeckoParent = this; } @@ -617,98 +602,6 @@ NeckoParent::AllocPRemoteOpenFileParent(const SerializedLoadContext& aSerialized } return nullptr; } - - nsAutoCString requestedPath; - fileURL->GetPath(requestedPath); - NS_UnescapeURL(requestedPath); - - // Check if we load the whitelisted app uri for the neterror page. - bool netErrorWhiteList = false; - - if (appUri) { - nsAdoptingString netErrorURI; - netErrorURI = Preferences::GetString("b2g.neterror.url"); - if (netErrorURI) { - nsAutoCString spec; - appUri->GetSpec(spec); - netErrorWhiteList = spec.Equals(NS_ConvertUTF16toUTF8(netErrorURI).get()); - } - } - - // Check if we load a resource from the shared theme url space. - // If we try to load the theme but have no permission, refuse to load. - bool themeWhitelist = false; - if (Preferences::GetBool("dom.mozApps.themable") && appUri) { - nsAutoCString origin; - nsPrincipal::GetOriginForURI(appUri, origin); - nsAutoCString themeOrigin; - themeOrigin = Preferences::GetCString("b2g.theme.origin"); - themeWhitelist = origin.Equals(themeOrigin); - if (themeWhitelist) { - bool hasThemePerm = false; - mozApp->HasPermission("themeable", &hasThemePerm); - if (!hasThemePerm) { - return nullptr; - } - } - } - - if (hasManage || netErrorWhiteList || themeWhitelist) { - // webapps-manage permission means allow reading any application.zip file - // in either the regular webapps directory, or the core apps directory (if - // we're using one). - NS_NAMED_LITERAL_CSTRING(appzip, "/application.zip"); - nsAutoCString pathEnd; - requestedPath.Right(pathEnd, appzip.Length()); - if (!pathEnd.Equals(appzip)) { - return nullptr; - } - nsAutoCString pathStart; - requestedPath.Left(pathStart, mWebAppsBasePath.Length()); - if (!pathStart.Equals(mWebAppsBasePath)) { - if (mCoreAppsBasePath.IsEmpty()) { - return nullptr; - } - requestedPath.Left(pathStart, mCoreAppsBasePath.Length()); - if (!pathStart.Equals(mCoreAppsBasePath)) { - return nullptr; - } - } - // Finally: make sure there are no "../" in URI. - // Note: not checking for symlinks (would cause I/O for each path - // component). So it's up to us to avoid creating symlinks that could - // provide attack vectors. - if (PL_strnstr(requestedPath.BeginReading(), "/../", - requestedPath.Length())) { - printf_stderr("NeckoParent::AllocPRemoteOpenFile: " - "FATAL error: requested file URI '%s' contains '/../' " - "KILLING CHILD PROCESS\n", requestedPath.get()); - return nullptr; - } - } else { - // regular packaged apps can only access their own application.zip file - nsAutoString basePath; - nsresult rv = mozApp->GetBasePath(basePath); - if (NS_FAILED(rv)) { - return nullptr; - } - nsAutoString uuid; - rv = mozApp->GetId(uuid); - if (NS_FAILED(rv)) { - return nullptr; - } - nsPrintfCString mustMatch("%s/%s/application.zip", - NS_LossyConvertUTF16toASCII(basePath).get(), - NS_LossyConvertUTF16toASCII(uuid).get()); - if (!requestedPath.Equals(mustMatch)) { - printf_stderr("NeckoParent::AllocPRemoteOpenFile: " - "FATAL error: app without webapps-manage permission is " - "requesting file '%s' but is only allowed to open its " - "own application.zip at %s: KILLING CHILD PROCESS\n", - requestedPath.get(), mustMatch.get()); - return nullptr; - } - } } RemoteOpenFileParent* parent = new RemoteOpenFileParent(fileURL); diff --git a/netwerk/ipc/NeckoParent.h b/netwerk/ipc/NeckoParent.h index 74dfbacfcc21..330489776711 100644 --- a/netwerk/ipc/NeckoParent.h +++ b/netwerk/ipc/NeckoParent.h @@ -235,8 +235,6 @@ protected: virtual bool RecvRemoveRequestContext(const nsCString& rcid) override; private: - nsCString mCoreAppsBasePath; - nsCString mWebAppsBasePath; RefPtr mObserver; }; diff --git a/netwerk/protocol/app/AppProtocolHandler.cpp b/netwerk/protocol/app/AppProtocolHandler.cpp deleted file mode 100644 index 27235f489290..000000000000 --- a/netwerk/protocol/app/AppProtocolHandler.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set expandtab ts=2 sw=2 sts=2 cin: */ -/* 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 "AppProtocolHandler.h" -#include "nsBaseChannel.h" -#include "nsJARChannel.h" -#include "nsNetCID.h" -#include "nsNetUtil.h" -#include "nsIStandardURL.h" -#include "nsIAppsService.h" -#include "nsILoadInfo.h" -#include "nsXULAppAPI.h" -#include "nsPrincipal.h" -#include "nsContentSecurityManager.h" -#include "nsContentUtils.h" - -#include "mozilla/dom/ScriptSettings.h" -#include "mozilla/Preferences.h" - -using namespace mozilla; - -/** - * This dummy channel implementation only provides enough functionality - * to return a fake 404 error when the caller asks for an app:// URL - * containing an unknown appId. - */ -class DummyChannel : public nsIJARChannel - , Runnable -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIREQUEST - NS_DECL_NSICHANNEL - NS_DECL_NSIJARCHANNEL - - DummyChannel(); - - NS_IMETHODIMP Run() override; - -private: - ~DummyChannel() {} - - bool mPending; - uint32_t mSuspendCount; - nsCOMPtr mListenerContext; - nsCOMPtr mListener; - nsCOMPtr mLoadGroup; - nsLoadFlags mLoadFlags; - nsCOMPtr mLoadInfo; -}; - -NS_IMPL_ISUPPORTS_INHERITED(DummyChannel, Runnable, nsIRequest, nsIChannel, nsIJARChannel) - -DummyChannel::DummyChannel() : mPending(false) - , mSuspendCount(0) - , mLoadFlags(LOAD_NORMAL) -{ -} - -NS_IMETHODIMP DummyChannel::GetName(nsACString &result) -{ - result = "dummy_app_channel"; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::GetStatus(nsresult *aStatus) -{ - *aStatus = NS_ERROR_FILE_NOT_FOUND; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::IsPending(bool *aResult) -{ - *aResult = mPending; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::Suspend() -{ - mSuspendCount++; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::Resume() -{ - if (mSuspendCount <= 0) { - return NS_ERROR_UNEXPECTED; - } - - if (--mSuspendCount == 0) { - NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); - } - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::Open(nsIInputStream**) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -DummyChannel::Open2(nsIInputStream** aStream) -{ - nsCOMPtr listener; - nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); - NS_ENSURE_SUCCESS(rv, rv); - return Open(aStream); -} - -NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext) -{ - MOZ_ASSERT(!mLoadInfo || - mLoadInfo->GetSecurityMode() == 0 || - mLoadInfo->GetInitialSecurityCheckDone() || - (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL && - nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())), - "security flags in loadInfo but asyncOpen2() not called"); - - mListener = aListener; - mListenerContext = aContext; - mPending = true; - - if (mLoadGroup) { - mLoadGroup->AddRequest(this, aContext); - } - - if (mSuspendCount == 0) { - NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); - } - - return NS_OK; -} - -NS_IMETHODIMP -DummyChannel::AsyncOpen2(nsIStreamListener* aListener) -{ - nsCOMPtr listener = aListener; - nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); - NS_ENSURE_SUCCESS(rv, rv); - return AsyncOpen(listener, nullptr); -} - -// nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into -// a 404 error. -NS_IMETHODIMP DummyChannel::GetIsUnsafe(bool *aResult) -{ - *aResult = false; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::SetAppURI(nsIURI *aURI) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetJarFile(nsIFile* *aFile) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetZipEntry(nsIZipEntry* *aEntry) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::Run() -{ - nsresult rv = mListener->OnStartRequest(this, mListenerContext); - mPending = false; - rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND); - if (mLoadGroup) { - mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND); - } - - mListener = nullptr; - mListenerContext = nullptr; - rv = SetNotificationCallbacks(nullptr); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::Cancel(nsresult) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup) -{ - *aLoadGroup = mLoadGroup; - NS_IF_ADDREF(*aLoadGroup); - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) -{ - mLoadGroup = aLoadGroup; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::GetLoadFlags(nsLoadFlags *aLoadFlags) -{ - *aLoadFlags = mLoadFlags; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::SetLoadFlags(nsLoadFlags aLoadFlags) -{ - mLoadFlags = aLoadFlags; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI**) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI*) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetOwner(nsISupports**) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetOwner(nsISupports*) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) -{ - NS_IF_ADDREF(*aLoadInfo = mLoadInfo); - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) -{ - mLoadInfo = aLoadInfo; - return NS_OK; -} - -NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor**) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor*) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports**) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetContentType(nsACString&) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetContentType(const nsACString&) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetContentCharset(nsACString&) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetContentCharset(const nsACString&) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetContentLength(int64_t*) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetContentLength(int64_t) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetContentDisposition(uint32_t*) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetContentDisposition(uint32_t) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetURI(nsIURI**) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetContentDispositionFilename(nsAString&) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::SetContentDispositionFilename(nsAString const &) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/** - * app:// protocol implementation. - */ - -AppProtocolHandler::AppProtocolHandler() { -} - -AppProtocolHandler::~AppProtocolHandler() { - mAppInfoCache.Clear(); -} - -NS_IMPL_ISUPPORTS(AppProtocolHandler, nsIProtocolHandler) - -/* static */ -nsresult -AppProtocolHandler::Create(nsISupports* aOuter, - const nsIID& aIID, - void* *aResult) -{ - // Instantiate the service here since that intializes gJarHandler, which we - // use indirectly (via our new JarChannel) in NewChannel. - nsCOMPtr jarInitializer( - do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar")); - AppProtocolHandler* ph = new AppProtocolHandler(); - if (ph == nullptr) { - return NS_ERROR_OUT_OF_MEMORY; - } - NS_ADDREF(ph); - nsresult rv = ph->QueryInterface(aIID, aResult); - NS_RELEASE(ph); - return rv; -} - -NS_IMETHODIMP -AppProtocolHandler::GetScheme(nsACString &aResult) -{ - aResult.AssignLiteral("app"); - return NS_OK; -} - -NS_IMETHODIMP -AppProtocolHandler::GetDefaultPort(int32_t *aResult) -{ - // No ports for the app protocol. - *aResult = -1; - return NS_OK; -} - -NS_IMETHODIMP -AppProtocolHandler::GetProtocolFlags(uint32_t *aResult) -{ - *aResult = URI_NOAUTH | - URI_DANGEROUS_TO_LOAD | - URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM; - return NS_OK; -} - -NS_IMETHODIMP -AppProtocolHandler::NewURI(const nsACString &aSpec, - const char *aCharset, // ignore charset info - nsIURI *aBaseURI, - nsIURI **result) -{ - nsresult rv; - nsCOMPtr surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr url(do_QueryInterface(surl, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - url.forget(result); - return NS_OK; -} - -NS_IMETHODIMP -AppProtocolHandler::NewChannel2(nsIURI* aUri, - nsILoadInfo* aLoadInfo, - nsIChannel** aResult) -{ - NS_ENSURE_ARG_POINTER(aUri); - RefPtr channel = new nsJARChannel(); - - nsAutoCString host; - nsresult rv = aUri->GetHost(host); - NS_ENSURE_SUCCESS(rv, rv); - - if (Preferences::GetBool("dom.mozApps.themable")) { - nsAutoCString origin; - nsPrincipal::GetOriginForURI(aUri, origin); - nsAdoptingCString themeOrigin; - themeOrigin = Preferences::GetCString("b2g.theme.origin"); - if (themeOrigin.Equals(origin)) { - // We are trying to load a theme resource. Check whether we have a - // package registered as a theme provider to override the file path. - nsAdoptingCString selectedTheme; - selectedTheme = Preferences::GetCString("dom.mozApps.selected_theme"); - if (!selectedTheme.IsEmpty()) { - // Substitute the path with the actual theme. - host = selectedTheme; - } - } - } - - nsAutoCString fileSpec; - nsCOMPtr url = do_QueryInterface(aUri); - rv = url->GetFilePath(fileSpec); - NS_ENSURE_SUCCESS(rv, rv); - - mozilla::dom::AppInfo *appInfo; - - if (!mAppInfoCache.Get(host, &appInfo)) { - nsCOMPtr appsService = do_GetService(APPS_SERVICE_CONTRACTID); - if (!appsService) { - return NS_ERROR_FAILURE; - } - - mozilla::AutoSafeJSContext cx; - JS::RootedValue jsInfo(cx); - rv = appsService->GetAppInfo(NS_ConvertUTF8toUTF16(host), &jsInfo); - if (NS_FAILED(rv) || !jsInfo.isObject()) { - // Return a DummyChannel. - printf_stderr("!! Creating a dummy channel for %s (no appInfo)\n", host.get()); - RefPtr dummyChannel = new DummyChannel(); - dummyChannel->SetLoadInfo(aLoadInfo); - dummyChannel.forget(aResult); - return NS_OK; - } - - appInfo = new mozilla::dom::AppInfo(); - JSAutoCompartment ac(cx, &jsInfo.toObject()); - if (!appInfo->Init(cx, jsInfo) || appInfo->mPath.IsEmpty()) { - // Return a DummyChannel. - printf_stderr("!! Creating a dummy channel for %s (invalid appInfo)\n", host.get()); - RefPtr dummyChannel = new DummyChannel(); - dummyChannel->SetLoadInfo(aLoadInfo); - dummyChannel.forget(aResult); - return NS_OK; - } - mAppInfoCache.Put(host, appInfo); - } - - // Even core apps are on /system partition and can be accessed directly, but - // to ease sandboxing code not to handle the special case of core apps, only - // use scheme jar:file in parent, see bug 1119692 comment 20. - nsAutoCString jarSpec(XRE_IsParentProcess() ? "jar:file://" - : "jar:remoteopenfile://"); - jarSpec += NS_ConvertUTF16toUTF8(appInfo->mPath) + - NS_LITERAL_CSTRING("/application.zip!") + - fileSpec; - - nsCOMPtr jarURI; - rv = NS_NewURI(getter_AddRefs(jarURI), - jarSpec, nullptr, nullptr); - NS_ENSURE_SUCCESS(rv, rv); - - rv = channel->Init(jarURI); - NS_ENSURE_SUCCESS(rv, rv); - - // set the loadInfo on the new channel - rv = channel->SetLoadInfo(aLoadInfo); - NS_ENSURE_SUCCESS(rv, rv); - - rv = channel->SetAppURI(aUri); - NS_ENSURE_SUCCESS(rv, rv); - - rv = channel->SetOriginalURI(aUri); - NS_ENSURE_SUCCESS(rv, rv); - - channel.forget(aResult); - return NS_OK; -} - -// We map app://ABCDEF/path/to/file.ext to -// jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext -NS_IMETHODIMP -AppProtocolHandler::NewChannel(nsIURI* aUri, nsIChannel* *aResult) -{ - return NewChannel2(aUri, nullptr, aResult); -} - -NS_IMETHODIMP -AppProtocolHandler::AllowPort(int32_t aPort, const char *aScheme, bool *aRetval) -{ - // No port allowed for this scheme. - *aRetval = false; - return NS_OK; -} - diff --git a/netwerk/protocol/app/AppProtocolHandler.h b/netwerk/protocol/app/AppProtocolHandler.h deleted file mode 100644 index e1819900437c..000000000000 --- a/netwerk/protocol/app/AppProtocolHandler.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim:set expandtab ts=4 sw=4 sts=4 cin: */ -/* 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/. */ - -#ifndef AppProtocolHandler_ -#define AppProtocolHandler_ - -#include "nsIProtocolHandler.h" -#include "nsClassHashtable.h" -#include "mozilla/dom/AppInfoBinding.h" - -class AppProtocolHandler : public nsIProtocolHandler -{ -public: - NS_DECL_ISUPPORTS - - // nsIProtocolHandler methods: - NS_DECL_NSIPROTOCOLHANDLER - - // AppProtocolHandler methods: - AppProtocolHandler(); - - // Define a Create method to be used with a factory: - static nsresult Create(nsISupports* aOuter, - const nsIID& aIID, - void* *aResult); - -private: - virtual ~AppProtocolHandler(); - nsClassHashtable mAppInfoCache; -}; - -#endif /* AppProtocolHandler_ */ diff --git a/netwerk/protocol/app/moz.build b/netwerk/protocol/app/moz.build deleted file mode 100644 index f71e7ec8d7ce..000000000000 --- a/netwerk/protocol/app/moz.build +++ /dev/null @@ -1,16 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -SOURCES += [ - 'AppProtocolHandler.cpp', -] - -FINAL_LIBRARY = 'xul' -LOCAL_INCLUDES += [ - '/caps', - '/modules/libjar', - '/netwerk/base', -] diff --git a/old-configure.in b/old-configure.in index e2b42f08c20a..8d4a8b51dcc8 100644 --- a/old-configure.in +++ b/old-configure.in @@ -2640,7 +2640,7 @@ fi MOZ_NO_SMART_CARDS= NSS_DISABLE_DBM= NECKO_COOKIES=1 -NECKO_PROTOCOLS_DEFAULT="about app data file ftp http res viewsource websocket wyciwyg device" +NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device" if test -n "$MOZ_RTSP"; then NECKO_PROTOCOLS_DEFAULT="$NECKO_PROTOCOLS_DEFAULT rtsp" fi From 01865c930aba6eb53dd86957b971a724006feeb8 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Fri, 8 Jul 2016 07:26:12 +0200 Subject: [PATCH 12/30] Bug 1277557 - CSP require-sri-for does not block when CSP is in meta tag r=francois --- netwerk/base/LoadInfo.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 52e0467b065b..0cfad010b87d 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -150,14 +150,24 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, // do not look into the CSP if already true: // a CSP saying that SRI isn't needed should not // overrule GetVerifySignedContent - nsCOMPtr csp; if (aLoadingPrincipal) { + nsCOMPtr csp; aLoadingPrincipal->GetCsp(getter_AddRefs(csp)); + uint32_t externalType = + nsContentUtils::InternalContentPolicyTypeToExternal(aContentPolicyType); // csp could be null if loading principal is system principal if (csp) { - uint32_t loadType = - nsContentUtils::InternalContentPolicyTypeToExternal(aContentPolicyType); - csp->RequireSRIForType(loadType, &mEnforceSRI); + csp->RequireSRIForType(externalType, &mEnforceSRI); + } + // if CSP is delivered via a meta tag, it's speculatively available + // as 'preloadCSP'. If we are preloading a script or style, we have + // to apply that speculative 'preloadCSP' for such loads. + if (!mEnforceSRI && nsContentUtils::IsPreloadType(aContentPolicyType)) { + nsCOMPtr preloadCSP; + aLoadingPrincipal->GetPreloadCsp(getter_AddRefs(preloadCSP)); + if (preloadCSP) { + preloadCSP->RequireSRIForType(externalType, &mEnforceSRI); + } } } } From 84f2bb53026921938ca37b0460e3c69160f539f6 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Fri, 8 Jul 2016 07:26:34 +0200 Subject: [PATCH 13/30] Bug 1277557 - Test require-sri-for in meta tag r=francois --- .../test/csp/file_require_sri_meta.js | 1 + .../test/csp/file_require_sri_meta.sjs | 54 +++++++++++++ dom/security/test/csp/mochitest.ini | 3 + .../test/csp/test_require_sri_meta.html | 77 +++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 dom/security/test/csp/file_require_sri_meta.js create mode 100644 dom/security/test/csp/file_require_sri_meta.sjs create mode 100644 dom/security/test/csp/test_require_sri_meta.html diff --git a/dom/security/test/csp/file_require_sri_meta.js b/dom/security/test/csp/file_require_sri_meta.js new file mode 100644 index 000000000000..af0113297eb5 --- /dev/null +++ b/dom/security/test/csp/file_require_sri_meta.js @@ -0,0 +1 @@ +var foo = 24; diff --git a/dom/security/test/csp/file_require_sri_meta.sjs b/dom/security/test/csp/file_require_sri_meta.sjs new file mode 100644 index 000000000000..acaf742db0a3 --- /dev/null +++ b/dom/security/test/csp/file_require_sri_meta.sjs @@ -0,0 +1,54 @@ +// custom *.sjs for Bug 1277557 +// META CSP: require-sri-for script; + +const PRE_INTEGRITY = + "" + + "" + + "Bug 1277557 - CSP require-sri-for does not block when CSP is in meta tag" + + "" + + "" + + "" + + "" + + "" + + ""; + +function handleRequest(request, response) +{ + // avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + + var queryString = request.queryString; + + if (queryString === "no-sri") { + response.write(PRE_INTEGRITY + POST_INTEGRITY); + return; + } + + if (queryString === "wrong-sri") { + response.write(PRE_INTEGRITY + WRONG_INTEGRITY + POST_INTEGRITY); + return; + } + + if (queryString === "correct-sri") { + response.write(PRE_INTEGRITY + CORRECT_INEGRITY + POST_INTEGRITY); + return; + } + + // we should never get here, but just in case + // return something unexpected + response.write("do'h"); +} diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini index 4f9636f98e0a..e627be4243a7 100644 --- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -182,6 +182,8 @@ support-files = file_sandbox_10.html file_sandbox_11.html file_sandbox_12.html + file_require_sri_meta.sjs + file_require_sri_meta.js [test_base-uri.html] [test_blob_data_schemes.html] @@ -272,3 +274,4 @@ tags = mcb [test_iframe_sandbox_top_1.html] [test_sandbox.html] [test_ping.html] +[test_require_sri_meta.html] diff --git a/dom/security/test/csp/test_require_sri_meta.html b/dom/security/test/csp/test_require_sri_meta.html new file mode 100644 index 000000000000..a06fe122a461 --- /dev/null +++ b/dom/security/test/csp/test_require_sri_meta.html @@ -0,0 +1,77 @@ + + + + + Bug 1277557 - CSP require-sri-for does not block when CSP is in meta tag + + + + + + + + + + From 3dedc86d90ba3e67e7c5a65ce9dadec8c343f657 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Fri, 8 Jul 2016 13:17:42 +0900 Subject: [PATCH 14/30] Bug 1277908 - Keep visited rule node alive while creating non-visited style context; r=dholbert MozReview-Commit-ID: Eqti28E14Jp --HG-- extra : rebase_source : b1ab439dd85e87c11dcc5a85b70fcc21a48e328e --- layout/style/nsStyleSet.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 3b068b63ef32..61f04a14df3a 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -908,6 +908,13 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext, relevantLinkVisited); if (!result) { + // |aVisitedRuleNode| may have a ref-count of zero since we are yet + // to create the style context that will hold an owning reference to it. + // As a result, we need to make sure it stays alive until that point + // in case something in the first call to NS_NewStyleContext triggers a + // GC sweep of rule nodes. + RefPtr kungFuDeathGrip{aVisitedRuleNode}; + result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType, aRuleNode, aFlags & eSkipParentDisplayBasedStyleFixup); From cebbecb62d70e1bc4e3a6a5094743a32f22ae1ff Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 29 Jun 2016 12:57:00 +0200 Subject: [PATCH 15/30] Bug 1283268 - Change nsAutoPtr to UniquePtr in EventTree and Accessible classes. r=nfroyd --- accessible/base/EventTree.cpp | 38 +++++++++++++++++-------------- accessible/base/EventTree.h | 5 ++-- accessible/generic/Accessible.cpp | 10 ++++---- accessible/generic/Accessible.h | 5 ++-- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/accessible/base/EventTree.cpp b/accessible/base/EventTree.cpp index 232f17eef957..2f57758e346e 100644 --- a/accessible/base/EventTree.cpp +++ b/accessible/base/EventTree.cpp @@ -12,6 +12,8 @@ #include "Logging.h" #endif +#include "mozilla/UniquePtr.h" + using namespace mozilla; using namespace mozilla::a11y; @@ -162,7 +164,7 @@ EventTree::Process(const RefPtr& aDeathGrip) return; } } - mFirst = mFirst->mNext.forget(); + mFirst = Move(mFirst->mNext); } MOZ_ASSERT(mContainer || mDependentEvents.IsEmpty(), @@ -229,11 +231,12 @@ EventTree* EventTree::FindOrInsert(Accessible* aContainer) { if (!mFirst) { - return mFirst = new EventTree(aContainer, true); + mFirst.reset(new EventTree(aContainer, true)); + return mFirst.get(); } EventTree* prevNode = nullptr; - EventTree* node = mFirst; + EventTree* node = mFirst.get(); do { MOZ_ASSERT(!node->mContainer->IsApplication(), "No event for application accessible is expected here"); @@ -277,18 +280,18 @@ EventTree::FindOrInsert(Accessible* aContainer) // Insert the tail node into the hierarchy between the current node and // its parent. node->mFireReorder = false; - nsAutoPtr& nodeOwnerRef = prevNode ? prevNode->mNext : mFirst; - nsAutoPtr newNode(new EventTree(aContainer, mDependentEvents.IsEmpty())); + UniquePtr& nodeOwnerRef = prevNode ? prevNode->mNext : mFirst; + UniquePtr newNode(new EventTree(aContainer, mDependentEvents.IsEmpty())); newNode->mFirst = Move(nodeOwnerRef); nodeOwnerRef = Move(newNode); nodeOwnerRef->mNext = Move(node->mNext); // Check if a next node is contained by the given node too, and move them // under the given node if so. - prevNode = nodeOwnerRef; - node = nodeOwnerRef->mNext; - nsAutoPtr* nodeRef = &nodeOwnerRef->mNext; - EventTree* insNode = nodeOwnerRef->mFirst; + prevNode = nodeOwnerRef.get(); + node = nodeOwnerRef->mNext.get(); + UniquePtr* nodeRef = &nodeOwnerRef->mNext; + EventTree* insNode = nodeOwnerRef->mFirst.get(); while (node) { Accessible* curParent = node->mContainer; while (curParent && !curParent->IsDoc()) { @@ -301,7 +304,7 @@ EventTree::FindOrInsert(Accessible* aContainer) node->mFireReorder = false; insNode->mNext = Move(*nodeRef); - insNode = insNode->mNext; + insNode = insNode->mNext.get(); prevNode->mNext = Move(node->mNext); node = prevNode; @@ -310,14 +313,14 @@ EventTree::FindOrInsert(Accessible* aContainer) prevNode = node; nodeRef = &node->mNext; - node = node->mNext; + node = node->mNext.get(); } - return nodeOwnerRef; + return nodeOwnerRef.get(); } prevNode = node; - } while ((node = node->mNext)); + } while ((node = node->mNext.get())); MOZ_ASSERT(prevNode, "Nowhere to insert"); MOZ_ASSERT(!prevNode->mNext, "Taken by another node"); @@ -327,7 +330,8 @@ EventTree::FindOrInsert(Accessible* aContainer) // if a dependent show event target contains the given container then do not // emit show / hide events (see Process() method) - return prevNode->mNext = new EventTree(aContainer, mDependentEvents.IsEmpty()); + prevNode->mNext.reset(new EventTree(aContainer, mDependentEvents.IsEmpty())); + return prevNode->mNext.get(); } void @@ -357,14 +361,14 @@ EventTree::Find(const Accessible* aContainer) const } if (et->mFirst) { - et = et->mFirst; + et = et->mFirst.get(); const EventTree* cet = et->Find(aContainer); if (cet) { return cet; } } - et = et->mNext; + et = et->mNext.get(); const EventTree* cet = et->Find(aContainer); if (cet) { return cet; @@ -421,7 +425,7 @@ EventTree::Mutated(AccMutationEvent* aEv) { // If shown or hidden node is a root of previously mutated subtree, then // discard those subtree mutations as we are no longer interested in them. - nsAutoPtr* node = &mFirst; + UniquePtr* node = &mFirst; while (*node) { if ((*node)->mContainer == aEv->mAccessible) { *node = Move((*node)->mNext); diff --git a/accessible/base/EventTree.h b/accessible/base/EventTree.h index eab6d37a2672..3c12d0ab130b 100644 --- a/accessible/base/EventTree.h +++ b/accessible/base/EventTree.h @@ -10,6 +10,7 @@ #include "Accessible.h" #include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" namespace mozilla { namespace a11y { @@ -101,8 +102,8 @@ private: void Mutated(AccMutationEvent* aEv); void Clear(); - nsAutoPtr mFirst; - nsAutoPtr mNext; + UniquePtr mFirst; + UniquePtr mNext; Accessible* mContainer; nsTArray> mDependentEvents; diff --git a/accessible/generic/Accessible.cpp b/accessible/generic/Accessible.cpp index 28e7ac83ed43..49a962315589 100644 --- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -2211,7 +2211,7 @@ Accessible::EmbeddedChildCount() { if (mStateFlags & eHasTextKids) { if (!mEmbeddedObjCollector) - mEmbeddedObjCollector = new EmbeddedObjCollector(this); + mEmbeddedObjCollector.reset(new EmbeddedObjCollector(this)); return mEmbeddedObjCollector->Count(); } @@ -2223,8 +2223,8 @@ Accessible::GetEmbeddedChildAt(uint32_t aIndex) { if (mStateFlags & eHasTextKids) { if (!mEmbeddedObjCollector) - mEmbeddedObjCollector = new EmbeddedObjCollector(this); - return mEmbeddedObjCollector ? + mEmbeddedObjCollector.reset(new EmbeddedObjCollector(this)); + return mEmbeddedObjCollector.get() ? mEmbeddedObjCollector->GetAccessibleAt(aIndex) : nullptr; } @@ -2236,8 +2236,8 @@ Accessible::GetIndexOfEmbeddedChild(Accessible* aChild) { if (mStateFlags & eHasTextKids) { if (!mEmbeddedObjCollector) - mEmbeddedObjCollector = new EmbeddedObjCollector(this); - return mEmbeddedObjCollector ? + mEmbeddedObjCollector.reset(new EmbeddedObjCollector(this)); + return mEmbeddedObjCollector.get() ? mEmbeddedObjCollector->GetIndexAt(aChild) : -1; } diff --git a/accessible/generic/Accessible.h b/accessible/generic/Accessible.h index 2e11a2cfba71..1050387252da 100644 --- a/accessible/generic/Accessible.h +++ b/accessible/generic/Accessible.h @@ -11,7 +11,8 @@ #include "mozilla/a11y/Role.h" #include "mozilla/a11y/States.h" -#include "nsAutoPtr.h" +#include "mozilla/UniquePtr.h" + #include "nsIContent.h" #include "nsString.h" #include "nsTArray.h" @@ -1138,7 +1139,7 @@ protected: friend class xpcAccessible; friend class TreeMutation; - nsAutoPtr mEmbeddedObjCollector; + UniquePtr mEmbeddedObjCollector; union { int32_t mIndexOfEmbeddedChild; uint32_t mProxyInterfaces; From d21c56347ac150a6cdc4d78548a3c9a768d1e485 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Mon, 4 Jul 2016 10:20:05 +0200 Subject: [PATCH 16/30] Bug 1284202 - Add deprecation warning for SEC_NORMAL. r=tanvi --- netwerk/base/nsILoadInfo.idl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 7a2d329e8278..7b10d4c611f6 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -33,7 +33,10 @@ typedef unsigned long nsSecurityFlags; interface nsILoadInfo : nsISupports { /** - * No special security flags: + * *** DEPRECATED *** + * No LoadInfo created within Gecko should contain this security flag. + * Please use any of the five security flags defined underneath. + * We only keep this security flag to provide backwards compatibilty. */ const unsigned long SEC_NORMAL = 0; From 7333d17d573d491e39a254367c469f632663b257 Mon Sep 17 00:00:00 2001 From: Rob Thijssen Date: Thu, 7 Jul 2016 14:08:09 +0100 Subject: [PATCH 17/30] Bug 1285222 - set case for z: rather than x: drive. r=pmoore --- taskcluster/ci/legacy/tasks/builds/firefox_windows_base.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskcluster/ci/legacy/tasks/builds/firefox_windows_base.yml b/taskcluster/ci/legacy/tasks/builds/firefox_windows_base.yml index 6aa563e0bd23..11a9b3f003ab 100644 --- a/taskcluster/ci/legacy/tasks/builds/firefox_windows_base.yml +++ b/taskcluster/ci/legacy/tasks/builds/firefox_windows_base.yml @@ -11,4 +11,4 @@ task: - 'mkdir .\build\src' - 'hg share c:\builds\hg-shared\mozilla-central .\build\src' - 'hg pull -u -R .\build\src --rev %GECKO_HEAD_REV% %GECKO_HEAD_REPOSITORY%' - - 'c:\mozilla-build\python\python.exe .\build\src\testing\mozharness\scripts\fx_desktop_build.py --config builds\taskcluster_firefox_{{build_name}}_{{build_type}}.py --branch {{project}} --skip-buildbot-actions --work-dir %cd:X:=x:%\build' + - 'c:\mozilla-build\python\python.exe .\build\src\testing\mozharness\scripts\fx_desktop_build.py --config builds\taskcluster_firefox_{{build_name}}_{{build_type}}.py --branch {{project}} --skip-buildbot-actions --work-dir %cd:Z:=z:%\build' From a66e2b79e928a5d08a15c8edd6f9467f839ab97a Mon Sep 17 00:00:00 2001 From: Morris Tseng Date: Fri, 8 Jul 2016 14:58:03 +0800 Subject: [PATCH 18/30] Bug 1284440 - Prevent CreateRenderTargetForWindow from clearing unwanted area. r=mattwoodrow MozReview-Commit-ID: BhUlnThiI2 --- gfx/layers/basic/BasicCompositor.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 2de39d3fc01b..fd0169c0524b 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -621,12 +621,19 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, clearRect = mInvalidRect; } + // Prevent CreateRenderTargetForWindow from clearing unwanted area. + gfxUtils::ClipToRegion(mDrawTarget, + mInvalidRegion.ToUnknownRegion()); + // Setup an intermediate render target to buffer all compositing. We will // copy this into mDrawTarget (the widget), and/or mTarget in EndFrame() RefPtr target = CreateRenderTargetForWindow(mInvalidRect, clearRect, bufferMode); + + mDrawTarget->PopClip(); + if (!target) { if (!mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); From 3054bd3c6ab4f8d994db6f5306eaf93202763310 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 8 Jul 2016 09:08:47 +0200 Subject: [PATCH 19/30] Bug 1283344 - Change the creation time of in some dom/filesystem tests, r=me --- dom/filesystem/tests/test_basic.html | 10 +++++----- dom/filesystem/tests/test_worker_basic.html | 9 ++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dom/filesystem/tests/test_basic.html b/dom/filesystem/tests/test_basic.html index 4cc3bff13bd7..0b0fa97ebc6d 100644 --- a/dom/filesystem/tests/test_basic.html +++ b/dom/filesystem/tests/test_basic.html @@ -8,17 +8,20 @@ - + + diff --git a/dom/push/test/xpcshell/xpcshell.ini b/dom/push/test/xpcshell/xpcshell.ini index 63ddfcc81b92..8ba71baa513b 100644 --- a/dom/push/test/xpcshell/xpcshell.ini +++ b/dom/push/test/xpcshell/xpcshell.ini @@ -1,6 +1,7 @@ [DEFAULT] head = head.js head-http2.js tail = +firefox-appdir = browser # Push notifications and alarms are currently disabled on Android. skip-if = toolkit == 'android' diff --git a/toolkit/forgetaboutsite/test/unit/xpcshell.ini b/toolkit/forgetaboutsite/test/unit/xpcshell.ini index b5f3268f1891..4e0420a435ee 100644 --- a/toolkit/forgetaboutsite/test/unit/xpcshell.ini +++ b/toolkit/forgetaboutsite/test/unit/xpcshell.ini @@ -1,6 +1,7 @@ [DEFAULT] head = head_forgetaboutsite.js ../../../../dom/push/test/xpcshell/head.js tail = +firefox-appdir = browser skip-if = toolkit == 'android' || toolkit == 'gonk' support-files = !/dom/push/test/xpcshell/head.js From df55ce4a13dbf7191787dac04e49db586bad3532 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 5 Jul 2016 15:55:53 +0200 Subject: [PATCH 22/30] Bug 1268024: Minimal signal handling features to catch and reject SIGBUS; r=luke, r=sunfish MozReview-Commit-ID: 5S2SQdoyRFE --HG-- extra : rebase_source : 5c7495d615d09a2826eea1338c0c1931b0b588bb --- js/src/asmjs/WasmSignalHandlers.cpp | 58 ++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/js/src/asmjs/WasmSignalHandlers.cpp b/js/src/asmjs/WasmSignalHandlers.cpp index a311c81a8766..5ef285de3574 100644 --- a/js/src/asmjs/WasmSignalHandlers.cpp +++ b/js/src/asmjs/WasmSignalHandlers.cpp @@ -733,8 +733,11 @@ MOZ_COLD static uint8_t* EmulateHeapAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddress, const MemoryAccess* memoryAccess, const Instance& instance) { - // TODO: Implement unaligned accesses. - return instance.codeSegment().outOfBoundsCode(); + // We forbid ARM instruction sets below ARMv7, so that solves unaligned + // integer memory accesses. So the only way to land here is because of a + // non-default configured kernel or an unaligned floating-point access. + // TODO Handle FPU unaligned accesses on ARM (bug 1283121). + return instance.codeSegment().unalignedAccessCode(); } #endif // defined(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_UNALIGNED) @@ -1097,16 +1100,28 @@ MachExceptionHandler::install(JSRuntime* rt) #else // If not Windows or Mac, assume Unix +enum class Signal { + SegFault, + BusError +}; + // Be very cautious and default to not handling; we don't want to accidentally // silence real crashes from real bugs. +template static bool HandleFault(int signum, siginfo_t* info, void* ctx) { // The signals we're expecting come from access violations, accessing // mprotected memory. If the signal originates anywhere else, don't try // to handle it. - MOZ_RELEASE_ASSERT(signum == SIGSEGV); - if (info->si_code != SEGV_ACCERR) + if (signal == Signal::SegFault) + MOZ_RELEASE_ASSERT(signum == SIGSEGV); + else + MOZ_RELEASE_ASSERT(signum == SIGBUS); + + if (signal == Signal::SegFault && info->si_code != SEGV_ACCERR) + return false; + if (signal == Signal::BusError && info->si_code != BUS_ADRALN) return false; CONTEXT* context = (CONTEXT*)ctx; @@ -1135,7 +1150,7 @@ HandleFault(int signum, siginfo_t* info, void* ctx) return false; const MemoryAccess* memoryAccess = instance.lookupMemoryAccess(pc); - if (!memoryAccess) + if (signal == Signal::SegFault && !memoryAccess) return false; *ppc = EmulateHeapAccess(context, pc, faultingAddress, memoryAccess, instance); @@ -1144,13 +1159,19 @@ HandleFault(int signum, siginfo_t* info, void* ctx) } static struct sigaction sPrevSEGVHandler; +static struct sigaction sPrevSIGBUSHandler; +template static void AsmJSFaultHandler(int signum, siginfo_t* info, void* context) { - if (HandleFault(signum, info, context)) + if (HandleFault(signum, info, context)) return; + struct sigaction* previousSignal = signal == Signal::SegFault + ? &sPrevSEGVHandler + : &sPrevSIGBUSHandler; + // This signal is not for any asm.js code we expect, so we need to forward // the signal to the next handler. If there is no next handler (SIG_IGN or // SIG_DFL), then it's time to crash. To do this, we set the signal back to @@ -1163,15 +1184,14 @@ AsmJSFaultHandler(int signum, siginfo_t* info, void* context) // signal to it's original disposition and returning. // // Note: the order of these tests matter. - if (sPrevSEGVHandler.sa_flags & SA_SIGINFO) - sPrevSEGVHandler.sa_sigaction(signum, info, context); - else if (sPrevSEGVHandler.sa_handler == SIG_DFL || sPrevSEGVHandler.sa_handler == SIG_IGN) - sigaction(signum, &sPrevSEGVHandler, nullptr); + if (previousSignal->sa_flags & SA_SIGINFO) + previousSignal->sa_sigaction(signum, info, context); + else if (previousSignal->sa_handler == SIG_DFL || previousSignal->sa_handler == SIG_IGN) + sigaction(signum, previousSignal, nullptr); else - sPrevSEGVHandler.sa_handler(signum); + previousSignal->sa_handler(signum); } -#endif - +# endif // XP_WIN || XP_DARWIN || assume unix #endif // defined(ASMJS_MAY_USE_SIGNAL_HANDLERS) static void @@ -1303,12 +1323,22 @@ wasm::EnsureSignalHandlersInstalled(JSRuntime* rt) // SA_NODEFER allows us to reenter the signal handler if we crash while // handling the signal, and fall through to the Breakpad handler by testing // handlingSegFault. + +# if defined(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB) struct sigaction faultHandler; faultHandler.sa_flags = SA_SIGINFO | SA_NODEFER; - faultHandler.sa_sigaction = &AsmJSFaultHandler; + faultHandler.sa_sigaction = &AsmJSFaultHandler; sigemptyset(&faultHandler.sa_mask); if (sigaction(SIGSEGV, &faultHandler, &sPrevSEGVHandler)) MOZ_CRASH("unable to install segv handler"); +# elif defined(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_UNALIGNED) + struct sigaction busHandler; + busHandler.sa_flags = SA_SIGINFO | SA_NODEFER; + busHandler.sa_sigaction = &AsmJSFaultHandler; + sigemptyset(&busHandler.sa_mask); + if (sigaction(SIGBUS, &busHandler, &sPrevSIGBUSHandler)) + MOZ_CRASH("unable to install sigbus handler"); +# endif # endif #endif // defined(ASMJS_MAY_USE_SIGNAL_HANDLERS) From 607a6490d3c0abe7b754e2cd0c061d1a728ba899 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Wed, 6 Jul 2016 16:29:03 +0200 Subject: [PATCH 23/30] Bug 1268024: Baldr: implement WasmBoundsCheck/Load/Store and semantics; r=luke, r=sunfish MozReview-Commit-ID: 7UOAz6OvNOO --HG-- extra : rebase_source : 140121cd3297d65c954a1877fea479c7d6077633 --- js/src/asmjs/WasmBaselineCompile.cpp | 29 +-- js/src/asmjs/WasmIonCompile.cpp | 140 ++++------- js/src/asmjs/WasmModule.h | 2 +- js/src/asmjs/WasmSignalHandlers.cpp | 7 + js/src/jit/AliasAnalysisShared.cpp | 2 + js/src/jit/MIR.h | 92 ++++++- js/src/jit/MIRGenerator.h | 1 - js/src/jit/MIRGraph.cpp | 10 +- js/src/jit/MOpcodes.h | 3 + js/src/jit/arm/Assembler-arm.h | 1 + js/src/jit/arm/CodeGenerator-arm.cpp | 113 +++++++++ js/src/jit/arm/CodeGenerator-arm.h | 3 + js/src/jit/arm/Lowering-arm.cpp | 42 ++++ js/src/jit/arm/Lowering-arm.h | 3 + js/src/jit/arm64/Lowering-arm64.cpp | 18 ++ js/src/jit/arm64/Lowering-arm64.h | 3 + js/src/jit/shared/LIR-shared.h | 57 +++++ js/src/jit/shared/LOpcodes-shared.h | 3 + js/src/jit/x64/CodeGenerator-x64.cpp | 232 +++++++++++------- js/src/jit/x64/CodeGenerator-x64.h | 8 +- js/src/jit/x64/Lowering-x64.cpp | 34 +++ js/src/jit/x64/Lowering-x64.h | 1 + js/src/jit/x86-shared/Assembler-x86-shared.h | 31 ++- .../x86-shared/CodeGenerator-x86-shared.cpp | 37 ++- .../jit/x86-shared/CodeGenerator-x86-shared.h | 23 +- js/src/jit/x86-shared/Lowering-x86-shared.cpp | 21 ++ js/src/jit/x86-shared/Lowering-x86-shared.h | 2 + js/src/jit/x86-shared/Patching-x86-shared.h | 11 - js/src/jit/x86/CodeGenerator-x86.cpp | 101 +++++--- js/src/jit/x86/CodeGenerator-x86.h | 6 +- js/src/jit/x86/Lowering-x86.cpp | 34 +++ js/src/jit/x86/Lowering-x86.h | 1 + 32 files changed, 795 insertions(+), 276 deletions(-) diff --git a/js/src/asmjs/WasmBaselineCompile.cpp b/js/src/asmjs/WasmBaselineCompile.cpp index e30b09860d4d..2e95aad01745 100644 --- a/js/src/asmjs/WasmBaselineCompile.cpp +++ b/js/src/asmjs/WasmBaselineCompile.cpp @@ -2710,13 +2710,12 @@ class BaseCompiler #if defined(JS_CODEGEN_X64) // Copied from CodeGenerator-x64.cpp // TODO / CLEANUP - share with the code generator. - - wasm::MemoryAccess - AsmJSMemoryAccess(uint32_t before, wasm::MemoryAccess::OutOfBoundsBehavior throwBehavior, - uint32_t offsetWithinWholeSimdVector = 0) + MemoryAccess + WasmMemoryAccess(uint32_t before) { - return wasm::MemoryAccess(before, throwBehavior, wasm::MemoryAccess::WrapOffset, - offsetWithinWholeSimdVector); + if (isCompilingAsmJS()) + return MemoryAccess(before, MemoryAccess::CarryOn, MemoryAccess::WrapOffset); + return MemoryAccess(before, MemoryAccess::Throw, MemoryAccess::DontWrapOffset); } #endif @@ -2760,6 +2759,11 @@ class BaseCompiler #endif void loadHeap(const MWasmMemoryAccess& access, RegI32 ptr, AnyReg dest) { + if (access.offset() > INT32_MAX) { + masm.jump(wasm::JumpTarget::OutOfBounds); + return; + } + #if defined(JS_CODEGEN_X64) // CodeGeneratorX64::visitAsmJSLoadHeap() @@ -2783,7 +2787,7 @@ class BaseCompiler } uint32_t after = masm.size(); - masm.append(AsmJSMemoryAccess(before, wasm::MemoryAccess::CarryOn)); + masm.append(WasmMemoryAccess(before)); verifyHeapAccessDisassembly(before, after, IsLoad(true), access.accessType(), 0, srcAddr, dest); #else MOZ_CRASH("BaseCompiler platform hook: loadHeap"); @@ -2814,7 +2818,7 @@ class BaseCompiler } uint32_t after = masm.size(); - masm.append(AsmJSMemoryAccess(before, wasm::MemoryAccess::CarryOn)); + masm.append(WasmMemoryAccess(before)); verifyHeapAccessDisassembly(before, after, IsLoad(false), access.accessType(), 0, dstAddr, src); #else MOZ_CRASH("BaseCompiler platform hook: storeHeap"); @@ -5210,8 +5214,7 @@ BaseCompiler::emitLoad(ValType type, Scalar::Type viewType) // TODO / OPTIMIZE: Disable bounds checking on constant accesses // below the minimum heap length. - MWasmMemoryAccess access(viewType, addr.align); - access.setOffset(addr.offset); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); switch (type) { case ValType::I32: { @@ -5260,8 +5263,7 @@ BaseCompiler::emitStore(ValType resultType, Scalar::Type viewType) // TODO / OPTIMIZE: Disable bounds checking on constant accesses // below the minimum heap length. - MWasmMemoryAccess access(viewType, addr.align); - access.setOffset(addr.offset); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); switch (resultType) { case ValType::I32: { @@ -5540,8 +5542,7 @@ BaseCompiler::emitStoreWithCoercion(ValType resultType, Scalar::Type viewType) // TODO / OPTIMIZE: Disable bounds checking on constant accesses // below the minimum heap length. - MWasmMemoryAccess access(viewType, addr.align); - access.setOffset(addr.offset); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); if (resultType == ValType::F32 && viewType == Scalar::Float64) { RegF32 rv = popF32(); diff --git a/js/src/asmjs/WasmIonCompile.cpp b/js/src/asmjs/WasmIonCompile.cpp index 6a7effb1b9ad..937fd2c6913f 100644 --- a/js/src/asmjs/WasmIonCompile.cpp +++ b/js/src/asmjs/WasmIonCompile.cpp @@ -594,7 +594,16 @@ class FunctionCompiler { if (inDeadCode()) return nullptr; - MAsmJSLoadHeap* load = MAsmJSLoadHeap::New(alloc(), base, access); + + MInstruction* load = nullptr; + if (mg().kind == ModuleKind::Wasm) { + if (!mg().usesSignal.forOOB) + curBlock_->add(MWasmBoundsCheck::New(alloc(), base, access)); + load = MWasmLoad::New(alloc(), base, access); + } else { + load = MAsmJSLoadHeap::New(alloc(), base, access); + } + curBlock_->add(load); return load; } @@ -603,7 +612,16 @@ class FunctionCompiler { if (inDeadCode()) return; - MAsmJSStoreHeap* store = MAsmJSStoreHeap::New(alloc(), base, access, v); + + MInstruction* store = nullptr; + if (mg().kind == ModuleKind::Wasm) { + if (!mg().usesSignal.forOOB) + curBlock_->add(MWasmBoundsCheck::New(alloc(), base, access)); + store = MWasmStore::New(alloc(), base, access, v); + } else { + store = MAsmJSStoreHeap::New(alloc(), base, access, v); + } + curBlock_->add(store); } @@ -2055,32 +2073,6 @@ EmitSelect(FunctionCompiler& f) return true; } -enum class IsAtomic { - No = false, - Yes = true -}; - -static bool -SetHeapAccessOffset(FunctionCompiler& f, uint32_t offset, MWasmMemoryAccess* access, - MDefinition** base, IsAtomic atomic = IsAtomic::No) -{ - // TODO Remove this after implementing non-wraparound offset semantics. - uint32_t endOffset = offset + access->byteSize(); - if (endOffset < offset) - return false; - - // Assume worst case. - if (endOffset > f.mirGen().foldableOffsetRange(/* bounds check */ true, bool(atomic))) { - MDefinition* rhs = f.constant(Int32Value(offset), MIRType::Int32); - *base = f.binary(*base, rhs, MIRType::Int32); - access->setOffset(0); - } else { - access->setOffset(offset); - } - - return true; -} - static bool EmitLoad(FunctionCompiler& f, ValType type, Scalar::Type viewType) { @@ -2088,13 +2080,8 @@ EmitLoad(FunctionCompiler& f, ValType type, Scalar::Type viewType) if (!f.iter().readLoad(type, Scalar::byteSize(viewType), &addr)) return false; - MWasmMemoryAccess access(viewType, addr.align); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base)) - return false; - - f.iter().setResult(f.loadHeap(base, access)); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); + f.iter().setResult(f.loadHeap(addr.base, access)); return true; } @@ -2106,13 +2093,8 @@ EmitStore(FunctionCompiler& f, ValType resultType, Scalar::Type viewType) if (!f.iter().readStore(resultType, Scalar::byteSize(viewType), &addr, &value)) return false; - MWasmMemoryAccess access(viewType, addr.align); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base)) - return false; - - f.storeHeap(base, access, value); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); + f.storeHeap(addr.base, access, value); return true; } @@ -2131,13 +2113,8 @@ EmitStoreWithCoercion(FunctionCompiler& f, ValType resultType, Scalar::Type view else MOZ_CRASH("unexpected coerced store"); - MWasmMemoryAccess access(viewType, addr.align); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base)) - return false; - - f.storeHeap(base, access, value); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); + f.storeHeap(addr.base, access, value); return true; } @@ -2207,13 +2184,9 @@ EmitAtomicsLoad(FunctionCompiler& f) if (!f.iter().readAtomicLoad(&addr, &viewType)) return false; - MWasmMemoryAccess access(viewType, addr.align, 0, MembarBeforeLoad, MembarAfterLoad); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base, IsAtomic::Yes)) - return false; - - f.iter().setResult(f.loadAtomicHeap(base, access)); + MWasmMemoryAccess access(viewType, addr.align, addr.offset, 0, + MembarBeforeLoad, MembarAfterLoad); + f.iter().setResult(f.loadAtomicHeap(addr.base, access)); return true; } @@ -2226,13 +2199,9 @@ EmitAtomicsStore(FunctionCompiler& f) if (!f.iter().readAtomicStore(&addr, &viewType, &value)) return false; - MWasmMemoryAccess access(viewType, addr.align, 0, MembarBeforeStore, MembarAfterStore); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base, IsAtomic::Yes)) - return false; - - f.storeAtomicHeap(base, access, value); + MWasmMemoryAccess access(viewType, addr.align, addr.offset, 0, + MembarBeforeStore, MembarAfterStore); + f.storeAtomicHeap(addr.base, access, value); f.iter().setResult(value); return true; } @@ -2247,13 +2216,8 @@ EmitAtomicsBinOp(FunctionCompiler& f) if (!f.iter().readAtomicBinOp(&addr, &viewType, &op, &value)) return false; - MWasmMemoryAccess access(viewType, addr.align); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base, IsAtomic::Yes)) - return false; - - f.iter().setResult(f.atomicBinopHeap(op, base, access, value)); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); + f.iter().setResult(f.atomicBinopHeap(op, addr.base, access, value)); return true; } @@ -2267,13 +2231,8 @@ EmitAtomicsCompareExchange(FunctionCompiler& f) if (!f.iter().readAtomicCompareExchange(&addr, &viewType, &oldValue, &newValue)) return false; - MWasmMemoryAccess access(viewType, addr.align); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base, IsAtomic::Yes)) - return false; - - f.iter().setResult(f.atomicCompareExchangeHeap(base, access, oldValue, newValue)); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); + f.iter().setResult(f.atomicCompareExchangeHeap(addr.base, access, oldValue, newValue)); return true; } @@ -2286,13 +2245,8 @@ EmitAtomicsExchange(FunctionCompiler& f) if (!f.iter().readAtomicExchange(&addr, &viewType, &value)) return false; - MWasmMemoryAccess access(viewType, addr.align); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base, IsAtomic::Yes)) - return false; - - f.iter().setResult(f.atomicExchangeHeap(base, access, value)); + MWasmMemoryAccess access(viewType, addr.align, addr.offset); + f.iter().setResult(f.atomicExchangeHeap(addr.base, access, value)); return true; } @@ -2513,13 +2467,8 @@ EmitSimdLoad(FunctionCompiler& f, ValType resultType, unsigned numElems) if (!f.iter().readLoad(resultType, Scalar::byteSize(viewType), &addr)) return false; - MWasmMemoryAccess access(viewType, addr.align, numElems); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base)) - return false; - - f.iter().setResult(f.loadSimdHeap(base, access)); + MWasmMemoryAccess access(viewType, addr.align, addr.offset, numElems); + f.iter().setResult(f.loadSimdHeap(addr.base, access)); return true; } @@ -2537,13 +2486,8 @@ EmitSimdStore(FunctionCompiler& f, ValType resultType, unsigned numElems) if (!f.iter().readStore(resultType, Scalar::byteSize(viewType), &addr, &value)) return false; - MWasmMemoryAccess access(viewType, addr.align, numElems); - - MDefinition* base = addr.base; - if (!SetHeapAccessOffset(f, addr.offset, &access, &base)) - return false; - - f.storeSimdHeap(base, access, value); + MWasmMemoryAccess access(viewType, addr.align, addr.offset, numElems); + f.storeSimdHeap(addr.base, access, value); return true; } diff --git a/js/src/asmjs/WasmModule.h b/js/src/asmjs/WasmModule.h index c7880027e840..396ff84f405c 100644 --- a/js/src/asmjs/WasmModule.h +++ b/js/src/asmjs/WasmModule.h @@ -56,7 +56,7 @@ struct LinkData : LinkDataCacheablePod RawPointer, CodeLabel, InstructionImmediate - }; + }; MOZ_INIT_OUTSIDE_CTOR uint32_t patchAtOffset; MOZ_INIT_OUTSIDE_CTOR uint32_t targetOffset; diff --git a/js/src/asmjs/WasmSignalHandlers.cpp b/js/src/asmjs/WasmSignalHandlers.cpp index 5ef285de3574..bf0cd98f5679 100644 --- a/js/src/asmjs/WasmSignalHandlers.cpp +++ b/js/src/asmjs/WasmSignalHandlers.cpp @@ -650,6 +650,13 @@ EmulateHeapAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddre MOZ_RELEASE_ASSERT(accessAddress + access.size() > instance.memoryBase() + instance.memoryLength(), "Computed access address is not actually out of bounds"); + // Wasm loads/stores don't wrap offsets at all, so hitting the guard page + // means we are out of bounds in any cases. + if (!memoryAccess->wrapOffset()) { + MOZ_ASSERT(memoryAccess->throwOnOOB()); + return instance.codeSegment().outOfBoundsCode(); + } + // The basic sandbox model is that all heap accesses are a heap base // register plus an index, and the index is always computed with 32-bit // operations, so we know it can only be 4 GiB off of the heap base. diff --git a/js/src/jit/AliasAnalysisShared.cpp b/js/src/jit/AliasAnalysisShared.cpp index 9f0b9c032f10..b0fbefb232a8 100644 --- a/js/src/jit/AliasAnalysisShared.cpp +++ b/js/src/jit/AliasAnalysisShared.cpp @@ -142,6 +142,8 @@ GetObject(const MDefinition* ins) case MDefinition::Op_AtomicTypedArrayElementBinop: case MDefinition::Op_AsmJSLoadHeap: case MDefinition::Op_AsmJSStoreHeap: + case MDefinition::Op_WasmLoad: + case MDefinition::Op_WasmStore: case MDefinition::Op_AsmJSCompareExchangeHeap: case MDefinition::Op_AsmJSAtomicBinopHeap: case MDefinition::Op_AsmJSLoadGlobalVar: diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index d0bb15a472b6..4c662cb8e304 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -12959,10 +12959,11 @@ class MWasmMemoryAccess MemoryBarrierBits barrierAfter_; public: - explicit MWasmMemoryAccess(Scalar::Type accessType, uint32_t align, unsigned numSimdElems = 0, + explicit MWasmMemoryAccess(Scalar::Type accessType, uint32_t align, uint32_t offset, + unsigned numSimdElems = 0, MemoryBarrierBits barrierBefore = MembarNobits, MemoryBarrierBits barrierAfter = MembarNobits) - : offset_(0), + : offset_(offset), align_(align), accessType_(accessType), needsBoundsCheck_(true), @@ -12984,13 +12985,94 @@ class MWasmMemoryAccess : TypedArrayElemSize(accessType()); } bool needsBoundsCheck() const { return needsBoundsCheck_; } - void removeBoundsCheck() { needsBoundsCheck_ = false; } unsigned numSimdElems() const { MOZ_ASSERT(Scalar::isSimdType(accessType_)); return numSimdElems_; } - void setOffset(uint32_t o) { offset_ = o; } - void setAlign(uint32_t a) { MOZ_ASSERT(mozilla::IsPowerOfTwo(a)); align_ = a; } MemoryBarrierBits barrierBefore() const { return barrierBefore_; } MemoryBarrierBits barrierAfter() const { return barrierAfter_; } bool isAtomicAccess() const { return (barrierBefore_|barrierAfter_) != MembarNobits; } + + void removeBoundsCheck() { needsBoundsCheck_ = false; } + void setOffset(uint32_t o) { offset_ = o; } +}; + +class MWasmBoundsCheck + : public MUnaryInstruction, + public MWasmMemoryAccess, + public NoTypePolicy::Data +{ + explicit MWasmBoundsCheck(MDefinition* index, const MWasmMemoryAccess& access) + : MUnaryInstruction(index), + MWasmMemoryAccess(access) + { + setMovable(); + setGuard(); // Effectful: throws for OOB. + } + + public: + INSTRUCTION_HEADER(WasmBoundsCheck) + TRIVIAL_NEW_WRAPPERS + + bool congruentTo(const MDefinition* ins) const override { + if (!congruentIfOperandsEqual(ins)) + return false; + const MWasmBoundsCheck* other = ins->toWasmBoundsCheck(); + return accessType() == other->accessType() && + offset() == other->offset() && + align() == other->align(); + } + + AliasSet getAliasSet() const override { + return AliasSet::None(); + } +}; + +class MWasmLoad + : public MUnaryInstruction, + public MWasmMemoryAccess, + public NoTypePolicy::Data +{ + MWasmLoad(MDefinition* base, const MWasmMemoryAccess& access) + : MUnaryInstruction(base), + MWasmMemoryAccess(access) + { + setGuard(); + MOZ_ASSERT(access.accessType() != Scalar::Uint8Clamped, "unexpected load heap in wasm"); + setResultType(ScalarTypeToMIRType(access.accessType())); + } + + public: + INSTRUCTION_HEADER(WasmLoad) + TRIVIAL_NEW_WRAPPERS + NAMED_OPERANDS((0, base)) + + AliasSet getAliasSet() const override { + // When a barrier is needed, make the instruction effectful by giving + // it a "store" effect. + if (isAtomicAccess()) + return AliasSet::Store(AliasSet::AsmJSHeap); + return AliasSet::Load(AliasSet::AsmJSHeap); + } +}; + +class MWasmStore + : public MBinaryInstruction, + public MWasmMemoryAccess, + public NoTypePolicy::Data +{ + MWasmStore(MDefinition* base, const MWasmMemoryAccess& access, MDefinition* value) + : MBinaryInstruction(base, value), + MWasmMemoryAccess(access) + { + setGuard(); + } + + public: + INSTRUCTION_HEADER(WasmStore) + TRIVIAL_NEW_WRAPPERS + NAMED_OPERANDS((0, base), (1, value)) + + AliasSet getAliasSet() const override { + return AliasSet::Store(AliasSet::AsmJSHeap); + } }; class MAsmJSLoadHeap diff --git a/js/src/jit/MIRGenerator.h b/js/src/jit/MIRGenerator.h index 2ce9efd0d43b..4253e9b6be93 100644 --- a/js/src/jit/MIRGenerator.h +++ b/js/src/jit/MIRGenerator.h @@ -224,7 +224,6 @@ class MIRGenerator bool needsBoundsCheckBranch(const MWasmMemoryAccess* access) const; size_t foldableOffsetRange(const MWasmMemoryAccess* access) const; - size_t foldableOffsetRange(bool accessNeedsBoundsCheck, bool atomic) const; private: GraphSpewer gs_; diff --git a/js/src/jit/MIRGraph.cpp b/js/src/jit/MIRGraph.cpp index 3686d3b5eb26..02005f6fc5a3 100644 --- a/js/src/jit/MIRGraph.cpp +++ b/js/src/jit/MIRGraph.cpp @@ -125,12 +125,6 @@ MIRGenerator::needsBoundsCheckBranch(const MWasmMemoryAccess* access) const size_t MIRGenerator::foldableOffsetRange(const MWasmMemoryAccess* access) const -{ - return foldableOffsetRange(access->needsBoundsCheck(), access->isAtomicAccess()); -} - -size_t -MIRGenerator::foldableOffsetRange(bool accessNeedsBoundsCheck, bool atomic) const { // This determines whether it's ok to fold up to WasmImmediateRange // offsets, instead of just WasmCheckedImmediateRange. @@ -148,14 +142,14 @@ MIRGenerator::foldableOffsetRange(bool accessNeedsBoundsCheck, bool atomic) cons // Signal-handling can be dynamically disabled by OS bugs or flags. // Bug 1254935: Atomic accesses can't be handled with signal handlers yet. - if (usesSignalHandlersForAsmJSOOB_ && !atomic) + if (usesSignalHandlersForAsmJSOOB_ && !access->isAtomicAccess()) return WasmImmediateRange; #endif // On 32-bit platforms, if we've proven the access is in bounds after // 32-bit wrapping, we can fold full offsets because they're added with // 32-bit arithmetic. - if (sizeof(intptr_t) == sizeof(int32_t) && !accessNeedsBoundsCheck) + if (sizeof(intptr_t) == sizeof(int32_t) && !access->needsBoundsCheck()) return WasmImmediateRange; // Otherwise, only allow the checked size. This is always less than the diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index dde1e3f1b72e..e9e325b92f7c 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -268,6 +268,9 @@ namespace jit { _(IsObject) \ _(HasClass) \ _(CopySign) \ + _(WasmBoundsCheck) \ + _(WasmLoad) \ + _(WasmStore) \ _(WasmTruncateToInt32) \ _(AsmJSNeg) \ _(AsmJSUnsignedToDouble) \ diff --git a/js/src/jit/arm/Assembler-arm.h b/js/src/jit/arm/Assembler-arm.h index 3f8954a10b90..f4b254307a1e 100644 --- a/js/src/jit/arm/Assembler-arm.h +++ b/js/src/jit/arm/Assembler-arm.h @@ -1206,6 +1206,7 @@ class Assembler : public AssemblerShared LessThan = LT, LessThanOrEqual = LE, Overflow = VS, + CarrySet = CS, Signed = MI, NotSigned = PL, Zero = EQ, diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index ee4fbd50b6cc..53b01033a3aa 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -2188,6 +2188,119 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins) memoryBarrier(mir->barrierAfter()); } +void +CodeGeneratorARM::visitWasmBoundsCheck(LWasmBoundsCheck* ins) +{ + MWasmBoundsCheck* mir = ins->mir(); + + uint32_t offset = mir->offset(); + if (offset > INT32_MAX) { + masm.as_b(wasm::JumpTarget::OutOfBounds); + return; + } + + // No guarantee that heapBase + endOffset can be properly encoded in + // the cmp immediate in ma_BoundsCheck, so use an explicit add instead. + uint32_t endOffset = mir->endOffset(); + + Register ptr = ToRegister(ins->ptr()); + + ScratchRegisterScope ptrPlusOffset(masm); + masm.move32(Imm32(endOffset), ptrPlusOffset); + masm.ma_add(ptr, ptrPlusOffset, SetCC); + + // Detect unsigned overflow by checking the carry bit. + masm.as_b(wasm::JumpTarget::OutOfBounds, Assembler::CarrySet); + + uint32_t cmpOffset = masm.ma_BoundsCheck(ptrPlusOffset).getOffset(); + masm.append(wasm::BoundsCheck(cmpOffset)); + masm.as_b(wasm::JumpTarget::OutOfBounds, Assembler::Above); +} + +void +CodeGeneratorARM::visitWasmLoad(LWasmLoad* lir) +{ + const MWasmLoad* mir = lir->mir(); + + MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI"); + + uint32_t offset = mir->offset(); + if (offset > INT32_MAX) { + // This is unreachable because of bounds checks. + masm.breakpoint(); + return; + } + + Register ptr = ToRegister(lir->ptr()); + AnyRegister output = ToAnyRegister(lir->output()); + + // Maybe add the offset. + if (offset) { + Register ptrPlusOffset = ToRegister(lir->ptrCopy()); + masm.ma_add(Imm32(offset), ptrPlusOffset); + ptr = ptrPlusOffset; + } else { + MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + } + + Scalar::Type type = mir->accessType(); + bool isSigned = type == Scalar::Int8 || type == Scalar::Int16 || type == Scalar::Int32; + bool isFloat = output.isFloat(); + + unsigned byteSize = mir->byteSize(); + + if (isFloat) { + MOZ_ASSERT((byteSize == 4) == output.fpu().isSingle()); + ScratchRegisterScope scratch(masm); + masm.ma_add(HeapReg, ptr, scratch); + masm.ma_vldr(Address(scratch, 0), output.fpu()); + } else { + masm.ma_dataTransferN(IsLoad, byteSize * 8, isSigned, HeapReg, ptr, output.gpr()); + } +} + +void +CodeGeneratorARM::visitWasmStore(LWasmStore* lir) +{ + const MWasmStore* mir = lir->mir(); + + MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI"); + + uint32_t offset = mir->offset(); + if (offset > INT32_MAX) { + // This is unreachable because of bounds checks. + masm.breakpoint(); + return; + } + + Register ptr = ToRegister(lir->ptr()); + + // Maybe add the offset. + if (offset) { + Register ptrPlusOffset = ToRegister(lir->ptrCopy()); + masm.ma_add(Imm32(offset), ptrPlusOffset); + ptr = ptrPlusOffset; + } else { + MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + } + + AnyRegister value = ToAnyRegister(lir->value()); + unsigned byteSize = mir->byteSize(); + Scalar::Type type = mir->accessType(); + + if (value.isFloat()) { + FloatRegister val = value.fpu(); + MOZ_ASSERT((byteSize == 4) == val.isSingle()); + ScratchRegisterScope scratch(masm); + masm.ma_add(HeapReg, ptr, scratch); + masm.ma_vstr(val, Address(scratch, 0)); + } else { + bool isSigned = type == Scalar::Uint32 || type == Scalar::Int32; // see AsmJSStoreHeap; + Register val = value.gpr(); + masm.ma_dataTransferN(IsStore, 8 * byteSize /* bits */, isSigned, HeapReg, ptr, val); + } +} + void CodeGeneratorARM::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins) { diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index 52ebaaf9e0b8..7a8a86805480 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -203,6 +203,9 @@ class CodeGeneratorARM : public CodeGeneratorShared void visitAsmSelect(LAsmSelect* ins); void visitAsmReinterpret(LAsmReinterpret* ins); void visitAsmJSCall(LAsmJSCall* ins); + void visitWasmBoundsCheck(LWasmBoundsCheck* ins); + void visitWasmLoad(LWasmLoad* ins); + void visitWasmStore(LWasmStore* ins); void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins); void visitAsmJSStoreHeap(LAsmJSStoreHeap* ins); void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins); diff --git a/js/src/jit/arm/Lowering-arm.cpp b/js/src/jit/arm/Lowering-arm.cpp index e7da9e2e7ceb..b6427f27e606 100644 --- a/js/src/jit/arm/Lowering-arm.cpp +++ b/js/src/jit/arm/Lowering-arm.cpp @@ -497,6 +497,48 @@ LIRGeneratorARM::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins) define(lir, ins); } +void +LIRGeneratorARM::visitWasmBoundsCheck(MWasmBoundsCheck* ins) +{ + MDefinition* input = ins->input(); + MOZ_ASSERT(input->type() == MIRType::Int32); + + LAllocation baseAlloc = useRegisterAtStart(input); + auto* lir = new(alloc()) LWasmBoundsCheck(baseAlloc); + add(lir, ins); +} + +void +LIRGeneratorARM::visitWasmLoad(MWasmLoad* ins) +{ + MDefinition* base = ins->base(); + MOZ_ASSERT(base->type() == MIRType::Int32); + + LAllocation baseAlloc = useRegisterAtStart(base); + auto* lir = new(alloc()) LWasmLoad(baseAlloc); + + if (ins->offset()) + lir->setTemp(0, tempCopy(base, 0)); + + define(lir, ins); +} + +void +LIRGeneratorARM::visitWasmStore(MWasmStore* ins) +{ + MDefinition* base = ins->base(); + MOZ_ASSERT(base->type() == MIRType::Int32); + + LAllocation baseAlloc = useRegisterAtStart(base); + LAllocation valueAlloc = useRegisterAtStart(ins->value()); + auto* lir = new(alloc()) LWasmStore(baseAlloc, valueAlloc); + + if (ins->offset()) + lir->setTemp(0, tempCopy(base, 0)); + + add(lir, ins); +} + void LIRGeneratorARM::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins) { diff --git a/js/src/jit/arm/Lowering-arm.h b/js/src/jit/arm/Lowering-arm.h index d6256730ac8b..0c061a0a6081 100644 --- a/js/src/jit/arm/Lowering-arm.h +++ b/js/src/jit/arm/Lowering-arm.h @@ -97,6 +97,9 @@ class LIRGeneratorARM : public LIRGeneratorShared void visitAsmSelect(MAsmSelect* ins); void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins); void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins); + void visitWasmBoundsCheck(MWasmBoundsCheck* ins); + void visitWasmLoad(MWasmLoad* ins); + void visitWasmStore(MWasmStore* ins); void visitAsmJSLoadHeap(MAsmJSLoadHeap* ins); void visitAsmJSStoreHeap(MAsmJSStoreHeap* ins); void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins); diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp index 7c467808ff65..2d0a0fe2e220 100644 --- a/js/src/jit/arm64/Lowering-arm64.cpp +++ b/js/src/jit/arm64/Lowering-arm64.cpp @@ -324,6 +324,24 @@ LIRGeneratorARM64::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins) MOZ_CRASH("NY"); } +void +LIRGeneratorARM64::visitWasmBoundsCheck(MWasmBoundsCheck* ins) +{ + MOZ_CRASH("NY"); +} + +void +LIRGeneratorARM64::visitWasmLoad(MWasmLoad* ins) +{ + MOZ_CRASH("NY"); +} + +void +LIRGeneratorARM64::visitWasmStore(MWasmStore* ins) +{ + MOZ_CRASH("NY"); +} + void LIRGeneratorARM64::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins) { diff --git a/js/src/jit/arm64/Lowering-arm64.h b/js/src/jit/arm64/Lowering-arm64.h index 3e61b517253a..0833a50c0002 100644 --- a/js/src/jit/arm64/Lowering-arm64.h +++ b/js/src/jit/arm64/Lowering-arm64.h @@ -113,6 +113,9 @@ class LIRGeneratorARM64 : public LIRGeneratorShared void visitSubstr(MSubstr* ins); void visitRandom(MRandom* ins); void visitWasmTruncateToInt64(MWasmTruncateToInt64* ins); + void visitWasmBoundsCheck(MWasmBoundsCheck* ins); + void visitWasmLoad(MWasmLoad* ins); + void visitWasmStore(MWasmStore* ins); void visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins); void visitCopySign(MCopySign* ins); }; diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index ebff7b9aa00b..3532bec86c81 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -7663,6 +7663,63 @@ class LAsmSelectI64 : public LAsmSelectBase } }; +class LWasmBoundsCheck : public LInstructionHelper<0, 1, 0> +{ + public: + LIR_HEADER(WasmBoundsCheck); + explicit LWasmBoundsCheck(const LAllocation& ptr) { + setOperand(0, ptr); + } + MWasmBoundsCheck* mir() const { + return mir_->toWasmBoundsCheck(); + } + const LAllocation* ptr() { + return getOperand(0); + } +}; + +class LWasmLoad : public LInstructionHelper<1, 1, 1> +{ + public: + LIR_HEADER(WasmLoad); + explicit LWasmLoad(const LAllocation& ptr) { + setOperand(0, ptr); + setTemp(0, LDefinition::BogusTemp()); + } + MWasmLoad* mir() const { + return mir_->toWasmLoad(); + } + const LAllocation* ptr() { + return getOperand(0); + } + const LDefinition* ptrCopy() { + return getTemp(0); + } +}; + +class LWasmStore : public LInstructionHelper<0, 2, 1> +{ + public: + LIR_HEADER(WasmStore); + LWasmStore(const LAllocation& ptr, const LAllocation& value) { + setOperand(0, ptr); + setOperand(1, value); + setTemp(0, LDefinition::BogusTemp()); + } + MWasmStore* mir() const { + return mir_->toWasmStore(); + } + const LAllocation* ptr() { + return getOperand(0); + } + const LDefinition* ptrCopy() { + return getTemp(0); + } + const LAllocation* value() { + return getOperand(1); + } +}; + class LAsmJSLoadHeap : public LInstructionHelper<1, 1, 0> { public: diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h index b3a37507921b..8193ebe86425 100644 --- a/js/src/jit/shared/LOpcodes-shared.h +++ b/js/src/jit/shared/LOpcodes-shared.h @@ -384,6 +384,9 @@ _(HasClass) \ _(AsmSelect) \ _(AsmSelectI64) \ + _(WasmLoad) \ + _(WasmStore) \ + _(WasmBoundsCheck) \ _(AsmJSLoadHeap) \ _(AsmJSStoreHeap) \ _(AsmJSLoadFuncPtr) \ diff --git a/js/src/jit/x64/CodeGenerator-x64.cpp b/js/src/jit/x64/CodeGenerator-x64.cpp index ad546fe15276..d8c58010c738 100644 --- a/js/src/jit/x64/CodeGenerator-x64.cpp +++ b/js/src/jit/x64/CodeGenerator-x64.cpp @@ -628,6 +628,66 @@ AsmJSMemoryAccess(uint32_t before, wasm::MemoryAccess::OutOfBoundsBehavior throw offsetWithinWholeSimdVector); } +static wasm::MemoryAccess +WasmMemoryAccess(uint32_t before) +{ + return wasm::MemoryAccess(before, + wasm::MemoryAccess::Throw, + wasm::MemoryAccess::DontWrapOffset); +} + +void +CodeGeneratorX64::visitWasmLoad(LWasmLoad* ins) +{ + const MWasmLoad* mir = ins->mir(); + + Scalar::Type accessType = mir->accessType(); + MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI"); + MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI"); + + if (mir->offset() > INT32_MAX) { + masm.jump(wasm::JumpTarget::OutOfBounds); + return; + } + + const LAllocation* ptr = ins->ptr(); + Operand srcAddr = ptr->isBogus() + ? Operand(HeapReg, mir->offset()) + : Operand(HeapReg, ToRegister(ptr), TimesOne, mir->offset()); + + AnyRegister out = ToAnyRegister(ins->output()); + + uint32_t before = masm.size(); + load(accessType, srcAddr, out); + masm.append(WasmMemoryAccess(before)); +} + +void +CodeGeneratorX64::visitWasmStore(LWasmStore* ins) +{ + const MWasmStore* mir = ins->mir(); + + Scalar::Type accessType = mir->accessType(); + MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI"); + MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI"); + + if (mir->offset() > INT32_MAX) { + masm.jump(wasm::JumpTarget::OutOfBounds); + return; + } + + const LAllocation* value = ins->value(); + const LAllocation* ptr = ins->ptr(); + Operand dstAddr = ptr->isBogus() + ? Operand(HeapReg, mir->offset()) + : Operand(HeapReg, ToRegister(ptr), TimesOne, mir->offset()); + + uint32_t before = masm.size(); + store(accessType, value, dstAddr); + + masm.append(WasmMemoryAccess(before)); +} + void CodeGeneratorX64::emitSimdLoad(LAsmJSLoadHeap* ins) { @@ -683,6 +743,29 @@ CodeGeneratorX64::emitSimdLoad(LAsmJSLoadHeap* ins) cleanupAfterAsmJSBoundsCheckBranch(mir, ToRegister(ptr)); } +void +CodeGeneratorX64::load(Scalar::Type type, const Operand& srcAddr, AnyRegister out) +{ + switch (type) { + case Scalar::Int8: masm.movsbl(srcAddr, out.gpr()); break; + case Scalar::Uint8: masm.movzbl(srcAddr, out.gpr()); break; + case Scalar::Int16: masm.movswl(srcAddr, out.gpr()); break; + case Scalar::Uint16: masm.movzwl(srcAddr, out.gpr()); break; + case Scalar::Int32: + case Scalar::Uint32: masm.movl(srcAddr, out.gpr()); break; + case Scalar::Float32: masm.loadFloat32(srcAddr, out.fpu()); break; + case Scalar::Float64: masm.loadDouble(srcAddr, out.fpu()); break; + case Scalar::Float32x4: + case Scalar::Int8x16: + case Scalar::Int16x8: + case Scalar::Int32x4: + MOZ_CRASH("SIMD loads should be handled in emitSimdLoad"); + case Scalar::Uint8Clamped: + case Scalar::MaxTypedArrayViewType: + MOZ_CRASH("unexpected array type"); + } +} + void CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins) { @@ -704,23 +787,7 @@ CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins) DebugOnly hasBoundsCheck = maybeEmitAsmJSLoadBoundsCheck(mir, ins, &ool); uint32_t before = masm.size(); - switch (accessType) { - case Scalar::Int8: masm.movsbl(srcAddr, ToRegister(out)); break; - case Scalar::Uint8: masm.movzbl(srcAddr, ToRegister(out)); break; - case Scalar::Int16: masm.movswl(srcAddr, ToRegister(out)); break; - case Scalar::Uint16: masm.movzwl(srcAddr, ToRegister(out)); break; - case Scalar::Int32: - case Scalar::Uint32: masm.movl(srcAddr, ToRegister(out)); break; - case Scalar::Float32: masm.loadFloat32(srcAddr, ToFloatRegister(out)); break; - case Scalar::Float64: masm.loadDouble(srcAddr, ToFloatRegister(out)); break; - case Scalar::Float32x4: - case Scalar::Int8x16: - case Scalar::Int16x8: - case Scalar::Int32x4: MOZ_CRASH("SIMD loads should be handled in emitSimdLoad"); - case Scalar::Uint8Clamped: - case Scalar::MaxTypedArrayViewType: - MOZ_CRASH("unexpected array type"); - } + load(accessType, srcAddr, ToAnyRegister(out)); uint32_t after = masm.size(); verifyHeapAccessDisassembly(before, after, /*isLoad=*/true, accessType, 0, srcAddr, *out->output()); @@ -736,6 +803,60 @@ CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins) masm.append(AsmJSMemoryAccess(before, wasm::MemoryAccess::CarryOn)); } +void +CodeGeneratorX64::store(Scalar::Type type, const LAllocation* value, const Operand& dstAddr) +{ + if (value->isConstant()) { + Imm32 cst(ToInt32(value)); + switch (type) { + case Scalar::Int8: + case Scalar::Uint8: masm.movb(cst, dstAddr); break; + case Scalar::Int16: + case Scalar::Uint16: masm.movw(cst, dstAddr); break; + case Scalar::Int32: + case Scalar::Uint32: masm.movl(cst, dstAddr); break; + case Scalar::Float32: + case Scalar::Float64: + case Scalar::Float32x4: + case Scalar::Int8x16: + case Scalar::Int16x8: + case Scalar::Int32x4: + case Scalar::Uint8Clamped: + case Scalar::MaxTypedArrayViewType: + MOZ_CRASH("unexpected array type"); + } + } else { + switch (type) { + case Scalar::Int8: + case Scalar::Uint8: + masm.movb(ToRegister(value), dstAddr); + break; + case Scalar::Int16: + case Scalar::Uint16: + masm.movw(ToRegister(value), dstAddr); + break; + case Scalar::Int32: + case Scalar::Uint32: + masm.movl(ToRegister(value), dstAddr); + break; + case Scalar::Float32: + masm.storeUncanonicalizedFloat32(ToFloatRegister(value), dstAddr); + break; + case Scalar::Float64: + masm.storeUncanonicalizedDouble(ToFloatRegister(value), dstAddr); + break; + case Scalar::Float32x4: + case Scalar::Int8x16: + case Scalar::Int16x8: + case Scalar::Int32x4: + MOZ_CRASH("SIMD stores must be handled in emitSimdStore"); + case Scalar::Uint8Clamped: + case Scalar::MaxTypedArrayViewType: + MOZ_CRASH("unexpected array type"); + } + } +} + void CodeGeneratorX64::storeSimd(Scalar::Type type, unsigned numElems, FloatRegister in, const Operand& dstAddr) @@ -861,54 +982,7 @@ CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins) DebugOnly hasBoundsCheck = maybeEmitAsmJSStoreBoundsCheck(mir, ins, &rejoin); uint32_t before = masm.size(); - if (value->isConstant()) { - switch (accessType) { - case Scalar::Int8: - case Scalar::Uint8: masm.movb(Imm32(ToInt32(value)), dstAddr); break; - case Scalar::Int16: - case Scalar::Uint16: masm.movw(Imm32(ToInt32(value)), dstAddr); break; - case Scalar::Int32: - case Scalar::Uint32: masm.movl(Imm32(ToInt32(value)), dstAddr); break; - case Scalar::Float32: - case Scalar::Float64: - case Scalar::Float32x4: - case Scalar::Int8x16: - case Scalar::Int16x8: - case Scalar::Int32x4: - case Scalar::Uint8Clamped: - case Scalar::MaxTypedArrayViewType: - MOZ_CRASH("unexpected array type"); - } - } else { - switch (accessType) { - case Scalar::Int8: - case Scalar::Uint8: - masm.movb(ToRegister(value), dstAddr); - break; - case Scalar::Int16: - case Scalar::Uint16: - masm.movw(ToRegister(value), dstAddr); - break; - case Scalar::Int32: - case Scalar::Uint32: - masm.movl(ToRegister(value), dstAddr); - break; - case Scalar::Float32: - masm.storeUncanonicalizedFloat32(ToFloatRegister(value), dstAddr); - break; - case Scalar::Float64: - masm.storeUncanonicalizedDouble(ToFloatRegister(value), dstAddr); - break; - case Scalar::Float32x4: - case Scalar::Int8x16: - case Scalar::Int16x8: - case Scalar::Int32x4: - MOZ_CRASH("SIMD stores must be handled in emitSimdStore"); - case Scalar::Uint8Clamped: - case Scalar::MaxTypedArrayViewType: - MOZ_CRASH("unexpected array type"); - } - } + store(accessType, value, dstAddr); uint32_t after = masm.size(); verifyHeapAccessDisassembly(before, after, /*isLoad=*/false, accessType, 0, dstAddr, *value); @@ -924,20 +998,6 @@ CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins) masm.append(AsmJSMemoryAccess(before, wasm::MemoryAccess::CarryOn)); } -static void -MaybeAddAtomicsBoundsCheck(MacroAssemblerX64& masm, MWasmMemoryAccess* mir, Register ptr) -{ - if (!mir->needsBoundsCheck()) - return; - - // Note that we can't use the same machinery as normal asm.js loads/stores - // since signal-handler bounds checking is not yet implemented for atomic - // accesses. - uint32_t cmpOffset = masm.cmp32WithPatch(ptr, Imm32(-mir->endOffset())).offset(); - masm.append(wasm::BoundsCheck(cmpOffset)); - masm.j(Assembler::Above, wasm::JumpTarget::OutOfBounds); -} - void CodeGeneratorX64::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins) { @@ -951,7 +1011,10 @@ CodeGeneratorX64::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins) Register oldval = ToRegister(ins->oldValue()); Register newval = ToRegister(ins->newValue()); - MaybeAddAtomicsBoundsCheck(masm, mir, ptr); + // Note that we can't use the same machinery as normal asm.js loads/stores + // since signal-handler bounds checking is not yet implemented for atomic + // accesses. + maybeEmitWasmBoundsCheckBranch(mir, ptr); masm.compareExchangeToTypedIntArray(accessType == Scalar::Uint32 ? Scalar::Int32 : accessType, srcAddr, @@ -977,7 +1040,8 @@ CodeGeneratorX64::visitAsmJSAtomicExchangeHeap(LAsmJSAtomicExchangeHeap* ins) BaseIndex srcAddr(HeapReg, ptr, TimesOne, mir->offset()); Register value = ToRegister(ins->value()); - MaybeAddAtomicsBoundsCheck(masm, mir, ptr); + // See comment in visitAsmJSCompareExchangeHeap. + maybeEmitWasmBoundsCheckBranch(mir, ptr); masm.atomicExchangeToTypedIntArray(accessType == Scalar::Uint32 ? Scalar::Int32 : accessType, srcAddr, @@ -1006,7 +1070,8 @@ CodeGeneratorX64::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins) const LAllocation* value = ins->value(); - MaybeAddAtomicsBoundsCheck(masm, mir, ptr); + // See comment in visitAsmJSCompareExchangeHeap. + maybeEmitWasmBoundsCheckBranch(mir, ptr); AnyRegister output = ToAnyRegister(ins->output()); if (value->isConstant()) { @@ -1036,7 +1101,8 @@ CodeGeneratorX64::visitAsmJSAtomicBinopHeapForEffect(LAsmJSAtomicBinopHeapForEff BaseIndex srcAddr(HeapReg, ptr, TimesOne, mir->offset()); const LAllocation* value = ins->value(); - MaybeAddAtomicsBoundsCheck(masm, mir, ptr); + // See comment in visitAsmJSCompareExchangeHeap. + maybeEmitWasmBoundsCheckBranch(mir, ptr); if (value->isConstant()) atomicBinopToTypedIntArray(op, accessType, Imm32(ToInt32(value)), srcAddr); diff --git a/js/src/jit/x64/CodeGenerator-x64.h b/js/src/jit/x64/CodeGenerator-x64.h index 1fa0447c9be1..776e00b7fc4f 100644 --- a/js/src/jit/x64/CodeGenerator-x64.h +++ b/js/src/jit/x64/CodeGenerator-x64.h @@ -27,9 +27,13 @@ class CodeGeneratorX64 : public CodeGeneratorX86Shared Operand dest, MIRType slotType); void memoryBarrier(MemoryBarrierBits barrier); + void load(Scalar::Type type, const Operand& srcAddr, AnyRegister out); void loadSimd(Scalar::Type type, unsigned numElems, const Operand& srcAddr, FloatRegister out); - void emitSimdLoad(LAsmJSLoadHeap* ins); + + void store(Scalar::Type type, const LAllocation* value, const Operand& dstAddr); void storeSimd(Scalar::Type type, unsigned numElems, FloatRegister in, const Operand& dstAddr); + + void emitSimdLoad(LAsmJSLoadHeap* ins); void emitSimdStore(LAsmJSStoreHeap* ins); public: CodeGeneratorX64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm); @@ -64,6 +68,8 @@ class CodeGeneratorX64 : public CodeGeneratorX86Shared void visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir); void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins); void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins); + void visitWasmLoad(LWasmLoad* ins); + void visitWasmStore(LWasmStore* ins); void visitAsmSelectI64(LAsmSelectI64* ins); void visitAsmJSCall(LAsmJSCall* ins); void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins); diff --git a/js/src/jit/x64/Lowering-x64.cpp b/js/src/jit/x64/Lowering-x64.cpp index e49eec8536fa..474dc969e4d2 100644 --- a/js/src/jit/x64/Lowering-x64.cpp +++ b/js/src/jit/x64/Lowering-x64.cpp @@ -155,6 +155,40 @@ LIRGeneratorX64::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins) define(lir, ins); } +void +LIRGeneratorX64::visitWasmStore(MWasmStore* ins) +{ + MDefinition* base = ins->base(); + MOZ_ASSERT(base->type() == MIRType::Int32); + + LAllocation value; + switch (ins->accessType()) { + case Scalar::Int8: + case Scalar::Uint8: + case Scalar::Int16: + case Scalar::Uint16: + case Scalar::Int32: + case Scalar::Uint32: + value = useRegisterOrConstantAtStart(ins->value()); + break; + case Scalar::Float32: + case Scalar::Float64: + case Scalar::Float32x4: + case Scalar::Int8x16: + case Scalar::Int16x8: + case Scalar::Int32x4: + value = useRegisterAtStart(ins->value()); + break; + case Scalar::Uint8Clamped: + case Scalar::MaxTypedArrayViewType: + MOZ_CRASH("unexpected array type"); + } + + LAllocation baseAlloc = useRegisterOrZeroAtStart(base); + auto* lir = new(alloc()) LWasmStore(baseAlloc, value); + add(lir, ins); +} + void LIRGeneratorX64::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins) { diff --git a/js/src/jit/x64/Lowering-x64.h b/js/src/jit/x64/Lowering-x64.h index 67eba7b4c004..589d3175a723 100644 --- a/js/src/jit/x64/Lowering-x64.h +++ b/js/src/jit/x64/Lowering-x64.h @@ -56,6 +56,7 @@ class LIRGeneratorX64 : public LIRGeneratorX86Shared void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins); void visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins); void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins); + void visitWasmStore(MWasmStore* ins); void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins); void visitSubstr(MSubstr* ins); void visitRandom(MRandom* ins); diff --git a/js/src/jit/x86-shared/Assembler-x86-shared.h b/js/src/jit/x86-shared/Assembler-x86-shared.h index c22a1b7494db..e60a4f37f037 100644 --- a/js/src/jit/x86-shared/Assembler-x86-shared.h +++ b/js/src/jit/x86-shared/Assembler-x86-shared.h @@ -1077,18 +1077,31 @@ class AssemblerX86Shared : public AssemblerShared } static void UpdateBoundsCheck(uint8_t* patchAt, uint32_t heapLength) { - // An access is out-of-bounds iff - // ptr + offset + data-type-byte-size > heapLength - // 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. - // // On x64, even with signal handling being used for most bounds checks, // there may be atomic operations that depend on explicit checks. All // accesses that have been recorded are the only ones that need bound - // checks (see also - // CodeGeneratorX64::visitAsmJS{Load,Store,CompareExchange,Exchange,AtomicBinop}Heap) - X86Encoding::AddInt32(patchAt, heapLength); + // checks. + // + // An access is out-of-bounds iff + // ptr + offset + data-type-byte-size > heapLength + // i.e ptr + offset + data-type-byte-size - 1 >= heapLength + // i.e. ptr >= heapLength - data-type-byte-size - offset + 1. + // + // before := data-type-byte-size + offset - 1 + uint32_t before = reinterpret_cast(patchAt)[-1]; + uint32_t after = before + heapLength; + + // If the computed index `before` already is out of bounds, + // we need to make sure the bounds check will fail all the time. + // For bounds checks, the sequence of instructions we use is: + // cmp(ptrReg, #before) + // jae(OutOfBounds) + // so replace the cmp immediate with 0. + if (after > heapLength) + after = 0; + + MOZ_ASSERT_IF(after, int32_t(after) >= int32_t(before)); + reinterpret_cast(patchAt)[-1] = after; } void breakpoint() { diff --git a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp index 63ed286015fc..1c9bd1f1f94f 100644 --- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp @@ -454,11 +454,14 @@ CodeGeneratorX86Shared::emitAsmJSBoundsCheckBranch(const MWasmMemoryAccess* acce // field, so -access->endOffset() will turn into // (heapLength - access->endOffset()), allowing us to test whether the end // of the access is beyond the end of the heap. - uint32_t cmpOffset = masm.cmp32WithPatch(ptr, Imm32(-access->endOffset())).offset(); + MOZ_ASSERT(access->endOffset() >= 1, + "need to subtract 1 to use JAE, see also AssemblerX86Shared::UpdateBoundsCheck"); + + uint32_t cmpOffset = masm.cmp32WithPatch(ptr, Imm32(1 - access->endOffset())).offset(); if (maybeFail) - masm.j(Assembler::Above, maybeFail); + masm.j(Assembler::AboveOrEqual, maybeFail); else - masm.j(Assembler::Above, wasm::JumpTarget::OutOfBounds); + masm.j(Assembler::AboveOrEqual, wasm::JumpTarget::OutOfBounds); if (pass) masm.bind(pass); @@ -466,6 +469,34 @@ CodeGeneratorX86Shared::emitAsmJSBoundsCheckBranch(const MWasmMemoryAccess* acce masm.append(wasm::BoundsCheck(cmpOffset)); } +void +CodeGeneratorX86Shared::visitWasmBoundsCheck(LWasmBoundsCheck* ins) +{ + const MWasmBoundsCheck* mir = ins->mir(); + MOZ_ASSERT(gen->needsBoundsCheckBranch(mir)); + if (mir->offset() > INT32_MAX) { + masm.jump(wasm::JumpTarget::OutOfBounds); + return; + } + + Register ptrReg = ToRegister(ins->ptr()); + maybeEmitWasmBoundsCheckBranch(mir, ptrReg); +} + +void +CodeGeneratorX86Shared::maybeEmitWasmBoundsCheckBranch(const MWasmMemoryAccess* mir, Register ptr) +{ + if (!mir->needsBoundsCheck()) + return; + + MOZ_ASSERT(mir->endOffset() >= 1, + "need to subtract 1 to use JAE, see also AssemblerX86Shared::UpdateBoundsCheck"); + + uint32_t cmpOffset = masm.cmp32WithPatch(ptr, Imm32(1 - mir->endOffset())).offset(); + masm.j(Assembler::AboveOrEqual, wasm::JumpTarget::OutOfBounds); + masm.append(wasm::BoundsCheck(cmpOffset)); +} + bool CodeGeneratorX86Shared::maybeEmitThrowingAsmJSBoundsCheck(const MWasmMemoryAccess* access, const MInstruction* mir, diff --git a/js/src/jit/x86-shared/CodeGenerator-x86-shared.h b/js/src/jit/x86-shared/CodeGenerator-x86-shared.h index 2053f8a5942e..6d53ac55f044 100644 --- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.h +++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.h @@ -94,24 +94,24 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared }; private: - void - emitAsmJSBoundsCheckBranch(const MWasmMemoryAccess* mir, const MInstruction* ins, - Register ptr, Label* fail); + void emitAsmJSBoundsCheckBranch(const MWasmMemoryAccess* mir, const MInstruction* ins, + Register ptr, Label* fail); + + protected: + void maybeEmitWasmBoundsCheckBranch(const MWasmMemoryAccess* mir, Register ptr); public: // For SIMD and atomic loads and stores (which throw on out-of-bounds): - bool - maybeEmitThrowingAsmJSBoundsCheck(const MWasmMemoryAccess* mir, const MInstruction* ins, - const LAllocation* ptr); + bool maybeEmitThrowingAsmJSBoundsCheck(const MWasmMemoryAccess* mir, const MInstruction* ins, + const LAllocation* ptr); // For asm.js plain and atomic loads that possibly require a bounds check: - bool - maybeEmitAsmJSLoadBoundsCheck(const MAsmJSLoadHeap* mir, LAsmJSLoadHeap* ins, - OutOfLineLoadTypedArrayOutOfBounds** ool); + bool maybeEmitAsmJSLoadBoundsCheck(const MAsmJSLoadHeap* mir, LAsmJSLoadHeap* ins, + OutOfLineLoadTypedArrayOutOfBounds** ool); // For asm.js plain and atomic stores that possibly require a bounds check: - bool - maybeEmitAsmJSStoreBoundsCheck(const MAsmJSStoreHeap* mir, LAsmJSStoreHeap* ins, Label** rejoin); + bool maybeEmitAsmJSStoreBoundsCheck(const MAsmJSStoreHeap* mir, LAsmJSStoreHeap* ins, + Label** rejoin); void cleanupAfterAsmJSBoundsCheckBranch(const MWasmMemoryAccess* mir, Register ptr); @@ -272,6 +272,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared virtual void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins); virtual void visitAsmSelect(LAsmSelect* ins); virtual void visitAsmReinterpret(LAsmReinterpret* lir); + virtual void visitWasmBoundsCheck(LWasmBoundsCheck* ins); virtual void visitMemoryBarrier(LMemoryBarrier* ins); virtual void visitAtomicTypedArrayElementBinop(LAtomicTypedArrayElementBinop* lir); virtual void visitAtomicTypedArrayElementBinopForEffect(LAtomicTypedArrayElementBinopForEffect* lir); diff --git a/js/src/jit/x86-shared/Lowering-x86-shared.cpp b/js/src/jit/x86-shared/Lowering-x86-shared.cpp index ecb0e669444c..3e19a2f52e97 100644 --- a/js/src/jit/x86-shared/Lowering-x86-shared.cpp +++ b/js/src/jit/x86-shared/Lowering-x86-shared.cpp @@ -322,6 +322,27 @@ LIRGeneratorX86Shared::visitAsmJSNeg(MAsmJSNeg* ins) } } +void +LIRGeneratorX86Shared::visitWasmBoundsCheck(MWasmBoundsCheck* ins) +{ + if (!gen->needsBoundsCheckBranch(ins)) + return; + + MDefinition* index = ins->input(); + auto* lir = new(alloc()) LWasmBoundsCheck(useRegisterAtStart(index)); + add(lir, ins); +} + +void +LIRGeneratorX86Shared::visitWasmLoad(MWasmLoad* ins) +{ + MDefinition* base = ins->base(); + MOZ_ASSERT(base->type() == MIRType::Int32); + + auto* lir = new(alloc()) LWasmLoad(useRegisterOrZeroAtStart(base)); + define(lir, ins); +} + void LIRGeneratorX86Shared::lowerUDiv(MDiv* div) { diff --git a/js/src/jit/x86-shared/Lowering-x86-shared.h b/js/src/jit/x86-shared/Lowering-x86-shared.h index ba8918a6f919..e8d63c58ef53 100644 --- a/js/src/jit/x86-shared/Lowering-x86-shared.h +++ b/js/src/jit/x86-shared/Lowering-x86-shared.h @@ -47,6 +47,8 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir, MDefinition* lhs, MDefinition* rhs); void visitAsmJSNeg(MAsmJSNeg* ins); + void visitWasmBoundsCheck(MWasmBoundsCheck* ins); + void visitWasmLoad(MWasmLoad* ins); void visitAsmSelect(MAsmSelect* ins); void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs); void lowerDivI(MDiv* div); diff --git a/js/src/jit/x86-shared/Patching-x86-shared.h b/js/src/jit/x86-shared/Patching-x86-shared.h index 317bebe92173..689fa36b5b2a 100644 --- a/js/src/jit/x86-shared/Patching-x86-shared.h +++ b/js/src/jit/x86-shared/Patching-x86-shared.h @@ -42,17 +42,6 @@ SetInt32(void* where, int32_t value) reinterpret_cast(where)[-1] = value; } -inline void -AddInt32(void* where, int32_t value) -{ -#ifdef DEBUG - uint32_t x = reinterpret_cast(where)[-1]; - uint32_t y = x + uint32_t(value); - MOZ_ASSERT(value >= 0 ? (int32_t(y) >= int32_t(x)) : (int32_t(y) < int32_t(x))); -#endif - reinterpret_cast(where)[-1] += uint32_t(value); -} - inline void SetRel32(void* from, void* to) { diff --git a/js/src/jit/x86/CodeGenerator-x86.cpp b/js/src/jit/x86/CodeGenerator-x86.cpp index f10efd387840..abb1dcc4853a 100644 --- a/js/src/jit/x86/CodeGenerator-x86.cpp +++ b/js/src/jit/x86/CodeGenerator-x86.cpp @@ -394,6 +394,57 @@ CodeGeneratorX86::loadSimd(Scalar::Type type, unsigned numElems, const Operand& } } +void +CodeGeneratorX86::visitWasmLoad(LWasmLoad* ins) +{ + const MWasmLoad* mir = ins->mir(); + + Scalar::Type accessType = mir->accessType(); + MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI"); + MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI"); + + if (mir->offset() > INT32_MAX) { + // This is unreachable because of the bounds check. + masm.breakpoint(); + return; + } + + const LAllocation* ptr = ins->ptr(); + Operand srcAddr = ptr->isBogus() + ? Operand(PatchedAbsoluteAddress(mir->offset())) + : Operand(ToRegister(ptr), mir->offset()); + + load(accessType, srcAddr, ins->output()); + + masm.append(wasm::MemoryAccess(masm.size())); +} + +void +CodeGeneratorX86::visitWasmStore(LWasmStore* ins) +{ + const MWasmStore* mir = ins->mir(); + + Scalar::Type accessType = mir->accessType(); + MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI"); + MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI"); + + if (mir->offset() > INT32_MAX) { + // This is unreachable because of the bounds check. + masm.breakpoint(); + return; + } + + const LAllocation* value = ins->value(); + const LAllocation* ptr = ins->ptr(); + Operand dstAddr = ptr->isBogus() + ? Operand(PatchedAbsoluteAddress(mir->offset())) + : Operand(ToRegister(ptr), mir->offset()); + + store(accessType, value, dstAddr); + + masm.append(wasm::MemoryAccess(masm.size())); +} + void CodeGeneratorX86::emitSimdLoad(LAsmJSLoadHeap* ins) { @@ -664,6 +715,23 @@ CodeGeneratorX86::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins) masm.append(wasm::MemoryAccess(after)); } +// Perform bounds checking on the access if necessary; if it fails, +// jump to out-of-line code that throws. If the bounds check passes, +// set up the heap address in addrTemp. + +void +CodeGeneratorX86::asmJSAtomicComputeAddress(Register addrTemp, Register ptrReg, + const MWasmMemoryAccess* mir) +{ + maybeEmitWasmBoundsCheckBranch(mir, ptrReg); + + // Add in the actual heap pointer explicitly, to avoid opening up + // the abstraction that is atomicBinopToTypedIntArray at this time. + masm.movl(ptrReg, addrTemp); + masm.addlWithPatch(Imm32(mir->offset()), addrTemp); + masm.append(wasm::MemoryAccess(masm.size())); +} + void CodeGeneratorX86::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins) { @@ -674,8 +742,7 @@ CodeGeneratorX86::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins) Register newval = ToRegister(ins->newValue()); Register addrTemp = ToRegister(ins->addrTemp()); - asmJSAtomicComputeAddress(addrTemp, ptrReg, mir->needsBoundsCheck(), mir->offset(), - mir->endOffset()); + asmJSAtomicComputeAddress(addrTemp, ptrReg, mir); Address memAddr(addrTemp, mir->offset()); masm.compareExchangeToTypedIntArray(accessType == Scalar::Uint32 ? Scalar::Int32 : accessType, @@ -686,27 +753,6 @@ CodeGeneratorX86::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins) ToAnyRegister(ins->output())); } -// Perform bounds checking on the access if necessary; if it fails, -// jump to out-of-line code that throws. If the bounds check passes, -// set up the heap address in addrTemp. - -void -CodeGeneratorX86::asmJSAtomicComputeAddress(Register addrTemp, Register ptrReg, bool boundsCheck, - uint32_t offset, uint32_t endOffset) -{ - if (boundsCheck) { - uint32_t cmpOffset = masm.cmp32WithPatch(ptrReg, Imm32(-endOffset)).offset(); - masm.j(Assembler::Above, wasm::JumpTarget::OutOfBounds); - masm.append(wasm::BoundsCheck(cmpOffset)); - } - - // Add in the actual heap pointer explicitly, to avoid opening up - // the abstraction that is atomicBinopToTypedIntArray at this time. - masm.movl(ptrReg, addrTemp); - masm.addlWithPatch(Imm32(offset), addrTemp); - masm.append(wasm::MemoryAccess(masm.size())); -} - void CodeGeneratorX86::visitAsmJSAtomicExchangeHeap(LAsmJSAtomicExchangeHeap* ins) { @@ -716,8 +762,7 @@ CodeGeneratorX86::visitAsmJSAtomicExchangeHeap(LAsmJSAtomicExchangeHeap* ins) Register value = ToRegister(ins->value()); Register addrTemp = ToRegister(ins->addrTemp()); - asmJSAtomicComputeAddress(addrTemp, ptrReg, mir->needsBoundsCheck(), mir->offset(), - mir->endOffset()); + asmJSAtomicComputeAddress(addrTemp, ptrReg, mir); Address memAddr(addrTemp, mir->offset()); masm.atomicExchangeToTypedIntArray(accessType == Scalar::Uint32 ? Scalar::Int32 : accessType, @@ -738,8 +783,7 @@ CodeGeneratorX86::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins) const LAllocation* value = ins->value(); AtomicOp op = mir->operation(); - asmJSAtomicComputeAddress(addrTemp, ptrReg, mir->needsBoundsCheck(), mir->offset(), - mir->endOffset()); + asmJSAtomicComputeAddress(addrTemp, ptrReg, mir); Address memAddr(addrTemp, mir->offset()); if (value->isConstant()) { @@ -771,8 +815,7 @@ CodeGeneratorX86::visitAsmJSAtomicBinopHeapForEffect(LAsmJSAtomicBinopHeapForEff MOZ_ASSERT(!mir->hasUses()); - asmJSAtomicComputeAddress(addrTemp, ptrReg, mir->needsBoundsCheck(), mir->offset(), - mir->endOffset()); + asmJSAtomicComputeAddress(addrTemp, ptrReg, mir); Address memAddr(addrTemp, mir->offset()); if (value->isConstant()) diff --git a/js/src/jit/x86/CodeGenerator-x86.h b/js/src/jit/x86/CodeGenerator-x86.h index 30cd31a5cb1d..a7c391478c13 100644 --- a/js/src/jit/x86/CodeGenerator-x86.h +++ b/js/src/jit/x86/CodeGenerator-x86.h @@ -58,6 +58,8 @@ class CodeGeneratorX86 : public CodeGeneratorX86Shared void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins); void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins); void visitAsmJSCall(LAsmJSCall* ins); + void visitWasmLoad(LWasmLoad* ins); + void visitWasmStore(LWasmStore* ins); void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins); void visitAsmJSStoreHeap(LAsmJSStoreHeap* ins); void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins); @@ -74,8 +76,8 @@ class CodeGeneratorX86 : public CodeGeneratorX86Shared void visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32* ool); private: - void asmJSAtomicComputeAddress(Register addrTemp, Register ptrReg, bool boundsCheck, - uint32_t offset, uint32_t endOffset); + void asmJSAtomicComputeAddress(Register addrTemp, Register ptrReg, + const MWasmMemoryAccess* access); }; typedef CodeGeneratorX86 CodeGeneratorSpecific; diff --git a/js/src/jit/x86/Lowering-x86.cpp b/js/src/jit/x86/Lowering-x86.cpp index 699b5f94c1cd..4b9bca1a4c84 100644 --- a/js/src/jit/x86/Lowering-x86.cpp +++ b/js/src/jit/x86/Lowering-x86.cpp @@ -203,6 +203,40 @@ LIRGeneratorX86::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins) define(lir, ins); } +void +LIRGeneratorX86::visitWasmStore(MWasmStore* ins) +{ + MDefinition* base = ins->base(); + MOZ_ASSERT(base->type() == MIRType::Int32); + + LAllocation baseAlloc = useRegisterOrZeroAtStart(base); + + LAllocation valueAlloc; + switch (ins->accessType()) { + case Scalar::Int8: case Scalar::Uint8: + // See comment for LIRGeneratorX86::useByteOpRegister. + valueAlloc = useFixed(ins->value(), eax); + break; + case Scalar::Int16: case Scalar::Uint16: + case Scalar::Int32: case Scalar::Uint32: + case Scalar::Float32: case Scalar::Float64: + case Scalar::Float32x4: + case Scalar::Int8x16: + case Scalar::Int16x8: + case Scalar::Int32x4: + // For now, don't allow constant values. The immediate operand affects + // instruction layout which affects patching. + valueAlloc = useRegisterAtStart(ins->value()); + break; + case Scalar::Uint8Clamped: + case Scalar::MaxTypedArrayViewType: + MOZ_CRASH("unexpected array type"); + } + + auto* lir = new(alloc()) LWasmStore(baseAlloc, valueAlloc); + add(lir, ins); +} + void LIRGeneratorX86::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins) { diff --git a/js/src/jit/x86/Lowering-x86.h b/js/src/jit/x86/Lowering-x86.h index 34c699d33f03..c42d14e05d2c 100644 --- a/js/src/jit/x86/Lowering-x86.h +++ b/js/src/jit/x86/Lowering-x86.h @@ -60,6 +60,7 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins); void visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins); void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins); + void visitWasmStore(MWasmStore* ins); void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins); void visitSubstr(MSubstr* ins); void visitRandom(MRandom* ins); From a61eb3acbb6f382e9fe56d6a8261ef9a5c140aa2 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Wed, 29 Jun 2016 18:36:21 +0200 Subject: [PATCH 24/30] Bug 1268024: Tests; r=luke MozReview-Commit-ID: 2AlSN0sQck3 --HG-- extra : rebase_source : f1a644adbb7bc606a1511f935d5c4bd563c002e5 --- js/src/jit-test/tests/wasm/basic-memory.js | 231 ++++++++++++------ .../jit-test/tests/wasm/spec/address.wast.js | 2 - .../jit-test/tests/wasm/spec/memory.wast.js | 2 +- js/src/jit-test/tests/wasm/spec/traps.wast.js | 2 +- 4 files changed, 158 insertions(+), 79 deletions(-) diff --git a/js/src/jit-test/tests/wasm/basic-memory.js b/js/src/jit-test/tests/wasm/basic-memory.js index bc4fe192bab0..4d88ff8edee0 100644 --- a/js/src/jit-test/tests/wasm/basic-memory.js +++ b/js/src/jit-test/tests/wasm/basic-memory.js @@ -1,74 +1,65 @@ // |jit-test| test-also-wasm-baseline load(libdir + "wasm.js"); +function loadModule(type, ext, offset, align) { + return wasmEvalText( + `(module + (memory 1 + (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f") + (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff") + ) + (func (param i32) (result ${type}) + (${type}.load${ext} + offset=${offset} + ${align != 0 ? 'align=' + align : ''} + (get_local 0) + ) + ) (export "" 0))` + ); +} + +function storeModule(type, ext, offset, align) { + var load_ext = ext === '' ? '' : ext + '_s'; + return wasmEvalText( + `(module + (memory 1 + (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f") + (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff") + ) + (func (param i32) (param ${type}) (result ${type}) + (${type}.store${ext} + offset=${offset} + ${align != 0 ? 'align=' + align : ''} + (get_local 0) + (get_local 1) + ) + ) (export "store" 0) + (func (param i32) (result ${type}) + (${type}.load${load_ext} + offset=${offset} + ${align != 0 ? 'align=' + align : ''} + (get_local 0) + ) + ) (export "load" 1))` + ); +} + function testLoad(type, ext, base, offset, align, expect) { - assertEq(wasmEvalText( - '(module' + - ' (memory 1' + - ' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' + - ' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' + - ' )' + - ' (func (param i32) (result ' + type + ')' + - ' (' + type + '.load' + ext + - ' offset=' + offset + - ' ' + (align != 0 ? 'align=' + align : '') + - ' (get_local 0)' + - ' )' + - ' ) (export "" 0))' - )(base), expect); + assertEq(loadModule(type, ext, offset, align)(base), expect); +} + +function testLoadOOB(type, ext, base, offset, align) { + assertErrorMessage(() => loadModule(type, ext, offset, align)(base), Error, /invalid or out-of-range index/); } function testStore(type, ext, base, offset, align, value) { - assertEq(wasmEvalText( - '(module' + - ' (memory 1' + - ' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' + - ' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' + - ' )' + - ' (func (param i32) (param ' + type + ') (result ' + type + ')' + - ' (' + type + '.store' + ext + - ' offset=' + offset + - ' ' + (align != 0 ? 'align=' + align : '') + - ' (get_local 0)' + - ' (get_local 1)' + - ' )' + - ' ) (export "" 0))' - )(base, value), value); + let module = storeModule(type, ext, offset, align); + assertEq(module.store(base, value), value); + assertEq(module.load(base), value); } -function testLoadError(type, ext, base, offset, align, errorMsg) { - assertErrorMessage(() => wasmEvalText( - '(module' + - ' (memory 1' + - ' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' + - ' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' + - ' )' + - ' (func (param i32) (result ' + type + ')' + - ' (' + type + '.load' + ext + - ' offset=' + offset + - ' ' + (align != 0 ? 'align=' + align : '') + - ' (get_local 0)' + - ' )' + - ' ) (export "" 0))' - ), Error, errorMsg); -} - -function testStoreError(type, ext, base, offset, align, errorMsg) { - assertErrorMessage(() => wasmEvalText( - '(module' + - ' (memory 1' + - ' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' + - ' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' + - ' )' + - ' (func (param i32) (param ' + type + ') (result ' + type + ')' + - ' (' + type + '.store' + ext + - ' offset=' + offset + - ' ' + (align != 0 ? 'align=' + align : '') + - ' (get_local 0)' + - ' (get_local 1)' + - ' )' + - ' ) (export "" 0))' - ), Error, errorMsg); +function testStoreOOB(type, ext, base, offset, align, value) { + assertErrorMessage(() => storeModule(type, ext, offset, align).store(base, value), Error, /invalid or out-of-range index/); } testLoad('i32', '', 0, 0, 0, 0x03020100); @@ -143,21 +134,70 @@ testStore('f64', '', 1, 7, 4, 0.89012345); testStore('i32', '8', 0, 0, 0, 0x23); testStore('i32', '16', 0, 0, 0, 0x2345); -testLoadError('i32', '8_s', 0, 0, 2, /greater than natural alignment/); -testLoadError('i32', '8_u', 0, 0, 2, /greater than natural alignment/); -testLoadError('i32', '16_s', 0, 0, 4, /greater than natural alignment/); -testLoadError('i32', '16_u', 0, 0, 4, /greater than natural alignment/); -testLoadError('i32', '', 0, 0, 8, /greater than natural alignment/); -testLoadError('f32', '', 0, 0, 8, /greater than natural alignment/); -testLoadError('f64', '', 0, 0, 16, /greater than natural alignment/); -testStoreError('i32', '8', 0, 0, 2, /greater than natural alignment/); -testStoreError('i32', '16', 0, 0, 4, /greater than natural alignment/); -testStoreError('i32', '', 0, 0, 8, /greater than natural alignment/); -testStoreError('f32', '', 0, 0, 8, /greater than natural alignment/); -testStoreError('f64', '', 0, 0, 16, /greater than natural alignment/); - assertErrorMessage(() => wasmEvalText('(module (memory 2 1))'), TypeError, /maximum memory size less than initial memory size/); +// Test bounds checks and edge cases. +const align = 0; +for (let offset of [0, 1, 2, 3, 4, 8, 16, 41, 0xfff8]) { + // Accesses of 1 byte. + let lastValidIndex = 0x10000 - 1 - offset; + + testLoad('i32', '8_s', lastValidIndex, offset, align, 0); + testLoadOOB('i32', '8_s', lastValidIndex + 1, offset, align); + + testLoad('i32', '8_u', lastValidIndex, offset, align, 0); + testLoadOOB('i32', '8_u', lastValidIndex + 1, offset, align); + + testStore('i32', '8', lastValidIndex, offset, align, -42); + testStoreOOB('i32', '8', lastValidIndex + 1, offset, align, -42); + + // Accesses of 2 bytes. + lastValidIndex = 0x10000 - 2 - offset; + + testLoad('i32', '16_s', lastValidIndex, offset, align, 0); + testLoadOOB('i32', '16_s', lastValidIndex + 1, offset, align); + + testLoad('i32', '16_u', lastValidIndex, offset, align, 0); + testLoadOOB('i32', '16_u', lastValidIndex + 1, offset, align); + + testStore('i32', '16', lastValidIndex, offset, align, -32768); + testStoreOOB('i32', '16', lastValidIndex + 1, offset, align, -32768); + + // Accesses of 4 bytes. + lastValidIndex = 0x10000 - 4 - offset; + + testLoad('i32', '', lastValidIndex, offset, align, 0); + testLoadOOB('i32', '', lastValidIndex + 1, offset, align); + + testLoad('f32', '', lastValidIndex, offset, align, 0); + testLoadOOB('f32', '', lastValidIndex + 1, offset, align); + + testStore('i32', '', lastValidIndex, offset, align, 1337); + testStoreOOB('i32', '', lastValidIndex + 1, offset, align, 1337); + + testStore('f32', '', lastValidIndex, offset, align, Math.fround(13.37)); + testStoreOOB('f32', '', lastValidIndex + 1, offset, align, Math.fround(13.37)); + + // Accesses of 8 bytes. + lastValidIndex = 0x10000 - 8 - offset; + + testLoad('f64', '', lastValidIndex, offset, align, 0); + testLoadOOB('f64', '', lastValidIndex + 1, offset, align); + + testStore('f64', '', lastValidIndex, offset, align, 1.23456789); + testStoreOOB('f64', '', lastValidIndex + 1, offset, align, 1.23456789); +} + +// Ensure wrapping doesn't apply. +offset = 0x7fffffff; // maximum allowed offset that doesn't always throw. +for (let index of [0, 1, 2, 3, 0x7fffffff, 0x80000000, 0x80000001]) { + testLoadOOB('i32', '8_s', index, offset, align); + testLoadOOB('i32', '16_s', index, offset, align); + testLoadOOB('i32', '', index, offset, align); + testLoadOOB('f32', '', index, offset, align); + testLoadOOB('f64', '', index, offset, align); +} + assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f64")); assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "f64")); @@ -170,3 +210,44 @@ assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (i32.store offse wasmEvalText('(module (memory 0 65535))') assertErrorMessage(() => wasmEvalText('(module (memory 0 65536))'), TypeError, /maximum memory size too big/); +// Test high charge of registers +function testRegisters() { + assertEq(wasmEvalText( + `(module + (memory 1 + (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f") + (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff") + ) + (func (param i32) (local i32 i32 i32 i32 f32 f64) (result i32) + (set_local 1 (i32.load8_s offset=4 (get_local 0))) + (set_local 2 (i32.load16_s (get_local 1))) + (i32.store8 offset=4 (get_local 0) (get_local 1)) + (set_local 3 (i32.load16_u (get_local 2))) + (i32.store16 (get_local 1) (get_local 2)) + (set_local 4 (i32.load (get_local 2))) + (i32.store (get_local 1) (get_local 2)) + (set_local 5 (f32.load (get_local 4))) + (f32.store (get_local 4) (get_local 5)) + (set_local 6 (f64.load (get_local 4))) + (f64.store (get_local 4) (get_local 6)) + (i32.add + (i32.add + (get_local 0) + (get_local 1) + ) + (i32.add + (i32.add + (get_local 2) + (get_local 3) + ) + (i32.add + (get_local 4) + (i32.reinterpret/f32 (get_local 5)) + ) + ) + ) + ) (export "" 0))` + )(1), 50464523); +} + +testRegisters(); diff --git a/js/src/jit-test/tests/wasm/spec/address.wast.js b/js/src/jit-test/tests/wasm/spec/address.wast.js index a961236bb600..f24a871b5d94 100644 --- a/js/src/jit-test/tests/wasm/spec/address.wast.js +++ b/js/src/jit-test/tests/wasm/spec/address.wast.js @@ -1,4 +1,2 @@ // |jit-test| test-also-wasm-baseline -// TODO: wrapping offsets -quit(); var importedArgs = ['address.wast']; load(scriptdir + '../spec.js'); diff --git a/js/src/jit-test/tests/wasm/spec/memory.wast.js b/js/src/jit-test/tests/wasm/spec/memory.wast.js index d5f63c8dd377..ac56fe8b3b09 100644 --- a/js/src/jit-test/tests/wasm/spec/memory.wast.js +++ b/js/src/jit-test/tests/wasm/spec/memory.wast.js @@ -1,4 +1,4 @@ // |jit-test| test-also-wasm-baseline -// TODO unaligned memory accesses +// TODO i64 loads quit(); var importedArgs = ['memory.wast']; load(scriptdir + '../spec.js'); diff --git a/js/src/jit-test/tests/wasm/spec/traps.wast.js b/js/src/jit-test/tests/wasm/spec/traps.wast.js index 6f8046fe2942..087d1b78abeb 100644 --- a/js/src/jit-test/tests/wasm/spec/traps.wast.js +++ b/js/src/jit-test/tests/wasm/spec/traps.wast.js @@ -1,4 +1,4 @@ // |jit-test| test-also-wasm-baseline -// TODO trap on OOB +// TODO dce'd effectful instructions quit(); var importedArgs = ['traps.wast']; load(scriptdir + '../spec.js'); From 3ce0700825d69330296d27c4fd6f8971a43bcb16 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 7 Jul 2016 16:25:58 +0200 Subject: [PATCH 25/30] Bug 1268024: Force triggering a GC after creating a mmapped array; r=luke MozReview-Commit-ID: 1tRLdOhVqBx --HG-- extra : rebase_source : 55a0089fcb056c002a1c2f8dd9d16d74298fd15e --- js/src/vm/ArrayBufferObject.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 3b6bd80699ce..a6e951a04bcf 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -462,7 +462,7 @@ ArrayBufferObject::createForWasm(JSContext* cx, uint32_t numBytes, bool signalsF #endif } - auto buffer = ArrayBufferObject::create(cx, numBytes); + auto* buffer = ArrayBufferObject::create(cx, numBytes); if (!buffer) return nullptr; @@ -633,6 +633,10 @@ ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents content size_t nAllocated = nbytes; if (contents.kind() == MAPPED) nAllocated = JS_ROUNDUP(nbytes, js::gc::SystemPageSize()); +#ifdef ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB + else if (contents.kind() == WASM_MAPPED) + nAllocated = wasm::MappedSize; +#endif cx->zone()->updateMallocCounter(nAllocated); } } else { From e0915741f11f80f89abcb74afd80ca559ca9f5d6 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 8 Jul 2016 10:07:05 +0200 Subject: [PATCH 26/30] Bug 1283344 - Enable dom/filesystem/test/test_worker_basic.html again, r=me --- dom/filesystem/tests/mochitest.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/dom/filesystem/tests/mochitest.ini b/dom/filesystem/tests/mochitest.ini index cc2ef1c71933..93e56b3da48c 100644 --- a/dom/filesystem/tests/mochitest.ini +++ b/dom/filesystem/tests/mochitest.ini @@ -7,4 +7,3 @@ support-files = [test_basic.html] [test_webkitdirectory.html] [test_worker_basic.html] -skip-if = true # bug 1283344 From d2841a58653ba7f5b27e1c1a3ff740aac40d5e8a Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Fri, 8 Jul 2016 17:56:30 +0900 Subject: [PATCH 27/30] Bug 1284206 - Update VIXL to 1.11. r=sstangl MozReview-Commit-ID: BUBOPBe8b6M --- js/src/jit/arm64/vixl/Debugger-vixl.cpp | 23 ++- js/src/jit/arm64/vixl/Debugger-vixl.h | 4 + js/src/jit/arm64/vixl/Decoder-vixl.h | 12 +- js/src/jit/arm64/vixl/Logic-vixl.cpp | 4 + js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp | 2 + js/src/jit/arm64/vixl/MacroAssembler-vixl.h | 2 + .../jit/arm64/vixl/Simulator-Constants-vixl.h | 141 ++++++++++++++++++ js/src/jit/arm64/vixl/Simulator-vixl.cpp | 71 ++++----- js/src/jit/arm64/vixl/Simulator-vixl.h | 131 ++-------------- 9 files changed, 214 insertions(+), 176 deletions(-) create mode 100644 js/src/jit/arm64/vixl/Simulator-Constants-vixl.h diff --git a/js/src/jit/arm64/vixl/Debugger-vixl.cpp b/js/src/jit/arm64/vixl/Debugger-vixl.cpp index 67a7ba4ef327..85097ed5a086 100644 --- a/js/src/jit/arm64/vixl/Debugger-vixl.cpp +++ b/js/src/jit/arm64/vixl/Debugger-vixl.cpp @@ -61,7 +61,7 @@ class Token { virtual bool IsUnknown() const { return false; } // Token properties. virtual bool CanAddressMemory() const { return false; } - virtual uint8_t* ToAddress(Debugger* debugger) const; + virtual uint8_t* ToAddress(Debugger* debugger) const = 0; virtual void Print(FILE* out = stdout) const = 0; static Token* Tokenize(const char* arg); @@ -77,6 +77,11 @@ template class ValueToken : public Token { T value() const { return value_; } + virtual uint8_t* ToAddress(Debugger* debugger) const { + USE(debugger); + VIXL_ABORT(); + } + protected: T value_; }; @@ -202,6 +207,11 @@ class FormatToken : public Token { virtual void PrintData(void* data, FILE* out = stdout) const = 0; virtual void Print(FILE* out = stdout) const = 0; + virtual uint8_t* ToAddress(Debugger* debugger) const { + USE(debugger); + VIXL_ABORT(); + } + static Token* Tokenize(const char* arg); static FormatToken* Cast(Token* tok) { VIXL_ASSERT(tok->IsFormat()); @@ -237,6 +247,10 @@ class UnknownToken : public Token { strncpy(unknown_, arg, size); } virtual ~UnknownToken() { js_free(unknown_); } + virtual uint8_t* ToAddress(Debugger* debugger) const { + USE(debugger); + VIXL_ABORT(); + } virtual bool IsUnknown() const { return true; } virtual void Print(FILE* out = stdout) const; @@ -797,13 +811,6 @@ static bool StringToInt64(int64_t* value, const char* line, int base = 10) { } -uint8_t* Token::ToAddress(Debugger* debugger) const { - USE(debugger); - VIXL_UNREACHABLE(); - return NULL; -} - - Token* Token::Tokenize(const char* arg) { if ((arg == NULL) || (*arg == '\0')) { return NULL; diff --git a/js/src/jit/arm64/vixl/Debugger-vixl.h b/js/src/jit/arm64/vixl/Debugger-vixl.h index 86c5a91c79f6..be2b3d9cf696 100644 --- a/js/src/jit/arm64/vixl/Debugger-vixl.h +++ b/js/src/jit/arm64/vixl/Debugger-vixl.h @@ -24,6 +24,8 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#ifdef JS_SIMULATOR_ARM64 + #ifndef VIXL_A64_DEBUGGER_A64_H_ #define VIXL_A64_DEBUGGER_A64_H_ @@ -111,3 +113,5 @@ class Debugger : public Simulator { } // namespace vixl #endif // VIXL_A64_DEBUGGER_A64_H_ + +#endif // JS_SIMULATOR_ARM64 diff --git a/js/src/jit/arm64/vixl/Decoder-vixl.h b/js/src/jit/arm64/vixl/Decoder-vixl.h index 1ac268f35a6d..95dd589e8ab0 100644 --- a/js/src/jit/arm64/vixl/Decoder-vixl.h +++ b/js/src/jit/arm64/vixl/Decoder-vixl.h @@ -37,7 +37,7 @@ // List macro containing all visitors needed by the decoder class. -#define VISITOR_LIST(V) \ +#define VISITOR_LIST_THAT_RETURN(V) \ V(PCRelAddressing) \ V(AddSubImmediate) \ V(LogicalImmediate) \ @@ -106,8 +106,14 @@ V(NEONShiftImmediate) \ V(NEONTable) \ V(NEONPerm) \ - V(Unallocated) \ - V(Unimplemented) + +#define VISITOR_LIST_THAT_DONT_RETURN(V) \ + V(Unallocated) \ + V(Unimplemented) \ + +#define VISITOR_LIST(V) \ + VISITOR_LIST_THAT_RETURN(V) \ + VISITOR_LIST_THAT_DONT_RETURN(V) \ namespace vixl { diff --git a/js/src/jit/arm64/vixl/Logic-vixl.cpp b/js/src/jit/arm64/vixl/Logic-vixl.cpp index d43e0951f787..539e145ec6c2 100644 --- a/js/src/jit/arm64/vixl/Logic-vixl.cpp +++ b/js/src/jit/arm64/vixl/Logic-vixl.cpp @@ -24,6 +24,8 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#ifdef JS_SIMULATOR_ARM64 + #include #include "jit/arm64/vixl/Simulator-vixl.h" @@ -4872,3 +4874,5 @@ LogicVRegister Simulator::ucvtf(VectorFormat vform, } // namespace vixl + +#endif // JS_SIMULATOR_ARM64 diff --git a/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp b/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp index 90822c3b71ef..02c62ecdbd1c 100644 --- a/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp +++ b/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp @@ -26,6 +26,8 @@ #include "jit/arm64/vixl/MacroAssembler-vixl.h" +#include + namespace vixl { MacroAssembler::MacroAssembler() diff --git a/js/src/jit/arm64/vixl/MacroAssembler-vixl.h b/js/src/jit/arm64/vixl/MacroAssembler-vixl.h index e52359a17fd1..474c1de00723 100644 --- a/js/src/jit/arm64/vixl/MacroAssembler-vixl.h +++ b/js/src/jit/arm64/vixl/MacroAssembler-vixl.h @@ -33,6 +33,8 @@ #include "jit/arm64/Assembler-arm64.h" #include "jit/arm64/vixl/Debugger-vixl.h" #include "jit/arm64/vixl/Globals-vixl.h" +#include "jit/arm64/vixl/Instrument-vixl.h" +#include "jit/arm64/vixl/Simulator-Constants-vixl.h" #define LS_MACRO_LIST(V) \ V(Ldrb, Register&, rt, LDRB_w) \ diff --git a/js/src/jit/arm64/vixl/Simulator-Constants-vixl.h b/js/src/jit/arm64/vixl/Simulator-Constants-vixl.h new file mode 100644 index 000000000000..9a66ab023581 --- /dev/null +++ b/js/src/jit/arm64/vixl/Simulator-Constants-vixl.h @@ -0,0 +1,141 @@ +// Copyright 2015, ARM Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of ARM Limited nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef VIXL_A64_SIMULATOR_CONSTANTS_A64_H_ +#define VIXL_A64_SIMULATOR_CONSTANTS_A64_H_ + +namespace vixl { + +// Debug instructions. +// +// VIXL's macro-assembler and simulator support a few pseudo instructions to +// make debugging easier. These pseudo instructions do not exist on real +// hardware. +// +// TODO: Also consider allowing these pseudo-instructions to be disabled in the +// simulator, so that users can check that the input is a valid native code. +// (This isn't possible in all cases. Printf won't work, for example.) +// +// Each debug pseudo instruction is represented by a HLT instruction. The HLT +// immediate field is used to identify the type of debug pseudo instruction. + +enum DebugHltOpcodes { + kUnreachableOpcode = 0xdeb0, + kPrintfOpcode, + kTraceOpcode, + kLogOpcode, + // Aliases. + kDebugHltFirstOpcode = kUnreachableOpcode, + kDebugHltLastOpcode = kLogOpcode +}; + +// Each pseudo instruction uses a custom encoding for additional arguments, as +// described below. + +// Unreachable - kUnreachableOpcode +// +// Instruction which should never be executed. This is used as a guard in parts +// of the code that should not be reachable, such as in data encoded inline in +// the instructions. + +// Printf - kPrintfOpcode +// - arg_count: The number of arguments. +// - arg_pattern: A set of PrintfArgPattern values, packed into two-bit fields. +// +// Simulate a call to printf. +// +// Floating-point and integer arguments are passed in separate sets of registers +// in AAPCS64 (even for varargs functions), so it is not possible to determine +// the type of each argument without some information about the values that were +// passed in. This information could be retrieved from the printf format string, +// but the format string is not trivial to parse so we encode the relevant +// information with the HLT instruction. +// +// Also, the following registers are populated (as if for a native A64 call): +// x0: The format string +// x1-x7: Optional arguments, if type == CPURegister::kRegister +// d0-d7: Optional arguments, if type == CPURegister::kFPRegister +const unsigned kPrintfArgCountOffset = 1 * kInstructionSize; +const unsigned kPrintfArgPatternListOffset = 2 * kInstructionSize; +const unsigned kPrintfLength = 3 * kInstructionSize; + +const unsigned kPrintfMaxArgCount = 4; + +// The argument pattern is a set of two-bit-fields, each with one of the +// following values: +enum PrintfArgPattern { + kPrintfArgW = 1, + kPrintfArgX = 2, + // There is no kPrintfArgS because floats are always converted to doubles in C + // varargs calls. + kPrintfArgD = 3 +}; +static const unsigned kPrintfArgPatternBits = 2; + +// Trace - kTraceOpcode +// - parameter: TraceParameter stored as a uint32_t +// - command: TraceCommand stored as a uint32_t +// +// Allow for trace management in the generated code. This enables or disables +// automatic tracing of the specified information for every simulated +// instruction. +const unsigned kTraceParamsOffset = 1 * kInstructionSize; +const unsigned kTraceCommandOffset = 2 * kInstructionSize; +const unsigned kTraceLength = 3 * kInstructionSize; + +// Trace parameters. +enum TraceParameters { + LOG_DISASM = 1 << 0, // Log disassembly. + LOG_REGS = 1 << 1, // Log general purpose registers. + LOG_VREGS = 1 << 2, // Log NEON and floating-point registers. + LOG_SYSREGS = 1 << 3, // Log the flags and system registers. + LOG_WRITE = 1 << 4, // Log writes to memory. + + LOG_NONE = 0, + LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYSREGS, + LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE +}; + +// Trace commands. +enum TraceCommand { + TRACE_ENABLE = 1, + TRACE_DISABLE = 2 +}; + +// Log - kLogOpcode +// - parameter: TraceParameter stored as a uint32_t +// +// Print the specified information once. This mechanism is separate from Trace. +// In particular, _all_ of the specified registers are printed, rather than just +// the registers that the instruction writes. +// +// Any combination of the TraceParameters values can be used, except that +// LOG_DISASM is not supported for Log. +const unsigned kLogParamsOffset = 1 * kInstructionSize; +const unsigned kLogLength = 2 * kInstructionSize; +} // namespace vixl + +#endif // VIXL_A64_SIMULATOR_CONSTANTS_A64_H_ diff --git a/js/src/jit/arm64/vixl/Simulator-vixl.cpp b/js/src/jit/arm64/vixl/Simulator-vixl.cpp index 940d5ff32426..9d95a2bb4b81 100644 --- a/js/src/jit/arm64/vixl/Simulator-vixl.cpp +++ b/js/src/jit/arm64/vixl/Simulator-vixl.cpp @@ -213,56 +213,39 @@ void Simulator::set_instruction_stats(bool value) { } // Helpers --------------------------------------------------------------------- -int64_t Simulator::AddWithCarry(unsigned reg_size, - bool set_flags, - int64_t src1, - int64_t src2, - int64_t carry_in) { +uint64_t Simulator::AddWithCarry(unsigned reg_size, + bool set_flags, + uint64_t left, + uint64_t right, + int carry_in) { VIXL_ASSERT((carry_in == 0) || (carry_in == 1)); VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize)); - uint64_t u1, u2; - int64_t result; - int64_t signed_sum = src1 + src2 + carry_in; + uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt; + uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask; + uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask; - uint32_t N, Z, C, V; - - if (reg_size == kWRegSize) { - u1 = static_cast(src1) & kWRegMask; - u2 = static_cast(src2) & kWRegMask; - - result = signed_sum & kWRegMask; - // Compute the C flag by comparing the sum to the max unsigned integer. - C = ((kWMaxUInt - u1) < (u2 + carry_in)) || - ((kWMaxUInt - u1 - carry_in) < u2); - // Overflow iff the sign bit is the same for the two inputs and different - // for the result. - int64_t s_src1 = src1 << (kXRegSize - kWRegSize); - int64_t s_src2 = src2 << (kXRegSize - kWRegSize); - int64_t s_result = result << (kXRegSize - kWRegSize); - V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0); - - } else { - u1 = static_cast(src1); - u2 = static_cast(src2); - - result = signed_sum; - // Compute the C flag by comparing the sum to the max unsigned integer. - C = ((kXMaxUInt - u1) < (u2 + carry_in)) || - ((kXMaxUInt - u1 - carry_in) < u2); - // Overflow iff the sign bit is the same for the two inputs and different - // for the result. - V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); - } - - N = CalcNFlag(result, reg_size); - Z = CalcZFlag(result); + left &= reg_mask; + right &= reg_mask; + uint64_t result = (left + right + carry_in) & reg_mask; if (set_flags) { - nzcv().SetN(N); - nzcv().SetZ(Z); - nzcv().SetC(C); - nzcv().SetV(V); + nzcv().SetN(CalcNFlag(result, reg_size)); + nzcv().SetZ(CalcZFlag(result)); + + // Compute the C flag by comparing the result to the max unsigned integer. + uint64_t max_uint_2op = max_uint - carry_in; + bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right); + nzcv().SetC(C ? 1 : 0); + + // Overflow iff the sign bit is the same for the two inputs and different + // for the result. + uint64_t left_sign = left & sign_mask; + uint64_t right_sign = right & sign_mask; + uint64_t result_sign = result & sign_mask; + bool V = (left_sign == right_sign) && (left_sign != result_sign); + nzcv().SetV(V ? 1 : 0); + LogSystemRegister(NZCV); } return result; diff --git a/js/src/jit/arm64/vixl/Simulator-vixl.h b/js/src/jit/arm64/vixl/Simulator-vixl.h index e8ded1746a36..bae6128f70e6 100644 --- a/js/src/jit/arm64/vixl/Simulator-vixl.h +++ b/js/src/jit/arm64/vixl/Simulator-vixl.h @@ -40,6 +40,7 @@ #include "jit/arm64/vixl/Globals-vixl.h" #include "jit/arm64/vixl/Instructions-vixl.h" #include "jit/arm64/vixl/Instrument-vixl.h" +#include "jit/arm64/vixl/Simulator-Constants-vixl.h" #include "jit/arm64/vixl/Utils-vixl.h" #include "jit/IonTypes.h" #include "threading/Mutex.h" @@ -55,120 +56,6 @@ namespace vixl { -// Debug instructions. -// -// VIXL's macro-assembler and simulator support a few pseudo instructions to -// make debugging easier. These pseudo instructions do not exist on real -// hardware. -// -// TODO: Provide controls to prevent the macro assembler from emitting -// pseudo-instructions. This is important for ahead-of-time compilers, where the -// macro assembler is built with USE_SIMULATOR but the code will eventually be -// run on real hardware. -// -// TODO: Also consider allowing these pseudo-instructions to be disabled in the -// simulator, so that users can check that the input is a valid native code. -// (This isn't possible in all cases. Printf won't work, for example.) -// -// Each debug pseudo instruction is represented by a HLT instruction. The HLT -// immediate field is used to identify the type of debug pseudo instruction. - -enum DebugHltOpcodes { - kUnreachableOpcode = 0xdeb0, - kPrintfOpcode, - kTraceOpcode, - kLogOpcode, - // Aliases. - kDebugHltFirstOpcode = kUnreachableOpcode, - kDebugHltLastOpcode = kLogOpcode -}; - -// Each pseudo instruction uses a custom encoding for additional arguments, as -// described below. - -// Unreachable - kUnreachableOpcode -// -// Instruction which should never be executed. This is used as a guard in parts -// of the code that should not be reachable, such as in data encoded inline in -// the instructions. - -// Printf - kPrintfOpcode -// - arg_count: The number of arguments. -// - arg_pattern: A set of PrintfArgPattern values, packed into two-bit fields. -// -// Simulate a call to printf. -// -// Floating-point and integer arguments are passed in separate sets of registers -// in AAPCS64 (even for varargs functions), so it is not possible to determine -// the type of each argument without some information about the values that were -// passed in. This information could be retrieved from the printf format string, -// but the format string is not trivial to parse so we encode the relevant -// information with the HLT instruction. -// -// Also, the following registers are populated (as if for a native A64 call): -// x0: The format string -// x1-x7: Optional arguments, if type == CPURegister::kRegister -// d0-d7: Optional arguments, if type == CPURegister::kFPRegister -const unsigned kPrintfArgCountOffset = 1 * kInstructionSize; -const unsigned kPrintfArgPatternListOffset = 2 * kInstructionSize; -const unsigned kPrintfLength = 3 * kInstructionSize; - -const unsigned kPrintfMaxArgCount = 4; - -// The argument pattern is a set of two-bit-fields, each with one of the -// following values: -enum PrintfArgPattern { - kPrintfArgW = 1, - kPrintfArgX = 2, - // There is no kPrintfArgS because floats are always converted to doubles in C - // varargs calls. - kPrintfArgD = 3 -}; -static const unsigned kPrintfArgPatternBits = 2; - -// Trace - kTraceOpcode -// - parameter: TraceParameter stored as a uint32_t -// - command: TraceCommand stored as a uint32_t -// -// Allow for trace management in the generated code. This enables or disables -// automatic tracing of the specified information for every simulated -// instruction. -const unsigned kTraceParamsOffset = 1 * kInstructionSize; -const unsigned kTraceCommandOffset = 2 * kInstructionSize; -const unsigned kTraceLength = 3 * kInstructionSize; - -// Trace parameters. -enum TraceParameters { - LOG_DISASM = 1 << 0, // Log disassembly. - LOG_REGS = 1 << 1, // Log general purpose registers. - LOG_VREGS = 1 << 2, // Log NEON and floating-point registers. - LOG_SYSREGS = 1 << 3, // Log the flags and system registers. - LOG_WRITE = 1 << 4, // Log writes to memory. - - LOG_NONE = 0, - LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYSREGS, - LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE -}; - -// Trace commands. -enum TraceCommand { - TRACE_ENABLE = 1, - TRACE_DISABLE = 2 -}; - -// Log - kLogOpcode -// - parameter: TraceParameter stored as a uint32_t -// -// Print the specified information once. This mechanism is separate from Trace. -// In particular, _all_ of the specified registers are printed, rather than just -// the registers that the instruction writes. -// -// Any combination of the TraceParameters values can be used, except that -// LOG_DISASM is not supported for Log. -const unsigned kLogParamsOffset = 1 * kInstructionSize; -const unsigned kLogLength = 2 * kInstructionSize; - - // Assemble the specified IEEE-754 components into the target type and apply // appropriate rounding. // sign: 0 = positive, 1 = negative @@ -877,9 +764,11 @@ class Simulator : public DecoderVisitor { // Declare all Visitor functions. #define DECLARE(A) virtual void Visit##A(const Instruction* instr); - VISITOR_LIST(DECLARE) + VISITOR_LIST_THAT_RETURN(DECLARE) + VISITOR_LIST_THAT_DONT_RETURN(DECLARE) #undef DECLARE + // Integer register accessors. // Basic accessor: Read the register as the specified type. @@ -1434,11 +1323,11 @@ class Simulator : public DecoderVisitor { } void AddSubHelper(const Instruction* instr, int64_t op2); - int64_t AddWithCarry(unsigned reg_size, - bool set_flags, - int64_t src1, - int64_t src2, - int64_t carry_in = 0); + uint64_t AddWithCarry(unsigned reg_size, + bool set_flags, + uint64_t left, + uint64_t right, + int carry_in = 0); void LogicalHelper(const Instruction* instr, int64_t op2); void ConditionalCompareHelper(const Instruction* instr, int64_t op2); void LoadStoreHelper(const Instruction* instr, @@ -2677,7 +2566,7 @@ class Simulator : public DecoderVisitor { } static int CalcZFlag(uint64_t result) { - return result == 0; + return (result == 0) ? 1 : 0; } static const uint32_t kConditionFlagsMask = 0xf0000000; From d59fd8b80f7476a8e5b427d3b443ebb46f2eeb20 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Fri, 8 Jul 2016 10:17:08 +0100 Subject: [PATCH 28/30] Bug 1284388 - Check shape table consistency in debug builds r=terrence --- js/src/gc/Marking.cpp | 4 +++- js/src/vm/Shape.cpp | 22 ++++++++++++++++++++++ js/src/vm/Shape.h | 6 ++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 9703c39177bc..cfb1dcca5c0c 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -1042,8 +1042,10 @@ js::GCMarker::eagerlyMarkChildren(Shape* shape) // be traced by this loop they do not need to be traced here as well. BaseShape* base = shape->base(); CheckTraversedEdge(shape, base); - if (mark(base)) + if (mark(base)) { + MOZ_ASSERT(base->canSkipMarkingShapeTable(shape)); base->traceChildrenSkipShapeTable(this); + } traverseEdge(shape, shape->propidRef().get()); diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index bba5c5257764..33fd0cd96de6 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1358,6 +1358,28 @@ BaseShape::traceShapeTable(JSTracer* trc) table().trace(trc); } +#ifdef DEBUG +bool +BaseShape::canSkipMarkingShapeTable(Shape* lastShape) +{ + // Check that every shape in the shape table will be marked by marking + // |lastShape|. + + if (!hasTable()) + return true; + + uint32_t count = 0; + for (Shape::Range r(lastShape); !r.empty(); r.popFront()) { + Shape* shape = &r.front(); + ShapeTable::Entry& entry = table().search(shape->propid()); + if (entry.isLive()) + count++; + } + + return count == table().entryCount(); +} +#endif + #ifdef JSGC_HASH_TABLE_CHECKS void diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index d5fddab625fc..1a6601b8df7d 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -129,6 +129,7 @@ enum class MaybeAdding { Adding = true, NotAdding = false }; class ShapeTable { public: friend class NativeObject; + friend class BaseShape; static const uint32_t MIN_ENTRIES = 11; class Entry { @@ -145,6 +146,7 @@ class ShapeTable { public: bool isFree() const { return shape_ == nullptr; } bool isRemoved() const { return shape_ == SHAPE_REMOVED; } + bool isLive() const { return !isFree() && !isRemoved(); } bool hadCollision() const { return uintptr_t(shape_) & SHAPE_COLLISION; } void setFree() { shape_ = nullptr; } @@ -454,6 +456,10 @@ class BaseShape : public gc::TenuredCell void traceChildren(JSTracer* trc); void traceChildrenSkipShapeTable(JSTracer* trc); +#ifdef DEBUG + bool canSkipMarkingShapeTable(Shape* lastShape); +#endif + private: static void staticAsserts() { JS_STATIC_ASSERT(offsetof(BaseShape, clasp_) == offsetof(js::shadow::BaseShape, clasp_)); From 60e9d13dc31a237373947bce054f708154025bda Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Thu, 30 Jun 2016 15:25:55 -0400 Subject: [PATCH 29/30] Bug 1283438 - Set AUTOCLOBBER to empty for l10n r=glandium. Needed because buildbot clones/checks out from the repo head (of default) and then updates to the rev for the nightly we're pulling, which can cause CLOBBER file changes to initiate an unwanted clobber of the object directory where we just pulled the nightly binary from. Even when CLOBBER hasn't actually been touched in the changeset range we're looking at between nightlies. MozReview-Commit-ID: 154d2iZeHgd --HG-- extra : rebase_source : 504b821955a870cabf6fc727d13e44a33aabb45c --- browser/config/mozconfigs/linux32/l10n-mozconfig | 4 ++++ browser/config/mozconfigs/linux64/l10n-mozconfig | 4 ++++ browser/config/mozconfigs/macosx-universal/l10n-mozconfig | 4 ++++ browser/config/mozconfigs/macosx64/l10n-mozconfig | 4 ++++ browser/config/mozconfigs/win32/l10n-mozconfig | 4 ++++ browser/config/mozconfigs/win64/l10n-mozconfig | 4 ++++ mobile/android/config/mozconfigs/android-api-15/l10n-nightly | 4 ++++ mobile/android/config/mozconfigs/android-api-15/l10n-release | 4 ++++ mobile/android/config/mozconfigs/android-x86/l10n-nightly | 4 ++++ mobile/android/config/mozconfigs/android-x86/l10n-release | 4 ++++ 10 files changed, 40 insertions(+) diff --git a/browser/config/mozconfigs/linux32/l10n-mozconfig b/browser/config/mozconfigs/linux32/l10n-mozconfig index 1f65f1149106..2e5966ef65bd 100644 --- a/browser/config/mozconfigs/linux32/l10n-mozconfig +++ b/browser/config/mozconfigs/linux32/l10n-mozconfig @@ -13,4 +13,8 @@ export MOZ_TELEMETRY_REPORTING=1 ac_add_options --disable-stdcxx-compat +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/build/mozconfig.common.override" diff --git a/browser/config/mozconfigs/linux64/l10n-mozconfig b/browser/config/mozconfigs/linux64/l10n-mozconfig index 63fd074cbee2..0de3ab7521e4 100644 --- a/browser/config/mozconfigs/linux64/l10n-mozconfig +++ b/browser/config/mozconfigs/linux64/l10n-mozconfig @@ -13,4 +13,8 @@ export MOZ_TELEMETRY_REPORTING=1 ac_add_options --disable-stdcxx-compat +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/build/mozconfig.common.override" diff --git a/browser/config/mozconfigs/macosx-universal/l10n-mozconfig b/browser/config/mozconfigs/macosx-universal/l10n-mozconfig index f0911efbdaef..5ff95274fbe9 100644 --- a/browser/config/mozconfigs/macosx-universal/l10n-mozconfig +++ b/browser/config/mozconfigs/macosx-universal/l10n-mozconfig @@ -14,5 +14,9 @@ export MOZILLA_OFFICIAL=1 # Enable Telemetry export MOZ_TELEMETRY_REPORTING=1 +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/build/mozconfig.common.override" . "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx64/l10n-mozconfig b/browser/config/mozconfigs/macosx64/l10n-mozconfig index 903bc2327a51..7f9316bbf729 100644 --- a/browser/config/mozconfigs/macosx64/l10n-mozconfig +++ b/browser/config/mozconfigs/macosx64/l10n-mozconfig @@ -4,5 +4,9 @@ ac_add_options --with-l10n-base=../../l10n ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --with-branding=browser/branding/nightly +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/build/mozconfig.common.override" . "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/win32/l10n-mozconfig b/browser/config/mozconfigs/win32/l10n-mozconfig index c604eb594d30..1b2a44550e96 100644 --- a/browser/config/mozconfigs/win32/l10n-mozconfig +++ b/browser/config/mozconfigs/win32/l10n-mozconfig @@ -10,6 +10,10 @@ export MOZILLA_OFFICIAL=1 # Enable Telemetry export MOZ_TELEMETRY_REPORTING=1 +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . $topsrcdir/build/win32/mozconfig.vs-latest . "$topsrcdir/build/mozconfig.common.override" diff --git a/browser/config/mozconfigs/win64/l10n-mozconfig b/browser/config/mozconfigs/win64/l10n-mozconfig index ee721b08208f..960c8a74debf 100644 --- a/browser/config/mozconfigs/win64/l10n-mozconfig +++ b/browser/config/mozconfigs/win64/l10n-mozconfig @@ -11,6 +11,10 @@ export MOZILLA_OFFICIAL=1 # Enable Telemetry export MOZ_TELEMETRY_REPORTING=1 +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . $topsrcdir/build/win64/mozconfig.vs-latest . "$topsrcdir/build/mozconfig.common.override" diff --git a/mobile/android/config/mozconfigs/android-api-15/l10n-nightly b/mobile/android/config/mozconfigs/android-api-15/l10n-nightly index db5a289789f1..ca8ceebfef05 100644 --- a/mobile/android/config/mozconfigs/android-api-15/l10n-nightly +++ b/mobile/android/config/mozconfigs/android-api-15/l10n-nightly @@ -21,4 +21,8 @@ ac_add_options --with-branding=mobile/android/branding/nightly ac_add_options --disable-stdcxx-compat +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-api-15/l10n-release b/mobile/android/config/mozconfigs/android-api-15/l10n-release index f3c1a8a3c1da..3fe79aebfd1e 100644 --- a/mobile/android/config/mozconfigs/android-api-15/l10n-release +++ b/mobile/android/config/mozconfigs/android-api-15/l10n-release @@ -22,4 +22,8 @@ ac_add_options --with-branding=mobile/android/branding/beta ac_add_options --disable-stdcxx-compat +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-x86/l10n-nightly b/mobile/android/config/mozconfigs/android-x86/l10n-nightly index c34b677b6be0..5a230e178184 100644 --- a/mobile/android/config/mozconfigs/android-x86/l10n-nightly +++ b/mobile/android/config/mozconfigs/android-x86/l10n-nightly @@ -20,4 +20,8 @@ ac_add_options --with-branding=mobile/android/branding/nightly ac_add_options --disable-stdcxx-compat +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-x86/l10n-release b/mobile/android/config/mozconfigs/android-x86/l10n-release index 05ad5cfdfcbd..0e9ed9749b8d 100644 --- a/mobile/android/config/mozconfigs/android-x86/l10n-release +++ b/mobile/android/config/mozconfigs/android-x86/l10n-release @@ -21,4 +21,8 @@ ac_add_options --with-branding=mobile/android/branding/beta ac_add_options --disable-stdcxx-compat +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/mobile/android/config/mozconfigs/common.override" From b8d55438dfafada4ce1a2f28e1b8a3420fe82237 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Fri, 8 Jul 2016 11:59:12 -0700 Subject: [PATCH 30/30] Backed out changeset cf971ca7f132 (bug 1278990) for likely nightly bustage a=backout CLOSED TREE --HG-- extra : amend_source : 885e0942249b31cba5b3123caad9d83c3f555c6c --- build/mozconfig.cache | 44 +------------------------------------------ 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/build/mozconfig.cache b/build/mozconfig.cache index f4427d834352..46c7acb4a5a8 100644 --- a/build/mozconfig.cache +++ b/build/mozconfig.cache @@ -7,8 +7,6 @@ # Avoid duplication if the file happens to be included twice. if test -z "$bucket" -a -z "$NO_CACHE"; then -# buildbot (or builders that use buildprops.json): -if [ -f $topsrcdir/../buildprops.json ]; then read branch platform master < /dev/null) EOF @@ -42,46 +40,6 @@ if test -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z esac fi -# taskcluster: -else - # timeout after 1 second, and don't retry (failure indicates instance is not in ec2 or wget, network issue) - # availability_zone is of the form where region is e.g. us-west-2, and az is us-west-2a - availability_zone=$(wget -T 1 -t 1 -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone) - # region is az with last letter trimmed - region=${availability_zone%?} - if test -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z "$MOZ_PGO"; then - # set S3 bucket according to tree (level) - case "${GECKO_HEAD_REPOSITORY}" in - *hg.mozilla.org/try*) - bucket=taskcluster-level-1-sccache-${region} - ;; - *hg.mozilla.org/integration/mozilla-inbound*|*hg.mozilla.org/integration/fx-team*) - bucket=taskcluster-level-3-sccache-${region} - ;; - esac - fi - - # set a dummy master - case "${region}" in - us-east-1) - master=dummy.use1.mozilla.com - ;; - us-west-1) - master=dummy.usw1.mozilla.com - ;; - us-west-2) - master=dummy.usw2.mozilla.com - ;; - esac - - # set platform based on the SYSTEMROOT env var - case "${SYSTEMROOT}" in - *Windows) - platform=windows - ;; - esac -fi - if test -z "$bucket"; then case "$platform" in win*) : ;; @@ -95,7 +53,7 @@ else fi mk_add_options "export SCCACHE_BUCKET=$bucket" case "$master" in - *us[ew][12].mozilla.com*) + *use1.mozilla.com*|*usw2.mozilla.com*) mk_add_options "export SCCACHE_NAMESERVER=169.254.169.253" ;; esac