☠☠ backed out by f2e06bf4ba8e ☠ ☠ | |
author | Steve Fink <sfink@mozilla.com> |
Fri, 20 Jul 2018 18:36:20 -0700 | |
changeset 441543 | c7b32ffa822e353b5479b6224194e3cdfd135e65 |
parent 441542 | a188327354ab83702eb9c2fec439f3a7cc019883 |
child 441544 | c22b643cdf5168be413948a2437584426bfd8c06 |
push id | 34867 |
push user | shindli@mozilla.com |
push date | Wed, 17 Oct 2018 00:55:53 +0000 |
treeherder | mozilla-central@778427bb6353 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jonco |
bugs | 1321014 |
milestone | 64.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
|
--- a/browser/config/mozconfigs/linux64/hazards +++ b/browser/config/mozconfigs/linux64/hazards @@ -31,15 +31,18 @@ mk_add_options MOZ_OBJDIR=obj-analyzed ac_add_options --enable-debug ac_add_options --enable-tests ac_add_options --enable-optimize ac_add_options --with-compiler-wrapper=$TOOLTOOL_DIR/sixgill/usr/libexec/sixgill/scripts/wrap_gcc/basecc ac_add_options --without-ccache ac_add_options --disable-replace-malloc -CFLAGS="$CFLAGS -Wno-attributes" -CPPFLAGS="$CPPFLAGS -Wno-attributes" -CXXFLAGS="$CXXFLAGS -Wno-attributes" +# -Wattributes is very verbose due to attributes being ignored on template +# instantiations. -Wignored-attributes is very verbose due to attributes being +# ignored on template parameters. +CFLAGS="$CFLAGS -Wno-attributes -Wno-ignored-attributes" +CPPFLAGS="$CPPFLAGS -Wno-attributes -Wno-ignored-attributes" +CXXFLAGS="$CXXFLAGS -Wno-attributes -Wno-ignored-attributes" NODEJS="$TOOLTOOL_DIR/node/bin/node" . "$topsrcdir/build/mozconfig.common.override"
--- a/js/public/GCAnnotations.h +++ b/js/public/GCAnnotations.h @@ -10,25 +10,28 @@ // Set of annotations for the rooting hazard analysis, used to categorize types // and functions. #ifdef XGILL_PLUGIN // Mark a type as being a GC thing (eg js::gc::Cell has this annotation). # define JS_HAZ_GC_THING __attribute__((annotate("GC Thing"))) // Mark a type as holding a pointer to a GC thing (eg JS::Value has this -// annotation.) +// annotation.) "Inherited" by templatized types with +// MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS. # define JS_HAZ_GC_POINTER __attribute__((annotate("GC Pointer"))) // Mark a type as a rooted pointer, suitable for use on the stack (eg all -// Rooted<T> instantiations should have this.) +// Rooted<T> instantiations should have this.) "Inherited" by templatized types with +// MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS. # define JS_HAZ_ROOTED __attribute__((annotate("Rooted Pointer"))) // Mark a type as something that should not be held live across a GC, but which -// is not itself a GC pointer. +// is not itself a GC pointer. Note that this property is *not* inherited by +// templatized types with MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS. # define JS_HAZ_GC_INVALIDATED __attribute__((annotate("Invalidated by GC"))) // Mark a class as a base class of rooted types, eg CustomAutoRooter. All // descendants of this class will be considered rooted, though classes that // merely contain these as a field member will not be. "Inherited" by // templatized types with MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS # define JS_HAZ_ROOTED_BASE __attribute__((annotate("Rooted Base")))
--- a/js/public/StableStringChars.h +++ b/js/public/StableStringChars.h @@ -51,17 +51,17 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Auto * When copying string char, use this many bytes of inline storage. This is * chosen to allow the inline string types to be copied without allocating. * This is asserted in AutoStableStringChars::allocOwnChars. */ static const size_t InlineCapacity = 24; /* Ensure the string is kept alive while we're using its chars. */ Rooted<JSString*> s_; - MOZ_INIT_OUTSIDE_CTOR union { + union MOZ_INIT_OUTSIDE_CTOR { const char16_t* twoByteChars_; const Latin1Char* latin1Chars_; }; mozilla::Maybe<js::Vector<uint8_t, InlineCapacity>> ownChars_; enum State { Uninitialized, Latin1, TwoByte }; State state_; public:
--- a/js/public/Utility.h +++ b/js/public/Utility.h @@ -506,17 +506,17 @@ static inline void js_free(void* p) * JS_DECLARE_NEW_METHODS (see js::MallocProvider for an example). * * Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS, * or the build will break. */ #define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS) \ template <class T, typename... Args> \ QUALIFIERS T * \ - NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \ + MOZ_HEAP_ALLOCATOR NEWNAME(Args&&... args) { \ void* memory = ALLOCATOR(sizeof(T)); \ return MOZ_LIKELY(memory) \ ? new(memory) T(std::forward<Args>(args)...) \ : nullptr; \ } /* * Given a class which should provide 'make' methods, add @@ -526,17 +526,17 @@ static inline void js_free(void* p) * ownership of the created object. * * Note: Do not add a ; at the end of a use of JS_DECLARE_MAKE_METHODS, * or the build will break. */ #define JS_DECLARE_MAKE_METHODS(MAKENAME, NEWNAME, QUALIFIERS)\ template <class T, typename... Args> \ QUALIFIERS mozilla::UniquePtr<T, JS::DeletePolicy<T>> \ - MAKENAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \ + MOZ_HEAP_ALLOCATOR MAKENAME(Args&&... args) { \ T* ptr = NEWNAME<T>(std::forward<Args>(args)...); \ return mozilla::UniquePtr<T, JS::DeletePolicy<T>>(ptr); \ } JS_DECLARE_NEW_METHODS(js_new, js_malloc, static MOZ_ALWAYS_INLINE) namespace js {
--- a/js/public/Value.h +++ b/js/public/Value.h @@ -311,17 +311,17 @@ CanonicalizeNaN(double d) * that toString, toObject, toSymbol will return an invalid pointer (because * some high bits will be set) when called on a Value with a different type * tag. * * - On 32-bit platforms,when unboxing an object/string/symbol Value, we use a * conditional move (not speculated) to zero the payload register if the type * doesn't match. */ -union MOZ_NON_PARAM alignas(8) Value +union alignas(8) Value { private: uint64_t asBits_; double asDouble_; #if defined(JS_PUNBOX64) && !defined(_WIN64) // MSVC doesn't pack these correctly :-( struct { @@ -924,17 +924,17 @@ union MOZ_NON_PARAM alignas(8) Value MOZ_ASSERT((((uintptr_t)cell) >> JSVAL_TAG_SHIFT) == 0); #endif asBits_ = bitsFromTagAndPayload(JSVAL_TAG_PRIVATE_GCTHING, PayloadType(cell)); } bool isPrivateGCThing() const { return toTag() == JSVAL_TAG_PRIVATE_GCTHING; } -} JS_HAZ_GC_POINTER; +} JS_HAZ_GC_POINTER MOZ_NON_PARAM; static_assert(sizeof(Value) == 8, "Value size must leave three tag bits, be a binary power, and " "is ubiquitously depended upon everywhere"); inline bool IsOptimizedPlaceholderMagicValue(const Value& v) {
--- a/js/src/devtools/rootAnalysis/computeGCTypes.js +++ b/js/src/devtools/rootAnalysis/computeGCTypes.js @@ -6,21 +6,23 @@ loadRelativeToScript('utility.js'); loadRelativeToScript('annotations.js'); var gcTypes_filename = scriptArgs[0] || "gcTypes.txt"; var typeInfo_filename = scriptArgs[1] || "typeInfo.txt"; var typeInfo = { 'GCPointers': [], 'GCThings': [], + 'GCInvalidated': [], 'NonGCTypes': {}, // unused 'NonGCPointers': {}, 'RootedGCThings': {}, 'RootedPointers': {}, 'RootedBases': {'JS::AutoGCRooter': true}, + 'InheritFromTemplateArgs': {}, // RAII types within which we should assume GC is suppressed, eg // AutoSuppressGC. 'GCSuppressors': {}, }; var gDescriptors = new Map; // Map from descriptor string => Set of typeName @@ -39,27 +41,29 @@ function processCSU(csu, body) { for (let { 'Name': [ annType, tag ] } of (body.Annotation || [])) { if (annType != 'annotate') continue; if (tag == 'GC Pointer') typeInfo.GCPointers.push(csu); else if (tag == 'Invalidated by GC') - typeInfo.GCPointers.push(csu); + typeInfo.GCInvalidated.push(csu); else if (tag == 'GC Thing') typeInfo.GCThings.push(csu); else if (tag == 'Suppressed GC Pointer') typeInfo.NonGCPointers[csu] = true; else if (tag == 'Rooted Pointer') typeInfo.RootedPointers[csu] = true; else if (tag == 'Rooted Base') typeInfo.RootedBases[csu] = true; else if (tag == 'Suppress GC') typeInfo.GCSuppressors[csu] = true; + else if (tag == 'moz_inherit_type_annotations_from_template_args') + typeInfo.InheritFromTemplateArgs[csu] = true; } for (let { 'Base': base } of (body.CSUBaseClass || [])) addBaseClass(csu, base); for (let field of (body.DataField || [])) { var type = field.Field.Type; var fieldName = field.Field.Name[0]; @@ -134,16 +138,57 @@ for (const typename of extraRootedPointe typeInfo.RootedPointers[typename] = true; // Now that we have the whole hierarchy set up, add all the types and propagate // info. for (const csu of typeInfo.GCThings) addGCType(csu); for (const csu of typeInfo.GCPointers) addGCPointer(csu); +for (const csu of typeInfo.GCInvalidated) + addGCPointer(csu); + +// GC Thing and GC Pointer annotations can be inherited from template args if +// this annotation is used. Think of Maybe<T> for example: Maybe<JSObject*> has +// the same GC rules as JSObject*. But this needs to be done in a conservative +// direction: Maybe<AutoSuppressGC> should not be regarding as suppressing GC +// (because it might still be None). +// +// Note that there is an order-dependence here that is being mostly ignored (eg +// Maybe<Maybe<Cell*>> -- if that is processed before Maybe<Cell*> is +// processed, we won't get the right answer). We'll at least sort by string +// length to make it hard to hit that case. +var inheritors = Object.keys(typeInfo.InheritFromTemplateArgs).sort((a, b) => a.length - b.length); +for (const csu of inheritors) { + // Unfortunately, we just have a string type name, not the full structure + // of a templatized type, so we will have to resort to loose (buggy) + // pattern matching. + // + // Currently, the simplest ways I know of to break this are: + // + // foo<T>::bar<U> + // foo<bar<T,U>> + // + const [_, params_str] = csu.match(/<(.*)>/); + for (let param of params_str.split(",")) { + param = param.replace(/^\s+/, '') + param = param.replace(/\s+$/, '') + const pieces = param.split("*"); + const core_type = pieces[0]; + const ptrdness = pieces.length - 1; + if (ptrdness > 1) + continue; + const paramDesc = 'template-param-' + param; + const why = '(inherited annotations from ' + param + ')'; + if (typeInfo.GCThings.indexOf(core_type) != -1) + markGCType(csu, paramDesc, why, ptrdness, 0, ""); + if (typeInfo.GCPointers.indexOf(core_type) != -1) + markGCType(csu, paramDesc, why, ptrdness + 1, 0, ""); + } +} // Everything that inherits from a "Rooted Base" is considered to be rooted. // This is for things like CustomAutoRooter and its subclasses. var basework = Object.keys(typeInfo.RootedBases); while (basework.length) { const base = basework.pop(); typeInfo.RootedPointers[base] = true; if (base in subClasses)
new file mode 100644 --- /dev/null +++ b/js/src/devtools/rootAnalysis/mozconfig.haz @@ -0,0 +1,46 @@ +# This mozconfig is used when compiling the browser for the rooting hazard +# analysis build (labeled H on treeherder). See +# https://wiki.mozilla.org/Javascript:SpiderMonkey:ExactStackRooting + +# Do NOT include build/unix/mozconfig.linux because it points directly at the +# tooltool-installed gcc, and the analysis works by wrapping the gcc invocation +# with a script that invokes the real gcc with -fplugin and its configuration +# directives. Instead, duplicate the contents of that mozconfig here: + +MOZ_HAZARD=1 + +# Skip as many non-compile steps as we can. +MOZ_AUTOMATION_BUILD_SYMBOLS=0 +MOZ_AUTOMATION_L10N_CHECK=0 +MOZ_AUTOMATION_PACKAGE=0 +MOZ_AUTOMATION_PACKAGE_TESTS=0 +MOZ_AUTOMATION_UPLOAD=0 + +ac_add_options --enable-js-shell + +# The objdir must be at a known location so its path can be stripped from the +# filenames stored by the analysis +mk_add_options MOZ_OBJDIR=obj-analyzed + +export LLVM_CONFIG=$TOOLTOOL_DIR/clang/bin/llvm-config +export CBINDGEN="${TOOLTOOL_DIR}/cbindgen/cbindgen" + +# The configuration options are chosen to compile the most code +# (--enable-debug, --enable-tests) in the trickiest way possible +# (--enable-optimize) to maximize the chance of seeing tricky static orderings. +ac_add_options --enable-debug +ac_add_options --enable-tests +ac_add_options --enable-optimize +ac_add_options --with-compiler-wrapper=$TOOLTOOL_DIR/sixgill/usr/libexec/sixgill/scripts/wrap_gcc/basecc +ac_add_options --without-ccache + +ac_add_options --disable-replace-malloc + +# -Wattributes is very verbose due to attributes being ignored on template +# instantiations. -Wignored-attributes is very verbose due to attributes being +# ignored on template parameters. +CFLAGS="$CFLAGS -Wno-attributes -Wno-ignored-attributes" +CPPFLAGS="$CPPFLAGS -Wno-attributes -Wno-ignored-attributes" +CXXFLAGS="$CXXFLAGS -Wno-attributes -Wno-ignored-attributes" + +NODEJS="$TOOLTOOL_DIR/node/bin/node"
--- a/js/src/devtools/rootAnalysis/t/hazards/source.cpp +++ b/js/src/devtools/rootAnalysis/t/hazards/source.cpp @@ -1,12 +1,17 @@ #define ANNOTATE(property) __attribute__((annotate(property))) struct Cell { int f; } ANNOTATE("GC Thing"); +template<typename T, typename U> +struct UntypedContainer { + char data[sizeof(T) + sizeof(U)]; +} ANNOTATE("moz_inherit_type_annotations_from_template_args"); + struct RootedCell { RootedCell(Cell*) {} } ANNOTATE("Rooted Pointer"); class AutoSuppressGC_Base { public: AutoSuppressGC_Base() {} ~AutoSuppressGC_Base() {} } ANNOTATE("Suppress GC"); @@ -52,16 +57,22 @@ struct GCInDestructor { ~GCInDestructor() { invisible(); asm(""); *xp = 4; GC(); } }; +template <typename T> +void +usecontainer(T* value) { + if (value) asm(""); +} + Cell* f() { GCInDestructor kaboom; Cell cell; Cell* cell1 = &cell; Cell* cell2 = &cell; @@ -80,16 +91,33 @@ f() // Old bug: it would look from the first AutoSuppressGC constructor it // found to the last destructor. This statement *should* have no effect. AutoSuppressGC nogc; } usecell(cell3); Cell* cell5 = &cell; usecell(cell5); + { + // Templatized container that inherits attributes from Cell*, should + // report a hazard. + UntypedContainer<int, Cell*> container1; + usecontainer(&container1); + GC(); + usecontainer(&container1); + } + + { + // As above, but with a non-GC type. + UntypedContainer<int, double> container2; + usecontainer(&container2); + GC(); + usecontainer(&container2); + } + // Hazard in return value due to ~GCInDestructor Cell* cell6 = &cell; return cell6; } Cell* copy_and_gc(Cell* src) { GC();
--- a/js/src/devtools/rootAnalysis/t/hazards/test.py +++ b/js/src/devtools/rootAnalysis/t/hazards/test.py @@ -30,16 +30,19 @@ assert(len(set(haz.function for haz in h # Check that the correct GC call is reported for each hazard. (cell3 has a # hazard from two different GC calls; it doesn't really matter which is # reported.) assert(hazmap['cell2'].GCFunction == 'void halfSuppressedFunction()') assert(hazmap['cell3'].GCFunction in ( 'void halfSuppressedFunction()', 'void unsuppressedFunction()')) assert(hazmap['<returnvalue>'].GCFunction == 'void GCInDestructor::~GCInDestructor()') +assert('container1' in hazmap); +assert('container2' not in hazmap); + # Type names are handy to have in the report. assert(hazmap['cell2'].type == 'Cell*') assert(hazmap['<returnvalue>'].type == 'Cell*') # loopy hazards. See comments in source. assert('haz1' not in hazmap) assert('haz2' not in hazmap) assert('haz3' in hazmap)
--- a/layout/base/AccessibleCaret.h +++ b/layout/base/AccessibleCaret.h @@ -209,17 +209,17 @@ protected: // Member variables Appearance mAppearance = Appearance::None; // AccessibleCaretManager owns us by a UniquePtr. When it's terminated by // AccessibleCaretEventHub::Terminate() which is called in // PresShell::Destroy(), it frees us automatically. No need to worry if we // outlive mPresShell. - nsIPresShell* MOZ_NON_OWNING_REF const mPresShell = nullptr; + nsIPresShell* const MOZ_NON_OWNING_REF mPresShell = nullptr; RefPtr<dom::AnonymousContent> mCaretElementHolder; // mImaginaryCaretRect is relative to root frame. nsRect mImaginaryCaretRect; // Cache current zoom level to determine whether position is changed. float mZoomLevel = 0.0f;
--- a/layout/base/gtest/TestAccessibleCaretEventHub.cpp +++ b/layout/base/gtest/TestAccessibleCaretEventHub.cpp @@ -257,23 +257,23 @@ public: ReleaseEventCreator aReleaseEventCreator); // Member variables RefPtr<MockAccessibleCaretEventHub> mHub{new MockAccessibleCaretEventHub()}; }; // class AccessibleCaretEventHubTester TEST_F(AccessibleCaretEventHubTester, TestMousePressReleaseOnNoCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnNoCaret(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressReleaseOnNoCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnNoCaret(CreateTouchStartEvent, CreateTouchEndEvent); } template <typename PressEventCreator, typename ReleaseEventCreator> void AccessibleCaretEventHubTester::TestPressReleaseOnNoCaret( PressEventCreator aPressEventCreator, @@ -291,23 +291,23 @@ AccessibleCaretEventHubTester::TestPress nsEventStatus_eIgnore); HandleEventAndCheckState(aReleaseEventCreator(0, 0), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestMousePressReleaseOnCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnCaret(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressReleaseOnCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnCaret(CreateTouchStartEvent, CreateTouchEndEvent); } template <typename PressEventCreator, typename ReleaseEventCreator> void AccessibleCaretEventHubTester::TestPressReleaseOnCaret( PressEventCreator aPressEventCreator, @@ -335,24 +335,24 @@ AccessibleCaretEventHubTester::TestPress nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(aReleaseEventCreator(0, 0), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eConsumeNoDefault); } TEST_F(AccessibleCaretEventHubTester, TestMousePressMoveReleaseOnNoCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnNoCaret(CreateMousePressEvent, CreateMouseMoveEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressMoveReleaseOnNoCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnNoCaret(CreateTouchStartEvent, CreateTouchMoveEvent, CreateTouchEndEvent); } template <typename PressEventCreator, typename MoveEventCreator, typename ReleaseEventCreator> void @@ -391,24 +391,24 @@ AccessibleCaretEventHubTester::TestPress nsEventStatus_eIgnore); HandleEventAndCheckState(aReleaseEventCreator(x3, y3), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestMousePressMoveReleaseOnCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnCaret(CreateMousePressEvent, CreateMouseMoveEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressMoveReleaseOnCaret) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnCaret(CreateTouchStartEvent, CreateTouchMoveEvent, CreateTouchEndEvent); } template <typename PressEventCreator, typename MoveEventCreator, typename ReleaseEventCreator> void @@ -460,17 +460,17 @@ AccessibleCaretEventHubTester::TestPress HandleEventAndCheckState(aReleaseEventCreator(x3, y3), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eConsumeNoDefault); } TEST_F(AccessibleCaretEventHubTester, TestTouchStartMoveEndOnCaretWithTouchCancelIgnored) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { nscoord x0 = 0, y0 = 0; nscoord x1 = 100, y1 = 100; nscoord x2 = 300, y2 = 300; nscoord x3 = 400, y3 = 400; { InSequence dummy; @@ -519,24 +519,24 @@ MOZ_CAN_RUN_SCRIPT MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(CreateTouchCancelEvent(x3, y3), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore);} TEST_F(AccessibleCaretEventHubTester, TestMouseLongTapWithSelectWordSuccessful) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordSuccessful(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchLongTapWithSelectWordSuccessful) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordSuccessful(CreateTouchStartEvent, CreateTouchEndEvent); } template <typename PressEventCreator, typename ReleaseEventCreator> void AccessibleCaretEventHubTester::TestLongTapWithSelectWordSuccessful( @@ -601,24 +601,24 @@ AccessibleCaretEventHubTester::TestLongT EXPECT_EQ(mHub->GetState(), MockAccessibleCaretEventHub::NoActionState()); HandleEventAndCheckState(aReleaseEventCreator(1, 1), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestMouseLongTapWithSelectWordFailed) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordFailed(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchLongTapWithSelectWordFailed) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordFailed(CreateTouchStartEvent, CreateTouchEndEvent); } template <typename PressEventCreator, typename ReleaseEventCreator> void AccessibleCaretEventHubTester::TestLongTapWithSelectWordFailed( @@ -644,24 +644,24 @@ AccessibleCaretEventHubTester::TestLongT nsEventStatus_eIgnore); HandleEventAndCheckState(aReleaseEventCreator(0, 0), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestTouchEventDrivenAsyncPanZoomScroll) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestEventDrivenAsyncPanZoomScroll(CreateTouchStartEvent, CreateTouchMoveEvent, CreateTouchEndEvent); } TEST_F(AccessibleCaretEventHubTester, TestMouseEventDrivenAsyncPanZoomScroll) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestEventDrivenAsyncPanZoomScroll(CreateMousePressEvent, CreateMouseMoveEvent, CreateMouseReleaseEvent); } template <typename PressEventCreator, typename MoveEventCreator, typename ReleaseEventCreator> void @@ -745,17 +745,18 @@ AccessibleCaretEventHubTester::TestEvent mHub->AsyncPanZoomStopped(); EXPECT_EQ(mHub->GetState(), MockAccessibleCaretEventHub::NoActionState()); HandleEventAndCheckState(aReleaseEventCreator(310, 310), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } -TEST_F(AccessibleCaretEventHubTester, TestAsyncPanZoomScroll) MOZ_CAN_RUN_SCRIPT +TEST_F(AccessibleCaretEventHubTester, TestAsyncPanZoomScroll) +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestAsyncPanZoomScroll(); } void AccessibleCaretEventHubTester::TestAsyncPanZoomScroll() { MockFunction<void(::std::string aCheckPointName)> check; @@ -796,17 +797,17 @@ AccessibleCaretEventHubTester::TestAsync mHub->ScrollPositionChanged(); EXPECT_EQ(mHub->GetState(), MockAccessibleCaretEventHub::ScrollState()); mHub->AsyncPanZoomStopped(); EXPECT_EQ(mHub->GetState(), MockAccessibleCaretEventHub::NoActionState()); } TEST_F(AccessibleCaretEventHubTester, TestAsyncPanZoomScrollStartedThenBlur) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()).Times(0); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnBlur()); } @@ -817,17 +818,17 @@ MOZ_CAN_RUN_SCRIPT mHub->ScrollPositionChanged(); EXPECT_EQ(mHub->GetState(), MockAccessibleCaretEventHub::ScrollState()); mHub->NotifyBlur(true); EXPECT_EQ(mHub->GetState(), MockAccessibleCaretEventHub::NoActionState()); } TEST_F(AccessibleCaretEventHubTester, TestAsyncPanZoomScrollEndedThenBlur) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnBlur()); }
--- a/layout/base/gtest/TestAccessibleCaretManager.cpp +++ b/layout/base/gtest/TestAccessibleCaretManager.cpp @@ -133,17 +133,17 @@ public: } // Member variables MockAccessibleCaretManager mManager; }; // class AccessibleCaretManagerTester TEST_F(AccessibleCaretManagerTester, TestUpdatesInSelectionMode) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Selection)); EXPECT_CALL(mManager, DispatchCaretStateChangedEvent( CaretChangedReason::Updateposition)).Times(3); mManager.UpdateCarets(); @@ -155,17 +155,17 @@ MOZ_CAN_RUN_SCRIPT EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal); mManager.OnScrollPositionChanged(); EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal); EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal); } TEST_F(AccessibleCaretManagerTester, TestSingleTapOnNonEmptyInput) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Cursor)); EXPECT_CALL(mManager, HasNonEmptyTextContent(_)) .WillRepeatedly(Return(true)); MockFunction<void(std::string aCheckPointName)> check; @@ -226,17 +226,17 @@ MOZ_CAN_RUN_SCRIPT EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal); check.Call("reflow2"); mManager.OnScrollPositionChanged(); EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal); } TEST_F(AccessibleCaretManagerTester, TestSingleTapOnEmptyInput) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Cursor)); EXPECT_CALL(mManager, HasNonEmptyTextContent(_)) .WillRepeatedly(Return(false)); MockFunction<void(std::string aCheckPointName)> check; @@ -296,17 +296,18 @@ MOZ_CAN_RUN_SCRIPT mManager.OnReflow(); EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown); check.Call("reflow2"); mManager.OnScrollPositionChanged(); EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown); } -TEST_F(AccessibleCaretManagerTester, TestTypingAtEndOfInput) MOZ_CAN_RUN_SCRIPT +TEST_F(AccessibleCaretManagerTester, TestTypingAtEndOfInput) +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Cursor)); EXPECT_CALL(mManager, HasNonEmptyTextContent(_)) .WillRepeatedly(Return(true)); MockFunction<void(std::string aCheckPointName)> check; @@ -339,17 +340,17 @@ TEST_F(AccessibleCaretManagerTester, Tes nsISelectionListener::NO_REASON); EXPECT_EQ(FirstCaretAppearance(), Appearance::None); mManager.OnScrollPositionChanged(); EXPECT_EQ(FirstCaretAppearance(), Appearance::None); } TEST_F(AccessibleCaretManagerTester, TestScrollInSelectionMode) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Selection)); MockFunction<void(std::string aCheckPointName)> check; { InSequence dummy; @@ -425,17 +426,17 @@ MOZ_CAN_RUN_SCRIPT mManager.OnScrollEnd(); EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal); EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal); check.Call("scrollend2"); } TEST_F(AccessibleCaretManagerTester, TestScrollInSelectionModeWithAlwaysTiltPref) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { // Simulate Firefox Android preference. bool oldPref = StaticPrefs::layout_accessiblecaret_always_tilt(); Preferences::SetBool("layout.accessiblecaret.always_tilt", true); EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Selection)); @@ -532,17 +533,17 @@ MOZ_CAN_RUN_SCRIPT EXPECT_EQ(FirstCaretAppearance(), Appearance::Left); EXPECT_EQ(SecondCaretAppearance(), Appearance::Right); check.Call("scrollend2"); Preferences::SetBool("layout.accessiblecaret.always_tilt", oldPref); } TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeWhenLogicallyVisible) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Cursor)); EXPECT_CALL(mManager, HasNonEmptyTextContent(_)) .WillRepeatedly(Return(true)); MockFunction<void(std::string aCheckPointName)> check; @@ -593,17 +594,17 @@ MOZ_CAN_RUN_SCRIPT check.Call("scrollstart2"); mManager.OnScrollEnd(); EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal); check.Call("scrollend2"); } TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeWhenHidden) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Cursor)); EXPECT_CALL(mManager, HasNonEmptyTextContent(_)) .WillRepeatedly(Return(true)); MockFunction<void(std::string aCheckPointName)> check; @@ -648,17 +649,17 @@ MOZ_CAN_RUN_SCRIPT EXPECT_EQ(FirstCaretAppearance(), Appearance::None); mManager.OnScrollEnd(); EXPECT_EQ(FirstCaretAppearance(), Appearance::None); check.Call("scrollend2"); } TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeOnEmptyContent) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Cursor)); EXPECT_CALL(mManager, HasNonEmptyTextContent(_)) .WillRepeatedly(Return(false)); MockFunction<void(std::string aCheckPointName)> check; @@ -720,17 +721,17 @@ MOZ_CAN_RUN_SCRIPT check.Call("scrollstart3"); mManager.OnScrollEnd(); EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown); check.Call("scrollend3"); } TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeWithCaretShownWhenLongTappingOnEmptyContentPref) -MOZ_CAN_RUN_SCRIPT +MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { // Simulate Firefox Android preference. bool oldPref = StaticPrefs::layout_accessiblecaret_caret_shown_when_long_tapping_on_empty_content(); Preferences::SetBool("layout.accessiblecaret.caret_shown_when_long_tapping_on_empty_content", true); EXPECT_CALL(mManager, GetCaretMode()) .WillRepeatedly(Return(CaretMode::Cursor));
--- a/mfbt/Attributes.h +++ b/mfbt/Attributes.h @@ -531,17 +531,23 @@ * goto target; * MOZ_CASE_ATTRIBUTE case 5: * MOZ_DEFAULT_ATTRIBUTE default: * * The static analyses that are performed by the plugin are as follows: * * MOZ_CAN_RUN_SCRIPT: Applies to functions which can run script. Callers of * this function must also be marked as MOZ_CAN_RUN_SCRIPT, and all refcounted - * arguments must be strongly held in the caller. + * arguments must be strongly held in the caller. Note that MOZ_CAN_RUN_SCRIPT + * should only be applied to function declarations, not definitions. If you + * need to apply it to a definition (eg because both are generated by a macro) + * use MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION. + * MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION: Same as MOZ_CAN_RUN_SCRIPT, but usable on + * a definition. If the declaration is in a header file, users of that header + * file may not see the annotation. * MOZ_CAN_RUN_SCRIPT_BOUNDARY: Applies to functions which need to call * MOZ_CAN_RUN_SCRIPT functions, but should not themselves be considered * MOZ_CAN_RUN_SCRIPT. This is important for some bindings and low level code * which need to opt out of the safety checks performed by MOZ_CAN_RUN_SCRIPT. * MOZ_MUST_OVERRIDE: Applies to all C++ member functions. All immediate * subclasses must provide an exact override of this method; if a subclass * does not override this method, the compiler will emit an error. This * attribute is not limited to virtual methods, so if it is applied to a @@ -709,18 +715,39 @@ * within the calling block using an explicit `return` statement. * Only calls to Constructors, references to local and member variables, * and calls to functions or methods marked as MOZ_MAY_CALL_AFTER_MUST_RETURN * may be made after the MUST_RETURN_FROM_CALLER call. * MOZ_MAY_CALL_AFTER_MUST_RETURN: Applies to function or method declarations. * Calls to these methods may be made in functions after calls a * MOZ_MUST_RETURN_FROM_CALLER function or method. */ -#ifdef MOZ_CLANG_PLUGIN + +// gcc emits a nuisance warning -Wignored-attributes because attributes do not +// affect mangled names, and therefore template arguments do not propagate +// their attributes. It is rare that this would affect anything in practice, +// and most compilers are silent about it. Similarly, -Wattributes complains +// about attributes being ignored during template instantiation. +// +// Be conservative and only suppress the warning when running in a +// configuration where it would be emitted, namely when compiling with the +// XGILL_PLUGIN for the rooting hazard analysis (which runs under gcc.) If we +// end up wanting these attributes in general GCC builds, change this to +// something like +// +// #if defined(__GNUC__) && ! defined(__clang__) +// +#ifdef XGILL_PLUGIN +#pragma GCC diagnostic ignored "-Wignored-attributes" +#pragma GCC diagnostic ignored "-Wattributes" +#endif + +#if defined(MOZ_CLANG_PLUGIN) || defined(XGILL_PLUGIN) # define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script"))) +# define MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION __attribute__((annotate("moz_can_run_script"))) # define MOZ_CAN_RUN_SCRIPT_BOUNDARY __attribute__((annotate("moz_can_run_script_boundary"))) # define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override"))) # define MOZ_STATIC_CLASS __attribute__((annotate("moz_global_class"))) # define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) # define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class"))) # define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class"))) # define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class"))) # define MOZ_TEMPORARY_CLASS __attribute__((annotate("moz_temporary_class"))) @@ -757,26 +784,30 @@ # define MOZ_REQUIRED_BASE_METHOD \ __attribute__((annotate("moz_required_base_method"))) # define MOZ_MUST_RETURN_FROM_CALLER \ __attribute__((annotate("moz_must_return_from_caller"))) # define MOZ_MAY_CALL_AFTER_MUST_RETURN \ __attribute__((annotate("moz_may_call_after_must_return"))) /* * It turns out that clang doesn't like void func() __attribute__ {} without a - * warning, so use pragmas to disable the warning. This code won't work on GCC - * anyways, so the warning is safe to ignore. + * warning, so use pragmas to disable the warning. */ -# define MOZ_HEAP_ALLOCATOR \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((annotate("moz_heap_allocator"))) \ - _Pragma("clang diagnostic pop") +# ifdef __clang__ +# define MOZ_HEAP_ALLOCATOR \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((annotate("moz_heap_allocator"))) \ + _Pragma("clang diagnostic pop") +# else +# define MOZ_HEAP_ALLOCATOR __attribute__((annotate("moz_heap_allocator"))) +# endif #else # define MOZ_CAN_RUN_SCRIPT /* nothing */ +# define MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION /* nothing */ # define MOZ_CAN_RUN_SCRIPT_BOUNDARY /* nothing */ # define MOZ_MUST_OVERRIDE /* nothing */ # define MOZ_STATIC_CLASS /* nothing */ # define MOZ_STACK_CLASS /* nothing */ # define MOZ_NONHEAP_CLASS /* nothing */ # define MOZ_HEAP_CLASS /* nothing */ # define MOZ_NON_TEMPORARY_CLASS /* nothing */ # define MOZ_TEMPORARY_CLASS /* nothing */ @@ -801,20 +832,31 @@ # define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */ # define MOZ_INIT_OUTSIDE_CTOR /* nothing */ # define MOZ_IS_CLASS_INIT /* nothing */ # define MOZ_NON_PARAM /* nothing */ # define MOZ_NON_AUTOABLE /* nothing */ # define MOZ_REQUIRED_BASE_METHOD /* nothing */ # define MOZ_MUST_RETURN_FROM_CALLER /* nothing */ # define MOZ_MAY_CALL_AFTER_MUST_RETURN /* nothing */ -#endif /* MOZ_CLANG_PLUGIN */ +#endif /* defined(MOZ_CLANG_PLUGIN) || defined(XGILL_PLUGIN) */ #define MOZ_RAII MOZ_NON_TEMPORARY_CLASS MOZ_STACK_CLASS +// gcc has different rules governing attribute placement. Since none of these +// attributes are actually used by the gcc-based static analysis, just +// eliminate them rather than updating all of the code. + +#ifdef XGILL_PLUGIN +# undef MOZ_MUST_OVERRIDE +# define MOZ_MUST_OVERRIDE /* nothing */ +# undef MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION +# define MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION /* nothing */ +#endif + #endif /* __cplusplus */ /** * Printf style formats. MOZ_FORMAT_PRINTF can be used to annotate a * function or method that is "printf-like"; this will let (some) * compilers check that the arguments match the template string. * * This macro takes two arguments. The first argument is the argument
--- a/mfbt/CheckedInt.h +++ b/mfbt/CheckedInt.h @@ -553,17 +553,17 @@ public: * * This constructor is not explicit. Instead, the type of its argument is a * separate template parameter, ensuring that no conversion is performed * before this constructor is actually called. As explained in the above * documentation for class CheckedInt, this constructor checks that its * argument is valid. */ template<typename U> - MOZ_IMPLICIT constexpr CheckedInt(U aValue) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT + MOZ_IMPLICIT MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT constexpr CheckedInt(U aValue) : mValue(T(aValue)), mIsValid(detail::IsInRange<T>(aValue)) { static_assert(detail::IsSupported<T>::value && detail::IsSupported<U>::value, "This type is not supported by CheckedInt"); }
--- a/taskcluster/scripts/builder/hazard-browser.sh +++ b/taskcluster/scripts/builder/hazard-browser.sh @@ -1,10 +1,10 @@ #!/bin/bash -e cd $SOURCE TOP=$(cd ..; pwd) export MOZBUILD_STATE_PATH=$TOP/mozbuild-state [ -d $MOZBUILD_STATE_PATH ] || mkdir $MOZBUILD_STATE_PATH -export MOZCONFIG=$SOURCE/browser/config/mozconfigs/linux64/hazards +export MOZCONFIG=$SOURCE/js/src/devtools/rootAnalysis/mozconfig.haz exec ./mach build -v -j8