Merge the last PGO-green inbound changeset to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-07-04 12:49:07 -04:00
commit 8567838adc
21 changed files with 601 additions and 135 deletions

View File

@ -161,6 +161,7 @@
@BINPATH@/components/dom.xpt
@BINPATH@/components/dom_apps.xpt
@BINPATH@/components/dom_base.xpt
@BINPATH@/components/dom_system.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_wifi.xpt

View File

@ -10,6 +10,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = dom
XPIDL_MODULE = dom_system
LIBRARY_NAME = domsystem_s
LIBXUL_LIBRARY = 1
@ -31,6 +32,9 @@ endif
DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
XPIDLSRCS = \
nsIOSFileConstantsService.idl \
$(NULL)
CPPSRCS = \
nsDeviceSensors.cpp \

View File

@ -33,6 +33,7 @@
#include "nsString.h"
#include "OSFileConstants.h"
#include "nsIOSFileConstantsService.h"
/**
* This module defines the basic libc constants (error numbers, open modes,
@ -64,7 +65,7 @@ nsresult InitOSFileConstants()
{
MOZ_ASSERT(NS_IsMainThread());
if (gInitialized) {
return NS_ERROR_ALREADY_INITIALIZED;
return NS_OK;
}
gInitialized = true;
@ -86,15 +87,15 @@ nsresult InitOSFileConstants()
return libDir->GetPath(*gLibDirectory);
}
nsresult CleanupOSFileConstants()
void CleanupOSFileConstants()
{
MOZ_ASSERT(NS_IsMainThread());
if (!gInitialized) {
return NS_ERROR_NOT_INITIALIZED;
return;
}
gInitialized = false;
delete gLibDirectory;
return NS_OK;
}
@ -474,5 +475,36 @@ bool DefineOSFileConstants(JSContext *cx, JSObject *global)
return true;
}
} // namespace mozilla
NS_IMPL_ISUPPORTS1(OSFileConstantsService, nsIOSFileConstantsService)
OSFileConstantsService::OSFileConstantsService()
{
MOZ_ASSERT(NS_IsMainThread());
}
OSFileConstantsService::~OSFileConstantsService()
{
mozilla::CleanupOSFileConstants();
}
NS_IMETHODIMP
OSFileConstantsService::Init(JSContext *aCx)
{
nsresult rv = mozilla::InitOSFileConstants();
if (NS_FAILED(rv)) {
return rv;
}
JSObject *global = JS_GetGlobalForScopeChain(aCx);
if (!global) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!mozilla::DefineOSFileConstants(aCx, global)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
} // namespace mozilla

View File

@ -6,6 +6,7 @@
#define mozilla_osfileconstants_h__
#include "jspubtd.h"
#include "nsIOSFileConstantsService.h"
namespace mozilla {
@ -14,8 +15,9 @@ namespace mozilla {
*
* This function _must_ be called:
* - from the main thread;
* - only once;
* - before any Chrome Worker is created.
*
* The function is idempotent.
*/
nsresult InitOSFileConstants();
@ -24,10 +26,11 @@ nsresult InitOSFileConstants();
*
* This function _must_ be called:
* - from the main thread;
* - only once;
* - after all Chrome Workers are dead.
*
* The function is idempotent.
*/
nsresult CleanupOSFileConstants();
void CleanupOSFileConstants();
/**
* Define OS-specific constants.
@ -37,6 +40,19 @@ nsresult CleanupOSFileConstants();
*/
bool DefineOSFileConstants(JSContext *cx, JSObject *global);
/**
* XPConnect initializer, for use in the main thread.
*/
class OSFileConstantsService: public nsIOSFileConstantsService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOSFILECONSTANTSSERVICE
OSFileConstantsService();
private:
~OSFileConstantsService();
};
}
#endif // mozilla_osfileconstants_h__

View File

@ -0,0 +1,28 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* 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"
[scriptable, uuid(d6dd239f-34d6-4b34-baa1-f69ab4a20bc4)]
interface nsIOSFileConstantsService: nsISupports
{
/**
* Inject module OS.Constants in the environment.
*
* This method must be called only from the main thread.
* Method is idempotent.
*/
[implicit_jscontext]
void init();
};
%{ C++
// {4BBE1B96-8956-457F-A03F-9C27435F2AFA}
#define OSFILECONSTANTSSERVICE_CID {0x4BBE1B96,0x8956,0x457F,{0xA0,0x3F,0x9C,0x27,0x43,0x5F,0x2A,0xFA}}
#define OSFILECONSTANTSSERVICE_CONTRACTID "@mozilla.org/net/osfileconstantsservice;1"
%}

View File

@ -16,8 +16,33 @@
let worker;
function test_xul() {
let lib;
isnot(null, OS.Constants.Path.libxul, "libxulpath is defined");
try {
lib = ctypes.open(OS.Constants.Path.libxul);
lib.declare("DumpJSStack", ctypes.default_abi, ctypes.void_t);
} catch (x) {
success = false;
ok(false, "Could not open libxul " + x);
}
if (lib) {
lib.close();
}
ok(true, "test_xul: opened libxul successfully");
}
function test() {
ok(true, "test_constants.xul: Starting test");
// Test 1: Load libxul from main thread
Components.classes["@mozilla.org/net/osfileconstantsservice;1"].
getService(Components.interfaces.nsIOSFileConstantsService).
init();
Components.utils.import("resource://gre/modules/ctypes.jsm");
test_xul();
// Test 2: Load libxul from chrome thread
worker = new ChromeWorker("worker_constants.js");
SimpleTest.waitForExplicitFinish();
ok(true, "test_constants.xul: Chrome worker created");

View File

@ -1050,10 +1050,7 @@ RuntimeService::Cleanup()
}
}
nsresult rv = CleanupOSFileConstants();
if (NS_FAILED(rv)) {
MOZ_NOT_REACHED("Could not cleanup OSFileConstants");
}
CleanupOSFileConstants();
}
// static

View File

@ -1539,8 +1539,6 @@ JS_WrapValue(JSContext *cx, jsval *vp)
* is used to make this happen if an object other than |target| is used.
*/
static bool RemapWrappers(JSContext *cx, JSObject *orig, JSObject *target);
JS_PUBLIC_API(JSObject *)
JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
{
@ -1582,7 +1580,7 @@ JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
// Now, iterate through other scopes looking for references to the
// old object, and update the relevant cross-compartment wrappers.
if (!RemapWrappers(cx, origobj, newIdentity))
if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
return NULL;
// Lastly, update the original object to point to the new one.
@ -1601,60 +1599,6 @@ JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
return newIdentity;
}
/*
* Remap cross-compartment wrappers pointing to |src| to point to |dst|. All
* wrappers are recomputed.
*/
static bool
RemapWrappers(JSContext *cx, JSObject *orig, JSObject *target)
{
Value origv = ObjectValue(*orig);
Value targetv = ObjectValue(*target);
CompartmentVector &vector = cx->runtime->compartments;
AutoValueVector toTransplant(cx);
if (!toTransplant.reserve(vector.length()))
return false;
for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
WrapperMap &pmap = (*p)->crossCompartmentWrappers;
if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
// We found a wrapper. Remember and root it.
toTransplant.infallibleAppend(wp->value);
}
}
for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
JSObject *wobj = &begin->toObject();
JSCompartment *wcompartment = wobj->compartment();
WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
// When we remove origv from the wrapper map, its wrapper, wobj, must
// immediately cease to be a cross-compartment wrapper. Neuter it.
JS_ASSERT(pmap.lookup(origv));
pmap.remove(origv);
NukeCrossCompartmentWrapper(wobj);
// First, we wrap it in the new compartment. This will return
// a new wrapper.
AutoCompartment ac(cx, wobj);
JSObject *tobj = target;
if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
return false;
// Now, because we need to maintain object identity, we do a
// brain transplant on the old object. At the same time, we
// update the entry in the compartment's wrapper map to point
// to the old wrapper.
JS_ASSERT(tobj != wobj);
if (!wobj->swap(cx, tobj))
return false;
pmap.put(targetv, ObjectValue(*wobj));
}
return true;
}
/*
* The location object is special. There is the location object itself and
* then the location object wrapper. Because there are no direct references to
@ -1706,7 +1650,7 @@ js_TransplantObjectWithWrapper(JSContext *cx,
// Now, iterate through other scopes looking for references to the old
// object. Note that the entries in the maps are for |origobj| and not
// |origwrapper|. They need to be updated to point at the new object.
if (!RemapWrappers(cx, origobj, targetobj))
if (!RemapAllWrappersForObject(cx, origobj, targetobj))
return NULL;
// Lastly, update things in the original compartment. Our invariants dictate
@ -1736,7 +1680,7 @@ js_TransplantObjectWithWrapper(JSContext *cx,
JS_PUBLIC_API(JSBool)
JS_RefreshCrossCompartmentWrappers(JSContext *cx, JSObject *obj)
{
return RemapWrappers(cx, obj, obj);
return RemapAllWrappersForObject(cx, obj, obj);
}
JS_PUBLIC_API(JSObject *)

View File

@ -1174,10 +1174,7 @@ JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
* all the allocations and released the empty GC chunks.
*/
ShrinkGCBuffers(this);
{
AutoLockGC lock(this);
gcHelperThread.waitBackgroundSweepOrAllocEnd();
}
gcHelperThread.waitBackgroundSweepOrAllocEnd();
if (!p)
p = OffTheBooks::malloc_(nbytes);
else if (p == reinterpret_cast<void *>(1))

View File

@ -259,6 +259,10 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
if (!wrapper)
return false;
// We maintain the invariant that the key in the cross-compartment wrapper
// map is always directly wrapped by the value.
JS_ASSERT(Wrapper::wrappedObject(wrapper) == &key.reference().toObject());
vp->setObject(*wrapper);
if (wrapper->getProto() != proto && !SetProto(cx, wrapper, proto, false))

View File

@ -828,7 +828,9 @@ js_InitGC(JSRuntime *rt, uint32_t maxbytes)
rt->gcMaxBytes = maxbytes;
rt->setGCMaxMallocBytes(maxbytes);
#ifndef JS_MORE_DETERMINISTIC
rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
#endif
return true;
}
@ -1664,7 +1666,6 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
if (secondAttempt)
break;
AutoLockGC lock(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
}
@ -2495,6 +2496,7 @@ MaybeGC(JSContext *cx)
return;
}
#ifndef JS_MORE_DETERMINISTIC
/*
* Access to the counters and, on 32 bit, setting gcNextFullGCTime below
* is not atomic and a race condition could trigger or suppress the GC. We
@ -2511,6 +2513,7 @@ MaybeGC(JSContext *cx)
rt->gcNextFullGCTime = now + GC_IDLE_FULL_SPAN;
}
}
#endif
}
static void
@ -2788,12 +2791,11 @@ GCHelperThread::prepareForBackgroundSweep()
#endif /* JS_THREADSAFE */
}
/* Must be called with the GC lock taken. */
void
GCHelperThread::startBackgroundSweep(bool shouldShrink)
{
#ifdef JS_THREADSAFE
/* The caller takes the GC lock. */
AutoLockGC lock(rt);
JS_ASSERT(state == IDLE);
JS_ASSERT(!sweepFlag);
sweepFlag = true;
@ -2833,11 +2835,11 @@ GCHelperThread::startBackgroundShrink()
}
#endif /* JS_THREADSAFE */
/* Must be called with the GC lock taken. */
void
GCHelperThread::waitBackgroundSweepEnd()
{
#ifdef JS_THREADSAFE
AutoLockGC lock(rt);
while (state == SWEEPING)
PR_WaitCondVar(done, PR_INTERVAL_NO_TIMEOUT);
#else
@ -2845,11 +2847,11 @@ GCHelperThread::waitBackgroundSweepEnd()
#endif /* JS_THREADSAFE */
}
/* Must be called with the GC lock taken. */
void
GCHelperThread::waitBackgroundSweepOrAllocEnd()
{
#ifdef JS_THREADSAFE
AutoLockGC lock(rt);
if (state == ALLOCATING)
state = CANCEL_ALLOCATION;
while (state == SWEEPING || state == CANCEL_ALLOCATION)
@ -2944,12 +2946,15 @@ GCHelperThread::doSweep()
static bool
ReleaseObservedTypes(JSRuntime *rt)
{
bool releaseTypes = false;
bool releaseTypes = rt->gcZeal() != 0;
#ifndef JS_MORE_DETERMINISTIC
int64_t now = PRMJ_Now();
if (rt->gcZeal() || now >= rt->gcJitReleaseTime) {
if (now >= rt->gcJitReleaseTime)
releaseTypes = true;
if (releaseTypes)
rt->gcJitReleaseTime = now + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
}
#endif
return releaseTypes;
}
@ -3028,7 +3033,7 @@ ShouldPreserveJITCode(JSCompartment *c, int64_t currentTime)
}
static void
BeginMarkPhase(JSRuntime *rt)
BeginMarkPhase(JSRuntime *rt, bool isIncremental)
{
int64_t currentTime = PRMJ_Now();
@ -3045,7 +3050,7 @@ BeginMarkPhase(JSRuntime *rt)
JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker));
/* For non-incremental GC the following sweep discards the jit code. */
if (rt->gcIncrementalState != NO_INCREMENTAL) {
if (isIncremental) {
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_CODE);
c->discardJitCode(rt->defaultFreeOp());
@ -3127,7 +3132,7 @@ ValidateIncrementalMarking(JSRuntime *rt);
#endif
static void
EndMarkPhase(JSRuntime *rt)
EndMarkPhase(JSRuntime *rt, bool isIncremental)
{
{
gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_MARK);
@ -3138,7 +3143,7 @@ EndMarkPhase(JSRuntime *rt)
JS_ASSERT(rt->gcMarker.isDrained());
#ifdef DEBUG
if (rt->gcIncrementalState != NO_INCREMENTAL)
if (isIncremental)
ValidateIncrementalMarking(rt);
#endif
@ -3214,7 +3219,7 @@ ValidateIncrementalMarking(JSRuntime *rt)
/* Re-do all the marking, but non-incrementally. */
js::gc::State state = rt->gcIncrementalState;
rt->gcIncrementalState = NO_INCREMENTAL;
rt->gcIncrementalState = MARK_ROOTS;
/* As we're re-doing marking, we need to reset the weak map list. */
WeakMapBase::resetWeakMapList(rt);
@ -3228,6 +3233,7 @@ ValidateIncrementalMarking(JSRuntime *rt)
MarkRuntime(gcmarker, true);
SliceBudget budget;
rt->gcIncrementalState = MARK;
rt->gcMarker.drainMarkStack(budget);
MarkGrayAndWeak(rt);
@ -3472,7 +3478,10 @@ AutoGCSession::~AutoGCSession()
for (GCCompartmentsIter c(runtime); !c.done(); c.next())
c->setCollecting(false);
#ifndef JS_MORE_DETERMINISTIC
runtime->gcNextFullGCTime = PRMJ_Now() + GC_IDLE_FULL_SPAN;
#endif
runtime->gcChunkAllocationSinceLastGC = false;
#ifdef JS_GC_ZEAL
@ -3581,13 +3590,18 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, boo
}
#endif
bool isIncremental = rt->gcIncrementalState != NO_INCREMENTAL ||
budget != SliceBudget::Unlimited ||
zeal == ZealIncrementalRootsThenFinish ||
zeal == ZealIncrementalMarkAllThenFinish;
if (rt->gcIncrementalState == NO_INCREMENTAL) {
rt->gcIncrementalState = MARK_ROOTS;
rt->gcLastMarkSlice = false;
}
if (rt->gcIncrementalState == MARK_ROOTS) {
BeginMarkPhase(rt);
BeginMarkPhase(rt, isIncremental);
rt->gcIncrementalState = MARK;
if (zeal == ZealIncrementalRootsThenFinish)
@ -3625,7 +3639,7 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, boo
{
rt->gcLastMarkSlice = true;
} else {
EndMarkPhase(rt);
EndMarkPhase(rt, isIncremental);
rt->gcIncrementalState = NO_INCREMENTAL;
*shouldSweep = true;
}
@ -3738,7 +3752,6 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
if (rt->inOOMReport)
return;
AutoLockGC lock(rt);
AutoGCSession gcsession(rt);
/*
@ -3754,8 +3767,6 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
bool startBackgroundSweep = false;
{
AutoUnlockGC unlock(rt);
if (!incremental) {
/* If non-incremental GC was requested, reset incremental GC. */
ResetIncrementalGC(rt, "requested");
@ -3962,11 +3973,9 @@ TraceRuntime(JSTracer *trc)
{
JSRuntime *rt = trc->runtime;
if (!rt->gcRunning) {
AutoLockGC lock(rt);
AutoHeapSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoUnlockGC unlock(rt);
AutoCopyFreeListToArenas copy(rt);
RecordNativeStackTopForGC(rt);
@ -4022,10 +4031,8 @@ IterateCompartmentsArenasCells(JSRuntime *rt, void *data,
{
JS_ASSERT(!rt->gcRunning);
AutoLockGC lock(rt);
AutoHeapSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoUnlockGC unlock(rt);
AutoCopyFreeListToArenas copy(rt);
for (CompartmentsIter c(rt); !c.done(); c.next()) {
@ -4047,10 +4054,8 @@ IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback)
/* :XXX: Any way to common this preamble with IterateCompartmentsArenasCells? */
JS_ASSERT(!rt->gcRunning);
AutoLockGC lock(rt);
AutoHeapSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoUnlockGC unlock(rt);
for (js::GCChunkSet::Range r = rt->gcChunkSet.all(); !r.empty(); r.popFront())
chunkCallback(rt, data, r.front());
@ -4063,10 +4068,8 @@ IterateCells(JSRuntime *rt, JSCompartment *compartment, AllocKind thingKind,
/* :XXX: Any way to common this preamble with IterateCompartmentsArenasCells? */
JS_ASSERT(!rt->gcRunning);
AutoLockGC lock(rt);
AutoHeapSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoUnlockGC unlock(rt);
AutoCopyFreeListToArenas copy(rt);
@ -4091,10 +4094,8 @@ IterateGrayObjects(JSCompartment *compartment, GCThingCallback *cellCallback, vo
JSRuntime *rt = compartment->rt;
JS_ASSERT(!rt->gcRunning);
AutoLockGC lock(rt);
AutoHeapSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoUnlockGC unlock(rt);
AutoCopyFreeListToArenas copy(rt);
@ -4453,7 +4454,6 @@ StartVerifyBarriers(JSRuntime *rt)
if (rt->gcVerifyData || rt->gcIncrementalState != NO_INCREMENTAL)
return;
AutoLockGC lock(rt);
AutoHeapSession session(rt);
if (!IsIncrementalGCSafe(rt))
@ -4461,8 +4461,6 @@ StartVerifyBarriers(JSRuntime *rt)
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
AutoUnlockGC unlock(rt);
AutoCopyFreeListToArenas copy(rt);
RecordNativeStackTopForGC(rt);
@ -4584,13 +4582,10 @@ AssertMarkedOrAllocated(const EdgeValue &edge)
static void
EndVerifyBarriers(JSRuntime *rt)
{
AutoLockGC lock(rt);
AutoHeapSession session(rt);
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
AutoUnlockGC unlock(rt);
AutoCopyFreeListToArenas copy(rt);
RecordNativeStackTopForGC(rt);
@ -4805,10 +4800,8 @@ JS_IterateCompartments(JSRuntime *rt, void *data,
{
JS_ASSERT(!rt->gcRunning);
AutoLockGC lock(rt);
AutoHeapSession session(rt);
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
AutoUnlockGC unlock(rt);
for (CompartmentsIter c(rt); !c.done(); c.next())
(*compartmentCallback)(rt, data, c);

View File

@ -1477,18 +1477,11 @@ proxy_TraceObject(JSTracer *trc, JSObject *obj)
JSObject *referent = &GetProxyPrivate(obj).toObject();
if (referent->compartment() != obj->compartment()) {
/*
* Assert that this proxy is tracked in the wrapper map. Normally,
* the wrapped object will be the key in the wrapper map. However,
* sometimes when wrapping Location objects, the wrapped object is
* not the key. In that case, we unwrap to find the key.
* Assert that this proxy is tracked in the wrapper map. We maintain
* the invariant that the wrapped object is the key in the wrapper map.
*/
Value key = ObjectValue(*referent);
WrapperMap::Ptr p = obj->compartment()->crossCompartmentWrappers.lookup(key);
if (!p) {
key = ObjectValue(*UnwrapObject(referent));
p = obj->compartment()->crossCompartmentWrappers.lookup(key);
JS_ASSERT(p.found());
}
JS_ASSERT(p->value.get() == ObjectValue(*obj));
}
}

View File

@ -1120,3 +1120,114 @@ js::NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj,
return JS_TRUE;
}
// Given a cross-compartment wrapper |wobj|, update it to point to
// |newTarget|. This recomputes the wrapper with JS_WrapValue, and thus can be
// useful even if wrapper already points to newTarget.
bool
js::RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget)
{
JS_ASSERT(IsCrossCompartmentWrapper(wobj));
JSObject *origTarget = Wrapper::wrappedObject(wobj);
JS_ASSERT(origTarget);
Value origv = ObjectValue(*origTarget);
JSCompartment *wcompartment = wobj->compartment();
WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
// When we remove origv from the wrapper map, its wrapper, wobj, must
// immediately cease to be a cross-compartment wrapper. Neuter it.
JS_ASSERT(pmap.lookup(origv));
pmap.remove(origv);
NukeCrossCompartmentWrapper(wobj);
// First, we wrap it in the new compartment. This will return
// a new wrapper.
AutoCompartment ac(cx, wobj);
JSObject *tobj = newTarget;
if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
return false;
// Now, because we need to maintain object identity, we do a
// brain transplant on the old object. At the same time, we
// update the entry in the compartment's wrapper map to point
// to the old wrapper.
JS_ASSERT(tobj != wobj);
if (!wobj->swap(cx, tobj))
return false;
pmap.put(ObjectValue(*newTarget), ObjectValue(*wobj));
return true;
}
// Remap all cross-compartment wrappers pointing to |oldTarget| to point to
// |newTarget|. All wrappers are recomputed.
bool
js::RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
JSObject *newTarget)
{
Value origv = ObjectValue(*oldTarget);
Value targetv = ObjectValue(*newTarget);
AutoValueVector toTransplant(cx);
if (!toTransplant.reserve(cx->runtime->compartments.length()))
return false;
for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
WrapperMap &pmap = c->crossCompartmentWrappers;
if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
// We found a wrapper. Remember and root it.
toTransplant.infallibleAppend(wp->value);
}
}
for (Value *begin = toTransplant.begin(), *end = toTransplant.end();
begin != end; ++begin)
{
if (!RemapWrapper(cx, &begin->toObject(), newTarget))
return false;
}
return true;
}
JS_FRIEND_API(bool)
js::RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter)
{
AutoValueVector toRecompute(cx);
for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
// Filter by source compartment.
if (!sourceFilter.match(c))
continue;
// Iterate over the wrappers, filtering appropriately.
WrapperMap &pmap = c->crossCompartmentWrappers;
for (WrapperMap::Enum e(pmap); !e.empty(); e.popFront()) {
// Filter out non-objects.
const CrossCompartmentKey &k = e.front().key;
if (k.kind != CrossCompartmentKey::ObjectWrapper)
continue;
// Filter by target compartment.
Value wrapper = e.front().value.get();
if (!targetFilter.match(k.wrapped->compartment()))
continue;
// Add it to the list.
if (!toRecompute.append(wrapper))
return false;
}
}
// Recompute all the wrappers in the list.
for (Value *begin = toRecompute.begin(), *end = toRecompute.end(); begin != end; ++begin)
{
JSObject *wrapper = &begin->toObject();
JSObject *wrapped = Wrapper::wrappedObject(wrapper);
if (!RemapWrapper(cx, wrapper, wrapped))
return false;
}
return true;
}

View File

@ -334,6 +334,50 @@ IsCrossCompartmentWrapper(const JSObject *obj);
void
NukeCrossCompartmentWrapper(JSObject *wrapper);
bool
RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget);
bool
RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
JSObject *newTarget);
// API to recompute all cross-compartment wrappers whose source and target
// match the given filters.
//
// These filters are designed to be ephemeral stack classes, and thus don't
// do any rooting or holding of their members.
struct CompartmentFilter {
virtual bool match(JSCompartment *c) const = 0;
};
struct AllCompartments : public CompartmentFilter {
virtual bool match(JSCompartment *c) const { return true; };
};
struct ContentCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return !IsSystemCompartment(c);
};
};
struct SingleCompartment : public CompartmentFilter {
JSCompartment *ours;
SingleCompartment(JSCompartment *c) : ours(c) {};
virtual bool match(JSCompartment *c) const { return c == ours; };
};
struct CompartmentsWithPrincipals : public CompartmentFilter {
JSPrincipals *principals;
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {};
virtual bool match(JSCompartment *c) const {
return JS_GetCompartmentPrincipals(c) == principals;
};
};
JS_FRIEND_API(bool)
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter);
} /* namespace js */
#endif

View File

@ -89,6 +89,7 @@
#include "nsJSON.h"
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
#include "mozilla/dom/DOMRequest.h"
#include "mozilla/OSFileConstants.h"
using mozilla::dom::indexedDB::IndexedDatabaseManager;
using mozilla::dom::DOMRequestService;
@ -618,6 +619,8 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsSystemPrincipal,
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNullPrincipal, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStructuredCloneContainer)
NS_GENERIC_FACTORY_CONSTRUCTOR(OSFileConstantsService)
static nsresult
Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
void **aResult)
@ -771,6 +774,7 @@ NS_DEFINE_NAMED_CID(SMS_SERVICE_CID);
NS_DEFINE_NAMED_CID(SMS_DATABASE_SERVICE_CID);
NS_DEFINE_NAMED_CID(SMS_REQUEST_MANAGER_CID);
NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID);
NS_DEFINE_NAMED_CID(OSFILECONSTANTSSERVICE_CID);
static nsresult
CreateWindowCommandTableConstructor(nsISupports *aOuter,
@ -1038,6 +1042,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kSMS_DATABASE_SERVICE_CID, false, NULL, nsISmsDatabaseServiceConstructor },
{ &kSMS_REQUEST_MANAGER_CID, false, NULL, SmsRequestManagerConstructor },
{ &kNS_POWERMANAGERSERVICE_CID, false, NULL, nsIPowerManagerServiceConstructor },
{ &kOSFILECONSTANTSSERVICE_CID, true, NULL, OSFileConstantsServiceConstructor },
{ NULL }
};
@ -1170,6 +1175,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ SMS_DATABASE_SERVICE_CONTRACTID, &kSMS_DATABASE_SERVICE_CID },
{ SMS_REQUEST_MANAGER_CONTRACTID, &kSMS_REQUEST_MANAGER_CID },
{ POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID },
{ OSFILECONSTANTSSERVICE_CONTRACTID, &kOSFILECONSTANTSSERVICE_CID },
{ NULL }
};

View File

@ -355,6 +355,10 @@ TelemetryPing.prototype = {
if (this._addons)
ret.addons = this._addons;
let flashVersion = this.getFlashVersion();
if (flashVersion)
ret.flashVersion = flashVersion;
return ret;
},
@ -734,6 +738,18 @@ TelemetryPing.prototype = {
}
},
getFlashVersion: function getFlashVersion() {
let host = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
let tags = host.getPluginTags();
for (let i = 0; i < tags.length; i++) {
if (tags[i].name == "Shockwave Flash")
return tags[i].version;
}
return null;
},
/**
* Remove observers to avoid leaks
*/

View File

@ -19,6 +19,7 @@ const IGNORE_HISTOGRAM_TO_CLONE = "MEMORY_HEAP_ALLOCATED";
const IGNORE_CLONED_HISTOGRAM = "test::ignore_me_also";
const ADDON_NAME = "Telemetry test addon";
const ADDON_HISTOGRAM = "addon-histogram";
const FLASH_VERSION = "1.1.1.1";
const BinaryInputStream = Components.Constructor(
"@mozilla.org/binaryinputstream;1",
@ -125,7 +126,8 @@ function checkPayloadInfo(payload, reason) {
appVersion: "1",
appName: "XPCShell",
appBuildID: "2007010101",
platformBuildID: "2007010101"
platformBuildID: "2007010101",
flashVersion: FLASH_VERSION
};
for (let f in expected_info) {
@ -326,6 +328,40 @@ function dummyTheme(id) {
};
}
// A fake plugin host for testing flash version telemetry
var PluginHost = {
getPluginTags: function(countRef) {
let plugins = [{name: "Shockwave Flash", version: FLASH_VERSION}];
countRef.value = plugins.length;
return plugins;
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsIPluginHost)
|| iid.equals(Ci.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
}
var PluginHostFactory = {
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return PluginHost.QueryInterface(iid);
}
};
const PLUGINHOST_CONTRACTID = "@mozilla.org/plugin/host;1";
const PLUGINHOST_CID = Components.ID("{2329e6ea-1f15-4cbe-9ded-6e98e842de0e}");
function registerFakePluginHost() {
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(PLUGINHOST_CID, "Fake Plugin Host",
PLUGINHOST_CONTRACTID, PluginHostFactory);
}
function run_test() {
try {
var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfoDebug);
@ -346,10 +382,13 @@ function run_test() {
gInternalManager.observe(null, "addons-startup", null);
LightweightThemeManager.currentTheme = dummyTheme("1234");
// fake plugin host for consistent flash version data
registerFakePluginHost();
Services.obs.addObserver(nonexistentServerObserver, "telemetry-test-xhr-complete", false);
telemetry_ping();
// spin the event loop
do_test_pending();
// ensure that test runs to completion
do_register_cleanup(function () do_check_true(gFinished));
}
}

View File

@ -480,14 +480,16 @@ nsWindow::GetLayerManager(PLayersChild* aShadowManager,
if (mLayerManager)
return mLayerManager;
// Set mUseAcceleratedRendering here to make it consistent with
// nsBaseWidget::GetLayerManager
// Set mUseAcceleratedRendering here to make it consistent with
// nsBaseWidget::GetLayerManager
mUseAcceleratedRendering = GetShouldAccelerate();
if (!mUseAcceleratedRendering) {
sFramebufferOpen = Framebuffer::Open();
if (!sFramebufferOpen) {
LOG("Failed to mmap fb(?!?), aborting ...");
NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
sFramebufferOpen = Framebuffer::Open();
if (!sFramebufferOpen) {
LOG("Failed to mmap fb(?!?), aborting ...");
NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
}
}
}
@ -505,7 +507,9 @@ nsWindow::GetLayerManager(PLayersChild* aShadowManager,
}
DebugOnly<nsIntRect> fbBounds = gScreenBounds;
sGLContext = GLContextProvider::CreateForWindow(this);
if (!sGLContext) {
sGLContext = GLContextProvider::CreateForWindow(this);
}
MOZ_ASSERT(fbBounds.value == gScreenBounds);
if (sGLContext) {
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);

View File

@ -26,12 +26,11 @@
#include "nsIModule.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
// class definition headers
#include "nsWindow.h"
#include "nsAppShell.h"
#include "nsAppShellSingleton.h"
#include "nsBidiKeyboard.h"
#include "nsWindow.h"
#include "nsDragService.h"
#include "nsIFile.h"
#include "nsFilePicker.h"

View File

@ -22,6 +22,7 @@
* - Window Message Handlers
* - Drag & Drop - Target methods
* - Keyboard Handlers
* - IME
* - Event Dispatch
*
*/
@ -42,11 +43,10 @@
#include "nsTHashtable.h"
#include "nsGkAtoms.h"
#include "wdgtos2rc.h"
#include "mozilla/Preferences.h"
#include <os2im.h>
using namespace mozilla;
//=============================================================================
// Macros
//=============================================================================
@ -163,9 +163,16 @@ static PRUint32 sDragStatus = 0;
#ifdef DEBUG_FOCUS
int currentWindowIdentifier = 0;
#endif
// IME stuffs
static HMODULE sIm32Mod = NULLHANDLE;
static APIRET (APIENTRY *spfnImGetInstance)(HWND, PHIMI);
static APIRET (APIENTRY *spfnImReleaseInstance)(HWND, HIMI);
static APIRET (APIENTRY *spfnImGetConversionString)(HIMI, ULONG, PVOID,
PULONG);
static APIRET (APIENTRY *spfnImGetResultString)(HIMI, ULONG, PVOID, PULONG);
static APIRET (APIENTRY *spfnImRequestIME)(HIMI, ULONG, ULONG, ULONG);
//-----------------------------------------------------------------------------
static PRUint32 WMChar2KeyCode(MPARAM mp1, MPARAM mp2);
//=============================================================================
@ -189,7 +196,7 @@ nsWindow::nsWindow() : nsBaseWidget()
mClipWnd = 0;
mCssCursorHPtr = 0;
mThebesSurface = 0;
mIsComposing = false;
if (!gOS2Flags) {
InitGlobals();
}
@ -274,8 +281,48 @@ void nsWindow::InitGlobals()
if (Preferences::GetBool("os2.trackpoint", false)) {
gOS2Flags |= kIsTrackPoint;
}
InitIME();
}
//-----------------------------------------------------------------------------
// Determine whether to use IME
static
void InitIME()
{
if (!getenv("MOZ_IME_OVERTHESPOT")) {
CHAR szName[CCHMAXPATH];
ULONG rc;
rc = DosLoadModule(szName, sizeof(szName), "os2im", &sIm32Mod);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 104, NULL,
(PFN *)&spfnImGetInstance);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 106, NULL,
(PFN *)&spfnImReleaseInstance);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 118, NULL,
(PFN *)&spfnImGetConversionString);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 122, NULL,
(PFN *)&spfnImGetResultString);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 131, NULL,
(PFN *)&spfnImRequestIME);
if (rc) {
DosFreeModule(sIm32Mod);
sIm32Mod = NULLHANDLE;
}
}
}
//-----------------------------------------------------------------------------
// Release Module-level variables.
@ -1841,6 +1888,10 @@ MRESULT nsWindow::ProcessMessage(ULONG msg, MPARAM mp1, MPARAM mp2)
case WM_QUERYCONVERTPOS:
isDone = OnQueryConvertPos(mp1, mresult);
break;
case WM_IMEREQUEST:
isDone = OnImeRequest(mp1, mp2);
break;
}
// If an event handler signalled that we should consume the event,
// return. Otherwise, pass it on to the default wndproc.
@ -2416,6 +2467,156 @@ bool nsWindow::OnQueryConvertPos(MPARAM mp1, MRESULT& mresult)
return true;
}
bool nsWindow::ImeResultString(HIMI himi)
{
PCHAR pBuf;
ULONG ulBufLen;
// Get a buffer size
ulBufLen = 0;
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, NULL, &ulBufLen))
return false;
pBuf = new CHAR[ulBufLen];
if (!pBuf)
return false;
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, pBuf,
&ulBufLen)) {
delete pBuf;
return false;
}
if (!mIsComposing) {
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
InitEvent(start);
DispatchWindowEvent(&start);
mIsComposing = true;
}
nsAutoChar16Buffer outBuf;
PRInt32 outBufLen;
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
delete pBuf;
nsTextEvent text(true, NS_TEXT_TEXT, this);
InitEvent(text);
text.theText = outBuf.Elements();
DispatchWindowEvent(&text);
nsCompositionEvent end(true, NS_COMPOSITION_END, this);
InitEvent(end);
end.data = text.theText;
DispatchWindowEvent(&end);
mIsComposing = false;
return true;
}
bool nsWindow::ImeConversionString(HIMI himi)
{
PCHAR pBuf;
ULONG ulBufLen;
// Get a buffer size
ulBufLen = 0;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, NULL,
&ulBufLen))
return false;
pBuf = new CHAR[ulBufLen];
if (!pBuf)
return false;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, pBuf,
&ulBufLen)) {
delete pBuf;
return false;
}
if (!mIsComposing) {
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
InitEvent(start);
DispatchWindowEvent(&start);
mIsComposing = true;
}
nsAutoChar16Buffer outBuf;
PRInt32 outBufLen;
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
delete pBuf;
nsAutoTArray<nsTextRange, 4> textRanges;
// Is there a conversion string ?
if (outBufLen) {
nsTextRange newRange;
newRange.mStartOffset = 0;
newRange.mEndOffset = outBufLen;
newRange.mRangeType = NS_TEXTRANGE_SELECTEDRAWTEXT;
textRanges.AppendElement(newRange);
newRange.mStartOffset = outBufLen;
newRange.mEndOffset = newRange.mStartOffset;
newRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
textRanges.AppendElement(newRange);
}
nsTextEvent text(true, NS_TEXT_TEXT, this);
InitEvent(text);
text.theText = outBuf.Elements();
text.rangeArray = textRanges.Elements();
text.rangeCount = textRanges.Length();
DispatchWindowEvent(&text);
if (outBufLen) {
nsCompositionEvent update(true, NS_COMPOSITION_UPDATE, this);
InitEvent(update);
update.data = text.theText;
DispatchWindowEvent(&update);
} else { // IME conversion was canceled ?
nsCompositionEvent end(true, NS_COMPOSITION_END, this);
InitEvent(end);
end.data = text.theText;
DispatchWindowEvent(&end);
mIsComposing = false;
}
return true;
}
bool nsWindow::OnImeRequest(MPARAM mp1, MPARAM mp2)
{
HIMI himi;
bool rc;
if (!sIm32Mod)
return false;
if (SHORT1FROMMP(mp1) != IMR_CONVRESULT)
return false;
if (spfnImGetInstance(mWnd, &himi))
return false;
if (LONGFROMMP(mp2) & IMR_RESULT_RESULTSTRING)
rc = ImeResultString(himi);
else if (LONGFROMMP(mp2) & IMR_CONV_CONVERSIONSTRING)
rc = ImeConversionString(himi);
else
rc = true;
spfnImReleaseInstance(mWnd, himi);
return rc;
}
//-----------------------------------------------------------------------------
// Key handler. Specs for the various text messages are really confused;
@ -2840,6 +3041,14 @@ bool nsWindow::DispatchMouseEvent(PRUint32 aEventType, MPARAM mp1, MPARAM mp2,
? nsMouseEvent::eContextMenuKey
: nsMouseEvent::eNormal);
event.button = aButton;
if (aEventType == NS_MOUSE_BUTTON_DOWN && mIsComposing) {
// If IME is composing, let it complete.
HIMI himi;
spfnImGetInstance(mWnd, &himi);
spfnImRequestIME(himi, REQ_CONVERSIONSTRING, CNV_COMPLETE, 0);
spfnImReleaseInstance(mWnd, himi);
}
if (aEventType == NS_MOUSE_ENTER || aEventType == NS_MOUSE_EXIT) {
// Ignore enter/leave msgs forwarded from the frame to FID_CLIENT

View File

@ -55,10 +55,10 @@
#define INCL_NLS
#define INCL_GPI
#include <os2.h>
#include <os2im.h>
//-----------------------------------------------------------------------------
// Items that may not be in the OS/2 Toolkit headers
// For WM_MOUSEENTER/LEAVE, mp2 is the other window.
#ifndef WM_MOUSEENTER
#define WM_MOUSEENTER 0x041E
@ -231,6 +231,9 @@ protected:
bool ReleaseIfDragHPS(HPS aHps);
bool OnTranslateAccelerator(PQMSG pQmsg);
bool OnQueryConvertPos(MPARAM mp1, MRESULT& mresult);
bool ImeResultString(HIMI himi);
bool ImeConversionString(HIMI himi);
bool OnImeRequest(MPARAM mp1, MPARAM mp2);
bool DispatchKeyEvent(MPARAM mp1, MPARAM mp2);
void InitEvent(nsGUIEvent& event, nsIntPoint* pt = 0);
bool DispatchWindowEvent(nsGUIEvent* event);
@ -267,6 +270,7 @@ protected:
HPOINTER mCssCursorHPtr; // created by SetCursor(imgIContainer*)
nsCOMPtr<imgIContainer> mCssCursorImg;// saved by SetCursor(imgIContainer*)
nsRefPtr<gfxOS2Surface> mThebesSurface;
bool mIsComposing;
#ifdef DEBUG_FOCUS
int mWindowIdentifier; // a serial number for each new window
#endif