This commit is contained in:
Ryan VanderMeulen 2014-06-10 00:45:12 -04:00
Родитель 1c967fe3ae d5156342b6
Коммит 028ca01a20
121 изменённых файлов: 2231 добавлений и 898 удалений

Просмотреть файл

@ -272,7 +272,14 @@ Target.prototype = {
},
_send: function target_send(data) {
shell.sendEvent(this.frame, 'developer-hud-update', Cu.cloneInto(data, this.frame));
let frame = this.frame;
let systemapp = document.querySelector('#systemapp');
if (this.frame === systemapp) {
frame = getContentWindow();
}
shell.sendEvent(frame, 'developer-hud-update', Cu.cloneInto(data, frame));
}
};

Просмотреть файл

@ -350,9 +350,7 @@ public:
// nsWrapperCache
virtual JSObject *WrapObject(JSContext *cx) MOZ_OVERRIDE
{
NS_ASSERTION(IsOuterWindow(),
"Inner window supports nsWrapperCache, fix WrapObject!");
return EnsureInnerWindow() ? GetWrapper() : nullptr;
return IsInnerWindow() || EnsureInnerWindow() ? GetWrapper() : nullptr;
}
// nsIGlobalJSObjectHolder

Просмотреть файл

@ -45,14 +45,13 @@
#include "MediaEngineDefault.h"
#if defined(MOZ_WEBRTC)
#include "MediaEngineWebRTC.h"
#include "browser_logging/WebRtcLog.h"
#endif
#ifdef MOZ_B2G
#include "MediaPermissionGonk.h"
#endif
#include "browser_logging/WebRtcLog.h"
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
// GetTickCount() and conflicts with MediaStream::GetCurrentTime.
#ifdef GetCurrentTime
@ -1577,7 +1576,9 @@ MediaManager::GetUserMedia(bool aPrivileged,
obs->NotifyObservers(req, "getUserMedia:request", nullptr);
}
#ifdef MOZ_WEBRTC
EnableWebRtcLog();
#endif
return NS_OK;
}

Просмотреть файл

@ -1 +1 @@
skip load 408431-1.html # bug 1022509 - renable when the cause of that is backed out
load 408431-1.html

Просмотреть файл

@ -9,19 +9,27 @@ const Ci = Components.interfaces;
const Cc = Components.classes;
const POSITION_UNAVAILABLE = Ci.nsIDOMGeoPositionError.POSITION_UNAVAILABLE;
const SETTING_DEBUG_ENABLED = "geolocation.debugging.enabled";
const SETTING_CHANGED_TOPIC = "mozsettings-changed";
const SETTINGS_DEBUG_ENABLED = "geolocation.debugging.enabled";
const SETTINGS_CHANGED_TOPIC = "mozsettings-changed";
const SETTINGS_WIFI_ENABLED = "wifi.enabled";
let gLoggingEnabled = false;
// if we don't see any wifi responses in 5 seconds, send the request.
let gTimeToWaitBeforeSending = 5000; //ms
/*
The gLocationRequestTimeout controls how long we wait on receiving an update
from the Wifi subsystem. If this timer fires, we believe the Wifi scan has
had a problem and we no longer can use Wifi to position the user this time
around (we will continue to be hopeful that Wifi will recover).
This timeout value is also used when Wifi scanning is disabled (see
gWifiScanningEnabled). In this case, we use this timer to collect cell/ip
data and xhr it to the location server.
*/
let gLocationRequestTimeout = 5000;
let gWifiScanningEnabled = true;
let gWifiResults;
let gCellScanningEnabled = false;
let gCellResults;
function LOG(aMsg) {
if (gLoggingEnabled) {
@ -59,7 +67,7 @@ function WifiGeoPositionProvider() {
} catch (e) {}
try {
gTimeToWaitBeforeSending = Services.prefs.getIntPref("geo.wifi.timeToWaitBeforeSending");
gLocationRequestTimeout = Services.prefs.getIntPref("geo.wifi.timeToWaitBeforeSending");
} catch (e) {}
try {
@ -71,7 +79,7 @@ function WifiGeoPositionProvider() {
} catch (e) {}
this.wifiService = null;
this.timeoutTimer = null;
this.timer = null;
this.started = false;
}
@ -84,28 +92,53 @@ WifiGeoPositionProvider.prototype = {
listener: null,
observe: function(aSubject, aTopic, aData) {
if (aTopic != SETTING_CHANGED_TOPIC) {
if (aTopic != SETTINGS_CHANGED_TOPIC) {
return;
}
try {
let setting = JSON.parse(aData);
if (setting.key != SETTING_DEBUG_ENABLED) {
return;
if (setting.key == SETTINGS_DEBUG_ENABLED) {
gLoggingEnabled = setting.value;
} else if (setting.key == SETTINGS_WIFI_ENABLED) {
gWifiScanningEnabled = setting.value;
}
gLoggingEnabled = setting.value;
} catch (e) {
}
},
resetTimer: function() {
if (this.timer) {
this.timer.cancel();
this.timer = null;
}
// wifi thread triggers WifiGeoPositionProvider to proceed, with no wifi, do manual timeout
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this.timer.initWithCallback(this,
gLocationRequestTimeout,
this.timer.TYPE_REPEATING_SLACK);
},
startup: function() {
if (this.started)
return;
this.started = true;
let self = this;
let settingsCallback = {
handle: function(name, result) {
gLoggingEnabled = result && result.value === true ? true : false;
if (name == SETTINGS_DEBUG_ENABLED) {
gLoggingEnabled = result;
} else if (name == SETTINGS_WIFI_ENABLED) {
gWifiScanningEnabled = result;
if (self.wifiService) {
self.wifiService.stopWatching(self);
}
if (gWifiScanningEnabled) {
self.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Ci.nsIWifiMonitor);
self.wifiService.startWatching(self);
}
}
},
handleError: function(message) {
@ -115,21 +148,23 @@ WifiGeoPositionProvider.prototype = {
};
try {
Services.obs.addObserver(this, SETTING_CHANGED_TOPIC, false);
Services.obs.addObserver(this, SETTINGS_CHANGED_TOPIC, false);
let settings = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
settings.createLock().get(SETTING_DEBUG_ENABLED, settingsCallback);
settings.createLock().get(SETTINGS_WIFI_ENABLED, settingsCallback);
settings.createLock().get(SETTINGS_DEBUG_ENABLED, settingsCallback);
} catch(ex) {
// This platform doesn't have the settings interface, and that is just peachy
}
if (gWifiScanningEnabled && Cc["@mozilla.org/wifi/monitor;1"]) {
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
if (this.wifiService) {
this.wifiService.stopWatching(this);
}
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Ci.nsIWifiMonitor);
this.wifiService.startWatching(this);
}
this.timeoutTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this.timeoutTimer.initWithCallback(this,
gTimeToWaitBeforeSending,
this.timeoutTimer.TYPE_REPEATING_SLACK);
this.resetTimer();
LOG("startup called.");
},
@ -143,9 +178,9 @@ WifiGeoPositionProvider.prototype = {
return;
}
if (this.timeoutTimer) {
this.timeoutTimer.cancel();
this.timeoutTimer = null;
if (this.timer) {
this.timer.cancel();
this.timer = null;
}
if(this.wifiService) {
@ -153,7 +188,7 @@ WifiGeoPositionProvider.prototype = {
this.wifiService = null;
}
Services.obs.removeObserver(this, SETTING_CHANGED_TOPIC);
Services.obs.removeObserver(this, SETTINGS_CHANGED_TOPIC);
this.listener = null;
this.started = false;
@ -164,6 +199,9 @@ WifiGeoPositionProvider.prototype = {
onChange: function(accessPoints) {
// we got some wifi data, rearm the timer.
this.resetTimer();
function isPublic(ap) {
let mask = "_nomap"
let result = ap.ssid.indexOf(mask, ap.ssid.length - mask.length);
@ -181,18 +219,19 @@ WifiGeoPositionProvider.prototype = {
return { 'macAddress': ap.mac, 'signalStrength': ap.signal };
};
let wifiData = null;
if (accessPoints) {
gWifiResults = accessPoints.filter(isPublic).sort(sort).map(encode);
} else {
gWifiResults = null;
wifiData = accessPoints.filter(isPublic).sort(sort).map(encode);
}
this.sendLocationRequest(wifiData);
},
onError: function (code) {
LOG("wifi error: " + code);
this.sendLocationRequest(null);
},
updateMobileInfo: function() {
getMobileInfo: function() {
LOG("updateMobileInfo called");
try {
let radioService = Cc["@mozilla.org/ril;1"]
@ -216,11 +255,15 @@ WifiGeoPositionProvider.prototype = {
}
return result;
} catch (e) {
gCellResults = null;
return null;
}
},
notify: function (timeoutTimer) {
notify: function (timer) {
this.sendLocationRequest(null);
},
sendLocationRequest: function (wifiData) {
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
let listener = this.listener;
LOG("Sending request: " + url + "\n");
@ -258,19 +301,19 @@ WifiGeoPositionProvider.prototype = {
listener.update(newLocation);
};
if (gCellScanningEnabled) {
this.updateMobileInfo();
let data = {};
if (wifiData) {
data.wifiAccessPoints = wifiData;
}
let data = {};
if (gWifiResults) {
data.wifiAccessPoints = gWifiResults;
}
if (gCellResults) {
data.cellTowers = gCellResults;
if (gCellScanningEnabled) {
let cellData = this.getMobileInfo();
if (cellData) {
data.cellTowers = cellData;
}
}
data = JSON.stringify(data);
gWifiResults = gCellResults = null;
LOG("sending " + data);
xhr.send(data);
},

Просмотреть файл

@ -703,10 +703,11 @@ GonkGPSGeolocationProvider::NetworkLocationUpdate::Update(nsIDOMGeoPosition *pos
// assume the MLS coord is unchanged, and stick with the GPS location
const double kMinMLSCoordChangeInMeters = 10;
// if we haven't seen anything from the GPS device for 1s,
// if we haven't seen anything from the GPS device for 10s,
// use this network derived location.
const int kMaxGPSDelayBeforeConsideringMLS = 10000;
int64_t diff = PR_Now() - provider->mLastGPSDerivedLocationTime;
if (provider->mLocationCallback && diff > kDefaultPeriod
if (provider->mLocationCallback && diff > kMaxGPSDelayBeforeConsideringMLS
&& delta > kMinMLSCoordChangeInMeters)
{
provider->mLocationCallback->Update(position);

Просмотреть файл

@ -118,6 +118,7 @@ AppendToString(nsACString& s, const FrameMetrics& m,
{
s += pfx;
AppendToString(s, m.mViewport, "{ viewport=");
AppendToString(s, m.mCompositionBounds, " cb=");
AppendToString(s, m.GetScrollOffset(), " viewportScroll=");
AppendToString(s, m.mDisplayPort, " displayport=");
AppendToString(s, m.mCriticalDisplayPort, " critdp=");

Просмотреть файл

@ -16,7 +16,6 @@
#include "nsRegion.h" // for nsIntRegion
#include "nscore.h" // for nsACString, etc
class gfx3DMatrix;
struct gfxRGBA;
struct nsIntPoint;
struct nsIntRect;
@ -46,10 +45,6 @@ nsACString&
AppendToString(nsACString& s, const gfxRGBA& c,
const char* pfx="", const char* sfx="");
nsACString&
AppendToString(nsACString& s, const gfx3DMatrix& m,
const char* pfx="", const char* sfx="");
nsACString&
AppendToString(nsACString& s, const nsIntPoint& p,
const char* pfx="", const char* sfx="");
@ -80,6 +75,18 @@ AppendToString(nsACString& s, const mozilla::gfx::RectTyped<T>& r,
return s += sfx;
}
template<class T>
nsACString&
AppendToString(nsACString& s, const mozilla::gfx::IntRectTyped<T>& r,
const char* pfx="", const char* sfx="")
{
s += pfx;
s.AppendPrintf(
"(x=%d, y=%d, w=%d, h=%d)",
r.x, r.y, r.width, r.height);
return s += sfx;
}
nsACString&
AppendToString(nsACString& s, const nsIntRegion& r,
const char* pfx="", const char* sfx="");

Просмотреть файл

@ -17,6 +17,7 @@
#include "nsRect.h" // for nsIntRect
#include "nsRegion.h" // for nsIntRegion
#include "nsTArray.h" // for nsTArray
#include "prlog.h" // for PR_LOG
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
#include <ui/Fence.h>
@ -25,6 +26,24 @@
namespace mozilla {
namespace layers {
// To get this logging, you need PR logging enabled (either by
// doing a debug build, or #define'ing FORCE_PR_LOG at the top
// of a .cpp file), and then run with NSPR_LOG_MODULES=tiling:5
// in your environment at runtime.
#ifdef PR_LOGGING
# define TILING_PRLOG(_args) PR_LOG(gTilingLog, PR_LOG_DEBUG, _args)
# define TILING_PRLOG_OBJ(_args, obj) \
{ \
nsAutoCString tmpstr; \
AppendToString(tmpstr, obj); \
PR_LOG(gTilingLog, PR_LOG_DEBUG, _args); \
}
extern PRLogModuleInfo* gTilingLog;
#else
# define TILING_PRLOG(_args)
# define TILING_PRLOG_OBJ(_args, obj)
#endif
// An abstract implementation of a tile buffer. This code covers the logic of
// moving and reusing tiles and leaves the validation up to the implementor. To
// avoid the overhead of virtual dispatch, we employ the curiously recurring

Просмотреть файл

@ -9,6 +9,7 @@
#include "CrossProcessMutex.h"
#include "mozilla/layers/GeckoContentController.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "mozilla/Monitor.h"
@ -38,7 +39,6 @@ class GestureEventListener;
class ContainerLayer;
class PCompositorParent;
class ViewTransform;
class APZCTreeManager;
class AsyncPanZoomAnimation;
class FlingAnimation;

Просмотреть файл

@ -28,6 +28,8 @@
namespace mozilla {
namespace layers {
PRLogModuleInfo* gTilingLog;
using namespace mozilla::gfx;
void
@ -143,6 +145,9 @@ ClientLayerManager::CreateThebesLayerWithHint(ThebesLayerCreationHint aHint)
(AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL ||
AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9 ||
AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D11)) {
if (!gTilingLog) {
gTilingLog = PR_NewLogModule("tiling");
}
if (gfxPrefs::LayersUseSimpleTiles()) {
nsRefPtr<SimpleClientTiledThebesLayer> layer =
new SimpleClientTiledThebesLayer(this);

Просмотреть файл

@ -2,6 +2,11 @@
* 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/. */
// Uncomment this to enable the TILING_PRLOG stuff in this file
// for release builds. To get the output you need to have
// NSPR_LOG_MODULES=tiling:5 in your environment at runtime.
// #define FORCE_PR_LOG
#include "ClientTiledThebesLayer.h"
#include "FrameMetrics.h" // for FrameMetrics
#include "Units.h" // for ScreenIntRect, CSSPoint, etc
@ -18,6 +23,7 @@
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
#include "nsRect.h" // for nsIntRect
#include "LayersLogging.h"
namespace mozilla {
namespace layers {
@ -52,10 +58,10 @@ ClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
aAttrs = ThebesLayerAttributes(GetValidRegion());
}
static LayoutDeviceRect
ApplyParentLayerToLayoutTransform(const gfx3DMatrix& aTransform, const ParentLayerRect& aParentLayerRect)
static LayerRect
ApplyParentLayerToLayerTransform(const gfx3DMatrix& aTransform, const ParentLayerRect& aParentLayerRect)
{
return TransformTo<LayoutDevicePixel>(aTransform, aParentLayerRect);
return TransformTo<LayerPixel>(aTransform, aParentLayerRect);
}
static gfx3DMatrix
@ -64,6 +70,12 @@ GetTransformToAncestorsParentLayer(Layer* aStart, Layer* aAncestor)
gfx::Matrix4x4 transform;
Layer* ancestorParent = aAncestor->GetParent();
for (Layer* iter = aStart; iter != ancestorParent; iter = iter->GetParent()) {
if (iter->AsContainerLayer()) {
// If the layer has a non-transient async transform then we need to apply it here
// because it will get applied by the APZ in the compositor as well
const FrameMetrics& metrics = iter->AsContainerLayer()->GetFrameMetrics();
transform = transform * gfx::Matrix4x4().Scale(metrics.mResolution.scale, metrics.mResolution.scale, 1.f);
}
transform = transform * iter->GetTransform();
}
gfx3DMatrix ret;
@ -117,49 +129,58 @@ ClientTiledThebesLayer::BeginPaint()
return;
}
TILING_PRLOG(("TILING 0x%p: Found scrollAncestor 0x%p and displayPortAncestor 0x%p\n", this,
scrollAncestor, displayPortAncestor));
const FrameMetrics& scrollMetrics = scrollAncestor->GetFrameMetrics();
const FrameMetrics& displayportMetrics = displayPortAncestor->GetFrameMetrics();
// Calculate the transform required to convert ParentLayer space of our
// display port ancestor to the LayoutDevice space of this layer.
gfx3DMatrix layoutDeviceToDisplayPort =
// display port ancestor to the Layer space of this layer.
gfx3DMatrix transformToDisplayPort =
GetTransformToAncestorsParentLayer(this, displayPortAncestor);
layoutDeviceToDisplayPort.ScalePost(scrollMetrics.mCumulativeResolution.scale,
scrollMetrics.mCumulativeResolution.scale,
1.f);
mPaintData.mTransformDisplayPortToLayoutDevice = layoutDeviceToDisplayPort.Inverse();
mPaintData.mTransformDisplayPortToLayer = transformToDisplayPort.Inverse();
// Note that below we use GetZoomToParent() in a number of places. Because this
// code runs on the client side, the mTransformScale field of the FrameMetrics
// will not have been set. This can result in incorrect values being returned
// by GetZoomToParent() when we have CSS transforms set on some of these layers.
// This code should be audited and updated as part of fixing bug 993525.
// Compute the critical display port that applies to this layer in the
// LayoutDevice space of this layer.
ParentLayerRect criticalDisplayPort =
(displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoomToParent())
+ displayportMetrics.mCompositionBounds.TopLeft();
mPaintData.mCriticalDisplayPort = LayoutDeviceIntRect::ToUntyped(RoundedOut(
ApplyParentLayerToLayoutTransform(mPaintData.mTransformDisplayPortToLayoutDevice,
criticalDisplayPort)));
mPaintData.mCriticalDisplayPort = RoundedOut(
ApplyParentLayerToLayerTransform(mPaintData.mTransformDisplayPortToLayer, criticalDisplayPort));
TILING_PRLOG_OBJ(("TILING 0x%p: Critical displayport %s\n", this, tmpstr.get()), mPaintData.mCriticalDisplayPort);
// Compute the viewport that applies to this layer in the LayoutDevice
// space of this layer.
ParentLayerRect viewport =
(displayportMetrics.mViewport * displayportMetrics.GetZoomToParent())
+ displayportMetrics.mCompositionBounds.TopLeft();
mPaintData.mViewport = ApplyParentLayerToLayoutTransform(
mPaintData.mTransformDisplayPortToLayoutDevice, viewport);
mPaintData.mViewport = ApplyParentLayerToLayerTransform(
mPaintData.mTransformDisplayPortToLayer, viewport);
TILING_PRLOG_OBJ(("TILING 0x%p: Viewport %s\n", this, tmpstr.get()), mPaintData.mViewport);
// Store the resolution from the displayport ancestor layer. Because this is Gecko-side,
// before any async transforms have occurred, we can use the zoom for this.
mPaintData.mResolution = displayportMetrics.GetZoomToParent();
TILING_PRLOG(("TILING 0x%p: Resolution %f\n", this, mPaintData.mResolution.scale));
// Store the applicable composition bounds in this layer's LayoutDevice units.
gfx3DMatrix layoutDeviceToCompBounds =
// Store the applicable composition bounds in this layer's Layer units.
gfx3DMatrix transformToCompBounds =
GetTransformToAncestorsParentLayer(this, scrollAncestor);
mPaintData.mCompositionBounds = TransformTo<LayoutDevicePixel>(
layoutDeviceToCompBounds.Inverse(),
scrollMetrics.mCompositionBounds / scrollMetrics.GetParentResolution());
mPaintData.mCompositionBounds = ApplyParentLayerToLayerTransform(
transformToCompBounds.Inverse(), ParentLayerRect(scrollMetrics.mCompositionBounds));
TILING_PRLOG_OBJ(("TILING 0x%p: Composition bounds %s\n", this, tmpstr.get()), mPaintData.mCompositionBounds);
// Calculate the scroll offset since the last transaction
mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent();
TILING_PRLOG_OBJ(("TILING 0x%p: Scroll offset %s\n", this, tmpstr.get()), mPaintData.mScrollOffset);
}
void
@ -172,6 +193,7 @@ ClientTiledThebesLayer::EndPaint(bool aFinish)
mPaintData.mLastScrollOffset = mPaintData.mScrollOffset;
mPaintData.mPaintFinished = true;
mPaintData.mFirstPaint = false;
TILING_PRLOG(("TILING 0x%p: Paint finished\n", this));
}
void
@ -197,6 +219,9 @@ ClientTiledThebesLayer::RenderLayer()
mValidRegion = nsIntRegion();
}
TILING_PRLOG_OBJ(("TILING 0x%p: Initial visible region %s\n", this, tmpstr.get()), mVisibleRegion);
TILING_PRLOG_OBJ(("TILING 0x%p: Initial valid region %s\n", this, tmpstr.get()), mValidRegion);
nsIntRegion invalidRegion = mVisibleRegion;
invalidRegion.Sub(invalidRegion, mValidRegion);
if (invalidRegion.IsEmpty()) {
@ -239,6 +264,9 @@ ClientTiledThebesLayer::RenderLayer()
return;
}
TILING_PRLOG_OBJ(("TILING 0x%p: Valid region %s\n", this, tmpstr.get()), mValidRegion);
TILING_PRLOG_OBJ(("TILING 0x%p: Visible region %s\n", this, tmpstr.get()), mVisibleRegion);
// Make sure that tiles that fall outside of the visible region are
// discarded on the first update.
if (!ClientManager()->IsRepeatTransaction()) {
@ -246,7 +274,7 @@ ClientTiledThebesLayer::RenderLayer()
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
// Make sure that tiles that fall outside of the critical displayport are
// discarded on the first update.
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
}
}
@ -262,13 +290,15 @@ ClientTiledThebesLayer::RenderLayer()
}
// Clip the invalid region to the critical display-port
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort);
invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
EndPaint(true);
return;
}
}
TILING_PRLOG_OBJ(("TILING 0x%p: Invalid region %s\n", this, tmpstr.get()), invalidRegion);
if (!invalidRegion.IsEmpty() && mPaintData.mLowPrecisionPaintCount == 0) {
bool updatedBuffer = false;
// Only draw progressively when the resolution is unchanged.
@ -281,9 +311,11 @@ ClientTiledThebesLayer::RenderLayer()
nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
oldValidRegion.And(oldValidRegion, mVisibleRegion);
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort);
oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
}
TILING_PRLOG_OBJ(("TILING 0x%p: Progressive update with old valid region %s\n", this, tmpstr.get()), oldValidRegion);
updatedBuffer =
mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, invalidRegion,
oldValidRegion, &mPaintData,
@ -292,8 +324,12 @@ ClientTiledThebesLayer::RenderLayer()
updatedBuffer = true;
mValidRegion = mVisibleRegion;
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
}
TILING_PRLOG_OBJ(("TILING 0x%p: Painting: valid region %s\n", this, tmpstr.get()), mValidRegion);
TILING_PRLOG_OBJ(("TILING 0x%p: and invalid region %s\n", this, tmpstr.get()), invalidRegion);
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
callback, data);
@ -318,11 +354,14 @@ ClientTiledThebesLayer::RenderLayer()
}
}
TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision valid region is %s\n", this, tmpstr.get()), mLowPrecisionValidRegion);
TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision invalid region is %s\n", this, tmpstr.get()), lowPrecisionInvalidRegion);
// Render the low precision buffer, if there's area to invalidate and the
// visible region is larger than the critical display port.
bool updatedLowPrecision = false;
if (!lowPrecisionInvalidRegion.IsEmpty() &&
!nsIntRegion(mPaintData.mCriticalDisplayPort).Contains(mVisibleRegion)) {
!nsIntRegion(LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)).Contains(mVisibleRegion)) {
nsIntRegion oldValidRegion =
mContentClient->mLowPrecisionTiledBuffer.GetValidRegion();
oldValidRegion.And(oldValidRegion, mVisibleRegion);

Просмотреть файл

@ -929,6 +929,7 @@ ContentClientIncremental::GetUpdateSurface(BufferType aType,
mContentType,
&desc)) {
NS_WARNING("creating SurfaceDescriptor failed!");
Clear();
return nullptr;
}

Просмотреть файл

@ -889,29 +889,29 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
return aTile;
}
static LayoutDeviceRect
static LayerRect
TransformCompositionBounds(const ParentLayerRect& aCompositionBounds,
const CSSToParentLayerScale& aZoom,
const ParentLayerPoint& aScrollOffset,
const CSSToParentLayerScale& aResolution,
const gfx3DMatrix& aTransformDisplayPortToLayoutDevice)
const gfx3DMatrix& aTransformDisplayPortToLayer)
{
// Transform the composition bounds from the space of the displayport ancestor
// layer into the LayoutDevice space of this layer. Do this by
// layer into the Layer space of this layer. Do this by
// compensating for the difference in resolution and subtracting the
// old composition bounds origin.
ParentLayerRect offsetViewportRect = (aCompositionBounds / aZoom) * aResolution;
offsetViewportRect.MoveBy(-aScrollOffset);
gfxRect transformedViewport =
aTransformDisplayPortToLayoutDevice.TransformBounds(
aTransformDisplayPortToLayer.TransformBounds(
gfxRect(offsetViewportRect.x, offsetViewportRect.y,
offsetViewportRect.width, offsetViewportRect.height));
return LayoutDeviceRect(transformedViewport.x,
transformedViewport.y,
transformedViewport.width,
transformedViewport.height);
return LayerRect(transformedViewport.x,
transformedViewport.y,
transformedViewport.width,
transformedViewport.height);
}
bool
@ -976,26 +976,27 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
}
}
LayoutDeviceRect transformedCompositionBounds =
LayerRect transformedCompositionBounds =
TransformCompositionBounds(compositionBounds, zoom, aPaintData->mScrollOffset,
aPaintData->mResolution, aPaintData->mTransformDisplayPortToLayoutDevice);
aPaintData->mResolution, aPaintData->mTransformDisplayPortToLayer);
// Paint tiles that have stale content or that intersected with the screen
// at the time of issuing the draw command in a single transaction first.
// This is to avoid rendering glitches on animated page content, and when
// layers change size/shape.
LayoutDeviceRect typedCoherentUpdateRect =
LayerRect typedCoherentUpdateRect =
transformedCompositionBounds.Intersect(aPaintData->mCompositionBounds);
// Offset by the viewport origin, as the composition bounds are stored in
// Layer space and not LayoutDevice space.
// TODO(kats): does this make sense?
typedCoherentUpdateRect.MoveBy(aPaintData->mViewport.TopLeft());
// Convert to untyped to intersect with the invalid region.
nsIntRect roundedCoherentUpdateRect =
LayoutDeviceIntRect::ToUntyped(RoundedOut(typedCoherentUpdateRect));
nsIntRect untypedCoherentUpdateRect(LayerIntRect::ToUntyped(
RoundedOut(typedCoherentUpdateRect)));
aRegionToPaint.And(aInvalidRegion, roundedCoherentUpdateRect);
aRegionToPaint.And(aInvalidRegion, untypedCoherentUpdateRect);
aRegionToPaint.Or(aRegionToPaint, staleRegion);
bool drawingStale = !aRegionToPaint.IsEmpty();
if (!drawingStale) {
@ -1004,8 +1005,8 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
// Prioritise tiles that are currently visible on the screen.
bool paintVisible = false;
if (aRegionToPaint.Intersects(roundedCoherentUpdateRect)) {
aRegionToPaint.And(aRegionToPaint, roundedCoherentUpdateRect);
if (aRegionToPaint.Intersects(untypedCoherentUpdateRect)) {
aRegionToPaint.And(aRegionToPaint, untypedCoherentUpdateRect);
paintVisible = true;
}

Просмотреть файл

@ -255,26 +255,23 @@ struct BasicTiledLayerPaintData {
/*
* The transform matrix to go from the display port layer's ParentLayer
* units to this layer's LayoutDevice units. The "display port layer" is
* units to this layer's Layer units. The "display port layer" is
* the closest ancestor layer with a displayport.
*/
gfx3DMatrix mTransformDisplayPortToLayoutDevice;
gfx3DMatrix mTransformDisplayPortToLayer;
/*
* The critical displayport of the content from the nearest ancestor layer
* that represents scrollable content with a display port set. Empty if a
* critical displayport is not set.
*
* This is in LayoutDevice coordinates, but is stored as an nsIntRect for
* convenience when intersecting with the layer's mValidRegion.
*/
nsIntRect mCriticalDisplayPort;
LayerIntRect mCriticalDisplayPort;
/*
* The viewport of the content from the nearest ancestor layer that
* represents scrollable content with a display port set.
*/
LayoutDeviceRect mViewport;
LayerRect mViewport;
/*
* The render resolution of the document that the content this layer
@ -283,11 +280,11 @@ struct BasicTiledLayerPaintData {
CSSToParentLayerScale mResolution;
/*
* The composition bounds of the layer, in LayoutDevice coordinates. This is
* The composition bounds of the layer, in Layer coordinates. This is
* used to make sure that tiled updates to regions that are visible to the
* user are grouped coherently.
*/
LayoutDeviceRect mCompositionBounds;
LayerRect mCompositionBounds;
/*
* Low precision updates are always executed a tile at a time in repeated

Просмотреть файл

@ -406,14 +406,6 @@ ContentHostIncremental::~ContentHostIncremental()
{
}
void
ContentHostIncremental::DestroyTextures()
{
mSource = nullptr;
mSourceOnWhite = nullptr;
mUpdateList.Clear();
}
bool
ContentHostIncremental::CreatedIncrementalTexture(ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo,
@ -501,6 +493,8 @@ ContentHostIncremental::TextureCreationRequest::Execute(ContentHostIncremental*
}
if (mTextureInfo.mDeprecatedTextureHostFlags & DeprecatedTextureHostFlags::COPY_PREVIOUS) {
MOZ_ASSERT(aHost->mSource);
MOZ_ASSERT(aHost->mSource->IsValid());
nsIntRect bufferRect = aHost->mBufferRect;
nsIntPoint bufferRotation = aHost->mBufferRotation;
nsIntRect overlap;

Просмотреть файл

@ -281,8 +281,6 @@ public:
virtual void PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE;
virtual void DestroyTextures();
virtual bool Lock() {
MOZ_ASSERT(!mLocked);
ProcessTextureUpdates();

Просмотреть файл

@ -385,8 +385,11 @@ TextureImageTextureSourceOGL::GetSize() const
gfx::SurfaceFormat
TextureImageTextureSourceOGL::GetFormat() const
{
MOZ_ASSERT(mTexImage);
return mTexImage->GetTextureFormat();
if (mTexImage) {
return mTexImage->GetTextureFormat();
}
NS_WARNING("Trying to query the format of an empty TextureSource.");
return gfx::SurfaceFormat::UNKNOWN;
}
nsIntRect TextureImageTextureSourceOGL::GetTileRect()

Просмотреть файл

@ -2,9 +2,10 @@ This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
Our reference repository is https://github.com/khaledhosny/ots/.
Current revision: d7d831edd171054c7974f5e0dec2fc19bf869574
Current revision: d6018b62bf41f6b419aeae6d2795725a55715481
Applied local patches:
ots-visibility.patch - make Process function externally visible for Windows DLL (bug 711079)
Upstream files included: LICENSE, src/, include/
ots-woff2 - disable WOFF2 support (bug 941019)
Additional files: README.mozilla, src/moz.build
Additional patch: ots-visibility.patch (bug 711079).

Просмотреть файл

@ -199,16 +199,6 @@ class OTSStream {
unsigned chksum_buffer_offset_;
};
// -----------------------------------------------------------------------------
// Process a given OpenType file and write out a sanitised version
// output: a pointer to an object implementing the OTSStream interface. The
// sanitisied output will be written to this. In the even of a failure,
// partial output may have been written.
// input: the OpenType file
// length: the size, in bytes, of |input|
// -----------------------------------------------------------------------------
bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length);
// Signature of the function to be provided by the client in order to report errors.
// The return type is a boolean so that it can be used within an expression,
// but the actual value is ignored. (Suggested convention is to always return 'false'.)
@ -219,9 +209,6 @@ bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length);
#endif
typedef bool (*MessageFunc)(void *user_data, const char *format, ...) MSGFUNC_FMT_ATTR;
// Set a callback function that will be called when OTS is reporting an error.
void OTS_API SetMessageCallback(MessageFunc func, void *user_data);
enum TableAction {
TABLE_ACTION_DEFAULT, // Use OTS's default action for that table
TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it
@ -231,20 +218,56 @@ enum TableAction {
// Signature of the function to be provided by the client to decide what action
// to do for a given table.
// tag: table tag as an integer in big-endian byte order, independent of platform endianness
// user_data: user defined data that are passed to SetTableActionCallback()
typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data);
// Set a callback function that will be called when OTS needs to decide what to
// do for a font table.
void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data);
class OTS_API OTSContext {
public:
OTSContext()
: message_func(0),
message_user_data(0),
table_action_func(0),
table_action_user_data(0)
{}
~OTSContext() {}
// Process a given OpenType file and write out a sanitised version
// output: a pointer to an object implementing the OTSStream interface. The
// sanitisied output will be written to this. In the even of a failure,
// partial output may have been written.
// input: the OpenType file
// length: the size, in bytes, of |input|
// context: optional context that holds various OTS settings like user callbacks
bool Process(OTSStream *output, const uint8_t *input, size_t length);
// Set a callback function that will be called when OTS is reporting an error.
void SetMessageCallback(MessageFunc func, void *user_data) {
message_func = func;
message_user_data = user_data;
}
// Set a callback function that will be called when OTS needs to decide what to
// do for a font table.
void SetTableActionCallback(TableActionFunc func, void *user_data) {
table_action_func = func;
table_action_user_data = user_data;
}
private:
MessageFunc message_func;
void *message_user_data;
TableActionFunc table_action_func;
void *table_action_user_data;
};
// Force to disable debug output even when the library is compiled with
// -DOTS_DEBUG.
void DisableDebugOutput();
#ifdef MOZ_OTS_WOFF2
// Enable WOFF2 support(experimental).
void EnableWOFF2();
#endif
} // namespace ots

Просмотреть файл

@ -37,52 +37,22 @@ diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-san
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
@@ -182,45 +202,45 @@ class OTSStream {
// -----------------------------------------------------------------------------
// Process a given OpenType file and write out a sanitised version
// output: a pointer to an object implementing the OTSStream interface. The
// sanitisied output will be written to this. In the even of a failure,
// partial output may have been written.
// input: the OpenType file
// length: the size, in bytes, of |input|
// -----------------------------------------------------------------------------
-bool Process(OTSStream *output, const uint8_t *input, size_t length);
+bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length);
// Signature of the function to be provided by the client in order to report errors.
// The return type is a boolean so that it can be used within an expression,
// but the actual value is ignored. (Suggested convention is to always return 'false'.)
#ifdef __GCC__
#define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3)))
#else
#define MSGFUNC_FMT_ATTR
#endif
typedef bool (*MessageFunc)(void *user_data, const char *format, ...) MSGFUNC_FMT_ATTR;
// Set a callback function that will be called when OTS is reporting an error.
-void SetMessageCallback(MessageFunc func, void *user_data);
+void OTS_API SetMessageCallback(MessageFunc func, void *user_data);
enum TableAction {
TABLE_ACTION_DEFAULT, // Use OTS's default action for that table
TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it
TABLE_ACTION_PASSTHRU, // Serialize the table unchanged
TABLE_ACTION_DROP // Drop the table
@@ -197,17 +217,17 @@ enum TableAction {
};
// Signature of the function to be provided by the client to decide what action
// to do for a given table.
// tag: table tag as an integer in big-endian byte order, independent of platform endianness
// user_data: user defined data that are passed to SetTableActionCallback()
typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data);
// Set a callback function that will be called when OTS needs to decide what to
// do for a font table.
-void SetTableActionCallback(TableActionFunc func, void *user_data);
+void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data);
// Force to disable debug output even when the library is compiled with
// -DOTS_DEBUG.
void DisableDebugOutput();
// Enable WOFF2 support(experimental).
void EnableWOFF2();
-class OTSContext {
+class OTS_API OTSContext {
public:
OTSContext()
: message_func(0),
message_user_data(0),
table_action_func(0),
table_action_user_data(0)
{}

Просмотреть файл

@ -1,134 +0,0 @@
diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-sanitiser.h
--- a/gfx/ots/include/opentype-sanitiser.h
+++ b/gfx/ots/include/opentype-sanitiser.h
@@ -236,14 +236,16 @@ typedef TableAction (*TableActionFunc)(u
// Set a callback function that will be called when OTS needs to decide what to
// do for a font table.
void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data);
// Force to disable debug output even when the library is compiled with
// -DOTS_DEBUG.
void DisableDebugOutput();
+#ifdef MOZ_OTS_WOFF2
// Enable WOFF2 support(experimental).
void EnableWOFF2();
+#endif
} // namespace ots
#endif // OPENTYPE_SANITISER_H_
diff --git a/gfx/ots/src/ots.cc b/gfx/ots/src/ots.cc
--- a/gfx/ots/src/ots.cc
+++ b/gfx/ots/src/ots.cc
@@ -9,25 +9,29 @@
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <map>
#include <vector>
+#ifdef MOZ_OTS_WOFF2
#include "woff2.h"
+#endif
// The OpenType Font File
// http://www.microsoft.com/typography/otspec/cmap.htm
namespace {
bool g_debug_output = true;
+#ifdef MOZ_OTS_WOFF2
bool g_enable_woff2 = false;
+#endif
ots::MessageFunc g_message_func = NULL;
void *g_message_user_data = NULL;
ots::TableActionFunc g_table_action_func = NULL;
void *g_table_action_user_data = NULL;
// Generate a message with or without a table tag, when 'header' is the OpenTypeFile pointer
@@ -395,16 +399,17 @@ bool ProcessWOFF(ots::OpenTypeFile *head
}
if (block_end != ots::Round4(length)) {
return OTS_FAILURE_MSG_HDR("file length mismatch (trailing junk?)");
}
return ProcessGeneric(header, woff_tag, output, data, length, tables, file);
}
+#ifdef MOZ_OTS_WOFF2
bool ProcessWOFF2(ots::OpenTypeFile *header,
ots::OTSStream *output, const uint8_t *data, size_t length) {
size_t decompressed_size = ots::ComputeWOFF2FinalSize(data, length);
if (decompressed_size == 0) {
return OTS_FAILURE();
}
// decompressed font must be <= 30MB
if (decompressed_size > 30 * 1024 * 1024) {
@@ -413,16 +418,17 @@ bool ProcessWOFF2(ots::OpenTypeFile *hea
std::vector<uint8_t> decompressed_buffer(decompressed_size);
if (!ots::ConvertWOFF2ToTTF(&decompressed_buffer[0], decompressed_size,
data, length)) {
return OTS_FAILURE();
}
return ProcessTTF(header, output, &decompressed_buffer[0], decompressed_size);
}
+#endif
ots::TableAction GetTableAction(uint32_t tag) {
ots::TableAction action = ots::TABLE_ACTION_DEFAULT;
if (g_table_action_func != NULL) {
action = g_table_action_func(htonl(tag), g_table_action_user_data);
}
@@ -795,19 +801,21 @@ bool IsValidVersionTag(uint32_t tag) {
tag == Tag("true") ||
tag == Tag("typ1");
}
void DisableDebugOutput() {
g_debug_output = false;
}
+#ifdef MOZ_OTS_WOFF2
void EnableWOFF2() {
g_enable_woff2 = true;
}
+#endif
void SetMessageCallback(MessageFunc func, void *user_data) {
g_message_func = func;
g_message_user_data = user_data;
}
void SetTableActionCallback(TableActionFunc func, void *user_data) {
g_table_action_func = func;
@@ -822,20 +830,22 @@ bool Process(OTSStream *output, const ui
if (length < 4) {
return OTS_FAILURE_MSG_(&header, "file less than 4 bytes");
}
bool result;
if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
result = ProcessWOFF(&header, output, data, length);
+#ifdef MOZ_OTS_WOFF2
} else if (g_enable_woff2 &&
data[0] == 'w' && data[1] == 'O' && data[2] == 'F' &&
data[3] == '2') {
result = ProcessWOFF2(&header, output, data, length);
+#endif
} else {
result = ProcessTTF(&header, output, data, length);
}
for (unsigned i = 0; ; ++i) {
if (table_parsers[i].parse == NULL) break;
table_parsers[i].free(&header);
}

Просмотреть файл

@ -1028,3 +1028,5 @@ void ots_cff_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -360,8 +360,8 @@ bool Parse31013(ots::OpenTypeFile *file,
if (!subtable.Skip(8)) {
return OTS_FAILURE_MSG("Bad cmap subtable length");
}
uint16_t language = 0;
if (!subtable.ReadU16(&language)) {
uint32_t language = 0;
if (!subtable.ReadU32(&language)) {
return OTS_FAILURE_MSG("Can't read cmap subtable language");
}
if (language) {
@ -876,7 +876,7 @@ bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) {
// Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
// (e.g., old fonts for Mac). We don't support them.
if (!have_304 && !have_314 && !have_034) {
if (!have_304 && !have_314 && !have_034 && !have_31012 && !have_31013) {
return OTS_FAILURE();
}
@ -1005,7 +1005,7 @@ bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) {
= file->cmap->subtable_3_10_13;
const unsigned num_groups = groups.size();
if (!out->WriteU16(13) ||
!out->WriteU16(0) ||
!out->WriteU32(0) ||
!out->WriteU32(num_groups * 12 + 14) ||
!out->WriteU32(0) ||
!out->WriteU32(num_groups)) {
@ -1101,3 +1101,5 @@ void ots_cmap_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -56,3 +56,5 @@ void ots_cvt_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -50,3 +50,5 @@ void ots_fpgm_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -110,3 +110,6 @@ void ots_gasp_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -384,3 +384,5 @@ void ots_gdef_free(OpenTypeFile *file) {
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -307,3 +307,5 @@ void ots_glyf_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -757,36 +757,48 @@ bool ots_gpos_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
DROP_THIS_TABLE("Bad version");
return true;
}
if ((offset_script_list < kGposHeaderSize ||
offset_script_list >= length) ||
(offset_feature_list < kGposHeaderSize ||
offset_feature_list >= length) ||
(offset_lookup_list < kGposHeaderSize ||
offset_lookup_list >= length)) {
DROP_THIS_TABLE("Bad offset in table header");
return true;
}
if (!ParseLookupListTable(file, data + offset_lookup_list,
length - offset_lookup_list,
&kGposLookupSubtableParser,
&gpos->num_lookups)) {
DROP_THIS_TABLE("Failed to parse lookup list table");
return true;
if (offset_lookup_list) {
if (offset_lookup_list < kGposHeaderSize || offset_lookup_list >= length) {
DROP_THIS_TABLE("Bad lookup list offset in table header");
return true;
}
if (!ParseLookupListTable(file, data + offset_lookup_list,
length - offset_lookup_list,
&kGposLookupSubtableParser,
&gpos->num_lookups)) {
DROP_THIS_TABLE("Failed to parse lookup list table");
return true;
}
}
uint16_t num_features = 0;
if (!ParseFeatureListTable(file, data + offset_feature_list,
length - offset_feature_list, gpos->num_lookups,
&num_features)) {
DROP_THIS_TABLE("Failed to parse feature list table");
return true;
if (offset_feature_list) {
if (offset_feature_list < kGposHeaderSize || offset_feature_list >= length) {
DROP_THIS_TABLE("Bad feature list offset in table header");
return true;
}
if (!ParseFeatureListTable(file, data + offset_feature_list,
length - offset_feature_list, gpos->num_lookups,
&num_features)) {
DROP_THIS_TABLE("Failed to parse feature list table");
return true;
}
}
if (!ParseScriptListTable(file, data + offset_script_list,
length - offset_script_list, num_features)) {
DROP_THIS_TABLE("Failed to parse script list table");
return true;
if (offset_script_list) {
if (offset_script_list < kGposHeaderSize || offset_script_list >= length) {
DROP_THIS_TABLE("Bad script list offset in table header");
return true;
}
if (!ParseScriptListTable(file, data + offset_script_list,
length - offset_script_list, num_features)) {
DROP_THIS_TABLE("Failed to parse script list table");
return true;
}
}
gpos->data = data;
@ -812,3 +824,5 @@ void ots_gpos_free(OpenTypeFile *file) {
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -614,36 +614,48 @@ bool ots_gsub_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
DROP_THIS_TABLE("Bad version");
return true;
}
if ((offset_script_list < kGsubHeaderSize ||
offset_script_list >= length) ||
(offset_feature_list < kGsubHeaderSize ||
offset_feature_list >= length) ||
(offset_lookup_list < kGsubHeaderSize ||
offset_lookup_list >= length)) {
DROP_THIS_TABLE("Bad offset in table header");
return true;
}
if (!ParseLookupListTable(file, data + offset_lookup_list,
length - offset_lookup_list,
&kGsubLookupSubtableParser,
&gsub->num_lookups)) {
DROP_THIS_TABLE("Failed to parse lookup list table");
return true;
if (offset_lookup_list) {
if (offset_lookup_list < kGsubHeaderSize || offset_lookup_list >= length) {
DROP_THIS_TABLE("Bad lookup list offset in table header");
return true;
}
if (!ParseLookupListTable(file, data + offset_lookup_list,
length - offset_lookup_list,
&kGsubLookupSubtableParser,
&gsub->num_lookups)) {
DROP_THIS_TABLE("Failed to parse lookup list table");
return true;
}
}
uint16_t num_features = 0;
if (!ParseFeatureListTable(file, data + offset_feature_list,
length - offset_feature_list, gsub->num_lookups,
&num_features)) {
DROP_THIS_TABLE("Failed to parse feature list table");
return true;
if (offset_feature_list) {
if (offset_feature_list < kGsubHeaderSize || offset_feature_list >= length) {
DROP_THIS_TABLE("Bad feature list offset in table header");
return true;
}
if (!ParseFeatureListTable(file, data + offset_feature_list,
length - offset_feature_list, gsub->num_lookups,
&num_features)) {
DROP_THIS_TABLE("Failed to parse feature list table");
return true;
}
}
if (!ParseScriptListTable(file, data + offset_script_list,
length - offset_script_list, num_features)) {
DROP_THIS_TABLE("Failed to parse script list table");
return true;
if (offset_script_list) {
if (offset_script_list < kGsubHeaderSize || offset_script_list >= length) {
DROP_THIS_TABLE("Bad script list offset in table header");
return true;
}
if (!ParseScriptListTable(file, data + offset_script_list,
length - offset_script_list, num_features)) {
DROP_THIS_TABLE("Failed to parse script list table");
return true;
}
}
gsub->data = data;
@ -669,3 +681,5 @@ void ots_gsub_free(OpenTypeFile *file) {
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -138,3 +138,6 @@ void ots_hdmx_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -149,3 +149,5 @@ void ots_head_free(OpenTypeFile *file) {
}
} // namespace
#undef TABLE_NAME

Просмотреть файл

@ -49,3 +49,5 @@ void ots_hhea_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -47,3 +47,5 @@ void ots_hmtx_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -200,3 +200,6 @@ void ots_kern_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -1510,3 +1510,4 @@ bool ParseExtensionSubtable(const OpenTypeFile *file,
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -98,3 +98,5 @@ void ots_loca_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -86,3 +86,6 @@ void ots_ltsh_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -606,3 +606,5 @@ void ots_math_free(OpenTypeFile *file) {
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -128,3 +128,5 @@ void ots_maxp_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -184,3 +184,4 @@ bool SerialiseMetricsTable(const ots::OpenTypeFile *file,
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -60,3 +60,6 @@ DEFINES['NOMINMAX'] = True
if CONFIG['OS_TARGET'] == 'WINNT':
DEFINES['OTS_DLL'] = True
DEFINES['OTS_DLL_EXPORTS'] = True
# Disable WOFF2 support.
DEFINES['OTS_DISABLE_WOFF2'] = True;

Просмотреть файл

@ -332,3 +332,5 @@ void ots_name_free(OpenTypeFile* file) {
}
} // namespace
#undef TABLE_NAME

Просмотреть файл

@ -290,3 +290,5 @@ void ots_os2_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -14,7 +14,7 @@
#include <map>
#include <vector>
#ifdef MOZ_OTS_WOFF2
#ifndef OTS_DISABLE_WOFF2
#include "woff2.h"
#endif
@ -24,15 +24,7 @@
namespace {
bool g_debug_output = true;
#ifdef MOZ_OTS_WOFF2
bool g_enable_woff2 = false;
#endif
ots::MessageFunc g_message_func = NULL;
void *g_message_user_data = NULL;
ots::TableActionFunc g_table_action_func = NULL;
void *g_table_action_user_data = NULL;
// Generate a message with or without a table tag, when 'header' is the OpenTypeFile pointer
#define OTS_FAILURE_MSG_TAG(msg_,tag_) OTS_FAILURE_MSG_TAG_(header, msg_, tag_)
@ -404,7 +396,7 @@ bool ProcessWOFF(ots::OpenTypeFile *header,
return ProcessGeneric(header, woff_tag, output, data, length, tables, file);
}
#ifdef MOZ_OTS_WOFF2
#ifndef OTS_DISABLE_WOFF2
bool ProcessWOFF2(ots::OpenTypeFile *header,
ots::OTSStream *output, const uint8_t *data, size_t length) {
size_t decompressed_size = ots::ComputeWOFF2FinalSize(data, length);
@ -425,11 +417,11 @@ bool ProcessWOFF2(ots::OpenTypeFile *header,
}
#endif
ots::TableAction GetTableAction(uint32_t tag) {
ots::TableAction GetTableAction(ots::OpenTypeFile *header, uint32_t tag) {
ots::TableAction action = ots::TABLE_ACTION_DEFAULT;
if (g_table_action_func != NULL) {
action = g_table_action_func(htonl(tag), g_table_action_user_data);
if (header->table_action_func != NULL) {
action = header->table_action_func(htonl(tag), header->table_action_user_data);
}
if (action == ots::TABLE_ACTION_DEFAULT) {
@ -578,10 +570,10 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
for (unsigned i = 0; ; ++i) {
if (table_parsers[i].parse == NULL) break;
const std::map<uint32_t, OpenTypeTable>::const_iterator it
= table_map.find(Tag(table_parsers[i].tag));
uint32_t tag = Tag(table_parsers[i].tag);
const std::map<uint32_t, OpenTypeTable>::const_iterator it = table_map.find(tag);
ots::TableAction action = GetTableAction(Tag(table_parsers[i].tag));
ots::TableAction action = GetTableAction(header, tag);
if (it == table_map.end()) {
if (table_parsers[i].required && action == ots::TABLE_ACTION_SANITIZE) {
return OTS_FAILURE_MSG_TAG("missing required table", table_parsers[i].tag);
@ -634,7 +626,7 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
for (std::map<uint32_t, OpenTypeTable>::const_iterator it = table_map.begin();
it != table_map.end(); ++it) {
ots::TableAction action = GetTableAction(it->first);
ots::TableAction action = GetTableAction(header, it->first);
if (action == ots::TABLE_ACTION_PASSTHRU) {
num_output_tables++;
}
@ -706,7 +698,7 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
for (std::map<uint32_t, OpenTypeTable>::const_iterator it = table_map.begin();
it != table_map.end(); ++it) {
ots::TableAction action = GetTableAction(it->first);
ots::TableAction action = GetTableAction(header, it->first);
if (action == ots::TABLE_ACTION_PASSTHRU) {
OutputTable out;
out.tag = it->second.tag;
@ -806,27 +798,19 @@ void DisableDebugOutput() {
g_debug_output = false;
}
#ifdef MOZ_OTS_WOFF2
void EnableWOFF2() {
g_enable_woff2 = true;
}
#endif
void SetMessageCallback(MessageFunc func, void *user_data) {
g_message_func = func;
g_message_user_data = user_data;
}
void SetTableActionCallback(TableActionFunc func, void *user_data) {
g_table_action_func = func;
g_table_action_user_data = user_data;
}
bool Process(OTSStream *output, const uint8_t *data, size_t length) {
bool OTSContext::Process(OTSStream *output,
const uint8_t *data,
size_t length) {
OpenTypeFile header;
header.message_func = g_message_func;
header.user_data = g_message_user_data;
header.message_func = message_func;
header.message_user_data = message_user_data;
header.table_action_func = table_action_func;
header.table_action_user_data = table_action_user_data;
if (length < 4) {
return OTS_FAILURE_MSG_(&header, "file less than 4 bytes");
@ -835,7 +819,7 @@ bool Process(OTSStream *output, const uint8_t *data, size_t length) {
bool result;
if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
result = ProcessWOFF(&header, output, data, length);
#ifdef MOZ_OTS_WOFF2
#ifndef OTS_DISABLE_WOFF2
} else if (g_enable_woff2 &&
data[0] == 'w' && data[1] == 'O' && data[2] == 'F' &&
data[3] == '2') {

Просмотреть файл

@ -53,13 +53,13 @@ void Warning(const char *f, int l, const char *format, ...)
// Generate a simple message
#define OTS_FAILURE_MSG_(otf_,...) \
((otf_)->message_func && \
(*(otf_)->message_func)((otf_)->user_data, __VA_ARGS__) && \
(*(otf_)->message_func)((otf_)->message_user_data, __VA_ARGS__) && \
false)
// Generate a message with an associated table tag
#define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
((otf_)->message_func && \
(*(otf_)->message_func)((otf_)->user_data, "%4.4s: %s", tag_, msg_) && \
(*(otf_)->message_func)((otf_)->message_user_data, "%4.4s: %s", tag_, msg_) && \
false)
// Convenience macro for use in files that only handle a single table tag,
@ -250,8 +250,11 @@ struct OpenTypeFile {
uint16_t entry_selector;
uint16_t range_shift;
MessageFunc message_func;
void *user_data;
MessageFunc message_func;
void *message_user_data;
TableActionFunc table_action_func;
void *table_action_user_data;
#define F(name, capname) OpenType##capname *name;
FOR_EACH_TABLE_TYPE

Просмотреть файл

@ -180,3 +180,5 @@ void ots_post_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -50,3 +50,5 @@ void ots_prep_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -181,3 +181,6 @@ void ots_vdmx_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

Просмотреть файл

@ -56,3 +56,4 @@ void ots_vhea_free(OpenTypeFile *file) {
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -52,3 +52,4 @@ void ots_vmtx_free(OpenTypeFile *file) {
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -101,3 +101,6 @@ void ots_vorg_free(OpenTypeFile *file) {
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE

1022
gfx/ots/src/woff2.cc Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

20
gfx/ots/src/woff2.h Normal file
Просмотреть файл

@ -0,0 +1,20 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_WOFF2_H_
#define OTS_WOFF2_H_
namespace ots {
// Compute the size of the final uncompressed font, or 0 on error.
size_t ComputeWOFF2FinalSize(const uint8_t *data, size_t length);
// Decompresses the font into the target buffer. The result_length should
// be the same as determined by ComputeFinalSize(). Returns true on successful
// decompression.
bool ConvertWOFF2ToTTF(uint8_t *result, size_t result_length,
const uint8_t *data, size_t length);
}
#endif // OTS_WOFF2_H_

Просмотреть файл

@ -388,10 +388,11 @@ gfxUserFontSet::SanitizeOpenTypeData(gfxMixedFontFamily *aFamily,
userData.mFamily = aFamily;
userData.mProxy = aProxy;
ots::SetTableActionCallback(&OTSTableAction, nullptr);
ots::SetMessageCallback(&gfxUserFontSet::OTSMessage, &userData);
ots::OTSContext otsContext;
otsContext.SetTableActionCallback(&OTSTableAction, nullptr);
otsContext.SetMessageCallback(&gfxUserFontSet::OTSMessage, &userData);
if (ots::Process(&output, aData, aLength)) {
if (otsContext.Process(&output, aData, aLength)) {
aSaneLength = output.Tell();
return static_cast<uint8_t*>(output.forget());
} else {

Просмотреть файл

@ -45,7 +45,7 @@ namespace JS {
D(TOO_MUCH_MALLOC) \
D(ALLOC_TRIGGER) \
D(DEBUG_GC) \
D(COMPARTMENT_REVIVED) \
D(TRANSPLANT) \
D(RESET) \
D(OUT_OF_NURSERY) \
D(EVICT_NURSERY) \

Просмотреть файл

@ -32,7 +32,6 @@ class AutoValueVector;
class AutoIdArray;
class JS_PUBLIC_API(AutoGCRooter);
template <typename T> class AutoVectorRooter;
template<typename K, typename V> class AutoHashMapRooter;
template<typename T> class AutoHashSetRooter;
@ -42,8 +41,6 @@ class MOZ_STACK_CLASS SourceBufferHolder;
class HandleValueArray;
class AutoCheckCannotGC;
}
// Do the importing.
@ -80,7 +77,6 @@ using JS::AutoValueVector;
using JS::AutoIdArray;
using JS::AutoGCRooter;
using JS::AutoHashMapRooter;
using JS::AutoHashSetRooter;
using JS::AutoVectorRooter;
@ -135,8 +131,6 @@ using JS::HandleValueArray;
using JS::Zone;
using JS::AutoCheckCannotGC;
} /* namespace js */
#endif /* NamespaceImports_h */

Просмотреть файл

@ -42,12 +42,12 @@ class HashableValue {
Value get() const { return value.get(); }
};
class AutoHashableValueRooter : private AutoGCRooter
class AutoHashableValueRooter : private JS::AutoGCRooter
{
public:
explicit AutoHashableValueRooter(JSContext *cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, HASHABLEVALUE)
: JS::AutoGCRooter(cx, HASHABLEVALUE)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
@ -62,7 +62,7 @@ class AutoHashableValueRooter : private AutoGCRooter
Value get() const { return value.get(); }
friend void AutoGCRooter::trace(JSTracer *trc);
friend void JS::AutoGCRooter::trace(JSTracer *trc);
void trace(JSTracer *trc);
private:

Просмотреть файл

@ -68,7 +68,7 @@ IsKeyword(JSLinearString *str);
/* GC marking. Defined in Parser.cpp. */
void
MarkParser(JSTracer *trc, AutoGCRooter *parser);
MarkParser(JSTracer *trc, JS::AutoGCRooter *parser);
} /* namespace frontend */
} /* namespace js */

Просмотреть файл

@ -42,8 +42,11 @@
using namespace js;
using namespace js::gc;
using mozilla::Maybe;
using JS::AutoGCRooter;
namespace js {
namespace frontend {

Просмотреть файл

@ -313,7 +313,7 @@ enum VarContext { HoistVars, DontHoistVars };
enum FunctionType { Getter, Setter, Normal };
template <typename ParseHandler>
class Parser : private AutoGCRooter, public StrictModeGetter
class Parser : private JS::AutoGCRooter, public StrictModeGetter
{
public:
ExclusiveContext *const context;
@ -392,7 +392,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
traceListHead = m.traceListHead;
}
friend void js::frontend::MarkParser(JSTracer *trc, AutoGCRooter *parser);
friend void js::frontend::MarkParser(JSTracer *trc, JS::AutoGCRooter *parser);
const char *getFilename() const { return tokenStream.getFilename(); }
JSVersion versionNumber() const { return tokenStream.versionNumber(); }

Просмотреть файл

@ -188,6 +188,9 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
DebugOnly<JSRuntime *> rt = trc->runtime();
JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc) && rt->gc.manipulatingDeadZones,
!thing->zone()->scheduledForDestruction);
JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
JS_ASSERT_IF(thing->zone()->requireGCTracer(),
@ -218,33 +221,6 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
}
/*
* We only set the maybeAlive flag for objects and scripts. It's assumed that,
* if a compartment is alive, then it will have at least some live object or
* script it in. Even if we get this wrong, the worst that will happen is that
* scheduledForDestruction will be set on the compartment, which will cause some
* extra GC activity to try to free the compartment.
*/
template<typename T>
static inline void
SetMaybeAliveFlag(T *thing)
{
}
template<>
void
SetMaybeAliveFlag(JSObject *thing)
{
thing->compartment()->maybeAlive = true;
}
template<>
void
SetMaybeAliveFlag(JSScript *thing)
{
thing->compartment()->maybeAlive = true;
}
template<typename T>
static void
MarkInternal(JSTracer *trc, T **thingp)
@ -278,7 +254,7 @@ MarkInternal(JSTracer *trc, T **thingp)
return;
PushMarkStack(AsGCMarker(trc), thing);
SetMaybeAliveFlag(thing);
thing->zone()->maybeAlive = true;
} else {
trc->callback(trc, (void **)thingp, MapTypeToTraceKind<T>::kind);
trc->unsetTracingLocation();

Просмотреть файл

@ -244,7 +244,7 @@ js::Nursery::reallocateSlots(JSContext *cx, JSObject *obj, HeapSlot *oldSlots,
if (!isInside(oldSlots)) {
HeapSlot *newSlots = static_cast<HeapSlot *>(cx->realloc_(oldSlots, oldSize, newSize));
if (oldSlots != newSlots) {
if (newSlots && oldSlots != newSlots) {
hugeSlots.remove(oldSlots);
/* If this put fails, we will only leak the slots. */
(void)hugeSlots.put(newSlots);
@ -257,7 +257,8 @@ js::Nursery::reallocateSlots(JSContext *cx, JSObject *obj, HeapSlot *oldSlots,
return oldSlots;
HeapSlot *newSlots = allocateSlots(cx, obj, newCount);
PodCopy(newSlots, oldSlots, oldCount);
if (newSlots)
PodCopy(newSlots, oldSlots, oldCount);
return newSlots;
}
@ -284,7 +285,8 @@ js::Nursery::allocateHugeSlots(JSContext *cx, size_t nslots)
{
HeapSlot *slots = cx->pod_malloc<HeapSlot>(nslots);
/* If this put fails, we will only leak the slots. */
(void)hugeSlots.put(slots);
if (slots)
(void)hugeSlots.put(slots);
return slots;
}

Просмотреть файл

@ -36,6 +36,8 @@ using namespace js::gc;
using mozilla::ArrayEnd;
using JS::AutoGCRooter;
typedef RootedValueMap::Range RootRange;
typedef RootedValueMap::Entry RootEntry;
typedef RootedValueMap::Enum RootEnum;
@ -582,7 +584,7 @@ AutoGCRooter::trace(JSTracer *trc)
AutoGCRooter::traceAll(JSTracer *trc)
{
for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) {
for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down)
for (AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down)
gcr->trace(trc);
}
}
@ -591,7 +593,7 @@ AutoGCRooter::traceAll(JSTracer *trc)
AutoGCRooter::traceAllWrappers(JSTracer *trc)
{
for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) {
for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down) {
for (AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down) {
if (gcr->tag_ == WRAPVECTOR || gcr->tag_ == WRAPPER)
gcr->trace(trc);
}

Просмотреть файл

@ -638,20 +638,7 @@ GCMarker::appendGrayRoot(void *thing, JSGCTraceKind kind)
Zone *zone = static_cast<Cell *>(thing)->tenuredZone();
if (zone->isCollecting()) {
// See the comment on SetMaybeAliveFlag to see why we only do this for
// objects and scripts. We rely on gray root buffering for this to work,
// but we only need to worry about uncollected dead compartments during
// incremental GCs (when we do gray root buffering).
switch (kind) {
case JSTRACE_OBJECT:
static_cast<JSObject *>(thing)->compartment()->maybeAlive = true;
break;
case JSTRACE_SCRIPT:
static_cast<JSScript *>(thing)->compartment()->maybeAlive = true;
break;
default:
break;
}
zone->maybeAlive = true;
if (!zone->gcGrayRoots.append(root)) {
resetBufferedGrayRoots();
grayBufferState = GRAY_BUFFER_FAILED;

Просмотреть файл

@ -35,6 +35,8 @@ JS::Zone::Zone(JSRuntime *rt)
data(nullptr),
isSystem(false),
usedByExclusiveThread(false),
scheduledForDestruction(false),
maybeAlive(true),
active(false),
jitZone_(nullptr),
gcState_(NoGC),

Просмотреть файл

@ -258,6 +258,11 @@ struct Zone : public JS::shadow::Zone,
bool usedByExclusiveThread;
// These flags help us to discover if a compartment that shouldn't be alive
// manages to outlive a GC.
bool scheduledForDestruction;
bool maybeAlive;
// True when there are active frames.
bool active;

Просмотреть файл

@ -1,20 +0,0 @@
assertEq(Number.toInteger(4), 4);
assertEq(Number.toInteger(4.), 4);
assertEq(Number.toInteger(4.3), 4);
assertEq(Number.toInteger(-4), -4);
assertEq(Number.toInteger(-4.), -4);
assertEq(Number.toInteger(-4.3), -4);
assertEq(Number.toInteger(0.), 0.);
assertEq(Number.toInteger(-0.), -0.);
assertEq(Number.toInteger(Infinity), Infinity);
assertEq(Number.toInteger(-Infinity), -Infinity);
assertEq(Number.toInteger(NaN), 0);
assertEq(Number.toInteger(null), 0);
assertEq(Number.toInteger(undefined), 0);
assertEq(Number.toInteger(true), 1);
assertEq(Number.toInteger(false), 0);
assertEq(Number.toInteger({valueOf : function () { return 4; }}), 4);
assertEq(Number.toInteger({valueOf : function () { return 4.3; }}), 4);
assertEq(Number.toInteger({valueOf : function () { return "4"; }}), 4);
assertEq(Number.toInteger({valueOf : function () { return {};}}), 0);
assertEq(Number.toInteger(), 0);

Просмотреть файл

@ -74,17 +74,17 @@ class TempAllocator
};
// Stack allocated rooter for all roots associated with a TempAllocator
class AutoTempAllocatorRooter : private AutoGCRooter
class AutoTempAllocatorRooter : private JS::AutoGCRooter
{
public:
explicit AutoTempAllocatorRooter(JSContext *cx, TempAllocator *temp
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, IONALLOC), temp(temp)
: JS::AutoGCRooter(cx, IONALLOC), temp(temp)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
friend void AutoGCRooter::trace(JSTracer *trc);
friend void JS::AutoGCRooter::trace(JSTracer *trc);
void trace(JSTracer *trc);
private:

Просмотреть файл

@ -548,6 +548,13 @@ MacroAssembler::allocateObject(Register result, Register slots, gc::AllocKind al
{
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
#ifdef JS_CODEGEN_ARM
// Bug 1011474: Always take the ool path when allocating malloc slots on
// ARM to work around a top-crasher while we investigate.
if (nDynamicSlots)
return jump(fail);
#endif
checkAllocatorState(fail);
if (shouldNurseryAllocate(allocKind, initialHeap))

Просмотреть файл

@ -41,13 +41,13 @@ class MacroAssembler : public MacroAssemblerSpecific
}
public:
class AutoRooter : public AutoGCRooter
class AutoRooter : public JS::AutoGCRooter
{
MacroAssembler *masm_;
public:
AutoRooter(JSContext *cx, MacroAssembler *masm)
: AutoGCRooter(cx, IONMASM),
: JS::AutoGCRooter(cx, IONMASM),
masm_(masm)
{ }

Просмотреть файл

@ -17,6 +17,8 @@
using namespace js;
using namespace jit;
using JS::AutoCheckCannotGC;
using parallel::Spew;
using parallel::SpewOps;
using parallel::SpewBailouts;

Просмотреть файл

@ -98,6 +98,8 @@ using mozilla::Maybe;
using mozilla::PodCopy;
using mozilla::PodZero;
using JS::AutoGCRooter;
using js::frontend::Parser;
#ifdef HAVE_VA_LIST_AS_ARRAY
@ -1088,6 +1090,7 @@ JS_TransplantObject(JSContext *cx, HandleObject origobj, HandleObject target)
JS_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
JS_ASSERT(!target->is<CrossCompartmentWrapperObject>());
AutoMaybeTouchDeadZones agc(cx);
AutoDisableProxyCheck adpc(cx->runtime());
JSCompartment *destination = target->compartment();

Просмотреть файл

@ -74,66 +74,6 @@ inline void AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v) {
}
#endif /* JS_DEBUG */
class JS_PUBLIC_API(AutoGCRooter) {
public:
AutoGCRooter(JSContext *cx, ptrdiff_t tag);
AutoGCRooter(js::ContextFriendFields *cx, ptrdiff_t tag);
~AutoGCRooter() {
JS_ASSERT(this == *stackTop);
*stackTop = down;
}
/* Implemented in gc/RootMarking.cpp. */
inline void trace(JSTracer *trc);
static void traceAll(JSTracer *trc);
static void traceAllWrappers(JSTracer *trc);
protected:
AutoGCRooter * const down;
/*
* Discriminates actual subclass of this being used. If non-negative, the
* subclass roots an array of values of the length stored in this field.
* If negative, meaning is indicated by the corresponding value in the enum
* below. Any other negative value indicates some deeper problem such as
* memory corruption.
*/
ptrdiff_t tag_;
enum {
VALARRAY = -2, /* js::AutoValueArray */
PARSER = -3, /* js::frontend::Parser */
SHAPEVECTOR = -4, /* js::AutoShapeVector */
IDARRAY = -6, /* js::AutoIdArray */
DESCVECTOR = -7, /* js::AutoPropDescVector */
VALVECTOR = -10, /* js::AutoValueVector */
IDVECTOR = -13, /* js::AutoIdVector */
OBJVECTOR = -14, /* js::AutoObjectVector */
STRINGVECTOR =-15, /* js::AutoStringVector */
SCRIPTVECTOR =-16, /* js::AutoScriptVector */
NAMEVECTOR = -17, /* js::AutoNameVector */
HASHABLEVALUE=-18, /* js::HashableValue */
IONMASM = -19, /* js::jit::MacroAssembler */
IONALLOC = -20, /* js::jit::AutoTempAllocatorRooter */
WRAPVECTOR = -21, /* js::AutoWrapperVector */
WRAPPER = -22, /* js::AutoWrapperRooter */
OBJOBJHASHMAP=-23, /* js::AutoObjectObjectHashMap */
OBJU32HASHMAP=-24, /* js::AutoObjectUnsigned32HashMap */
OBJHASHSET = -25, /* js::AutoObjectHashSet */
JSONPARSER = -26, /* js::JSONParser */
CUSTOM = -27, /* js::CustomAutoRooter */
FUNVECTOR = -28 /* js::AutoFunctionVector */
};
private:
AutoGCRooter ** const stackTop;
/* No copy or assignment semantics. */
AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
void operator=(AutoGCRooter &ida) MOZ_DELETE;
};
/* AutoValueArray roots an internal fixed-size array of Values. */
template <size_t N>
class AutoValueArray : public AutoGCRooter

Просмотреть файл

@ -49,6 +49,8 @@ using mozilla::DebugOnly;
using mozilla::IsNaN;
using mozilla::PointerRangeSize;
using JS::AutoCheckCannotGC;
bool
js::GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp)
{

Просмотреть файл

@ -914,12 +914,12 @@ class AutoObjectHashSet : public AutoHashSetRooter<JSObject *>
};
/* AutoArrayRooter roots an external array of Values. */
class AutoArrayRooter : private AutoGCRooter
class AutoArrayRooter : private JS::AutoGCRooter
{
public:
AutoArrayRooter(JSContext *cx, size_t len, Value *vec
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, len), array(vec)
: JS::AutoGCRooter(cx, len), array(vec)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
JS_ASSERT(tag_ >= 0);
@ -961,7 +961,7 @@ class AutoArrayRooter : private AutoGCRooter
return HandleValue::fromMarkedLocation(&array[i]);
}
friend void AutoGCRooter::trace(JSTracer *trc);
friend void JS::AutoGCRooter::trace(JSTracer *trc);
private:
Value *array;

Просмотреть файл

@ -65,9 +65,7 @@ JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options =
debugScriptMap(nullptr),
debugScopes(nullptr),
enumerators(nullptr),
compartmentStats(nullptr),
scheduledForDestruction(false),
maybeAlive(true)
compartmentStats(nullptr)
#ifdef JS_ION
, jitCompartment_(nullptr)
#endif

Просмотреть файл

@ -448,11 +448,6 @@ struct JSCompartment
/* Used by memory reporters and invalid otherwise. */
void *compartmentStats;
// These flags help us to discover if a compartment that shouldn't be alive
// manages to outlive a GC.
bool scheduledForDestruction;
bool maybeAlive;
#ifdef JS_ION
private:
js::jit::JitCompartment *jitCompartment_;
@ -656,11 +651,11 @@ class AutoWrapperVector : public AutoVectorRooter<WrapperValue>
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoWrapperRooter : private AutoGCRooter {
class AutoWrapperRooter : private JS::AutoGCRooter {
public:
AutoWrapperRooter(JSContext *cx, WrapperValue v
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, WRAPPER), value(v)
: JS::AutoGCRooter(cx, WRAPPER), value(v)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
@ -669,7 +664,7 @@ class AutoWrapperRooter : private AutoGCRooter {
return value.get().toObjectOrNull();
}
friend void AutoGCRooter::trace(JSTracer *trc);
friend void JS::AutoGCRooter::trace(JSTracer *trc);
private:
WrapperValue value;

Просмотреть файл

@ -978,6 +978,8 @@ JS::IncrementalObjectBarrier(JSObject *obj)
JS_ASSERT(!obj->zone()->runtimeFromMainThread()->isHeapMajorCollecting());
AutoMarkInDeadZone amn(obj->zone());
JSObject::writeBarrierPre(obj);
}
@ -988,13 +990,13 @@ JS::IncrementalReferenceBarrier(void *ptr, JSGCTraceKind kind)
return;
gc::Cell *cell = static_cast<gc::Cell *>(ptr);
#ifdef DEBUG
Zone *zone = kind == JSTRACE_OBJECT
? static_cast<JSObject *>(cell)->zone()
: cell->tenuredZone();
JS_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting());
#endif
AutoMarkInDeadZone amn(zone);
if (kind == JSTRACE_OBJECT)
JSObject::writeBarrierPre(static_cast<JSObject*>(cell));

Просмотреть файл

@ -230,6 +230,8 @@ using mozilla::DebugOnly;
using mozilla::Maybe;
using mozilla::Swap;
using JS::AutoGCRooter;
/* Perform a Full GC every 20 seconds if MaybeGC is called */
static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
@ -2982,14 +2984,14 @@ GCRuntime::beginMarkPhase()
isFull = false;
}
zone->scheduledForDestruction = false;
zone->maybeAlive = false;
zone->setPreservingCode(false);
}
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
JS_ASSERT(c->gcLiveArrayBuffers.empty());
c->marked = false;
c->scheduledForDestruction = false;
c->maybeAlive = false;
if (shouldPreserveJITCode(c, currentTime))
c->zone()->setPreservingCode(true);
}
@ -3090,50 +3092,40 @@ GCRuntime::beginMarkPhase()
bufferGrayRoots();
/*
* This code ensures that if a compartment is "dead", then it will be
* collected in this GC. A compartment is considered dead if its maybeAlive
* This code ensures that if a zone is "dead", then it will be
* collected in this GC. A zone is considered dead if its maybeAlive
* flag is false. The maybeAlive flag is set if:
* (1) the compartment has incoming cross-compartment edges, or
* (2) an object in the compartment was marked during root marking, either
* (1) the zone has incoming cross-compartment edges, or
* (2) an object in the zone was marked during root marking, either
* as a black root or a gray root.
* If the maybeAlive is false, then we set the scheduledForDestruction flag.
* At the end of the GC, we look for compartments where
* scheduledForDestruction is true. These are compartments that were somehow
* "revived" during the incremental GC. If any are found, we do a special,
* non-incremental GC of those compartments to try to collect them.
* At any time later in the GC, if we try to mark an object whose
* zone is scheduled for destruction, we will assert.
* NOTE: Due to bug 811587, we only assert if gcManipulatingDeadCompartments
* is true (e.g., if we're doing a brain transplant).
*
* Compartments can be revived for a variety of reasons. On reason is bug
* 811587, where a reflector that was dead can be revived by DOM code that
* still refers to the underlying DOM node.
* The purpose of this check is to ensure that a zone that we would
* normally destroy is not resurrected by a read barrier or an
* allocation. This might happen during a function like JS_TransplantObject,
* which iterates over all compartments, live or dead, and operates on their
* objects. See bug 803376 for details on this problem. To avoid the
* problem, we are very careful to avoid allocation and read barriers during
* JS_TransplantObject and the like. The code here ensures that we don't
* regress.
*
* Read barriers and allocations can also cause revival. This might happen
* during a function like JS_TransplantObject, which iterates over all
* compartments, live or dead, and operates on their objects. See bug 803376
* for details on this problem. To avoid the problem, we try to avoid
* allocation and read barriers during JS_TransplantObject and the like.
* Note that there are certain cases where allocations or read barriers in
* dead zone are difficult to avoid. We detect such cases (via the
* gcObjectsMarkedInDeadCompartment counter) and redo any ongoing GCs after
* the JS_TransplantObject function has finished. This ensures that the dead
* zones will be cleaned up. See AutoMarkInDeadZone and
* AutoMaybeTouchDeadZones for details.
*/
/* Set the maybeAlive flag based on cross-compartment edges. */
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
const CrossCompartmentKey &key = e.front().key();
JSCompartment *dest;
switch (key.kind) {
case CrossCompartmentKey::ObjectWrapper:
case CrossCompartmentKey::DebuggerObject:
case CrossCompartmentKey::DebuggerSource:
case CrossCompartmentKey::DebuggerEnvironment:
dest = static_cast<JSObject *>(key.wrapped)->compartment();
break;
case CrossCompartmentKey::DebuggerScript:
dest = static_cast<JSScript *>(key.wrapped)->compartment();
break;
default:
dest = nullptr;
break;
}
if (dest)
dest->maybeAlive = true;
Cell *dst = e.front().key().wrapped;
dst->tenuredZone()->maybeAlive = true;
}
}
@ -3142,9 +3134,9 @@ GCRuntime::beginMarkPhase()
* during MarkRuntime.
*/
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
if (!c->maybeAlive && !rt->isAtomsCompartment(c))
c->scheduledForDestruction = true;
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
if (!zone->maybeAlive && !rt->isAtomsZone(zone))
zone->scheduledForDestruction = true;
}
foundBlackGrayEdges = false;
@ -4520,8 +4512,8 @@ GCRuntime::resetIncrementalGC(const char *reason)
case SWEEP:
marker.reset();
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
c->scheduledForDestruction = false;
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
zone->scheduledForDestruction = false;
/* Finish sweeping the current zone group, then abort. */
abortSweepAfterCurrentGroup = true;
@ -4999,30 +4991,13 @@ GCRuntime::collect(bool incremental, int64_t budget, JSGCInvocationKind gckind,
if (poked && shouldCleanUpEverything)
JS::PrepareForFullGC(rt);
/*
* This code makes an extra effort to collect compartments that we
* thought were dead at the start of the GC. See the large comment in
* beginMarkPhase.
*/
bool repeatForDeadZone = false;
if (incremental && incrementalState == NO_INCREMENTAL) {
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
if (c->scheduledForDestruction) {
incremental = false;
repeatForDeadZone = true;
reason = JS::gcreason::COMPARTMENT_REVIVED;
c->zone()->scheduleGC();
}
}
}
/*
* If we reset an existing GC, we need to start a new one. Also, we
* repeat GCs that happen during shutdown (the gcShouldCleanUpEverything
* case) until we can be sure that no additional garbage is created
* (which typically happens if roots are dropped during finalizers).
*/
repeat = (poked && shouldCleanUpEverything) || wasReset || repeatForDeadZone;
repeat = (poked && shouldCleanUpEverything) || wasReset;
} while (repeat);
if (incrementalState == NO_INCREMENTAL) {
@ -5559,6 +5534,34 @@ ArenaLists::containsArena(JSRuntime *rt, ArenaHeader *needle)
}
AutoMaybeTouchDeadZones::AutoMaybeTouchDeadZones(JSContext *cx)
: runtime(cx->runtime()),
markCount(runtime->gc.objectsMarkedInDeadZones),
inIncremental(JS::IsIncrementalGCInProgress(runtime)),
manipulatingDeadZones(runtime->gc.manipulatingDeadZones)
{
runtime->gc.manipulatingDeadZones = true;
}
AutoMaybeTouchDeadZones::AutoMaybeTouchDeadZones(JSObject *obj)
: runtime(obj->compartment()->runtimeFromMainThread()),
markCount(runtime->gc.objectsMarkedInDeadZones),
inIncremental(JS::IsIncrementalGCInProgress(runtime)),
manipulatingDeadZones(runtime->gc.manipulatingDeadZones)
{
runtime->gc.manipulatingDeadZones = true;
}
AutoMaybeTouchDeadZones::~AutoMaybeTouchDeadZones()
{
runtime->gc.manipulatingDeadZones = manipulatingDeadZones;
if (inIncremental && runtime->gc.objectsMarkedInDeadZones != markCount) {
JS::PrepareForFullGC(runtime);
js::GC(runtime, GC_NORMAL, JS::gcreason::TRANSPLANT);
}
}
AutoSuppressGC::AutoSuppressGC(ExclusiveContext *cx)
: suppressGC_(cx->perThreadData->suppressGC)
{

Просмотреть файл

@ -15,6 +15,33 @@ namespace js {
class Shape;
/*
* This auto class should be used around any code that might cause a mark bit to
* be set on an object in a dead zone. See AutoMaybeTouchDeadZones
* for more details.
*/
struct AutoMarkInDeadZone
{
explicit AutoMarkInDeadZone(JS::Zone *zone)
: zone(zone),
scheduled(zone->scheduledForDestruction)
{
JSRuntime *rt = zone->runtimeFromMainThread();
if (rt->gc.manipulatingDeadZones && zone->scheduledForDestruction) {
rt->gc.objectsMarkedInDeadZones++;
zone->scheduledForDestruction = false;
}
}
~AutoMarkInDeadZone() {
zone->scheduledForDestruction = scheduled;
}
private:
JS::Zone *zone;
bool scheduled;
};
inline Allocator *
ThreadSafeContext::allocator() const
{

Просмотреть файл

@ -203,7 +203,7 @@ IdToTypeId(jsid id)
if (JSID_IS_STRING(id)) {
JSAtom *atom = JSID_TO_ATOM(id);
AutoCheckCannotGC nogc;
JS::AutoCheckCannotGC nogc;
bool isNumeric = atom->hasLatin1Chars()
? IdIsNumericTypeId(atom->latin1Range(nogc))
: IdIsNumericTypeId(atom->twoByteRange(nogc));

Просмотреть файл

@ -46,6 +46,8 @@ using mozilla::NegativeInfinity;
using mozilla::PodCopy;
using mozilla::PositiveInfinity;
using mozilla::RangedPtr;
using JS::AutoCheckCannotGC;
using JS::GenericNaN;
/*
@ -1058,22 +1060,6 @@ Number_isInteger(JSContext *cx, unsigned argc, Value *vp)
return true;
}
// ES6 drafult ES6 15.7.3.13
static bool
Number_toInteger(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1) {
args.rval().setInt32(0);
return true;
}
double asint;
if (!ToInteger(cx, args[0], &asint))
return false;
args.rval().setNumber(asint);
return true;
}
static const JSFunctionSpec number_static_methods[] = {
JS_SELF_HOSTED_FN("isFinite", "Number_isFinite", 1,0),
@ -1082,7 +1068,6 @@ static const JSFunctionSpec number_static_methods[] = {
JS_SELF_HOSTED_FN("isSafeInteger", "Number_isSafeInteger", 1,0),
JS_FN("parseFloat", num_parseFloat, 1, 0),
JS_FN("parseInt", num_parseInt, 2, 0),
JS_FN("toInteger", Number_toInteger, 1, 0),
JS_FS_END
};

Просмотреть файл

@ -2505,6 +2505,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
bool
JSObject::swap(JSContext *cx, HandleObject a, HandleObject b)
{
AutoMarkInDeadZone adc1(a->zone());
AutoMarkInDeadZone adc2(b->zone());
// Ensure swap doesn't cause a finalizer to not be run.
JS_ASSERT(IsBackgroundFinalized(a->tenuredGetAllocKind()) ==
IsBackgroundFinalized(b->tenuredGetAllocKind()));

Просмотреть файл

@ -9,12 +9,14 @@
#include "mozilla/Attributes.h"
#include "jspubtd.h"
#include "ds/IdValuePair.h"
#include "vm/String.h"
namespace js {
class MOZ_STACK_CLASS JSONParser : private AutoGCRooter
class MOZ_STACK_CLASS JSONParser : private JS::AutoGCRooter
{
public:
enum ErrorHandling { RaiseError, NoError };

Просмотреть файл

@ -45,6 +45,8 @@
using namespace js;
using namespace js::gc;
using JS::AutoCheckCannotGC;
using js::frontend::IsIdentifier;
/*

Просмотреть файл

@ -1094,95 +1094,6 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
// This variable exists solely to provide a unique address for use as an identifier.
static const char sScriptedDirectProxyHandlerFamily = 0;
// Aux.2 FromGenericPropertyDescriptor(Desc)
static bool
FromGenericPropertyDescriptor(JSContext *cx, MutableHandle<PropDesc> desc, MutableHandleValue rval)
{
// Aux.2 step 1
if (desc.isUndefined()) {
rval.setUndefined();
return true;
}
// steps 3-9
if (!desc.makeObject(cx))
return false;
rval.set(desc.descriptorValue());
return true;
}
/*
* Aux.3 NormalizePropertyDescriptor(Attributes)
*
* NOTE: to minimize code duplication, the code for this function is shared with
* that for Aux.4 NormalizeAndCompletePropertyDescriptor (see below). The
* argument complete is used to distinguish between the two.
*/
static bool
NormalizePropertyDescriptor(JSContext *cx, MutableHandleValue vp, bool complete = false)
{
// Aux.4 step 1
if (complete && vp.isUndefined())
return true;
// Aux.3 steps 1-2 / Aux.4 steps 2-3
Rooted<PropDesc> desc(cx);
if (!desc.initialize(cx, vp.get()))
return false;
if (complete)
desc.complete();
JS_ASSERT(vp.isObject()); // due to desc->initialize
RootedObject attributes(cx, &vp.toObject());
/*
* Aux.3 step 3 / Aux.4 step 4
*
* NOTE: Aux.4 step 4 actually specifies FromPropertyDescriptor here.
* However, the way FromPropertyDescriptor is implemented (PropDesc::
* makeObject) is actually closer to FromGenericPropertyDescriptor,
* and is in fact used to implement the latter, so we might as well call it
* directly.
*/
if (!FromGenericPropertyDescriptor(cx, &desc, vp))
return false;
if (vp.isUndefined())
return true;
RootedObject descObj(cx, &vp.toObject());
// Aux.3 steps 4-5 / Aux.4 steps 5-6
AutoIdVector props(cx);
if (!GetPropertyNames(cx, attributes, 0, &props))
return false;
size_t n = props.length();
for (size_t i = 0; i < n; ++i) {
RootedId id(cx, props[i]);
if (JSID_IS_ATOM(id)) {
JSAtom *atom = JSID_TO_ATOM(id);
const JSAtomState &atomState = cx->names();
if (atom == atomState.value || atom == atomState.writable ||
atom == atomState.get || atom == atomState.set ||
atom == atomState.enumerable || atom == atomState.configurable)
{
continue;
}
}
RootedValue v(cx);
if (!JSObject::getGeneric(cx, descObj, attributes, id, &v))
return false;
if (!JSObject::defineGeneric(cx, descObj, id, v, nullptr, nullptr, JSPROP_ENUMERATE))
return false;
}
return true;
}
// Aux.4 NormalizeAndCompletePropertyDescriptor(Attributes)
static inline bool
NormalizeAndCompletePropertyDescriptor(JSContext *cx, MutableHandleValue vp)
{
return NormalizePropertyDescriptor(cx, vp, true);
}
static inline bool
IsDataDescriptor(const PropertyDescriptor &desc)
{

Просмотреть файл

@ -11,6 +11,7 @@
* JS public API typedefs.
*/
#include "mozilla/Assertions.h"
#include "mozilla/LinkedList.h"
#include "mozilla/NullPtr.h"
#include "mozilla/PodOperations.h"
@ -32,8 +33,6 @@ class CallArgs;
template <typename T>
class Rooted;
class JS_PUBLIC_API(AutoGCRooter);
class JS_FRIEND_API(CompileOptions);
class JS_FRIEND_API(ReadOnlyCompileOptions);
class JS_FRIEND_API(OwningCompileOptions);
@ -43,6 +42,10 @@ struct Zone;
} /* namespace JS */
namespace js {
struct ContextFriendFields;
} // namespace js
/*
* Run-time version enumeration. For compile-time version checking, please use
* the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION,
@ -246,6 +249,68 @@ inline mozilla::LinkedList<PersistentRootedValue>
&Runtime::getPersistentRootedList<Value>() { return valuePersistentRooteds; }
} /* namespace shadow */
class JS_PUBLIC_API(AutoGCRooter)
{
public:
AutoGCRooter(JSContext *cx, ptrdiff_t tag);
AutoGCRooter(js::ContextFriendFields *cx, ptrdiff_t tag);
~AutoGCRooter() {
MOZ_ASSERT(this == *stackTop);
*stackTop = down;
}
/* Implemented in gc/RootMarking.cpp. */
inline void trace(JSTracer *trc);
static void traceAll(JSTracer *trc);
static void traceAllWrappers(JSTracer *trc);
protected:
AutoGCRooter * const down;
/*
* Discriminates actual subclass of this being used. If non-negative, the
* subclass roots an array of values of the length stored in this field.
* If negative, meaning is indicated by the corresponding value in the enum
* below. Any other negative value indicates some deeper problem such as
* memory corruption.
*/
ptrdiff_t tag_;
enum {
VALARRAY = -2, /* js::AutoValueArray */
PARSER = -3, /* js::frontend::Parser */
SHAPEVECTOR = -4, /* js::AutoShapeVector */
IDARRAY = -6, /* js::AutoIdArray */
DESCVECTOR = -7, /* js::AutoPropDescVector */
VALVECTOR = -10, /* js::AutoValueVector */
IDVECTOR = -13, /* js::AutoIdVector */
OBJVECTOR = -14, /* js::AutoObjectVector */
STRINGVECTOR =-15, /* js::AutoStringVector */
SCRIPTVECTOR =-16, /* js::AutoScriptVector */
NAMEVECTOR = -17, /* js::AutoNameVector */
HASHABLEVALUE=-18, /* js::HashableValue */
IONMASM = -19, /* js::jit::MacroAssembler */
IONALLOC = -20, /* js::jit::AutoTempAllocatorRooter */
WRAPVECTOR = -21, /* js::AutoWrapperVector */
WRAPPER = -22, /* js::AutoWrapperRooter */
OBJOBJHASHMAP=-23, /* js::AutoObjectObjectHashMap */
OBJU32HASHMAP=-24, /* js::AutoObjectUnsigned32HashMap */
OBJHASHSET = -25, /* js::AutoObjectHashSet */
JSONPARSER = -26, /* js::JSONParser */
CUSTOM = -27, /* js::CustomAutoRooter */
FUNVECTOR = -28 /* js::AutoFunctionVector */
};
private:
AutoGCRooter ** const stackTop;
/* No copy or assignment semantics. */
AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
void operator=(AutoGCRooter &ida) MOZ_DELETE;
};
} /* namespace JS */
namespace js {

Просмотреть файл

@ -73,6 +73,8 @@ using mozilla::PodCopy;
using mozilla::PodEqual;
using mozilla::SafeCast;
using JS::AutoCheckCannotGC;
typedef Handle<JSLinearString*> HandleLinearString;
static JSLinearString *

Просмотреть файл

@ -44,6 +44,8 @@ Wrapper::New(JSContext *cx, JSObject *obj, JSObject *parent, Wrapper *handler,
{
JS_ASSERT(parent);
AutoMarkInDeadZone amd(cx->zone());
RootedValue priv(cx, ObjectValue(*obj));
mozilla::Maybe<WrapperOptions> opts;
if (!options) {
@ -1043,6 +1045,8 @@ JS_FRIEND_API(bool)
js::RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter)
{
AutoMaybeTouchDeadZones agc(cx);
AutoWrapperVector toRecompute(cx);
for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {

Просмотреть файл

@ -304,6 +304,34 @@ JS_FRIEND_API(bool)
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter);
/*
* This auto class should be used around any code, such as brain transplants,
* that may touch dead zones. Brain transplants can cause problems
* because they operate on all compartments, whether live or dead. A brain
* transplant can cause a formerly dead object to be "reanimated" by causing a
* read or write barrier to be invoked on it during the transplant. In this way,
* a zone becomes a zombie, kept alive by repeatedly consuming
* (transplanted) brains.
*
* To work around this issue, we observe when mark bits are set on objects in
* dead zones. If this happens during a brain transplant, we do a full,
* non-incremental GC at the end of the brain transplant. This will clean up any
* objects that were improperly marked.
*/
struct JS_FRIEND_API(AutoMaybeTouchDeadZones)
{
// The version that takes an object just uses it for its runtime.
explicit AutoMaybeTouchDeadZones(JSContext *cx);
explicit AutoMaybeTouchDeadZones(JSObject *obj);
~AutoMaybeTouchDeadZones();
private:
JSRuntime *runtime;
unsigned markCount;
bool inIncremental;
bool manipulatingDeadZones;
};
} /* namespace js */
#endif /* jswrapper_h */

Просмотреть файл

@ -25,3 +25,5 @@ user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_com
user_pref("toolkit.telemetry.enabled", false);
user_pref("browser.safebrowsing.enabled", false);
user_pref("browser.safebrowsing.malware.enabled", false);
user_pref("browser.snippets.enabled", false);
user_pref("browser.snippets.syncPromo.enabled", false);

Просмотреть файл

@ -2093,7 +2093,7 @@ Debugger::addAllGlobalsAsDebuggees(JSContext *cx, unsigned argc, Value *vp)
for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
if (c == dbg->object->compartment() || c->options().invisibleToDebugger())
continue;
c->scheduledForDestruction = false;
c->zone()->scheduledForDestruction = false;
GlobalObject *global = c->maybeGlobal();
if (global) {
Rooted<GlobalObject*> rg(cx, global);
@ -2890,7 +2890,7 @@ Debugger::findAllGlobals(JSContext *cx, unsigned argc, Value *vp)
if (c->options().invisibleToDebugger())
continue;
c->scheduledForDestruction = false;
c->zone()->scheduledForDestruction = false;
GlobalObject *global = c->maybeGlobal();

Просмотреть файл

@ -77,7 +77,14 @@ ProxyObject::initHandler(BaseProxyHandler *handler)
static void
NukeSlot(ProxyObject *proxy, uint32_t slot)
{
proxy->setReservedSlot(slot, NullValue());
Value old = proxy->getSlot(slot);
if (old.isMarkable()) {
Zone *zone = ZoneOfValue(old);
AutoMarkInDeadZone amd(zone);
proxy->setReservedSlot(slot, NullValue());
} else {
proxy->setReservedSlot(slot, NullValue());
}
}
void

Просмотреть файл

@ -33,6 +33,8 @@
using namespace js;
using namespace js::selfhosted;
using JS::AutoCheckCannotGC;
static void
selfHosting_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{

Просмотреть файл

@ -88,7 +88,7 @@ NewFatInlineString(ExclusiveContext *cx, Handle<JSLinearString*> base, size_t st
if (!s)
return nullptr;
AutoCheckCannotGC nogc;
JS::AutoCheckCannotGC nogc;
mozilla::PodCopy(chars, base->chars<CharT>(nogc) + start, length);
chars[length] = 0;
return s;

Просмотреть файл

@ -24,6 +24,8 @@ using mozilla::PodCopy;
using mozilla::RangedPtr;
using mozilla::RoundUpPow2;
using JS::AutoCheckCannotGC;
size_t
JSString::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
{

Просмотреть файл

@ -188,7 +188,7 @@ IsTypedArrayIndex(jsid id, uint64_t *indexp)
if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
return false;
AutoCheckCannotGC nogc;
JS::AutoCheckCannotGC nogc;
JSAtom *atom = JSID_TO_ATOM(id);
size_t length = atom->length();

Просмотреть файл

@ -356,6 +356,9 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper,
mozilla::Maybe<JSAutoCompartment> ac;
if (sciWrapper.GetFlags().WantPreCreate()) {
// PreCreate may touch dead compartments.
js::AutoMaybeTouchDeadZones agc(parent);
RootedObject plannedParent(cx, parent);
nsresult rv = sciWrapper.GetCallback()->PreCreate(identity, cx,
parent, parent.address());
@ -1282,6 +1285,9 @@ RescueOrphans(HandleObject obj)
return NS_OK; // Global object. We're done.
parentObj = js::UncheckedUnwrap(parentObj, /* stopAtOuter = */ false);
// PreCreate may touch dead compartments.
js::AutoMaybeTouchDeadZones agc(parentObj);
// Recursively fix up orphans on the parent chain.
rv = RescueOrphans(parentObj);
NS_ENSURE_SUCCESS(rv, rv);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше