Merge mozilla-central to autoland. a=merge CLOSED TREE
authorshindli <shindli@mozilla.com>
Sat, 06 Apr 2019 00:51:18 +0300
changeset 468247 161cd9e81d7104807d1e8a68933ca28bed1f2e8c
parent 468246 ed9c289b46b85b95c35f7fc65e6a484743469ec0 (current diff)
parent 468209 8cc6d083001bd54e17fd6b332807f32b6e336d96 (diff)
child 468248 662b776a02e6d046b0358cb89b53c19477a4bc67
push id35824
push userapavel@mozilla.com
push dateSat, 06 Apr 2019 10:57:50 +0000
treeherdermozilla-central@a765634b9ec2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland. a=merge CLOSED TREE
mfbt/Assertions.h
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1510,17 +1510,19 @@ class BaseStackFrame final : public Base
     // It assumes the stack is growing down and that locals are on the stack
     // at lower addresses than Frame, and is the offset from Frame of the
     // lowest-addressed byte of the local.
     const int32_t offs;
 
     Local(MIRType type, int32_t offs) : type(type), offs(offs) {}
   };
 
-  using LocalVector = Vector<Local, 8, SystemAllocPolicy>;
+  // Profiling shows that the number of parameters and locals frequently
+  // touches or exceeds 8.  So 16 seems like a reasonable starting point.
+  using LocalVector = Vector<Local, 16, SystemAllocPolicy>;
 
   // Initialize `localInfo` based on the types of `locals` and `args`.
   bool setupLocals(const ValTypeVector& locals, const ValTypeVector& args,
                    bool debugEnabled, LocalVector* localInfo) {
     if (!localInfo->reserve(locals.length())) {
       return false;
     }
 
@@ -1985,17 +1987,17 @@ struct Stk {
     return slot_;
   }
   uint32_t offs() const {
     MOZ_ASSERT(isMem());
     return offs_;
   }
 };
 
-typedef Vector<Stk, 8, SystemAllocPolicy> StkVector;
+typedef Vector<Stk, 0, SystemAllocPolicy> StkVector;
 
 // MachineStackTracker, used for stack-slot pointerness tracking.
 
 class MachineStackTracker {
   // Simulates the machine's stack, with one bool per word.  Index zero in
   // this vector corresponds to the highest address in the machine stack.  The
   // last entry corresponds to what SP currently points at.  This all assumes
   // a grow-down stack.
@@ -2560,18 +2562,19 @@ class BaseCompiler final : public BaseCo
   RegF64 joinRegF64_;
 
   // There are more members scattered throughout.
 
  public:
   BaseCompiler(const ModuleEnvironment& env, const FuncCompileInput& input,
                const ValTypeVector& locals, const MachineState& trapExitLayout,
                size_t trapExitLayoutNumWords, Decoder& decoder,
-               TempAllocator* alloc, MacroAssembler* masm,
+               StkVector& stkSource, TempAllocator* alloc, MacroAssembler* masm,
                StackMaps* stackMaps);
+  ~BaseCompiler();
 
   MOZ_MUST_USE bool init();
 
   FuncOffsets finish();
 
   MOZ_MUST_USE bool emitFunction();
   void emitInitStackLocals();
 
@@ -2860,18 +2863,32 @@ class BaseCompiler final : public BaseCo
   // and immediate-constant use.  It tracks constants, latent
   // references to locals, register contents, and values on the CPU
   // stack.
   //
   // The stack can be flushed to memory using sync().  This is handy
   // to avoid problems with control flow and messy register usage
   // patterns.
 
+  // This is the value stack actually used during compilation.  It is a
+  // StkVector rather than a StkVector& since constantly dereferencing a
+  // StkVector& adds about 0.5% or more to the compiler's dynamic instruction
+  // count.
   StkVector stk_;
 
+  // BaselineCompileFunctions() "lends" us the StkVector to use in this
+  // BaseCompiler object, and that is installed in |stk_| in our constructor.
+  // This is so as to avoid having to malloc/free the vector's contents at
+  // each creation/destruction of a BaseCompiler object.  It does however mean
+  // that we need to hold on to a reference to BaselineCompileFunctions()'s
+  // vector, so we can swap (give) its contents back when this BaseCompiler
+  // object is destroyed.  This significantly reduces the heap turnover of the
+  // baseline compiler.  See bug 1532592.
+  StkVector& stkSource_;
+
 #ifdef DEBUG
   size_t countMemRefsOnStk() {
     size_t nRefs = 0;
     for (Stk& v : stk_) {
       if (v.kind() == Stk::MemRef) {
         nRefs++;
       }
     }
@@ -11771,18 +11788,18 @@ bool BaseCompiler::emitFunction() {
   return true;
 }
 
 BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
                            const FuncCompileInput& func,
                            const ValTypeVector& locals,
                            const MachineState& trapExitLayout,
                            size_t trapExitLayoutNumWords, Decoder& decoder,
-                           TempAllocator* alloc, MacroAssembler* masm,
-                           StackMaps* stackMaps)
+                           StkVector& stkSource, TempAllocator* alloc,
+                           MacroAssembler* masm, StackMaps* stackMaps)
     : env_(env),
       iter_(env, decoder),
       func_(func),
       lastReadCallSite_(0),
       alloc_(*alloc),
       locals_(locals),
       deadCode_(false),
       bceSafe_(0),
@@ -11794,17 +11811,38 @@ BaseCompiler::BaseCompiler(const ModuleE
       ra(*this),
       fr(*masm),
       stackMapGenerator_(stackMaps, trapExitLayout, trapExitLayoutNumWords,
                          *masm),
       joinRegI32_(RegI32(ReturnReg)),
       joinRegI64_(RegI64(ReturnReg64)),
       joinRegPtr_(RegPtr(ReturnReg)),
       joinRegF32_(RegF32(ReturnFloat32Reg)),
-      joinRegF64_(RegF64(ReturnDoubleReg)) {}
+      joinRegF64_(RegF64(ReturnDoubleReg)),
+      stkSource_(stkSource) {
+  // Our caller, BaselineCompileFunctions, will lend us the vector contents to
+  // use for the eval stack.  To get hold of those contents, we'll temporarily
+  // installing an empty one in its place.
+  MOZ_ASSERT(stk_.empty());
+  stk_.swap(stkSource_);
+
+  // Assuming that previously processed wasm functions are well formed, the
+  // eval stack should now be empty.  But empty it anyway; any non-emptyness
+  // at this point will cause chaos.
+  stk_.clear();
+}
+
+BaseCompiler::~BaseCompiler() {
+  stk_.swap(stkSource_);
+  // We've returned the eval stack vector contents to our caller,
+  // BaselineCompileFunctions.  We expect the vector we get in return to be
+  // empty since that's what we swapped for the stack vector in our
+  // constructor.
+  MOZ_ASSERT(stk_.empty());
+}
 
 bool BaseCompiler::init() {
   if (!SigD_.append(ValType::F64)) {
     return false;
   }
   if (!SigF_.append(ValType::F32)) {
     return false;
   }
@@ -11875,33 +11913,41 @@ bool js::wasm::BaselineCompileFunctions(
     return false;
   }
 
   // Create a description of the stack layout created by GenerateTrapExit().
   MachineState trapExitLayout;
   size_t trapExitLayoutNumWords;
   GenerateTrapExitMachineState(&trapExitLayout, &trapExitLayoutNumWords);
 
+  // The compiler's operand stack.  We reuse it across all functions so as to
+  // avoid malloc/free.  Presize it to 128 elements in the hope of avoiding
+  // reallocation later.
+  StkVector stk;
+  if (!stk.reserve(128)) {
+    return false;
+  }
+
   for (const FuncCompileInput& func : inputs) {
     Decoder d(func.begin, func.end, func.lineOrBytecode, error);
 
     // Build the local types vector.
 
     ValTypeVector locals;
     if (!locals.appendAll(env.funcTypes[func.index]->args())) {
       return false;
     }
     if (!DecodeLocalEntries(d, env.types, env.gcTypesEnabled(), &locals)) {
       return false;
     }
 
     // One-pass baseline compilation.
 
     BaseCompiler f(env, func, locals, trapExitLayout, trapExitLayoutNumWords, d,
-                   &alloc, &masm, &code->stackMaps);
+                   stk, &alloc, &masm, &code->stackMaps);
     if (!f.init()) {
       return false;
     }
     if (!f.emitFunction()) {
       return false;
     }
     if (!code->codeRanges.emplaceBack(func.index, func.lineOrBytecode,
                                       f.finish())) {
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -100,17 +100,21 @@ using mozilla::Unused;
 class Code;
 class DebugState;
 class GeneratedSourceMap;
 class Memory;
 class Module;
 class Instance;
 class Table;
 
-typedef Vector<uint32_t, 0, SystemAllocPolicy> Uint32Vector;
+// Uint32Vector has initial size 8 on the basis that the dominant use cases
+// (line numbers and control stacks) tend to have a small but nonzero number
+// of elements.
+typedef Vector<uint32_t, 8, SystemAllocPolicy> Uint32Vector;
+
 typedef Vector<uint8_t, 0, SystemAllocPolicy> Bytes;
 typedef UniquePtr<Bytes> UniqueBytes;
 typedef UniquePtr<const Bytes> UniqueConstBytes;
 typedef Vector<char, 0, SystemAllocPolicy> UTF8Bytes;
 typedef Vector<Instance*, 0, SystemAllocPolicy> InstanceVector;
 typedef Vector<UniqueChars, 0, SystemAllocPolicy> UniqueCharsVector;
 
 // To call Vector::podResizeToFit, a type must specialize mozilla::IsPod
@@ -446,17 +450,20 @@ class ValType {
   bool operator==(Code that) const {
     MOZ_ASSERT(that != Code::Ref);
     return code() == that;
   }
 
   bool operator!=(Code that) const { return !(*this == that); }
 };
 
-typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
+// The dominant use of this data type is for locals and args, and profiling
+// with ZenGarden and Tanks suggests an initial size of 16 minimises heap
+// allocation, both in terms of blocks and bytes.
+typedef Vector<ValType, 16, SystemAllocPolicy> ValTypeVector;
 
 // ValType utilities
 
 static inline unsigned SizeOf(ValType vt) {
   switch (vt.code()) {
     case ValType::I32:
     case ValType::F32:
       return 4;
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -686,12 +686,37 @@ struct AssertionConditionType {
 #  define MOZ_ALWAYS_ERR(expr)      \
     do {                            \
       if ((expr).isErr()) {         \
         /* Silence MOZ_MUST_USE. */ \
       }                             \
     } while (false)
 #endif
 
+/*
+ * MOZ_DIAGNOSTIC_ALWAYS_TRUE is like MOZ_ALWAYS_TRUE, but using
+ * MOZ_DIAGNOSTIC_ASSERT as the underlying assert.
+ *
+ * See the block comment for MOZ_DIAGNOSTIC_ASSERT above for more details on how
+ * diagnostic assertions work and how to use them.
+ */
+#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
+#  define MOZ_DIAGNOSTIC_ALWAYS_TRUE(expr)   \
+    do {                                     \
+      if ((expr)) {                          \
+        /* Do nothing. */                    \
+      } else {                               \
+        MOZ_DIAGNOSTIC_ASSERT(false, #expr); \
+      }                                      \
+    } while (false)
+#else
+#  define MOZ_DIAGNOSTIC_ALWAYS_TRUE(expr) \
+    do {                                   \
+      if ((expr)) {                        \
+        /* Silence MOZ_MUST_USE. */        \
+      }                                    \
+    } while (false)
+#endif
+
 #undef MOZ_DUMP_ASSERTION_STACK
 #undef MOZ_CRASH_CRASHREPORT
 
 #endif /* mozilla_Assertions_h */
--- a/taskcluster/ci/beetmover-repackage/kind.yml
+++ b/taskcluster/ci/beetmover-repackage/kind.yml
@@ -53,11 +53,11 @@ only-for-build-platforms:
     - linux64-asan-reporter-nightly/opt
     - win64-asan-reporter-nightly/opt
 
 job-template:
     shipping-phase: promote
     attributes:
         artifact_map:
             by-project:
-                mozilla-release: taskcluster/taskgraph/manifests/firefox_candidates.yml
+                default: taskcluster/taskgraph/manifests/firefox_nightly.yml
                 mozilla-beta: taskcluster/taskgraph/manifests/firefox_candidates.yml
-                default: taskcluster/taskgraph/manifests/firefox_nightly.yml
+                mozilla-release: taskcluster/taskgraph/manifests/firefox_candidates.yml
--- a/taskcluster/ci/release-beetmover-signed-langpacks-checksums/kind.yml
+++ b/taskcluster/ci/release-beetmover-signed-langpacks-checksums/kind.yml
@@ -9,8 +9,11 @@ transforms:
    - taskgraph.transforms.beetmover_langpack_checksums:transforms
    - taskgraph.transforms.task:transforms
 
 kind-dependencies:
    - release-beetmover-signed-langpacks
 
 job-template:
    shipping-phase: promote
+   attributes:
+      artifact_prefix: public
+      artifact_map: taskcluster/taskgraph/manifests/firefox_candidates_checksums.yml
--- a/taskcluster/ci/release-beetmover-signed-langpacks/kind.yml
+++ b/taskcluster/ci/release-beetmover-signed-langpacks/kind.yml
@@ -19,8 +19,10 @@ only-for-attributes:
 job-template:
    description: Beetmover submission for platform-independent langpacks {locales} in {platform} directory
    worker-type:
       by-release-level:
          production: scriptworker-prov-v1/beetmoverworker-v1
          staging: scriptworker-prov-v1/beetmoverworker-dev
    run-on-projects: []
    shipping-phase: promote
+   attributes:
+      artifact_map: taskcluster/taskgraph/manifests/firefox_candidates.yml
new file mode 100644
--- /dev/null
+++ b/taskcluster/taskgraph/manifests/firefox_candidates.yml
@@ -0,0 +1,353 @@
+# This file contains exhaustive information about all the release artifacs that
+# are needed within a type of release.
+#
+# Structure
+# --------
+# `s3_bucket_paths`       -- prefix to be used per product to correctly access our S3 buckets
+# `default_locales`       -- list of locales to be used when composing upstream artifacts or the list of
+#                      destinations. If given an empty locale, it uses these locales instead.
+# `tasktype_map`          -- mapping between task reference and task type, particularly usefule when
+#                      composing the upstreamArtifacts for scriptworker.
+# `platform_names`        -- various platform mappings used in reckoning artifacts or other paths
+# `default`               -- a default entry, which the mappings extend and override in such a way that
+#                      final path full-destinations will be a concatenation of the following:
+#                      `s3_bucket_paths`, `destinations`, `locale_prefix`, `pretty_name`
+# `from`                  -- specifies the dependency(ies) from which to expect the particular artifact
+# `all_locales`           -- boolean argument to specify whether that particular artifact is to be expected
+#                      for all locales or just the default one
+# `description`           -- brief summary of what that artifact is
+# `locale_prefix`         -- prefix to be used in the final destination paths, whether that's for default locale or not
+# `source_path_modifier`  -- any parent dir that might be used in between artifact prefix and filename at source location
+#                            for example `public/build` vs `public/build/ach/`.
+# `destinations`          -- final list of directories where to push the artifacts in S3
+# `pretty_name`           -- the final name the artifact will have at destination
+# `checksums_path`        -- the name to identify one artifact within the checksums file
+# `not_for_platforms`     -- filtering option to avoid associating an artifact with a specific platform
+# `only_for_platforms`    -- filtering option to exclusively include the association of an artifact for a specific platform
+# `partials_only`         -- filtering option to avoid associating an artifact unless this flag is present
+# `update_balrog_manifest`-- flag needed downstream in beetmover jobs to reckon the balrog manifest
+# `from_buildid`          -- flag needed downstream in beetmover jobs to reckon the balrog manifest
+
+---
+s3_bucket_paths:
+  - pub/firefox/candidates
+default_locales:
+  - en-US
+tasktype_map:
+  build: build
+  signing: signing
+  mar-signing: signing
+  partials-signing: signing
+  repackage: repackage
+  repackage-signing: repackage
+  repackage-signing-msi: repackage
+  release-sign-and-push-langpacks: scriptworker
+platform_names:
+  path_platform:
+    by-platform:
+      linux-nightly: 'linux-i686'
+      linux64-nightly: 'linux-x86_64'
+      linux64-asan-reporter-nightly: 'linux-x86_64-asan-reporter'
+      macosx64-nightly: 'mac'
+      win32-nightly: 'win32'
+      win64-nightly: 'win64'
+      win64-aarch64-nightly: 'win64-aarch64'
+      win64-asan-reporter-nightly: 'win64-asan-reporter'
+  filename_platform:
+    by-platform:
+      linux-nightly: 'linux-i686'
+      linux64-nightly: 'linux-x86_64'
+      linux64-asan-reporter-nightly: 'linux-x86_64-asan-reporter'
+      macosx64-nightly: 'mac'
+      win32-nightly: 'win32'
+      win64-nightly: 'win64'
+      win64-aarch64-nightly: 'win64-aarch64'
+      win64-asan-reporter-nightly: 'win64-asan-reporter'
+  stage_platform:
+    by-platform:
+      linux-nightly: 'linux'
+      linux64-nightly: 'linux64'
+      linux64-asan-reporter-nightly: 'linux-x86_64-asan-reporter'
+      macosx64-nightly: 'macosx64'
+      win32-nightly: 'win32'
+      win64-nightly: 'win64'
+      win64-aarch64-nightly: 'win64-aarch64'
+      win64-asan-reporter-nightly: 'win64-asan-reporter'
+
+default: &default
+  from:
+    - build
+  all_locales: false
+  description: "TO_BE_OVERRIDDEN"
+  locale_prefix: '${locale}/'
+  source_path_modifier:
+    by-locale:
+      default: '${locale}'
+      en-US: ''
+  destinations:
+    - ${version}-candidates/build${build_number}/${path_platform}
+
+mapping:
+  buildhub.json:
+    <<: *default
+    all_locales: false
+    description: "Build related information to be consumed by Buildhub service"
+    pretty_name: buildhub.json
+    checksums_path: ${path_platform}/${locale}/buildhub.json
+  target.common.tests.tar.gz:
+    <<: *default
+    description: "Mixture of reftests, mochitests, UI and others, commonly bundled together in a test suite"
+    pretty_name: firefox-${version}.common.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.common.tests.tar.gz
+  target.cppunittest.tests.tar.gz:
+    <<: *default
+    description: "C++ unittests related in-tree test infrastructure"
+    pretty_name: firefox-${version}.cppunittest.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.cppunittest.tests.tar.gz
+  target.crashreporter-symbols.zip:
+    <<: *default
+    description: "Crashreporter symbols to be consumed by Socorro"
+    pretty_name: firefox-${version}.crashreporter-symbols.zip
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.crashreporter-symbols.zip
+  target.json:
+    <<: *default
+    description: "Various compile and moz_app flags baked together in a json file"
+    pretty_name: firefox-${version}.json
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.json
+  target.mochitest.tests.tar.gz:
+    <<: *default
+    description: "Results for running the mochitest testing framework via Javascript function calls"
+    pretty_name: firefox-${version}.mochitest.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.mochitest.tests.tar.gz
+  target.mozinfo.json:
+    <<: *default
+    description: "Various compile and moz_app flags baked together in a json file"
+    pretty_name: firefox-${version}.mozinfo.json
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.mozinfo.json
+  target.reftest.tests.tar.gz:
+    <<: *default
+    description: "Results for running the reftest testing framework via display of two Web pages comparison"
+    pretty_name: firefox-${version}.reftest.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.reftest.tests.tar.gz
+  target.talos.tests.tar.gz:
+    <<: *default
+    description: "Results for running the talos testing framework to measure performance"
+    pretty_name: firefox-${version}.talos.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.talos.tests.tar.gz
+  target.awsy.tests.tar.gz:
+    <<: *default
+    description: "Results for running the awsy testing framework to track memory usage"
+    pretty_name: firefox-${version}.awsy.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.awsy.tests.tar.gz
+  target.test_packages.json:
+    <<: *default
+    description: "File containing metadata about all other files and testing harnesses specifics"
+    pretty_name: firefox-${version}.test_packages.json
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.test_packages.json
+  target.txt:
+    <<: *default
+    description: "File containing buildid and revision"
+    pretty_name: firefox-${version}.txt
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.txt
+  target.web-platform.tests.tar.gz:
+    <<: *default
+    description: "Results for running the webplatform testing framework to cover standard Web platform features"
+    pretty_name: firefox-${version}.web-platform.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.web-platform.tests.tar.gz
+  target.xpcshell.tests.tar.gz:
+    <<: *default
+    description: "Results for running the xpcshell testing framework to enable XPConnect console application"
+    pretty_name: firefox-${version}.xpcshell.tests.tar.gz
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.xpcshell.tests.tar.gz
+  target_info.txt:
+    <<: *default
+    description: "File containing the buildID"
+    locale_prefix: ''
+    pretty_name: ${stage_platform}_info.txt
+    checksums_path: ${stage_platform}_info.txt
+    destinations:
+      - ${version}-candidates/build${build_number}
+  mozharness.zip:
+    <<: *default
+    description: "File containing the mozharness set of scripts and configuration used by various automation tools"
+    pretty_name: mozharness.zip
+    checksums_path: ${path_platform}/${locale}/mozharness.zip
+  target.jsshell.zip:
+    <<: *default
+    description: "Set of shells to allow test snippets of Javascript code without needing to reload the page"
+    locale_prefix: ''
+    pretty_name: jsshell-${filename_platform}.zip
+    checksums_path: jsshell/jsshell-${filename_platform}.zip
+    destinations:
+      - ${version}-candidates/build${build_number}/jsshell
+  target.langpack.xpi:
+    <<: *default
+    all_locales: true
+    description: "Localized repack that grabs a packaged en-US Firefox and repackages it as locale-specific Firefox"
+    locale_prefix: ''
+    source_path_modifier: '${locale}'
+    from:
+      - release-sign-and-push-langpacks
+    only_for_platforms:
+      - linux-nightly
+      - linux64-nightly
+      - macosx64-nightly
+      - win32-nightly
+      - win64-nightly
+    pretty_name: ${locale}.xpi
+    checksums_path: ${path_platform}/xpi/${locale}.xpi
+    destinations:
+      - ${version}-candidates/build${build_number}/${path_platform}/xpi
+  mar:
+    <<: *default
+    description: "Alongside `mbsdiff`, a tool used to generate partials"
+    locale_prefix: ''
+    source_path_modifier: 'host/bin'
+    pretty_name: ${stage_platform}/mar
+    checksums_path: mar-tools/${stage_platform}/mar
+    not_for_platforms:
+      - win32-nightly
+      - win64-nightly
+      - win64-aarch64-nightly
+    destinations:
+      - ${version}-candidates/build${build_number}/mar-tools
+  mbsdiff:
+    <<: *default
+    description: "Alongside `mar`, a tool used to generate partials"
+    locale_prefix: ''
+    source_path_modifier: 'host/bin'
+    pretty_name: ${stage_platform}/mbsdiff
+    checksums_path: mar-tools/${stage_platform}/mbsdiff
+    not_for_platforms:
+      - win32-nightly
+      - win64-nightly
+      - win64-aarch64-nightly
+    destinations:
+      - ${version}-candidates/build${build_number}/mar-tools
+  mar.exe:
+    <<: *default
+    description: "Alongside `mbsdiff.exe`, a tool used to generate partials for Windows platforms"
+    locale_prefix: ''
+    source_path_modifier: 'host/bin'
+    pretty_name: ${stage_platform}/mar.exe
+    checksums_path: mar-tools/${stage_platform}/mar.exe
+    only_for_platforms:
+      - win32-nightly
+      - win64-nightly
+      - win64-aarch64-nightly
+    destinations:
+      - ${version}-candidates/build${build_number}/mar-tools
+  mbsdiff.exe:
+    <<: *default
+    locale_prefix: ''
+    description: "Alongside `mar.exe`, a tool used to generate partials for Windows platforms"
+    source_path_modifier: 'host/bin'
+    pretty_name: ${stage_platform}/mbsdiff.exe
+    checksums_path: mar-tools/${stage_platform}/mbsdiff.exe
+    only_for_platforms:
+      - win32-nightly
+      - win64-nightly
+      - win64-aarch64-nightly
+    destinations:
+      - ${version}-candidates/build${build_number}/mar-tools
+  target.tar.bz2:
+    <<: *default
+    description: "Main installer for Linux platforms"
+    all_locales: true
+    from:
+      - signing
+    only_for_platforms:
+      - linux-nightly
+      - linux64-nightly
+    pretty_name: firefox-${version}.tar.bz2
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.tar.bz2
+  target.tar.bz2.asc:
+    <<: *default
+    description: "Detached signature for the checksums file"
+    all_locales: true
+    from:
+      - signing
+    only_for_platforms:
+      - linux-nightly
+      - linux64-nightly
+    pretty_name: firefox-${version}.tar.bz2.asc
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.tar.bz2.asc
+  target.dmg:
+    <<: *default
+    description: "Main package installer for Mac OS X platforms"
+    all_locales: true
+    from:
+      - repackage
+    only_for_platforms:
+      - macosx64-nightly
+    pretty_name: Firefox ${version}.dmg
+    checksums_path: ${path_platform}/${locale}/Firefox ${version}.dmg
+  target.zip:
+    <<: *default
+    description: "Main package installer for Windows platforms"
+    all_locales: true
+    from:
+      - signing
+    only_for_platforms:
+      - win64-nightly
+      - win32-nightly
+      - win64-aarch64-nightly
+    pretty_name: firefox-${version}.zip
+    checksums_path: ${path_platform}/${locale}/firefox-${version}.zip
+  target.installer.exe:
+    <<: *default
+    description: "Main installer for Windows platforms"
+    all_locales: true
+    from:
+      - repackage-signing
+    only_for_platforms:
+      - win64-nightly
+      - win32-nightly
+      - win64-aarch64-nightly
+    pretty_name: Firefox Setup ${version}.exe
+    checksums_path: ${path_platform}/${locale}/Firefox Setup ${version}.exe
+  target.stub-installer.exe:
+    <<: *default
+    description: "Stub installer for Win32 platforms"
+    all_locales: true
+    from:
+      - repackage-signing
+    only_for_platforms:
+      - win32-nightly
+    pretty_name: Firefox Installer.exe
+    checksums_path: ${path_platform}/${locale}/Firefox Installer.exe
+  target.installer.msi:
+    <<: *default
+    description: "Windows installer for MSI platform"
+    all_locales: true
+    from:
+      - repackage-signing-msi
+    only_for_platforms:
+      - win64-nightly
+      - win32-nightly
+    pretty_name: Firefox Setup ${version}.msi
+    checksums_path: ${path_platform}/${locale}/Firefox Setup ${version}.msi
+  target.complete.mar:
+    <<: *default
+    description: "The main installer we ship our mobile products baked within"
+    all_locales: true
+    from:
+      - mar-signing
+    pretty_name: firefox-${version}.complete.mar
+    checksums_path: update/${path_platform}/${locale}/firefox-${version}.complete.mar
+    update_balrog_manifest: true
+    destinations:
+      - ${version}-candidates/build${build_number}/update/${path_platform}
+  ${partial}:
+    <<: *default
+    description: "Partials MAR files to serve as updates"
+    all_locales: true
+    from:
+      - partials-signing
+    partials_only: true
+    pretty_name: firefox-${previous_version}-${version}.partial.mar
+    checksums_path: update/${path_platform}/${locale}/firefox-${previous_version}-${version}.partial.mar
+    update_balrog_manifest: true
+    from_buildid: ${from_buildid}
+    destinations:
+      - ${version}-candidates/build${build_number}/update/${path_platform}
new file mode 100644
--- /dev/null
+++ b/taskcluster/taskgraph/manifests/firefox_candidates_checksums.yml
@@ -0,0 +1,117 @@
+# This file contains exhaustive information about all the release artifacs that
+# are needed within a type of release.
+#
+# Structure
+# --------
+# `s3_bucket_paths`       -- prefix to be used per product to correctly access our S3 buckets
+# `default_locales`       -- list of locales to be used when composing upstream artifacts or the list of
+#                      destinations. If given an empty locale, it uses these locales instead.
+# `tasktype_map`          -- mapping between task reference and task type, particularly usefule when
+#                      composing the upstreamArtifacts for scriptworker.
+# `platform_names`        -- various platform mappings used in reckoning artifacts or other paths
+# `default`               -- a default entry, which the mappings extend and override in such a way that
+#                      final path full-destinations will be a concatenation of the following:
+#                      `s3_bucket_paths`, `destinations`, `locale_prefix`, `pretty_name`
+# `from`                  -- specifies the dependency(ies) from which to expect the particular artifact
+# `all_locales`           -- boolean argument to specify whether that particular artifact is to be expected
+#                      for all locales or just the default one
+# `description`           -- brief summary of what that artifact is
+# `locale_prefix`         -- prefix to be used in the final destination paths, whether that's for default locale or not
+# `source_path_modifier`  -- any parent dir that might be used in between artifact prefix and filename at source location
+#                            for example `public/build` vs `public/build/ach/`.
+# `destinations`          -- final list of directories where to push the artifacts in S3
+# `pretty_name`           -- the final name the artifact will have at destination
+# `checksums_path`        -- the name to identify one artifact within the checksums file
+# `not_for_platforms`     -- filtering option to avoid associating an artifact with a specific platform
+# `only_for_platforms`    -- filtering option to exclusively include the association of an artifact for a specific platform
+# `partials_only`         -- filtering option to avoid associating an artifact unless this flag is present
+# `update_balrog_manifest`-- flag needed downstream in beetmover jobs to reckon the balrog manifest
+# `from_buildid`          -- flag needed downstream in beetmover jobs to reckon the balrog manifest
+---
+s3_bucket_paths:
+  by-platform:
+    .*devedition.*:
+      - pub/devedition/candidates
+    default:
+      - pub/firefox/candidates
+default_locales:
+  - en-US
+tasktype_map:
+  checksums-signing: signing
+  release-beetmover-signed-langpacks: signing
+platform_names:
+  path_platform:
+    by-platform:
+      linux-nightly: 'linux-i686'
+      linux64-nightly: 'linux-x86_64'
+      linux64-asan-reporter-nightly: 'linux-x86_64-asan-reporter'
+      macosx64-nightly: 'mac'
+      win32-nightly: 'win32'
+      win64-nightly: 'win64'
+      win64-aarch64-nightly: 'win64-aarch64'
+      win64-asan-reporter-nightly: 'win64-asan-reporter'
+      linux-shippable: 'linux-i686'
+      linux64-shippable: 'linux-x86_64'
+      macosx64-shippable: 'mac'
+      win32-shippable: 'win32'
+      win64-shippable: 'win64'
+      win64-aarch64-shippable: 'win64-aarch64'
+      linux: 'linux-i686'
+      linux64: 'linux-x86_64'
+      macosx64: 'mac'
+      win32: 'win32'
+      win64: 'win64'
+  filename_platform:
+    by-platform:
+      linux-nightly: 'linux-i686'
+      linux64-nightly: 'linux-x86_64'
+      linux64-asan-reporter-nightly: 'linux-x86_64-asan-reporter'
+      macosx64-nightly: 'mac'
+      win32-nightly: 'win32'
+      win64-nightly: 'win64'
+      win64-aarch64-nightly: 'win64-aarch64'
+      win64-asan-reporter-nightly: 'win64-asan-reporter'
+      linux-shippable: 'linux-i686'
+      linux64-shippable: 'linux-x86_64'
+      macosx64-shippable: 'mac'
+      win32-shippable: 'win32'
+      win64-shippable: 'win64'
+      win64-aarch64-shippable: 'win64-aarch64'
+      linux: 'linux-i686'
+      linux64: 'linux-x86_64'
+      macosx64: 'mac'
+      win32: 'win32'
+      win64: 'win64'
+  stage_platform: ''
+
+default: &default
+  from:
+    - checksums-signing
+  all_locales: true
+  description: "TO_BE_OVERRIDDEN"
+  locale_prefix: '${locale}/'
+  source_path_modifier: ''
+  destinations:
+    - ${version}-candidates/build${build_number}/beetmover-checksums/${path_platform}
+
+mapping:
+  target.checksums:
+    <<: *default
+    description: "Checksums file containing size, hash, sha algorithm and filename"
+    pretty_name: firefox-${version}.checksums.beet
+    checksums_path: beetmover-checksums/${path_platform}/${locale}/firefox-${version}.checksums.beet
+  target.checksums.asc:
+    <<: *default
+    description: "Detached signature for the checksums file"
+    pretty_name: firefox-${version}.checksums.asc
+    checksums_path: beetmover-checksums/${path_platform}/${locale}/firefox-${version}.checksums.asc
+  target-langpack.checksums:
+    <<: *default
+    description: "Checksums file containing size, hash, sha algorithm and filename for the langpack"
+    locale_prefix: ''
+    from:
+      - release-beetmover-signed-langpacks
+    pretty_name: ${locale}.checksums.beet
+    checksums_path: beetmover-checksums/${path_platform}/xpi/${locale}.checksums.beet
+    destinations:
+      - ${version}-candidates/build${build_number}/beetmover-checksums/${path_platform}/xpi
--- a/taskcluster/taskgraph/transforms/beetmover_langpack_checksums.py
+++ b/taskcluster/taskgraph/transforms/beetmover_langpack_checksums.py
@@ -6,24 +6,28 @@ Transform release-beetmover-langpack-che
 """
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 from taskgraph.loader.single_dep import schema
 from taskgraph.transforms.base import TransformSequence
 from taskgraph.transforms.beetmover import craft_release_properties
 from taskgraph.util.attributes import copy_attributes_from_dependent_job
-from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
+from taskgraph.util.scriptworker import (generate_beetmover_artifact_map,
+                                         generate_beetmover_upstream_artifacts,
                                          get_beetmover_action_scope,
-                                         get_worker_type_for_scope)
+                                         get_beetmover_bucket_scope,
+                                         get_worker_type_for_scope,
+                                         should_use_artifact_map)
 from taskgraph.transforms.task import task_description_schema
 from voluptuous import Required, Optional
 
 beetmover_checksums_description_schema = schema.extend({
     Required('depname', default='build'): basestring,
+    Required('attributes'): {basestring: object},
     Optional('label'): basestring,
     Optional('treeherder'): task_description_schema['treeherder'],
     Optional('locale'): basestring,
     Optional('shipping-phase'): task_description_schema['shipping-phase'],
     Optional('shipping-product'): task_description_schema['shipping-product'],
 })
 
 transforms = TransformSequence()
@@ -62,16 +66,17 @@ def make_beetmover_checksums_description
         dependencies = {dep_job.kind: dep_job.label}
         for k, v in dep_job.dependencies.items():
             if k.startswith('beetmover'):
                 dependencies[k] = v
 
         attributes = copy_attributes_from_dependent_job(dep_job)
         if 'chunk_locales' in dep_job.attributes:
             attributes['chunk_locales'] = dep_job.attributes['chunk_locales']
+        attributes.update(job.get('attributes', {}))
 
         bucket_scope = get_beetmover_bucket_scope(config)
         action_scope = get_beetmover_action_scope(config)
 
         task = {
             'label': label,
             'description': description,
             'worker-type': get_worker_type_for_scope(config, bucket_scope),
@@ -131,16 +136,25 @@ def make_beetmover_checksums_worker(conf
                 refs['beetmover'] = "<{}>".format(dependency)
         if None in refs.values():
             raise NotImplementedError(
                 "Beetmover checksums must have a beetmover dependency!")
 
         worker = {
             'implementation': 'beetmover',
             'release-properties': craft_release_properties(config, job),
-            'upstream-artifacts': generate_upstream_artifacts(
-                refs, platform, locales
-            ),
         }
 
+        if should_use_artifact_map(platform, config.params['project']):
+            upstream_artifacts = generate_beetmover_upstream_artifacts(
+                config, job, platform, locales
+            )
+            worker['artifact-map'] = generate_beetmover_artifact_map(
+                config, job, platform=platform, locale=locales)
+        else:
+            upstream_artifacts = generate_upstream_artifacts(
+                refs, platform, locales
+            )
+
+        worker['upstream-artifacts'] = upstream_artifacts
         job["worker"] = worker
 
         yield job
--- a/taskcluster/taskgraph/transforms/release_beetmover_signed_addons.py
+++ b/taskcluster/taskgraph/transforms/release_beetmover_signed_addons.py
@@ -8,17 +8,20 @@ Transform the beetmover task into an act
 from __future__ import absolute_import, print_function, unicode_literals
 
 from taskgraph.loader.single_dep import schema
 from taskgraph.transforms.base import TransformSequence
 from taskgraph.transforms.beetmover import craft_release_properties
 from taskgraph.util.attributes import copy_attributes_from_dependent_job
 from taskgraph.util.schema import optionally_keyed_by, resolve_keyed_by
 from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
-                                         get_beetmover_action_scope)
+                                         get_beetmover_action_scope,
+                                         generate_beetmover_upstream_artifacts,
+                                         generate_beetmover_artifact_map,
+                                         should_use_artifact_map)
 from taskgraph.transforms.task import task_description_schema
 from taskgraph.transforms.release_sign_and_push_langpacks import get_upstream_task_ref
 from voluptuous import Required, Optional
 
 import logging
 import copy
 
 logger = logging.getLogger(__name__)
@@ -26,16 +29,19 @@ logger = logging.getLogger(__name__)
 
 transforms = TransformSequence()
 
 
 beetmover_description_schema = schema.extend({
     # depname is used in taskref's to identify the taskID of the unsigned things
     Required('depname', default='build'): basestring,
 
+    # attributes is used for enabling artifact-map by declarative artifacts
+    Required('attributes'): {basestring: object},
+
     # unique label to describe this beetmover task, defaults to {dep.label}-beetmover
     Optional('label'): basestring,
 
     # treeherder is allowed here to override any defaults we use for beetmover.  See
     # taskcluster/taskgraph/transforms/task.py for the schema details, and the
     # below transforms for defaults of various values.
     Optional('treeherder'): task_description_schema['treeherder'],
 
@@ -61,20 +67,24 @@ def set_label(config, jobs):
 
 
 transforms.add_validate(beetmover_description_schema)
 
 
 @transforms.add
 def resolve_keys(config, jobs):
     for job in jobs:
-        resolve_keyed_by(
-            job, 'worker-type', item_name=job['label'],
-            **{'release-level': config.params.release_level()}
-        )
+        for field in ('worker-type', 'attributes.artifact_map'):
+            resolve_keyed_by(
+                job, field, item_name=job['label'],
+                **{
+                    'release-level': config.params.release_level(),
+                    'project': config.params['project']
+                }
+            )
         yield job
 
 
 @transforms.add
 def make_task_description(config, jobs):
     for job in jobs:
         dep_job = job['primary-dependency']
         attributes = dep_job.attributes
@@ -83,17 +93,17 @@ def make_task_description(config, jobs):
         treeherder.setdefault('symbol', 'langpack(BM{})'.format(attributes.get('l10n_chunk', '')))
         dep_th_platform = dep_job.task.get('extra', {}).get(
             'treeherder', {}).get('machine', {}).get('platform', '')
         treeherder.setdefault('platform',
                               "{}/opt".format(dep_th_platform))
         treeherder.setdefault('tier', 1)
         treeherder.setdefault('kind', 'build')
 
-        job['attributes'] = copy_attributes_from_dependent_job(dep_job)
+        job['attributes'].update(copy_attributes_from_dependent_job(dep_job))
         job['attributes']['chunk_locales'] = dep_job.attributes['chunk_locales']
 
         job['description'] = job['description'].format(
             locales='/'.join(job['attributes']['chunk_locales']),
             platform=job['attributes']['build_platform']
         )
 
         job['scopes'] = [
@@ -113,24 +123,36 @@ def make_task_description(config, jobs):
 
 @transforms.add
 def make_task_worker(config, jobs):
     for job in jobs:
         signing_task_ref = get_upstream_task_ref(
             job, expected_kinds=('release-sign-and-push-langpacks',)
         )
 
+        platform = job["attributes"]["build_platform"]
+        locale = job["attributes"]["chunk_locales"]
+        if should_use_artifact_map(platform, config.params['project']):
+            upstream_artifacts = generate_beetmover_upstream_artifacts(
+                config, job, platform, locale,
+            )
+        else:
+            upstream_artifacts = generate_upstream_artifacts(
+                signing_task_ref, job['attributes']['chunk_locales']
+            )
         job['worker'] = {
             'implementation': 'beetmover',
             'release-properties': craft_release_properties(config, job),
-            'upstream-artifacts': generate_upstream_artifacts(
-                signing_task_ref, job['attributes']['chunk_locales']
-            ),
+            'upstream-artifacts': upstream_artifacts,
         }
 
+        if should_use_artifact_map(platform, config.params['project']):
+            job['worker']['artifact-map'] = generate_beetmover_artifact_map(
+                config, job, platform=platform, locale=locale)
+
         yield job
 
 
 def generate_upstream_artifacts(upstream_task_ref, locales):
     return [{
         'taskId': {'task-reference': upstream_task_ref},
         'taskType': 'scriptworker',
         'locale': locale,
@@ -162,17 +184,17 @@ def yield_all_platform_jobs(config, jobs
             if 'devedition' in job['attributes']['build_platform']:
                 platforms = ('{}-devedition'.format(plat) for plat in platforms)
             for platform in platforms:
                 platform_job = copy.deepcopy(job)
                 if 'ja' in platform_job['attributes']['chunk_locales'] and \
                         platform in ('macosx64', 'macosx64-devedition'):
                     platform_job = _strip_ja_data_from_linux_job(platform_job)
 
-                platform_job = _change_platform_data(platform_job, platform)
+                platform_job = _change_platform_data(config, platform_job, platform)
 
                 yield platform_job
 
 
 def _strip_ja_data_from_linux_job(platform_job):
     # Let's take "ja" out the description. This locale is in a substring like "aa/bb/cc/dd", where
     # "ja" could be any of "aa", "bb", "cc", "dd"
     platform_job['description'] = platform_job['description'].replace('ja/', '')
@@ -182,21 +204,57 @@ def _strip_ja_data_from_linux_job(platfo
         artifact
         for artifact in platform_job['worker']['upstream-artifacts']
         if artifact['locale'] != 'ja'
     ]
 
     return platform_job
 
 
-def _change_platform_data(platform_job, platform):
+def _change_platform_in_artifact_map_paths(paths, orig_platform, new_platform):
+    amended_paths = {}
+    for artifact, artifact_info in paths.iteritems():
+        amended_artifact_info = {
+            'checksums_path': artifact_info['checksums_path'].replace(orig_platform, new_platform),
+            'destinations': [
+                d.replace(orig_platform, new_platform) for d in artifact_info['destinations']
+            ]
+        }
+        amended_paths[artifact] = amended_artifact_info
+
+    return amended_paths
+
+
+def _change_platform_data(config, platform_job, platform):
     orig_platform = 'linux64'
     if 'devedition' in platform:
         orig_platform = 'linux64-devedition'
+    backup_platform = platform_job['attributes']['build_platform']
     platform_job['attributes']['build_platform'] = platform
     platform_job['label'] = platform_job['label'].replace(orig_platform, platform)
     platform_job['description'] = platform_job['description'].replace(orig_platform, platform)
     platform_job['treeherder']['platform'] = platform_job['treeherder']['platform'].replace(
         orig_platform, platform
     )
     platform_job['worker']['release-properties']['platform'] = platform
 
+    # amend artifactMap entries as well
+    if should_use_artifact_map(backup_platform, config.params['project']):
+        platform_mapping = {
+            'linux64': 'linux-x86_64',
+            'linux': 'linux-i686',
+            'macosx64': 'mac',
+            'win32': 'win32',
+            'win64': 'win64',
+        }
+        orig_platform = platform_mapping.get(orig_platform, orig_platform)
+        platform = platform_mapping.get(platform, platform)
+        platform_job['worker']['artifact-map'] = [
+            {
+                'locale': entry['locale'],
+                'taskId': entry['taskId'],
+                'paths': _change_platform_in_artifact_map_paths(entry['paths'],
+                                                                orig_platform,
+                                                                platform)
+            } for entry in platform_job['worker']['artifact-map']
+        ]
+
     return platform_job
--- a/taskcluster/taskgraph/util/scriptworker.py
+++ b/taskcluster/taskgraph/util/scriptworker.py
@@ -427,16 +427,18 @@ def generate_beetmover_upstream_artifact
         project=config.params['project'],
         platform=platform
     )
     map_config = deepcopy(cached_load_yaml(job['attributes']['artifact_map']))
     upstream_artifacts = list()
 
     if not locale:
         locales = map_config['default_locales']
+    elif isinstance(locale, list):
+        locales = locale
     else:
         locales = [locale]
 
     if not dependencies:
         dependencies = job['dependencies'].keys()
 
     for locale, dep in itertools.product(locales, dependencies):
         paths = list()
@@ -557,17 +559,20 @@ def generate_beetmover_artifact_map(conf
     map_config = deepcopy(cached_load_yaml(job['attributes']['artifact_map']))
     base_artifact_prefix = map_config.get('base_artifact_prefix', get_artifact_prefix(job))
 
     artifacts = list()
 
     dependencies = job['dependencies'].keys()
 
     if kwargs.get('locale'):
-        locales = [kwargs['locale']]
+        if isinstance(kwargs['locale'], list):
+            locales = kwargs['locale']
+        else:
+            locales = [kwargs['locale']]
     else:
         locales = map_config['default_locales']
 
     resolve_keyed_by(map_config, 's3_bucket_paths', 's3_bucket_paths', platform=platform)
 
     for locale, dep in itertools.product(locales, dependencies):
         paths = dict()
         for filename in map_config['mapping']:
@@ -775,16 +780,17 @@ def generate_beetmover_partials_artifact
                 # optional flag: from_buildid
                 if file_config.get('from_buildid'):
                     partials_paths[key]['from_buildid'] = file_config['from_buildid']
 
                 # render buildid
                 kwargs.update({
                     'partial': pname,
                     'from_buildid': info['buildid'],
+                    'previous_version': info.get('previousVersion'),
                     'buildid': str(config.params['moz_build_date']),
                     'locale': locale,
                     'version': config.params['version'],
                     'branch': config.params['project'],
                     'build_number': config.params['build_number'],
                     'filename_platform': platforms['filename_platform'],
                     'path_platform': platforms['path_platform'],
                     'stage_platform': platforms['stage_platform'],
@@ -821,26 +827,33 @@ def should_use_artifact_map(platform, pr
     # FIXME: once we're ready to switch fully to declarative artifacts on other
     # branches, we can expand this; for now, Fennec is rolled-out to all
     # release branches, while Firefox only to mozilla-central
     platforms = [
         'android',
         'fennec'
     ]
     projects = ['mozilla-central', 'mozilla-beta', 'mozilla-release']
-    if any([pl in platform for pl in platforms]) and any([pj in project for pj in projects]):
+    if any([pl in platform for pl in platforms]) and any([pj == project for pj in projects]):
         return True
 
     platforms = [
+        'linux',    # needed for beetmover-langpacks-checksums
+        'linux64',  # which inherit amended platform from their beetmover counterpart
+        'win32',
+        'win64',
+        'macosx64',
         'linux-shippable',
         'linux64-shippable',
         'macosx64-shippable',
         'win32-shippable',
         'win64-shippable',
         'win64-aarch64-shippable',
         'win64-asan-reporter-nightly',
         'linux64-asan-reporter-nightly',
+        'firefox-source',
+        'firefox-release',
     ]
-    projects = ['mozilla-central']
-    if any([pl in platform for pl in platforms]) and any([pj in project for pj in projects]):
+    projects = ['mozilla-central', 'mozilla-beta', 'mozilla-release']
+    if any([pl == platform for pl in platforms]) and any([pj == project for pj in projects]):
         return True
 
     return False