Merge m-c to b-i

This commit is contained in:
Phil Ringnalda 2015-02-01 09:20:02 -08:00
commit 6e34c70597
123 changed files with 7066 additions and 6295 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 870366 - Blacklisting PREF_JS_EXPORTS in Makefile.ins (because of 852814)
Bug 1109248 - This needed a CLOBBER on Windows and OSX.

View File

@ -83,10 +83,14 @@ exports.RecordingUtils.getSamplesFromAllocations = function(allocations) {
samples.push(sample);
while (frame) {
let source = frame.source + ":" + frame.line + ":" + frame.column;
let funcName = frame.functionDisplayName || "";
sample.frames.push({
location: frame.source + ":" + frame.line + ":" + frame.column,
location: funcName ? funcName + " (" + source + ")" : source,
allocations: count
});
site = frame.parent;
frame = frames[site];
count = counts[site];

View File

@ -25,18 +25,21 @@ let TEST_DATA = {
source: "A",
line: 1,
column: 2,
functionDisplayName: "x",
parent: 0
},
{
source: "B",
line: 3,
column: 4,
functionDisplayName: "y",
parent: 1
},
{
source: "C",
line: 5,
column: 6,
functionDisplayName: null,
parent: 2
}
],
@ -52,25 +55,25 @@ let EXPECTED_OUTPUT = [{
}, {
time: 150,
frames: [{
location: "A:1:2",
location: "x (A:1:2)",
allocations: 22
}]
}, {
time: 200,
frames: [{
location: "A:1:2",
location: "x (A:1:2)",
allocations: 22
}, {
location: "B:3:4",
location: "y (B:3:4)",
allocations: 33
}]
}, {
time: 250,
frames: [{
location: "A:1:2",
location: "x (A:1:2)",
allocations: 22
}, {
location: "B:3:4",
location: "y (B:3:4)",
allocations: 33
}, {
location: "C:5:6",

View File

@ -90,7 +90,6 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
NO_DIST_INSTALL \
OS_LIBS \
PARALLEL_DIRS \
PREF_JS_EXPORTS \
PROGRAM \
PYTHON_UNIT_TESTS \
RESOURCE_FILES \

View File

@ -71,7 +71,7 @@ GCONF_VERSION=1.2.1
GIO_VERSION=2.20
STARTUP_NOTIFICATION_VERSION=0.8
DBUS_VERSION=0.60
SQLITE_VERSION=3.8.8.1
SQLITE_VERSION=3.8.8.2
MSMANIFEST_TOOL=

View File

@ -1,4 +1,5 @@
This is SQLite 3.8.8.1
This is the SQLite amalgamation.
Check sqlite3.h for the version number and source id.
See http://www.sqlite.org/ for more info.

View File

@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.8.8.1. By combining all the individual C code files into this
** version 3.8.8.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@ -278,9 +278,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.8.1"
#define SQLITE_VERSION "3.8.8.2"
#define SQLITE_VERSION_NUMBER 3008008
#define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55"
#define SQLITE_SOURCE_ID "2015-01-30 14:30:45 7757fc721220e136620a89c9d28247f28bbbc098"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -50197,7 +50197,7 @@ static int walCheckpoint(
int sync_flags, /* Flags for OsSync() (or 0) */
u8 *zBuf /* Temporary buffer to use */
){
int rc; /* Return code */
int rc = SQLITE_OK; /* Return code */
int szPage; /* Database page-size */
WalIterator *pIter = 0; /* Wal iterator context */
u32 iDbpage = 0; /* Next database page to write */
@ -50211,104 +50211,107 @@ static int walCheckpoint(
testcase( szPage<=32768 );
testcase( szPage>=65536 );
pInfo = walCkptInfo(pWal);
if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
if( pInfo->nBackfill<pWal->hdr.mxFrame ){
/* Allocate the iterator */
rc = walIteratorInit(pWal, &pIter);
if( rc!=SQLITE_OK ){
return rc;
}
assert( pIter );
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
/* Compute in mxSafeFrame the index of the last frame of the WAL that is
** safe to write into the database. Frames beyond mxSafeFrame might
** overwrite database pages that are in use by active readers and thus
** cannot be backfilled from the WAL.
*/
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
for(i=1; i<WAL_NREADER; i++){
u32 y = pInfo->aReadMark[i];
if( mxSafeFrame>y ){
assert( y<=pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
}else if( rc==SQLITE_BUSY ){
mxSafeFrame = y;
xBusy = 0;
}else{
goto walcheckpoint_out;
}
/* Allocate the iterator */
rc = walIteratorInit(pWal, &pIter);
if( rc!=SQLITE_OK ){
return rc;
}
}
assert( pIter );
if( pInfo->nBackfill<mxSafeFrame
&& (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK
){
i64 nSize; /* Current size of database file */
u32 nBackfill = pInfo->nBackfill;
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
/* Sync the WAL to disk */
if( sync_flags ){
rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
}
/* If the database may grow as a result of this checkpoint, hint
** about the eventual size of the db file to the VFS layer.
/* Compute in mxSafeFrame the index of the last frame of the WAL that is
** safe to write into the database. Frames beyond mxSafeFrame might
** overwrite database pages that are in use by active readers and thus
** cannot be backfilled from the WAL.
*/
if( rc==SQLITE_OK ){
i64 nReq = ((i64)mxPage * szPage);
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSize<nReq ){
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
}
}
/* Iterate through the contents of the WAL, copying data to the db file. */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
iOffset = (iDbpage-1)*(i64)szPage;
testcase( IS_BIG_INT(iOffset) );
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
}
/* If work was actually accomplished... */
if( rc==SQLITE_OK ){
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
i64 szDb = pWal->hdr.nPage*(i64)szPage;
testcase( IS_BIG_INT(szDb) );
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
if( rc==SQLITE_OK && sync_flags ){
rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
for(i=1; i<WAL_NREADER; i++){
u32 y = pInfo->aReadMark[i];
if( mxSafeFrame>y ){
assert( y<=pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
}else if( rc==SQLITE_BUSY ){
mxSafeFrame = y;
xBusy = 0;
}else{
goto walcheckpoint_out;
}
}
if( rc==SQLITE_OK ){
pInfo->nBackfill = mxSafeFrame;
}
}
/* Release the reader lock held while backfilling */
walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
}
if( pInfo->nBackfill<mxSafeFrame
&& (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
){
i64 nSize; /* Current size of database file */
u32 nBackfill = pInfo->nBackfill;
if( rc==SQLITE_BUSY ){
/* Reset the return code so as not to report a checkpoint failure
** just because there are active readers. */
rc = SQLITE_OK;
/* Sync the WAL to disk */
if( sync_flags ){
rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
}
/* If the database may grow as a result of this checkpoint, hint
** about the eventual size of the db file to the VFS layer.
*/
if( rc==SQLITE_OK ){
i64 nReq = ((i64)mxPage * szPage);
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSize<nReq ){
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
}
}
/* Iterate through the contents of the WAL, copying data to the db file */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
continue;
}
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
iOffset = (iDbpage-1)*(i64)szPage;
testcase( IS_BIG_INT(iOffset) );
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
}
/* If work was actually accomplished... */
if( rc==SQLITE_OK ){
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
i64 szDb = pWal->hdr.nPage*(i64)szPage;
testcase( IS_BIG_INT(szDb) );
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
if( rc==SQLITE_OK && sync_flags ){
rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
}
}
if( rc==SQLITE_OK ){
pInfo->nBackfill = mxSafeFrame;
}
}
/* Release the reader lock held while backfilling */
walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
}
if( rc==SQLITE_BUSY ){
/* Reset the return code so as not to report a checkpoint failure
** just because there are active readers. */
rc = SQLITE_OK;
}
}
/* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the
@ -50323,7 +50326,7 @@ static int walCheckpoint(
}else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
u32 salt1;
sqlite3_randomness(4, &salt1);
assert( mxSafeFrame==pWal->hdr.mxFrame );
assert( pInfo->nBackfill==pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
if( rc==SQLITE_OK ){
if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){
@ -128369,6 +128372,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
rc = SQLITE_ERROR;
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb);
}else{
db->busyHandler.nBusy = 0;
rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
sqlite3Error(db, rc);
}

View File

@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.8.1"
#define SQLITE_VERSION "3.8.8.2"
#define SQLITE_VERSION_NUMBER 3008008
#define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55"
#define SQLITE_SOURCE_ID "2015-01-30 14:30:45 7757fc721220e136620a89c9d28247f28bbbc098"
/*
** CAPI3REF: Run-Time Library Version Numbers

View File

@ -2075,7 +2075,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
if (aWin->GetDoc()) {
aWin->GetDoc()->WarnOnceAbout(nsIDocument::eWindow_Controllers);
}
JS::Rooted<JSObject*> shim(cx, JS_NewObject(cx, &ControllersShimClass, JS::NullPtr(), obj));
JS::Rooted<JSObject*> shim(cx, JS_NewObject(cx, &ControllersShimClass, obj));
if (NS_WARN_IF(!shim)) {
return NS_ERROR_OUT_OF_MEMORY;
}

View File

@ -6154,7 +6154,7 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
}
if (!aOptions.mPrototype) {
protoObject = JS_NewObject(aCx, nullptr, htmlProto, JS::NullPtr());
protoObject = JS_NewObjectWithGivenProto(aCx, nullptr, htmlProto, JS::NullPtr());
if (!protoObject) {
rv.Throw(NS_ERROR_UNEXPECTED);
return;

View File

@ -481,8 +481,8 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
JS::Rooted<JSObject*> constructor(cx);
if (constructorClass) {
MOZ_ASSERT(constructorProto);
constructor = JS_NewObject(cx, Jsvalify(constructorClass), constructorProto,
global);
constructor = JS_NewObjectWithGivenProto(cx, Jsvalify(constructorClass),
constructorProto, global);
} else {
MOZ_ASSERT(constructorNative);
MOZ_ASSERT(constructorProto == JS_GetFunctionPrototype(cx, global));

View File

@ -2798,7 +2798,7 @@ public:
JS::Handle<JSObject*> aProto, JS::Handle<JSObject*> aParent,
T* aNative, JS::MutableHandle<JSObject*> aReflector)
{
aReflector.set(JS_NewObject(aCx, aClass, aProto, aParent));
aReflector.set(JS_NewObjectWithGivenProto(aCx, aClass, aProto, aParent));
if (aReflector) {
js::SetReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
mNative = aNative;

View File

@ -172,8 +172,7 @@ GetJSValFromKeyPathString(JSContext* aCx,
}
else {
JS::Rooted<JSObject*> dummy(aCx,
JS_NewObject(aCx, IDBObjectStore::DummyPropClass(), JS::NullPtr(),
JS::NullPtr()));
JS_NewObject(aCx, IDBObjectStore::DummyPropClass()));
if (!dummy) {
IDB_REPORT_INTERNAL_ERR();
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;

View File

@ -124,10 +124,10 @@ class TabChild::DelayedFireSingleTapEvent MOZ_FINAL : public nsITimerCallback
public:
NS_DECL_ISUPPORTS
DelayedFireSingleTapEvent(TabChild* aTabChild,
DelayedFireSingleTapEvent(nsIWidget* aWidget,
LayoutDevicePoint& aPoint,
nsITimer* aTimer)
: mTabChild(do_GetWeakReference(static_cast<nsITabChild*>(aTabChild)))
: mWidget(do_GetWeakReference(aWidget))
, mPoint(aPoint)
// Hold the reference count until we are called back.
, mTimer(aTimer)
@ -136,9 +136,9 @@ public:
NS_IMETHODIMP Notify(nsITimer*) MOZ_OVERRIDE
{
nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(mTabChild);
if (tabChild) {
static_cast<TabChild*>(tabChild.get())->FireSingleTapEvent(mPoint);
nsCOMPtr<nsIWidget> widget = do_QueryReferent(mWidget);
if (widget) {
APZCCallbackHelper::FireSingleTapEvent(mPoint, widget);
}
mTimer = nullptr;
return NS_OK;
@ -153,7 +153,7 @@ private:
{
}
nsWeakPtr mTabChild;
nsWeakPtr mWidget;
LayoutDevicePoint mPoint;
nsCOMPtr<nsITimer> mTimer;
};
@ -602,46 +602,6 @@ TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
return newMetrics;
}
nsEventStatus
TabChildBase::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
const LayoutDevicePoint& aRefPoint,
nsIWidget* aWidget)
{
MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
aMsg == NS_MOUSE_BUTTON_UP || aMsg == NS_MOUSE_MOZLONGTAP);
WidgetMouseEvent event(true, aMsg, nullptr,
WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
event.time = aTime;
event.button = WidgetMouseEvent::eLeftButton;
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
event.ignoreRootScrollFrame = true;
if (aMsg != NS_MOUSE_MOVE) {
event.clickCount = 1;
}
event.widget = aWidget;
return DispatchWidgetEvent(event);
}
nsEventStatus
TabChildBase::DispatchWidgetEvent(WidgetGUIEvent& event)
{
if (!event.widget)
return nsEventStatus_eConsumeNoDefault;
if (TabParent* capturer = TabParent::GetEventCapturer()) {
if (capturer->TryCapture(event)) {
return nsEventStatus_eConsumeNoDefault;
}
}
nsEventStatus status;
NS_ENSURE_SUCCESS(event.widget->DispatchEvent(&event, status),
nsEventStatus_eConsumeNoDefault);
return status;
}
bool
TabChildBase::IsAsyncPanZoomEnabled()
{
@ -2155,14 +2115,14 @@ TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid&
// If the active element isn't visually affected by the :active style, we
// have no need to wait the extra sActiveDurationMs to make the activation
// visually obvious to the user.
FireSingleTapEvent(currentPoint);
APZCCallbackHelper::FireSingleTapEvent(currentPoint, mWidget);
return true;
}
TABC_LOG("Active element uses style, scheduling timer for click event\n");
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
nsRefPtr<DelayedFireSingleTapEvent> callback =
new DelayedFireSingleTapEvent(this, currentPoint, timer);
new DelayedFireSingleTapEvent(mWidget, currentPoint, timer);
nsresult rv = timer->InitWithCallback(callback,
sActiveDurationMs,
nsITimer::TYPE_ONE_SHOT);
@ -2174,20 +2134,6 @@ TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid&
return true;
}
void
TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
{
if (mDestroyed) {
return;
}
TABC_LOG("Dispatching single-tap component events to %s\n",
Stringify(aPoint).c_str());
int time = 0;
DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, mWidget);
DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, mWidget);
DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, mWidget);
}
bool
TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId)
{
@ -2215,7 +2161,7 @@ TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& a
* mWidget->GetDefaultScale();
int time = 0;
nsEventStatus status =
DispatchSynthesizedMouseEvent(NS_MOUSE_MOZLONGTAP, time, currentPoint, mWidget);
APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_MOZLONGTAP, time, currentPoint, mWidget);
eventHandled = (status == nsEventStatus_eConsumeNoDefault);
TABC_LOG("MOZLONGTAP event handled: %d\n", eventHandled);
}
@ -2342,7 +2288,7 @@ TabChild::RecvRealMouseEvent(const WidgetMouseEvent& event)
{
WidgetMouseEvent localEvent(event);
localEvent.widget = mWidget;
DispatchWidgetEvent(localEvent);
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
return true;
}
@ -2367,7 +2313,7 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
WidgetWheelEvent event(aEvent);
event.widget = mWidget;
DispatchWidgetEvent(event);
APZCCallbackHelper::DispatchWidgetEvent(event);
if (IsAsyncPanZoomEnabled()) {
SendContentReceivedInputBlock(aGuid, aInputBlockId, event.mFlags.mDefaultPrevented);
@ -2461,9 +2407,9 @@ TabChild::UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus)
case NS_TOUCH_END:
if (!nsIPresShell::gPreventMouseEvents) {
DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget);
DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget);
DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget);
APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget);
APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget);
APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget);
}
// fall through
case NS_TOUCH_CANCEL:
@ -2702,7 +2648,7 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
WidgetTouchEvent localEvent(aEvent);
localEvent.widget = mWidget;
// Dispatch event to content (potentially a long-running operation)
nsEventStatus status = DispatchWidgetEvent(localEvent);
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
if (!IsAsyncPanZoomEnabled()) {
UpdateTapState(localEvent, status);
@ -2807,7 +2753,7 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
WidgetKeyboardEvent localEvent(event);
localEvent.widget = mWidget;
nsEventStatus status = DispatchWidgetEvent(localEvent);
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
if (event.message == NS_KEY_DOWN) {
mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
@ -2844,7 +2790,7 @@ TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
{
WidgetCompositionEvent localEvent(event);
localEvent.widget = mWidget;
DispatchWidgetEvent(localEvent);
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
return true;
}
@ -2853,7 +2799,7 @@ TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
{
WidgetSelectionEvent localEvent(event);
localEvent.widget = mWidget;
DispatchWidgetEvent(localEvent);
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
return true;
}

View File

@ -196,10 +196,6 @@ public:
const bool& aIsRoot,
const mozilla::layers::ZoomConstraints& aConstraints) = 0;
nsEventStatus DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
const LayoutDevicePoint& aRefPoint,
nsIWidget* aWidget);
protected:
virtual ~TabChildBase();
CSSSize GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport);
@ -221,8 +217,6 @@ protected:
void DispatchMessageManagerMessage(const nsAString& aMessageName,
const nsAString& aJSONData);
nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& event);
void InitializeRootMetrics();
mozilla::layers::FrameMetrics ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
@ -659,7 +653,6 @@ private:
bool mPendingTouchPreventedResponse;
ScrollableLayerGuid mPendingTouchPreventedGuid;
uint64_t mPendingTouchPreventedBlockId;
void FireSingleTapEvent(LayoutDevicePoint aPoint);
bool mTouchEndCancelled;
bool mEndTouchIsClick;

View File

@ -182,7 +182,9 @@ ToMediaKeyStatus(GMPMediaKeyStatus aStatus) {
switch (aStatus) {
case kGMPUsable: return MediaKeyStatus::Usable;
case kGMPExpired: return MediaKeyStatus::Expired;
case kGMPOutputDownscaled: return MediaKeyStatus::Output_downscaled;
case kGMPOutputNotAllowed: return MediaKeyStatus::Output_not_allowed;
case kGMPInternalError: return MediaKeyStatus::Internal_error;
default: return MediaKeyStatus::Internal_error;
}
}

View File

@ -1,5 +1,5 @@
Name: fake
Description: Fake GMP Plugin
Version: 1.0
APIs: encode-video[h264], decode-video[h264], eme-decrypt-v5[fake]
APIs: encode-video[h264], decode-video[h264], eme-decrypt-v6[fake]
Libraries: dxva2.dll

View File

@ -79,9 +79,11 @@ enum GMPSessionMessageType {
enum GMPMediaKeyStatus {
kGMPUsable = 0,
kGMPExpired = 1,
kGMPOutputNotAllowed = 2,
kGMPUnknown = 3,
kGMPMediaKeyStatusInvalid = 4 // Must always be last.
kGMPOutputDownscaled = 2,
kGMPOutputNotAllowed = 3,
kGMPInternalError = 4,
kGMPUnknown = 5,
kGMPMediaKeyStatusInvalid = 6 // Must always be last.
};
// Time in milliseconds, as offset from epoch, 1 Jan 1970.
@ -222,7 +224,7 @@ enum GMPSessionType {
kGMPSessionInvalid = 2 // Must always be last.
};
#define GMP_API_DECRYPTOR "eme-decrypt-v5"
#define GMP_API_DECRYPTOR "eme-decrypt-v6"
// API exposed by plugin library to manage decryption sessions.
// When the Host requests this by calling GMPGetAPIFunc().

View File

@ -1906,8 +1906,7 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, NPObject *npobj)
// No existing JSObject, create one.
JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, js::Jsvalify(&sNPObjectJSWrapperClass),
JS::NullPtr(), JS::NullPtr()));
JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, js::Jsvalify(&sNPObjectJSWrapperClass)));
if (generation != sNPObjWrappers.Generation()) {
// Reload entry if the JS_NewObject call caused a GC and reallocated
@ -2076,7 +2075,7 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
// during initialization.
memset(memberPrivate, 0, sizeof(NPObjectMemberPrivate));
JSObject *memobj = ::JS_NewObject(cx, &sNPObjectMemberClass, JS::NullPtr(), JS::NullPtr());
JSObject *memobj = ::JS_NewObject(cx, &sNPObjectMemberClass);
if (!memobj) {
PR_Free(memberPrivate);
return false;

View File

@ -4,7 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "APZCCallbackHelper.h"
#include "gfxPlatform.h" // For gfxPlatform::UseTiling
#include "mozilla/dom/TabParent.h"
#include "nsIScrollableFrame.h"
#include "nsLayoutUtils.h"
#include "nsIDOMElement.h"
@ -13,9 +15,14 @@
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#define APZCCH_LOG(...)
// #define APZCCH_LOG(...) printf_stderr("APZCCH: " __VA_ARGS__)
namespace mozilla {
namespace layers {
using dom::TabParent;
bool
APZCCallbackHelper::HasValidPresShellId(nsIDOMWindowUtils* aUtils,
const FrameMetrics& aMetrics)
@ -360,5 +367,67 @@ APZCCallbackHelper::ApplyCallbackTransform(const nsIntPoint& aPoint,
return nsIntPoint(ret.x, ret.y);
}
nsEventStatus
APZCCallbackHelper::DispatchWidgetEvent(WidgetGUIEvent& aEvent)
{
if (!aEvent.widget)
return nsEventStatus_eConsumeNoDefault;
// A nested process may be capturing events.
if (TabParent* capturer = TabParent::GetEventCapturer()) {
if (capturer->TryCapture(aEvent)) {
// Only touch events should be captured, and touch events from a parent
// process should not make it here. Capture for those is done elsewhere
// (for gonk, in nsWindow::DispatchTouchInputViaAPZ).
MOZ_ASSERT(!XRE_IsParentProcess());
return nsEventStatus_eConsumeNoDefault;
}
}
nsEventStatus status;
NS_ENSURE_SUCCESS(aEvent.widget->DispatchEvent(&aEvent, status),
nsEventStatus_eConsumeNoDefault);
return status;
}
nsEventStatus
APZCCallbackHelper::DispatchSynthesizedMouseEvent(uint32_t aMsg,
uint64_t aTime,
const LayoutDevicePoint& aRefPoint,
nsIWidget* aWidget)
{
MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
aMsg == NS_MOUSE_BUTTON_UP || aMsg == NS_MOUSE_MOZLONGTAP);
WidgetMouseEvent event(true, aMsg, nullptr,
WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
event.time = aTime;
event.button = WidgetMouseEvent::eLeftButton;
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
event.ignoreRootScrollFrame = true;
if (aMsg != NS_MOUSE_MOVE) {
event.clickCount = 1;
}
event.widget = aWidget;
return DispatchWidgetEvent(event);
}
void
APZCCallbackHelper::FireSingleTapEvent(const LayoutDevicePoint& aPoint,
nsIWidget* aWidget)
{
if (aWidget->Destroyed()) {
return;
}
APZCCH_LOG("Dispatching single-tap component events to %s\n",
Stringify(aPoint).c_str());
int time = 0;
DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, aWidget);
DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, aWidget);
DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, aWidget);
}
}
}

View File

@ -7,10 +7,12 @@
#define mozilla_layers_APZCCallbackHelper_h
#include "FrameMetrics.h"
#include "mozilla/EventForwards.h"
#include "nsIDOMWindowUtils.h"
class nsIContent;
class nsIDocument;
class nsIWidget;
template<class T> struct already_AddRefed;
namespace mozilla {
@ -104,6 +106,23 @@ public:
const ScrollableLayerGuid& aGuid,
const CSSToLayoutDeviceScale& aScale,
float aPresShellResolution);
/* Dispatch a widget event via the widget stored in the event, if any.
* In a child process, allows the TabParent event-capture mechanism to
* intercept the event. */
static nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& aEvent);
/* Synthesize a mouse event with the given parameters, and dispatch it
* via the given widget. */
static nsEventStatus DispatchSynthesizedMouseEvent(uint32_t aMsg,
uint64_t aTime,
const LayoutDevicePoint& aRefPoint,
nsIWidget* aWidget);
/* Fire a single-tap event at the given point. The event is dispatched
* via the given widget. */
static void FireSingleTapEvent(const LayoutDevicePoint& aPoint,
nsIWidget* aWidget);
};
}

View File

@ -97,3 +97,31 @@ ChromeProcessController::Destroy()
MOZ_ASSERT(MessageLoop::current() == mUILoop);
mWidget = nullptr;
}
float
ChromeProcessController::GetPresShellResolution() const
{
// The document in the chrome process cannot be zoomed, so its pres shell
// resolution is 1.
return 1.0f;
}
void
ChromeProcessController::HandleSingleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ChromeProcessController::HandleSingleTap,
aPoint, aModifiers, aGuid));
return;
}
LayoutDevicePoint point =
APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid, GetPresShellResolution())
* mWidget->GetDefaultScale();
APZCCallbackHelper::FireSingleTapEvent(point, mWidget);
}

View File

@ -38,7 +38,7 @@ public:
virtual void HandleDoubleTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers,
const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {}
virtual void HandleSingleTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers,
const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {}
const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
virtual void HandleLongTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) MOZ_OVERRIDE {}
@ -52,6 +52,7 @@ private:
MessageLoop* mUILoop;
void InitializeRoot();
float GetPresShellResolution() const;
};
} // namespace layers

View File

@ -614,16 +614,11 @@ RasterImage::IsOpaque()
void
RasterImage::OnSurfaceDiscarded()
{
if (!NS_IsMainThread()) {
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &RasterImage::OnSurfaceDiscarded);
NS_DispatchToMainThread(runnable);
return;
}
MOZ_ASSERT(mProgressTracker);
if (mProgressTracker) {
mProgressTracker->OnDiscard();
}
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(mProgressTracker, &ProgressTracker::OnDiscard);
NS_DispatchToMainThread(runnable);
}
//******************************************************************************

View File

@ -362,7 +362,7 @@ public:
SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
uint32_t aSurfaceCacheDiscardFactor,
uint32_t aSurfaceCacheSize)
: mExpirationTracker(this, aSurfaceCacheExpirationTimeMS)
: mExpirationTracker(aSurfaceCacheExpirationTimeMS)
, mMemoryPressureObserver(new MemoryPressureObserver)
, mMutex("SurfaceCache")
, mDiscardFactor(aSurfaceCacheDiscardFactor)
@ -742,6 +742,8 @@ public:
nsISupports* aData,
bool aAnonymize) MOZ_OVERRIDE
{
MutexAutoLock lock(mMutex);
// We have explicit memory reporting for the surface cache which is more
// accurate than the cost metrics we report here, but these metrics are
// still useful to report, since they control the cache's behavior.
@ -809,21 +811,18 @@ private:
struct SurfaceTracker : public nsExpirationTracker<CachedSurface, 2>
{
SurfaceTracker(SurfaceCacheImpl* aCache, uint32_t aSurfaceCacheExpirationTimeMS)
explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
: nsExpirationTracker<CachedSurface, 2>(aSurfaceCacheExpirationTimeMS)
, mCache(aCache)
{ }
protected:
virtual void NotifyExpired(CachedSurface* aSurface) MOZ_OVERRIDE
{
if (mCache) {
mCache->Remove(aSurface);
if (sInstance) {
MutexAutoLock lock(sInstance->GetMutex());
sInstance->Remove(aSurface);
}
}
private:
SurfaceCacheImpl* const mCache; // Weak pointer to owner.
};
struct MemoryPressureObserver : public nsIObserver
@ -835,6 +834,7 @@ private:
const char16_t*) MOZ_OVERRIDE
{
if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
MutexAutoLock lock(sInstance->GetMutex());
sInstance->DiscardForMemoryPressure();
}
return NS_OK;

View File

@ -27,18 +27,6 @@ function currentRequest() {
return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
}
function attachDiscardObserver(result) {
// Create the discard observer.
let observer = new ImageDiscardObserver(result);
let scriptedObserver = Cc["@mozilla.org/image/tools;1"]
.getService(Ci.imgITools)
.createScriptedObserver(observer);
// Clone the current imgIRequest with our new observer.
let request = currentRequest();
return request.clone(scriptedObserver);
}
function isImgDecoded() {
let request = currentRequest();
return request.imageStatus & Ci.imgIRequest.STATUS_FRAME_COMPLETE ? true : false;
@ -69,9 +57,18 @@ function test() {
}
function step2() {
// Attach a discard listener and create a place to hold the result.
// Create a place to hold the result.
var result = { wasDiscarded: false };
var clonedRequest = attachDiscardObserver(result);
// Create the discard observer.
var observer = new ImageDiscardObserver(result);
var scriptedObserver = Cc["@mozilla.org/image/tools;1"]
.getService(Ci.imgITools)
.createScriptedObserver(observer);
// Clone the current imgIRequest with our new observer.
var request = currentRequest();
var clonedRequest = request.clone(scriptedObserver);
// Check that the image is decoded.
forceDecodeImg();
@ -83,6 +80,19 @@ function step2() {
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
os.notifyObservers(null, 'memory-pressure', 'heap-minimize');
// The discard notification is delivered asynchronously, so pump the event
// loop before checking.
window.addEventListener('message', function (event) {
if (event.data == 'step3') {
step3(result, scriptedObserver, clonedRequest);
}
}, false);
window.postMessage('step3', '*');
}
function step3(result, scriptedObserver, clonedRequest) {
ok(result.wasDiscarded, 'Image should be discarded.');
// And we're done.

View File

@ -1548,7 +1548,7 @@ class CloneBufferObject : public NativeObject {
static const Class class_;
static CloneBufferObject *Create(JSContext *cx) {
RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&class_), JS::NullPtr(), JS::NullPtr()));
RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&class_)));
if (!obj)
return nullptr;
obj->as<CloneBufferObject>().setReservedSlot(DATA_SLOT, PrivateValue(nullptr));

View File

@ -1700,7 +1700,7 @@ TypedObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
return obj_lookupElement(cx, obj, index, objp, propp);
if (JSID_IS_ATOM(id, cx->names().length)) {
MarkNonNativePropertyFound(propp);
MarkNonNativePropertyFound<CanGC>(propp);
objp.set(obj);
return true;
}
@ -1712,7 +1712,7 @@ TypedObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
StructTypeDescr &structDescr = descr->as<StructTypeDescr>();
size_t index;
if (structDescr.fieldIndex(id, &index)) {
MarkNonNativePropertyFound(propp);
MarkNonNativePropertyFound<CanGC>(propp);
objp.set(obj);
return true;
}
@ -1746,7 +1746,7 @@ TypedObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp)
{
MOZ_ASSERT(obj->is<TypedObject>());
MarkNonNativePropertyFound(propp);
MarkNonNativePropertyFound<CanGC>(propp);
objp.set(obj);
return true;
}

View File

@ -909,7 +909,7 @@ InitCTypeClass(JSContext* cx, HandleObject parent)
MOZ_ASSERT(fnproto);
// Set up ctypes.CType.prototype.
RootedObject prototype(cx, JS_NewObject(cx, &sCTypeProtoClass, fnproto, parent));
RootedObject prototype(cx, JS_NewObjectWithGivenProto(cx, &sCTypeProtoClass, fnproto, parent));
if (!prototype)
return nullptr;
@ -965,7 +965,7 @@ InitCDataClass(JSContext* cx, HandleObject parent, HandleObject CTypeProto)
return nullptr;
// Set up ctypes.CData.prototype.
RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, NullPtr(), parent));
RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, parent));
if (!prototype)
return nullptr;
@ -1029,7 +1029,7 @@ InitTypeConstructor(JSContext* cx,
return false;
// Set up the .prototype and .prototype.constructor properties.
typeProto.set(JS_NewObject(cx, &sCTypeProtoClass, CTypeProto, parent));
typeProto.set(JS_NewObjectWithGivenProto(cx, &sCTypeProtoClass, CTypeProto, parent));
if (!typeProto)
return false;
@ -1056,7 +1056,7 @@ InitTypeConstructor(JSContext* cx,
// created from the given type constructor. This has ctypes.CData.prototype
// as its prototype, such that it inherits the properties and functions
// common to all CDatas.
dataProto.set(JS_NewObject(cx, &sCDataProtoClass, CDataProto, parent));
dataProto.set(JS_NewObjectWithGivenProto(cx, &sCDataProtoClass, CDataProto, parent));
if (!dataProto)
return false;
@ -1363,7 +1363,7 @@ JS_PUBLIC_API(bool)
JS_InitCTypesClass(JSContext* cx, HandleObject global)
{
// attach ctypes property to global object
RootedObject ctypes(cx, JS_NewObject(cx, &sCTypesGlobalClass, NullPtr(), NullPtr()));
RootedObject ctypes(cx, JS_NewObject(cx, &sCTypesGlobalClass));
if (!ctypes)
return false;
@ -1386,7 +1386,7 @@ JS_InitCTypesClass(JSContext* cx, HandleObject global)
if (!GetObjectProperty(cx, ctypes, "CDataFinalizer", &ctor))
return false;
RootedObject prototype(cx, JS_NewObject(cx, &sCDataFinalizerProtoClass, NullPtr(), ctypes));
RootedObject prototype(cx, JS_NewObject(cx, &sCDataFinalizerProtoClass, ctypes));
if (!prototype)
return false;
@ -3301,7 +3301,7 @@ CType::Create(JSContext* cx,
// * 'constructor' property === 't'
// * Additional properties specified by 'ps', as appropriate for the
// specific type instance 't'.
RootedObject typeObj(cx, JS_NewObject(cx, &sCTypeClass, typeProto, parent));
RootedObject typeObj(cx, JS_NewObjectWithGivenProto(cx, &sCTypeClass, typeProto, parent));
if (!typeObj)
return nullptr;
@ -3316,7 +3316,7 @@ CType::Create(JSContext* cx,
if (dataProto) {
// Set up the 'prototype' and 'prototype.constructor' properties.
RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, dataProto, parent));
RootedObject prototype(cx, JS_NewObjectWithGivenProto(cx, &sCDataProtoClass, dataProto, parent));
if (!prototype)
return nullptr;
@ -4868,7 +4868,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
// Set up the 'prototype' and 'prototype.constructor' properties.
// The prototype will reflect the struct fields as properties on CData objects
// created from this type.
RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, dataProto, NullPtr()));
RootedObject prototype(cx, JS_NewObjectWithGivenProto(cx, &sCDataProtoClass, dataProto, NullPtr()));
if (!prototype)
return false;
@ -6075,7 +6075,7 @@ CClosure::Create(JSContext* cx,
RootedValue errVal(cx, errVal_);
MOZ_ASSERT(fnObj);
RootedObject result(cx, JS_NewObject(cx, &sCClosureClass, NullPtr(), NullPtr()));
RootedObject result(cx, JS_NewObject(cx, &sCClosureClass));
if (!result)
return nullptr;
@ -6377,7 +6377,7 @@ CData::Create(JSContext* cx,
RootedObject parent(cx, JS_GetParent(typeObj));
MOZ_ASSERT(parent);
RootedObject dataObj(cx, JS_NewObject(cx, &sCDataClass, proto, parent));
RootedObject dataObj(cx, JS_NewObjectWithGivenProto(cx, &sCDataClass, proto, parent));
if (!dataObj)
return nullptr;
@ -6958,7 +6958,8 @@ CDataFinalizer::Construct(JSContext* cx, unsigned argc, jsval *vp)
// Get arguments
if (args.length() == 0) { // Special case: the empty (already finalized) object
JSObject *objResult = JS_NewObject(cx, &sCDataFinalizerClass, objProto, NullPtr());
JSObject *objResult = JS_NewObjectWithGivenProto(cx, &sCDataFinalizerClass, objProto,
NullPtr());
args.rval().setObject(*objResult);
return true;
}
@ -7057,7 +7058,7 @@ CDataFinalizer::Construct(JSContext* cx, unsigned argc, jsval *vp)
// 5. Create |objResult|
JSObject *objResult = JS_NewObject(cx, &sCDataFinalizerClass, objProto, NullPtr());
JSObject *objResult = JS_NewObjectWithGivenProto(cx, &sCDataFinalizerClass, objProto, NullPtr());
if (!objResult) {
return false;
}
@ -7357,7 +7358,7 @@ Int64Base::Construct(JSContext* cx,
{
const JSClass* clasp = isUnsigned ? &sUInt64Class : &sInt64Class;
RootedObject parent(cx, JS_GetParent(proto));
RootedObject result(cx, JS_NewObject(cx, clasp, proto, parent));
RootedObject result(cx, JS_NewObjectWithGivenProto(cx, clasp, proto, parent));
if (!result)
return nullptr;

View File

@ -83,8 +83,7 @@ JSObject*
Library::Create(JSContext* cx, jsval path_, const JSCTypesCallbacks* callbacks)
{
RootedValue path(cx, path_);
RootedObject libraryObj(cx,
JS_NewObject(cx, &sLibraryClass, NullPtr(), NullPtr()));
RootedObject libraryObj(cx, JS_NewObject(cx, &sLibraryClass));
if (!libraryObj)
return nullptr;

View File

@ -0,0 +1,17 @@
var threshold = getJitCompilerOptions()["ion.warmup.trigger"] + 101;
function bar(i) {
if (!i)
with (this) {}; // Don't inline.
if (i === threshold)
minorgc();
}
function f() {
var o2 = Object.create({get foo() { return this.x; }, set foo(x) { this.x = x + 1; }});
for (var i=0; i<2000; i++) {
o2.foo = i;
assertEq(o2.foo, i + 1);
bar(i);
}
}
f();

View File

@ -3334,14 +3334,6 @@ IsCacheableGetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *sh
return false;
JSFunction *func = &shape->getterObject()->as<JSFunction>();
// Information from get prop call ICs may be used directly from Ion code,
// and should not be nursery allocated.
if (IsInsideNursery(holder) || IsInsideNursery(func)) {
*isTemporarilyUnoptimizable = true;
return false;
}
if (func->isNative()) {
*isScripted = false;
return true;
@ -3457,13 +3449,6 @@ IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *sh
JSFunction *func = &shape->setterObject()->as<JSFunction>();
// Information from set prop call ICs may be used directly from Ion code,
// and should not be nursery allocated.
if (IsInsideNursery(holder) || IsInsideNursery(func)) {
*isTemporarilyUnoptimizable = true;
return false;
}
if (func->isNative()) {
*isScripted = false;
return true;

View File

@ -2154,6 +2154,19 @@ CodeGenerator::visitPointer(LPointer *lir)
masm.movePtr(ImmPtr(lir->ptr()), ToRegister(lir->output()));
}
void
CodeGenerator::visitNurseryObject(LNurseryObject *lir)
{
Register output = ToRegister(lir->output());
uint32_t index = lir->mir()->index();
// Store a dummy JSObject pointer. We will fix it up on the main thread,
// in JitCode::fixupNurseryObjects. The low bit is set to distinguish
// it from a real JSObject pointer.
JSObject *ptr = reinterpret_cast<JSObject*>((uintptr_t(index) << 1) | 1);
masm.movePtr(ImmGCPtr(IonNurseryPtr(ptr)), output);
}
void
CodeGenerator::visitSlots(LSlots *lir)
{
@ -7383,6 +7396,9 @@ CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
}
#endif
// Replace dummy JSObject pointers embedded by LNurseryObject.
code->fixupNurseryObjects(cx, gen->nurseryObjects());
// The correct state for prebarriers is unknown until the end of compilation,
// since a GC can occur during code generation. All barriers are emitted
// off-by-default, and are toggled on here if necessary.

View File

@ -111,6 +111,7 @@ class CodeGenerator : public CodeGeneratorSpecific
void visitLambdaArrow(LLambdaArrow *lir);
void visitLambdaForSingleton(LLambdaForSingleton *lir);
void visitPointer(LPointer *lir);
void visitNurseryObject(LNurseryObject *lir);
void visitSlots(LSlots *lir);
void visitLoadSlotT(LLoadSlotT *lir);
void visitLoadSlotV(LLoadSlotV *lir);

View File

@ -163,7 +163,8 @@ JitRuntime::JitRuntime()
osrTempData_(nullptr),
mutatingBackedgeList_(false),
ionReturnOverride_(MagicValue(JS_ARG_POISON)),
jitcodeGlobalTable_(nullptr)
jitcodeGlobalTable_(nullptr),
hasIonNurseryObjects_(false)
{
}
@ -653,6 +654,17 @@ JitCode::trace(JSTracer *trc)
}
}
void
JitCode::fixupNurseryObjects(JSContext *cx, const ObjectVector &nurseryObjects)
{
if (nurseryObjects.empty() || !dataRelocTableBytes_)
return;
uint8_t *start = code_ + dataRelocTableOffset();
CompactBufferReader reader(start, start + dataRelocTableBytes_);
MacroAssembler::FixupNurseryObjects(cx, this, reader, nurseryObjects);
}
void
JitCode::finalize(FreeOp *fop)
{
@ -1671,6 +1683,62 @@ AttachFinishedCompilations(JSContext *cx)
}
}
void
MIRGenerator::traceNurseryObjects(JSTracer *trc)
{
MarkObjectRootRange(trc, nurseryObjects_.length(), nurseryObjects_.begin(), "ion-nursery-objects");
}
class MarkOffThreadNurseryObjects : public gc::BufferableRef
{
public:
void mark(JSTracer *trc);
};
void
MarkOffThreadNurseryObjects::mark(JSTracer *trc)
{
JSRuntime *rt = trc->runtime();
MOZ_ASSERT(rt->jitRuntime()->hasIonNurseryObjects());
rt->jitRuntime()->setHasIonNurseryObjects(false);
AutoLockHelperThreadState lock;
if (!HelperThreadState().threads)
return;
// Trace nursery objects of any builders which haven't started yet.
GlobalHelperThreadState::IonBuilderVector &worklist = HelperThreadState().ionWorklist();
for (size_t i = 0; i < worklist.length(); i++) {
jit::IonBuilder *builder = worklist[i];
if (builder->script()->runtimeFromAnyThread() == rt)
builder->traceNurseryObjects(trc);
}
// Trace nursery objects of in-progress entries.
for (size_t i = 0; i < HelperThreadState().threadCount; i++) {
HelperThread &helper = HelperThreadState().threads[i];
if (helper.ionBuilder && helper.ionBuilder->script()->runtimeFromAnyThread() == rt)
helper.ionBuilder->traceNurseryObjects(trc);
}
// Trace nursery objects of any completed entries.
GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
for (size_t i = 0; i < finished.length(); i++) {
jit::IonBuilder *builder = finished[i];
if (builder->script()->runtimeFromAnyThread() == rt)
builder->traceNurseryObjects(trc);
}
// Trace nursery objects of lazy-linked builders.
jit::IonBuilder *builder = HelperThreadState().ionLazyLinkList().getFirst();
while (builder) {
if (builder->script()->runtimeFromAnyThread() == rt)
builder->traceNurseryObjects(trc);
builder = builder->getNext();
}
}
static inline bool
OffThreadCompilationAvailable(JSContext *cx)
{
@ -1866,6 +1934,15 @@ IonCompile(JSContext *cx, JSScript *script,
JitSpew(JitSpew_IonLogs, "Can't log script %s:%d. (Compiled on background thread.)",
builderScript->filename(), builderScript->lineno());
JSRuntime *rt = cx->runtime();
if (!builder->nurseryObjects().empty() && !rt->jitRuntime()->hasIonNurseryObjects()) {
// Ensure the builder's nursery objects are marked when a nursery
// GC happens on the main thread.
MarkOffThreadNurseryObjects mark;
rt->gc.storeBuffer.putGeneric(mark);
rt->jitRuntime()->setHasIonNurseryObjects(true);
}
if (!StartOffThreadIonCompile(cx, builder)) {
JitSpew(JitSpew_IonAbort, "Unable to start off-thread ion compilation.");
return AbortReason_Alloc;

View File

@ -216,6 +216,37 @@ IonBuilder::spew(const char *message)
#endif
}
MInstruction *
IonBuilder::constantMaybeNursery(JSObject *obj)
{
MOZ_ASSERT(obj);
if (!IsInsideNursery(obj))
return constant(ObjectValue(*obj));
// If |obj| is in the nursery, we have to add it to the list of nursery
// objects that get traced during off-thread compilation. We use
// MNurseryObject to ensure we will patch the code with the right
// pointer after codegen is done.
size_t index = UINT32_MAX;
for (size_t i = 0, len = nurseryObjects_.length(); i < len; i++) {
if (nurseryObjects_[i] == obj) {
index = i;
break;
}
}
if (index == UINT32_MAX) {
if (!nurseryObjects_.append(obj))
return nullptr;
index = nurseryObjects_.length() - 1;
}
MNurseryObject *ins = MNurseryObject::New(alloc(), obj, index, constraints());
current->add(ins);
return ins;
}
static inline int32_t
GetJumpOffset(jsbytecode *pc)
{
@ -5838,6 +5869,9 @@ bool
IonBuilder::testShouldDOMCall(types::TypeSet *inTypes,
JSFunction *func, JSJitInfo::OpType opType)
{
if (IsInsideNursery(func))
return false;
if (!func->isNative() || !func->jitInfo())
return false;
@ -9297,9 +9331,7 @@ IonBuilder::objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyN
}
}
if (!type->hasTenuredProto())
return false;
JSObject *proto = type->proto().toObjectOrNull();
JSObject *proto = type->protoMaybeInNursery().toObjectOrNull();
if (proto == foundProto)
break;
if (!proto) {
@ -9307,7 +9339,7 @@ IonBuilder::objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyN
// object's prototype chain.
return false;
}
type = types::TypeObjectKey::get(type->proto().toObjectOrNull());
type = types::TypeObjectKey::get(proto);
}
}
@ -9336,14 +9368,14 @@ IonBuilder::freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, P
// Don't mark the proto. It will be held down by the shape
// guard. This allows us to use properties found on prototypes
// with properties unknown to TI.
if (type->proto() == TaggedProto(foundProto))
if (type->protoMaybeInNursery() == TaggedProto(foundProto))
break;
type = types::TypeObjectKey::get(type->proto().toObjectOrNull());
type = types::TypeObjectKey::get(type->protoMaybeInNursery().toObjectOrNull());
}
}
}
inline bool
bool
IonBuilder::testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
bool isGetter, JSObject *foundProto, Shape *lastProperty,
MDefinition **guard,
@ -9385,7 +9417,7 @@ IonBuilder::testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName
return true;
}
MInstruction *wrapper = constant(ObjectValue(*foundProto));
MInstruction *wrapper = constantMaybeNursery(foundProto);
*guard = addShapeGuard(wrapper, lastProperty, Bailout_ShapeGuard);
return true;
}
@ -10049,7 +10081,7 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName
// Make sure there's enough room
if (!current->ensureHasSlots(2))
return false;
pushConstant(ObjectValue(*commonGetter));
current->push(constantMaybeNursery(commonGetter));
current->push(obj);
@ -10089,7 +10121,8 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName
}
}
if (!makeCall(commonGetter, callInfo, false))
JSFunction *tenuredCommonGetter = IsInsideNursery(commonGetter) ? nullptr : commonGetter;
if (!makeCall(tenuredCommonGetter, callInfo, false))
return false;
// If the getter could have been inlined, don't track success. The call to
@ -10497,8 +10530,7 @@ IonBuilder::setPropTryCommonSetter(bool *emitted, MDefinition *obj,
if (!current->ensureHasSlots(3))
return false;
pushConstant(ObjectValue(*commonSetter));
current->push(constantMaybeNursery(commonSetter));
current->push(obj);
current->push(value);
@ -10528,7 +10560,8 @@ IonBuilder::setPropTryCommonSetter(bool *emitted, MDefinition *obj,
}
}
MCall *call = makeCallHelper(commonSetter, callInfo, false);
JSFunction *tenuredCommonSetter = IsInsideNursery(commonSetter) ? nullptr : commonSetter;
MCall *call = makeCallHelper(tenuredCommonSetter, callInfo, false);
if (!call)
return false;

View File

@ -238,6 +238,8 @@ class IonBuilder
void trackActionableAbort(const char *message);
void spew(const char *message);
MInstruction *constantMaybeNursery(JSObject *obj);
JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
ObjectVector &targets, uint32_t maxTargets);

View File

@ -1177,9 +1177,17 @@ CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &ca
// of turn. We don't mind doing this even when purity isn't required, because we
// only miss out on shape hashification, which is only a temporary perf cost.
// The limits were arbitrarily set, anyways.
if (!LookupPropertyPure(cx, obj, NameToId(name), holder.address(), shape.address()))
JSObject *baseHolder = nullptr;
if (!LookupPropertyPure(cx, obj, NameToId(name), &baseHolder, shape.address()))
return GetPropertyIC::CanAttachNone;
MOZ_ASSERT(!holder);
if (baseHolder) {
if (!baseHolder->isNative())
return GetPropertyIC::CanAttachNone;
holder.set(&baseHolder->as<NativeObject>());
}
RootedScript script(cx);
jsbytecode *pc;
cache.getScriptedLocation(&script, &pc);
@ -2645,7 +2653,7 @@ IsPropertyAddInlineable(NativeObject *obj, HandleId id, ConstantOrRegister val,
static SetPropertyIC::NativeSetPropCacheability
CanAttachNativeSetProp(JSContext *cx, HandleObject obj, HandleId id, ConstantOrRegister val,
bool needsTypeBarrier, MutableHandleNativeObject holder,
bool needsTypeBarrier, MutableHandleObject holder,
MutableHandleShape shape, bool *checkTypeset)
{
if (!obj->isNative())
@ -2723,7 +2731,7 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
}
RootedShape shape(cx);
RootedNativeObject holder(cx);
RootedObject holder(cx);
bool checkTypeset;
canCache = CanAttachNativeSetProp(cx, obj, id, cache.value(), cache.needsTypeBarrier(),
&holder, &shape, &checkTypeset);

View File

@ -32,6 +32,8 @@ class CodeOffsetLabel;
class PatchableBackedge;
class IonBuilder;
typedef Vector<JSObject *, 4, JitAllocPolicy> ObjectVector;
class JitCode : public gc::TenuredCell
{
protected:
@ -112,6 +114,8 @@ class JitCode : public gc::TenuredCell
invalidated_ = true;
}
void fixupNurseryObjects(JSContext *cx, const ObjectVector &nurseryObjects);
void setHasBytecodeMap() {
hasBytecodeMap_ = true;
}

View File

@ -235,6 +235,8 @@ class JitRuntime
// Global table of jitcode native address => bytecode address mappings.
JitcodeGlobalTable *jitcodeGlobalTable_;
bool hasIonNurseryObjects_;
private:
JitCode *generateLazyLinkStub(JSContext *cx);
JitCode *generateProfilerExitFrameTailStub(JSContext *cx);
@ -390,6 +392,13 @@ class JitRuntime
ionReturnOverride_ = v;
}
bool hasIonNurseryObjects() const {
return hasIonNurseryObjects_;
}
void setHasIonNurseryObjects(bool b) {
hasIonNurseryObjects_ = b;
}
bool hasJitcodeGlobalTable() const {
return jitcodeGlobalTable_ != nullptr;
}

View File

@ -683,6 +683,16 @@ class LValue : public LInstructionHelper<BOX_PIECES, 0, 0>
}
};
class LNurseryObject : public LInstructionHelper<1, 0, 0>
{
public:
LIR_HEADER(NurseryObject);
MNurseryObject *mir() const {
return mir_->toNurseryObject();
}
};
// Clone an object literal such as we are not modifying the object contained in
// the sources.
class LCloneLiteral : public LCallInstructionHelper<1, 1, 0>

View File

@ -335,6 +335,7 @@
_(AssertRangeV) \
_(LexicalCheck) \
_(ThrowUninitializedLexical) \
_(NurseryObject) \
_(Debugger)
#if defined(JS_CODEGEN_X86)

View File

@ -4003,6 +4003,12 @@ LIRGenerator::visitDebugger(MDebugger *ins)
add(lir, ins);
}
void
LIRGenerator::visitNurseryObject(MNurseryObject *ins)
{
define(new(alloc()) LNurseryObject(), ins);
}
static void
SpewResumePoint(MBasicBlock *block, MInstruction *ins, MResumePoint *resumePoint)
{

View File

@ -287,6 +287,7 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitLexicalCheck(MLexicalCheck *ins);
void visitThrowUninitializedLexical(MThrowUninitializedLexical *ins);
void visitDebugger(MDebugger *ins);
void visitNurseryObject(MNurseryObject *ins);
};
} // namespace jit

View File

@ -676,6 +676,7 @@ MConstant::MConstant(const js::Value &vp, types::CompilerConstraintList *constra
if (vp.isObject()) {
// Create a singleton type set for the object. This isn't necessary for
// other types as the result type encodes all needed information.
MOZ_ASSERT(!IsInsideNursery(&vp.toObject()));
setResultTypeSet(MakeSingletonTypeSet(constraints, &vp.toObject()));
}
if (vp.isMagic() && vp.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
@ -695,6 +696,7 @@ MConstant::MConstant(const js::Value &vp, types::CompilerConstraintList *constra
MConstant::MConstant(JSObject *obj)
: value_(ObjectValue(*obj))
{
MOZ_ASSERT(!IsInsideNursery(obj));
setResultType(MIRType_Object);
setMovable();
}
@ -804,6 +806,39 @@ MConstant::canProduceFloat32() const
return true;
}
MNurseryObject::MNurseryObject(JSObject *obj, uint32_t index, types::CompilerConstraintList *constraints)
: index_(index)
{
setResultType(MIRType_Object);
MOZ_ASSERT(IsInsideNursery(obj));
MOZ_ASSERT(!obj->hasSingletonType());
setResultTypeSet(MakeSingletonTypeSet(constraints, obj));
setMovable();
}
MNurseryObject *
MNurseryObject::New(TempAllocator &alloc, JSObject *obj, uint32_t index,
types::CompilerConstraintList *constraints)
{
return new(alloc) MNurseryObject(obj, index, constraints);
}
HashNumber
MNurseryObject::valueHash() const
{
return HashNumber(index_);
}
bool
MNurseryObject::congruentTo(const MDefinition *ins) const
{
if (!ins->isNurseryObject())
return false;
return ins->toNurseryObject()->index_ == index_;
}
MDefinition*
MSimdValueX4::foldsTo(TempAllocator &alloc)
{

View File

@ -1329,6 +1329,33 @@ class MConstant : public MNullaryInstruction
ALLOW_CLONE(MConstant)
};
class MNurseryObject : public MNullaryInstruction
{
// Index in MIRGenerator::nurseryObjects_.
uint32_t index_;
protected:
MNurseryObject(JSObject *obj, uint32_t index, types::CompilerConstraintList *constraints);
public:
INSTRUCTION_HEADER(NurseryObject)
static MNurseryObject *New(TempAllocator &alloc, JSObject *obj, uint32_t index,
types::CompilerConstraintList *constraints = nullptr);
HashNumber valueHash() const MOZ_OVERRIDE;
bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE;
uint32_t index() const {
return index_;
}
AliasSet getAliasSet() const MOZ_OVERRIDE {
return AliasSet::None();
}
ALLOW_CLONE(MNurseryObject)
};
// Generic constructor of SIMD valuesX4.
class MSimdValueX4
: public MQuaternaryInstruction,
@ -9825,7 +9852,7 @@ class MGuardObjectIdentity
: public MUnaryInstruction,
public SingleObjectPolicy::Data
{
AlwaysTenured<JSObject *> singleObject_;
AlwaysTenuredObject singleObject_;
bool bailOnEquality_;
MGuardObjectIdentity(MDefinition *obj, JSObject *singleObject, bool bailOnEquality)

View File

@ -193,6 +193,12 @@ class MIRGenerator
bool instrumentedProfiling_;
bool instrumentedProfilingIsCached_;
// List of nursery objects used by this compilation. Can be traced by a
// minor GC while compilation happens off-thread. This Vector should only
// be accessed on the main thread (IonBuilder, nursery GC or
// CodeGenerator::link).
ObjectVector nurseryObjects_;
void addAbortedNewScriptPropertiesType(types::TypeObject *type);
void setForceAbort() {
shouldForceAbort_ = true;
@ -210,6 +216,12 @@ class MIRGenerator
public:
const JitCompileOptions options;
void traceNurseryObjects(JSTracer *trc);
const ObjectVector &nurseryObjects() const {
return nurseryObjects_;
}
};
} // namespace jit

View File

@ -39,6 +39,7 @@ MIRGenerator::MIRGenerator(CompileCompartment *compartment, const JitCompileOpti
modifiesFrameArguments_(false),
instrumentedProfiling_(false),
instrumentedProfilingIsCached_(false),
nurseryObjects_(*alloc),
options(options)
{ }

View File

@ -12,6 +12,7 @@ namespace jit {
#define MIR_OPCODE_LIST(_) \
_(Constant) \
_(NurseryObject) \
_(SimdBox) \
_(SimdUnbox) \
_(SimdValueX4) \

View File

@ -805,6 +805,12 @@ TraceOneDataRelocation(JSTracer *trc, Iter *iter, MacroAssemblerARM *masm)
const void *prior = Assembler::GetPtr32Target(iter, &dest, &rs);
void *ptr = const_cast<void *>(prior);
// The low bit shouldn't be set. If it is, we probably got a dummy
// pointer inserted by CodeGenerator::visitNurseryObject, but we
// shouldn't be able to trigger GC before those are patched to their
// real values.
MOZ_ASSERT(!(uintptr_t(ptr) & 0x1));
// No barrier needed since these are constants.
gc::MarkGCThingUnbarriered(trc, &ptr, "ion-masm-ptr");
@ -846,6 +852,51 @@ Assembler::TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReade
::TraceDataRelocations(trc, code->raw(), reader, static_cast<MacroAssemblerARM *>(Dummy));
}
void
Assembler::FixupNurseryObjects(JSContext *cx, JitCode *code, CompactBufferReader &reader,
const ObjectVector &nurseryObjects)
{
MOZ_ASSERT(!nurseryObjects.empty());
uint8_t *buffer = code->raw();
bool hasNurseryPointers = false;
MacroAssemblerARM *masm = static_cast<MacroAssemblerARM *>(Dummy);
while (reader.more()) {
size_t offset = reader.readUnsigned();
InstructionIterator iter((Instruction*)(buffer + offset));
Instruction *ins = iter.cur();
Register dest;
Assembler::RelocStyle rs;
const void *prior = Assembler::GetPtr32Target(&iter, &dest, &rs);
void *ptr = const_cast<void *>(prior);
uintptr_t word = reinterpret_cast<uintptr_t>(ptr);
if (!(word & 0x1))
continue;
uint32_t index = word >> 1;
JSObject *obj = nurseryObjects[index];
masm->ma_movPatchable(Imm32(int32_t(obj)), dest, Assembler::Always, rs, ins);
if (rs != Assembler::L_LDR) {
// L_LDR won't cause any instructions to be updated.
AutoFlushICache::flush(uintptr_t(ins), 4);
AutoFlushICache::flush(uintptr_t(ins->next()), 4);
}
// Either all objects are still in the nursery, or all objects are
// tenured.
MOZ_ASSERT_IF(hasNurseryPointers, IsInsideNursery(obj));
if (!hasNurseryPointers && IsInsideNursery(obj))
hasNurseryPointers = true;
}
if (hasNurseryPointers)
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(code);
}
void
Assembler::copyJumpRelocationTable(uint8_t *dest)
{

View File

@ -1597,6 +1597,9 @@ class Assembler : public AssemblerShared
static void TraceJumpRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader);
static void TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader);
static void FixupNurseryObjects(JSContext *cx, JitCode *code, CompactBufferReader &reader,
const ObjectVector &nurseryObjects);
static bool SupportsFloatingPoint() {
return HasVFP();
}

View File

@ -288,6 +288,12 @@ TraceOneDataRelocation(JSTracer *trc, Instruction *inst)
void *ptr = (void *)Assembler::ExtractLuiOriValue(inst, inst->next());
void *prior = ptr;
// The low bit shouldn't be set. If it is, we probably got a dummy
// pointer inserted by CodeGenerator::visitNurseryObject, but we
// shouldn't be able to trigger GC before those are patched to their
// real values.
MOZ_ASSERT(!(uintptr_t(ptr) & 0x1));
// No barrier needed since these are constants.
gc::MarkGCThingUnbarriered(trc, reinterpret_cast<void **>(&ptr), "ion-masm-ptr");
if (ptr != prior) {
@ -322,6 +328,43 @@ Assembler::TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReade
::TraceDataRelocations(trc, code->raw(), reader);
}
void
Assembler::FixupNurseryObjects(JSContext *cx, JitCode *code, CompactBufferReader &reader,
const ObjectVector &nurseryObjects)
{
MOZ_ASSERT(!nurseryObjects.empty());
uint8_t *buffer = code->raw();
bool hasNurseryPointers = false;
while (reader.more()) {
size_t offset = reader.readUnsigned();
Instruction *inst = (Instruction*)(buffer + offset);
void *ptr = (void *)Assembler::ExtractLuiOriValue(inst, inst->next());
uintptr_t word = uintptr_t(ptr);
if (!(word & 0x1))
continue;
uint32_t index = word >> 1;
JSObject *obj = nurseryObjects[index];
Assembler::UpdateLuiOriValue(inst, inst->next(), uint32_t(obj));
AutoFlushICache::flush(uintptr_t(inst), 8);
// Either all objects are still in the nursery, or all objects are
// tenured.
MOZ_ASSERT_IF(hasNurseryPointers, IsInsideNursery(obj));
if (!hasNurseryPointers && IsInsideNursery(obj))
hasNurseryPointers = true;
}
if (hasNurseryPointers)
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(code);
}
void
Assembler::copyJumpRelocationTable(uint8_t *dest)
{

View File

@ -1012,6 +1012,9 @@ class Assembler : public AssemblerShared
static void TraceJumpRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader);
static void TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader);
static void FixupNurseryObjects(JSContext *cx, JitCode *code, CompactBufferReader &reader,
const ObjectVector &nurseryObjects);
static bool SupportsFloatingPoint() {
#if (defined(__mips_hard_float) && !defined(__mips_single_float)) || defined(JS_MIPS_SIMULATOR)
return true;

View File

@ -156,6 +156,12 @@ class MacroAssemblerNone : public Assembler
static void TraceJumpRelocations(JSTracer *, JitCode *, CompactBufferReader &) { MOZ_CRASH(); }
static void TraceDataRelocations(JSTracer *, JitCode *, CompactBufferReader &) { MOZ_CRASH(); }
static void FixupNurseryObjects(JSContext *, JitCode *, CompactBufferReader &,
const ObjectVector &)
{
MOZ_CRASH();
}
static bool SupportsFloatingPoint() { return false; }
static bool SupportsSimd() { return false; }

View File

@ -233,6 +233,22 @@ class ImmMaybeNurseryPtr
}
};
// Dummy value used for nursery pointers during Ion compilation, see
// LNurseryObject.
class IonNurseryPtr
{
const gc::Cell *ptr;
public:
friend class ImmGCPtr;
explicit IonNurseryPtr(const gc::Cell *ptr) : ptr(ptr)
{
MOZ_ASSERT(ptr);
MOZ_ASSERT(uintptr_t(ptr) & 0x1);
}
};
// Used for immediates which require relocation.
class ImmGCPtr
{
@ -248,6 +264,15 @@ class ImmGCPtr
MOZ_ASSERT(!IsCompilingAsmJS());
}
explicit ImmGCPtr(IonNurseryPtr ptr) : value(ptr.ptr)
{
MOZ_ASSERT(!IsPoisonedPtr(value));
MOZ_ASSERT(value);
// asm.js shouldn't be creating GC things
MOZ_ASSERT(!IsCompilingAsmJS());
}
private:
ImmGCPtr() : value(0) {}

View File

@ -67,6 +67,12 @@ TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader
}
#endif
// The low bit shouldn't be set. If it is, we probably got a dummy
// pointer inserted by CodeGenerator::visitNurseryObject, but we
// shouldn't be able to trigger GC before those are patched to their
// real values.
MOZ_ASSERT(!(*reinterpret_cast<uintptr_t *>(ptr) & 0x1));
// No barrier needed since these are constants.
gc::MarkGCThingUnbarriered(trc, ptr, "ion-masm-ptr");
}
@ -79,6 +85,45 @@ AssemblerX86Shared::TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBu
::TraceDataRelocations(trc, code->raw(), reader);
}
void
AssemblerX86Shared::FixupNurseryObjects(JSContext *cx, JitCode *code, CompactBufferReader &reader,
const ObjectVector &nurseryObjects)
{
MOZ_ASSERT(!nurseryObjects.empty());
uint8_t *buffer = code->raw();
bool hasNurseryPointers = false;
while (reader.more()) {
size_t offset = reader.readUnsigned();
void **ptr = X86Encoding::GetPointerRef(buffer + offset);
uintptr_t *word = reinterpret_cast<uintptr_t *>(ptr);
#ifdef JS_PUNBOX64
if (*word >> JSVAL_TAG_SHIFT)
continue; // This is a Value.
#endif
if (!(*word & 0x1))
continue;
uint32_t index = *word >> 1;
JSObject *obj = nurseryObjects[index];
*word = uintptr_t(obj);
// Either all objects are still in the nursery, or all objects are
// tenured.
MOZ_ASSERT_IF(hasNurseryPointers, IsInsideNursery(obj));
if (!hasNurseryPointers && IsInsideNursery(obj))
hasNurseryPointers = true;
}
if (hasNurseryPointers)
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(code);
}
void
AssemblerX86Shared::trace(JSTracer *trc)
{

View File

@ -327,6 +327,9 @@ class AssemblerX86Shared : public AssemblerShared
static void TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader);
static void FixupNurseryObjects(JSContext *cx, JitCode *code, CompactBufferReader &reader,
const ObjectVector &nurseryObjects);
// MacroAssemblers hold onto gcthings, so they are traced by the GC.
void trace(JSTracer *trc);

View File

@ -46,7 +46,7 @@ BEGIN_TEST(testAddPropertyHook)
JS::RootedObject arrObj(cx, &arr.toObject());
for (int i = 0; i < ExpectedCount; ++i) {
obj = JS_NewObject(cx, &AddPropertyClass, JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, &AddPropertyClass);
CHECK(obj);
CHECK(JS_DefineElement(cx, arrObj, i, obj,
JSPROP_ENUMERATE,

View File

@ -40,7 +40,7 @@ BEGIN_TEST(test_CallNonGenericMethodOnProxy)
JS::RootedObject globalA(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook));
CHECK(globalA);
JS::RootedObject customA(cx, JS_NewObject(cx, &CustomClass, JS::NullPtr(), JS::NullPtr()));
JS::RootedObject customA(cx, JS_NewObject(cx, &CustomClass));
CHECK(customA);
JS_SetReservedSlot(customA, CUSTOM_SLOT, Int32Value(17));
@ -60,7 +60,7 @@ BEGIN_TEST(test_CallNonGenericMethodOnProxy)
// ...and enter it.
JSAutoCompartment enter(cx, globalB);
JS::RootedObject customB(cx, JS_NewObject(cx, &CustomClass, JS::NullPtr(), JS::NullPtr()));
JS::RootedObject customB(cx, JS_NewObject(cx, &CustomClass));
CHECK(customB);
JS_SetReservedSlot(customB, CUSTOM_SLOT, Int32Value(42));

View File

@ -68,7 +68,7 @@ BEGIN_TEST(testGCNurseryFinalizer)
JS::RootedObject obj(cx);
obj = JS_NewObject(cx, Jsvalify(&TenuredClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&TenuredClass));
CHECK(!js::gc::IsInsideNursery(obj));
// Null finalization list with empty nursery.
@ -85,7 +85,7 @@ BEGIN_TEST(testGCNurseryFinalizer)
CHECK(ranFinalizer == 0);
// Single finalizable nursery thing.
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
CHECK(js::gc::IsInsideNursery(obj));
obj = nullptr;
rt->gc.minorGC(JS::gcreason::EVICT_NURSERY);
@ -93,9 +93,9 @@ BEGIN_TEST(testGCNurseryFinalizer)
ranFinalizer = 0;
// Multiple finalizable nursery things.
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
CHECK(js::gc::IsInsideNursery(obj));
obj = nullptr;
rt->gc.minorGC(JS::gcreason::EVICT_NURSERY);
@ -104,13 +104,13 @@ BEGIN_TEST(testGCNurseryFinalizer)
// Interleaved finalizable things in nursery.
obj = JS_NewPlainObject(cx);
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
obj = JS_NewPlainObject(cx);
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
obj = JS_NewPlainObject(cx);
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
obj = JS_NewPlainObject(cx);
obj = JS_NewObject(cx, Jsvalify(&NurseryClass), JS::NullPtr(), JS::NullPtr());
obj = JS_NewObject(cx, Jsvalify(&NurseryClass));
obj = JS_NewPlainObject(cx);
CHECK(js::gc::IsInsideNursery(obj));
obj = nullptr;

View File

@ -56,8 +56,7 @@ document_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *res
if (!flatStr)
return false;
if (JS_FlatStringEqualsAscii(flatStr, "all")) {
JS::Rooted<JSObject*> docAll(cx,
JS_NewObject(cx, &DocumentAllClass, JS::NullPtr(), JS::NullPtr()));
JS::Rooted<JSObject*> docAll(cx, JS_NewObject(cx, &DocumentAllClass));
if (!docAll)
return false;
@ -82,7 +81,7 @@ static const JSClass document_class = {
BEGIN_TEST(testLookup_bug570195)
{
JS::RootedObject obj(cx, JS_NewObject(cx, &document_class, JS::NullPtr(), JS::NullPtr()));
JS::RootedObject obj(cx, JS_NewObject(cx, &document_class));
CHECK(obj);
CHECK(JS_DefineProperty(cx, global, "document", obj, 0));
JS::RootedValue v(cx);

View File

@ -100,7 +100,7 @@ BEGIN_TEST(testNewObject_1)
nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, constructHook
};
JS::RootedObject ctor(cx, JS_NewObject(cx, &cls, JS::NullPtr(), JS::NullPtr()));
JS::RootedObject ctor(cx, JS_NewObject(cx, &cls));
CHECK(ctor);
JS::RootedValue rt2(cx, OBJECT_TO_JSVAL(ctor));
obj = JS_New(cx, ctor, JS::HandleValueArray::subarray(argv, 0, 3));

View File

@ -33,7 +33,7 @@ createMyObject(JSContext* context, unsigned argc, jsval *vp)
//JS_GC(context); //<- if we make GC here, all is ok
JSObject* myObject = JS_NewObject(context, &myClass, JS::NullPtr(), JS::NullPtr());
JSObject* myObject = JS_NewObject(context, &myClass);
*vp = OBJECT_TO_JSVAL(myObject);
JS_EndRequest(context);

View File

@ -55,7 +55,7 @@ struct Kennel {
MOZ_NEVER_INLINE static Kennel *
Allocate(JSContext *cx)
{
RootedObject barker(cx, JS_NewObject(cx, &BarkWhenTracedClass::class_, JS::NullPtr(), JS::NullPtr()));
RootedObject barker(cx, JS_NewObject(cx, &BarkWhenTracedClass::class_));
if (!barker)
return nullptr;
@ -196,7 +196,7 @@ BEGIN_TEST(test_GlobalPersistentRooted)
CHECK(!gGlobalRoot.initialized());
{
RootedObject barker(cx, JS_NewObject(cx, &BarkWhenTracedClass::class_, JS::NullPtr(), JS::NullPtr()));
RootedObject barker(cx, JS_NewObject(cx, &BarkWhenTracedClass::class_));
CHECK(barker);
gGlobalRoot.init(cx, barker);

View File

@ -25,9 +25,9 @@ BEGIN_TEST(testResolveRecursion)
my_resolve
};
obj1.init(cx, JS_NewObject(cx, &my_resolve_class, JS::NullPtr(), JS::NullPtr()));
obj1.init(cx, JS_NewObject(cx, &my_resolve_class));
CHECK(obj1);
obj2.init(cx, JS_NewObject(cx, &my_resolve_class, JS::NullPtr(), JS::NullPtr()));
obj2.init(cx, JS_NewObject(cx, &my_resolve_class));
CHECK(obj2);
JS_SetPrivate(obj1, this);
JS_SetPrivate(obj2, this);

View File

@ -164,11 +164,7 @@ JSObject *newKey()
JS_NULL_OBJECT_OPS
};
JS::RootedObject key(cx);
key = JS_NewObject(cx,
Jsvalify(&keyClass),
JS::NullPtr(),
JS::NullPtr());
JS::RootedObject key(cx, JS_NewObject(cx, Jsvalify(&keyClass)));
if (!key)
return nullptr;

View File

@ -2032,12 +2032,12 @@ JS_FireOnNewGlobalObject(JSContext *cx, JS::HandleObject global)
}
JS_PUBLIC_API(JSObject *)
JS_NewObject(JSContext *cx, const JSClass *jsclasp, HandleObject proto, HandleObject parent)
JS_NewObject(JSContext *cx, const JSClass *jsclasp, HandleObject parent)
{
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, proto, parent);
assertSameCompartment(cx, parent);
const Class *clasp = Valueify(jsclasp);
if (!clasp)
@ -2046,7 +2046,7 @@ JS_NewObject(JSContext *cx, const JSClass *jsclasp, HandleObject proto, HandleOb
MOZ_ASSERT(clasp != &JSFunction::class_);
MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
JSObject *obj = NewObjectWithClassProto(cx, clasp, nullptr, parent);
MOZ_ASSERT_IF(obj, obj->getParent());
return obj;
}
@ -2066,10 +2066,7 @@ JS_NewObjectWithGivenProto(JSContext *cx, const JSClass *jsclasp, HandleObject p
MOZ_ASSERT(clasp != &JSFunction::class_);
MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
if (obj)
MarkTypeObjectUnknownProperties(cx, obj->type());
return obj;
return NewObjectWithGivenProto(cx, clasp, proto, parent);
}
JS_PUBLIC_API(JSObject *)

View File

@ -2569,8 +2569,7 @@ extern JS_PUBLIC_API(void)
JS_FireOnNewGlobalObject(JSContext *cx, JS::HandleObject global);
extern JS_PUBLIC_API(JSObject *)
JS_NewObject(JSContext *cx, const JSClass *clasp, JS::Handle<JSObject*> proto,
JS::Handle<JSObject*> parent);
JS_NewObject(JSContext *cx, const JSClass *clasp, JS::Handle<JSObject*> parent = JS::NullPtr());
/* Queries the [[Extensible]] property of the object. */
extern JS_PUBLIC_API(bool)
@ -2583,8 +2582,8 @@ extern JS_PUBLIC_API(JSRuntime *)
JS_GetObjectRuntime(JSObject *obj);
/*
* Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
* proto if proto's actual parameter value is null.
* Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default proto.
* If proto is JS::NullPtr, the JS object will have `null` as [[Prototype]].
*/
extern JS_PUBLIC_API(JSObject *)
JS_NewObjectWithGivenProto(JSContext *cx, const JSClass *clasp, JS::Handle<JSObject*> proto,

View File

@ -1074,6 +1074,12 @@ TypeObjectKey::proto()
return isTypeObject() ? asTypeObject()->proto() : asSingleObject()->getTaggedProto();
}
TaggedProto
TypeObjectKey::protoMaybeInNursery()
{
return isTypeObject() ? asTypeObject()->proto() : asSingleObject()->getTaggedProto();
}
bool
JSObject::hasTenuredProto() const
{

View File

@ -1521,10 +1521,8 @@ struct TypeObjectKey
static intptr_t keyBits(TypeObjectKey *obj) { return (intptr_t) obj; }
static TypeObjectKey *getKey(TypeObjectKey *obj) { return obj; }
static TypeObjectKey *get(JSObject *obj) {
MOZ_ASSERT(obj);
return (TypeObjectKey *) (uintptr_t(obj) | 1);
}
static inline TypeObjectKey *get(JSObject *obj);
static TypeObjectKey *get(TypeObject *obj) {
MOZ_ASSERT(obj);
return (TypeObjectKey *) obj;
@ -1545,6 +1543,7 @@ struct TypeObjectKey
const Class *clasp();
TaggedProto proto();
TaggedProto protoMaybeInNursery();
bool hasTenuredProto();
JSObject *singleton();
TypeNewScript *newScript();

View File

@ -122,6 +122,14 @@ TypeObjectKey::asSingleObject()
return res;
}
/* static */ inline TypeObjectKey *
TypeObjectKey::get(JSObject *obj)
{
if (obj->hasSingletonType())
return (TypeObjectKey *) (uintptr_t(obj) | 1);
return TypeObjectKey::get(obj->type());
}
/* static */ inline Type
Type::ObjectType(JSObject *obj)
{

View File

@ -3047,79 +3047,73 @@ js::HasOwnProperty(JSContext *cx, HandleObject obj, HandleId id, bool *result)
return true;
}
static MOZ_ALWAYS_INLINE bool
LookupPropertyPureInline(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
Shape **propp)
bool
js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, JSObject **objp,
Shape **propp)
{
if (!obj->isNative())
return false;
do {
if (obj->isNative()) {
/* Search for a native dense element, typed array element, or property. */
NativeObject *current = &obj->as<NativeObject>();
while (true) {
/* Search for a native dense element, typed array element, or property. */
if (JSID_IS_INT(id) && obj->as<NativeObject>().containsDenseElement(JSID_TO_INT(id))) {
*objp = obj;
MarkDenseOrTypedArrayElementFound<NoGC>(propp);
return true;
}
if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) {
*objp = current;
MarkDenseOrTypedArrayElementFound<NoGC>(propp);
return true;
}
if (IsAnyTypedArray(current)) {
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
if (index < AnyTypedArrayLength(obj)) {
*objp = current;
MarkDenseOrTypedArrayElementFound<NoGC>(propp);
} else {
*objp = nullptr;
*propp = nullptr;
if (IsAnyTypedArray(obj)) {
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
if (index < AnyTypedArrayLength(obj)) {
*objp = obj;
MarkDenseOrTypedArrayElementFound<NoGC>(propp);
} else {
*objp = nullptr;
*propp = nullptr;
}
return true;
}
}
if (Shape *shape = obj->as<NativeObject>().lookupPure(id)) {
*objp = obj;
*propp = shape;
return true;
}
// Fail if there's a resolve hook. We allow the JSFunction resolve hook
// if we know it will never add a property with this name or str_resolve
// with a non-integer property.
do {
const Class *clasp = obj->getClass();
if (!clasp->resolve)
break;
if (clasp->resolve == fun_resolve && !FunctionHasResolveHook(cx->names(), id))
break;
if (clasp->resolve == str_resolve && !JSID_IS_INT(id))
break;
return false;
} while (0);
} else {
// Search for a property on an unboxed object. Other non-native objects
// are not handled here.
if (!obj->is<UnboxedPlainObject>())
return false;
if (obj->as<UnboxedPlainObject>().layout().lookup(id)) {
*objp = obj;
MarkNonNativePropertyFound<NoGC>(propp);
return true;
}
}
if (Shape *shape = current->lookupPure(id)) {
*objp = current;
*propp = shape;
return true;
}
// Fail if there's a resolve hook. We allow the JSFunction resolve hook
// if we know it will never add a property with this name or str_resolve
// with a non-integer property.
do {
const Class *clasp = current->getClass();
if (!clasp->resolve)
break;
if (clasp->resolve == fun_resolve && !FunctionHasResolveHook(cx->names(), id))
break;
if (clasp->resolve == str_resolve && !JSID_IS_INT(id))
break;
return false;
} while (0);
JSObject *proto = current->getProto();
if (!proto)
break;
if (!proto->isNative())
return false;
current = &proto->as<NativeObject>();
}
obj = obj->getProto();
} while (obj);
*objp = nullptr;
*propp = nullptr;
return true;
}
bool
js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
Shape **propp)
{
return LookupPropertyPureInline(cx, obj, id, objp, propp);
}
bool
JSObject::reportReadOnly(JSContext *cx, jsid id, unsigned report)
{

View File

@ -1226,7 +1226,7 @@ js_FindVariableScope(JSContext *cx, JSFunction **funp);
namespace js {
bool
LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, JSObject **objp,
Shape **propp);
bool

View File

@ -559,7 +559,7 @@ js::proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
return false;
if (found) {
MarkNonNativePropertyFound(propp);
MarkNonNativePropertyFound<CanGC>(propp);
objp.set(obj);
} else {
objp.set(nullptr);

View File

@ -1035,7 +1035,7 @@ CacheEntry(JSContext* cx, unsigned argc, JS::Value *vp)
return false;
}
RootedObject obj(cx, JS_NewObject(cx, &CacheEntry_class, JS::NullPtr(), JS::NullPtr()));
RootedObject obj(cx, JS_NewObject(cx, &CacheEntry_class));
if (!obj)
return false;
@ -4039,7 +4039,7 @@ ObjectEmulatingUndefined(JSContext *cx, unsigned argc, jsval *vp)
JSCLASS_EMULATES_UNDEFINED
};
RootedObject obj(cx, JS_NewObject(cx, &cls, JS::NullPtr(), JS::NullPtr()));
RootedObject obj(cx, JS_NewObject(cx, &cls));
if (!obj)
return false;
args.rval().setObject(*obj);
@ -5092,7 +5092,7 @@ dom_constructor(JSContext* cx, unsigned argc, JS::Value *vp)
}
RootedObject proto(cx, &protov.toObject());
RootedObject domObj(cx, JS_NewObject(cx, &dom_class, proto, JS::NullPtr()));
RootedObject domObj(cx, JS_NewObjectWithGivenProto(cx, &dom_class, proto, JS::NullPtr()));
if (!domObj)
return false;

View File

@ -332,6 +332,7 @@ NativeObject::setLastProperty(ExclusiveContext *cx, HandleNativeObject obj, Hand
MOZ_ASSERT(!shape->inDictionary());
MOZ_ASSERT(shape->compartment() == obj->compartment());
MOZ_ASSERT(shape->numFixedSlots() == obj->numFixedSlots());
MOZ_ASSERT(shape->getObjectClass() == obj->getClass());
size_t oldSpan = obj->lastProperty()->slotSpan();
size_t newSpan = shape->slotSpan();
@ -355,6 +356,7 @@ NativeObject::setLastPropertyShrinkFixedSlots(Shape *shape)
MOZ_ASSERT(!shape->inDictionary());
MOZ_ASSERT(shape->compartment() == compartment());
MOZ_ASSERT(lastProperty()->slotSpan() == shape->slotSpan());
MOZ_ASSERT(shape->getObjectClass() == getClass());
DebugOnly<size_t> oldFixed = numFixedSlots();
DebugOnly<size_t> newFixed = shape->numFixedSlots();
@ -381,6 +383,30 @@ NativeObject::setLastPropertyMakeNonNative(Shape *shape)
shape_ = shape;
}
/* static */ void
NativeObject::setLastPropertyMakeNative(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape shape)
{
MOZ_ASSERT(obj->getClass()->isNative());
MOZ_ASSERT(!obj->lastProperty()->isNative());
MOZ_ASSERT(shape->isNative());
MOZ_ASSERT(!obj->inDictionaryMode());
MOZ_ASSERT(!shape->inDictionary());
MOZ_ASSERT(shape->compartment() == obj->compartment());
obj->shape_ = shape;
obj->slots_ = nullptr;
obj->elements_ = emptyObjectElements;
size_t oldSpan = shape->numFixedSlots();
size_t newSpan = shape->slotSpan();
// A failures at this point will leave the object as a mutant, and we
// can't recover.
if (oldSpan != newSpan && !updateSlotsForSpan(cx, obj, oldSpan, newSpan))
CrashAtUnhandlableOOM("NativeObject::setLastPropertyMakeNative");
}
/* static */ bool
NativeObject::setSlotSpan(ExclusiveContext *cx, HandleNativeObject obj, uint32_t span)
{

View File

@ -417,6 +417,12 @@ class NativeObject : public JSObject
// that are (temporarily) inconsistent.
void setLastPropertyMakeNonNative(Shape *shape);
// As for setLastProperty(), but changes the class associated with the
// object to a native one. The object's type has already been changed, and
// this brings the shape into sync with it.
static void setLastPropertyMakeNative(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape shape);
protected:
#ifdef DEBUG
void checkShapeConsistency();

View File

@ -1495,8 +1495,9 @@ template<> struct RootKind<BaseShape *> : SpecificRootKind<BaseShape *, THING_RO
// properties of non-native objects, and dense elements for native objects.
// Use separate APIs for these two cases.
template <AllowGC allowGC>
static inline void
MarkNonNativePropertyFound(MutableHandleShape propp)
MarkNonNativePropertyFound(typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
{
propp.set(reinterpret_cast<Shape*>(1));
}

View File

@ -196,15 +196,11 @@ UnboxedPlainObject::convertToNative(JSContext *cx)
if (!SetClassAndProto(cx, obj, &PlainObject::class_, proto))
return false;
// Any failures after this point will leave the object as a mutant, and we
// can't recover.
RootedPlainObject nobj(cx, &obj->as<PlainObject>());
if (!nobj->setLastProperty(cx, nobj, shape))
CrashAtUnhandlableOOM("UnboxedPlainObject::convertToNative");
RootedNativeObject nobj(cx, &obj->as<PlainObject>());
NativeObject::setLastPropertyMakeNative(cx, nobj, shape);
for (size_t i = 0; i < values.length(); i++)
nobj->initSlot(i, values[i]);
nobj->initSlotUnchecked(i, values[i]);
return true;
}
@ -250,7 +246,7 @@ UnboxedPlainObject::obj_lookupGeneric(JSContext *cx, HandleObject obj,
MutableHandleShape propp)
{
if (obj->as<UnboxedPlainObject>().layout().lookup(id)) {
MarkNonNativePropertyFound(propp);
MarkNonNativePropertyFound<CanGC>(propp);
objp.set(obj);
return true;
}

View File

@ -28,6 +28,12 @@ UnboxedTypeSize(JSValueType type)
}
}
static inline bool
UnboxedTypeNeedsPreBarrier(JSValueType type)
{
return type == JSVAL_TYPE_STRING || type == JSVAL_TYPE_OBJECT;
}
// Class describing the layout of an UnboxedPlainObject.
class UnboxedLayout
{

View File

@ -312,29 +312,33 @@ def print_opcode(opcode):
print("""<dt>{names}</dt>
<dd>
<table class="standard-table">
<tbody>
<tr><th>Value</th><td><code>{values}</code></td></tr>
<tr><th>Operands</th><td><code>{operands}</code></td></tr>
<tr><th>Length</th><td><code>{length}</code></td></tr>
<tr><th>Stack Uses</th><td><code>{stack_uses}</code></td></tr>
<tr><th>Stack Defs</th><td><code>{stack_defs}</code></td></tr>
</tbody>
</table>
{desc}
</dd>
""".format(names='<br>'.join(names),
values='<br>'.join(values),
operands=escape(opcode.operands),
operands=escape(opcode.operands) or "&nbsp;",
length=escape(override(opcode.length,
opcode.length_override)),
stack_uses=escape(opcode.stack_uses),
stack_defs=escape(opcode.stack_defs),
stack_uses=escape(opcode.stack_uses) or "&nbsp;",
stack_defs=escape(opcode.stack_defs) or "&nbsp;",
desc=opcode.desc)) # desc is already escaped
def make_element_id(name):
return name.replace(' ', '-')
def print_doc(version, index):
print("""<h2 id="Bytecode_Listing">Bytecode Listing</h2>
print("""<div>{{{{SpiderMonkeySidebar("Internals")}}}}</div>
<h2 id="Bytecode_Listing">Bytecode Listing</h2>
<p>This document is automatically generated from
<a href="{source_base}/js/src/vm/Opcodes.h">Opcodes.h</a> and

View File

@ -588,7 +588,7 @@ mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx,
if (aReuseLoaderGlobal) {
// If we're reusing the loader global, we don't actually use the
// global, but rather we use a different object as the 'this' object.
obj = JS_NewObject(aCx, &kFakeBackstagePassJSClass, NullPtr(), NullPtr());
obj = JS_NewObject(aCx, &kFakeBackstagePassJSClass);
NS_ENSURE_TRUE(obj, nullptr);
}

View File

@ -464,7 +464,7 @@ CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectInOptions &options,
RootedObject obj(cx);
{
JSAutoCompartment ac(cx, scope);
obj = JS_NewObject(cx, nullptr, JS::NullPtr(), scope);
obj = JS_NewObject(cx, nullptr, scope);
if (!obj)
return false;

View File

@ -1467,7 +1467,7 @@ JSObject*
xpc::NewOutObject(JSContext* cx, JSObject* scope)
{
RootedObject global(cx, JS_GetGlobalForObject(cx, scope));
return JS_NewObject(cx, nullptr, NullPtr(), global);
return JS_NewObject(cx, nullptr, global);
}

View File

@ -808,7 +808,7 @@ XPCWrappedNative::Init(HandleObject parent,
return false;
}
mFlatJSObject = JS_NewObject(cx, jsclazz, protoJSObject, parent);
mFlatJSObject = JS_NewObjectWithGivenProto(cx, jsclazz, protoJSObject, parent);
if (!mFlatJSObject) {
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
return false;
@ -1573,9 +1573,7 @@ XPCWrappedNative::InitTearOffJSObject(XPCWrappedNativeTearOff* to)
AutoJSContext cx;
RootedObject parent(cx, mFlatJSObject);
RootedObject proto(cx, JS_GetObjectPrototype(cx, parent));
JSObject* obj = JS_NewObject(cx, Jsvalify(&XPC_WN_Tearoff_JSClass),
proto, parent);
JSObject* obj = JS_NewObject(cx, Jsvalify(&XPC_WN_Tearoff_JSClass), parent);
if (!obj)
return false;

View File

@ -1,4 +1,4 @@
<html><head>
<html class="reftest-wait"><head>
<style>
*::first-line { font-size:310%; }
</style>
@ -104,10 +104,13 @@ mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmm
mmmmmmmmmmmmmmmmmmmmmmmmmm
</span>
<script>
function finish() {
document.documentElement.removeAttribute('class');
}
function doe(){
document.body.removeAttribute('style');
document.body.removeAttribute('style');
setTimeout(finish, 100);
}
setTimeout(doe,300,0);
setTimeout(function() {window.location.reload()}, 600);
</script>
</body></html>
</body></html>

View File

@ -125,7 +125,7 @@ load 385344-2.html
load 385414-1.html
load 385414-2.html
load 385426-1.html
skip-if(B2G) skip-if(Android&&AndroidVersion==10) load 385526.html # Bug 891347
load 385526.html
load 385681.html
load 385885-1.xul
load 386799-1.html

View File

@ -226,6 +226,15 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
aMetrics.SetSize(wm, convertedSize);
aMetrics.SetBlockStartAscent(kidMetrics.BlockStartAscent() +
bp.BStart(wm));
// Ensure that the overflow rect contains the child textframe's
// overflow rect.
// Note that if this is floating, the overline/underline drawable
// area is in the overflow rect of the child textframe.
aMetrics.UnionOverflowAreasWithDesiredBounds();
ConsiderChildOverflow(aMetrics.mOverflowAreas, kid);
FinishAndStoreOverflow(&aMetrics);
}
else {
// Pretend we are a span and reflow the child frame
@ -247,12 +256,6 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
nsLayoutUtils::SetBSizeFromFontMetrics(this, aMetrics, bp, lineWM, wm);
}
// Ensure that the overflow rect contains the child textframe's overflow rect.
// Note that if this is floating, the overline/underline drawable area is in
// the overflow rect of the child textframe.
aMetrics.UnionOverflowAreasWithDesiredBounds();
ConsiderChildOverflow(aMetrics.mOverflowAreas, kid);
if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
// Create a continuation or remove existing continuations based on
// the reflow completion status.
@ -287,8 +290,6 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
}
}
FinishAndStoreOverflow(&aMetrics);
NS_FRAME_SET_TRUNCATION(aReflowStatus, aReflowState, aMetrics);
}

View File

@ -916,7 +916,7 @@ fuzzy-if(Android&&AndroidVersion>=15,8,50) == 404553-1.html 404553-1-ref.html #
== 407016-1-b.html 407016-1-ref.html
== 407078-1.html 407078-1-ref.html
== 407095-1.html 407095-1-ref.html
== 407111-1.html 407111-1-ref.html
fuzzy-if(Android,13,9) == 407111-1.html 407111-1-ref.html # Bug 1128229
== 407227-1.html 407227-1-ref.html
== 407243-1.html 407243-1-ref.html
== 407419-1.html 407419-1-ref.html

View File

@ -0,0 +1,14 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 8em; width: 5em;
padding: 3px;
background: yellow; color: black;
line-height: 1.0;
}
div::first-letter { font-size: 1.2em; float: left; }
</style>
<div>Hello world, testing, testing, testing, testing</div>

View File

@ -0,0 +1,15 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 8em; width: 5em;
padding: 3px;
background: yellow; color: black;
overflow: auto;
line-height: 1.0;
}
div::first-letter { font-size: 1.2em; float: left; }
</style>
<div>Hello world, testing, testing, testing, testing</div>

View File

@ -0,0 +1,14 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 3em; width: 8em;
padding: 3px;
background: yellow; color: black;
line-height: 1.0;
}
div::first-letter { font-size: 4em; float: left; }
</style>
<div>Hello</div>

View File

@ -0,0 +1,15 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 3em; width: 8em;
padding: 3px;
background: yellow; color: black;
overflow: auto;
line-height: 1.0;
}
div::first-letter { font-size: 4em; float: left; }
</style>
<div>Hello</div>

View File

@ -0,0 +1,14 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 8em; width: 5em;
padding: 3px;
background: yellow; color: black;
line-height: 1.0;
}
div::first-letter { font-size: 1.2em }
</style>
<div>Hello world, testing, testing, testing, testing</div>

View File

@ -0,0 +1,15 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 8em; width: 5em;
padding: 3px;
background: yellow; color: black;
overflow: auto;
line-height: 1.0;
}
div::first-letter { font-size: 1.2em }
</style>
<div>Hello world, testing, testing, testing, testing</div>

View File

@ -0,0 +1,14 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 3em; width: 8em;
padding: 3px;
background: yellow; color: black;
line-height: 1.0;
}
div::first-letter { font-size: 4em }
</style>
<div>Hello</div>

View File

@ -0,0 +1,15 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 3em; width: 8em;
padding: 3px;
background: yellow; color: black;
overflow: auto;
line-height: 1.0;
}
span { font-size: 4em }
</style>
<div><span>H</span>ello</div>

View File

@ -0,0 +1,15 @@
<title>::first-letter and overflow</title>
<style>
div {
height: 3em; width: 8em;
padding: 3px;
background: yellow; color: black;
overflow: auto;
line-height: 1.0;
}
div::first-letter { font-size: 4em }
</style>
<div>Hello</div>

View File

@ -67,3 +67,8 @@ fails-if(winWidget||cocoaWidget) == 617869-1.html 617869-1-ref.html
fails-if(gtk2Widget) random-if(winWidget&&!d2d) == font-text-styles-floater.html font-text-styles-floater-ref.html # bug 992846
== inline-height-empty.html inline-height-empty-ref.html
HTTP(..) == indic-clusters-1.html indic-clusters-1-ref.html
== overflow-float-nooverflow.html overflow-float-nooverflow-ref.html
== overflow-float-overflow.html overflow-float-overflow-notref.html
== overflow-inline-nooverflow.html overflow-inline-nooverflow-ref.html
!= overflow-inline-overflow.html overflow-inline-overflow-notref.html
== overflow-inline-overflow.html overflow-inline-overflow-ref.html

View File

@ -1,6 +1,6 @@
skip-if(B2G) == ellipsis-font-fallback.html ellipsis-font-fallback-ref.html
== line-clipping.html line-clipping-ref.html
skip-if(B2G) HTTP(..) == marker-basic.html marker-basic-ref.html
fuzzy-if(Android,16,244) skip-if(B2G) HTTP(..) == marker-basic.html marker-basic-ref.html # Bug 1128229
skip-if(B2G) HTTP(..) == marker-string.html marker-string-ref.html
skip-if(Android||B2G) HTTP(..) == bidi-simple.html bidi-simple-ref.html # Fails on Android due to anti-aliasing
skip-if(!gtk2Widget) fuzzy-if(gtk2Widget,1,104) HTTP(..) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing

Some files were not shown because too many files have changed in this diff Show More