From c18aecde615e6998978e73f920de95b34876a61e Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Thu, 14 Aug 2014 07:36:13 +0200 Subject: [PATCH 001/119] Bug 1053269 - Null-check for ownerDoc OpenDatabaseHelper.cpp, r=ehsan --- dom/indexedDB/OpenDatabaseHelper.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dom/indexedDB/OpenDatabaseHelper.cpp b/dom/indexedDB/OpenDatabaseHelper.cpp index 1bc5aa858905..1f3cde303a33 100644 --- a/dom/indexedDB/OpenDatabaseHelper.cpp +++ b/dom/indexedDB/OpenDatabaseHelper.cpp @@ -1707,7 +1707,9 @@ public: NS_ASSERTION(database->IsClosed(), "AbortCloseStoragesForWindow should have closed database"); - ownerDoc->DisallowBFCaching(); + if (ownerDoc) { + ownerDoc->DisallowBFCaching(); + } continue; } From 51a18d912ff907b2a5283b82a82974cf3d2c1dda Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Thu, 14 Aug 2014 17:08:44 +0900 Subject: [PATCH 002/119] Bug 1051669 - Use --disable-tools on cross build option of ICU. r=glandium --- build/autoconf/icu.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/autoconf/icu.m4 b/build/autoconf/icu.m4 index f7417d8f096a..df7f5edf3efd 100644 --- a/build/autoconf/icu.m4 +++ b/build/autoconf/icu.m4 @@ -180,7 +180,7 @@ if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then # --with-cross-build requires absolute path ICU_HOST_PATH=`cd $_objdir/intl/icu/host && pwd` - ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH" + ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH --disable-tools" ICU_TARGET_OPT="--build=$build --host=$target" else # CROSS_COMPILE isn't set build and target are i386 and x86-64. From 5a1e63fec0b0770d796cae668dfa54d8fc9190fa Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 14 Aug 2014 17:58:15 +0900 Subject: [PATCH 003/119] Bug 1052286 nsTextStore::SetInputContext() should handle password state as editable state r=jimm --- widget/nsIWidget.h | 5 +++++ widget/windows/WinIMEHandler.cpp | 6 +++--- widget/windows/nsTextStore.cpp | 24 +++++++++++------------- widget/windows/nsTextStore.h | 2 +- widget/windows/winrt/MetroWidget.cpp | 6 ++---- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index dac93db2d841..334146e7619b 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -373,6 +373,11 @@ struct IMEState { mEnabled(aEnabled), mOpen(aOpen) { } + + bool IsEditable() const + { + return mEnabled == ENABLED || mEnabled == PASSWORD; + } }; struct InputContext { diff --git a/widget/windows/WinIMEHandler.cpp b/widget/windows/WinIMEHandler.cpp index fd62d1afd6ce..d695675dee43 100644 --- a/widget/windows/WinIMEHandler.cpp +++ b/widget/windows/WinIMEHandler.cpp @@ -169,10 +169,10 @@ IMEHandler::NotifyIME(nsWindow* aWindow, return nsTextStore::OnTextChange(aIMENotification); case NOTIFY_IME_OF_FOCUS: return nsTextStore::OnFocusChange(true, aWindow, - aWindow->GetInputContext().mIMEState.mEnabled); + aWindow->GetInputContext().mIMEState); case NOTIFY_IME_OF_BLUR: return nsTextStore::OnFocusChange(false, aWindow, - aWindow->GetInputContext().mIMEState.mEnabled); + aWindow->GetInputContext().mIMEState); case REQUEST_TO_COMMIT_COMPOSITION: if (nsTextStore::IsComposingOn(aWindow)) { nsTextStore::CommitComposition(false); @@ -208,7 +208,7 @@ IMEHandler::NotifyIME(nsWindow* aWindow, // the blur. if (nsTextStore::ThinksHavingFocus()) { return nsTextStore::OnFocusChange(false, aWindow, - aWindow->GetInputContext().mIMEState.mEnabled); + aWindow->GetInputContext().mIMEState); } return NS_ERROR_NOT_IMPLEMENTED; #endif //NS_ENABLE_TSF diff --git a/widget/windows/nsTextStore.cpp b/widget/windows/nsTextStore.cpp index 308f2b87e765..c5fd60e4d0d5 100644 --- a/widget/windows/nsTextStore.cpp +++ b/widget/windows/nsTextStore.cpp @@ -3274,25 +3274,25 @@ nsTextStore::OnActivated(DWORD dwProfileType, nsresult nsTextStore::OnFocusChange(bool aGotFocus, nsWindowBase* aFocusedWidget, - IMEState::Enabled aIMEEnabled) + const IMEState& aIMEState) { PR_LOG(sTextStoreLog, PR_LOG_DEBUG, ("TSF: nsTextStore::OnFocusChange(aGotFocus=%s, " - "aFocusedWidget=0x%p, aIMEEnabled=%s), sTsfThreadMgr=0x%p, " - "sTsfTextStore=0x%p", + "aFocusedWidget=0x%p, aIMEState={ mEnabled=%s }), " + "sTsfThreadMgr=0x%p, sTsfTextStore=0x%p", GetBoolName(aGotFocus), aFocusedWidget, - GetIMEEnabledName(aIMEEnabled), sTsfThreadMgr, sTsfTextStore)); + GetIMEEnabledName(aIMEState.mEnabled), + sTsfThreadMgr, sTsfTextStore)); // no change notifications if TSF is disabled NS_ENSURE_TRUE(sTsfThreadMgr && sTsfTextStore, NS_ERROR_NOT_AVAILABLE); nsRefPtr prevFocusedDocumentMgr; - if (aGotFocus && (aIMEEnabled == IMEState::ENABLED || - aIMEEnabled == IMEState::PASSWORD)) { + if (aGotFocus && aIMEState.IsEditable()) { bool bRet = sTsfTextStore->Create(aFocusedWidget); NS_ENSURE_TRUE(bRet, NS_ERROR_FAILURE); NS_ENSURE_TRUE(sTsfTextStore->mDocumentMgr, NS_ERROR_FAILURE); - if (aIMEEnabled == IMEState::PASSWORD) { + if (aIMEState.mEnabled == IMEState::PASSWORD) { MarkContextAsKeyboardDisabled(sTsfTextStore->mContext); nsRefPtr topContext; sTsfTextStore->mDocumentMgr->GetTop(getter_AddRefs(topContext)); @@ -3762,12 +3762,10 @@ nsTextStore::SetInputContext(nsWindowBase* aWidget, // If focus isn't actually changed but the enabled state is changed, // emulate the focus move. - if (!ThinksHavingFocus() && - aContext.mIMEState.mEnabled == IMEState::ENABLED) { - OnFocusChange(true, aWidget, aContext.mIMEState.mEnabled); - } else if (ThinksHavingFocus() && - aContext.mIMEState.mEnabled != IMEState::ENABLED) { - OnFocusChange(false, aWidget, aContext.mIMEState.mEnabled); + if (!ThinksHavingFocus() && aContext.mIMEState.IsEditable()) { + OnFocusChange(true, aWidget, aContext.mIMEState); + } else if (ThinksHavingFocus() && !aContext.mIMEState.IsEditable()) { + OnFocusChange(false, aWidget, aContext.mIMEState); } } diff --git a/widget/windows/nsTextStore.h b/widget/windows/nsTextStore.h index 08cc1e752a16..e347d805b393 100644 --- a/widget/windows/nsTextStore.h +++ b/widget/windows/nsTextStore.h @@ -138,7 +138,7 @@ public: static nsresult OnFocusChange(bool aGotFocus, nsWindowBase* aFocusedWidget, - IMEState::Enabled aIMEEnabled); + const IMEState& aIMEState); static nsresult OnTextChange(const IMENotification& aIMENotification) { NS_ENSURE_TRUE(sTsfTextStore, NS_ERROR_NOT_AVAILABLE); diff --git a/widget/windows/winrt/MetroWidget.cpp b/widget/windows/winrt/MetroWidget.cpp index b965078a7085..aafe87e7d99a 100644 --- a/widget/windows/winrt/MetroWidget.cpp +++ b/widget/windows/winrt/MetroWidget.cpp @@ -1570,11 +1570,9 @@ MetroWidget::NotifyIME(const IMENotification& aIMENotification) nsTextStore::CommitComposition(true); return NS_OK; case NOTIFY_IME_OF_FOCUS: - return nsTextStore::OnFocusChange(true, this, - mInputContext.mIMEState.mEnabled); + return nsTextStore::OnFocusChange(true, this, mInputContext.mIMEState); case NOTIFY_IME_OF_BLUR: - return nsTextStore::OnFocusChange(false, this, - mInputContext.mIMEState.mEnabled); + return nsTextStore::OnFocusChange(false, this, mInputContext.mIMEState); case NOTIFY_IME_OF_SELECTION_CHANGE: return nsTextStore::OnSelectionChange(); case NOTIFY_IME_OF_TEXT_CHANGE: From 5a19c6c4f0996ef932234dc752b8c95a4fe35828 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 10:32:06 +0100 Subject: [PATCH 004/119] Bug 1052422 - Remove trivial shim functions that call into the GC r=sfink --- js/public/GCAPI.h | 2 +- js/src/builtin/TestingFunctions.cpp | 6 +- js/src/gc/GCRuntime.h | 9 +- js/src/gc/Iteration.cpp | 6 +- js/src/gc/Verifier.cpp | 4 +- js/src/gc/Zone.cpp | 6 +- js/src/jit/BaselineDebugModeOSR.cpp | 2 +- js/src/jsapi-tests/testGCFinalizeCallback.cpp | 4 +- js/src/jsapi-tests/testGCHeapPostBarriers.cpp | 2 +- js/src/jsapi-tests/testWeakMap.cpp | 4 +- js/src/jsapi.cpp | 4 +- js/src/jscntxt.cpp | 4 +- js/src/jscntxt.h | 8 ++ js/src/jsfriendapi.cpp | 10 +- js/src/jsgc.cpp | 94 ++++--------------- js/src/jsgc.h | 37 -------- js/src/jsgcinlines.h | 13 ++- js/src/vm/ForkJoin.cpp | 7 +- js/src/vm/Interpreter.cpp | 2 +- js/src/vm/Runtime.cpp | 2 +- 20 files changed, 75 insertions(+), 151 deletions(-) diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h index 7d1ef07960fa..8cdcfe99e38e 100644 --- a/js/public/GCAPI.h +++ b/js/public/GCAPI.h @@ -90,7 +90,7 @@ namespace JS { D(REFRESH_FRAME) \ D(FULL_GC_TIMER) \ D(SHUTDOWN_CC) \ - D(FINISH_LARGE_EVALUTE) + D(FINISH_LARGE_EVALUATE) namespace gcreason { diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index b70d744d3d76..74e979ddb700 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -268,7 +268,7 @@ MinorGC(JSContext *cx, unsigned argc, jsval *vp) if (args.get(0) == BooleanValue(true)) cx->runtime()->gc.storeBuffer.setAboutToOverflow(); - MinorGC(cx, gcreason::API); + cx->minorGC(gcreason::API); #endif args.rval().setUndefined(); return true; @@ -519,7 +519,7 @@ SelectForGC(JSContext *cx, unsigned argc, Value *vp) * to be in the set, so evict the nursery before adding items. */ JSRuntime *rt = cx->runtime(); - MinorGC(rt, JS::gcreason::EVICT_NURSERY); + rt->gc.evictNursery(); for (unsigned i = 0; i < args.length(); i++) { if (args[i].isObject()) { @@ -628,7 +628,7 @@ GCSlice(JSContext *cx, unsigned argc, Value *vp) limit = false; } - GCDebugSlice(cx->runtime(), limit, budget); + cx->runtime()->gc.gcDebugSlice(limit, budget); args.rval().setUndefined(); return true; } diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 5379ceb4f4d8..b9f7a03caa98 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -278,10 +278,13 @@ class GCRuntime void maybePeriodicFullGC(); void minorGC(JS::gcreason::Reason reason); void minorGC(JSContext *cx, JS::gcreason::Reason reason); + void evictNursery(JS::gcreason::Reason reason = JS::gcreason::EVICT_NURSERY) { minorGC(reason); } void gcIfNeeded(JSContext *cx); - void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, - JS::gcreason::Reason reason); + void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason); void gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); + void gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason); + void gcDebugSlice(bool limit, int64_t objCount); + void runDebugGC(); inline void poke(); @@ -465,6 +468,8 @@ class GCRuntime bool initZeal(); void requestInterrupt(JS::gcreason::Reason reason); + void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, + JS::gcreason::Reason reason); bool gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind, JS::gcreason::Reason reason); gcstats::ZoneGCStats scanZonesBeforeGC(); diff --git a/js/src/gc/Iteration.cpp b/js/src/gc/Iteration.cpp index c6e799580e96..0c2e31fce44e 100644 --- a/js/src/gc/Iteration.cpp +++ b/js/src/gc/Iteration.cpp @@ -23,7 +23,7 @@ js::TraceRuntime(JSTracer *trc) JS_ASSERT(!IS_GC_MARKING_TRACER(trc)); JSRuntime *rt = trc->runtime(); - MinorGC(rt, JS::gcreason::EVICT_NURSERY); + rt->gc.evictNursery(); AutoPrepareForTracing prep(rt, WithAtoms); rt->gc.markRuntime(trc); } @@ -93,7 +93,7 @@ void js::IterateScripts(JSRuntime *rt, JSCompartment *compartment, void *data, IterateScriptCallback scriptCallback) { - MinorGC(rt, JS::gcreason::EVICT_NURSERY); + rt->gc.evictNursery(); AutoPrepareForTracing prep(rt, SkipAtoms); if (compartment) { @@ -113,7 +113,7 @@ js::IterateScripts(JSRuntime *rt, JSCompartment *compartment, void js::IterateGrayObjects(Zone *zone, GCThingCallback cellCallback, void *data) { - MinorGC(zone->runtimeFromMainThread(), JS::gcreason::EVICT_NURSERY); + zone->runtimeFromMainThread()->gc.evictNursery(); AutoPrepareForTracing prep(zone->runtimeFromMainThread(), SkipAtoms); for (size_t finalizeKind = 0; finalizeKind <= FINALIZE_OBJECT_LAST; finalizeKind++) { diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index 5499a53b6f7f..9bbe39a25f4a 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -182,7 +182,7 @@ gc::GCRuntime::startVerifyPreBarriers() if (verifyPostData) return; - MinorGC(rt, JS::gcreason::EVICT_NURSERY); + evictNursery(); AutoPrepareForTracing prep(rt, WithAtoms); @@ -410,7 +410,7 @@ gc::GCRuntime::startVerifyPostBarriers() return; } - MinorGC(rt, JS::gcreason::EVICT_NURSERY); + evictNursery(); number++; diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index ad2613456399..0bf676576bd6 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -97,8 +97,10 @@ Zone::setGCMaxMallocBytes(size_t value) void Zone::onTooMuchMalloc() { - if (!gcMallocGCTriggered) - gcMallocGCTriggered = TriggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC); + if (!gcMallocGCTriggered) { + GCRuntime &gc = runtimeFromAnyThread()->gc; + gcMallocGCTriggered = gc.triggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC); + } } void diff --git a/js/src/jit/BaselineDebugModeOSR.cpp b/js/src/jit/BaselineDebugModeOSR.cpp index c118ce94ef80..6472f8f1bf6e 100644 --- a/js/src/jit/BaselineDebugModeOSR.cpp +++ b/js/src/jit/BaselineDebugModeOSR.cpp @@ -658,7 +658,7 @@ jit::RecompileOnStackBaselineScriptsForDebugMode(JSContext *cx, JSCompartment *c #ifdef JSGC_GENERATIONAL // Scripts can entrain nursery things. See note in js::ReleaseAllJITCode. if (!entries.empty()) - MinorGC(cx->runtime(), JS::gcreason::EVICT_NURSERY); + cx->runtime()->gc.evictNursery(); #endif // When the profiler is enabled, we need to suppress sampling from here until diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp index fc4dc708464b..4c38c45407f6 100644 --- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp +++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp @@ -88,12 +88,12 @@ BEGIN_TEST(testGCFinalizeCallback) FinalizeCalls = 0; JS_SetGCZeal(cx, 9, 1000000); JS::PrepareForFullGC(rt); - js::GCDebugSlice(rt, true, 1); + rt->gc.gcDebugSlice(true, 1); CHECK(rt->gc.state() == js::gc::MARK); CHECK(rt->gc.isFullGc()); JS::RootedObject global4(cx, createGlobal()); - js::GCDebugSlice(rt, true, 1); + rt->gc.gcDebugSlice(true, 1); CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL); CHECK(!rt->gc.isFullGc()); CHECK(checkMultipleGroups()); diff --git a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp index 6aa4dced04a1..2fc66907921c 100644 --- a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp +++ b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp @@ -51,7 +51,7 @@ TestHeapPostBarriers(T initialObj) uintptr_t initialObjAsInt = uintptr_t(initialObj); /* Perform minor GC and check heap wrapper is udated with new pointer. */ - js::MinorGC(cx, JS::gcreason::API); + cx->minorGC(JS::gcreason::API); CHECK(uintptr_t(heapData->get()) != initialObjAsInt); CHECK(!js::gc::IsInsideNursery(heapData->get())); diff --git a/js/src/jsapi-tests/testWeakMap.cpp b/js/src/jsapi-tests/testWeakMap.cpp index 7bfacf118017..8c3db691d2fa 100644 --- a/js/src/jsapi-tests/testWeakMap.cpp +++ b/js/src/jsapi-tests/testWeakMap.cpp @@ -87,7 +87,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) * zone to finish marking before the delegate zone. */ CHECK(newCCW(map, delegate)); - GCDebugSlice(rt, true, 1000000); + rt->gc.gcDebugSlice(true, 1000000); #ifdef DEBUG CHECK(map->zone()->lastZoneGroupIndex() < delegate->zone()->lastZoneGroupIndex()); #endif @@ -100,7 +100,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) /* Check the delegate keeps the entry alive even if the key is not reachable. */ key = nullptr; CHECK(newCCW(map, delegate)); - GCDebugSlice(rt, true, 100000); + rt->gc.gcDebugSlice(true, 100000); CHECK(checkSize(map, 1)); /* diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index c2d15765045b..89bfa8e876a7 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1873,7 +1873,7 @@ JS_GC(JSRuntime *rt) { AssertHeapIsIdle(rt); JS::PrepareForFullGC(rt); - GC(rt, GC_NORMAL, JS::gcreason::API); + rt->gc.gc(GC_NORMAL, JS::gcreason::API); } JS_PUBLIC_API(void) @@ -4807,7 +4807,7 @@ Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsA if (script->length() > LARGE_SCRIPT_LENGTH) { script = nullptr; PrepareZoneForGC(cx->zone()); - GC(cx->runtime(), GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUTE); + cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUATE); } return result; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index f5effb931662..e6aa3c0c2cb0 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -251,7 +251,7 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode) if (mode == DCM_FORCE_GC) { JS_ASSERT(!rt->isHeapBusy()); JS::PrepareForFullGC(rt); - GC(rt, GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); + rt->gc.gc(GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); } js_delete_poison(cx); } @@ -986,7 +986,7 @@ js::InvokeInterruptCallback(JSContext *cx) // callbacks. rt->resetJitStackLimit(); - js::gc::GCIfNeeded(cx); + cx->gcIfNeeded(); rt->interruptPar = false; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 7f7a8add373d..734ee731f1ec 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -548,6 +548,14 @@ struct JSContext : public js::ExclusiveContext, } #endif + void minorGC(JS::gcreason::Reason reason) { + runtime_->gc.minorGC(this, reason); + } + + void gcIfNeeded() { + runtime_->gc.gcIfNeeded(this); + } + private: /* Innermost-executing generator or null if no generator are executing. */ JSGenerator *innermostGenerator_; diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index d46d33db6c2b..520ba1b18cf1 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -197,25 +197,25 @@ JS::SkipZoneForGC(Zone *zone) JS_FRIEND_API(void) JS::GCForReason(JSRuntime *rt, gcreason::Reason reason) { - GC(rt, GC_NORMAL, reason); + rt->gc.gc(GC_NORMAL, reason); } JS_FRIEND_API(void) JS::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason) { - GC(rt, GC_SHRINK, reason); + rt->gc.gc(GC_SHRINK, reason); } JS_FRIEND_API(void) JS::IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis) { - GCSlice(rt, GC_NORMAL, reason, millis); + rt->gc.gcSlice(GC_NORMAL, reason, millis); } JS_FRIEND_API(void) JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason) { - GCFinalSlice(rt, GC_NORMAL, reason); + rt->gc.gcFinalSlice(GC_NORMAL, reason); } JS_FRIEND_API(JSPrincipals *) @@ -810,7 +810,7 @@ js::DumpHeapComplete(JSRuntime *rt, FILE *fp, js::DumpHeapNurseryBehaviour nurse { #ifdef JSGC_GENERATIONAL if (nurseryBehaviour == js::CollectNurseryBeforeDump) - MinorGC(rt, JS::gcreason::API); + rt->gc.evictNursery(JS::gcreason::API); #endif DumpHeapTracer dtrc(fp, rt, DumpHeapVisitRoot, TraceWeakMapKeysValues); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 07d3a4ffbc3c..1ef5dde331a1 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -939,7 +939,7 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind) if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) { AutoUnlockGC unlock(rt); - TriggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); } return aheader; @@ -1186,7 +1186,7 @@ GCRuntime::setZeal(uint8_t zeal, uint32_t frequency) #ifdef JSGC_GENERATIONAL if (zealMode == ZealGenerationalGCValue) { - minorGC(JS::gcreason::DEBUG_GC); + evictNursery(JS::gcreason::DEBUG_GC); nursery.leaveZealMode(); } @@ -2169,7 +2169,7 @@ RunLastDitchGC(JSContext *cx, JS::Zone *zone, AllocKind thingKind) /* The last ditch GC preserves all atoms. */ AutoKeepAtoms keepAtoms(cx->perThreadData); - GC(rt, GC_NORMAL, JS::gcreason::LAST_DITCH); + rt->gc.gc(GC_NORMAL, JS::gcreason::LAST_DITCH); /* * The JSGC_END callback can legitimately allocate new GC @@ -2271,12 +2271,6 @@ ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); template void * ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); -JSGCTraceKind -js_GetGCThingTraceKind(void *thing) -{ - return GetGCThingTraceKind(thing); -} - /* static */ int64_t SliceBudget::TimeBudget(int64_t millis) { @@ -2334,12 +2328,6 @@ GCRuntime::requestInterrupt(JS::gcreason::Reason reason) rt->requestInterrupt(JSRuntime::RequestInterruptMainThread); } -bool -js::TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason) -{ - return rt->gc.triggerGC(reason); -} - bool GCRuntime::triggerGC(JS::gcreason::Reason reason) { @@ -2369,12 +2357,6 @@ GCRuntime::triggerGC(JS::gcreason::Reason reason) return true; } -bool -js::TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason) -{ - return zone->runtimeFromAnyThread()->gc.triggerZoneGC(zone, reason); -} - bool GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) { @@ -2401,14 +2383,14 @@ GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) #ifdef JS_GC_ZEAL if (zealMode == ZealAllocValue) { - TriggerGC(rt, reason); + triggerGC(reason); return true; } #endif if (rt->isAtomsZone(zone)) { /* We can't do a zone GC of the atoms compartment. */ - TriggerGC(rt, reason); + triggerGC(reason); return true; } @@ -2425,13 +2407,13 @@ GCRuntime::maybeGC(Zone *zone) #ifdef JS_GC_ZEAL if (zealMode == ZealAllocValue || zealMode == ZealPokeValue) { JS::PrepareForFullGC(rt); - GC(rt, GC_NORMAL, JS::gcreason::MAYBEGC); + gc(GC_NORMAL, JS::gcreason::MAYBEGC); return true; } #endif if (isNeeded) { - GCSlice(rt, GC_NORMAL, JS::gcreason::MAYBEGC); + gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -2442,7 +2424,7 @@ GCRuntime::maybeGC(Zone *zone) !isBackgroundSweeping()) { PrepareZoneForGC(zone); - GCSlice(rt, GC_NORMAL, JS::gcreason::MAYBEGC); + gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -2468,7 +2450,7 @@ GCRuntime::maybePeriodicFullGC() numArenasFreeCommitted > decommitThreshold) { JS::PrepareForFullGC(rt); - GCSlice(rt, GC_SHRINK, JS::gcreason::MAYBEGC); + gcSlice(GC_SHRINK, JS::gcreason::MAYBEGC); } else { nextFullGCTime = now + GC_IDLE_FULL_SPAN; } @@ -4767,7 +4749,7 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (reason == JS::gcreason::DEBUG_GC && budget != SliceBudget::Unlimited) { /* * Do the incremental collection type specified by zeal mode if the - * collection was triggered by RunDebugGC() and incremental GC has not + * collection was triggered by runDebugGC() and incremental GC has not * been cancelled by resetIncrementalGC(). */ zeal = zealMode; @@ -5200,15 +5182,9 @@ GCRuntime::collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, } void -js::GC(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason) +GCRuntime::gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - rt->gc.collect(false, SliceBudget::Unlimited, gckind, reason); -} - -void -js::GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) -{ - rt->gc.gcSlice(gckind, reason, millis); + collect(false, SliceBudget::Unlimited, gckind, reason); } void @@ -5226,9 +5202,9 @@ GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64 } void -js::GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason) +GCRuntime::gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - rt->gc.collect(true, SliceBudget::Unlimited, gckind, reason); + collect(true, SliceBudget::Unlimited, gckind, reason); } void @@ -5271,7 +5247,7 @@ ZonesSelected(JSRuntime *rt) } void -js::GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount) +GCRuntime::gcDebugSlice(bool limit, int64_t objCount) { int64_t budget = limit ? SliceBudget::WorkBudget(objCount) : SliceBudget::Unlimited; if (!ZonesSelected(rt)) { @@ -5280,7 +5256,7 @@ js::GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount) else JS::PrepareForFullGC(rt); } - rt->gc.collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); + collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); } /* Schedule a full GC unless a zone will already be collected. */ @@ -5310,12 +5286,6 @@ GCRuntime::shrinkBuffers() expireChunksAndArenas(true); } -void -js::MinorGC(JSRuntime *rt, JS::gcreason::Reason reason) -{ - rt->gc.minorGC(reason); -} - void GCRuntime::minorGC(JS::gcreason::Reason reason) { @@ -5328,16 +5298,10 @@ GCRuntime::minorGC(JS::gcreason::Reason reason) } void -js::MinorGC(JSContext *cx, JS::gcreason::Reason reason) +GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason) { // Alternate to the runtime-taking form above which allows marking type // objects as needing pretenuring. - cx->runtime()->gc.minorGC(cx, reason); -} - -void -GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason) -{ #ifdef JSGC_GENERATIONAL TraceLogger *logger = TraceLoggerForMainThread(rt); AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC); @@ -5377,12 +5341,6 @@ GCRuntime::enableGenerationalGC() #endif } -void -js::gc::GCIfNeeded(JSContext *cx) -{ - cx->runtime()->gc.gcIfNeeded(cx); -} - void GCRuntime::gcIfNeeded(JSContext *cx) { @@ -5399,12 +5357,6 @@ GCRuntime::gcIfNeeded(JSContext *cx) gcSlice(GC_NORMAL, rt->gc.triggerReason, 0); } -void -js::gc::FinishBackgroundFinalize(JSRuntime *rt) -{ - rt->gc.waitBackgroundSweepEnd(); -} - AutoFinishGC::AutoFinishGC(JSRuntime *rt) { if (JS::IsIncrementalGCInProgress(rt)) { @@ -5412,7 +5364,7 @@ AutoFinishGC::AutoFinishGC(JSRuntime *rt) JS::FinishIncrementalGC(rt, JS::gcreason::API); } - gc::FinishBackgroundFinalize(rt); + rt->gc.waitBackgroundSweepEnd(); } AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt, ZoneSelector selector) @@ -5520,12 +5472,6 @@ gc::MergeCompartments(JSCompartment *source, JSCompartment *target) target->zone()->types.typeLifoAlloc.transferFrom(&source->zone()->types.typeLifoAlloc); } -void -gc::RunDebugGC(JSContext *cx) -{ - cx->runtime()->gc.runDebugGC(); -} - void GCRuntime::runDebugGC() { @@ -5536,7 +5482,7 @@ GCRuntime::runDebugGC() return; if (type == js::gc::ZealGenerationalGCValue) - return MinorGC(rt, JS::gcreason::DEBUG_GC); + return minorGC(JS::gcreason::DEBUG_GC); PrepareForDebugGC(rt); @@ -5634,7 +5580,7 @@ js::ReleaseAllJITCode(FreeOp *fop) * Scripts can entrain nursery things, inserting references to the script * into the store buffer. Clear the store buffer before discarding scripts. */ - MinorGC(fop->runtime(), JS::gcreason::EVICT_NURSERY); + fop->runtime()->gc.evictNursery(); #endif for (ZonesIter zone(fop->runtime(), SkipAtoms); !zone.done(); zone.next()) { diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 8cdd447a3e92..c5f5a5571636 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -963,14 +963,6 @@ MarkCompartmentActive(js::InterpreterFrame *fp); extern void TraceRuntime(JSTracer *trc); -/* Must be called with GC lock taken. */ -extern bool -TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason); - -/* Must be called with GC lock taken. */ -extern bool -TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason); - extern void ReleaseAllJITCode(FreeOp *op); @@ -985,27 +977,9 @@ typedef enum JSGCInvocationKind { GC_SHRINK = 1 } JSGCInvocationKind; -extern void -GC(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason); - -extern void -GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); - -extern void -GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason); - -extern void -GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount); - extern void PrepareForDebugGC(JSRuntime *rt); -extern void -MinorGC(JSRuntime *rt, JS::gcreason::Reason reason); - -extern void -MinorGC(JSContext *cx, JS::gcreason::Reason reason); - /* Functions for managing cross compartment gray pointers. */ extern void @@ -1225,17 +1199,6 @@ NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals, namespace gc { -extern void -GCIfNeeded(JSContext *cx); - -/* Tries to run a GC no matter what (used for GC zeal). */ -void -RunDebugGC(JSContext *cx); - -/* Wait for the background thread to finish sweeping if it is running. */ -void -FinishBackgroundFinalize(JSRuntime *rt); - /* * Merge all contents of source into target. This can only be used if source is * the only compartment in its zone. diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 8e764d08d0d6..384b2a0af4a2 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -368,14 +368,13 @@ class ZoneCellIter : public ZoneCellIterImpl if (IsBackgroundFinalized(kind) && zone->allocator.arenas.needBackgroundFinalizeWait(kind)) { - gc::FinishBackgroundFinalize(zone->runtimeFromMainThread()); + zone->runtimeFromMainThread()->gc.waitBackgroundSweepEnd(); } #ifdef JSGC_GENERATIONAL /* Evict the nursery before iterating so we can see all things. */ JSRuntime *rt = zone->runtimeFromMainThread(); - if (!rt->gc.nursery.isEmpty()) - MinorGC(rt, JS::gcreason::EVICT_NURSERY); + rt->gc.evictNursery(); #endif if (lists->isSynchronizedFreeList(kind)) { @@ -473,7 +472,7 @@ TryNewNurseryObject(JSContext *cx, size_t thingSize, size_t nDynamicSlots) if (obj) return obj; if (allowGC && !rt->mainThread.suppressGC) { - MinorGC(cx, JS::gcreason::OUT_OF_NURSERY); + cx->minorGC(JS::gcreason::OUT_OF_NURSERY); /* Exceeding gcMaxBytes while tenuring can disable the Nursery. */ if (nursery.isEnabled()) { @@ -547,13 +546,13 @@ CheckAllocatorState(ThreadSafeContext *cx, AllocKind kind) if (allowGC) { #ifdef JS_GC_ZEAL if (rt->gc.needZealousGC()) - js::gc::RunDebugGC(ncx); + rt->gc.runDebugGC(); #endif if (rt->interrupt) { // Invoking the interrupt callback can fail and we can't usefully // handle that here. Just check in case we need to collect instead. - js::gc::GCIfNeeded(ncx); + ncx->gcIfNeeded(); } } @@ -682,7 +681,7 @@ AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap) JSObject *obj = TryNewNurseryObject(cx, thingSize, 0); if (!obj && allowGC) { - MinorGC(cx, JS::gcreason::OUT_OF_NURSERY); + cx->minorGC(JS::gcreason::OUT_OF_NURSERY); return nullptr; } return obj; diff --git a/js/src/vm/ForkJoin.cpp b/js/src/vm/ForkJoin.cpp index a7f9952b6b1f..fe89743475b4 100644 --- a/js/src/vm/ForkJoin.cpp +++ b/js/src/vm/ForkJoin.cpp @@ -355,7 +355,7 @@ ForkJoinActivation::ForkJoinActivation(JSContext *cx) JS::FinishIncrementalGC(cx->runtime(), JS::gcreason::API); } - MinorGC(cx->runtime(), JS::gcreason::API); + cx->runtime()->gc.evictNursery(); cx->runtime()->gc.waitBackgroundSweepEnd(); @@ -1492,10 +1492,11 @@ ForkJoinShared::transferArenasToCompartmentAndProcessGCRequests() if (gcRequested_) { Spew(SpewGC, "Triggering garbage collection in SpiderMonkey heap"); + gc::GCRuntime &gc = cx_->runtime()->gc; if (!gcZone_) - TriggerGC(cx_->runtime(), gcReason_); + gc.triggerGC(gcReason_); else - TriggerZoneGC(gcZone_, gcReason_); + gc.triggerZoneGC(gcZone_, gcReason_); gcRequested_ = false; gcZone_ = nullptr; } diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 9967804c1dea..e5fc625344b1 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -415,7 +415,7 @@ struct AutoGCIfNeeded { JSContext *cx_; explicit AutoGCIfNeeded(JSContext *cx) : cx_(cx) {} - ~AutoGCIfNeeded() { js::gc::GCIfNeeded(cx_); } + ~AutoGCIfNeeded() { cx_->gcIfNeeded(); } }; /* diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 9c1729d7c655..994cdfd3f9d1 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -376,7 +376,7 @@ JSRuntime::~JSRuntime() profilingScripts = false; JS::PrepareForFullGC(this); - GC(this, GC_NORMAL, JS::gcreason::DESTROY_RUNTIME); + gc.gc(GC_NORMAL, JS::gcreason::DESTROY_RUNTIME); } /* From 6846d7c3554704b54296b8e8efb028e9dde15339 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:46:26 +0100 Subject: [PATCH 005/119] Bug 650161 - Add --enable-gccompacting configure flag for compacting GC r=terrence r=ted --- configure.in | 14 ++++++++++++++ js/src/configure.in | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/configure.in b/configure.in index 7cbc077b5cb4..eb5206638998 100644 --- a/configure.in +++ b/configure.in @@ -7148,6 +7148,17 @@ if test -n "$JSGC_GENERATIONAL"; then AC_DEFINE(JSGC_GENERATIONAL) fi +dnl ======================================================== +dnl = Use compacting GC +dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(gccompacting, +[ --enable-gccompacting Compact the JS heap by moving GC things], + JS_GCCOMPACTING=1, + JS_GCCOMPACTING= ) +if test -n "$JS_GCCOMPACTING"; then + AC_DEFINE(JS_GCCOMPACTING) +fi + dnl ======================================================== dnl = Use a smaller chunk size for GC chunks dnl ======================================================== @@ -9109,6 +9120,9 @@ fi if test -z "$JSGC_GENERATIONAL" ; then ac_configure_args="$ac_configure_args --disable-gcgenerational" fi +if test -n "$JS_GCCOMPACTING" ; then + ac_configure_args="$ac_configure_args --enable-gccompacting" +fi if test -n "$JS_GC_SMALL_CHUNK_SIZE" ; then ac_configure_args="$ac_configure_args --enable-small-chunk-size" fi diff --git a/js/src/configure.in b/js/src/configure.in index 6f053b7803d1..e8372d8acbee 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -3114,6 +3114,18 @@ if test -n "$JSGC_USE_EXACT_ROOTING"; then AC_DEFINE(JSGC_USE_EXACT_ROOTING) fi +dnl ======================================================== +dnl = Use compacting GC +dnl ======================================================== +dnl Compact the heap by moving GC things when doing a shrinking colletion. +MOZ_ARG_ENABLE_BOOL(gccompacting, +[ --enable-gccompacting Compact the heap by moving GC things], + JSGC_COMPACTING=1, + JSGC_COMPACTING= ) +if test -n "$JSGC_COMPACTING"; then + AC_DEFINE(JSGC_COMPACTING) +fi + dnl ======================================================== dnl = Use a smaller chunk size for GC chunks dnl ======================================================== From e93ae2a7fc7f9ddcbc04526b6656d0d322d7dc87 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:46:29 +0100 Subject: [PATCH 006/119] Bug 650161 - Add functions for forwarding cells r=terrence --- js/src/jsgc.cpp | 19 +++++++++++++ js/src/jsgc.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 1ef5dde331a1..cdb24d24ac4e 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1985,6 +1985,25 @@ ArenaLists::wipeDuringParallelExecution(JSRuntime *rt) } } +#ifdef JSGC_COMPACTING + +static void +ForwardCell(Cell *dest, Cell *src) +{ + // Mark a cell has having been relocated and astore forwarding pointer to + // the new cell. + MOZ_ASSERT(src->tenuredZone() == dest->tenuredZone()); + + // Putting the values this way round is a terrible hack to make + // ObjectImpl::zone() work on forwarded objects. + MOZ_ASSERT(ObjectImpl::offsetOfShape() == 0); + uintptr_t *ptr = reinterpret_cast(src); + ptr[0] = reinterpret_cast(dest); // Forwarding address + ptr[1] = ForwardedCellMagicValue; // Moved! +} + +#endif + void ArenaLists::finalizeNow(FreeOp *fop, AllocKind thingKind) { diff --git a/js/src/jsgc.h b/js/src/jsgc.h index c5f5a5571636..fdcf5ca8c687 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -12,6 +12,7 @@ #include "mozilla/Atomics.h" #include "mozilla/DebugOnly.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/TypeTraits.h" #include "jslock.h" #include "jsobj.h" @@ -1206,6 +1207,78 @@ namespace gc { void MergeCompartments(JSCompartment *source, JSCompartment *target); +#ifdef JSGC_COMPACTING + +/* Functions for checking and updating things that might be moved by compacting GC. */ + +#ifdef JS_PUNBOX64 +const uintptr_t ForwardedCellMagicValue = 0xf1f1f1f1f1f1f1f1; +#else +const uintptr_t ForwardedCellMagicValue = 0xf1f1f1f1; +#endif + +template +inline bool +IsForwarded(T *t) +{ + static_assert(mozilla::IsBaseOf::value, "T must be a subclass of Cell"); + uintptr_t *ptr = reinterpret_cast(t); + return ptr[1] == ForwardedCellMagicValue; +} + +inline bool +IsForwarded(const JS::Value &value) +{ + if (value.isObject()) + return IsForwarded(&value.toObject()); + + if (value.isString()) + return IsForwarded(value.toString()); + + if (value.isSymbol()) + return IsForwarded(value.toSymbol()); + + JS_ASSERT(!value.isGCThing()); + return false; +} + +template +inline T * +Forwarded(T *t) +{ + JS_ASSERT(IsForwarded(t)); + uintptr_t *ptr = reinterpret_cast(t); + return reinterpret_cast(ptr[0]); +} + +inline Value +Forwarded(const JS::Value &value) +{ + if (value.isObject()) + return ObjectValue(*Forwarded(&value.toObject())); + else if (value.isString()) + return StringValue(Forwarded(value.toString())); + else if (value.isSymbol()) + return SymbolValue(Forwarded(value.toSymbol())); + + JS_ASSERT(!value.isGCThing()); + return value; +} + +template +inline T +MaybeForwarded(T t) +{ + return IsForwarded(t) ? Forwarded(t) : t; +} + +#else + +template inline bool IsForwarded(T t) { return false; } +template inline T MaybeForwarded(T t) { return t; } + +#endif // JSGC_COMPACTING + const int ZealPokeValue = 1; const int ZealAllocValue = 2; const int ZealFrameGCValue = 3; From 66a856d9a09f70e690abfffc56b41a569981ad8b Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:46:33 +0100 Subject: [PATCH 007/119] Bug 650161 - Update internal hash table checks for use after compacting GC as well r=terrence --- js/src/gc/GCInternals.h | 6 ++++ js/src/gc/Nursery.cpp | 22 +++------------ js/src/jscompartment.cpp | 8 +++--- js/src/jscompartment.h | 5 ++-- js/src/jsgc.cpp | 18 ++++++++++++ js/src/jsgc.h | 25 +++++++++++++++++ js/src/jsinfer.cpp | 58 ++++++++++++++++++++++++--------------- js/src/jspubtd.h | 5 ++++ js/src/vm/ScopeObject.cpp | 18 ++++++------ js/src/vm/Shape.cpp | 17 ++++++++---- 10 files changed, 121 insertions(+), 61 deletions(-) diff --git a/js/src/gc/GCInternals.h b/js/src/gc/GCInternals.h index 368f27e4a06d..3712af872884 100644 --- a/js/src/gc/GCInternals.h +++ b/js/src/gc/GCInternals.h @@ -131,6 +131,12 @@ struct AutoStopVerifyingBarriers }; #endif /* JS_GC_ZEAL */ +#ifdef JSGC_HASH_TABLE_CHECKS +void +CheckHashTablesAfterMovingGC(JSRuntime *rt); +#endif + + } /* namespace gc */ } /* namespace js */ diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index ff927c985429..64faf27c1989 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -722,23 +722,6 @@ js::Nursery::MinorGCCallback(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) *thingp = trc->nursery->moveToTenured(trc, static_cast(*thingp)); } -static void -CheckHashTablesAfterMovingGC(JSRuntime *rt) -{ -#ifdef JS_GC_ZEAL - if (rt->gcZeal() == ZealCheckHashTablesOnMinorGC) { - /* Check that internal hash tables no longer have any pointers into the nursery. */ - for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { - c->checkNewTypeObjectTableAfterMovingGC(); - c->checkInitialShapesTableAfterMovingGC(); - c->checkWrapperMapAfterMovingGC(); - if (c->debugScopes) - c->debugScopes->checkHashTablesAfterMovingGC(rt); - } - } -#endif -} - #ifdef PROFILE_NURSERY #define TIME_START(name) int64_t timstampStart_##name = PRMJ_Now() #define TIME_END(name) int64_t timstampEnd_##name = PRMJ_Now() @@ -810,7 +793,10 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList TIME_END(markGenericEntries); TIME_START(checkHashTables); - CheckHashTablesAfterMovingGC(rt); +#ifdef JS_GC_ZEAL + if (rt->gcZeal() == ZealCheckHashTablesOnMinorGC) + CheckHashTablesAfterMovingGC(rt); +#endif TIME_END(checkHashTables); TIME_START(markRuntime); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 6dbe8279dac5..c1e3b17c6468 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -210,7 +210,7 @@ class WrapperMapRef : public BufferableRef } }; -#ifdef JS_GC_ZEAL +#ifdef JSGC_HASH_TABLE_CHECKS void JSCompartment::checkWrapperMapAfterMovingGC() { @@ -221,9 +221,9 @@ JSCompartment::checkWrapperMapAfterMovingGC() */ for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { CrossCompartmentKey key = e.front().key(); - JS_ASSERT(!IsInsideNursery(key.debugger)); - JS_ASSERT(!IsInsideNursery(key.wrapped)); - JS_ASSERT(!IsInsideNursery(static_cast(e.front().value().get().toGCThing()))); + CheckGCThingAfterMovingGC(key.debugger); + CheckGCThingAfterMovingGC(key.wrapped); + CheckGCThingAfterMovingGC(static_cast(e.front().value().get().toGCThing())); WrapperMap::Ptr ptr = crossCompartmentWrappers.lookup(key); JS_ASSERT(ptr.found() && &*ptr == &e.front()); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index ffdc97eb6e58..6c71d0e91033 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -254,8 +254,9 @@ struct JSCompartment js::types::TypeObjectWithNewScriptSet newTypeObjects; js::types::TypeObjectWithNewScriptSet lazyTypeObjects; void sweepNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table); -#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL) - void checkNewTypeObjectTableAfterMovingGC(); +#ifdef JSGC_HASH_TABLE_CHECKS + void checkNewTypeObjectTablesAfterMovingGC(); + void checkNewTypeObjectTableAfterMovingGC(js::types::TypeObjectWithNewScriptSet &table); void checkInitialShapesTableAfterMovingGC(); void checkWrapperMapAfterMovingGC(); #endif diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index cdb24d24ac4e..706ba90584f6 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -5829,3 +5829,21 @@ JS::AutoAssertOnGC::VerifyIsSafeToGC(JSRuntime *rt) MOZ_CRASH("[AutoAssertOnGC] possible GC in GC-unsafe region"); } #endif + +#ifdef JSGC_HASH_TABLE_CHECKS +void +js::gc::CheckHashTablesAfterMovingGC(JSRuntime *rt) +{ + /* + * Check that internal hash tables no longer have any pointers to things + * that have been moved. + */ + for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { + c->checkNewTypeObjectTablesAfterMovingGC(); + c->checkInitialShapesTableAfterMovingGC(); + c->checkWrapperMapAfterMovingGC(); + if (c->debugScopes) + c->debugScopes->checkHashTablesAfterMovingGC(rt); + } +} +#endif diff --git a/js/src/jsgc.h b/js/src/jsgc.h index fdcf5ca8c687..d44ff381f1fc 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1279,6 +1279,31 @@ template inline T MaybeForwarded(T t) { return t; } #endif // JSGC_COMPACTING +#ifdef JSGC_HASH_TABLE_CHECKS + +template +inline void +CheckGCThingAfterMovingGC(T *t) +{ + JS_ASSERT_IF(t, !IsInsideNursery(t)); +#ifdef JSGC_COMPACTING + JS_ASSERT_IF(t, !IsForwarded(t)); +#endif +} + +inline void +CheckValueAfterMovingGC(const JS::Value& value) +{ + if (value.isObject()) + return CheckGCThingAfterMovingGC(&value.toObject()); + else if (value.isString()) + return CheckGCThingAfterMovingGC(value.toString()); + else if (value.isSymbol()) + return CheckGCThingAfterMovingGC(value.toSymbol()); +} + +#endif // JSGC_HASH_TABLE_CHECKS + const int ZealPokeValue = 1; const int ZealAllocValue = 2; const int ZealFrameGCValue = 3; diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 5d2bf9b26130..790794631c8a 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3887,28 +3887,6 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSFunction * return type; } -#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL) -void -JSCompartment::checkNewTypeObjectTableAfterMovingGC() -{ - /* - * Assert that the postbarriers have worked and that nothing is left in - * newTypeObjects that points into the nursery, and that the hash table - * entries are discoverable. - */ - for (TypeObjectWithNewScriptSet::Enum e(newTypeObjects); !e.empty(); e.popFront()) { - TypeObjectWithNewScriptEntry entry = e.front(); - JS_ASSERT(!IsInsideNursery(entry.newFunction)); - TaggedProto proto = entry.object->proto(); - JS_ASSERT_IF(proto.isObject(), !IsInsideNursery(proto.toObject())); - TypeObjectWithNewScriptEntry::Lookup - lookup(entry.object->clasp(), proto, entry.newFunction); - TypeObjectWithNewScriptSet::Ptr ptr = newTypeObjects.lookup(lookup); - JS_ASSERT(ptr.found() && &*ptr == &e.front()); - } -} -#endif - TypeObject * ExclusiveContext::getSingletonType(const Class *clasp, TaggedProto proto) { @@ -4220,6 +4198,42 @@ JSCompartment::sweepNewTypeObjectTable(TypeObjectWithNewScriptSet &table) } } +#ifdef JSGC_HASH_TABLE_CHECKS + +void +JSCompartment::checkNewTypeObjectTablesAfterMovingGC() +{ + checkNewTypeObjectTableAfterMovingGC(newTypeObjects); + checkNewTypeObjectTableAfterMovingGC(lazyTypeObjects); +} + +void +JSCompartment::checkNewTypeObjectTableAfterMovingGC(TypeObjectWithNewScriptSet &table) +{ + /* + * Assert that nothing points into the nursery or needs to be relocated, and + * that the hash table entries are discoverable. + */ + if (!table.initialized()) + return; + + for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) { + TypeObjectWithNewScriptEntry entry = e.front(); + CheckGCThingAfterMovingGC(entry.object.get()); + TaggedProto proto = entry.object->proto(); + if (proto.isObject()) + CheckGCThingAfterMovingGC(proto.toObject()); + CheckGCThingAfterMovingGC(entry.newFunction); + + TypeObjectWithNewScriptEntry::Lookup + lookup(entry.object->clasp(), proto, entry.newFunction); + TypeObjectWithNewScriptSet::Ptr ptr = table.lookup(lookup); + JS_ASSERT(ptr.found() && &*ptr == &e.front()); + } +} + +#endif // JSGC_HASH_TABLE_CHECKS + TypeCompartment::~TypeCompartment() { js_delete(arrayTypeTable); diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 576fa4134cf2..86145d0afe7f 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -25,6 +25,11 @@ # define JSGC_TRACK_EXACT_ROOTS #endif +#if (defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)) || \ + (defined(JSGC_COMPACTING) && defined(DEBUG)) +# define JSGC_HASH_TABLE_CHECKS +#endif + namespace JS { class AutoIdVector; diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 0d3ae2b4f0f5..c882e4f44b4b 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1801,7 +1801,7 @@ DebugScopes::sweep(JSRuntime *rt) } } -#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL) +#ifdef JSGC_HASH_TABLE_CHECKS void DebugScopes::checkHashTablesAfterMovingGC(JSRuntime *runtime) { @@ -1811,18 +1811,18 @@ DebugScopes::checkHashTablesAfterMovingGC(JSRuntime *runtime) * pointing into the nursery. */ for (ObjectWeakMap::Range r = proxiedScopes.all(); !r.empty(); r.popFront()) { - JS_ASSERT(!IsInsideNursery(r.front().key().get())); - JS_ASSERT(!IsInsideNursery(r.front().value().get())); + CheckGCThingAfterMovingGC(r.front().key().get()); + CheckGCThingAfterMovingGC(r.front().value().get()); } for (MissingScopeMap::Range r = missingScopes.all(); !r.empty(); r.popFront()) { - JS_ASSERT(!IsInsideNursery(r.front().key().cur())); - JS_ASSERT(!IsInsideNursery(r.front().key().staticScope())); - JS_ASSERT(!IsInsideNursery(r.front().value().get())); + CheckGCThingAfterMovingGC(r.front().key().cur()); + CheckGCThingAfterMovingGC(r.front().key().staticScope()); + CheckGCThingAfterMovingGC(r.front().value().get()); } for (LiveScopeMap::Range r = liveScopes.all(); !r.empty(); r.popFront()) { - JS_ASSERT(!IsInsideNursery(r.front().key())); - JS_ASSERT(!IsInsideNursery(r.front().value().cur_.get())); - JS_ASSERT(!IsInsideNursery(r.front().value().staticScope_.get())); + CheckGCThingAfterMovingGC(r.front().key()); + CheckGCThingAfterMovingGC(r.front().value().cur_.get()); + CheckGCThingAfterMovingGC(r.front().value().staticScope_.get()); } } #endif diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index e683548c25b6..247a186f0967 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1652,7 +1652,10 @@ class InitialShapeSetRef : public BufferableRef } }; -#ifdef JS_GC_ZEAL +#endif // JSGC_GENERATIONAL + +#ifdef JSGC_HASH_TABLE_CHECKS + void JSCompartment::checkInitialShapesTableAfterMovingGC() { @@ -1669,9 +1672,12 @@ JSCompartment::checkInitialShapesTableAfterMovingGC() TaggedProto proto = entry.proto; Shape *shape = entry.shape.get(); - JS_ASSERT_IF(proto.isObject(), !IsInsideNursery(proto.toObject())); - JS_ASSERT_IF(shape->getObjectParent(), !IsInsideNursery(shape->getObjectParent())); - JS_ASSERT_IF(shape->getObjectMetadata(), !IsInsideNursery(shape->getObjectMetadata())); + if (proto.isObject()) + CheckGCThingAfterMovingGC(proto.toObject()); + if (shape->getObjectParent()) + CheckGCThingAfterMovingGC(shape->getObjectParent()); + if (shape->getObjectMetadata()) + CheckGCThingAfterMovingGC(shape->getObjectMetadata()); InitialShapeEntry::Lookup lookup(shape->getObjectClass(), proto, @@ -1683,9 +1689,8 @@ JSCompartment::checkInitialShapesTableAfterMovingGC() JS_ASSERT(ptr.found() && &*ptr == &e.front()); } } -#endif -#endif +#endif // JSGC_HASH_TABLE_CHECKS /* static */ Shape * EmptyShape::getInitialShape(ExclusiveContext *cx, const Class *clasp, TaggedProto proto, From d48fac5c81fe10bc670a564b1abfa3e2797dc1d0 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:46:46 +0100 Subject: [PATCH 008/119] Bug 650161 - Use the invocation kind passed to the first slice for the whole GC r=terrence --- js/src/gc/GCRuntime.h | 10 ++++++---- js/src/jsgc.cpp | 22 +++++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index b9f7a03caa98..6d1d5dc88cdf 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -424,7 +424,7 @@ class GCRuntime bool isGcNeeded() { return isNeeded; } double computeHeapGrowthFactor(size_t lastBytes); - size_t computeTriggerBytes(double growthFactor, size_t lastBytes, JSGCInvocationKind gckind); + size_t computeTriggerBytes(double growthFactor, size_t lastBytes); JSGCMode gcMode() const { return mode; } void setGCMode(JSGCMode m) { @@ -475,8 +475,7 @@ class GCRuntime gcstats::ZoneGCStats scanZonesBeforeGC(); void budgetIncrementalGC(int64_t *budget); void resetIncrementalGC(const char *reason); - void incrementalCollectSlice(int64_t budget, JS::gcreason::Reason reason, - JSGCInvocationKind gckind); + void incrementalCollectSlice(int64_t budget, JS::gcreason::Reason reason); void pushZealSelectedObjects(); bool beginMarkPhase(JS::gcreason::Reason reason); bool shouldPreserveJITCode(JSCompartment *comp, int64_t currentTime, @@ -496,7 +495,7 @@ class GCRuntime bool shouldReleaseObservedTypes(); void endSweepingZoneGroup(); bool sweepPhase(SliceBudget &sliceBudget); - void endSweepPhase(JSGCInvocationKind gckind, bool lastGC); + void endSweepPhase(bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); void decommitArenasFromAvailableList(Chunk **availableListHeadp); void decommitArenas(); @@ -612,6 +611,9 @@ class GCRuntime /* Whether all compartments are being collected in first GC slice. */ bool isFull; + /* The invocation kind of the current GC, taken from the first slice. */ + JSGCInvocationKind invocationKind; + /* The reason that an interrupt-triggered GC should be called. */ JS::gcreason::Reason triggerReason; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 706ba90584f6..24c7a6b7b6bc 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -4388,7 +4388,7 @@ GCRuntime::sweepPhase(SliceBudget &sliceBudget) } void -GCRuntime::endSweepPhase(JSGCInvocationKind gckind, bool lastGC) +GCRuntime::endSweepPhase(bool lastGC) { gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP); FreeOp fop(rt); @@ -4460,7 +4460,7 @@ GCRuntime::endSweepPhase(JSGCInvocationKind gckind, bool lastGC) * Expire needs to unlock it for other callers. */ AutoLockGC lock(rt); - expireChunksAndArenas(gckind == GC_SHRINK); + expireChunksAndArenas(invocationKind == GC_SHRINK); } } @@ -4502,7 +4502,8 @@ GCRuntime::endSweepPhase(JSGCInvocationKind gckind, bool lastGC) schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - zone->threshold.updateAfterGC(zone->usage.gcBytes(), gckind, tunables, schedulingState); + zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables, + schedulingState); if (zone->isCollecting()) { JS_ASSERT(zone->isGCFinished()); zone->setGCState(Zone::NoGC); @@ -4653,7 +4654,7 @@ GCRuntime::resetIncrementalGC(const char *reason) /* Finish sweeping the current zone group, then abort. */ abortSweepAfterCurrentGroup = true; - incrementalCollectSlice(SliceBudget::Unlimited, JS::gcreason::RESET, GC_NORMAL); + incrementalCollectSlice(SliceBudget::Unlimited, JS::gcreason::RESET); { gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD); @@ -4751,8 +4752,7 @@ GCRuntime::pushZealSelectedObjects() void GCRuntime::incrementalCollectSlice(int64_t budget, - JS::gcreason::Reason reason, - JSGCInvocationKind gckind) + JS::gcreason::Reason reason) { JS_ASSERT(rt->currentThreadHasExclusiveAccess()); @@ -4865,10 +4865,10 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (!finished) break; - endSweepPhase(gckind, lastGC); + endSweepPhase(lastGC); if (sweepOnBackgroundThread) - helperState.startBackgroundSweep(gckind == GC_SHRINK); + helperState.startBackgroundSweep(invocationKind == GC_SHRINK); incrementalState = NO_INCREMENTAL; break; @@ -5031,7 +5031,11 @@ GCRuntime::gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind, TraceMajorGCStart(); - incrementalCollectSlice(budget, reason, gckind); + /* Set the invocation kind in the first slice. */ + if (incrementalState == NO_INCREMENTAL) + invocationKind = gckind; + + incrementalCollectSlice(budget, reason); #ifndef JS_MORE_DETERMINISTIC nextFullGCTime = PRMJ_Now() + GC_IDLE_FULL_SPAN; From 5b1c8897ed8faa3840a2e5f3c7184fe3fe25df43 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 5 Jun 2012 11:47:42 -0700 Subject: [PATCH 009/119] Bug 650161 - Update pointers to relocated objects r=terrence --- js/public/HashTable.h | 1 + js/src/builtin/TypedObject.cpp | 40 ++++++++++++++++--- js/src/builtin/TypedObject.h | 20 ++++++++++ js/src/gc/GCRuntime.h | 5 +++ js/src/gc/Marking.cpp | 59 +++++++++++++++++++-------- js/src/gc/Zone.cpp | 7 ++-- js/src/gc/Zone.h | 8 +++- js/src/jscntxt.cpp | 17 +++++--- js/src/jscntxt.h | 14 +++++++ js/src/jscompartment.cpp | 61 +++++++++++++++++++++++++++- js/src/jscompartment.h | 8 ++++ js/src/jsgc.h | 5 ++- js/src/jsinfer.cpp | 68 +++++++++++++++++++++++-------- js/src/jsiter.cpp | 2 + js/src/jspropertytree.cpp | 71 +++++++++++++++++++++++++++++++++ js/src/jspropertytree.h | 2 +- js/src/jsproxy.cpp | 3 +- js/src/jsscript.cpp | 2 +- js/src/jswrapper.cpp | 5 +++ js/src/vm/ArrayBufferObject.cpp | 25 +++++++++--- js/src/vm/Debugger.cpp | 6 +-- js/src/vm/Debugger.h | 3 ++ js/src/vm/Runtime.h | 3 +- js/src/vm/ScopeObject.cpp | 20 ++++++++-- js/src/vm/ScopeObject.h | 3 ++ js/src/vm/Shape-inl.h | 9 +++++ js/src/vm/Shape.cpp | 71 ++++++++++++++++++++++++++++++++- js/src/vm/Shape.h | 20 +++++++++- 28 files changed, 489 insertions(+), 69 deletions(-) diff --git a/js/public/HashTable.h b/js/public/HashTable.h index f8d91ef092ea..b958c8e9cc42 100644 --- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -959,6 +959,7 @@ class HashTable : private AllocPolicy // a new key at the new Lookup position. |front()| is invalid after // this operation until the next call to |popFront()|. void rekeyFront(const Lookup &l, const Key &k) { + JS_ASSERT(&k != &HashPolicy::getKey(this->cur->get())); Ptr p(*this->cur, table_); table_.rekeyWithoutRehash(p, l, k); rekeyed = true; diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index b52f6d835510..412cbebf99f7 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -1126,6 +1126,14 @@ StructTypeDescr::fieldCount() const return getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject().getDenseInitializedLength(); } +size_t +StructTypeDescr::maybeForwardedFieldCount() const +{ + JSObject *fieldNames = + MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject()); + return fieldNames->getDenseInitializedLength(); +} + bool StructTypeDescr::fieldIndex(jsid id, size_t *out) const { @@ -1157,6 +1165,15 @@ StructTypeDescr::fieldOffset(size_t index) const return SafeCast(fieldOffsets.getDenseElement(index).toInt32()); } +size_t +StructTypeDescr::maybeForwardedFieldOffset(size_t index) const +{ + JSObject &fieldOffsets = + *MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS).toObject()); + JS_ASSERT(index < fieldOffsets.getDenseInitializedLength()); + return SafeCast(fieldOffsets.getDenseElement(index).toInt32()); +} + SizedTypeDescr& StructTypeDescr::fieldDescr(size_t index) const { @@ -1166,6 +1183,15 @@ StructTypeDescr::fieldDescr(size_t index) const return fieldDescrs.getDenseElement(index).toObject().as(); } +SizedTypeDescr& +StructTypeDescr::maybeForwardedFieldDescr(size_t index) const +{ + JSObject &fieldDescrs = + *MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES).toObject()); + JS_ASSERT(index < fieldDescrs.getDenseInitializedLength()); + return fieldDescrs.getDenseElement(index).toObject().as(); +} + /****************************************************************************** * Creating the TypedObject "module" * @@ -1630,7 +1656,11 @@ TypedObject::obj_trace(JSTracer *trace, JSObject *object) JS_ASSERT(object->is()); TypedObject &typedObj = object->as(); - TypeDescr &descr = typedObj.typeDescr(); + + // When this is called for compacting GC, the related objects we touch here + // may not have had their slots updated yet. + TypeDescr &descr = typedObj.maybeForwardedTypeDescr(); + if (descr.opaque()) { uint8_t *mem = typedObj.typedMem(); if (!mem) @@ -3092,7 +3122,7 @@ visitReferences(SizedTypeDescr &descr, case type::SizedArray: { SizedArrayTypeDescr &arrayDescr = descr.as(); - SizedTypeDescr &elementDescr = arrayDescr.elementType(); + SizedTypeDescr &elementDescr = arrayDescr.maybeForwardedElementType(); for (int32_t i = 0; i < arrayDescr.length(); i++) { visitReferences(elementDescr, mem, visitor); mem += elementDescr.size(); @@ -3108,9 +3138,9 @@ visitReferences(SizedTypeDescr &descr, case type::Struct: { StructTypeDescr &structDescr = descr.as(); - for (size_t i = 0; i < structDescr.fieldCount(); i++) { - SizedTypeDescr &descr = structDescr.fieldDescr(i); - size_t offset = structDescr.fieldOffset(i); + for (size_t i = 0; i < structDescr.maybeForwardedFieldCount(); i++) { + SizedTypeDescr &descr = structDescr.maybeForwardedFieldDescr(i); + size_t offset = structDescr.maybeForwardedFieldOffset(i); visitReferences(descr, mem + offset, visitor); } return; diff --git a/js/src/builtin/TypedObject.h b/js/src/builtin/TypedObject.h index bfc59e0d4f05..78cbcfbbcf13 100644 --- a/js/src/builtin/TypedObject.h +++ b/js/src/builtin/TypedObject.h @@ -169,6 +169,10 @@ class TypedProto : public JSObject return getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject().as(); } + TypeDescr &maybeForwardedTypeDescr() const { + return MaybeForwarded(&getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject())->as(); + } + inline type::Kind kind() const; }; @@ -453,6 +457,11 @@ class SizedArrayTypeDescr : public ComplexTypeDescr return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as(); } + SizedTypeDescr &maybeForwardedElementType() const { + JSObject *elemType = &getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject(); + return MaybeForwarded(elemType)->as(); + } + int32_t length() const { return getReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH).toInt32(); } @@ -492,6 +501,7 @@ class StructTypeDescr : public ComplexTypeDescr // Returns the number of fields defined in this struct. size_t fieldCount() const; + size_t maybeForwardedFieldCount() const; // Set `*out` to the index of the field named `id` and returns true, // or return false if no such field exists. @@ -502,9 +512,11 @@ class StructTypeDescr : public ComplexTypeDescr // Return the type descr of the field at index `index`. SizedTypeDescr &fieldDescr(size_t index) const; + SizedTypeDescr &maybeForwardedFieldDescr(size_t index) const; // Return the offset of the field at index `index`. size_t fieldOffset(size_t index) const; + size_t maybeForwardedFieldOffset(size_t index) const; }; typedef Handle HandleStructTypeDescr; @@ -678,10 +690,18 @@ class TypedObject : public ArrayBufferViewObject return getProto()->as(); } + TypedProto &maybeForwardedTypedProto() const { + return MaybeForwarded(getProto())->as(); + } + TypeDescr &typeDescr() const { return typedProto().typeDescr(); } + TypeDescr &maybeForwardedTypeDescr() const { + return maybeForwardedTypedProto().maybeForwardedTypeDescr(); + } + uint8_t *typedMem() const { return (uint8_t*) getPrivate(); } diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 6d1d5dc88cdf..e66033129051 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -262,6 +262,11 @@ class GCRuntime bool isHeapMajorCollecting() { return heapState == js::MajorCollecting; } bool isHeapMinorCollecting() { return heapState == js::MinorCollecting; } bool isHeapCollecting() { return isHeapMajorCollecting() || isHeapMinorCollecting(); } +#ifdef JSGC_COMPACTING + bool isHeapCompacting() { return isHeapMajorCollecting() && state() == COMPACT; } +#else + bool isHeapCompacting() { return false; } +#endif // Performance note: if isFJMinorCollecting turns out to be slow because // reading the counter is slow then we may be able to augment the counter diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 073704606d66..4e4f2e8a0d47 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -164,6 +164,10 @@ CheckMarkedThing(JSTracer *trc, T **thingp) T *thing = *thingp; JS_ASSERT(*thingp); +#ifdef JSGC_COMPACTING + thing = MaybeForwarded(thing); +#endif + # ifdef JSGC_FJGENERATIONAL /* * The code below (runtimeFromMainThread(), etc) makes assumptions @@ -442,6 +446,10 @@ IsMarked(T **thingp) Zone *zone = (*thingp)->tenuredZone(); if (!zone->isCollecting() || zone->isGCFinished()) return true; +#ifdef JSGC_COMPACTING + if (zone->isGCCompacting() && IsForwarded(*thingp)) + *thingp = Forwarded(*thingp); +#endif return (*thingp)->isMarked(); } @@ -480,19 +488,27 @@ IsAboutToBeFinalized(T **thingp) } #endif // JSGC_GENERATIONAL - if (!thing->tenuredZone()->isGCSweeping()) + Zone *zone = thing->tenuredZone(); + if (zone->isGCSweeping()) { + /* + * We should return false for things that have been allocated during + * incremental sweeping, but this possibility doesn't occur at the moment + * because this function is only called at the very start of the sweeping a + * compartment group and during minor gc. Rather than do the extra check, + * we just assert that it's not necessary. + */ + JS_ASSERT_IF(!rt->isHeapMinorCollecting(), !thing->arenaHeader()->allocatedDuringIncremental); + + return !thing->isMarked(); + } +#ifdef JSGC_COMPACTING + else if (zone->isGCCompacting() && IsForwarded(thing)) { + *thingp = Forwarded(thing); return false; + } +#endif - /* - * We should return false for things that have been allocated during - * incremental sweeping, but this possibility doesn't occur at the moment - * because this function is only called at the very start of the sweeping a - * compartment group and during minor gc. Rather than do the extra check, - * we just assert that it's not necessary. - */ - JS_ASSERT_IF(!rt->isHeapMinorCollecting(), !thing->arenaHeader()->allocatedDuringIncremental); - - return !thing->isMarked(); + return false; } template @@ -500,21 +516,32 @@ T * UpdateIfRelocated(JSRuntime *rt, T **thingp) { JS_ASSERT(thingp); + if (!*thingp) + return nullptr; + #ifdef JSGC_GENERATIONAL + #ifdef JSGC_FJGENERATIONAL - if (*thingp && rt->isFJMinorCollecting()) { + if (rt->isFJMinorCollecting()) { ForkJoinContext *ctx = ForkJoinContext::current(); ForkJoinNursery &nursery = ctx->nursery(); if (nursery.isInsideFromspace(*thingp)) nursery.getForwardedPointer(thingp); + return *thingp; } - else #endif - { - if (*thingp && rt->isHeapMinorCollecting() && IsInsideNursery(*thingp)) - rt->gc.nursery.getForwardedPointer(thingp); + + if (rt->isHeapMinorCollecting() && IsInsideNursery(*thingp)) { + rt->gc.nursery.getForwardedPointer(thingp); + return *thingp; } #endif // JSGC_GENERATIONAL + +#ifdef JSGC_COMPACTING + Zone *zone = (*thingp)->tenuredZone(); + if (zone->isGCCompacting() && IsForwarded(*thingp)) + *thingp = Forwarded(*thingp); +#endif return *thingp; } diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 0bf676576bd6..fa6104768a8c 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -135,10 +135,10 @@ Zone::sweepBreakpoints(FreeOp *fop) gcstats::AutoPhase ap1(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES); gcstats::AutoPhase ap2(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES_BREAKPOINT); - JS_ASSERT(isGCSweeping()); + JS_ASSERT(isGCSweepingOrCompacting()); for (ZoneCellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); - JS_ASSERT(script->zone()->isGCSweeping()); + JS_ASSERT_IF(isGCSweeping(), script->zone()->isGCSweeping()); if (!script->hasAnyBreakpointsOrStepMode()) continue; @@ -153,7 +153,8 @@ Zone::sweepBreakpoints(FreeOp *fop) for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) { nextbp = bp->nextInSite(); HeapPtrObject &dbgobj = bp->debugger->toJSObjectRef(); - JS_ASSERT_IF(dbgobj->zone()->isCollecting(), dbgobj->zone()->isGCSweeping()); + JS_ASSERT_IF(isGCSweeping() && dbgobj->zone()->isCollecting(), + dbgobj->zone()->isGCSweeping()); bool dying = scriptGone || IsObjectAboutToBeFinalized(&dbgobj); JS_ASSERT_IF(!dying, !IsAboutToBeFinalized(&bp->getHandlerRef())); if (dying) diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 0f3318da4cd9..1749052518df 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -175,7 +175,8 @@ struct Zone : public JS::shadow::Zone, Mark, MarkGray, Sweep, - Finished + Finished, + Compact }; void setGCState(GCState state) { JS_ASSERT(runtimeFromMainThread()->isHeapBusy()); @@ -193,7 +194,8 @@ struct Zone : public JS::shadow::Zone, // If this returns true, all object tracing must be done with a GC marking // tracer. bool requireGCTracer() const { - return runtimeFromMainThread()->isHeapMajorCollecting() && gcState_ != NoGC; + JSRuntime *rt = runtimeFromMainThread(); + return rt->isHeapMajorCollecting() && !rt->isHeapCompacting() && gcState_ != NoGC; } bool isGCMarking() { @@ -208,6 +210,8 @@ struct Zone : public JS::shadow::Zone, bool isGCMarkingGray() { return gcState_ == MarkGray; } bool isGCSweeping() { return gcState_ == Sweep; } bool isGCFinished() { return gcState_ == Finished; } + bool isGCCompacting() { return gcState_ == Compact; } + bool isGCSweepingOrCompacting() { return gcState_ == Sweep || gcState_ == Compact; } // Get a number that is incremented whenever this zone is collected, and // possibly at other times too. diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e6aa3c0c2cb0..eb4cf1c38759 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -87,10 +87,11 @@ void js::TraceCycleDetectionSet(JSTracer *trc, js::ObjectSet &set) { for (js::ObjectSet::Enum e(set); !e.empty(); e.popFront()) { - JSObject *prior = e.front(); - MarkObjectRoot(trc, const_cast(&e.front()), "cycle detector table entry"); - if (prior != e.front()) - e.rekeyFront(e.front()); + JSObject *key = e.front(); + trc->setTracingLocation((void *)&e.front()); + MarkObjectRoot(trc, &key, "cycle detector table entry"); + if (key != e.front()) + e.rekeyFront(key); } } @@ -100,9 +101,13 @@ JSCompartment::sweepCallsiteClones() if (callsiteClones.initialized()) { for (CallsiteCloneTable::Enum e(callsiteClones); !e.empty(); e.popFront()) { CallsiteCloneKey key = e.front().key(); - JSFunction *fun = e.front().value(); - if (!IsScriptMarked(&key.script) || !IsObjectMarked(&fun)) + if (IsObjectAboutToBeFinalized(&key.original) || IsScriptAboutToBeFinalized(&key.script) || + IsObjectAboutToBeFinalized(e.front().value().unsafeGet())) + { e.removeFront(); + } else if (key != e.front().key()) { + e.rekeyFront(key); + } } } } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 734ee731f1ec..93bb160c8e34 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -49,6 +49,14 @@ struct CallsiteCloneKey { CallsiteCloneKey(JSFunction *f, JSScript *s, uint32_t o) : original(f), script(s), offset(o) {} + bool operator==(const CallsiteCloneKey& other) { + return original == other.original && script == other.script && offset == other.offset; + } + + bool operator!=(const CallsiteCloneKey& other) { + return !(*this == other); + } + typedef CallsiteCloneKey Lookup; static inline uint32_t hash(CallsiteCloneKey key) { @@ -58,6 +66,12 @@ struct CallsiteCloneKey { static inline bool match(const CallsiteCloneKey &a, const CallsiteCloneKey &b) { return a.script == b.script && a.offset == b.offset && a.original == b.original; } + + static void rekey(CallsiteCloneKey &k, const CallsiteCloneKey &newKey) { + k.original = newKey.original; + k.script = newKey.script; + k.offset = newKey.offset; + } }; typedef HashMapgc.stats, + gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); + sweepNewTypeObjectTable(newTypeObjects); + sweepNewTypeObjectTable(lazyTypeObjects); + } sweepCallsiteClones(); savedStacks_.sweep(rt); @@ -656,6 +660,59 @@ JSCompartment::sweepCrossCompartmentWrappers() } } +#ifdef JSGC_COMPACTING + +/* + * Fixup wrappers with moved keys or values. + */ +void +JSCompartment::fixupCrossCompartmentWrappers(JSTracer *trc) +{ + for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { + Value val = e.front().value(); + if (IsForwarded(val)) { + val = Forwarded(val); + e.front().value().set(val); + } + + // CrossCompartmentKey's hash does not depend on the debugger object, + // so update it but do not rekey if it changes + CrossCompartmentKey key = e.front().key(); + if (key.debugger) + key.debugger = MaybeForwarded(key.debugger); + if (key.wrapped && IsForwarded(key.wrapped)) { + key.wrapped = Forwarded(key.wrapped); + e.rekeyFront(key, key); + } + + if (!zone()->isCollecting() && val.isObject()) { + // Call the trace hook to update any pointers to relocated things. + JSObject *obj = &val.toObject(); + const Class *clasp = obj->getClass(); + if (clasp->trace) + clasp->trace(trc, obj); + } + } +} + +void JSCompartment::fixupAfterMovingGC() +{ + fixupGlobal(); + fixupNewTypeObjectTable(newTypeObjects); + fixupNewTypeObjectTable(lazyTypeObjects); + fixupInitialShapeTable(); +} + +void +JSCompartment::fixupGlobal() +{ + GlobalObject *global = *global_.unsafeGet(); + if (global) + global_.set(MaybeForwarded(global)); +} + +#endif // JSGC_COMPACTING + void JSCompartment::purge() { diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 6c71d0e91033..bb03696fbcea 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -347,6 +347,14 @@ struct JSCompartment void purge(); void clearTables(); +#ifdef JSGC_COMPACTING + void fixupInitialShapeTable(); + void fixupNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table); + void fixupCrossCompartmentWrappers(JSTracer *trc); + void fixupAfterMovingGC(); + void fixupGlobal(); +#endif + bool hasObjectMetadataCallback() const { return objectMetadataCallback; } void setObjectMetadataCallback(js::ObjectMetadataCallback callback); void forgetObjectMetadataCallback() { diff --git a/js/src/jsgc.h b/js/src/jsgc.h index d44ff381f1fc..05c825c83919 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -47,7 +47,9 @@ enum State { MARK_ROOTS, MARK, SWEEP, - INVALID +#ifdef JSGC_COMPACTING + COMPACT +#endif }; static inline JSGCTraceKind @@ -1275,6 +1277,7 @@ MaybeForwarded(T t) #else template inline bool IsForwarded(T t) { return false; } +template inline T Forwarded(T t) { return t; } template inline T MaybeForwarded(T t) { return t; } #endif // JSGC_COMPACTING diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 790794631c8a..275a288705f0 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3440,12 +3440,13 @@ types::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args } static inline bool -IsAboutToBeFinalized(TypeObjectKey *key) +IsAboutToBeFinalized(TypeObjectKey **keyp) { /* Mask out the low bit indicating whether this is a type or JS object. */ - gc::Cell *tmp = reinterpret_cast(uintptr_t(key) & ~1); + uintptr_t flagBit = uintptr_t(*keyp) & 1; + gc::Cell *tmp = reinterpret_cast(uintptr_t(*keyp) & ~1); bool isAboutToBeFinalized = IsCellAboutToBeFinalized(&tmp); - JS_ASSERT(tmp == reinterpret_cast(uintptr_t(key) & ~1)); + *keyp = reinterpret_cast(uintptr_t(tmp) | flagBit); return isAboutToBeFinalized; } @@ -3943,7 +3944,7 @@ ConstraintTypeSet::sweep(Zone *zone, bool *oom) objectCount = 0; for (unsigned i = 0; i < oldCapacity; i++) { TypeObjectKey *object = oldArray[i]; - if (object && !IsAboutToBeFinalized(object)) { + if (object && !IsAboutToBeFinalized(&object)) { TypeObjectKey **pentry = HashSetInsert (zone->types.typeLifoAlloc, objectSet, objectCount, object); @@ -3961,9 +3962,11 @@ ConstraintTypeSet::sweep(Zone *zone, bool *oom) setBaseObjectCount(objectCount); } else if (objectCount == 1) { TypeObjectKey *object = (TypeObjectKey *) objectSet; - if (IsAboutToBeFinalized(object)) { + if (IsAboutToBeFinalized(&object)) { objectSet = nullptr; setBaseObjectCount(0); + } else { + objectSet = reinterpret_cast(object); } } @@ -4177,26 +4180,59 @@ TypeCompartment::sweep(FreeOp *fop) void JSCompartment::sweepNewTypeObjectTable(TypeObjectWithNewScriptSet &table) { - gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, - gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); - - JS_ASSERT(zone()->isGCSweeping()); + JS_ASSERT(zone()->isCollecting()); if (table.initialized()) { for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) { TypeObjectWithNewScriptEntry entry = e.front(); - if (IsTypeObjectAboutToBeFinalized(entry.object.unsafeGet())) { + if (IsTypeObjectAboutToBeFinalized(entry.object.unsafeGet()) || + (entry.newFunction && IsObjectAboutToBeFinalized(&entry.newFunction))) + { e.removeFront(); - } else if (entry.newFunction && IsObjectAboutToBeFinalized(&entry.newFunction)) { - e.removeFront(); - } else if (entry.object.unbarrieredGet() != e.front().object.unbarrieredGet()) { + } else { + /* Any rekeying necessary is handled by fixupNewTypeObjectTable() below. */ + JS_ASSERT(entry.object == e.front().object); + JS_ASSERT(entry.newFunction == e.front().newFunction); + } + } + } +} + +#ifdef JSGC_COMPACTING +void +JSCompartment::fixupNewTypeObjectTable(TypeObjectWithNewScriptSet &table) +{ + /* + * Each entry's hash depends on the object's prototype and we can't tell + * whether that has been moved or not in sweepNewTypeObjectTable(). + */ + JS_ASSERT(zone()->isCollecting()); + if (table.initialized()) { + for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) { + TypeObjectWithNewScriptEntry entry = e.front(); + bool needRekey = false; + if (IsForwarded(entry.object.get())) { + entry.object.set(Forwarded(entry.object.get())); + needRekey = true; + } + TaggedProto proto = entry.object->proto(); + if (proto.isObject() && IsForwarded(proto.toObject())) { + proto = TaggedProto(Forwarded(proto.toObject())); + needRekey = true; + } + if (entry.newFunction && IsForwarded(entry.newFunction)) { + entry.newFunction = Forwarded(entry.newFunction); + needRekey = true; + } + if (needRekey) { TypeObjectWithNewScriptSet::Lookup lookup(entry.object->clasp(), - entry.object->proto(), + proto, entry.newFunction); e.rekeyFront(lookup, entry); } } } } +#endif #ifdef JSGC_HASH_TABLE_CHECKS @@ -4245,7 +4281,7 @@ TypeCompartment::~TypeCompartment() TypeScript::Sweep(FreeOp *fop, JSScript *script, bool *oom) { JSCompartment *compartment = script->compartment(); - JS_ASSERT(compartment->zone()->isGCSweeping()); + JS_ASSERT(compartment->zone()->isGCSweepingOrCompacting()); unsigned num = NumTypeSets(script); StackTypeSet *typeArray = script->types->typeArray(); @@ -4324,7 +4360,7 @@ TypeZone::~TypeZone() void TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) { - JS_ASSERT(zone()->isGCSweeping()); + JS_ASSERT(zone()->isGCSweepingOrCompacting()); JSRuntime *rt = fop->runtime(); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 17dba45ac105..d9688403f955 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1571,6 +1571,8 @@ FinalizeGenerator(FreeOp *fop, JSObject *obj) static void MarkGeneratorFrame(JSTracer *trc, JSGenerator *gen) { + gen->obj = MaybeForwarded(gen->obj.get()); + MarkObject(trc, &gen->obj, "Generator Object"); MarkValueRange(trc, HeapValueify(gen->fp->generatorArgsSnapshotBegin()), HeapValueify(gen->fp->generatorArgsSnapshotEnd()), diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index c6656f40c872..8c338e22b3ce 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -17,6 +17,7 @@ #include "vm/Shape-inl.h" using namespace js; +using namespace js::gc; inline HashNumber ShapeHasher::hash(const Lookup &l) @@ -268,6 +269,76 @@ Shape::finalize(FreeOp *fop) fop->delete_(kids.toHash()); } +#ifdef JSGC_COMPACTING + +void +Shape::fixupDictionaryShapeAfterMovingGC() +{ + if (!listp) + return; + + JS_ASSERT(!IsInsideNursery(reinterpret_cast(listp))); + AllocKind kind = reinterpret_cast(listp)->tenuredGetAllocKind(); + JS_ASSERT(kind == FINALIZE_SHAPE || kind <= FINALIZE_OBJECT_LAST); + if (kind == FINALIZE_SHAPE) { + // listp points to the parent field of the next shape. + Shape *next = reinterpret_cast(uintptr_t(listp) - + offsetof(Shape, parent)); + listp = &gc::MaybeForwarded(next)->parent; + } else { + // listp points to the shape_ field of an object. + JSObject *last = reinterpret_cast(uintptr_t(listp) - + offsetof(JSObject, shape_)); + listp = &gc::MaybeForwarded(last)->shape_; + } +} + +void +Shape::fixupShapeTreeAfterMovingGC() +{ + if (kids.isNull()) + return; + + if (kids.isShape()) { + if (gc::IsForwarded(kids.toShape())) + kids.setShape(gc::Forwarded(kids.toShape())); + return; + } + + JS_ASSERT(kids.isHash()); + KidsHash *kh = kids.toHash(); + for (KidsHash::Enum e(*kh); !e.empty(); e.popFront()) { + Shape *key = e.front(); + if (!IsForwarded(key)) + continue; + + key = Forwarded(key); + BaseShape *base = key->base(); + if (IsForwarded(base)) + base = Forwarded(base); + UnownedBaseShape *unowned = base->unowned(); + if (IsForwarded(unowned)) + unowned = Forwarded(unowned); + StackShape lookup(unowned, + const_cast(key)->propidRef(), + key->slotInfo & Shape::SLOT_MASK, + key->attrs, + key->flags); + e.rekeyFront(lookup, key); + } +} + +void +Shape::fixupAfterMovingGC() +{ + if (inDictionary()) + fixupDictionaryShapeAfterMovingGC(); + else + fixupShapeTreeAfterMovingGC(); +} + +#endif // JSGC_COMPACTING + #ifdef DEBUG void diff --git a/js/src/jspropertytree.h b/js/src/jspropertytree.h index 40b509be9ab8..f0c526cdc832 100644 --- a/js/src/jspropertytree.h +++ b/js/src/jspropertytree.h @@ -17,7 +17,7 @@ namespace js { class Shape; struct StackShape; -struct ShapeHasher { +struct ShapeHasher : public DefaultHasher { typedef Shape *Key; typedef StackShape Lookup; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 1fdfdc4f0131..ae41836dc408 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -2834,7 +2834,7 @@ ProxyObject::trace(JSTracer *trc, JSObject *obj) #ifdef DEBUG if (trc->runtime()->gc.isStrictProxyCheckingEnabled() && proxy->is()) { - JSObject *referent = &proxy->private_().toObject(); + JSObject *referent = MaybeForwarded(&proxy->private_().toObject()); if (referent->compartment() != proxy->compartment()) { /* * Assert that this proxy is tracked in the wrapper map. We maintain @@ -2842,6 +2842,7 @@ ProxyObject::trace(JSTracer *trc, JSObject *obj) */ Value key = ObjectValue(*referent); WrapperMap::Ptr p = proxy->compartment()->lookupWrapper(key); + JS_ASSERT(p); JS_ASSERT(*p->value().unsafeGet() == ObjectValue(*proxy)); } } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index ff6f3eb1b001..d7978e07345b 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -3339,7 +3339,7 @@ JSScript::markChildren(JSTracer *trc) } if (sourceObject()) { - JS_ASSERT(sourceObject()->compartment() == compartment()); + JS_ASSERT(MaybeForwarded(sourceObject())->compartment() == compartment()); MarkObject(trc, &sourceObject_, "sourceObject"); } diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 1a629cba7dd2..59fc41680da5 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -88,6 +88,11 @@ js::UncheckedUnwrap(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp) } flags |= Wrapper::wrapperHandler(wrapped)->flags(); wrapped = wrapped->as().private_().toObjectOrNull(); + + // This can be called from DirectProxyHandler::weakmapKeyDelegate() on a + // wrapper whose referent has been moved while it is still unmarked. + if (wrapped) + wrapped = MaybeForwarded(wrapped); } if (flagsp) *flagsp = flags; diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 6e0d35d3880b..0c7d2cf34f54 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -826,9 +826,10 @@ ArrayBufferObject::finalize(FreeOp *fop, JSObject *obj) /* static */ void ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) { - if (!IS_GC_MARKING_TRACER(trc) && !trc->runtime()->isHeapMinorCollecting() + JSRuntime *rt = trc->runtime(); + if (!IS_GC_MARKING_TRACER(trc) && !rt->isHeapMinorCollecting() && !rt->isHeapCompacting() #ifdef JSGC_FJGENERATIONAL - && !trc->runtime()->isFJMinorCollecting() + && !rt->isFJMinorCollecting() #endif ) { @@ -852,15 +853,16 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) if (!viewsHead) return; - buffer.setViewList(UpdateObjectIfRelocated(trc->runtime(), &viewsHead)); + ArrayBufferViewObject *tmp = viewsHead; + buffer.setViewList(UpdateObjectIfRelocated(rt, &tmp)); - if (viewsHead->nextView() == nullptr) { + if (tmp->nextView() == nullptr) { // Single view: mark it, but only if we're actually doing a GC pass // right now. Otherwise, the tracing pass for barrier verification will // fail if we add another view and the pointer becomes weak. MarkObjectUnbarriered(trc, &viewsHead, "arraybuffer.singleview"); buffer.setViewListNoBarrier(viewsHead); - } else { + } else if (!rt->isHeapCompacting()) { // Multiple views: do not mark, but append buffer to list. ArrayBufferVector &gcLiveArrayBuffers = buffer.compartment()->gcLiveArrayBuffers; @@ -878,6 +880,19 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) } else { CrashAtUnhandlableOOM("OOM while updating live array buffers"); } + } else { + // If we're fixing up pointers after compacting then trace everything. + ArrayBufferViewObject *prev = nullptr; + ArrayBufferViewObject *view = viewsHead; + while (view) { + JS_ASSERT(buffer.compartment() == MaybeForwarded(view)->compartment()); + MarkObjectUnbarriered(trc, &view, "arraybuffer.singleview"); + if (prev) + prev->setNextView(view); + else + buffer.setViewListNoBarrier(view); + view = view->nextView(); + } } } diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 3810ba0e5353..d6aee1c85812 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1707,7 +1707,7 @@ Debugger::trace(JSTracer *trc) */ for (FrameMap::Range r = frames.all(); !r.empty(); r.popFront()) { RelocatablePtrObject &frameobj = r.front().value(); - JS_ASSERT(frameobj->getPrivate()); + JS_ASSERT(MaybeForwarded(frameobj.get())->getPrivate()); MarkObject(trc, &frameobj, "live Debugger.Frame"); } @@ -1759,9 +1759,9 @@ Debugger::sweepAll(FreeOp *fop) if (IsObjectAboutToBeFinalized(&global)) { // See infallibility note above. detachAllDebuggersFromGlobal(fop, global, &e); - } - else if (global != e.front()) + } else if (global != e.front()) { e.rekeyFront(global); + } } } } diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 02d66156b211..784e7f944f3b 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -127,6 +127,9 @@ class DebuggerWeakMap : private WeakMap > if (gc::IsAboutToBeFinalized(&k)) { e.removeFront(); decZoneCount(k->zone()); + } else { + // markKeys() should have done any necessary relocation. + JS_ASSERT(k == e.front().key()); } } Base::assertEntriesNotAboutToBeFinalized(); diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 348e2a1be9c9..a6441186694f 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -937,13 +937,14 @@ struct JSRuntime : public JS::shadow::Runtime, /* Garbage collector state, used by jsgc.c. */ js::gc::GCRuntime gc; - /* Garbase collector state has been sucessfully initialized. */ + /* Garbage collector state has been sucessfully initialized. */ bool gcInitialized; bool isHeapBusy() { return gc.isHeapBusy(); } bool isHeapMajorCollecting() { return gc.isHeapMajorCollecting(); } bool isHeapMinorCollecting() { return gc.isHeapMinorCollecting(); } bool isHeapCollecting() { return gc.isHeapCollecting(); } + bool isHeapCompacting() { return gc.isHeapCompacting(); } bool isFJMinorCollecting() { return gc.isFJMinorCollecting(); } diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index c882e4f44b4b..6032961017f8 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -24,6 +24,7 @@ #include "vm/Stack-inl.h" using namespace js; +using namespace js::gc; using namespace js::types; using mozilla::PodZero; @@ -1784,6 +1785,19 @@ DebugScopes::sweep(JSRuntime *rt) */ liveScopes.remove(&(*debugScope)->scope()); e.removeFront(); + } else { + ScopeIterKey key = e.front().key(); + bool needsUpdate = false; + if (IsForwarded(key.cur())) { + key.updateCur(js::gc::Forwarded(key.cur())); + needsUpdate = true; + } + if (IsForwarded(key.staticScope())) { + key.updateStaticScope(Forwarded(key.staticScope())); + needsUpdate = true; + } + if (needsUpdate) + e.rekeyFront(key); } } @@ -1794,10 +1808,10 @@ DebugScopes::sweep(JSRuntime *rt) * Scopes can be finalized when a debugger-synthesized ScopeObject is * no longer reachable via its DebugScopeObject. */ - if (IsObjectAboutToBeFinalized(&scope)) { + if (IsObjectAboutToBeFinalized(&scope)) e.removeFront(); - continue; - } + else if (scope != e.front().key()) + e.rekeyFront(scope); } } diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 5bed48fb20f5..22c9464e86a6 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -704,6 +704,9 @@ class ScopeIterKey JSObject *enclosingScope() const { return cur_; } JSObject *&enclosingScope() { return cur_; } + void updateCur(JSObject *obj) { cur_ = obj; } + void updateStaticScope(NestedScopeObject *obj) { staticScope_ = obj; } + /* For use as hash policy */ typedef ScopeIterKey Lookup; static HashNumber hash(ScopeIterKey si); diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index 7f91e3658529..6cd5241bdb5e 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -220,6 +220,15 @@ GetShapeAttributes(JSObject *obj, Shape *shape) return shape->attributes(); } +#ifdef JSGC_COMPACTING +inline void +BaseShape::fixupAfterMovingGC() +{ + if (hasTable()) + table().fixupAfterMovingGC(); +} +#endif + } /* namespace js */ #endif /* vm_Shape_inl_h */ diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 247a186f0967..173f44d1c501 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -248,6 +248,20 @@ ShapeTable::search(jsid id, bool adding) return nullptr; } +#ifdef JSGC_COMPACTING +void +ShapeTable::fixupAfterMovingGC() +{ + int log2 = HASH_BITS - hashShift; + uint32_t size = JS_BIT(log2); + for (HashNumber i = 0; i < size; i++) { + Shape *shape = SHAPE_FETCH(&entries[i]); + if (shape && IsForwarded(shape)) + SHAPE_STORE_PRESERVING_COLLISION(&entries[i], Forwarded(shape)); + } +} +#endif + bool ShapeTable::change(int log2Delta, ThreadSafeContext *cx) { @@ -429,6 +443,11 @@ js::ObjectImpl::toDictionaryMode(ThreadSafeContext *cx) { JS_ASSERT(!inDictionaryMode()); +#ifdef JSGC_COMPACTING + // TODO: This crashes if we run a compacting GC here. + js::gc::AutoSuppressGC nogc(zone()->runtimeFromAnyThread()); +#endif + /* We allocate the shapes from cx->compartment(), so make sure it's right. */ JS_ASSERT(cx->isInsideCurrentCompartment(this)); @@ -1529,8 +1548,13 @@ JSCompartment::sweepBaseShapeTable() if (baseShapes.initialized()) { for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) { UnownedBaseShape *base = e.front().unbarrieredGet(); - if (IsBaseShapeAboutToBeFinalized(&base)) + if (IsBaseShapeAboutToBeFinalized(&base)) { e.removeFront(); + } else if (base != e.front()) { + StackBaseShape sbase(base); + ReadBarriered b(base); + e.rekeyFront(&sbase, b); + } } } } @@ -1823,7 +1847,9 @@ JSCompartment::sweepInitialShapeTable() const InitialShapeEntry &entry = e.front(); Shape *shape = entry.shape.unbarrieredGet(); JSObject *proto = entry.proto.raw(); - if (IsShapeAboutToBeFinalized(&shape) || (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) { + if (IsShapeAboutToBeFinalized(&shape) || + (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) + { e.removeFront(); } else { #ifdef DEBUG @@ -1841,6 +1867,47 @@ JSCompartment::sweepInitialShapeTable() } } +#ifdef JSGC_COMPACTING +void +JSCompartment::fixupInitialShapeTable() +{ + if (!initialShapes.initialized()) + return; + + for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) { + InitialShapeEntry entry = e.front(); + bool needRekey = false; + if (IsForwarded(entry.shape.get())) { + entry.shape.set(Forwarded(entry.shape.get())); + needRekey = true; + } + if (entry.proto.isObject() && IsForwarded(entry.proto.toObject())) { + entry.proto = TaggedProto(Forwarded(entry.proto.toObject())); + needRekey = true; + } + JSObject *parent = entry.shape->getObjectParent(); + if (parent) { + parent = MaybeForwarded(parent); + needRekey = true; + } + JSObject *metadata = entry.shape->getObjectMetadata(); + if (metadata) { + metadata = MaybeForwarded(metadata); + needRekey = true; + } + if (needRekey) { + InitialShapeEntry::Lookup relookup(entry.shape->getObjectClass(), + entry.proto, + parent, + metadata, + entry.shape->numFixedSlots(), + entry.shape->getObjectFlags()); + e.rekeyFront(relookup, entry); + } + } +} +#endif // JSGC_COMPACTING + void AutoRooterGetterSetter::Inner::trace(JSTracer *trc) { diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index e334c466cfde..90f35873ef89 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -190,6 +190,11 @@ struct ShapeTable { bool init(ThreadSafeContext *cx, Shape *lastProp); bool change(int log2Delta, ThreadSafeContext *cx); Shape **search(jsid id, bool adding); + +#ifdef JSGC_COMPACTING + /* Update entries whose shapes have been moved */ + void fixupAfterMovingGC(); +#endif }; /* @@ -505,6 +510,10 @@ class BaseShape : public gc::BarrieredCell gc::MarkObject(trc, &metadata, "metadata"); } +#ifdef JSGC_COMPACTING + void fixupAfterMovingGC(); +#endif + private: static void staticAsserts() { JS_STATIC_ASSERT(offsetof(BaseShape, clasp_) == offsetof(js::shadow::BaseShape, clasp_)); @@ -550,7 +559,7 @@ BaseShape::baseUnowned() } /* Entries for the per-compartment baseShapes set of unowned base shapes. */ -struct StackBaseShape +struct StackBaseShape : public DefaultHasher { typedef const StackBaseShape *Lookup; @@ -1028,10 +1037,19 @@ class Shape : public gc::BarrieredCell inline Shape *search(ExclusiveContext *cx, jsid id); inline Shape *searchLinear(jsid id); +#ifdef JSGC_COMPACTING + void fixupAfterMovingGC(); +#endif + /* For JIT usage */ static inline size_t offsetOfBase() { return offsetof(Shape, base_); } private: +#ifdef JSGC_COMPACTING + void fixupDictionaryShapeAfterMovingGC(); + void fixupShapeTreeAfterMovingGC(); +#endif + static void staticAsserts() { JS_STATIC_ASSERT(offsetof(Shape, base_) == offsetof(js::shadow::Shape, base)); JS_STATIC_ASSERT(offsetof(Shape, slotInfo) == offsetof(js::shadow::Shape, slotInfo)); From eec4a0fd3635809bc3a25d2b039d97c619ca0462 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:46:55 +0100 Subject: [PATCH 010/119] Bug 650161 - Update pointers in TraceDataRelocations r=mjrosenb --- js/src/jit/arm/Assembler-arm.cpp | 43 +++++++++++++++------- js/src/jit/mips/Assembler-mips.cpp | 2 + js/src/jit/shared/Assembler-x86-shared.cpp | 2 +- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/js/src/jit/arm/Assembler-arm.cpp b/js/src/jit/arm/Assembler-arm.cpp index 220486b56eef..b519dacf3b9c 100644 --- a/js/src/jit/arm/Assembler-arm.cpp +++ b/js/src/jit/arm/Assembler-arm.cpp @@ -795,36 +795,49 @@ Assembler::TraceJumpRelocations(JSTracer *trc, JitCode *code, CompactBufferReade } } +template static void -TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader) +TraceOneDataRelocation(JSTracer *trc, Iter *iter, MacroAssemblerARM *masm) +{ + Instruction *ins = iter->cur(); + Register dest; + Assembler::RelocStyle rs; + const void *prior = Assembler::GetPtr32Target(iter, &dest, &rs); + void *ptr = const_cast(prior); + + // No barrier needed since these are constants. + gc::MarkGCThingUnbarriered(trc, &ptr, "ion-masm-ptr"); + + if (ptr != prior) + masm->ma_movPatchable(Imm32(int32_t(ptr)), dest, Assembler::Always, rs, ins); +} + +static void +TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader, + MacroAssemblerARM *masm) { while (reader.more()) { size_t offset = reader.readUnsigned(); InstructionIterator iter((Instruction*)(buffer + offset)); - void *ptr = const_cast(Assembler::GetPtr32Target(&iter)); - // No barrier needed since these are constants. - gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); + TraceOneDataRelocation(trc, &iter, masm); } - } + static void TraceDataRelocations(JSTracer *trc, ARMBuffer *buffer, - Vector *locs) + Vector *locs, MacroAssemblerARM *masm) { for (unsigned int idx = 0; idx < locs->length(); idx++) { BufferOffset bo = (*locs)[idx]; ARMBuffer::AssemblerBufferInstIterator iter(bo, buffer); - void *ptr = const_cast(Assembler::GetPtr32Target(&iter)); - - // No barrier needed since these are constants. - gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); + TraceOneDataRelocation(trc, &iter, masm); } - } + void Assembler::TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader) { - ::TraceDataRelocations(trc, code->raw(), reader); + ::TraceDataRelocations(trc, code->raw(), reader, static_cast(Dummy)); } void @@ -860,8 +873,10 @@ Assembler::trace(JSTracer *trc) } } - if (tmpDataRelocations_.length()) - ::TraceDataRelocations(trc, &m_buffer, &tmpDataRelocations_); + if (tmpDataRelocations_.length()) { + ::TraceDataRelocations(trc, &m_buffer, &tmpDataRelocations_, + static_cast(this)); + } } void diff --git a/js/src/jit/mips/Assembler-mips.cpp b/js/src/jit/mips/Assembler-mips.cpp index 58a077255fc8..0ba04c834be9 100644 --- a/js/src/jit/mips/Assembler-mips.cpp +++ b/js/src/jit/mips/Assembler-mips.cpp @@ -262,6 +262,7 @@ TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader // No barrier needed since these are constants. gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); + Assembler::UpdateLuiOriValue(inst, inst->next(), uint32_t(ptr)); } } @@ -276,6 +277,7 @@ TraceDataRelocations(JSTracer *trc, MIPSBuffer *buffer, CompactBufferReader &rea // No barrier needed since these are constants. gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); + Assembler::UpdateLuiOriValue(iter.cur(), iter.next(), uint32_t(ptr)); } } diff --git a/js/src/jit/shared/Assembler-x86-shared.cpp b/js/src/jit/shared/Assembler-x86-shared.cpp index 53fd21018568..665d80835418 100644 --- a/js/src/jit/shared/Assembler-x86-shared.cpp +++ b/js/src/jit/shared/Assembler-x86-shared.cpp @@ -54,7 +54,7 @@ TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader layout.asBits = *word; Value v = IMPL_TO_JSVAL(layout); gc::MarkValueUnbarriered(trc, &v, "ion-masm-value"); - JS_ASSERT(*word == JSVAL_TO_IMPL(v).asBits); + *word = JSVAL_TO_IMPL(v).asBits; continue; } #endif From 01b56566aa15389a902b407eff997464ce41f40d Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:52:24 +0100 Subject: [PATCH 011/119] Bug 650161 - Implement compacting GC for JSObjects r=terrence --- js/public/Utility.h | 1 + js/src/builtin/TestingFunctions.cpp | 1 + js/src/gc/GCRuntime.h | 27 +- js/src/gc/Heap.h | 17 + js/src/gc/RootMarking.cpp | 26 +- js/src/gc/Tracer.cpp | 2 +- js/src/gc/Zone.cpp | 2 - js/src/jsapi-tests/testWeakMap.cpp | 2 +- js/src/jsgc.cpp | 514 ++++++++++++++++++++++++++-- js/src/jsgc.h | 15 +- 10 files changed, 560 insertions(+), 47 deletions(-) diff --git a/js/public/Utility.h b/js/public/Utility.h index 89c495e41116..f6714f9d7836 100644 --- a/js/public/Utility.h +++ b/js/public/Utility.h @@ -43,6 +43,7 @@ namespace js {} #define JS_SWEPT_NURSERY_PATTERN 0x2B #define JS_ALLOCATED_NURSERY_PATTERN 0x2D #define JS_FRESH_TENURED_PATTERN 0x4F +#define JS_MOVED_TENURED_PATTERN 0x49 #define JS_SWEPT_TENURED_PATTERN 0x4B #define JS_ALLOCATED_TENURED_PATTERN 0x4D #define JS_SWEPT_CODE_PATTERN 0x3b diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 74e979ddb700..acb17c74cac9 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2062,6 +2062,7 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { " 11: Verify post write barriers between instructions\n" " 12: Verify post write barriers between paints\n" " 13: Check internal hashtables on minor GC\n" +" 14: Always compact arenas after GC\n" " Period specifies that collection happens every n allocations.\n"), JS_FN_HELP("schedulegc", ScheduleGC, 1, 0, diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index e66033129051..6eb990d45e61 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -293,7 +293,17 @@ class GCRuntime void runDebugGC(); inline void poke(); - void markRuntime(JSTracer *trc, bool useSavedRoots = false); + enum TraceOrMarkRuntime { + TraceRuntime, + MarkRuntime + }; + enum TraceRootsOrUsedSaved { + TraceRoots, + UseSavedRoots + }; + void markRuntime(JSTracer *trc, + TraceOrMarkRuntime traceOrMark = TraceRuntime, + TraceRootsOrUsedSaved rootsSource = TraceRoots); void notifyDidPaint(); void shrinkBuffers(); @@ -491,6 +501,9 @@ class GCRuntime void markWeakReferencesInCurrentGroup(gcstats::Phase phase); template void markGrayReferences(); void markGrayReferencesInCurrentGroup(); + void markAllWeakReferences(gcstats::Phase phase); + void markAllGrayReferences(); + void beginSweepPhase(bool lastGC); void findZoneGroups(); bool findZoneEdgesForWeakMaps(); @@ -507,6 +520,13 @@ class GCRuntime void expireChunksAndArenas(bool shouldShrink); void sweepBackgroundThings(bool onBackgroundThread); void assertBackgroundSweepingFinished(); + bool shouldCompact(); +#ifdef JSGC_COMPACTING + void compactPhase(); + void updatePointersToRelocatedCells(); + void releaseRelocatedArenas(ArenaHeader *relocatedList); +#endif + void finishCollection(); void computeNonIncrementalMarkingForValidation(); void validateIncrementalMarking(); @@ -516,8 +536,6 @@ class GCRuntime #ifdef DEBUG void checkForCompartmentMismatches(); - void markAllWeakReferences(gcstats::Phase phase); - void markAllGrayReferences(); #endif public: @@ -839,7 +857,8 @@ GCRuntime::needZealousGC() { if (zealMode == ZealAllocValue || zealMode == ZealGenerationalGCValue || (zealMode >= ZealIncrementalRootsThenFinish && - zealMode <= ZealIncrementalMultipleSlices)) + zealMode <= ZealIncrementalMultipleSlices) || + zealMode == ZealCompactValue) { nextScheduled = zealFrequency; } diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index d3444b1f9bd4..0758d12b7d91 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -102,6 +102,7 @@ struct Cell MOZ_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const; MOZ_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const; MOZ_ALWAYS_INLINE void unmark(uint32_t color) const; + MOZ_ALWAYS_INLINE void copyMarkBitsFrom(const Cell *src); inline JSRuntime *runtimeFromMainThread() const; inline JS::shadow::Runtime *shadowRuntimeFromMainThread() const; @@ -761,6 +762,12 @@ struct ChunkBitmap *word &= ~mask; } + MOZ_ALWAYS_INLINE void copyMarkBit(Cell *dst, const Cell *src, uint32_t color) { + uintptr_t *word, mask; + getMarkWordAndMask(dst, color, &word, &mask); + *word = (*word & ~mask) | (src->isMarked(color) ? mask : 0); + } + void clear() { memset((void *)bitmap, 0, sizeof(bitmap)); } @@ -1112,6 +1119,16 @@ Cell::unmark(uint32_t color) const chunk()->bitmap.unmark(this, color); } +void +Cell::copyMarkBitsFrom(const Cell *src) +{ + JS_ASSERT(isTenured()); + JS_ASSERT(src->isTenured()); + ChunkBitmap &bitmap = chunk()->bitmap; + bitmap.copyMarkBit(this, src, BLACK); + bitmap.copyMarkBit(this, src, GRAY); +} + JS::Zone * Cell::tenuredZone() const { diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 62df4ff4cb4a..5949fe798efb 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -707,13 +707,17 @@ js::gc::MarkForkJoinStack(ForkJoinNurseryCollectionTracer *trc) #endif // JSGC_FJGENERATIONAL void -js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) +js::gc::GCRuntime::markRuntime(JSTracer *trc, + TraceOrMarkRuntime traceOrMark, + TraceRootsOrUsedSaved rootsSource) { JS_ASSERT(trc->callback != GCMarker::GrayCallback); + JS_ASSERT(traceOrMark == TraceRuntime || traceOrMark == MarkRuntime); + JS_ASSERT(rootsSource == TraceRoots || rootsSource == UseSavedRoots); JS_ASSERT(!rt->mainThread.suppressGC); - if (IS_GC_MARKING_TRACER(trc)) { + if (traceOrMark == MarkRuntime) { for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { if (!c->zone()->isCollecting()) c->markCrossCompartmentWrappers(trc); @@ -727,7 +731,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) #ifdef JSGC_USE_EXACT_ROOTING MarkExactStackRoots(rt, trc); #else - markConservativeStackRoots(trc, useSavedRoots); + markConservativeStackRoots(trc, rootsSource == UseSavedRoots); #endif rt->markSelfHostingGlobal(trc); } @@ -760,7 +764,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) } if (!rt->isBeingDestroyed() && !trc->runtime()->isHeapMinorCollecting()) { - if (!IS_GC_MARKING_TRACER(trc) || rt->atomsCompartment()->zone()->isCollecting()) { + if (traceOrMark == TraceRuntime || rt->atomsCompartment()->zone()->isCollecting()) { MarkPermanentAtoms(trc); MarkAtoms(trc); MarkWellKnownSymbols(trc); @@ -772,7 +776,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) acx->mark(trc); for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { - if (IS_GC_MARKING_TRACER(trc) && !zone->isCollecting()) + if (traceOrMark == MarkRuntime && !zone->isCollecting()) continue; /* Do not discard scripts with counts while profiling. */ @@ -792,11 +796,11 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) if (trc->runtime()->isHeapMinorCollecting()) c->globalWriteBarriered = false; - if (IS_GC_MARKING_TRACER(trc) && !c->zone()->isCollecting()) + if (traceOrMark == MarkRuntime && !c->zone()->isCollecting()) continue; /* During a GC, these are treated as weak pointers. */ - if (!IS_GC_MARKING_TRACER(trc)) { + if (traceOrMark == TraceRuntime) { if (c->watchpointMap) c->watchpointMap->markAll(trc); } @@ -812,9 +816,9 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) if (!isHeapMinorCollecting()) { /* - * All JSCompartment::mark does is mark the globals for compartments - * which have been entered. Globals aren't nursery allocated so there's - * no need to do this for minor GCs. + * All JSCompartment::markRoots() does is mark the globals for + * compartments which have been entered. Globals aren't nursery + * allocated so there's no need to do this for minor GCs. */ for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) c->markRoots(trc); @@ -833,7 +837,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) /* During GC, we don't mark gray roots at this stage. */ if (JSTraceDataOp op = grayRootTracer.op) { - if (!IS_GC_MARKING_TRACER(trc)) + if (traceOrMark == TraceRuntime) (*op)(trc, grayRootTracer.data); } } diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index f5c9d6761dad..4abfec97eb16 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -632,7 +632,7 @@ void GCMarker::markBufferedGrayRoots(JS::Zone *zone) { JS_ASSERT(grayBufferState == GRAY_BUFFER_OK); - JS_ASSERT(zone->isGCMarkingGray()); + JS_ASSERT(zone->isGCMarkingGray() || zone->isGCCompacting()); for (GrayRoot *elem = zone->gcGrayRoots.begin(); elem != zone->gcGrayRoots.end(); elem++) { #ifdef DEBUG diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index fa6104768a8c..77a270aac5e7 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -120,8 +120,6 @@ Zone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) if (!fop->runtime()->debuggerList.isEmpty()) sweepBreakpoints(fop); - - active = false; } void diff --git a/js/src/jsapi-tests/testWeakMap.cpp b/js/src/jsapi-tests/testWeakMap.cpp index 8c3db691d2fa..ef583c299bd2 100644 --- a/js/src/jsapi-tests/testWeakMap.cpp +++ b/js/src/jsapi-tests/testWeakMap.cpp @@ -111,7 +111,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) CHECK(map->zone()->lastZoneGroupIndex() == delegate->zone()->lastZoneGroupIndex()); #endif - /* Check that when the delegate becomes unreacable the entry is removed. */ + /* Check that when the delegate becomes unreachable the entry is removed. */ delegate = nullptr; JS_GC(rt); CHECK(checkSize(map, 0)); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 24c7a6b7b6bc..cca8bae4b403 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -169,6 +169,16 @@ * the mark state, this just stops marking, but if we have started sweeping * already, we continue until we have swept the current zone group. Following a * reset, a new non-incremental collection is started. + * + * Compacting GC + * ------------- + * + * Compacting GC happens at the end of a major GC as part of the last slice. + * There are three parts: + * + * - Arenas are selected for compaction. + * - The contents of those arenas are moved to new arenas. + * - All references to moved things are updated. */ #include "jsgcinlines.h" @@ -916,7 +926,10 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind) JS_ASSERT(hasAvailableArenas()); JSRuntime *rt = zone->runtimeFromAnyThread(); - if (!rt->isHeapMinorCollecting() && rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) { + if (!rt->isHeapMinorCollecting() && + !rt->isHeapCompacting() && + rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) + { #ifdef JSGC_FJGENERATIONAL // This is an approximation to the best test, which would check that // this thread is currently promoting into the tenured area. I doubt @@ -937,7 +950,7 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind) zone->usage.addGCArena(); - if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) { + if (!rt->isHeapCompacting() && zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) { AutoUnlockGC unlock(rt); rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); } @@ -1985,6 +1998,18 @@ ArenaLists::wipeDuringParallelExecution(JSRuntime *rt) } } +/* Compacting GC */ + +bool +GCRuntime::shouldCompact() +{ +#ifdef JSGC_COMPACTING + return invocationKind == GC_SHRINK; +#else + return false; +#endif +} + #ifdef JSGC_COMPACTING static void @@ -2002,8 +2027,381 @@ ForwardCell(Cell *dest, Cell *src) ptr[1] = ForwardedCellMagicValue; // Moved! } +static bool +ArenaContainsGlobal(ArenaHeader *arena) +{ + if (arena->getAllocKind() > FINALIZE_OBJECT_LAST) + return false; + + for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { + JSObject *obj = static_cast(i.getCell()); + if (obj->is()) + return true; + } + + return false; +} + +static bool +CanRelocateArena(ArenaHeader *arena) +{ + /* + * We can't currently move global objects because their address is baked + * into compiled code. We therefore skip moving the contents of any arena + * containing a global. + */ + return arena->getAllocKind() <= FINALIZE_OBJECT_LAST && !ArenaContainsGlobal(arena); +} + +static bool +ShouldRelocateArena(ArenaHeader *arena) +{ +#ifdef JS_GC_ZEAL + if (arena->zone->runtimeFromMainThread()->gc.zeal() == ZealCompactValue) + return true; #endif + /* + * Eventually, this will be based on brilliant heuristics that look at fill + * percentage and fragmentation and... stuff. + */ + return arena->hasFreeThings(); +} + +/* + * Choose some arenas to relocate all cells out of and remove them from the + * arena list. Return the head of the list of arenas to relocate. + */ +ArenaHeader * +ArenaList::pickArenasToRelocate() +{ + check(); + ArenaHeader *head = nullptr; + ArenaHeader **tailp = &head; + + // TODO: Only scan through the arenas with space available. + ArenaHeader **arenap = &head_; + while (*arenap) { + ArenaHeader *arena = *arenap; + JS_ASSERT(arena); + if (CanRelocateArena(arena) && ShouldRelocateArena(arena)) { + // Remove from arena list + if (cursorp_ == &arena->next) + cursorp_ = arenap; + *arenap = arena->next; + arena->next = nullptr; + + // Append to relocation list + *tailp = arena; + tailp = &arena->next; + } else { + arenap = &arena->next; + } + } + + check(); + return head; +} + +static bool +RelocateCell(Zone *zone, Cell *src, AllocKind thingKind, size_t thingSize) +{ + // Allocate a new cell. + void *dst = zone->allocator.arenas.allocateFromFreeList(thingKind, thingSize); + if (!dst) + dst = js::gc::ArenaLists::refillFreeListInGC(zone, thingKind); + if (!dst) + return false; + + // Copy source cell contents to destination. + memcpy(dst, src, thingSize); + + // Mark source cell as forwarded and leave a pointer to the destination. + ForwardCell(static_cast(dst), src); + + // Fixup the pointer to inline object elements if necessary. + if (thingKind <= FINALIZE_OBJECT_LAST) { + JSObject *srcObj = static_cast(src); + JSObject *dstObj = static_cast(dst); + if (srcObj->hasFixedElements()) + dstObj->setFixedElements(); + JS_ASSERT( + uintptr_t((HeapSlot*)dstObj->getElementsHeader()) - uintptr_t(srcObj) >= thingSize); + } + + // Copy the mark bits. + static_cast(dst)->copyMarkBitsFrom(src); + + return true; +} + +static bool +RelocateArena(ArenaHeader *aheader) +{ + JS_ASSERT(aheader->allocated()); + JS_ASSERT(!aheader->hasDelayedMarking); + JS_ASSERT(!aheader->markOverflow); + JS_ASSERT(!aheader->allocatedDuringIncremental); + + Zone *zone = aheader->zone; + + AllocKind thingKind = aheader->getAllocKind(); + size_t thingSize = aheader->getThingSize(); + + for (ArenaCellIterUnderFinalize i(aheader); !i.done(); i.next()) { + if (!RelocateCell(zone, i.getCell(), thingKind, thingSize)) { + MOZ_CRASH(); // TODO: Handle failure here. + return false; + } + } + + return true; +} + +/* + * Relocate all arenas identified by pickArenasToRelocate: for each arena, + * relocate each cell within it, then tack it onto a list of relocated arenas. + * Currently, we allow the relocation to fail, in which case the arena will be + * moved back onto the list of arenas with space available. (I did this + * originally to test my list manipulation before implementing the actual + * moving, with half a thought to allowing pinning (moving only a portion of + * the cells in an arena), but now it's probably just dead weight. FIXME) + */ +ArenaHeader * +ArenaList::relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated) +{ + check(); + + while (ArenaHeader *arena = toRelocate) { + toRelocate = arena->next; + + if (RelocateArena(arena)) { + // Prepend to list of relocated arenas + arena->next = relocated; + relocated = arena; + } else { + // For some reason, the arena did not end up empty. Prepend it to + // the portion of the list that the cursor is pointing to (the + // arenas with space available) so that it will be used for future + // allocations. + JS_ASSERT(arena->hasFreeThings()); + insertAtCursor(arena); + } + } + + check(); + + return relocated; +} + +ArenaHeader * +ArenaLists::relocateArenas(ArenaHeader *relocatedList) +{ + // Flush all the freeLists back into the arena headers + purge(); + checkEmptyFreeLists(); + + for (size_t i = 0; i < FINALIZE_LIMIT; i++) { + ArenaList &al = arenaLists[i]; + ArenaHeader *toRelocate = al.pickArenasToRelocate(); + if (toRelocate) + relocatedList = al.relocateArenas(toRelocate, relocatedList); + } + + /* + * When we allocate new locations for cells, we use + * allocateFromFreeList(). Reset the free list again so that + * AutoCopyFreeListToArenasForGC doesn't complain that the free lists + * are different now. + */ + purge(); + checkEmptyFreeLists(); + + return relocatedList; +} + +struct MovingTracer : JSTracer { + MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapValues) {} + + static void Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind); + static void Sweep(JSTracer *jstrc); +}; + +void +MovingTracer::Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) +{ + Cell *thing = static_cast(*thingp); + if (!thing->tenuredZone()->isGCCompacting()) { + JS_ASSERT(!IsForwarded(thing)); + return; + } + + if (IsForwarded(thing)) { + Cell *dst = Forwarded(thing); + *thingp = dst; + } +} + +void +MovingTracer::Sweep(JSTracer *jstrc) +{ + JSRuntime *rt = jstrc->runtime(); + FreeOp *fop = rt->defaultFreeOp(); + + WatchpointMap::sweepAll(rt); + + Debugger::sweepAll(fop); + + for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { + if (zone->isCollecting()) { + gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_COMPARTMENTS); + + bool oom = false; + zone->sweep(fop, false, &oom); + JS_ASSERT(!oom); + + for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) { + c->sweep(fop, false); + ArrayBufferObject::sweep(c); + } + } else { + /* Update cross compartment wrappers into moved zones. */ + for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) + c->sweepCrossCompartmentWrappers(); + } + } + + /* Type inference may put more blocks here to free. */ + rt->freeLifoAlloc.freeAll(); +} + +/* + * Update the interal pointers in a single cell. + */ +static void +UpdateCellPointers(MovingTracer *trc, Cell *cell, JSGCTraceKind traceKind) { + TraceChildren(trc, cell, traceKind); + + if (traceKind == JSTRACE_SHAPE) { + Shape *shape = static_cast(cell); + shape->fixupAfterMovingGC(); + } else if (traceKind == JSTRACE_BASE_SHAPE) { + BaseShape *base = static_cast(cell); + base->fixupAfterMovingGC(); + } +} + +/* + * Update pointers to relocated cells by doing a full heap traversal and sweep. + * + * The latter is necessary to update weak references which are not marked as + * part of the traversal. + */ +void +GCRuntime::updatePointersToRelocatedCells() +{ + JS_ASSERT(rt->currentThreadHasExclusiveAccess()); + MovingTracer trc(rt); + + { + // TODO: Maybe give compaction its own set of phases. + gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK); + + // TODO: We may need to fix up other weak pointers here. + + // Fixup compartment global pointers as these get accessed during marking. + for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) + comp->fixupAfterMovingGC(); + + // Fixup cross compartment wrappers as we assert the existence of wrappers in the map. + for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) + comp->fixupCrossCompartmentWrappers(&trc); + + // Fixup generators as these are not normally traced. + for (ContextIter i(rt); !i.done(); i.next()) { + for (JSGenerator *gen = i.get()->innermostGenerator(); gen; gen = gen->prevGenerator) + gen->obj = MaybeForwarded(gen->obj.get()); + } + + // Iterate through all allocated cells to update internal pointers. + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + ArenaLists &al = zone->allocator.arenas; + for (unsigned i = 0; i < FINALIZE_LIMIT; ++i) { + AllocKind thingKind = static_cast(i); + JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind); + for (ArenaHeader *arena = al.getFirstArena(thingKind); arena; arena = arena->next) { + for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { + UpdateCellPointers(&trc, i.getCell(), traceKind); + } + } + } + } + + // Mark roots to update them. + markRuntime(&trc, MarkRuntime); + Debugger::markAll(&trc); + Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); + + for (GCCompartmentsIter c(rt); !c.done(); c.next()) { + if (c->watchpointMap) + c->watchpointMap->markAll(&trc); + } + } + + { + gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP); + + markAllGrayReferences(); + + MovingTracer::Sweep(&trc); + } +} + +void +GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) +{ + // Release the relocated arenas, now containing only forwarding pointers + +#ifdef DEBUG + for (ArenaHeader *arena = relocatedList; arena; arena = arena->next) { + for (ArenaCellIterUnderFinalize i(arena); !i.done(); i.next()) { + Cell *src = i.getCell(); + JS_ASSERT(IsForwarded(src)); + Cell *dest = Forwarded(src); + JS_ASSERT(src->isMarked(BLACK) == dest->isMarked(BLACK)); + JS_ASSERT(src->isMarked(GRAY) == dest->isMarked(GRAY)); + } + } +#endif + + unsigned count = 0; + while (relocatedList) { + ArenaHeader *aheader = relocatedList; + relocatedList = relocatedList->next; + + // Mark arena as empty + AllocKind thingKind = aheader->getAllocKind(); + size_t thingSize = aheader->getThingSize(); + Arena *arena = aheader->getArena(); + FreeSpan fullSpan; + fullSpan.initFinal(arena->thingsStart(thingKind), arena->thingsEnd() - thingSize, thingSize); + aheader->setFirstFreeSpan(&fullSpan); + +#if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL) + JS_POISON(reinterpret_cast(arena->thingsStart(thingKind)), + JS_MOVED_TENURED_PATTERN, Arena::thingsSpan(thingSize)); +#endif + + aheader->chunk()->releaseArena(aheader); + ++count; + } + + AutoLockGC lock(rt); + expireChunksAndArenas(true); +} + +#endif // JSGC_COMPACTING + void ArenaLists::finalizeNow(FreeOp *fop, AllocKind thingKind) { @@ -2290,6 +2688,22 @@ ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); template void * ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); +/* static */ void * +ArenaLists::refillFreeListInGC(Zone *zone, AllocKind thingKind) +{ + /* + * Called by compacting GC to refill a free list while we are in a GC. + */ + + Allocator &allocator = zone->allocator; + JS_ASSERT(allocator.arenas.freeLists[thingKind].isEmpty()); + JSRuntime *rt = zone->runtimeFromMainThread(); + JS_ASSERT(rt->isHeapMajorCollecting()); + JS_ASSERT(!rt->gc.isBackgroundSweeping()); + + return allocator.arenas.allocateFromArena(zone, thingKind); +} + /* static */ int64_t SliceBudget::TimeBudget(int64_t millis) { @@ -3256,7 +3670,7 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason) if (isFull) UnmarkScriptData(rt); - markRuntime(gcmarker); + markRuntime(gcmarker, MarkRuntime); if (isIncremental) bufferGrayRoots(); @@ -3387,8 +3801,6 @@ GCRuntime::markGrayReferencesInCurrentGroup() markGrayReferences(); } -#ifdef DEBUG - void GCRuntime::markAllWeakReferences(gcstats::Phase phase) { @@ -3401,6 +3813,8 @@ GCRuntime::markAllGrayReferences() markGrayReferences(); } +#ifdef DEBUG + class js::gc::MarkingValidator { public: @@ -3505,7 +3919,7 @@ js::gc::MarkingValidator::nonIncrementalMark() { gcstats::AutoPhase ap1(gc->stats, gcstats::PHASE_MARK); gcstats::AutoPhase ap2(gc->stats, gcstats::PHASE_MARK_ROOTS); - gc->markRuntime(gcmarker, true); + gc->markRuntime(gcmarker, GCRuntime::MarkRuntime, GCRuntime::UseSavedRoots); } { @@ -4267,7 +4681,8 @@ GCRuntime::beginSweepPhase(bool lastGC) gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP); - sweepOnBackgroundThread = !lastGC && !TraceEnabled() && CanUseExtraThreads(); + sweepOnBackgroundThread = + !lastGC && !TraceEnabled() && CanUseExtraThreads() && !shouldCompact(); releaseObservedTypes = shouldReleaseObservedTypes(); @@ -4395,9 +4810,6 @@ GCRuntime::endSweepPhase(bool lastGC) JS_ASSERT_IF(lastGC, !sweepOnBackgroundThread); - JS_ASSERT(marker.isDrained()); - marker.stop(); - /* * Recalculate whether GC was full or not as this may have changed due to * newly created zones. Can only change from full to not full. @@ -4498,30 +4910,17 @@ GCRuntime::endSweepPhase(bool lastGC) sweepZones(&fop, lastGC); } - uint64_t currentTime = PRMJ_Now(); - schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); - - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables, - schedulingState); - if (zone->isCollecting()) { - JS_ASSERT(zone->isGCFinished()); - zone->setGCState(Zone::NoGC); - } + finishMarkingValidation(); #ifdef DEBUG - JS_ASSERT(!zone->isCollecting()); - JS_ASSERT(!zone->wasGCStarted()); - + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i) { JS_ASSERT_IF(!IsBackgroundFinalized(AllocKind(i)) || !sweepOnBackgroundThread, !zone->allocator.arenas.arenaListsToSweep[i]); } -#endif } -#ifdef DEBUG for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { JS_ASSERT(!c->gcIncomingGrayPointers); JS_ASSERT(c->gcLiveArrayBuffers.empty()); @@ -4532,8 +4931,61 @@ GCRuntime::endSweepPhase(bool lastGC) } } #endif +} - finishMarkingValidation(); +#ifdef JSGC_COMPACTING +void +GCRuntime::compactPhase() +{ + JS_ASSERT(rt->gc.nursery.isEmpty()); + JS_ASSERT(!sweepOnBackgroundThread); + + ArenaHeader *relocatedList = nullptr; + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + JS_ASSERT(zone->isGCFinished()); + JS_ASSERT(!zone->isPreservingCode()); + + // We cannot move atoms as we depend on their addresses being constant. + if (!rt->isAtomsZone(zone)) { + zone->setGCState(Zone::Compact); + relocatedList = zone->allocator.arenas.relocateArenas(relocatedList); + } + } + + updatePointersToRelocatedCells(); + releaseRelocatedArenas(relocatedList); + +#ifdef DEBUG + CheckHashTablesAfterMovingGC(rt); + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + if (!rt->isAtomsZone(zone) && !zone->isPreservingCode()) + zone->allocator.arenas.checkEmptyFreeLists(); + } +#endif +} +#endif // JSGC_COMPACTING + +void +GCRuntime::finishCollection() +{ + JS_ASSERT(marker.isDrained()); + marker.stop(); + + uint64_t currentTime = PRMJ_Now(); + schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); + + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { + zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables, + schedulingState); + if (zone->isCollecting()) { + JS_ASSERT(zone->isGCFinished() || zone->isGCCompacting()); + zone->setGCState(Zone::NoGC); + zone->active = false; + } + + JS_ASSERT(!zone->isCollecting()); + JS_ASSERT(!zone->wasGCStarted()); + } lastGCTime = currentTime; } @@ -4870,6 +5322,14 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (sweepOnBackgroundThread) helperState.startBackgroundSweep(invocationKind == GC_SHRINK); +#ifdef JSGC_COMPACTING + if (shouldCompact()) { + incrementalState = COMPACT; + compactPhase(); + } +#endif + + finishCollection(); incrementalState = NO_INCREMENTAL; break; } @@ -5542,6 +6002,8 @@ GCRuntime::runDebugGC() { incrementalLimit = zealFrequency / 2; } + } else if (type == ZealCompactValue) { + collect(false, SliceBudget::Unlimited, GC_SHRINK, JS::gcreason::DEBUG_GC); } else { collect(false, SliceBudget::Unlimited, GC_NORMAL, JS::gcreason::DEBUG_GC); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 05c825c83919..4098135495de 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -523,6 +523,11 @@ class ArenaList { check(); return *this; } + +#ifdef JSGC_COMPACTING + ArenaHeader *pickArenasToRelocate(); + ArenaHeader *relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated); +#endif }; /* @@ -799,7 +804,6 @@ class ArenaLists clearFreeListInArena(AllocKind(i)); } - void clearFreeListInArena(AllocKind kind) { FreeList *freeList = &freeLists[kind]; if (!freeList->isEmpty()) { @@ -845,6 +849,8 @@ class ArenaLists template static void *refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); + static void *refillFreeListInGC(Zone *zone, AllocKind thingKind); + /* * Moves all arenas from |fromArenaLists| into |this|. In * parallel blocks, we temporarily create one ArenaLists per @@ -868,6 +874,10 @@ class ArenaLists JS_ASSERT(freeLists[kind].isEmpty()); } +#ifdef JSGC_COMPACTING + ArenaHeader *relocateArenas(ArenaHeader *relocatedList); +#endif + void queueObjectsForSweep(FreeOp *fop); void queueStringsAndSymbolsForSweep(FreeOp *fop); void queueShapesForSweep(FreeOp *fop); @@ -1320,7 +1330,8 @@ const int ZealIncrementalMultipleSlices = 10; const int ZealVerifierPostValue = 11; const int ZealFrameVerifierPostValue = 12; const int ZealCheckHashTablesOnMinorGC = 13; -const int ZealLimit = 13; +const int ZealCompactValue = 14; +const int ZealLimit = 14; enum VerifierType { PreBarrierVerifier, From d168093063165d2db2cac681571c0d4e675a73d2 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:52:31 +0100 Subject: [PATCH 012/119] Bug 650161 - Add new stats phases for compacting GC r=terrence --- js/src/gc/GCRuntime.h | 7 +- js/src/gc/Statistics.cpp | 4 + js/src/gc/Statistics.h | 19 +++-- js/src/gc/Tracer.cpp | 5 +- js/src/gc/Zone.cpp | 15 ++-- js/src/jscompartment.cpp | 90 ++++++++++---------- js/src/jsgc.cpp | 176 +++++++++++++++++++-------------------- js/src/jsinfer.cpp | 9 +- js/src/vm/Shape.cpp | 10 ++- 9 files changed, 173 insertions(+), 162 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 6eb990d45e61..f75889b621f4 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -499,10 +499,10 @@ class GCRuntime bool drainMarkStack(SliceBudget &sliceBudget, gcstats::Phase phase); template void markWeakReferences(gcstats::Phase phase); void markWeakReferencesInCurrentGroup(gcstats::Phase phase); - template void markGrayReferences(); - void markGrayReferencesInCurrentGroup(); + template void markGrayReferences(gcstats::Phase phase); + void markGrayReferencesInCurrentGroup(gcstats::Phase phase); void markAllWeakReferences(gcstats::Phase phase); - void markAllGrayReferences(); + void markAllGrayReferences(gcstats::Phase phase); void beginSweepPhase(bool lastGC); void findZoneGroups(); @@ -523,6 +523,7 @@ class GCRuntime bool shouldCompact(); #ifdef JSGC_COMPACTING void compactPhase(); + ArenaHeader *relocateArenas(); void updatePointersToRelocatedCells(); void releaseRelocatedArenas(ArenaHeader *relocatedList); #endif diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp index c8789f6ca5ca..8bd0896a2db4 100644 --- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -307,6 +307,10 @@ static const PhaseInfo phases[] = { { PHASE_SWEEP_SCRIPT, "Sweep Script", PHASE_SWEEP }, { PHASE_SWEEP_SHAPE, "Sweep Shape", PHASE_SWEEP }, { PHASE_SWEEP_JITCODE, "Sweep JIT code", PHASE_SWEEP }, + { PHASE_COMPACT, "Compact", PHASE_NO_PARENT }, + { PHASE_COMPACT_MOVE, "Compact Move", PHASE_COMPACT }, + { PHASE_COMPACT_UPDATE, "Compact Update", PHASE_COMPACT, }, + { PHASE_COMPACT_UPDATE_GRAY, "Compact Update Gray", PHASE_COMPACT_UPDATE, }, { PHASE_FINALIZE_END, "Finalize End Callback", PHASE_SWEEP }, { PHASE_DESTROY, "Deallocate", PHASE_SWEEP }, { PHASE_GC_END, "End Callback", PHASE_NO_PARENT }, diff --git a/js/src/gc/Statistics.h b/js/src/gc/Statistics.h index f211004b7c72..258119064d01 100644 --- a/js/src/gc/Statistics.h +++ b/js/src/gc/Statistics.h @@ -58,6 +58,10 @@ enum Phase { PHASE_SWEEP_SCRIPT, PHASE_SWEEP_SHAPE, PHASE_SWEEP_JITCODE, + PHASE_COMPACT, + PHASE_COMPACT_MOVE, + PHASE_COMPACT_UPDATE, + PHASE_COMPACT_UPDATE_GRAY, PHASE_FINALIZE_END, PHASE_DESTROY, PHASE_GC_END, @@ -227,17 +231,16 @@ struct AutoPhase struct MaybeAutoPhase { - explicit MaybeAutoPhase(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) + explicit MaybeAutoPhase(Statistics &statsArg, bool condition, Phase phaseArg + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : stats(nullptr) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - void construct(Statistics &statsArg, Phase phaseArg) - { - JS_ASSERT(!stats); - stats = &statsArg; - phase = phaseArg; - stats->beginPhase(phase); + if (condition) { + stats = &statsArg; + phase = phaseArg; + stats->beginPhase(phase); + } } ~MaybeAutoPhase() { if (stats) diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 4abfec97eb16..5e5831c6f72e 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -554,9 +554,8 @@ GCMarker::markDelayedChildren(ArenaHeader *aheader) bool GCMarker::markDelayedChildren(SliceBudget &budget) { - gcstats::MaybeAutoPhase ap; - if (runtime()->gc.state() == MARK) - ap.construct(runtime()->gc.stats, gcstats::PHASE_MARK_DELAYED); + GCRuntime &gc = runtime()->gc; + gcstats::MaybeAutoPhase ap(gc.stats, gc.state() == MARK, gcstats::PHASE_MARK_DELAYED); JS_ASSERT(unmarkedArenaStackTop); do { diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 77a270aac5e7..3e949df80caa 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -113,13 +113,21 @@ Zone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) if (active) releaseTypes = false; + GCRuntime &gc = fop->runtime()->gc; + { - gcstats::AutoPhase ap(fop->runtime()->gc.stats, gcstats::PHASE_DISCARD_ANALYSIS); + gcstats::MaybeAutoPhase ap(gc.stats, !gc.isHeapCompacting(), + gcstats::PHASE_DISCARD_ANALYSIS); types.sweep(fop, releaseTypes, oom); } - if (!fop->runtime()->debuggerList.isEmpty()) + if (!fop->runtime()->debuggerList.isEmpty()) { + gcstats::MaybeAutoPhase ap1(gc.stats, !gc.isHeapCompacting(), + gcstats::PHASE_SWEEP_TABLES); + gcstats::MaybeAutoPhase ap2(gc.stats, !gc.isHeapCompacting(), + gcstats::PHASE_SWEEP_TABLES_BREAKPOINT); sweepBreakpoints(fop); + } } void @@ -130,9 +138,6 @@ Zone::sweepBreakpoints(FreeOp *fop) * to iterate over the scripts belonging to a single compartment in a zone. */ - gcstats::AutoPhase ap1(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES); - gcstats::AutoPhase ap2(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES_BREAKPOINT); - JS_ASSERT(isGCSweepingOrCompacting()); for (ZoneCellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index b95a4619611d..d69ef9043a28 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -572,54 +572,53 @@ void JSCompartment::sweep(FreeOp *fop, bool releaseTypes) { JS_ASSERT(!activeAnalysis); - - /* This function includes itself in PHASE_SWEEP_TABLES. */ - sweepCrossCompartmentWrappers(); - JSRuntime *rt = runtimeFromMainThread(); { - gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_TABLES); - - /* Remove dead references held weakly by the compartment. */ - - sweepBaseShapeTable(); - sweepInitialShapeTable(); - { - gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, - gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); - sweepNewTypeObjectTable(newTypeObjects); - sweepNewTypeObjectTable(lazyTypeObjects); - } - sweepCallsiteClones(); - savedStacks_.sweep(rt); - - if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet())) - global_.set(nullptr); - - if (selfHostingScriptSource && - IsObjectAboutToBeFinalized((JSObject **) selfHostingScriptSource.unsafeGet())) - { - selfHostingScriptSource.set(nullptr); - } - - if (jitCompartment_) - jitCompartment_->sweep(fop, this); - - /* - * JIT code increments activeUseCount for any RegExpShared used by jit - * code for the lifetime of the JIT script. Thus, we must perform - * sweeping after clearing jit code. - */ - regExps.sweep(rt); - - if (debugScopes) - debugScopes->sweep(rt); - - /* Finalize unreachable (key,value) pairs in all weak maps. */ - WeakMapBase::sweepCompartment(this); + gcstats::MaybeAutoPhase ap(rt->gc.stats, !rt->isHeapCompacting(), + gcstats::PHASE_SWEEP_TABLES_WRAPPER); + sweepCrossCompartmentWrappers(); } + /* Remove dead references held weakly by the compartment. */ + + sweepBaseShapeTable(); + sweepInitialShapeTable(); + { + gcstats::MaybeAutoPhase ap(rt->gc.stats, !rt->isHeapCompacting(), + gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); + sweepNewTypeObjectTable(newTypeObjects); + sweepNewTypeObjectTable(lazyTypeObjects); + } + sweepCallsiteClones(); + savedStacks_.sweep(rt); + + if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet())) + global_.set(nullptr); + + if (selfHostingScriptSource && + IsObjectAboutToBeFinalized((JSObject **) selfHostingScriptSource.unsafeGet())) + { + selfHostingScriptSource.set(nullptr); + } + + if (jitCompartment_) + jitCompartment_->sweep(fop, this); + + /* + * JIT code increments activeUseCount for any RegExpShared used by jit + * code for the lifetime of the JIT script. Thus, we must perform + * sweeping after clearing jit code. + */ + regExps.sweep(rt); + + if (debugScopes) + debugScopes->sweep(rt); + + /* Finalize unreachable (key,value) pairs in all weak maps. */ + WeakMapBase::sweepCompartment(this); + + /* Sweep list of native iterators. */ NativeIterator *ni = enumerators->next(); while (ni != enumerators) { JSObject *iterObj = ni->iterObj(); @@ -638,11 +637,6 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes) void JSCompartment::sweepCrossCompartmentWrappers() { - JSRuntime *rt = runtimeFromMainThread(); - - gcstats::AutoPhase ap1(rt->gc.stats, gcstats::PHASE_SWEEP_TABLES); - gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_SWEEP_TABLES_WRAPPER); - /* Remove dead wrappers from the table. */ for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { CrossCompartmentKey key = e.front().key(); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index cca8bae4b403..0ccc64b68342 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2220,6 +2220,26 @@ ArenaLists::relocateArenas(ArenaHeader *relocatedList) return relocatedList; } +ArenaHeader * +GCRuntime::relocateArenas() +{ + gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT_MOVE); + + ArenaHeader *relocatedList = nullptr; + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + JS_ASSERT(zone->isGCFinished()); + JS_ASSERT(!zone->isPreservingCode()); + + // We cannot move atoms as we depend on their addresses being constant. + if (!rt->isAtomsZone(zone)) { + zone->setGCState(Zone::Compact); + relocatedList = zone->allocator.arenas.relocateArenas(relocatedList); + } + } + + return relocatedList; +} + struct MovingTracer : JSTracer { MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapValues) {} @@ -2254,8 +2274,6 @@ MovingTracer::Sweep(JSTracer *jstrc) for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { if (zone->isCollecting()) { - gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_COMPARTMENTS); - bool oom = false; zone->sweep(fop, false, &oom); JS_ASSERT(!oom); @@ -2301,60 +2319,54 @@ void GCRuntime::updatePointersToRelocatedCells() { JS_ASSERT(rt->currentThreadHasExclusiveAccess()); + + gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT_UPDATE); MovingTracer trc(rt); - { - // TODO: Maybe give compaction its own set of phases. - gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK); + // TODO: We may need to fix up other weak pointers here. - // TODO: We may need to fix up other weak pointers here. + // Fixup compartment global pointers as these get accessed during marking. + for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) + comp->fixupAfterMovingGC(); - // Fixup compartment global pointers as these get accessed during marking. - for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) - comp->fixupAfterMovingGC(); + // Fixup cross compartment wrappers as we assert the existence of wrappers in the map. + for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) + comp->fixupCrossCompartmentWrappers(&trc); - // Fixup cross compartment wrappers as we assert the existence of wrappers in the map. - for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) - comp->fixupCrossCompartmentWrappers(&trc); + // Fixup generators as these are not normally traced. + for (ContextIter i(rt); !i.done(); i.next()) { + for (JSGenerator *gen = i.get()->innermostGenerator(); gen; gen = gen->prevGenerator) + gen->obj = MaybeForwarded(gen->obj.get()); + } - // Fixup generators as these are not normally traced. - for (ContextIter i(rt); !i.done(); i.next()) { - for (JSGenerator *gen = i.get()->innermostGenerator(); gen; gen = gen->prevGenerator) - gen->obj = MaybeForwarded(gen->obj.get()); - } - - // Iterate through all allocated cells to update internal pointers. - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - ArenaLists &al = zone->allocator.arenas; - for (unsigned i = 0; i < FINALIZE_LIMIT; ++i) { - AllocKind thingKind = static_cast(i); - JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind); - for (ArenaHeader *arena = al.getFirstArena(thingKind); arena; arena = arena->next) { - for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { - UpdateCellPointers(&trc, i.getCell(), traceKind); - } + // Iterate through all allocated cells to update internal pointers. + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + ArenaLists &al = zone->allocator.arenas; + for (unsigned i = 0; i < FINALIZE_LIMIT; ++i) { + AllocKind thingKind = static_cast(i); + JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind); + for (ArenaHeader *arena = al.getFirstArena(thingKind); arena; arena = arena->next) { + for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { + UpdateCellPointers(&trc, i.getCell(), traceKind); } } } - - // Mark roots to update them. - markRuntime(&trc, MarkRuntime); - Debugger::markAll(&trc); - Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); - - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - if (c->watchpointMap) - c->watchpointMap->markAll(&trc); - } } - { - gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP); + // Mark roots to update them. + markRuntime(&trc, MarkRuntime); + Debugger::markAll(&trc); + Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); - markAllGrayReferences(); - - MovingTracer::Sweep(&trc); + for (GCCompartmentsIter c(rt); !c.done(); c.next()) { + if (c->watchpointMap) + c->watchpointMap->markAll(&trc); } + + markAllGrayReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); + markAllWeakReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); + + MovingTracer::Sweep(&trc); } void @@ -3742,7 +3754,6 @@ GCRuntime::markWeakReferences(gcstats::Phase phase) { JS_ASSERT(marker.isDrained()); - gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_MARK); gcstats::AutoPhase ap1(stats, phase); for (;;) { @@ -3770,35 +3781,25 @@ GCRuntime::markWeakReferencesInCurrentGroup(gcstats::Phase phase) template void -GCRuntime::markGrayReferences() +GCRuntime::markGrayReferences(gcstats::Phase phase) { - { - gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_MARK); - gcstats::AutoPhase ap1(stats, gcstats::PHASE_SWEEP_MARK_GRAY); - marker.setMarkColorGray(); - if (marker.hasBufferedGrayRoots()) { - for (ZoneIterT zone(rt); !zone.done(); zone.next()) - marker.markBufferedGrayRoots(zone); - } else { - JS_ASSERT(!isIncremental); - if (JSTraceDataOp op = grayRootTracer.op) - (*op)(&marker, grayRootTracer.data); - } - SliceBudget budget; - marker.drainMarkStack(budget); + gcstats::AutoPhase ap(stats, phase); + if (marker.hasBufferedGrayRoots()) { + for (ZoneIterT zone(rt); !zone.done(); zone.next()) + marker.markBufferedGrayRoots(zone); + } else { + JS_ASSERT(!isIncremental); + if (JSTraceDataOp op = grayRootTracer.op) + (*op)(&marker, grayRootTracer.data); } - - markWeakReferences(gcstats::PHASE_SWEEP_MARK_GRAY_WEAK); - - JS_ASSERT(marker.isDrained()); - - marker.setMarkColorBlack(); + SliceBudget budget; + marker.drainMarkStack(budget); } void -GCRuntime::markGrayReferencesInCurrentGroup() +GCRuntime::markGrayReferencesInCurrentGroup(gcstats::Phase phase) { - markGrayReferences(); + markGrayReferences(phase); } void @@ -3808,9 +3809,9 @@ GCRuntime::markAllWeakReferences(gcstats::Phase phase) } void -GCRuntime::markAllGrayReferences() +GCRuntime::markAllGrayReferences(gcstats::Phase phase) { - markGrayReferences(); + markGrayReferences(phase); } #ifdef DEBUG @@ -3931,7 +3932,8 @@ js::gc::MarkingValidator::nonIncrementalMark() gc->incrementalState = SWEEP; { - gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_SWEEP); + gcstats::AutoPhase ap1(gc->stats, gcstats::PHASE_SWEEP); + gcstats::AutoPhase ap2(gc->stats, gcstats::PHASE_SWEEP_MARK); gc->markAllWeakReferences(gcstats::PHASE_SWEEP_MARK_WEAK); /* Update zone state for gray marking. */ @@ -3939,14 +3941,18 @@ js::gc::MarkingValidator::nonIncrementalMark() JS_ASSERT(zone->isGCMarkingBlack()); zone->setGCState(Zone::MarkGray); } + gc->marker.setMarkColorGray(); - gc->markAllGrayReferences(); + gc->markAllGrayReferences(gcstats::PHASE_SWEEP_MARK_GRAY); + gc->markAllWeakReferences(gcstats::PHASE_SWEEP_MARK_GRAY_WEAK); /* Restore zone state. */ for (GCZonesIter zone(runtime); !zone.done(); zone.next()) { JS_ASSERT(zone->isGCMarkingGray()); zone->setGCState(Zone::Mark); } + JS_ASSERT(gc->marker.isDrained()); + gc->marker.setMarkColorBlack(); } /* Take a copy of the non-incremental mark state and restore the original. */ @@ -4347,7 +4353,6 @@ MarkIncomingCrossCompartmentPointers(JSRuntime *rt, const uint32_t color) { JS_ASSERT(color == BLACK || color == GRAY); - gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_MARK); static const gcstats::Phase statsPhases[] = { gcstats::PHASE_SWEEP_MARK_INCOMING_BLACK, gcstats::PHASE_SWEEP_MARK_INCOMING_GRAY @@ -4472,6 +4477,8 @@ js::NotifyGCPostSwap(JSObject *a, JSObject *b, unsigned removedFlags) void GCRuntime::endMarkingZoneGroup() { + gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_MARK); + /* * Mark any incoming black pointers from previously swept compartments * whose referents are not marked. This can occur when gray cells become @@ -4491,22 +4498,22 @@ GCRuntime::endMarkingZoneGroup() JS_ASSERT(zone->isGCMarkingBlack()); zone->setGCState(Zone::MarkGray); } + marker.setMarkColorGray(); /* Mark incoming gray pointers from previously swept compartments. */ - marker.setMarkColorGray(); MarkIncomingCrossCompartmentPointers(rt, GRAY); - marker.setMarkColorBlack(); /* Mark gray roots and mark transitively inside the current compartment group. */ - markGrayReferencesInCurrentGroup(); + markGrayReferencesInCurrentGroup(gcstats::PHASE_SWEEP_MARK_GRAY); + markWeakReferencesInCurrentGroup(gcstats::PHASE_SWEEP_MARK_GRAY_WEAK); /* Restore marking state. */ for (GCZoneGroupIter zone(rt); !zone.done(); zone.next()) { JS_ASSERT(zone->isGCMarkingGray()); zone->setGCState(Zone::Mark); } - - JS_ASSERT(marker.isDrained()); + MOZ_ASSERT(marker.isDrained()); + marker.setMarkColorBlack(); } void @@ -4579,6 +4586,8 @@ GCRuntime::beginSweepingZoneGroup() for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) { gcstats::AutoSCC scc(stats, zoneGroupIndex); + gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_TABLES); + c->sweep(&fop, releaseObservedTypes && !c->zone()->isPreservingCode()); } @@ -4940,18 +4949,9 @@ GCRuntime::compactPhase() JS_ASSERT(rt->gc.nursery.isEmpty()); JS_ASSERT(!sweepOnBackgroundThread); - ArenaHeader *relocatedList = nullptr; - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - JS_ASSERT(zone->isGCFinished()); - JS_ASSERT(!zone->isPreservingCode()); - - // We cannot move atoms as we depend on their addresses being constant. - if (!rt->isAtomsZone(zone)) { - zone->setGCState(Zone::Compact); - relocatedList = zone->allocator.arenas.relocateArenas(relocatedList); - } - } + gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT); + ArenaHeader *relocatedList = relocateArenas(); updatePointersToRelocatedCells(); releaseRelocatedArenas(relocatedList); diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 275a288705f0..a0a7eb49a22b 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -4390,7 +4390,8 @@ TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) } { - gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_DISCARD_TI); + gcstats::MaybeAutoPhase ap2(rt->gc.stats, !rt->isHeapCompacting(), + gcstats::PHASE_DISCARD_TI); for (ZoneCellIterUnderGC i(zone(), FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); @@ -4421,7 +4422,8 @@ TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) } { - gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_SWEEP_TYPES); + gcstats::MaybeAutoPhase ap2(rt->gc.stats, !rt->isHeapCompacting(), + gcstats::PHASE_SWEEP_TYPES); for (gc::ZoneCellIterUnderGC iter(zone(), gc::FINALIZE_TYPE_OBJECT); !iter.done(); iter.next()) @@ -4449,7 +4451,8 @@ TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) } { - gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_FREE_TI_ARENA); + gcstats::MaybeAutoPhase ap2(rt->gc.stats, !rt->isHeapCompacting(), + gcstats::PHASE_FREE_TI_ARENA); rt->freeLifoAlloc.transferFrom(&oldAlloc); } } diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 173f44d1c501..e5616a738100 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1542,8 +1542,9 @@ BaseShape::assertConsistency() void JSCompartment::sweepBaseShapeTable() { - gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, - gcstats::PHASE_SWEEP_TABLES_BASE_SHAPE); + GCRuntime &gc = runtimeFromMainThread()->gc; + gcstats::MaybeAutoPhase ap(gc.stats, !gc.isHeapCompacting(), + gcstats::PHASE_SWEEP_TABLES_BASE_SHAPE); if (baseShapes.initialized()) { for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) { @@ -1839,8 +1840,9 @@ EmptyShape::insertInitialShape(ExclusiveContext *cx, HandleShape shape, HandleOb void JSCompartment::sweepInitialShapeTable() { - gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, - gcstats::PHASE_SWEEP_TABLES_INITIAL_SHAPE); + GCRuntime &gc = runtimeFromMainThread()->gc; + gcstats::MaybeAutoPhase ap(gc.stats, !gc.isHeapCompacting(), + gcstats::PHASE_SWEEP_TABLES_INITIAL_SHAPE); if (initialShapes.initialized()) { for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) { From 30739ea48b24600a2d28f0498f0eb6c286bc1b1f Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 11:52:33 +0100 Subject: [PATCH 013/119] Bug 650161 - Fix test failures with compacting GC enabled r=terrence --- js/src/gc/Barrier.h | 2 + js/src/gc/GCRuntime.h | 14 ++++++ js/src/gc/Marking.cpp | 1 + js/src/gc/Marking.h | 2 + js/src/gc/Tracer.cpp | 12 ++--- js/src/gc/Tracer.h | 2 +- js/src/jscompartment.cpp | 17 +++++-- js/src/jscompartment.h | 4 +- js/src/jsgc.cpp | 82 ++++++++++++++++++++++++++++----- js/src/jsgc.h | 20 ++++++-- js/src/jshashutil.h | 2 +- js/src/jsweakmap.cpp | 7 +++ js/src/jsweakmap.h | 3 ++ js/src/shell/jsheaptools.cpp | 2 + js/src/vm/ArrayBufferObject.cpp | 11 ++++- js/src/vm/ArrayBufferObject.h | 2 + js/src/vm/Debugger.cpp | 14 ------ js/src/vm/SavedStacks.cpp | 5 +- js/src/vm/ScopeObject.cpp | 13 +++++- js/src/vm/ScopeObject.h | 2 + js/src/vm/Shape.cpp | 2 +- js/src/vm/TypedArrayObject.h | 3 ++ 22 files changed, 174 insertions(+), 48 deletions(-) diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 34468f74b295..21bce82f0517 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -169,6 +169,7 @@ class BaseShape; class DebugScopeObject; class GlobalObject; class LazyScript; +class NestedScopeObject; class Nursery; class ObjectImpl; class PropertyName; @@ -217,6 +218,7 @@ template <> struct MapTypeToTraceKind { static const JSGCTrace template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SCRIPT; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_LAZY_SCRIPT; }; +template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index f75889b621f4..91daac090be9 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -396,6 +396,11 @@ class GCRuntime void disableGenerationalGC(); void enableGenerationalGC(); +#ifdef JSGC_COMPACTING + void disableCompactingGC(); + void enableCompactingGC(); +#endif + void setGrayRootsTracer(JSTraceDataOp traceOp, void *data); bool addBlackRootsTracer(JSTraceDataOp traceOp, void *data); void removeBlackRootsTracer(JSTraceDataOp traceOp, void *data); @@ -713,6 +718,15 @@ class GCRuntime */ unsigned generationalDisabled; +#ifdef JSGC_COMPACTING + /* + * Some code cannot tolerate compacting GC so it can be disabled with this + * counter. This can happen from code executing in a ThreadSafeContext so + * we make it atomic. + */ + mozilla::Atomic compactingDisabled; +#endif + /* * This is true if we are in the middle of a brain transplant (e.g., * JS_TransplantObject) or some other operation that can manipulate diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 4e4f2e8a0d47..583361534b4d 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -629,6 +629,7 @@ DeclMarkerImpl(Object, DebugScopeObject) DeclMarkerImpl(Object, GlobalObject) DeclMarkerImpl(Object, JSObject) DeclMarkerImpl(Object, JSFunction) +DeclMarkerImpl(Object, NestedScopeObject) DeclMarkerImpl(Object, ObjectImpl) DeclMarkerImpl(Object, SavedFrame) DeclMarkerImpl(Object, ScopeObject) diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index 440b33261a02..ade9c5df0ee3 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -23,6 +23,7 @@ class DebugScopeObject; class GCMarker; class GlobalObject; class LazyScript; +class NestedScopeObject; class SavedFrame; class ScopeObject; class Shape; @@ -112,6 +113,7 @@ DeclMarker(Object, DebugScopeObject) DeclMarker(Object, GlobalObject) DeclMarker(Object, JSObject) DeclMarker(Object, JSFunction) +DeclMarker(Object, NestedScopeObject) DeclMarker(Object, SavedFrame) DeclMarker(Object, ScopeObject) DeclMarker(Script, JSScript) diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 5e5831c6f72e..7648cd2e59e1 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -637,28 +637,26 @@ GCMarker::markBufferedGrayRoots(JS::Zone *zone) #ifdef DEBUG setTracingDetails(elem->debugPrinter, elem->debugPrintArg, elem->debugPrintIndex); #endif - void *tmp = elem->thing; - setTracingLocation((void *)&elem->thing); - MarkKind(this, &tmp, elem->kind); - JS_ASSERT(tmp == elem->thing); + MarkKind(this, elem->thingp, elem->kind); } } void -GCMarker::appendGrayRoot(void *thing, JSGCTraceKind kind) +GCMarker::appendGrayRoot(void **thingp, JSGCTraceKind kind) { JS_ASSERT(started); if (grayBufferState == GRAY_BUFFER_FAILED) return; - GrayRoot root(thing, kind); + GrayRoot root(thingp, kind); #ifdef DEBUG root.debugPrinter = debugPrinter(); root.debugPrintArg = debugPrintArg(); root.debugPrintIndex = debugPrintIndex(); #endif + void *thing = *thingp; Zone *zone = static_cast(thing)->tenuredZone(); if (zone->isCollecting()) { // See the comment on SetMaybeAliveFlag to see why we only do this for @@ -688,7 +686,7 @@ GCMarker::GrayCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind) JS_ASSERT(thingp); JS_ASSERT(*thingp); GCMarker *gcmarker = static_cast(trc); - gcmarker->appendGrayRoot(*thingp, kind); + gcmarker->appendGrayRoot(thingp, kind); } size_t diff --git a/js/src/gc/Tracer.h b/js/src/gc/Tracer.h index 19161c4232ca..902e556d6027 100644 --- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -275,7 +275,7 @@ class GCMarker : public JSTracer inline void processMarkStackTop(SliceBudget &budget); void processMarkStackOther(uintptr_t tag, uintptr_t addr); - void appendGrayRoot(void *thing, JSGCTraceKind kind); + void appendGrayRoot(void **thingp, JSGCTraceKind kind); /* The color is only applied to objects and functions. */ uint32_t color; diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index d69ef9043a28..82a1aaf257ee 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -627,6 +627,17 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes) ni->unlink(); ni = next; } + + /* For each debuggee being GC'd, detach it from all its debuggers. */ + for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) { + GlobalObject *global = e.front(); + if (IsObjectAboutToBeFinalized(&global)) { + // See infallibility note above. + Debugger::detachAllDebuggersFromGlobal(fop, global, &e); + } else if (global != e.front()) { + e.rekeyFront(global); + } + } } /* @@ -881,7 +892,7 @@ JSCompartment::updateJITForDebugMode(JSContext *maybecx, AutoDebugModeInvalidati } bool -JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global) +JSCompartment::addDebuggee(JSContext *cx, JS::Handle global) { AutoDebugModeInvalidation invalidate(this); return addDebuggee(cx, global, invalidate); @@ -889,11 +900,9 @@ JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global) bool JSCompartment::addDebuggee(JSContext *cx, - GlobalObject *globalArg, + JS::Handle global, AutoDebugModeInvalidation &invalidate) { - Rooted global(cx, globalArg); - bool wasEnabled = debugMode(); if (!debuggees.put(global)) { js_ReportOutOfMemory(cx); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index bb03696fbcea..0c1a9675029f 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -423,8 +423,8 @@ struct JSCompartment public: js::GlobalObjectSet &getDebuggees() { return debuggees; } - bool addDebuggee(JSContext *cx, js::GlobalObject *global); - bool addDebuggee(JSContext *cx, js::GlobalObject *global, + bool addDebuggee(JSContext *cx, JS::Handle global); + bool addDebuggee(JSContext *cx, JS::Handle global, js::AutoDebugModeInvalidation &invalidate); bool removeDebuggee(JSContext *cx, js::GlobalObject *global, js::GlobalObjectSet::Enum *debuggeesEnum = nullptr); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 0ccc64b68342..6fba654c6a81 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1158,6 +1158,9 @@ GCRuntime::GCRuntime(JSRuntime *rt) : sliceBudget(SliceBudget::Unlimited), incrementalAllowed(true), generationalDisabled(0), +#ifdef JSGC_COMPACTING + compactingDisabled(0), +#endif manipulatingDeadZones(false), objectsMarkedInDeadZones(0), poked(false), @@ -2004,7 +2007,7 @@ bool GCRuntime::shouldCompact() { #ifdef JSGC_COMPACTING - return invocationKind == GC_SHRINK; + return invocationKind == GC_SHRINK && !compactingDisabled; #else return false; #endif @@ -2012,6 +2015,30 @@ GCRuntime::shouldCompact() #ifdef JSGC_COMPACTING +void +GCRuntime::disableCompactingGC() +{ + ++rt->gc.compactingDisabled; +} + +void +GCRuntime::enableCompactingGC() +{ + JS_ASSERT(compactingDisabled > 0); + --compactingDisabled; +} + +AutoDisableCompactingGC::AutoDisableCompactingGC(JSRuntime *rt) + : gc(rt->gc) +{ + gc.disableCompactingGC(); +} + +AutoDisableCompactingGC::~AutoDisableCompactingGC() +{ + gc.enableCompactingGC(); +} + static void ForwardCell(Cell *dest, Cell *src) { @@ -2048,9 +2075,11 @@ CanRelocateArena(ArenaHeader *arena) /* * We can't currently move global objects because their address is baked * into compiled code. We therefore skip moving the contents of any arena - * containing a global. + * containing a global if ion or baseline are enabled. */ - return arena->getAllocKind() <= FINALIZE_OBJECT_LAST && !ArenaContainsGlobal(arena); + JSRuntime *rt = arena->zone->runtimeFromMainThread(); + return arena->getAllocKind() <= FINALIZE_OBJECT_LAST && + ((!rt->options().baseline() && !rt->options().ion()) || !ArenaContainsGlobal(arena)); } static bool @@ -2103,6 +2132,14 @@ ArenaList::pickArenasToRelocate() return head; } +#ifdef DEBUG +inline bool +PtrIsInRange(void *ptr, void *start, size_t length) +{ + return uintptr_t(ptr) - uintptr_t(start) < length; +} +#endif + static bool RelocateCell(Zone *zone, Cell *src, AllocKind thingKind, size_t thingSize) { @@ -2116,22 +2153,38 @@ RelocateCell(Zone *zone, Cell *src, AllocKind thingKind, size_t thingSize) // Copy source cell contents to destination. memcpy(dst, src, thingSize); - // Mark source cell as forwarded and leave a pointer to the destination. - ForwardCell(static_cast(dst), src); - // Fixup the pointer to inline object elements if necessary. if (thingKind <= FINALIZE_OBJECT_LAST) { JSObject *srcObj = static_cast(src); JSObject *dstObj = static_cast(dst); if (srcObj->hasFixedElements()) dstObj->setFixedElements(); - JS_ASSERT( - uintptr_t((HeapSlot*)dstObj->getElementsHeader()) - uintptr_t(srcObj) >= thingSize); + + if (srcObj->is()) { + // We must fix up any inline data pointers while we know the source + // object and before we mark any of the views. + ArrayBufferObject::fixupDataPointerAfterMovingGC( + srcObj->as(), dstObj->as()); + } else if (srcObj->is()) { + TypedArrayObject &typedArray = srcObj->as(); + if (!typedArray.hasBuffer()) { + JS_ASSERT(srcObj->getPrivate() == + srcObj->fixedData(TypedArrayObject::FIXED_DATA_START)); + dstObj->setPrivate(dstObj->fixedData(TypedArrayObject::FIXED_DATA_START)); + } + } + + + JS_ASSERT_IF(dstObj->isNative(), + !PtrIsInRange((HeapSlot*)dstObj->getDenseElements(), src, thingSize)); } // Copy the mark bits. static_cast(dst)->copyMarkBitsFrom(src); + // Mark source cell as forwarded and leave a pointer to the destination. + ForwardCell(static_cast(dst), src); + return true; } @@ -2251,10 +2304,12 @@ void MovingTracer::Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) { Cell *thing = static_cast(*thingp); - if (!thing->tenuredZone()->isGCCompacting()) { + Zone *zone = thing->tenuredZoneFromAnyThread(); + if (!zone->isGCCompacting()) { JS_ASSERT(!IsForwarded(thing)); return; } + JS_ASSERT(CurrentThreadCanAccessZone(zone)); if (IsForwarded(thing)) { Cell *dst = Forwarded(thing); @@ -2280,7 +2335,6 @@ MovingTracer::Sweep(JSTracer *jstrc) for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) { c->sweep(fop, false); - ArrayBufferObject::sweep(c); } } else { /* Update cross compartment wrappers into moved zones. */ @@ -2291,6 +2345,9 @@ MovingTracer::Sweep(JSTracer *jstrc) /* Type inference may put more blocks here to free. */ rt->freeLifoAlloc.freeAll(); + + /* Clear the new object cache as this can contain cell pointers. */ + rt->newObjectCache.purge(); } /* @@ -2359,12 +2416,15 @@ GCRuntime::updatePointersToRelocatedCells() Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); for (GCCompartmentsIter c(rt); !c.done(); c.next()) { + WeakMapBase::markAll(c, &trc); if (c->watchpointMap) c->watchpointMap->markAll(&trc); } + // Mark all gray roots, making sure we call the trace callback to get the + // current set. + marker.resetBufferedGrayRoots(); markAllGrayReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); - markAllWeakReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); MovingTracer::Sweep(&trc); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 4098135495de..115fc9583b8e 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1138,7 +1138,7 @@ struct GCChunkHasher { typedef HashSet GCChunkSet; struct GrayRoot { - void *thing; + void **thingp; JSGCTraceKind kind; #ifdef DEBUG JSTraceNamePrinter debugPrinter; @@ -1146,8 +1146,8 @@ struct GrayRoot { size_t debugPrintIndex; #endif - GrayRoot(void *thing, JSGCTraceKind kind) - : thing(thing), kind(kind) {} + GrayRoot(void **thingp, JSGCTraceKind kind) + : thingp(thingp), kind(kind) {} }; void @@ -1427,6 +1427,20 @@ struct AutoDisableProxyCheck }; #endif +struct AutoDisableCompactingGC +{ +#ifdef JSGC_COMPACTING + explicit AutoDisableCompactingGC(JSRuntime *rt); + ~AutoDisableCompactingGC(); + + private: + gc::GCRuntime &gc; +#else + explicit AutoDisableCompactingGC(JSRuntime *rt) {} + ~AutoDisableCompactingGC() {} +#endif +}; + void PurgeJITCaches(JS::Zone *zone); diff --git a/js/src/jshashutil.h b/js/src/jshashutil.h index aebb15bcfc31..d95cbd41a9ba 100644 --- a/js/src/jshashutil.h +++ b/js/src/jshashutil.h @@ -13,7 +13,7 @@ namespace js { /* * Used to add entries to a js::HashMap or HashSet where the key depends on a GC - * thing that may be moved by generational collection between the call to + * thing that may be moved by generational or compacting GC between the call to * lookupForAdd() and relookupOrAdd(). */ template diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index 2783658a0f9a..c25a0dc2a14e 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -68,6 +68,13 @@ WeakMapBase::unmarkCompartment(JSCompartment *c) m->marked = false; } +void +WeakMapBase::markAll(JSCompartment *c, JSTracer *tracer) +{ + for (WeakMapBase *m = c->gcWeakMapList; m; m = m->next) + m->markIteratively(tracer); +} + bool WeakMapBase::markCompartmentIteratively(JSCompartment *c, JSTracer *tracer) { diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 690278be3a72..07fa008fc61f 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -49,6 +49,9 @@ class WeakMapBase { // Unmark all weak maps in a compartment. static void unmarkCompartment(JSCompartment *c); + // Mark all the weakmaps in a compartment. + static void markAll(JSCompartment *c, JSTracer *tracer); + // Check all weak maps in a compartment that have been marked as live in this garbage // collection, and mark the values of all entries that have become strong references // to them. Return true if we marked any new values, indicating that we need to make diff --git a/js/src/shell/jsheaptools.cpp b/js/src/shell/jsheaptools.cpp index 93cc36cbdd28..f172b1710e05 100644 --- a/js/src/shell/jsheaptools.cpp +++ b/js/src/shell/jsheaptools.cpp @@ -157,6 +157,7 @@ class HeapReverser : public JSTracer, public JS::CustomAutoRooter : JSTracer(cx->runtime(), traverseEdgeWithThis), JS::CustomAutoRooter(cx), noggc(JS_GetRuntime(cx)), + nocgc(JS_GetRuntime(cx)), runtime(JS_GetRuntime(cx)), parent(nullptr) { @@ -169,6 +170,7 @@ class HeapReverser : public JSTracer, public JS::CustomAutoRooter private: JS::AutoDisableGenerationalGC noggc; + js::AutoDisableCompactingGC nocgc; /* A runtime pointer for use by the destructor. */ JSRuntime *runtime; diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 0c7d2cf34f54..2aaf5b34f246 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -932,6 +932,15 @@ ArrayBufferObject::sweep(JSCompartment *compartment) gcLiveArrayBuffers.clear(); } +/* static */ void +ArrayBufferObject::fixupDataPointerAfterMovingGC(const ArrayBufferObject &src, ArrayBufferObject &dst) +{ + // Fix up possible inline data pointer. + const size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&ArrayBufferObject::class_); + if (src.dataPointer() == src.fixedData(reservedSlots)) + dst.setSlot(DATA_SLOT, PrivateValue(dst.fixedData(reservedSlots))); +} + void ArrayBufferObject::resetArrayBufferList(JSCompartment *comp) { @@ -992,7 +1001,7 @@ ArrayBufferViewObject::trace(JSTracer *trc, JSObject *obj) // Update obj's data pointer if the array buffer moved. Note that during // initialization, bufSlot may still contain |undefined|. if (bufSlot.isObject()) { - ArrayBufferObject &buf = AsArrayBuffer(&bufSlot.toObject()); + ArrayBufferObject &buf = AsArrayBuffer(MaybeForwarded(&bufSlot.toObject())); int32_t offset = obj->getReservedSlot(BYTEOFFSET_SLOT).toInt32(); MOZ_ASSERT(buf.dataPointer() != nullptr); obj->initPrivate(buf.dataPointer() + offset); diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h index 22b84081320b..8bf20bc76584 100644 --- a/js/src/vm/ArrayBufferObject.h +++ b/js/src/vm/ArrayBufferObject.h @@ -95,6 +95,8 @@ class ArrayBufferObject : public JSObject static void sweep(JSCompartment *rt); + static void fixupDataPointerAfterMovingGC(const ArrayBufferObject &src, ArrayBufferObject &dst); + static void resetArrayBufferList(JSCompartment *rt); static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector); static void restoreArrayBufferLists(ArrayBufferVector &vector); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index d6aee1c85812..5e016a39a8c0 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1750,20 +1750,6 @@ Debugger::sweepAll(FreeOp *fop) } } } - - for (gc::GCCompartmentGroupIter comp(rt); !comp.done(); comp.next()) { - /* For each debuggee being GC'd, detach it from all its debuggers. */ - GlobalObjectSet &debuggees = comp->getDebuggees(); - for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) { - GlobalObject *global = e.front(); - if (IsObjectAboutToBeFinalized(&global)) { - // See infallibility note above. - detachAllDebuggersFromGlobal(fop, global, &e); - } else if (global != e.front()) { - e.rekeyFront(global); - } - } - } } void diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index 815b7e5d5d16..3ecaff67ba65 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -10,6 +10,7 @@ #include "jsapi.h" #include "jscompartment.h" #include "jsfriendapi.h" +#include "jshashutil.h" #include "jsnum.h" #include "gc/Marking.h" @@ -562,7 +563,7 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram SavedFrame * SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup lookup) { - SavedFrame::Set::AddPtr p = frames.lookupForAdd(lookup); + DependentAddPtr p(cx, frames, lookup); if (p) return *p; @@ -570,7 +571,7 @@ SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup looku if (!frame) return nullptr; - if (!frames.relookupOrAdd(p, lookup, frame)) + if (!p.add(cx, frames, lookup, frame)) return nullptr; return frame; diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 6032961017f8..5fe614acb05f 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1070,6 +1070,15 @@ ScopeIterKey::match(ScopeIterKey si1, ScopeIterKey si2) si1.type_ == si2.type_)); } +void +ScopeIterVal::sweep() +{ + /* We need to update possibly moved pointers on sweep. */ + MOZ_ALWAYS_FALSE(IsObjectAboutToBeFinalized(cur_.unsafeGet())); + if (staticScope_) + MOZ_ALWAYS_FALSE(IsObjectAboutToBeFinalized(staticScope_.unsafeGet())); +} + // Live ScopeIter values may be added to DebugScopes::liveScopes, as // ScopeIterVal instances. They need to have write barriers when they are added // to the hash table, but no barriers when rehashing inside GC. It's a nasty @@ -1792,7 +1801,7 @@ DebugScopes::sweep(JSRuntime *rt) key.updateCur(js::gc::Forwarded(key.cur())); needsUpdate = true; } - if (IsForwarded(key.staticScope())) { + if (key.staticScope() && IsForwarded(key.staticScope())) { key.updateStaticScope(Forwarded(key.staticScope())); needsUpdate = true; } @@ -1804,6 +1813,8 @@ DebugScopes::sweep(JSRuntime *rt) for (LiveScopeMap::Enum e(liveScopes); !e.empty(); e.popFront()) { ScopeObject *scope = e.front().key(); + e.front().value().sweep(); + /* * Scopes can be finalized when a debugger-synthesized ScopeObject is * no longer reachable via its DebugScopeObject. diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 22c9464e86a6..30e86d50ef0f 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -733,6 +733,8 @@ class ScopeIterVal ScopeIter::Type type_; bool hasScopeObject_; + void sweep(); + static void staticAsserts(); public: diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index e5616a738100..267a6ffc41e9 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -445,7 +445,7 @@ js::ObjectImpl::toDictionaryMode(ThreadSafeContext *cx) #ifdef JSGC_COMPACTING // TODO: This crashes if we run a compacting GC here. - js::gc::AutoSuppressGC nogc(zone()->runtimeFromAnyThread()); + js::AutoDisableCompactingGC nogc(zone()->runtimeFromAnyThread()); #endif /* We allocate the shapes from cx->compartment(), so make sure it's right. */ diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index 75916593f1f9..0fdbbba4a6d8 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -80,6 +80,9 @@ class TypedArrayObject : public ArrayBufferViewObject ensureHasBuffer(JSContext *cx, Handle tarray); ArrayBufferObject *sharedBuffer() const; + bool hasBuffer() const { + return bufferValue(const_cast(this)).isObject(); + } ArrayBufferObject *buffer() const { JSObject *obj = bufferValue(const_cast(this)).toObjectOrNull(); if (!obj) From 620e9723f983c2ace782443650a7c0c77c0cd117 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Thu, 14 Aug 2014 12:26:06 +0100 Subject: [PATCH 014/119] Bug 650161 - Fix build error in non-unified builds r=me --- js/src/jscompartment.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 82a1aaf257ee..46ee7e5ad958 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -20,6 +20,7 @@ #include "gc/Marking.h" #include "jit/JitCompartment.h" #include "js/RootingAPI.h" +#include "vm/Debugger.h" #include "vm/StopIterationObject.h" #include "vm/WrapperObject.h" From aa6933168595b6601e5d623b8b896270ccf2fd61 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Wed, 13 Aug 2014 17:55:28 +0200 Subject: [PATCH 015/119] Bug 1041808 - Thousands of about:blank windows when cookies policy set to "Keep until: I close Firefox". r=smaug. --HG-- extra : rebase_source : 8706fb4ca98b9d01893dd4544d395161a4277474 --- extensions/cookie/nsCookiePromptService.cpp | 6 ++ extensions/cookie/test/mochitest.ini | 1 + extensions/cookie/test/test_bug1041808.html | 61 +++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 extensions/cookie/test/test_bug1041808.html diff --git a/extensions/cookie/nsCookiePromptService.cpp b/extensions/cookie/nsCookiePromptService.cpp index 32c875d56b79..f50c077ce8f0 100644 --- a/extensions/cookie/nsCookiePromptService.cpp +++ b/extensions/cookie/nsCookiePromptService.cpp @@ -13,6 +13,7 @@ #include "nsString.h" #include "nsIDialogParamBlock.h" #include "nsIMutableArray.h" +#include "mozilla/dom/ScriptSettings.h" /**************************************************************** ************************ nsCookiePromptService ***************** @@ -71,6 +72,11 @@ nsCookiePromptService::CookieDialog(nsIDOMWindow *aParent, parent = do_QueryInterface(privateParent); } + // We're opening a chrome window and passing in a nsIDialogParamBlock. Setting + // the nsIDialogParamBlock as the .arguments property on the chrome window + // requires system principals on the stack, so we use an AutoNoJSAPI for that. + mozilla::dom::AutoNoJSAPI nojsapi; + // The cookie dialog will be modal for the root chrome window rather than the // tab containing the permission-requesting page. This removes confusion // about which monitor is displaying the dialog (see bug 470356), but also diff --git a/extensions/cookie/test/mochitest.ini b/extensions/cookie/test/mochitest.ini index 794dce7d52e0..0d5c8ec3832f 100644 --- a/extensions/cookie/test/mochitest.ini +++ b/extensions/cookie/test/mochitest.ini @@ -38,3 +38,4 @@ support-files = [test_same_base_domain_5.html] [test_same_base_domain_6.html] [test_samedomain.html] +[test_bug1041808.html] diff --git a/extensions/cookie/test/test_bug1041808.html b/extensions/cookie/test/test_bug1041808.html new file mode 100644 index 000000000000..38a8832e0e94 --- /dev/null +++ b/extensions/cookie/test/test_bug1041808.html @@ -0,0 +1,61 @@ + + + + + + Test for Bug 1041808 + + + + + + +Mozilla Bug 1041808 +

+ +
+
+ + From 30803169a460d20d591c2db292310b923ae807ac Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Fri, 8 Aug 2014 15:03:29 +0200 Subject: [PATCH 016/119] Bug 1036186 - Reset Migration wizard no longer skips the first step to choose a browser. r=smaug. --HG-- extra : rebase_source : 599d78a04a085304154e8231d5bd2239d025ab22 --- dom/base/nsDOMClassInfo.cpp | 22 +++------------------- dom/base/nsDOMClassInfo.h | 7 +------ dom/bindings/BindingUtils.cpp | 29 +++++++++++++++++++++++++++++ dom/bindings/BindingUtils.h | 8 ++++++++ 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d851b683acef..ff2e586e978f 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -429,7 +429,6 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] = #undef NS_DEFINE_CONSTRUCTOR_FUNC_DATA nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr; -nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nullptr; bool nsDOMClassInfo::sIsInitialized = false; @@ -780,19 +779,11 @@ nsDOMClassInfo::Init() nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); - nsresult rv = CallGetService(nsIXPConnect::GetCID(), &sXPConnect); - NS_ENSURE_SUCCESS(rv, rv); + NS_ADDREF(sXPConnect = nsContentUtils::XPConnect()); nsCOMPtr elt = new nsEventListenerThisTranslator(); sXPConnect->SetFunctionThisTranslator(NS_GET_IID(nsIDOMEventListener), elt); - nsCOMPtr sm = - do_GetService("@mozilla.org/scriptsecuritymanager;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - sSecMan = sm; - NS_ADDREF(sSecMan); - AutoSafeJSContext cx; DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow) @@ -1043,9 +1034,6 @@ nsDOMClassInfo::Init() RegisterExternalClasses(); - // Register new DOM bindings - mozilla::dom::Register(nameSpaceManager); - sIsInitialized = true; return NS_OK; @@ -1524,11 +1512,8 @@ NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID) return nullptr; } - if (!nsDOMClassInfo::sIsInitialized) { - nsresult rv = nsDOMClassInfo::Init(); - - NS_ENSURE_SUCCESS(rv, nullptr); - } + nsresult rv = RegisterDOMNames(); + NS_ENSURE_SUCCESS(rv, nullptr); if (!sClassInfoData[aID].mCachedClassInfo) { nsDOMClassInfoData& data = sClassInfoData[aID]; @@ -1589,7 +1574,6 @@ nsDOMClassInfo::ShutDown() sWrappedJSObject_id = JSID_VOID; NS_IF_RELEASE(sXPConnect); - NS_IF_RELEASE(sSecMan); sIsInitialized = false; } diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index 39eea5c28162..77e353f7317a 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -96,6 +96,7 @@ public: static nsIClassInfo* GetClassInfoInstance(nsDOMClassInfoData* aData); + static nsresult Init(); static void ShutDown(); static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) @@ -127,10 +128,6 @@ public: { return sXPConnect; } - static nsIScriptSecurityManager *ScriptSecurityManager() - { - return sSecMan; - } protected: friend nsIClassInfo* NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID); @@ -146,14 +143,12 @@ protected: return mData->mInterfacesBitmap; } - static nsresult Init(); static nsresult RegisterClassProtos(int32_t aDOMClassInfoID); static nsresult RegisterExternalClasses(); nsresult ResolveConstructor(JSContext *cx, JSObject *obj, JSObject **objp); static nsIXPConnect *sXPConnect; - static nsIScriptSecurityManager *sSecMan; // nsIXPCScriptable code static nsresult DefineStaticJSVals(JSContext *cx); diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 62992a63368f..303b952d7b86 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -43,6 +43,7 @@ #include "mozilla/dom/HTMLAppletElementBinding.h" #include "mozilla/dom/Promise.h" #include "WorkerPrivate.h" +#include "nsDOMClassInfo.h" namespace mozilla { namespace dom { @@ -2561,6 +2562,34 @@ CreateGlobalOptions::TraceGlobal(JSTracer* aTrc, JSObject* aObj) xpc::TraceXPCGlobal(aTrc, aObj); } +static bool sRegisteredDOMNames = false; + +nsresult +RegisterDOMNames() +{ + if (sRegisteredDOMNames) { + return NS_OK; + } + + nsresult rv = nsDOMClassInfo::Init(); + if (NS_FAILED(rv)) { + NS_ERROR("Could not initialize nsDOMClassInfo"); + return rv; + } + + // Register new DOM bindings + nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager(); + if (!nameSpaceManager) { + NS_ERROR("Could not initialize nsScriptNameSpaceManager"); + return NS_ERROR_FAILURE; + } + mozilla::dom::Register(nameSpaceManager); + + sRegisteredDOMNames = true; + + return NS_OK; +} + /* static */ bool CreateGlobalOptions::PostCreateGlobal(JSContext* aCx, diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 0e051600d277..2795eaca5aa3 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -2808,6 +2808,9 @@ struct CreateGlobalOptions static bool PostCreateGlobal(JSContext* aCx, JS::Handle aGlobal); }; +nsresult +RegisterDOMNames(); + template bool CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache, @@ -2815,6 +2818,11 @@ CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache, JSPrincipals* aPrincipal, bool aInitStandardClasses, JS::MutableHandle aGlobal) { + nsresult rv = RegisterDOMNames(); + if (NS_FAILED(rv)) { + return Throw(aCx, rv); + } + aOptions.setTrace(CreateGlobalOptions::TraceGlobal); aGlobal.set(JS_NewGlobalObject(aCx, aClass, aPrincipal, From 71a3f0a5705210896514e257a55d75d93696a97f Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:23 +0100 Subject: [PATCH 017/119] Backed out changeset 55126a7a7447 (bug 650161) --- js/src/jscompartment.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 46ee7e5ad958..82a1aaf257ee 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -20,7 +20,6 @@ #include "gc/Marking.h" #include "jit/JitCompartment.h" #include "js/RootingAPI.h" -#include "vm/Debugger.h" #include "vm/StopIterationObject.h" #include "vm/WrapperObject.h" From d26ef3fb13906b906656f2e1daf4cc4004e7a410 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:27 +0100 Subject: [PATCH 018/119] Backed out changeset 8d1e96d1eb31 (bug 650161) --- js/src/gc/Barrier.h | 2 - js/src/gc/GCRuntime.h | 14 ------ js/src/gc/Marking.cpp | 1 - js/src/gc/Marking.h | 2 - js/src/gc/Tracer.cpp | 12 +++-- js/src/gc/Tracer.h | 2 +- js/src/jscompartment.cpp | 17 ++----- js/src/jscompartment.h | 4 +- js/src/jsgc.cpp | 82 +++++---------------------------- js/src/jsgc.h | 20 ++------ js/src/jshashutil.h | 2 +- js/src/jsweakmap.cpp | 7 --- js/src/jsweakmap.h | 3 -- js/src/shell/jsheaptools.cpp | 2 - js/src/vm/ArrayBufferObject.cpp | 11 +---- js/src/vm/ArrayBufferObject.h | 2 - js/src/vm/Debugger.cpp | 14 ++++++ js/src/vm/SavedStacks.cpp | 5 +- js/src/vm/ScopeObject.cpp | 13 +----- js/src/vm/ScopeObject.h | 2 - js/src/vm/Shape.cpp | 2 +- js/src/vm/TypedArrayObject.h | 3 -- 22 files changed, 48 insertions(+), 174 deletions(-) diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 21bce82f0517..34468f74b295 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -169,7 +169,6 @@ class BaseShape; class DebugScopeObject; class GlobalObject; class LazyScript; -class NestedScopeObject; class Nursery; class ObjectImpl; class PropertyName; @@ -218,7 +217,6 @@ template <> struct MapTypeToTraceKind { static const JSGCTrace template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SCRIPT; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_LAZY_SCRIPT; }; -template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 91daac090be9..f75889b621f4 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -396,11 +396,6 @@ class GCRuntime void disableGenerationalGC(); void enableGenerationalGC(); -#ifdef JSGC_COMPACTING - void disableCompactingGC(); - void enableCompactingGC(); -#endif - void setGrayRootsTracer(JSTraceDataOp traceOp, void *data); bool addBlackRootsTracer(JSTraceDataOp traceOp, void *data); void removeBlackRootsTracer(JSTraceDataOp traceOp, void *data); @@ -718,15 +713,6 @@ class GCRuntime */ unsigned generationalDisabled; -#ifdef JSGC_COMPACTING - /* - * Some code cannot tolerate compacting GC so it can be disabled with this - * counter. This can happen from code executing in a ThreadSafeContext so - * we make it atomic. - */ - mozilla::Atomic compactingDisabled; -#endif - /* * This is true if we are in the middle of a brain transplant (e.g., * JS_TransplantObject) or some other operation that can manipulate diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 583361534b4d..4e4f2e8a0d47 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -629,7 +629,6 @@ DeclMarkerImpl(Object, DebugScopeObject) DeclMarkerImpl(Object, GlobalObject) DeclMarkerImpl(Object, JSObject) DeclMarkerImpl(Object, JSFunction) -DeclMarkerImpl(Object, NestedScopeObject) DeclMarkerImpl(Object, ObjectImpl) DeclMarkerImpl(Object, SavedFrame) DeclMarkerImpl(Object, ScopeObject) diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index ade9c5df0ee3..440b33261a02 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -23,7 +23,6 @@ class DebugScopeObject; class GCMarker; class GlobalObject; class LazyScript; -class NestedScopeObject; class SavedFrame; class ScopeObject; class Shape; @@ -113,7 +112,6 @@ DeclMarker(Object, DebugScopeObject) DeclMarker(Object, GlobalObject) DeclMarker(Object, JSObject) DeclMarker(Object, JSFunction) -DeclMarker(Object, NestedScopeObject) DeclMarker(Object, SavedFrame) DeclMarker(Object, ScopeObject) DeclMarker(Script, JSScript) diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 7648cd2e59e1..5e5831c6f72e 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -637,26 +637,28 @@ GCMarker::markBufferedGrayRoots(JS::Zone *zone) #ifdef DEBUG setTracingDetails(elem->debugPrinter, elem->debugPrintArg, elem->debugPrintIndex); #endif - MarkKind(this, elem->thingp, elem->kind); + void *tmp = elem->thing; + setTracingLocation((void *)&elem->thing); + MarkKind(this, &tmp, elem->kind); + JS_ASSERT(tmp == elem->thing); } } void -GCMarker::appendGrayRoot(void **thingp, JSGCTraceKind kind) +GCMarker::appendGrayRoot(void *thing, JSGCTraceKind kind) { JS_ASSERT(started); if (grayBufferState == GRAY_BUFFER_FAILED) return; - GrayRoot root(thingp, kind); + GrayRoot root(thing, kind); #ifdef DEBUG root.debugPrinter = debugPrinter(); root.debugPrintArg = debugPrintArg(); root.debugPrintIndex = debugPrintIndex(); #endif - void *thing = *thingp; Zone *zone = static_cast(thing)->tenuredZone(); if (zone->isCollecting()) { // See the comment on SetMaybeAliveFlag to see why we only do this for @@ -686,7 +688,7 @@ GCMarker::GrayCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind) JS_ASSERT(thingp); JS_ASSERT(*thingp); GCMarker *gcmarker = static_cast(trc); - gcmarker->appendGrayRoot(thingp, kind); + gcmarker->appendGrayRoot(*thingp, kind); } size_t diff --git a/js/src/gc/Tracer.h b/js/src/gc/Tracer.h index 902e556d6027..19161c4232ca 100644 --- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -275,7 +275,7 @@ class GCMarker : public JSTracer inline void processMarkStackTop(SliceBudget &budget); void processMarkStackOther(uintptr_t tag, uintptr_t addr); - void appendGrayRoot(void **thingp, JSGCTraceKind kind); + void appendGrayRoot(void *thing, JSGCTraceKind kind); /* The color is only applied to objects and functions. */ uint32_t color; diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 82a1aaf257ee..d69ef9043a28 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -627,17 +627,6 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes) ni->unlink(); ni = next; } - - /* For each debuggee being GC'd, detach it from all its debuggers. */ - for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) { - GlobalObject *global = e.front(); - if (IsObjectAboutToBeFinalized(&global)) { - // See infallibility note above. - Debugger::detachAllDebuggersFromGlobal(fop, global, &e); - } else if (global != e.front()) { - e.rekeyFront(global); - } - } } /* @@ -892,7 +881,7 @@ JSCompartment::updateJITForDebugMode(JSContext *maybecx, AutoDebugModeInvalidati } bool -JSCompartment::addDebuggee(JSContext *cx, JS::Handle global) +JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global) { AutoDebugModeInvalidation invalidate(this); return addDebuggee(cx, global, invalidate); @@ -900,9 +889,11 @@ JSCompartment::addDebuggee(JSContext *cx, JS::Handle global) bool JSCompartment::addDebuggee(JSContext *cx, - JS::Handle global, + GlobalObject *globalArg, AutoDebugModeInvalidation &invalidate) { + Rooted global(cx, globalArg); + bool wasEnabled = debugMode(); if (!debuggees.put(global)) { js_ReportOutOfMemory(cx); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 0c1a9675029f..bb03696fbcea 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -423,8 +423,8 @@ struct JSCompartment public: js::GlobalObjectSet &getDebuggees() { return debuggees; } - bool addDebuggee(JSContext *cx, JS::Handle global); - bool addDebuggee(JSContext *cx, JS::Handle global, + bool addDebuggee(JSContext *cx, js::GlobalObject *global); + bool addDebuggee(JSContext *cx, js::GlobalObject *global, js::AutoDebugModeInvalidation &invalidate); bool removeDebuggee(JSContext *cx, js::GlobalObject *global, js::GlobalObjectSet::Enum *debuggeesEnum = nullptr); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 6fba654c6a81..0ccc64b68342 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1158,9 +1158,6 @@ GCRuntime::GCRuntime(JSRuntime *rt) : sliceBudget(SliceBudget::Unlimited), incrementalAllowed(true), generationalDisabled(0), -#ifdef JSGC_COMPACTING - compactingDisabled(0), -#endif manipulatingDeadZones(false), objectsMarkedInDeadZones(0), poked(false), @@ -2007,7 +2004,7 @@ bool GCRuntime::shouldCompact() { #ifdef JSGC_COMPACTING - return invocationKind == GC_SHRINK && !compactingDisabled; + return invocationKind == GC_SHRINK; #else return false; #endif @@ -2015,30 +2012,6 @@ GCRuntime::shouldCompact() #ifdef JSGC_COMPACTING -void -GCRuntime::disableCompactingGC() -{ - ++rt->gc.compactingDisabled; -} - -void -GCRuntime::enableCompactingGC() -{ - JS_ASSERT(compactingDisabled > 0); - --compactingDisabled; -} - -AutoDisableCompactingGC::AutoDisableCompactingGC(JSRuntime *rt) - : gc(rt->gc) -{ - gc.disableCompactingGC(); -} - -AutoDisableCompactingGC::~AutoDisableCompactingGC() -{ - gc.enableCompactingGC(); -} - static void ForwardCell(Cell *dest, Cell *src) { @@ -2075,11 +2048,9 @@ CanRelocateArena(ArenaHeader *arena) /* * We can't currently move global objects because their address is baked * into compiled code. We therefore skip moving the contents of any arena - * containing a global if ion or baseline are enabled. + * containing a global. */ - JSRuntime *rt = arena->zone->runtimeFromMainThread(); - return arena->getAllocKind() <= FINALIZE_OBJECT_LAST && - ((!rt->options().baseline() && !rt->options().ion()) || !ArenaContainsGlobal(arena)); + return arena->getAllocKind() <= FINALIZE_OBJECT_LAST && !ArenaContainsGlobal(arena); } static bool @@ -2132,14 +2103,6 @@ ArenaList::pickArenasToRelocate() return head; } -#ifdef DEBUG -inline bool -PtrIsInRange(void *ptr, void *start, size_t length) -{ - return uintptr_t(ptr) - uintptr_t(start) < length; -} -#endif - static bool RelocateCell(Zone *zone, Cell *src, AllocKind thingKind, size_t thingSize) { @@ -2153,38 +2116,22 @@ RelocateCell(Zone *zone, Cell *src, AllocKind thingKind, size_t thingSize) // Copy source cell contents to destination. memcpy(dst, src, thingSize); + // Mark source cell as forwarded and leave a pointer to the destination. + ForwardCell(static_cast(dst), src); + // Fixup the pointer to inline object elements if necessary. if (thingKind <= FINALIZE_OBJECT_LAST) { JSObject *srcObj = static_cast(src); JSObject *dstObj = static_cast(dst); if (srcObj->hasFixedElements()) dstObj->setFixedElements(); - - if (srcObj->is()) { - // We must fix up any inline data pointers while we know the source - // object and before we mark any of the views. - ArrayBufferObject::fixupDataPointerAfterMovingGC( - srcObj->as(), dstObj->as()); - } else if (srcObj->is()) { - TypedArrayObject &typedArray = srcObj->as(); - if (!typedArray.hasBuffer()) { - JS_ASSERT(srcObj->getPrivate() == - srcObj->fixedData(TypedArrayObject::FIXED_DATA_START)); - dstObj->setPrivate(dstObj->fixedData(TypedArrayObject::FIXED_DATA_START)); - } - } - - - JS_ASSERT_IF(dstObj->isNative(), - !PtrIsInRange((HeapSlot*)dstObj->getDenseElements(), src, thingSize)); + JS_ASSERT( + uintptr_t((HeapSlot*)dstObj->getElementsHeader()) - uintptr_t(srcObj) >= thingSize); } // Copy the mark bits. static_cast(dst)->copyMarkBitsFrom(src); - // Mark source cell as forwarded and leave a pointer to the destination. - ForwardCell(static_cast(dst), src); - return true; } @@ -2304,12 +2251,10 @@ void MovingTracer::Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) { Cell *thing = static_cast(*thingp); - Zone *zone = thing->tenuredZoneFromAnyThread(); - if (!zone->isGCCompacting()) { + if (!thing->tenuredZone()->isGCCompacting()) { JS_ASSERT(!IsForwarded(thing)); return; } - JS_ASSERT(CurrentThreadCanAccessZone(zone)); if (IsForwarded(thing)) { Cell *dst = Forwarded(thing); @@ -2335,6 +2280,7 @@ MovingTracer::Sweep(JSTracer *jstrc) for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) { c->sweep(fop, false); + ArrayBufferObject::sweep(c); } } else { /* Update cross compartment wrappers into moved zones. */ @@ -2345,9 +2291,6 @@ MovingTracer::Sweep(JSTracer *jstrc) /* Type inference may put more blocks here to free. */ rt->freeLifoAlloc.freeAll(); - - /* Clear the new object cache as this can contain cell pointers. */ - rt->newObjectCache.purge(); } /* @@ -2416,15 +2359,12 @@ GCRuntime::updatePointersToRelocatedCells() Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - WeakMapBase::markAll(c, &trc); if (c->watchpointMap) c->watchpointMap->markAll(&trc); } - // Mark all gray roots, making sure we call the trace callback to get the - // current set. - marker.resetBufferedGrayRoots(); markAllGrayReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); + markAllWeakReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); MovingTracer::Sweep(&trc); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 115fc9583b8e..4098135495de 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1138,7 +1138,7 @@ struct GCChunkHasher { typedef HashSet GCChunkSet; struct GrayRoot { - void **thingp; + void *thing; JSGCTraceKind kind; #ifdef DEBUG JSTraceNamePrinter debugPrinter; @@ -1146,8 +1146,8 @@ struct GrayRoot { size_t debugPrintIndex; #endif - GrayRoot(void **thingp, JSGCTraceKind kind) - : thingp(thingp), kind(kind) {} + GrayRoot(void *thing, JSGCTraceKind kind) + : thing(thing), kind(kind) {} }; void @@ -1427,20 +1427,6 @@ struct AutoDisableProxyCheck }; #endif -struct AutoDisableCompactingGC -{ -#ifdef JSGC_COMPACTING - explicit AutoDisableCompactingGC(JSRuntime *rt); - ~AutoDisableCompactingGC(); - - private: - gc::GCRuntime &gc; -#else - explicit AutoDisableCompactingGC(JSRuntime *rt) {} - ~AutoDisableCompactingGC() {} -#endif -}; - void PurgeJITCaches(JS::Zone *zone); diff --git a/js/src/jshashutil.h b/js/src/jshashutil.h index d95cbd41a9ba..aebb15bcfc31 100644 --- a/js/src/jshashutil.h +++ b/js/src/jshashutil.h @@ -13,7 +13,7 @@ namespace js { /* * Used to add entries to a js::HashMap or HashSet where the key depends on a GC - * thing that may be moved by generational or compacting GC between the call to + * thing that may be moved by generational collection between the call to * lookupForAdd() and relookupOrAdd(). */ template diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index c25a0dc2a14e..2783658a0f9a 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -68,13 +68,6 @@ WeakMapBase::unmarkCompartment(JSCompartment *c) m->marked = false; } -void -WeakMapBase::markAll(JSCompartment *c, JSTracer *tracer) -{ - for (WeakMapBase *m = c->gcWeakMapList; m; m = m->next) - m->markIteratively(tracer); -} - bool WeakMapBase::markCompartmentIteratively(JSCompartment *c, JSTracer *tracer) { diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 07fa008fc61f..690278be3a72 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -49,9 +49,6 @@ class WeakMapBase { // Unmark all weak maps in a compartment. static void unmarkCompartment(JSCompartment *c); - // Mark all the weakmaps in a compartment. - static void markAll(JSCompartment *c, JSTracer *tracer); - // Check all weak maps in a compartment that have been marked as live in this garbage // collection, and mark the values of all entries that have become strong references // to them. Return true if we marked any new values, indicating that we need to make diff --git a/js/src/shell/jsheaptools.cpp b/js/src/shell/jsheaptools.cpp index f172b1710e05..93cc36cbdd28 100644 --- a/js/src/shell/jsheaptools.cpp +++ b/js/src/shell/jsheaptools.cpp @@ -157,7 +157,6 @@ class HeapReverser : public JSTracer, public JS::CustomAutoRooter : JSTracer(cx->runtime(), traverseEdgeWithThis), JS::CustomAutoRooter(cx), noggc(JS_GetRuntime(cx)), - nocgc(JS_GetRuntime(cx)), runtime(JS_GetRuntime(cx)), parent(nullptr) { @@ -170,7 +169,6 @@ class HeapReverser : public JSTracer, public JS::CustomAutoRooter private: JS::AutoDisableGenerationalGC noggc; - js::AutoDisableCompactingGC nocgc; /* A runtime pointer for use by the destructor. */ JSRuntime *runtime; diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 2aaf5b34f246..0c7d2cf34f54 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -932,15 +932,6 @@ ArrayBufferObject::sweep(JSCompartment *compartment) gcLiveArrayBuffers.clear(); } -/* static */ void -ArrayBufferObject::fixupDataPointerAfterMovingGC(const ArrayBufferObject &src, ArrayBufferObject &dst) -{ - // Fix up possible inline data pointer. - const size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&ArrayBufferObject::class_); - if (src.dataPointer() == src.fixedData(reservedSlots)) - dst.setSlot(DATA_SLOT, PrivateValue(dst.fixedData(reservedSlots))); -} - void ArrayBufferObject::resetArrayBufferList(JSCompartment *comp) { @@ -1001,7 +992,7 @@ ArrayBufferViewObject::trace(JSTracer *trc, JSObject *obj) // Update obj's data pointer if the array buffer moved. Note that during // initialization, bufSlot may still contain |undefined|. if (bufSlot.isObject()) { - ArrayBufferObject &buf = AsArrayBuffer(MaybeForwarded(&bufSlot.toObject())); + ArrayBufferObject &buf = AsArrayBuffer(&bufSlot.toObject()); int32_t offset = obj->getReservedSlot(BYTEOFFSET_SLOT).toInt32(); MOZ_ASSERT(buf.dataPointer() != nullptr); obj->initPrivate(buf.dataPointer() + offset); diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h index 8bf20bc76584..22b84081320b 100644 --- a/js/src/vm/ArrayBufferObject.h +++ b/js/src/vm/ArrayBufferObject.h @@ -95,8 +95,6 @@ class ArrayBufferObject : public JSObject static void sweep(JSCompartment *rt); - static void fixupDataPointerAfterMovingGC(const ArrayBufferObject &src, ArrayBufferObject &dst); - static void resetArrayBufferList(JSCompartment *rt); static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector); static void restoreArrayBufferLists(ArrayBufferVector &vector); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 5e016a39a8c0..d6aee1c85812 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1750,6 +1750,20 @@ Debugger::sweepAll(FreeOp *fop) } } } + + for (gc::GCCompartmentGroupIter comp(rt); !comp.done(); comp.next()) { + /* For each debuggee being GC'd, detach it from all its debuggers. */ + GlobalObjectSet &debuggees = comp->getDebuggees(); + for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) { + GlobalObject *global = e.front(); + if (IsObjectAboutToBeFinalized(&global)) { + // See infallibility note above. + detachAllDebuggersFromGlobal(fop, global, &e); + } else if (global != e.front()) { + e.rekeyFront(global); + } + } + } } void diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index 3ecaff67ba65..815b7e5d5d16 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -10,7 +10,6 @@ #include "jsapi.h" #include "jscompartment.h" #include "jsfriendapi.h" -#include "jshashutil.h" #include "jsnum.h" #include "gc/Marking.h" @@ -563,7 +562,7 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram SavedFrame * SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup lookup) { - DependentAddPtr p(cx, frames, lookup); + SavedFrame::Set::AddPtr p = frames.lookupForAdd(lookup); if (p) return *p; @@ -571,7 +570,7 @@ SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup looku if (!frame) return nullptr; - if (!p.add(cx, frames, lookup, frame)) + if (!frames.relookupOrAdd(p, lookup, frame)) return nullptr; return frame; diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 5fe614acb05f..6032961017f8 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1070,15 +1070,6 @@ ScopeIterKey::match(ScopeIterKey si1, ScopeIterKey si2) si1.type_ == si2.type_)); } -void -ScopeIterVal::sweep() -{ - /* We need to update possibly moved pointers on sweep. */ - MOZ_ALWAYS_FALSE(IsObjectAboutToBeFinalized(cur_.unsafeGet())); - if (staticScope_) - MOZ_ALWAYS_FALSE(IsObjectAboutToBeFinalized(staticScope_.unsafeGet())); -} - // Live ScopeIter values may be added to DebugScopes::liveScopes, as // ScopeIterVal instances. They need to have write barriers when they are added // to the hash table, but no barriers when rehashing inside GC. It's a nasty @@ -1801,7 +1792,7 @@ DebugScopes::sweep(JSRuntime *rt) key.updateCur(js::gc::Forwarded(key.cur())); needsUpdate = true; } - if (key.staticScope() && IsForwarded(key.staticScope())) { + if (IsForwarded(key.staticScope())) { key.updateStaticScope(Forwarded(key.staticScope())); needsUpdate = true; } @@ -1813,8 +1804,6 @@ DebugScopes::sweep(JSRuntime *rt) for (LiveScopeMap::Enum e(liveScopes); !e.empty(); e.popFront()) { ScopeObject *scope = e.front().key(); - e.front().value().sweep(); - /* * Scopes can be finalized when a debugger-synthesized ScopeObject is * no longer reachable via its DebugScopeObject. diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 30e86d50ef0f..22c9464e86a6 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -733,8 +733,6 @@ class ScopeIterVal ScopeIter::Type type_; bool hasScopeObject_; - void sweep(); - static void staticAsserts(); public: diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 267a6ffc41e9..e5616a738100 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -445,7 +445,7 @@ js::ObjectImpl::toDictionaryMode(ThreadSafeContext *cx) #ifdef JSGC_COMPACTING // TODO: This crashes if we run a compacting GC here. - js::AutoDisableCompactingGC nogc(zone()->runtimeFromAnyThread()); + js::gc::AutoSuppressGC nogc(zone()->runtimeFromAnyThread()); #endif /* We allocate the shapes from cx->compartment(), so make sure it's right. */ diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index 0fdbbba4a6d8..75916593f1f9 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -80,9 +80,6 @@ class TypedArrayObject : public ArrayBufferViewObject ensureHasBuffer(JSContext *cx, Handle tarray); ArrayBufferObject *sharedBuffer() const; - bool hasBuffer() const { - return bufferValue(const_cast(this)).isObject(); - } ArrayBufferObject *buffer() const { JSObject *obj = bufferValue(const_cast(this)).toObjectOrNull(); if (!obj) From 6a3ca7c2a2317a7cd16097b4147451bba245f196 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:30 +0100 Subject: [PATCH 019/119] Backed out changeset bdcd60020523 (bug 650161) --- js/src/gc/GCRuntime.h | 7 +- js/src/gc/Statistics.cpp | 4 - js/src/gc/Statistics.h | 19 ++--- js/src/gc/Tracer.cpp | 5 +- js/src/gc/Zone.cpp | 15 ++-- js/src/jscompartment.cpp | 90 ++++++++++---------- js/src/jsgc.cpp | 176 +++++++++++++++++++-------------------- js/src/jsinfer.cpp | 9 +- js/src/vm/Shape.cpp | 10 +-- 9 files changed, 162 insertions(+), 173 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index f75889b621f4..6eb990d45e61 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -499,10 +499,10 @@ class GCRuntime bool drainMarkStack(SliceBudget &sliceBudget, gcstats::Phase phase); template void markWeakReferences(gcstats::Phase phase); void markWeakReferencesInCurrentGroup(gcstats::Phase phase); - template void markGrayReferences(gcstats::Phase phase); - void markGrayReferencesInCurrentGroup(gcstats::Phase phase); + template void markGrayReferences(); + void markGrayReferencesInCurrentGroup(); void markAllWeakReferences(gcstats::Phase phase); - void markAllGrayReferences(gcstats::Phase phase); + void markAllGrayReferences(); void beginSweepPhase(bool lastGC); void findZoneGroups(); @@ -523,7 +523,6 @@ class GCRuntime bool shouldCompact(); #ifdef JSGC_COMPACTING void compactPhase(); - ArenaHeader *relocateArenas(); void updatePointersToRelocatedCells(); void releaseRelocatedArenas(ArenaHeader *relocatedList); #endif diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp index 8bd0896a2db4..c8789f6ca5ca 100644 --- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -307,10 +307,6 @@ static const PhaseInfo phases[] = { { PHASE_SWEEP_SCRIPT, "Sweep Script", PHASE_SWEEP }, { PHASE_SWEEP_SHAPE, "Sweep Shape", PHASE_SWEEP }, { PHASE_SWEEP_JITCODE, "Sweep JIT code", PHASE_SWEEP }, - { PHASE_COMPACT, "Compact", PHASE_NO_PARENT }, - { PHASE_COMPACT_MOVE, "Compact Move", PHASE_COMPACT }, - { PHASE_COMPACT_UPDATE, "Compact Update", PHASE_COMPACT, }, - { PHASE_COMPACT_UPDATE_GRAY, "Compact Update Gray", PHASE_COMPACT_UPDATE, }, { PHASE_FINALIZE_END, "Finalize End Callback", PHASE_SWEEP }, { PHASE_DESTROY, "Deallocate", PHASE_SWEEP }, { PHASE_GC_END, "End Callback", PHASE_NO_PARENT }, diff --git a/js/src/gc/Statistics.h b/js/src/gc/Statistics.h index 258119064d01..f211004b7c72 100644 --- a/js/src/gc/Statistics.h +++ b/js/src/gc/Statistics.h @@ -58,10 +58,6 @@ enum Phase { PHASE_SWEEP_SCRIPT, PHASE_SWEEP_SHAPE, PHASE_SWEEP_JITCODE, - PHASE_COMPACT, - PHASE_COMPACT_MOVE, - PHASE_COMPACT_UPDATE, - PHASE_COMPACT_UPDATE_GRAY, PHASE_FINALIZE_END, PHASE_DESTROY, PHASE_GC_END, @@ -231,16 +227,17 @@ struct AutoPhase struct MaybeAutoPhase { - explicit MaybeAutoPhase(Statistics &statsArg, bool condition, Phase phaseArg - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + explicit MaybeAutoPhase(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) : stats(nullptr) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; - if (condition) { - stats = &statsArg; - phase = phaseArg; - stats->beginPhase(phase); - } + } + void construct(Statistics &statsArg, Phase phaseArg) + { + JS_ASSERT(!stats); + stats = &statsArg; + phase = phaseArg; + stats->beginPhase(phase); } ~MaybeAutoPhase() { if (stats) diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 5e5831c6f72e..4abfec97eb16 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -554,8 +554,9 @@ GCMarker::markDelayedChildren(ArenaHeader *aheader) bool GCMarker::markDelayedChildren(SliceBudget &budget) { - GCRuntime &gc = runtime()->gc; - gcstats::MaybeAutoPhase ap(gc.stats, gc.state() == MARK, gcstats::PHASE_MARK_DELAYED); + gcstats::MaybeAutoPhase ap; + if (runtime()->gc.state() == MARK) + ap.construct(runtime()->gc.stats, gcstats::PHASE_MARK_DELAYED); JS_ASSERT(unmarkedArenaStackTop); do { diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 3e949df80caa..77a270aac5e7 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -113,21 +113,13 @@ Zone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) if (active) releaseTypes = false; - GCRuntime &gc = fop->runtime()->gc; - { - gcstats::MaybeAutoPhase ap(gc.stats, !gc.isHeapCompacting(), - gcstats::PHASE_DISCARD_ANALYSIS); + gcstats::AutoPhase ap(fop->runtime()->gc.stats, gcstats::PHASE_DISCARD_ANALYSIS); types.sweep(fop, releaseTypes, oom); } - if (!fop->runtime()->debuggerList.isEmpty()) { - gcstats::MaybeAutoPhase ap1(gc.stats, !gc.isHeapCompacting(), - gcstats::PHASE_SWEEP_TABLES); - gcstats::MaybeAutoPhase ap2(gc.stats, !gc.isHeapCompacting(), - gcstats::PHASE_SWEEP_TABLES_BREAKPOINT); + if (!fop->runtime()->debuggerList.isEmpty()) sweepBreakpoints(fop); - } } void @@ -138,6 +130,9 @@ Zone::sweepBreakpoints(FreeOp *fop) * to iterate over the scripts belonging to a single compartment in a zone. */ + gcstats::AutoPhase ap1(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES); + gcstats::AutoPhase ap2(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES_BREAKPOINT); + JS_ASSERT(isGCSweepingOrCompacting()); for (ZoneCellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index d69ef9043a28..b95a4619611d 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -572,53 +572,54 @@ void JSCompartment::sweep(FreeOp *fop, bool releaseTypes) { JS_ASSERT(!activeAnalysis); + + /* This function includes itself in PHASE_SWEEP_TABLES. */ + sweepCrossCompartmentWrappers(); + JSRuntime *rt = runtimeFromMainThread(); { - gcstats::MaybeAutoPhase ap(rt->gc.stats, !rt->isHeapCompacting(), - gcstats::PHASE_SWEEP_TABLES_WRAPPER); - sweepCrossCompartmentWrappers(); + gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_TABLES); + + /* Remove dead references held weakly by the compartment. */ + + sweepBaseShapeTable(); + sweepInitialShapeTable(); + { + gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, + gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); + sweepNewTypeObjectTable(newTypeObjects); + sweepNewTypeObjectTable(lazyTypeObjects); + } + sweepCallsiteClones(); + savedStacks_.sweep(rt); + + if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet())) + global_.set(nullptr); + + if (selfHostingScriptSource && + IsObjectAboutToBeFinalized((JSObject **) selfHostingScriptSource.unsafeGet())) + { + selfHostingScriptSource.set(nullptr); + } + + if (jitCompartment_) + jitCompartment_->sweep(fop, this); + + /* + * JIT code increments activeUseCount for any RegExpShared used by jit + * code for the lifetime of the JIT script. Thus, we must perform + * sweeping after clearing jit code. + */ + regExps.sweep(rt); + + if (debugScopes) + debugScopes->sweep(rt); + + /* Finalize unreachable (key,value) pairs in all weak maps. */ + WeakMapBase::sweepCompartment(this); } - /* Remove dead references held weakly by the compartment. */ - - sweepBaseShapeTable(); - sweepInitialShapeTable(); - { - gcstats::MaybeAutoPhase ap(rt->gc.stats, !rt->isHeapCompacting(), - gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); - sweepNewTypeObjectTable(newTypeObjects); - sweepNewTypeObjectTable(lazyTypeObjects); - } - sweepCallsiteClones(); - savedStacks_.sweep(rt); - - if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet())) - global_.set(nullptr); - - if (selfHostingScriptSource && - IsObjectAboutToBeFinalized((JSObject **) selfHostingScriptSource.unsafeGet())) - { - selfHostingScriptSource.set(nullptr); - } - - if (jitCompartment_) - jitCompartment_->sweep(fop, this); - - /* - * JIT code increments activeUseCount for any RegExpShared used by jit - * code for the lifetime of the JIT script. Thus, we must perform - * sweeping after clearing jit code. - */ - regExps.sweep(rt); - - if (debugScopes) - debugScopes->sweep(rt); - - /* Finalize unreachable (key,value) pairs in all weak maps. */ - WeakMapBase::sweepCompartment(this); - - /* Sweep list of native iterators. */ NativeIterator *ni = enumerators->next(); while (ni != enumerators) { JSObject *iterObj = ni->iterObj(); @@ -637,6 +638,11 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes) void JSCompartment::sweepCrossCompartmentWrappers() { + JSRuntime *rt = runtimeFromMainThread(); + + gcstats::AutoPhase ap1(rt->gc.stats, gcstats::PHASE_SWEEP_TABLES); + gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_SWEEP_TABLES_WRAPPER); + /* Remove dead wrappers from the table. */ for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { CrossCompartmentKey key = e.front().key(); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 0ccc64b68342..cca8bae4b403 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2220,26 +2220,6 @@ ArenaLists::relocateArenas(ArenaHeader *relocatedList) return relocatedList; } -ArenaHeader * -GCRuntime::relocateArenas() -{ - gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT_MOVE); - - ArenaHeader *relocatedList = nullptr; - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - JS_ASSERT(zone->isGCFinished()); - JS_ASSERT(!zone->isPreservingCode()); - - // We cannot move atoms as we depend on their addresses being constant. - if (!rt->isAtomsZone(zone)) { - zone->setGCState(Zone::Compact); - relocatedList = zone->allocator.arenas.relocateArenas(relocatedList); - } - } - - return relocatedList; -} - struct MovingTracer : JSTracer { MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapValues) {} @@ -2274,6 +2254,8 @@ MovingTracer::Sweep(JSTracer *jstrc) for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { if (zone->isCollecting()) { + gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_COMPARTMENTS); + bool oom = false; zone->sweep(fop, false, &oom); JS_ASSERT(!oom); @@ -2319,54 +2301,60 @@ void GCRuntime::updatePointersToRelocatedCells() { JS_ASSERT(rt->currentThreadHasExclusiveAccess()); - - gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT_UPDATE); MovingTracer trc(rt); - // TODO: We may need to fix up other weak pointers here. + { + // TODO: Maybe give compaction its own set of phases. + gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK); - // Fixup compartment global pointers as these get accessed during marking. - for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) - comp->fixupAfterMovingGC(); + // TODO: We may need to fix up other weak pointers here. - // Fixup cross compartment wrappers as we assert the existence of wrappers in the map. - for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) - comp->fixupCrossCompartmentWrappers(&trc); + // Fixup compartment global pointers as these get accessed during marking. + for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) + comp->fixupAfterMovingGC(); - // Fixup generators as these are not normally traced. - for (ContextIter i(rt); !i.done(); i.next()) { - for (JSGenerator *gen = i.get()->innermostGenerator(); gen; gen = gen->prevGenerator) - gen->obj = MaybeForwarded(gen->obj.get()); - } + // Fixup cross compartment wrappers as we assert the existence of wrappers in the map. + for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) + comp->fixupCrossCompartmentWrappers(&trc); - // Iterate through all allocated cells to update internal pointers. - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - ArenaLists &al = zone->allocator.arenas; - for (unsigned i = 0; i < FINALIZE_LIMIT; ++i) { - AllocKind thingKind = static_cast(i); - JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind); - for (ArenaHeader *arena = al.getFirstArena(thingKind); arena; arena = arena->next) { - for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { - UpdateCellPointers(&trc, i.getCell(), traceKind); + // Fixup generators as these are not normally traced. + for (ContextIter i(rt); !i.done(); i.next()) { + for (JSGenerator *gen = i.get()->innermostGenerator(); gen; gen = gen->prevGenerator) + gen->obj = MaybeForwarded(gen->obj.get()); + } + + // Iterate through all allocated cells to update internal pointers. + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + ArenaLists &al = zone->allocator.arenas; + for (unsigned i = 0; i < FINALIZE_LIMIT; ++i) { + AllocKind thingKind = static_cast(i); + JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind); + for (ArenaHeader *arena = al.getFirstArena(thingKind); arena; arena = arena->next) { + for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { + UpdateCellPointers(&trc, i.getCell(), traceKind); + } } } } + + // Mark roots to update them. + markRuntime(&trc, MarkRuntime); + Debugger::markAll(&trc); + Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); + + for (GCCompartmentsIter c(rt); !c.done(); c.next()) { + if (c->watchpointMap) + c->watchpointMap->markAll(&trc); + } } - // Mark roots to update them. - markRuntime(&trc, MarkRuntime); - Debugger::markAll(&trc); - Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); + { + gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP); - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - if (c->watchpointMap) - c->watchpointMap->markAll(&trc); + markAllGrayReferences(); + + MovingTracer::Sweep(&trc); } - - markAllGrayReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); - markAllWeakReferences(gcstats::PHASE_COMPACT_UPDATE_GRAY); - - MovingTracer::Sweep(&trc); } void @@ -3754,6 +3742,7 @@ GCRuntime::markWeakReferences(gcstats::Phase phase) { JS_ASSERT(marker.isDrained()); + gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_MARK); gcstats::AutoPhase ap1(stats, phase); for (;;) { @@ -3781,25 +3770,35 @@ GCRuntime::markWeakReferencesInCurrentGroup(gcstats::Phase phase) template void -GCRuntime::markGrayReferences(gcstats::Phase phase) +GCRuntime::markGrayReferences() { - gcstats::AutoPhase ap(stats, phase); - if (marker.hasBufferedGrayRoots()) { - for (ZoneIterT zone(rt); !zone.done(); zone.next()) - marker.markBufferedGrayRoots(zone); - } else { - JS_ASSERT(!isIncremental); - if (JSTraceDataOp op = grayRootTracer.op) - (*op)(&marker, grayRootTracer.data); + { + gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_MARK); + gcstats::AutoPhase ap1(stats, gcstats::PHASE_SWEEP_MARK_GRAY); + marker.setMarkColorGray(); + if (marker.hasBufferedGrayRoots()) { + for (ZoneIterT zone(rt); !zone.done(); zone.next()) + marker.markBufferedGrayRoots(zone); + } else { + JS_ASSERT(!isIncremental); + if (JSTraceDataOp op = grayRootTracer.op) + (*op)(&marker, grayRootTracer.data); + } + SliceBudget budget; + marker.drainMarkStack(budget); } - SliceBudget budget; - marker.drainMarkStack(budget); + + markWeakReferences(gcstats::PHASE_SWEEP_MARK_GRAY_WEAK); + + JS_ASSERT(marker.isDrained()); + + marker.setMarkColorBlack(); } void -GCRuntime::markGrayReferencesInCurrentGroup(gcstats::Phase phase) +GCRuntime::markGrayReferencesInCurrentGroup() { - markGrayReferences(phase); + markGrayReferences(); } void @@ -3809,9 +3808,9 @@ GCRuntime::markAllWeakReferences(gcstats::Phase phase) } void -GCRuntime::markAllGrayReferences(gcstats::Phase phase) +GCRuntime::markAllGrayReferences() { - markGrayReferences(phase); + markGrayReferences(); } #ifdef DEBUG @@ -3932,8 +3931,7 @@ js::gc::MarkingValidator::nonIncrementalMark() gc->incrementalState = SWEEP; { - gcstats::AutoPhase ap1(gc->stats, gcstats::PHASE_SWEEP); - gcstats::AutoPhase ap2(gc->stats, gcstats::PHASE_SWEEP_MARK); + gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_SWEEP); gc->markAllWeakReferences(gcstats::PHASE_SWEEP_MARK_WEAK); /* Update zone state for gray marking. */ @@ -3941,18 +3939,14 @@ js::gc::MarkingValidator::nonIncrementalMark() JS_ASSERT(zone->isGCMarkingBlack()); zone->setGCState(Zone::MarkGray); } - gc->marker.setMarkColorGray(); - gc->markAllGrayReferences(gcstats::PHASE_SWEEP_MARK_GRAY); - gc->markAllWeakReferences(gcstats::PHASE_SWEEP_MARK_GRAY_WEAK); + gc->markAllGrayReferences(); /* Restore zone state. */ for (GCZonesIter zone(runtime); !zone.done(); zone.next()) { JS_ASSERT(zone->isGCMarkingGray()); zone->setGCState(Zone::Mark); } - JS_ASSERT(gc->marker.isDrained()); - gc->marker.setMarkColorBlack(); } /* Take a copy of the non-incremental mark state and restore the original. */ @@ -4353,6 +4347,7 @@ MarkIncomingCrossCompartmentPointers(JSRuntime *rt, const uint32_t color) { JS_ASSERT(color == BLACK || color == GRAY); + gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_MARK); static const gcstats::Phase statsPhases[] = { gcstats::PHASE_SWEEP_MARK_INCOMING_BLACK, gcstats::PHASE_SWEEP_MARK_INCOMING_GRAY @@ -4477,8 +4472,6 @@ js::NotifyGCPostSwap(JSObject *a, JSObject *b, unsigned removedFlags) void GCRuntime::endMarkingZoneGroup() { - gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_MARK); - /* * Mark any incoming black pointers from previously swept compartments * whose referents are not marked. This can occur when gray cells become @@ -4498,22 +4491,22 @@ GCRuntime::endMarkingZoneGroup() JS_ASSERT(zone->isGCMarkingBlack()); zone->setGCState(Zone::MarkGray); } - marker.setMarkColorGray(); /* Mark incoming gray pointers from previously swept compartments. */ + marker.setMarkColorGray(); MarkIncomingCrossCompartmentPointers(rt, GRAY); + marker.setMarkColorBlack(); /* Mark gray roots and mark transitively inside the current compartment group. */ - markGrayReferencesInCurrentGroup(gcstats::PHASE_SWEEP_MARK_GRAY); - markWeakReferencesInCurrentGroup(gcstats::PHASE_SWEEP_MARK_GRAY_WEAK); + markGrayReferencesInCurrentGroup(); /* Restore marking state. */ for (GCZoneGroupIter zone(rt); !zone.done(); zone.next()) { JS_ASSERT(zone->isGCMarkingGray()); zone->setGCState(Zone::Mark); } - MOZ_ASSERT(marker.isDrained()); - marker.setMarkColorBlack(); + + JS_ASSERT(marker.isDrained()); } void @@ -4586,8 +4579,6 @@ GCRuntime::beginSweepingZoneGroup() for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) { gcstats::AutoSCC scc(stats, zoneGroupIndex); - gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_TABLES); - c->sweep(&fop, releaseObservedTypes && !c->zone()->isPreservingCode()); } @@ -4949,9 +4940,18 @@ GCRuntime::compactPhase() JS_ASSERT(rt->gc.nursery.isEmpty()); JS_ASSERT(!sweepOnBackgroundThread); - gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT); + ArenaHeader *relocatedList = nullptr; + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + JS_ASSERT(zone->isGCFinished()); + JS_ASSERT(!zone->isPreservingCode()); + + // We cannot move atoms as we depend on their addresses being constant. + if (!rt->isAtomsZone(zone)) { + zone->setGCState(Zone::Compact); + relocatedList = zone->allocator.arenas.relocateArenas(relocatedList); + } + } - ArenaHeader *relocatedList = relocateArenas(); updatePointersToRelocatedCells(); releaseRelocatedArenas(relocatedList); diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index a0a7eb49a22b..275a288705f0 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -4390,8 +4390,7 @@ TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) } { - gcstats::MaybeAutoPhase ap2(rt->gc.stats, !rt->isHeapCompacting(), - gcstats::PHASE_DISCARD_TI); + gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_DISCARD_TI); for (ZoneCellIterUnderGC i(zone(), FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); @@ -4422,8 +4421,7 @@ TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) } { - gcstats::MaybeAutoPhase ap2(rt->gc.stats, !rt->isHeapCompacting(), - gcstats::PHASE_SWEEP_TYPES); + gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_SWEEP_TYPES); for (gc::ZoneCellIterUnderGC iter(zone(), gc::FINALIZE_TYPE_OBJECT); !iter.done(); iter.next()) @@ -4451,8 +4449,7 @@ TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) } { - gcstats::MaybeAutoPhase ap2(rt->gc.stats, !rt->isHeapCompacting(), - gcstats::PHASE_FREE_TI_ARENA); + gcstats::AutoPhase ap2(rt->gc.stats, gcstats::PHASE_FREE_TI_ARENA); rt->freeLifoAlloc.transferFrom(&oldAlloc); } } diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index e5616a738100..173f44d1c501 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1542,9 +1542,8 @@ BaseShape::assertConsistency() void JSCompartment::sweepBaseShapeTable() { - GCRuntime &gc = runtimeFromMainThread()->gc; - gcstats::MaybeAutoPhase ap(gc.stats, !gc.isHeapCompacting(), - gcstats::PHASE_SWEEP_TABLES_BASE_SHAPE); + gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, + gcstats::PHASE_SWEEP_TABLES_BASE_SHAPE); if (baseShapes.initialized()) { for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) { @@ -1840,9 +1839,8 @@ EmptyShape::insertInitialShape(ExclusiveContext *cx, HandleShape shape, HandleOb void JSCompartment::sweepInitialShapeTable() { - GCRuntime &gc = runtimeFromMainThread()->gc; - gcstats::MaybeAutoPhase ap(gc.stats, !gc.isHeapCompacting(), - gcstats::PHASE_SWEEP_TABLES_INITIAL_SHAPE); + gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, + gcstats::PHASE_SWEEP_TABLES_INITIAL_SHAPE); if (initialShapes.initialized()) { for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) { From ffff7b0770d5370008f1770ed9148401ccabf42e Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:34 +0100 Subject: [PATCH 020/119] Backed out changeset edc768336c80 (bug 650161) --- js/public/Utility.h | 1 - js/src/builtin/TestingFunctions.cpp | 1 - js/src/gc/GCRuntime.h | 27 +- js/src/gc/Heap.h | 17 - js/src/gc/RootMarking.cpp | 26 +- js/src/gc/Tracer.cpp | 2 +- js/src/gc/Zone.cpp | 2 + js/src/jsapi-tests/testWeakMap.cpp | 2 +- js/src/jsgc.cpp | 514 ++-------------------------- js/src/jsgc.h | 15 +- 10 files changed, 47 insertions(+), 560 deletions(-) diff --git a/js/public/Utility.h b/js/public/Utility.h index f6714f9d7836..89c495e41116 100644 --- a/js/public/Utility.h +++ b/js/public/Utility.h @@ -43,7 +43,6 @@ namespace js {} #define JS_SWEPT_NURSERY_PATTERN 0x2B #define JS_ALLOCATED_NURSERY_PATTERN 0x2D #define JS_FRESH_TENURED_PATTERN 0x4F -#define JS_MOVED_TENURED_PATTERN 0x49 #define JS_SWEPT_TENURED_PATTERN 0x4B #define JS_ALLOCATED_TENURED_PATTERN 0x4D #define JS_SWEPT_CODE_PATTERN 0x3b diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index acb17c74cac9..74e979ddb700 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2062,7 +2062,6 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { " 11: Verify post write barriers between instructions\n" " 12: Verify post write barriers between paints\n" " 13: Check internal hashtables on minor GC\n" -" 14: Always compact arenas after GC\n" " Period specifies that collection happens every n allocations.\n"), JS_FN_HELP("schedulegc", ScheduleGC, 1, 0, diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 6eb990d45e61..e66033129051 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -293,17 +293,7 @@ class GCRuntime void runDebugGC(); inline void poke(); - enum TraceOrMarkRuntime { - TraceRuntime, - MarkRuntime - }; - enum TraceRootsOrUsedSaved { - TraceRoots, - UseSavedRoots - }; - void markRuntime(JSTracer *trc, - TraceOrMarkRuntime traceOrMark = TraceRuntime, - TraceRootsOrUsedSaved rootsSource = TraceRoots); + void markRuntime(JSTracer *trc, bool useSavedRoots = false); void notifyDidPaint(); void shrinkBuffers(); @@ -501,9 +491,6 @@ class GCRuntime void markWeakReferencesInCurrentGroup(gcstats::Phase phase); template void markGrayReferences(); void markGrayReferencesInCurrentGroup(); - void markAllWeakReferences(gcstats::Phase phase); - void markAllGrayReferences(); - void beginSweepPhase(bool lastGC); void findZoneGroups(); bool findZoneEdgesForWeakMaps(); @@ -520,13 +507,6 @@ class GCRuntime void expireChunksAndArenas(bool shouldShrink); void sweepBackgroundThings(bool onBackgroundThread); void assertBackgroundSweepingFinished(); - bool shouldCompact(); -#ifdef JSGC_COMPACTING - void compactPhase(); - void updatePointersToRelocatedCells(); - void releaseRelocatedArenas(ArenaHeader *relocatedList); -#endif - void finishCollection(); void computeNonIncrementalMarkingForValidation(); void validateIncrementalMarking(); @@ -536,6 +516,8 @@ class GCRuntime #ifdef DEBUG void checkForCompartmentMismatches(); + void markAllWeakReferences(gcstats::Phase phase); + void markAllGrayReferences(); #endif public: @@ -857,8 +839,7 @@ GCRuntime::needZealousGC() { if (zealMode == ZealAllocValue || zealMode == ZealGenerationalGCValue || (zealMode >= ZealIncrementalRootsThenFinish && - zealMode <= ZealIncrementalMultipleSlices) || - zealMode == ZealCompactValue) + zealMode <= ZealIncrementalMultipleSlices)) { nextScheduled = zealFrequency; } diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index 0758d12b7d91..d3444b1f9bd4 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -102,7 +102,6 @@ struct Cell MOZ_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const; MOZ_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const; MOZ_ALWAYS_INLINE void unmark(uint32_t color) const; - MOZ_ALWAYS_INLINE void copyMarkBitsFrom(const Cell *src); inline JSRuntime *runtimeFromMainThread() const; inline JS::shadow::Runtime *shadowRuntimeFromMainThread() const; @@ -762,12 +761,6 @@ struct ChunkBitmap *word &= ~mask; } - MOZ_ALWAYS_INLINE void copyMarkBit(Cell *dst, const Cell *src, uint32_t color) { - uintptr_t *word, mask; - getMarkWordAndMask(dst, color, &word, &mask); - *word = (*word & ~mask) | (src->isMarked(color) ? mask : 0); - } - void clear() { memset((void *)bitmap, 0, sizeof(bitmap)); } @@ -1119,16 +1112,6 @@ Cell::unmark(uint32_t color) const chunk()->bitmap.unmark(this, color); } -void -Cell::copyMarkBitsFrom(const Cell *src) -{ - JS_ASSERT(isTenured()); - JS_ASSERT(src->isTenured()); - ChunkBitmap &bitmap = chunk()->bitmap; - bitmap.copyMarkBit(this, src, BLACK); - bitmap.copyMarkBit(this, src, GRAY); -} - JS::Zone * Cell::tenuredZone() const { diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 5949fe798efb..62df4ff4cb4a 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -707,17 +707,13 @@ js::gc::MarkForkJoinStack(ForkJoinNurseryCollectionTracer *trc) #endif // JSGC_FJGENERATIONAL void -js::gc::GCRuntime::markRuntime(JSTracer *trc, - TraceOrMarkRuntime traceOrMark, - TraceRootsOrUsedSaved rootsSource) +js::gc::GCRuntime::markRuntime(JSTracer *trc, bool useSavedRoots) { JS_ASSERT(trc->callback != GCMarker::GrayCallback); - JS_ASSERT(traceOrMark == TraceRuntime || traceOrMark == MarkRuntime); - JS_ASSERT(rootsSource == TraceRoots || rootsSource == UseSavedRoots); JS_ASSERT(!rt->mainThread.suppressGC); - if (traceOrMark == MarkRuntime) { + if (IS_GC_MARKING_TRACER(trc)) { for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { if (!c->zone()->isCollecting()) c->markCrossCompartmentWrappers(trc); @@ -731,7 +727,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, #ifdef JSGC_USE_EXACT_ROOTING MarkExactStackRoots(rt, trc); #else - markConservativeStackRoots(trc, rootsSource == UseSavedRoots); + markConservativeStackRoots(trc, useSavedRoots); #endif rt->markSelfHostingGlobal(trc); } @@ -764,7 +760,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, } if (!rt->isBeingDestroyed() && !trc->runtime()->isHeapMinorCollecting()) { - if (traceOrMark == TraceRuntime || rt->atomsCompartment()->zone()->isCollecting()) { + if (!IS_GC_MARKING_TRACER(trc) || rt->atomsCompartment()->zone()->isCollecting()) { MarkPermanentAtoms(trc); MarkAtoms(trc); MarkWellKnownSymbols(trc); @@ -776,7 +772,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, acx->mark(trc); for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { - if (traceOrMark == MarkRuntime && !zone->isCollecting()) + if (IS_GC_MARKING_TRACER(trc) && !zone->isCollecting()) continue; /* Do not discard scripts with counts while profiling. */ @@ -796,11 +792,11 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, if (trc->runtime()->isHeapMinorCollecting()) c->globalWriteBarriered = false; - if (traceOrMark == MarkRuntime && !c->zone()->isCollecting()) + if (IS_GC_MARKING_TRACER(trc) && !c->zone()->isCollecting()) continue; /* During a GC, these are treated as weak pointers. */ - if (traceOrMark == TraceRuntime) { + if (!IS_GC_MARKING_TRACER(trc)) { if (c->watchpointMap) c->watchpointMap->markAll(trc); } @@ -816,9 +812,9 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, if (!isHeapMinorCollecting()) { /* - * All JSCompartment::markRoots() does is mark the globals for - * compartments which have been entered. Globals aren't nursery - * allocated so there's no need to do this for minor GCs. + * All JSCompartment::mark does is mark the globals for compartments + * which have been entered. Globals aren't nursery allocated so there's + * no need to do this for minor GCs. */ for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) c->markRoots(trc); @@ -837,7 +833,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc, /* During GC, we don't mark gray roots at this stage. */ if (JSTraceDataOp op = grayRootTracer.op) { - if (traceOrMark == TraceRuntime) + if (!IS_GC_MARKING_TRACER(trc)) (*op)(trc, grayRootTracer.data); } } diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 4abfec97eb16..f5c9d6761dad 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -632,7 +632,7 @@ void GCMarker::markBufferedGrayRoots(JS::Zone *zone) { JS_ASSERT(grayBufferState == GRAY_BUFFER_OK); - JS_ASSERT(zone->isGCMarkingGray() || zone->isGCCompacting()); + JS_ASSERT(zone->isGCMarkingGray()); for (GrayRoot *elem = zone->gcGrayRoots.begin(); elem != zone->gcGrayRoots.end(); elem++) { #ifdef DEBUG diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 77a270aac5e7..fa6104768a8c 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -120,6 +120,8 @@ Zone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) if (!fop->runtime()->debuggerList.isEmpty()) sweepBreakpoints(fop); + + active = false; } void diff --git a/js/src/jsapi-tests/testWeakMap.cpp b/js/src/jsapi-tests/testWeakMap.cpp index ef583c299bd2..8c3db691d2fa 100644 --- a/js/src/jsapi-tests/testWeakMap.cpp +++ b/js/src/jsapi-tests/testWeakMap.cpp @@ -111,7 +111,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) CHECK(map->zone()->lastZoneGroupIndex() == delegate->zone()->lastZoneGroupIndex()); #endif - /* Check that when the delegate becomes unreachable the entry is removed. */ + /* Check that when the delegate becomes unreacable the entry is removed. */ delegate = nullptr; JS_GC(rt); CHECK(checkSize(map, 0)); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index cca8bae4b403..24c7a6b7b6bc 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -169,16 +169,6 @@ * the mark state, this just stops marking, but if we have started sweeping * already, we continue until we have swept the current zone group. Following a * reset, a new non-incremental collection is started. - * - * Compacting GC - * ------------- - * - * Compacting GC happens at the end of a major GC as part of the last slice. - * There are three parts: - * - * - Arenas are selected for compaction. - * - The contents of those arenas are moved to new arenas. - * - All references to moved things are updated. */ #include "jsgcinlines.h" @@ -926,10 +916,7 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind) JS_ASSERT(hasAvailableArenas()); JSRuntime *rt = zone->runtimeFromAnyThread(); - if (!rt->isHeapMinorCollecting() && - !rt->isHeapCompacting() && - rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) - { + if (!rt->isHeapMinorCollecting() && rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) { #ifdef JSGC_FJGENERATIONAL // This is an approximation to the best test, which would check that // this thread is currently promoting into the tenured area. I doubt @@ -950,7 +937,7 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind) zone->usage.addGCArena(); - if (!rt->isHeapCompacting() && zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) { + if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) { AutoUnlockGC unlock(rt); rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); } @@ -1998,18 +1985,6 @@ ArenaLists::wipeDuringParallelExecution(JSRuntime *rt) } } -/* Compacting GC */ - -bool -GCRuntime::shouldCompact() -{ -#ifdef JSGC_COMPACTING - return invocationKind == GC_SHRINK; -#else - return false; -#endif -} - #ifdef JSGC_COMPACTING static void @@ -2027,381 +2002,8 @@ ForwardCell(Cell *dest, Cell *src) ptr[1] = ForwardedCellMagicValue; // Moved! } -static bool -ArenaContainsGlobal(ArenaHeader *arena) -{ - if (arena->getAllocKind() > FINALIZE_OBJECT_LAST) - return false; - - for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { - JSObject *obj = static_cast(i.getCell()); - if (obj->is()) - return true; - } - - return false; -} - -static bool -CanRelocateArena(ArenaHeader *arena) -{ - /* - * We can't currently move global objects because their address is baked - * into compiled code. We therefore skip moving the contents of any arena - * containing a global. - */ - return arena->getAllocKind() <= FINALIZE_OBJECT_LAST && !ArenaContainsGlobal(arena); -} - -static bool -ShouldRelocateArena(ArenaHeader *arena) -{ -#ifdef JS_GC_ZEAL - if (arena->zone->runtimeFromMainThread()->gc.zeal() == ZealCompactValue) - return true; #endif - /* - * Eventually, this will be based on brilliant heuristics that look at fill - * percentage and fragmentation and... stuff. - */ - return arena->hasFreeThings(); -} - -/* - * Choose some arenas to relocate all cells out of and remove them from the - * arena list. Return the head of the list of arenas to relocate. - */ -ArenaHeader * -ArenaList::pickArenasToRelocate() -{ - check(); - ArenaHeader *head = nullptr; - ArenaHeader **tailp = &head; - - // TODO: Only scan through the arenas with space available. - ArenaHeader **arenap = &head_; - while (*arenap) { - ArenaHeader *arena = *arenap; - JS_ASSERT(arena); - if (CanRelocateArena(arena) && ShouldRelocateArena(arena)) { - // Remove from arena list - if (cursorp_ == &arena->next) - cursorp_ = arenap; - *arenap = arena->next; - arena->next = nullptr; - - // Append to relocation list - *tailp = arena; - tailp = &arena->next; - } else { - arenap = &arena->next; - } - } - - check(); - return head; -} - -static bool -RelocateCell(Zone *zone, Cell *src, AllocKind thingKind, size_t thingSize) -{ - // Allocate a new cell. - void *dst = zone->allocator.arenas.allocateFromFreeList(thingKind, thingSize); - if (!dst) - dst = js::gc::ArenaLists::refillFreeListInGC(zone, thingKind); - if (!dst) - return false; - - // Copy source cell contents to destination. - memcpy(dst, src, thingSize); - - // Mark source cell as forwarded and leave a pointer to the destination. - ForwardCell(static_cast(dst), src); - - // Fixup the pointer to inline object elements if necessary. - if (thingKind <= FINALIZE_OBJECT_LAST) { - JSObject *srcObj = static_cast(src); - JSObject *dstObj = static_cast(dst); - if (srcObj->hasFixedElements()) - dstObj->setFixedElements(); - JS_ASSERT( - uintptr_t((HeapSlot*)dstObj->getElementsHeader()) - uintptr_t(srcObj) >= thingSize); - } - - // Copy the mark bits. - static_cast(dst)->copyMarkBitsFrom(src); - - return true; -} - -static bool -RelocateArena(ArenaHeader *aheader) -{ - JS_ASSERT(aheader->allocated()); - JS_ASSERT(!aheader->hasDelayedMarking); - JS_ASSERT(!aheader->markOverflow); - JS_ASSERT(!aheader->allocatedDuringIncremental); - - Zone *zone = aheader->zone; - - AllocKind thingKind = aheader->getAllocKind(); - size_t thingSize = aheader->getThingSize(); - - for (ArenaCellIterUnderFinalize i(aheader); !i.done(); i.next()) { - if (!RelocateCell(zone, i.getCell(), thingKind, thingSize)) { - MOZ_CRASH(); // TODO: Handle failure here. - return false; - } - } - - return true; -} - -/* - * Relocate all arenas identified by pickArenasToRelocate: for each arena, - * relocate each cell within it, then tack it onto a list of relocated arenas. - * Currently, we allow the relocation to fail, in which case the arena will be - * moved back onto the list of arenas with space available. (I did this - * originally to test my list manipulation before implementing the actual - * moving, with half a thought to allowing pinning (moving only a portion of - * the cells in an arena), but now it's probably just dead weight. FIXME) - */ -ArenaHeader * -ArenaList::relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated) -{ - check(); - - while (ArenaHeader *arena = toRelocate) { - toRelocate = arena->next; - - if (RelocateArena(arena)) { - // Prepend to list of relocated arenas - arena->next = relocated; - relocated = arena; - } else { - // For some reason, the arena did not end up empty. Prepend it to - // the portion of the list that the cursor is pointing to (the - // arenas with space available) so that it will be used for future - // allocations. - JS_ASSERT(arena->hasFreeThings()); - insertAtCursor(arena); - } - } - - check(); - - return relocated; -} - -ArenaHeader * -ArenaLists::relocateArenas(ArenaHeader *relocatedList) -{ - // Flush all the freeLists back into the arena headers - purge(); - checkEmptyFreeLists(); - - for (size_t i = 0; i < FINALIZE_LIMIT; i++) { - ArenaList &al = arenaLists[i]; - ArenaHeader *toRelocate = al.pickArenasToRelocate(); - if (toRelocate) - relocatedList = al.relocateArenas(toRelocate, relocatedList); - } - - /* - * When we allocate new locations for cells, we use - * allocateFromFreeList(). Reset the free list again so that - * AutoCopyFreeListToArenasForGC doesn't complain that the free lists - * are different now. - */ - purge(); - checkEmptyFreeLists(); - - return relocatedList; -} - -struct MovingTracer : JSTracer { - MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapValues) {} - - static void Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind); - static void Sweep(JSTracer *jstrc); -}; - -void -MovingTracer::Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) -{ - Cell *thing = static_cast(*thingp); - if (!thing->tenuredZone()->isGCCompacting()) { - JS_ASSERT(!IsForwarded(thing)); - return; - } - - if (IsForwarded(thing)) { - Cell *dst = Forwarded(thing); - *thingp = dst; - } -} - -void -MovingTracer::Sweep(JSTracer *jstrc) -{ - JSRuntime *rt = jstrc->runtime(); - FreeOp *fop = rt->defaultFreeOp(); - - WatchpointMap::sweepAll(rt); - - Debugger::sweepAll(fop); - - for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { - if (zone->isCollecting()) { - gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP_COMPARTMENTS); - - bool oom = false; - zone->sweep(fop, false, &oom); - JS_ASSERT(!oom); - - for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) { - c->sweep(fop, false); - ArrayBufferObject::sweep(c); - } - } else { - /* Update cross compartment wrappers into moved zones. */ - for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) - c->sweepCrossCompartmentWrappers(); - } - } - - /* Type inference may put more blocks here to free. */ - rt->freeLifoAlloc.freeAll(); -} - -/* - * Update the interal pointers in a single cell. - */ -static void -UpdateCellPointers(MovingTracer *trc, Cell *cell, JSGCTraceKind traceKind) { - TraceChildren(trc, cell, traceKind); - - if (traceKind == JSTRACE_SHAPE) { - Shape *shape = static_cast(cell); - shape->fixupAfterMovingGC(); - } else if (traceKind == JSTRACE_BASE_SHAPE) { - BaseShape *base = static_cast(cell); - base->fixupAfterMovingGC(); - } -} - -/* - * Update pointers to relocated cells by doing a full heap traversal and sweep. - * - * The latter is necessary to update weak references which are not marked as - * part of the traversal. - */ -void -GCRuntime::updatePointersToRelocatedCells() -{ - JS_ASSERT(rt->currentThreadHasExclusiveAccess()); - MovingTracer trc(rt); - - { - // TODO: Maybe give compaction its own set of phases. - gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK); - - // TODO: We may need to fix up other weak pointers here. - - // Fixup compartment global pointers as these get accessed during marking. - for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) - comp->fixupAfterMovingGC(); - - // Fixup cross compartment wrappers as we assert the existence of wrappers in the map. - for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) - comp->fixupCrossCompartmentWrappers(&trc); - - // Fixup generators as these are not normally traced. - for (ContextIter i(rt); !i.done(); i.next()) { - for (JSGenerator *gen = i.get()->innermostGenerator(); gen; gen = gen->prevGenerator) - gen->obj = MaybeForwarded(gen->obj.get()); - } - - // Iterate through all allocated cells to update internal pointers. - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - ArenaLists &al = zone->allocator.arenas; - for (unsigned i = 0; i < FINALIZE_LIMIT; ++i) { - AllocKind thingKind = static_cast(i); - JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind); - for (ArenaHeader *arena = al.getFirstArena(thingKind); arena; arena = arena->next) { - for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) { - UpdateCellPointers(&trc, i.getCell(), traceKind); - } - } - } - } - - // Mark roots to update them. - markRuntime(&trc, MarkRuntime); - Debugger::markAll(&trc); - Debugger::markCrossCompartmentDebuggerObjectReferents(&trc); - - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - if (c->watchpointMap) - c->watchpointMap->markAll(&trc); - } - } - - { - gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_SWEEP); - - markAllGrayReferences(); - - MovingTracer::Sweep(&trc); - } -} - -void -GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) -{ - // Release the relocated arenas, now containing only forwarding pointers - -#ifdef DEBUG - for (ArenaHeader *arena = relocatedList; arena; arena = arena->next) { - for (ArenaCellIterUnderFinalize i(arena); !i.done(); i.next()) { - Cell *src = i.getCell(); - JS_ASSERT(IsForwarded(src)); - Cell *dest = Forwarded(src); - JS_ASSERT(src->isMarked(BLACK) == dest->isMarked(BLACK)); - JS_ASSERT(src->isMarked(GRAY) == dest->isMarked(GRAY)); - } - } -#endif - - unsigned count = 0; - while (relocatedList) { - ArenaHeader *aheader = relocatedList; - relocatedList = relocatedList->next; - - // Mark arena as empty - AllocKind thingKind = aheader->getAllocKind(); - size_t thingSize = aheader->getThingSize(); - Arena *arena = aheader->getArena(); - FreeSpan fullSpan; - fullSpan.initFinal(arena->thingsStart(thingKind), arena->thingsEnd() - thingSize, thingSize); - aheader->setFirstFreeSpan(&fullSpan); - -#if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL) - JS_POISON(reinterpret_cast(arena->thingsStart(thingKind)), - JS_MOVED_TENURED_PATTERN, Arena::thingsSpan(thingSize)); -#endif - - aheader->chunk()->releaseArena(aheader); - ++count; - } - - AutoLockGC lock(rt); - expireChunksAndArenas(true); -} - -#endif // JSGC_COMPACTING - void ArenaLists::finalizeNow(FreeOp *fop, AllocKind thingKind) { @@ -2688,22 +2290,6 @@ ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); template void * ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); -/* static */ void * -ArenaLists::refillFreeListInGC(Zone *zone, AllocKind thingKind) -{ - /* - * Called by compacting GC to refill a free list while we are in a GC. - */ - - Allocator &allocator = zone->allocator; - JS_ASSERT(allocator.arenas.freeLists[thingKind].isEmpty()); - JSRuntime *rt = zone->runtimeFromMainThread(); - JS_ASSERT(rt->isHeapMajorCollecting()); - JS_ASSERT(!rt->gc.isBackgroundSweeping()); - - return allocator.arenas.allocateFromArena(zone, thingKind); -} - /* static */ int64_t SliceBudget::TimeBudget(int64_t millis) { @@ -3670,7 +3256,7 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason) if (isFull) UnmarkScriptData(rt); - markRuntime(gcmarker, MarkRuntime); + markRuntime(gcmarker); if (isIncremental) bufferGrayRoots(); @@ -3801,6 +3387,8 @@ GCRuntime::markGrayReferencesInCurrentGroup() markGrayReferences(); } +#ifdef DEBUG + void GCRuntime::markAllWeakReferences(gcstats::Phase phase) { @@ -3813,8 +3401,6 @@ GCRuntime::markAllGrayReferences() markGrayReferences(); } -#ifdef DEBUG - class js::gc::MarkingValidator { public: @@ -3919,7 +3505,7 @@ js::gc::MarkingValidator::nonIncrementalMark() { gcstats::AutoPhase ap1(gc->stats, gcstats::PHASE_MARK); gcstats::AutoPhase ap2(gc->stats, gcstats::PHASE_MARK_ROOTS); - gc->markRuntime(gcmarker, GCRuntime::MarkRuntime, GCRuntime::UseSavedRoots); + gc->markRuntime(gcmarker, true); } { @@ -4681,8 +4267,7 @@ GCRuntime::beginSweepPhase(bool lastGC) gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP); - sweepOnBackgroundThread = - !lastGC && !TraceEnabled() && CanUseExtraThreads() && !shouldCompact(); + sweepOnBackgroundThread = !lastGC && !TraceEnabled() && CanUseExtraThreads(); releaseObservedTypes = shouldReleaseObservedTypes(); @@ -4810,6 +4395,9 @@ GCRuntime::endSweepPhase(bool lastGC) JS_ASSERT_IF(lastGC, !sweepOnBackgroundThread); + JS_ASSERT(marker.isDrained()); + marker.stop(); + /* * Recalculate whether GC was full or not as this may have changed due to * newly created zones. Can only change from full to not full. @@ -4910,17 +4498,30 @@ GCRuntime::endSweepPhase(bool lastGC) sweepZones(&fop, lastGC); } - finishMarkingValidation(); + uint64_t currentTime = PRMJ_Now(); + schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); + + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { + zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables, + schedulingState); + if (zone->isCollecting()) { + JS_ASSERT(zone->isGCFinished()); + zone->setGCState(Zone::NoGC); + } #ifdef DEBUG - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { + JS_ASSERT(!zone->isCollecting()); + JS_ASSERT(!zone->wasGCStarted()); + for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i) { JS_ASSERT_IF(!IsBackgroundFinalized(AllocKind(i)) || !sweepOnBackgroundThread, !zone->allocator.arenas.arenaListsToSweep[i]); } +#endif } +#ifdef DEBUG for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { JS_ASSERT(!c->gcIncomingGrayPointers); JS_ASSERT(c->gcLiveArrayBuffers.empty()); @@ -4931,61 +4532,8 @@ GCRuntime::endSweepPhase(bool lastGC) } } #endif -} -#ifdef JSGC_COMPACTING -void -GCRuntime::compactPhase() -{ - JS_ASSERT(rt->gc.nursery.isEmpty()); - JS_ASSERT(!sweepOnBackgroundThread); - - ArenaHeader *relocatedList = nullptr; - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - JS_ASSERT(zone->isGCFinished()); - JS_ASSERT(!zone->isPreservingCode()); - - // We cannot move atoms as we depend on their addresses being constant. - if (!rt->isAtomsZone(zone)) { - zone->setGCState(Zone::Compact); - relocatedList = zone->allocator.arenas.relocateArenas(relocatedList); - } - } - - updatePointersToRelocatedCells(); - releaseRelocatedArenas(relocatedList); - -#ifdef DEBUG - CheckHashTablesAfterMovingGC(rt); - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - if (!rt->isAtomsZone(zone) && !zone->isPreservingCode()) - zone->allocator.arenas.checkEmptyFreeLists(); - } -#endif -} -#endif // JSGC_COMPACTING - -void -GCRuntime::finishCollection() -{ - JS_ASSERT(marker.isDrained()); - marker.stop(); - - uint64_t currentTime = PRMJ_Now(); - schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); - - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables, - schedulingState); - if (zone->isCollecting()) { - JS_ASSERT(zone->isGCFinished() || zone->isGCCompacting()); - zone->setGCState(Zone::NoGC); - zone->active = false; - } - - JS_ASSERT(!zone->isCollecting()); - JS_ASSERT(!zone->wasGCStarted()); - } + finishMarkingValidation(); lastGCTime = currentTime; } @@ -5322,14 +4870,6 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (sweepOnBackgroundThread) helperState.startBackgroundSweep(invocationKind == GC_SHRINK); -#ifdef JSGC_COMPACTING - if (shouldCompact()) { - incrementalState = COMPACT; - compactPhase(); - } -#endif - - finishCollection(); incrementalState = NO_INCREMENTAL; break; } @@ -6002,8 +5542,6 @@ GCRuntime::runDebugGC() { incrementalLimit = zealFrequency / 2; } - } else if (type == ZealCompactValue) { - collect(false, SliceBudget::Unlimited, GC_SHRINK, JS::gcreason::DEBUG_GC); } else { collect(false, SliceBudget::Unlimited, GC_NORMAL, JS::gcreason::DEBUG_GC); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 4098135495de..05c825c83919 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -523,11 +523,6 @@ class ArenaList { check(); return *this; } - -#ifdef JSGC_COMPACTING - ArenaHeader *pickArenasToRelocate(); - ArenaHeader *relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated); -#endif }; /* @@ -804,6 +799,7 @@ class ArenaLists clearFreeListInArena(AllocKind(i)); } + void clearFreeListInArena(AllocKind kind) { FreeList *freeList = &freeLists[kind]; if (!freeList->isEmpty()) { @@ -849,8 +845,6 @@ class ArenaLists template static void *refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); - static void *refillFreeListInGC(Zone *zone, AllocKind thingKind); - /* * Moves all arenas from |fromArenaLists| into |this|. In * parallel blocks, we temporarily create one ArenaLists per @@ -874,10 +868,6 @@ class ArenaLists JS_ASSERT(freeLists[kind].isEmpty()); } -#ifdef JSGC_COMPACTING - ArenaHeader *relocateArenas(ArenaHeader *relocatedList); -#endif - void queueObjectsForSweep(FreeOp *fop); void queueStringsAndSymbolsForSweep(FreeOp *fop); void queueShapesForSweep(FreeOp *fop); @@ -1330,8 +1320,7 @@ const int ZealIncrementalMultipleSlices = 10; const int ZealVerifierPostValue = 11; const int ZealFrameVerifierPostValue = 12; const int ZealCheckHashTablesOnMinorGC = 13; -const int ZealCompactValue = 14; -const int ZealLimit = 14; +const int ZealLimit = 13; enum VerifierType { PreBarrierVerifier, From a8824390bc2032ca71b2e16f9f5ab3bb6ec25711 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:37 +0100 Subject: [PATCH 021/119] Backed out changeset d4fca818c9a8 (bug 650161) --- js/src/jit/arm/Assembler-arm.cpp | 45 ++++++++-------------- js/src/jit/mips/Assembler-mips.cpp | 2 - js/src/jit/shared/Assembler-x86-shared.cpp | 2 +- 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/js/src/jit/arm/Assembler-arm.cpp b/js/src/jit/arm/Assembler-arm.cpp index b519dacf3b9c..220486b56eef 100644 --- a/js/src/jit/arm/Assembler-arm.cpp +++ b/js/src/jit/arm/Assembler-arm.cpp @@ -795,49 +795,36 @@ Assembler::TraceJumpRelocations(JSTracer *trc, JitCode *code, CompactBufferReade } } -template static void -TraceOneDataRelocation(JSTracer *trc, Iter *iter, MacroAssemblerARM *masm) -{ - Instruction *ins = iter->cur(); - Register dest; - Assembler::RelocStyle rs; - const void *prior = Assembler::GetPtr32Target(iter, &dest, &rs); - void *ptr = const_cast(prior); - - // No barrier needed since these are constants. - gc::MarkGCThingUnbarriered(trc, &ptr, "ion-masm-ptr"); - - if (ptr != prior) - masm->ma_movPatchable(Imm32(int32_t(ptr)), dest, Assembler::Always, rs, ins); -} - -static void -TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader, - MacroAssemblerARM *masm) +TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader) { while (reader.more()) { size_t offset = reader.readUnsigned(); InstructionIterator iter((Instruction*)(buffer + offset)); - TraceOneDataRelocation(trc, &iter, masm); + void *ptr = const_cast(Assembler::GetPtr32Target(&iter)); + // No barrier needed since these are constants. + gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); } -} +} static void TraceDataRelocations(JSTracer *trc, ARMBuffer *buffer, - Vector *locs, MacroAssemblerARM *masm) + Vector *locs) { for (unsigned int idx = 0; idx < locs->length(); idx++) { BufferOffset bo = (*locs)[idx]; ARMBuffer::AssemblerBufferInstIterator iter(bo, buffer); - TraceOneDataRelocation(trc, &iter, masm); - } -} + void *ptr = const_cast(Assembler::GetPtr32Target(&iter)); + // No barrier needed since these are constants. + gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); + } + +} void Assembler::TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader) { - ::TraceDataRelocations(trc, code->raw(), reader, static_cast(Dummy)); + ::TraceDataRelocations(trc, code->raw(), reader); } void @@ -873,10 +860,8 @@ Assembler::trace(JSTracer *trc) } } - if (tmpDataRelocations_.length()) { - ::TraceDataRelocations(trc, &m_buffer, &tmpDataRelocations_, - static_cast(this)); - } + if (tmpDataRelocations_.length()) + ::TraceDataRelocations(trc, &m_buffer, &tmpDataRelocations_); } void diff --git a/js/src/jit/mips/Assembler-mips.cpp b/js/src/jit/mips/Assembler-mips.cpp index 0ba04c834be9..58a077255fc8 100644 --- a/js/src/jit/mips/Assembler-mips.cpp +++ b/js/src/jit/mips/Assembler-mips.cpp @@ -262,7 +262,6 @@ TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader // No barrier needed since these are constants. gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); - Assembler::UpdateLuiOriValue(inst, inst->next(), uint32_t(ptr)); } } @@ -277,7 +276,6 @@ TraceDataRelocations(JSTracer *trc, MIPSBuffer *buffer, CompactBufferReader &rea // No barrier needed since these are constants. gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); - Assembler::UpdateLuiOriValue(iter.cur(), iter.next(), uint32_t(ptr)); } } diff --git a/js/src/jit/shared/Assembler-x86-shared.cpp b/js/src/jit/shared/Assembler-x86-shared.cpp index 665d80835418..53fd21018568 100644 --- a/js/src/jit/shared/Assembler-x86-shared.cpp +++ b/js/src/jit/shared/Assembler-x86-shared.cpp @@ -54,7 +54,7 @@ TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader layout.asBits = *word; Value v = IMPL_TO_JSVAL(layout); gc::MarkValueUnbarriered(trc, &v, "ion-masm-value"); - *word = JSVAL_TO_IMPL(v).asBits; + JS_ASSERT(*word == JSVAL_TO_IMPL(v).asBits); continue; } #endif From 1b0adcea1143ceb80db5743ff5b1e866aada99a8 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:41 +0100 Subject: [PATCH 022/119] Backed out changeset 3adf62f886d9 (bug 650161) --- js/public/HashTable.h | 1 - js/src/builtin/TypedObject.cpp | 40 +++---------------- js/src/builtin/TypedObject.h | 20 ---------- js/src/gc/GCRuntime.h | 5 --- js/src/gc/Marking.cpp | 59 ++++++++------------------- js/src/gc/Zone.cpp | 7 ++-- js/src/gc/Zone.h | 8 +--- js/src/jscntxt.cpp | 17 +++----- js/src/jscntxt.h | 14 ------- js/src/jscompartment.cpp | 61 +--------------------------- js/src/jscompartment.h | 8 ---- js/src/jsgc.h | 5 +-- js/src/jsinfer.cpp | 68 ++++++++----------------------- js/src/jsiter.cpp | 2 - js/src/jspropertytree.cpp | 71 --------------------------------- js/src/jspropertytree.h | 2 +- js/src/jsproxy.cpp | 3 +- js/src/jsscript.cpp | 2 +- js/src/jswrapper.cpp | 5 --- js/src/vm/ArrayBufferObject.cpp | 25 +++--------- js/src/vm/Debugger.cpp | 6 +-- js/src/vm/Debugger.h | 3 -- js/src/vm/Runtime.h | 3 +- js/src/vm/ScopeObject.cpp | 20 ++-------- js/src/vm/ScopeObject.h | 3 -- js/src/vm/Shape-inl.h | 9 ----- js/src/vm/Shape.cpp | 71 +-------------------------------- js/src/vm/Shape.h | 20 +--------- 28 files changed, 69 insertions(+), 489 deletions(-) diff --git a/js/public/HashTable.h b/js/public/HashTable.h index b958c8e9cc42..f8d91ef092ea 100644 --- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -959,7 +959,6 @@ class HashTable : private AllocPolicy // a new key at the new Lookup position. |front()| is invalid after // this operation until the next call to |popFront()|. void rekeyFront(const Lookup &l, const Key &k) { - JS_ASSERT(&k != &HashPolicy::getKey(this->cur->get())); Ptr p(*this->cur, table_); table_.rekeyWithoutRehash(p, l, k); rekeyed = true; diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 412cbebf99f7..b52f6d835510 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -1126,14 +1126,6 @@ StructTypeDescr::fieldCount() const return getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject().getDenseInitializedLength(); } -size_t -StructTypeDescr::maybeForwardedFieldCount() const -{ - JSObject *fieldNames = - MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject()); - return fieldNames->getDenseInitializedLength(); -} - bool StructTypeDescr::fieldIndex(jsid id, size_t *out) const { @@ -1165,15 +1157,6 @@ StructTypeDescr::fieldOffset(size_t index) const return SafeCast(fieldOffsets.getDenseElement(index).toInt32()); } -size_t -StructTypeDescr::maybeForwardedFieldOffset(size_t index) const -{ - JSObject &fieldOffsets = - *MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS).toObject()); - JS_ASSERT(index < fieldOffsets.getDenseInitializedLength()); - return SafeCast(fieldOffsets.getDenseElement(index).toInt32()); -} - SizedTypeDescr& StructTypeDescr::fieldDescr(size_t index) const { @@ -1183,15 +1166,6 @@ StructTypeDescr::fieldDescr(size_t index) const return fieldDescrs.getDenseElement(index).toObject().as(); } -SizedTypeDescr& -StructTypeDescr::maybeForwardedFieldDescr(size_t index) const -{ - JSObject &fieldDescrs = - *MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES).toObject()); - JS_ASSERT(index < fieldDescrs.getDenseInitializedLength()); - return fieldDescrs.getDenseElement(index).toObject().as(); -} - /****************************************************************************** * Creating the TypedObject "module" * @@ -1656,11 +1630,7 @@ TypedObject::obj_trace(JSTracer *trace, JSObject *object) JS_ASSERT(object->is()); TypedObject &typedObj = object->as(); - - // When this is called for compacting GC, the related objects we touch here - // may not have had their slots updated yet. - TypeDescr &descr = typedObj.maybeForwardedTypeDescr(); - + TypeDescr &descr = typedObj.typeDescr(); if (descr.opaque()) { uint8_t *mem = typedObj.typedMem(); if (!mem) @@ -3122,7 +3092,7 @@ visitReferences(SizedTypeDescr &descr, case type::SizedArray: { SizedArrayTypeDescr &arrayDescr = descr.as(); - SizedTypeDescr &elementDescr = arrayDescr.maybeForwardedElementType(); + SizedTypeDescr &elementDescr = arrayDescr.elementType(); for (int32_t i = 0; i < arrayDescr.length(); i++) { visitReferences(elementDescr, mem, visitor); mem += elementDescr.size(); @@ -3138,9 +3108,9 @@ visitReferences(SizedTypeDescr &descr, case type::Struct: { StructTypeDescr &structDescr = descr.as(); - for (size_t i = 0; i < structDescr.maybeForwardedFieldCount(); i++) { - SizedTypeDescr &descr = structDescr.maybeForwardedFieldDescr(i); - size_t offset = structDescr.maybeForwardedFieldOffset(i); + for (size_t i = 0; i < structDescr.fieldCount(); i++) { + SizedTypeDescr &descr = structDescr.fieldDescr(i); + size_t offset = structDescr.fieldOffset(i); visitReferences(descr, mem + offset, visitor); } return; diff --git a/js/src/builtin/TypedObject.h b/js/src/builtin/TypedObject.h index 78cbcfbbcf13..bfc59e0d4f05 100644 --- a/js/src/builtin/TypedObject.h +++ b/js/src/builtin/TypedObject.h @@ -169,10 +169,6 @@ class TypedProto : public JSObject return getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject().as(); } - TypeDescr &maybeForwardedTypeDescr() const { - return MaybeForwarded(&getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject())->as(); - } - inline type::Kind kind() const; }; @@ -457,11 +453,6 @@ class SizedArrayTypeDescr : public ComplexTypeDescr return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as(); } - SizedTypeDescr &maybeForwardedElementType() const { - JSObject *elemType = &getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject(); - return MaybeForwarded(elemType)->as(); - } - int32_t length() const { return getReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH).toInt32(); } @@ -501,7 +492,6 @@ class StructTypeDescr : public ComplexTypeDescr // Returns the number of fields defined in this struct. size_t fieldCount() const; - size_t maybeForwardedFieldCount() const; // Set `*out` to the index of the field named `id` and returns true, // or return false if no such field exists. @@ -512,11 +502,9 @@ class StructTypeDescr : public ComplexTypeDescr // Return the type descr of the field at index `index`. SizedTypeDescr &fieldDescr(size_t index) const; - SizedTypeDescr &maybeForwardedFieldDescr(size_t index) const; // Return the offset of the field at index `index`. size_t fieldOffset(size_t index) const; - size_t maybeForwardedFieldOffset(size_t index) const; }; typedef Handle HandleStructTypeDescr; @@ -690,18 +678,10 @@ class TypedObject : public ArrayBufferViewObject return getProto()->as(); } - TypedProto &maybeForwardedTypedProto() const { - return MaybeForwarded(getProto())->as(); - } - TypeDescr &typeDescr() const { return typedProto().typeDescr(); } - TypeDescr &maybeForwardedTypeDescr() const { - return maybeForwardedTypedProto().maybeForwardedTypeDescr(); - } - uint8_t *typedMem() const { return (uint8_t*) getPrivate(); } diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index e66033129051..6d1d5dc88cdf 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -262,11 +262,6 @@ class GCRuntime bool isHeapMajorCollecting() { return heapState == js::MajorCollecting; } bool isHeapMinorCollecting() { return heapState == js::MinorCollecting; } bool isHeapCollecting() { return isHeapMajorCollecting() || isHeapMinorCollecting(); } -#ifdef JSGC_COMPACTING - bool isHeapCompacting() { return isHeapMajorCollecting() && state() == COMPACT; } -#else - bool isHeapCompacting() { return false; } -#endif // Performance note: if isFJMinorCollecting turns out to be slow because // reading the counter is slow then we may be able to augment the counter diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 4e4f2e8a0d47..073704606d66 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -164,10 +164,6 @@ CheckMarkedThing(JSTracer *trc, T **thingp) T *thing = *thingp; JS_ASSERT(*thingp); -#ifdef JSGC_COMPACTING - thing = MaybeForwarded(thing); -#endif - # ifdef JSGC_FJGENERATIONAL /* * The code below (runtimeFromMainThread(), etc) makes assumptions @@ -446,10 +442,6 @@ IsMarked(T **thingp) Zone *zone = (*thingp)->tenuredZone(); if (!zone->isCollecting() || zone->isGCFinished()) return true; -#ifdef JSGC_COMPACTING - if (zone->isGCCompacting() && IsForwarded(*thingp)) - *thingp = Forwarded(*thingp); -#endif return (*thingp)->isMarked(); } @@ -488,27 +480,19 @@ IsAboutToBeFinalized(T **thingp) } #endif // JSGC_GENERATIONAL - Zone *zone = thing->tenuredZone(); - if (zone->isGCSweeping()) { - /* - * We should return false for things that have been allocated during - * incremental sweeping, but this possibility doesn't occur at the moment - * because this function is only called at the very start of the sweeping a - * compartment group and during minor gc. Rather than do the extra check, - * we just assert that it's not necessary. - */ - JS_ASSERT_IF(!rt->isHeapMinorCollecting(), !thing->arenaHeader()->allocatedDuringIncremental); - - return !thing->isMarked(); - } -#ifdef JSGC_COMPACTING - else if (zone->isGCCompacting() && IsForwarded(thing)) { - *thingp = Forwarded(thing); + if (!thing->tenuredZone()->isGCSweeping()) return false; - } -#endif - return false; + /* + * We should return false for things that have been allocated during + * incremental sweeping, but this possibility doesn't occur at the moment + * because this function is only called at the very start of the sweeping a + * compartment group and during minor gc. Rather than do the extra check, + * we just assert that it's not necessary. + */ + JS_ASSERT_IF(!rt->isHeapMinorCollecting(), !thing->arenaHeader()->allocatedDuringIncremental); + + return !thing->isMarked(); } template @@ -516,32 +500,21 @@ T * UpdateIfRelocated(JSRuntime *rt, T **thingp) { JS_ASSERT(thingp); - if (!*thingp) - return nullptr; - #ifdef JSGC_GENERATIONAL - #ifdef JSGC_FJGENERATIONAL - if (rt->isFJMinorCollecting()) { + if (*thingp && rt->isFJMinorCollecting()) { ForkJoinContext *ctx = ForkJoinContext::current(); ForkJoinNursery &nursery = ctx->nursery(); if (nursery.isInsideFromspace(*thingp)) nursery.getForwardedPointer(thingp); - return *thingp; } + else #endif - - if (rt->isHeapMinorCollecting() && IsInsideNursery(*thingp)) { - rt->gc.nursery.getForwardedPointer(thingp); - return *thingp; + { + if (*thingp && rt->isHeapMinorCollecting() && IsInsideNursery(*thingp)) + rt->gc.nursery.getForwardedPointer(thingp); } #endif // JSGC_GENERATIONAL - -#ifdef JSGC_COMPACTING - Zone *zone = (*thingp)->tenuredZone(); - if (zone->isGCCompacting() && IsForwarded(*thingp)) - *thingp = Forwarded(*thingp); -#endif return *thingp; } diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index fa6104768a8c..0bf676576bd6 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -135,10 +135,10 @@ Zone::sweepBreakpoints(FreeOp *fop) gcstats::AutoPhase ap1(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES); gcstats::AutoPhase ap2(fop->runtime()->gc.stats, gcstats::PHASE_SWEEP_TABLES_BREAKPOINT); - JS_ASSERT(isGCSweepingOrCompacting()); + JS_ASSERT(isGCSweeping()); for (ZoneCellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); - JS_ASSERT_IF(isGCSweeping(), script->zone()->isGCSweeping()); + JS_ASSERT(script->zone()->isGCSweeping()); if (!script->hasAnyBreakpointsOrStepMode()) continue; @@ -153,8 +153,7 @@ Zone::sweepBreakpoints(FreeOp *fop) for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) { nextbp = bp->nextInSite(); HeapPtrObject &dbgobj = bp->debugger->toJSObjectRef(); - JS_ASSERT_IF(isGCSweeping() && dbgobj->zone()->isCollecting(), - dbgobj->zone()->isGCSweeping()); + JS_ASSERT_IF(dbgobj->zone()->isCollecting(), dbgobj->zone()->isGCSweeping()); bool dying = scriptGone || IsObjectAboutToBeFinalized(&dbgobj); JS_ASSERT_IF(!dying, !IsAboutToBeFinalized(&bp->getHandlerRef())); if (dying) diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 1749052518df..0f3318da4cd9 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -175,8 +175,7 @@ struct Zone : public JS::shadow::Zone, Mark, MarkGray, Sweep, - Finished, - Compact + Finished }; void setGCState(GCState state) { JS_ASSERT(runtimeFromMainThread()->isHeapBusy()); @@ -194,8 +193,7 @@ struct Zone : public JS::shadow::Zone, // If this returns true, all object tracing must be done with a GC marking // tracer. bool requireGCTracer() const { - JSRuntime *rt = runtimeFromMainThread(); - return rt->isHeapMajorCollecting() && !rt->isHeapCompacting() && gcState_ != NoGC; + return runtimeFromMainThread()->isHeapMajorCollecting() && gcState_ != NoGC; } bool isGCMarking() { @@ -210,8 +208,6 @@ struct Zone : public JS::shadow::Zone, bool isGCMarkingGray() { return gcState_ == MarkGray; } bool isGCSweeping() { return gcState_ == Sweep; } bool isGCFinished() { return gcState_ == Finished; } - bool isGCCompacting() { return gcState_ == Compact; } - bool isGCSweepingOrCompacting() { return gcState_ == Sweep || gcState_ == Compact; } // Get a number that is incremented whenever this zone is collected, and // possibly at other times too. diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index eb4cf1c38759..e6aa3c0c2cb0 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -87,11 +87,10 @@ void js::TraceCycleDetectionSet(JSTracer *trc, js::ObjectSet &set) { for (js::ObjectSet::Enum e(set); !e.empty(); e.popFront()) { - JSObject *key = e.front(); - trc->setTracingLocation((void *)&e.front()); - MarkObjectRoot(trc, &key, "cycle detector table entry"); - if (key != e.front()) - e.rekeyFront(key); + JSObject *prior = e.front(); + MarkObjectRoot(trc, const_cast(&e.front()), "cycle detector table entry"); + if (prior != e.front()) + e.rekeyFront(e.front()); } } @@ -101,13 +100,9 @@ JSCompartment::sweepCallsiteClones() if (callsiteClones.initialized()) { for (CallsiteCloneTable::Enum e(callsiteClones); !e.empty(); e.popFront()) { CallsiteCloneKey key = e.front().key(); - if (IsObjectAboutToBeFinalized(&key.original) || IsScriptAboutToBeFinalized(&key.script) || - IsObjectAboutToBeFinalized(e.front().value().unsafeGet())) - { + JSFunction *fun = e.front().value(); + if (!IsScriptMarked(&key.script) || !IsObjectMarked(&fun)) e.removeFront(); - } else if (key != e.front().key()) { - e.rekeyFront(key); - } } } } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 93bb160c8e34..734ee731f1ec 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -49,14 +49,6 @@ struct CallsiteCloneKey { CallsiteCloneKey(JSFunction *f, JSScript *s, uint32_t o) : original(f), script(s), offset(o) {} - bool operator==(const CallsiteCloneKey& other) { - return original == other.original && script == other.script && offset == other.offset; - } - - bool operator!=(const CallsiteCloneKey& other) { - return !(*this == other); - } - typedef CallsiteCloneKey Lookup; static inline uint32_t hash(CallsiteCloneKey key) { @@ -66,12 +58,6 @@ struct CallsiteCloneKey { static inline bool match(const CallsiteCloneKey &a, const CallsiteCloneKey &b) { return a.script == b.script && a.offset == b.offset && a.original == b.original; } - - static void rekey(CallsiteCloneKey &k, const CallsiteCloneKey &newKey) { - k.original = newKey.original; - k.script = newKey.script; - k.offset = newKey.offset; - } }; typedef HashMapgc.stats, - gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); - sweepNewTypeObjectTable(newTypeObjects); - sweepNewTypeObjectTable(lazyTypeObjects); - } + sweepNewTypeObjectTable(newTypeObjects); + sweepNewTypeObjectTable(lazyTypeObjects); sweepCallsiteClones(); savedStacks_.sweep(rt); @@ -660,59 +656,6 @@ JSCompartment::sweepCrossCompartmentWrappers() } } -#ifdef JSGC_COMPACTING - -/* - * Fixup wrappers with moved keys or values. - */ -void -JSCompartment::fixupCrossCompartmentWrappers(JSTracer *trc) -{ - for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { - Value val = e.front().value(); - if (IsForwarded(val)) { - val = Forwarded(val); - e.front().value().set(val); - } - - // CrossCompartmentKey's hash does not depend on the debugger object, - // so update it but do not rekey if it changes - CrossCompartmentKey key = e.front().key(); - if (key.debugger) - key.debugger = MaybeForwarded(key.debugger); - if (key.wrapped && IsForwarded(key.wrapped)) { - key.wrapped = Forwarded(key.wrapped); - e.rekeyFront(key, key); - } - - if (!zone()->isCollecting() && val.isObject()) { - // Call the trace hook to update any pointers to relocated things. - JSObject *obj = &val.toObject(); - const Class *clasp = obj->getClass(); - if (clasp->trace) - clasp->trace(trc, obj); - } - } -} - -void JSCompartment::fixupAfterMovingGC() -{ - fixupGlobal(); - fixupNewTypeObjectTable(newTypeObjects); - fixupNewTypeObjectTable(lazyTypeObjects); - fixupInitialShapeTable(); -} - -void -JSCompartment::fixupGlobal() -{ - GlobalObject *global = *global_.unsafeGet(); - if (global) - global_.set(MaybeForwarded(global)); -} - -#endif // JSGC_COMPACTING - void JSCompartment::purge() { diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index bb03696fbcea..6c71d0e91033 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -347,14 +347,6 @@ struct JSCompartment void purge(); void clearTables(); -#ifdef JSGC_COMPACTING - void fixupInitialShapeTable(); - void fixupNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table); - void fixupCrossCompartmentWrappers(JSTracer *trc); - void fixupAfterMovingGC(); - void fixupGlobal(); -#endif - bool hasObjectMetadataCallback() const { return objectMetadataCallback; } void setObjectMetadataCallback(js::ObjectMetadataCallback callback); void forgetObjectMetadataCallback() { diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 05c825c83919..d44ff381f1fc 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -47,9 +47,7 @@ enum State { MARK_ROOTS, MARK, SWEEP, -#ifdef JSGC_COMPACTING - COMPACT -#endif + INVALID }; static inline JSGCTraceKind @@ -1277,7 +1275,6 @@ MaybeForwarded(T t) #else template inline bool IsForwarded(T t) { return false; } -template inline T Forwarded(T t) { return t; } template inline T MaybeForwarded(T t) { return t; } #endif // JSGC_COMPACTING diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 275a288705f0..790794631c8a 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3440,13 +3440,12 @@ types::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args } static inline bool -IsAboutToBeFinalized(TypeObjectKey **keyp) +IsAboutToBeFinalized(TypeObjectKey *key) { /* Mask out the low bit indicating whether this is a type or JS object. */ - uintptr_t flagBit = uintptr_t(*keyp) & 1; - gc::Cell *tmp = reinterpret_cast(uintptr_t(*keyp) & ~1); + gc::Cell *tmp = reinterpret_cast(uintptr_t(key) & ~1); bool isAboutToBeFinalized = IsCellAboutToBeFinalized(&tmp); - *keyp = reinterpret_cast(uintptr_t(tmp) | flagBit); + JS_ASSERT(tmp == reinterpret_cast(uintptr_t(key) & ~1)); return isAboutToBeFinalized; } @@ -3944,7 +3943,7 @@ ConstraintTypeSet::sweep(Zone *zone, bool *oom) objectCount = 0; for (unsigned i = 0; i < oldCapacity; i++) { TypeObjectKey *object = oldArray[i]; - if (object && !IsAboutToBeFinalized(&object)) { + if (object && !IsAboutToBeFinalized(object)) { TypeObjectKey **pentry = HashSetInsert (zone->types.typeLifoAlloc, objectSet, objectCount, object); @@ -3962,11 +3961,9 @@ ConstraintTypeSet::sweep(Zone *zone, bool *oom) setBaseObjectCount(objectCount); } else if (objectCount == 1) { TypeObjectKey *object = (TypeObjectKey *) objectSet; - if (IsAboutToBeFinalized(&object)) { + if (IsAboutToBeFinalized(object)) { objectSet = nullptr; setBaseObjectCount(0); - } else { - objectSet = reinterpret_cast(object); } } @@ -4180,59 +4177,26 @@ TypeCompartment::sweep(FreeOp *fop) void JSCompartment::sweepNewTypeObjectTable(TypeObjectWithNewScriptSet &table) { - JS_ASSERT(zone()->isCollecting()); - if (table.initialized()) { - for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) { - TypeObjectWithNewScriptEntry entry = e.front(); - if (IsTypeObjectAboutToBeFinalized(entry.object.unsafeGet()) || - (entry.newFunction && IsObjectAboutToBeFinalized(&entry.newFunction))) - { - e.removeFront(); - } else { - /* Any rekeying necessary is handled by fixupNewTypeObjectTable() below. */ - JS_ASSERT(entry.object == e.front().object); - JS_ASSERT(entry.newFunction == e.front().newFunction); - } - } - } -} + gcstats::AutoPhase ap(runtimeFromMainThread()->gc.stats, + gcstats::PHASE_SWEEP_TABLES_TYPE_OBJECT); -#ifdef JSGC_COMPACTING -void -JSCompartment::fixupNewTypeObjectTable(TypeObjectWithNewScriptSet &table) -{ - /* - * Each entry's hash depends on the object's prototype and we can't tell - * whether that has been moved or not in sweepNewTypeObjectTable(). - */ - JS_ASSERT(zone()->isCollecting()); + JS_ASSERT(zone()->isGCSweeping()); if (table.initialized()) { for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) { TypeObjectWithNewScriptEntry entry = e.front(); - bool needRekey = false; - if (IsForwarded(entry.object.get())) { - entry.object.set(Forwarded(entry.object.get())); - needRekey = true; - } - TaggedProto proto = entry.object->proto(); - if (proto.isObject() && IsForwarded(proto.toObject())) { - proto = TaggedProto(Forwarded(proto.toObject())); - needRekey = true; - } - if (entry.newFunction && IsForwarded(entry.newFunction)) { - entry.newFunction = Forwarded(entry.newFunction); - needRekey = true; - } - if (needRekey) { + if (IsTypeObjectAboutToBeFinalized(entry.object.unsafeGet())) { + e.removeFront(); + } else if (entry.newFunction && IsObjectAboutToBeFinalized(&entry.newFunction)) { + e.removeFront(); + } else if (entry.object.unbarrieredGet() != e.front().object.unbarrieredGet()) { TypeObjectWithNewScriptSet::Lookup lookup(entry.object->clasp(), - proto, + entry.object->proto(), entry.newFunction); e.rekeyFront(lookup, entry); } } } } -#endif #ifdef JSGC_HASH_TABLE_CHECKS @@ -4281,7 +4245,7 @@ TypeCompartment::~TypeCompartment() TypeScript::Sweep(FreeOp *fop, JSScript *script, bool *oom) { JSCompartment *compartment = script->compartment(); - JS_ASSERT(compartment->zone()->isGCSweepingOrCompacting()); + JS_ASSERT(compartment->zone()->isGCSweeping()); unsigned num = NumTypeSets(script); StackTypeSet *typeArray = script->types->typeArray(); @@ -4360,7 +4324,7 @@ TypeZone::~TypeZone() void TypeZone::sweep(FreeOp *fop, bool releaseTypes, bool *oom) { - JS_ASSERT(zone()->isGCSweepingOrCompacting()); + JS_ASSERT(zone()->isGCSweeping()); JSRuntime *rt = fop->runtime(); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index d9688403f955..17dba45ac105 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1571,8 +1571,6 @@ FinalizeGenerator(FreeOp *fop, JSObject *obj) static void MarkGeneratorFrame(JSTracer *trc, JSGenerator *gen) { - gen->obj = MaybeForwarded(gen->obj.get()); - MarkObject(trc, &gen->obj, "Generator Object"); MarkValueRange(trc, HeapValueify(gen->fp->generatorArgsSnapshotBegin()), HeapValueify(gen->fp->generatorArgsSnapshotEnd()), diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index 8c338e22b3ce..c6656f40c872 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -17,7 +17,6 @@ #include "vm/Shape-inl.h" using namespace js; -using namespace js::gc; inline HashNumber ShapeHasher::hash(const Lookup &l) @@ -269,76 +268,6 @@ Shape::finalize(FreeOp *fop) fop->delete_(kids.toHash()); } -#ifdef JSGC_COMPACTING - -void -Shape::fixupDictionaryShapeAfterMovingGC() -{ - if (!listp) - return; - - JS_ASSERT(!IsInsideNursery(reinterpret_cast(listp))); - AllocKind kind = reinterpret_cast(listp)->tenuredGetAllocKind(); - JS_ASSERT(kind == FINALIZE_SHAPE || kind <= FINALIZE_OBJECT_LAST); - if (kind == FINALIZE_SHAPE) { - // listp points to the parent field of the next shape. - Shape *next = reinterpret_cast(uintptr_t(listp) - - offsetof(Shape, parent)); - listp = &gc::MaybeForwarded(next)->parent; - } else { - // listp points to the shape_ field of an object. - JSObject *last = reinterpret_cast(uintptr_t(listp) - - offsetof(JSObject, shape_)); - listp = &gc::MaybeForwarded(last)->shape_; - } -} - -void -Shape::fixupShapeTreeAfterMovingGC() -{ - if (kids.isNull()) - return; - - if (kids.isShape()) { - if (gc::IsForwarded(kids.toShape())) - kids.setShape(gc::Forwarded(kids.toShape())); - return; - } - - JS_ASSERT(kids.isHash()); - KidsHash *kh = kids.toHash(); - for (KidsHash::Enum e(*kh); !e.empty(); e.popFront()) { - Shape *key = e.front(); - if (!IsForwarded(key)) - continue; - - key = Forwarded(key); - BaseShape *base = key->base(); - if (IsForwarded(base)) - base = Forwarded(base); - UnownedBaseShape *unowned = base->unowned(); - if (IsForwarded(unowned)) - unowned = Forwarded(unowned); - StackShape lookup(unowned, - const_cast(key)->propidRef(), - key->slotInfo & Shape::SLOT_MASK, - key->attrs, - key->flags); - e.rekeyFront(lookup, key); - } -} - -void -Shape::fixupAfterMovingGC() -{ - if (inDictionary()) - fixupDictionaryShapeAfterMovingGC(); - else - fixupShapeTreeAfterMovingGC(); -} - -#endif // JSGC_COMPACTING - #ifdef DEBUG void diff --git a/js/src/jspropertytree.h b/js/src/jspropertytree.h index f0c526cdc832..40b509be9ab8 100644 --- a/js/src/jspropertytree.h +++ b/js/src/jspropertytree.h @@ -17,7 +17,7 @@ namespace js { class Shape; struct StackShape; -struct ShapeHasher : public DefaultHasher { +struct ShapeHasher { typedef Shape *Key; typedef StackShape Lookup; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index ae41836dc408..1fdfdc4f0131 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -2834,7 +2834,7 @@ ProxyObject::trace(JSTracer *trc, JSObject *obj) #ifdef DEBUG if (trc->runtime()->gc.isStrictProxyCheckingEnabled() && proxy->is()) { - JSObject *referent = MaybeForwarded(&proxy->private_().toObject()); + JSObject *referent = &proxy->private_().toObject(); if (referent->compartment() != proxy->compartment()) { /* * Assert that this proxy is tracked in the wrapper map. We maintain @@ -2842,7 +2842,6 @@ ProxyObject::trace(JSTracer *trc, JSObject *obj) */ Value key = ObjectValue(*referent); WrapperMap::Ptr p = proxy->compartment()->lookupWrapper(key); - JS_ASSERT(p); JS_ASSERT(*p->value().unsafeGet() == ObjectValue(*proxy)); } } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index d7978e07345b..ff6f3eb1b001 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -3339,7 +3339,7 @@ JSScript::markChildren(JSTracer *trc) } if (sourceObject()) { - JS_ASSERT(MaybeForwarded(sourceObject())->compartment() == compartment()); + JS_ASSERT(sourceObject()->compartment() == compartment()); MarkObject(trc, &sourceObject_, "sourceObject"); } diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 59fc41680da5..1a629cba7dd2 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -88,11 +88,6 @@ js::UncheckedUnwrap(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp) } flags |= Wrapper::wrapperHandler(wrapped)->flags(); wrapped = wrapped->as().private_().toObjectOrNull(); - - // This can be called from DirectProxyHandler::weakmapKeyDelegate() on a - // wrapper whose referent has been moved while it is still unmarked. - if (wrapped) - wrapped = MaybeForwarded(wrapped); } if (flagsp) *flagsp = flags; diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 0c7d2cf34f54..6e0d35d3880b 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -826,10 +826,9 @@ ArrayBufferObject::finalize(FreeOp *fop, JSObject *obj) /* static */ void ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) { - JSRuntime *rt = trc->runtime(); - if (!IS_GC_MARKING_TRACER(trc) && !rt->isHeapMinorCollecting() && !rt->isHeapCompacting() + if (!IS_GC_MARKING_TRACER(trc) && !trc->runtime()->isHeapMinorCollecting() #ifdef JSGC_FJGENERATIONAL - && !rt->isFJMinorCollecting() + && !trc->runtime()->isFJMinorCollecting() #endif ) { @@ -853,16 +852,15 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) if (!viewsHead) return; - ArrayBufferViewObject *tmp = viewsHead; - buffer.setViewList(UpdateObjectIfRelocated(rt, &tmp)); + buffer.setViewList(UpdateObjectIfRelocated(trc->runtime(), &viewsHead)); - if (tmp->nextView() == nullptr) { + if (viewsHead->nextView() == nullptr) { // Single view: mark it, but only if we're actually doing a GC pass // right now. Otherwise, the tracing pass for barrier verification will // fail if we add another view and the pointer becomes weak. MarkObjectUnbarriered(trc, &viewsHead, "arraybuffer.singleview"); buffer.setViewListNoBarrier(viewsHead); - } else if (!rt->isHeapCompacting()) { + } else { // Multiple views: do not mark, but append buffer to list. ArrayBufferVector &gcLiveArrayBuffers = buffer.compartment()->gcLiveArrayBuffers; @@ -880,19 +878,6 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) } else { CrashAtUnhandlableOOM("OOM while updating live array buffers"); } - } else { - // If we're fixing up pointers after compacting then trace everything. - ArrayBufferViewObject *prev = nullptr; - ArrayBufferViewObject *view = viewsHead; - while (view) { - JS_ASSERT(buffer.compartment() == MaybeForwarded(view)->compartment()); - MarkObjectUnbarriered(trc, &view, "arraybuffer.singleview"); - if (prev) - prev->setNextView(view); - else - buffer.setViewListNoBarrier(view); - view = view->nextView(); - } } } diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index d6aee1c85812..3810ba0e5353 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1707,7 +1707,7 @@ Debugger::trace(JSTracer *trc) */ for (FrameMap::Range r = frames.all(); !r.empty(); r.popFront()) { RelocatablePtrObject &frameobj = r.front().value(); - JS_ASSERT(MaybeForwarded(frameobj.get())->getPrivate()); + JS_ASSERT(frameobj->getPrivate()); MarkObject(trc, &frameobj, "live Debugger.Frame"); } @@ -1759,9 +1759,9 @@ Debugger::sweepAll(FreeOp *fop) if (IsObjectAboutToBeFinalized(&global)) { // See infallibility note above. detachAllDebuggersFromGlobal(fop, global, &e); - } else if (global != e.front()) { - e.rekeyFront(global); } + else if (global != e.front()) + e.rekeyFront(global); } } } diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 784e7f944f3b..02d66156b211 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -127,9 +127,6 @@ class DebuggerWeakMap : private WeakMap > if (gc::IsAboutToBeFinalized(&k)) { e.removeFront(); decZoneCount(k->zone()); - } else { - // markKeys() should have done any necessary relocation. - JS_ASSERT(k == e.front().key()); } } Base::assertEntriesNotAboutToBeFinalized(); diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index a6441186694f..348e2a1be9c9 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -937,14 +937,13 @@ struct JSRuntime : public JS::shadow::Runtime, /* Garbage collector state, used by jsgc.c. */ js::gc::GCRuntime gc; - /* Garbage collector state has been sucessfully initialized. */ + /* Garbase collector state has been sucessfully initialized. */ bool gcInitialized; bool isHeapBusy() { return gc.isHeapBusy(); } bool isHeapMajorCollecting() { return gc.isHeapMajorCollecting(); } bool isHeapMinorCollecting() { return gc.isHeapMinorCollecting(); } bool isHeapCollecting() { return gc.isHeapCollecting(); } - bool isHeapCompacting() { return gc.isHeapCompacting(); } bool isFJMinorCollecting() { return gc.isFJMinorCollecting(); } diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 6032961017f8..c882e4f44b4b 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -24,7 +24,6 @@ #include "vm/Stack-inl.h" using namespace js; -using namespace js::gc; using namespace js::types; using mozilla::PodZero; @@ -1785,19 +1784,6 @@ DebugScopes::sweep(JSRuntime *rt) */ liveScopes.remove(&(*debugScope)->scope()); e.removeFront(); - } else { - ScopeIterKey key = e.front().key(); - bool needsUpdate = false; - if (IsForwarded(key.cur())) { - key.updateCur(js::gc::Forwarded(key.cur())); - needsUpdate = true; - } - if (IsForwarded(key.staticScope())) { - key.updateStaticScope(Forwarded(key.staticScope())); - needsUpdate = true; - } - if (needsUpdate) - e.rekeyFront(key); } } @@ -1808,10 +1794,10 @@ DebugScopes::sweep(JSRuntime *rt) * Scopes can be finalized when a debugger-synthesized ScopeObject is * no longer reachable via its DebugScopeObject. */ - if (IsObjectAboutToBeFinalized(&scope)) + if (IsObjectAboutToBeFinalized(&scope)) { e.removeFront(); - else if (scope != e.front().key()) - e.rekeyFront(scope); + continue; + } } } diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 22c9464e86a6..5bed48fb20f5 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -704,9 +704,6 @@ class ScopeIterKey JSObject *enclosingScope() const { return cur_; } JSObject *&enclosingScope() { return cur_; } - void updateCur(JSObject *obj) { cur_ = obj; } - void updateStaticScope(NestedScopeObject *obj) { staticScope_ = obj; } - /* For use as hash policy */ typedef ScopeIterKey Lookup; static HashNumber hash(ScopeIterKey si); diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index 6cd5241bdb5e..7f91e3658529 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -220,15 +220,6 @@ GetShapeAttributes(JSObject *obj, Shape *shape) return shape->attributes(); } -#ifdef JSGC_COMPACTING -inline void -BaseShape::fixupAfterMovingGC() -{ - if (hasTable()) - table().fixupAfterMovingGC(); -} -#endif - } /* namespace js */ #endif /* vm_Shape_inl_h */ diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 173f44d1c501..247a186f0967 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -248,20 +248,6 @@ ShapeTable::search(jsid id, bool adding) return nullptr; } -#ifdef JSGC_COMPACTING -void -ShapeTable::fixupAfterMovingGC() -{ - int log2 = HASH_BITS - hashShift; - uint32_t size = JS_BIT(log2); - for (HashNumber i = 0; i < size; i++) { - Shape *shape = SHAPE_FETCH(&entries[i]); - if (shape && IsForwarded(shape)) - SHAPE_STORE_PRESERVING_COLLISION(&entries[i], Forwarded(shape)); - } -} -#endif - bool ShapeTable::change(int log2Delta, ThreadSafeContext *cx) { @@ -443,11 +429,6 @@ js::ObjectImpl::toDictionaryMode(ThreadSafeContext *cx) { JS_ASSERT(!inDictionaryMode()); -#ifdef JSGC_COMPACTING - // TODO: This crashes if we run a compacting GC here. - js::gc::AutoSuppressGC nogc(zone()->runtimeFromAnyThread()); -#endif - /* We allocate the shapes from cx->compartment(), so make sure it's right. */ JS_ASSERT(cx->isInsideCurrentCompartment(this)); @@ -1548,13 +1529,8 @@ JSCompartment::sweepBaseShapeTable() if (baseShapes.initialized()) { for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) { UnownedBaseShape *base = e.front().unbarrieredGet(); - if (IsBaseShapeAboutToBeFinalized(&base)) { + if (IsBaseShapeAboutToBeFinalized(&base)) e.removeFront(); - } else if (base != e.front()) { - StackBaseShape sbase(base); - ReadBarriered b(base); - e.rekeyFront(&sbase, b); - } } } } @@ -1847,9 +1823,7 @@ JSCompartment::sweepInitialShapeTable() const InitialShapeEntry &entry = e.front(); Shape *shape = entry.shape.unbarrieredGet(); JSObject *proto = entry.proto.raw(); - if (IsShapeAboutToBeFinalized(&shape) || - (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) - { + if (IsShapeAboutToBeFinalized(&shape) || (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) { e.removeFront(); } else { #ifdef DEBUG @@ -1867,47 +1841,6 @@ JSCompartment::sweepInitialShapeTable() } } -#ifdef JSGC_COMPACTING -void -JSCompartment::fixupInitialShapeTable() -{ - if (!initialShapes.initialized()) - return; - - for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) { - InitialShapeEntry entry = e.front(); - bool needRekey = false; - if (IsForwarded(entry.shape.get())) { - entry.shape.set(Forwarded(entry.shape.get())); - needRekey = true; - } - if (entry.proto.isObject() && IsForwarded(entry.proto.toObject())) { - entry.proto = TaggedProto(Forwarded(entry.proto.toObject())); - needRekey = true; - } - JSObject *parent = entry.shape->getObjectParent(); - if (parent) { - parent = MaybeForwarded(parent); - needRekey = true; - } - JSObject *metadata = entry.shape->getObjectMetadata(); - if (metadata) { - metadata = MaybeForwarded(metadata); - needRekey = true; - } - if (needRekey) { - InitialShapeEntry::Lookup relookup(entry.shape->getObjectClass(), - entry.proto, - parent, - metadata, - entry.shape->numFixedSlots(), - entry.shape->getObjectFlags()); - e.rekeyFront(relookup, entry); - } - } -} -#endif // JSGC_COMPACTING - void AutoRooterGetterSetter::Inner::trace(JSTracer *trc) { diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 90f35873ef89..e334c466cfde 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -190,11 +190,6 @@ struct ShapeTable { bool init(ThreadSafeContext *cx, Shape *lastProp); bool change(int log2Delta, ThreadSafeContext *cx); Shape **search(jsid id, bool adding); - -#ifdef JSGC_COMPACTING - /* Update entries whose shapes have been moved */ - void fixupAfterMovingGC(); -#endif }; /* @@ -510,10 +505,6 @@ class BaseShape : public gc::BarrieredCell gc::MarkObject(trc, &metadata, "metadata"); } -#ifdef JSGC_COMPACTING - void fixupAfterMovingGC(); -#endif - private: static void staticAsserts() { JS_STATIC_ASSERT(offsetof(BaseShape, clasp_) == offsetof(js::shadow::BaseShape, clasp_)); @@ -559,7 +550,7 @@ BaseShape::baseUnowned() } /* Entries for the per-compartment baseShapes set of unowned base shapes. */ -struct StackBaseShape : public DefaultHasher +struct StackBaseShape { typedef const StackBaseShape *Lookup; @@ -1037,19 +1028,10 @@ class Shape : public gc::BarrieredCell inline Shape *search(ExclusiveContext *cx, jsid id); inline Shape *searchLinear(jsid id); -#ifdef JSGC_COMPACTING - void fixupAfterMovingGC(); -#endif - /* For JIT usage */ static inline size_t offsetOfBase() { return offsetof(Shape, base_); } private: -#ifdef JSGC_COMPACTING - void fixupDictionaryShapeAfterMovingGC(); - void fixupShapeTreeAfterMovingGC(); -#endif - static void staticAsserts() { JS_STATIC_ASSERT(offsetof(Shape, base_) == offsetof(js::shadow::Shape, base)); JS_STATIC_ASSERT(offsetof(Shape, slotInfo) == offsetof(js::shadow::Shape, slotInfo)); From 3c2b0ecc3fa317acb39fe4cfd4f1b2d584bc468a Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:45 +0100 Subject: [PATCH 023/119] Backed out changeset a6b5fcc90664 (bug 650161) --- js/src/gc/GCRuntime.h | 10 ++++------ js/src/jsgc.cpp | 22 +++++++++------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 6d1d5dc88cdf..b9f7a03caa98 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -424,7 +424,7 @@ class GCRuntime bool isGcNeeded() { return isNeeded; } double computeHeapGrowthFactor(size_t lastBytes); - size_t computeTriggerBytes(double growthFactor, size_t lastBytes); + size_t computeTriggerBytes(double growthFactor, size_t lastBytes, JSGCInvocationKind gckind); JSGCMode gcMode() const { return mode; } void setGCMode(JSGCMode m) { @@ -475,7 +475,8 @@ class GCRuntime gcstats::ZoneGCStats scanZonesBeforeGC(); void budgetIncrementalGC(int64_t *budget); void resetIncrementalGC(const char *reason); - void incrementalCollectSlice(int64_t budget, JS::gcreason::Reason reason); + void incrementalCollectSlice(int64_t budget, JS::gcreason::Reason reason, + JSGCInvocationKind gckind); void pushZealSelectedObjects(); bool beginMarkPhase(JS::gcreason::Reason reason); bool shouldPreserveJITCode(JSCompartment *comp, int64_t currentTime, @@ -495,7 +496,7 @@ class GCRuntime bool shouldReleaseObservedTypes(); void endSweepingZoneGroup(); bool sweepPhase(SliceBudget &sliceBudget); - void endSweepPhase(bool lastGC); + void endSweepPhase(JSGCInvocationKind gckind, bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); void decommitArenasFromAvailableList(Chunk **availableListHeadp); void decommitArenas(); @@ -611,9 +612,6 @@ class GCRuntime /* Whether all compartments are being collected in first GC slice. */ bool isFull; - /* The invocation kind of the current GC, taken from the first slice. */ - JSGCInvocationKind invocationKind; - /* The reason that an interrupt-triggered GC should be called. */ JS::gcreason::Reason triggerReason; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 24c7a6b7b6bc..706ba90584f6 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -4388,7 +4388,7 @@ GCRuntime::sweepPhase(SliceBudget &sliceBudget) } void -GCRuntime::endSweepPhase(bool lastGC) +GCRuntime::endSweepPhase(JSGCInvocationKind gckind, bool lastGC) { gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP); FreeOp fop(rt); @@ -4460,7 +4460,7 @@ GCRuntime::endSweepPhase(bool lastGC) * Expire needs to unlock it for other callers. */ AutoLockGC lock(rt); - expireChunksAndArenas(invocationKind == GC_SHRINK); + expireChunksAndArenas(gckind == GC_SHRINK); } } @@ -4502,8 +4502,7 @@ GCRuntime::endSweepPhase(bool lastGC) schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables, - schedulingState); + zone->threshold.updateAfterGC(zone->usage.gcBytes(), gckind, tunables, schedulingState); if (zone->isCollecting()) { JS_ASSERT(zone->isGCFinished()); zone->setGCState(Zone::NoGC); @@ -4654,7 +4653,7 @@ GCRuntime::resetIncrementalGC(const char *reason) /* Finish sweeping the current zone group, then abort. */ abortSweepAfterCurrentGroup = true; - incrementalCollectSlice(SliceBudget::Unlimited, JS::gcreason::RESET); + incrementalCollectSlice(SliceBudget::Unlimited, JS::gcreason::RESET, GC_NORMAL); { gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD); @@ -4752,7 +4751,8 @@ GCRuntime::pushZealSelectedObjects() void GCRuntime::incrementalCollectSlice(int64_t budget, - JS::gcreason::Reason reason) + JS::gcreason::Reason reason, + JSGCInvocationKind gckind) { JS_ASSERT(rt->currentThreadHasExclusiveAccess()); @@ -4865,10 +4865,10 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (!finished) break; - endSweepPhase(lastGC); + endSweepPhase(gckind, lastGC); if (sweepOnBackgroundThread) - helperState.startBackgroundSweep(invocationKind == GC_SHRINK); + helperState.startBackgroundSweep(gckind == GC_SHRINK); incrementalState = NO_INCREMENTAL; break; @@ -5031,11 +5031,7 @@ GCRuntime::gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind, TraceMajorGCStart(); - /* Set the invocation kind in the first slice. */ - if (incrementalState == NO_INCREMENTAL) - invocationKind = gckind; - - incrementalCollectSlice(budget, reason); + incrementalCollectSlice(budget, reason, gckind); #ifndef JS_MORE_DETERMINISTIC nextFullGCTime = PRMJ_Now() + GC_IDLE_FULL_SPAN; From 3a7c91cbe8bea291637658cab3adf28c61733396 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:49 +0100 Subject: [PATCH 024/119] Backed out changeset a52d8157462f (bug 650161) --- js/src/gc/GCInternals.h | 6 ---- js/src/gc/Nursery.cpp | 22 ++++++++++++--- js/src/jscompartment.cpp | 8 +++--- js/src/jscompartment.h | 5 ++-- js/src/jsgc.cpp | 18 ------------ js/src/jsgc.h | 25 ----------------- js/src/jsinfer.cpp | 58 +++++++++++++++------------------------ js/src/jspubtd.h | 5 ---- js/src/vm/ScopeObject.cpp | 18 ++++++------ js/src/vm/Shape.cpp | 17 ++++-------- 10 files changed, 61 insertions(+), 121 deletions(-) diff --git a/js/src/gc/GCInternals.h b/js/src/gc/GCInternals.h index 3712af872884..368f27e4a06d 100644 --- a/js/src/gc/GCInternals.h +++ b/js/src/gc/GCInternals.h @@ -131,12 +131,6 @@ struct AutoStopVerifyingBarriers }; #endif /* JS_GC_ZEAL */ -#ifdef JSGC_HASH_TABLE_CHECKS -void -CheckHashTablesAfterMovingGC(JSRuntime *rt); -#endif - - } /* namespace gc */ } /* namespace js */ diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index 64faf27c1989..ff927c985429 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -722,6 +722,23 @@ js::Nursery::MinorGCCallback(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) *thingp = trc->nursery->moveToTenured(trc, static_cast(*thingp)); } +static void +CheckHashTablesAfterMovingGC(JSRuntime *rt) +{ +#ifdef JS_GC_ZEAL + if (rt->gcZeal() == ZealCheckHashTablesOnMinorGC) { + /* Check that internal hash tables no longer have any pointers into the nursery. */ + for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { + c->checkNewTypeObjectTableAfterMovingGC(); + c->checkInitialShapesTableAfterMovingGC(); + c->checkWrapperMapAfterMovingGC(); + if (c->debugScopes) + c->debugScopes->checkHashTablesAfterMovingGC(rt); + } + } +#endif +} + #ifdef PROFILE_NURSERY #define TIME_START(name) int64_t timstampStart_##name = PRMJ_Now() #define TIME_END(name) int64_t timstampEnd_##name = PRMJ_Now() @@ -793,10 +810,7 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList TIME_END(markGenericEntries); TIME_START(checkHashTables); -#ifdef JS_GC_ZEAL - if (rt->gcZeal() == ZealCheckHashTablesOnMinorGC) - CheckHashTablesAfterMovingGC(rt); -#endif + CheckHashTablesAfterMovingGC(rt); TIME_END(checkHashTables); TIME_START(markRuntime); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index c1e3b17c6468..6dbe8279dac5 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -210,7 +210,7 @@ class WrapperMapRef : public BufferableRef } }; -#ifdef JSGC_HASH_TABLE_CHECKS +#ifdef JS_GC_ZEAL void JSCompartment::checkWrapperMapAfterMovingGC() { @@ -221,9 +221,9 @@ JSCompartment::checkWrapperMapAfterMovingGC() */ for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { CrossCompartmentKey key = e.front().key(); - CheckGCThingAfterMovingGC(key.debugger); - CheckGCThingAfterMovingGC(key.wrapped); - CheckGCThingAfterMovingGC(static_cast(e.front().value().get().toGCThing())); + JS_ASSERT(!IsInsideNursery(key.debugger)); + JS_ASSERT(!IsInsideNursery(key.wrapped)); + JS_ASSERT(!IsInsideNursery(static_cast(e.front().value().get().toGCThing()))); WrapperMap::Ptr ptr = crossCompartmentWrappers.lookup(key); JS_ASSERT(ptr.found() && &*ptr == &e.front()); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 6c71d0e91033..ffdc97eb6e58 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -254,9 +254,8 @@ struct JSCompartment js::types::TypeObjectWithNewScriptSet newTypeObjects; js::types::TypeObjectWithNewScriptSet lazyTypeObjects; void sweepNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table); -#ifdef JSGC_HASH_TABLE_CHECKS - void checkNewTypeObjectTablesAfterMovingGC(); - void checkNewTypeObjectTableAfterMovingGC(js::types::TypeObjectWithNewScriptSet &table); +#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL) + void checkNewTypeObjectTableAfterMovingGC(); void checkInitialShapesTableAfterMovingGC(); void checkWrapperMapAfterMovingGC(); #endif diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 706ba90584f6..cdb24d24ac4e 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -5829,21 +5829,3 @@ JS::AutoAssertOnGC::VerifyIsSafeToGC(JSRuntime *rt) MOZ_CRASH("[AutoAssertOnGC] possible GC in GC-unsafe region"); } #endif - -#ifdef JSGC_HASH_TABLE_CHECKS -void -js::gc::CheckHashTablesAfterMovingGC(JSRuntime *rt) -{ - /* - * Check that internal hash tables no longer have any pointers to things - * that have been moved. - */ - for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { - c->checkNewTypeObjectTablesAfterMovingGC(); - c->checkInitialShapesTableAfterMovingGC(); - c->checkWrapperMapAfterMovingGC(); - if (c->debugScopes) - c->debugScopes->checkHashTablesAfterMovingGC(rt); - } -} -#endif diff --git a/js/src/jsgc.h b/js/src/jsgc.h index d44ff381f1fc..fdcf5ca8c687 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1279,31 +1279,6 @@ template inline T MaybeForwarded(T t) { return t; } #endif // JSGC_COMPACTING -#ifdef JSGC_HASH_TABLE_CHECKS - -template -inline void -CheckGCThingAfterMovingGC(T *t) -{ - JS_ASSERT_IF(t, !IsInsideNursery(t)); -#ifdef JSGC_COMPACTING - JS_ASSERT_IF(t, !IsForwarded(t)); -#endif -} - -inline void -CheckValueAfterMovingGC(const JS::Value& value) -{ - if (value.isObject()) - return CheckGCThingAfterMovingGC(&value.toObject()); - else if (value.isString()) - return CheckGCThingAfterMovingGC(value.toString()); - else if (value.isSymbol()) - return CheckGCThingAfterMovingGC(value.toSymbol()); -} - -#endif // JSGC_HASH_TABLE_CHECKS - const int ZealPokeValue = 1; const int ZealAllocValue = 2; const int ZealFrameGCValue = 3; diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 790794631c8a..5d2bf9b26130 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3887,6 +3887,28 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSFunction * return type; } +#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL) +void +JSCompartment::checkNewTypeObjectTableAfterMovingGC() +{ + /* + * Assert that the postbarriers have worked and that nothing is left in + * newTypeObjects that points into the nursery, and that the hash table + * entries are discoverable. + */ + for (TypeObjectWithNewScriptSet::Enum e(newTypeObjects); !e.empty(); e.popFront()) { + TypeObjectWithNewScriptEntry entry = e.front(); + JS_ASSERT(!IsInsideNursery(entry.newFunction)); + TaggedProto proto = entry.object->proto(); + JS_ASSERT_IF(proto.isObject(), !IsInsideNursery(proto.toObject())); + TypeObjectWithNewScriptEntry::Lookup + lookup(entry.object->clasp(), proto, entry.newFunction); + TypeObjectWithNewScriptSet::Ptr ptr = newTypeObjects.lookup(lookup); + JS_ASSERT(ptr.found() && &*ptr == &e.front()); + } +} +#endif + TypeObject * ExclusiveContext::getSingletonType(const Class *clasp, TaggedProto proto) { @@ -4198,42 +4220,6 @@ JSCompartment::sweepNewTypeObjectTable(TypeObjectWithNewScriptSet &table) } } -#ifdef JSGC_HASH_TABLE_CHECKS - -void -JSCompartment::checkNewTypeObjectTablesAfterMovingGC() -{ - checkNewTypeObjectTableAfterMovingGC(newTypeObjects); - checkNewTypeObjectTableAfterMovingGC(lazyTypeObjects); -} - -void -JSCompartment::checkNewTypeObjectTableAfterMovingGC(TypeObjectWithNewScriptSet &table) -{ - /* - * Assert that nothing points into the nursery or needs to be relocated, and - * that the hash table entries are discoverable. - */ - if (!table.initialized()) - return; - - for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) { - TypeObjectWithNewScriptEntry entry = e.front(); - CheckGCThingAfterMovingGC(entry.object.get()); - TaggedProto proto = entry.object->proto(); - if (proto.isObject()) - CheckGCThingAfterMovingGC(proto.toObject()); - CheckGCThingAfterMovingGC(entry.newFunction); - - TypeObjectWithNewScriptEntry::Lookup - lookup(entry.object->clasp(), proto, entry.newFunction); - TypeObjectWithNewScriptSet::Ptr ptr = table.lookup(lookup); - JS_ASSERT(ptr.found() && &*ptr == &e.front()); - } -} - -#endif // JSGC_HASH_TABLE_CHECKS - TypeCompartment::~TypeCompartment() { js_delete(arrayTypeTable); diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 86145d0afe7f..576fa4134cf2 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -25,11 +25,6 @@ # define JSGC_TRACK_EXACT_ROOTS #endif -#if (defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)) || \ - (defined(JSGC_COMPACTING) && defined(DEBUG)) -# define JSGC_HASH_TABLE_CHECKS -#endif - namespace JS { class AutoIdVector; diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index c882e4f44b4b..0d3ae2b4f0f5 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1801,7 +1801,7 @@ DebugScopes::sweep(JSRuntime *rt) } } -#ifdef JSGC_HASH_TABLE_CHECKS +#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL) void DebugScopes::checkHashTablesAfterMovingGC(JSRuntime *runtime) { @@ -1811,18 +1811,18 @@ DebugScopes::checkHashTablesAfterMovingGC(JSRuntime *runtime) * pointing into the nursery. */ for (ObjectWeakMap::Range r = proxiedScopes.all(); !r.empty(); r.popFront()) { - CheckGCThingAfterMovingGC(r.front().key().get()); - CheckGCThingAfterMovingGC(r.front().value().get()); + JS_ASSERT(!IsInsideNursery(r.front().key().get())); + JS_ASSERT(!IsInsideNursery(r.front().value().get())); } for (MissingScopeMap::Range r = missingScopes.all(); !r.empty(); r.popFront()) { - CheckGCThingAfterMovingGC(r.front().key().cur()); - CheckGCThingAfterMovingGC(r.front().key().staticScope()); - CheckGCThingAfterMovingGC(r.front().value().get()); + JS_ASSERT(!IsInsideNursery(r.front().key().cur())); + JS_ASSERT(!IsInsideNursery(r.front().key().staticScope())); + JS_ASSERT(!IsInsideNursery(r.front().value().get())); } for (LiveScopeMap::Range r = liveScopes.all(); !r.empty(); r.popFront()) { - CheckGCThingAfterMovingGC(r.front().key()); - CheckGCThingAfterMovingGC(r.front().value().cur_.get()); - CheckGCThingAfterMovingGC(r.front().value().staticScope_.get()); + JS_ASSERT(!IsInsideNursery(r.front().key())); + JS_ASSERT(!IsInsideNursery(r.front().value().cur_.get())); + JS_ASSERT(!IsInsideNursery(r.front().value().staticScope_.get())); } } #endif diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 247a186f0967..e683548c25b6 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1652,10 +1652,7 @@ class InitialShapeSetRef : public BufferableRef } }; -#endif // JSGC_GENERATIONAL - -#ifdef JSGC_HASH_TABLE_CHECKS - +#ifdef JS_GC_ZEAL void JSCompartment::checkInitialShapesTableAfterMovingGC() { @@ -1672,12 +1669,9 @@ JSCompartment::checkInitialShapesTableAfterMovingGC() TaggedProto proto = entry.proto; Shape *shape = entry.shape.get(); - if (proto.isObject()) - CheckGCThingAfterMovingGC(proto.toObject()); - if (shape->getObjectParent()) - CheckGCThingAfterMovingGC(shape->getObjectParent()); - if (shape->getObjectMetadata()) - CheckGCThingAfterMovingGC(shape->getObjectMetadata()); + JS_ASSERT_IF(proto.isObject(), !IsInsideNursery(proto.toObject())); + JS_ASSERT_IF(shape->getObjectParent(), !IsInsideNursery(shape->getObjectParent())); + JS_ASSERT_IF(shape->getObjectMetadata(), !IsInsideNursery(shape->getObjectMetadata())); InitialShapeEntry::Lookup lookup(shape->getObjectClass(), proto, @@ -1689,8 +1683,9 @@ JSCompartment::checkInitialShapesTableAfterMovingGC() JS_ASSERT(ptr.found() && &*ptr == &e.front()); } } +#endif -#endif // JSGC_HASH_TABLE_CHECKS +#endif /* static */ Shape * EmptyShape::getInitialShape(ExclusiveContext *cx, const Class *clasp, TaggedProto proto, From 8c97e6daa45dfae28c3dae2357fba5dca680cce0 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:52:52 +0100 Subject: [PATCH 025/119] Backed out changeset c965ceb8b24a (bug 650161) --- js/src/jsgc.cpp | 19 ------------- js/src/jsgc.h | 73 ------------------------------------------------- 2 files changed, 92 deletions(-) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index cdb24d24ac4e..1ef5dde331a1 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1985,25 +1985,6 @@ ArenaLists::wipeDuringParallelExecution(JSRuntime *rt) } } -#ifdef JSGC_COMPACTING - -static void -ForwardCell(Cell *dest, Cell *src) -{ - // Mark a cell has having been relocated and astore forwarding pointer to - // the new cell. - MOZ_ASSERT(src->tenuredZone() == dest->tenuredZone()); - - // Putting the values this way round is a terrible hack to make - // ObjectImpl::zone() work on forwarded objects. - MOZ_ASSERT(ObjectImpl::offsetOfShape() == 0); - uintptr_t *ptr = reinterpret_cast(src); - ptr[0] = reinterpret_cast(dest); // Forwarding address - ptr[1] = ForwardedCellMagicValue; // Moved! -} - -#endif - void ArenaLists::finalizeNow(FreeOp *fop, AllocKind thingKind) { diff --git a/js/src/jsgc.h b/js/src/jsgc.h index fdcf5ca8c687..c5f5a5571636 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -12,7 +12,6 @@ #include "mozilla/Atomics.h" #include "mozilla/DebugOnly.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/TypeTraits.h" #include "jslock.h" #include "jsobj.h" @@ -1207,78 +1206,6 @@ namespace gc { void MergeCompartments(JSCompartment *source, JSCompartment *target); -#ifdef JSGC_COMPACTING - -/* Functions for checking and updating things that might be moved by compacting GC. */ - -#ifdef JS_PUNBOX64 -const uintptr_t ForwardedCellMagicValue = 0xf1f1f1f1f1f1f1f1; -#else -const uintptr_t ForwardedCellMagicValue = 0xf1f1f1f1; -#endif - -template -inline bool -IsForwarded(T *t) -{ - static_assert(mozilla::IsBaseOf::value, "T must be a subclass of Cell"); - uintptr_t *ptr = reinterpret_cast(t); - return ptr[1] == ForwardedCellMagicValue; -} - -inline bool -IsForwarded(const JS::Value &value) -{ - if (value.isObject()) - return IsForwarded(&value.toObject()); - - if (value.isString()) - return IsForwarded(value.toString()); - - if (value.isSymbol()) - return IsForwarded(value.toSymbol()); - - JS_ASSERT(!value.isGCThing()); - return false; -} - -template -inline T * -Forwarded(T *t) -{ - JS_ASSERT(IsForwarded(t)); - uintptr_t *ptr = reinterpret_cast(t); - return reinterpret_cast(ptr[0]); -} - -inline Value -Forwarded(const JS::Value &value) -{ - if (value.isObject()) - return ObjectValue(*Forwarded(&value.toObject())); - else if (value.isString()) - return StringValue(Forwarded(value.toString())); - else if (value.isSymbol()) - return SymbolValue(Forwarded(value.toSymbol())); - - JS_ASSERT(!value.isGCThing()); - return value; -} - -template -inline T -MaybeForwarded(T t) -{ - return IsForwarded(t) ? Forwarded(t) : t; -} - -#else - -template inline bool IsForwarded(T t) { return false; } -template inline T MaybeForwarded(T t) { return t; } - -#endif // JSGC_COMPACTING - const int ZealPokeValue = 1; const int ZealAllocValue = 2; const int ZealFrameGCValue = 3; From 69034689d981a6254f397a14e8af4fcd34caaf85 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 12:53:15 +0100 Subject: [PATCH 026/119] Backed out changeset 297ca183fff9 (bug 650161) for crashes; CLOSED TREE --- configure.in | 14 -------------- js/src/configure.in | 12 ------------ 2 files changed, 26 deletions(-) diff --git a/configure.in b/configure.in index eb5206638998..7cbc077b5cb4 100644 --- a/configure.in +++ b/configure.in @@ -7148,17 +7148,6 @@ if test -n "$JSGC_GENERATIONAL"; then AC_DEFINE(JSGC_GENERATIONAL) fi -dnl ======================================================== -dnl = Use compacting GC -dnl ======================================================== -MOZ_ARG_ENABLE_BOOL(gccompacting, -[ --enable-gccompacting Compact the JS heap by moving GC things], - JS_GCCOMPACTING=1, - JS_GCCOMPACTING= ) -if test -n "$JS_GCCOMPACTING"; then - AC_DEFINE(JS_GCCOMPACTING) -fi - dnl ======================================================== dnl = Use a smaller chunk size for GC chunks dnl ======================================================== @@ -9120,9 +9109,6 @@ fi if test -z "$JSGC_GENERATIONAL" ; then ac_configure_args="$ac_configure_args --disable-gcgenerational" fi -if test -n "$JS_GCCOMPACTING" ; then - ac_configure_args="$ac_configure_args --enable-gccompacting" -fi if test -n "$JS_GC_SMALL_CHUNK_SIZE" ; then ac_configure_args="$ac_configure_args --enable-small-chunk-size" fi diff --git a/js/src/configure.in b/js/src/configure.in index e8372d8acbee..6f053b7803d1 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -3114,18 +3114,6 @@ if test -n "$JSGC_USE_EXACT_ROOTING"; then AC_DEFINE(JSGC_USE_EXACT_ROOTING) fi -dnl ======================================================== -dnl = Use compacting GC -dnl ======================================================== -dnl Compact the heap by moving GC things when doing a shrinking colletion. -MOZ_ARG_ENABLE_BOOL(gccompacting, -[ --enable-gccompacting Compact the heap by moving GC things], - JSGC_COMPACTING=1, - JSGC_COMPACTING= ) -if test -n "$JSGC_COMPACTING"; then - AC_DEFINE(JSGC_COMPACTING) -fi - dnl ======================================================== dnl = Use a smaller chunk size for GC chunks dnl ======================================================== From a6d33c86fde2107bc5774fc8c05c26a4f7e83da8 Mon Sep 17 00:00:00 2001 From: John Daggett Date: Thu, 14 Aug 2014 21:36:25 +0900 Subject: [PATCH 027/119] Bug 1053114 - test other shorthands affected by variable usage. r=heycam --- layout/style/test/test_value_storage.html | 28 ++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/layout/style/test/test_value_storage.html b/layout/style/test/test_value_storage.html index 9129a52dcd03..46985c8c8d4d 100644 --- a/layout/style/test/test_value_storage.html +++ b/layout/style/test/test_value_storage.html @@ -81,6 +81,9 @@ function xfail_compute(property, value) return false; } +// constructed to map longhands ==> list of containing shorthands +var gPropertyShorthands = {}; + var gElement = document.getElementById("testnode"); var gDeclaration = gElement.style; var gComputedStyle = window.getComputedStyle(gElement, ""); @@ -105,6 +108,17 @@ function test_property(property) is(gDeclaration.cssText, "", "non-empty serialization after removing all properties " + errstr); } + function test_other_shorthands_empty(value, subprop) { + if (!(subprop in gPropertyShorthands)) return; + var shorthands = gPropertyShorthands[subprop]; + for (idx in shorthands) { + var sh = shorthands[idx]; + if (sh.replace("-moz-","") == property.replace("-moz-","")) continue; + is(gDeclaration.getPropertyValue(sh), "", + "setting '" + value + "' on '" + property + "' (for shorthand '" + sh + "')"); + } + } + function test_value(value, resolved_value) { var value_has_variable_reference = resolved_value != null; @@ -134,6 +148,7 @@ function test_property(property) (!info.alias_for || info.type == CSS_TYPE_TRUE_SHORTHAND)) { is(gDeclaration.getPropertyValue(subprop), "", "setting '" + value + "' on '" + property + "' (for '" + subprop + "')"); + test_other_shorthands_empty(value, subprop); } else { isnot(gDeclaration.getPropertyValue(subprop), "", "setting '" + value + "' on '" + property + "' (for '" + subprop + "')"); @@ -273,8 +288,19 @@ function runTest() { // property at a time. ok(SpecialPowers.getBoolPref("layout.css.variables.enabled"), "pref not set #1"); var props = []; - for (var prop in gCSSProperties) + for (var prop in gCSSProperties) { + var info = gCSSProperties[prop]; + if ("subproperties" in info) { + for (var idx in info.subproperties) { + var subprop = info.subproperties[idx]; + if (!(subprop in gPropertyShorthands)) { + gPropertyShorthands[subprop] = []; + } + gPropertyShorthands[subprop].push(prop); + } + } props.push(prop); + } props = props.reverse(); function do_one() { if (props.length == 0) { From c89334b52391ef3f1c69d64e57deeefcddae4141 Mon Sep 17 00:00:00 2001 From: John Daggett Date: Thu, 14 Aug 2014 21:36:25 +0900 Subject: [PATCH 028/119] Bug 1053114 - fix serialization of shorthands with token value subproperties. r=heycam --- layout/style/Declaration.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/layout/style/Declaration.cpp b/layout/style/Declaration.cpp index 62d450552210..610c8ac660ef 100644 --- a/layout/style/Declaration.cpp +++ b/layout/style/Declaration.cpp @@ -199,7 +199,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, const nsCSSValue* tokenStream = nullptr; uint32_t totalCount = 0, importantCount = 0, initialCount = 0, inheritCount = 0, unsetCount = 0, - matchingTokenStreamCount = 0; + matchingTokenStreamCount = 0, nonMatchingTokenStreamCount = 0; CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) { if (*p == eCSSProperty__x_system_font || nsCSSProps::PropHasFlags(*p, CSS_PROPERTY_DIRECTIONAL_SOURCE)) { @@ -224,10 +224,13 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, ++initialCount; } else if (val->GetUnit() == eCSSUnit_Unset) { ++unsetCount; - } else if (val->GetUnit() == eCSSUnit_TokenStream && - val->GetTokenStreamValue()->mShorthandPropertyID == aProperty) { - tokenStream = val; - ++matchingTokenStreamCount; + } else if (val->GetUnit() == eCSSUnit_TokenStream) { + if (val->GetTokenStreamValue()->mShorthandPropertyID == aProperty) { + tokenStream = val; + ++matchingTokenStreamCount; + } else { + ++nonMatchingTokenStreamCount; + } } } if (importantCount != 0 && importantCount != totalCount) { @@ -252,8 +255,9 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, nsCSSValue::eNormalized); return; } - if (initialCount != 0 || inheritCount != 0 || unsetCount != 0) { - // Case (2): partially initial, inherit or unset. + if (initialCount != 0 || inheritCount != 0 || + unsetCount != 0 || nonMatchingTokenStreamCount != 0) { + // Case (2): partially initial, inherit, unset or token stream. return; } if (tokenStream) { From 28007bed9cd60fa424bafbe812f0cec5291dea44 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 13:38:51 +0100 Subject: [PATCH 029/119] Backed out changeset dc66d16f19c8 (bug 1052422) for hazard analysis failures --- js/public/GCAPI.h | 2 +- js/src/builtin/TestingFunctions.cpp | 6 +- js/src/gc/GCRuntime.h | 9 +- js/src/gc/Iteration.cpp | 6 +- js/src/gc/Verifier.cpp | 4 +- js/src/gc/Zone.cpp | 6 +- js/src/jit/BaselineDebugModeOSR.cpp | 2 +- js/src/jsapi-tests/testGCFinalizeCallback.cpp | 4 +- js/src/jsapi-tests/testGCHeapPostBarriers.cpp | 2 +- js/src/jsapi-tests/testWeakMap.cpp | 4 +- js/src/jsapi.cpp | 4 +- js/src/jscntxt.cpp | 4 +- js/src/jscntxt.h | 8 -- js/src/jsfriendapi.cpp | 10 +- js/src/jsgc.cpp | 94 +++++++++++++++---- js/src/jsgc.h | 37 ++++++++ js/src/jsgcinlines.h | 13 +-- js/src/vm/ForkJoin.cpp | 7 +- js/src/vm/Interpreter.cpp | 2 +- js/src/vm/Runtime.cpp | 2 +- 20 files changed, 151 insertions(+), 75 deletions(-) diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h index 8cdcfe99e38e..7d1ef07960fa 100644 --- a/js/public/GCAPI.h +++ b/js/public/GCAPI.h @@ -90,7 +90,7 @@ namespace JS { D(REFRESH_FRAME) \ D(FULL_GC_TIMER) \ D(SHUTDOWN_CC) \ - D(FINISH_LARGE_EVALUATE) + D(FINISH_LARGE_EVALUTE) namespace gcreason { diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 74e979ddb700..b70d744d3d76 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -268,7 +268,7 @@ MinorGC(JSContext *cx, unsigned argc, jsval *vp) if (args.get(0) == BooleanValue(true)) cx->runtime()->gc.storeBuffer.setAboutToOverflow(); - cx->minorGC(gcreason::API); + MinorGC(cx, gcreason::API); #endif args.rval().setUndefined(); return true; @@ -519,7 +519,7 @@ SelectForGC(JSContext *cx, unsigned argc, Value *vp) * to be in the set, so evict the nursery before adding items. */ JSRuntime *rt = cx->runtime(); - rt->gc.evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); for (unsigned i = 0; i < args.length(); i++) { if (args[i].isObject()) { @@ -628,7 +628,7 @@ GCSlice(JSContext *cx, unsigned argc, Value *vp) limit = false; } - cx->runtime()->gc.gcDebugSlice(limit, budget); + GCDebugSlice(cx->runtime(), limit, budget); args.rval().setUndefined(); return true; } diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index b9f7a03caa98..5379ceb4f4d8 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -278,13 +278,10 @@ class GCRuntime void maybePeriodicFullGC(); void minorGC(JS::gcreason::Reason reason); void minorGC(JSContext *cx, JS::gcreason::Reason reason); - void evictNursery(JS::gcreason::Reason reason = JS::gcreason::EVICT_NURSERY) { minorGC(reason); } void gcIfNeeded(JSContext *cx); - void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason); + void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, + JS::gcreason::Reason reason); void gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); - void gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason); - void gcDebugSlice(bool limit, int64_t objCount); - void runDebugGC(); inline void poke(); @@ -468,8 +465,6 @@ class GCRuntime bool initZeal(); void requestInterrupt(JS::gcreason::Reason reason); - void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, - JS::gcreason::Reason reason); bool gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind, JS::gcreason::Reason reason); gcstats::ZoneGCStats scanZonesBeforeGC(); diff --git a/js/src/gc/Iteration.cpp b/js/src/gc/Iteration.cpp index 0c2e31fce44e..c6e799580e96 100644 --- a/js/src/gc/Iteration.cpp +++ b/js/src/gc/Iteration.cpp @@ -23,7 +23,7 @@ js::TraceRuntime(JSTracer *trc) JS_ASSERT(!IS_GC_MARKING_TRACER(trc)); JSRuntime *rt = trc->runtime(); - rt->gc.evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(rt, WithAtoms); rt->gc.markRuntime(trc); } @@ -93,7 +93,7 @@ void js::IterateScripts(JSRuntime *rt, JSCompartment *compartment, void *data, IterateScriptCallback scriptCallback) { - rt->gc.evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(rt, SkipAtoms); if (compartment) { @@ -113,7 +113,7 @@ js::IterateScripts(JSRuntime *rt, JSCompartment *compartment, void js::IterateGrayObjects(Zone *zone, GCThingCallback cellCallback, void *data) { - zone->runtimeFromMainThread()->gc.evictNursery(); + MinorGC(zone->runtimeFromMainThread(), JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(zone->runtimeFromMainThread(), SkipAtoms); for (size_t finalizeKind = 0; finalizeKind <= FINALIZE_OBJECT_LAST; finalizeKind++) { diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index 9bbe39a25f4a..5499a53b6f7f 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -182,7 +182,7 @@ gc::GCRuntime::startVerifyPreBarriers() if (verifyPostData) return; - evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(rt, WithAtoms); @@ -410,7 +410,7 @@ gc::GCRuntime::startVerifyPostBarriers() return; } - evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); number++; diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 0bf676576bd6..ad2613456399 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -97,10 +97,8 @@ Zone::setGCMaxMallocBytes(size_t value) void Zone::onTooMuchMalloc() { - if (!gcMallocGCTriggered) { - GCRuntime &gc = runtimeFromAnyThread()->gc; - gcMallocGCTriggered = gc.triggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC); - } + if (!gcMallocGCTriggered) + gcMallocGCTriggered = TriggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC); } void diff --git a/js/src/jit/BaselineDebugModeOSR.cpp b/js/src/jit/BaselineDebugModeOSR.cpp index 6472f8f1bf6e..c118ce94ef80 100644 --- a/js/src/jit/BaselineDebugModeOSR.cpp +++ b/js/src/jit/BaselineDebugModeOSR.cpp @@ -658,7 +658,7 @@ jit::RecompileOnStackBaselineScriptsForDebugMode(JSContext *cx, JSCompartment *c #ifdef JSGC_GENERATIONAL // Scripts can entrain nursery things. See note in js::ReleaseAllJITCode. if (!entries.empty()) - cx->runtime()->gc.evictNursery(); + MinorGC(cx->runtime(), JS::gcreason::EVICT_NURSERY); #endif // When the profiler is enabled, we need to suppress sampling from here until diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp index 4c38c45407f6..fc4dc708464b 100644 --- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp +++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp @@ -88,12 +88,12 @@ BEGIN_TEST(testGCFinalizeCallback) FinalizeCalls = 0; JS_SetGCZeal(cx, 9, 1000000); JS::PrepareForFullGC(rt); - rt->gc.gcDebugSlice(true, 1); + js::GCDebugSlice(rt, true, 1); CHECK(rt->gc.state() == js::gc::MARK); CHECK(rt->gc.isFullGc()); JS::RootedObject global4(cx, createGlobal()); - rt->gc.gcDebugSlice(true, 1); + js::GCDebugSlice(rt, true, 1); CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL); CHECK(!rt->gc.isFullGc()); CHECK(checkMultipleGroups()); diff --git a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp index 2fc66907921c..6aa4dced04a1 100644 --- a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp +++ b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp @@ -51,7 +51,7 @@ TestHeapPostBarriers(T initialObj) uintptr_t initialObjAsInt = uintptr_t(initialObj); /* Perform minor GC and check heap wrapper is udated with new pointer. */ - cx->minorGC(JS::gcreason::API); + js::MinorGC(cx, JS::gcreason::API); CHECK(uintptr_t(heapData->get()) != initialObjAsInt); CHECK(!js::gc::IsInsideNursery(heapData->get())); diff --git a/js/src/jsapi-tests/testWeakMap.cpp b/js/src/jsapi-tests/testWeakMap.cpp index 8c3db691d2fa..7bfacf118017 100644 --- a/js/src/jsapi-tests/testWeakMap.cpp +++ b/js/src/jsapi-tests/testWeakMap.cpp @@ -87,7 +87,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) * zone to finish marking before the delegate zone. */ CHECK(newCCW(map, delegate)); - rt->gc.gcDebugSlice(true, 1000000); + GCDebugSlice(rt, true, 1000000); #ifdef DEBUG CHECK(map->zone()->lastZoneGroupIndex() < delegate->zone()->lastZoneGroupIndex()); #endif @@ -100,7 +100,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) /* Check the delegate keeps the entry alive even if the key is not reachable. */ key = nullptr; CHECK(newCCW(map, delegate)); - rt->gc.gcDebugSlice(true, 100000); + GCDebugSlice(rt, true, 100000); CHECK(checkSize(map, 1)); /* diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 89bfa8e876a7..c2d15765045b 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1873,7 +1873,7 @@ JS_GC(JSRuntime *rt) { AssertHeapIsIdle(rt); JS::PrepareForFullGC(rt); - rt->gc.gc(GC_NORMAL, JS::gcreason::API); + GC(rt, GC_NORMAL, JS::gcreason::API); } JS_PUBLIC_API(void) @@ -4807,7 +4807,7 @@ Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsA if (script->length() > LARGE_SCRIPT_LENGTH) { script = nullptr; PrepareZoneForGC(cx->zone()); - cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUATE); + GC(cx->runtime(), GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUTE); } return result; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e6aa3c0c2cb0..f5effb931662 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -251,7 +251,7 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode) if (mode == DCM_FORCE_GC) { JS_ASSERT(!rt->isHeapBusy()); JS::PrepareForFullGC(rt); - rt->gc.gc(GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); + GC(rt, GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); } js_delete_poison(cx); } @@ -986,7 +986,7 @@ js::InvokeInterruptCallback(JSContext *cx) // callbacks. rt->resetJitStackLimit(); - cx->gcIfNeeded(); + js::gc::GCIfNeeded(cx); rt->interruptPar = false; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 734ee731f1ec..7f7a8add373d 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -548,14 +548,6 @@ struct JSContext : public js::ExclusiveContext, } #endif - void minorGC(JS::gcreason::Reason reason) { - runtime_->gc.minorGC(this, reason); - } - - void gcIfNeeded() { - runtime_->gc.gcIfNeeded(this); - } - private: /* Innermost-executing generator or null if no generator are executing. */ JSGenerator *innermostGenerator_; diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 520ba1b18cf1..d46d33db6c2b 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -197,25 +197,25 @@ JS::SkipZoneForGC(Zone *zone) JS_FRIEND_API(void) JS::GCForReason(JSRuntime *rt, gcreason::Reason reason) { - rt->gc.gc(GC_NORMAL, reason); + GC(rt, GC_NORMAL, reason); } JS_FRIEND_API(void) JS::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason) { - rt->gc.gc(GC_SHRINK, reason); + GC(rt, GC_SHRINK, reason); } JS_FRIEND_API(void) JS::IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis) { - rt->gc.gcSlice(GC_NORMAL, reason, millis); + GCSlice(rt, GC_NORMAL, reason, millis); } JS_FRIEND_API(void) JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason) { - rt->gc.gcFinalSlice(GC_NORMAL, reason); + GCFinalSlice(rt, GC_NORMAL, reason); } JS_FRIEND_API(JSPrincipals *) @@ -810,7 +810,7 @@ js::DumpHeapComplete(JSRuntime *rt, FILE *fp, js::DumpHeapNurseryBehaviour nurse { #ifdef JSGC_GENERATIONAL if (nurseryBehaviour == js::CollectNurseryBeforeDump) - rt->gc.evictNursery(JS::gcreason::API); + MinorGC(rt, JS::gcreason::API); #endif DumpHeapTracer dtrc(fp, rt, DumpHeapVisitRoot, TraceWeakMapKeysValues); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 1ef5dde331a1..07d3a4ffbc3c 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -939,7 +939,7 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind) if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) { AutoUnlockGC unlock(rt); - rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + TriggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); } return aheader; @@ -1186,7 +1186,7 @@ GCRuntime::setZeal(uint8_t zeal, uint32_t frequency) #ifdef JSGC_GENERATIONAL if (zealMode == ZealGenerationalGCValue) { - evictNursery(JS::gcreason::DEBUG_GC); + minorGC(JS::gcreason::DEBUG_GC); nursery.leaveZealMode(); } @@ -2169,7 +2169,7 @@ RunLastDitchGC(JSContext *cx, JS::Zone *zone, AllocKind thingKind) /* The last ditch GC preserves all atoms. */ AutoKeepAtoms keepAtoms(cx->perThreadData); - rt->gc.gc(GC_NORMAL, JS::gcreason::LAST_DITCH); + GC(rt, GC_NORMAL, JS::gcreason::LAST_DITCH); /* * The JSGC_END callback can legitimately allocate new GC @@ -2271,6 +2271,12 @@ ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); template void * ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); +JSGCTraceKind +js_GetGCThingTraceKind(void *thing) +{ + return GetGCThingTraceKind(thing); +} + /* static */ int64_t SliceBudget::TimeBudget(int64_t millis) { @@ -2328,6 +2334,12 @@ GCRuntime::requestInterrupt(JS::gcreason::Reason reason) rt->requestInterrupt(JSRuntime::RequestInterruptMainThread); } +bool +js::TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason) +{ + return rt->gc.triggerGC(reason); +} + bool GCRuntime::triggerGC(JS::gcreason::Reason reason) { @@ -2357,6 +2369,12 @@ GCRuntime::triggerGC(JS::gcreason::Reason reason) return true; } +bool +js::TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason) +{ + return zone->runtimeFromAnyThread()->gc.triggerZoneGC(zone, reason); +} + bool GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) { @@ -2383,14 +2401,14 @@ GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) #ifdef JS_GC_ZEAL if (zealMode == ZealAllocValue) { - triggerGC(reason); + TriggerGC(rt, reason); return true; } #endif if (rt->isAtomsZone(zone)) { /* We can't do a zone GC of the atoms compartment. */ - triggerGC(reason); + TriggerGC(rt, reason); return true; } @@ -2407,13 +2425,13 @@ GCRuntime::maybeGC(Zone *zone) #ifdef JS_GC_ZEAL if (zealMode == ZealAllocValue || zealMode == ZealPokeValue) { JS::PrepareForFullGC(rt); - gc(GC_NORMAL, JS::gcreason::MAYBEGC); + GC(rt, GC_NORMAL, JS::gcreason::MAYBEGC); return true; } #endif if (isNeeded) { - gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); + GCSlice(rt, GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -2424,7 +2442,7 @@ GCRuntime::maybeGC(Zone *zone) !isBackgroundSweeping()) { PrepareZoneForGC(zone); - gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); + GCSlice(rt, GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -2450,7 +2468,7 @@ GCRuntime::maybePeriodicFullGC() numArenasFreeCommitted > decommitThreshold) { JS::PrepareForFullGC(rt); - gcSlice(GC_SHRINK, JS::gcreason::MAYBEGC); + GCSlice(rt, GC_SHRINK, JS::gcreason::MAYBEGC); } else { nextFullGCTime = now + GC_IDLE_FULL_SPAN; } @@ -4749,7 +4767,7 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (reason == JS::gcreason::DEBUG_GC && budget != SliceBudget::Unlimited) { /* * Do the incremental collection type specified by zeal mode if the - * collection was triggered by runDebugGC() and incremental GC has not + * collection was triggered by RunDebugGC() and incremental GC has not * been cancelled by resetIncrementalGC(). */ zeal = zealMode; @@ -5182,9 +5200,15 @@ GCRuntime::collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, } void -GCRuntime::gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason) +js::GC(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - collect(false, SliceBudget::Unlimited, gckind, reason); + rt->gc.collect(false, SliceBudget::Unlimited, gckind, reason); +} + +void +js::GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) +{ + rt->gc.gcSlice(gckind, reason, millis); } void @@ -5202,9 +5226,9 @@ GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64 } void -GCRuntime::gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason) +js::GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - collect(true, SliceBudget::Unlimited, gckind, reason); + rt->gc.collect(true, SliceBudget::Unlimited, gckind, reason); } void @@ -5247,7 +5271,7 @@ ZonesSelected(JSRuntime *rt) } void -GCRuntime::gcDebugSlice(bool limit, int64_t objCount) +js::GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount) { int64_t budget = limit ? SliceBudget::WorkBudget(objCount) : SliceBudget::Unlimited; if (!ZonesSelected(rt)) { @@ -5256,7 +5280,7 @@ GCRuntime::gcDebugSlice(bool limit, int64_t objCount) else JS::PrepareForFullGC(rt); } - collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); + rt->gc.collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); } /* Schedule a full GC unless a zone will already be collected. */ @@ -5286,6 +5310,12 @@ GCRuntime::shrinkBuffers() expireChunksAndArenas(true); } +void +js::MinorGC(JSRuntime *rt, JS::gcreason::Reason reason) +{ + rt->gc.minorGC(reason); +} + void GCRuntime::minorGC(JS::gcreason::Reason reason) { @@ -5298,10 +5328,16 @@ GCRuntime::minorGC(JS::gcreason::Reason reason) } void -GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason) +js::MinorGC(JSContext *cx, JS::gcreason::Reason reason) { // Alternate to the runtime-taking form above which allows marking type // objects as needing pretenuring. + cx->runtime()->gc.minorGC(cx, reason); +} + +void +GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason) +{ #ifdef JSGC_GENERATIONAL TraceLogger *logger = TraceLoggerForMainThread(rt); AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC); @@ -5341,6 +5377,12 @@ GCRuntime::enableGenerationalGC() #endif } +void +js::gc::GCIfNeeded(JSContext *cx) +{ + cx->runtime()->gc.gcIfNeeded(cx); +} + void GCRuntime::gcIfNeeded(JSContext *cx) { @@ -5357,6 +5399,12 @@ GCRuntime::gcIfNeeded(JSContext *cx) gcSlice(GC_NORMAL, rt->gc.triggerReason, 0); } +void +js::gc::FinishBackgroundFinalize(JSRuntime *rt) +{ + rt->gc.waitBackgroundSweepEnd(); +} + AutoFinishGC::AutoFinishGC(JSRuntime *rt) { if (JS::IsIncrementalGCInProgress(rt)) { @@ -5364,7 +5412,7 @@ AutoFinishGC::AutoFinishGC(JSRuntime *rt) JS::FinishIncrementalGC(rt, JS::gcreason::API); } - rt->gc.waitBackgroundSweepEnd(); + gc::FinishBackgroundFinalize(rt); } AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt, ZoneSelector selector) @@ -5472,6 +5520,12 @@ gc::MergeCompartments(JSCompartment *source, JSCompartment *target) target->zone()->types.typeLifoAlloc.transferFrom(&source->zone()->types.typeLifoAlloc); } +void +gc::RunDebugGC(JSContext *cx) +{ + cx->runtime()->gc.runDebugGC(); +} + void GCRuntime::runDebugGC() { @@ -5482,7 +5536,7 @@ GCRuntime::runDebugGC() return; if (type == js::gc::ZealGenerationalGCValue) - return minorGC(JS::gcreason::DEBUG_GC); + return MinorGC(rt, JS::gcreason::DEBUG_GC); PrepareForDebugGC(rt); @@ -5580,7 +5634,7 @@ js::ReleaseAllJITCode(FreeOp *fop) * Scripts can entrain nursery things, inserting references to the script * into the store buffer. Clear the store buffer before discarding scripts. */ - fop->runtime()->gc.evictNursery(); + MinorGC(fop->runtime(), JS::gcreason::EVICT_NURSERY); #endif for (ZonesIter zone(fop->runtime(), SkipAtoms); !zone.done(); zone.next()) { diff --git a/js/src/jsgc.h b/js/src/jsgc.h index c5f5a5571636..8cdd447a3e92 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -963,6 +963,14 @@ MarkCompartmentActive(js::InterpreterFrame *fp); extern void TraceRuntime(JSTracer *trc); +/* Must be called with GC lock taken. */ +extern bool +TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason); + +/* Must be called with GC lock taken. */ +extern bool +TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason); + extern void ReleaseAllJITCode(FreeOp *op); @@ -977,9 +985,27 @@ typedef enum JSGCInvocationKind { GC_SHRINK = 1 } JSGCInvocationKind; +extern void +GC(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason); + +extern void +GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); + +extern void +GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason); + +extern void +GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount); + extern void PrepareForDebugGC(JSRuntime *rt); +extern void +MinorGC(JSRuntime *rt, JS::gcreason::Reason reason); + +extern void +MinorGC(JSContext *cx, JS::gcreason::Reason reason); + /* Functions for managing cross compartment gray pointers. */ extern void @@ -1199,6 +1225,17 @@ NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals, namespace gc { +extern void +GCIfNeeded(JSContext *cx); + +/* Tries to run a GC no matter what (used for GC zeal). */ +void +RunDebugGC(JSContext *cx); + +/* Wait for the background thread to finish sweeping if it is running. */ +void +FinishBackgroundFinalize(JSRuntime *rt); + /* * Merge all contents of source into target. This can only be used if source is * the only compartment in its zone. diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 384b2a0af4a2..8e764d08d0d6 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -368,13 +368,14 @@ class ZoneCellIter : public ZoneCellIterImpl if (IsBackgroundFinalized(kind) && zone->allocator.arenas.needBackgroundFinalizeWait(kind)) { - zone->runtimeFromMainThread()->gc.waitBackgroundSweepEnd(); + gc::FinishBackgroundFinalize(zone->runtimeFromMainThread()); } #ifdef JSGC_GENERATIONAL /* Evict the nursery before iterating so we can see all things. */ JSRuntime *rt = zone->runtimeFromMainThread(); - rt->gc.evictNursery(); + if (!rt->gc.nursery.isEmpty()) + MinorGC(rt, JS::gcreason::EVICT_NURSERY); #endif if (lists->isSynchronizedFreeList(kind)) { @@ -472,7 +473,7 @@ TryNewNurseryObject(JSContext *cx, size_t thingSize, size_t nDynamicSlots) if (obj) return obj; if (allowGC && !rt->mainThread.suppressGC) { - cx->minorGC(JS::gcreason::OUT_OF_NURSERY); + MinorGC(cx, JS::gcreason::OUT_OF_NURSERY); /* Exceeding gcMaxBytes while tenuring can disable the Nursery. */ if (nursery.isEnabled()) { @@ -546,13 +547,13 @@ CheckAllocatorState(ThreadSafeContext *cx, AllocKind kind) if (allowGC) { #ifdef JS_GC_ZEAL if (rt->gc.needZealousGC()) - rt->gc.runDebugGC(); + js::gc::RunDebugGC(ncx); #endif if (rt->interrupt) { // Invoking the interrupt callback can fail and we can't usefully // handle that here. Just check in case we need to collect instead. - ncx->gcIfNeeded(); + js::gc::GCIfNeeded(ncx); } } @@ -681,7 +682,7 @@ AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap) JSObject *obj = TryNewNurseryObject(cx, thingSize, 0); if (!obj && allowGC) { - cx->minorGC(JS::gcreason::OUT_OF_NURSERY); + MinorGC(cx, JS::gcreason::OUT_OF_NURSERY); return nullptr; } return obj; diff --git a/js/src/vm/ForkJoin.cpp b/js/src/vm/ForkJoin.cpp index fe89743475b4..a7f9952b6b1f 100644 --- a/js/src/vm/ForkJoin.cpp +++ b/js/src/vm/ForkJoin.cpp @@ -355,7 +355,7 @@ ForkJoinActivation::ForkJoinActivation(JSContext *cx) JS::FinishIncrementalGC(cx->runtime(), JS::gcreason::API); } - cx->runtime()->gc.evictNursery(); + MinorGC(cx->runtime(), JS::gcreason::API); cx->runtime()->gc.waitBackgroundSweepEnd(); @@ -1492,11 +1492,10 @@ ForkJoinShared::transferArenasToCompartmentAndProcessGCRequests() if (gcRequested_) { Spew(SpewGC, "Triggering garbage collection in SpiderMonkey heap"); - gc::GCRuntime &gc = cx_->runtime()->gc; if (!gcZone_) - gc.triggerGC(gcReason_); + TriggerGC(cx_->runtime(), gcReason_); else - gc.triggerZoneGC(gcZone_, gcReason_); + TriggerZoneGC(gcZone_, gcReason_); gcRequested_ = false; gcZone_ = nullptr; } diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index e5fc625344b1..9967804c1dea 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -415,7 +415,7 @@ struct AutoGCIfNeeded { JSContext *cx_; explicit AutoGCIfNeeded(JSContext *cx) : cx_(cx) {} - ~AutoGCIfNeeded() { cx_->gcIfNeeded(); } + ~AutoGCIfNeeded() { js::gc::GCIfNeeded(cx_); } }; /* diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 994cdfd3f9d1..9c1729d7c655 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -376,7 +376,7 @@ JSRuntime::~JSRuntime() profilingScripts = false; JS::PrepareForFullGC(this); - gc.gc(GC_NORMAL, JS::gcreason::DESTROY_RUNTIME); + GC(this, GC_NORMAL, JS::gcreason::DESTROY_RUNTIME); } /* From b159f72e251ca11ba351a6dddfc22f73f2e98bb0 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Thu, 14 Aug 2014 14:43:30 +0200 Subject: [PATCH 030/119] Bug 1053135 - Disable the usage of -freorder-blocks when using clang r=glandium In future version of clang, unsupported optimization flags are going to trigger a warning. They used to be silently ignored or triggering an error. --- configure.in | 10 ++++++++-- js/src/configure.in | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/configure.in b/configure.in index 7cbc077b5cb4..3364a6600d4e 100644 --- a/configure.in +++ b/configure.in @@ -1992,7 +1992,10 @@ ia64*-hpux*) TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"' MOZ_GFX_OPTIMIZE_MOBILE=1 - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions" + MOZ_OPTIMIZE_FLAGS="-Os -fno-reorder-functions" + if test -z "$CLANG_CC"; then + MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS" + fi ;; *-*linux*) @@ -2009,7 +2012,10 @@ ia64*-hpux*) MOZ_OPTIMIZE_SIZE_TWEAK="-finline-limit=50" esac MOZ_PGO_OPTIMIZE_FLAGS="-O3" - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK" + MOZ_OPTIMIZE_FLAGS="-Os $MOZ_OPTIMIZE_SIZE_TWEAK" + if test -z "$CLANG_CC"; then + MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS" + fi fi TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"' diff --git a/js/src/configure.in b/js/src/configure.in index 6f053b7803d1..9399ec1836ae 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -1550,7 +1550,10 @@ ia64*-hpux*) TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"' MOZ_GFX_OPTIMIZE_MOBILE=1 - MOZ_OPTIMIZE_FLAGS="-O3 -freorder-blocks -fno-reorder-functions" + MOZ_OPTIMIZE_FLAGS="-O3 -fno-reorder-functions" + if test -z "$CLANG_CC"; then + MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS" + fi # The Maemo builders don't know about this flag MOZ_ARM_VFP_FLAGS="-mfpu=vfp" ;; @@ -1569,7 +1572,10 @@ ia64*-hpux*) MOZ_OPTIMIZE_SIZE_TWEAK="-finline-limit=50" esac MOZ_PGO_OPTIMIZE_FLAGS="-O3" - MOZ_OPTIMIZE_FLAGS="-O3 -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK" + MOZ_OPTIMIZE_FLAGS="-O3 $MOZ_OPTIMIZE_SIZE_TWEAK" + if test -z "$CLANG_CC"; then + MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS" + fi fi TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"' From 68a45ecbf7c2b633d3dcd5cb1dd235de9dfb4849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20WENG?= Date: Thu, 14 Aug 2014 15:11:43 +0200 Subject: [PATCH 031/119] Bug 998485 - IonMonkey: Remove analyzeEdge* functions. r=nbp --- js/src/jit/EdgeCaseAnalysis.cpp | 44 ------- js/src/jit/EdgeCaseAnalysis.h | 31 ----- js/src/jit/Ion.cpp | 13 -- js/src/jit/MIR.cpp | 206 -------------------------------- js/src/jit/MIR.h | 11 -- js/src/moz.build | 1 - 6 files changed, 306 deletions(-) delete mode 100644 js/src/jit/EdgeCaseAnalysis.cpp delete mode 100644 js/src/jit/EdgeCaseAnalysis.h diff --git a/js/src/jit/EdgeCaseAnalysis.cpp b/js/src/jit/EdgeCaseAnalysis.cpp deleted file mode 100644 index 30a18249639d..000000000000 --- a/js/src/jit/EdgeCaseAnalysis.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "jit/EdgeCaseAnalysis.h" - -#include "jit/MIR.h" -#include "jit/MIRGraph.h" - -using namespace js; -using namespace js::jit; - -EdgeCaseAnalysis::EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph) - : mir(mir), graph(graph) -{ -} - -bool -EdgeCaseAnalysis::analyzeLate() -{ - // Renumber definitions for NeedNegativeZeroCheck under analyzeEdgeCasesBackward. - uint32_t nextId = 0; - - for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) { - if (mir->shouldCancel("Analyze Late (first loop)")) - return false; - for (MDefinitionIterator iter(*block); iter; iter++) { - iter->setId(nextId++); - iter->analyzeEdgeCasesForward(); - } - block->lastIns()->setId(nextId++); - } - - for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) { - if (mir->shouldCancel("Analyze Late (second loop)")) - return false; - for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++) - riter->analyzeEdgeCasesBackward(); - } - - return true; -} diff --git a/js/src/jit/EdgeCaseAnalysis.h b/js/src/jit/EdgeCaseAnalysis.h deleted file mode 100644 index 3e38e7483cc7..000000000000 --- a/js/src/jit/EdgeCaseAnalysis.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef jit_EdgeCaseAnalysis_h -#define jit_EdgeCaseAnalysis_h - -#include "jit/MIRGenerator.h" - -namespace js { -namespace jit { - -class MIRGraph; - -class EdgeCaseAnalysis -{ - MIRGenerator *mir; - MIRGraph &graph; - - public: - EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph); - bool analyzeLate(); -}; - - -} // namespace jit -} // namespace js - -#endif /* jit_EdgeCaseAnalysis_h */ diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index a5d8c44f1849..45e011046e24 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -21,7 +21,6 @@ #include "jit/BaselineInspector.h" #include "jit/BaselineJIT.h" #include "jit/CodeGenerator.h" -#include "jit/EdgeCaseAnalysis.h" #include "jit/EffectiveAddressAnalysis.h" #include "jit/IonAnalysis.h" #include "jit/IonBuilder.h" @@ -1580,18 +1579,6 @@ OptimizeMIR(MIRGenerator *mir) // Passes after this point must not move instructions; these analyses // depend on knowing the final order in which instructions will execute. - if (mir->optimizationInfo().edgeCaseAnalysisEnabled()) { - AutoTraceLog log(logger, TraceLogger::EdgeCaseAnalysis); - EdgeCaseAnalysis edgeCaseAnalysis(mir, graph); - if (!edgeCaseAnalysis.analyzeLate()) - return false; - IonSpewPass("Edge Case Analysis (Late)"); - AssertGraphCoherency(graph); - - if (mir->shouldCancel("Edge Case Analysis (Late)")) - return false; - } - if (mir->optimizationInfo().eliminateRedundantChecksEnabled()) { AutoTraceLog log(logger, TraceLogger::EliminateRedundantChecks); // Note: check elimination has to run after all other passes that move diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 39874ca40540..f6339a364830 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -222,16 +222,6 @@ MDefinition::foldsTo(TempAllocator &alloc) return this; } -void -MDefinition::analyzeEdgeCasesForward() -{ -} - -void -MDefinition::analyzeEdgeCasesBackward() -{ -} - static bool MaybeEmulatesUndefined(MDefinition *op) { @@ -1404,109 +1394,6 @@ MUrsh::infer(BaselineInspector *inspector, jsbytecode *pc) setResultType(MIRType_Int32); } -static inline bool -NeedNegativeZeroCheck(MDefinition *def) -{ - // Test if all uses have the same semantics for -0 and 0 - for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) { - if (use->consumer()->isResumePoint()) - continue; - - MDefinition *use_def = use->consumer()->toDefinition(); - switch (use_def->op()) { - case MDefinition::Op_Add: { - // If add is truncating -0 and 0 are observed as the same. - if (use_def->toAdd()->isTruncated()) - break; - - // x + y gives -0, when both x and y are -0 - - // Figure out the order in which the addition's operands will - // execute. EdgeCaseAnalysis::analyzeLate has renumbered the MIR - // definitions for us so that this just requires comparing ids. - MDefinition *first = use_def->toAdd()->getOperand(0); - MDefinition *second = use_def->toAdd()->getOperand(1); - if (first->id() > second->id()) { - MDefinition *temp = first; - first = second; - second = temp; - } - - if (def == first) { - // Negative zero checks can be removed on the first executed - // operand only if it is guaranteed the second executed operand - // will produce a value other than -0. While the second is - // typed as an int32, a bailout taken between execution of the - // operands may change that type and cause a -0 to flow to the - // second. - // - // There is no way to test whether there are any bailouts - // between execution of the operands, so remove negative - // zero checks from the first only if the second's type is - // independent from type changes that may occur after bailing. - switch (second->op()) { - case MDefinition::Op_Constant: - case MDefinition::Op_BitAnd: - case MDefinition::Op_BitOr: - case MDefinition::Op_BitXor: - case MDefinition::Op_BitNot: - case MDefinition::Op_Lsh: - case MDefinition::Op_Rsh: - break; - default: - return true; - } - } - - // The negative zero check can always be removed on the second - // executed operand; by the time this executes the first will have - // been evaluated as int32 and the addition's result cannot be -0. - break; - } - case MDefinition::Op_Sub: - // If sub is truncating -0 and 0 are observed as the same - if (use_def->toSub()->isTruncated()) - break; - /* Fall through... */ - case MDefinition::Op_StoreElement: - case MDefinition::Op_StoreElementHole: - case MDefinition::Op_LoadElement: - case MDefinition::Op_LoadElementHole: - case MDefinition::Op_LoadTypedArrayElement: - case MDefinition::Op_LoadTypedArrayElementHole: - case MDefinition::Op_CharCodeAt: - case MDefinition::Op_Mod: - // Only allowed to remove check when definition is the second operand - if (use_def->getOperand(0) == def) - return true; - for (size_t i = 2, e = use_def->numOperands(); i < e; i++) { - if (use_def->getOperand(i) == def) - return true; - } - break; - case MDefinition::Op_BoundsCheck: - // Only allowed to remove check when definition is the first operand - if (use_def->toBoundsCheck()->getOperand(1) == def) - return true; - break; - case MDefinition::Op_ToString: - case MDefinition::Op_FromCharCode: - case MDefinition::Op_TableSwitch: - case MDefinition::Op_Compare: - case MDefinition::Op_BitAnd: - case MDefinition::Op_BitOr: - case MDefinition::Op_BitXor: - case MDefinition::Op_Abs: - case MDefinition::Op_TruncateToInt32: - // Always allowed to remove check. No matter which operand. - break; - default: - return true; - } - } - return false; -} - MDefinition * MBinaryArithInstruction::foldsTo(TempAllocator &alloc) { @@ -1620,45 +1507,6 @@ MDiv::foldsTo(TempAllocator &alloc) return this; } -void -MDiv::analyzeEdgeCasesForward() -{ - // This is only meaningful when doing integer division. - if (specialization_ != MIRType_Int32) - return; - - // Try removing divide by zero check - if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0)) - canBeDivideByZero_ = false; - - // If lhs is a constant int != INT32_MIN, then - // negative overflow check can be skipped. - if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(INT32_MIN)) - canBeNegativeOverflow_ = false; - - // If rhs is a constant int != -1, likewise. - if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(-1)) - canBeNegativeOverflow_ = false; - - // If lhs is != 0, then negative zero check can be skipped. - if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(0)) - setCanBeNegativeZero(false); - - // If rhs is >= 0, likewise. - if (rhs()->isConstant()) { - const js::Value &val = rhs()->toConstant()->value(); - if (val.isInt32() && val.toInt32() >= 0) - setCanBeNegativeZero(false); - } -} - -void -MDiv::analyzeEdgeCasesBackward() -{ - if (canBeNegativeZero() && !NeedNegativeZeroCheck(this)) - setCanBeNegativeZero(false); -} - bool MDiv::fallible() const { @@ -1677,23 +1525,6 @@ MMod::foldsTo(TempAllocator &alloc) return this; } -void -MMod::analyzeEdgeCasesForward() -{ - // These optimizations make sense only for integer division - if (specialization_ != MIRType_Int32) - return; - - if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0)) - canBeDivideByZero_ = false; - - if (rhs()->isConstant()) { - int32_t n = rhs()->toConstant()->value().toInt32(); - if (n > 0 && !IsPowerOfTwo(n)) - canBePowerOfTwoDivisor_ = false; - } -} - bool MMod::fallible() const { @@ -1753,36 +1584,6 @@ MMul::foldsTo(TempAllocator &alloc) return this; } -void -MMul::analyzeEdgeCasesForward() -{ - // Try to remove the check for negative zero - // This only makes sense when using the integer multiplication - if (specialization() != MIRType_Int32) - return; - - // If lhs is > 0, no need for negative zero check. - if (lhs()->isConstant()) { - const js::Value &val = lhs()->toConstant()->value(); - if (val.isInt32() && val.toInt32() > 0) - setCanBeNegativeZero(false); - } - - // If rhs is > 0, likewise. - if (rhs()->isConstant()) { - const js::Value &val = rhs()->toConstant()->value(); - if (val.isInt32() && val.toInt32() > 0) - setCanBeNegativeZero(false); - } -} - -void -MMul::analyzeEdgeCasesBackward() -{ - if (canBeNegativeZero() && !NeedNegativeZeroCheck(this)) - setCanBeNegativeZero(false); -} - bool MMul::updateForReplacement(MDefinition *ins_) { @@ -2483,13 +2284,6 @@ MToInt32::foldsTo(TempAllocator &alloc) return this; } -void -MToInt32::analyzeEdgeCasesBackward() -{ - if (!NeedNegativeZeroCheck(this)) - setCanBeNegativeZero(false); -} - MDefinition * MTruncateToInt32::foldsTo(TempAllocator &alloc) { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 93277f2b6a23..82878332afd6 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -482,8 +482,6 @@ class MDefinition : public MNode } bool congruentIfOperandsEqual(const MDefinition *ins) const; virtual MDefinition *foldsTo(TempAllocator &alloc); - virtual void analyzeEdgeCasesForward(); - virtual void analyzeEdgeCasesBackward(); // When a floating-point value is used by nodes which would prefer to // recieve integer inputs, we may be able to help by computing our result @@ -3804,9 +3802,6 @@ class MToInt32 MDefinition *foldsTo(TempAllocator &alloc); - // this only has backwards information flow. - void analyzeEdgeCasesBackward(); - bool canBeNegativeZero() const { return canBeNegativeZero_; } @@ -4951,8 +4946,6 @@ class MMul : public MBinaryArithInstruction } MDefinition *foldsTo(TempAllocator &alloc); - void analyzeEdgeCasesForward(); - void analyzeEdgeCasesBackward(); void collectRangeInfoPreTrunc(); double getIdentity() { @@ -5048,8 +5041,6 @@ class MDiv : public MBinaryArithInstruction } MDefinition *foldsTo(TempAllocator &alloc); - void analyzeEdgeCasesForward(); - void analyzeEdgeCasesBackward(); double getIdentity() { MOZ_ASSUME_UNREACHABLE("not used"); @@ -5166,8 +5157,6 @@ class MMod : public MBinaryArithInstruction return canBePowerOfTwoDivisor_; } - void analyzeEdgeCasesForward(); - bool isUnsigned() const { return unsigned_; } diff --git a/js/src/moz.build b/js/src/moz.build index 7a5c0f04ad14..4d5e932a625b 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -156,7 +156,6 @@ UNIFIED_SOURCES += [ 'jit/C1Spewer.cpp', 'jit/CodeGenerator.cpp', 'jit/CompileWrappers.cpp', - 'jit/EdgeCaseAnalysis.cpp', 'jit/EffectiveAddressAnalysis.cpp', 'jit/ExecutableAllocator.cpp', 'jit/Ion.cpp', From 095b8e75ff9863c2405a8f424e151a4085f8189c Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 14:21:46 +0100 Subject: [PATCH 032/119] Backed out changeset e349895861e2 (bug 1036186) for xpcshell failures --- dom/base/nsDOMClassInfo.cpp | 22 +++++++++++++++++++--- dom/base/nsDOMClassInfo.h | 7 ++++++- dom/bindings/BindingUtils.cpp | 29 ----------------------------- dom/bindings/BindingUtils.h | 8 -------- 4 files changed, 25 insertions(+), 41 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index ff2e586e978f..d851b683acef 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -429,6 +429,7 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] = #undef NS_DEFINE_CONSTRUCTOR_FUNC_DATA nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr; +nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nullptr; bool nsDOMClassInfo::sIsInitialized = false; @@ -779,11 +780,19 @@ nsDOMClassInfo::Init() nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); - NS_ADDREF(sXPConnect = nsContentUtils::XPConnect()); + nsresult rv = CallGetService(nsIXPConnect::GetCID(), &sXPConnect); + NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr elt = new nsEventListenerThisTranslator(); sXPConnect->SetFunctionThisTranslator(NS_GET_IID(nsIDOMEventListener), elt); + nsCOMPtr sm = + do_GetService("@mozilla.org/scriptsecuritymanager;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + sSecMan = sm; + NS_ADDREF(sSecMan); + AutoSafeJSContext cx; DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow) @@ -1034,6 +1043,9 @@ nsDOMClassInfo::Init() RegisterExternalClasses(); + // Register new DOM bindings + mozilla::dom::Register(nameSpaceManager); + sIsInitialized = true; return NS_OK; @@ -1512,8 +1524,11 @@ NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID) return nullptr; } - nsresult rv = RegisterDOMNames(); - NS_ENSURE_SUCCESS(rv, nullptr); + if (!nsDOMClassInfo::sIsInitialized) { + nsresult rv = nsDOMClassInfo::Init(); + + NS_ENSURE_SUCCESS(rv, nullptr); + } if (!sClassInfoData[aID].mCachedClassInfo) { nsDOMClassInfoData& data = sClassInfoData[aID]; @@ -1574,6 +1589,7 @@ nsDOMClassInfo::ShutDown() sWrappedJSObject_id = JSID_VOID; NS_IF_RELEASE(sXPConnect); + NS_IF_RELEASE(sSecMan); sIsInitialized = false; } diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index 77e353f7317a..39eea5c28162 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -96,7 +96,6 @@ public: static nsIClassInfo* GetClassInfoInstance(nsDOMClassInfoData* aData); - static nsresult Init(); static void ShutDown(); static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) @@ -128,6 +127,10 @@ public: { return sXPConnect; } + static nsIScriptSecurityManager *ScriptSecurityManager() + { + return sSecMan; + } protected: friend nsIClassInfo* NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID); @@ -143,12 +146,14 @@ protected: return mData->mInterfacesBitmap; } + static nsresult Init(); static nsresult RegisterClassProtos(int32_t aDOMClassInfoID); static nsresult RegisterExternalClasses(); nsresult ResolveConstructor(JSContext *cx, JSObject *obj, JSObject **objp); static nsIXPConnect *sXPConnect; + static nsIScriptSecurityManager *sSecMan; // nsIXPCScriptable code static nsresult DefineStaticJSVals(JSContext *cx); diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 303b952d7b86..62992a63368f 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -43,7 +43,6 @@ #include "mozilla/dom/HTMLAppletElementBinding.h" #include "mozilla/dom/Promise.h" #include "WorkerPrivate.h" -#include "nsDOMClassInfo.h" namespace mozilla { namespace dom { @@ -2562,34 +2561,6 @@ CreateGlobalOptions::TraceGlobal(JSTracer* aTrc, JSObject* aObj) xpc::TraceXPCGlobal(aTrc, aObj); } -static bool sRegisteredDOMNames = false; - -nsresult -RegisterDOMNames() -{ - if (sRegisteredDOMNames) { - return NS_OK; - } - - nsresult rv = nsDOMClassInfo::Init(); - if (NS_FAILED(rv)) { - NS_ERROR("Could not initialize nsDOMClassInfo"); - return rv; - } - - // Register new DOM bindings - nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager(); - if (!nameSpaceManager) { - NS_ERROR("Could not initialize nsScriptNameSpaceManager"); - return NS_ERROR_FAILURE; - } - mozilla::dom::Register(nameSpaceManager); - - sRegisteredDOMNames = true; - - return NS_OK; -} - /* static */ bool CreateGlobalOptions::PostCreateGlobal(JSContext* aCx, diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 2795eaca5aa3..0e051600d277 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -2808,9 +2808,6 @@ struct CreateGlobalOptions static bool PostCreateGlobal(JSContext* aCx, JS::Handle aGlobal); }; -nsresult -RegisterDOMNames(); - template bool CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache, @@ -2818,11 +2815,6 @@ CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache, JSPrincipals* aPrincipal, bool aInitStandardClasses, JS::MutableHandle aGlobal) { - nsresult rv = RegisterDOMNames(); - if (NS_FAILED(rv)) { - return Throw(aCx, rv); - } - aOptions.setTrace(CreateGlobalOptions::TraceGlobal); aGlobal.set(JS_NewGlobalObject(aCx, aClass, aPrincipal, From 2fd0a320bd3ebc037df2a9a1fb7f0eee418451e7 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Thu, 14 Aug 2014 09:24:08 -0400 Subject: [PATCH 033/119] Bug 1053248 - Add new gesture debug logger. r=yzen --- accessible/jsat/Gestures.jsm | 8 ++++---- accessible/jsat/Utils.jsm | 24 ++++++++++++++++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/accessible/jsat/Gestures.jsm b/accessible/jsat/Gestures.jsm index cecd40b648a1..3d2fd2fde982 100644 --- a/accessible/jsat/Gestures.jsm +++ b/accessible/jsat/Gestures.jsm @@ -228,7 +228,7 @@ this.GestureTracker = { // jshint ignore:line * @param {Number} aTimeStamp A new pointer event timeStamp. */ handle: function GestureTracker_handle(aDetail, aTimeStamp) { - Logger.debug(() => { + Logger.gesture(() => { return ['Pointer event', aDetail.type, 'at:', aTimeStamp, JSON.stringify(aDetail.points)]; }); @@ -332,7 +332,7 @@ function compileDetail(aType, aPoints, keyMap = {x: 'startX', y: 'startY'}) { */ function Gesture(aTimeStamp, aPoints = {}, aLastEvent = undefined) { this.startTime = Date.now(); - Logger.debug('Creating', this.id, 'gesture.'); + Logger.gesture('Creating', this.id, 'gesture.'); this.points = aPoints; this.lastEvent = aLastEvent; this._deferred = Promise.defer(); @@ -509,7 +509,7 @@ Gesture.prototype = { if (this.isComplete) { return; } - Logger.debug('Resolving', this.id, 'gesture.'); + Logger.gesture('Resolving', this.id, 'gesture.'); this.isComplete = true; let detail = this.compile(); if (detail) { @@ -533,7 +533,7 @@ Gesture.prototype = { if (this.isComplete) { return; } - Logger.debug('Rejecting', this.id, 'gesture.'); + Logger.gesture('Rejecting', this.id, 'gesture.'); this.isComplete = true; return { id: this.id, diff --git a/accessible/jsat/Utils.jsm b/accessible/jsat/Utils.jsm index d7fc792578db..57ab6c5176d3 100644 --- a/accessible/jsat/Utils.jsm +++ b/accessible/jsat/Utils.jsm @@ -473,11 +473,12 @@ State.prototype = { }; this.Logger = { // jshint ignore:line + GESTURE: -1, DEBUG: 0, INFO: 1, WARNING: 2, ERROR: 3, - _LEVEL_NAMES: ['DEBUG', 'INFO', 'WARNING', 'ERROR'], + _LEVEL_NAMES: ['GESTURE', 'DEBUG', 'INFO', 'WARNING', 'ERROR'], logLevel: 1, // INFO; @@ -490,7 +491,7 @@ this.Logger = { // jshint ignore:line let args = Array.prototype.slice.call(arguments, 1); let message = (typeof(args[0]) === 'function' ? args[0]() : args).join(' '); - message = '[' + Utils.ScriptName + '] ' + this._LEVEL_NAMES[aLogLevel] + + message = '[' + Utils.ScriptName + '] ' + this._LEVEL_NAMES[aLogLevel + 1] + ' ' + message + '\n'; dump(message); // Note: used for testing purposes. If |this.test| is true, also log to @@ -509,6 +510,11 @@ this.Logger = { // jshint ignore:line this, [this.INFO].concat(Array.prototype.slice.call(arguments))); }, + gesture: function gesture() { + this.log.apply( + this, [this.GESTURE].concat(Array.prototype.slice.call(arguments))); + }, + debug: function debug() { this.log.apply( this, [this.DEBUG].concat(Array.prototype.slice.call(arguments))); @@ -552,14 +558,16 @@ this.Logger = { // jshint ignore:line }, accessibleToString: function accessibleToString(aAccessible) { - let str = '[ defunct ]'; - try { - str = '[ ' + Utils.AccRetrieval.getStringRole(aAccessible.role) + - ' | ' + aAccessible.name + ' ]'; - } catch (x) { + if (!aAccessible) { + return '[ null ]'; } - return str; + try { + return'[ ' + Utils.AccRetrieval.getStringRole(aAccessible.role) + + ' | ' + aAccessible.name + ' ]'; + } catch (x) { + return '[ defunct ]'; + } }, eventToString: function eventToString(aEvent) { From 4c18079e6ccd30c1a2d674cdaebbabc44b59135e Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Thu, 14 Aug 2014 09:24:08 -0400 Subject: [PATCH 034/119] Bug 1053247 - Fix content integration tests. r=yzen --- accessible/tests/mochitest/jsat/jsatcommon.js | 8 ++++-- .../jsat/test_content_integration.html | 25 +++++++++++-------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/accessible/tests/mochitest/jsat/jsatcommon.js b/accessible/tests/mochitest/jsat/jsatcommon.js index 97c566bb9fe4..0f97929460a6 100644 --- a/accessible/tests/mochitest/jsat/jsatcommon.js +++ b/accessible/tests/mochitest/jsat/jsatcommon.js @@ -255,7 +255,7 @@ AccessFuContentTest.prototype = { this.currentPair = this.queue.shift(); if (this.currentPair) { - if (this.currentPair[0] instanceof Function) { + if (typeof this.currentPair[0] === 'function') { this.currentPair[0](this.mms[0]); } else if (this.currentPair[0]) { this.mms[0].sendAsyncMessage(this.currentPair[0].name, @@ -290,7 +290,11 @@ AccessFuContentTest.prototype = { if (expected.speak) { var checkFunc = SimpleTest[expected.speak_checkFunc] || isDeeply; checkFunc.apply(SimpleTest, [speech, expected.speak, - '"' + JSON.stringify(speech) + '" spoken']); + 'spoken: ' + JSON.stringify(speech) + + ' expected: ' + JSON.stringify(expected.speak) + + ' after: ' + (typeof this.currentPair[0] === 'function' ? + this.currentPair[0].toString() : + JSON.stringify(this.currentPair[0]))]); } if (expected.android) { diff --git a/accessible/tests/mochitest/jsat/test_content_integration.html b/accessible/tests/mochitest/jsat/test_content_integration.html index 5bbac658c195..f45c02c5c0bf 100644 --- a/accessible/tests/mochitest/jsat/test_content_integration.html +++ b/accessible/tests/mochitest/jsat/test_content_integration.html @@ -136,8 +136,8 @@ speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'] }], [ContentMessages.focusSelector('button#home', false), { - speak: ['Home button'] - }] + speak: ['Home', {'string': 'pushbutton'}] + }], // Blur button and reset cursor [ContentMessages.focusSelector('button#home', true), null], @@ -152,13 +152,13 @@ speak: ['Phone status bar', 'Traversal Rule test document'] }], [doc.defaultView.showAlert, { - speak: ['This is an alert! heading level 1 dialog'] + speak: ['This is an alert!', + {'string': 'headingLevel', 'args': [1]}, + {'string': 'dialog'}] }], - [function() { - doc.defaultView.hideAlert() - }, { - speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'] + [doc.defaultView.hideAlert, { + speak: ["wow", {"string": "headingLevel","args": [1]}, "such app"], }], [ContentMessages.clearCursor, 'AccessFu:CursorCleared'], @@ -171,12 +171,15 @@ speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'] }], [doc.defaultView.showAlert, { - speak: ['This is an alert! heading level 1 dialog'] + speak: ['This is an alert!', + {'string': 'headingLevel', 'args': [1]}, + {'string': 'dialog'}] }], // XXX: Place cursor back where it was. [doc.defaultView.hideAlert, { - speak: ['many option not checked check button such app'] + speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'], + speak_checkFunc: 'todo_is' }], [ContentMessages.clearCursor, 'AccessFu:CursorCleared'], @@ -186,7 +189,9 @@ speak: ['Phone status bar', 'Traversal Rule test document'] }], [doc.defaultView.showAlert, { - speak: ['This is an alert! heading level 1 dialog'] + speak: ['This is an alert!', + {'string': 'headingLevel', 'args': [1]}, + {'string': 'dialog'}] }], [function() { From c60f12d6d2095358f60f5ed0d10e64fe15b2cf44 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Thu, 14 Aug 2014 09:24:08 -0400 Subject: [PATCH 035/119] Bug 1053250 - When automoving back into a remote iframe preserve the frame's vc position. r=yzen --- accessible/jsat/ContentControl.jsm | 7 ++++++- accessible/jsat/EventManager.jsm | 6 ++++-- .../tests/mochitest/jsat/test_content_integration.html | 1 - 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/accessible/jsat/ContentControl.jsm b/accessible/jsat/ContentControl.jsm index 741da1fb2bd9..96b0bb005c4a 100644 --- a/accessible/jsat/ContentControl.jsm +++ b/accessible/jsat/ContentControl.jsm @@ -425,7 +425,12 @@ this.ContentControl.prototype = { let sentToChild = this.sendToChild(vc, { name: 'AccessFu:AutoMove', - json: aOptions + json: { + moveMethod: aOptions.moveMethod, + moveToFocused: aOptions.moveToFocused, + noOpIfOnScreen: true, + forcePresent: true + } }); if (!moved && !sentToChild) { diff --git a/accessible/jsat/EventManager.jsm b/accessible/jsat/EventManager.jsm index f93932e8d991..c4d6fe52469b 100644 --- a/accessible/jsat/EventManager.jsm +++ b/accessible/jsat/EventManager.jsm @@ -279,8 +279,10 @@ this.EventManager.prototype = { // Put vc where the focus is at let acc = aEvent.accessible; let doc = aEvent.accessibleDocument; - if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) { - this.contentControl.autoMove(acc); + if ([Roles.CHROME_WINDOW, + Roles.DOCUMENT, + Roles.APPLICATION].indexOf(acc.role) < 0) { + this.contentControl.autoMove(acc); } break; } diff --git a/accessible/tests/mochitest/jsat/test_content_integration.html b/accessible/tests/mochitest/jsat/test_content_integration.html index f45c02c5c0bf..14f7a4a62570 100644 --- a/accessible/tests/mochitest/jsat/test_content_integration.html +++ b/accessible/tests/mochitest/jsat/test_content_integration.html @@ -179,7 +179,6 @@ // XXX: Place cursor back where it was. [doc.defaultView.hideAlert, { speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'], - speak_checkFunc: 'todo_is' }], [ContentMessages.clearCursor, 'AccessFu:CursorCleared'], From 172799ed62a4656084cf28fdc616e34ef3fdcc77 Mon Sep 17 00:00:00 2001 From: Andrew Halberstadt Date: Thu, 14 Aug 2014 10:24:47 -0400 Subject: [PATCH 036/119] Bug 969146 - DeviceRunner should always check for crashes onFinish, r=davehunt --- testing/mozbase/mozrunner/mozrunner/base/device.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testing/mozbase/mozrunner/mozrunner/base/device.py b/testing/mozbase/mozrunner/mozrunner/base/device.py index 8326ebb329b2..127a7a2afd9c 100644 --- a/testing/mozbase/mozrunner/mozrunner/base/device.py +++ b/testing/mozbase/mozrunner/mozrunner/base/device.py @@ -37,6 +37,7 @@ class DeviceRunner(BaseRunner): process_args = {'stream': sys.stdout, 'processOutputLine': self.on_output, + 'onFinish': self.on_finish, 'onTimeout': self.on_timeout } process_args.update(kwargs.get('process_args') or {}) @@ -122,6 +123,9 @@ class DeviceRunner(BaseRunner): print(msg % (self.last_test, timeout)) self.check_for_crashes() + def on_finish(self): + self.check_for_crashes() + def check_for_crashes(self): dump_dir = self.device.pull_minidumps() BaseRunner.check_for_crashes(self, dump_directory=dump_dir, test_name=self.last_test) From c188c767bb43ae8b47bacf1f40051e3d3810e480 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 14 Aug 2014 10:29:29 -0400 Subject: [PATCH 037/119] Bug 1047842 - Remove assertion annotations that are no longer needed. --- .../tests/mochitest/test_getUserMedia_basicScreenshare.html | 2 -- .../tests/mochitest/test_getUserMedia_basicWindowshare.html | 2 -- .../tests/mochitest/test_peerConnection_basicScreenshare.html | 2 -- .../tests/mochitest/test_peerConnection_basicWindowshare.html | 2 -- 4 files changed, 8 deletions(-) diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html b/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html index f94f0d82a1c9..58bd42f61e06 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html @@ -23,8 +23,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=983504 * Run a test to verify that we can complete a start and stop media playback * cycle for an screenshare LocalMediaStream on a video HTMLMediaElement. */ - SimpleTest.expectAssertions(0, 3); // Bug 1047842 - runTest(function () { const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; if (IsMacOSX10_6orOlder() || isWinXP) { diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html b/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html index 079d9294e3da..0c4aac42abd9 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html @@ -23,8 +23,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=983504 * Run a test to verify that we can complete a start and stop media playback * cycle for an screenshare LocalMediaStream on a video HTMLMediaElement. */ - SimpleTest.expectAssertions(0, 3); // Bug 1047842 - runTest(function () { const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; if (IsMacOSX10_6orOlder() || isWinXP) { diff --git a/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html b/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html index 123175e20949..0e1c93fc8d7b 100644 --- a/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html +++ b/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html @@ -17,8 +17,6 @@ title: "Basic screenshare-only peer connection" }); - SimpleTest.expectAssertions(0, 1); // Bug 1047842 - var test; runNetworkTest(function (options) { const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; diff --git a/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html b/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html index 37a6c86b8850..ae8369c06b7c 100644 --- a/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html +++ b/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html @@ -17,8 +17,6 @@ title: "Basic windowshare-only peer connection" }); - SimpleTest.expectAssertions(0, 1); // Bug 1047842 - var test; runNetworkTest(function (options) { const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; From 84487d075a0b1fb521c8582cc93ad63647d5f2e1 Mon Sep 17 00:00:00 2001 From: Alexander Seleznev Date: Sun, 10 Aug 2014 16:05:51 +0700 Subject: [PATCH 038/119] Bug 803633 - Add basic support for new scrollbar behavior in GTK+ [Part 1]. r=mstange, r=karlt --- layout/xul/nsSliderFrame.cpp | 31 +++++++++++++++++++++++++++++-- modules/libpref/init/all.js | 12 +++++++----- widget/gtk/nsLookAndFeel.cpp | 20 ++++++++++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index 5bb1720d7e6d..6bd31a5a26f7 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -534,6 +534,21 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext, mDragStart = pos - mThumbStart; } +#ifdef MOZ_WIDGET_GTK + else if (ShouldScrollForEvent(aEvent) && + aEvent->mClass == eMouseEventClass && + aEvent->AsMouseEvent()->button == WidgetMouseEvent::eRightButton) { + // HandlePress and HandleRelease are usually called via + // nsFrame::HandleEvent, but only for the left mouse button. + if (aEvent->message == NS_MOUSE_BUTTON_DOWN) { + HandlePress(aPresContext, aEvent, aEventStatus); + } else if (aEvent->message == NS_MOUSE_BUTTON_UP) { + HandleRelease(aPresContext, aEvent, aEventStatus); + } + + return NS_OK; + } +#endif // XXX hack until handle release is actually called in nsframe. // if (aEvent->message == NS_MOUSE_EXIT_SYNTH || aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) @@ -955,8 +970,14 @@ nsSliderFrame::ShouldScrollForEvent(WidgetGUIEvent* aEvent) case NS_MOUSE_BUTTON_DOWN: case NS_MOUSE_BUTTON_UP: { uint16_t button = aEvent->AsMouseEvent()->button; +#ifdef MOZ_WIDGET_GTK + return (button == WidgetMouseEvent::eLeftButton) || + (button == WidgetMouseEvent::eRightButton && GetScrollToClick()) || + (button == WidgetMouseEvent::eMiddleButton && gMiddlePref && !GetScrollToClick()); +#else return (button == WidgetMouseEvent::eLeftButton) || (button == WidgetMouseEvent::eMiddleButton && gMiddlePref); +#endif } default: return false; @@ -978,8 +999,8 @@ nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent) return false; } -#ifdef XP_MACOSX - // On Mac, clicking the scrollbar thumb should never scroll to click. +#if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK) + // On Mac and Linux, clicking the scrollbar thumb should never scroll to click. if (IsEventOverThumb(aEvent)) { return false; } @@ -995,6 +1016,12 @@ nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent) return GetScrollToClick() != invertPref; } +#ifdef MOZ_WIDGET_GTK + if (mouseEvent->button == WidgetMouseEvent::eRightButton) { + return !GetScrollToClick(); + } +#endif + return true; } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ba6c82c5ea7f..7fb9caee9646 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -574,16 +574,18 @@ pref("accessibility.browsewithcaret_shortcut.enabled", true); // unless accessibility.tabfocus is set by the user. pref("accessibility.tabfocus", 7); pref("accessibility.tabfocus_applies_to_xul", false); - -// On OS X, we follow the "Click in the scrollbar to:" system preference -// unless this preference was set manually -pref("ui.scrollToClick", 0); - #else // Only on mac tabfocus is expected to handle UI widgets as well as web content pref("accessibility.tabfocus_applies_to_xul", true); #endif +// We follow the "Click in the scrollbar to:" system preference on OS X and +// "gtk-primary-button-warps-slider" property with GTK (since 2.24 / 3.6), +// unless this preference is explicitly set. +#if !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GTK) +pref("ui.scrollToClick", 0); +#endif + // provide ability to turn on support for canvas focus rings pref("canvas.focusring.enabled", true); pref("canvas.customfocusring.enabled", false); diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp index 01343406cc38..93066b4f1109 100644 --- a/widget/gtk/nsLookAndFeel.cpp +++ b/widget/gtk/nsLookAndFeel.cpp @@ -555,6 +555,26 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) g_object_unref(entry); } break; + case eIntID_ScrollToClick: + { + GtkSettings *settings; + gboolean warps_slider = FALSE; + + settings = gtk_settings_get_default (); + if (g_object_class_find_property (G_OBJECT_GET_CLASS(settings), + "gtk-primary-button-warps-slider")) { + g_object_get (settings, + "gtk-primary-button-warps-slider", + &warps_slider, + nullptr); + } + + if (warps_slider) + aResult = 1; + else + aResult = 0; + } + break; case eIntID_SubmenuDelay: { GtkSettings *settings; From 10dae0a1f304f494cea577286e96c0e05ea82d56 Mon Sep 17 00:00:00 2001 From: Alexander Seleznev Date: Thu, 31 Jul 2014 02:03:00 -0400 Subject: [PATCH 039/119] Bug 803633 - Add basic support for new scrollbar behavior in GTK+ [2/4]. r=mstange --- layout/xul/nsSliderFrame.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index 6bd31a5a26f7..f49b62d2b24a 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -438,12 +438,15 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext, break; } if (mChange) { - // We're in the process of moving the thumb to the mouse, - // but the mouse just moved. Make sure to update our - // destination point. + // On Linux the destination point is determined by the initial click + // on the scrollbar track and doesn't change until the mouse button + // is released. +#ifndef MOZ_WIDGET_GTK + // On the other platforms we need to update the destination point now. mDestinationPoint = eventPoint; StopRepeat(); StartRepeat(); +#endif break; } @@ -1081,7 +1084,25 @@ nsSliderFrame::HandlePress(nsPresContext* aPresContext, mChange = change; DragThumb(true); + // On Linux we want to keep scrolling in the direction indicated by |change| + // until the mouse is released. On the other platforms we want to stop + // scrolling as soon as the scrollbar thumb has reached the current mouse + // position. +#ifdef MOZ_WIDGET_GTK + nsRect clientRect; + GetClientRect(clientRect); + + // Set the destination point to the very end of the scrollbar so that + // scrolling doesn't stop halfway through. + if (change > 0) { + mDestinationPoint = nsPoint(clientRect.width, clientRect.height); + } + else { + mDestinationPoint = nsPoint(0, 0); + } +#else mDestinationPoint = eventPoint; +#endif StartRepeat(); PageUpDown(change); return NS_OK; From 53c607e0104e09195ee22266074a921a5487165a Mon Sep 17 00:00:00 2001 From: Alexander Seleznev Date: Wed, 13 Aug 2014 06:02:00 -0400 Subject: [PATCH 040/119] Bug 803633 - Add basic support for new scrollbar behavior in GTK+ [Part 3]. r=mstange --- layout/xul/nsSliderFrame.cpp | 20 ++++++++++++++++++++ widget/gtk/nsNativeThemeGTK.cpp | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index f49b62d2b24a..7b9c0f571f18 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -526,6 +526,12 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext, NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK); DragThumb(true); + +#ifdef MOZ_WIDGET_GTK + nsCOMPtr thumb = thumbFrame->GetContent(); + thumb->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), true); +#endif + if (aEvent->mClass == eTouchEventClass) { *aEventStatus = nsEventStatus_eConsumeNoDefault; } @@ -880,6 +886,11 @@ nsSliderFrame::StartDrag(nsIDOMEvent* aEvent) return NS_OK; } +#ifdef MOZ_WIDGET_GTK + nsCOMPtr thumb = thumbFrame->GetContent(); + thumb->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), true); +#endif + if (isHorizontal) mThumbStart = thumbFrame->GetPosition().x; else @@ -899,6 +910,15 @@ nsSliderFrame::StopDrag() { AddListener(); DragThumb(false); + +#ifdef MOZ_WIDGET_GTK + nsIFrame* thumbFrame = mFrames.FirstChild(); + if (thumbFrame) { + nsCOMPtr thumb = thumbFrame->GetContent(); + thumb->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, true); + } +#endif + if (mChange) { StopRepeat(); mChange = 0; diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp index 1c25019ea185..969fb0a76239 100644 --- a/widget/gtk/nsNativeThemeGTK.cpp +++ b/widget/gtk/nsNativeThemeGTK.cpp @@ -269,6 +269,10 @@ nsNativeThemeGTK::GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, aState->curpos = CheckIntAttr(tmpFrame, nsGkAtoms::curpos, 0); aState->maxpos = CheckIntAttr(tmpFrame, nsGkAtoms::maxpos, 100); + + if (CheckBooleanAttr(aFrame, nsGkAtoms::active)) { + aState->active = TRUE; + } } if (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_UP || @@ -1306,6 +1310,13 @@ nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, return NS_OK; } + if ((aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL || + aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) && + aAttribute == nsGkAtoms::active) { + *aShouldRepaint = true; + return NS_OK; + } + if ((aWidgetType == NS_THEME_SCROLLBAR_BUTTON_UP || aWidgetType == NS_THEME_SCROLLBAR_BUTTON_DOWN || aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT || From c331ffe05f0b79ca81612f1dbf18b5373d3a2dd3 Mon Sep 17 00:00:00 2001 From: Alexander Seleznev Date: Sun, 10 Aug 2014 05:38:00 -0400 Subject: [PATCH 041/119] Bug 803633 - Update tests. r=mstange --- .../content/tests/chrome/test_scrollbar.xul | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/toolkit/content/tests/chrome/test_scrollbar.xul b/toolkit/content/tests/chrome/test_scrollbar.xul index df01593ee94d..11dccbee949b 100644 --- a/toolkit/content/tests/chrome/test_scrollbar.xul +++ b/toolkit/content/tests/chrome/test_scrollbar.xul @@ -47,16 +47,21 @@ var scrollbarTester = { var x = 160; // on the right half of the thumb var y = 5; + var isMac = navigator.platform.indexOf("Mac") != -1; + var runtime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + var isGtk = runtime.widgetToolkit.indexOf("gtk") != -1; + // Start the drag. this.mousedown(x, y, button, withAlt, withShift); var newPos = this.getPos(); var scrollToClick = (newPos != 0); - if (navigator.platform.indexOf("Mac") != -1) { - ok(!scrollToClick, - "On Mac OS X, clicking the scrollbar thumb should never move it."); + if (isMac || isGtk) { + ok(!scrollToClick, "On Linux and Mac OS X, clicking the scrollbar thumb "+ + "should never move it."); } else if (button == 0 && withShift) { - ok(scrollToClick, "On platforms other than Mac OS X, holding shift should "+ - "enable scroll-to-click on the scrollbar thumb."); + ok(scrollToClick, "On platforms other than Linux and Mac OS X, holding "+ + "shift should enable scroll-to-click on the scrollbar thumb."); } else if (button == 1 && this.middlePref) { ok(scrollToClick, "When middlemouse.scrollbarPosition is on, clicking the "+ "thumb with the middle mouse button should center it "+ @@ -69,13 +74,13 @@ var scrollbarTester = { if (newPos2 != newPos) { ok(newPos2 > newPos, "Scrollbar thumb should follow the mouse when dragged."); ok(newPos2 - newPos < 3, "Scrollbar shouldn't move further than the mouse when dragged."); - ok(button == 0 || (button == 1 && this.middlePref), + ok(button == 0 || (button == 1 && this.middlePref) || (button == 2 && isGtk), "Dragging the scrollbar should only be possible with the left mouse button."); } else { // Dragging had no effect. if (button == 0) { ok(false, "Dragging the scrollbar thumb should work."); - } else if (button == 1 && this.middlePref && navigator.platform.indexOf("Mac") == -1) { + } else if (button == 1 && this.middlePref && (!isGtk && !isMac)) { ok(false, "When middlemouse.scrollbarPosition is on, dragging the "+ "scrollbar thumb should be possible using the middle mouse button."); } else { From fe70832590c6a1fd8a4b8ebf7b13fb0159ed582f Mon Sep 17 00:00:00 2001 From: Kershaw Chang Date: Wed, 13 Aug 2014 02:18:00 -0400 Subject: [PATCH 042/119] Bug 1020204 - Allow creating nested oop MozApp iframe. r=khuey, r=kanru --- dom/ipc/ContentParent.cpp | 294 +++++++++++++++++++------------ dom/ipc/ContentParent.h | 26 ++- toolkit/xre/nsAppRunner.cpp | 2 +- toolkit/xre/nsEmbedFunctions.cpp | 2 +- 4 files changed, 201 insertions(+), 123 deletions(-) mode change 100644 => 100755 dom/ipc/ContentParent.cpp diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp old mode 100644 new mode 100755 index 96c08893e191..94c1d111ea03 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -575,7 +575,7 @@ ContentParent::RunNuwaProcess() // PreallocateAppProcess is called by the PreallocatedProcessManager. // ContentParent then takes this process back within -// MaybeTakePreallocatedAppProcess. +// GetNewOrPreallocatedAppProcess. /*static*/ already_AddRefed ContentParent::PreallocateAppProcess() { @@ -590,21 +590,47 @@ ContentParent::PreallocateAppProcess() } /*static*/ already_AddRefed -ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL, - ProcessPriority aInitialPriority) +ContentParent::GetNewOrPreallocatedAppProcess(mozIApplication* aApp, + ProcessPriority aInitialPriority, + ContentParent* aOpener, + /*out*/ bool* aTookPreAllocated) { + MOZ_ASSERT(aApp); nsRefPtr process = PreallocatedProcessManager::Take(); - if (!process) { - return nullptr; + + if (process) { + if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) { + // Kill the process just in case it's not actually dead; we don't want + // to "leak" this process! + process->KillHard(); + } + else { + nsAutoString manifestURL; + if (NS_FAILED(aApp->GetManifestURL(manifestURL))) { + NS_ERROR("Failed to get manifest URL"); + return nullptr; + } + process->TransformPreallocatedIntoApp(manifestURL); + if (aTookPreAllocated) { + *aTookPreAllocated = true; + } + return process.forget(); + } } - if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) { - // Kill the process just in case it's not actually dead; we don't want - // to "leak" this process! - process->KillHard(); - return nullptr; + // XXXkhuey Nuwa wants the frame loader to try again later, but the + // frame loader is really not set up to do that ... + NS_WARNING("Unable to use pre-allocated app process"); + process = new ContentParent(aApp, + /* aOpener = */ aOpener, + /* isForBrowserElement = */ false, + /* isForPreallocated = */ false, + aInitialPriority); + process->Init(); + + if (aTookPreAllocated) { + *aTookPreAllocated = false; } - process->TransformPreallocatedIntoApp(aAppManifestURL); return process.forget(); } @@ -693,9 +719,9 @@ ContentParent::JoinAllSubprocesses() } /*static*/ already_AddRefed -ContentParent::GetNewOrUsed(bool aForBrowserElement, - ProcessPriority aPriority, - ContentParent* aOpener) +ContentParent::GetNewOrUsedBrowserProcess(bool aForBrowserElement, + ProcessPriority aPriority, + ContentParent* aOpener) { if (!sNonAppContentParents) sNonAppContentParents = new nsTArray(); @@ -805,10 +831,31 @@ ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext, return false; } #endif + nsRefPtr cp; + MaybeInvalidTabContext tc(aContext); + if (!tc.IsValid()) { + NS_ERROR(nsPrintfCString("Received an invalid TabContext from " + "the child process. (%s)", + tc.GetInvalidReason()).get()); + return false; + } + + nsCOMPtr ownApp = tc.GetTabContext().GetOwnApp(); + if (ownApp) { + cp = GetNewOrPreallocatedAppProcess(ownApp, + aPriority, + this); + } + else { + cp = GetNewOrUsedBrowserProcess(/* isBrowserElement = */ true, + aPriority, + this); + } + + if (!cp) { + return false; + } - nsRefPtr cp = GetNewOrUsed(/* isBrowserElement = */ true, - aPriority, - this); *aId = cp->ChildID(); *aIsForApp = cp->IsForApp(); *aIsForBrowser = cp->IsForBrowser(); @@ -849,36 +896,20 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext, } ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement); + bool isInContentProcess = (XRE_GetProcessType() != GeckoProcessType_Default); if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) { nsRefPtr tp; nsRefPtr constructorSender; - if (XRE_GetProcessType() != GeckoProcessType_Default) { + if (isInContentProcess) { MOZ_ASSERT(aContext.IsBrowserElement()); - ContentChild* child = ContentChild::GetSingleton(); - uint64_t id; - bool isForApp; - bool isForBrowser; - if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(), - initialPriority, - &id, - &isForApp, - &isForBrowser)) { - return nullptr; - } - if (!child->CallBridgeToChildProcess(id)) { - return nullptr; - } - ContentBridgeParent* parent = child->GetLastBridge(); - parent->SetChildID(id); - parent->SetIsForApp(isForApp); - parent->SetIsForBrowser(isForBrowser); - constructorSender = parent; + constructorSender = CreateContentBridgeParent(aContext, initialPriority); } else { if (aOpenerContentParent) { constructorSender = aOpenerContentParent; } else { - constructorSender = GetNewOrUsed(aContext.IsBrowserElement(), initialPriority); + constructorSender = GetNewOrUsedBrowserProcess(aContext.IsBrowserElement(), + initialPriority); } } if (constructorSender) { @@ -928,105 +959,115 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext, // If we got here, we have an app and we're not a browser element. ownApp // shouldn't be null, because we otherwise would have gone into the // !HasOwnApp() branch above. - nsCOMPtr ownApp = aContext.GetOwnApp(); - - if (!sAppContentParents) { - sAppContentParents = - new nsDataHashtable(); - } - - // Each app gets its own ContentParent instance unless it shares it with - // a parent app. + nsRefPtr parent; + bool reused = false; + bool tookPreallocated = false; nsAutoString manifestURL; - if (NS_FAILED(ownApp->GetManifestURL(manifestURL))) { - NS_ERROR("Failed to get manifest URL"); - return nullptr; + + if (isInContentProcess) { + parent = CreateContentBridgeParent(aContext, initialPriority); } + else { + nsCOMPtr ownApp = aContext.GetOwnApp(); - nsRefPtr p = sAppContentParents->Get(manifestURL); + if (!sAppContentParents) { + sAppContentParents = + new nsDataHashtable(); + } - if (!p && Preferences::GetBool("dom.ipc.reuse_parent_app")) { - nsAutoString parentAppManifestURL; - aFrameElement->GetAttr(kNameSpaceID_None, - nsGkAtoms::parentapp, parentAppManifestURL); - nsAdoptingString systemAppManifestURL = - Preferences::GetString("b2g.system_manifest_url"); - nsCOMPtr appsService = - do_GetService(APPS_SERVICE_CONTRACTID); - if (!parentAppManifestURL.IsEmpty() && - !parentAppManifestURL.Equals(systemAppManifestURL) && - appsService) { - nsCOMPtr parentApp; - nsCOMPtr app; - appsService->GetAppByManifestURL(parentAppManifestURL, - getter_AddRefs(parentApp)); - appsService->GetAppByManifestURL(manifestURL, - getter_AddRefs(app)); + // Each app gets its own ContentParent instance unless it shares it with + // a parent app. + if (NS_FAILED(ownApp->GetManifestURL(manifestURL))) { + NS_ERROR("Failed to get manifest URL"); + return nullptr; + } - // Only let certified apps re-use the same process. - unsigned short parentAppStatus = 0; - unsigned short appStatus = 0; - if (app && - NS_SUCCEEDED(app->GetAppStatus(&appStatus)) && - appStatus == nsIPrincipal::APP_STATUS_CERTIFIED && - parentApp && - NS_SUCCEEDED(parentApp->GetAppStatus(&parentAppStatus)) && - parentAppStatus == nsIPrincipal::APP_STATUS_CERTIFIED) { - // Check if we can re-use the process of the parent app. - p = sAppContentParents->Get(parentAppManifestURL); + nsRefPtr p = sAppContentParents->Get(manifestURL); + + if (!p && Preferences::GetBool("dom.ipc.reuse_parent_app")) { + nsAutoString parentAppManifestURL; + aFrameElement->GetAttr(kNameSpaceID_None, + nsGkAtoms::parentapp, parentAppManifestURL); + nsAdoptingString systemAppManifestURL = + Preferences::GetString("b2g.system_manifest_url"); + nsCOMPtr appsService = + do_GetService(APPS_SERVICE_CONTRACTID); + if (!parentAppManifestURL.IsEmpty() && + !parentAppManifestURL.Equals(systemAppManifestURL) && + appsService) { + nsCOMPtr parentApp; + nsCOMPtr app; + appsService->GetAppByManifestURL(parentAppManifestURL, + getter_AddRefs(parentApp)); + appsService->GetAppByManifestURL(manifestURL, + getter_AddRefs(app)); + + // Only let certified apps re-use the same process. + unsigned short parentAppStatus = 0; + unsigned short appStatus = 0; + if (app && + NS_SUCCEEDED(app->GetAppStatus(&appStatus)) && + appStatus == nsIPrincipal::APP_STATUS_CERTIFIED && + parentApp && + NS_SUCCEEDED(parentApp->GetAppStatus(&parentAppStatus)) && + parentAppStatus == nsIPrincipal::APP_STATUS_CERTIFIED) { + // Check if we can re-use the process of the parent app. + p = sAppContentParents->Get(parentAppManifestURL); + } } } + + if (p) { + // Check that the process is still alive and set its priority. + // Hopefully the process won't die after this point, if this call + // succeeds. + if (!p->SetPriorityAndCheckIsAlive(initialPriority)) { + p = nullptr; + } + } + + reused = !!p; + if (!p) { + p = GetNewOrPreallocatedAppProcess(ownApp, + initialPriority, + nullptr, + &tookPreallocated); + MOZ_ASSERT(p); + sAppContentParents->Put(manifestURL, p); + } + parent = static_cast(p); } - if (p) { - // Check that the process is still alive and set its priority. - // Hopefully the process won't die after this point, if this call - // succeeds. - if (!p->SetPriorityAndCheckIsAlive(initialPriority)) { - p = nullptr; - } - } - - bool reused = !!p; - bool tookPreallocated = false; - if (!p) { - p = MaybeTakePreallocatedAppProcess(manifestURL, - initialPriority); - tookPreallocated = !!p; - if (!tookPreallocated) { - // XXXkhuey Nuwa wants the frame loader to try again later, but the - // frame loader is really not set up to do that ... - NS_WARNING("Unable to use pre-allocated app process"); - p = new ContentParent(ownApp, - /* aOpener = */ nullptr, - /* isForBrowserElement = */ false, - /* isForPreallocated = */ false, - initialPriority); - p->Init(); - } - sAppContentParents->Put(manifestURL, p); + if (!parent) { + return nullptr; } uint32_t chromeFlags = 0; - nsRefPtr tp = new TabParent(p, aContext, chromeFlags); + nsRefPtr tp = new TabParent(parent, aContext, chromeFlags); tp->SetOwnerElement(aFrameElement); - PBrowserParent* browser = p->SendPBrowserConstructor( + PBrowserParent* browser = parent->SendPBrowserConstructor( // DeallocPBrowserParent() releases this ref. nsRefPtr(tp).forget().take(), aContext.AsIPCTabContext(), chromeFlags, - p->ChildID(), - p->IsForApp(), - p->IsForBrowser()); + parent->ChildID(), + parent->IsForApp(), + parent->IsForBrowser()); + + if (isInContentProcess) { + // Just return directly without the following check in content process. + return static_cast(browser); + } + if (!browser) { // We failed to actually start the PBrowser. This can happen if the // other process has already died. if (!reused) { // Don't leave a broken ContentParent in the hashtable. - p->KillHard(); + parent->AsContentParent()->KillHard(); sAppContentParents->Remove(manifestURL); - p = nullptr; + parent = nullptr; } // If we took the preallocated process and it was already dead, try @@ -1043,11 +1084,36 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext, return nullptr; } - p->MaybeTakeCPUWakeLock(aFrameElement); + parent->AsContentParent()->MaybeTakeCPUWakeLock(aFrameElement); return static_cast(browser); } +/*static*/ ContentBridgeParent* +ContentParent::CreateContentBridgeParent(const TabContext& aContext, + const hal::ProcessPriority& aPriority) +{ + ContentChild* child = ContentChild::GetSingleton(); + uint64_t id; + bool isForApp; + bool isForBrowser; + if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(), + aPriority, + &id, + &isForApp, + &isForBrowser)) { + return nullptr; + } + if (!child->CallBridgeToChildProcess(id)) { + return nullptr; + } + ContentBridgeParent* parent = child->GetLastBridge(); + parent->SetChildID(id); + parent->SetIsForApp(isForApp); + parent->SetIsForBrowser(isForBrowser); + return parent; +} + void ContentParent::GetAll(nsTArray& aArray) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 5edb6287cc0a..84f93501a01c 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -63,6 +63,7 @@ class ClonedMessageData; class MemoryReport; class TabContext; class PFileDescriptorSetParent; +class ContentBridgeParent; class ContentParent : public PContentParent , public nsIContentParent @@ -96,11 +97,17 @@ public: static bool PreallocatedProcessReady(); static void RunAfterPreallocatedProcessReady(nsIRunnable* aRequest); + /** + * Get or create a content process for: + * 1. browser iframe + * 2. remote xul + * 3. normal iframe + */ static already_AddRefed - GetNewOrUsed(bool aForBrowserElement = false, - hal::ProcessPriority aPriority = - hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND, - ContentParent* aOpener = nullptr); + GetNewOrUsedBrowserProcess(bool aForBrowserElement = false, + hal::ProcessPriority aPriority = + hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND, + ContentParent* aOpener = nullptr); /** * Create a subprocess suitable for use as a preallocated app process. @@ -286,13 +293,18 @@ private: // Take the preallocated process and transform it into a "real" app process, // for the specified manifest URL. If there is no preallocated process (or - // if it's dead), this returns false. + // if it's dead), create a new one and set aTookPreAllocated to false. static already_AddRefed - MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL, - hal::ProcessPriority aInitialPriority); + GetNewOrPreallocatedAppProcess(mozIApplication* aApp, + hal::ProcessPriority aInitialPriority, + ContentParent* aOpener, + /*out*/ bool* aTookPreAllocated = nullptr); static hal::ProcessPriority GetInitialProcessPriority(Element* aFrameElement); + static ContentBridgeParent* CreateContentBridgeParent(const TabContext& aContext, + const hal::ProcessPriority& aPriority); + // Hide the raw constructor methods since we don't want client code // using them. virtual PBrowserParent* SendPBrowserConstructor( diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index fe8ed3c449e9..e9a0c5bc9b79 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -820,7 +820,7 @@ nsXULAppInfo::EnsureContentProcess() if (XRE_GetProcessType() != GeckoProcessType_Default) return NS_ERROR_NOT_AVAILABLE; - nsRefPtr unused = ContentParent::GetNewOrUsed(); + nsRefPtr unused = ContentParent::GetNewOrUsedBrowserProcess(); return NS_OK; } diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index e616748994b3..3cdbb37a15ec 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -741,7 +741,7 @@ ContentParent* gContentParent; //long-lived, manually refcounted TestShellParent* GetOrCreateTestShellParent() { if (!gContentParent) { - nsRefPtr parent = ContentParent::GetNewOrUsed(); + nsRefPtr parent = ContentParent::GetNewOrUsedBrowserProcess(); parent.forget(&gContentParent); } else if (!gContentParent->IsAlive()) { return nullptr; From 1b49fb456bcf145269960cbda25b6a93077a6344 Mon Sep 17 00:00:00 2001 From: Ahmed Kachkach Date: Wed, 13 Aug 2014 12:03:00 -0400 Subject: [PATCH 043/119] Bug 1039833 - Add structured logging command line arguments for mochitest/mach. r=chmanchester, r=ahal --- .../config/mozharness/android_arm_config.py | 2 +- .../config/mozharness/android_panda_config.py | 2 +- .../config/mozharness/android_x86_config.py | 2 +- .../config/mozharness/b2g_desktop_config.py | 2 +- .../config/mozharness/b2g_emulator_config.py | 3 +- testing/config/mozharness/linux_config.py | 2 +- testing/config/mozharness/mac_config.py | 2 +- testing/config/mozharness/windows_config.py | 2 +- testing/mochitest/mach_commands.py | 12 +- testing/mochitest/runtests.py | 159 +++++++++--------- testing/mochitest/runtestsb2g.py | 40 ++--- testing/mochitest/runtestsremote.py | 92 +++++----- .../mozdevice/mozdevice/devicemanagerSUT.py | 2 +- 13 files changed, 167 insertions(+), 155 deletions(-) diff --git a/testing/config/mozharness/android_arm_config.py b/testing/config/mozharness/android_arm_config.py index 3ee1fb0298c5..bd4a07532882 100644 --- a/testing/config/mozharness/android_arm_config.py +++ b/testing/config/mozharness/android_arm_config.py @@ -12,7 +12,7 @@ config = { "--deviceIP=%(device_ip)s", "--devicePort=%(device_port)s", "--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s", "--certificate-path=%(certs_path)s", "--symbols-path=%(symbols_path)s", - "--quiet" + "--quiet", "--log-raw=%(raw_log_file)s" ], }, "reftest": { diff --git a/testing/config/mozharness/android_panda_config.py b/testing/config/mozharness/android_panda_config.py index d17b635b7e9d..8bc1e99ddddd 100644 --- a/testing/config/mozharness/android_panda_config.py +++ b/testing/config/mozharness/android_panda_config.py @@ -10,7 +10,7 @@ config = { "--app=%(app_name)s", "--console-level=INFO", "--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s", "--run-only-tests=android.json", "--symbols-path=%(symbols_path)s", - "--quiet" + "--quiet", "--log-raw=%(raw_log_file)s" ], "reftest_options": [ "--deviceIP=%(device_ip)s", diff --git a/testing/config/mozharness/android_x86_config.py b/testing/config/mozharness/android_x86_config.py index 3ee1fb0298c5..bd4a07532882 100644 --- a/testing/config/mozharness/android_x86_config.py +++ b/testing/config/mozharness/android_x86_config.py @@ -12,7 +12,7 @@ config = { "--deviceIP=%(device_ip)s", "--devicePort=%(device_port)s", "--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s", "--certificate-path=%(certs_path)s", "--symbols-path=%(symbols_path)s", - "--quiet" + "--quiet", "--log-raw=%(raw_log_file)s" ], }, "reftest": { diff --git a/testing/config/mozharness/b2g_desktop_config.py b/testing/config/mozharness/b2g_desktop_config.py index 4c83c55d82ed..7ccde18d32e7 100644 --- a/testing/config/mozharness/b2g_desktop_config.py +++ b/testing/config/mozharness/b2g_desktop_config.py @@ -9,7 +9,7 @@ config = { "--profile=%(gaia_profile)s", "--app=%(application)s", "--desktop", "--utility-path=%(utility_path)s", "--certificate-path=%(cert_path)s", "--symbols-path=%(symbols_path)s", "--browser-arg=%(browser_arg)s", - "--quiet" + "--quiet", "--log-raw=%(raw_log_file)s" ], "reftest_options": [ diff --git a/testing/config/mozharness/b2g_emulator_config.py b/testing/config/mozharness/b2g_emulator_config.py index afa0d1005b46..fd0629c99395 100644 --- a/testing/config/mozharness/b2g_emulator_config.py +++ b/testing/config/mozharness/b2g_emulator_config.py @@ -19,7 +19,8 @@ config = { "--remote-webserver=%(remote_webserver)s", "%(test_manifest)s", "--xre-path=%(xre_path)s", "--symbols-path=%(symbols_path)s", "--busybox=%(busybox)s", "--total-chunks=%(total_chunks)s", "--this-chunk=%(this_chunk)s", - "--quiet", "--certificate-path=%(certificate_path)s", + "--quiet", "--log-raw=%(raw_log_file)s", + "--certificate-path=%(certificate_path)s", "--test-path=%(test_path)s", ], diff --git a/testing/config/mozharness/linux_config.py b/testing/config/mozharness/linux_config.py index e0fff9a9469f..f799918a4c4d 100644 --- a/testing/config/mozharness/linux_config.py +++ b/testing/config/mozharness/linux_config.py @@ -12,7 +12,7 @@ config = { "--extra-profile-file=tests/bin/plugins", "--symbols-path=%(symbols_path)s", "--certificate-path=tests/certs", "--autorun", "--close-when-done", "--console-level=INFO", "--setpref=webgl.force-enabled=true", - "--quiet", + "--quiet", "--log-raw=%(raw_log_file)s", "--use-test-media-devices" ], "webapprt_options": [ diff --git a/testing/config/mozharness/mac_config.py b/testing/config/mozharness/mac_config.py index 99d89e761ced..483159ae5de4 100644 --- a/testing/config/mozharness/mac_config.py +++ b/testing/config/mozharness/mac_config.py @@ -12,7 +12,7 @@ config = { "--extra-profile-file=tests/bin/plugins", "--symbols-path=%(symbols_path)s", "--certificate-path=tests/certs", "--autorun", "--close-when-done", "--console-level=INFO", - "--quiet" + "--quiet", "--log-raw=%(raw_log_file)s" ], "webapprt_options": [ "--app=%(app_path)s", "--utility-path=tests/bin", diff --git a/testing/config/mozharness/windows_config.py b/testing/config/mozharness/windows_config.py index 99d89e761ced..483159ae5de4 100644 --- a/testing/config/mozharness/windows_config.py +++ b/testing/config/mozharness/windows_config.py @@ -12,7 +12,7 @@ config = { "--extra-profile-file=tests/bin/plugins", "--symbols-path=%(symbols_path)s", "--certificate-path=tests/certs", "--autorun", "--close-when-done", "--console-level=INFO", - "--quiet" + "--quiet", "--log-raw=%(raw_log_file)s" ], "webapprt_options": [ "--app=%(app_path)s", "--utility-path=tests/bin", diff --git a/testing/mochitest/mach_commands.py b/testing/mochitest/mach_commands.py index 3beadd750e4c..7a91a94157cb 100644 --- a/testing/mochitest/mach_commands.py +++ b/testing/mochitest/mach_commands.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals +import argparse import logging import mozpack.path import os @@ -24,6 +25,8 @@ from mach.decorators import ( ) +from mozlog import structured + ADB_NOT_FOUND = ''' The %s command requires the adb binary to be on your path. @@ -248,8 +251,6 @@ class MochitestRunner(MozbuildObject): for handler in remove_handlers: logging.getLogger().removeHandler(handler) - runner = mochitest.Mochitest() - opts = mochitest.MochitestOptions() options, args = opts.parse_args([]) @@ -359,6 +360,8 @@ class MochitestRunner(MozbuildObject): elif app_override: options.app = app_override + logger_options = {key: value for key, value in vars(options).iteritems() if key.startswith('log')} + runner = mochitest.Mochitest(logger_options) options = opts.verifyOptions(options, runner) if options is None: @@ -602,12 +605,15 @@ def B2GCommand(func): return func +_st_parser = argparse.ArgumentParser() +structured.commandline.add_logging_group(_st_parser) @CommandProvider class MachCommands(MachCommandBase): @Command('mochitest-plain', category='testing', conditions=[conditions.is_firefox_or_mulet], - description='Run a plain mochitest (integration test, plain web page).') + description='Run a plain mochitest (integration test, plain web page).', + parser=_st_parser) @MochitestCommand def run_mochitest_plain(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'plain', **kwargs) diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py index 908370bf1e83..af60e120b91b 100644 --- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -40,8 +40,8 @@ from mozprofile import Profile, Preferences from mozprofile.permissions import ServerLocations from urllib import quote_plus as encodeURIComponent from mozlog.structured.formatters import TbplFormatter +from mozlog.structured.commandline import add_logging_group, setup_logging from mozlog.structured.handlers import StreamHandler -from mozlog.structured.structuredlog import StructuredLogger # This should use the `which` module already in tree, but it is # not yet present in the mozharness environment @@ -98,7 +98,7 @@ class MessageLogger(object): 'test_status', 'log', 'buffering_on', 'buffering_off']) - def __init__(self, logger, buffering=True, name='mochitest'): + def __init__(self, logger, buffering=True): self.logger = logger self.buffering = buffering self.tests_started = False @@ -220,7 +220,7 @@ def call(*args, **kwargs): process.run() return process.wait() -def killPid(pid): +def killPid(pid, log): # see also https://bugzilla.mozilla.org/show_bug.cgi?id=911249#c58 try: os.kill(pid, getattr(signal, "SIGKILL", signal.SIGTERM)) @@ -269,9 +269,10 @@ else: class MochitestServer(object): "Web server used to serve Mochitests, for closer fidelity to the real web." - def __init__(self, options): + def __init__(self, options, logger): if isinstance(options, optparse.Values): options = vars(options) + self._log = logger self._closeWhenDone = options['closeWhenDone'] self._utilityPath = options['utilityPath'] self._xrePath = options['xrePath'] @@ -317,9 +318,9 @@ class MochitestServer(object): command = [xpcshell] + args self._process = mozprocess.ProcessHandler(command, cwd=SCRIPT_DIR, env=env) self._process.run() - log.info("%s : launching %s" % (self.__class__.__name__, command)) + self._log.info("%s : launching %s" % (self.__class__.__name__, command)) pid = self._process.pid - log.info("runtests.py | Server pid: %d" % pid) + self._log.info("runtests.py | Server pid: %d" % pid) def ensureReady(self, timeout): assert timeout >= 0 @@ -332,7 +333,7 @@ class MochitestServer(object): time.sleep(1) i += 1 else: - log.error("TEST-UNEXPECTED-FAIL | runtests.py | Timed out while waiting for server startup.") + self._log.error("TEST-UNEXPECTED-FAIL | runtests.py | Timed out while waiting for server startup.") self.stop() sys.exit(1) @@ -356,10 +357,12 @@ class MochitestServer(object): class WebSocketServer(object): "Class which encapsulates the mod_pywebsocket server" - def __init__(self, options, scriptdir, debuggerInfo=None): + def __init__(self, options, scriptdir, logger, debuggerInfo=None): self.port = options.webSocketPort - self._scriptdir = scriptdir self.debuggerInfo = debuggerInfo + self._log = logger + self._scriptdir = scriptdir + def start(self): # Invoke pywebsocket through a wrapper which adds special SIGINT handling. @@ -383,7 +386,7 @@ class WebSocketServer(object): self._process = mozprocess.ProcessHandler(cmd, cwd=SCRIPT_DIR) self._process.run() pid = self._process.pid - log.info("runtests.py | Websocket server pid: %d" % pid) + self._log.info("runtests.py | Websocket server pid: %d" % pid) def stop(self): self._process.kill() @@ -406,13 +409,28 @@ class MochitestUtilsMixin(object): TEST_PATH = "tests" CHROME_PATH = "redirect.html" urlOpts = [] + structured_logger = None - def __init__(self): + def __init__(self, logger_options): self.update_mozinfo() self.server = None self.wsserver = None self.sslTunnel = None self._locations = None + # Structured logger + if self.structured_logger is None: + self.structured_logger = setup_logging('mochitest', logger_options, {}) + # Add the tbpl logger if no handler is logging to stdout, to display formatted logs by default + has_stdout_logger = any(h.stream == sys.stdout for h in self.structured_logger.handlers) + if not has_stdout_logger: + handler = StreamHandler(sys.stdout, MochitestFormatter()) + self.structured_logger.add_handler(handler) + MochitestUtilsMixin.structured_logger = self.structured_logger + + self.message_logger = MessageLogger(logger=self.structured_logger) + + # self.log should also be structured_logger, but to avoid regressions like bug 1044206 we're now logging with the stdlib's logger + self.log = log def update_mozinfo(self): """walk up directories to find mozinfo.json update the info""" @@ -628,13 +646,13 @@ class MochitestUtilsMixin(object): def startWebSocketServer(self, options, debuggerInfo): """ Launch the websocket server """ - self.wsserver = WebSocketServer(options, SCRIPT_DIR, debuggerInfo) + self.wsserver = WebSocketServer(options, SCRIPT_DIR, self.log, debuggerInfo) self.wsserver.start() def startWebServer(self, options): """Create the webserver and start it up""" - self.server = MochitestServer(options) + self.server = MochitestServer(options, self.log) self.server.start() if options.pidFile != "": @@ -659,7 +677,7 @@ class MochitestUtilsMixin(object): self.startWebSocketServer(options, debuggerInfo) # start SSL pipe - self.sslTunnel = SSLTunnel(options) + self.sslTunnel = SSLTunnel(options, logger=self.log) self.sslTunnel.buildConfig(self.locations) self.sslTunnel.start() @@ -675,24 +693,24 @@ class MochitestUtilsMixin(object): might spew to console might confuse things.""" if self.server is not None: try: - log.info('Stopping web server') + self.log.info('Stopping web server') self.server.stop() except Exception: - log.critical('Exception when stopping web server') + self.log.critical('Exception when stopping web server') if self.wsserver is not None: try: - log.info('Stopping web socket server') + self.log.info('Stopping web socket server') self.wsserver.stop() except Exception: - log.critical('Exception when stopping web socket server'); + self.log.critical('Exception when stopping web socket server'); if self.sslTunnel is not None: try: - log.info('Stopping ssltunnel') + self.log.info('Stopping ssltunnel') self.sslTunnel.stop() except Exception: - log.critical('Exception stopping ssltunnel'); + self.log.critical('Exception stopping ssltunnel'); def copyExtraFilesToProfile(self, options): "Copy extra files or dirs specified on the command line to the testing profile." @@ -704,7 +722,7 @@ class MochitestUtilsMixin(object): dest = os.path.join(options.profilePath, os.path.basename(abspath)) shutil.copytree(abspath, dest) else: - log.warning("runtests.py | Failed to copy %s to profile" % abspath) + self.log.warning("runtests.py | Failed to copy %s to profile" % abspath) def installChromeJar(self, chrome, options): """ @@ -749,7 +767,7 @@ toolbar#nav-bar { # Call installChromeJar(). if not os.path.isdir(os.path.join(SCRIPT_DIR, self.jarDir)): - log.error(message="TEST-UNEXPECTED-FAIL | invalid setup: missing mochikit extension") + self.log.error("TEST-UNEXPECTED-FAIL | invalid setup: missing mochikit extension") return None # Support Firefox (browser), B2G (shell), SeaMonkey (navigator), and Webapp @@ -792,7 +810,8 @@ overlay chrome://webapprt/content/webapp.xul chrome://mochikit/content/browser-t return extensions class SSLTunnel: - def __init__(self, options): + def __init__(self, options, logger): + self.log = logger self.process = None self.utilityPath = options.utilityPath self.xrePath = options.xrePath @@ -847,7 +866,7 @@ class SSLTunnel: bin_suffix = mozinfo.info.get('bin_suffix', '') ssltunnel = os.path.join(self.utilityPath, "ssltunnel" + bin_suffix) if not os.path.exists(ssltunnel): - log.error("INFO | runtests.py | expected to find ssltunnel at %s" % ssltunnel) + self.log.error("INFO | runtests.py | expected to find ssltunnel at %s" % ssltunnel) exit(1) env = environment(xrePath=self.xrePath) @@ -855,7 +874,7 @@ class SSLTunnel: self.process = mozprocess.ProcessHandler([ssltunnel, self.configFile], env=env) self.process.run() - log.info("runtests.py | SSL tunnel pid: %d" % self.process.pid) + self.log.info("runtests.py | SSL tunnel pid: %d" % self.process.pid) def stop(self): """ Stops the SSL Tunnel and cleans up """ @@ -924,7 +943,7 @@ def checkAndConfigureV4l2loopback(device): return True, vcap.card -def findTestMediaDevices(): +def findTestMediaDevices(log): ''' Find the test media devices configured on this system, and return a dict containing information about them. The dict will have keys for 'audio' @@ -981,24 +1000,13 @@ class Mochitest(MochitestUtilsMixin): vmwareHelper = None DEFAULT_TIMEOUT = 60.0 mediaDevices = None - structured_logger = None # XXX use automation.py for test name to avoid breaking legacy # TODO: replace this with 'runtests.py' or 'mochitest' or the like test_name = 'automation.py' - def __init__(self): - # Structured logger - if self.structured_logger is None: - self.structured_logger = StructuredLogger('mochitest') - stream_handler = StreamHandler(stream=sys.stdout, formatter=MochitestFormatter()) - self.structured_logger.add_handler(stream_handler) - Mochitest.structured_logger = self.structured_logger - - super(Mochitest, self).__init__() - - # Structured logs parser - self.message_logger = MessageLogger(logger=self.structured_logger) + def __init__(self, logger_options): + super(Mochitest, self).__init__(logger_options) # environment function for browserEnv self.environment = environment @@ -1143,7 +1151,7 @@ class Mochitest(MochitestUtilsMixin): # TODO: this should really be upstreamed somewhere, maybe mozprofile certificateStatus = self.fillCertificateDB(options) if certificateStatus: - log.error("TEST-UNEXPECTED-FAIL | runtests.py | Certificate integration failed") + self.log.error("TEST-UNEXPECTED-FAIL | runtests.py | Certificate integration failed") return None return manifest @@ -1180,7 +1188,7 @@ class Mochitest(MochitestUtilsMixin): try: browserEnv.update(dict(parseKeyValue(options.environment, context='--setenv'))) except KeyValueParseError, e: - log.error(str(e)) + self.log.error(str(e)) return None browserEnv["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file @@ -1221,12 +1229,12 @@ class Mochitest(MochitestUtilsMixin): if os.path.exists(options.pidFile + ".xpcshell.pid"): os.remove(options.pidFile + ".xpcshell.pid") except: - log.warning("cleaning up pidfile '%s' was unsuccessful from the test harness" % options.pidFile) + self.log.warning("cleaning up pidfile '%s' was unsuccessful from the test harness" % options.pidFile) options.manifestFile = None def dumpScreen(self, utilityPath): if self.haveDumpedScreen: - log.info("Not taking screenshot here: see the one that was previously logged") + self.log.info("Not taking screenshot here: see the one that was previously logged") return self.haveDumpedScreen = True dumpScreen(utilityPath) @@ -1255,26 +1263,26 @@ class Mochitest(MochitestUtilsMixin): os.kill(processPID, signal.SIGABRT) except OSError: # https://bugzilla.mozilla.org/show_bug.cgi?id=921509 - log.info("Can't trigger Breakpad, process no longer exists") + self.log.info("Can't trigger Breakpad, process no longer exists") return - log.info("Can't trigger Breakpad, just killing process") - killPid(processPID) + self.log.info("Can't trigger Breakpad, just killing process") + killPid(processPID, self.log) def checkForZombies(self, processLog, utilityPath, debuggerInfo): """Look for hung processes""" if not os.path.exists(processLog): - log.info('Automation Error: PID log not found: %s' % processLog) + self.log.info('Automation Error: PID log not found: %s' % processLog) # Whilst no hung process was found, the run should still display as a failure return True # scan processLog for zombies - log.info('zombiecheck | Reading PID log: %s' % processLog) + self.log.info('zombiecheck | Reading PID log: %s' % processLog) processList = [] pidRE = re.compile(r'launched child process (\d+)$') with open(processLog) as processLogFD: for line in processLogFD: - log.info(line.rstrip()) + self.log.info(line.rstrip()) m = pidRE.search(line) if m: processList.append(int(m.group(1))) @@ -1282,10 +1290,10 @@ class Mochitest(MochitestUtilsMixin): # kill zombies foundZombie = False for processPID in processList: - log.info("zombiecheck | Checking for orphan process with PID: %d" % processPID) + self.log.info("zombiecheck | Checking for orphan process with PID: %d" % processPID) if isPidAlive(processPID): foundZombie = True - log.error("TEST-UNEXPECTED-FAIL | zombiecheck | child process %d still alive after shutdown" % processPID) + self.log.error("TEST-UNEXPECTED-FAIL | zombiecheck | child process %d still alive after shutdown" % processPID) self.killAndGetStack(processPID, utilityPath, debuggerInfo, dump_screen=not debuggerInfo) return foundZombie @@ -1296,14 +1304,14 @@ class Mochitest(MochitestUtilsMixin): from ctypes import cdll self.vmwareHelper = cdll.LoadLibrary(self.vmwareHelperPath) if self.vmwareHelper is None: - log.warning("runtests.py | Failed to load " + self.log.warning("runtests.py | Failed to load " "VMware recording helper") return - log.info("runtests.py | Starting VMware recording.") + self.log.info("runtests.py | Starting VMware recording.") try: self.vmwareHelper.StartRecording() except Exception, e: - log.warning("runtests.py | Failed to start " + self.log.warning("runtests.py | Failed to start " "VMware recording: (%s)" % str(e)) self.vmwareHelper = None @@ -1312,12 +1320,12 @@ class Mochitest(MochitestUtilsMixin): try: assert mozinfo.isWin if self.vmwareHelper is not None: - log.info("runtests.py | Stopping VMware recording.") + self.log.info("runtests.py | Stopping VMware recording.") self.vmwareHelper.StopRecording() except Exception, e: - log.warning("runtests.py | Failed to stop " + self.log.warning("runtests.py | Failed to stop " "VMware recording: (%s)" % str(e)) - log.exception('Error stopping VMWare recording') + self.log.exception('Error stopping VMWare recording') self.vmwareHelper = None @@ -1384,12 +1392,12 @@ class Mochitest(MochitestUtilsMixin): args.append(testUrl) if detectShutdownLeaks: - shutdownLeaks = ShutdownLeaks(log.info) + shutdownLeaks = ShutdownLeaks(self.log.info) else: shutdownLeaks = None if mozinfo.info["asan"] and (mozinfo.isLinux or mozinfo.isMac): - lsanLeaks = LSANLeaks(log.info) + lsanLeaks = LSANLeaks(self.log.info) else: lsanLeaks = None @@ -1434,7 +1442,7 @@ class Mochitest(MochitestUtilsMixin): interactive=interactive, outputTimeout=timeout) proc = runner.process_handler - log.info("runtests.py | Application pid: %d" % proc.pid) + self.log.info("runtests.py | Application pid: %d" % proc.pid) if onLaunch is not None: # Allow callers to specify an onLaunch callback to be fired after the @@ -1463,11 +1471,11 @@ class Mochitest(MochitestUtilsMixin): # record post-test information if status: self.message_logger.dump_buffered() - log.error("TEST-UNEXPECTED-FAIL | %s | application terminated with exit code %s" % (self.lastTestSeen, status)) + self.log.error("TEST-UNEXPECTED-FAIL | %s | application terminated with exit code %s" % (self.lastTestSeen, status)) else: self.lastTestSeen = 'Main app process exited normally' - log.info("runtests.py | Application ran for: %s" % str(datetime.now() - startTime)) + self.log.info("runtests.py | Application ran for: %s" % str(datetime.now() - startTime)) # Do a final check for zombie child processes. zombieProcesses = self.checkForZombies(processLog, utilityPath, debuggerInfo) @@ -1542,7 +1550,7 @@ class Mochitest(MochitestUtilsMixin): continue if not self.isTest(options, tp): - log.warning('Warning: %s from manifest %s is not a valid test' % (test['name'], test['manifest'])) + self.log.warning('Warning: %s from manifest %s is not a valid test' % (test['name'], test['manifest'])) continue testob = {'path': tp} @@ -1567,7 +1575,7 @@ class Mochitest(MochitestUtilsMixin): testsToRun = [] for test in tests: if test.has_key('disabled'): - log.info('TEST-SKIPPED | %s | %s' % (test['path'], test['disabled'])) + self.log.info('TEST-SKIPPED | %s | %s' % (test['path'], test['disabled'])) continue testsToRun.append(test['path']) @@ -1677,9 +1685,9 @@ class Mochitest(MochitestUtilsMixin): options.debuggerInteractive) if options.useTestMediaDevices: - devices = findTestMediaDevices() + devices = findTestMediaDevices(self.log) if not devices: - log.error("Could not find test media devices to use") + self.log.error("Could not find test media devices to use") return 1 self.mediaDevices = devices @@ -1746,7 +1754,7 @@ class Mochitest(MochitestUtilsMixin): # detect shutdown leaks for m-bc runs detectShutdownLeaks = mozinfo.info["debug"] and options.browserChrome and not options.webapprtChrome - log.info("runtests.py | Running tests: start.\n") + self.log.info("runtests.py | Running tests: start.\n") try: status = self.runApp(testURL, self.browserEnv, @@ -1765,11 +1773,11 @@ class Mochitest(MochitestUtilsMixin): quiet=options.quiet ) except KeyboardInterrupt: - log.info("runtests.py | Received keyboard interrupt.\n"); + self.log.info("runtests.py | Received keyboard interrupt.\n"); status = -1 except: traceback.print_exc() - log.error("Automation Error: Received unexpected exception while running application\n") + self.log.error("Automation Error: Received unexpected exception while running application\n") status = 1 finally: @@ -1785,7 +1793,7 @@ class Mochitest(MochitestUtilsMixin): logzip.write(logfile) os.remove(logfile) - log.info("runtests.py | Running tests: end.") + self.log.info("runtests.py | Running tests: end.") if self.manifest is not None: self.cleanup(options) @@ -1802,7 +1810,7 @@ class Mochitest(MochitestUtilsMixin): self.message_logger.dump_buffered() self.message_logger.buffering = False - log.error(error_message) + self.log.error(error_message) browserProcessId = browserProcessId or proc.pid self.killAndGetStack(browserProcessId, utilityPath, debuggerInfo, dump_screen=not debuggerInfo) @@ -1909,7 +1917,7 @@ class Mochitest(MochitestUtilsMixin): self.stackFixerProcess.communicate() status = self.stackFixerProcess.returncode if status and not didTimeout: - log.info("TEST-UNEXPECTED-FAIL | runtests.py | Stack fixer process exited with code %d during test run" % status) + self.harness.log.info("TEST-UNEXPECTED-FAIL | runtests.py | Stack fixer process exited with code %d during test run" % status) if self.shutdownLeaks: self.shutdownLeaks.process() @@ -2053,15 +2061,16 @@ class Mochitest(MochitestUtilsMixin): return dirlist def main(): - # parse command line options - mochitest = Mochitest() parser = MochitestOptions() + add_logging_group(parser) options, args = parser.parse_args() - options = parser.verifyOptions(options, mochitest) if options is None: # parsing error sys.exit(1) + logger_options = {key: value for key, value in vars(options).iteritems() if key.startswith('log')} + mochitest = Mochitest(logger_options) + options = parser.verifyOptions(options, mochitest) options.utilityPath = mochitest.getFullPath(options.utilityPath) options.certPath = mochitest.getFullPath(options.certPath) diff --git a/testing/mochitest/runtestsb2g.py b/testing/mochitest/runtestsb2g.py index 259c5a470e30..b9010e6d7b15 100644 --- a/testing/mochitest/runtestsb2g.py +++ b/testing/mochitest/runtestsb2g.py @@ -17,27 +17,21 @@ sys.path.insert(0, here) from automationutils import processLeakLog from runtests import Mochitest from runtests import MochitestUtilsMixin -from runtests import MessageLogger -from runtests import MochitestFormatter from mochitest_options import B2GOptions, MochitestOptions from marionette import Marionette from mozprofile import Profile, Preferences +from mozlog import structured import mozinfo -from mozlog.structured.handlers import StreamHandler -from mozlog.structured.structuredlog import StructuredLogger - -log = StructuredLogger('Mochitest') -stream_handler = StreamHandler(stream=sys.stdout, formatter=MochitestFormatter()) -log.add_handler(stream_handler) class B2GMochitest(MochitestUtilsMixin): marionette = None def __init__(self, marionette_args, + logger_options, out_of_process=True, profile_data_dir=None, locations=os.path.join(here, 'server-locations.txt')): - super(B2GMochitest, self).__init__() + super(B2GMochitest, self).__init__(logger_options) self.marionette_args = marionette_args self.out_of_process = out_of_process self.locations_file = locations @@ -47,9 +41,6 @@ class B2GMochitest(MochitestUtilsMixin): self.test_script_args = [self.out_of_process] self.product = 'b2g' - # structured logging - self.message_logger = MessageLogger(logger=log) - if profile_data_dir: self.preferences = [os.path.join(profile_data_dir, f) for f in os.listdir(profile_data_dir) if f.startswith('pref')] @@ -136,7 +127,7 @@ class B2GMochitest(MochitestUtilsMixin): options.timeout = 300 timeout = options.timeout + 30.0 - log.info("runtestsb2g.py | Running tests: start.") + self.log.info("runtestsb2g.py | Running tests: start.") status = 0 try: def on_output(line): @@ -213,18 +204,18 @@ class B2GMochitest(MochitestUtilsMixin): processLeakLog(local_leak_file.name, options.leakThreshold) except KeyboardInterrupt: - log.info("runtests.py | Received keyboard interrupt.\n"); + self.log.info("runtests.py | Received keyboard interrupt.\n"); status = -1 except: traceback.print_exc() - log.error("Automation Error: Received unexpected exception while running application\n") + self.log.error("Automation Error: Received unexpected exception while running application\n") if hasattr(self, 'runner'): self.runner.check_for_crashes() status = 1 self.stopServers() - log.info("runtestsb2g.py | Running tests: end.") + self.log.info("runtestsb2g.py | Running tests: end.") if manifest is not None: self.cleanup(manifest, options) @@ -238,9 +229,9 @@ class B2GMochitest(MochitestUtilsMixin): class B2GDeviceMochitest(B2GMochitest, Mochitest): remote_log = None - def __init__(self, marionette_args, profile_data_dir, + def __init__(self, marionette_args, logger_options, profile_data_dir, local_binary_dir, remote_test_root=None, remote_log_file=None): - B2GMochitest.__init__(self, marionette_args, out_of_process=True, profile_data_dir=profile_data_dir) + B2GMochitest.__init__(self, marionette_args, logger_options, out_of_process=True, profile_data_dir=profile_data_dir) self.local_log = None self.local_binary_dir = local_binary_dir @@ -294,9 +285,9 @@ class B2GDeviceMochitest(B2GMochitest, Mochitest): class B2GDesktopMochitest(B2GMochitest, Mochitest): - def __init__(self, marionette_args, profile_data_dir): - B2GMochitest.__init__(self, marionette_args, out_of_process=False, profile_data_dir=profile_data_dir) - Mochitest.__init__(self) + def __init__(self, marionette_args, logger_options, profile_data_dir): + B2GMochitest.__init__(self, marionette_args, logger_options, out_of_process=False, profile_data_dir=profile_data_dir) + Mochitest.__init__(self, logger_options) self.certdbNew = True def runMarionetteScript(self, marionette, test_script, test_script_args): @@ -363,8 +354,8 @@ def run_remote_mochitests(parser, options): print "ERROR: Invalid options specified, use --help for a list of valid options" sys.exit(1) - mochitest = B2GDeviceMochitest(marionette_args, options.profile_data_dir, options.xrePath, - remote_log_file=options.remoteLogFile) + mochitest = B2GDeviceMochitest(marionette_args, options, options.profile_data_dir, + options.xrePath, remote_log_file=options.remoteLogFile) options = parser.verifyOptions(options, mochitest) if (options == None): @@ -395,13 +386,13 @@ def run_desktop_mochitests(parser, options): host, port = options.marionette.split(':') marionette_args['host'] = host marionette_args['port'] = int(port) - mochitest = B2GDesktopMochitest(marionette_args, options.profile_data_dir) # add a -bin suffix if b2g-bin exists, but just b2g was specified if options.app[-4:] != '-bin': if os.path.isfile("%s-bin" % options.app): options.app = "%s-bin" % options.app + mochitest = B2GDesktopMochitest(marionette_args, options, options.profile_data_dir) options = MochitestOptions.verifyOptions(parser, options, mochitest) if options == None: sys.exit(1) @@ -418,6 +409,7 @@ def run_desktop_mochitests(parser, options): def main(): parser = B2GOptions() + structured.commandline.add_logging_group(parser) options, args = parser.parse_args() if options.desktop: diff --git a/testing/mochitest/runtestsremote.py b/testing/mochitest/runtestsremote.py index cc9d359c0876..4434ff883e93 100644 --- a/testing/mochitest/runtestsremote.py +++ b/testing/mochitest/runtestsremote.py @@ -4,6 +4,7 @@ import base64 import json +import logging import math import os import re @@ -16,20 +17,15 @@ sys.path.insert(0, os.path.abspath(os.path.realpath(os.path.dirname(__file__)))) from automation import Automation from remoteautomation import RemoteAutomation, fennecLogcatFilters -from runtests import Mochitest, MessageLogger, MochitestFormatter +from runtests import Mochitest, MessageLogger from mochitest_options import MochitestOptions +from mozlog import structured import devicemanager import droid import manifestparser import mozinfo import moznetwork -from mozlog.structured.handlers import StreamHandler -from mozlog.structured.structuredlog import StructuredLogger - -log = StructuredLogger('Mochi-Remote') -stream_handler = StreamHandler(stream=sys.stdout, formatter=MochitestFormatter()) -log.add_handler(stream_handler) SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__))) @@ -125,6 +121,8 @@ class RemoteOptions(MochitestOptions): self.set_defaults(**defaults) def verifyRemoteOptions(self, options, automation): + options_logger = logging.getLogger('MochitestRemote') + if not options.remoteTestRoot: options.remoteTestRoot = automation._devicemanager.deviceRoot @@ -132,13 +130,13 @@ class RemoteOptions(MochitestOptions): if os.name != "nt": options.remoteWebServer = moznetwork.get_ip() else: - log.error("you must specify a --remote-webserver=") + options_logger.error("you must specify a --remote-webserver=") return None options.webServer = options.remoteWebServer if (options.deviceIP == None): - log.error("you must provide a device IP") + options_logger.error("you must provide a device IP") return None if (options.remoteLogFile == None): @@ -149,13 +147,13 @@ class RemoteOptions(MochitestOptions): # remoteAppPath or app must be specified to find the product to launch if (options.remoteAppPath and options.app): - log.error("You cannot specify both the remoteAppPath and the app setting") + options_logger.error("You cannot specify both the remoteAppPath and the app setting") return None elif (options.remoteAppPath): options.app = options.remoteTestRoot + "/" + options.remoteAppPath elif (options.app == None): # Neither remoteAppPath nor app are set -- error - log.error("You must specify either appPath or app") + options_logger.error("You must specify either appPath or app") return None # Only reset the xrePath if it wasn't provided @@ -170,14 +168,14 @@ class RemoteOptions(MochitestOptions): # Robocop specific deprecated options. if options.robocop: if options.robocopIni: - log.error("can not use deprecated --robocop and replacement --robocop-ini together") + options_logger.error("can not use deprecated --robocop and replacement --robocop-ini together") return None options.robocopIni = options.robocop del options.robocop if options.robocopPath: if options.robocopApk: - log.error("can not use deprecated --robocop-path and replacement --robocop-apk together") + options_logger.error("can not use deprecated --robocop-path and replacement --robocop-apk together") return None options.robocopApk = os.path.join(options.robocopPath, 'robocop.apk') del options.robocopPath @@ -185,19 +183,19 @@ class RemoteOptions(MochitestOptions): # Robocop specific options if options.robocopIni != "": if not os.path.exists(options.robocopIni): - log.error("Unable to find specified robocop .ini manifest '%s'" % options.robocopIni) + options_logger.error("Unable to find specified robocop .ini manifest '%s'" % options.robocopIni) return None options.robocopIni = os.path.abspath(options.robocopIni) if options.robocopApk != "": if not os.path.exists(options.robocopApk): - log.error("Unable to find robocop APK '%s'" % options.robocopApk) + options_logger.error("Unable to find robocop APK '%s'" % options.robocopApk) return None options.robocopApk = os.path.abspath(options.robocopApk) if options.robocopIds != "": if not os.path.exists(options.robocopIds): - log.error("Unable to find specified robocop IDs file '%s'" % options.robocopIds) + options_logger.error("Unable to find specified robocop IDs file '%s'" % options.robocopIds) return None options.robocopIds = os.path.abspath(options.robocopIds) @@ -230,9 +228,10 @@ class MochiRemote(Mochitest): localProfile = None logMessages = [] - def __init__(self, automation, devmgr, options, message_logger=None): + def __init__(self, automation, devmgr, options): + Mochitest.__init__(self, options) + self._automation = automation - Mochitest.__init__(self) self._dm = devmgr self.environment = self._automation.environment self.remoteProfile = options.remoteTestRoot + "/profile" @@ -246,15 +245,12 @@ class MochiRemote(Mochitest): self._dm.removeDir(self.remoteNSPR); self._dm.mkDir(self.remoteNSPR); - # structured logging - self.message_logger = message_logger or MessageLogger(logger=log) - def cleanup(self, options): if self._dm.fileExists(self.remoteLog): self._dm.getFile(self.remoteLog, self.localLog) self._dm.removeFile(self.remoteLog) else: - log.warning("Unable to retrieve log file (%s) from remote device" % self.remoteLog) + self.log.warning("Unable to retrieve log file (%s) from remote device" % self.remoteLog) self._dm.removeDir(self.remoteProfile) self._dm.getDirectory(self.remoteNSPR, os.environ["MOZ_UPLOAD_DIR"]) Mochitest.cleanup(self, options) @@ -305,7 +301,7 @@ class MochiRemote(Mochitest): ] options.xrePath = self.findPath(paths) if options.xrePath == None: - log.error("unable to find xulrunner path for %s, please specify with --xre-path" % os.name) + self.log.error("unable to find xulrunner path for %s, please specify with --xre-path" % os.name) sys.exit(1) xpcshell = "xpcshell" @@ -319,12 +315,12 @@ class MochiRemote(Mochitest): options.utilityPath = self.findPath(paths, xpcshell) if options.utilityPath == None: - log.error("unable to find utility path for %s, please specify with --utility-path" % os.name) + self.log.error("unable to find utility path for %s, please specify with --utility-path" % os.name) sys.exit(1) xpcshell_path = os.path.join(options.utilityPath, xpcshell) if localAutomation.elf_arm(xpcshell_path): - log.error('xpcshell at %s is an ARM binary; please use ' + self.log.error('xpcshell at %s is an ARM binary; please use ' 'the --utility-path argument to specify the path ' 'to a desktop version.' % xpcshell_path) sys.exit(1) @@ -364,7 +360,7 @@ class MochiRemote(Mochitest): try: self._dm.pushDir(options.profilePath, self.remoteProfile) except devicemanager.DMError: - log.error("Automation Error: Unable to copy profile to device.") + self.log.error("Automation Error: Unable to copy profile to device.") raise restoreRemotePaths() @@ -383,7 +379,7 @@ class MochiRemote(Mochitest): try: self._dm.pushDir(options.profilePath, self.remoteProfile) except devicemanager.DMError: - log.error("Automation Error: Unable to copy profile to device.") + self.log.error("Automation Error: Unable to copy profile to device.") raise options.profilePath = self.remoteProfile @@ -414,7 +410,7 @@ class MochiRemote(Mochitest): try: self._dm.pushFile(filename, manifest) except devicemanager.DMError: - log.error("Automation Error: Unable to install Chrome files on device.") + self.log.error("Automation Error: Unable to install Chrome files on device.") raise return manifest @@ -453,7 +449,7 @@ class MochiRemote(Mochitest): if fail_found: result = 1 if not end_found: - log.error("Automation Error: Missing end of test marker (process crashed?)") + self.log.error("Automation Error: Missing end of test marker (process crashed?)") result = 1 return result @@ -498,33 +494,33 @@ class MochiRemote(Mochitest): def printScreenshots(self, screenShotDir): # TODO: This can be re-written after completion of bug 749421 if not self._dm.dirExists(screenShotDir): - log.info("SCREENSHOT: No ScreenShots directory available: " + screenShotDir) + self.log.info("SCREENSHOT: No ScreenShots directory available: " + screenShotDir) return printed = 0 for name in self._dm.listFiles(screenShotDir): fullName = screenShotDir + "/" + name - log.info("SCREENSHOT: FOUND: [%s]" % fullName) + self.log.info("SCREENSHOT: FOUND: [%s]" % fullName) try: image = self._dm.pullFile(fullName) encoded = base64.b64encode(image) - log.info("SCREENSHOT: data:image/jpg;base64,%s" % encoded) + self.log.info("SCREENSHOT: data:image/jpg;base64,%s" % encoded) printed += 1 except: - log.info("SCREENSHOT: Could not be parsed") + self.log.info("SCREENSHOT: Could not be parsed") pass - log.info("SCREENSHOT: TOTAL PRINTED: [%s]" % printed) + self.log.info("SCREENSHOT: TOTAL PRINTED: [%s]" % printed) def printDeviceInfo(self, printLogcat=False): try: if printLogcat: logcat = self._dm.getLogcat(filterOutRegexps=fennecLogcatFilters) - log.info('\n' + ''.join(logcat).decode('utf-8', 'replace')) - log.info("Device info: %s" % self._dm.getInfo()) - log.info("Test root: %s" % self._dm.deviceRoot) + self.log.info('\n' + ''.join(logcat).decode('utf-8', 'replace')) + self.log.info("Device info: %s" % self._dm.getInfo()) + self.log.info("Test root: %s" % self._dm.deviceRoot) except devicemanager.DMError: - log.warn("Error getting device information") + self.log.warning("Error getting device information") def buildRobotiumConfig(self, options, browserEnv): deviceRoot = self._dm.deviceRoot @@ -543,8 +539,8 @@ class MochiRemote(Mochitest): for key, value in browserEnv.items(): try: value.index(',') - log.error("buildRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" % (key, value)) - log.error("browserEnv=%s" % browserEnv) + self.log.error("buildRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" % (key, value)) + self.log.error("browserEnv=%s" % browserEnv) except ValueError: envstr += "%s%s=%s" % (delim, key, value) delim = "," @@ -586,10 +582,12 @@ class MochiRemote(Mochitest): return self._automation.runApp(*args, **kwargs) def main(): - message_logger = MessageLogger(logger=log) + message_logger = MessageLogger(logger=None) process_args = {'messageLogger': message_logger} auto = RemoteAutomation(None, "fennec", processArgs=process_args) + parser = RemoteOptions(auto) + structured.commandline.add_logging_group(parser) options, args = parser.parse_args() if (options.dm_trans == "adb"): @@ -601,6 +599,14 @@ def main(): dm = droid.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot) auto.setDeviceManager(dm) options = parser.verifyRemoteOptions(options, auto) + + mochitest = MochiRemote(auto, dm, options) + + log = mochitest.log + structured_logger = mochitest.structured_logger + message_logger.logger = mochitest.structured_logger + mochitest.message_logger = message_logger + if (options == None): log.error("Invalid options specified, use --help for a list of valid options") sys.exit(1) @@ -612,8 +618,6 @@ def main(): auto.setProduct(options.remoteProductName) auto.setAppName(options.remoteappname) - mochitest = MochiRemote(auto, dm, options, message_logger) - options = parser.verifyOptions(options, mochitest) if (options == None): sys.exit(1) @@ -699,7 +703,7 @@ def main(): active_tests.append(test) - log.suite_start([t['name'] for t in active_tests]) + structured_logger.suite_start([t['name'] for t in active_tests]) for test in active_tests: # When running in a loop, we need to create a fresh profile for each cycle diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py index 4928c6c03c0c..41825ba22647 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py @@ -235,7 +235,7 @@ class DeviceManagerSUT(DeviceManager): # Wait up to a second for socket to become ready for reading... if select.select([self._sock], [], [], select_timeout)[0]: temp = self._sock.recv(1024) - self._logger.debug("response: %s" % temp) + self._logger.debug(u"response: %s" % temp.decode('utf8', 'replace')) timer = 0 if not temp: socketClosed = True From ab701788514610d36a8e1aa5886988257f01a6ae Mon Sep 17 00:00:00 2001 From: JW Wang Date: Wed, 13 Aug 2014 20:08:00 -0400 Subject: [PATCH 044/119] Bug 1046756 - Wait until AudioInitTask finished before proceeding to Shutdown(). r=kinetik --- content/media/AudioStream.cpp | 44 +++++++++++++++++++++-------------- content/media/AudioStream.h | 4 ++++ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/content/media/AudioStream.cpp b/content/media/AudioStream.cpp index 04c160c5ff5a..02a5282a9953 100644 --- a/content/media/AudioStream.cpp +++ b/content/media/AudioStream.cpp @@ -17,6 +17,7 @@ #include "mozilla/Telemetry.h" #include "soundtouch/SoundTouch.h" #include "Latency.h" +#include "nsPrintfCString.h" #ifdef XP_MACOSX #include #endif @@ -254,6 +255,7 @@ AudioStream::AudioStream() , mState(INITIALIZED) , mNeedsStart(false) , mShouldDropFrames(false) + , mPendingAudioInitTask(false) { // keep a ref in case we shut down later than nsLayoutStatics mLatencyLog = AsyncLatencyLogger::Get(true); @@ -535,19 +537,24 @@ AudioStream::Init(int32_t aNumChannels, int32_t aRate, // cause us to move from INITIALIZED to RUNNING. Until then, we // can't access any cubeb functions. // Use a RefPtr to avoid leaks if Dispatch fails + mPendingAudioInitTask = true; RefPtr init = new AudioInitTask(this, aLatencyRequest, params); - init->Dispatch(); - return NS_OK; + nsresult rv = init->Dispatch(); + if (NS_FAILED(rv)) { + mPendingAudioInitTask = false; + } + return rv; } // High latency - open synchronously nsresult rv = OpenCubeb(params, aLatencyRequest); + NS_ENSURE_SUCCESS(rv, rv); // See if we need to start() the stream, since we must do that from this // thread for now (cubeb API issue) { MonitorAutoLock mon(mMonitor); CheckForStart(); } - return rv; + return NS_OK; } // On certain MacBookPro, the microphone is located near the left speaker. @@ -627,15 +634,9 @@ nsresult AudioStream::OpenCubeb(cubeb_stream_params &aParams, LatencyRequest aLatencyRequest) { - { - MonitorAutoLock mon(mMonitor); - if (mState == AudioStream::SHUTDOWN) { - return NS_ERROR_FAILURE; - } - } - cubeb* cubebContext = GetCubebContext(); if (!cubebContext) { + NS_WARNING("Can't get cubeb context!"); MonitorAutoLock mon(mMonitor); mState = AudioStream::ERRORED; return NS_ERROR_FAILURE; @@ -658,21 +659,15 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams, if (cubeb_stream_init(cubebContext, &stream, "AudioStream", aParams, latency, DataCallback_S, StateCallback_S, this) == CUBEB_OK) { MonitorAutoLock mon(mMonitor); + MOZ_ASSERT(mState != SHUTDOWN); mCubebStream.own(stream); - // Make sure we weren't shut down while in flight! - if (mState == SHUTDOWN) { - mCubebStream.reset(); - LOG(("AudioStream::OpenCubeb() %p Shutdown while opening cubeb", this)); - return NS_ERROR_FAILURE; - } - // We can't cubeb_stream_start() the thread from a transient thread due to // cubeb API requirements (init can be called from another thread, but // not start/stop/destroy/etc) } else { MonitorAutoLock mon(mMonitor); mState = ERRORED; - LOG(("AudioStream::OpenCubeb() %p failed to init cubeb", this)); + NS_WARNING(nsPrintfCString("AudioStream::OpenCubeb() %p failed to init cubeb", this).get()); return NS_ERROR_FAILURE; } } @@ -693,6 +688,14 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams, return NS_OK; } +void +AudioStream::AudioInitTaskFinished() +{ + MonitorAutoLock mon(mMonitor); + mPendingAudioInitTask = false; + mon.NotifyAll(); +} + void AudioStream::CheckForStart() { @@ -731,6 +734,7 @@ AudioInitTask::Run() } nsresult rv = mAudioStream->OpenCubeb(mParams, mLatencyRequest); + mAudioStream->AudioInitTaskFinished(); // and now kill this thread NS_DispatchToMainThread(this); @@ -951,6 +955,10 @@ AudioStream::Shutdown() MonitorAutoLock mon(mMonitor); LOG(("AudioStream: Shutdown %p, state %d", this, mState)); + while (mPendingAudioInitTask) { + mon.Wait(); + } + if (mCubebStream) { MonitorAutoUnlock mon(mMonitor); // Force stop to put the cubeb stream in a stable state before deletion. diff --git a/content/media/AudioStream.h b/content/media/AudioStream.h index c2914b2f7425..927a5438ddb3 100644 --- a/content/media/AudioStream.h +++ b/content/media/AudioStream.h @@ -299,6 +299,7 @@ private: // So we can call it asynchronously from AudioInitTask nsresult OpenCubeb(cubeb_stream_params &aParams, LatencyRequest aLatencyRequest); + void AudioInitTaskFinished(); void CheckForStart(); @@ -425,6 +426,9 @@ private: // is not going to be called for a little while, simply drop incoming frames. // This is only on OSX for now, because other systems handle this gracefully. bool mShouldDropFrames; + // True if there is a pending AudioInitTask. Shutdown() will wait until the + // pending AudioInitTask is finished. + bool mPendingAudioInitTask; // This mutex protects the static members below. static StaticMutex sMutex; From f19a6b8ed494dcf2ee83433232e7154bb1e6e5a2 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 14 Aug 2014 10:00:37 -0500 Subject: [PATCH 045/119] Bug 1053544 - OdinMonkey: issue link-time validation error when given non-primitive import value (r=bbouvier) --- js/src/asmjs/AsmJSLink.cpp | 5 +++++ js/src/jit-test/tests/asm.js/testGlobals.js | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/js/src/asmjs/AsmJSLink.cpp b/js/src/asmjs/AsmJSLink.cpp index 2e52f41bb5c4..4a057fe647aa 100644 --- a/js/src/asmjs/AsmJSLink.cpp +++ b/js/src/asmjs/AsmJSLink.cpp @@ -123,6 +123,9 @@ ValidateGlobalVariable(JSContext *cx, const AsmJSModule &module, AsmJSModule::Gl if (!GetDataProperty(cx, importVal, field, &v)) return false; + if (!v.isPrimitive()) + return LinkFail(cx, "Imported values must be primitives"); + switch (global.varInitCoercion()) { case AsmJS_ToInt32: if (!ToInt32(cx, v, (int32_t *)datum)) @@ -181,6 +184,7 @@ ValidateMathBuiltinFunction(JSContext *cx, AsmJSModule::Global &global, HandleVa RootedValue v(cx); if (!GetDataProperty(cx, globalVal, cx->names().Math, &v)) return false; + RootedPropertyName field(cx, global.mathName()); if (!GetDataProperty(cx, v, field, &v)) return false; @@ -226,6 +230,7 @@ ValidateConstant(JSContext *cx, AsmJSModule::Global &global, HandleValue globalV if (!GetDataProperty(cx, v, field, &v)) return false; + if (!v.isNumber()) return LinkFail(cx, "math / global constant value needs to be a number"); diff --git a/js/src/jit-test/tests/asm.js/testGlobals.js b/js/src/jit-test/tests/asm.js/testGlobals.js index 37d5938ee469..28386a2008d5 100644 --- a/js/src/jit-test/tests/asm.js/testGlobals.js +++ b/js/src/jit-test/tests/asm.js/testGlobals.js @@ -1,4 +1,5 @@ load(libdir + "asm.js"); +load(libdir + "asserts.js"); assertAsmTypeFail(USE_ASM + "var i; function f(){} return f"); assertAsmTypeFail(USE_ASM + "const i; function f(){} return f"); @@ -117,6 +118,14 @@ assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4); assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4); assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var i=42; while (1) { break; } g = i; return g|0 } return f"))(), 42); +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}}); +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}}); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f'), null, {x:"blah"})(), 0); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() { return +i} return f'), null, {x:"blah"})(), NaN); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f'), this, {x:"blah"})(), NaN); +assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f')(null, {x:Symbol("blah")}), TypeError); +assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = +foreign.x; function f() { return +i} return f')(null, {x:Symbol("blah")}), TypeError); +assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f')(this, {x:Symbol("blah")}), TypeError); var f1 = asmCompile('global', 'foreign', 'heap', USE_ASM + 'var i32 = new global.Int32Array(heap); function g() { return i32[4]|0 } return g'); var global = this; From b7977bc57cb0c2c71b60209c9c0e1092747d2b78 Mon Sep 17 00:00:00 2001 From: Theodore Kokkoris Date: Tue, 12 Aug 2014 18:59:56 +0300 Subject: [PATCH 046/119] Bug 1052100 - Make updater respect mobile hotspot setting on Android. r=snorp --HG-- extra : histedit_source : 85a2017bd4e6e68a5a7d1b7b1dbf9fdb0d45b59c --- mobile/android/base/updater/UpdateService.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/updater/UpdateService.java b/mobile/android/base/updater/UpdateService.java index 356e47253074..9a48b6bee26f 100644 --- a/mobile/android/base/updater/UpdateService.java +++ b/mobile/android/base/updater/UpdateService.java @@ -208,7 +208,6 @@ public class UpdateService extends IntentService { Log.i(LOGTAG, "update available, buildID = " + info.buildID); - int connectionType = netInfo.getType(); int autoDownloadPolicy = getAutoDownloadPolicy(); @@ -217,12 +216,11 @@ public class UpdateService extends IntentService { * * - We have a FORCE_DOWNLOAD flag passed in * - The preference is set to 'always' - * - The preference is set to 'wifi' and we are actually using wifi (or regular ethernet) + * - The preference is set to 'wifi' and we are using a non-metered network (i.e. the user is OK with large data transfers occuring) */ boolean shouldStartDownload = hasFlag(flags, UpdateServiceHelper.FLAG_FORCE_DOWNLOAD) || autoDownloadPolicy == UpdateServiceHelper.AUTODOWNLOAD_ENABLED || - (autoDownloadPolicy == UpdateServiceHelper.AUTODOWNLOAD_WIFI && - (connectionType == ConnectivityManager.TYPE_WIFI || connectionType == ConnectivityManager.TYPE_ETHERNET)); + (autoDownloadPolicy == UpdateServiceHelper.AUTODOWNLOAD_WIFI && !mConnectivityManager.isActiveNetworkMetered()); if (!shouldStartDownload) { Log.i(LOGTAG, "not initiating automatic update download due to policy " + autoDownloadPolicy); From 6930452844dabfa0ac8cd7b3807b525373cdfcbd Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Thu, 14 Aug 2014 17:25:12 +0200 Subject: [PATCH 047/119] Backed out changeset 04892482d288 (Bug 998485) for Octane regressions. --- js/src/jit/EdgeCaseAnalysis.cpp | 44 +++++++ js/src/jit/EdgeCaseAnalysis.h | 31 +++++ js/src/jit/Ion.cpp | 13 ++ js/src/jit/MIR.cpp | 206 ++++++++++++++++++++++++++++++++ js/src/jit/MIR.h | 11 ++ js/src/moz.build | 1 + 6 files changed, 306 insertions(+) create mode 100644 js/src/jit/EdgeCaseAnalysis.cpp create mode 100644 js/src/jit/EdgeCaseAnalysis.h diff --git a/js/src/jit/EdgeCaseAnalysis.cpp b/js/src/jit/EdgeCaseAnalysis.cpp new file mode 100644 index 000000000000..30a18249639d --- /dev/null +++ b/js/src/jit/EdgeCaseAnalysis.cpp @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "jit/EdgeCaseAnalysis.h" + +#include "jit/MIR.h" +#include "jit/MIRGraph.h" + +using namespace js; +using namespace js::jit; + +EdgeCaseAnalysis::EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph) + : mir(mir), graph(graph) +{ +} + +bool +EdgeCaseAnalysis::analyzeLate() +{ + // Renumber definitions for NeedNegativeZeroCheck under analyzeEdgeCasesBackward. + uint32_t nextId = 0; + + for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) { + if (mir->shouldCancel("Analyze Late (first loop)")) + return false; + for (MDefinitionIterator iter(*block); iter; iter++) { + iter->setId(nextId++); + iter->analyzeEdgeCasesForward(); + } + block->lastIns()->setId(nextId++); + } + + for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) { + if (mir->shouldCancel("Analyze Late (second loop)")) + return false; + for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++) + riter->analyzeEdgeCasesBackward(); + } + + return true; +} diff --git a/js/src/jit/EdgeCaseAnalysis.h b/js/src/jit/EdgeCaseAnalysis.h new file mode 100644 index 000000000000..3e38e7483cc7 --- /dev/null +++ b/js/src/jit/EdgeCaseAnalysis.h @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_EdgeCaseAnalysis_h +#define jit_EdgeCaseAnalysis_h + +#include "jit/MIRGenerator.h" + +namespace js { +namespace jit { + +class MIRGraph; + +class EdgeCaseAnalysis +{ + MIRGenerator *mir; + MIRGraph &graph; + + public: + EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph); + bool analyzeLate(); +}; + + +} // namespace jit +} // namespace js + +#endif /* jit_EdgeCaseAnalysis_h */ diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 45e011046e24..a5d8c44f1849 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -21,6 +21,7 @@ #include "jit/BaselineInspector.h" #include "jit/BaselineJIT.h" #include "jit/CodeGenerator.h" +#include "jit/EdgeCaseAnalysis.h" #include "jit/EffectiveAddressAnalysis.h" #include "jit/IonAnalysis.h" #include "jit/IonBuilder.h" @@ -1579,6 +1580,18 @@ OptimizeMIR(MIRGenerator *mir) // Passes after this point must not move instructions; these analyses // depend on knowing the final order in which instructions will execute. + if (mir->optimizationInfo().edgeCaseAnalysisEnabled()) { + AutoTraceLog log(logger, TraceLogger::EdgeCaseAnalysis); + EdgeCaseAnalysis edgeCaseAnalysis(mir, graph); + if (!edgeCaseAnalysis.analyzeLate()) + return false; + IonSpewPass("Edge Case Analysis (Late)"); + AssertGraphCoherency(graph); + + if (mir->shouldCancel("Edge Case Analysis (Late)")) + return false; + } + if (mir->optimizationInfo().eliminateRedundantChecksEnabled()) { AutoTraceLog log(logger, TraceLogger::EliminateRedundantChecks); // Note: check elimination has to run after all other passes that move diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index f6339a364830..39874ca40540 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -222,6 +222,16 @@ MDefinition::foldsTo(TempAllocator &alloc) return this; } +void +MDefinition::analyzeEdgeCasesForward() +{ +} + +void +MDefinition::analyzeEdgeCasesBackward() +{ +} + static bool MaybeEmulatesUndefined(MDefinition *op) { @@ -1394,6 +1404,109 @@ MUrsh::infer(BaselineInspector *inspector, jsbytecode *pc) setResultType(MIRType_Int32); } +static inline bool +NeedNegativeZeroCheck(MDefinition *def) +{ + // Test if all uses have the same semantics for -0 and 0 + for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) { + if (use->consumer()->isResumePoint()) + continue; + + MDefinition *use_def = use->consumer()->toDefinition(); + switch (use_def->op()) { + case MDefinition::Op_Add: { + // If add is truncating -0 and 0 are observed as the same. + if (use_def->toAdd()->isTruncated()) + break; + + // x + y gives -0, when both x and y are -0 + + // Figure out the order in which the addition's operands will + // execute. EdgeCaseAnalysis::analyzeLate has renumbered the MIR + // definitions for us so that this just requires comparing ids. + MDefinition *first = use_def->toAdd()->getOperand(0); + MDefinition *second = use_def->toAdd()->getOperand(1); + if (first->id() > second->id()) { + MDefinition *temp = first; + first = second; + second = temp; + } + + if (def == first) { + // Negative zero checks can be removed on the first executed + // operand only if it is guaranteed the second executed operand + // will produce a value other than -0. While the second is + // typed as an int32, a bailout taken between execution of the + // operands may change that type and cause a -0 to flow to the + // second. + // + // There is no way to test whether there are any bailouts + // between execution of the operands, so remove negative + // zero checks from the first only if the second's type is + // independent from type changes that may occur after bailing. + switch (second->op()) { + case MDefinition::Op_Constant: + case MDefinition::Op_BitAnd: + case MDefinition::Op_BitOr: + case MDefinition::Op_BitXor: + case MDefinition::Op_BitNot: + case MDefinition::Op_Lsh: + case MDefinition::Op_Rsh: + break; + default: + return true; + } + } + + // The negative zero check can always be removed on the second + // executed operand; by the time this executes the first will have + // been evaluated as int32 and the addition's result cannot be -0. + break; + } + case MDefinition::Op_Sub: + // If sub is truncating -0 and 0 are observed as the same + if (use_def->toSub()->isTruncated()) + break; + /* Fall through... */ + case MDefinition::Op_StoreElement: + case MDefinition::Op_StoreElementHole: + case MDefinition::Op_LoadElement: + case MDefinition::Op_LoadElementHole: + case MDefinition::Op_LoadTypedArrayElement: + case MDefinition::Op_LoadTypedArrayElementHole: + case MDefinition::Op_CharCodeAt: + case MDefinition::Op_Mod: + // Only allowed to remove check when definition is the second operand + if (use_def->getOperand(0) == def) + return true; + for (size_t i = 2, e = use_def->numOperands(); i < e; i++) { + if (use_def->getOperand(i) == def) + return true; + } + break; + case MDefinition::Op_BoundsCheck: + // Only allowed to remove check when definition is the first operand + if (use_def->toBoundsCheck()->getOperand(1) == def) + return true; + break; + case MDefinition::Op_ToString: + case MDefinition::Op_FromCharCode: + case MDefinition::Op_TableSwitch: + case MDefinition::Op_Compare: + case MDefinition::Op_BitAnd: + case MDefinition::Op_BitOr: + case MDefinition::Op_BitXor: + case MDefinition::Op_Abs: + case MDefinition::Op_TruncateToInt32: + // Always allowed to remove check. No matter which operand. + break; + default: + return true; + } + } + return false; +} + MDefinition * MBinaryArithInstruction::foldsTo(TempAllocator &alloc) { @@ -1507,6 +1620,45 @@ MDiv::foldsTo(TempAllocator &alloc) return this; } +void +MDiv::analyzeEdgeCasesForward() +{ + // This is only meaningful when doing integer division. + if (specialization_ != MIRType_Int32) + return; + + // Try removing divide by zero check + if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0)) + canBeDivideByZero_ = false; + + // If lhs is a constant int != INT32_MIN, then + // negative overflow check can be skipped. + if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(INT32_MIN)) + canBeNegativeOverflow_ = false; + + // If rhs is a constant int != -1, likewise. + if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(-1)) + canBeNegativeOverflow_ = false; + + // If lhs is != 0, then negative zero check can be skipped. + if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(0)) + setCanBeNegativeZero(false); + + // If rhs is >= 0, likewise. + if (rhs()->isConstant()) { + const js::Value &val = rhs()->toConstant()->value(); + if (val.isInt32() && val.toInt32() >= 0) + setCanBeNegativeZero(false); + } +} + +void +MDiv::analyzeEdgeCasesBackward() +{ + if (canBeNegativeZero() && !NeedNegativeZeroCheck(this)) + setCanBeNegativeZero(false); +} + bool MDiv::fallible() const { @@ -1525,6 +1677,23 @@ MMod::foldsTo(TempAllocator &alloc) return this; } +void +MMod::analyzeEdgeCasesForward() +{ + // These optimizations make sense only for integer division + if (specialization_ != MIRType_Int32) + return; + + if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0)) + canBeDivideByZero_ = false; + + if (rhs()->isConstant()) { + int32_t n = rhs()->toConstant()->value().toInt32(); + if (n > 0 && !IsPowerOfTwo(n)) + canBePowerOfTwoDivisor_ = false; + } +} + bool MMod::fallible() const { @@ -1584,6 +1753,36 @@ MMul::foldsTo(TempAllocator &alloc) return this; } +void +MMul::analyzeEdgeCasesForward() +{ + // Try to remove the check for negative zero + // This only makes sense when using the integer multiplication + if (specialization() != MIRType_Int32) + return; + + // If lhs is > 0, no need for negative zero check. + if (lhs()->isConstant()) { + const js::Value &val = lhs()->toConstant()->value(); + if (val.isInt32() && val.toInt32() > 0) + setCanBeNegativeZero(false); + } + + // If rhs is > 0, likewise. + if (rhs()->isConstant()) { + const js::Value &val = rhs()->toConstant()->value(); + if (val.isInt32() && val.toInt32() > 0) + setCanBeNegativeZero(false); + } +} + +void +MMul::analyzeEdgeCasesBackward() +{ + if (canBeNegativeZero() && !NeedNegativeZeroCheck(this)) + setCanBeNegativeZero(false); +} + bool MMul::updateForReplacement(MDefinition *ins_) { @@ -2284,6 +2483,13 @@ MToInt32::foldsTo(TempAllocator &alloc) return this; } +void +MToInt32::analyzeEdgeCasesBackward() +{ + if (!NeedNegativeZeroCheck(this)) + setCanBeNegativeZero(false); +} + MDefinition * MTruncateToInt32::foldsTo(TempAllocator &alloc) { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 82878332afd6..93277f2b6a23 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -482,6 +482,8 @@ class MDefinition : public MNode } bool congruentIfOperandsEqual(const MDefinition *ins) const; virtual MDefinition *foldsTo(TempAllocator &alloc); + virtual void analyzeEdgeCasesForward(); + virtual void analyzeEdgeCasesBackward(); // When a floating-point value is used by nodes which would prefer to // recieve integer inputs, we may be able to help by computing our result @@ -3802,6 +3804,9 @@ class MToInt32 MDefinition *foldsTo(TempAllocator &alloc); + // this only has backwards information flow. + void analyzeEdgeCasesBackward(); + bool canBeNegativeZero() const { return canBeNegativeZero_; } @@ -4946,6 +4951,8 @@ class MMul : public MBinaryArithInstruction } MDefinition *foldsTo(TempAllocator &alloc); + void analyzeEdgeCasesForward(); + void analyzeEdgeCasesBackward(); void collectRangeInfoPreTrunc(); double getIdentity() { @@ -5041,6 +5048,8 @@ class MDiv : public MBinaryArithInstruction } MDefinition *foldsTo(TempAllocator &alloc); + void analyzeEdgeCasesForward(); + void analyzeEdgeCasesBackward(); double getIdentity() { MOZ_ASSUME_UNREACHABLE("not used"); @@ -5157,6 +5166,8 @@ class MMod : public MBinaryArithInstruction return canBePowerOfTwoDivisor_; } + void analyzeEdgeCasesForward(); + bool isUnsigned() const { return unsigned_; } diff --git a/js/src/moz.build b/js/src/moz.build index 4d5e932a625b..7a5c0f04ad14 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -156,6 +156,7 @@ UNIFIED_SOURCES += [ 'jit/C1Spewer.cpp', 'jit/CodeGenerator.cpp', 'jit/CompileWrappers.cpp', + 'jit/EdgeCaseAnalysis.cpp', 'jit/EffectiveAddressAnalysis.cpp', 'jit/ExecutableAllocator.cpp', 'jit/Ion.cpp', From 5a7beb0db0cc0530e8808f1703e633852e7b2529 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Fri, 8 Aug 2014 03:06:00 -0400 Subject: [PATCH 048/119] Bug 1049263 - Do not report ccache stats unless ccache was used. r=glandium --- python/mozbuild/mozbuild/controller/building.py | 6 ++++++ python/mozbuild/mozbuild/mach_commands.py | 5 +++-- .../mozbuild/test/controller/test_ccachestats.py | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/python/mozbuild/mozbuild/controller/building.py b/python/mozbuild/mozbuild/controller/building.py index 78ff61ec5f84..c3294e86f611 100644 --- a/python/mozbuild/mozbuild/controller/building.py +++ b/python/mozbuild/mozbuild/controller/building.py @@ -611,6 +611,12 @@ class CCacheStats(object): return '\n'.join(lines) + def __nonzero__(self): + relative_values = [v for k, v in self._values.items() + if k not in self.ABSOLUTE_KEYS] + return (all(v >= 0 for v in relative_values) and + any(v > 0 for v in relative_values)) + @staticmethod def _format_value(v): if v > CCacheStats.GiB: diff --git a/python/mozbuild/mozbuild/mach_commands.py b/python/mozbuild/mozbuild/mach_commands.py index b43c4326b6e7..2a498ded8a3c 100644 --- a/python/mozbuild/mozbuild/mach_commands.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -397,8 +397,9 @@ class Build(MachCommandBase): if ccache_start and ccache_end: ccache_diff = ccache_end - ccache_start - self.log(logging.INFO, 'ccache', - {'msg': ccache_diff.hit_rate_message()}, "{msg}") + if ccache_diff: + self.log(logging.INFO, 'ccache', + {'msg': ccache_diff.hit_rate_message()}, "{msg}") if monitor.elapsed > 300: # Display a notification when the build completes. diff --git a/python/mozbuild/mozbuild/test/controller/test_ccachestats.py b/python/mozbuild/mozbuild/test/controller/test_ccachestats.py index bb430d12dc75..6678977304f2 100644 --- a/python/mozbuild/mozbuild/test/controller/test_ccachestats.py +++ b/python/mozbuild/mozbuild/test/controller/test_ccachestats.py @@ -73,6 +73,21 @@ class TestCcacheStats(unittest.TestCase): stats_diff = stats2 - stats1 self.assertEqual(stats_diff.hit_rates(), (0.9, 0.05, 0.05)) + def test_stats_contains_data(self): + stats0 = CCacheStats(self.STAT0) + stats1 = CCacheStats(self.STAT1) + stats2 = CCacheStats(self.STAT2) + stats_diff_zero = stats1 - stats1 + stats_diff_negative1 = stats0 - stats1 + stats_diff_negative2 = stats1 - stats2 + + self.assertFalse(stats0) + self.assertTrue(stats1) + self.assertTrue(stats2) + self.assertFalse(stats_diff_zero) + self.assertFalse(stats_diff_negative1) + self.assertFalse(stats_diff_negative2) + if __name__ == '__main__': main() From b61a78aeb44b49b147360f050c3b10e3ddc03d6b Mon Sep 17 00:00:00 2001 From: Steffen Michalke Date: Tue, 12 Aug 2014 08:40:00 -0400 Subject: [PATCH 049/119] Bug 1052508 - Fix --with-system-nss build bustage. r=glandium --- config/external/nss/crmf/moz.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/external/nss/crmf/moz.build b/config/external/nss/crmf/moz.build index 3f51ab5f1a61..d0ceb4bd9cf4 100644 --- a/config/external/nss/crmf/moz.build +++ b/config/external/nss/crmf/moz.build @@ -8,7 +8,7 @@ LIBRARY_NAME = 'crmf' if CONFIG['MOZ_NATIVE_NSS']: OS_LIBS += [l for l in CONFIG['NSS_LIBS'] if l.startswith('-L')] - OS_LIBS += '-lcrmf' + OS_LIBS += ['-lcrmf'] else: USE_LIBS += [ # The dependency on nss is not real, but is required to force the From 8b62fa8a0ef2338c8fb08203b342269bae8af18e Mon Sep 17 00:00:00 2001 From: Blake Wu Date: Tue, 12 Aug 2014 20:06:00 -0400 Subject: [PATCH 050/119] Bug 1052536 - Remove extra space to silence configure warning. r=glandium --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 3364a6600d4e..34d447600152 100644 --- a/configure.in +++ b/configure.in @@ -3785,7 +3785,7 @@ MOZ_WMF= if test -n "$MOZ_FMP4"; then MOZ_FMP4=1 else - MOZ_FMP4 = + MOZ_FMP4= fi MOZ_EME=1 MOZ_FFMPEG= From e115b2cd6b2cf183df722744b6e316845e455718 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 13 Aug 2014 23:15:29 -0700 Subject: [PATCH 051/119] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/e4a068c1ec04 Author: Luke Chang Desc: Merge pull request #22772 from luke-chang/1050682_sms_wrong_multiline_style Bug 1050682 - [Messages] The recipient container will remain multiline style when removing the last recipient from opened panel, r=steveck-chung ======== https://hg.mozilla.org/integration/gaia-central/rev/4c487cca6baf Author: Luke Chang Desc: Bug 1050682 - [Messages] The recipient container will remain multiline style when removing the last recipient from opened panel ======== https://hg.mozilla.org/integration/gaia-central/rev/6b71ee9997c5 Author: Julien Wajsberg Desc: Merge pull request #22843 from julienw/1046828-fix-marionette-tests Bug 1046828 - [Notifications API] We should never send the "show" event ... ======== https://hg.mozilla.org/integration/gaia-central/rev/681fd8fa0f10 Author: Julien Wajsberg Desc: Bug 1046828 - [Notifications API] We should never send the "show" event using system messages at a reboot r=mhenretty Fix marionette tests --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a0ce63d4cb4f..a4c27d23a642 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "2fb6119da922ebdab70c79e7f515f49fa582b2c5", + "revision": "e4a068c1ec044595738a3698fa32840764dd7ca0", "repo_path": "/integration/gaia-central" } From 6bb4c50b9f869a9dd9196af714151583cbcb43b3 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 13 Aug 2014 23:21:25 -0700 Subject: [PATCH 052/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 3a4f590e65c1..e548f8d03df6 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index d9f07e68f6db..ff05f561932d 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index ce0d311ed4d2..9f8636fe2084 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 3a4f590e65c1..e548f8d03df6 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index adf020c02175..f8566c728918 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 9ba977901cd1..b48762965bc9 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 814bba4a6cbe..1e2caf145bec 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index a1ce7155d5de..bb1794d6ea63 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index ce0fbfcb823b..a37c9d18aa33 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From c36483f38eb0447d4f159002bd971effb984ed91 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 00:30:26 -0700 Subject: [PATCH 053/119] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/b6ce93c01bda Author: Yuren Ju Desc: Merge pull request #22835 from sudheesh001/Patch_1032033 Fixes Bug 1032033, build/test/integration/helper.js r=yurenju ======== https://hg.mozilla.org/integration/gaia-central/rev/6013ce199eeb Author: sudheesh001 Desc: Fixes Bug 1032033, build/test/integration/helper.js r=yurenju --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a4c27d23a642..20a6aebd6944 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "e4a068c1ec044595738a3698fa32840764dd7ca0", + "revision": "b6ce93c01bda41c1536d905d2b358e0227b962d2", "repo_path": "/integration/gaia-central" } From d72adeb462eb1abeae853b6e052da786bf360eac Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 00:36:47 -0700 Subject: [PATCH 054/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index e548f8d03df6..b99372bc1b8d 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index ff05f561932d..6f5c182bed29 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 9f8636fe2084..35daeccbf034 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index e548f8d03df6..b99372bc1b8d 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index f8566c728918..2c34d0a1f74e 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index b48762965bc9..5ba75b89f008 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 1e2caf145bec..ef05a026913d 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index bb1794d6ea63..3ebd558299fc 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a37c9d18aa33..a0108ed55fde 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 51875374d259055b4c78ff0682cfa781b531f08d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 01:40:31 -0700 Subject: [PATCH 055/119] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/989b85b7cba0 Author: Jose M. Cantera Desc: Merge pull request #22831 from ADLR-es/fix-bug-1050744 Bug 1050744 - [Contacts] Search results highlighting does not work properly with special chars like accents ======== https://hg.mozilla.org/integration/gaia-central/rev/1fff71c80b0c Author: Adrián de la Rosa Desc: [Contacts] Search results highlighting does not work properly with special chars like accents --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 20a6aebd6944..78fba2921599 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "b6ce93c01bda41c1536d905d2b358e0227b962d2", + "revision": "989b85b7cba0da1b648a43ec324d9731794cd3eb", "repo_path": "/integration/gaia-central" } From f4f536a14d6246d52b928e72291c1e09560a8abe Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 01:46:20 -0700 Subject: [PATCH 056/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b99372bc1b8d..4247f3e698ad 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6f5c182bed29..75a99177449b 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 35daeccbf034..86b2550a5c45 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b99372bc1b8d..4247f3e698ad 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 2c34d0a1f74e..ed186c9422b9 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 5ba75b89f008..ab0db4a71490 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index ef05a026913d..a49bef47c12c 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 3ebd558299fc..71cd54bd0061 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a0108ed55fde..d7a7f35b6b2b 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From d13ca5f44d8904ba000d1147f6d4ca2179549fae Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 02:50:26 -0700 Subject: [PATCH 057/119] Bumping gaia.json for 5 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/dbcde4fcff9e Author: Francisco Jordano Desc: Bug 1050722 - Reduce overpaint of the contacts app r=arcturus ======== https://hg.mozilla.org/integration/gaia-central/rev/0210a1bc308c Author: John Hu Desc: Merge pull request #22761 from huchengtw-moz/bug-1045523-rwd-device-type-2 Bug 1045523 - customize default window size of responsive web design, r=yurenju ======== https://hg.mozilla.org/integration/gaia-central/rev/afb2d55d2977 Author: John Hu Desc: Bug 1045523 - customize default window size of responsive web design ======== https://hg.mozilla.org/integration/gaia-central/rev/1a0177f6b96b Author: Aleh Zasypkin Desc: Merge pull request #22712 from azasypkin/bug-1048362-highlight-composer Bug 1048362 - [Messages] Compose Panel refresh (highlight actionable part). r=schung ======== https://hg.mozilla.org/integration/gaia-central/rev/e525a54b441e Author: Aleh Zasypkin Desc: Bug 1048362 - [Messages] Compose Panel refresh (highlight actionable part). r=schung --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 78fba2921599..ab239d150658 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "989b85b7cba0da1b648a43ec324d9731794cd3eb", + "revision": "dbcde4fcff9ec20301f9d5db163a5ee6a0436178", "repo_path": "/integration/gaia-central" } From 270538d5655f370eec8d66d51d65e4b46a037920 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 02:56:22 -0700 Subject: [PATCH 058/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 4247f3e698ad..ca8d40760abf 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 75a99177449b..12543a7b1f74 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 86b2550a5c45..69067bfdaf5d 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 4247f3e698ad..ca8d40760abf 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index ed186c9422b9..bd85bb2af4f1 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index ab0db4a71490..8480a8101aba 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index a49bef47c12c..d86060d83e72 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 71cd54bd0061..c6d7a28e17c2 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index d7a7f35b6b2b..e870dbf20c16 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 05d2f43572537bda3b61c4942bb6b29b2ff7a106 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 03:05:28 -0700 Subject: [PATCH 059/119] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/a3937490c2c0 Author: gasolin Desc: Merge pull request #22871 from gasolin/issue-1053131 Bug 1053131 - [settings]SIM security is hard to find, r=eragon ======== https://hg.mozilla.org/integration/gaia-central/rev/6c8016aa1cea Author: gasolin Desc: Bug 1053131 - [settings]SIM security is hard to find ======== https://hg.mozilla.org/integration/gaia-central/rev/664a3a0924d1 Author: EragonJ Desc: Merge pull request #22825 from EragonJ/bug-1050699 Bug 1050699 - [B2G] "Unknow SIM card state" is shown on "Call Settings" ... ======== https://hg.mozilla.org/integration/gaia-central/rev/2820bebc7c53 Author: EragonJ Desc: Bug 1050699 - [B2G] "Unknow SIM card state" is shown on "Call Settings" and ... --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ab239d150658..6aca2305da98 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "dbcde4fcff9ec20301f9d5db163a5ee6a0436178", + "revision": "a3937490c2c043644a7a14def2c4068ea6267245", "repo_path": "/integration/gaia-central" } From accc3754318c7aca84ee701f901170aa6a5c936e Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 03:11:14 -0700 Subject: [PATCH 060/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index ca8d40760abf..00e5df162086 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 12543a7b1f74..6d944dabaf1a 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 69067bfdaf5d..d81fc19ce37b 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index ca8d40760abf..00e5df162086 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index bd85bb2af4f1..cca8bf59f3a3 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 8480a8101aba..eb196a4641f9 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index d86060d83e72..a7515eb62b8f 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index c6d7a28e17c2..e6b9b89179ab 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index e870dbf20c16..3bb9abe5f299 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From d50164a280bbec6a9a567eabe5c6fe2b8f64f919 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 03:21:16 -0700 Subject: [PATCH 061/119] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/1d172e72d1e8 Author: Etienne Segonzac Desc: Merge pull request #22065 from weigao123/bug1031652-master Bug 1031652 - [master] Show warn dialog when call non emergency number on lockscreen. r=Etienne. ======== https://hg.mozilla.org/integration/gaia-central/rev/ea114265ed2f Author: wei.gao Desc: Bug 1031652 - [master] Show warn dialog when call non emergency number on lockscreen. r=Etienne. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 6aca2305da98..f2b6f099e097 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "a3937490c2c043644a7a14def2c4068ea6267245", + "revision": "1d172e72d1e88975f410f82c6c840f725821a8d8", "repo_path": "/integration/gaia-central" } From 14bc7962cca7ac41c27456e19b4b8d52cc10b6c3 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 03:22:28 -0700 Subject: [PATCH 062/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 00e5df162086..12c67bf2e2c7 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6d944dabaf1a..b9c389667db1 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index d81fc19ce37b..57c538150a6b 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 00e5df162086..12c67bf2e2c7 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index cca8bf59f3a3..2a6a54d590d4 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index eb196a4641f9..26d9512c2b99 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index a7515eb62b8f..22d6e30ccdbc 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index e6b9b89179ab..29dfb444ca40 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 3bb9abe5f299..79c716a79425 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From b602399fecdb4bfb0ab5f3a1803e19b2b3fb7b44 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 03:35:27 -0700 Subject: [PATCH 063/119] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/a7a129e7b9cb Author: Fernando Jiménez Moreno Desc: Merge pull request #22481 from ferjm/bug1044060.mobileiduitest Bug 1044060 - [MobileID] Add Mobile ID test to Gaia UI test app. r=timdream ======== https://hg.mozilla.org/integration/gaia-central/rev/e8e9a74dc5ae Author: Fernando Jiménez Desc: Bug 1044060 - [MobileID] Add Mobile ID test to Gaia UI test app. r=timdream --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index f2b6f099e097..cddfebf2860f 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "1d172e72d1e88975f410f82c6c840f725821a8d8", + "revision": "a7a129e7b9cbeb2ae4508148402367e39c4d4492", "repo_path": "/integration/gaia-central" } From 37b47d0c2c1af7ac2db9cf4ee5a5dc3206d24776 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 03:41:42 -0700 Subject: [PATCH 064/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 12c67bf2e2c7..a26727d3c211 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index b9c389667db1..3b8223874821 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 57c538150a6b..7bb691a2c96c 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 12c67bf2e2c7..a26727d3c211 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 2a6a54d590d4..59d2d2c9ddcb 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 26d9512c2b99..755c35431afd 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 22d6e30ccdbc..e8a87f3c782a 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 29dfb444ca40..13dfaf736f1f 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 79c716a79425..ed4c6109c212 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From a73d9d1206c035720ade6bb8970826268d9f7419 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 04:05:28 -0700 Subject: [PATCH 065/119] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/72013ef0318f Author: Ben Francis Desc: Merge pull request #22848 from benfrancis/1053416 Bug 1053416 - Increase size of reload button r=cwiiis ======== https://hg.mozilla.org/integration/gaia-central/rev/004eaaf80a3c Author: Ben Francis Desc: Bug 1053416 - Increase size of reload button ======== https://hg.mozilla.org/integration/gaia-central/rev/72f6a8f55257 Author: Pavel Ivanov Desc: Merge pull request #22499 from pivanov/bug-1037146 The "show password" check box in the wifi connection details page in the FTU app is cut off on the right edge in RTL mode and label is cut off too ======== https://hg.mozilla.org/integration/gaia-central/rev/0c1a285fca92 Author: Pavel Ivanov Desc: The "show password" check box in the wifi connection details page in the FTU app is cut off on the right edge in RTL mode and label is cut off too --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index cddfebf2860f..d96380c8a1ff 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "a7a129e7b9cbeb2ae4508148402367e39c4d4492", + "revision": "72013ef0318fab1b633559f3a9d8d6b4c56b95c8", "repo_path": "/integration/gaia-central" } From c9dafbf6832234430949b32a11962b95db59ca17 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 04:11:14 -0700 Subject: [PATCH 066/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index a26727d3c211..2be3b4a9d799 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 3b8223874821..e8cfe6d72c59 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 7bb691a2c96c..7c6a9648ea89 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index a26727d3c211..2be3b4a9d799 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 59d2d2c9ddcb..cc6e75cd030c 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 755c35431afd..045f04633c42 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index e8a87f3c782a..3c1228ef48a0 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 13dfaf736f1f..89f3d3f2389d 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index ed4c6109c212..9b8e6491d197 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 45fce766f0a584856f89de4501b4c71448a1df94 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 04:35:28 -0700 Subject: [PATCH 067/119] Bumping gaia.json for 3 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/683da6d984f8 Author: Ed Morley Desc: Revert "Bug 1045523 - customize default window size of responsive web design" for build failures This reverts commit 72b887d20811cbf00c080922c358738c9c9dd886. ======== https://hg.mozilla.org/integration/gaia-central/rev/19d68aebc93d Author: Jan Jongboom Desc: Merge pull request #22401 from comoyo/bug1046798 Bug 1046798 - Yield uppercase suggestions if input is uppercase. r=djf ======== https://hg.mozilla.org/integration/gaia-central/rev/4aee9eac99a2 Author: Jan Jongboom Desc: Bug 1046798 - Yield uppercase suggestions if input is uppercase --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index d96380c8a1ff..48c2349ffc0e 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "72013ef0318fab1b633559f3a9d8d6b4c56b95c8", + "revision": "683da6d984f8fe731d98ea16fc9d127f604f330c", "repo_path": "/integration/gaia-central" } From ad769480e6a3e40a799b7d76cc7b2de2681fe125 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 04:41:14 -0700 Subject: [PATCH 068/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 2be3b4a9d799..1cdbeab9df39 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e8cfe6d72c59..bf19b0872807 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 7c6a9648ea89..030e53d3acb6 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 2be3b4a9d799..1cdbeab9df39 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index cc6e75cd030c..739690b997b7 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 045f04633c42..23f7a8bacb07 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 3c1228ef48a0..a5a9a5c0bf62 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 89f3d3f2389d..ac81c3690d28 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 9b8e6491d197..f18d9bc9d1bf 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From a97b8e75bc911d5ac346eda7d9d1cf6377b6a473 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 05:20:28 -0700 Subject: [PATCH 069/119] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/91e958581943 Author: Pavel Ivanov Desc: Bug 1037146 - The "show password" check box in the wifi connection details page in the FTU app is cut off on the right edge in RTL mode and label is cut off too r=fcampo r=Nefzaoui ======== https://hg.mozilla.org/integration/gaia-central/rev/089def910f8b Author: Kevin Grandon Desc: Revert "The "show password" check box in the wifi connection details page in the FTU app is cut off on the right edge in RTL mode and label is cut off too" This reverts commit bb911ea6588ee273e397105910d0fccc84aecd64. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 48c2349ffc0e..27967c52a335 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "683da6d984f8fe731d98ea16fc9d127f604f330c", + "revision": "91e95858194355cffc1c438f0a0192d603d6cfec", "repo_path": "/integration/gaia-central" } From 9b182a4c6aac37b094955fbf51e107d6acb87c0c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 05:21:52 -0700 Subject: [PATCH 070/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 1cdbeab9df39..f8a2103e8d3b 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index bf19b0872807..c1efd031fd65 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 030e53d3acb6..fdf99220622e 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 1cdbeab9df39..f8a2103e8d3b 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 739690b997b7..8a02165773fc 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 23f7a8bacb07..e70dbb5aeed7 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index a5a9a5c0bf62..65df52d205fa 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index ac81c3690d28..a1f94d0340a2 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index f18d9bc9d1bf..49019baf62a2 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From f4546cf8439bcb68e0e3d83145db5965658ab20f Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 05:35:27 -0700 Subject: [PATCH 071/119] Bumping gaia.json for 1 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/014d028c7f53 Author: Dave Hunt Desc: Bug 1043718 - Add support for submitting device results to Treeherder. r=jgriffin --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 27967c52a335..abc998a40d21 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "91e95858194355cffc1c438f0a0192d603d6cfec", + "revision": "014d028c7f532da78cc18a53d3c441456e485bdf", "repo_path": "/integration/gaia-central" } From a99a8cdbad05b5d1cba0d4d9a855e2403bd2b649 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 05:41:15 -0700 Subject: [PATCH 072/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index f8a2103e8d3b..41425c0971c1 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index c1efd031fd65..83371a8ec5e4 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index fdf99220622e..77bbc4ac94e2 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index f8a2103e8d3b..41425c0971c1 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 8a02165773fc..6f153b848303 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index e70dbb5aeed7..faea0f70251c 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 65df52d205fa..bad1ab7b61f5 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index a1f94d0340a2..47776281dc07 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 49019baf62a2..bc186d615781 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From c1b83c1e6ae300c235e9eb843e8d4b5415dce187 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 05:50:27 -0700 Subject: [PATCH 073/119] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/69fd573db341 Author: Jose M. Cantera Desc: Merge pull request #22570 from jmcanterafonseca/remove_undo Bug 1048160 - [Contacts Actionable Fields] Remove undo functionality ======== https://hg.mozilla.org/integration/gaia-central/rev/e721e8ad642e Author: Jose M. Cantera Desc: Bug 1048160 - [Contacts Actionable Fields] Remove undo functionality ======== https://hg.mozilla.org/integration/gaia-central/rev/39fbf8efab82 Author: Kevin Grandon Desc: Merge pull request #22863 from KevinGrandon/bug_1053626_search_legazy_moz_activity_removal Bug 1053626 - [Search] Remove legacy MozActivity calls ======== https://hg.mozilla.org/integration/gaia-central/rev/9065c41876d6 Author: Kevin Grandon Desc: Bug 1053626 - [Search] Remove legacy MozActivity calls r=me --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index abc998a40d21..903cd7030760 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "014d028c7f532da78cc18a53d3c441456e485bdf", + "revision": "69fd573db341e4028ed5cf5fe5096a0df583e562", "repo_path": "/integration/gaia-central" } From 23027d733bcab76b8c0b3d331e6187842215630b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 05:51:51 -0700 Subject: [PATCH 074/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 41425c0971c1..19cd3d08fbef 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 83371a8ec5e4..831d244a0a69 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 77bbc4ac94e2..9360fabecf1a 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 41425c0971c1..19cd3d08fbef 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 6f153b848303..2f50657b3620 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index faea0f70251c..22bd37c8e0de 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index bad1ab7b61f5..c98b508acb24 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 47776281dc07..9f3d451c0ea0 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index bc186d615781..4dc1f1ffc58b 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 7103f63880100d65c7d8d610757b91b340072cb0 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 06:35:27 -0700 Subject: [PATCH 075/119] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/3020523f9c74 Author: Min-Zhong "John" Lu Desc: Merge pull request #22819 from mnjul/bug_1024298_full_kb_panel_for_number_input Bug 1024298 - [Keyboard UX update] Show the full symbol panel for type="number". r=timdream, f=rudyl, f=yurenju ======== https://hg.mozilla.org/integration/gaia-central/rev/ca2421396500 Author: John Lu [:mnjul] Desc: Bug 1024298 - [Keyboard UX update] Show the full symbol panel for type="number" ======== https://hg.mozilla.org/integration/gaia-central/rev/71b6c350375e Author: chirarobert Desc: Merge pull request #22787 from viorelaioia/bug_1052473 Bug 1052473 - Fix failure in test_setup_and_send_imap_email.py ======== https://hg.mozilla.org/integration/gaia-central/rev/2b7f17a4cbd5 Author: Viorela Ioia Desc: Bug 1052473 - Fix failure in test_setup_and_send_imap_email.py --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 903cd7030760..f143e70bd72b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "69fd573db341e4028ed5cf5fe5096a0df583e562", + "revision": "3020523f9c74816fa77f937f5339b7720dfb8384", "repo_path": "/integration/gaia-central" } From e4ea8bd7466ac967d428ccfd125dc3e3e657b1a0 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 06:36:53 -0700 Subject: [PATCH 076/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 19cd3d08fbef..929de089ea92 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 831d244a0a69..48b07f97218c 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 9360fabecf1a..1c4fafd309f8 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 19cd3d08fbef..929de089ea92 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 2f50657b3620..e46cfe428586 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 22bd37c8e0de..225c82104e6c 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index c98b508acb24..f7cb13683f69 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 9f3d451c0ea0..0864e954ac7a 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 4dc1f1ffc58b..f0e023d49827 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 2e223b483c7d2ab0ba0a0db7f3a2330cfa36d201 Mon Sep 17 00:00:00 2001 From: Shawn Ku Date: Wed, 13 Aug 2014 17:00:52 +0800 Subject: [PATCH 077/119] Bug 1046649 - Part 1: RIL patch - B2G RIL: Need to handle wild char for EF_OPL. v3. r=Edgar --- dom/system/gonk/ril_worker.js | 129 ++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 29 deletions(-) diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 1a94ebde4b34..5a65f61e31eb 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -1116,6 +1116,48 @@ RilObject.prototype = { } }, + /** + * Check if operator name needs to be overriden by current voiceRegistrationState + * , EFOPL and EFPNN. See 3GPP TS 31.102 clause 4.2.58 EFPNN and 4.2.59 EFOPL + * for detail. + * + * @return true if operator name is overridden, false otherwise. + */ + overrideICCNetworkName: function() { + if (!this.operator) { + return false; + } + + // We won't get network name using PNN and OPL if voice registration isn't + // ready. + if (!this.voiceRegistrationState.cell || + this.voiceRegistrationState.cell.gsmLocationAreaCode == -1) { + return false; + } + + let ICCUtilsHelper = this.context.ICCUtilsHelper; + let networkName = ICCUtilsHelper.getNetworkNameFromICC( + this.operator.mcc, + this.operator.mnc, + this.voiceRegistrationState.cell.gsmLocationAreaCode); + + if (!networkName) { + return false; + } + + if (DEBUG) { + this.context.debug("Operator names will be overriden: " + + "longName = " + networkName.fullName + ", " + + "shortName = " + networkName.shortName); + } + + this.operator.longName = networkName.fullName; + this.operator.shortName = networkName.shortName; + + this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator); + return true; + }, + /** * Request the phone's radio to be enabled or disabled. * @@ -3903,35 +3945,20 @@ RilObject.prototype = { } } + this.operator.longName = longName; + this.operator.shortName = shortName; + let ICCUtilsHelper = this.context.ICCUtilsHelper; - let networkName; - // We won't get network name using PNN and OPL if voice registration isn't ready - if (this.voiceRegistrationState.cell && - this.voiceRegistrationState.cell.gsmLocationAreaCode != -1) { - networkName = ICCUtilsHelper.getNetworkNameFromICC( - this.operator.mcc, - this.operator.mnc, - this.voiceRegistrationState.cell.gsmLocationAreaCode); - } - - if (networkName) { - if (DEBUG) { - this.context.debug("Operator names will be overriden: " + - "longName = " + networkName.fullName + ", " + - "shortName = " + networkName.shortName); - } - - this.operator.longName = networkName.fullName; - this.operator.shortName = networkName.shortName; - } else { - this.operator.longName = longName; - this.operator.shortName = shortName; - } - if (ICCUtilsHelper.updateDisplayCondition()) { ICCUtilsHelper.handleICCInfoChange(); } - this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator); + + // NETWORK_INFO_OPERATOR message will be sent out by overrideICCNetworkName + // itself if operator name is overridden after checking, or we have to + // do it by ourself. + if (!this.overrideICCNetworkName()) { + this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator); + } } }, @@ -13695,11 +13722,14 @@ SimRecordHelperObject.prototype = { } Buf.readStringDelimiter(strLen); + let RIL = this.context.RIL; if (options.p1 < options.totalRecords) { ICCIOHelper.loadNextRecord(options); } else { - this.context.RIL.iccInfoPrivate.OPL = opl; + RIL.iccInfoPrivate.OPL = opl; } + + RIL.overrideICCNetworkName(); } ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_OPL, @@ -13757,6 +13787,7 @@ SimRecordHelperObject.prototype = { pnn.push(pnnElement); } + let RIL = this.context.RIL; // Will ignore remaining records when got the contents of a record are all 0xff. if (pnnElement && options.p1 < options.totalRecords) { ICCIOHelper.loadNextRecord(options); @@ -13766,8 +13797,10 @@ SimRecordHelperObject.prototype = { this.context.debug("PNN: [" + i + "]: " + JSON.stringify(pnn[i])); } } - this.context.RIL.iccInfoPrivate.PNN = pnn; + RIL.iccInfoPrivate.PNN = pnn; } + + RIL.overrideICCNetworkName(); } let pnn = []; @@ -14204,17 +14237,55 @@ ICCUtilsHelperObject.prototype = { pnnEntry = iccInfoPriv.PNN[0]; } } else { + let GsmPDUHelper = this.context.GsmPDUHelper; + let wildChar = GsmPDUHelper.bcdChars.charAt(0x0d); // According to 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42, // the ME shall use this EF_OPL in association with the EF_PNN in place // of any network name stored within the ME's internal list and any network // name received when registered to the PLMN. let length = iccInfoPriv.OPL ? iccInfoPriv.OPL.length : 0; for (let i = 0; i < length; i++) { + let unmatch = false; let opl = iccInfoPriv.OPL[i]; - // Try to match the MCC/MNC. - if (mcc != opl.mcc || mnc != opl.mnc) { + // Try to match the MCC/MNC. Besides, A BCD value of 'D' in any of the + // MCC and/or MNC digits shall be used to indicate a "wild" value for + // that corresponding MCC/MNC digit. + if (opl.mcc.indexOf(wildChar) !== -1) { + for (let j = 0; j < opl.mcc.length; j++) { + if (opl.mcc[j] !== wildChar && opl.mcc[j] !== mcc[j]) { + unmatch = true; + break; + } + } + if (unmatch) { + continue; + } + } else { + if (mcc !== opl.mcc) { + continue; + } + } + + if (mnc.length !== opl.mnc.length) { continue; } + + if (opl.mnc.indexOf(wildChar) !== -1) { + for (let j = 0; j < opl.mnc.length; j++) { + if (opl.mnc[j] !== wildChar && opl.mnc[j] !== mnc[j]) { + unmatch = true; + break; + } + } + if (unmatch) { + continue; + } + } else { + if (mnc !== opl.mnc) { + continue; + } + } + // Try to match the location area code. If current local area code is // covered by lac range that specified in the OPL entry, use the PNN // that specified in the OPL entry. From adf1456ebaafbe9c1119a519f1e01d2fa47faa1d Mon Sep 17 00:00:00 2001 From: Shawn Ku Date: Wed, 13 Aug 2014 16:54:55 +0800 Subject: [PATCH 078/119] Bug 1046649 - Part 2: Test patch - B2G RIL: Need to handle wild char for EF_OPL. r=Edgar --- .../test_ril_worker_icc_ICCUtilsHelper.js | 84 +++++++++++++++---- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js index e8a523937617..3cd82647dff3 100644 --- a/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js +++ b/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js @@ -161,12 +161,12 @@ add_test(function test_get_network_name_from_icc() { } // Before EF_OPL and EF_PNN have been loaded. - testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000}, null); - testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x2000}, null); + testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000}, null); + testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x2000}, null); // Set HPLMN - RIL.iccInfo.mcc = 123; - RIL.iccInfo.mnc = 456; + RIL.iccInfo.mcc = "123"; + RIL.iccInfo.mnc = "456"; RIL.voiceRegistrationState = { cell: { @@ -181,56 +181,108 @@ add_test(function test_get_network_name_from_icc() { {"fullName": "PNN1Long", "shortName": "PNN1Short"}, {"fullName": "PNN2Long", "shortName": "PNN2Short"}, {"fullName": "PNN3Long", "shortName": "PNN3Short"}, - {"fullName": "PNN4Long", "shortName": "PNN4Short"} + {"fullName": "PNN4Long", "shortName": "PNN4Short"}, + {"fullName": "PNN5Long", "shortName": "PNN5Short"}, + {"fullName": "PNN6Long", "shortName": "PNN6Short"}, + {"fullName": "PNN7Long", "shortName": "PNN7Short"}, + {"fullName": "PNN8Long", "shortName": "PNN8Short"} ] }; // EF_OPL isn't available and current isn't in HPLMN, - testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000}, null); + testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x1000}, null); // EF_OPL isn't available and current is in HPLMN, // the first record of PNN should be returned. - testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000}, + testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000}, {longName: "PNN1Long", shortName: "PNN1Short"}); // Set EF_OPL RIL.iccInfoPrivate.OPL = [ { - "mcc": 123, - "mnc": 456, + "mcc": "123", + "mnc": "456", "lacTacStart": 0, "lacTacEnd": 0xFFFE, "pnnRecordId": 4 }, { - "mcc": 321, - "mnc": 654, + "mcc": "321", + "mnc": "654", "lacTacStart": 0, "lacTacEnd": 0x0010, "pnnRecordId": 3 }, { - "mcc": 321, - "mnc": 654, + "mcc": "321", + "mnc": "654", "lacTacStart": 0x0100, "lacTacEnd": 0x1010, "pnnRecordId": 2 + }, + { + "mcc": ";;;", + "mnc": "01", + "lacTacStart": 0, + "lacTacEnd": 0xFFFE, + "pnnRecordId": 5 + }, + { + "mcc": "00;", + "mnc": "02", + "lacTacStart": 0, + "lacTacEnd": 0xFFFE, + "pnnRecordId": 6 + }, + { + "mcc": "001", + "mnc": ";;", + "lacTacStart": 0, + "lacTacEnd": 0xFFFE, + "pnnRecordId": 7 + }, + { + "mcc": "002", + "mnc": "0;", + "lacTacStart": 0, + "lacTacEnd": 0xFFFE, + "pnnRecordId": 8 } ]; // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN, - testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000}, + testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000}, {longName: "PNN4Long", shortName: "PNN4Short"}); // Current PLMN is not HPLMN, and according to LAC, we should get // the second PNN record. - testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000}, + testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x1000}, {longName: "PNN2Long", shortName: "PNN2Short"}); // Current PLMN is not HPLMN, and according to LAC, we should get // the thrid PNN record. - testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x0001}, + testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x0001}, {longName: "PNN3Long", shortName: "PNN3Short"}); + // Current PLMN is not HPLMN, and according to LAC, we should get + // the 5th PNN record after wild char (ie: ';') handling. + testGetNetworkNameFromICC({mcc: "001", mnc: "01", lac: 0x0001}, + {longName: "PNN5Long", shortName: "PNN5Short"}); + + // Current PLMN is not HPLMN, and according to LAC, we should get + // the 6th PNN record after wild char (ie: ';') handling. + testGetNetworkNameFromICC({mcc: "001", mnc: "02", lac: 0x0001}, + {longName: "PNN6Long", shortName: "PNN6Short"}); + + // Current PLMN is not HPLMN, and according to LAC, we should get + // the 7th PNN record after wild char (ie: ';') handling. + testGetNetworkNameFromICC({mcc: "001", mnc: "03", lac: 0x0001}, + {longName: "PNN7Long", shortName: "PNN7Short"}); + + // Current PLMN is not HPLMN, and according to LAC, we should get + // the 8th PNN record after wild char (ie: ';') handling. + testGetNetworkNameFromICC({mcc: "002", mnc: "03", lac: 0x0001}, + {longName: "PNN8Long", shortName: "PNN8Short"}); + run_next_test(); }); From d90f09a6ba9f5db50bebec219485dd4db99d26fe Mon Sep 17 00:00:00 2001 From: Morris Tseng Date: Wed, 13 Aug 2014 19:29:00 -0400 Subject: [PATCH 079/119] Bug 1052246 - Send correct rect information for selectionchange event. r=fabrice --- b2g/chrome/content/shell.js | 4 ++-- dom/browser-element/BrowserElementChildPreload.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index 885e38f7115a..6341b26b580c 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -522,8 +522,8 @@ var shell = { // based on tab's coordinate. So get the actual offsets between shell and evt.target. let elt = evt.target; let win = elt.ownerDocument.defaultView; - let offsetX = win.mozInnerScreenX; - let offsetY = win.mozInnerScreenY; + let offsetX = win.mozInnerScreenX - window.mozInnerScreenX; + let offsetY = win.mozInnerScreenY - window.mozInnerScreenY; let rect = elt.getBoundingClientRect(); offsetX += rect.left; diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js index abeda31582c6..887c55d41d6b 100644 --- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -644,15 +644,15 @@ BrowserElementChild.prototype = { isCollapsed: (e.selectedText.length == 0), }; - // Get correct geometry information if we have nested - - - - - - diff --git a/dom/base/Crypto.cpp b/dom/base/Crypto.cpp index ddff2aea59b8..52cfb880936c 100644 --- a/dom/base/Crypto.cpp +++ b/dom/base/Crypto.cpp @@ -127,82 +127,6 @@ Crypto::Subtle() return mSubtle; } -#ifndef MOZ_DISABLE_CRYPTOLEGACY -// Stub out the legacy nsIDOMCrypto methods. The actual -// implementations are in security/manager/ssl/src/nsCrypto.{cpp,h} - -NS_IMETHODIMP -Crypto::GetEnableSmartCardEvents(bool *aEnableSmartCardEvents) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -Crypto::SetEnableSmartCardEvents(bool aEnableSmartCardEvents) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -bool -Crypto::EnableSmartCardEvents() -{ - return false; -} - -void -Crypto::SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv) -{ - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); -} - -void -Crypto::GetVersion(nsString& aVersion) -{ -} - -mozilla::dom::CRMFObject* -Crypto::GenerateCRMFRequest(JSContext* aContext, - const nsCString& aReqDN, - const nsCString& aRegToken, - const nsCString& aAuthenticator, - const nsCString& aEaCert, - const nsCString& aJsCallback, - const Sequence& aArgs, - ErrorResult& aRv) -{ - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); - return nullptr; -} - -void -Crypto::ImportUserCertificates(const nsAString& aNickname, - const nsAString& aCmmfResponse, - bool aDoForcedBackup, - nsAString& aReturn, - ErrorResult& aRv) -{ - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); -} - -void -Crypto::SignText(JSContext* aContext, - const nsAString& aStringToSign, - const nsAString& aCaOption, - const Sequence& aArgs, - nsAString& aReturn) - -{ - aReturn.AssignLiteral("error:internalError"); -} - -void -Crypto::Logout(ErrorResult& aRv) -{ - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); -} - -#endif - /* static */ uint8_t* Crypto::GetRandomValues(uint32_t aLength) { diff --git a/dom/base/Crypto.h b/dom/base/Crypto.h index dd2c204940bf..641e855453f8 100644 --- a/dom/base/Crypto.h +++ b/dom/base/Crypto.h @@ -4,17 +4,7 @@ #ifndef mozilla_dom_Crypto_h #define mozilla_dom_Crypto_h -#ifdef MOZ_DISABLE_CRYPTOLEGACY #include "nsIDOMCrypto.h" -#else -#include "nsIDOMCryptoLegacy.h" -namespace mozilla { -namespace dom { -class CRMFObject; -} -} -#endif - #include "mozilla/dom/SubtleCrypto.h" #include "nsPIDOMWindow.h" @@ -51,38 +41,6 @@ public: SubtleCrypto* Subtle(); -#ifndef MOZ_DISABLE_CRYPTOLEGACY - virtual bool EnableSmartCardEvents(); - virtual void SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv); - - virtual void GetVersion(nsString& aVersion); - - virtual mozilla::dom::CRMFObject* - GenerateCRMFRequest(JSContext* aContext, - const nsCString& aReqDN, - const nsCString& aRegToken, - const nsCString& aAuthenticator, - const nsCString& aEaCert, - const nsCString& aJsCallback, - const Sequence& aArgs, - ErrorResult& aRv); - - virtual void ImportUserCertificates(const nsAString& aNickname, - const nsAString& aCmmfResponse, - bool aDoForcedBackup, - nsAString& aReturn, - ErrorResult& aRv); - - virtual void SignText(JSContext* aContext, - const nsAString& aStringToSign, - const nsAString& aCaOption, - const Sequence& aArgs, - nsAString& aReturn); - - virtual void Logout(ErrorResult& aRv); - -#endif - // WebIDL nsPIDOMWindow* diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 87dfd49a02f9..d3f6cd9ccea5 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -83,9 +83,6 @@ #include "nsIDocCharset.h" #include "nsIDocument.h" #include "Crypto.h" -#ifndef MOZ_DISABLE_CRYPTOLEGACY -#include "nsIDOMCryptoLegacy.h" -#endif #include "nsIDOMDocument.h" #include "nsIDOMElement.h" #include "nsIDOMEvent.h" @@ -2364,14 +2361,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, nsCOMPtr oldDoc = mDoc; -#ifndef MOZ_DISABLE_CRYPTOLEGACY - // clear smartcard events, our document has gone away. - if (mCrypto && XRE_GetProcessType() != GeckoProcessType_Content) { - nsresult rv = mCrypto->SetEnableSmartCardEvents(false); - NS_ENSURE_SUCCESS(rv, rv); - } -#endif - AutoJSAPI jsapi; jsapi.Init(); JSContext *cx = jsapi.cx(); @@ -4459,20 +4448,7 @@ nsGlobalWindow::GetCrypto(ErrorResult& aError) FORWARD_TO_INNER_OR_THROW(GetCrypto, (aError), aError, nullptr); if (!mCrypto) { -#ifndef MOZ_DISABLE_CRYPTOLEGACY - if (XRE_GetProcessType() != GeckoProcessType_Content) { - nsresult rv; - mCrypto = do_CreateInstance(NS_CRYPTO_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - aError.Throw(rv); - return nullptr; - } - } else -#endif - { - mCrypto = new Crypto(); - } - + mCrypto = new Crypto(); mCrypto->Init(this); } return mCrypto; diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index fa49d1e9309e..06ebeb4482b0 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -251,14 +251,7 @@ DOMInterfaces = { 'headerFile': 'nsGeoPosition.h' }, -'CRMFObject': { - 'headerFile': 'nsCrypto.h', - 'nativeOwnership': 'owned', - 'wrapperCache': False, -}, - 'Crypto' : { - 'implicitJSContext': [ 'generateCRMFRequest', 'signText' ], 'headerFile': 'Crypto.h' }, diff --git a/dom/events/test/test_all_synthetic_events.html b/dom/events/test/test_all_synthetic_events.html index 07c5fe413413..ac0803f85a57 100644 --- a/dom/events/test/test_all_synthetic_events.html +++ b/dom/events/test/test_all_synthetic_events.html @@ -371,10 +371,6 @@ const kEventConstructors = { return e; }, }, - SmartCardEvent: { create: function (aName, aProps) { - return new SmartCardEvent(aName, aProps); - }, - }, SpeechRecognitionEvent: { create: function (aName, aProps) { return new SpeechRecognitionEvent(aName, aProps); }, diff --git a/dom/events/test/test_eventctors.html b/dom/events/test/test_eventctors.html index 41062d144f23..d55e40a734ae 100644 --- a/dom/events/test/test_eventctors.html +++ b/dom/events/test/test_eventctors.html @@ -748,29 +748,6 @@ is(e.requestingWindow, window); is(e.popupWindowFeatures, "features"); is(e.popupWindowName, "name"); - -// SmartCardEvent - -try { - e = new SmartCardEvent(); -} catch(exp) { - ex = true; -} -ok(ex, "SmartCardEvent: First parameter is required!"); -ex = false; - -e = new SmartCardEvent("hello"); -is(e.type, "hello", "SmartCardEvent: Wrong event type!"); -ok(!e.isTrusted, "SmartCardEvent: Event shouldn't be trusted!"); -ok(!e.bubbles, "SmartCardEvent: Event shouldn't bubble!"); -ok(!e.cancelable, "SmartCardEvent: Event shouldn't be cancelable!"); -is(e.tokenName, ""); -document.dispatchEvent(e); -is(receivedEvent, e, "SmartCardEvent: Wrong event!"); - -e = new SmartCardEvent("hello", { tokenName: "foo" }); -is(e.tokenName, "foo"); - // WheelEvent try { diff --git a/dom/interfaces/base/moz.build b/dom/interfaces/base/moz.build index dd21b6005ce0..b9a5b20fd3aa 100644 --- a/dom/interfaces/base/moz.build +++ b/dom/interfaces/base/moz.build @@ -16,6 +16,7 @@ XPIDL_SOURCES += [ 'nsIDOMClientRect.idl', 'nsIDOMClientRectList.idl', 'nsIDOMConstructor.idl', + 'nsIDOMCrypto.idl', 'nsIDOMGlobalObjectConstructor.idl', 'nsIDOMGlobalPropertyInitializer.idl', 'nsIDOMHistory.idl', @@ -37,15 +38,6 @@ XPIDL_SOURCES += [ 'nsITabParent.idl', ] -if CONFIG['MOZ_DISABLE_CRYPTOLEGACY']: - XPIDL_SOURCES += [ - 'nsIDOMCrypto.idl', - ] -else: - XPIDL_SOURCES += [ - 'nsIDOMCryptoLegacy.idl', - ] - if CONFIG['MOZ_B2G']: XPIDL_SOURCES += [ 'nsIDOMWindowB2G.idl', diff --git a/dom/interfaces/base/nsIDOMCryptoLegacy.idl b/dom/interfaces/base/nsIDOMCryptoLegacy.idl deleted file mode 100644 index 4af74bcf84f7..000000000000 --- a/dom/interfaces/base/nsIDOMCryptoLegacy.idl +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "domstubs.idl" - -interface nsIDOMWindow; - -[uuid(c25ecf08-3f46-4420-bee4-8505792fd63a)] -interface nsIDOMCrypto : nsISupports -{ - [notxpcom] void init(in nsIDOMWindow window); - attribute boolean enableSmartCardEvents; -}; diff --git a/dom/tests/mochitest/crypto/mochitest-legacy.ini b/dom/tests/mochitest/crypto/mochitest-legacy.ini deleted file mode 100644 index 30274031e346..000000000000 --- a/dom/tests/mochitest/crypto/mochitest-legacy.ini +++ /dev/null @@ -1,2 +0,0 @@ -[test_legacy.html] -skip-if = e10s diff --git a/dom/tests/mochitest/crypto/mochitest.ini b/dom/tests/mochitest/crypto/mochitest.ini index 9194b85295fb..14e454cf3cb1 100644 --- a/dom/tests/mochitest/crypto/mochitest.ini +++ b/dom/tests/mochitest/crypto/mochitest.ini @@ -2,4 +2,3 @@ skip-if = e10s [test_getRandomValues.html] -[test_no_legacy.html] diff --git a/dom/tests/mochitest/crypto/test_legacy.html b/dom/tests/mochitest/crypto/test_legacy.html deleted file mode 100644 index 9dfb48f06b38..000000000000 --- a/dom/tests/mochitest/crypto/test_legacy.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - Test presence of legacy window.crypto features when - MOZ_DISABLE_CRYPTOLEGACY is NOT set and dom.unsafe_legacy_crypto.enabled is true - - - - - - diff --git a/dom/tests/mochitest/crypto/test_no_legacy.html b/dom/tests/mochitest/crypto/test_no_legacy.html deleted file mode 100644 index b250da2ae596..000000000000 --- a/dom/tests/mochitest/crypto/test_no_legacy.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - Test lack of legacy window.crypto features when - MOZ_DISABLE_CRYPTOLEGACY is set or dom.unsafe_legacy_crypto.enabled is false - - - - - - diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 56755d1bd29f..4f6f15d622bc 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -857,8 +857,6 @@ var interfaceNamesInGlobalScope = "SimpleGestureEvent", // IMPORTANT: Do not change this list without review from a DOM peer! {name: "SimpleTest", xbl: false}, -// IMPORTANT: Do not change this list without review from a DOM peer! - "SmartCardEvent", // IMPORTANT: Do not change this list without review from a DOM peer! {name: "SpeechSynthesisEvent", b2g: true}, // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/tests/moz.build b/dom/tests/moz.build index 38a3b4837189..16631f67168f 100644 --- a/dom/tests/moz.build +++ b/dom/tests/moz.build @@ -48,11 +48,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gtk2': 'mochitest/pointerlock/mochitest.ini', ] -if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']: - MOCHITEST_MANIFESTS += [ - 'mochitest/crypto/mochitest-legacy.ini', - ] - if CONFIG['MOZ_GAMEPAD']: MOCHITEST_MANIFESTS += [ 'mochitest/gamepad/mochitest.ini', diff --git a/dom/webidl/CRMFObject.webidl b/dom/webidl/CRMFObject.webidl deleted file mode 100644 index 388e88f3008d..000000000000 --- a/dom/webidl/CRMFObject.webidl +++ /dev/null @@ -1,10 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. - */ - -[NoInterfaceObject] -interface CRMFObject { - readonly attribute DOMString request; -}; diff --git a/dom/webidl/Crypto.webidl b/dom/webidl/Crypto.webidl index f76801dee020..0eaaa777995c 100644 --- a/dom/webidl/Crypto.webidl +++ b/dom/webidl/Crypto.webidl @@ -19,38 +19,3 @@ interface Crypto { [Pref="dom.webcrypto.enabled"] readonly attribute SubtleCrypto subtle; }; - -#ifndef MOZ_DISABLE_CRYPTOLEGACY -[NoInterfaceObject] -interface CryptoLegacy { - [Pref="dom.unsafe_legacy_crypto.enabled"] - readonly attribute DOMString version; - - [SetterThrows,Pref="dom.unsafe_legacy_crypto.enabled"] - attribute boolean enableSmartCardEvents; - - [Throws,NewObject,Pref="dom.unsafe_legacy_crypto.enabled"] - CRMFObject? generateCRMFRequest(ByteString? reqDN, - ByteString? regToken, - ByteString? authenticator, - ByteString? eaCert, - ByteString? jsCallback, - any... args); - - [Throws,Pref="dom.unsafe_legacy_crypto.enabled"] - DOMString importUserCertificates(DOMString nickname, - DOMString cmmfResponse, - boolean doForcedBackup); - - [Pref="dom.unsafe_legacy_crypto.enabled"] - DOMString signText(DOMString stringToSign, - DOMString caOption, - ByteString... args); - - [Throws,Pref="dom.unsafe_legacy_crypto.enabled"] - void logout(); -}; - -Crypto implements CryptoLegacy; -#endif // !MOZ_DISABLE_CRYPTOLEGACY - diff --git a/dom/webidl/SmartCardEvent.webidl b/dom/webidl/SmartCardEvent.webidl deleted file mode 100644 index e3cf6323d465..000000000000 --- a/dom/webidl/SmartCardEvent.webidl +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. - */ - -[Constructor(DOMString type, optional SmartCardEventInit eventInitDict)] -interface SmartCardEvent : Event -{ - readonly attribute DOMString? tokenName; -}; - -dictionary SmartCardEventInit : EventInit -{ - DOMString tokenName = ""; -}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index b609225d13b5..727fa07f0f0a 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -552,7 +552,6 @@ WEBIDL_FILES += [ 'PopupBlockedEvent.webidl', 'ProgressEvent.webidl', 'RecordErrorEvent.webidl', - 'SmartCardEvent.webidl', 'StyleRuleChangeEvent.webidl', 'StyleSheetApplicableStateChangeEvent.webidl', 'StyleSheetChangeEvent.webidl', @@ -627,11 +626,6 @@ if CONFIG['MOZ_B2G_FM']: 'FMRadio.webidl', ] -if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']: - WEBIDL_FILES += [ - 'CRMFObject.webidl', - ] - GENERATED_EVENTS_WEBIDL_FILES = [ 'AutocompleteErrorEvent.webidl', 'BlobEvent.webidl', @@ -672,7 +666,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [ 'RTCPeerConnectionIdentityErrorEvent.webidl', 'RTCPeerConnectionIdentityEvent.webidl', 'SelectionChangeEvent.webidl', - 'SmartCardEvent.webidl', 'StyleRuleChangeEvent.webidl', 'StyleSheetApplicableStateChangeEvent.webidl', 'StyleSheetChangeEvent.webidl', diff --git a/mobile/android/confvars.sh b/mobile/android/confvars.sh index 3c7b4744486d..d7affe0b28a9 100644 --- a/mobile/android/confvars.sh +++ b/mobile/android/confvars.sh @@ -18,7 +18,7 @@ MOZ_ANDROID_MIN_SDK_VERSION=9 MOZ_SAFE_BROWSING=1 -MOZ_DISABLE_CRYPTOLEGACY=1 +MOZ_NO_SMART_CARDS=1 # Enable getUserMedia MOZ_MEDIA_NAVIGATOR=1 diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp index 4cbfe4813c27..77f2728e7fcc 100644 --- a/security/certverifier/CertVerifier.cpp +++ b/security/certverifier/CertVerifier.cpp @@ -372,8 +372,7 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage, case certificateUsageVerifyCA: case certificateUsageStatusResponder: { // XXX This is a pretty useless way to verify a certificate. It is used - // by the implementation of window.crypto.importCertificates and in the - // certificate viewer UI. Because we don't know what trust bit is + // by the certificate viewer UI. Because we don't know what trust bit is // interesting, we just try them all. mozilla::pkix::EndEntityOrCA endEntityOrCA; mozilla::pkix::KeyUsage keyUsage; diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.dtd b/security/manager/locales/en-US/chrome/pippki/pippki.dtd index 8df3a003b07f..a75bcd6b2436 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.dtd +++ b/security/manager/locales/en-US/chrome/pippki/pippki.dtd @@ -81,11 +81,6 @@ - - - - - diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.properties b/security/manager/locales/en-US/chrome/pippki/pippki.properties index 1d257bf1a54d..15d0d4584e60 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.properties +++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties @@ -133,9 +133,6 @@ importCACertsPrompt=Select File containing CA certificate(s) to import importServerCertPrompt=Select File containing Server certificate to import file_browse_Certificate_spec=Certificate Files -# Form Signing confirmation prompt -formSigningIntro=The site '%S' has requested that you sign the following text message: - # Cert export SaveCertAs=Save Certificate To File CertFormatBase64=X.509 Certificate (PEM) diff --git a/security/manager/pki/resources/content/certManager.js b/security/manager/pki/resources/content/certManager.js index bcb1f8a9281d..b3f2b5fd3750 100644 --- a/security/manager/pki/resources/content/certManager.js +++ b/security/manager/pki/resources/content/certManager.js @@ -32,11 +32,22 @@ var emailTreeView; var userTreeView; var orphanTreeView; +var smartCardObserver = { + observe: function() { + onSmartCardChange(); + } +}; + +function DeregisterSmartCardObservers() +{ + Services.obs.removeObserver(smartCardObserver, "smartcard-insert"); + Services.obs.removeObserver(smartCardObserver, "smartcard-remove"); +} + function LoadCerts() { - window.crypto.enableSmartCardEvents = true; - document.addEventListener("smartcard-insert", onSmartCardChange, false); - document.addEventListener("smartcard-remove", onSmartCardChange, false); + Services.obs.addObserver(smartCardObserver, "smartcard-insert", false); + Services.obs.addObserver(smartCardObserver, "smartcard-remove", false); certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB); var certcache = Components.classes[nsNSSCertCache].createInstance(nsINSSCertCache); @@ -613,4 +624,3 @@ function addException() orphanTreeView.loadCertsFromCache(certcache, nsIX509Cert.UNKNOWN_CERT); orphanTreeView.selection.clearSelection(); } - diff --git a/security/manager/pki/resources/content/certManager.xul b/security/manager/pki/resources/content/certManager.xul index 8ecd88f56357..3522d60f22f3 100644 --- a/security/manager/pki/resources/content/certManager.xul +++ b/security/manager/pki/resources/content/certManager.xul @@ -18,6 +18,7 @@ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" title="&certmgr.title;" onload="LoadCerts();" + onunload="DeregisterSmartCardObservers();" buttons="accept" style="width: 48em; height: 32em;" persist="screenX screenY width height"> diff --git a/security/manager/pki/resources/content/device_manager.js b/security/manager/pki/resources/content/device_manager.js index bf2e65d7c5e7..ab748fee6978 100644 --- a/security/manager/pki/resources/content/device_manager.js +++ b/security/manager/pki/resources/content/device_manager.js @@ -16,18 +16,31 @@ const nsDialogParamBlock = "@mozilla.org/embedcomp/dialogparam;1"; const nsIPKCS11 = Components.interfaces.nsIPKCS11; const nsPKCS11ContractID = "@mozilla.org/security/pkcs11;1"; +let { Services } = Components.utils.import("resource://gre/modules/Services.jsm", {}); + var bundle; var secmoddb; var skip_enable_buttons = false; +var smartCardObserver = { + observe: function() { + onSmartCardChange(); + } +}; + +function DeregisterSmartCardObservers() +{ + Services.obs.removeObserver(smartCardObserver, "smartcard-insert"); + Services.obs.removeObserver(smartCardObserver, "smartcard-remove"); +} + /* Do the initial load of all PKCS# modules and list them. */ function LoadModules() { bundle = document.getElementById("pippki_bundle"); secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB); - window.crypto.enableSmartCardEvents = true; - document.addEventListener("smartcard-insert", onSmartCardChange, false); - document.addEventListener("smartcard-remove", onSmartCardChange, false); + Services.obs.addObserver(smartCardObserver, "smartcard-insert", false); + Services.obs.addObserver(smartCardObserver, "smartcard-remove", false); RefreshDeviceList(); } diff --git a/security/manager/pki/resources/content/device_manager.xul b/security/manager/pki/resources/content/device_manager.xul index cd7d2bbc353f..13250478b3ce 100644 --- a/security/manager/pki/resources/content/device_manager.xul +++ b/security/manager/pki/resources/content/device_manager.xul @@ -19,6 +19,7 @@ style="&devmgr.style;" persist="screenX screenY width height" onload="LoadModules();" + onunload="DeregisterSmartCardObservers();" buttons="accept"> diff --git a/security/manager/pki/resources/content/formsigning.js b/security/manager/pki/resources/content/formsigning.js deleted file mode 100644 index e2ce261aec41..000000000000 --- a/security/manager/pki/resources/content/formsigning.js +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* 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/. */ - -const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock; - -var dialogParams; -var itemCount = 0; - -function onLoad() -{ - dialogParams = window.arguments[0].QueryInterface(nsIDialogParamBlock); - - var hostname = dialogParams.GetString(0); - var bundle = document.getElementById("pippki_bundle"); - var intro = bundle.getFormattedString("formSigningIntro", [hostname]); - setText("sign.intro", intro); - - document.getElementById("sign.text").value = dialogParams.GetString(1); - - var selectElement = document.getElementById("nicknames"); - itemCount = dialogParams.GetInt(0); - for (var index = 0; index < itemCount; ++index) { - var menuItemNode = document.createElement("menuitem"); - var nick = dialogParams.GetString(2 + 2 * index); - menuItemNode.setAttribute("value", index); - menuItemNode.setAttribute("label", nick); // this is displayed - selectElement.firstChild.appendChild(menuItemNode); - if (index == 0) { - selectElement.selectedItem = menuItemNode; - } - } - setDetails(); - document.getElementById("pw").focus(); -} - -function setDetails() -{ - var index = parseInt(document.getElementById("nicknames").value); - if (index == "NaN") - return; - - var details = dialogParams.GetString(2 + (2 * index + 1)); - document.getElementById("certdetails").value = details; -} - -function onCertSelected() -{ - setDetails(); -} - -function doOK() -{ - dialogParams.SetInt(0, 1); - var index = parseInt(document.getElementById("nicknames").value); - dialogParams.SetInt(1, index); - var password = document.getElementById("pw").value; - dialogParams.SetString(0, password); - return true; -} - -function doCancel() -{ - dialogParams.SetInt(0, 0); - return true; -} diff --git a/security/manager/pki/resources/content/formsigning.xul b/security/manager/pki/resources/content/formsigning.xul deleted file mode 100644 index 18fb0fc1e5c3..000000000000 --- a/security/manager/pki/resources/content/formsigning.xul +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - -%pippkiDTD; -]> - - - - - - - \ No newline at end of file diff --git a/security/manager/ssl/crashtests/crashtests.list b/security/manager/ssl/crashtests/crashtests.list index 8e4b0a9c4752..f869c9f65739 100644 --- a/security/manager/ssl/crashtests/crashtests.list +++ b/security/manager/ssl/crashtests/crashtests.list @@ -1,2 +1 @@ -skip-if(browserIsRemote) asserts-if(browserIsRemote,0-1) load 327524-1.html # bug 582297, bug 918119 asserts-if(browserIsRemote,1) load 398665-1.html # bug 582297 diff --git a/security/manager/ssl/public/moz.build b/security/manager/ssl/public/moz.build index 7b0e0758fd90..4426b524f494 100644 --- a/security/manager/ssl/public/moz.build +++ b/security/manager/ssl/public/moz.build @@ -17,7 +17,6 @@ XPIDL_SOURCES += [ 'nsIClientAuthDialogs.idl', 'nsIDataSignatureVerifier.idl', 'nsIDOMCryptoDialogs.idl', - 'nsIFormSigningDialog.idl', 'nsIGenKeypairInfoDlg.idl', 'nsIIdentityInfo.idl', 'nsIKeygenThread.idl', diff --git a/security/manager/ssl/public/nsIFormSigningDialog.idl b/security/manager/ssl/public/nsIFormSigningDialog.idl deleted file mode 100644 index 5de5979e6bc9..000000000000 --- a/security/manager/ssl/public/nsIFormSigningDialog.idl +++ /dev/null @@ -1,39 +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/. */ - -#include "nsISupports.idl" - -interface nsIInterfaceRequestor; - -/** - * nsIFormSigningDialog - * Provides UI for form signing. - */ -[scriptable, uuid(4fe04d6d-4b66-4023-a0bc-b43ce68b3e15)] -interface nsIFormSigningDialog : nsISupports -{ - /** - * confirmSignText - * UI shown when a web site calls crypto.signText, - * asking the user to confirm the confirm the signing request. - * - * returns true if the user confirmed, false on cancel - */ - boolean confirmSignText(in nsIInterfaceRequestor ctxt, - in AString host, - in AString signText, - [array, size_is(count)] in wstring certNickList, - [array, size_is(count)] in wstring certDetailsList, - in uint32_t count, - out int32_t selectedIndex, - out AString password); -}; - -/** - * NS_FORMSIGNINGDIALOG_CONTRACTID - contract id to obtain an instance - * that implements nsIFormSigningDialog. - */ -%{C++ -#define NS_FORMSIGNINGDIALOG_CONTRACTID "@mozilla.org/nsFormSigningDialog;1" -%} diff --git a/security/manager/ssl/src/moz.build b/security/manager/ssl/src/moz.build index a5d85b6dfd45..5ad3892e6fde 100644 --- a/security/manager/ssl/src/moz.build +++ b/security/manager/ssl/src/moz.build @@ -73,7 +73,7 @@ SOURCES += [ 'PSMContentListener.cpp', ] -if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']: +if not CONFIG['MOZ_NO_SMART_CARDS']: SOURCES += [ 'nsSmartCardMonitor.cpp', ] diff --git a/security/manager/ssl/src/nsCrypto.cpp b/security/manager/ssl/src/nsCrypto.cpp index f656eeeadbc9..a5e29e4f8d1d 100644 --- a/security/manager/ssl/src/nsCrypto.cpp +++ b/security/manager/ssl/src/nsCrypto.cpp @@ -14,213 +14,7 @@ #include "nsNativeCharsetUtils.h" #include "nsServiceManagerUtils.h" -#ifndef MOZ_DISABLE_CRYPTOLEGACY -#include "mozilla/dom/ScriptSettings.h" -#include "nsKeygenHandler.h" -#include "nsKeygenThread.h" -#include "nsNSSCertificate.h" -#include "nsNSSCertificateDB.h" -#include "nsPKCS12Blob.h" -#include "nsPK11TokenDB.h" -#include "nsThreadUtils.h" -#include "nsIServiceManager.h" -#include "nsIMemory.h" -#include "nsAlgorithm.h" -#include "prprf.h" -#include "nsDOMCID.h" -#include "nsIDOMWindow.h" -#include "nsIDOMClassInfo.h" -#include "nsIDOMDocument.h" -#include "nsIDocument.h" -#include "nsIScriptObjectPrincipal.h" -#include "nsIScriptContext.h" -#include "nsIGlobalObject.h" -#include "nsContentUtils.h" -#include "nsCxPusher.h" -#include "nsDOMJSUtils.h" -#include "nsJSUtils.h" -#include "nsIXPConnect.h" -#include "nsIRunnable.h" -#include "nsIWindowWatcher.h" -#include "nsIPrompt.h" -#include "nsIFilePicker.h" -#include "nsJSPrincipals.h" -#include "nsJSUtils.h" -#include "nsIPrincipal.h" -#include "nsIScriptSecurityManager.h" -#include "nsIGenKeypairInfoDlg.h" -#include "nsIDOMCryptoDialogs.h" -#include "nsIFormSigningDialog.h" -#include "nsIContentSecurityPolicy.h" -#include "nsIURI.h" -#include "jsapi.h" -#include "js/OldDebugAPI.h" -#include -#include "pk11func.h" -#include "keyhi.h" -#include "cryptohi.h" -#include "seccomon.h" -#include "secerr.h" -#include "sechash.h" -#include "crmf.h" -#include "pk11pqg.h" -#include "cmmf.h" -#include "nssb64.h" -#include "base64.h" -#include "cert.h" -#include "certdb.h" -#include "secmod.h" -#include "ScopedNSSTypes.h" -#include "pkix/pkixtypes.h" - -#include "ssl.h" // For SSL_ClearSessionCache - -#include "nsNSSCleaner.h" - -#include "nsNSSCertHelper.h" -#include -#include "nsWrapperCacheInlines.h" -#endif -#ifndef MOZ_DISABLE_CRYPTOLEGACY -#include "mozilla/dom/CRMFObjectBinding.h" -#endif - -using namespace mozilla; -using namespace mozilla::dom; - -/* - * These are the most common error strings that are returned - * by the JavaScript methods in case of error. - */ - -#define JS_ERROR "error:" -#define JS_ERROR_INTERNAL JS_ERROR"internalError" - -#undef REPORT_INCORRECT_NUM_ARGS - -#define JS_OK_ADD_MOD 3 -#define JS_OK_DEL_EXTERNAL_MOD 2 -#define JS_OK_DEL_INTERNAL_MOD 1 - -#define JS_ERR_INTERNAL -1 -#define JS_ERR_USER_CANCEL_ACTION -2 -#define JS_ERR_INCORRECT_NUM_OF_ARGUMENTS -3 -#define JS_ERR_DEL_MOD -4 -#define JS_ERR_ADD_MOD -5 -#define JS_ERR_BAD_MODULE_NAME -6 -#define JS_ERR_BAD_DLL_NAME -7 -#define JS_ERR_BAD_MECHANISM_FLAGS -8 -#define JS_ERR_BAD_CIPHER_ENABLE_FLAGS -9 -#define JS_ERR_ADD_DUPLICATE_MOD -10 - -#ifndef MOZ_DISABLE_CRYPTOLEGACY - -NSSCleanupAutoPtrClass_WithParam(PK11Context, PK11_DestroyContext, TrueParam, true) - -/* - * This structure is used to store information for one key generation. - * The nsCrypto::GenerateCRMFRequest method parses the inputs and then - * stores one of these structures for every key generation that happens. - * The information stored in this structure is then used to set some - * values in the CRMF request. - */ -typedef enum { - rsaEnc, rsaDualUse, rsaSign, rsaNonrepudiation, rsaSignNonrepudiation, - ecEnc, ecDualUse, ecSign, ecNonrepudiation, ecSignNonrepudiation, - dhEx, dsaSignNonrepudiation, dsaSign, dsaNonrepudiation, invalidKeyGen -} nsKeyGenType; - -bool isECKeyGenType(nsKeyGenType kgt) -{ - switch (kgt) - { - case ecEnc: - case ecDualUse: - case ecSign: - case ecNonrepudiation: - case ecSignNonrepudiation: - return true; - - default: - break; - } - - return false; -} - -typedef struct nsKeyPairInfoStr { - SECKEYPublicKey *pubKey; /* The putlic key associated with gen'd - priv key. */ - SECKEYPrivateKey *privKey; /* The private key we generated */ - nsKeyGenType keyGenType; /* What type of key gen are we doing.*/ - - CERTCertificate *ecPopCert; - /* null: use signing for pop - other than null: a cert that defines EC keygen params - and will be used for dhMac PoP. */ - - SECKEYPublicKey *ecPopPubKey; - /* extracted public key from ecPopCert */ -} nsKeyPairInfo; - - -//This class is just used to pass arguments -//to the nsCryptoRunnable event. -class nsCryptoRunArgs : public nsISupports { -public: - nsCryptoRunArgs(); - nsCOMPtr m_globalObject; - nsXPIDLCString m_jsCallback; - NS_DECL_ISUPPORTS -protected: - virtual ~nsCryptoRunArgs(); -}; - -//This class is used to run the callback code -//passed to crypto.generateCRMFRequest -//We have to do that for backwards compatibility -//reasons w/ PSM 1.x and Communciator 4.x -class nsCryptoRunnable : public nsIRunnable { -public: - nsCryptoRunnable(nsCryptoRunArgs *args); - - NS_IMETHOD Run (); - NS_DECL_ISUPPORTS -private: - virtual ~nsCryptoRunnable(); - - nsCryptoRunArgs *m_args; -}; - -//We're going to inherit the memory passed -//into us. -//This class backs up an array of certificates -//as an event. -class nsP12Runnable : public nsIRunnable { -public: - nsP12Runnable(nsIX509Cert **certArr, int32_t numCerts, nsIPK11Token *token); - - NS_IMETHOD Run(); - NS_DECL_ISUPPORTS -protected: - virtual ~nsP12Runnable(); -private: - nsCOMPtr mToken; - nsIX509Cert **mCertArr; - int32_t mNumCerts; -}; - -// QueryInterface implementation for nsCrypto -NS_INTERFACE_MAP_BEGIN(nsCrypto) - NS_INTERFACE_MAP_ENTRY(nsIDOMCrypto) -NS_INTERFACE_MAP_END_INHERITING(mozilla::dom::Crypto) - -NS_IMPL_ADDREF_INHERITED(nsCrypto, mozilla::dom::Crypto) -NS_IMPL_RELEASE_INHERITED(nsCrypto, mozilla::dom::Crypto) - // QueryInterface implementation for nsPkcs11 -#endif // MOZ_DISABLE_CRYPTOLEGACY - NS_INTERFACE_MAP_BEGIN(nsPkcs11) NS_INTERFACE_MAP_ENTRY(nsIPKCS11) NS_INTERFACE_MAP_ENTRY(nsISupports) @@ -229,2593 +23,6 @@ NS_INTERFACE_MAP_END NS_IMPL_ADDREF(nsPkcs11) NS_IMPL_RELEASE(nsPkcs11) -#ifndef MOZ_DISABLE_CRYPTOLEGACY - -// ISupports implementation for nsCryptoRunnable -NS_IMPL_ISUPPORTS(nsCryptoRunnable, nsIRunnable) - -// ISupports implementation for nsP12Runnable -NS_IMPL_ISUPPORTS(nsP12Runnable, nsIRunnable) - -// ISupports implementation for nsCryptoRunArgs -NS_IMPL_ISUPPORTS0(nsCryptoRunArgs) - -nsCrypto::nsCrypto() : - mEnableSmartCardEvents(false) -{ -} - -nsCrypto::~nsCrypto() -{ -} - -void -nsCrypto::Init(nsIDOMWindow* aWindow) -{ - mozilla::dom::Crypto::Init(aWindow); -} - -void -nsCrypto::SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv) -{ - NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); - - nsresult rv = NS_OK; - - // this has the side effect of starting the nssComponent (and initializing - // NSS) even if it isn't already going. Starting the nssComponent is a - // prerequisite for getting smartCard events. - if (aEnable) { - nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv)); - } - - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return; - } - - mEnableSmartCardEvents = aEnable; -} - -NS_IMETHODIMP -nsCrypto::SetEnableSmartCardEvents(bool aEnable) -{ - ErrorResult rv; - SetEnableSmartCardEvents(aEnable, rv); - return rv.ErrorCode(); -} - -bool -nsCrypto::EnableSmartCardEvents() -{ - return mEnableSmartCardEvents; -} - -NS_IMETHODIMP -nsCrypto::GetEnableSmartCardEvents(bool *aEnable) -{ - *aEnable = EnableSmartCardEvents(); - return NS_OK; -} - -//A quick function to let us know if the key we're trying to generate -//can be escrowed. -static bool -ns_can_escrow(nsKeyGenType keyGenType) -{ - /* For now, we only escrow rsa-encryption and ec-encryption keys. */ - return (bool)(keyGenType == rsaEnc || keyGenType == ecEnc); -} - -//Retrieve crypto.version so that callers know what -//version of PSM this is. -void -nsCrypto::GetVersion(nsString& aVersion) -{ - aVersion.Assign(NS_LITERAL_STRING(PSM_VERSION_STRING)); -} - -/* - * Given an nsKeyGenType, return the PKCS11 mechanism that will - * perform the correct key generation. - */ -static uint32_t -cryptojs_convert_to_mechanism(nsKeyGenType keyGenType) -{ - uint32_t retMech; - - switch (keyGenType) { - case rsaEnc: - case rsaDualUse: - case rsaSign: - case rsaNonrepudiation: - case rsaSignNonrepudiation: - retMech = CKM_RSA_PKCS_KEY_PAIR_GEN; - break; - case ecEnc: - case ecDualUse: - case ecSign: - case ecNonrepudiation: - case ecSignNonrepudiation: - retMech = CKM_EC_KEY_PAIR_GEN; - break; - case dhEx: - retMech = CKM_DH_PKCS_KEY_PAIR_GEN; - break; - case dsaSign: - case dsaSignNonrepudiation: - case dsaNonrepudiation: - retMech = CKM_DSA_KEY_PAIR_GEN; - break; - default: - retMech = CKM_INVALID_MECHANISM; - } - return retMech; -} - -/* - * This function takes a string read through JavaScript parameters - * and translates it to the internal enumeration representing the - * key gen type. Leading and trailing whitespace must be already removed. - */ -static nsKeyGenType -cryptojs_interpret_key_gen_type(const nsAString& keyAlg) -{ - if (keyAlg.EqualsLiteral("rsa-ex")) { - return rsaEnc; - } - if (keyAlg.EqualsLiteral("rsa-dual-use")) { - return rsaDualUse; - } - if (keyAlg.EqualsLiteral("rsa-sign")) { - return rsaSign; - } - if (keyAlg.EqualsLiteral("rsa-sign-nonrepudiation")) { - return rsaSignNonrepudiation; - } - if (keyAlg.EqualsLiteral("rsa-nonrepudiation")) { - return rsaNonrepudiation; - } - if (keyAlg.EqualsLiteral("ec-ex")) { - return ecEnc; - } - if (keyAlg.EqualsLiteral("ec-dual-use")) { - return ecDualUse; - } - if (keyAlg.EqualsLiteral("ec-sign")) { - return ecSign; - } - if (keyAlg.EqualsLiteral("ec-sign-nonrepudiation")) { - return ecSignNonrepudiation; - } - if (keyAlg.EqualsLiteral("ec-nonrepudiation")) { - return ecNonrepudiation; - } - if (keyAlg.EqualsLiteral("dsa-sign-nonrepudiation")) { - return dsaSignNonrepudiation; - } - if (keyAlg.EqualsLiteral("dsa-sign")) { - return dsaSign; - } - if (keyAlg.EqualsLiteral("dsa-nonrepudiation")) { - return dsaNonrepudiation; - } - if (keyAlg.EqualsLiteral("dh-ex")) { - return dhEx; - } - return invalidKeyGen; -} - -/* - * input: null terminated char* pointing to (the remainder of) an - * EC key param string. - * - * bool return value, false means "no more name=value pair found", - * true means "found, see out params" - * - * out param name: char * pointing to name (not zero terminated) - * out param name_len: length of found name - * out param value: char * pointing to value (not zero terminated) - * out param value_len: length of found value - * out param next_pair: to be used for a follow up call to this function - */ - -bool getNextNameValueFromECKeygenParamString(char *input, - char *&name, - int &name_len, - char *&value, - int &value_len, - char *&next_call) -{ - if (!input || !*input) - return false; - - // we allow leading ; and leading space in front of each name value pair - - while (*input && *input == ';') - ++input; - - while (*input && *input == ' ') - ++input; - - name = input; - - while (*input && *input != '=') - ++input; - - if (*input != '=') - return false; - - name_len = input - name; - ++input; - - value = input; - - while (*input && *input != ';') - ++input; - - value_len = input - value; - next_call = input; - - return true; -} - -//Take the string passed into us via crypto.generateCRMFRequest -//as the keygen type parameter and convert it to parameters -//we can actually pass to the PKCS#11 layer. -static void* -nsConvertToActualKeyGenParams(uint32_t keyGenMech, char *params, - uint32_t paramLen, int32_t keySize, - nsKeyPairInfo *keyPairInfo) -{ - void *returnParams = nullptr; - - - switch (keyGenMech) { - case CKM_RSA_PKCS_KEY_PAIR_GEN: - { - // For RSA, we don't support passing in key generation arguments from - // the JS code just yet. - if (params) - return nullptr; - - PK11RSAGenParams *rsaParams; - rsaParams = static_cast - (nsMemory::Alloc(sizeof(PK11RSAGenParams))); - - if (!rsaParams) { - return nullptr; - } - /* I'm just taking the same parameters used in - * certdlgs.c:GenKey - */ - if (keySize > 0) { - rsaParams->keySizeInBits = keySize; - } else { - rsaParams->keySizeInBits = 1024; - } - rsaParams->pe = DEFAULT_RSA_KEYGEN_PE; - returnParams = rsaParams; - break; - } - case CKM_EC_KEY_PAIR_GEN: - { - /* - * keygen params for generating EC keys must be composed of name=value pairs, - * multiple pairs allowed, separated using semicolon ; - * - * Either param "curve" or param "popcert" must be specified. - * curve=name-of-curve - * popcert=base64-encoded-cert - * - * When both params are specified, popcert will be used. - * If no popcert param is given, or if popcert can not be decoded, - * we will fall back to the curve param. - * - * Additional name=value pairs may be defined in the future. - * - * If param popcert is present and valid, the given certificate will be used - * to determine the key generation params. In addition the certificate - * will be used to produce a dhMac based Proof of Posession, - * using the cert's public key, subject and issuer names, - * as specified in RFC 2511 section 4.3 paragraph 2 and Appendix A. - * - * If neither param popcert nor param curve could be used, - * tse a curve based on the keysize param. - * NOTE: Here keysize is used only as an indication of - * High/Medium/Low strength; elliptic curve - * cryptography uses smaller keys than RSA to provide - * equivalent security. - */ - - char *curve = nullptr; - - { - // extract components of name=value list - - char *next_input = params; - char *name = nullptr; - char *value = nullptr; - int name_len = 0; - int value_len = 0; - - while (getNextNameValueFromECKeygenParamString( - next_input, name, name_len, value, value_len, - next_input)) - { - // use only the first specified curve - if (!curve && PL_strncmp(name, "curve", std::min(name_len, 5)) == 0) - { - curve = PL_strndup(value, value_len); - } - // use only the first specified popcert - else if (!keyPairInfo->ecPopCert && - PL_strncmp(name, "popcert", std::min(name_len, 7)) == 0) - { - char *certstr = PL_strndup(value, value_len); - if (certstr) { - keyPairInfo->ecPopCert = CERT_ConvertAndDecodeCertificate(certstr); - PL_strfree(certstr); - - if (keyPairInfo->ecPopCert) - { - keyPairInfo->ecPopPubKey = CERT_ExtractPublicKey(keyPairInfo->ecPopCert); - } - } - } - } - } - - // first try to use the params of the provided CA cert - if (keyPairInfo->ecPopPubKey && keyPairInfo->ecPopPubKey->keyType == ecKey) - { - returnParams = SECITEM_DupItem(&keyPairInfo->ecPopPubKey->u.ec.DEREncodedParams); - } - - // if we did not yet find good params, do we have a curve name? - if (!returnParams && curve) - { - returnParams = decode_ec_params(curve); - } - - // if we did not yet find good params, do something based on keysize - if (!returnParams) - { - switch (keySize) { - case 512: - case 1024: - returnParams = decode_ec_params("secp256r1"); - break; - case 2048: - default: - returnParams = decode_ec_params("secp384r1"); - break; - } - } - - if (curve) - PL_strfree(curve); - - break; - } - case CKM_DSA_KEY_PAIR_GEN: - { - // For DSA, we don't support passing in key generation arguments from - // the JS code just yet. - if (params) - return nullptr; - - PQGParams *pqgParams = nullptr; - PQGVerify *vfy = nullptr; - SECStatus rv; - int index; - - index = PQG_PBITS_TO_INDEX(keySize); - if (index == -1) { - returnParams = nullptr; - break; - } - rv = PK11_PQG_ParamGen(0, &pqgParams, &vfy); - if (vfy) { - PK11_PQG_DestroyVerify(vfy); - } - if (rv != SECSuccess) { - if (pqgParams) { - PK11_PQG_DestroyParams(pqgParams); - } - return nullptr; - } - returnParams = pqgParams; - break; - } - default: - returnParams = nullptr; - } - return returnParams; -} - -//We need to choose which PKCS11 slot we're going to generate -//the key on. Calls the default implementation provided by -//nsKeygenHandler.cpp -static PK11SlotInfo* -nsGetSlotForKeyGen(nsKeyGenType keyGenType, nsIInterfaceRequestor *ctx) -{ - nsNSSShutDownPreventionLock locker; - uint32_t mechanism = cryptojs_convert_to_mechanism(keyGenType); - PK11SlotInfo *slot = nullptr; - nsresult rv = GetSlotWithMechanism(mechanism,ctx, &slot); - if (NS_FAILED(rv)) { - if (slot) - PK11_FreeSlot(slot); - slot = nullptr; - } - return slot; -} - -//Free the parameters that were passed into PK11_GenerateKeyPair -//depending on the mechanism type used. -static void -nsFreeKeyGenParams(CK_MECHANISM_TYPE keyGenMechanism, void *params) -{ - switch (keyGenMechanism) { - case CKM_RSA_PKCS_KEY_PAIR_GEN: - nsMemory::Free(params); - break; - case CKM_EC_KEY_PAIR_GEN: - SECITEM_FreeItem(reinterpret_cast(params), true); - break; - case CKM_DSA_KEY_PAIR_GEN: - PK11_PQG_DestroyParams(static_cast(params)); - break; - } -} - -//Function that is used to generate a single key pair. -//Once all the arguments have been parsed and processed, this -//function gets called and takes care of actually generating -//the key pair passing the appopriate parameters to the NSS -//functions. -static nsresult -cryptojs_generateOneKeyPair(JSContext *cx, nsKeyPairInfo *keyPairInfo, - int32_t keySize, char *params, - nsIInterfaceRequestor *uiCxt, - PK11SlotInfo *slot, bool willEscrow) - -{ - const PK11AttrFlags sensitiveFlags = (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE); - const PK11AttrFlags temporarySessionFlags = PK11_ATTR_SESSION; - const PK11AttrFlags permanentTokenFlags = PK11_ATTR_TOKEN; - const PK11AttrFlags extractableFlags = PK11_ATTR_EXTRACTABLE; - - nsIGeneratingKeypairInfoDialogs * dialogs; - nsKeygenThread *KeygenRunnable = 0; - nsCOMPtr runnable; - - uint32_t mechanism = cryptojs_convert_to_mechanism(keyPairInfo->keyGenType); - void *keyGenParams = nsConvertToActualKeyGenParams(mechanism, params, - (params) ? strlen(params):0, - keySize, keyPairInfo); - - if (!keyGenParams || !slot) { - return NS_ERROR_INVALID_ARG; - } - - // Make sure the token has password already set on it before trying - // to generate the key. - - nsresult rv = setPassword(slot, uiCxt); - if (NS_FAILED(rv)) - return rv; - - if (PK11_Authenticate(slot, true, uiCxt) != SECSuccess) - return NS_ERROR_FAILURE; - - // Smart cards will not let you extract a private key once - // it is on the smart card. If we've been told to escrow - // a private key that will be stored on a smart card, - // then we'll use the following strategy to ensure we can escrow it. - // We'll attempt to generate the key on our internal token, - // because this is expected to avoid some problems. - // If it works, we'll escrow, move the key to the smartcard, done. - // If it didn't work (or the internal key doesn't support the desired - // mechanism), then we'll attempt to generate the key on - // the destination token, with the EXTRACTABLE flag set. - // If it works, we'll extract, escrow, done. - // If it failed, then we're unable to escrow and return failure. - // NOTE: We call PK11_GetInternalSlot instead of PK11_GetInternalKeySlot - // so that the key has zero chance of being store in the - // user's key3.db file. Which the slot returned by - // PK11_GetInternalKeySlot has access to and PK11_GetInternalSlot - // does not. - ScopedPK11SlotInfo intSlot; - - if (willEscrow && !PK11_IsInternal(slot)) { - intSlot = PK11_GetInternalSlot(); - NS_ASSERTION(intSlot,"Couldn't get the internal slot"); - - if (!PK11_DoesMechanism(intSlot, mechanism)) { - // Set to null, and the subsequent code will not attempt to use it. - intSlot = nullptr; - } - } - - rv = getNSSDialogs((void**)&dialogs, - NS_GET_IID(nsIGeneratingKeypairInfoDialogs), - NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID); - - if (NS_SUCCEEDED(rv)) { - KeygenRunnable = new nsKeygenThread(); - if (KeygenRunnable) { - NS_ADDREF(KeygenRunnable); - } - } - - // "firstAttemptSlot" and "secondAttemptSlot" are alternative names - // for better code readability, we don't increase the reference counts. - - PK11SlotInfo *firstAttemptSlot = nullptr; - PK11AttrFlags firstAttemptFlags = 0; - - PK11SlotInfo *secondAttemptSlot = slot; - PK11AttrFlags secondAttemptFlags = sensitiveFlags | permanentTokenFlags; - - if (willEscrow) { - secondAttemptFlags |= extractableFlags; - } - - if (!intSlot || PK11_IsInternal(slot)) { - // if we cannot use the internal slot, then there is only one attempt - // if the destination slot is the internal slot, then there is only one attempt - firstAttemptSlot = secondAttemptSlot; - firstAttemptFlags = secondAttemptFlags; - secondAttemptSlot = nullptr; - secondAttemptFlags = 0; - } - else { - firstAttemptSlot = intSlot; - firstAttemptFlags = sensitiveFlags | temporarySessionFlags; - - // We always need the extractable flag on the first attempt, - // because we want to move the key to another slot - ### is this correct? - firstAttemptFlags |= extractableFlags; - } - - bool mustMoveKey = false; - - if (NS_FAILED(rv) || !KeygenRunnable) { - /* execute key generation on this thread */ - rv = NS_OK; - - keyPairInfo->privKey = - PK11_GenerateKeyPairWithFlags(firstAttemptSlot, mechanism, - keyGenParams, &keyPairInfo->pubKey, - firstAttemptFlags, uiCxt); - - if (keyPairInfo->privKey) { - // success on first attempt - if (secondAttemptSlot) { - mustMoveKey = true; - } - } - else { - keyPairInfo->privKey = - PK11_GenerateKeyPairWithFlags(secondAttemptSlot, mechanism, - keyGenParams, &keyPairInfo->pubKey, - secondAttemptFlags, uiCxt); - } - - } else { - /* execute key generation on separate thread */ - KeygenRunnable->SetParams( firstAttemptSlot, firstAttemptFlags, - secondAttemptSlot, secondAttemptFlags, - mechanism, keyGenParams, uiCxt ); - - runnable = do_QueryInterface(KeygenRunnable); - - if (runnable) { - { - nsPSMUITracker tracker; - if (tracker.isUIForbidden()) { - rv = NS_ERROR_NOT_AVAILABLE; - } - else { - rv = dialogs->DisplayGeneratingKeypairInfo(uiCxt, runnable); - // We call join on the thread, - // so we can be sure that no simultaneous access to the passed parameters will happen. - KeygenRunnable->Join(); - } - } - - NS_RELEASE(dialogs); - if (NS_SUCCEEDED(rv)) { - PK11SlotInfo *used_slot = nullptr; - rv = KeygenRunnable->ConsumeResult(&used_slot, - &keyPairInfo->privKey, &keyPairInfo->pubKey); - - if (NS_SUCCEEDED(rv)) { - if ((used_slot == firstAttemptSlot) && secondAttemptSlot) { - mustMoveKey = true; - } - - if (used_slot) { - PK11_FreeSlot(used_slot); - } - } - } - } - } - - firstAttemptSlot = nullptr; - secondAttemptSlot = nullptr; - - nsFreeKeyGenParams(mechanism, keyGenParams); - - if (KeygenRunnable) { - NS_RELEASE(KeygenRunnable); - } - - if (!keyPairInfo->privKey || !keyPairInfo->pubKey) { - return NS_ERROR_FAILURE; - } - - //If we generated the key pair on the internal slot because the - // keys were going to be escrowed, move the keys over right now. - if (mustMoveKey) { - ScopedSECKEYPrivateKey newPrivKey(PK11_LoadPrivKey(slot, - keyPairInfo->privKey, - keyPairInfo->pubKey, - true, true)); - if (!newPrivKey) - return NS_ERROR_FAILURE; - - // The private key is stored on the selected slot now, and the copy we - // ultimately use for escrowing when the time comes lives - // in the internal slot. We will delete it from that slot - // after the requests are made. - } - - return NS_OK; -} - -/* - * FUNCTION: cryptojs_ReadArgsAndGenerateKey - * ------------------------------------- - * INPUTS: - * cx - * The JSContext associated with the execution of the corresponging - * crypto.generateCRMFRequest call - * argv - * A pointer to an array of JavaScript parameters passed to the - * method crypto.generateCRMFRequest. The array should have the - * 3 arguments keySize, "keyParams", and "keyGenAlg" mentioned in - * the definition of crypto.generateCRMFRequest at the following - * document http://docs.iplanet.com/docs/manuals/psm/11/cmcjavascriptapi.html - * keyGenType - * A structure used to store the information about the newly created - * key pair. - * uiCxt - * An interface requestor that would be used to get an nsIPrompt - * if we need to ask the user for a password. - * slotToUse - * The PKCS11 slot to use for generating the key pair. If nullptr, then - * this function should select a slot that can do the key generation - * from the keytype associted with the keyPairInfo, and pass it back to - * the caller so that subsequence key generations can use the same slot. - * willEscrow - * If true, then that means we will try to escrow the generated - * private key when building the CRMF request. If false, then - * we will not try to escrow the private key. - * - * NOTES: - * This function takes care of reading a set of 3 parameters that define - * one key generation. The argv pointer should be one that originates - * from the argv parameter passed in to the method nsCrypto::GenerateCRMFRequest. - * The function interprets the argument in the first index as an integer and - * passes that as the key size for the key generation-this parameter is - * mandatory. The second parameter is read in as a string. This value can - * be null in JavaScript world and everything will still work. The third - * parameter is a mandatory string that indicates what kind of key to generate. - * There should always be 1-to-1 correspondence between the strings compared - * in the function cryptojs_interpret_key_gen_type and the strings listed in - * document at http://docs.iplanet.com/docs/manuals/psm/11/cmcjavascriptapi.html - * under the definition of the method generateCRMFRequest, for the parameter - * "keyGenAlgN". After reading the parameters, the function then - * generates the key pairs passing the parameters parsed from the JavaScript i - * routine. - * - * RETURN: - * NS_OK if creating the Key was successful. Any other return value - * indicates an error. - */ - -static nsresult -cryptojs_ReadArgsAndGenerateKey(JSContext *cx, - JS::Value *argv, - nsKeyPairInfo *keyGenType, - nsIInterfaceRequestor *uiCxt, - PK11SlotInfo **slot, bool willEscrow) -{ - JSString *jsString; - JSAutoByteString params; - int keySize; - nsresult rv; - - if (!argv[0].isInt32()) { - JS_ReportError(cx, "%s%s", JS_ERROR, - "passed in non-integer for key size"); - return NS_ERROR_FAILURE; - } - keySize = argv[0].toInt32(); - if (!argv[1].isNull()) { - JS::Rooted v(cx, argv[1]); - jsString = JS::ToString(cx, v); - NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY); - argv[1] = STRING_TO_JSVAL(jsString); - params.encodeLatin1(cx, jsString); - NS_ENSURE_TRUE(!!params, NS_ERROR_OUT_OF_MEMORY); - } - - if (argv[2].isNull()) { - JS_ReportError(cx,"%s%s", JS_ERROR, - "key generation type not specified"); - return NS_ERROR_FAILURE; - } - JS::Rooted v(cx, argv[2]); - jsString = JS::ToString(cx, v); - NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY); - argv[2] = STRING_TO_JSVAL(jsString); - nsAutoJSString autoJSKeyGenAlg; - NS_ENSURE_TRUE(autoJSKeyGenAlg.init(cx, jsString), NS_ERROR_UNEXPECTED); - nsAutoString keyGenAlg(autoJSKeyGenAlg); - keyGenAlg.Trim("\r\n\t "); - keyGenType->keyGenType = cryptojs_interpret_key_gen_type(keyGenAlg); - if (keyGenType->keyGenType == invalidKeyGen) { - NS_LossyConvertUTF16toASCII keyGenAlgNarrow(autoJSKeyGenAlg); - JS_ReportError(cx, "%s%s%s", JS_ERROR, - "invalid key generation argument:", - keyGenAlgNarrow.get()); - goto loser; - } - if (!*slot) { - *slot = nsGetSlotForKeyGen(keyGenType->keyGenType, uiCxt); - if (!*slot) - goto loser; - } - - rv = cryptojs_generateOneKeyPair(cx,keyGenType,keySize,params.ptr(),uiCxt, - *slot,willEscrow); - - if (rv != NS_OK) { - NS_LossyConvertUTF16toASCII keyGenAlgNarrow(autoJSKeyGenAlg); - JS_ReportError(cx,"%s%s%s", JS_ERROR, - "could not generate the key for algorithm ", - keyGenAlgNarrow.get()); - goto loser; - } - return NS_OK; -loser: - return NS_ERROR_FAILURE; -} - -//Utility funciton to free up the memory used by nsKeyPairInfo -//arrays. -static void -nsFreeKeyPairInfo(nsKeyPairInfo *keyids, int numIDs) -{ - NS_ASSERTION(keyids, "NULL pointer passed to nsFreeKeyPairInfo"); - if (!keyids) - return; - int i; - for (i=0; iGetCert()); - if (!cert) - return NS_ERROR_FAILURE; - - CRMFEncryptedKey *encrKey = - CRMF_CreateEncryptedKeyWithEncryptedValue(keyInfo->privKey, cert.get()); - if (!encrKey) - return NS_ERROR_FAILURE; - - CRMFPKIArchiveOptions *archOpt = - CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encrKey); - if (!archOpt) { - CRMF_DestroyEncryptedKey(encrKey); - return NS_ERROR_FAILURE; - } - SECStatus srv = CRMF_CertRequestSetPKIArchiveOptions(certReq, archOpt); - CRMF_DestroyEncryptedKey(encrKey); - CRMF_DestroyPKIArchiveOptions(archOpt); - if (srv != SECSuccess) - return NS_ERROR_FAILURE; - - return NS_OK; -} - -//Set the Distinguished Name (Subject Name) for the cert -//being requested. -static nsresult -nsSetDNForRequest(CRMFCertRequest *certReq, char *reqDN) -{ - if (!reqDN || CRMF_CertRequestIsFieldPresent(certReq, crmfSubject)) { - return NS_ERROR_FAILURE; - } - ScopedCERTName subjectName(CERT_AsciiToName(reqDN)); - if (!subjectName) { - return NS_ERROR_FAILURE; - } - SECStatus srv = CRMF_CertRequestSetTemplateField(certReq, crmfSubject, - static_cast - (subjectName)); - return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE; -} - -//Set Registration Token Control on the request. -static nsresult -nsSetRegToken(CRMFCertRequest *certReq, char *regToken) -{ - // this should never happen, but might as well add this. - NS_ASSERTION(certReq, "A bogus certReq passed to nsSetRegToken"); - if (regToken){ - if (CRMF_CertRequestIsControlPresent(certReq, crmfRegTokenControl)) - return NS_ERROR_FAILURE; - - SECItem src; - src.data = (unsigned char*)regToken; - src.len = strlen(regToken); - SECItem *derEncoded = SEC_ASN1EncodeItem(nullptr, nullptr, &src, - SEC_ASN1_GET(SEC_UTF8StringTemplate)); - - if (!derEncoded) - return NS_ERROR_FAILURE; - - SECStatus srv = CRMF_CertRequestSetRegTokenControl(certReq, derEncoded); - SECITEM_FreeItem(derEncoded,true); - if (srv != SECSuccess) - return NS_ERROR_FAILURE; - } - return NS_OK; -} - -//Set the Authenticator control on the cert reuest. It's just -//a string that gets passed along. -static nsresult -nsSetAuthenticator(CRMFCertRequest *certReq, char *authenticator) -{ - //This should never happen, but might as well check. - NS_ASSERTION(certReq, "Bogus certReq passed to nsSetAuthenticator"); - if (authenticator) { - if (CRMF_CertRequestIsControlPresent(certReq, crmfAuthenticatorControl)) - return NS_ERROR_FAILURE; - - SECItem src; - src.data = (unsigned char*)authenticator; - src.len = strlen(authenticator); - SECItem *derEncoded = SEC_ASN1EncodeItem(nullptr, nullptr, &src, - SEC_ASN1_GET(SEC_UTF8StringTemplate)); - if (!derEncoded) - return NS_ERROR_FAILURE; - - SECStatus srv = CRMF_CertRequestSetAuthenticatorControl(certReq, - derEncoded); - SECITEM_FreeItem(derEncoded, true); - if (srv != SECSuccess) - return NS_ERROR_FAILURE; - } - return NS_OK; -} - -// ASN1 DER encoding rules say that when encoding a BIT string, -// the length in the header for the bit string is the number -// of "useful" bits in the BIT STRING. So the function finds -// it and sets accordingly for the returned item. -static void -nsPrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value) -{ - unsigned char onebyte; - unsigned int i, len = 0; - - /* to prevent warning on some platform at compile time */ - onebyte = '\0'; - /* Get the position of the right-most turn-on bit */ - for (i = 0; i < (value->len ) * 8; ++i) { - if (i % 8 == 0) - onebyte = value->data[i/8]; - if (onebyte & 0x80) - len = i; - onebyte <<= 1; - } - - bitsmap->data = value->data; - /* Add one here since we work with base 1 */ - bitsmap->len = len + 1; -} - -//This next section defines all the functions that sets the -//keyUsageExtension for all the different types of key gens -//we handle. The keyUsageExtension is just a bit flag extension -//that we set in wrapper functions that call straight into -//nsSetKeyUsageExtension. There is one wrapper funciton for each -//keyGenType. The correct function will eventually be called -//by going through a switch statement based on the nsKeyGenType -//in the nsKeyPairInfo struct. -static nsresult -nsSetKeyUsageExtension(CRMFCertRequest *crmfReq, - unsigned char keyUsage) -{ - SECItem *encodedExt= nullptr; - SECItem keyUsageValue = { (SECItemType) 0, nullptr, 0 }; - SECItem bitsmap = { (SECItemType) 0, nullptr, 0 }; - SECStatus srv; - CRMFCertExtension *ext = nullptr; - CRMFCertExtCreationInfo extAddParams; - SEC_ASN1Template bitStrTemplate = {SEC_ASN1_BIT_STRING, 0, nullptr, - sizeof(SECItem)}; - - keyUsageValue.data = &keyUsage; - keyUsageValue.len = 1; - nsPrepareBitStringForEncoding(&bitsmap, &keyUsageValue); - - encodedExt = SEC_ASN1EncodeItem(nullptr, nullptr, &bitsmap,&bitStrTemplate); - if (!encodedExt) { - goto loser; - } - ext = CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, true, encodedExt); - if (!ext) { - goto loser; - } - extAddParams.numExtensions = 1; - extAddParams.extensions = &ext; - srv = CRMF_CertRequestSetTemplateField(crmfReq, crmfExtension, - &extAddParams); - if (srv != SECSuccess) { - goto loser; - } - CRMF_DestroyCertExtension(ext); - SECITEM_FreeItem(encodedExt, true); - return NS_OK; - loser: - if (ext) { - CRMF_DestroyCertExtension(ext); - } - if (encodedExt) { - SECITEM_FreeItem(encodedExt, true); - } - return NS_ERROR_FAILURE; -} - -static nsresult -nsSetRSADualUse(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE - | KU_NON_REPUDIATION - | KU_KEY_ENCIPHERMENT; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetRSAKeyEx(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_KEY_ENCIPHERMENT; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetRSASign(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE; - - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetRSANonRepudiation(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_NON_REPUDIATION; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetRSASignNonRepudiation(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE | - KU_NON_REPUDIATION; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetECDualUse(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE - | KU_NON_REPUDIATION - | KU_KEY_AGREEMENT; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetECKeyEx(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_KEY_AGREEMENT; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetECSign(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE; - - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetECNonRepudiation(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_NON_REPUDIATION; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetECSignNonRepudiation(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE | - KU_NON_REPUDIATION; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetDH(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_KEY_AGREEMENT; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetDSASign(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetDSANonRepudiation(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_NON_REPUDIATION; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetDSASignNonRepudiation(CRMFCertRequest *crmfReq) -{ - unsigned char keyUsage = KU_DIGITAL_SIGNATURE | - KU_NON_REPUDIATION; - - return nsSetKeyUsageExtension(crmfReq, keyUsage); -} - -static nsresult -nsSetKeyUsageExtension(CRMFCertRequest *crmfReq, nsKeyGenType keyGenType) -{ - nsresult rv; - - switch (keyGenType) { - case rsaDualUse: - rv = nsSetRSADualUse(crmfReq); - break; - case rsaEnc: - rv = nsSetRSAKeyEx(crmfReq); - break; - case rsaSign: - rv = nsSetRSASign(crmfReq); - break; - case rsaNonrepudiation: - rv = nsSetRSANonRepudiation(crmfReq); - break; - case rsaSignNonrepudiation: - rv = nsSetRSASignNonRepudiation(crmfReq); - break; - case ecDualUse: - rv = nsSetECDualUse(crmfReq); - break; - case ecEnc: - rv = nsSetECKeyEx(crmfReq); - break; - case ecSign: - rv = nsSetECSign(crmfReq); - break; - case ecNonrepudiation: - rv = nsSetECNonRepudiation(crmfReq); - break; - case ecSignNonrepudiation: - rv = nsSetECSignNonRepudiation(crmfReq); - break; - case dhEx: - rv = nsSetDH(crmfReq); - break; - case dsaSign: - rv = nsSetDSASign(crmfReq); - break; - case dsaNonrepudiation: - rv = nsSetDSANonRepudiation(crmfReq); - break; - case dsaSignNonrepudiation: - rv = nsSetDSASignNonRepudiation(crmfReq); - break; - default: - rv = NS_ERROR_FAILURE; - break; - } - return rv; -} - -//Create a single CRMFCertRequest with all of the necessary parts -//already installed. The request returned by this function will -//have all the parts necessary and can just be added to a -//Certificate Request Message. -static CRMFCertRequest* -nsCreateSingleCertReq(nsKeyPairInfo *keyInfo, char *reqDN, char *regToken, - char *authenticator, nsNSSCertificate *wrappingCert) -{ - uint32_t reqID; - nsresult rv; - - //The draft says the ID of the request should be a random - //number. We don't have a way of tracking this number - //to compare when the reply actually comes back,though. - PK11_GenerateRandom((unsigned char*)&reqID, sizeof(reqID)); - CRMFCertRequest *certReq = CRMF_CreateCertRequest(reqID); - if (!certReq) - return nullptr; - - long version = SEC_CERTIFICATE_VERSION_3; - SECStatus srv; - CERTSubjectPublicKeyInfo *spki = nullptr; - srv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion, &version); - if (srv != SECSuccess) - goto loser; - - spki = SECKEY_CreateSubjectPublicKeyInfo(keyInfo->pubKey); - if (!spki) - goto loser; - - srv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, spki); - SECKEY_DestroySubjectPublicKeyInfo(spki); - if (srv != SECSuccess) - goto loser; - - if (wrappingCert && ns_can_escrow(keyInfo->keyGenType)) { - rv = nsSetEscrowAuthority(certReq, keyInfo, wrappingCert); - if (NS_FAILED(rv)) - goto loser; - } - rv = nsSetDNForRequest(certReq, reqDN); - if (NS_FAILED(rv)) - goto loser; - - rv = nsSetRegToken(certReq, regToken); - if (NS_FAILED(rv)) - goto loser; - - rv = nsSetAuthenticator(certReq, authenticator); - if (NS_FAILED(rv)) - goto loser; - - rv = nsSetKeyUsageExtension(certReq, keyInfo->keyGenType); - if (NS_FAILED(rv)) - goto loser; - - return certReq; -loser: - if (certReq) { - CRMF_DestroyCertRequest(certReq); - } - return nullptr; -} - -/* - * This function will set the Proof Of Possession (POP) for a request - * associated with a key pair intended to do Key Encipherment. Currently - * this means encryption only keys. - */ -static nsresult -nsSetKeyEnciphermentPOP(CRMFCertReqMsg *certReqMsg, bool isEscrowed) -{ - SECItem bitString; - unsigned char der[2]; - SECStatus srv; - - if (isEscrowed) { - /* For proof of possession on escrowed keys, we use the - * this Message option of POPOPrivKey and include a zero - * length bit string in the POP field. This is OK because the encrypted - * private key already exists as part of the PKIArchiveOptions - * Control and that for all intents and purposes proves that - * we do own the private key. - */ - der[0] = 0x03; /*We've got a bit string */ - der[1] = 0x00; /*We've got a 0 length bit string */ - bitString.data = der; - bitString.len = 2; - srv = CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg, crmfThisMessage, - crmfNoSubseqMess, &bitString); - } else { - /* If the encryption key is not being escrowed, then we set the - * Proof Of Possession to be a Challenge Response mechanism. - */ - srv = CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg, - crmfSubsequentMessage, - crmfChallengeResp, nullptr); - } - return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE; -} - -static void -nsCRMFEncoderItemCount(void *arg, const char *buf, unsigned long len); - -static void -nsCRMFEncoderItemStore(void *arg, const char *buf, unsigned long len); - -static nsresult -nsSet_EC_DHMAC_ProofOfPossession(CRMFCertReqMsg *certReqMsg, - nsKeyPairInfo *keyInfo, - CRMFCertRequest *certReq) -{ - // RFC 2511 Appendix A section 2 a) defines, - // the "text" input for HMAC shall be the DER encoded version of - // of the single cert request. - // We'll produce that encoding and destroy it afterwards, - // because when sending the complete package to the CA, - // we'll use a different encoding, one that includes POP and - // allows multiple requests to be sent in one step. - - unsigned long der_request_len = 0; - ScopedSECItem der_request; - - if (SECSuccess != CRMF_EncodeCertRequest(certReq, - nsCRMFEncoderItemCount, - &der_request_len)) - return NS_ERROR_FAILURE; - - der_request = SECITEM_AllocItem(nullptr, nullptr, der_request_len); - if (!der_request) - return NS_ERROR_FAILURE; - - // set len in returned SECItem back to zero, because it will - // be used as the destination offset inside the - // nsCRMFEncoderItemStore callback. - - der_request->len = 0; - - if (SECSuccess != CRMF_EncodeCertRequest(certReq, - nsCRMFEncoderItemStore, - der_request)) - return NS_ERROR_FAILURE; - - // RFC 2511 Appendix A section 2 c): - // "A key K is derived from the shared secret Kec and the subject and - // issuer names in the CA's certificate as follows: - // K = SHA1(DER-encoded-subjectName | Kec | DER-encoded-issuerName)" - - ScopedPK11SymKey shared_secret; - ScopedPK11SymKey subject_and_secret; - ScopedPK11SymKey subject_and_secret_and_issuer; - ScopedPK11SymKey sha1_of_subject_and_secret_and_issuer; - - shared_secret = - PK11_PubDeriveWithKDF(keyInfo->privKey, // SECKEYPrivateKey *privKey - keyInfo->ecPopPubKey, // SECKEYPublicKey *pubKey - false, // bool isSender - nullptr, // SECItem *randomA - nullptr, // SECItem *randomB - CKM_ECDH1_DERIVE, // CK_MECHANISM_TYPE derive - CKM_CONCATENATE_DATA_AND_BASE, // CK_MECHANISM_TYPE target - CKA_DERIVE, // CK_ATTRIBUTE_TYPE operation - 0, // int keySize - CKD_NULL, // CK_ULONG kdf - nullptr, // SECItem *sharedData - nullptr); // void *wincx - - if (!shared_secret) - return NS_ERROR_FAILURE; - - CK_KEY_DERIVATION_STRING_DATA concat_data_base; - concat_data_base.pData = keyInfo->ecPopCert->derSubject.data; - concat_data_base.ulLen = keyInfo->ecPopCert->derSubject.len; - SECItem concat_data_base_item; - concat_data_base_item.data = (unsigned char*)&concat_data_base; - concat_data_base_item.len = sizeof(CK_KEY_DERIVATION_STRING_DATA); - - subject_and_secret = - PK11_Derive(shared_secret, // PK11SymKey *baseKey - CKM_CONCATENATE_DATA_AND_BASE, // CK_MECHANISM_TYPE mechanism - &concat_data_base_item, // SECItem *param - CKM_CONCATENATE_BASE_AND_DATA, // CK_MECHANISM_TYPE target - CKA_DERIVE, // CK_ATTRIBUTE_TYPE operation - 0); // int keySize - - if (!subject_and_secret) - return NS_ERROR_FAILURE; - - CK_KEY_DERIVATION_STRING_DATA concat_base_data; - concat_base_data.pData = keyInfo->ecPopCert->derSubject.data; - concat_base_data.ulLen = keyInfo->ecPopCert->derSubject.len; - SECItem concat_base_data_item; - concat_base_data_item.data = (unsigned char*)&concat_base_data; - concat_base_data_item.len = sizeof(CK_KEY_DERIVATION_STRING_DATA); - - subject_and_secret_and_issuer = - PK11_Derive(subject_and_secret, // PK11SymKey *baseKey - CKM_CONCATENATE_BASE_AND_DATA, // CK_MECHANISM_TYPE mechanism - &concat_base_data_item, // SECItem *param - CKM_SHA1_KEY_DERIVATION, // CK_MECHANISM_TYPE target - CKA_DERIVE, // CK_ATTRIBUTE_TYPE operation - 0); // int keySize - - if (!subject_and_secret_and_issuer) - return NS_ERROR_FAILURE; - - sha1_of_subject_and_secret_and_issuer = - PK11_Derive(subject_and_secret_and_issuer, // PK11SymKey *baseKey - CKM_SHA1_KEY_DERIVATION, // CK_MECHANISM_TYPE mechanism - nullptr, // SECItem *param - CKM_SHA_1_HMAC, // CK_MECHANISM_TYPE target - CKA_SIGN, // CK_ATTRIBUTE_TYPE operation - 0); // int keySize - - if (!sha1_of_subject_and_secret_and_issuer) - return NS_ERROR_FAILURE; - - PK11Context *context = nullptr; - PK11ContextCleanerTrueParam context_cleaner(context); - - SECItem ignore; - ignore.data = 0; - ignore.len = 0; - - context = - PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, // CK_MECHANISM_TYPE type - CKA_SIGN, // CK_ATTRIBUTE_TYPE operation - sha1_of_subject_and_secret_and_issuer, // PK11SymKey *symKey - &ignore); // SECItem *param - - if (!context) - return NS_ERROR_FAILURE; - - if (SECSuccess != PK11_DigestBegin(context)) - return NS_ERROR_FAILURE; - - if (SECSuccess != - PK11_DigestOp(context, der_request->data, der_request->len)) - return NS_ERROR_FAILURE; - - ScopedAutoSECItem result_hmac_sha1_item(SHA1_LENGTH); - - if (SECSuccess != - PK11_DigestFinal(context, - result_hmac_sha1_item.data, - &result_hmac_sha1_item.len, - SHA1_LENGTH)) - return NS_ERROR_FAILURE; - - if (SECSuccess != - CRMF_CertReqMsgSetKeyAgreementPOP(certReqMsg, crmfDHMAC, - crmfNoSubseqMess, &result_hmac_sha1_item)) - return NS_ERROR_FAILURE; - - return NS_OK; -} - -static nsresult -nsSetProofOfPossession(CRMFCertReqMsg *certReqMsg, - nsKeyPairInfo *keyInfo, - CRMFCertRequest *certReq) -{ - // Depending on the type of cert request we'll try - // POP mechanisms in different order, - // and add the result to the cert request message. - // - // For any signing or dual use cert, - // try signing first, - // fall back to DHMAC if we can - // (EC cert requests that provide keygen param "popcert"), - // otherwise fail. - // - // For encryption only certs that get escrowed, this is sufficient. - // - // For encryption only certs, that are not being escrowed, - // try DHMAC if we can - // (EC cert requests that provide keygen param "popcert"), - // otherwise we'll indicate challenge response should be used. - - bool isEncryptionOnlyCertRequest = false; - bool escrowEncryptionOnlyCert = false; - - switch (keyInfo->keyGenType) - { - case rsaEnc: - case ecEnc: - isEncryptionOnlyCertRequest = true; - break; - - case rsaSign: - case rsaDualUse: - case rsaNonrepudiation: - case rsaSignNonrepudiation: - case ecSign: - case ecDualUse: - case ecNonrepudiation: - case ecSignNonrepudiation: - case dsaSign: - case dsaNonrepudiation: - case dsaSignNonrepudiation: - break; - - case dhEx: - /* This case may be supported in the future, but for now, we just fall - * though to the default case and return an error for diffie-hellman keys. - */ - default: - return NS_ERROR_FAILURE; - }; - - if (isEncryptionOnlyCertRequest) - { - escrowEncryptionOnlyCert = - CRMF_CertRequestIsControlPresent(certReq,crmfPKIArchiveOptionsControl); - } - - bool gotDHMACParameters = false; - - if (isECKeyGenType(keyInfo->keyGenType) && - keyInfo->ecPopCert && - keyInfo->ecPopPubKey) - { - gotDHMACParameters = true; - } - - if (isEncryptionOnlyCertRequest) - { - if (escrowEncryptionOnlyCert) - return nsSetKeyEnciphermentPOP(certReqMsg, true); // escrowed - - if (gotDHMACParameters) - return nsSet_EC_DHMAC_ProofOfPossession(certReqMsg, keyInfo, certReq); - - return nsSetKeyEnciphermentPOP(certReqMsg, false); // not escrowed - } - - // !isEncryptionOnlyCertRequest - - SECStatus srv = CRMF_CertReqMsgSetSignaturePOP(certReqMsg, - keyInfo->privKey, - keyInfo->pubKey, nullptr, - nullptr, nullptr); - - if (srv == SECSuccess) - return NS_OK; - - if (!gotDHMACParameters) - return NS_ERROR_FAILURE; - - return nsSet_EC_DHMAC_ProofOfPossession(certReqMsg, keyInfo, certReq); -} - -static void -nsCRMFEncoderItemCount(void *arg, const char *buf, unsigned long len) -{ - unsigned long *count = (unsigned long *)arg; - *count += len; -} - -static void -nsCRMFEncoderItemStore(void *arg, const char *buf, unsigned long len) -{ - SECItem *dest = (SECItem *)arg; - memcpy(dest->data + dest->len, buf, len); - dest->len += len; -} - -static SECItem* -nsEncodeCertReqMessages(CRMFCertReqMsg **certReqMsgs) -{ - unsigned long len = 0; - if (CRMF_EncodeCertReqMessages(certReqMsgs, nsCRMFEncoderItemCount, &len) - != SECSuccess) { - return nullptr; - } - SECItem *dest = (SECItem *)PORT_Alloc(sizeof(SECItem)); - if (!dest) { - return nullptr; - } - dest->type = siBuffer; - dest->data = (unsigned char *)PORT_Alloc(len); - if (!dest->data) { - PORT_Free(dest); - return nullptr; - } - dest->len = 0; - - if (CRMF_EncodeCertReqMessages(certReqMsgs, nsCRMFEncoderItemStore, dest) - != SECSuccess) { - SECITEM_FreeItem(dest, true); - return nullptr; - } - return dest; -} - -//Create a Base64 encoded CRMFCertReqMsg that can be sent to a CA -//requesting one or more certificates to be issued. This function -//creates a single cert request per key pair and then appends it to -//a message that is ultimately sent off to a CA. -static char* -nsCreateReqFromKeyPairs(nsKeyPairInfo *keyids, int32_t numRequests, - char *reqDN, char *regToken, char *authenticator, - nsNSSCertificate *wrappingCert) -{ - // We'use the goto notation for clean-up purposes in this function - // that calls the C API of NSS. - int32_t i; - // The ASN1 encoder in NSS wants the last entry in the array to be - // nullptr so that it knows when the last element is. - CRMFCertReqMsg **certReqMsgs = new CRMFCertReqMsg*[numRequests+1]; - CRMFCertRequest *certReq; - if (!certReqMsgs) - return nullptr; - memset(certReqMsgs, 0, sizeof(CRMFCertReqMsg*)*(1+numRequests)); - SECStatus srv; - nsresult rv; - SECItem *encodedReq; - char *retString; - for (i=0; i& aArgs, - ErrorResult& aRv) -{ - nsNSSShutDownPreventionLock locker; - nsresult nrv; - - uint32_t argc = aArgs.Length(); - - /* - * Get all of the parameters. - */ - if (argc % 3 != 0) { - aRv.ThrowNotEnoughArgsError(); - return nullptr; - } - - if (aReqDN.IsVoid()) { - NS_WARNING("no DN specified"); - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - if (aJsCallback.IsVoid()) { - NS_WARNING("no completion function specified"); - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr globalObject = do_QueryInterface(GetParentObject()); - if (MOZ_UNLIKELY(!globalObject)) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - nsCOMPtr csp; - if (!nsContentUtils::GetContentSecurityPolicy(getter_AddRefs(csp))) { - NS_ERROR("Error: failed to get CSP"); - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - bool evalAllowed = true; - bool reportEvalViolations = false; - if (csp && NS_FAILED(csp->GetAllowsEval(&reportEvalViolations, &evalAllowed))) { - NS_WARNING("CSP: failed to get allowsEval"); - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - if (reportEvalViolations) { - NS_NAMED_LITERAL_STRING(scriptSample, "window.crypto.generateCRMFRequest: call to eval() or related function blocked by CSP"); - - const char *fileName; - uint32_t lineNum; - nsJSUtils::GetCallingLocation(aContext, &fileName, &lineNum); - csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL, - NS_ConvertASCIItoUTF16(fileName), - scriptSample, - lineNum, - EmptyString(), - EmptyString()); - } - - if (!evalAllowed) { - NS_WARNING("eval() not allowed by Content Security Policy"); - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - //Put up some UI warning that someone is trying to - //escrow the private key. - //Don't addref this copy. That way ths reference goes away - //at the same the nsIX09Cert ref goes away. - nsNSSCertificate *escrowCert = nullptr; - nsCOMPtr nssCert; - bool willEscrow = false; - if (!aEaCert.IsVoid()) { - SECItem certDer = {siBuffer, nullptr, 0}; - SECStatus srv = ATOB_ConvertAsciiToItem(&certDer, aEaCert.get()); - if (srv != SECSuccess) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - ScopedCERTCertificate cert( - CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - &certDer, nullptr, false, true)); - if (!cert) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - escrowCert = nsNSSCertificate::Create(cert.get()); - nssCert = escrowCert; - if (!nssCert) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - - nsCOMPtr dialogs; - nsresult rv = getNSSDialogs(getter_AddRefs(dialogs), - NS_GET_IID(nsIDOMCryptoDialogs), - NS_DOMCRYPTODIALOGS_CONTRACTID); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return nullptr; - } - - bool okay=false; - { - nsPSMUITracker tracker; - if (tracker.isUIForbidden()) { - okay = false; - } - else { - dialogs->ConfirmKeyEscrow(nssCert, &okay); - } - } - if (!okay) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - willEscrow = true; - } - nsCOMPtr uiCxt = new PipUIContext; - int32_t numRequests = argc / 3; - nsKeyPairInfo *keyids = new nsKeyPairInfo[numRequests]; - memset(keyids, 0, sizeof(nsKeyPairInfo)*numRequests); - int keyInfoIndex; - uint32_t i; - PK11SlotInfo *slot = nullptr; - // Go through all of the arguments and generate the appropriate key pairs. - for (i=0,keyInfoIndex=0; i(&aArgs[i]), - &keyids[keyInfoIndex], - uiCxt, &slot, willEscrow); - - if (NS_FAILED(nrv)) { - if (slot) - PK11_FreeSlot(slot); - nsFreeKeyPairInfo(keyids,numRequests); - aRv.Throw(nrv); - return nullptr; - } - } - // By this time we'd better have a slot for the key gen. - NS_ASSERTION(slot, "There was no slot selected for key generation"); - if (slot) - PK11_FreeSlot(slot); - - char *encodedRequest = nsCreateReqFromKeyPairs(keyids,numRequests, - const_cast(aReqDN.get()), - const_cast(aRegToken.get()), - const_cast(aAuthenticator.get()), - escrowCert); - if (!encodedRequest) { - nsFreeKeyPairInfo(keyids, numRequests); - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - CRMFObject* newObject = new CRMFObject(); - newObject->SetCRMFRequest(encodedRequest); - PORT_Free(encodedRequest); - nsFreeKeyPairInfo(keyids, numRequests); - - // Post an event on the UI queue so that the JS gets called after - // we return control to the JS layer. Why do we have to this? - // Because when this API was implemented for PSM 1.x w/ Communicator, - // the only way to make this method work was to have a callback - // in the JS layer that got called after key generation had happened. - // So for backwards compatibility, we return control and then just post - // an event to call the JS the script provides as the code to execute - // when the request has been generated. - // - - MOZ_ASSERT(nsContentUtils::GetCurrentJSContext()); - nsCryptoRunArgs *args = new nsCryptoRunArgs(); - - args->m_globalObject = globalObject; - if (!aJsCallback.IsVoid()) { - args->m_jsCallback = aJsCallback; - } - - nsRefPtr cryptoRunnable(new nsCryptoRunnable(args)); - - nsresult rv = NS_DispatchToMainThread(cryptoRunnable); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - } - - return newObject; -} - -// Reminder that we inherit the memory passed into us here. -// An implementation to let us back up certs as an event. -nsP12Runnable::nsP12Runnable(nsIX509Cert **certArr, int32_t numCerts, - nsIPK11Token *token) -{ - mCertArr = certArr; - mNumCerts = numCerts; - mToken = token; -} - -nsP12Runnable::~nsP12Runnable() -{ - int32_t i; - for (i=0; i nssComponent(do_GetService(kNSSComponentCID, &rv)); - if (NS_FAILED(rv)) - return rv; - - //Build up the message that let's the user know we're trying to - //make PKCS12 backups of the new certs. - nssComponent->GetPIPNSSBundleString("ForcedBackup1", final); - final.Append(MOZ_UTF16("\n\n")); - nssComponent->GetPIPNSSBundleString("ForcedBackup2", temp); - final.Append(temp.get()); - final.Append(MOZ_UTF16("\n\n")); - - nssComponent->GetPIPNSSBundleString("ForcedBackup3", temp); - - final.Append(temp.get()); - nsNSSComponent::ShowAlertWithConstructedString(final); - - nsCOMPtr filePicker = - do_CreateInstance("@mozilla.org/filepicker;1", &rv); - if (!filePicker) { - NS_ERROR("Could not create a file picker when backing up certs."); - return rv; - } - - nsCOMPtr wwatch = - (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr window; - wwatch->GetActiveWindow(getter_AddRefs(window)); - - nsString filePickMessage; - nssComponent->GetPIPNSSBundleString("chooseP12BackupFileDialog", - filePickMessage); - rv = filePicker->Init(window, filePickMessage, nsIFilePicker::modeSave); - NS_ENSURE_SUCCESS(rv, rv); - - filePicker->AppendFilter(NS_LITERAL_STRING("PKCS12"), - NS_LITERAL_STRING("*.p12")); - filePicker->AppendFilters(nsIFilePicker::filterAll); - - int16_t dialogReturn; - filePicker->Show(&dialogReturn); - if (dialogReturn == nsIFilePicker::returnCancel) - return NS_OK; //User canceled. It'd be nice if they couldn't, - //but oh well. - - nsCOMPtr localFile; - rv = filePicker->GetFile(getter_AddRefs(localFile)); - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; - - nsPKCS12Blob p12Cxt; - - p12Cxt.SetToken(mToken); - p12Cxt.ExportToFile(localFile, mCertArr, mNumCerts); - return NS_OK; -} - -nsCryptoRunArgs::nsCryptoRunArgs() {} - -nsCryptoRunArgs::~nsCryptoRunArgs() {} - -nsCryptoRunnable::nsCryptoRunnable(nsCryptoRunArgs *args) -{ - nsNSSShutDownPreventionLock locker; - NS_ASSERTION(args,"Passed nullptr to nsCryptoRunnable constructor."); - m_args = args; - NS_IF_ADDREF(m_args); -} - -nsCryptoRunnable::~nsCryptoRunnable() -{ - nsNSSShutDownPreventionLock locker; - NS_IF_RELEASE(m_args); -} - -//Implementation that runs the callback passed to -//crypto.generateCRMFRequest as an event. -NS_IMETHODIMP -nsCryptoRunnable::Run() -{ - nsNSSShutDownPreventionLock locker; - - // We're going to run script via JS_EvaluateScript, so we need an - // AutoEntryScript. This is Gecko specific and not on a standards track. - AutoEntryScript aes(m_args->m_globalObject); - JSContext* cx = aes.cx(); - JS::RootedObject scope(cx, JS::CurrentGlobalOrNull(cx)); - - bool ok = - JS_EvaluateScript(cx, scope, m_args->m_jsCallback, - strlen(m_args->m_jsCallback), nullptr, 0); - return ok ? NS_OK : NS_ERROR_FAILURE; -} - -//Quick helper function to check if a newly issued cert -//already exists in the user's database. -static bool -nsCertAlreadyExists(SECItem *derCert) -{ - CERTCertDBHandle *handle = CERT_GetDefaultCertDB(); - bool retVal = false; - - ScopedCERTCertificate cert(CERT_FindCertByDERCert(handle, derCert)); - if (cert) { - if (cert->isperm && !cert->nickname && !cert->emailAddr) { - //If the cert doesn't have a nickname or email addr, it is - //bogus cruft, so delete it. - SEC_DeletePermCertificate(cert.get()); - } else if (cert->isperm) { - retVal = true; - } - } - return retVal; -} - -static int32_t -nsCertListCount(CERTCertList *certList) -{ - int32_t numCerts = 0; - CERTCertListNode *node; - - node = CERT_LIST_HEAD(certList); - while (!CERT_LIST_END(node, certList)) { - numCerts++; - node = CERT_LIST_NEXT(node); - } - return numCerts; -} - -//Import user certificates that arrive as a CMMF base64 encoded -//string. -void -nsCrypto::ImportUserCertificates(const nsAString& aNickname, - const nsAString& aCmmfResponse, - bool aDoForcedBackup, - nsAString& aReturn, - ErrorResult& aRv) -{ - nsNSSShutDownPreventionLock locker; - char *nickname=nullptr, *cmmfResponse=nullptr; - CMMFCertRepContent *certRepContent = nullptr; - int numResponses = 0; - nsIX509Cert **certArr = nullptr; - int i; - CMMFCertResponse *currResponse; - CMMFPKIStatus reqStatus; - CERTCertificate *currCert; - PK11SlotInfo *slot; - nsAutoCString localNick; - nsCOMPtr ctx = new PipUIContext(); - nsresult rv = NS_OK; - nsCOMPtr token; - - nickname = ToNewCString(aNickname); - cmmfResponse = ToNewCString(aCmmfResponse); - if (nsCRT::strcmp("null", nickname) == 0) { - nsMemory::Free(nickname); - nickname = nullptr; - } - - SECItem cmmfDer = {siBuffer, nullptr, 0}; - SECStatus srv = ATOB_ConvertAsciiToItem(&cmmfDer, cmmfResponse); - - if (srv != SECSuccess) { - rv = NS_ERROR_FAILURE; - goto loser; - } - - certRepContent = CMMF_CreateCertRepContentFromDER(CERT_GetDefaultCertDB(), - (const char*)cmmfDer.data, - cmmfDer.len); - if (!certRepContent) { - rv = NS_ERROR_FAILURE; - goto loser; - } - - numResponses = CMMF_CertRepContentGetNumResponses(certRepContent); - - if (aDoForcedBackup) { - //We've been asked to force the user to back up these - //certificates. Let's keep an array of them around which - //we pass along to the nsP12Runnable to use. - certArr = new nsIX509Cert*[numResponses]; - // If this is nullptr, chances are we're gonna fail really - // soon, but let's try to keep going just in case. - if (!certArr) - aDoForcedBackup = false; - - memset(certArr, 0, sizeof(nsIX509Cert*)*numResponses); - } - for (i=0; iderCert)) { - if (aDoForcedBackup) { - certArr[i] = nsNSSCertificate::Create(currCert); - if (!certArr[i]) - goto loser; - NS_ADDREF(certArr[i]); - } - CERT_DestroyCertificate(currCert); - CMMF_DestroyCertResponse(currResponse); - continue; - } - // Let's figure out which nickname to give the cert. If - // a certificate with the same subject name already exists, - // then just use that one, otherwise, get the default nickname. - if (currCert->nickname) { - localNick = currCert->nickname; - } - else if (!nickname || nickname[0] == '\0') { - nsNSSCertificateDB::get_default_nickname(currCert, ctx, localNick, locker); - } else { - //This is the case where we're getting a brand new - //cert that doesn't have the same subjectName as a cert - //that already exists in our db and the CA page has - //designated a nickname to use for the newly issued cert. - localNick = nickname; - } - { - char *cast_const_away = const_cast(localNick.get()); - slot = PK11_ImportCertForKey(currCert, cast_const_away, ctx); - } - if (!slot) { - rv = NS_ERROR_FAILURE; - goto loser; - } - if (aDoForcedBackup) { - certArr[i] = nsNSSCertificate::Create(currCert); - if (!certArr[i]) - goto loser; - NS_ADDREF(certArr[i]); - } - CERT_DestroyCertificate(currCert); - - if (!token) - token = new nsPK11Token(slot); - - PK11_FreeSlot(slot); - CMMF_DestroyCertResponse(currResponse); - } - //Let the loser: label take care of freeing up our reference to - //nickname (This way we don't free it twice and avoid crashing. - //That would be a good thing. - - //Import the root chain into the cert db. - { - ScopedCERTCertList caPubs(CMMF_CertRepContentGetCAPubs(certRepContent)); - if (caPubs) { - int32_t numCAs = nsCertListCount(caPubs.get()); - - NS_ASSERTION(numCAs > 0, "Invalid number of CA's"); - if (numCAs > 0) { - CERTCertListNode *node; - SECItem *derCerts; - - derCerts = static_cast - (nsMemory::Alloc(sizeof(SECItem)*numCAs)); - if (!derCerts) { - rv = NS_ERROR_OUT_OF_MEMORY; - goto loser; - } - for (node = CERT_LIST_HEAD(caPubs), i=0; - !CERT_LIST_END(node, caPubs); - node = CERT_LIST_NEXT(node), i++) { - derCerts[i] = node->cert->derCert; - } - nsNSSCertificateDB::ImportValidCACerts(numCAs, derCerts, ctx, locker); - nsMemory::Free(derCerts); - } - } - } - - if (aDoForcedBackup) { - // I can't pop up a file picker from the depths of JavaScript, - // so I'll just post an event on the UI queue to do the backups - // later. - nsCOMPtr p12Runnable = new nsP12Runnable(certArr, numResponses, - token); - if (!p12Runnable) { - rv = NS_ERROR_FAILURE; - goto loser; - } - - // null out the certArr pointer which has now been inherited by - // the nsP12Runnable instance so that we don't free up the - // memory on the way out. - certArr = nullptr; - - rv = NS_DispatchToMainThread(p12Runnable); - if (NS_FAILED(rv)) - goto loser; - } - - loser: - if (certArr) { - for (i=0; i domWindow = - do_QueryInterface(scriptContext->GetGlobalObject()); - if (!domWindow) { - return; - } - - nsCOMPtr domDocument; - domWindow->GetDocument(getter_AddRefs(domDocument)); - if (!domDocument) { - return; - } - - CallQueryInterface(domDocument, aDocument); - - return; -} - -void signTextOutputCallback(void *arg, const char *buf, unsigned long len) -{ - ((nsCString*)arg)->Append(buf, len); -} - -void -nsCrypto::SignText(JSContext* aContext, - const nsAString& aStringToSign, - const nsAString& aCaOption, - const Sequence& aArgs, - nsAString& aReturn) -{ - // XXX This code should return error codes, but we're keeping this - // backwards compatible with NS4.x and so we can't throw exceptions. - NS_NAMED_LITERAL_STRING(internalError, "error:internalError"); - - aReturn.Truncate(); - - uint32_t argc = aArgs.Length(); - - if (!aCaOption.EqualsLiteral("auto") && - !aCaOption.EqualsLiteral("ask")) { - NS_WARNING("caOption argument must be ask or auto"); - aReturn.Append(internalError); - - return; - } - - // It was decided to always behave as if "ask" were specified. - // XXX Should we warn in the JS Console for auto? - - nsCOMPtr uiContext = new PipUIContext; - if (!uiContext) { - aReturn.Append(internalError); - - return; - } - - bool bestOnly = true; - bool validOnly = true; - CERTCertList* certList = - CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), certUsageEmailSigner, - bestOnly, validOnly, uiContext); - - uint32_t numCAs = argc; - if (numCAs > 0) { - nsAutoArrayPtr caNames(new char*[numCAs]); - if (!caNames) { - aReturn.Append(internalError); - return; - } - - uint32_t i; - for (i = 0; i < numCAs; ++i) - caNames[i] = const_cast(aArgs[i].get()); - - if (certList && - CERT_FilterCertListByCANames(certList, numCAs, caNames, - certUsageEmailSigner) != SECSuccess) { - aReturn.Append(internalError); - - return; - } - } - - if (!certList || CERT_LIST_EMPTY(certList)) { - aReturn.AppendLiteral("error:noMatchingCert"); - - return; - } - - nsCOMPtr fsd = - do_CreateInstance(NS_FORMSIGNINGDIALOG_CONTRACTID); - if (!fsd) { - aReturn.Append(internalError); - - return; - } - - nsCOMPtr document; - GetDocumentFromContext(aContext, getter_AddRefs(document)); - if (!document) { - aReturn.Append(internalError); - - return; - } - - // Get the hostname from the URL of the document. - nsIURI* uri = document->GetDocumentURI(); - if (!uri) { - aReturn.Append(internalError); - - return; - } - - nsresult rv; - - nsCString host; - rv = uri->GetHost(host); - if (NS_FAILED(rv)) { - aReturn.Append(internalError); - - return; - } - - int32_t numberOfCerts = 0; - CERTCertListNode* node; - for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); - node = CERT_LIST_NEXT(node)) { - ++numberOfCerts; - } - - ScopedCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList)); - - if (!nicknames) { - aReturn.Append(internalError); - - return; - } - - NS_ASSERTION(nicknames->numnicknames == numberOfCerts, - "nicknames->numnicknames != numberOfCerts"); - - nsAutoArrayPtr certNicknameList(new char16_t*[nicknames->numnicknames * 2]); - if (!certNicknameList) { - aReturn.Append(internalError); - - return; - } - - char16_t** certDetailsList = certNicknameList.get() + nicknames->numnicknames; - - int32_t certsToUse; - for (node = CERT_LIST_HEAD(certList), certsToUse = 0; - !CERT_LIST_END(node, certList) && certsToUse < nicknames->numnicknames; - node = CERT_LIST_NEXT(node)) { - RefPtr tempCert(nsNSSCertificate::Create(node->cert)); - if (tempCert) { - nsAutoString nickWithSerial, details; - rv = tempCert->FormatUIStrings(NS_ConvertUTF8toUTF16(nicknames->nicknames[certsToUse]), - nickWithSerial, details); - if (NS_SUCCEEDED(rv)) { - certNicknameList[certsToUse] = ToNewUnicode(nickWithSerial); - if (certNicknameList[certsToUse]) { - certDetailsList[certsToUse] = ToNewUnicode(details); - if (!certDetailsList[certsToUse]) { - nsMemory::Free(certNicknameList[certsToUse]); - continue; - } - ++certsToUse; - } - } - } - } - - if (certsToUse == 0) { - aReturn.Append(internalError); - - return; - } - - NS_ConvertUTF8toUTF16 utf16Host(host); - - CERTCertificate *signingCert = nullptr; - bool tryAgain, canceled; - nsAutoString password; - do { - // Throw up the form signing confirmation dialog and get back the index - // of the selected cert. - int32_t selectedIndex = -1; - rv = fsd->ConfirmSignText(uiContext, utf16Host, aStringToSign, - const_cast(certNicknameList.get()), - const_cast(certDetailsList), - certsToUse, &selectedIndex, password, - &canceled); - if (NS_FAILED(rv) || canceled) { - break; // out of tryAgain loop - } - - int32_t j = 0; - for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); - node = CERT_LIST_NEXT(node)) { - if (j == selectedIndex) { - signingCert = CERT_DupCertificate(node->cert); - break; // out of cert list iteration loop - } - ++j; - } - - if (!signingCert) { - rv = NS_ERROR_FAILURE; - break; // out of tryAgain loop - } - - NS_ConvertUTF16toUTF8 pwUtf8(password); - - tryAgain = - PK11_CheckUserPassword(signingCert->slot, - const_cast(pwUtf8.get())) != SECSuccess; - // XXX we should show an error dialog before retrying - } while (tryAgain); - - int32_t k; - for (k = 0; k < certsToUse; ++k) { - nsMemory::Free(certNicknameList[k]); - nsMemory::Free(certDetailsList[k]); - } - - if (NS_FAILED(rv)) { // something went wrong inside the tryAgain loop - aReturn.Append(internalError); - - return; - } - - if (canceled) { - aReturn.AppendLiteral("error:userCancel"); - - return; - } - - SECKEYPrivateKey* privKey = PK11_FindKeyByAnyCert(signingCert, uiContext); - if (!privKey) { - aReturn.Append(internalError); - - return; - } - - nsAutoCString charset(document->GetDocumentCharacterSet()); - - // XXX Doing what nsFormSubmission::GetEncoder does (see - // http://bugzilla.mozilla.org/show_bug.cgi?id=81203). - if (charset.EqualsLiteral("ISO-8859-1")) { - charset.AssignLiteral("windows-1252"); - } - - nsCOMPtr encoder = - do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID); - if (encoder) { - rv = encoder->Init(charset.get(), - (nsISaveAsCharset::attr_EntityAfterCharsetConv + - nsISaveAsCharset::attr_FallbackDecimalNCR), - 0); - } - - nsXPIDLCString buffer; - if (aStringToSign.Length() > 0) { - if (encoder && NS_SUCCEEDED(rv)) { - rv = encoder->Convert(PromiseFlatString(aStringToSign).get(), - getter_Copies(buffer)); - if (NS_FAILED(rv)) { - aReturn.Append(internalError); - - return; - } - } - else { - AppendUTF16toUTF8(aStringToSign, buffer); - } - } - - HASHContext *hc = HASH_Create(HASH_AlgSHA1); - if (!hc) { - aReturn.Append(internalError); - - return; - } - - unsigned char hash[SHA1_LENGTH]; - - SECItem digest; - digest.data = hash; - - HASH_Begin(hc); - HASH_Update(hc, reinterpret_cast(buffer.get()), - buffer.Length()); - HASH_End(hc, digest.data, &digest.len, SHA1_LENGTH); - HASH_Destroy(hc); - - nsCString p7; - SECStatus srv = SECFailure; - - SEC_PKCS7ContentInfo *ci = SEC_PKCS7CreateSignedData(signingCert, - certUsageEmailSigner, - nullptr, SEC_OID_SHA1, - &digest, nullptr, uiContext); - if (ci) { - srv = SEC_PKCS7IncludeCertChain(ci, nullptr); - if (srv == SECSuccess) { - srv = SEC_PKCS7AddSigningTime(ci); - if (srv == SECSuccess) { - srv = SEC_PKCS7Encode(ci, signTextOutputCallback, &p7, nullptr, nullptr, - uiContext); - } - } - - SEC_PKCS7DestroyContentInfo(ci); - } - - if (srv != SECSuccess) { - aReturn.Append(internalError); - - return; - } - - SECItem binary_item; - binary_item.data = reinterpret_cast - (const_cast(p7.get())); - binary_item.len = p7.Length(); - - char *result = NSSBase64_EncodeItem(nullptr, nullptr, 0, &binary_item); - if (result) { - AppendASCIItoUTF16(result, aReturn); - } - else { - aReturn.Append(internalError); - } - - PORT_Free(result); - - return; -} - -void -nsCrypto::Logout(ErrorResult& aRv) -{ - NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); - - nsresult rv; - nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv)); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return; - } - - { - nsNSSShutDownPreventionLock locker; - PK11_LogoutAll(); - SSL_ClearSessionCache(); - } - - rv = nssComponent->LogoutAuthenticatedPK11(); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - } -} - -CRMFObject::CRMFObject() -{ - MOZ_COUNT_CTOR(CRMFObject); -} - -CRMFObject::~CRMFObject() -{ - MOZ_COUNT_DTOR(CRMFObject); -} - -JSObject* -CRMFObject::WrapObject(JSContext *aCx, bool* aTookOwnership) -{ - return CRMFObjectBinding::Wrap(aCx, this, aTookOwnership); -} - -void -CRMFObject::GetRequest(nsAString& aRequest) -{ - aRequest.Assign(mBase64Request); -} - -nsresult -CRMFObject::SetCRMFRequest(char *inRequest) -{ - mBase64Request.AssignWithConversion(inRequest); - return NS_OK; -} - -#endif // MOZ_DISABLE_CRYPTOLEGACY - nsPkcs11::nsPkcs11() { } @@ -2848,7 +55,7 @@ nsPkcs11::DeleteModule(const nsAString& aModuleName) if (srv == SECSuccess) { SECMODModule *module = SECMOD_FindModule(modName.get()); if (module) { -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS nssComponent->ShutdownSmartCardThread(module); #endif SECMOD_DestroyModule(module); @@ -2884,7 +91,7 @@ nsPkcs11::AddModule(const nsAString& aModuleName, if (srv == SECSuccess) { SECMODModule *module = SECMOD_FindModule(moduleName.get()); if (module) { -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS nssComponent->LaunchSmartCardThread(module); #endif SECMOD_DestroyModule(module); @@ -2904,4 +111,3 @@ nsPkcs11::AddModule(const nsAString& aModuleName, NS_ERROR("Bogus return value, this should never happen"); return NS_ERROR_FAILURE; } - diff --git a/security/manager/ssl/src/nsCrypto.h b/security/manager/ssl/src/nsCrypto.h index 4b4726278a49..3bb42944d789 100644 --- a/security/manager/ssl/src/nsCrypto.h +++ b/security/manager/ssl/src/nsCrypto.h @@ -6,97 +6,6 @@ #ifndef _nsCrypto_h_ #define _nsCrypto_h_ -#include "mozilla/dom/BindingDeclarations.h" -#include "mozilla/ErrorResult.h" -#ifndef MOZ_DISABLE_CRYPTOLEGACY -#include "mozilla/dom/NonRefcountedDOMObject.h" -#include "Crypto.h" -#include "nsCOMPtr.h" -#include "nsIDOMCryptoLegacy.h" -#include "nsIRunnable.h" -#include "nsString.h" -#include "nsIPrincipal.h" - -#define NS_CRYPTO_CID \ - {0x929d9320, 0x251e, 0x11d4, { 0x8a, 0x7c, 0x00, 0x60, 0x08, 0xc8, 0x44, 0xc3} } -#define PSM_VERSION_STRING "2.4" - -class nsIPSMComponent; -class nsIDOMScriptObjectFactory; - -namespace mozilla { -namespace dom { - -class CRMFObject : public NonRefcountedDOMObject -{ -public: - CRMFObject(); - virtual ~CRMFObject(); - - nsresult SetCRMFRequest(char *inRequest); - - JSObject* WrapObject(JSContext *aCx, bool* aTookOwnership); - - void GetRequest(nsAString& aRequest); - -private: - nsString mBase64Request; -}; - -} -} - -class nsCrypto: public mozilla::dom::Crypto -{ -public: - nsCrypto(); - - NS_DECL_ISUPPORTS_INHERITED - - // If legacy DOM crypto is enabled this is the class that actually - // implements the legacy methods. - NS_DECL_NSIDOMCRYPTO - - virtual bool EnableSmartCardEvents() MOZ_OVERRIDE; - virtual void SetEnableSmartCardEvents(bool aEnable, - mozilla::ErrorResult& aRv) MOZ_OVERRIDE; - - virtual void GetVersion(nsString& aVersion) MOZ_OVERRIDE; - - virtual mozilla::dom::CRMFObject* - GenerateCRMFRequest(JSContext* aContext, - const nsCString& aReqDN, - const nsCString& aRegToken, - const nsCString& aAuthenticator, - const nsCString& aEaCert, - const nsCString& aJsCallback, - const mozilla::dom::Sequence& aArgs, - mozilla::ErrorResult& aRv) MOZ_OVERRIDE; - - virtual void ImportUserCertificates(const nsAString& aNickname, - const nsAString& aCmmfResponse, - bool aDoForcedBackup, - nsAString& aReturn, - mozilla::ErrorResult& aRv) MOZ_OVERRIDE; - - virtual void SignText(JSContext* aContext, - const nsAString& aStringToSign, - const nsAString& aCaOption, - const mozilla::dom::Sequence& aArgs, - nsAString& aReturn) MOZ_OVERRIDE; - - virtual void Logout(mozilla::ErrorResult& aRv) MOZ_OVERRIDE; - -protected: - virtual ~nsCrypto(); - -private: - static already_AddRefed GetScriptPrincipal(JSContext *cx); - - bool mEnableSmartCardEvents; -}; -#endif // MOZ_DISABLE_CRYPTOLEGACY - #include "nsIPKCS11.h" #define NS_PKCS11_CID \ diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index f33c2fe0481b..ab14939e7178 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -23,7 +23,7 @@ #include "mozilla/PublicSSL.h" #include "mozilla/StaticPtr.h" -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS #include "nsSmartCardMonitor.h" #endif @@ -212,7 +212,7 @@ GetOCSPBehaviorFromPrefs(/*out*/ CertVerifier::ocsp_download_config* odc, nsNSSComponent::nsNSSComponent() :mutex("nsNSSComponent.mutex"), mNSSInitialized(false), -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS mThreadList(nullptr), #endif mCertVerificationThread(nullptr) @@ -356,7 +356,7 @@ nsNSSComponent::GetNSSBundleString(const char* name, nsAString& outString) return rv; } -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS void nsNSSComponent::LaunchSmartCardThreads() { @@ -412,7 +412,7 @@ nsNSSComponent::ShutdownSmartCardThreads() delete mThreadList; mThreadList = nullptr; } -#endif // MOZ_DISABLE_CRYPTOLEGACY +#endif // MOZ_NO_SMART_CARDS void nsNSSComponent::LoadLoadableRoots() @@ -1033,7 +1033,7 @@ nsNSSComponent::InitializeNSS() mHttpForNSS.initTable(); -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS LaunchSmartCardThreads(); #endif @@ -1063,7 +1063,7 @@ nsNSSComponent::ShutdownNSS() PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("nsNSSComponent::ShutdownNSS cannot stop observing cipher suite change\n")); } -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS ShutdownSmartCardThreads(); #endif SSL_ClearSessionCache(); diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index 34862d4679bf..9eba6845b5a5 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -14,8 +14,6 @@ #include "nsIStringBundle.h" #include "nsIObserver.h" #include "nsIObserverService.h" -#ifndef MOZ_DISABLE_CRYPTOLEGACY -#endif #include "nsINSSErrorsService.h" #include "nsNSSCallbacks.h" #include "SharedCertVerifier.h" @@ -87,7 +85,7 @@ class NS_NO_VTABLE nsINSSComponent : public nsISupports { NS_IMETHOD LogoutAuthenticatedPK11() = 0; -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS NS_IMETHOD LaunchSmartCardThread(SECMODModule* module) = 0; NS_IMETHOD ShutdownSmartCardThread(SECMODModule* module) = 0; @@ -140,7 +138,7 @@ public: nsAString& outString); NS_IMETHOD LogoutAuthenticatedPK11(); -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS NS_IMETHOD LaunchSmartCardThread(SECMODModule* module); NS_IMETHOD ShutdownSmartCardThread(SECMODModule* module); void LaunchSmartCardThreads(); @@ -187,7 +185,7 @@ private: bool mObserversRegistered; static int mInstanceCount; nsNSSShutDownList* mShutdownObjectList; -#ifndef MOZ_DISABLE_CRYPTOLEGACY +#ifndef MOZ_NO_SMART_CARDS SmartCardThreadList* mThreadList; #endif bool mIsNetworkDown; diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index 48bae911c476..851e0fdaf94d 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -188,9 +188,6 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsNSSCertList) #ifdef MOZ_XUL NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsCertTree) #endif -#ifndef MOZ_DISABLE_CRYPTOLEGACY -NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsCrypto) -#endif NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsPkcs11) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsCertPicker) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsNTLMAuthModule, InitTest) @@ -225,9 +222,6 @@ NS_DEFINE_NAMED_CID(NS_FORMPROCESSOR_CID); NS_DEFINE_NAMED_CID(NS_CERTTREE_CID); #endif NS_DEFINE_NAMED_CID(NS_PKCS11_CID); -#ifndef MOZ_DISABLE_CRYPTOLEGACY -NS_DEFINE_NAMED_CID(NS_CRYPTO_CID); -#endif NS_DEFINE_NAMED_CID(NS_CRYPTO_HASH_CID); NS_DEFINE_NAMED_CID(NS_CRYPTO_HMAC_CID); NS_DEFINE_NAMED_CID(NS_CERT_PICKER_CID); @@ -260,9 +254,6 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = { { &kNS_CERTTREE_CID, false, nullptr, nsCertTreeConstructor }, #endif { &kNS_PKCS11_CID, false, nullptr, nsPkcs11Constructor }, -#ifndef MOZ_DISABLE_CRYPTOLEGACY - { &kNS_CRYPTO_CID, false, nullptr, nsCryptoConstructor }, -#endif { &kNS_CRYPTO_HASH_CID, false, nullptr, nsCryptoHashConstructor }, { &kNS_CRYPTO_HMAC_CID, false, nullptr, nsCryptoHMACConstructor }, { &kNS_CERT_PICKER_CID, false, nullptr, nsCertPickerConstructor }, @@ -298,9 +289,6 @@ static const mozilla::Module::ContractIDEntry kNSSContracts[] = { { NS_CERTTREE_CONTRACTID, &kNS_CERTTREE_CID }, #endif { NS_PKCS11_CONTRACTID, &kNS_PKCS11_CID }, -#ifndef MOZ_DISABLE_CRYPTOLEGACY - { NS_CRYPTO_CONTRACTID, &kNS_CRYPTO_CID }, -#endif { NS_CRYPTO_HASH_CONTRACTID, &kNS_CRYPTO_HASH_CID }, { NS_CRYPTO_HMAC_CONTRACTID, &kNS_CRYPTO_HMAC_CID }, { NS_CERT_PICKER_CONTRACTID, &kNS_CERT_PICKER_CID }, diff --git a/security/manager/ssl/src/nsSmartCardMonitor.cpp b/security/manager/ssl/src/nsSmartCardMonitor.cpp index c0fd3342940a..018d5addead3 100644 --- a/security/manager/ssl/src/nsSmartCardMonitor.cpp +++ b/security/manager/ssl/src/nsSmartCardMonitor.cpp @@ -3,22 +3,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" -#include "mozilla/dom/SmartCardEvent.h" #include "mozilla/Services.h" #include "mozilla/unused.h" -#include "nsIDOMCryptoLegacy.h" -#include "nsIDOMDocument.h" -#include "nsIDOMWindow.h" -#include "nsIDOMWindowCollection.h" #include "nsIObserverService.h" -#include "nsISimpleEnumerator.h" -#include "nsIWindowWatcher.h" #include "nsServiceManagerUtils.h" #include "nsSmartCardMonitor.h" +#include "nsThreadUtils.h" #include "pk11func.h" using namespace mozilla; -using namespace mozilla::dom; // // The SmartCard monitoring thread should start up for each module we load @@ -50,7 +43,6 @@ public: private: virtual ~nsTokenEventRunnable() {} - nsresult DispatchEventToWindow(nsIDOMWindow* domWin); nsString mType; nsString mTokenName; @@ -71,121 +63,8 @@ nsTokenEventRunnable::Run() // This conversion is safe because mType can only be "smartcard-insert" // or "smartcard-remove". NS_ConvertUTF16toUTF8 eventTypeUTF8(mType); - nsresult rv = observerService->NotifyObservers(nullptr, eventTypeUTF8.get(), - mTokenName.get()); - if (NS_FAILED(rv)) { - return rv; - } - - // 'Dispatch' the event to all the windows. 'DispatchEventToWindow()' will - // first check to see if a given window has requested crypto events. - nsCOMPtr windowWatcher = - do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - return rv; - } - - nsCOMPtr enumerator; - rv = windowWatcher->GetWindowEnumerator(getter_AddRefs(enumerator)); - if (NS_FAILED(rv)) { - return rv; - } - - for (;;) { - bool hasMoreWindows; - rv = enumerator->HasMoreElements(&hasMoreWindows); - if (NS_FAILED(rv) || !hasMoreWindows) { - return rv; - } - nsCOMPtr supports; - enumerator->GetNext(getter_AddRefs(supports)); - nsCOMPtr domWin(do_QueryInterface(supports)); - if (domWin) { - rv = DispatchEventToWindow(domWin); - if (NS_FAILED(rv)) { - return rv; - } - } - } - return rv; -} - -nsresult -nsTokenEventRunnable::DispatchEventToWindow(nsIDOMWindow* domWin) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(domWin); - - // first walk the children and dispatch their events - nsCOMPtr frames; - nsresult rv = domWin->GetFrames(getter_AddRefs(frames)); - if (NS_FAILED(rv)) { - return rv; - } - - uint32_t length; - rv = frames->GetLength(&length); - if (NS_FAILED(rv)) { - return rv; - } - for (uint32_t i = 0; i < length; i++) { - nsCOMPtr childWin; - rv = frames->Item(i, getter_AddRefs(childWin)); - if (NS_FAILED(rv)) { - return rv; - } - if (domWin) { - rv = DispatchEventToWindow(childWin); - if (NS_FAILED(rv)) { - return rv; - } - } - } - - // check if we've enabled smart card events on this window - // NOTE: it's not an error to say that we aren't going to dispatch - // the event. - nsCOMPtr crypto; - rv = domWin->GetCrypto(getter_AddRefs(crypto)); - if (NS_FAILED(rv)) { - return rv; - } - if (!crypto) { - return NS_OK; // nope, it doesn't have a crypto property - } - - bool boolrv; - rv = crypto->GetEnableSmartCardEvents(&boolrv); - if (NS_FAILED(rv)) { - return rv; - } - if (!boolrv) { - return NS_OK; // nope, it's not enabled. - } - - // dispatch the event ... - - // find the document - nsCOMPtr doc; - rv = domWin->GetDocument(getter_AddRefs(doc)); - if (NS_FAILED(rv)) { - return rv; - } - if (!doc) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr d = do_QueryInterface(doc); - - SmartCardEventInit init; - init.mBubbles = false; - init.mCancelable = true; - init.mTokenName = mTokenName; - - nsRefPtr event(SmartCardEvent::Constructor(d, mType, init)); - event->SetTrusted(true); - - return d->DispatchEvent(event, &boolrv); + return observerService->NotifyObservers(nullptr, eventTypeUTF8.get(), + mTokenName.get()); } // self linking and removing double linked entry diff --git a/security/manager/ssl/tests/mochitest/bugs/mochitest-legacy.ini b/security/manager/ssl/tests/mochitest/bugs/mochitest-legacy.ini deleted file mode 100644 index 44ae449f4d6d..000000000000 --- a/security/manager/ssl/tests/mochitest/bugs/mochitest-legacy.ini +++ /dev/null @@ -1,2 +0,0 @@ -[test_generateCRMFRequest.html] -skip-if = e10s \ No newline at end of file diff --git a/security/manager/ssl/tests/mochitest/bugs/moz.build b/security/manager/ssl/tests/mochitest/bugs/moz.build index 6a73225477fa..76deffb6d1f3 100644 --- a/security/manager/ssl/tests/mochitest/bugs/moz.build +++ b/security/manager/ssl/tests/mochitest/bugs/moz.build @@ -5,10 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOCHITEST_MANIFESTS += ['mochitest.ini'] -# test_generateCRMFRequest.html tests crypto.generateCRMFRequest, which isn't -# available if legacy crypto has been disabled. -if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']: - MOCHITEST_MANIFESTS += ['mochitest-legacy.ini'] - MOCHITEST_CHROME_MANIFESTS += ['chrome.ini'] diff --git a/security/manager/ssl/tests/mochitest/bugs/test_generateCRMFRequest.html b/security/manager/ssl/tests/mochitest/bugs/test_generateCRMFRequest.html deleted file mode 100644 index 2d265053d002..000000000000 --- a/security/manager/ssl/tests/mochitest/bugs/test_generateCRMFRequest.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - crypto.generateCRMFRequest bugs - - - - - - - diff --git a/security/manager/ssl/tests/moz.build b/security/manager/ssl/tests/moz.build index 82ae36fe18c5..24b2069bf8e8 100644 --- a/security/manager/ssl/tests/moz.build +++ b/security/manager/ssl/tests/moz.build @@ -17,5 +17,5 @@ TEST_DIRS += [ XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini'] -if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']: +if not CONFIG['MOZ_NO_SMART_CARDS']: XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell-smartcards.ini'] diff --git a/security/manager/ssl/tests/unit/moz.build b/security/manager/ssl/tests/unit/moz.build index 32b9771792f1..2ffee37ee693 100644 --- a/security/manager/ssl/tests/unit/moz.build +++ b/security/manager/ssl/tests/unit/moz.build @@ -6,5 +6,5 @@ DIRS += ['tlsserver'] -if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']: +if not CONFIG['MOZ_NO_SMART_CARDS']: DIRS += ['pkcs11testmodule'] From 0fb6b8b1086e36d9108d1095b59929b115970310 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 14 Aug 2014 17:40:04 +0100 Subject: [PATCH 112/119] Backed out changeset 52fc270e59ad (bug 1051754) for intermittent test failures --- dom/nfc/tests/marionette/head.js | 20 ++------ dom/nfc/tests/marionette/manifest.ini | 1 - .../marionette/test_nfc_peer_sendFile.js | 49 ------------------- 3 files changed, 3 insertions(+), 67 deletions(-) delete mode 100644 dom/nfc/tests/marionette/test_nfc_peer_sendFile.js diff --git a/dom/nfc/tests/marionette/head.js b/dom/nfc/tests/marionette/head.js index 9a3c8cf65925..e4e3bf80eb9e 100644 --- a/dom/nfc/tests/marionette/head.js +++ b/dom/nfc/tests/marionette/head.js @@ -60,33 +60,19 @@ let sysMsgHelper = (function() { } } - function sendFile(msg) { - log("system message nfc-manager-send-file"); - let send = mSendFile.shift(); - if (send) { - send(msg); - } - } - - let mDiscovered = [], mLost = [], mSendFile = []; + let mDiscovered = [], mLost = []; window.navigator.mozSetMessageHandler("nfc-manager-tech-discovered", techDiscovered); window.navigator.mozSetMessageHandler("nfc-manager-tech-lost", techLost); - window.navigator.mozSetMessageHandler("nfc-manager-send-file", sendFile); return { - waitForTechDiscovered: function(discovered) { + waitForTechDiscovered: function (discovered) { mDiscovered.push(discovered); }, - waitForTechLost: function(lost) { + waitForTechLost: function (lost) { mLost.push(lost); }, - - waitForSendFile: function(sendFile) { - mSendFile.push(sendFile); - }, - }; }()); diff --git a/dom/nfc/tests/marionette/manifest.ini b/dom/nfc/tests/marionette/manifest.ini index d9c258f204ab..da072c9ee140 100644 --- a/dom/nfc/tests/marionette/manifest.ini +++ b/dom/nfc/tests/marionette/manifest.ini @@ -10,7 +10,6 @@ qemu=true [test_nfc_manager_tech_lost.js] [test_nfc_peer.js] [test_nfc_peer_sendndef.js] -[test_nfc_peer_sendFile.js] [test_nfc_read_tag.js] [test_nfc_checkP2PRegistration.js] [test_nfc_error_messages.js] diff --git a/dom/nfc/tests/marionette/test_nfc_peer_sendFile.js b/dom/nfc/tests/marionette/test_nfc_peer_sendFile.js deleted file mode 100644 index ee93cf99209d..000000000000 --- a/dom/nfc/tests/marionette/test_nfc_peer_sendFile.js +++ /dev/null @@ -1,49 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -MARIONETTE_TIMEOUT = 30000; -MARIONETTE_HEAD_JS = "head.js"; - -let MANIFEST_URL = "app://system.gaiamobile.org/manifest.webapp"; - -function sendFile(msg) { - log("sendFile msg="+JSON.stringify(msg)); - let peer = nfc.getNFCPeer(msg.sessionToken); - ok(peer instanceof MozNFCPeer, "should get a MozNFCPeer"); - ok(msg.blob instanceof Blob, "should get a Blob"); - - nfc.peerready = null; - NCI.deactivate().then(() => toggleNFC(false)).then(runNextTest); -} - -function testSendFile() { - nfc.onpeerready = function(evt) { - let peer = evt.peer; - peer.sendFile(new Blob()); - sysMsgHelper.waitForSendFile(sendFile); - }; - - sysMsgHelper.waitForTechDiscovered(function(msg) { - let request = nfc.checkP2PRegistration(MANIFEST_URL); - request.onsuccess = function(evt) { - is(request.result, true, "check for P2P registration result"); - nfc.notifyUserAcceptedP2P(MANIFEST_URL); - } - - request.onerror = function() { - ok(false, "checkP2PRegistration failed."); - toggleNFC(false).then(runNextTest); - } - }); - - toggleNFC(true).then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0)); -} - -let tests = [ - testSendFile -]; - -SpecialPowers.pushPermissions( - [{"type": "nfc", "allow": true, - "read": true, 'write': true, context: document}, - {"type": "nfc-manager", 'allow': true, context: document}], runTests); From 41c8db387e8e7c00a0d15f332b6588c4f5d4eb66 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 10:15:34 -0700 Subject: [PATCH 113/119] Bumping gaia.json for 1 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/86740b556acb Author: kumarrishav Desc: Bug 1020306 - Make the thread/message edit mode to match the style used by other applications r=gsvelto,julien --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 22d53b797c49..de895d1ac98a 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "77b08e358e8f12305ccc55e16dc57d6fa77d9a33", + "revision": "86740b556acb1f8d851876b4230085804a2247b6", "repo_path": "/integration/gaia-central" } From 10bdccc0190c7be3948e84132ecc977f8b34f356 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 10:21:21 -0700 Subject: [PATCH 114/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b04e106e8b5e..bc2cf1ebd604 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 2feeaf33cb62..1533db14fb1d 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 2e23d36d28b1..3d96cfeb9033 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b04e106e8b5e..bc2cf1ebd604 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 14c71033d749..959026ff629c 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 576b133aa0f3..0f9af965c422 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index ab755f676068..2f9659b9f874 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 773655f8515b..5ed356af064e 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index a8819426f4d6..367d4466003b 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 11d6465111e994a5f4b8f155edd34f48533eef9c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 10:30:29 -0700 Subject: [PATCH 115/119] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/450a6e9725d4 Author: Kevin Grandon Desc: Merge pull request #22850 from KevinGrandon/bug_1035272_default_entertainment_collection_icon Bug 1035272 - [B2G][Homescreen] Entertainment smart collection icon is not migrated ======== https://hg.mozilla.org/integration/gaia-central/rev/c5282abd10b1 Author: Kevin Grandon Desc: Bug 1035272 - [B2G][Homescreen] Entertainment smart collection icon is not migrated r=yurenju --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index de895d1ac98a..adfe71007e72 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "86740b556acb1f8d851876b4230085804a2247b6", + "revision": "450a6e9725d4233de8e973750fa740ff2ea30aad", "repo_path": "/integration/gaia-central" } From 352fbe8103e85b4fe1d28def6bcc3e5f14f1a0ae Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 10:36:14 -0700 Subject: [PATCH 116/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index bc2cf1ebd604..ada2de06e16a 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 1533db14fb1d..6a67a9500c75 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 3d96cfeb9033..7a4becc7e991 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index bc2cf1ebd604..ada2de06e16a 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 959026ff629c..5fa330eb4966 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 0f9af965c422..06227b9c767a 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 2f9659b9f874..64320083557b 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 5ed356af064e..4b349481f496 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 367d4466003b..b7e8784439e5 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From eeace956e5baa6d45176548ada394a2bc36af33b Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 14 Aug 2014 10:38:38 -0700 Subject: [PATCH 117/119] Bug 1050654: Replace "flex: 0 0 main-size" with equivalent & more concise "none" keyword, in webconsole.inc.css. r=robcee --- .../themes/shared/devtools/webconsole.inc.css | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/browser/themes/shared/devtools/webconsole.inc.css b/browser/themes/shared/devtools/webconsole.inc.css index aa49039dfd75..f471a4e87467 100644 --- a/browser/themes/shared/devtools/webconsole.inc.css +++ b/browser/themes/shared/devtools/webconsole.inc.css @@ -17,24 +17,24 @@ a { .message { display: flex; - flex: 0 0 main-size; + flex: none; padding: 0 7px; width: 100%; box-sizing: border-box; } .message > .timestamp { - flex: 0 0 main-size; + flex: none; color: GrayText; margin: 4px 6px 0 0; } .message > .indent { - flex: 0 0 main-size; + flex: none; } .message > .icon { - flex: 0 0 main-size; + flex: none; margin: 3px 6px 0 0; padding: 0 4px; height: 1em; @@ -66,7 +66,7 @@ a { /* The red bubble that shows the number of times a message is repeated */ .message-repeats { -moz-user-select: none; - flex: 0 0 main-size; + flex: none; margin: 2px 6px; padding: 0 6px; height: 1.25em; @@ -84,7 +84,7 @@ a { .message-location { display: flex; - flex: 0 0 main-size; + flex: none; align-self: flex-start; justify-content: flex-end; width: 10em; @@ -106,7 +106,7 @@ a { } .message-location > .line-number { - flex: 0 0 main-size; + flex: none; } .message-flex-body { @@ -236,7 +236,7 @@ a { } .message[category=network] .method { - flex: 0 0 main-size; + flex: none; } .message[category=network]:not(.navigation-marker) .url { @@ -250,7 +250,7 @@ a { } .message[category=network] .status { - flex: 0 0 main-size; + flex: none; -moz-margin-start: 6px; } From fcd56083864c7b2554b6462ccf550dd6be6750b7 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 11:25:30 -0700 Subject: [PATCH 118/119] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/a5d998cfe7cd Author: Julien Wajsberg Desc: Merge pull request #21941 from giovannic/smsbugfix2 Bug 1040271 - [L10n][SMS] Clean up mozL10n.get uses in SMS app ======== https://hg.mozilla.org/integration/gaia-central/rev/619241f6415d Author: Giovanni Charles Desc: Bug 1040271 - [L10n][SMS] Clean up mozL10n.get uses in SMS app r=gandalf,azasypkin,julien --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index adfe71007e72..00ee864ac91a 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "450a6e9725d4233de8e973750fa740ff2ea30aad", + "revision": "a5d998cfe7cd004c7967e40efaaad0ccb829ecc4", "repo_path": "/integration/gaia-central" } From 0f793d6041290dc3a089349e32225ecc08cb0354 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 14 Aug 2014 11:27:03 -0700 Subject: [PATCH 119/119] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index ada2de06e16a..7df0ca77ae71 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6a67a9500c75..b9babb11b9cf 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 7a4becc7e991..4a12dcff25a8 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index ada2de06e16a..7df0ca77ae71 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 5fa330eb4966..c858bc45d90f 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 06227b9c767a..a8b5d1703430 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 64320083557b..27153a46f257 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 4b349481f496..03d8a9eb2c98 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index b7e8784439e5..cc3d0197d66a 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - +