Merge mozilla-central into holly
authorMike Conley <mconley@mozilla.com>
Mon, 09 Dec 2013 01:24:53 -0500
changeset 175144 f37f87abf269848b375790c0d012393726aef14f
parent 175139 1c599e4e665025063bc6219f45bddb64233f1a68 (current diff)
parent 175143 85196889c598679878fd65d6f36832623f1de7e9 (diff)
child 175184 894b56f8bbf54f4269df3ab89a896f343b3dbad0
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.0a1
Merge mozilla-central into holly
netwerk/sctp/datachannel/Makefile.in
--- a/browser/metro/shell/commandexecutehandler/Makefile.in
+++ b/browser/metro/shell/commandexecutehandler/Makefile.in
@@ -1,14 +1,12 @@
 # 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/.
 
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-
 include $(topsrcdir)/config/config.mk
 
 DIST_PROGRAM = CommandExecuteHandler$(BIN_SUFFIX)
 
 # Don't link against mozglue.dll
 MOZ_GLUE_LDFLAGS =
 MOZ_GLUE_PROGRAM_LDFLAGS =
 
--- a/browser/metro/shell/commandexecutehandler/moz.build
+++ b/browser/metro/shell/commandexecutehandler/moz.build
@@ -11,8 +11,10 @@ SOURCES += [
     'CommandExecuteHandler.cpp',
 ]
 
 # We want this exe in dist/bin
 DIST_SUBDIR = ''
 
 for var in ('UNICODE', '_UNICODE', 'NS_NO_XPCOM'):
     DEFINES[var] = True
+
+NO_PGO = True
--- a/browser/metro/shell/linktool/Makefile.in
+++ b/browser/metro/shell/linktool/Makefile.in
@@ -1,14 +1,12 @@
 # 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/.
 
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-
 include $(topsrcdir)/config/config.mk
 
 OS_LIBS = \
 	kernel32.lib \
 	user32.lib \
 	ole32.lib \
 	shlwapi.lib \
 	shell32.lib \
--- a/browser/metro/shell/linktool/moz.build
+++ b/browser/metro/shell/linktool/moz.build
@@ -9,8 +9,10 @@ PROGRAM = 'linktool'
 SOURCES += [
     'linktool.cpp',
 ]
 
 DIST_SUBDIR = 'metro/install'
 
 for var in ('UNICODE', '_UNICODE'):
     DEFINES[var] = True
+
+NO_PGO = True
--- a/browser/metro/shell/testing/Makefile.in
+++ b/browser/metro/shell/testing/Makefile.in
@@ -4,18 +4,16 @@
 
 # static win runtime linking
 USE_STATIC_LIBS = 1
 
 # don't use moz glue libs
 MOZ_GLUE_LDFLAGS =
 MOZ_GLUE_PROGRAM_LDFLAGS =
 
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-
 include $(topsrcdir)/config/config.mk
 
 OS_LIBS = \
 	kernel32.lib \
 	user32.lib \
 	ole32.lib \
 	shlwapi.lib \
 	propsys.lib \
--- a/browser/metro/shell/testing/moz.build
+++ b/browser/metro/shell/testing/moz.build
@@ -10,8 +10,10 @@ SOURCES += [
     'metrotestharness.cpp',
 ]
 
 # We want this exe in dist/bin
 DIST_SUBDIR = ''
 
 for var in ('UNICODE', '_UNICODE'):
     DEFINES[var] = True
+
+NO_PGO = True
--- a/build/unix/elfhack/Makefile.in
+++ b/build/unix/elfhack/Makefile.in
@@ -1,17 +1,15 @@
 #
 # 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/.
 
 INTERNAL_TOOLS = 1
 
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-
 VPATH += $(topsrcdir)/build
 
 OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
 
 WRAP_LDFLAGS=
 
 include $(topsrcdir)/config/rules.mk
 
--- a/build/unix/elfhack/inject/Makefile.in
+++ b/build/unix/elfhack/inject/Makefile.in
@@ -1,15 +1,14 @@
 #
 # 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/.
 
 INTERNAL_TOOLS = 1
-NO_PROFILE_GUIDED_OPTIMIZE = 1
 
 include $(topsrcdir)/config/rules.mk
 
 export:: $(CSRCS:.c=.$(OBJ_SUFFIX))
 
 $(CSRCS): %.c: ../inject.c
 	cp $< $@
 
--- a/build/unix/elfhack/inject/moz.build
+++ b/build/unix/elfhack/inject/moz.build
@@ -13,8 +13,10 @@ elif CONFIG['TARGET_CPU'].startswith('ar
 else:
     cpu = CONFIG['TARGET_CPU']
 
 GENERATED_SOURCES += [
     "%s.c" % cpu,
 ]
 
 DEFINES['ELFHACK_BUILD'] = True
+
+NO_PGO = True
--- a/build/unix/elfhack/moz.build
+++ b/build/unix/elfhack/moz.build
@@ -20,8 +20,10 @@ if not CONFIG['CROSS_COMPILE']:
 HOST_SOURCES += [
     'elf.cpp',
     'elfhack.cpp',
 ]
 
 HOST_PROGRAM = 'elfhack'
 
 DEFINES['ELFHACK_BUILD'] = True
+
+NO_PGO = True
--- a/build/unix/stdc++compat/Makefile.in
+++ b/build/unix/stdc++compat/Makefile.in
@@ -1,12 +1,11 @@
 # 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/.
 
 STL_FLAGS =
 NO_EXPAND_LIBS = 1
-NO_PROFILE_GUIDED_OPTIMIZE = 1
 
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_TARGET_VERSION)
 HOST_CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_HOST_VERSION)
--- a/build/unix/stdc++compat/moz.build
+++ b/build/unix/stdc++compat/moz.build
@@ -10,8 +10,10 @@ if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION'
 
 if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
     HOST_LIBRARY_NAME = 'host_stdc++compat'
     HOST_SOURCES += [
         'stdc++compat.cpp',
     ]
 
 FORCE_STATIC_LIB = True
+
+NO_PGO = True
--- a/build/win32/Makefile.in
+++ b/build/win32/Makefile.in
@@ -1,14 +1,12 @@
 # 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/.
 
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-
 ifdef ENABLE_TESTS
 
 USE_STATIC_LIBS = 1
 
 endif # ENABLE_TESTS
 
 MOZ_GLUE_LDFLAGS =
 
--- a/build/win32/moz.build
+++ b/build/win32/moz.build
@@ -9,8 +9,10 @@ if CONFIG['_MSC_VER'] and CONFIG['OS_TES
 
 TEST_DIRS += ['crashinjectdll']
 
 if CONFIG['ENABLE_TESTS']:
     PROGRAM = 'crashinject'
     SOURCES += [
         'crashinject.cpp',
     ]
+
+NO_PGO = True
--- a/db/sqlite3/src/Makefile.in
+++ b/db/sqlite3/src/Makefile.in
@@ -41,21 +41,16 @@ MODULE_OPTIMIZE_FLAGS = -O2
 endif
 
 # Force /O2 optimisation on Windows because using the default /O1 causes
 # crashes with MSVC2005 and PGO. See bug 719584.
 ifeq ($(OS_ARCH),WINNT)
 MODULE_OPTIMIZE_FLAGS = -O2
 endif
 
-# disable PGO for Sun Studio
-ifdef SOLARIS_SUNPRO_CC
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-endif
-
 include $(topsrcdir)/config/rules.mk
 
 # next line allows use of MOZ_OBJDIR in .mozconfig with older gcc on BeOS, maybe others
 LOCAL_INCLUDES += -I$(srcdir)
 
 ifeq ($(OS_ARCH),OS2)
 ADD_TO_DEF_FILE = $(PYTHON) -m mozbuild.action.preprocessor $(DEFINES) \
        $(srcdir)/sqlite.def | sed -e '1,/^EXPORTS$$/ d' -e 's,sqlite3,_\0,' \
--- a/db/sqlite3/src/moz.build
+++ b/db/sqlite3/src/moz.build
@@ -57,8 +57,12 @@ if CONFIG['OS_TARGET'] == 'Android':
     # default to user readable only to fit Android security model
     DEFINES['SQLITE_DEFAULT_FILE_PERMISSIONS'] = '0600'
 
 # Force using malloc_usable_size when building with jemalloc because _msize
 # causes assertions on Win64. See bug 719579.
 if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_MEMORY']:
     DEFINES['HAVE_MALLOC_USABLE_SIZE'] = True
     DEFINES['SQLITE_WITHOUT_MSIZE'] = True
+
+# disable PGO for Sun Studio
+if CONFIG['SOLARIS_SUNPRO_CC']:
+    NO_PGO = True
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -20,18 +20,8 @@ include $(topsrcdir)/config/rules.mk
 CXXFLAGS += \
         -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright \
         -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright/openmax \
         -I$(ANDROID_SOURCE)/frameworks/av/include/media/stagefright \
         -I$(ANDROID_SOURCE)/frameworks/native/include/media/openmax \
         $(NULL)
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
-
-ifdef _MSC_VER
-ifeq ($(CPU_ARCH),x86_64)
-# Workaround compiler bug (Bug 795594)
-NO_PROFILE_GUIDED_OPTIMIZE := \
-  LayerTreeInvalidation.cpp \
-  Layers.cpp \
-  $(NULL)
-endif
-endif
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -249,38 +249,46 @@ UNIFIED_SOURCES += [
     'ipc/LayerTransactionChild.cpp',
     'ipc/LayerTransactionParent.cpp',
     'ipc/ShadowLayerChild.cpp',
     'ipc/ShadowLayerParent.cpp',
     'ipc/ShadowLayers.cpp',
     'ipc/SharedPlanarYCbCrImage.cpp',
     'ipc/SharedRGBImage.cpp',
     'ipc/TaskThrottler.cpp',
-    'Layers.cpp',
     'LayerScope.cpp',
     'LayersLogging.cpp',
     'LayerSorter.cpp',
-    'LayerTreeInvalidation.cpp',
     'opengl/CompositingRenderTargetOGL.cpp',
     'opengl/CompositorOGL.cpp',
     'opengl/OGLShaderProgram.cpp',
     'opengl/TextureClientOGL.cpp',
     'opengl/TextureHostOGL.cpp',
     'opengl/TexturePoolOGL.cpp',
     'ReadbackProcessor.cpp',
     'RenderTrace.cpp',
     'RotatedBuffer.cpp',
     'YCbCrImageDataSerializer.cpp',
 ]
 
 SOURCES += [
     'basic/BasicImageLayer.cpp',
     'ImageContainer.cpp',
+    'Layers.cpp',
+    'LayerTreeInvalidation.cpp',
 ]
 
+# Workaround compiler bug (Bug 795594)
+if CONFIG['_MSC_VER'] and CONFIG['CPU_ARCH'] == 'x86_64':
+    for src in [
+        'Layers.cpp',
+        'LayerTreeInvalidation.cpp',
+    ]:
+        SOURCES[src].no_pgo = True
+
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     SOURCES += [
         'basic/MacIOSurfaceTextureHostBasic.cpp',
         'opengl/MacIOSurfaceTextureClientOGL.cpp',
         'opengl/MacIOSurfaceTextureHostOGL.cpp',
     ]
 
 IPDL_SOURCES = [
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -375,32 +375,16 @@ EXTRA_DSO_LDOPTS += $(MOZ_ICU_LIBS)
 else
 SHARED_LIBRARY_LIBS += $(MOZ_ICU_LIBS)
 endif
 
 # Prevent floating point errors caused by VC++ optimizations
 ifdef _MSC_VER
 # XXX We should add this to CXXFLAGS, too?
 CFLAGS += -fp:precise
-
-ifeq ($(CPU_ARCH),x86)
-# Workaround compiler bug on PGO (Bug 721284)
-NO_PROFILE_GUIDED_OPTIMIZE := \
-  MonoIC.cpp \
-  Compiler.cpp \
-  $(NULL)
-# Ditto (Bug 772303)
-NO_PROFILE_GUIDED_OPTIMIZE += RegExp.cpp
-endif
-# Ditto (Bug 810661)
-ifeq ($(CPU_ARCH),x86_64)
-NO_PROFILE_GUIDED_OPTIMIZE := \
-  CTypes.cpp \
-  $(NULL)
-endif
 endif # _MSC_VER
 
 ifeq ($(OS_ARCH),FreeBSD)
 EXTRA_LIBS	+= -pthread
 endif
 ifeq ($(OS_ARCH),Linux)
 EXTRA_LIBS	+= -ldl
 endif
--- a/js/src/jit/RangeAnalysis.h
+++ b/js/src/jit/RangeAnalysis.h
@@ -8,16 +8,20 @@
 #define jit_RangeAnalysis_h
 
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MathAlgorithms.h"
 
 #include "jit/IonAnalysis.h"
 #include "jit/MIR.h"
 
+// windows.h defines those, which messes with the definitions below.
+#undef min
+#undef max
+
 namespace js {
 namespace jit {
 
 class MBasicBlock;
 class MIRGraph;
 
 // An upper bound computed on the number of backedges a loop will take.
 // This count only includes backedges taken while running Ion code: for OSR
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -93,17 +93,16 @@ EXPORTS.js += [
 UNIFIED_SOURCES += [
     'assembler/jit/ExecutableAllocator.cpp',
     'builtin/Eval.cpp',
     'builtin/Intl.cpp',
     'builtin/MapObject.cpp',
     'builtin/Object.cpp',
     'builtin/ParallelArray.cpp',
     'builtin/Profilers.cpp',
-    'builtin/RegExp.cpp',
     'builtin/TestingFunctions.cpp',
     'builtin/TypedObject.cpp',
     'builtin/TypeRepresentation.cpp',
     'devtools/sharkctl.cpp',
     'ds/LifoAlloc.cpp',
     'frontend/BytecodeCompiler.cpp',
     'frontend/BytecodeEmitter.cpp',
     'frontend/FoldConstants.cpp',
@@ -192,23 +191,26 @@ UNIFIED_SOURCES += [
     'yarr/YarrCanonicalizeUCS2.cpp',
     'yarr/YarrInterpreter.cpp',
     'yarr/YarrPattern.cpp',
     'yarr/YarrSyntaxChecker.cpp',
 ]
 
 # jsarray.cpp and jsatom.cpp cannot be built in unified mode because
 # xpcshell is broken during packaging when compiled with gcc-4.8.2
+# builtin/RegExp.cpp cannot be built in unified mode because it is built
+# without PGO
 # frontend/Parser.cpp cannot be built in unified mode because of explicit
 # template instantiations.
 # jsmath.cpp cannot be built in unified mode because it needs to pull rand_s
 # from <stdlib.h> on Windows through a preprocessor define.
 # jsutil.cpp cannot be built in unified mode because it is needed for
 # check-vanilla-allocations.
 SOURCES += [
+    'builtin/RegExp.cpp',
     'frontend/Parser.cpp',
     'jsarray.cpp',
     'jsatom.cpp',
     'jsmath.cpp',
     'jsutil.cpp',
 ]
 
 if CONFIG['JS_POSIX_NSPR']:
@@ -418,8 +420,14 @@ if CONFIG['JS_THREADSAFE']:
 
 if CONFIG['JS_HAS_CTYPES']:
     DEFINES['JS_HAS_CTYPES'] = True
     for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
         DEFINES[var] = '"%s"' % CONFIG[var]
 
 if CONFIG['MOZ_LINKER']:
     DEFINES['MOZ_LINKER'] = True
+
+if CONFIG['_MSC_VER']:
+    if CONFIG['CPU_ARCH'] == 'x86':
+        SOURCES['builtin/RegExp.cpp'].no_pgo = True # Bug 772303
+    elif CONFIG['CPU_ARCH'] == 'x86_64':
+        SOURCES['ctypes/CTypes.cpp'].no_pgo = True # Bug 810661
--- a/js/src/shell/Makefile.in
+++ b/js/src/shell/Makefile.in
@@ -1,21 +1,14 @@
 # -*- Mode: makefile -*-
 #
 # 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/.
 
-ifdef _MSC_VER
-# unnecessary PGO for js shell.  But gcc cannot turn off pgo because it is
-# necessary to link PGO lib on gcc when a object/static lib are compiled
-# for PGO.
-NO_PROFILE_GUIDED_OPTIMIZE := 1
-endif
-
 LIBS      = $(NSPR_LIBS) $(EDITLINE_LIBS) $(DEPTH)/$(LIB_PREFIX)js_static.$(LIB_SUFFIX) $(MOZ_ZLIB_LIBS)
 ifdef MOZ_NATIVE_FFI
 EXTRA_LIBS += $(MOZ_FFI_LIBS)
 endif
 ifdef MOZ_SHARED_ICU
 EXTRA_LIBS += $(MOZ_ICU_LIBS)
 endif
 
--- a/js/src/shell/moz.build
+++ b/js/src/shell/moz.build
@@ -11,8 +11,14 @@ UNIFIED_SOURCES += [
     'jsheaptools.cpp',
     'jsoptparse.cpp',
 ]
 
 # Building against js_static requires that we declare mfbt sybols "exported"
 # on its behalf.
 for var in ('EXPORT_JS_API', 'IMPL_MFBT'):
     DEFINES[var] = True
+
+if CONFIG['_MSC_VER']:
+    # unnecessary PGO for js shell.  But gcc cannot turn off pgo because it is
+    # necessary to link PGO lib on gcc when a object/static lib are compiled
+    # for PGO.
+    NO_PGO = True
--- a/media/libvpx/Makefile.in
+++ b/media/libvpx/Makefile.in
@@ -115,35 +115,26 @@ ifndef _MSC_VER
 %_avx2.$(OBJ_SUFFIX): CFLAGS += -mavx2
 endif
 
 quantize_sse4.$(OBJ_SUFFIX): vp8_asm_enc_offsets.asm
 quantize_ssse3.$(OBJ_SUFFIX): vp8_asm_enc_offsets.asm
 
 ifdef VPX_NEED_OBJ_INT_EXTRACT
 
-# only for MSVC
-ifdef _MSC_VER
-NO_PROFILE_GUIDED_OPTIMIZE := vpx_scale_asm_offsets.c
-endif
-
 vpx_scale_asm_offsets.asm: vpx_scale_asm_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
 	./$(HOST_PROGRAM) $(VPX_OIE_FORMAT) $< \
 	    $(if $(VPX_AS_CONVERSION),| $(VPX_AS_CONVERSION)) > $@
 
 # Filter out this object, because we don't want to link against it.
 # It was generated solely so it could be parsed by obj_int_extract.
 OBJS := $(filter-out vpx_scale_asm_offsets.$(OBJ_SUFFIX),$(OBJS))
 
 ifdef MOZ_VP8_ENCODER
 
-ifdef _MSC_VER
-NO_PROFILE_GUIDED_OPTIMIZE += vp8_asm_enc_offsets.c
-endif
-
 vp8_asm_enc_offsets.asm: vp8_asm_enc_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
 	./$(HOST_PROGRAM) $(VPX_OIE_FORMAT) $< \
 	    $(if $(VPX_AS_CONVERSION),| $(VPX_AS_CONVERSION)) > $@
 
 # Filter out this object, because we don't want to link against it.
 # It was generated solely so it could be parsed by obj_int_extract.
 OBJS := $(filter-out vp8_asm_enc_offsets.$(OBJ_SUFFIX),$(OBJS))
 
--- a/media/libvpx/moz.build
+++ b/media/libvpx/moz.build
@@ -26,20 +26,24 @@ if CONFIG['MOZ_VP8_ENCODER']:
 #postproc is only enabled on x86 with asm
 if CONFIG['VPX_X86_ASM']:
     SOURCES += files['VP8_POSTPROC']
 
 if CONFIG['VPX_X86_ASM'] and CONFIG['OS_TARGET'] == 'WINNT':
     SOURCES += [
         'vpx_scale/vpx_scale_asm_offsets.c',
     ]
+    if CONFIG['_MSC_VER']:
+        SOURCES['vpx_scale/vpx_scale_asm_offsets.c'].no_pgo = True
     if CONFIG['MOZ_VP8_ENCODER']:
         SOURCES += [
             'vp8/encoder/vp8_asm_enc_offsets.c',
         ]
+        if CONFIG['_MSC_VER']:
+            SOURCES['vp8/encoder/vp8_asm_enc_offsets.c'].no_pgo = True
 
 if CONFIG['VPX_X86_ASM']:
     SOURCES += files['X86_ASM']
 
     if '64' in CONFIG['OS_TEST']:
         SOURCES += files['X86-64_ASM']
 
     # AVX2 only supported on
--- a/memory/mozjemalloc/Makefile.in
+++ b/memory/mozjemalloc/Makefile.in
@@ -4,17 +4,11 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 ifndef MOZ_JEMALLOC3
 ifeq ($(OS_ARCH),SunOS)
 ifndef GNU_CC
 MODULE_OPTIMIZE_FLAGS = -xO5
 endif
 endif
-
-ifeq (Linux,$(OS_TARGET))
-#XXX: PGO on Linux causes problems here
-# See bug 419470
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-endif
 endif
 
 LOCAL_INCLUDES += -I$(topsrcdir)/memory/build
--- a/memory/mozjemalloc/moz.build
+++ b/memory/mozjemalloc/moz.build
@@ -21,8 +21,13 @@ if CONFIG['MOZ_UPDATE_CHANNEL'] not in (
     DEFINES['MOZ_JEMALLOC_HARD_ASSERTS'] = True
 
 DEFINES['abort'] = 'moz_abort'
 
 if CONFIG['MOZ_REPLACE_MALLOC']:
     DEFINES['MOZ_REPLACE_MALLOC'] = True
 
 DEFINES['MOZ_JEMALLOC_IMPL'] = True
+
+#XXX: PGO on Linux causes problems here
+# See bug 419470
+if CONFIG['OS_TARGET'] == 'Linux':
+    NO_PGO = True
deleted file mode 100644
--- a/netwerk/sctp/datachannel/Makefile.in
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-NO_PROFILE_GUIDED_OPTIMIZE = 1 # Don't PGO
--- a/netwerk/sctp/datachannel/moz.build
+++ b/netwerk/sctp/datachannel/moz.build
@@ -34,8 +34,10 @@ DEFINES['SCTP_DEBUG'] = 1
 
 if CONFIG['OS_TARGET'] != 'Android':
     DEFINES['INET6'] = 1
 
 if CONFIG['OS_TARGET'] == 'WINNT':
     DEFINES['__Userspace_os_Windows'] = 1
 else:
     DEFINES['__Userspace_os_%s' % CONFIG['OS_TARGET']] = 1
+
+NO_PGO = True # Don't PGO
--- a/netwerk/sctp/src/Makefile.in
+++ b/netwerk/sctp/src/Makefile.in
@@ -1,15 +1,13 @@
 #
 # 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/.
 
-NO_PROFILE_GUIDED_OPTIMIZE = 1 # Don't PGO
-
 ifeq ($(OS_TARGET),Darwin)
 DEFINES += \
   -U__APPLE__ \
   $(NULL)
 else
 ifeq ($(OS_TARGET),FreeBSD)
 DEFINES += \
   -U__FreeBSD__ \
--- a/netwerk/sctp/src/moz.build
+++ b/netwerk/sctp/src/moz.build
@@ -75,8 +75,10 @@ else:
     DEFINES['__Userspace_os_%s' % CONFIG['OS_TARGET']] = 1
 
 if CONFIG['OS_TARGET'] == 'Darwin':
     DEFINES['__APPLE_USE_RFC_2292'] = 1
 
 if CONFIG['OS_TARGET'] in ('Linux', 'Android'):
     # to make sure that in6_pktinfo gets defined on all distros
     DEFINES['_GNU_SOURCE'] = True
+
+NO_PGO = True # Don't PGO
--- a/netwerk/wifi/moz.build
+++ b/netwerk/wifi/moz.build
@@ -1,16 +1,14 @@
 # -*- 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/.
 
-FAIL_ON_WARNINGS = True
-
 XPIDL_SOURCES += [
     'nsIWifiAccessPoint.idl',
     'nsIWifiListener.idl',
     'nsIWifiMonitor.idl',
 ]
 
 XPIDL_MODULE = 'necko_wifi'
 
@@ -22,19 +20,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
     UNIFIED_SOURCES += [
         'nsWifiMonitorGonk.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'nsWifiMonitor.cpp',
     ]
 
+# osx_corewlan.mm has warnings I don't understand.
+FAIL_ON_WARNINGS = CONFIG['OS_ARCH'] != 'Darwin'
+
 if CONFIG['OS_ARCH'] == 'Darwin':
-    # osx_corewlan.mm has warnings I don't understand.
-    FAIL_ON_WARNINGS = False
     UNIFIED_SOURCES += [
         'nsWifiScannerMac.cpp',
     ]
     UNIFIED_SOURCES += [
         'osx_corewlan.mm',
     ]
 elif CONFIG['OS_ARCH'] == 'WINNT':
     UNIFIED_SOURCES += [
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -19,17 +19,17 @@ from __future__ import unicode_literals
 
 import os
 
 from collections import OrderedDict
 from mozbuild.util import (
     shell_quote,
     StrictOrderingOnAppendList,
 )
-from .sandbox_symbols import compute_final_target
+from .sandbox_symbols import FinalTargetValue
 
 
 class TreeMetadata(object):
     """Base class for all data being captured."""
 
     def __init__(self):
         self._ack = False
 
@@ -494,11 +494,11 @@ class InstallationTarget(SandboxDerived)
         self.subdir = sandbox.get('DIST_SUBDIR', '')
         self.target = sandbox['FINAL_TARGET']
         self.enabled = not sandbox.get('NO_DIST_INSTALL', False)
 
     def is_custom(self):
         """Returns whether or not the target is not derived from the default
         given xpiname and subdir."""
 
-        return compute_final_target(dict(
+        return FinalTargetValue(dict(
             XPI_NAME=self.xpiname,
             DIST_SUBDIR=self.subdir)) == self.target
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -253,16 +253,26 @@ class TreeMetadataEmitter(LoggingMixin):
                 if ext not in mapping:
                     raise SandboxValidationError('%s has an unknown file type in %s' % (f, sandbox['RELATIVEDIR']))
                 l = passthru.variables.setdefault(mapping[ext], [])
                 l.append(f)
                 if variable.startswith('GENERATED_'):
                     l = passthru.variables.setdefault('GARBAGE', [])
                     l.append(f)
 
+        no_pgo = sandbox.get('NO_PGO')
+        sources = sandbox.get('SOURCES', [])
+        no_pgo_sources = [f for f in sources if sources[f].no_pgo]
+        if no_pgo:
+            if no_pgo_sources:
+                raise SandboxValidationError('NO_PGO and SOURCES[...].no_pgo cannot be set at the same time')
+            passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo
+        if no_pgo_sources:
+            passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo_sources
+
         exports = sandbox.get('EXPORTS')
         if exports:
             yield Exports(sandbox, exports,
                 dist_install=not sandbox.get('NO_DIST_INSTALL', False))
 
         defines = sandbox.get('DEFINES')
         if defines:
             yield Defines(sandbox, defines)
--- a/python/mozbuild/mozbuild/frontend/reader.py
+++ b/python/mozbuild/mozbuild/frontend/reader.py
@@ -180,19 +180,19 @@ class MozbuildSandbox(Sandbox):
             var = metadata.get('var', None)
             if var and var in ['TOOL_DIRS', 'TEST_TOOL_DIRS']:
                 d['IS_TOOL_DIR'] = True
 
             # Register functions.
             for name, func in FUNCTIONS.items():
                 d[name] = getattr(self, func[0])
 
-        # Initialize the exports that we need in the global.
-        extra_vars = self.metadata.get('exports', dict())
-        self._globals.update(extra_vars)
+            # Initialize the exports that we need in the global.
+            extra_vars = self.metadata.get('exports', dict())
+            self._globals.update(extra_vars)
 
     def exec_file(self, path, filesystem_absolute=False):
         """Override exec_file to normalize paths and restrict file loading.
 
         If the path is absolute, behavior is governed by filesystem_absolute.
         If filesystem_absolute is True, the path is interpreted as absolute on
         the actual filesystem. If it is false, the path is treated as absolute
         within the current topsrcdir.
--- a/python/mozbuild/mozbuild/frontend/sandbox.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox.py
@@ -29,16 +29,22 @@ import sys
 from contextlib import contextmanager
 
 from mozbuild.util import (
     ReadOnlyDefaultDict,
     ReadOnlyDict,
 )
 
 
+class SandboxDerivedValue(object):
+    """Classes deriving from this one receive a special treatment in a
+    sandbox GlobalNamespace. See GlobalNamespace documentation.
+    """
+
+
 def alphabetical_sorted(iterable, cmp=None, key=lambda x: x.lower(),
                         reverse=False):
     """sorted() replacement for the sandbox, ordering alphabetically by
     default.
     """
     return sorted(iterable, cmp, key, reverse)
 
 
@@ -56,20 +62,27 @@ class GlobalNamespace(dict):
 
     When variables are assigned to, we verify assignment is allowed. Assignment
     is allowed if the variable is known (set defined at constructor time) and
     if the value being assigned is the expected type (also defined at
     constructor time).
 
     When variables are read, we first try to read the existing value. If a
     value is not found and it is defined in the allowed variables set, we
-    return the default value for it. We don't assign default values until
-    they are accessed because this makes debugging the end-result much
-    simpler. Instead of a data structure with lots of empty/default values,
-    you have a data structure with only the values that were read or touched.
+    return a new instance of the class for that variable. We don't assign
+    default instances until they are accessed because this makes debugging
+    the end-result much simpler. Instead of a data structure with lots of
+    empty/default values, you have a data structure with only the values
+    that were read or touched.
+
+    Instances of variables classes are created by invoking class_name(),
+    except when class_name derives from SandboxDerivedValue, in which
+    case class_name(instance_of_the_global_namespace) is invoked.
+    A value is added to those calls when instances are created during
+    assignment (setitem).
 
     Instantiators of this class are given a backdoor to perform setting of
     arbitrary values. e.g.
 
         ns = GlobalNamespace()
         with ns.allow_all_writes():
             ns['foo'] = True
 
@@ -106,47 +119,64 @@ class GlobalNamespace(dict):
         self._allowed_variables = allowed_variables or {}
 
         # We need to record this because it gets swallowed as part of
         # evaluation.
         self.last_name_error = None
 
         self._allow_all_writes = False
 
+        self._allow_one_mutation = set()
+
     def __getitem__(self, name):
         try:
             return dict.__getitem__(self, name)
         except KeyError:
             pass
 
         # The variable isn't present yet. Fall back to VARIABLES.
         default = self._allowed_variables.get(name, None)
         if default is None:
             self.last_name_error = KeyError('global_ns', 'get_unknown', name)
             raise self.last_name_error
 
         # If the default is specifically a lambda (or, rather, any function--but
         # not a class that can be called), then it is actually a rule to
         # generate the default that should be used.
-        default_rule = default[2]
-        if isinstance(default_rule, type(lambda: None)):
-            default_rule = default_rule(self)
+        default = default[0]
+        if issubclass(default, SandboxDerivedValue):
+            value = default(self)
+        else:
+            value = default()
 
-        dict.__setitem__(self, name, copy.deepcopy(default_rule))
+        dict.__setitem__(self, name, value)
         return dict.__getitem__(self, name)
 
     def __setitem__(self, name, value):
         if self._allow_all_writes:
             dict.__setitem__(self, name, value)
+            self._allow_one_mutation.add(name)
             return
 
+        # Forbid assigning over a previously set value. Interestingly, when
+        # doing FOO += ['bar'], python actually does something like:
+        #   foo = namespace.__getitem__('FOO')
+        #   foo.__iadd__(['bar'])
+        #   namespace.__setitem__('FOO', foo)
+        # This means __setitem__ is called with the value that is already
+        # in the dict, when doing +=, which is permitted.
+        if name in self._allow_one_mutation:
+            self._allow_one_mutation.remove(name)
+        elif name in self and dict.__getitem__(self, name) is not value:
+            raise Exception('Reassigning %s is forbidden' % name)
+
         # We don't need to check for name.isupper() here because LocalNamespace
         # only sends variables our way if isupper() is True.
-        stored_type, input_type, default, docs, tier = \
-            self._allowed_variables.get(name, (None, None, None, None, None))
+        stored_type, input_type, docs, tier = \
+            self._allowed_variables.get(name, (None, None, None, None))
 
         # Variable is unknown.
         if stored_type is None:
             self.last_name_error = KeyError('global_ns', 'set_unknown', name,
                 value)
             raise self.last_name_error
 
         # If the incoming value is not the type we store, we try to convert
@@ -155,33 +185,41 @@ class GlobalNamespace(dict):
         # not be in the allowed set if the constructor function for the stored
         # type does not accept an instance of that type.
         if not isinstance(value, stored_type):
             if not isinstance(value, input_type):
                 self.last_name_error = ValueError('global_ns', 'set_type', name,
                     value, input_type)
                 raise self.last_name_error
 
-            value = stored_type(value)
+            if issubclass(stored_type, SandboxDerivedValue):
+                value = stored_type(self, value)
+            else:
+                value = stored_type(value)
 
         dict.__setitem__(self, name, value)
 
     @contextmanager
     def allow_all_writes(self):
         """Allow any variable to be written to this instance.
 
         This is used as a context manager. When activated, all writes
         (__setitem__ calls) are allowed. When the context manager is exited,
         the instance goes back to its default behavior of only allowing
         whitelisted mutations.
         """
         self._allow_all_writes = True
         yield self
         self._allow_all_writes = False
 
+    # dict.update doesn't call our __setitem__, so we have to override it.
+    def update(self, other):
+        for name, value in other.items():
+            self.__setitem__(name, value)
+
 
 class LocalNamespace(dict):
     """Represents the locals namespace in a Sandbox.
 
     This behaves like a dict except with some additional behavior tailored
     to our sandbox execution model.
 
     Under normal rules of exec(), doing things like += could have interesting
@@ -377,11 +415,11 @@ class Sandbox(object):
 
     def __contains__(self, key):
         return key in self._globals
 
     def get(self, key, default=None):
         return self._globals.get(key, default)
 
     def get_affected_tiers(self):
-        tiers = (self._allowed_variables[key][4] for key in self
+        tiers = (self._allowed_variables[key][3] for key in self
                  if key in self._allowed_variables)
         return set(tier for tier in tiers if tier)
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -16,112 +16,116 @@ the Sandbox consists of, you've come to 
 """
 
 from __future__ import unicode_literals
 
 from collections import OrderedDict
 from mozbuild.util import (
     HierarchicalStringList,
     StrictOrderingOnAppendList,
+    StrictOrderingOnAppendListWithFlagsFactory,
 )
+from .sandbox import SandboxDerivedValue
+from types import StringTypes
 
 
-def compute_final_target(variables):
-    """Convert the default value for FINAL_TARGET"""
-    basedir = 'dist/'
-    if variables['XPI_NAME']:
-        basedir += 'xpi-stage/' + variables['XPI_NAME']
-    else:
-        basedir += 'bin'
-    if variables['DIST_SUBDIR']:
-        basedir += '/' + variables['DIST_SUBDIR']
-    return basedir
- 
- 
+class FinalTargetValue(SandboxDerivedValue, unicode):
+    def __new__(cls, sandbox, value=""):
+        if not value:
+            value = 'dist/'
+            if sandbox['XPI_NAME']:
+                value += 'xpi-stage/' + sandbox['XPI_NAME']
+            else:
+                value += 'bin'
+            if sandbox['DIST_SUBDIR']:
+                value += '/' + sandbox['DIST_SUBDIR']
+        return unicode.__new__(cls, value)
+
+
 # This defines the set of mutable global variables.
 #
 # Each variable is a tuple of:
 #
-#   (storage_type, input_types, default_value, docs, tier)
+#   (storage_type, input_types, docs, tier)
 #
 # Tier says for which specific tier the variable has an effect.
 # Valid tiers are:
 # - 'export'
 # - 'compile': everything in relation with compiling objects.
 # - 'binaries': everything in relation with linking objects, producing
 #      programs and libraries.
 # - 'libs': everything that is not compile or binaries and that has
 #      traditionally been in the libs tier.
 # - 'tools'
 # A value of None means the variable has no direct effect on any tier.
 
 VARIABLES = {
     # Variables controlling reading of other frontend files.
-    'ANDROID_GENERATED_RESFILES': (StrictOrderingOnAppendList, list, [],
+    'ANDROID_GENERATED_RESFILES': (StrictOrderingOnAppendList, list,
         """Android resource files generated as part of the build.
 
         This variable contains a list of files that are expected to be
         generated (often by preprocessing) into a 'res' directory as
         part of the build process, and subsequently merged into an APK
         file.
         """, 'export'),
 
-    'ANDROID_RESFILES': (StrictOrderingOnAppendList, list, [],
+    'ANDROID_RESFILES': (StrictOrderingOnAppendList, list,
         """Android resource files.
 
         This variable contains a list of files to package into a 'res'
         directory and merge into an APK file.
         """, 'export'),
 
-    'SOURCES': (StrictOrderingOnAppendList, list, [],
+    'SOURCES': (StrictOrderingOnAppendListWithFlagsFactory({'no_pgo': bool}), list,
         """Source code files.
 
         This variable contains a list of source code files to compile.
         Accepts assembler, C, C++, Objective C/C++.
         """, 'compile'),
 
-    'GENERATED_SOURCES': (StrictOrderingOnAppendList, list, [],
+    'GENERATED_SOURCES': (StrictOrderingOnAppendList, list,
         """Generated source code files.
 
         This variable contains a list of generated source code files to
         compile. Accepts assembler, C, C++, Objective C/C++.
         """, 'compile'),
 
-    'FILES_PER_UNIFIED_FILE': (int, int, None,
+    'FILES_PER_UNIFIED_FILE': (int, int,
         """The number of source files to compile into each unified source file.
 
         """, 'None'),
 
-    'UNIFIED_SOURCES': (StrictOrderingOnAppendList, list, [],
+    'UNIFIED_SOURCES': (StrictOrderingOnAppendList, list,
         """Source code files that can be compiled together.
 
         This variable contains a list of source code files to compile,
         that can be concatenated all together and built as a single source
         file. This can help make the build faster and reduce the debug info
         size.
         """, 'compile'),
 
-    'GENERATED_UNIFIED_SOURCES': (StrictOrderingOnAppendList, list, [],
+    'GENERATED_UNIFIED_SOURCES': (StrictOrderingOnAppendList, list,
         """Generated source code files that can be compiled together.
 
         This variable contains a list of generated source code files to
         compile, that can be concatenated all together, with UNIFIED_SOURCES,
         and built as a single source file. This can help make the build faster
         and reduce the debug info size.
         """, 'compile'),
 
-    'GENERATED_FILES': (StrictOrderingOnAppendList, list, [],
+    'GENERATED_FILES': (StrictOrderingOnAppendList, list,
         """Generic generated files.
 
         This variable contains a list of generate files for the build system
         to generate at export time. The rules for those files still live in
         Makefile.in.
         """, 'export'),
 
-    'DEFINES': (OrderedDict, dict, OrderedDict(),
+    'DEFINES': (OrderedDict, dict,
         """Dictionary of compiler defines to declare.
 
         These are passed in to the compiler as ``-Dkey='value'`` for string
         values, ``-Dkey=value`` for numeric values, or ``-Dkey`` if the
         value is True. Note that for string values, the outer-level of
         single-quotes will be consumed by the shell. If you want to have
         a string-literal in the program, the value needs to have
         double-quotes.
@@ -139,230 +143,234 @@ VARIABLES = {
 
            DEFINES.update({
                'NS_NO_XPCOM': True,
                'MOZ_EXTENSIONS_DB_SCHEMA': 15,
                'DLL_SUFFIX': '".so"',
            })
         """, None),
 
-    'DIRS': (list, list, [],
+    'DIRS': (list, list,
         """Child directories to descend into looking for build frontend files.
 
         This works similarly to the ``DIRS`` variable in make files. Each str
         value in the list is the name of a child directory. When this file is
         done parsing, the build reader will descend into each listed directory
         and read the frontend file there. If there is no frontend file, an error
         is raised.
 
         Values are relative paths. They can be multiple directory levels
         above or below. Use ``..`` for parent directories and ``/`` for path
         delimiters.
         """, None),
 
-    'EXPORT_LIBRARY': (bool, bool, False,
+    'EXPORT_LIBRARY': (bool, bool,
         """Install the library to the static libraries folder.
         """, None),
 
-    'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list, [],
+    'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list,
         """Additional component files to distribute.
 
        This variable contains a list of files to copy into
        ``$(FINAL_TARGET)/components/``.
         """, 'libs'),
 
-    'EXTRA_JS_MODULES': (StrictOrderingOnAppendList, list, [],
+    'EXTRA_JS_MODULES': (StrictOrderingOnAppendList, list,
         """Additional JavaScript files to distribute.
 
         This variable contains a list of files to copy into
         ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``. ``JS_MODULES_PATH`` defaults
         to ``modules`` if left undefined.
         """, 'libs'),
 
-    'EXTRA_PP_JS_MODULES': (StrictOrderingOnAppendList, list, [],
+    'EXTRA_PP_JS_MODULES': (StrictOrderingOnAppendList, list,
         """Additional JavaScript files to distribute.
 
         This variable contains a list of files to copy into
         ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``, after preprocessing.
         ``JS_MODULES_PATH`` defaults to ``modules`` if left undefined.
         """, 'libs'),
 
-    'EXTRA_PP_COMPONENTS': (StrictOrderingOnAppendList, list, [],
+    'EXTRA_PP_COMPONENTS': (StrictOrderingOnAppendList, list,
         """Javascript XPCOM files.
 
        This variable contains a list of files to preprocess.  Generated
        files will be installed in the ``/components`` directory of the distribution.
         """, 'libs'),
 
-    'FINAL_LIBRARY': (unicode, unicode, "",
+    'FINAL_LIBRARY': (unicode, unicode,
         """Library in which the objects of the current directory will be linked.
 
         This variable contains the name of a library, defined elsewhere with
         ``LIBRARY_NAME``, in which the objects of the current directory will be
         linked.
         """, 'binaries'),
 
-    'CPP_UNIT_TESTS': (StrictOrderingOnAppendList, list, [],
+    'CPP_UNIT_TESTS': (StrictOrderingOnAppendList, list,
         """C++ source files for unit tests.
 
         This is a list of C++ unit test sources. Entries must be files that
         exist. These generally have ``.cpp`` extensions.
         """, 'binaries'),
 
-    'FAIL_ON_WARNINGS': (bool, bool, False,
+    'FAIL_ON_WARNINGS': (bool, bool,
         """Whether to treat warnings as errors.
         """, None),
 
-    'FORCE_SHARED_LIB': (bool, bool, False,
+    'FORCE_SHARED_LIB': (bool, bool,
         """Whether the library in this directory is a shared library.
         """, None),
 
-    'FORCE_STATIC_LIB': (bool, bool, False,
+    'FORCE_STATIC_LIB': (bool, bool,
         """Whether the library in this directory is a static library.
         """, None),
 
-    'GENERATED_INCLUDES' : (StrictOrderingOnAppendList, list, [],
+    'GENERATED_INCLUDES' : (StrictOrderingOnAppendList, list,
         """Directories generated by the build system to be searched for include
         files by the compiler.
         """, None),
 
-    'HOST_SOURCES': (StrictOrderingOnAppendList, list, [],
+    'HOST_SOURCES': (StrictOrderingOnAppendList, list,
         """Source code files to compile with the host compiler.
 
         This variable contains a list of source code files to compile.
         with the host compiler.
         """, 'compile'),
 
-    'IS_COMPONENT': (bool, bool, False,
+    'IS_COMPONENT': (bool, bool,
         """Whether the library contains a binary XPCOM component manifest.
         """, None),
 
-    'PARALLEL_DIRS': (list, list, [],
+    'PARALLEL_DIRS': (list, list,
         """A parallel version of ``DIRS``.
 
         Ideally this variable does not exist. It is provided so a transition
         from recursive makefiles can be made. Once the build system has been
         converted to not use Makefile's for the build frontend, this will
         likely go away.
         """, None),
 
-    'HOST_LIBRARY_NAME': (unicode, unicode, "",
+    'HOST_LIBRARY_NAME': (unicode, unicode,
         """Name of target library generated when cross compiling.
         """, 'binaries'),
 
-    'JAVA_JAR_TARGETS': (dict, dict, {},
+    'JAVA_JAR_TARGETS': (dict, dict,
         """Defines Java JAR targets to be built.
 
         This variable should not be populated directly. Instead, it should
         populated by calling add_java_jar().
         """, 'binaries'),
 
-    'JS_MODULES_PATH': (unicode, unicode, "",
+    'JS_MODULES_PATH': (unicode, unicode,
         """Sub-directory of ``$(FINAL_TARGET)`` to install
         ``EXTRA_JS_MODULES``.
 
         ``EXTRA_JS_MODULES`` files are copied to
         ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``. This variable does not
         need to be defined if the desired destination directory is
         ``$(FINAL_TARGET)/modules``.
         """, None),
 
-    'LIBRARY_NAME': (unicode, unicode, "",
+    'LIBRARY_NAME': (unicode, unicode,
         """The name of the library generated for a directory.
 
         In ``example/components/moz.build``,::
 
            LIBRARY_NAME = 'xpcomsample'
 
         would generate ``example/components/libxpcomsample.so`` on Linux, or
         ``example/components/xpcomsample.lib`` on Windows.
         """, 'binaries'),
 
-    'LIBS': (StrictOrderingOnAppendList, list, [],
+    'LIBS': (StrictOrderingOnAppendList, list,
         """Linker libraries and flags.
 
         A list of libraries and flags to include when linking.
         """, None),
 
-    'LIBXUL_LIBRARY': (bool, bool, False,
+    'LIBXUL_LIBRARY': (bool, bool,
         """Whether the library in this directory is linked into libxul.
 
         Implies ``MOZILLA_INTERNAL_API`` and ``FORCE_STATIC_LIB``.
         """, None),
 
-    'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list, [],
+    'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list,
         """Additional directories to be searched for include files by the compiler.
         """, None),
 
-    'MSVC_ENABLE_PGO': (bool, bool, False,
-        """Whether profile-guided optimization is enabled in this directory.
+    'MSVC_ENABLE_PGO': (bool, bool,
+        """Whether profile-guided optimization is enabled for MSVC in this directory.
         """, None),
 
-    'NO_VISIBILITY_FLAGS': (bool, bool, False,
+    'NO_PGO': (bool, bool,
+        """Whether profile-guided optimization is disable in this directory.
+        """, None),
+
+    'NO_VISIBILITY_FLAGS': (bool, bool,
         """Build sources listed in this file without VISIBILITY_FLAGS.
         """, None),
 
-    'OS_LIBS': (list, list, [],
+    'OS_LIBS': (list, list,
         """System link libraries.
 
         This variable contains a list of system libaries to link against.
         """, None),
 
-    'SDK_LIBRARY': (StrictOrderingOnAppendList, list, [],
+    'SDK_LIBRARY': (StrictOrderingOnAppendList, list,
         """Elements of the distributed SDK.
 
         Files on this list will be copied into ``SDK_LIB_DIR``
         (``$DIST/sdk/lib``).
         """, None),
 
-    'SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list, [],
+    'SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list,
         """Compile a list of executable names.
 
         Each name in this variable corresponds to an executable built from the
         corresponding source file with the same base name.
 
         If the configuration token ``BIN_SUFFIX`` is set, its value will be
         automatically appended to each name. If a name already ends with
         ``BIN_SUFFIX``, the name will remain unchanged.
         """, 'binaries'),
 
-    'HOST_SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list, [],
+    'HOST_SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list,
         """Compile a list of host executable names.
 
         Each name in this variable corresponds to a hosst executable built
         from the corresponding source file with the same base name.
 
         If the configuration token ``HOST_BIN_SUFFIX`` is set, its value will
         be automatically appended to each name. If a name already ends with
         ``HOST_BIN_SUFFIX``, the name will remain unchanged.
         """, 'binaries'),
 
-    'TOOL_DIRS': (list, list, [],
+    'TOOL_DIRS': (list, list,
         """Like DIRS but for tools.
 
         Tools are for pieces of the build system that aren't required to
         produce a working binary (in theory). They provide things like test
         code and utilities.
         """, None),
 
-    'TEST_DIRS': (list, list, [],
+    'TEST_DIRS': (list, list,
         """Like DIRS but only for directories that contain test-only code.
 
         If tests are not enabled, this variable will be ignored.
 
         This variable may go away once the transition away from Makefiles is
         complete.
         """, None),
 
-    'TEST_TOOL_DIRS': (list, list, [],
+    'TEST_TOOL_DIRS': (list, list,
         """TOOL_DIRS that is only executed if tests are enabled.
         """, None),
 
 
-    'TIERS': (OrderedDict, dict, OrderedDict(),
+    'TIERS': (OrderedDict, dict,
         """Defines directories constituting the tier traversal mechanism.
 
         The recursive make backend iteration is organized into tiers. There are
         major tiers (keys in this dict) that correspond roughly to applications
         or libraries being built. e.g. base, nspr, js, platform, app. Within
         each tier are phases like export, libs, and tools. The recursive make
         backend iterates over each phase in the first tier then proceeds to the
         next tier until all tiers are exhausted.
@@ -370,196 +378,196 @@ VARIABLES = {
         Tiers are a way of working around deficiencies in recursive make. These
         will probably disappear once we no longer rely on recursive make for
         the build backend. They will likely be replaced by ``DIRS``.
 
         This variable is typically not populated directly. Instead, it is
         populated by calling add_tier_dir().
         """, None),
 
-    'EXTERNAL_MAKE_DIRS': (list, list, [],
+    'EXTERNAL_MAKE_DIRS': (list, list,
         """Directories that build with make but don't use moz.build files.
 
         This is like ``DIRS`` except it implies that ``make`` is used to build the
         directory and that the directory does not define itself with moz.build
         files.
         """, None),
 
-    'PARALLEL_EXTERNAL_MAKE_DIRS': (list, list, [],
+    'PARALLEL_EXTERNAL_MAKE_DIRS': (list, list,
         """Parallel version of ``EXTERNAL_MAKE_DIRS``.
         """, None),
 
-    'CONFIGURE_SUBST_FILES': (StrictOrderingOnAppendList, list, [],
+    'CONFIGURE_SUBST_FILES': (StrictOrderingOnAppendList, list,
         """Output files that will be generated using configure-like substitution.
 
         This is a substitute for ``AC_OUTPUT`` in autoconf. For each path in this
         list, we will search for a file in the srcdir having the name
         ``{path}.in``. The contents of this file will be read and variable
         patterns like ``@foo@`` will be substituted with the values of the
         ``AC_SUBST`` variables declared during configure.
         """, None),
 
-    'CONFIGURE_DEFINE_FILES': (StrictOrderingOnAppendList, list, [],
+    'CONFIGURE_DEFINE_FILES': (StrictOrderingOnAppendList, list,
         """Output files generated from configure/config.status.
 
         This is a substitute for ``AC_CONFIG_HEADER`` in autoconf. This is very
         similar to ``CONFIGURE_SUBST_FILES`` except the generation logic takes
         into account the values of ``AC_DEFINE`` instead of ``AC_SUBST``.
         """, None),
 
-    'EXPORTS': (HierarchicalStringList, list, HierarchicalStringList(),
+    'EXPORTS': (HierarchicalStringList, list,
         """List of files to be exported, and in which subdirectories.
 
         ``EXPORTS`` is generally used to list the include files to be exported to
         ``dist/include``, but it can be used for other files as well. This variable
         behaves as a list when appending filenames for export in the top-level
         directory. Files can also be appended to a field to indicate which
         subdirectory they should be exported to. For example, to export
         ``foo.h`` to the top-level directory, and ``bar.h`` to ``mozilla/dom/``,
         append to ``EXPORTS`` like so::
 
            EXPORTS += ['foo.h']
            EXPORTS.mozilla.dom += ['bar.h']
         """, None),
 
-    'PROGRAM' : (unicode, unicode, "",
+    'PROGRAM' : (unicode, unicode,
         """Compiled executable name.
 
         If the configuration token ``BIN_SUFFIX`` is set, its value will be
         automatically appended to ``PROGRAM``. If ``PROGRAM`` already ends with
         ``BIN_SUFFIX``, ``PROGRAM`` will remain unchanged.
         """, 'binaries'),
 
-    'HOST_PROGRAM' : (unicode, unicode, "",
+    'HOST_PROGRAM' : (unicode, unicode,
         """Compiled host executable name.
 
         If the configuration token ``HOST_BIN_SUFFIX`` is set, its value will be
         automatically appended to ``HOST_PROGRAM``. If ``HOST_PROGRAM`` already
         ends with ``HOST_BIN_SUFFIX``, ``HOST_PROGRAM`` will remain unchanged.
         """, 'binaries'),
 
-    'NO_DIST_INSTALL': (bool, bool, False,
+    'NO_DIST_INSTALL': (bool, bool,
         """Disable installing certain files into the distribution directory.
 
         If present, some files defined by other variables won't be
         distributed/shipped with the produced build.
         """, None),
 
     # IDL Generation.
-    'XPIDL_SOURCES': (StrictOrderingOnAppendList, list, [],
+    'XPIDL_SOURCES': (StrictOrderingOnAppendList, list,
         """XPCOM Interface Definition Files (xpidl).
 
         This is a list of files that define XPCOM interface definitions.
         Entries must be files that exist. Entries are almost certainly ``.idl``
         files.
         """, 'libs'),
 
-    'XPIDL_MODULE': (unicode, unicode, "",
+    'XPIDL_MODULE': (unicode, unicode,
         """XPCOM Interface Definition Module Name.
 
         This is the name of the ``.xpt`` file that is created by linking
         ``XPIDL_SOURCES`` together. If unspecified, it defaults to be the same
         as ``MODULE``.
         """, None),
 
-    'IPDL_SOURCES': (StrictOrderingOnAppendList, list, [],
+    'IPDL_SOURCES': (StrictOrderingOnAppendList, list,
         """IPDL source files.
 
         These are ``.ipdl`` files that will be parsed and converted to
         ``.cpp`` files.
         """, 'export'),
 
-    'WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
+    'WEBIDL_FILES': (StrictOrderingOnAppendList, list,
         """WebIDL source files.
 
         These will be parsed and converted to ``.cpp`` and ``.h`` files.
         """, 'export'),
 
-    'GENERATED_EVENTS_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
+    'GENERATED_EVENTS_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
         """WebIDL source files for generated events.
 
         These will be parsed and converted to ``.cpp`` and ``.h`` files.
         """, 'export'),
 
-    'TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
+    'TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
          """Test WebIDL source files.
 
          These will be parsed and converted to ``.cpp`` and ``.h`` files
          if tests are enabled.
          """, 'export'),
 
-    'GENERATED_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
+    'GENERATED_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
          """Generated WebIDL source files.
 
          These will be generated from some other files.
          """, 'export'),
 
-    'PREPROCESSED_TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
+    'PREPROCESSED_TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
          """Preprocessed test WebIDL source files.
 
          These will be preprocessed, then parsed and converted to .cpp
          and ``.h`` files if tests are enabled.
          """, 'export'),
 
-    'PREPROCESSED_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
+    'PREPROCESSED_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
          """Preprocessed WebIDL source files.
 
          These will be preprocessed before being parsed and converted.
          """, 'export'),
 
     # Test declaration.
-    'A11Y_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'A11Y_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining a11y tests.
         """, None),
 
-    'BROWSER_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'BROWSER_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining browser chrome tests.
         """, None),
 
-    'METRO_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'METRO_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining metro browser chrome tests.
         """, None),
 
-    'MOCHITEST_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'MOCHITEST_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining mochitest chrome tests.
         """, None),
 
-    'MOCHITEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'MOCHITEST_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining mochitest tests.
         """, None),
 
-    'MOCHITEST_WEBAPPRT_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'MOCHITEST_WEBAPPRT_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining webapprt mochitest chrome tests.
         """, None),
 
-    'WEBRTC_SIGNALLING_TEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'WEBRTC_SIGNALLING_TEST_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining WebRTC signalling tests.
         """, None),
 
-    'XPCSHELL_TESTS_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+    'XPCSHELL_TESTS_MANIFESTS': (StrictOrderingOnAppendList, list,
         """List of manifest files defining xpcshell tests.
         """, None),
 
     # The following variables are used to control the target of installed files.
-    'XPI_NAME': (unicode, unicode, "",
+    'XPI_NAME': (unicode, unicode,
         """The name of an extension XPI to generate.
 
         When this variable is present, the results of this directory will end up
         being packaged into an extension instead of the main dist/bin results.
         """, 'libs'),
 
-    'DIST_SUBDIR': (unicode, unicode, "",
+    'DIST_SUBDIR': (unicode, unicode,
         """The name of an alternate directory to install files to.
 
         When this variable is present, the results of this directory will end up
         being placed in the $(DIST_SUBDIR) subdirectory of where it would
         otherwise be placed.
         """, 'libs'),
 
-    'FINAL_TARGET': (unicode, unicode, compute_final_target,
+    'FINAL_TARGET': (FinalTargetValue, unicode,
         """The name of the directory to install targets to.
 
         The directory is relative to the top of the object directory. The
         default value is dependent on the values of XPI_NAME and DIST_SUBDIR. If
         neither are present, the result is dist/bin. If XPI_NAME is present, the
         result is dist/xpi-stage/$(XPI_NAME). If DIST_SUBDIR is present, then
         the $(DIST_SUBDIR) directory of the otherwise default value is used.
         """, 'libs'),
--- a/python/mozbuild/mozbuild/sphinx.py
+++ b/python/mozbuild/mozbuild/sphinx.py
@@ -44,34 +44,33 @@ def function_reference(f, attr, args, do
     ])
 
     lines.extend(docstring[1:])
     lines.append('')
 
     return lines
 
 
-def variable_reference(v, st_type, in_type, default, doc, tier):
+def variable_reference(v, st_type, in_type, doc, tier):
     lines = [
         v,
         '-' * len(v),
         '',
     ]
 
     docstring = prepare_docstring(doc)
 
     lines.extend([
         docstring[0],
         '',
     ])
 
     lines.extend([
         ':Storage Type: ``%s``' % st_type.__name__,
         ':Input Type: ``%s``' % in_type.__name__,
-        ':Default Value: %s' % default,
         '',
     ])
 
     lines.extend(docstring[1:])
     lines.append('')
 
     return lines
 
--- a/python/mozbuild/mozbuild/test/frontend/data/inheriting-variables/bar/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/inheriting-variables/bar/moz.build
@@ -1,7 +1,5 @@
 # -*- 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/.
-
-XPIDL_MODULE = 'bazbar'
--- a/python/mozbuild/mozbuild/test/frontend/test_namespaces.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_namespaces.py
@@ -71,20 +71,33 @@ class TestGlobalNamespace(unittest.TestC
     def test_allow_all_writes(self):
         ns = GlobalNamespace(allowed_variables=VARIABLES)
 
         with ns.allow_all_writes() as d:
             d['foo'] = True
             self.assertTrue(d['foo'])
 
         with self.assertRaises(KeyError) as ke:
-            ns['foo'] = False
+            ns['bar'] = False
 
         self.assertEqual(ke.exception.args[1], 'set_unknown')
 
+        ns['DIRS'] = []
+        with self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden') as ke:
+            ns['DIRS'] = []
+
+        with ns.allow_all_writes() as d:
+            d['DIST_SUBDIR'] = 'foo'
+
+        self.assertEqual(ns['DIST_SUBDIR'], 'foo')
+        ns['DIST_SUBDIR'] = 'bar'
+        self.assertEqual(ns['DIST_SUBDIR'], 'bar')
+        with self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden') as ke:
+            ns['DIST_SUBDIR'] = 'baz'
+
         self.assertTrue(d['foo'])
 
     def test_key_checking(self):
         # Checking for existence of a key should not populate the key if it
         # doesn't exist.
         g = GlobalNamespace(allowed_variables=VARIABLES)
 
         self.assertFalse('DIRS' in g)
--- a/python/mozbuild/mozbuild/test/frontend/test_reader.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_reader.py
@@ -257,12 +257,12 @@ class TestBuildReader(unittest.TestCase)
         reader = self.reader('inheriting-variables')
 
         sandboxes = list(reader.read_topsrcdir())
 
         self.assertEqual(len(sandboxes), 4)
         self.assertEqual([sandbox['RELATIVEDIR'] for sandbox in sandboxes],
             ['', 'foo', 'foo/baz', 'bar'])
         self.assertEqual([sandbox['XPIDL_MODULE'] for sandbox in sandboxes],
-            ['foobar', 'foobar', 'foobar', 'bazbar'])
+            ['foobar', 'foobar', 'foobar', 'foobar'])
 
 if __name__ == '__main__':
     main()
--- a/python/mozbuild/mozbuild/test/frontend/test_sandbox.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_sandbox.py
@@ -141,19 +141,19 @@ class TestSandbox(unittest.TestCase):
 
         self.assertIsInstance(se.exception, SandboxExecutionError)
         self.assertEqual(se.exception.exc_type, ImportError)
 
     def test_exec_source_multiple(self):
         sandbox = self.sandbox()
 
         sandbox.exec_source('DIRS = ["foo"]', 'foo.py')
-        sandbox.exec_source('DIRS = ["bar"]', 'foo.py')
+        sandbox.exec_source('DIRS += ["bar"]', 'foo.py')
 
-        self.assertEqual(sandbox['DIRS'], ['bar'])
+        self.assertEqual(sandbox['DIRS'], ['foo', 'bar'])
 
     def test_exec_source_illegal_key_set(self):
         sandbox = self.sandbox()
 
         with self.assertRaises(SandboxExecutionError) as se:
             sandbox.exec_source('ILLEGAL = True', 'foo.py')
 
         e = se.exception
--- a/python/mozbuild/mozbuild/test/frontend/test_sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_sandbox_symbols.py
@@ -31,17 +31,17 @@ class TestSymbols(unittest.TestCase):
 
         self.assertGreater(len(lines), 0)
         self.assertGreater(len(lines[0].strip()), 0)
 
         # Last line should be empty.
         self.assertEqual(lines[-1].strip(), '')
 
     def test_documentation_formatting(self):
-        for typ, inp, default, doc, tier in VARIABLES.values():
+        for typ, inp, doc, tier in VARIABLES.values():
             self._verify_doc(doc)
 
         for attr, args, doc in FUNCTIONS.values():
             self._verify_doc(doc)
 
         for typ, doc in SPECIAL_VARIABLES.values():
             self._verify_doc(doc)
 
--- a/python/mozbuild/mozbuild/test/test_util.py
+++ b/python/mozbuild/mozbuild/test/test_util.py
@@ -17,16 +17,17 @@ from mozunit import (
 
 from mozbuild.util import (
     FileAvoidWrite,
     hash_file,
     resolve_target_to_make,
     MozbuildDeletionError,
     HierarchicalStringList,
     StrictOrderingOnAppendList,
+    StrictOrderingOnAppendListWithFlagsFactory,
     UnsortedError,
 )
 
 if sys.version_info[0] == 3:
     str_type = 'str'
 else:
     str_type = 'unicode'
 
@@ -280,10 +281,44 @@ class TestStrictOrderingOnAppendList(uni
         self.assertIsInstance(l, StrictOrderingOnAppendList)
 
         with self.assertRaises(UnsortedError):
             l += ['b', 'a']
 
         self.assertEqual(len(l), 2)
 
 
+class TestStrictOrderingOnAppendListWithFlagsFactory(unittest.TestCase):
+    def test_strict_ordering_on_append_list_with_flags_factory(self):
+        cls = StrictOrderingOnAppendListWithFlagsFactory({
+            'foo': bool,
+            'bar': int,
+        })
+
+        l = cls()
+        l += ['a', 'b']
+
+        with self.assertRaises(Exception):
+            l['a'] = 'foo'
+
+        with self.assertRaises(Exception):
+            c = l['c']
+
+        self.assertEqual(l['a'].foo, False)
+        l['a'].foo = True
+        self.assertEqual(l['a'].foo, True)
+
+        with self.assertRaises(TypeError):
+            l['a'].bar = 'bar'
+
+        self.assertEqual(l['a'].bar, 0)
+        l['a'].bar = 42
+        self.assertEqual(l['a'].bar, 42)
+
+        l['b'].foo = True
+        self.assertEqual(l['b'].foo, True)
+
+        with self.assertRaises(AttributeError):
+            l['b'].baz = False
+
+
 if __name__ == '__main__':
     main()
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -296,16 +296,84 @@ class StrictOrderingOnAppendList(list):
         list.__iadd__(self, other)
 
         return self
 
 
 class MozbuildDeletionError(Exception):
     pass
 
+
+def StrictOrderingOnAppendListWithFlagsFactory(flags):
+    """Returns a StrictOrderingOnAppendList-like object, with optional
+    flags on each item.
+
+    The flags are defined in the dict given as argument, where keys are
+    the flag names, and values the type used for the value of that flag.
+
+    Example:
+        FooList = StrictOrderingOnAppendListWithFlagsFactory({
+            'foo': bool, 'bar': unicode
+        })
+        foo = FooList(['a', 'b', 'c'])
+        foo['a'].foo = True
+        foo['b'].bar = 'bar'
+    """
+
+    assert isinstance(flags, dict)
+    assert all(isinstance(v, type) for v in flags.values())
+
+    class Flags(object):
+        __slots__ = flags.keys()
+        _flags = flags
+
+        def __getattr__(self, name):
+            if name not in self.__slots__:
+                raise AttributeError("'%s' object has no attribute '%s'" %
+                                     (self.__class__.__name__, name))
+            try:
+                return object.__getattr__(self, name)
+            except AttributeError:
+                value = self._flags[name]()
+                self.__setattr__(name, value)
+                return value
+
+        def __setattr__(self, name, value):
+            if name not in self.__slots__:
+                raise AttributeError("'%s' object has no attribute '%s'" %
+                                     (self.__class__.__name__, name))
+            if not isinstance(value, self._flags[name]):
+                raise TypeError("'%s' attribute of class '%s' must be '%s'" %
+                                (name, self.__class__.__name__,
+                                 self._flags[name].__name__))
+            return object.__setattr__(self, name, value)
+
+        def __delattr__(self, name):
+            raise MozbuildDeletionError('Unable to delete attributes for this object')
+
+    class StrictOrderingOnAppendListWithFlags(StrictOrderingOnAppendList):
+        def __init__(self, iterable=[]):
+            StrictOrderingOnAppendList.__init__(self, iterable)
+            self._flags_type = Flags
+            self._flags = dict()
+
+        def __getitem__(self, name):
+            if name not in self._flags:
+                if name not in self:
+                    raise KeyError("'%s'" % name)
+                self._flags[name] = self._flags_type()
+            return self._flags[name]
+
+        def __setitem__(self, name, value):
+            raise TypeError("'%s' object does not support item assignment" %
+                            self.__class__.__name__)
+
+    return StrictOrderingOnAppendListWithFlags
+
+
 class HierarchicalStringList(object):
     """A hierarchy of lists of strings.
 
     Each instance of this object contains a list of strings, which can be set or
     appended to. A sub-level of the hierarchy is also an instance of this class,
     can be added by appending to an attribute instead.
 
     For example, the moz.build variable EXPORTS is an instance of this class. We
--- a/toolkit/components/diskspacewatcher/moz.build
+++ b/toolkit/components/diskspacewatcher/moz.build
@@ -8,17 +8,16 @@ XPIDL_SOURCES += [
     'nsIDiskSpaceWatcher.idl',
 ]
 
 EXPORTS += [
     'DiskSpaceWatcher.h'
 ]
 
 XPIDL_MODULE = 'diskspacewatcher'
-XPIDL_MODULE = 'toolkitcomps'
 
 SOURCES = [
     'DiskSpaceWatcher.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/xpcom/base/Makefile.in
+++ b/xpcom/base/Makefile.in
@@ -1,17 +1,15 @@
 #
 # 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/.
 
 MOZILLA_INTERNAL_API =1
 
-NO_PROFILE_GUIDED_OPTIMIZE = nsDebugImpl.cpp
-
 INSTALL_TARGETS += errorlist
 errorlist_FILES := \
   ErrorListCDefines.h \
   ErrorListCxxDefines.h \
   $(NULL)
 errorlist_DEST = $(DIST)/include
 errorlist_TARGET := export
 
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -89,17 +89,16 @@ if CONFIG['OS_ARCH'] == 'WINNT':
 UNIFIED_SOURCES += [
     'AvailableMemoryTracker.cpp',
     'ClearOnShutdown.cpp',
     'CycleCollectedJSRuntime.cpp',
     'Debug.cpp',
     'nsConsoleMessage.cpp',
     'nsConsoleService.cpp',
     'nsCycleCollector.cpp',
-    'nsDebugImpl.cpp',
     'nsErrorService.cpp',
     'nsGZFileWriter.cpp',
     'nsInterfaceRequestorAgg.cpp',
     'nsMemoryImpl.cpp',
     'nsMemoryInfoDumper.cpp',
     'nsMemoryReporterManager.cpp',
     'nsMessageLoop.cpp',
     'nsSecurityConsoleMessage.cpp',
@@ -119,15 +118,16 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wi
     SOURCES += [
         'nsCrashOnException.cpp',
     ]
 
 UNIFIED_SOURCES += [
     'nsErrorAssertsC.c',
 ]
 
-
+SOURCES += ['nsDebugImpl.cpp']
+SOURCES['nsDebugImpl.cpp'].no_pgo = True
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xpcom_core'
--- a/xpcom/reflect/xptcall/src/md/unix/Makefile.in
+++ b/xpcom/reflect/xptcall/src/md/unix/Makefile.in
@@ -1,28 +1,15 @@
 #
 # 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/.
 
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-
 MOZILLA_INTERNAL_API = 1
 
-#
-# The default is this buildable, but non-functioning code.
-#
-ifeq ($(OS_ARCH),SunOS)
-ifneq (86,$(findstring 86,$(OS_TEST)))
-# disable PGO for this directory with Sun Studio on SPARC because
-# compiling with xprofile=collect will insert code into nsXPTCStubBase::Stub##n
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-endif
-endif
-
 ######################################################################
 # ARM
 ######################################################################
 #
 # Linux/ARM
 #
 ifeq ($(OS_ARCH),Linux)
 ifneq (,$(filter arm% sa110,$(OS_TEST)))
--- a/xpcom/reflect/xptcall/src/md/unix/moz.build
+++ b/xpcom/reflect/xptcall/src/md/unix/moz.build
@@ -321,8 +321,10 @@ if CONFIG['OS_ARCH'] == 'Linux':
         ]
     elif CONFIG['OS_TEST'] == 's390x':
         SOURCES += [
             'xptcinvoke_linux_s390x.cpp',
             'xptcstubs_linux_s390x.cpp',
         ]
 
 FINAL_LIBRARY = 'xpcom_core'
+
+NO_PGO = True
--- a/xpcom/reflect/xptcall/src/md/win32/Makefile.in
+++ b/xpcom/reflect/xptcall/src/md/win32/Makefile.in
@@ -2,19 +2,11 @@
 # 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/.
 
 MOZILLA_INTERNAL_API = 1
 
 LOCAL_INCLUDES += -I$(srcdir)/../../../../xptinfo/src
 
-
-ifneq ($(TARGET_CPU),x86_64)
-ifndef GNU_CXX
-# FIXME: bug 413019
-NO_PROFILE_GUIDED_OPTIMIZE = 1
-endif #!GNU_CXX
-endif #!x86_64
-
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES	+= -I$(srcdir)/../..
--- a/xpcom/reflect/xptcall/src/md/win32/moz.build
+++ b/xpcom/reflect/xptcall/src/md/win32/moz.build
@@ -30,8 +30,13 @@ else:
         ]
     else:
         SOURCES += [
             'xptcinvoke.cpp',
             'xptcstubs.cpp',
         ]
 
 FINAL_LIBRARY = 'xpcom_core'
+
+if CONFIG['TARGET_CPU'] != 'x86_64':
+    if not CONFIG['GNU_CXX']:
+        # FIXME: bug 413019
+        NO_PGO = True