mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
08314b3ec8
@ -593,30 +593,13 @@ nsAccessible::VisibilityState()
|
||||
{
|
||||
PRUint64 vstates = states::INVISIBLE | states::OFFSCREEN;
|
||||
|
||||
// We need to check the parent chain for visibility.
|
||||
nsAccessible* accessible = this;
|
||||
do {
|
||||
// We don't want background tab page content to be aggressively invisible.
|
||||
// Otherwise this foils screen reader virtual buffer caches.
|
||||
roles::Role role = accessible->Role();
|
||||
if (role == roles::PROPERTYPAGE || role == roles::PANE)
|
||||
break;
|
||||
|
||||
nsIFrame* frame = accessible->GetFrame();
|
||||
if (!frame)
|
||||
return vstates;
|
||||
|
||||
const nsIView* view = frame->GetView();
|
||||
if (view && view->GetVisibility() == nsViewVisibility_kHide)
|
||||
return vstates;
|
||||
|
||||
} while (accessible = accessible->Parent());
|
||||
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (!frame)
|
||||
return vstates;
|
||||
|
||||
const nsCOMPtr<nsIPresShell> shell(GetPresShell());
|
||||
if (!shell)
|
||||
return vstates;
|
||||
|
||||
// We need to know if at least a kMinPixels around the object is visible,
|
||||
// otherwise it will be marked states::OFFSCREEN.
|
||||
@ -644,6 +627,10 @@ nsAccessible::VisibilityState()
|
||||
|
||||
}
|
||||
|
||||
// XXX Do we really need to cross from content to chrome ancestor?
|
||||
if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY))
|
||||
return vstates;
|
||||
|
||||
// Assume we are visible enough.
|
||||
return vstates &= ~states::INVISIBLE;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
|
||||
MOZ_SAFE_BROWSING=
|
||||
MOZ_SERVICES_SYNC=
|
||||
|
||||
MOZ_WEBSMS_BACKEND=1
|
||||
MOZ_DISABLE_DOMCRYPTO=1
|
||||
MOZ_APP_STATIC_INI=1
|
||||
|
||||
|
@ -60,6 +60,12 @@ public interface Actions {
|
||||
* @param geckoEvent The geckoEvent JSONObject's type
|
||||
*/
|
||||
EventExpecter expectGeckoEvent(String geckoEvent);
|
||||
|
||||
/**
|
||||
* Listens for a paint event.
|
||||
*/
|
||||
EventExpecter expectPaint();
|
||||
|
||||
// Send the string kewsToSend to the application
|
||||
void sendKeys(String keysToSend);
|
||||
//Send any of the above keys to the element
|
||||
|
@ -52,4 +52,7 @@ public interface Assert {
|
||||
void todo_is(Object a, Object b, String name);
|
||||
void todo_isnot(Object a, Object b, String name);
|
||||
void info(String name, String message);
|
||||
|
||||
// robocop-specific asserts
|
||||
void ispixel(int actual, int r, int g, int b, String name);
|
||||
}
|
||||
|
@ -68,4 +68,11 @@ public interface Driver {
|
||||
|
||||
void startFrameRecording();
|
||||
int stopFrameRecording();
|
||||
|
||||
/**
|
||||
* Get a copy of the painted content region.
|
||||
* @return A 2-D array of pixels (indexed by y, then x). The pixels
|
||||
* are in ARGB-8888 format.
|
||||
*/
|
||||
int[][] getPaintedSurface();
|
||||
}
|
||||
|
@ -73,20 +73,24 @@ public class FennecNativeActions implements Actions {
|
||||
// Map of IDs to element names.
|
||||
private Solo solo;
|
||||
private Instrumentation instr;
|
||||
private Activity geckoApp;
|
||||
|
||||
// Objects for reflexive access of fennec classes.
|
||||
private ClassLoader classLoader;
|
||||
private Class gel;
|
||||
private Class ge;
|
||||
private Class gas;
|
||||
private Class drawListener;
|
||||
private Method registerGEL;
|
||||
private Method unregisterGEL;
|
||||
private Method sendGE;
|
||||
|
||||
private Method getLayerClient;
|
||||
private Method setDrawListener;
|
||||
|
||||
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation){
|
||||
this.solo = robocop;
|
||||
this.instr = instrumentation;
|
||||
this.geckoApp = activity;
|
||||
// Set up reflexive access of java classes and methods.
|
||||
try {
|
||||
classLoader = activity.getClassLoader();
|
||||
@ -101,6 +105,11 @@ public class FennecNativeActions implements Actions {
|
||||
parameters = new Class[1];
|
||||
parameters[0] = ge;
|
||||
sendGE = gas.getMethod("sendEventToGecko", parameters);
|
||||
|
||||
getLayerClient = activity.getClass().getMethod("getSoftwareLayerClient");
|
||||
Class gslc = classLoader.loadClass("org.mozilla.gecko.gfx.GeckoSoftwareLayerClient");
|
||||
drawListener = classLoader.loadClass("org.mozilla.gecko.gfx.GeckoSoftwareLayerClient$DrawListener");
|
||||
setDrawListener = gslc.getDeclaredMethod("setDrawListener", drawListener);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SecurityException e) {
|
||||
@ -205,6 +214,75 @@ public class FennecNativeActions implements Actions {
|
||||
return null;
|
||||
}
|
||||
|
||||
class DrawListenerProxy implements InvocationHandler {
|
||||
private final PaintExpecter mPaintExpecter;
|
||||
|
||||
DrawListenerProxy(PaintExpecter paintExpecter) {
|
||||
mPaintExpecter = paintExpecter;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
String methodName = method.getName();
|
||||
if ("drawFinished".equals(methodName)) {
|
||||
Log.i("Robocop", "Received drawFinished notification");
|
||||
mPaintExpecter.notifyOfEvent();
|
||||
} else if ("toString".equals(methodName)) {
|
||||
return "DrawListenerProxy";
|
||||
} else if ("equals".equals(methodName)) {
|
||||
return false;
|
||||
} else if ("hashCode".equals(methodName)) {
|
||||
return 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class PaintExpecter implements EventExpecter {
|
||||
private Object mLayerClient;
|
||||
private boolean mPaintDone;
|
||||
|
||||
PaintExpecter() throws IllegalAccessException, InvocationTargetException {
|
||||
mLayerClient = getLayerClient.invoke(geckoApp);
|
||||
setDrawListener.invoke(mLayerClient, Proxy.newProxyInstance(classLoader, new Class[] { drawListener }, new DrawListenerProxy(this)));
|
||||
}
|
||||
|
||||
void notifyOfEvent() {
|
||||
try {
|
||||
setDrawListener.invoke(mLayerClient, (Object)null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
synchronized (this) {
|
||||
mPaintDone = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void blockForEvent() {
|
||||
while (! mPaintDone) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean eventReceived() {
|
||||
return mPaintDone;
|
||||
}
|
||||
}
|
||||
|
||||
public EventExpecter expectPaint() {
|
||||
try {
|
||||
return new PaintExpecter();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendSpecialKey(SpecialKey button) {
|
||||
switch( button) {
|
||||
case DOWN:
|
||||
|
@ -243,6 +243,23 @@ public class FennecNativeAssert implements Assert {
|
||||
ok(pass, name, diag);
|
||||
}
|
||||
|
||||
public void ispixel(int actual, int r, int g, int b, String name) {
|
||||
// When we read GL pixels the GPU has already processed them and they
|
||||
// are usually off by a little bit. For example a CSS-color pixel of color #64FFF5
|
||||
// was turned into #63FFF7 when it came out of glReadPixels. So in order to compare
|
||||
// against the expected value, we use a little fuzz factor. For the alpha we just
|
||||
// make sure it is always 0xFF.
|
||||
int aAlpha = ((actual >> 24) & 0xFF);
|
||||
int aR = ((actual >> 16) & 0xFF);
|
||||
int aG = ((actual >> 8) & 0xFF);
|
||||
int aB = (actual & 0xFF);
|
||||
boolean pass = (aAlpha == 0xFF) /* alpha */
|
||||
&& (Math.abs(aR - r) < 8) /* red */
|
||||
&& (Math.abs(aG - g) < 8) /* green */
|
||||
&& (Math.abs(aB - b) < 8); /* blue */
|
||||
ok(pass, name, "Color rgba(" + aR + "," + aG + "," + aB + "," + aAlpha + ")" + (pass ? " " : " not") + " close enough to expected rgb(" + r + "," + g + "," + b + ")");
|
||||
}
|
||||
|
||||
public void todo(boolean condition, String name, String diag) {
|
||||
testInfo test = new testInfo(condition, name, diag, true);
|
||||
_logMochitestResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
|
||||
|
@ -45,6 +45,7 @@ import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashMap;
|
||||
@ -58,6 +59,7 @@ import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.Long;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
@ -81,6 +83,7 @@ public class FennecNativeDriver implements Driver {
|
||||
private Method sendGE;
|
||||
private Method _startFrameRecording;
|
||||
private Method _stopFrameRecording;
|
||||
private Method _getPixels;
|
||||
|
||||
public FennecNativeDriver(Activity activity, Solo robocop){
|
||||
this.activity = activity;
|
||||
@ -107,6 +110,9 @@ public class FennecNativeDriver implements Driver {
|
||||
Class gfx = classLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI");
|
||||
_startFrameRecording = gfx.getDeclaredMethod("startFrameTimeRecording");
|
||||
_stopFrameRecording = gfx.getDeclaredMethod("stopFrameTimeRecording");
|
||||
|
||||
Class layerView = classLoader.loadClass("org.mozilla.gecko.gfx.LayerView");
|
||||
_getPixels = layerView.getDeclaredMethod("getPixels");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SecurityException e) {
|
||||
@ -212,6 +218,43 @@ public class FennecNativeDriver implements Driver {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private GLSurfaceView getSurfaceView() {
|
||||
for (View v : solo.getCurrentViews()) {
|
||||
if (v instanceof GLSurfaceView) {
|
||||
return (GLSurfaceView)v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int[][] getPaintedSurface() {
|
||||
GLSurfaceView view = getSurfaceView();
|
||||
if (view == null) {
|
||||
return null;
|
||||
}
|
||||
IntBuffer pixelBuffer;
|
||||
try {
|
||||
pixelBuffer = (IntBuffer)_getPixels.invoke(view);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
// now we need to (1) flip the image, because GL likes to do things up-side-down,
|
||||
// and (2) rearrange the bits from AGBR-8888 to ARGB-8888.
|
||||
int w = view.getWidth();
|
||||
int h = view.getHeight();
|
||||
pixelBuffer.position(0);
|
||||
int[][] pixels = new int[h][w];
|
||||
for (int y = h - 1; y >= 0; y--) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int agbr = pixelBuffer.get();
|
||||
pixels[y][x] = (agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
class scrollHandler implements InvocationHandler {
|
||||
public scrollHandler(){};
|
||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
|
@ -68,6 +68,7 @@ _TEST_FILES = \
|
||||
$(TESTPATH)/robocop_blank_01.html \
|
||||
$(TESTPATH)/robocop_blank_02.html \
|
||||
$(TESTPATH)/robocop_blank_03.html \
|
||||
$(TESTPATH)/robocop_boxes.html \
|
||||
$(NULL)
|
||||
|
||||
_ROBOCOP_TOOLS = \
|
||||
|
@ -70,6 +70,6 @@ JAVAC_FLAGS = \
|
||||
-classpath $(JAVA_CLASSPATH) \
|
||||
-bootclasspath $(JAVA_BOOTCLASSPATH) \
|
||||
-encoding UTF8 \
|
||||
-g \
|
||||
-g:source,lines \
|
||||
-Werror \
|
||||
$(NULL)
|
||||
|
@ -4906,12 +4906,14 @@ cairo-android)
|
||||
|
||||
cairo-gonk)
|
||||
AC_DEFINE(MOZ_WIDGET_GONK)
|
||||
AC_DEFINE(MOZ_TOUCH)
|
||||
MOZ_WIDGET_TOOLKIT=gonk
|
||||
TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
|
||||
TK_LIBS='$(MOZ_CAIRO_LIBS)'
|
||||
MOZ_WEBGL=1
|
||||
MOZ_PDF_PRINTING=1
|
||||
MOZ_B2G_RIL=1
|
||||
MOZ_TOUCH=1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
@ -178,6 +178,48 @@ enum EventNameType {
|
||||
EventNameType_All = 0xFFFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Information retrieved from the <meta name="viewport"> tag. See
|
||||
* GetViewportInfo for more information on this functionality.
|
||||
*/
|
||||
struct ViewportInfo
|
||||
{
|
||||
// Default zoom indicates the level at which the display is 'zoomed in'
|
||||
// initially for the user, upon loading of the page.
|
||||
double defaultZoom;
|
||||
|
||||
// The minimum zoom level permitted by the page.
|
||||
double minZoom;
|
||||
|
||||
// The maximum zoom level permitted by the page.
|
||||
double maxZoom;
|
||||
|
||||
// The width of the viewport, specified by the <meta name="viewport"> tag,
|
||||
// in CSS pixels.
|
||||
PRUint32 width;
|
||||
|
||||
// The height of the viewport, specified by the <meta name="viewport"> tag,
|
||||
// in CSS pixels.
|
||||
PRUint32 height;
|
||||
|
||||
// Whether or not we should automatically size the viewport to the device's
|
||||
// width. This is true if the document has been optimized for mobile, and
|
||||
// the width property of a specified <meta name="viewport"> tag is either
|
||||
// not specified, or is set to the special value 'device-width'.
|
||||
bool autoSize;
|
||||
|
||||
// Whether or not the user can zoom in and out on the page. Default is true.
|
||||
bool allowZoom;
|
||||
|
||||
// This is a holdover from e10s fennec, and might be removed in the future.
|
||||
// It's a hack to work around bugs that didn't allow zooming of documents
|
||||
// from within the parent process. It is still used in native Fennec for XUL
|
||||
// documents, but it should probably be removed.
|
||||
// Currently, from, within GetViewportInfo(), This is only set to false
|
||||
// if the document is a XUL document.
|
||||
bool autoScale;
|
||||
};
|
||||
|
||||
struct EventNameMapping
|
||||
{
|
||||
nsIAtom* mAtom;
|
||||
@ -1489,6 +1531,18 @@ public:
|
||||
return sScriptBlockerCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about the viewport as a data structure.
|
||||
* This will return information in the viewport META data section
|
||||
* of the document. This can be used in lieu of ProcessViewportInfo(),
|
||||
* which places the viewport information in the document header instead
|
||||
* of returning it directly.
|
||||
*
|
||||
* NOTE: If the site is optimized for mobile (via the doctype), this
|
||||
* will return viewport information that specifies default information.
|
||||
*/
|
||||
static ViewportInfo GetViewportInfo(nsIDocument* aDocument);
|
||||
|
||||
/* Process viewport META data. This gives us information for the scale
|
||||
* and zoom of a page on mobile devices. We stick the information in
|
||||
* the document header and use it later on after rendering.
|
||||
|
@ -211,6 +211,8 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsIDOMDocumentType.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
@ -221,6 +223,17 @@ using namespace mozilla;
|
||||
|
||||
const char kLoadAsData[] = "loadAsData";
|
||||
|
||||
/**
|
||||
* Default values for the ViewportInfo structure.
|
||||
*/
|
||||
static const float kViewportMinScale = 0.0;
|
||||
static const float kViewportMaxScale = 10.0;
|
||||
static const PRUint32 kViewportMinWidth = 200;
|
||||
static const PRUint32 kViewportMaxWidth = 10000;
|
||||
static const PRUint32 kViewportMinHeight = 223;
|
||||
static const PRUint32 kViewportMaxHeight = 10000;
|
||||
static const PRInt32 kViewportDefaultScreenWidth = 980;
|
||||
|
||||
static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
|
||||
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
|
||||
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
||||
@ -4556,6 +4569,198 @@ static void ProcessViewportToken(nsIDocument *aDocument,
|
||||
#define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
|
||||
(c == '\t') || (c == '\n') || (c == '\r'))
|
||||
|
||||
/* static */
|
||||
ViewportInfo
|
||||
nsContentUtils::GetViewportInfo(nsIDocument *aDocument)
|
||||
{
|
||||
ViewportInfo ret;
|
||||
ret.defaultZoom = 1.0;
|
||||
ret.autoSize = true;
|
||||
ret.allowZoom = true;
|
||||
ret.autoScale = true;
|
||||
|
||||
// If the docType specifies that we are on a site optimized for mobile,
|
||||
// then we want to return specially crafted defaults for the viewport info.
|
||||
nsCOMPtr<nsIDOMDocument>
|
||||
domDoc(do_QueryInterface(aDocument));
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentType> docType;
|
||||
nsresult rv = domDoc->GetDoctype(getter_AddRefs(docType));
|
||||
if (NS_SUCCEEDED(rv) && docType) {
|
||||
nsAutoString docId;
|
||||
rv = docType->GetPublicId(docId);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if ((docId.Find("WAP") != -1) ||
|
||||
(docId.Find("Mobile") != -1) ||
|
||||
(docId.Find("WML") != -1))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aDocument->IsXUL()) {
|
||||
ret.autoScale = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsIDOMWindow* window = aDocument->GetWindow();
|
||||
nsCOMPtr<nsIDOMWindowUtils> windowUtils(do_GetInterface(window));
|
||||
|
||||
if (!windowUtils) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsAutoString handheldFriendly;
|
||||
aDocument->GetHeaderData(nsGkAtoms::handheldFriendly, handheldFriendly);
|
||||
|
||||
if (handheldFriendly.EqualsLiteral("true")) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PRInt32 errorCode;
|
||||
|
||||
nsAutoString minScaleStr;
|
||||
aDocument->GetHeaderData(nsGkAtoms::minimum_scale, minScaleStr);
|
||||
|
||||
float scaleMinFloat = minScaleStr.ToFloat(&errorCode);
|
||||
|
||||
if (errorCode) {
|
||||
scaleMinFloat = kViewportMinScale;
|
||||
}
|
||||
|
||||
scaleMinFloat = NS_MIN(scaleMinFloat, kViewportMaxScale);
|
||||
scaleMinFloat = NS_MAX(scaleMinFloat, kViewportMinScale);
|
||||
|
||||
nsAutoString maxScaleStr;
|
||||
aDocument->GetHeaderData(nsGkAtoms::maximum_scale, maxScaleStr);
|
||||
|
||||
// We define a special error code variable for the scale and max scale,
|
||||
// because they are used later (see the width calculations).
|
||||
PRInt32 scaleMaxErrorCode;
|
||||
float scaleMaxFloat = maxScaleStr.ToFloat(&scaleMaxErrorCode);
|
||||
|
||||
if (scaleMaxErrorCode) {
|
||||
scaleMaxFloat = kViewportMaxScale;
|
||||
}
|
||||
|
||||
scaleMaxFloat = NS_MIN(scaleMaxFloat, kViewportMaxScale);
|
||||
scaleMaxFloat = NS_MAX(scaleMaxFloat, kViewportMinScale);
|
||||
|
||||
nsAutoString scaleStr;
|
||||
aDocument->GetHeaderData(nsGkAtoms::viewport_initial_scale, scaleStr);
|
||||
|
||||
PRInt32 scaleErrorCode;
|
||||
float scaleFloat = scaleStr.ToFloat(&scaleErrorCode);
|
||||
scaleFloat = NS_MIN(scaleFloat, scaleMaxFloat);
|
||||
scaleFloat = NS_MAX(scaleFloat, scaleMinFloat);
|
||||
|
||||
nsAutoString widthStr, heightStr;
|
||||
|
||||
aDocument->GetHeaderData(nsGkAtoms::viewport_height, heightStr);
|
||||
aDocument->GetHeaderData(nsGkAtoms::viewport_width, widthStr);
|
||||
|
||||
bool autoSize = false;
|
||||
|
||||
if (widthStr.EqualsLiteral("device-width")) {
|
||||
autoSize = true;
|
||||
}
|
||||
|
||||
if (widthStr.IsEmpty() &&
|
||||
(heightStr.EqualsLiteral("device-height") ||
|
||||
scaleFloat == 1.0))
|
||||
{
|
||||
autoSize = true;
|
||||
}
|
||||
|
||||
// XXXjwir3:
|
||||
// See bug 706918, comment 23 for more information on this particular section
|
||||
// of the code. We're using "screen size" in place of the size of the content
|
||||
// area, because on mobile, these are close or equal. This will work for our
|
||||
// purposes (bug 706198), but it will need to be changed in the future to be
|
||||
// more correct when we bring the rest of the viewport code into platform.
|
||||
// We actually want the size of the content area, in the event that we don't
|
||||
// have any metadata about the width and/or height. On mobile, the screen size
|
||||
// and the size of the content area are very close, or the same value.
|
||||
// In XUL fennec, the content area is the size of the <browser> widget, but
|
||||
// in native fennec, the content area is the size of the Gecko LayerView
|
||||
// object.
|
||||
|
||||
// TODO:
|
||||
// Once bug 716575 has been resolved, this code should be changed so that it
|
||||
// does the right thing on all platforms.
|
||||
nsresult result;
|
||||
PRInt32 screenLeft, screenTop, screenWidth, screenHeight;
|
||||
nsCOMPtr<nsIScreenManager> screenMgr =
|
||||
do_GetService("@mozilla.org/gfx/screenmanager;1", &result);
|
||||
|
||||
nsCOMPtr<nsIScreen> screen;
|
||||
screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
|
||||
screen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
|
||||
|
||||
PRUint32 width = widthStr.ToInteger(&errorCode);
|
||||
if (errorCode) {
|
||||
if (autoSize) {
|
||||
width = screenWidth;
|
||||
} else {
|
||||
width = Preferences::GetInt("browser.viewport.desktopWidth", 0);
|
||||
}
|
||||
}
|
||||
|
||||
width = NS_MIN(width, kViewportMaxWidth);
|
||||
width = NS_MAX(width, kViewportMinWidth);
|
||||
|
||||
// Also recalculate the default zoom, if it wasn't specified in the metadata,
|
||||
// and the width is specified.
|
||||
if (scaleStr.IsEmpty() && !widthStr.IsEmpty()) {
|
||||
scaleFloat = NS_MAX(scaleFloat, (float)(screenWidth/width));
|
||||
}
|
||||
|
||||
PRUint32 height = heightStr.ToInteger(&errorCode);
|
||||
|
||||
if (errorCode) {
|
||||
height = width * ((float)screenHeight / screenWidth);
|
||||
}
|
||||
|
||||
// If height was provided by the user, but width wasn't, then we should
|
||||
// calculate the width.
|
||||
if (widthStr.IsEmpty() && !heightStr.IsEmpty()) {
|
||||
width = (PRUint32) ((height * screenWidth) / screenHeight);
|
||||
}
|
||||
|
||||
height = NS_MIN(height, kViewportMaxHeight);
|
||||
height = NS_MAX(height, kViewportMinHeight);
|
||||
|
||||
// We need to perform a conversion, but only if the initial or maximum
|
||||
// scale were set explicitly by the user.
|
||||
if (!scaleStr.IsEmpty() && !scaleErrorCode) {
|
||||
width = NS_MAX(width, (PRUint32)(screenWidth / scaleFloat));
|
||||
height = NS_MAX(height, (PRUint32)(screenHeight / scaleFloat));
|
||||
} else if (!maxScaleStr.IsEmpty() && !scaleMaxErrorCode) {
|
||||
width = NS_MAX(width, (PRUint32)(screenWidth / scaleMaxFloat));
|
||||
height = NS_MAX(height, (PRUint32)(screenHeight / scaleMaxFloat));
|
||||
}
|
||||
|
||||
bool allowZoom = true;
|
||||
nsAutoString userScalable;
|
||||
aDocument->GetHeaderData(nsGkAtoms::viewport_user_scalable, userScalable);
|
||||
|
||||
if ((userScalable.EqualsLiteral("0")) ||
|
||||
(userScalable.EqualsLiteral("no")) ||
|
||||
(userScalable.EqualsLiteral("false"))) {
|
||||
allowZoom = false;
|
||||
}
|
||||
|
||||
ret.allowZoom = allowZoom;
|
||||
ret.width = width;
|
||||
ret.height = height;
|
||||
ret.defaultZoom = scaleFloat;
|
||||
ret.minZoom = scaleMinFloat;
|
||||
ret.maxZoom = scaleMaxFloat;
|
||||
ret.autoSize = autoSize;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
|
||||
|
@ -995,7 +995,7 @@ NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
|
||||
!Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(XP_LINUX)
|
||||
#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(LINUX)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#endif
|
||||
|
||||
|
@ -283,6 +283,9 @@ static bool gDragServiceDisabled = false;
|
||||
static FILE *gDumpFile = nsnull;
|
||||
static PRUint64 gNextWindowID = 0;
|
||||
static PRUint32 gSerialCounter = 0;
|
||||
static PRUint32 gTimeoutsRecentlySet = 0;
|
||||
static TimeStamp gLastRecordedRecentTimeouts;
|
||||
#define STATISTICS_INTERVAL (30 * PR_MSEC_PER_SEC)
|
||||
|
||||
#ifdef DEBUG_jst
|
||||
PRInt32 gTimeoutCnt = 0;
|
||||
@ -9054,6 +9057,7 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
||||
timeout->mPrincipal = ourPrincipal;
|
||||
}
|
||||
|
||||
++gTimeoutsRecentlySet;
|
||||
TimeDuration delta = TimeDuration::FromMilliseconds(realInterval);
|
||||
|
||||
if (!IsFrozen() && !mTimeoutsSuspendDepth) {
|
||||
@ -9228,6 +9232,16 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
|
||||
return;
|
||||
}
|
||||
|
||||
// Record telemetry information about timers set recently.
|
||||
TimeDuration recordingInterval = TimeDuration::FromMilliseconds(STATISTICS_INTERVAL);
|
||||
if (gLastRecordedRecentTimeouts.IsNull() ||
|
||||
now - gLastRecordedRecentTimeouts > recordingInterval) {
|
||||
PRUint32 count = gTimeoutsRecentlySet;
|
||||
gTimeoutsRecentlySet = 0;
|
||||
Telemetry::Accumulate(Telemetry::DOM_TIMERS_RECENTLY_SET, count);
|
||||
gLastRecordedRecentTimeouts = now;
|
||||
}
|
||||
|
||||
// Insert a dummy timeout into the list of timeouts between the
|
||||
// portion of the list that we are about to process now and those
|
||||
// timeouts that will be processed in a future call to
|
||||
|
@ -483,15 +483,34 @@ var WifiManager = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function parseStatus(status) {
|
||||
if (status === null) {
|
||||
debug("Unable to get wpa supplicant's status");
|
||||
return;
|
||||
}
|
||||
|
||||
var lines = status.split("\n");
|
||||
for (let i = 0; i < lines.length; ++i) {
|
||||
let [key, value] = lines[i].split("=");
|
||||
if (key === "wpa_state") {
|
||||
if (value === "COMPLETED")
|
||||
onconnected();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try to connect to the supplicant
|
||||
var connectTries = 0;
|
||||
var retryTimer = null;
|
||||
function connectCallback(ok) {
|
||||
if (ok === 0) {
|
||||
// tell the event worker to start waiting for events
|
||||
// Tell the event worker to start waiting for events.
|
||||
retryTimer = null;
|
||||
waitForEvent();
|
||||
notify("supplicantconnection");
|
||||
|
||||
// Load up the supplicant state.
|
||||
statusCommand(parseStatus);
|
||||
return;
|
||||
}
|
||||
if (connectTries++ < 3) {
|
||||
@ -788,12 +807,9 @@ function nsWifiWorker() {
|
||||
var networks = Object.create(null);
|
||||
WifiManager.onscanresultsavailable = function() {
|
||||
debug("Scan results are available! Asking for them.");
|
||||
if (networks["Mozilla Guest"])
|
||||
return;
|
||||
WifiManager.getScanResults(function(r) {
|
||||
let lines = r.split("\n");
|
||||
// NB: Skip the header line.
|
||||
let added = !("Mozilla Guest" in networks);
|
||||
for (let i = 1; i < lines.length; ++i) {
|
||||
// bssid / frequency / signal level / flags / ssid
|
||||
var match = /([\S]+)\s+([\S]+)\s+([\S]+)\s+(\[[\S]+\])?\s+(.*)/.exec(lines[i])
|
||||
@ -802,27 +818,6 @@ function nsWifiWorker() {
|
||||
else
|
||||
debug("Match didn't find anything for: " + lines[i]);
|
||||
}
|
||||
|
||||
if (("Mozilla Guest" in networks) && added) {
|
||||
debug("Mozilla Guest exists in networks, trying to connect!");
|
||||
var config = Object.create(null);
|
||||
config["ssid"] = '"Mozilla Guest"';
|
||||
//config["bssid"] = '"' + networks["Mozilla Guest"] + '"';
|
||||
config["key_mgmt"] = "NONE";
|
||||
config["scan_ssid"] = 1;
|
||||
WifiManager.addNetwork(config, function (ok) {
|
||||
if (ok) {
|
||||
WifiManager.enableNetwork(config.netId, false, function (ok) {
|
||||
if (ok)
|
||||
debug("Enabled the network!");
|
||||
else
|
||||
debug("Failed to enable the network :(");
|
||||
});
|
||||
} else {
|
||||
debug("Failed to add the network :(");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -232,16 +232,16 @@ public:
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
JS::IterateData data(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
|
||||
xpc::DestroyCompartmentName);
|
||||
nsresult rv = CollectForRuntime(/* isQuick = */false, &data);
|
||||
JS::RuntimeStats rtStats(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
|
||||
xpc::DestroyCompartmentName);
|
||||
nsresult rv = CollectForRuntime(/* isQuick = */false, &rtStats);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Always report, even if we're disabled, so that we at least get an entry
|
||||
// in about::memory.
|
||||
ReportJSRuntimeStats(data, mPathPrefix, aCallback, aClosure);
|
||||
ReportJSRuntimeStats(rtStats, mPathPrefix, aCallback, aClosure);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1524,7 +1524,7 @@ public:
|
||||
|
||||
*mSucceeded = mIsQuick
|
||||
? JS::GetExplicitNonHeapForRuntime(JS_GetRuntime(aCx), static_cast<int64_t*>(mData), xpc::JsMallocSizeOf)
|
||||
: JS::CollectCompartmentStatsForRuntime(JS_GetRuntime(aCx), static_cast<JS::IterateData*>(mData));
|
||||
: JS::CollectRuntimeStats(JS_GetRuntime(aCx), static_cast<JS::RuntimeStats*>(mData));
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
@ -165,7 +165,8 @@ gssInit()
|
||||
const char *const verLibNames[] = {
|
||||
"libgssapi_krb5.so.2", /* MIT - FC, Suse10, Debian */
|
||||
"libgssapi.so.4", /* Heimdal - Suse10, MDK */
|
||||
"libgssapi.so.1" /* Heimdal - Suse9, CITI - FC, MDK, Suse10*/
|
||||
"libgssapi.so.1", /* Heimdal - Suse9, CITI - FC, MDK, Suse10*/
|
||||
"libgssapi.so" /* OpenBSD */
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ArrayLength(verLibNames) && !lib; ++i) {
|
||||
|
@ -9143,423 +9143,425 @@
|
||||
15629,15630d21435
|
||||
< carburetter/SM
|
||||
< carburettor/SM
|
||||
15788d21592
|
||||
15701a21507
|
||||
> carnitas
|
||||
15788d21593
|
||||
< cashpoint/S
|
||||
15797d21600
|
||||
15797d21601
|
||||
< cassino/M
|
||||
15832a21636
|
||||
15832a21637
|
||||
> catalyses
|
||||
15940d21743
|
||||
15940d21744
|
||||
< caviare/M
|
||||
16372c22175
|
||||
16372c22176
|
||||
< chickenshit/S!
|
||||
---
|
||||
> chickenshit/SM!
|
||||
16404c22207
|
||||
16404c22208
|
||||
< children
|
||||
---
|
||||
> children/M
|
||||
16488d22290
|
||||
16488d22291
|
||||
< chlorophyl/M
|
||||
16629,16630c22431
|
||||
16629,16630c22432
|
||||
< cider's
|
||||
< cider/S
|
||||
---
|
||||
> cider/MS
|
||||
17072d22872
|
||||
17072d22873
|
||||
< cocain/M
|
||||
17102,17103c22902
|
||||
17102,17103c22903
|
||||
< cocksucker's
|
||||
< cocksucker/S!
|
||||
---
|
||||
> cocksucker/SM!
|
||||
17755c23554
|
||||
17755c23555
|
||||
< confer/S
|
||||
---
|
||||
> confer/SB
|
||||
18151d23949
|
||||
18151d23950
|
||||
< convenor/S
|
||||
18206c24004
|
||||
18206c24005
|
||||
< cookie/M
|
||||
---
|
||||
> cookie/SM
|
||||
18467a24266
|
||||
18467a24267
|
||||
> could've
|
||||
19246c25045
|
||||
19246c25046
|
||||
< cysteine
|
||||
---
|
||||
> cysteine/M
|
||||
20196,20197c25995,25996
|
||||
20196,20197c25996,25997
|
||||
< dialog/SM
|
||||
< dialogue/SM
|
||||
---
|
||||
> dialog/SMGD
|
||||
> dialogue/SMRGD
|
||||
20481a26281
|
||||
20481a26282
|
||||
> disclose/DSG
|
||||
20830c26630
|
||||
20830c26631
|
||||
< dogie/M
|
||||
---
|
||||
> dogie/SM
|
||||
20895a26696
|
||||
20895a26697
|
||||
> donator/MS
|
||||
21820a27622
|
||||
21820a27623
|
||||
> elicitor/MS
|
||||
22071a27874
|
||||
22071a27875
|
||||
> encyclopaedia
|
||||
22556a28360
|
||||
22556a28361
|
||||
> estoppel
|
||||
22638c28442
|
||||
22638c28443
|
||||
< euthanize
|
||||
---
|
||||
> euthanize/DSG
|
||||
22719a28524
|
||||
22719a28525
|
||||
> exabyte/MS
|
||||
22947a28753
|
||||
22947a28754
|
||||
> experimentalism
|
||||
23207,23208d29012
|
||||
23207,23208d29013
|
||||
< faecal
|
||||
< faeces/M
|
||||
23215c29019
|
||||
23215c29020
|
||||
< faggoting's
|
||||
---
|
||||
> faggot/SMG
|
||||
23701a29506
|
||||
23701a29507
|
||||
> filesystem/MS
|
||||
24155c29960
|
||||
24155c29961
|
||||
< fluidized
|
||||
---
|
||||
> fluidize/DSG
|
||||
24216a30022
|
||||
24216a30023
|
||||
> foci
|
||||
24736d30541
|
||||
24736d30542
|
||||
< frier/M
|
||||
24855,24856c30660,30661
|
||||
24855,24856c30661,30662
|
||||
< fucker/M!
|
||||
< fuckhead/S!
|
||||
---
|
||||
> fucker/SM!
|
||||
> fuckhead/SM!
|
||||
24953d30757
|
||||
24953d30758
|
||||
< furore/MS
|
||||
25125c30929
|
||||
25125c30930
|
||||
< gaolbird/S
|
||||
---
|
||||
> gaolbirds
|
||||
25180d30983
|
||||
25180d30984
|
||||
< gasolene/M
|
||||
25190a30994
|
||||
25190a30995
|
||||
> gastroenterologist/M
|
||||
25262c31066
|
||||
25262c31067
|
||||
< geezer/M
|
||||
---
|
||||
> geezer/MS
|
||||
25327c31131
|
||||
25327c31132
|
||||
< genomic
|
||||
---
|
||||
> genomic/S
|
||||
25462a31267
|
||||
25462a31268
|
||||
> gigabit/MS
|
||||
25464a31270,31272
|
||||
25464a31271,31273
|
||||
> gigajoule/MS
|
||||
> gigapixel/MS
|
||||
> gigawatt/MS
|
||||
25560d31367
|
||||
25560d31368
|
||||
< glamourize/DSG
|
||||
25674c31481
|
||||
25674c31482
|
||||
< glycerine's
|
||||
---
|
||||
> glycerine/M
|
||||
25905c31712
|
||||
25905c31713
|
||||
< gram/MS
|
||||
---
|
||||
> gram/KMS
|
||||
25909d31715
|
||||
25909d31716
|
||||
< gramme/SM
|
||||
26063c31869,31870
|
||||
26063c31870,31871
|
||||
< greybeard
|
||||
---
|
||||
> grey/MDRTGSP
|
||||
> greybeard/SM
|
||||
26066c31873
|
||||
26066c31874
|
||||
< greyness
|
||||
---
|
||||
> greyness/M
|
||||
26246,26247d32052
|
||||
26246,26247d32053
|
||||
< guerilla's
|
||||
< guerillas
|
||||
26432,26436d32236
|
||||
26432,26436d32237
|
||||
< haemoglobin's
|
||||
< haemophilia/M
|
||||
< haemorrhage/DSMG
|
||||
< haemorrhoid/S
|
||||
< haemorrhoids/M
|
||||
27167c32967
|
||||
27167c32968
|
||||
< hexane
|
||||
---
|
||||
> hexane/SM
|
||||
27273a33074
|
||||
27273a33075
|
||||
> hippopotami
|
||||
27875d33675
|
||||
27875d33676
|
||||
< hyaena/SM
|
||||
28017c33817
|
||||
28017c33818
|
||||
< iPod/M
|
||||
---
|
||||
> iPod/MS
|
||||
28105a33906
|
||||
28105a33907
|
||||
> idolator/SM
|
||||
28513c34314
|
||||
28513c34315
|
||||
< inbound
|
||||
---
|
||||
> inbound/s
|
||||
28650a34452
|
||||
28650a34453
|
||||
> indices
|
||||
28812d34613
|
||||
28812d34614
|
||||
< inflexion/SM
|
||||
29216a35018
|
||||
29216a35019
|
||||
> intern/GDL
|
||||
29272a35075,35078
|
||||
29272a35076,35079
|
||||
> intersex
|
||||
> intersexual/MS
|
||||
> intersexualism
|
||||
> intersexuality
|
||||
29724c35530
|
||||
29724c35531
|
||||
< jewellery's
|
||||
---
|
||||
> jewellery/M
|
||||
29870a35677
|
||||
29870a35678
|
||||
> judgement/MS
|
||||
30066c35873
|
||||
30066c35874
|
||||
< kiddie/M
|
||||
---
|
||||
> kiddie/SM
|
||||
30262,30263c36069
|
||||
30262,30263c36070
|
||||
< kraut's
|
||||
< kraut/S!
|
||||
---
|
||||
> kraut/MS!
|
||||
30665a36472
|
||||
30665a36473
|
||||
> lector/MS
|
||||
31031c36838
|
||||
31031c36839
|
||||
< linguini's
|
||||
---
|
||||
> linguini/M
|
||||
31151,31152c36958
|
||||
31151,31152c36959
|
||||
< liver's
|
||||
< liver/S
|
||||
---
|
||||
> liver/MS
|
||||
32230c38036
|
||||
32230c38037
|
||||
< meanie/M
|
||||
---
|
||||
> meanie/MS
|
||||
32317,32318c38123
|
||||
32317,32318c38124
|
||||
< megadeath/M
|
||||
< megadeaths
|
||||
---
|
||||
> megadeath/SM
|
||||
32320c38125
|
||||
32320c38126
|
||||
< megajoules
|
||||
---
|
||||
> megajoule/SM
|
||||
32329c38134
|
||||
32329c38135
|
||||
< megapixel/S
|
||||
---
|
||||
> megapixel/MS
|
||||
32708a38514
|
||||
32708a38515
|
||||
> might've
|
||||
32777d38582
|
||||
32777d38583
|
||||
< millionnaire/M
|
||||
32934a38740
|
||||
32934a38741
|
||||
> miscommunication/S
|
||||
32991a38798
|
||||
32991a38799
|
||||
> misjudgement/MS
|
||||
33784a39592
|
||||
33784a39593
|
||||
> must've
|
||||
33963c39771
|
||||
33963c39772
|
||||
< native/MS
|
||||
---
|
||||
> native/MSY
|
||||
34169,34171c39977,39978
|
||||
34169,34171c39978,39979
|
||||
< neurone/S
|
||||
< neurophysiology
|
||||
< neuroscience
|
||||
---
|
||||
> neurophysiology/M
|
||||
> neuroscience/MS
|
||||
34275c40082
|
||||
34275c40083
|
||||
< nightie/M
|
||||
---
|
||||
> nightie/SM
|
||||
35104a40912
|
||||
35104a40913
|
||||
> octopi
|
||||
35219d41026
|
||||
35219d41027
|
||||
< oleomargarin/M
|
||||
35226a41034
|
||||
35226a41035
|
||||
> oligo
|
||||
35913c41721
|
||||
35913c41722
|
||||
< oversize/D
|
||||
---
|
||||
> oversize
|
||||
36056,36059d41863
|
||||
36056,36059d41864
|
||||
< paederast/S
|
||||
< paediatrician's
|
||||
< paediatricians
|
||||
< paediatrics/M
|
||||
36291a42096
|
||||
36291a42097
|
||||
> paralyses
|
||||
36403d42207
|
||||
36403d42208
|
||||
< parrakeet/MS
|
||||
36449d42252
|
||||
36449d42253
|
||||
< partizan/SM
|
||||
37093a42897
|
||||
37093a42898
|
||||
> petabyte/MS
|
||||
37102c42906
|
||||
37102c42907
|
||||
< petitioner/M
|
||||
---
|
||||
> petitioner/MS
|
||||
37264a43069
|
||||
37264a43070
|
||||
> phosphorylate/DSGN
|
||||
37316d43120
|
||||
37316d43121
|
||||
< phrenetic
|
||||
37796a43601
|
||||
37796a43602
|
||||
> plugin/MS
|
||||
37987c43792
|
||||
37987c43793
|
||||
< polypeptide/S
|
||||
---
|
||||
> polypeptide/MS
|
||||
38291d44095
|
||||
38291d44096
|
||||
< practise's
|
||||
38451a44256
|
||||
38451a44257
|
||||
> prejudgement/MS
|
||||
38891a44697,44698
|
||||
38891a44698,44699
|
||||
> pronate/DSGN
|
||||
> pronator/MS
|
||||
38951c44758
|
||||
38951c44759
|
||||
< proprietorship/M
|
||||
---
|
||||
> proprietorship/MS
|
||||
39039a44847
|
||||
39039a44848
|
||||
> provender/M
|
||||
40036a45845
|
||||
40036a45846
|
||||
> recency
|
||||
40141a45951
|
||||
40141a45952
|
||||
> recuse/DGS
|
||||
40208a46019
|
||||
40208a46020
|
||||
> refactor/SMDG
|
||||
40244d46054
|
||||
40244d46055
|
||||
< reflexion/SM
|
||||
40829c46639
|
||||
40829c46640
|
||||
< reverie/M
|
||||
---
|
||||
> reverie/MS
|
||||
41415a47226
|
||||
41415a47227
|
||||
> sabre/MS
|
||||
41914c47725
|
||||
41914c47726
|
||||
< schnaps's
|
||||
---
|
||||
> schnaps/M
|
||||
41949c47760
|
||||
41949c47761
|
||||
< schrod's
|
||||
---
|
||||
> schrod/SM
|
||||
41998a42010
|
||||
41998a47811
|
||||
> scot-free
|
||||
42883,42885c48695
|
||||
42883,42885c48696
|
||||
< shit's
|
||||
< shit/S!
|
||||
< shite/S!
|
||||
---
|
||||
> shit/MS!
|
||||
42887,42888c48697,48698
|
||||
42887,42888c48698,48699
|
||||
< shithead/S!
|
||||
< shitload/!
|
||||
---
|
||||
> shithead/MS!
|
||||
> shitload/MS!
|
||||
42891c48701
|
||||
42891c48702
|
||||
< shitty/RT!
|
||||
---
|
||||
> shitty/TR!
|
||||
42976a48787
|
||||
42976a48788
|
||||
> should've
|
||||
43008c48819
|
||||
43008c48820
|
||||
< showtime
|
||||
---
|
||||
> showtime/MS
|
||||
43724,43726c49535
|
||||
43724,43726c49536
|
||||
< smoulder's
|
||||
< smouldered
|
||||
< smoulders
|
||||
---
|
||||
> smoulder/GSMD
|
||||
44062c49871
|
||||
44062c49872
|
||||
< sonofabitch
|
||||
---
|
||||
> sonofabitch/!
|
||||
44371a50181
|
||||
44371a50182
|
||||
> spick/S!
|
||||
44383c50193
|
||||
44383c50194
|
||||
< spik/S
|
||||
---
|
||||
> spik/S!
|
||||
46106a51917
|
||||
46106a51918
|
||||
> syllabi
|
||||
46160c51971
|
||||
46160c51972
|
||||
< synch/GMD
|
||||
---
|
||||
> synch/GMDS
|
||||
46167d51977
|
||||
46167d51978
|
||||
< synchs
|
||||
46203,46204c52013,52014
|
||||
46203,46204c52014,52015
|
||||
< sysadmin/S
|
||||
< sysop/S
|
||||
---
|
||||
> sysadmin/MS
|
||||
> sysop/MS
|
||||
46752a52563
|
||||
46752a52564
|
||||
> terabit/MS
|
||||
46753a52565,52566
|
||||
46753a52566,52567
|
||||
> terahertz/M
|
||||
> terapixel/MS
|
||||
46817a52631
|
||||
46817a52632
|
||||
> testcase/MS
|
||||
46831a52646
|
||||
46831a52647
|
||||
> testsuite/MS
|
||||
46925a52741
|
||||
46925a52742
|
||||
> theremin/MS
|
||||
47755a53572
|
||||
47755a53573
|
||||
> transfect/DSMG
|
||||
47774a53592,53593
|
||||
47774a53593,53594
|
||||
> transgenderism
|
||||
> transgene/MS
|
||||
47951c53770
|
||||
47951c53771
|
||||
< triage/M
|
||||
---
|
||||
> triage/MG
|
||||
48869a54689
|
||||
48869a54690
|
||||
> unlikeable
|
||||
49211c55031
|
||||
49211c55032
|
||||
< vagina/M
|
||||
---
|
||||
> vagina/MS
|
||||
49368,49369c55188
|
||||
49368,49369c55189
|
||||
< velour's
|
||||
< velours's
|
||||
---
|
||||
> velour/MS
|
||||
49478a55298
|
||||
49478a55299
|
||||
> vertices
|
||||
50148a55969
|
||||
50148a55970
|
||||
> weaponize/DSG
|
||||
50260,50261d56080
|
||||
50260,50261d56081
|
||||
< werwolf/M
|
||||
< werwolves
|
||||
50728c56547
|
||||
50728c56548
|
||||
< women
|
||||
---
|
||||
> women/M
|
||||
50794c56613
|
||||
50794c56614
|
||||
< wop/S!
|
||||
---
|
||||
> wop/MS!
|
||||
|
@ -1,4 +1,4 @@
|
||||
57435
|
||||
57436
|
||||
0/nm
|
||||
0th/pt
|
||||
1/n1
|
||||
@ -21765,6 +21765,7 @@ carnality/M
|
||||
carnation/IMS
|
||||
carnelian/MS
|
||||
carney/MS
|
||||
carnitas
|
||||
carnival/MS
|
||||
carnivore/SM
|
||||
carnivorous/YP
|
||||
|
@ -901,6 +901,14 @@ DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
|
||||
// so flip it to the top left
|
||||
CGContextTranslateCTM(mCg, 0, mSize.height);
|
||||
CGContextScaleCTM(mCg, 1, -1);
|
||||
// See Bug 722164 for performance details
|
||||
// Medium or higher quality lead to expensive interpolation
|
||||
// for canvas we want to use low quality interpolation
|
||||
// to have competitive performance with other canvas
|
||||
// implementation.
|
||||
// XXX: Create input parameter to control interpolation and
|
||||
// use the default for content.
|
||||
CGContextSetInterpolationQuality(mCg, kCGInterpolationLow);
|
||||
|
||||
//XXX: set correct format
|
||||
mFormat = FORMAT_B8G8R8A8;
|
||||
|
@ -1985,6 +1985,12 @@ DrawTargetD2D::CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix
|
||||
// surface.
|
||||
uploadRect = uploadRect.Intersect(rect);
|
||||
|
||||
if (uploadRect.IsEmpty()) {
|
||||
// This bitmap does not cover anything on the screen. XXX -
|
||||
// we need to deal with EXTEND modes here!
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uploadRect.width <= mRT->GetMaximumBitmapSize() &&
|
||||
uploadRect.height <= mRT->GetMaximumBitmapSize()) {
|
||||
|
||||
|
@ -97,7 +97,7 @@ Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFor
|
||||
}
|
||||
break;
|
||||
}
|
||||
#elif defined XP_MACOSX || defined ANDROID
|
||||
#elif defined XP_MACOSX || defined ANDROID || defined LINUX
|
||||
#ifdef USE_SKIA
|
||||
case BACKEND_SKIA:
|
||||
{
|
||||
|
@ -166,12 +166,37 @@ SourceSurfaceD2DTarget::GetBitmap(ID2D1RenderTarget *aRT)
|
||||
AlphaMode(mFormat))),
|
||||
byRef(mBitmap));
|
||||
|
||||
RefPtr<ID2D1RenderTarget> rt;
|
||||
|
||||
if (mDrawTarget) {
|
||||
mBitmap->CopyFromRenderTarget(NULL, mDrawTarget->mRT, NULL);
|
||||
return mBitmap;
|
||||
rt = mDrawTarget->mRT;
|
||||
}
|
||||
gfxWarning() << "Failed to create shared bitmap for DrawTarget snapshot. Code: " << hr;
|
||||
return NULL;
|
||||
|
||||
if (!rt) {
|
||||
// Okay, we already separated from our drawtarget. And we're an A8
|
||||
// surface the only way we can get to a bitmap is by creating a
|
||||
// a rendertarget and from there copying to a bitmap! Terrible!
|
||||
RefPtr<IDXGISurface> surface;
|
||||
|
||||
hr = mTexture->QueryInterface((IDXGISurface**)byRef(surface));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to QI texture to surface.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D2D1_RENDER_TARGET_PROPERTIES props =
|
||||
D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGIFormat(mFormat), AlphaMode(mFormat)));
|
||||
hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(surface, props, byRef(rt));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to create D2D render target for texture.";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mBitmap->CopyFromRenderTarget(NULL, rt, NULL);
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
return mBitmap;
|
||||
|
@ -178,6 +178,8 @@ unicode-printing.patch: Print as unicode (bug 454532)
|
||||
|
||||
quartz-mark-dirty.patch: Add a quartz implementation of mark_dirty_rectangle (bug 715704)
|
||||
|
||||
expose-snapshot.patch: Make functions to add snapshots public, as well as allow creating null surfaces publically. (bug 715658)
|
||||
|
||||
==== pixman patches ====
|
||||
|
||||
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
|
||||
|
@ -70,9 +70,6 @@ cairo_private cairo_int_status_t
|
||||
_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
|
||||
cairo_int_status_t status_b);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_null_surface_create (cairo_content_t content);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_ANALYSIS_SURFACE_H */
|
||||
|
@ -907,7 +907,7 @@ static const cairo_surface_backend_t cairo_null_surface_backend = {
|
||||
};
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_null_surface_create (cairo_content_t content)
|
||||
cairo_null_surface_create (cairo_content_t content)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
|
||||
|
@ -1956,14 +1956,14 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
srcSurf->data,
|
||||
srcSurf->stride);
|
||||
cairo_surface_t *nullSurf =
|
||||
_cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cachebitmap->refs++;
|
||||
cachebitmap->dirty = false;
|
||||
cairo_surface_set_user_data(nullSurf,
|
||||
&bitmap_key_snapshot,
|
||||
cachebitmap,
|
||||
NULL);
|
||||
_cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
nullSurf,
|
||||
_d2d_snapshot_detached);
|
||||
}
|
||||
@ -2020,12 +2020,12 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
cachebitmap,
|
||||
_d2d_release_bitmap);
|
||||
cairo_surface_t *nullSurf =
|
||||
_cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cairo_surface_set_user_data(nullSurf,
|
||||
&bitmap_key_snapshot,
|
||||
cachebitmap,
|
||||
NULL);
|
||||
_cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
nullSurf,
|
||||
_d2d_snapshot_detached);
|
||||
cache_usage += _d2d_compute_bitmap_mem_size(sourceBitmap);
|
||||
|
@ -281,7 +281,7 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface,
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_surface_attach_snapshot (&surface->base, image, NULL);
|
||||
cairo_surface_attach_snapshot (&surface->base, image, NULL);
|
||||
|
||||
*image_out = (cairo_image_surface_t *) image;
|
||||
*image_extra = NULL;
|
||||
@ -1051,7 +1051,7 @@ _recording_surface_get_ink_bbox (cairo_recording_surface_t *surface,
|
||||
cairo_surface_t *analysis_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
null_surface = _cairo_null_surface_create (surface->content);
|
||||
null_surface = cairo_null_surface_create (surface->content);
|
||||
analysis_surface = _cairo_analysis_surface_create (null_surface);
|
||||
cairo_surface_destroy (null_surface);
|
||||
|
||||
|
@ -45,8 +45,6 @@
|
||||
#include "cairo-reference-count-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
typedef void (*cairo_surface_func_t) (cairo_surface_t *);
|
||||
|
||||
struct _cairo_surface {
|
||||
const cairo_surface_backend_t *backend;
|
||||
cairo_device_t *device;
|
||||
|
@ -214,7 +214,7 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
|
||||
snap->device_transform = surface->device_transform;
|
||||
snap->device_transform_inverse = surface->device_transform_inverse;
|
||||
|
||||
_cairo_surface_attach_snapshot (surface, snap, NULL);
|
||||
cairo_surface_attach_snapshot (surface, snap, NULL);
|
||||
|
||||
return snap;
|
||||
}
|
||||
@ -247,7 +247,7 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
|
||||
snapshot->base.device_transform = surface->device_transform;
|
||||
snapshot->base.device_transform_inverse = surface->device_transform_inverse;
|
||||
|
||||
_cairo_surface_attach_snapshot (surface,
|
||||
cairo_surface_attach_snapshot (surface,
|
||||
&snapshot->base,
|
||||
_cairo_surface_snapshot_copy_on_write);
|
||||
|
||||
|
@ -331,7 +331,7 @@ _cairo_surface_subsurface_acquire_source_image (void *abstrac
|
||||
|
||||
cairo_surface_paint_to_target (&image->base, surface);
|
||||
|
||||
_cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
|
||||
*image_out = image;
|
||||
*extra_out = NULL;
|
||||
|
@ -310,17 +310,17 @@ _cairo_surface_detach_mime_data (cairo_surface_t *surface)
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_surface_detach_snapshots (cairo_surface_t *surface)
|
||||
cairo_surface_detach_snapshots (cairo_surface_t *surface)
|
||||
{
|
||||
while (_cairo_surface_has_snapshots (surface)) {
|
||||
_cairo_surface_detach_snapshot (cairo_list_first_entry (&surface->snapshots,
|
||||
cairo_surface_detach_snapshot (cairo_list_first_entry (&surface->snapshots,
|
||||
cairo_surface_t,
|
||||
snapshot));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
|
||||
cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
|
||||
{
|
||||
assert (snapshot->snapshot_of != NULL);
|
||||
|
||||
@ -334,7 +334,7 @@ _cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
cairo_surface_t *snapshot,
|
||||
cairo_surface_func_t detach_func)
|
||||
{
|
||||
@ -344,7 +344,7 @@ _cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
cairo_surface_reference (snapshot);
|
||||
|
||||
if (snapshot->snapshot_of != NULL)
|
||||
_cairo_surface_detach_snapshot (snapshot);
|
||||
cairo_surface_detach_snapshot (snapshot);
|
||||
|
||||
snapshot->snapshot_of = surface;
|
||||
snapshot->snapshot_detach = detach_func;
|
||||
@ -387,7 +387,7 @@ _cairo_surface_begin_modification (cairo_surface_t *surface)
|
||||
assert (! surface->finished);
|
||||
assert (surface->snapshot_of == NULL);
|
||||
|
||||
_cairo_surface_detach_snapshots (surface);
|
||||
cairo_surface_detach_snapshots (surface);
|
||||
_cairo_surface_detach_mime_data (surface);
|
||||
}
|
||||
|
||||
@ -716,9 +716,9 @@ cairo_surface_finish (cairo_surface_t *surface)
|
||||
return;
|
||||
|
||||
/* update the snapshots *before* we declare the surface as finished */
|
||||
_cairo_surface_detach_snapshots (surface);
|
||||
cairo_surface_detach_snapshots (surface);
|
||||
if (surface->snapshot_of != NULL)
|
||||
_cairo_surface_detach_snapshot (surface);
|
||||
cairo_surface_detach_snapshot (surface);
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
surface->finished = TRUE;
|
||||
@ -1111,7 +1111,7 @@ cairo_surface_flush (cairo_surface_t *surface)
|
||||
return;
|
||||
|
||||
/* update the current snapshots *before* the user updates the surface */
|
||||
_cairo_surface_detach_snapshots (surface);
|
||||
cairo_surface_detach_snapshots (surface);
|
||||
|
||||
if (surface->backend->flush) {
|
||||
status = surface->backend->flush (surface);
|
||||
@ -1633,7 +1633,7 @@ _cairo_recording_surface_clone_similar (cairo_surface_t *surface,
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_surface_attach_snapshot (src, similar, NULL);
|
||||
cairo_surface_attach_snapshot (src, similar, NULL);
|
||||
|
||||
src_x = src_y = 0;
|
||||
}
|
||||
|
@ -982,7 +982,7 @@ _vg_setup_surface_source (cairo_vg_context_t *context,
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_surface_attach_snapshot (spat->surface, &clone->base,
|
||||
cairo_surface_attach_snapshot (spat->surface, &clone->base,
|
||||
_vg_surface_remove_from_cache);
|
||||
|
||||
DONE:
|
||||
|
@ -565,7 +565,7 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
|
||||
DONE:
|
||||
*image_out = image;
|
||||
@ -718,7 +718,7 @@ _cairo_xcb_surface_flush (void *abstract_surface)
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
_cairo_surface_attach_snapshot (&surface->base,
|
||||
cairo_surface_attach_snapshot (&surface->base,
|
||||
surface->fallback,
|
||||
cairo_surface_finish);
|
||||
}
|
||||
|
@ -218,6 +218,15 @@ typedef struct _cairo_pattern cairo_pattern_t;
|
||||
**/
|
||||
typedef void (*cairo_destroy_func_t) (void *data);
|
||||
|
||||
/**
|
||||
* cairo_surface_func_t:
|
||||
* @surface: The surface being referred to.
|
||||
*
|
||||
* #cairo_surface_func_t the type of function which is used for callback
|
||||
* when a surface needs to be apssed as a parameter.
|
||||
*/
|
||||
typedef void (*cairo_surface_func_t) (cairo_surface_t *surface);
|
||||
|
||||
/**
|
||||
* cairo_user_data_key_t:
|
||||
* @unused: not used; ignore.
|
||||
@ -2155,6 +2164,14 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
cairo_public void
|
||||
cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
cairo_surface_t *snapshot,
|
||||
cairo_surface_func_t detach_func);
|
||||
|
||||
cairo_public void
|
||||
cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
|
||||
|
||||
#define CAIRO_MIME_TYPE_JPEG "image/jpeg"
|
||||
#define CAIRO_MIME_TYPE_PNG "image/png"
|
||||
#define CAIRO_MIME_TYPE_JP2 "image/jp2"
|
||||
@ -2333,6 +2350,11 @@ cairo_recording_surface_ink_extents (cairo_surface_t *surface,
|
||||
double *width,
|
||||
double *height);
|
||||
|
||||
/* Null-surface functions */
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_null_surface_create (cairo_content_t content);
|
||||
|
||||
/* Pattern creation functions */
|
||||
|
||||
cairo_public cairo_pattern_t *
|
||||
|
@ -1775,17 +1775,9 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_snapshot (cairo_surface_t *surface);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
cairo_surface_t *snapshot,
|
||||
cairo_surface_func_t detach_func);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_has_snapshot (cairo_surface_t *surface,
|
||||
const cairo_surface_backend_t *backend);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
|
||||
const cairo_surface_backend_t *backend);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_similar (cairo_surface_t *surface_a,
|
||||
|
528
gfx/cairo/expose-snapshot.patch
Normal file
528
gfx/cairo/expose-snapshot.patch
Normal file
@ -0,0 +1,528 @@
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
|
||||
--- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
|
||||
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h
|
||||
@@ -65,14 +65,11 @@ _cairo_analysis_surface_has_unsupported
|
||||
cairo_private void
|
||||
_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
|
||||
cairo_box_t *bbox);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
|
||||
cairo_int_status_t status_b);
|
||||
|
||||
-cairo_private cairo_surface_t *
|
||||
-_cairo_null_surface_create (cairo_content_t content);
|
||||
-
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_ANALYSIS_SURFACE_H */
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-analysis-surface.c b/gfx/cairo/cairo/src/cairo-analysis-surface.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
|
||||
@@ -902,17 +902,17 @@ static const cairo_surface_backend_t cai
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
NULL, /* has_show_text_glyphs */
|
||||
NULL /* show_text_glyphs */
|
||||
};
|
||||
|
||||
cairo_surface_t *
|
||||
-_cairo_null_surface_create (cairo_content_t content)
|
||||
+cairo_null_surface_create (cairo_content_t content)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
|
||||
surface = malloc (sizeof (cairo_surface_t));
|
||||
if (unlikely (surface == NULL)) {
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
|
||||
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
|
||||
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
|
||||
@@ -1951,24 +1951,24 @@ _cairo_d2d_create_brush_for_pattern(cair
|
||||
rect = D2D1::RectU(1, 1, srcSurf->width + 1, srcSurf->height + 1);
|
||||
} else {
|
||||
rect = D2D1::RectU(0, 0, srcSurf->width, srcSurf->height);
|
||||
}
|
||||
sourceBitmap->CopyFromMemory(&rect,
|
||||
srcSurf->data,
|
||||
srcSurf->stride);
|
||||
cairo_surface_t *nullSurf =
|
||||
- _cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
+ cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cachebitmap->refs++;
|
||||
cachebitmap->dirty = false;
|
||||
cairo_surface_set_user_data(nullSurf,
|
||||
&bitmap_key_snapshot,
|
||||
cachebitmap,
|
||||
NULL);
|
||||
- _cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
+ cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
nullSurf,
|
||||
_d2d_snapshot_detached);
|
||||
}
|
||||
} else {
|
||||
if (pattern->extend != CAIRO_EXTEND_NONE) {
|
||||
d2dsurf->rt->CreateBitmap(D2D1::SizeU(width, height),
|
||||
data + yoffset * stride + xoffset * Bpp,
|
||||
stride,
|
||||
@@ -2015,22 +2015,22 @@ _cairo_d2d_create_brush_for_pattern(cair
|
||||
* and one more in the user data structure.
|
||||
*/
|
||||
cachebitmap->refs = 2;
|
||||
cairo_surface_set_user_data(surfacePattern->surface,
|
||||
key,
|
||||
cachebitmap,
|
||||
_d2d_release_bitmap);
|
||||
cairo_surface_t *nullSurf =
|
||||
- _cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
+ cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cairo_surface_set_user_data(nullSurf,
|
||||
&bitmap_key_snapshot,
|
||||
cachebitmap,
|
||||
NULL);
|
||||
- _cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
+ cairo_surface_attach_snapshot(surfacePattern->surface,
|
||||
nullSurf,
|
||||
_d2d_snapshot_detached);
|
||||
cache_usage += _d2d_compute_bitmap_mem_size(sourceBitmap);
|
||||
}
|
||||
if (pix_image) {
|
||||
pixman_image_unref(pix_image);
|
||||
}
|
||||
}
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-recording-surface.c b/gfx/cairo/cairo/src/cairo-recording-surface.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-recording-surface.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-recording-surface.c
|
||||
@@ -276,17 +276,17 @@ _cairo_recording_surface_acquire_source_
|
||||
-surface->extents.y);
|
||||
|
||||
status = _cairo_recording_surface_replay (&surface->base, image);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (image);
|
||||
return status;
|
||||
}
|
||||
|
||||
- _cairo_surface_attach_snapshot (&surface->base, image, NULL);
|
||||
+ cairo_surface_attach_snapshot (&surface->base, image, NULL);
|
||||
|
||||
*image_out = (cairo_image_surface_t *) image;
|
||||
*image_extra = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_recording_surface_release_source_image (void *abstract_surface,
|
||||
@@ -1046,17 +1046,17 @@ static cairo_status_t
|
||||
_recording_surface_get_ink_bbox (cairo_recording_surface_t *surface,
|
||||
cairo_box_t *bbox,
|
||||
const cairo_matrix_t *transform)
|
||||
{
|
||||
cairo_surface_t *null_surface;
|
||||
cairo_surface_t *analysis_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
- null_surface = _cairo_null_surface_create (surface->content);
|
||||
+ null_surface = cairo_null_surface_create (surface->content);
|
||||
analysis_surface = _cairo_analysis_surface_create (null_surface);
|
||||
cairo_surface_destroy (null_surface);
|
||||
|
||||
status = analysis_surface->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (transform != NULL)
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-surface-private.h b/gfx/cairo/cairo/src/cairo-surface-private.h
|
||||
--- a/gfx/cairo/cairo/src/cairo-surface-private.h
|
||||
+++ b/gfx/cairo/cairo/src/cairo-surface-private.h
|
||||
@@ -40,18 +40,16 @@
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-list-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
-typedef void (*cairo_surface_func_t) (cairo_surface_t *);
|
||||
-
|
||||
struct _cairo_surface {
|
||||
const cairo_surface_backend_t *backend;
|
||||
cairo_device_t *device;
|
||||
|
||||
/* We allow surfaces to override the backend->type by shoving something
|
||||
* else into surface->type. This is for "wrapper" surfaces that want to
|
||||
* hide their internal type from the user-level API. */
|
||||
cairo_surface_type_t type;
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-surface-snapshot.c b/gfx/cairo/cairo/src/cairo-surface-snapshot.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-surface-snapshot.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-surface-snapshot.c
|
||||
@@ -209,17 +209,17 @@ _cairo_surface_snapshot (cairo_surface_t
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (snap);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
snap->device_transform = surface->device_transform;
|
||||
snap->device_transform_inverse = surface->device_transform_inverse;
|
||||
|
||||
- _cairo_surface_attach_snapshot (surface, snap, NULL);
|
||||
+ cairo_surface_attach_snapshot (surface, snap, NULL);
|
||||
|
||||
return snap;
|
||||
}
|
||||
}
|
||||
|
||||
snapshot = (cairo_surface_snapshot_t *)
|
||||
_cairo_surface_has_snapshot (surface, &_cairo_surface_snapshot_backend);
|
||||
if (snapshot != NULL)
|
||||
@@ -242,14 +242,14 @@ _cairo_surface_snapshot (cairo_surface_t
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&snapshot->base);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
snapshot->base.device_transform = surface->device_transform;
|
||||
snapshot->base.device_transform_inverse = surface->device_transform_inverse;
|
||||
|
||||
- _cairo_surface_attach_snapshot (surface,
|
||||
+ cairo_surface_attach_snapshot (surface,
|
||||
&snapshot->base,
|
||||
_cairo_surface_snapshot_copy_on_write);
|
||||
|
||||
return &snapshot->base;
|
||||
}
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-surface-subsurface.c b/gfx/cairo/cairo/src/cairo-surface-subsurface.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-surface-subsurface.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-surface-subsurface.c
|
||||
@@ -326,17 +326,17 @@ _cairo_surface_subsurface_acquire_source
|
||||
_cairo_image_surface_create_with_content (meta->content,
|
||||
surface->extents.width,
|
||||
surface->extents.height);
|
||||
if (unlikely (image->base.status))
|
||||
return image->base.status;
|
||||
|
||||
cairo_surface_paint_to_target (&image->base, surface);
|
||||
|
||||
- _cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
+ cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
|
||||
*image_out = image;
|
||||
*extra_out = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
extra = malloc (sizeof (struct extra));
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-surface.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-surface.c
|
||||
@@ -305,51 +305,51 @@ _cairo_surface_detach_mime_data (cairo_s
|
||||
if (! _cairo_surface_has_mime_data (surface))
|
||||
return;
|
||||
|
||||
_cairo_user_data_array_fini (&surface->mime_data);
|
||||
_cairo_user_data_array_init (&surface->mime_data);
|
||||
}
|
||||
|
||||
static void
|
||||
-_cairo_surface_detach_snapshots (cairo_surface_t *surface)
|
||||
+cairo_surface_detach_snapshots (cairo_surface_t *surface)
|
||||
{
|
||||
while (_cairo_surface_has_snapshots (surface)) {
|
||||
- _cairo_surface_detach_snapshot (cairo_list_first_entry (&surface->snapshots,
|
||||
+ cairo_surface_detach_snapshot (cairo_list_first_entry (&surface->snapshots,
|
||||
cairo_surface_t,
|
||||
snapshot));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
-_cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
|
||||
+cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
|
||||
{
|
||||
assert (snapshot->snapshot_of != NULL);
|
||||
|
||||
snapshot->snapshot_of = NULL;
|
||||
cairo_list_del (&snapshot->snapshot);
|
||||
|
||||
if (snapshot->snapshot_detach != NULL)
|
||||
snapshot->snapshot_detach (snapshot);
|
||||
|
||||
cairo_surface_destroy (snapshot);
|
||||
}
|
||||
|
||||
void
|
||||
-_cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
+cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
cairo_surface_t *snapshot,
|
||||
cairo_surface_func_t detach_func)
|
||||
{
|
||||
assert (surface != snapshot);
|
||||
assert (snapshot->snapshot_of != surface);
|
||||
|
||||
cairo_surface_reference (snapshot);
|
||||
|
||||
if (snapshot->snapshot_of != NULL)
|
||||
- _cairo_surface_detach_snapshot (snapshot);
|
||||
+ cairo_surface_detach_snapshot (snapshot);
|
||||
|
||||
snapshot->snapshot_of = surface;
|
||||
snapshot->snapshot_detach = detach_func;
|
||||
|
||||
cairo_list_add (&snapshot->snapshot, &surface->snapshots);
|
||||
|
||||
assert (_cairo_surface_has_snapshot (surface, snapshot->backend) == snapshot);
|
||||
}
|
||||
@@ -382,17 +382,17 @@ _cairo_surface_is_writable (cairo_surfac
|
||||
|
||||
static void
|
||||
_cairo_surface_begin_modification (cairo_surface_t *surface)
|
||||
{
|
||||
assert (surface->status == CAIRO_STATUS_SUCCESS);
|
||||
assert (! surface->finished);
|
||||
assert (surface->snapshot_of == NULL);
|
||||
|
||||
- _cairo_surface_detach_snapshots (surface);
|
||||
+ cairo_surface_detach_snapshots (surface);
|
||||
_cairo_surface_detach_mime_data (surface);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_init (cairo_surface_t *surface,
|
||||
const cairo_surface_backend_t *backend,
|
||||
cairo_device_t *device,
|
||||
cairo_content_t content)
|
||||
@@ -711,19 +711,19 @@ cairo_surface_finish (cairo_surface_t *s
|
||||
|
||||
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
|
||||
return;
|
||||
|
||||
if (surface->finished)
|
||||
return;
|
||||
|
||||
/* update the snapshots *before* we declare the surface as finished */
|
||||
- _cairo_surface_detach_snapshots (surface);
|
||||
+ cairo_surface_detach_snapshots (surface);
|
||||
if (surface->snapshot_of != NULL)
|
||||
- _cairo_surface_detach_snapshot (surface);
|
||||
+ cairo_surface_detach_snapshot (surface);
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
surface->finished = TRUE;
|
||||
|
||||
/* call finish even if in error mode */
|
||||
if (surface->backend->finish) {
|
||||
status = surface->backend->finish (surface);
|
||||
if (unlikely (status))
|
||||
@@ -1106,17 +1106,17 @@ cairo_surface_flush (cairo_surface_t *su
|
||||
|
||||
if (surface->status)
|
||||
return;
|
||||
|
||||
if (surface->finished)
|
||||
return;
|
||||
|
||||
/* update the current snapshots *before* the user updates the surface */
|
||||
- _cairo_surface_detach_snapshots (surface);
|
||||
+ cairo_surface_detach_snapshots (surface);
|
||||
|
||||
if (surface->backend->flush) {
|
||||
status = surface->backend->flush (surface);
|
||||
if (unlikely (status))
|
||||
status = _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
}
|
||||
slim_hidden_def (cairo_surface_flush);
|
||||
@@ -1628,17 +1628,17 @@ _cairo_recording_surface_clone_similar (
|
||||
return similar->status;
|
||||
|
||||
status = _cairo_recording_surface_replay (src, similar);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (similar);
|
||||
return status;
|
||||
}
|
||||
|
||||
- _cairo_surface_attach_snapshot (src, similar, NULL);
|
||||
+ cairo_surface_attach_snapshot (src, similar, NULL);
|
||||
|
||||
src_x = src_y = 0;
|
||||
}
|
||||
|
||||
*clone_out = similar;
|
||||
*clone_offset_x = src_x;
|
||||
*clone_offset_y = src_y;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-vg-surface.c b/gfx/cairo/cairo/src/cairo-vg-surface.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-vg-surface.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-vg-surface.c
|
||||
@@ -977,17 +977,17 @@ _vg_setup_surface_source (cairo_vg_conte
|
||||
status = _cairo_cache_insert (&context->snapshot_cache,
|
||||
&clone->snapshot_cache_entry);
|
||||
if (unlikely (status)) {
|
||||
clone->snapshot_cache_entry.hash = 0;
|
||||
cairo_surface_destroy (&clone->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
- _cairo_surface_attach_snapshot (spat->surface, &clone->base,
|
||||
+ cairo_surface_attach_snapshot (spat->surface, &clone->base,
|
||||
_vg_surface_remove_from_cache);
|
||||
|
||||
DONE:
|
||||
cairo_surface_destroy (&context->source->base);
|
||||
context->source = clone;
|
||||
|
||||
vgSetParameteri (context->paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
|
||||
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo-xcb-surface.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-xcb-surface.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-xcb-surface.c
|
||||
@@ -560,17 +560,17 @@ _cairo_xcb_surface_acquire_source_image
|
||||
image = (cairo_image_surface_t *) cairo_surface_reference (&image->base);
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
status = _get_image (surface, FALSE, &image);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
- _cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
+ cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
|
||||
DONE:
|
||||
*image_out = image;
|
||||
*image_extra = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -713,17 +713,17 @@ _cairo_xcb_surface_flush (void *abstract
|
||||
status = cairo_surface_status (surface->fallback);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
status = _put_image (surface,
|
||||
(cairo_image_surface_t *) surface->fallback);
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
- _cairo_surface_attach_snapshot (&surface->base,
|
||||
+ cairo_surface_attach_snapshot (&surface->base,
|
||||
surface->fallback,
|
||||
cairo_surface_finish);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface->fallback);
|
||||
surface->fallback = NULL;
|
||||
|
||||
diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h
|
||||
--- a/gfx/cairo/cairo/src/cairo.h
|
||||
+++ b/gfx/cairo/cairo/src/cairo.h
|
||||
@@ -214,16 +214,25 @@ typedef struct _cairo_pattern cairo_patt
|
||||
*
|
||||
* #cairo_destroy_func_t the type of function which is called when a
|
||||
* data element is destroyed. It is passed the pointer to the data
|
||||
* element and should free any memory and resources allocated for it.
|
||||
**/
|
||||
typedef void (*cairo_destroy_func_t) (void *data);
|
||||
|
||||
/**
|
||||
+ * cairo_surface_func_t:
|
||||
+ * @surface: The surface being referred to.
|
||||
+ *
|
||||
+ * #cairo_surface_func_t the type of function which is used for callback
|
||||
+ * when a surface needs to be apssed as a parameter.
|
||||
+ */
|
||||
+typedef void (*cairo_surface_func_t) (cairo_surface_t *surface);
|
||||
+
|
||||
+/**
|
||||
* cairo_user_data_key_t:
|
||||
* @unused: not used; ignore.
|
||||
*
|
||||
* #cairo_user_data_key_t is used for attaching user data to cairo
|
||||
* data structures. The actual contents of the struct is never used,
|
||||
* and there is no need to initialize the object; only the unique
|
||||
* address of a #cairo_data_key_t object is used. Typically, you
|
||||
* would just use the address of a static #cairo_data_key_t object.
|
||||
@@ -2150,16 +2159,24 @@ cairo_surface_get_user_data (cairo_surfa
|
||||
const cairo_user_data_key_t *key);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_set_user_data (cairo_surface_t *surface,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
+cairo_public void
|
||||
+cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
+ cairo_surface_t *snapshot,
|
||||
+ cairo_surface_func_t detach_func);
|
||||
+
|
||||
+cairo_public void
|
||||
+cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
|
||||
+
|
||||
#define CAIRO_MIME_TYPE_JPEG "image/jpeg"
|
||||
#define CAIRO_MIME_TYPE_PNG "image/png"
|
||||
#define CAIRO_MIME_TYPE_JP2 "image/jp2"
|
||||
#define CAIRO_MIME_TYPE_URI "text/x-uri"
|
||||
|
||||
cairo_public void
|
||||
cairo_surface_get_mime_data (cairo_surface_t *surface,
|
||||
const char *mime_type,
|
||||
@@ -2328,16 +2345,21 @@ cairo_recording_surface_create (cairo_co
|
||||
|
||||
cairo_public void
|
||||
cairo_recording_surface_ink_extents (cairo_surface_t *surface,
|
||||
double *x0,
|
||||
double *y0,
|
||||
double *width,
|
||||
double *height);
|
||||
|
||||
+/* Null-surface functions */
|
||||
+
|
||||
+cairo_public cairo_surface_t *
|
||||
+cairo_null_surface_create (cairo_content_t content);
|
||||
+
|
||||
/* Pattern creation functions */
|
||||
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_create_rgb (double red, double green, double blue);
|
||||
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_create_rgba (double red, double green, double blue,
|
||||
double alpha);
|
||||
diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h
|
||||
--- a/gfx/cairo/cairo/src/cairoint.h
|
||||
+++ b/gfx/cairo/cairo/src/cairoint.h
|
||||
@@ -1770,27 +1770,19 @@ _cairo_surface_clone_similar (cairo_surf
|
||||
int height,
|
||||
int *clone_offset_x,
|
||||
int *clone_offset_y,
|
||||
cairo_surface_t **clone_out);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_snapshot (cairo_surface_t *surface);
|
||||
|
||||
-cairo_private void
|
||||
-_cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
||||
- cairo_surface_t *snapshot,
|
||||
- cairo_surface_func_t detach_func);
|
||||
-
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_has_snapshot (cairo_surface_t *surface,
|
||||
- const cairo_surface_backend_t *backend);
|
||||
-
|
||||
-cairo_private void
|
||||
-_cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
|
||||
+ const cairo_surface_backend_t *backend);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_similar (cairo_surface_t *surface_a,
|
||||
cairo_surface_t *surface_b);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_get_extents (cairo_surface_t *surface,
|
||||
cairo_rectangle_int_t *extents);
|
@ -309,7 +309,9 @@ endif
|
||||
|
||||
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += \
|
||||
SkFontHost_none.cpp \
|
||||
SkFontHost_FreeType.cpp \
|
||||
SkFontHost_android.cpp \
|
||||
SkFontHost_gamma.cpp \
|
||||
SkMMapStream.cpp \
|
||||
SkTime_Unix.cpp \
|
||||
$(NULL)
|
||||
@ -321,8 +323,8 @@ endif
|
||||
ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += \
|
||||
SkFontHost_FreeType.cpp \
|
||||
SkFontHost_gamma_none.cpp \
|
||||
SkFontHost_linux.cpp \
|
||||
SkFontHost_gamma.cpp \
|
||||
SkTime_Unix.cpp \
|
||||
SkMMapStream.cpp \
|
||||
SkOSFile.cpp \
|
||||
|
530
gfx/skia/old-android-fonthost.patch
Normal file
530
gfx/skia/old-android-fonthost.patch
Normal file
@ -0,0 +1,530 @@
|
||||
# HG changeset patch
|
||||
# Parent 9ee29e4aace683ddf6cf8ddb2893cd34fcfc772c
|
||||
# User James Willcox <jwillcox@mozilla.com>
|
||||
diff --git a/gfx/skia/Makefile.in b/gfx/skia/Makefile.in
|
||||
--- a/gfx/skia/Makefile.in
|
||||
+++ b/gfx/skia/Makefile.in
|
||||
@@ -305,21 +305,20 @@ CPPSRCS += \
|
||||
SkFontHost_mac_coretext.cpp \
|
||||
SkTime_Unix.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += \
|
||||
SkFontHost_FreeType.cpp \
|
||||
SkFontHost_android.cpp \
|
||||
SkFontHost_gamma.cpp \
|
||||
- FontHostConfiguration_android.cpp \
|
||||
SkMMapStream.cpp \
|
||||
SkTime_Unix.cpp \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DSK_BUILD_FOR_ANDROID_NDK
|
||||
OS_CXXFLAGS += $(CAIRO_FT_CFLAGS)
|
||||
endif
|
||||
|
||||
ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += \
|
||||
diff --git a/gfx/skia/src/ports/SkFontHost_android.cpp b/gfx/skia/src/ports/SkFontHost_android.cpp
|
||||
--- a/gfx/skia/src/ports/SkFontHost_android.cpp
|
||||
+++ b/gfx/skia/src/ports/SkFontHost_android.cpp
|
||||
@@ -1,38 +1,31 @@
|
||||
+
|
||||
/*
|
||||
-**
|
||||
-** Copyright 2006, The Android Open Source Project
|
||||
-**
|
||||
-** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-** you may not use this file except in compliance with the License.
|
||||
-** You may obtain a copy of the License at
|
||||
-**
|
||||
-** http://www.apache.org/licenses/LICENSE-2.0
|
||||
-**
|
||||
-** Unless required by applicable law or agreed to in writing, software
|
||||
-** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-** See the License for the specific language governing permissions and
|
||||
-** limitations under the License.
|
||||
-*/
|
||||
+ * Copyright 2006 The Android Open Source Project
|
||||
+ *
|
||||
+ * Use of this source code is governed by a BSD-style license that can be
|
||||
+ * found in the LICENSE file.
|
||||
+ */
|
||||
+
|
||||
|
||||
#include "SkFontHost.h"
|
||||
#include "SkDescriptor.h"
|
||||
#include "SkMMapStream.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkString.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkThread.h"
|
||||
#include "SkTSearch.h"
|
||||
-#include "FontHostConfiguration_android.h"
|
||||
#include <stdio.h>
|
||||
|
||||
+#define FONT_CACHE_MEMORY_BUDGET (768 * 1024)
|
||||
+
|
||||
#ifndef SK_FONT_FILE_PREFIX
|
||||
#define SK_FONT_FILE_PREFIX "/fonts/"
|
||||
#endif
|
||||
|
||||
SkTypeface::Style find_name_and_attributes(SkStream* stream, SkString* name,
|
||||
bool* isFixedWidth);
|
||||
|
||||
static void GetFullPathForSysFonts(SkString* full, const char name[]) {
|
||||
full->set(getenv("ANDROID_ROOT"));
|
||||
full->append(SK_FONT_FILE_PREFIX);
|
||||
@@ -99,21 +92,21 @@ static SkTypeface* find_best_face(const
|
||||
if (faces[SkTypeface::kNormal] != NULL) {
|
||||
return faces[SkTypeface::kNormal];
|
||||
}
|
||||
// look for anything
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (faces[i] != NULL) {
|
||||
return faces[i];
|
||||
}
|
||||
}
|
||||
// should never get here, since the faces list should not be empty
|
||||
- SkDEBUGFAIL("faces list is empty");
|
||||
+ SkASSERT(!"faces list is empty");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static FamilyRec* find_family(const SkTypeface* member) {
|
||||
FamilyRec* curr = gFamilyHead;
|
||||
while (curr != NULL) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (curr->fFaces[i] == member) {
|
||||
return curr;
|
||||
}
|
||||
@@ -138,31 +131,27 @@ static SkTypeface* find_from_uniqueID(ui
|
||||
curr = curr->fNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove reference to this face from its family. If the resulting family
|
||||
is empty (has no faces), return that family, otherwise return NULL
|
||||
*/
|
||||
static FamilyRec* remove_from_family(const SkTypeface* face) {
|
||||
FamilyRec* family = find_family(face);
|
||||
- if (family) {
|
||||
- SkASSERT(family->fFaces[face->style()] == face);
|
||||
- family->fFaces[face->style()] = NULL;
|
||||
+ SkASSERT(family->fFaces[face->style()] == face);
|
||||
+ family->fFaces[face->style()] = NULL;
|
||||
|
||||
- for (int i = 0; i < 4; i++) {
|
||||
- if (family->fFaces[i] != NULL) { // family is non-empty
|
||||
- return NULL;
|
||||
- }
|
||||
+ for (int i = 0; i < 4; i++) {
|
||||
+ if (family->fFaces[i] != NULL) { // family is non-empty
|
||||
+ return NULL;
|
||||
}
|
||||
- } else {
|
||||
-// SkDebugf("remove_from_family(%p) face not found", face);
|
||||
}
|
||||
return family; // return the empty family
|
||||
}
|
||||
|
||||
// maybe we should make FamilyRec be doubly-linked
|
||||
static void detach_and_delete_family(FamilyRec* family) {
|
||||
FamilyRec* curr = gFamilyHead;
|
||||
FamilyRec* prev = NULL;
|
||||
|
||||
while (curr != NULL) {
|
||||
@@ -172,21 +161,21 @@ static void detach_and_delete_family(Fam
|
||||
gFamilyHead = next;
|
||||
} else {
|
||||
prev->fNext = next;
|
||||
}
|
||||
SkDELETE(family);
|
||||
return;
|
||||
}
|
||||
prev = curr;
|
||||
curr = next;
|
||||
}
|
||||
- SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete");
|
||||
+ SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
|
||||
}
|
||||
|
||||
static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
|
||||
NameFamilyPair* list = gNameList.begin();
|
||||
int count = gNameList.count();
|
||||
|
||||
int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
|
||||
|
||||
if (index >= 0) {
|
||||
return find_best_face(list[index].fFamily, style);
|
||||
@@ -387,111 +376,90 @@ static bool get_name_and_style(const cha
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// used to record our notion of the pre-existing fonts
|
||||
struct FontInitRec {
|
||||
const char* fFileName;
|
||||
const char* const* fNames; // null-terminated list
|
||||
};
|
||||
|
||||
+static const char* gSansNames[] = {
|
||||
+ "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
|
||||
+};
|
||||
+
|
||||
+static const char* gSerifNames[] = {
|
||||
+ "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
|
||||
+ "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
|
||||
+};
|
||||
+
|
||||
+static const char* gMonoNames[] = {
|
||||
+ "monospace", "courier", "courier new", "monaco", NULL
|
||||
+};
|
||||
+
|
||||
// deliberately empty, but we use the address to identify fallback fonts
|
||||
static const char* gFBNames[] = { NULL };
|
||||
|
||||
+/* Fonts must be grouped by family, with the first font in a family having the
|
||||
+ list of names (even if that list is empty), and the following members having
|
||||
+ null for the list. The names list must be NULL-terminated
|
||||
+*/
|
||||
+static const FontInitRec gSystemFonts[] = {
|
||||
+ { "DroidSans.ttf", gSansNames },
|
||||
+ { "DroidSans-Bold.ttf", NULL },
|
||||
+ { "DroidSerif-Regular.ttf", gSerifNames },
|
||||
+ { "DroidSerif-Bold.ttf", NULL },
|
||||
+ { "DroidSerif-Italic.ttf", NULL },
|
||||
+ { "DroidSerif-BoldItalic.ttf", NULL },
|
||||
+ { "DroidSansMono.ttf", gMonoNames },
|
||||
+ /* These are optional, and can be ignored if not found in the file system.
|
||||
+ These are appended to gFallbackFonts[] as they are seen, so we list
|
||||
+ them in the order we want them to be accessed by NextLogicalFont().
|
||||
+ */
|
||||
+ { "DroidSansArabic.ttf", gFBNames },
|
||||
+ { "DroidSansHebrew.ttf", gFBNames },
|
||||
+ { "DroidSansThai.ttf", gFBNames },
|
||||
+ { "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font
|
||||
+ { "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font
|
||||
+ { "DroidSansJapanese.ttf", gFBNames },
|
||||
+ { "DroidSansFallback.ttf", gFBNames }
|
||||
+};
|
||||
|
||||
-/* Fonts are grouped by family, with the first font in a family having the
|
||||
- list of names (even if that list is empty), and the following members having
|
||||
- null for the list. The names list must be NULL-terminated.
|
||||
-*/
|
||||
-static FontInitRec *gSystemFonts;
|
||||
-static size_t gNumSystemFonts = 0;
|
||||
-
|
||||
-#define SYSTEM_FONTS_FILE "/system/etc/system_fonts.cfg"
|
||||
+#define DEFAULT_NAMES gSansNames
|
||||
|
||||
// these globals are assigned (once) by load_system_fonts()
|
||||
static FamilyRec* gDefaultFamily;
|
||||
static SkTypeface* gDefaultNormal;
|
||||
-static char** gDefaultNames = NULL;
|
||||
-static uint32_t *gFallbackFonts;
|
||||
|
||||
-/* Load info from a configuration file that populates the system/fallback font structures
|
||||
-*/
|
||||
-static void load_font_info() {
|
||||
-// load_font_info_xml("/system/etc/system_fonts.xml");
|
||||
- SkTDArray<FontFamily*> fontFamilies;
|
||||
- getFontFamilies(fontFamilies);
|
||||
-
|
||||
- SkTDArray<FontInitRec> fontInfo;
|
||||
- bool firstInFamily = false;
|
||||
- for (int i = 0; i < fontFamilies.count(); ++i) {
|
||||
- FontFamily *family = fontFamilies[i];
|
||||
- firstInFamily = true;
|
||||
- for (int j = 0; j < family->fFileNames.count(); ++j) {
|
||||
- FontInitRec fontInfoRecord;
|
||||
- fontInfoRecord.fFileName = family->fFileNames[j];
|
||||
- if (j == 0) {
|
||||
- if (family->fNames.count() == 0) {
|
||||
- // Fallback font
|
||||
- fontInfoRecord.fNames = (char **)gFBNames;
|
||||
- } else {
|
||||
- SkTDArray<const char*> names = family->fNames;
|
||||
- const char **nameList = (const char**)
|
||||
- malloc((names.count() + 1) * sizeof(char*));
|
||||
- if (nameList == NULL) {
|
||||
- // shouldn't get here
|
||||
- break;
|
||||
- }
|
||||
- if (gDefaultNames == NULL) {
|
||||
- gDefaultNames = (char**) nameList;
|
||||
- }
|
||||
- for (int i = 0; i < names.count(); ++i) {
|
||||
- nameList[i] = names[i];
|
||||
- }
|
||||
- nameList[names.count()] = NULL;
|
||||
- fontInfoRecord.fNames = nameList;
|
||||
- }
|
||||
- } else {
|
||||
- fontInfoRecord.fNames = NULL;
|
||||
- }
|
||||
- *fontInfo.append() = fontInfoRecord;
|
||||
- }
|
||||
- }
|
||||
- gNumSystemFonts = fontInfo.count();
|
||||
- gSystemFonts = (FontInitRec*) malloc(gNumSystemFonts * sizeof(FontInitRec));
|
||||
- gFallbackFonts = (uint32_t*) malloc((gNumSystemFonts + 1) * sizeof(uint32_t));
|
||||
- if (gSystemFonts == NULL) {
|
||||
- // shouldn't get here
|
||||
- gNumSystemFonts = 0;
|
||||
- }
|
||||
- for (size_t i = 0; i < gNumSystemFonts; ++i) {
|
||||
- gSystemFonts[i].fFileName = fontInfo[i].fFileName;
|
||||
- gSystemFonts[i].fNames = fontInfo[i].fNames;
|
||||
- }
|
||||
- fontFamilies.deleteAll();
|
||||
-}
|
||||
+/* This is sized conservatively, assuming that it will never be a size issue.
|
||||
+ It will be initialized in load_system_fonts(), and will be filled with the
|
||||
+ fontIDs that can be used for fallback consideration, in sorted order (sorted
|
||||
+ meaning element[0] should be used first, then element[1], etc. When we hit
|
||||
+ a fontID==0 in the array, the list is done, hence our allocation size is
|
||||
+ +1 the total number of possible system fonts. Also see NextLogicalFont().
|
||||
+ */
|
||||
+static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
|
||||
|
||||
/* Called once (ensured by the sentinel check at the beginning of our body).
|
||||
Initializes all the globals, and register the system fonts.
|
||||
*/
|
||||
static void load_system_fonts() {
|
||||
// check if we've already be called
|
||||
if (NULL != gDefaultNormal) {
|
||||
return;
|
||||
}
|
||||
|
||||
- load_font_info();
|
||||
-
|
||||
const FontInitRec* rec = gSystemFonts;
|
||||
SkTypeface* firstInFamily = NULL;
|
||||
int fallbackCount = 0;
|
||||
|
||||
- for (size_t i = 0; i < gNumSystemFonts; i++) {
|
||||
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
|
||||
// if we're the first in a new family, clear firstInFamily
|
||||
if (rec[i].fNames != NULL) {
|
||||
firstInFamily = NULL;
|
||||
}
|
||||
|
||||
bool isFixedWidth;
|
||||
SkString name;
|
||||
SkTypeface::Style style;
|
||||
|
||||
// we expect all the fonts, except the "fallback" fonts
|
||||
@@ -515,120 +483,75 @@ static void load_system_fonts() {
|
||||
// SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
|
||||
// rec[i].fFileName, fallbackCount, tf->uniqueID());
|
||||
gFallbackFonts[fallbackCount++] = tf->uniqueID();
|
||||
}
|
||||
|
||||
firstInFamily = tf;
|
||||
FamilyRec* family = find_family(tf);
|
||||
const char* const* names = rec[i].fNames;
|
||||
|
||||
// record the default family if this is it
|
||||
- if (names == gDefaultNames) {
|
||||
+ if (names == DEFAULT_NAMES) {
|
||||
gDefaultFamily = family;
|
||||
}
|
||||
// add the names to map to this family
|
||||
while (*names) {
|
||||
add_name(*names, family);
|
||||
names += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do this after all fonts are loaded. This is our default font, and it
|
||||
// acts as a sentinel so we only execute load_system_fonts() once
|
||||
gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
|
||||
// now terminate our fallback list with the sentinel value
|
||||
gFallbackFonts[fallbackCount] = 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
|
||||
- // lookup and record if the font is custom (i.e. not a system font)
|
||||
- bool isCustomFont = !((FamilyTypeface*)face)->isSysFont();
|
||||
- stream->writeBool(isCustomFont);
|
||||
+ const char* name = ((FamilyTypeface*)face)->getUniqueString();
|
||||
|
||||
- if (isCustomFont) {
|
||||
- SkStream* fontStream = ((FamilyTypeface*)face)->openStream();
|
||||
+ stream->write8((uint8_t)face->style());
|
||||
|
||||
- // store the length of the custom font
|
||||
- uint32_t len = fontStream->getLength();
|
||||
- stream->write32(len);
|
||||
-
|
||||
- // store the entire font in the serialized stream
|
||||
- void* fontData = malloc(len);
|
||||
-
|
||||
- fontStream->read(fontData, len);
|
||||
- stream->write(fontData, len);
|
||||
-
|
||||
- fontStream->unref();
|
||||
- free(fontData);
|
||||
-// SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len);
|
||||
-
|
||||
+ if (NULL == name || 0 == *name) {
|
||||
+ stream->writePackedUInt(0);
|
||||
+// SkDebugf("--- fonthost serialize null\n");
|
||||
} else {
|
||||
- const char* name = ((FamilyTypeface*)face)->getUniqueString();
|
||||
-
|
||||
- stream->write8((uint8_t)face->style());
|
||||
-
|
||||
- if (NULL == name || 0 == *name) {
|
||||
- stream->writePackedUInt(0);
|
||||
-// SkDebugf("--- fonthost serialize null\n");
|
||||
- } else {
|
||||
- uint32_t len = strlen(name);
|
||||
- stream->writePackedUInt(len);
|
||||
- stream->write(name, len);
|
||||
-// SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
|
||||
- }
|
||||
+ uint32_t len = strlen(name);
|
||||
+ stream->writePackedUInt(len);
|
||||
+ stream->write(name, len);
|
||||
+// SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
|
||||
}
|
||||
}
|
||||
|
||||
SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
|
||||
load_system_fonts();
|
||||
|
||||
- // check if the font is a custom or system font
|
||||
- bool isCustomFont = stream->readBool();
|
||||
+ int style = stream->readU8();
|
||||
|
||||
- if (isCustomFont) {
|
||||
+ int len = stream->readPackedUInt();
|
||||
+ if (len > 0) {
|
||||
+ SkString str;
|
||||
+ str.resize(len);
|
||||
+ stream->read(str.writable_str(), len);
|
||||
|
||||
- // read the length of the custom font from the stream
|
||||
- uint32_t len = stream->readU32();
|
||||
-
|
||||
- // generate a new stream to store the custom typeface
|
||||
- SkMemoryStream* fontStream = new SkMemoryStream(len);
|
||||
- stream->read((void*)fontStream->getMemoryBase(), len);
|
||||
-
|
||||
- SkTypeface* face = CreateTypefaceFromStream(fontStream);
|
||||
-
|
||||
- fontStream->unref();
|
||||
-
|
||||
-// SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len);
|
||||
- return face;
|
||||
-
|
||||
- } else {
|
||||
- int style = stream->readU8();
|
||||
-
|
||||
- int len = stream->readPackedUInt();
|
||||
- if (len > 0) {
|
||||
- SkString str;
|
||||
- str.resize(len);
|
||||
- stream->read(str.writable_str(), len);
|
||||
-
|
||||
- const FontInitRec* rec = gSystemFonts;
|
||||
- for (size_t i = 0; i < gNumSystemFonts; i++) {
|
||||
- if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
|
||||
- // backup until we hit the fNames
|
||||
- for (int j = i; j >= 0; --j) {
|
||||
- if (rec[j].fNames != NULL) {
|
||||
- return SkFontHost::CreateTypeface(NULL,
|
||||
- rec[j].fNames[0], NULL, 0,
|
||||
- (SkTypeface::Style)style);
|
||||
- }
|
||||
+ const FontInitRec* rec = gSystemFonts;
|
||||
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
|
||||
+ if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
|
||||
+ // backup until we hit the fNames
|
||||
+ for (int j = i; j >= 0; --j) {
|
||||
+ if (rec[j].fNames != NULL) {
|
||||
+ return SkFontHost::CreateTypeface(NULL,
|
||||
+ rec[j].fNames[0], NULL, 0, (SkTypeface::Style)style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -697,49 +620,32 @@ size_t SkFontHost::GetFileName(SkFontID
|
||||
}
|
||||
return size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
|
||||
load_system_fonts();
|
||||
|
||||
- const SkTypeface* origTypeface = find_from_uniqueID(origFontID);
|
||||
- const SkTypeface* currTypeface = find_from_uniqueID(currFontID);
|
||||
-
|
||||
- SkASSERT(origTypeface != 0);
|
||||
- SkASSERT(currTypeface != 0);
|
||||
-
|
||||
- // Our fallback list always stores the id of the plain in each fallback
|
||||
- // family, so we transform currFontID to its plain equivalent.
|
||||
- currFontID = find_typeface(currTypeface, SkTypeface::kNormal)->uniqueID();
|
||||
-
|
||||
/* First see if fontID is already one of our fallbacks. If so, return
|
||||
its successor. If fontID is not in our list, then return the first one
|
||||
in our list. Note: list is zero-terminated, and returning zero means
|
||||
we have no more fonts to use for fallbacks.
|
||||
*/
|
||||
const uint32_t* list = gFallbackFonts;
|
||||
for (int i = 0; list[i] != 0; i++) {
|
||||
if (list[i] == currFontID) {
|
||||
- if (list[i+1] == 0)
|
||||
- return 0;
|
||||
- const SkTypeface* nextTypeface = find_from_uniqueID(list[i+1]);
|
||||
- return find_typeface(nextTypeface, origTypeface->style())->uniqueID();
|
||||
+ return list[i+1];
|
||||
}
|
||||
}
|
||||
-
|
||||
- // If we get here, currFontID was not a fallback, so we start at the
|
||||
- // beginning of our list.
|
||||
- const SkTypeface* firstTypeface = find_from_uniqueID(list[0]);
|
||||
- return find_typeface(firstTypeface, origTypeface->style())->uniqueID();
|
||||
+ return list[0];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
||||
if (NULL == stream || stream->getLength() <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool isFixedWidth;
|
||||
@@ -754,10 +660,11 @@ SkTypeface* SkFontHost::CreateTypefaceFr
|
||||
}
|
||||
|
||||
SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
||||
SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
|
||||
SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
|
||||
// since we created the stream, we let go of our ref() here
|
||||
stream->unref();
|
||||
return face;
|
||||
}
|
||||
|
||||
+///////////////////////////////////////////////////////////////////////////////
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "FontHostConfiguration_android.h"
|
||||
#include <expat_config.h>
|
||||
#include <expat.h>
|
||||
#include "SkTDArray.h"
|
||||
|
||||
|
@ -1,19 +1,11 @@
|
||||
|
||||
/*
|
||||
**
|
||||
** Copyright 2006, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
* Copyright 2006 The Android Open Source Project
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#include "SkFontHost.h"
|
||||
#include "SkDescriptor.h"
|
||||
@ -23,9 +15,10 @@
|
||||
#include "SkStream.h"
|
||||
#include "SkThread.h"
|
||||
#include "SkTSearch.h"
|
||||
#include "FontHostConfiguration_android.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define FONT_CACHE_MEMORY_BUDGET (768 * 1024)
|
||||
|
||||
#ifndef SK_FONT_FILE_PREFIX
|
||||
#define SK_FONT_FILE_PREFIX "/fonts/"
|
||||
#endif
|
||||
@ -106,7 +99,7 @@ static SkTypeface* find_best_face(const FamilyRec* family,
|
||||
}
|
||||
}
|
||||
// should never get here, since the faces list should not be empty
|
||||
SkDEBUGFAIL("faces list is empty");
|
||||
SkASSERT(!"faces list is empty");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -145,17 +138,13 @@ static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
|
||||
*/
|
||||
static FamilyRec* remove_from_family(const SkTypeface* face) {
|
||||
FamilyRec* family = find_family(face);
|
||||
if (family) {
|
||||
SkASSERT(family->fFaces[face->style()] == face);
|
||||
family->fFaces[face->style()] = NULL;
|
||||
SkASSERT(family->fFaces[face->style()] == face);
|
||||
family->fFaces[face->style()] = NULL;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (family->fFaces[i] != NULL) { // family is non-empty
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (family->fFaces[i] != NULL) { // family is non-empty
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
// SkDebugf("remove_from_family(%p) face not found", face);
|
||||
}
|
||||
return family; // return the empty family
|
||||
}
|
||||
@ -179,7 +168,7 @@ static void detach_and_delete_family(FamilyRec* family) {
|
||||
prev = curr;
|
||||
curr = next;
|
||||
}
|
||||
SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete");
|
||||
SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
|
||||
}
|
||||
|
||||
static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
|
||||
@ -394,80 +383,61 @@ struct FontInitRec {
|
||||
const char* const* fNames; // null-terminated list
|
||||
};
|
||||
|
||||
static const char* gSansNames[] = {
|
||||
"sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
|
||||
};
|
||||
|
||||
static const char* gSerifNames[] = {
|
||||
"serif", "times", "times new roman", "palatino", "georgia", "baskerville",
|
||||
"goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
|
||||
};
|
||||
|
||||
static const char* gMonoNames[] = {
|
||||
"monospace", "courier", "courier new", "monaco", NULL
|
||||
};
|
||||
|
||||
// deliberately empty, but we use the address to identify fallback fonts
|
||||
static const char* gFBNames[] = { NULL };
|
||||
|
||||
|
||||
/* Fonts are grouped by family, with the first font in a family having the
|
||||
/* Fonts must be grouped by family, with the first font in a family having the
|
||||
list of names (even if that list is empty), and the following members having
|
||||
null for the list. The names list must be NULL-terminated.
|
||||
null for the list. The names list must be NULL-terminated
|
||||
*/
|
||||
static FontInitRec *gSystemFonts;
|
||||
static size_t gNumSystemFonts = 0;
|
||||
static const FontInitRec gSystemFonts[] = {
|
||||
{ "DroidSans.ttf", gSansNames },
|
||||
{ "DroidSans-Bold.ttf", NULL },
|
||||
{ "DroidSerif-Regular.ttf", gSerifNames },
|
||||
{ "DroidSerif-Bold.ttf", NULL },
|
||||
{ "DroidSerif-Italic.ttf", NULL },
|
||||
{ "DroidSerif-BoldItalic.ttf", NULL },
|
||||
{ "DroidSansMono.ttf", gMonoNames },
|
||||
/* These are optional, and can be ignored if not found in the file system.
|
||||
These are appended to gFallbackFonts[] as they are seen, so we list
|
||||
them in the order we want them to be accessed by NextLogicalFont().
|
||||
*/
|
||||
{ "DroidSansArabic.ttf", gFBNames },
|
||||
{ "DroidSansHebrew.ttf", gFBNames },
|
||||
{ "DroidSansThai.ttf", gFBNames },
|
||||
{ "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font
|
||||
{ "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font
|
||||
{ "DroidSansJapanese.ttf", gFBNames },
|
||||
{ "DroidSansFallback.ttf", gFBNames }
|
||||
};
|
||||
|
||||
#define SYSTEM_FONTS_FILE "/system/etc/system_fonts.cfg"
|
||||
#define DEFAULT_NAMES gSansNames
|
||||
|
||||
// these globals are assigned (once) by load_system_fonts()
|
||||
static FamilyRec* gDefaultFamily;
|
||||
static SkTypeface* gDefaultNormal;
|
||||
static char** gDefaultNames = NULL;
|
||||
static uint32_t *gFallbackFonts;
|
||||
|
||||
/* Load info from a configuration file that populates the system/fallback font structures
|
||||
*/
|
||||
static void load_font_info() {
|
||||
// load_font_info_xml("/system/etc/system_fonts.xml");
|
||||
SkTDArray<FontFamily*> fontFamilies;
|
||||
getFontFamilies(fontFamilies);
|
||||
|
||||
SkTDArray<FontInitRec> fontInfo;
|
||||
bool firstInFamily = false;
|
||||
for (int i = 0; i < fontFamilies.count(); ++i) {
|
||||
FontFamily *family = fontFamilies[i];
|
||||
firstInFamily = true;
|
||||
for (int j = 0; j < family->fFileNames.count(); ++j) {
|
||||
FontInitRec fontInfoRecord;
|
||||
fontInfoRecord.fFileName = family->fFileNames[j];
|
||||
if (j == 0) {
|
||||
if (family->fNames.count() == 0) {
|
||||
// Fallback font
|
||||
fontInfoRecord.fNames = (char **)gFBNames;
|
||||
} else {
|
||||
SkTDArray<const char*> names = family->fNames;
|
||||
const char **nameList = (const char**)
|
||||
malloc((names.count() + 1) * sizeof(char*));
|
||||
if (nameList == NULL) {
|
||||
// shouldn't get here
|
||||
break;
|
||||
}
|
||||
if (gDefaultNames == NULL) {
|
||||
gDefaultNames = (char**) nameList;
|
||||
}
|
||||
for (int i = 0; i < names.count(); ++i) {
|
||||
nameList[i] = names[i];
|
||||
}
|
||||
nameList[names.count()] = NULL;
|
||||
fontInfoRecord.fNames = nameList;
|
||||
}
|
||||
} else {
|
||||
fontInfoRecord.fNames = NULL;
|
||||
}
|
||||
*fontInfo.append() = fontInfoRecord;
|
||||
}
|
||||
}
|
||||
gNumSystemFonts = fontInfo.count();
|
||||
gSystemFonts = (FontInitRec*) malloc(gNumSystemFonts * sizeof(FontInitRec));
|
||||
gFallbackFonts = (uint32_t*) malloc((gNumSystemFonts + 1) * sizeof(uint32_t));
|
||||
if (gSystemFonts == NULL) {
|
||||
// shouldn't get here
|
||||
gNumSystemFonts = 0;
|
||||
}
|
||||
for (size_t i = 0; i < gNumSystemFonts; ++i) {
|
||||
gSystemFonts[i].fFileName = fontInfo[i].fFileName;
|
||||
gSystemFonts[i].fNames = fontInfo[i].fNames;
|
||||
}
|
||||
fontFamilies.deleteAll();
|
||||
}
|
||||
/* This is sized conservatively, assuming that it will never be a size issue.
|
||||
It will be initialized in load_system_fonts(), and will be filled with the
|
||||
fontIDs that can be used for fallback consideration, in sorted order (sorted
|
||||
meaning element[0] should be used first, then element[1], etc. When we hit
|
||||
a fontID==0 in the array, the list is done, hence our allocation size is
|
||||
+1 the total number of possible system fonts. Also see NextLogicalFont().
|
||||
*/
|
||||
static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
|
||||
|
||||
/* Called once (ensured by the sentinel check at the beginning of our body).
|
||||
Initializes all the globals, and register the system fonts.
|
||||
@ -478,13 +448,11 @@ static void load_system_fonts() {
|
||||
return;
|
||||
}
|
||||
|
||||
load_font_info();
|
||||
|
||||
const FontInitRec* rec = gSystemFonts;
|
||||
SkTypeface* firstInFamily = NULL;
|
||||
int fallbackCount = 0;
|
||||
|
||||
for (size_t i = 0; i < gNumSystemFonts; i++) {
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
|
||||
// if we're the first in a new family, clear firstInFamily
|
||||
if (rec[i].fNames != NULL) {
|
||||
firstInFamily = NULL;
|
||||
@ -522,7 +490,7 @@ static void load_system_fonts() {
|
||||
const char* const* names = rec[i].fNames;
|
||||
|
||||
// record the default family if this is it
|
||||
if (names == gDefaultNames) {
|
||||
if (names == DEFAULT_NAMES) {
|
||||
gDefaultFamily = family;
|
||||
}
|
||||
// add the names to map to this family
|
||||
@ -543,85 +511,40 @@ static void load_system_fonts() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
|
||||
// lookup and record if the font is custom (i.e. not a system font)
|
||||
bool isCustomFont = !((FamilyTypeface*)face)->isSysFont();
|
||||
stream->writeBool(isCustomFont);
|
||||
const char* name = ((FamilyTypeface*)face)->getUniqueString();
|
||||
|
||||
if (isCustomFont) {
|
||||
SkStream* fontStream = ((FamilyTypeface*)face)->openStream();
|
||||
|
||||
// store the length of the custom font
|
||||
uint32_t len = fontStream->getLength();
|
||||
stream->write32(len);
|
||||
|
||||
// store the entire font in the serialized stream
|
||||
void* fontData = malloc(len);
|
||||
|
||||
fontStream->read(fontData, len);
|
||||
stream->write(fontData, len);
|
||||
|
||||
fontStream->unref();
|
||||
free(fontData);
|
||||
// SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len);
|
||||
stream->write8((uint8_t)face->style());
|
||||
|
||||
if (NULL == name || 0 == *name) {
|
||||
stream->writePackedUInt(0);
|
||||
// SkDebugf("--- fonthost serialize null\n");
|
||||
} else {
|
||||
const char* name = ((FamilyTypeface*)face)->getUniqueString();
|
||||
|
||||
stream->write8((uint8_t)face->style());
|
||||
|
||||
if (NULL == name || 0 == *name) {
|
||||
stream->writePackedUInt(0);
|
||||
// SkDebugf("--- fonthost serialize null\n");
|
||||
} else {
|
||||
uint32_t len = strlen(name);
|
||||
stream->writePackedUInt(len);
|
||||
stream->write(name, len);
|
||||
// SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
|
||||
}
|
||||
uint32_t len = strlen(name);
|
||||
stream->writePackedUInt(len);
|
||||
stream->write(name, len);
|
||||
// SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
|
||||
}
|
||||
}
|
||||
|
||||
SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
|
||||
load_system_fonts();
|
||||
|
||||
// check if the font is a custom or system font
|
||||
bool isCustomFont = stream->readBool();
|
||||
int style = stream->readU8();
|
||||
|
||||
if (isCustomFont) {
|
||||
int len = stream->readPackedUInt();
|
||||
if (len > 0) {
|
||||
SkString str;
|
||||
str.resize(len);
|
||||
stream->read(str.writable_str(), len);
|
||||
|
||||
// read the length of the custom font from the stream
|
||||
uint32_t len = stream->readU32();
|
||||
|
||||
// generate a new stream to store the custom typeface
|
||||
SkMemoryStream* fontStream = new SkMemoryStream(len);
|
||||
stream->read((void*)fontStream->getMemoryBase(), len);
|
||||
|
||||
SkTypeface* face = CreateTypefaceFromStream(fontStream);
|
||||
|
||||
fontStream->unref();
|
||||
|
||||
// SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len);
|
||||
return face;
|
||||
|
||||
} else {
|
||||
int style = stream->readU8();
|
||||
|
||||
int len = stream->readPackedUInt();
|
||||
if (len > 0) {
|
||||
SkString str;
|
||||
str.resize(len);
|
||||
stream->read(str.writable_str(), len);
|
||||
|
||||
const FontInitRec* rec = gSystemFonts;
|
||||
for (size_t i = 0; i < gNumSystemFonts; i++) {
|
||||
if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
|
||||
// backup until we hit the fNames
|
||||
for (int j = i; j >= 0; --j) {
|
||||
if (rec[j].fNames != NULL) {
|
||||
return SkFontHost::CreateTypeface(NULL,
|
||||
rec[j].fNames[0], NULL, 0,
|
||||
(SkTypeface::Style)style);
|
||||
}
|
||||
const FontInitRec* rec = gSystemFonts;
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
|
||||
if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
|
||||
// backup until we hit the fNames
|
||||
for (int j = i; j >= 0; --j) {
|
||||
if (rec[j].fNames != NULL) {
|
||||
return SkFontHost::CreateTypeface(NULL,
|
||||
rec[j].fNames[0], NULL, 0, (SkTypeface::Style)style);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -704,16 +627,6 @@ size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
|
||||
SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
|
||||
load_system_fonts();
|
||||
|
||||
const SkTypeface* origTypeface = find_from_uniqueID(origFontID);
|
||||
const SkTypeface* currTypeface = find_from_uniqueID(currFontID);
|
||||
|
||||
SkASSERT(origTypeface != 0);
|
||||
SkASSERT(currTypeface != 0);
|
||||
|
||||
// Our fallback list always stores the id of the plain in each fallback
|
||||
// family, so we transform currFontID to its plain equivalent.
|
||||
currFontID = find_typeface(currTypeface, SkTypeface::kNormal)->uniqueID();
|
||||
|
||||
/* First see if fontID is already one of our fallbacks. If so, return
|
||||
its successor. If fontID is not in our list, then return the first one
|
||||
in our list. Note: list is zero-terminated, and returning zero means
|
||||
@ -722,17 +635,10 @@ SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
|
||||
const uint32_t* list = gFallbackFonts;
|
||||
for (int i = 0; list[i] != 0; i++) {
|
||||
if (list[i] == currFontID) {
|
||||
if (list[i+1] == 0)
|
||||
return 0;
|
||||
const SkTypeface* nextTypeface = find_from_uniqueID(list[i+1]);
|
||||
return find_typeface(nextTypeface, origTypeface->style())->uniqueID();
|
||||
return list[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, currFontID was not a fallback, so we start at the
|
||||
// beginning of our list.
|
||||
const SkTypeface* firstTypeface = find_from_uniqueID(list[0]);
|
||||
return find_typeface(firstTypeface, origTypeface->style())->uniqueID();
|
||||
return list[0];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -761,3 +667,4 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
||||
return face;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -30,8 +30,7 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) {
|
||||
// static
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID,
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t*, uint32_t) {
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
|
||||
SkDEBUGFAIL("SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -110,3 +110,5 @@ patch -p3 < user-config.patch
|
||||
patch -p3 < uninitialized-margin.patch
|
||||
# Bug 722011 - Fix comma at end of enum list
|
||||
patch -p3 < fix-comma-end-enum-list.patch
|
||||
# Bug 719872 - Fix crash on Android by reverting to older FontHost impl
|
||||
patch -p3 < old-android-fonthost.patch
|
||||
|
@ -436,6 +436,14 @@ void SourceBufferDestroy(void *srcBuffer)
|
||||
static_cast<SourceSurface*>(srcBuffer)->Release();
|
||||
}
|
||||
|
||||
void SourceSnapshotDetached(cairo_surface_t *nullSurf)
|
||||
{
|
||||
gfxImageSurface* origSurf =
|
||||
static_cast<gfxImageSurface*>(cairo_surface_get_user_data(nullSurf, &kSourceSurface));
|
||||
|
||||
origSurf->SetData(&kSourceSurface, NULL, NULL);
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface>
|
||||
gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
|
||||
{
|
||||
@ -503,6 +511,15 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
|
||||
IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height),
|
||||
imgSurface->Stride(),
|
||||
format);
|
||||
|
||||
cairo_surface_t *nullSurf =
|
||||
cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cairo_surface_set_user_data(nullSurf,
|
||||
&kSourceSurface,
|
||||
imgSurface,
|
||||
NULL);
|
||||
cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
|
||||
cairo_surface_destroy(nullSurf);
|
||||
}
|
||||
|
||||
srcBuffer->AddRef();
|
||||
|
@ -342,6 +342,12 @@ gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce)
|
||||
nsRefPtr<IDXGIFactory1> factory1;
|
||||
HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
|
||||
getter_AddRefs(factory1));
|
||||
|
||||
if (FAILED(hr) || !factory1) {
|
||||
// This seems to happen with some people running the iZ3D driver.
|
||||
// They won't get acceleration.
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<IDXGIAdapter1> adapter1;
|
||||
hr = factory1->EnumAdapters1(0, getter_AddRefs(adapter1));
|
||||
|
@ -61,8 +61,8 @@ SyncChannel::SyncChannel(SyncListener* aListener)
|
||||
, mPendingReply(0)
|
||||
, mProcessingSyncMessage(false)
|
||||
, mNextSeqno(0)
|
||||
, mTimeoutMs(kNoTimeout)
|
||||
, mInTimeoutSecondHalf(false)
|
||||
, mTimeoutMs(kNoTimeout)
|
||||
#ifdef OS_WIN
|
||||
, mTopFrame(NULL)
|
||||
#endif
|
||||
|
@ -1061,6 +1061,7 @@ XPCShellEnvironment::~XPCShellEnvironment()
|
||||
|
||||
JSRuntime* rt = gOldContextCallback ? JS_GetRuntime(mCx) : NULL;
|
||||
|
||||
JS_EndRequest(mCx);
|
||||
JS_DestroyContext(mCx);
|
||||
|
||||
if (gOldContextCallback) {
|
||||
|
@ -53,12 +53,12 @@
|
||||
namespace JS {
|
||||
|
||||
/* Data for tracking analysis/inference memory usage. */
|
||||
struct TypeInferenceMemoryStats
|
||||
struct TypeInferenceSizes
|
||||
{
|
||||
int64_t scripts;
|
||||
int64_t objects;
|
||||
int64_t tables;
|
||||
int64_t temporary;
|
||||
size_t scripts;
|
||||
size_t objects;
|
||||
size_t tables;
|
||||
size_t temporary;
|
||||
};
|
||||
|
||||
typedef void* (* GetNameCallback)(JSContext *cx, JSCompartment *c);
|
||||
@ -86,40 +86,40 @@ struct CompartmentStats
|
||||
void *name;
|
||||
DestroyNameCallback destroyNameCb;
|
||||
|
||||
int64_t gcHeapArenaHeaders;
|
||||
int64_t gcHeapArenaPadding;
|
||||
int64_t gcHeapArenaUnused;
|
||||
size_t gcHeapArenaHeaders;
|
||||
size_t gcHeapArenaPadding;
|
||||
size_t gcHeapArenaUnused;
|
||||
|
||||
int64_t gcHeapObjectsNonFunction;
|
||||
int64_t gcHeapObjectsFunction;
|
||||
int64_t gcHeapStrings;
|
||||
int64_t gcHeapShapesTree;
|
||||
int64_t gcHeapShapesDict;
|
||||
int64_t gcHeapShapesBase;
|
||||
int64_t gcHeapScripts;
|
||||
int64_t gcHeapTypeObjects;
|
||||
int64_t gcHeapXML;
|
||||
size_t gcHeapObjectsNonFunction;
|
||||
size_t gcHeapObjectsFunction;
|
||||
size_t gcHeapStrings;
|
||||
size_t gcHeapShapesTree;
|
||||
size_t gcHeapShapesDict;
|
||||
size_t gcHeapShapesBase;
|
||||
size_t gcHeapScripts;
|
||||
size_t gcHeapTypeObjects;
|
||||
size_t gcHeapXML;
|
||||
|
||||
int64_t objectSlots;
|
||||
int64_t objectElements;
|
||||
int64_t stringChars;
|
||||
int64_t shapesExtraTreeTables;
|
||||
int64_t shapesExtraDictTables;
|
||||
int64_t shapesExtraTreeShapeKids;
|
||||
int64_t shapesCompartmentTables;
|
||||
int64_t scriptData;
|
||||
size_t objectSlots;
|
||||
size_t objectElements;
|
||||
size_t stringChars;
|
||||
size_t shapesExtraTreeTables;
|
||||
size_t shapesExtraDictTables;
|
||||
size_t shapesExtraTreeShapeKids;
|
||||
size_t shapesCompartmentTables;
|
||||
size_t scriptData;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
int64_t mjitCode;
|
||||
int64_t mjitData;
|
||||
size_t mjitCode;
|
||||
size_t mjitData;
|
||||
#endif
|
||||
TypeInferenceMemoryStats typeInferenceMemory;
|
||||
TypeInferenceSizes typeInferenceSizes;
|
||||
};
|
||||
|
||||
struct IterateData
|
||||
struct RuntimeStats
|
||||
{
|
||||
IterateData(JSMallocSizeOfFun mallocSizeOf, GetNameCallback getNameCb,
|
||||
DestroyNameCallback destroyNameCb)
|
||||
RuntimeStats(JSMallocSizeOfFun mallocSizeOf, GetNameCallback getNameCb,
|
||||
DestroyNameCallback destroyNameCb)
|
||||
: runtimeObject(0)
|
||||
, runtimeAtomsTable(0)
|
||||
, runtimeContexts(0)
|
||||
@ -151,30 +151,30 @@ struct IterateData
|
||||
, destroyNameCb(destroyNameCb)
|
||||
{}
|
||||
|
||||
int64_t runtimeObject;
|
||||
int64_t runtimeAtomsTable;
|
||||
int64_t runtimeContexts;
|
||||
int64_t runtimeNormal;
|
||||
int64_t runtimeTemporary;
|
||||
int64_t runtimeRegexpCode;
|
||||
int64_t runtimeStackCommitted;
|
||||
int64_t gcHeapChunkTotal;
|
||||
int64_t gcHeapChunkCleanUnused;
|
||||
int64_t gcHeapChunkDirtyUnused;
|
||||
int64_t gcHeapChunkCleanDecommitted;
|
||||
int64_t gcHeapChunkDirtyDecommitted;
|
||||
int64_t gcHeapArenaUnused;
|
||||
int64_t gcHeapChunkAdmin;
|
||||
int64_t gcHeapUnusedPercentage;
|
||||
int64_t totalObjects;
|
||||
int64_t totalShapes;
|
||||
int64_t totalScripts;
|
||||
int64_t totalStrings;
|
||||
size_t runtimeObject;
|
||||
size_t runtimeAtomsTable;
|
||||
size_t runtimeContexts;
|
||||
size_t runtimeNormal;
|
||||
size_t runtimeTemporary;
|
||||
size_t runtimeRegexpCode;
|
||||
size_t runtimeStackCommitted;
|
||||
size_t gcHeapChunkTotal;
|
||||
size_t gcHeapChunkCleanUnused;
|
||||
size_t gcHeapChunkDirtyUnused;
|
||||
size_t gcHeapChunkCleanDecommitted;
|
||||
size_t gcHeapChunkDirtyDecommitted;
|
||||
size_t gcHeapArenaUnused;
|
||||
size_t gcHeapChunkAdmin;
|
||||
size_t gcHeapUnusedPercentage;
|
||||
size_t totalObjects;
|
||||
size_t totalShapes;
|
||||
size_t totalScripts;
|
||||
size_t totalStrings;
|
||||
#ifdef JS_METHODJIT
|
||||
int64_t totalMjit;
|
||||
size_t totalMjit;
|
||||
#endif
|
||||
int64_t totalTypeInference;
|
||||
int64_t totalAnalysisTemp;
|
||||
size_t totalTypeInference;
|
||||
size_t totalAnalysisTemp;
|
||||
|
||||
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
||||
CompartmentStats *currCompartmentStats;
|
||||
@ -187,7 +187,7 @@ struct IterateData
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data);
|
||||
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,
|
||||
@ -195,19 +195,6 @@ GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,
|
||||
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
extern void
|
||||
SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment,
|
||||
TypeInferenceMemoryStats *stats,
|
||||
JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
extern void
|
||||
SizeOfTypeObjectExcludingThis(/*TypeObject*/ void *object,
|
||||
TypeInferenceMemoryStats *stats,
|
||||
JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
extern size_t
|
||||
SizeOfCompartmentShapeTable(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
SystemCompartmentCount(const JSRuntime *rt);
|
||||
|
||||
|
@ -55,26 +55,23 @@ namespace JS {
|
||||
using namespace js;
|
||||
|
||||
static void
|
||||
CompartmentMemoryCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||
CompartmentStatsCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||
{
|
||||
// Append a new CompartmentStats to the vector.
|
||||
IterateData *data = static_cast<IterateData *>(vdata);
|
||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
||||
|
||||
// CollectCompartmentStatsForRuntime reserves enough space.
|
||||
MOZ_ALWAYS_TRUE(data->compartmentStatsVector.growBy(1));
|
||||
CompartmentStats &curr = data->compartmentStatsVector.back();
|
||||
curr.init(data->getNameCb(cx, compartment), data->destroyNameCb);
|
||||
data->currCompartmentStats = &curr;
|
||||
// CollectRuntimeStats reserves enough space.
|
||||
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
|
||||
CompartmentStats &cStats = rtStats->compartmentStatsVector.back();
|
||||
cStats.init(rtStats->getNameCb(cx, compartment), rtStats->destroyNameCb);
|
||||
rtStats->currCompartmentStats = &cStats;
|
||||
|
||||
// Get the compartment-level numbers.
|
||||
#ifdef JS_METHODJIT
|
||||
curr.mjitCode = compartment->sizeOfMjitCode();
|
||||
cStats.mjitCode = compartment->sizeOfMjitCode();
|
||||
#endif
|
||||
SizeOfCompartmentTypeInferenceData(cx, compartment,
|
||||
&curr.typeInferenceMemory,
|
||||
data->mallocSizeOf);
|
||||
curr.shapesCompartmentTables =
|
||||
SizeOfCompartmentShapeTable(compartment, data->mallocSizeOf);
|
||||
compartment->sizeOfTypeInferenceData(cx, &cStats.typeInferenceSizes, rtStats->mallocSizeOf);
|
||||
cStats.shapesCompartmentTables = compartment->sizeOfShapeTable(rtStats->mallocSizeOf);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -91,109 +88,107 @@ ChunkCallback(JSContext *cx, void *vdata, gc::Chunk *chunk)
|
||||
{
|
||||
// Nb: This function is only called for dirty chunks, which is why we
|
||||
// increment gcHeapChunkDirtyDecommitted.
|
||||
IterateData *data = static_cast<IterateData *>(vdata);
|
||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
||||
for (size_t i = 0; i < gc::ArenasPerChunk; i++)
|
||||
if (chunk->decommittedArenas.get(i))
|
||||
data->gcHeapChunkDirtyDecommitted += gc::ArenaSize;
|
||||
rtStats->gcHeapChunkDirtyDecommitted += gc::ArenaSize;
|
||||
}
|
||||
|
||||
static void
|
||||
ArenaCallback(JSContext *cx, void *vdata, gc::Arena *arena,
|
||||
JSGCTraceKind traceKind, size_t thingSize)
|
||||
{
|
||||
IterateData *data = static_cast<IterateData *>(vdata);
|
||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
||||
|
||||
data->currCompartmentStats->gcHeapArenaHeaders +=
|
||||
sizeof(gc::ArenaHeader);
|
||||
rtStats->currCompartmentStats->gcHeapArenaHeaders += sizeof(gc::ArenaHeader);
|
||||
size_t allocationSpace = arena->thingsSpan(thingSize);
|
||||
data->currCompartmentStats->gcHeapArenaPadding +=
|
||||
rtStats->currCompartmentStats->gcHeapArenaPadding +=
|
||||
gc::ArenaSize - allocationSpace - sizeof(gc::ArenaHeader);
|
||||
// We don't call the callback on unused things. So we compute the
|
||||
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
|
||||
// We do this by setting arenaUnused to maxArenaUnused here, and then
|
||||
// subtracting thingSize for every used cell, in CellCallback().
|
||||
data->currCompartmentStats->gcHeapArenaUnused += allocationSpace;
|
||||
rtStats->currCompartmentStats->gcHeapArenaUnused += allocationSpace;
|
||||
}
|
||||
|
||||
static void
|
||||
CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
size_t thingSize)
|
||||
{
|
||||
IterateData *data = static_cast<IterateData *>(vdata);
|
||||
CompartmentStats *curr = data->currCompartmentStats;
|
||||
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
|
||||
CompartmentStats *cStats = rtStats->currCompartmentStats;
|
||||
switch (traceKind) {
|
||||
case JSTRACE_OBJECT:
|
||||
{
|
||||
JSObject *obj = static_cast<JSObject *>(thing);
|
||||
if (obj->isFunction()) {
|
||||
curr->gcHeapObjectsFunction += thingSize;
|
||||
cStats->gcHeapObjectsFunction += thingSize;
|
||||
} else {
|
||||
curr->gcHeapObjectsNonFunction += thingSize;
|
||||
cStats->gcHeapObjectsNonFunction += thingSize;
|
||||
}
|
||||
size_t slotsSize, elementsSize;
|
||||
obj->sizeOfExcludingThis(data->mallocSizeOf, &slotsSize, &elementsSize);
|
||||
curr->objectSlots += slotsSize;
|
||||
curr->objectElements += elementsSize;
|
||||
obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize, &elementsSize);
|
||||
cStats->objectSlots += slotsSize;
|
||||
cStats->objectElements += elementsSize;
|
||||
break;
|
||||
}
|
||||
case JSTRACE_STRING:
|
||||
{
|
||||
JSString *str = static_cast<JSString *>(thing);
|
||||
curr->gcHeapStrings += thingSize;
|
||||
curr->stringChars += str->sizeOfExcludingThis(data->mallocSizeOf);
|
||||
cStats->gcHeapStrings += thingSize;
|
||||
cStats->stringChars += str->sizeOfExcludingThis(rtStats->mallocSizeOf);
|
||||
break;
|
||||
}
|
||||
case JSTRACE_SHAPE:
|
||||
{
|
||||
Shape *shape = static_cast<Shape*>(thing);
|
||||
size_t propTableSize, kidsSize;
|
||||
shape->sizeOfExcludingThis(data->mallocSizeOf, &propTableSize, &kidsSize);
|
||||
shape->sizeOfExcludingThis(rtStats->mallocSizeOf, &propTableSize, &kidsSize);
|
||||
if (shape->inDictionary()) {
|
||||
curr->gcHeapShapesDict += thingSize;
|
||||
curr->shapesExtraDictTables += propTableSize;
|
||||
cStats->gcHeapShapesDict += thingSize;
|
||||
cStats->shapesExtraDictTables += propTableSize;
|
||||
JS_ASSERT(kidsSize == 0);
|
||||
} else {
|
||||
curr->gcHeapShapesTree += thingSize;
|
||||
curr->shapesExtraTreeTables += propTableSize;
|
||||
curr->shapesExtraTreeShapeKids += kidsSize;
|
||||
cStats->gcHeapShapesTree += thingSize;
|
||||
cStats->shapesExtraTreeTables += propTableSize;
|
||||
cStats->shapesExtraTreeShapeKids += kidsSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
{
|
||||
curr->gcHeapShapesBase += thingSize;
|
||||
cStats->gcHeapShapesBase += thingSize;
|
||||
break;
|
||||
}
|
||||
case JSTRACE_SCRIPT:
|
||||
{
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
curr->gcHeapScripts += thingSize;
|
||||
curr->scriptData += script->sizeOfData(data->mallocSizeOf);
|
||||
cStats->gcHeapScripts += thingSize;
|
||||
cStats->scriptData += script->sizeOfData(rtStats->mallocSizeOf);
|
||||
#ifdef JS_METHODJIT
|
||||
curr->mjitData += script->sizeOfJitScripts(data->mallocSizeOf);
|
||||
cStats->mjitData += script->sizeOfJitScripts(rtStats->mallocSizeOf);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
{
|
||||
types::TypeObject *obj = static_cast<types::TypeObject *>(thing);
|
||||
curr->gcHeapTypeObjects += thingSize;
|
||||
SizeOfTypeObjectExcludingThis(obj, &curr->typeInferenceMemory,
|
||||
data->mallocSizeOf);
|
||||
cStats->gcHeapTypeObjects += thingSize;
|
||||
obj->sizeOfExcludingThis(&cStats->typeInferenceSizes, rtStats->mallocSizeOf);
|
||||
break;
|
||||
}
|
||||
case JSTRACE_XML:
|
||||
{
|
||||
curr->gcHeapXML += thingSize;
|
||||
cStats->gcHeapXML += thingSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Yes, this is a subtraction: see ArenaCallback() for details.
|
||||
curr->gcHeapArenaUnused -= thingSize;
|
||||
cStats->gcHeapArenaUnused -= thingSize;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
||||
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
|
||||
{
|
||||
JSContext *cx = JS_NewContext(rt, 0);
|
||||
if (!cx)
|
||||
@ -202,119 +197,110 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
if (!data->compartmentStatsVector.reserve(rt->compartments.length()))
|
||||
if (!rtStats->compartmentStatsVector.reserve(rt->compartments.length()))
|
||||
return false;
|
||||
|
||||
data->gcHeapChunkCleanDecommitted =
|
||||
rt->gcChunkPool.countCleanDecommittedArenas(rt) *
|
||||
gc::ArenaSize;
|
||||
data->gcHeapChunkCleanUnused =
|
||||
int64_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) *
|
||||
gc::ChunkSize -
|
||||
data->gcHeapChunkCleanDecommitted;
|
||||
data->gcHeapChunkTotal =
|
||||
int64_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) *
|
||||
gc::ChunkSize;
|
||||
rtStats->gcHeapChunkCleanDecommitted =
|
||||
rt->gcChunkPool.countCleanDecommittedArenas(rt) * gc::ArenaSize;
|
||||
rtStats->gcHeapChunkCleanUnused =
|
||||
size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize -
|
||||
rtStats->gcHeapChunkCleanDecommitted;
|
||||
rtStats->gcHeapChunkTotal =
|
||||
size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
|
||||
|
||||
IterateCompartmentsArenasCells(cx, data, CompartmentMemoryCallback,
|
||||
IterateCompartmentsArenasCells(cx, rtStats, CompartmentStatsCallback,
|
||||
ArenaCallback, CellCallback);
|
||||
IterateChunks(cx, data, ChunkCallback);
|
||||
IterateChunks(cx, rtStats, ChunkCallback);
|
||||
|
||||
data->runtimeObject = data->mallocSizeOf(rt);
|
||||
rtStats->runtimeObject = rtStats->mallocSizeOf(rt);
|
||||
|
||||
size_t normal, temporary, regexpCode, stackCommitted;
|
||||
rt->sizeOfExcludingThis(data->mallocSizeOf,
|
||||
&normal,
|
||||
&temporary,
|
||||
®expCode,
|
||||
&stackCommitted);
|
||||
|
||||
data->runtimeNormal = normal;
|
||||
data->runtimeTemporary = temporary;
|
||||
data->runtimeRegexpCode = regexpCode;
|
||||
data->runtimeStackCommitted = stackCommitted;
|
||||
rt->sizeOfExcludingThis(rtStats->mallocSizeOf,
|
||||
&rtStats->runtimeNormal,
|
||||
&rtStats->runtimeTemporary,
|
||||
&rtStats->runtimeRegexpCode,
|
||||
&rtStats->runtimeStackCommitted);
|
||||
|
||||
// Nb: we use sizeOfExcludingThis() because atomState.atoms is within
|
||||
// JSRuntime, and so counted when JSRuntime is counted.
|
||||
data->runtimeAtomsTable =
|
||||
rt->atomState.atoms.sizeOfExcludingThis(data->mallocSizeOf);
|
||||
rtStats->runtimeAtomsTable =
|
||||
rt->atomState.atoms.sizeOfExcludingThis(rtStats->mallocSizeOf);
|
||||
|
||||
JSContext *acx, *iter = NULL;
|
||||
while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL)
|
||||
data->runtimeContexts += acx->sizeOfIncludingThis(data->mallocSizeOf);
|
||||
rtStats->runtimeContexts += acx->sizeOfIncludingThis(rtStats->mallocSizeOf);
|
||||
}
|
||||
|
||||
JS_DestroyContextNoGC(cx);
|
||||
|
||||
// This is initialized to all bytes stored in used chunks, and then we
|
||||
// subtract used space from it each time around the loop.
|
||||
data->gcHeapChunkDirtyUnused = data->gcHeapChunkTotal -
|
||||
data->gcHeapChunkCleanUnused -
|
||||
data->gcHeapChunkCleanDecommitted -
|
||||
data->gcHeapChunkDirtyDecommitted;
|
||||
rtStats->gcHeapChunkDirtyUnused = rtStats->gcHeapChunkTotal -
|
||||
rtStats->gcHeapChunkCleanUnused -
|
||||
rtStats->gcHeapChunkCleanDecommitted -
|
||||
rtStats->gcHeapChunkDirtyDecommitted;
|
||||
|
||||
for (size_t index = 0;
|
||||
index < data->compartmentStatsVector.length();
|
||||
index < rtStats->compartmentStatsVector.length();
|
||||
index++) {
|
||||
CompartmentStats &stats = data->compartmentStatsVector[index];
|
||||
CompartmentStats &cStats = rtStats->compartmentStatsVector[index];
|
||||
|
||||
int64_t used = stats.gcHeapArenaHeaders +
|
||||
stats.gcHeapArenaPadding +
|
||||
stats.gcHeapArenaUnused +
|
||||
stats.gcHeapObjectsNonFunction +
|
||||
stats.gcHeapObjectsFunction +
|
||||
stats.gcHeapStrings +
|
||||
stats.gcHeapShapesTree +
|
||||
stats.gcHeapShapesDict +
|
||||
stats.gcHeapShapesBase +
|
||||
stats.gcHeapScripts +
|
||||
stats.gcHeapTypeObjects +
|
||||
stats.gcHeapXML;
|
||||
size_t used = cStats.gcHeapArenaHeaders +
|
||||
cStats.gcHeapArenaPadding +
|
||||
cStats.gcHeapArenaUnused +
|
||||
cStats.gcHeapObjectsNonFunction +
|
||||
cStats.gcHeapObjectsFunction +
|
||||
cStats.gcHeapStrings +
|
||||
cStats.gcHeapShapesTree +
|
||||
cStats.gcHeapShapesDict +
|
||||
cStats.gcHeapShapesBase +
|
||||
cStats.gcHeapScripts +
|
||||
cStats.gcHeapTypeObjects +
|
||||
cStats.gcHeapXML;
|
||||
|
||||
data->gcHeapChunkDirtyUnused -= used;
|
||||
data->gcHeapArenaUnused += stats.gcHeapArenaUnused;
|
||||
data->totalObjects += stats.gcHeapObjectsNonFunction +
|
||||
stats.gcHeapObjectsFunction +
|
||||
stats.objectSlots +
|
||||
stats.objectElements;
|
||||
data->totalShapes += stats.gcHeapShapesTree +
|
||||
stats.gcHeapShapesDict +
|
||||
stats.gcHeapShapesBase +
|
||||
stats.shapesExtraTreeTables +
|
||||
stats.shapesExtraDictTables +
|
||||
stats.shapesCompartmentTables;
|
||||
data->totalScripts += stats.gcHeapScripts +
|
||||
stats.scriptData;
|
||||
data->totalStrings += stats.gcHeapStrings +
|
||||
stats.stringChars;
|
||||
rtStats->gcHeapChunkDirtyUnused -= used;
|
||||
rtStats->gcHeapArenaUnused += cStats.gcHeapArenaUnused;
|
||||
rtStats->totalObjects += cStats.gcHeapObjectsNonFunction +
|
||||
cStats.gcHeapObjectsFunction +
|
||||
cStats.objectSlots +
|
||||
cStats.objectElements;
|
||||
rtStats->totalShapes += cStats.gcHeapShapesTree +
|
||||
cStats.gcHeapShapesDict +
|
||||
cStats.gcHeapShapesBase +
|
||||
cStats.shapesExtraTreeTables +
|
||||
cStats.shapesExtraDictTables +
|
||||
cStats.shapesCompartmentTables;
|
||||
rtStats->totalScripts += cStats.gcHeapScripts +
|
||||
cStats.scriptData;
|
||||
rtStats->totalStrings += cStats.gcHeapStrings +
|
||||
cStats.stringChars;
|
||||
#ifdef JS_METHODJIT
|
||||
data->totalMjit += stats.mjitCode +
|
||||
stats.mjitData;
|
||||
rtStats->totalMjit += cStats.mjitCode +
|
||||
cStats.mjitData;
|
||||
#endif
|
||||
data->totalTypeInference += stats.gcHeapTypeObjects +
|
||||
stats.typeInferenceMemory.objects +
|
||||
stats.typeInferenceMemory.scripts +
|
||||
stats.typeInferenceMemory.tables;
|
||||
data->totalAnalysisTemp += stats.typeInferenceMemory.temporary;
|
||||
rtStats->totalTypeInference += cStats.gcHeapTypeObjects +
|
||||
cStats.typeInferenceSizes.objects +
|
||||
cStats.typeInferenceSizes.scripts +
|
||||
cStats.typeInferenceSizes.tables;
|
||||
rtStats->totalAnalysisTemp += cStats.typeInferenceSizes.temporary;
|
||||
}
|
||||
|
||||
size_t numDirtyChunks = (data->gcHeapChunkTotal -
|
||||
data->gcHeapChunkCleanUnused) /
|
||||
size_t numDirtyChunks = (rtStats->gcHeapChunkTotal -
|
||||
rtStats->gcHeapChunkCleanUnused) /
|
||||
gc::ChunkSize;
|
||||
int64_t perChunkAdmin =
|
||||
size_t perChunkAdmin =
|
||||
sizeof(gc::Chunk) - (sizeof(gc::Arena) * gc::ArenasPerChunk);
|
||||
data->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin;
|
||||
data->gcHeapChunkDirtyUnused -= data->gcHeapChunkAdmin;
|
||||
rtStats->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin;
|
||||
rtStats->gcHeapChunkDirtyUnused -= rtStats->gcHeapChunkAdmin;
|
||||
|
||||
// Why 10000x? 100x because it's a percentage, and another 100x
|
||||
// because nsIMemoryReporter requires that for percentage amounts so
|
||||
// they can be fractional.
|
||||
data->gcHeapUnusedPercentage = (data->gcHeapChunkCleanUnused +
|
||||
data->gcHeapChunkDirtyUnused +
|
||||
data->gcHeapChunkCleanDecommitted +
|
||||
data->gcHeapChunkDirtyDecommitted +
|
||||
data->gcHeapArenaUnused) * 10000 /
|
||||
data->gcHeapChunkTotal;
|
||||
rtStats->gcHeapUnusedPercentage = (rtStats->gcHeapChunkCleanUnused +
|
||||
rtStats->gcHeapChunkDirtyUnused +
|
||||
rtStats->gcHeapChunkCleanDecommitted +
|
||||
rtStats->gcHeapChunkDirtyDecommitted +
|
||||
rtStats->gcHeapArenaUnused) * 10000 /
|
||||
rtStats->gcHeapChunkTotal;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -70,6 +70,22 @@ static bool isVFPPresent()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__VFP_FP__)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef WTF_OS_ANDROID
|
||||
FILE *fp = fopen("/proc/cpuinfo", "r");
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
char buf[1024];
|
||||
fread(buf, sizeof(char), sizeof(buf), fp);
|
||||
fclose(fp);
|
||||
if (strstr(buf, "vfp"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -434,18 +434,47 @@ struct TreeContext { /* tree context for semantic checks */
|
||||
return flags & TCF_FUN_MUTATES_PARAMETER;
|
||||
}
|
||||
|
||||
void noteArgumentsUse(ParseNode *pn) {
|
||||
/*
|
||||
* Accessing the implicit |arguments| local binding in a function must
|
||||
* trigger appropriate code generation such that the access works.
|
||||
*/
|
||||
void noteArgumentsNameUse(ParseNode *node) {
|
||||
JS_ASSERT(inFunction());
|
||||
countArgumentsUse(pn);
|
||||
JS_ASSERT(node->isKind(PNK_NAME));
|
||||
JS_ASSERT(node->pn_atom == parser->context->runtime->atomState.argumentsAtom);
|
||||
countArgumentsUse(node);
|
||||
flags |= TCF_FUN_USES_ARGUMENTS;
|
||||
if (funbox)
|
||||
funbox->node->pn_dflags |= PND_FUNARG;
|
||||
}
|
||||
|
||||
void countArgumentsUse(ParseNode *pn) {
|
||||
JS_ASSERT(pn->pn_atom == parser->context->runtime->atomState.argumentsAtom);
|
||||
/*
|
||||
* Non-dynamic accesses to a property named "arguments" inside a function
|
||||
* have to deoptimize the function in case those accesses are to the
|
||||
* function's arguments. (However, this is unnecessary in strict mode
|
||||
* functions because of the f.arguments poison-pill. O frabjous day!)
|
||||
*/
|
||||
void noteArgumentsPropertyAccess(ParseNode *node) {
|
||||
JS_ASSERT(inFunction());
|
||||
JS_ASSERT(&node->asPropertyAccess().name() ==
|
||||
parser->context->runtime->atomState.argumentsAtom);
|
||||
if (!inStrictMode()) {
|
||||
flags |= TCF_FUN_USES_ARGUMENTS;
|
||||
if (funbox)
|
||||
funbox->node->pn_dflags |= PND_FUNARG;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Uses of |arguments| must be noted so that such uses can be forbidden if
|
||||
* they occur inside generator expressions (which desugar to functions and
|
||||
* yields, in which |arguments| would have an entirely different meaning).
|
||||
*/
|
||||
void countArgumentsUse(ParseNode *node) {
|
||||
JS_ASSERT(node->isKind(PNK_NAME));
|
||||
JS_ASSERT(node->pn_atom == parser->context->runtime->atomState.argumentsAtom);
|
||||
argumentsCount++;
|
||||
argumentsNode = pn;
|
||||
argumentsNode = node;
|
||||
}
|
||||
|
||||
bool needsEagerArguments() const {
|
||||
|
@ -484,6 +484,7 @@ class BreakStatement;
|
||||
class ContinueStatement;
|
||||
class XMLProcessingInstruction;
|
||||
class ConditionalExpression;
|
||||
class PropertyAccess;
|
||||
|
||||
struct ParseNode {
|
||||
private:
|
||||
@ -927,6 +928,7 @@ struct ParseNode {
|
||||
inline XMLProcessingInstruction &asXMLProcessingInstruction();
|
||||
#endif
|
||||
inline ConditionalExpression &asConditionalExpression();
|
||||
inline PropertyAccess &asPropertyAccess();
|
||||
};
|
||||
|
||||
struct NullaryNode : public ParseNode {
|
||||
@ -1230,6 +1232,14 @@ class PropertyAccess : public ParseNode {
|
||||
}
|
||||
};
|
||||
|
||||
inline PropertyAccess &
|
||||
ParseNode::asPropertyAccess()
|
||||
{
|
||||
JS_ASSERT(isKind(PNK_DOT));
|
||||
JS_ASSERT(pn_arity == PN_NAME);
|
||||
return *static_cast<PropertyAccess *>(this);
|
||||
}
|
||||
|
||||
class PropertyByValue : public ParseNode {
|
||||
public:
|
||||
PropertyByValue(ParseNode *lhs, ParseNode *propExpr,
|
||||
|
@ -4393,7 +4393,7 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va
|
||||
pn2->pn_pos.end = init->pn_pos.end;
|
||||
|
||||
if (tc->inFunction() && name == context->runtime->atomState.argumentsAtom) {
|
||||
tc->noteArgumentsUse(pn2);
|
||||
tc->noteArgumentsNameUse(pn2);
|
||||
if (!blockObj)
|
||||
tc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
}
|
||||
@ -5746,11 +5746,21 @@ Parser::memberExpr(JSBool allowCallSyntax)
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
nextMember = new_<PropertyAccess>(lhs, tokenStream.currentToken().name(),
|
||||
PropertyName *field = tokenStream.currentToken().name();
|
||||
nextMember = new_<PropertyAccess>(lhs, field,
|
||||
lhs->pn_pos.begin,
|
||||
tokenStream.currentToken().pos.end);
|
||||
if (!nextMember)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* A property access of the form |<expr>.arguments| might
|
||||
* access this function's arguments, so we need to flag a
|
||||
* potential arguments use to ensure an arguments object
|
||||
* will be created. See bug 721322.
|
||||
*/
|
||||
if (tc->inFunction() && field == context->runtime->atomState.argumentsAtom)
|
||||
tc->noteArgumentsPropertyAccess(nextMember);
|
||||
}
|
||||
}
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
@ -6614,7 +6624,7 @@ Parser::propertyQualifiedIdentifier()
|
||||
#endif
|
||||
|
||||
ParseNode *
|
||||
Parser::identifierName(bool afterDot)
|
||||
Parser::identifierName(bool afterDoubleDot)
|
||||
{
|
||||
JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME));
|
||||
|
||||
@ -6626,26 +6636,25 @@ Parser::identifierName(bool afterDot)
|
||||
node->setOp(JSOP_NAME);
|
||||
|
||||
if ((tc->flags & (TCF_IN_FUNCTION | TCF_FUN_PARAM_ARGUMENTS)) == TCF_IN_FUNCTION &&
|
||||
name == context->runtime->atomState.argumentsAtom) {
|
||||
/*
|
||||
* Flag arguments usage so we can avoid unsafe optimizations such
|
||||
* as formal parameter assignment analysis (because of the hated
|
||||
* feature whereby arguments alias formals). We do this even for
|
||||
* a reference of the form foo.arguments, which ancient code may
|
||||
* still use instead of arguments (more hate).
|
||||
*/
|
||||
tc->noteArgumentsUse(node);
|
||||
|
||||
name == context->runtime->atomState.argumentsAtom)
|
||||
{
|
||||
/*
|
||||
* Bind early to JSOP_ARGUMENTS to relieve later code from having
|
||||
* to do this work (new rule for the emitter to count on).
|
||||
*/
|
||||
if (!afterDot && !(tc->flags & TCF_DECL_DESTRUCTURING)
|
||||
&& !tc->inStatement(STMT_WITH)) {
|
||||
node->setOp(JSOP_ARGUMENTS);
|
||||
node->pn_dflags |= PND_BOUND;
|
||||
if (!afterDoubleDot) {
|
||||
/*
|
||||
* Note use of |arguments| to ensure we can properly create the
|
||||
* |arguments| object for this function.
|
||||
*/
|
||||
tc->noteArgumentsNameUse(node);
|
||||
|
||||
if (!(tc->flags & TCF_DECL_DESTRUCTURING) && !tc->inStatement(STMT_WITH)) {
|
||||
node->setOp(JSOP_ARGUMENTS);
|
||||
node->pn_dflags |= PND_BOUND;
|
||||
}
|
||||
}
|
||||
} else if ((!afterDot
|
||||
} else if ((!afterDoubleDot
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|| (!tc->inStrictMode() && tokenStream.peekToken() == TOK_DBLCOLON)
|
||||
#endif
|
||||
@ -6708,7 +6717,7 @@ Parser::identifierName(bool afterDot)
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (!tc->inStrictMode() && tokenStream.matchToken(TOK_DBLCOLON)) {
|
||||
if (afterDot) {
|
||||
if (afterDoubleDot) {
|
||||
if (!checkForFunctionNode(name, node))
|
||||
return NULL;
|
||||
}
|
||||
@ -6735,7 +6744,7 @@ Parser::starOrAtPropertyIdentifier(TokenKind tt)
|
||||
#endif
|
||||
|
||||
ParseNode *
|
||||
Parser::primaryExpr(TokenKind tt, JSBool afterDot)
|
||||
Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
|
||||
{
|
||||
JS_ASSERT(tokenStream.isCurrentTokenType(tt));
|
||||
|
||||
@ -7168,7 +7177,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
|
||||
#endif
|
||||
|
||||
case TOK_NAME:
|
||||
pn = identifierName(afterDot);
|
||||
pn = identifierName(afterDoubleDot);
|
||||
break;
|
||||
|
||||
case TOK_REGEXP:
|
||||
|
@ -234,7 +234,7 @@ struct Parser : private AutoGCRooter
|
||||
ParseNode *mulExpr1n();
|
||||
ParseNode *unaryExpr();
|
||||
ParseNode *memberExpr(JSBool allowCallSyntax);
|
||||
ParseNode *primaryExpr(TokenKind tt, JSBool afterDot);
|
||||
ParseNode *primaryExpr(TokenKind tt, bool afterDoubleDot);
|
||||
ParseNode *parenExpr(JSBool *genexp = NULL);
|
||||
|
||||
/*
|
||||
@ -259,7 +259,7 @@ struct Parser : private AutoGCRooter
|
||||
|
||||
bool checkForFunctionNode(PropertyName *name, ParseNode *node);
|
||||
|
||||
ParseNode *identifierName(bool afterDot);
|
||||
ParseNode *identifierName(bool afterDoubleDot);
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
ParseNode *endBracketedExpr();
|
||||
|
@ -0,0 +1,6 @@
|
||||
function f()
|
||||
{
|
||||
var x = <><arguments/><arguments/></>;
|
||||
x..arguments;
|
||||
}
|
||||
f();
|
8
js/src/jit-test/tests/basic/bug714616.js
Normal file
8
js/src/jit-test/tests/basic/bug714616.js
Normal file
@ -0,0 +1,8 @@
|
||||
array1 = new Array();
|
||||
size = 10;
|
||||
for (i = 0; i < size; (array1.length)++)
|
||||
{
|
||||
array1.push(array1.shift());
|
||||
++i
|
||||
}
|
||||
|
13
js/src/jit-test/tests/pic/getelem-large-index.js
Normal file
13
js/src/jit-test/tests/pic/getelem-large-index.js
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
function testProperty(i)
|
||||
{
|
||||
actual = obj[String(i)];
|
||||
}
|
||||
|
||||
var obj = {};
|
||||
var index = [null, 1073741824, 1073741825];
|
||||
for (var j in index)
|
||||
testProperty(index[j]);
|
@ -765,7 +765,6 @@ JSRuntime::JSRuntime()
|
||||
data(NULL),
|
||||
#ifdef JS_THREADSAFE
|
||||
gcLock(NULL),
|
||||
requestCount(0),
|
||||
gcHelperThread(thisFromCtor()),
|
||||
#endif
|
||||
debuggerMutations(0),
|
||||
@ -1013,10 +1012,9 @@ StartRequest(JSContext *cx)
|
||||
AutoLockGC lock(rt);
|
||||
|
||||
/* Indicate that a request is running. */
|
||||
rt->requestCount++;
|
||||
rt->requestDepth = 1;
|
||||
|
||||
if (rt->requestCount == 1 && rt->activityCallback)
|
||||
if (rt->activityCallback)
|
||||
rt->activityCallback(rt->activityCallbackArg, true);
|
||||
}
|
||||
}
|
||||
@ -1037,13 +1035,8 @@ StopRequest(JSContext *cx)
|
||||
|
||||
rt->requestDepth = 0;
|
||||
|
||||
/* Give the GC a chance to run if this was the last request running. */
|
||||
JS_ASSERT(rt->requestCount > 0);
|
||||
rt->requestCount--;
|
||||
if (rt->requestCount == 0) {
|
||||
if (rt->activityCallback)
|
||||
rt->activityCallback(rt->activityCallbackArg, false);
|
||||
}
|
||||
if (rt->activityCallback)
|
||||
rt->activityCallback(rt->activityCallbackArg, false);
|
||||
}
|
||||
}
|
||||
#endif /* JS_THREADSAFE */
|
||||
@ -2216,7 +2209,7 @@ JS_free(JSContext *cx, void *p)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_updateMallocCounter(JSContext *cx, size_t nbytes)
|
||||
{
|
||||
return cx->runtime->updateMallocCounter(nbytes);
|
||||
return cx->runtime->updateMallocCounter(cx, nbytes);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(char *)
|
||||
|
@ -2506,7 +2506,7 @@ mjit::stubs::ArrayShift(VMFrame &f)
|
||||
* themselves.
|
||||
*/
|
||||
uint32_t initlen = obj->getDenseArrayInitializedLength();
|
||||
obj->moveDenseArrayElements(0, 1, initlen);
|
||||
obj->moveDenseArrayElementsUnbarriered(0, 1, initlen);
|
||||
}
|
||||
#endif /* JS_METHODJIT */
|
||||
|
||||
@ -2533,7 +2533,7 @@ js::array_shift(JSContext *cx, uintN argc, Value *vp)
|
||||
args.rval() = obj->getDenseArrayElement(0);
|
||||
if (args.rval().isMagic(JS_ARRAY_HOLE))
|
||||
args.rval().setUndefined();
|
||||
obj->moveDenseArrayElements(0, 1, length);
|
||||
obj->moveDenseArrayElements(0, 1, obj->getDenseArrayInitializedLength() - 1);
|
||||
obj->setDenseArrayInitializedLength(obj->getDenseArrayInitializedLength() - 1);
|
||||
obj->setArrayLength(cx, length);
|
||||
if (!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(length)))
|
||||
|
@ -245,13 +245,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
JS_ASSERT(!cx->enumerators);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* For API compatibility we support destroying contexts with non-zero
|
||||
* cx->outstandingRequests but we assume that all JS_BeginRequest calls
|
||||
* on this cx contributes to cx->thread->data.requestDepth and there is no
|
||||
* JS_SuspendRequest calls that set aside the counter.
|
||||
*/
|
||||
JS_ASSERT(cx->outstandingRequests <= cx->runtime->requestDepth);
|
||||
JS_ASSERT(cx->outstandingRequests == 0);
|
||||
#endif
|
||||
|
||||
if (mode != JSDCM_NEW_FAILED) {
|
||||
@ -268,11 +262,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
JS_LOCK_GC(rt);
|
||||
JS_REMOVE_LINK(&cx->link);
|
||||
bool last = !rt->hasContexts();
|
||||
if (last || mode == JSDCM_FORCE_GC || mode == JSDCM_MAYBE_GC
|
||||
#ifdef JS_THREADSAFE
|
||||
|| cx->outstandingRequests != 0
|
||||
#endif
|
||||
) {
|
||||
if (last || mode == JSDCM_FORCE_GC || mode == JSDCM_MAYBE_GC) {
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
@ -281,16 +271,6 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
||||
if (last) {
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* If this thread is not in a request already, begin one now so
|
||||
* that we wait for any racing GC started on a not-last context to
|
||||
* finish, before we plow ahead and unpin atoms.
|
||||
*/
|
||||
if (cx->runtime->requestDepth == 0)
|
||||
JS_BeginRequest(cx);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dump remaining type inference results first. This printing
|
||||
* depends on atoms still existing.
|
||||
@ -308,27 +288,15 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||
c->clearTraps(cx);
|
||||
JS_ClearAllWatchPoints(cx);
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Destroying a context implicitly calls JS_EndRequest(). */
|
||||
while (cx->outstandingRequests != 0)
|
||||
JS_EndRequest(cx);
|
||||
#endif
|
||||
|
||||
if (last) {
|
||||
js_GC(cx, NULL, GC_NORMAL, gcreason::LAST_CONTEXT);
|
||||
|
||||
/* Take the runtime down, now that it has no contexts or atoms. */
|
||||
JS_LOCK_GC(rt);
|
||||
} else {
|
||||
if (mode == JSDCM_FORCE_GC)
|
||||
js_GC(cx, NULL, GC_NORMAL, gcreason::DESTROY_CONTEXT);
|
||||
else if (mode == JSDCM_MAYBE_GC)
|
||||
JS_MaybeGC(cx);
|
||||
|
||||
JS_LOCK_GC(rt);
|
||||
} else if (mode == JSDCM_FORCE_GC) {
|
||||
js_GC(cx, NULL, GC_NORMAL, gcreason::DESTROY_CONTEXT);
|
||||
} else if (mode == JSDCM_MAYBE_GC) {
|
||||
JS_MaybeGC(cx);
|
||||
}
|
||||
JS_LOCK_GC(rt);
|
||||
}
|
||||
#ifdef JS_THREADSAFE
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
@ -352,21 +320,6 @@ js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp)
|
||||
return cx;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSContext *)
|
||||
js_NextActiveContext(JSRuntime *rt, JSContext *cx)
|
||||
{
|
||||
JSContext *iter = cx;
|
||||
#ifdef JS_THREADSAFE
|
||||
while ((cx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
|
||||
if (cx->outstandingRequests && cx->runtime->requestDepth)
|
||||
break;
|
||||
}
|
||||
return cx;
|
||||
#else
|
||||
return js_ContextIterator(rt, JS_FALSE, &iter);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
@ -1170,6 +1123,19 @@ JSContext::runningWithTrustedPrincipals() const
|
||||
return !compartment || compartment->principals == runtime->trustedPrincipals();
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::updateMallocCounter(JSContext *cx, size_t nbytes)
|
||||
{
|
||||
/* We tolerate any thread races when updating gcMallocBytes. */
|
||||
ptrdiff_t oldCount = gcMallocBytes;
|
||||
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
|
||||
gcMallocBytes = newCount;
|
||||
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
|
||||
onTooMuchMalloc();
|
||||
else if (cx && cx->compartment)
|
||||
cx->compartment->updateMallocCounter(nbytes);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JSRuntime::onTooMuchMalloc()
|
||||
{
|
||||
|
@ -453,7 +453,6 @@ struct JSRuntime
|
||||
#ifdef JS_THREADSAFE
|
||||
/* These combine to interlock the GC and new requests. */
|
||||
PRLock *gcLock;
|
||||
uint32_t requestCount;
|
||||
|
||||
js::GCHelperThread gcHelperThread;
|
||||
#endif /* JS_THREADSAFE */
|
||||
@ -559,7 +558,7 @@ struct JSRuntime
|
||||
* reporting OOM error when cx is not null. We will not GC from here.
|
||||
*/
|
||||
void* malloc_(size_t bytes, JSContext *cx = NULL) {
|
||||
updateMallocCounter(bytes);
|
||||
updateMallocCounter(cx, bytes);
|
||||
void *p = ::js_malloc(bytes);
|
||||
return JS_LIKELY(!!p) ? p : onOutOfMemory(NULL, bytes, cx);
|
||||
}
|
||||
@ -569,14 +568,14 @@ struct JSRuntime
|
||||
* reporting OOM error when cx is not null. We will not GC from here.
|
||||
*/
|
||||
void* calloc_(size_t bytes, JSContext *cx = NULL) {
|
||||
updateMallocCounter(bytes);
|
||||
updateMallocCounter(cx, bytes);
|
||||
void *p = ::js_calloc(bytes);
|
||||
return JS_LIKELY(!!p) ? p : onOutOfMemory(reinterpret_cast<void *>(1), bytes, cx);
|
||||
}
|
||||
|
||||
void* realloc_(void* p, size_t oldBytes, size_t newBytes, JSContext *cx = NULL) {
|
||||
JS_ASSERT(oldBytes < newBytes);
|
||||
updateMallocCounter(newBytes - oldBytes);
|
||||
updateMallocCounter(cx, newBytes - oldBytes);
|
||||
void *p2 = ::js_realloc(p, newBytes);
|
||||
return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, newBytes, cx);
|
||||
}
|
||||
@ -587,7 +586,7 @@ struct JSRuntime
|
||||
* previously allocated memory.
|
||||
*/
|
||||
if (!p)
|
||||
updateMallocCounter(bytes);
|
||||
updateMallocCounter(cx, bytes);
|
||||
void *p2 = ::js_realloc(p, bytes);
|
||||
return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
|
||||
}
|
||||
@ -621,13 +620,7 @@ struct JSRuntime
|
||||
* The function must be called outside the GC lock and in case of OOM error
|
||||
* the caller must ensure that no deadlock possible during OOM reporting.
|
||||
*/
|
||||
void updateMallocCounter(size_t nbytes) {
|
||||
/* We tolerate any thread races when updating gcMallocBytes. */
|
||||
ptrdiff_t newCount = gcMallocBytes - ptrdiff_t(nbytes);
|
||||
gcMallocBytes = newCount;
|
||||
if (JS_UNLIKELY(newCount <= 0))
|
||||
onTooMuchMalloc();
|
||||
}
|
||||
void updateMallocCounter(JSContext *cx, size_t nbytes);
|
||||
|
||||
/*
|
||||
* The function must be called outside the GC lock.
|
||||
@ -1364,14 +1357,6 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
|
||||
extern JSContext *
|
||||
js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp);
|
||||
|
||||
/*
|
||||
* Iterate through contexts with active requests. The caller must be holding
|
||||
* rt->gcLock in case of a thread-safe build, or otherwise guarantee that the
|
||||
* context list is not alternated asynchroniously.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSContext *)
|
||||
js_NextActiveContext(JSRuntime *, JSContext *);
|
||||
|
||||
#ifdef va_start
|
||||
extern JSBool
|
||||
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
|
||||
|
@ -92,6 +92,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
watchpointMap(NULL)
|
||||
{
|
||||
PodArrayZero(evalCache);
|
||||
setGCMaxMallocBytes(rt->gcMaxMallocBytes * 0.9);
|
||||
}
|
||||
|
||||
JSCompartment::~JSCompartment()
|
||||
@ -569,6 +570,30 @@ JSCompartment::purge(JSContext *cx)
|
||||
toSourceCache.destroyIfConstructed();
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::resetGCMallocBytes()
|
||||
{
|
||||
gcMallocBytes = ptrdiff_t(gcMaxMallocBytes);
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::setGCMaxMallocBytes(size_t value)
|
||||
{
|
||||
/*
|
||||
* For compatibility treat any value that exceeds PTRDIFF_T_MAX to
|
||||
* mean that value.
|
||||
*/
|
||||
gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
|
||||
resetGCMallocBytes();
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::onTooMuchMalloc()
|
||||
{
|
||||
TriggerCompartmentGC(this, gcreason::TOO_MUCH_MALLOC);
|
||||
}
|
||||
|
||||
|
||||
MathCache *
|
||||
JSCompartment::allocMathCache(JSContext *cx)
|
||||
{
|
||||
@ -745,10 +770,10 @@ JSCompartment::createBarrierTracer()
|
||||
}
|
||||
|
||||
size_t
|
||||
JS::SizeOfCompartmentShapeTable(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf)
|
||||
JSCompartment::sizeOfShapeTable(JSMallocSizeOfFun mallocSizeOf)
|
||||
{
|
||||
return c->baseShapes.sizeOfExcludingThis(mallocSizeOf)
|
||||
+ c->initialShapes.sizeOfExcludingThis(mallocSizeOf)
|
||||
+ c->newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
|
||||
+ c->lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
|
||||
return baseShapes.sizeOfExcludingThis(mallocSizeOf)
|
||||
+ initialShapes.sizeOfExcludingThis(mallocSizeOf)
|
||||
+ newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
|
||||
+ lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
@ -164,6 +164,10 @@ typedef HashSet<ScriptFilenameEntry *,
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
namespace JS {
|
||||
struct TypeInferenceSizes;
|
||||
}
|
||||
|
||||
struct JSCompartment
|
||||
{
|
||||
JSRuntime *rt;
|
||||
@ -188,6 +192,7 @@ struct JSCompartment
|
||||
size_t gcBytes;
|
||||
size_t gcTriggerBytes;
|
||||
size_t gcLastBytes;
|
||||
size_t gcMaxMallocBytes;
|
||||
|
||||
bool hold;
|
||||
bool isSystemCompartment;
|
||||
@ -239,6 +244,10 @@ struct JSCompartment
|
||||
size_t sizeOfMjitCode() const;
|
||||
#endif
|
||||
|
||||
size_t sizeOfShapeTable(JSMallocSizeOfFun mallocSizeOf);
|
||||
void sizeOfTypeInferenceData(JSContext *cx, JS::TypeInferenceSizes *stats,
|
||||
JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
/*
|
||||
* Shared scope property tree, and arena-pool for allocating its nodes.
|
||||
*/
|
||||
@ -279,6 +288,12 @@ struct JSCompartment
|
||||
enum { DebugFromC = 1, DebugFromJS = 2 };
|
||||
|
||||
uintN debugModeBits; // see debugMode() below
|
||||
|
||||
/*
|
||||
* Malloc counter to measure memory pressure for GC scheduling. It runs
|
||||
* from gcMaxMallocBytes down to zero.
|
||||
*/
|
||||
volatile ptrdiff_t gcMallocBytes;
|
||||
|
||||
public:
|
||||
js::NativeIterCache nativeIterCache;
|
||||
@ -312,6 +327,18 @@ struct JSCompartment
|
||||
|
||||
void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
|
||||
void reduceGCTriggerBytes(size_t amount);
|
||||
|
||||
void resetGCMallocBytes();
|
||||
void setGCMaxMallocBytes(size_t value);
|
||||
void updateMallocCounter(size_t nbytes) {
|
||||
ptrdiff_t oldCount = gcMallocBytes;
|
||||
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
|
||||
gcMallocBytes = newCount;
|
||||
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
|
||||
onTooMuchMalloc();
|
||||
}
|
||||
|
||||
void onTooMuchMalloc();
|
||||
|
||||
js::DtoaCache dtoaCache;
|
||||
|
||||
|
@ -2850,6 +2850,16 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind)
|
||||
/* Clear gcIsNeeded now, when we are about to start a normal GC cycle. */
|
||||
rt->gcIsNeeded = false;
|
||||
rt->gcTriggerCompartment = NULL;
|
||||
|
||||
/* Clear gcMallocBytes for all compartments */
|
||||
JSCompartment **read = rt->compartments.begin();
|
||||
JSCompartment **end = rt->compartments.end();
|
||||
JS_ASSERT(rt->compartments.length() >= 1);
|
||||
|
||||
while (read < end) {
|
||||
JSCompartment *compartment = *read++;
|
||||
compartment->resetGCMallocBytes();
|
||||
}
|
||||
|
||||
/* Reset weak map list. */
|
||||
WeakMapBase::resetWeakMapList(rt);
|
||||
|
@ -6258,12 +6258,12 @@ TypeScript::destroy()
|
||||
}
|
||||
|
||||
inline size_t
|
||||
TypeSet::dynamicSize()
|
||||
TypeSet::computedSizeOfExcludingThis()
|
||||
{
|
||||
/*
|
||||
* This memory is allocated within the temp pool (but accounted for
|
||||
* elsewhere) so we can't use a JSMallocSizeOfFun to measure it. We must
|
||||
* do it analytically.
|
||||
* compute its size analytically.
|
||||
*/
|
||||
uint32_t count = baseObjectCount();
|
||||
if (count >= 2)
|
||||
@ -6272,12 +6272,12 @@ TypeSet::dynamicSize()
|
||||
}
|
||||
|
||||
inline size_t
|
||||
TypeObject::dynamicSize()
|
||||
TypeObject::computedSizeOfExcludingThis()
|
||||
{
|
||||
/*
|
||||
* This memory is allocated within the temp pool (but accounted for
|
||||
* elsewhere) so we can't use a JSMallocSizeOfFun to measure it. We must
|
||||
* do it analytically.
|
||||
* compute its size analytically.
|
||||
*/
|
||||
size_t bytes = 0;
|
||||
|
||||
@ -6289,14 +6289,15 @@ TypeObject::dynamicSize()
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
Property *prop = getProperty(i);
|
||||
if (prop)
|
||||
bytes += sizeof(Property) + prop->types.dynamicSize();
|
||||
bytes += sizeof(Property) + prop->types.computedSizeOfExcludingThis();
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static void
|
||||
GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
|
||||
SizeOfScriptTypeInferenceData(JSScript *script, TypeInferenceSizes *sizes,
|
||||
JSMallocSizeOfFun mallocSizeOf)
|
||||
{
|
||||
TypeScript *typeScript = script->types;
|
||||
if (!typeScript)
|
||||
@ -6304,18 +6305,18 @@ GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSMalloc
|
||||
|
||||
/* If TI is disabled, a single TypeScript is still present. */
|
||||
if (!script->compartment()->types.inferenceEnabled) {
|
||||
stats->scripts += mallocSizeOf(typeScript);
|
||||
sizes->scripts += mallocSizeOf(typeScript);
|
||||
return;
|
||||
}
|
||||
|
||||
stats->scripts += mallocSizeOf(typeScript->nesting);
|
||||
sizes->scripts += mallocSizeOf(typeScript->nesting);
|
||||
|
||||
unsigned count = TypeScript::NumTypeSets(script);
|
||||
stats->scripts += mallocSizeOf(typeScript);
|
||||
sizes->scripts += mallocSizeOf(typeScript);
|
||||
|
||||
TypeResult *result = typeScript->dynamicList;
|
||||
while (result) {
|
||||
stats->scripts += mallocSizeOf(result);
|
||||
sizes->scripts += mallocSizeOf(result);
|
||||
result = result->next;
|
||||
}
|
||||
|
||||
@ -6325,15 +6326,14 @@ GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSMalloc
|
||||
*/
|
||||
TypeSet *typeArray = typeScript->typeArray();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
size_t bytes = typeArray[i].dynamicSize();
|
||||
stats->scripts += bytes;
|
||||
stats->temporary -= bytes;
|
||||
size_t bytes = typeArray[i].computedSizeOfExcludingThis();
|
||||
sizes->scripts += bytes;
|
||||
sizes->temporary -= bytes;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JS::SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment,
|
||||
TypeInferenceMemoryStats *stats,
|
||||
JSCompartment::sizeOfTypeInferenceData(JSContext *cx, TypeInferenceSizes *sizes,
|
||||
JSMallocSizeOfFun mallocSizeOf)
|
||||
{
|
||||
/*
|
||||
@ -6341,28 +6341,27 @@ JS::SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment
|
||||
* by being copied to the replacement pool. This memory will be counted
|
||||
* elsewhere and deducted from the amount of temporary data.
|
||||
*/
|
||||
stats->temporary += compartment->typeLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
|
||||
sizes->temporary += typeLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
|
||||
|
||||
/* Pending arrays are cleared on GC along with the analysis pool. */
|
||||
stats->temporary +=
|
||||
mallocSizeOf(compartment->types.pendingArray);
|
||||
sizes->temporary += mallocSizeOf(types.pendingArray);
|
||||
|
||||
/* TypeCompartment::pendingRecompiles is non-NULL only while inference code is running. */
|
||||
JS_ASSERT(!compartment->types.pendingRecompiles);
|
||||
JS_ASSERT(!types.pendingRecompiles);
|
||||
|
||||
for (gc::CellIter i(cx, compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next())
|
||||
GetScriptMemoryStats(i.get<JSScript>(), stats, mallocSizeOf);
|
||||
for (gc::CellIter i(cx, this, gc::FINALIZE_SCRIPT); !i.done(); i.next())
|
||||
SizeOfScriptTypeInferenceData(i.get<JSScript>(), sizes, mallocSizeOf);
|
||||
|
||||
if (compartment->types.allocationSiteTable)
|
||||
stats->tables += compartment->types.allocationSiteTable->sizeOfIncludingThis(mallocSizeOf);
|
||||
if (types.allocationSiteTable)
|
||||
sizes->tables += types.allocationSiteTable->sizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
if (compartment->types.arrayTypeTable)
|
||||
stats->tables += compartment->types.arrayTypeTable->sizeOfIncludingThis(mallocSizeOf);
|
||||
if (types.arrayTypeTable)
|
||||
sizes->tables += types.arrayTypeTable->sizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
if (compartment->types.objectTypeTable) {
|
||||
stats->tables += compartment->types.objectTypeTable->sizeOfIncludingThis(mallocSizeOf);
|
||||
if (types.objectTypeTable) {
|
||||
sizes->tables += types.objectTypeTable->sizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
for (ObjectTypeTable::Enum e(*compartment->types.objectTypeTable);
|
||||
for (ObjectTypeTable::Enum e(*types.objectTypeTable);
|
||||
!e.empty();
|
||||
e.popFront())
|
||||
{
|
||||
@ -6370,34 +6369,31 @@ JS::SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment
|
||||
const ObjectTableEntry &value = e.front().value;
|
||||
|
||||
/* key.ids and values.types have the same length. */
|
||||
stats->tables += mallocSizeOf(key.ids) + mallocSizeOf(value.types);
|
||||
sizes->tables += mallocSizeOf(key.ids) + mallocSizeOf(value.types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JS::SizeOfTypeObjectExcludingThis(void *object_, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
|
||||
TypeObject::sizeOfExcludingThis(TypeInferenceSizes *sizes, JSMallocSizeOfFun mallocSizeOf)
|
||||
{
|
||||
TypeObject *object = (TypeObject *) object_;
|
||||
|
||||
if (object->singleton) {
|
||||
if (singleton) {
|
||||
/*
|
||||
* Properties and associated type sets for singletons are cleared on
|
||||
* every GC. The type object is normally destroyed too, but we don't
|
||||
* charge this to 'temporary' as this is not for GC heap values.
|
||||
*/
|
||||
JS_ASSERT(!object->newScript);
|
||||
JS_ASSERT(!newScript);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object->newScript)
|
||||
stats->objects += mallocSizeOf(object->newScript);
|
||||
sizes->objects += mallocSizeOf(newScript);
|
||||
|
||||
/*
|
||||
* This counts memory that is in the temp pool but gets attributed
|
||||
* elsewhere. See JS_GetTypeInferenceMemoryStats for more details.
|
||||
* elsewhere. See JSCompartment::sizeOfTypeInferenceData for more details.
|
||||
*/
|
||||
size_t bytes = object->dynamicSize();
|
||||
stats->objects += bytes;
|
||||
stats->temporary -= bytes;
|
||||
size_t bytes = computedSizeOfExcludingThis();
|
||||
sizes->objects += bytes;
|
||||
sizes->temporary -= bytes;
|
||||
}
|
||||
|
@ -51,6 +51,10 @@
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/HashTable.h"
|
||||
|
||||
namespace JS {
|
||||
struct TypeInferenceSizes;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace types {
|
||||
|
||||
@ -366,7 +370,7 @@ class TypeSet
|
||||
void print(JSContext *cx);
|
||||
|
||||
inline void sweep(JSContext *cx, JSCompartment *compartment);
|
||||
inline size_t dynamicSize();
|
||||
inline size_t computedSizeOfExcludingThis();
|
||||
|
||||
/* Whether this set contains a specific type. */
|
||||
inline bool hasType(Type type);
|
||||
@ -865,7 +869,9 @@ struct TypeObject : gc::Cell
|
||||
inline void clearProperties();
|
||||
inline void sweep(JSContext *cx);
|
||||
|
||||
inline size_t dynamicSize();
|
||||
inline size_t computedSizeOfExcludingThis();
|
||||
|
||||
void sizeOfExcludingThis(TypeInferenceSizes *sizes, JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
/*
|
||||
* Type objects don't have explicit finalizers. Memory owned by a type
|
||||
|
@ -1066,6 +1066,7 @@ struct JSObject : js::gc::Cell
|
||||
inline void copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count);
|
||||
inline void initDenseArrayElements(uintN dstStart, const js::Value *src, uintN count);
|
||||
inline void moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count);
|
||||
inline void moveDenseArrayElementsUnbarriered(uintN dstStart, uintN srcStart, uintN count);
|
||||
inline bool denseArrayHasInlineSlots() const;
|
||||
|
||||
/* Packed information for this array. */
|
||||
|
@ -607,7 +607,7 @@ inline void
|
||||
JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count)
|
||||
{
|
||||
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
|
||||
JS_ASSERT(srcStart + count <= getDenseArrayCapacity());
|
||||
JS_ASSERT(srcStart + count <= getDenseArrayInitializedLength());
|
||||
|
||||
/*
|
||||
* Use a custom write barrier here since it's performance sensitive. We
|
||||
@ -626,6 +626,13 @@ JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count)
|
||||
memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::moveDenseArrayElementsUnbarriered(uintN dstStart, uintN srcStart, uintN count)
|
||||
{
|
||||
JS_ASSERT(!compartment()->needsBarrier());
|
||||
memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::denseArrayHasInlineSlots() const
|
||||
{
|
||||
|
@ -2607,7 +2607,8 @@ GetElementIC::update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *
|
||||
* indexes in the emitter, i.e. js_GetProtoIfDenseArray is only valid to
|
||||
* use when looking up non-integer identifiers.
|
||||
*/
|
||||
if (v.isString() && js_CheckForStringIndex(id) == id)
|
||||
uint32_t dummy;
|
||||
if (v.isString() && JSID_IS_ATOM(id) && !JSID_TO_ATOM(id)->isIndex(&dummy))
|
||||
return attachGetProp(f, obj, v, JSID_TO_ATOM(id)->asPropertyName(), vp);
|
||||
|
||||
if (obj->isArguments())
|
||||
|
@ -3888,15 +3888,6 @@ MJitChunkLimit(JSContext *cx, uintN argc, jsval *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
StringStats(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
// XXX: should report something meaningful; bug 625305 will probably fix
|
||||
// this.
|
||||
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
enum CompartmentKind { SAME_COMPARTMENT, NEW_COMPARTMENT };
|
||||
|
||||
static JSObject *
|
||||
@ -4062,7 +4053,6 @@ static JSFunctionSpec shell_functions[] = {
|
||||
JS_FN("mjitcodestats", MJitCodeStats, 0,0),
|
||||
#endif
|
||||
JS_FN("mjitChunkLimit", MJitChunkLimit, 1,0),
|
||||
JS_FN("stringstats", StringStats, 0,0),
|
||||
JS_FN("newGlobal", NewGlobal, 1,0),
|
||||
JS_FN("parseLegacyJSON",ParseLegacyJSON,1,0),
|
||||
JS_FN("enableStackWalkingAssertion",EnableStackWalkingAssertion,1,0),
|
||||
@ -4211,7 +4201,6 @@ static const char *const shell_help_messages[] = {
|
||||
"mjitcodestats() Return stats on mjit code memory usage.",
|
||||
#endif
|
||||
"mjitChunkLimit(N) Specify limit on compiled chunk size during mjit compilation.",
|
||||
"stringstats() Return stats on string memory usage.",
|
||||
"newGlobal(kind) Return a new global object, in the current\n"
|
||||
" compartment if kind === 'same-compartment' or in a\n"
|
||||
" new compartment if kind === 'new-compartment'",
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
* Contributor:
|
||||
* Jeff Walden <jwalden+code@mit.edu>
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 721322;
|
||||
var summary =
|
||||
'f.arguments must trigger an arguments object in non-strict mode functions';
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
var obj =
|
||||
{
|
||||
test: function()
|
||||
{
|
||||
var args = obj.test.arguments;
|
||||
assertEq(args !== null, true);
|
||||
assertEq(args[0], 5);
|
||||
assertEq(args[1], undefined);
|
||||
assertEq(args.length, 2);
|
||||
}
|
||||
};
|
||||
obj.test(5, undefined);
|
||||
|
||||
var sobj =
|
||||
{
|
||||
test: function()
|
||||
{
|
||||
"use strict";
|
||||
|
||||
try
|
||||
{
|
||||
var args = sobj.test.arguments;
|
||||
throw new Error("access to arguments property of strict mode " +
|
||||
"function didn't throw");
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
assertEq(e instanceof TypeError, true,
|
||||
"should have thrown TypeError, instead got: " + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
sobj.test(5, undefined);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
@ -1,4 +1,5 @@
|
||||
url-prefix ../../jsreftest.html?test=ecma_5/extensions/
|
||||
script arguments-property-access-in-function.js
|
||||
script 8.12.5-01.js
|
||||
script 15.4.4.11.js
|
||||
script 15.9.4.2.js
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
* Contributor:
|
||||
* Jeff Walden <jwalden+code@mit.edu>
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 721322;
|
||||
var summary = 'Allow f.arguments in generator expressions';
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
eval("(function() { return (f.arguments for (x in [1])); })()");
|
||||
eval("(function() { var f = { arguments: 12 }; return [f.arguments for (x in [1])]; })()");
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
@ -1,4 +1,5 @@
|
||||
url-prefix ../../jsreftest.html?test=js1_8/genexps/
|
||||
script arguments-property-access-in-generator.js
|
||||
script regress-347739.js
|
||||
script regress-349012-01.js
|
||||
script regress-349326.js
|
||||
|
@ -249,7 +249,7 @@ JSExternalString::new_(JSContext *cx, const jschar *chars, size_t length, intN t
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->init(chars, length, type, closure);
|
||||
cx->runtime->updateMallocCounter((length + 1) * sizeof(jschar));
|
||||
cx->runtime->updateMallocCounter(cx, (length + 1) * sizeof(jschar));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -2012,6 +2012,7 @@ main(int argc, char **argv, char **envp)
|
||||
cxstack = nsnull;
|
||||
JS_GC(cx);
|
||||
} //this scopes the JSAutoCrossCompartmentCall
|
||||
JS_EndRequest(cx);
|
||||
JS_DestroyContext(cx);
|
||||
} // this scopes the nsCOMPtrs
|
||||
|
||||
|
@ -1350,11 +1350,11 @@ ReportMemoryPercentage(const nsACString &path, PRInt32 kind, PRInt64 amount,
|
||||
template <int N>
|
||||
inline const nsCString
|
||||
MakeMemoryReporterPath(const nsACString &pathPrefix,
|
||||
const JS::CompartmentStats &compartmentStats,
|
||||
const JS::CompartmentStats &cStats,
|
||||
const char (&reporterName)[N])
|
||||
{
|
||||
return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
|
||||
*static_cast<nsCString*>(compartmentStats.name) +
|
||||
*static_cast<nsCString*>(cStats.name) +
|
||||
NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName);
|
||||
}
|
||||
|
||||
@ -1421,56 +1421,53 @@ namespace mozilla {
|
||||
namespace xpconnect {
|
||||
namespace memory {
|
||||
|
||||
#define SLOP_BYTES_STRING \
|
||||
" The measurement includes slop bytes caused by the heap allocator rounding up request sizes."
|
||||
|
||||
static PRInt64
|
||||
ReportCompartmentStats(const JS::CompartmentStats &stats,
|
||||
ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
||||
const nsACString &pathPrefix,
|
||||
nsIMemoryMultiReporterCallback *callback,
|
||||
nsISupports *closure)
|
||||
{
|
||||
PRInt64 gcTotal = 0;
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/arena/headers"),
|
||||
&gcTotal, stats.gcHeapArenaHeaders,
|
||||
&gcTotal, cStats.gcHeapArenaHeaders,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap, within "
|
||||
"arenas, that is used to hold internal book-keeping information.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/arena/padding"),
|
||||
&gcTotal, stats.gcHeapArenaPadding,
|
||||
&gcTotal, cStats.gcHeapArenaPadding,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap, within "
|
||||
"arenas, that is unused and present only so that other data is aligned. "
|
||||
"This constitutes internal fragmentation.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/arena/unused"),
|
||||
&gcTotal, stats.gcHeapArenaUnused,
|
||||
&gcTotal, cStats.gcHeapArenaUnused,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap, within "
|
||||
"arenas, that could be holding useful data but currently isn't.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/objects/non-function"),
|
||||
&gcTotal, stats.gcHeapObjectsNonFunction,
|
||||
&gcTotal, cStats.gcHeapObjectsNonFunction,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"non-function objects.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/objects/function"),
|
||||
&gcTotal, stats.gcHeapObjectsFunction,
|
||||
&gcTotal, cStats.gcHeapObjectsFunction,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"function objects.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/strings"),
|
||||
&gcTotal, stats.gcHeapStrings,
|
||||
&gcTotal, cStats.gcHeapStrings,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"string headers. String headers contain various pieces of information "
|
||||
"about a string, but do not contain (except in the case of very short "
|
||||
@ -1478,69 +1475,69 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
|
||||
"under 'gc-heap/string-chars' instead.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/scripts"),
|
||||
&gcTotal, stats.gcHeapScripts,
|
||||
&gcTotal, cStats.gcHeapScripts,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"JSScript instances. A JSScript is created for each user-defined function "
|
||||
"in a script. One is also created for the top-level code in a script.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/shapes/tree"),
|
||||
&gcTotal, stats.gcHeapShapesTree,
|
||||
&gcTotal, cStats.gcHeapShapesTree,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"shapes that are in a property tree.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/shapes/dict"),
|
||||
&gcTotal, stats.gcHeapShapesDict,
|
||||
&gcTotal, cStats.gcHeapShapesDict,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"shapes that are in dictionary mode.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/shapes/base"),
|
||||
&gcTotal, stats.gcHeapShapesBase,
|
||||
&gcTotal, cStats.gcHeapShapesBase,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that collates "
|
||||
"data common to many shapes.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/type-objects"),
|
||||
&gcTotal, stats.gcHeapTypeObjects,
|
||||
&gcTotal, cStats.gcHeapTypeObjects,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"type inference information.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"gc-heap/xml"),
|
||||
&gcTotal, stats.gcHeapXML,
|
||||
&gcTotal, cStats.gcHeapXML,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"E4X XML objects.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"object-slots"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.objectSlots,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectSlots,
|
||||
"Memory allocated for the compartment's non-fixed object slot arrays, "
|
||||
"which are used to represent object properties. Some objects also "
|
||||
"contain a fixed number of slots which are stored on the compartment's "
|
||||
"JavaScript heap; those slots are not counted here, but in "
|
||||
"'gc-heap/objects' instead." SLOP_BYTES_STRING,
|
||||
"'gc-heap/objects' instead.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"object-elements"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.objectElements,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectElements,
|
||||
"Memory allocated for the compartment's object element arrays, "
|
||||
"which are used to represent indexed object properties." SLOP_BYTES_STRING,
|
||||
"which are used to represent indexed object properties.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"string-chars"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.stringChars,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.stringChars,
|
||||
"Memory allocated to hold the compartment's string characters. Sometimes "
|
||||
"more memory is allocated than necessary, to simplify string "
|
||||
"concatenation. Each string also includes a header which is stored on the "
|
||||
@ -1548,83 +1545,83 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
|
||||
"'gc-heap/strings' instead.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"shapes-extra/tree-tables"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraTreeTables,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeTables,
|
||||
"Memory allocated for the compartment's property tables that belong to "
|
||||
"shapes that are in a property tree." SLOP_BYTES_STRING,
|
||||
"shapes that are in a property tree.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"shapes-extra/dict-tables"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraDictTables,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraDictTables,
|
||||
"Memory allocated for the compartment's property tables that belong to "
|
||||
"shapes that are in dictionary mode." SLOP_BYTES_STRING,
|
||||
"shapes that are in dictionary mode.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"shapes-extra/tree-shape-kids"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraTreeShapeKids,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeShapeKids,
|
||||
"Memory allocated for the compartment's kid hashes that belong to shapes "
|
||||
"that are in a property tree.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"shapes-extra/compartment-tables"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.shapesCompartmentTables,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesCompartmentTables,
|
||||
"Memory used by compartment wide tables storing shape information "
|
||||
"for use during object construction.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"script-data"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.scriptData,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.scriptData,
|
||||
"Memory allocated for JSScript bytecode and various variable-length "
|
||||
"tables." SLOP_BYTES_STRING,
|
||||
"tables.",
|
||||
callback, closure);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"mjit-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, stats.mjitCode,
|
||||
nsIMemoryReporter::KIND_NONHEAP, cStats.mjitCode,
|
||||
"Memory used by the method JIT to hold the compartment's generated code.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"mjit-data"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats.mjitData,
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.mjitData,
|
||||
"Memory used by the method JIT for the compartment's compilation data: "
|
||||
"JITScripts, native maps, and inline cache structs." SLOP_BYTES_STRING,
|
||||
"JITScripts, native maps, and inline cache structs.",
|
||||
callback, closure);
|
||||
#endif
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"type-inference/script-main"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
stats.typeInferenceMemory.scripts,
|
||||
cStats.typeInferenceSizes.scripts,
|
||||
"Memory used during type inference to store type sets of variables "
|
||||
"and dynamically observed types.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"type-inference/object-main"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
stats.typeInferenceMemory.objects,
|
||||
cStats.typeInferenceSizes.objects,
|
||||
"Memory used during type inference to store types and possible "
|
||||
"property types of JS objects.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"type-inference/tables"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
stats.typeInferenceMemory.tables,
|
||||
cStats.typeInferenceSizes.tables,
|
||||
"Memory used during type inference for compartment-wide tables.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
|
||||
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
|
||||
"analysis-temporary"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
stats.typeInferenceMemory.temporary,
|
||||
cStats.typeInferenceSizes.temporary,
|
||||
"Memory used during type inference and compilation to hold transient "
|
||||
"analysis information. Cleared on GC.",
|
||||
callback, closure);
|
||||
@ -1633,55 +1630,54 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
|
||||
}
|
||||
|
||||
void
|
||||
ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
|
||||
ReportJSRuntimeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix,
|
||||
nsIMemoryMultiReporterCallback *callback,
|
||||
nsISupports *closure)
|
||||
{
|
||||
PRInt64 gcTotal = 0;
|
||||
for (size_t index = 0;
|
||||
index < data.compartmentStatsVector.length();
|
||||
index < rtStats.compartmentStatsVector.length();
|
||||
index++) {
|
||||
gcTotal += ReportCompartmentStats(data.compartmentStatsVector[index], pathPrefix,
|
||||
gcTotal += ReportCompartmentStats(rtStats.compartmentStatsVector[index], pathPrefix,
|
||||
callback, closure);
|
||||
}
|
||||
|
||||
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"),
|
||||
nsIMemoryReporter::KIND_HEAP, data.runtimeObject,
|
||||
"Memory used by the JSRuntime object." SLOP_BYTES_STRING,
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeObject,
|
||||
"Memory used by the JSRuntime object.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"),
|
||||
nsIMemoryReporter::KIND_HEAP, data.runtimeAtomsTable,
|
||||
"Memory used by the atoms table." SLOP_BYTES_STRING,
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeAtomsTable,
|
||||
"Memory used by the atoms table.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"),
|
||||
nsIMemoryReporter::KIND_HEAP, data.runtimeContexts,
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeContexts,
|
||||
"Memory used by JSContext objects and certain structures "
|
||||
"hanging off them." SLOP_BYTES_STRING,
|
||||
"hanging off them." ,
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/normal"),
|
||||
nsIMemoryReporter::KIND_HEAP, data.runtimeNormal,
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeNormal,
|
||||
"Memory used by a JSRuntime, "
|
||||
"excluding memory that is reported by "
|
||||
"other reporters under 'explicit/js/runtime/'." SLOP_BYTES_STRING,
|
||||
"other reporters under 'explicit/js/runtime/'.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"),
|
||||
nsIMemoryReporter::KIND_HEAP, data.runtimeTemporary,
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeTemporary,
|
||||
"Memory held transiently in JSRuntime and used during "
|
||||
"compilation. It mostly holds parse nodes."
|
||||
SLOP_BYTES_STRING,
|
||||
"compilation. It mostly holds parse nodes.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes0(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, data.runtimeRegexpCode,
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeRegexpCode,
|
||||
"Memory used by the regexp JIT to hold generated code.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, data.runtimeStackCommitted,
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeStackCommitted,
|
||||
"Memory used for the JS call stack. This is the committed portion "
|
||||
"of the stack; the uncommitted portion is not measured because it "
|
||||
"hardly costs anything.",
|
||||
@ -1689,7 +1685,7 @@ ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
|
||||
|
||||
ReportGCHeapBytes(pathPrefix +
|
||||
NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"),
|
||||
&gcTotal, data.gcHeapChunkDirtyUnused,
|
||||
&gcTotal, rtStats.gcHeapChunkDirtyUnused,
|
||||
"Memory on the garbage-collected JavaScript heap, within chunks with at "
|
||||
"least one allocated GC thing, that could be holding useful data but "
|
||||
"currently isn't. Memory here is mutually exclusive with memory reported"
|
||||
@ -1698,7 +1694,7 @@ ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
|
||||
|
||||
ReportGCHeapBytes(pathPrefix +
|
||||
NS_LITERAL_CSTRING("gc-heap-chunk-clean-unused"),
|
||||
&gcTotal, data.gcHeapChunkCleanUnused,
|
||||
&gcTotal, rtStats.gcHeapChunkCleanUnused,
|
||||
"Memory on the garbage-collected JavaScript heap taken by completely empty "
|
||||
"chunks, that soon will be released unless claimed for new allocations. "
|
||||
"Memory here is mutually exclusive with memory reported under "
|
||||
@ -1708,21 +1704,21 @@ ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
|
||||
ReportGCHeapBytes(pathPrefix +
|
||||
NS_LITERAL_CSTRING("gc-heap-decommitted"),
|
||||
&gcTotal,
|
||||
data.gcHeapChunkCleanDecommitted + data.gcHeapChunkDirtyDecommitted,
|
||||
rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted,
|
||||
"Memory in the address space of the garbage-collected JavaScript heap that "
|
||||
"is currently returned to the OS.",
|
||||
callback, closure);
|
||||
|
||||
ReportGCHeapBytes(pathPrefix +
|
||||
NS_LITERAL_CSTRING("gc-heap-chunk-admin"),
|
||||
&gcTotal, data.gcHeapChunkAdmin,
|
||||
&gcTotal, rtStats.gcHeapChunkAdmin,
|
||||
"Memory on the garbage-collected JavaScript heap, within chunks, that is "
|
||||
"used to hold internal book-keeping information.",
|
||||
callback, closure);
|
||||
|
||||
// gcTotal is the sum of everything we've reported for the GC heap. It
|
||||
// should equal data.gcHeapChunkTotal.
|
||||
JS_ASSERT(gcTotal == data.gcHeapChunkTotal);
|
||||
// should equal rtStats.gcHeapChunkTotal.
|
||||
JS_ASSERT(gcTotal == rtStats.gcHeapChunkTotal);
|
||||
}
|
||||
|
||||
} // namespace memory
|
||||
@ -1744,12 +1740,12 @@ public:
|
||||
// the callback. Separating these steps is important because the
|
||||
// callback may be a JS function, and executing JS while getting these
|
||||
// stats seems like a bad idea.
|
||||
JS::IterateData data(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
|
||||
xpc::DestroyCompartmentName);
|
||||
if (!JS::CollectCompartmentStatsForRuntime(xpcrt->GetJSRuntime(), &data))
|
||||
JS::RuntimeStats rtStats(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
|
||||
xpc::DestroyCompartmentName);
|
||||
if (!JS::CollectRuntimeStats(xpcrt->GetJSRuntime(), &rtStats))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
uint64_t xpconnect;
|
||||
size_t xpconnect;
|
||||
{
|
||||
xpconnect =
|
||||
xpcrt->SizeOfIncludingThis(xpc::JsMallocSizeOf) +
|
||||
@ -1759,37 +1755,37 @@ public:
|
||||
NS_NAMED_LITERAL_CSTRING(pathPrefix, "explicit/js/");
|
||||
|
||||
// This is the second step (see above).
|
||||
ReportJSRuntimeStats(data, pathPrefix, callback, closure);
|
||||
ReportJSRuntimeStats(rtStats, pathPrefix, callback, closure);
|
||||
|
||||
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("xpconnect"),
|
||||
nsIMemoryReporter::KIND_HEAP, xpconnect,
|
||||
"Memory used by XPConnect." SLOP_BYTES_STRING,
|
||||
"Memory used by XPConnect.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-chunk-dirty-unused"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
data.gcHeapChunkDirtyUnused,
|
||||
rtStats.gcHeapChunkDirtyUnused,
|
||||
"The same as 'explicit/js/gc-heap-chunk-dirty-unused'. Shown here for "
|
||||
"easy comparison with other 'js-gc' reporters.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-chunk-clean-unused"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
data.gcHeapChunkCleanUnused,
|
||||
rtStats.gcHeapChunkCleanUnused,
|
||||
"The same as 'explicit/js/gc-heap-chunk-clean-unused'. Shown here for "
|
||||
"easy comparison with other 'js-gc' reporters.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-decommitted"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
data.gcHeapChunkCleanDecommitted + data.gcHeapChunkDirtyDecommitted,
|
||||
rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted,
|
||||
"The same as 'explicit/js/gc-heap-decommitted'. Shown here for "
|
||||
"easy comparison with other 'js-gc' reporters.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-arena-unused"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
data.gcHeapArenaUnused,
|
||||
rtStats.gcHeapArenaUnused,
|
||||
"Memory on the garbage-collected JavaScript heap, within arenas, that "
|
||||
"could be holding useful data but currently isn't. This is the sum of "
|
||||
"all compartments' 'gc-heap/arena-unused' numbers.",
|
||||
@ -1797,7 +1793,7 @@ public:
|
||||
|
||||
ReportMemoryPercentage(NS_LITERAL_CSTRING("js-gc-heap-unused-fraction"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
data.gcHeapUnusedPercentage,
|
||||
rtStats.gcHeapUnusedPercentage,
|
||||
"Fraction of the garbage-collected JavaScript heap that is unused. "
|
||||
"Computed as ('js-gc-heap-chunk-clean-unused' + "
|
||||
"'js-gc-heap-chunk-dirty-unused' + 'js-gc-heap-decommitted' + "
|
||||
@ -1805,14 +1801,14 @@ public:
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-objects"),
|
||||
nsIMemoryReporter::KIND_OTHER, data.totalObjects,
|
||||
nsIMemoryReporter::KIND_OTHER, rtStats.totalObjects,
|
||||
"Memory used for all object-related data. This is the sum of all "
|
||||
"compartments' 'gc-heap/objects-non-function', "
|
||||
"'gc-heap/objects-function' and 'object-slots' numbers.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-shapes"),
|
||||
nsIMemoryReporter::KIND_OTHER, data.totalShapes,
|
||||
nsIMemoryReporter::KIND_OTHER, rtStats.totalShapes,
|
||||
"Memory used for all shape-related data. This is the sum of all "
|
||||
"compartments' 'gc-heap/shapes/tree', 'gc-heap/shapes/dict', "
|
||||
"'gc-heap/shapes/base', "
|
||||
@ -1821,32 +1817,32 @@ public:
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-scripts"),
|
||||
nsIMemoryReporter::KIND_OTHER, data.totalScripts,
|
||||
nsIMemoryReporter::KIND_OTHER, rtStats.totalScripts,
|
||||
"Memory used for all script-related data. This is the sum of all "
|
||||
"compartments' 'gc-heap/scripts' and 'script-data' numbers.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-strings"),
|
||||
nsIMemoryReporter::KIND_OTHER, data.totalStrings,
|
||||
nsIMemoryReporter::KIND_OTHER, rtStats.totalStrings,
|
||||
"Memory used for all string-related data. This is the sum of all "
|
||||
"compartments' 'gc-heap/strings' and 'string-chars' numbers.",
|
||||
callback, closure);
|
||||
#ifdef JS_METHODJIT
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-mjit"),
|
||||
nsIMemoryReporter::KIND_OTHER, data.totalMjit,
|
||||
nsIMemoryReporter::KIND_OTHER, rtStats.totalMjit,
|
||||
"Memory used by the method JIT. This is the sum of all compartments' "
|
||||
"'mjit-code', and 'mjit-data' numbers.",
|
||||
callback, closure);
|
||||
#endif
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-type-inference"),
|
||||
nsIMemoryReporter::KIND_OTHER, data.totalTypeInference,
|
||||
nsIMemoryReporter::KIND_OTHER, rtStats.totalTypeInference,
|
||||
"Non-transient memory used by type inference. This is the sum of all "
|
||||
"compartments' 'gc-heap/type-objects', 'type-inference/script-main', "
|
||||
"'type-inference/object-main' and 'type-inference/tables' numbers.",
|
||||
callback, closure);
|
||||
|
||||
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-analysis-temporary"),
|
||||
nsIMemoryReporter::KIND_OTHER, data.totalAnalysisTemp,
|
||||
nsIMemoryReporter::KIND_OTHER, rtStats.totalAnalysisTemp,
|
||||
"Memory used transiently during type inference and compilation. "
|
||||
"This is the sum of all compartments' 'analysis-temporary' numbers.",
|
||||
callback, closure);
|
||||
|
@ -230,7 +230,7 @@ namespace xpconnect {
|
||||
namespace memory {
|
||||
|
||||
void
|
||||
ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
|
||||
ReportJSRuntimeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix,
|
||||
nsIMemoryMultiReporterCallback *callback,
|
||||
nsISupports *closure);
|
||||
|
||||
|
@ -4804,7 +4804,18 @@ nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame,
|
||||
/* static */ bool
|
||||
nsLayoutUtils::FontSizeInflationEnabled(nsPresContext *aPresContext)
|
||||
{
|
||||
return (sFontSizeInflationEmPerLine != 0 ||
|
||||
sFontSizeInflationMinTwips != 0) &&
|
||||
!aPresContext->IsChrome();
|
||||
if ((sFontSizeInflationEmPerLine == 0 &&
|
||||
sFontSizeInflationMinTwips == 0) ||
|
||||
aPresContext->IsChrome()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ViewportInfo vInf =
|
||||
nsContentUtils::GetViewportInfo(aPresContext->PresShell()->GetDocument());
|
||||
|
||||
if (vInf.defaultZoom >= 1.0 || vInf.autoSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
Without the patch for bug 706198, this website should not show up as inflated. That means
|
||||
that with a 450px container, the minimum font size with 15em per line should be 30px.
|
||||
So, we map 0px-45px into 30px-45px, and thus 12px gets mapped to 34px.
|
||||
|
||||
With the patch, the text should be uninflated, which means that 12px should still be
|
||||
12px.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content='True' name='HandheldFriendly' />
|
||||
<style>
|
||||
p { font-size: 12px; line-height: 1.0;}
|
||||
</style>
|
||||
<body>
|
||||
<p>Some uninflated text.</p>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
Without the patch for bug 706198, this website should not show up as inflated. That means
|
||||
that with a 450px container, the minimum font size with 15em per line should be 30px.
|
||||
So, we map 0px-45px into 30px-45px, and thus 12px gets mapped to 34px.
|
||||
|
||||
With the patch, the text should be uninflated, which means that 12px should still be
|
||||
12px.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
|
||||
<style>
|
||||
p { font-size: 12px; line-height: 1.0;}
|
||||
</style>
|
||||
<body>
|
||||
<p>Some uninflated text.</p>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
Without the patch for bug 706198, this website should not show up as inflated. That means
|
||||
that with a 450px container, the minimum font size with 15em per line should be 30px.
|
||||
So, we map 0px-45px into 30px-45px, and thus 12px gets mapped to 34px.
|
||||
|
||||
With the patch, the text should be uninflated, which means that 12px should still be
|
||||
12px.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=320"/>
|
||||
<style>
|
||||
p { font-size: 12px; line-height: 1.0;}
|
||||
</style>
|
||||
<body>
|
||||
<p>Some uninflated text.</p>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
@ -0,0 +1,19 @@
|
||||
<!--
|
||||
Without the patch for bug 706198, this website should not show up as inflated. That means
|
||||
that with a 450px container, the minimum font size with 15em per line should be 30px.
|
||||
So, we map 0px-45px into 30px-45px, and thus 12px gets mapped to 34px.
|
||||
|
||||
With the patch, the text should be uninflated, which means that 12px should still be
|
||||
12px.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
p { font-size: 12px; line-height: 1.0;}
|
||||
</style>
|
||||
<body>
|
||||
<p>Some uninflated text.</p>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
|
||||
|
||||
<!--
|
||||
Without the patch for bug 706198, this website should not show up as inflated. That means
|
||||
that with a 450px container, the minimum font size with 15em per line should be 30px.
|
||||
So, we map 0px-45px into 30px-45px, and thus 12px gets mapped to 34px.
|
||||
|
||||
With the patch, the text should be uninflated, which means that 12px should still be
|
||||
12px.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
p { font-size: 12px; line-height: 1.0;}
|
||||
</style>
|
||||
<body>
|
||||
<p>Some uninflated text.</p>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
@ -61,6 +61,10 @@ var gTests = [
|
||||
"!= select-combobox-2.html select-combobox-2.html",
|
||||
"!= input-checkbox.html input-checkbox.html",
|
||||
"!= input-radio.html input-radio.html",
|
||||
"== disable-fontinfl-on-mobile.html disable-fontinfl-on-mobile-ref.html",
|
||||
"== disable-fontinfl-on-mobile-2.html disable-fontinfl-on-mobile-ref.html",
|
||||
"== disable-fontinfl-on-mobile-3.html disable-fontinfl-on-mobile-ref.html",
|
||||
"== disable-fontinfl-on-mobile-4.html disable-fontinfl-on-mobile-ref.html",
|
||||
];
|
||||
|
||||
// Maintain a reference count of how many things we're waiting for until
|
||||
|
@ -1012,7 +1012,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
||||
// ALWAYS drain overflow. We never want to leave the previnflow's
|
||||
// overflow lines hanging around; block reflow depends on the
|
||||
// overflow line lists being cleared out between reflow passes.
|
||||
DrainOverflowLines(state);
|
||||
DrainOverflowLines();
|
||||
|
||||
// Handle paginated overflow (see nsContainerFrame.h)
|
||||
nsOverflowAreas ocBounds;
|
||||
@ -4439,7 +4439,7 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
|
||||
// the invariant that the property is never set if the list is empty.
|
||||
|
||||
bool
|
||||
nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
nsBlockFrame::DrainOverflowLines()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
VerifyOverflowSituation();
|
||||
|
@ -452,7 +452,7 @@ protected:
|
||||
* part of this block's mLines list.
|
||||
* @return true if any lines were drained.
|
||||
*/
|
||||
bool DrainOverflowLines(nsBlockReflowState& aState);
|
||||
bool DrainOverflowLines();
|
||||
|
||||
/** grab pushed floats from this block's prevInFlow, and splice
|
||||
* them into this block's mFloats list.
|
||||
|
@ -1639,9 +1639,9 @@ skip-if(Android) == 632781-verybig.html 632781-ref.html
|
||||
== 633344-1.html 633344-1-ref.html
|
||||
fails-if(Android) == 634232-1.html 634232-1-ref.html
|
||||
fails-if(Android) == 635302-1.html 635302-1-ref.html
|
||||
== 635373-1.html 635373-1-ref.html
|
||||
== 635373-2.html 635373-2-ref.html
|
||||
== 635373-3.html 635373-3-ref.html
|
||||
random-if(d2d) == 635373-1.html 635373-1-ref.html
|
||||
random-if(d2d) == 635373-2.html 635373-2-ref.html
|
||||
random-if(d2d) == 635373-3.html 635373-3-ref.html
|
||||
HTTP(..) == 635639-1.html 635639-1-ref.html
|
||||
HTTP(..) == 635639-2.html 635639-2-ref.html
|
||||
random == 637597-1.html 637597-1-ref.html # bug 637597 was never really fixed!
|
||||
|
@ -218,8 +218,10 @@ pref("extensions.logging.enabled", false);
|
||||
pref("extensions.hideInstallButton", true);
|
||||
pref("extensions.showMismatchUI", false);
|
||||
pref("extensions.hideUpdateButton", false);
|
||||
pref("extensions.strictCompatibility", false);
|
||||
pref("extensions.minCompatibleAppVersion", "11.0");
|
||||
|
||||
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%");
|
||||
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
|
||||
|
||||
/* preferences for the Get Add-ons pane */
|
||||
pref("extensions.getAddons.cache.enabled", true);
|
||||
@ -227,7 +229,7 @@ pref("extensions.getAddons.maxResults", 15);
|
||||
pref("extensions.getAddons.recommended.browseURL", "https://addons.mozilla.org/%LOCALE%/mobile/recommended/");
|
||||
pref("extensions.getAddons.recommended.url", "https://services.addons.mozilla.org/%LOCALE%/mobile/api/%API_VERSION%/list/featured/all/%MAX_RESULTS%/%OS%/%VERSION%");
|
||||
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/mobile/search?q=%TERMS%");
|
||||
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/mobile/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%");
|
||||
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/mobile/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%/%COMPATIBILITY_MODE%");
|
||||
pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/mobile/");
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/mobile/api/%API_VERSION%/search/guid:%IDS%?src=mobile&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
|
||||
|
||||
|
@ -317,4 +317,16 @@ public class BrowserToolbar extends LinearLayout {
|
||||
else
|
||||
mSiteSecurity.setImageLevel(0);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
if (tab != null) {
|
||||
setTitle(tab.getDisplayTitle());
|
||||
setFavicon(tab.getFavicon());
|
||||
setSecurityMode(tab.getSecurityMode());
|
||||
setProgressVisibility(tab.isLoading());
|
||||
setShadowVisibility(!(tab.getURL().startsWith("about:")));
|
||||
updateTabs(Tabs.getInstance().getCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -583,12 +583,12 @@ abstract public class GeckoApp
|
||||
mLastViewport = viewportMetrics.toJSON();
|
||||
|
||||
mLastTitle = lastHistoryEntry.mTitle;
|
||||
getAndProcessThumbnailForTab(tab);
|
||||
getAndProcessThumbnailForTab(tab, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getAndProcessThumbnailForTab(final Tab tab) {
|
||||
void getAndProcessThumbnailForTab(final Tab tab, boolean forceBigSceenshot) {
|
||||
boolean isSelectedTab = Tabs.getInstance().isSelectedTab(tab);
|
||||
final Bitmap bitmap = isSelectedTab ?
|
||||
mSoftwareLayerClient.getBitmap() : null;
|
||||
@ -599,10 +599,10 @@ abstract public class GeckoApp
|
||||
processThumbnail(tab, bitmap, bos.toByteArray());
|
||||
} else {
|
||||
mLastScreen = null;
|
||||
int sw = isSelectedTab ? mSoftwareLayerClient.getWidth() : tab.getMinScreenshotWidth();
|
||||
int sh = isSelectedTab ? mSoftwareLayerClient.getHeight(): tab.getMinScreenshotHeight();
|
||||
int dw = isSelectedTab ? sw : tab.getThumbnailWidth();
|
||||
int dh = isSelectedTab ? sh : tab.getThumbnailHeight();
|
||||
int sw = forceBigSceenshot ? mSoftwareLayerClient.getWidth() : tab.getMinScreenshotWidth();
|
||||
int sh = forceBigSceenshot ? mSoftwareLayerClient.getHeight(): tab.getMinScreenshotHeight();
|
||||
int dw = forceBigSceenshot ? sw : tab.getThumbnailWidth();
|
||||
int dh = forceBigSceenshot ? sh : tab.getThumbnailHeight();
|
||||
try {
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("tabID", tab.getId());
|
||||
@ -1071,6 +1071,17 @@ abstract public class GeckoApp
|
||||
}
|
||||
} else if (event.equals("Update:Restart")) {
|
||||
doRestart("org.mozilla.gecko.restart_update");
|
||||
} else if (event.equals("Tab:HasTouchListener")) {
|
||||
int tabId = message.getInt("tabID");
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
tab.setHasTouchListeners(true);
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mLayerController.setWaitForTouchListeners(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
@ -1446,6 +1457,20 @@ abstract public class GeckoApp
|
||||
});
|
||||
}
|
||||
|
||||
// The ActionBar needs to be refreshed on rotation as different orientation uses different resources
|
||||
public void refreshActionBar() {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.browser_toolbar, null);
|
||||
mBrowserToolbar.refresh();
|
||||
GeckoActionBar.setBackgroundDrawable(this, getResources().getDrawable(R.drawable.gecko_actionbar_bg));
|
||||
GeckoActionBar.setDisplayOptions(this, ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM |
|
||||
ActionBar.DISPLAY_SHOW_HOME |
|
||||
ActionBar.DISPLAY_SHOW_TITLE |
|
||||
ActionBar.DISPLAY_USE_LOGO);
|
||||
GeckoActionBar.setCustomView(this, mBrowserToolbar);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
@ -1531,14 +1556,7 @@ abstract public class GeckoApp
|
||||
mOrientation = getResources().getConfiguration().orientation;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.browser_toolbar, null);
|
||||
|
||||
GeckoActionBar.setBackgroundDrawable(this, getResources().getDrawable(R.drawable.gecko_actionbar_bg));
|
||||
GeckoActionBar.setDisplayOptions(this, ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM |
|
||||
ActionBar.DISPLAY_SHOW_HOME |
|
||||
ActionBar.DISPLAY_SHOW_TITLE |
|
||||
ActionBar.DISPLAY_USE_LOGO);
|
||||
GeckoActionBar.setCustomView(this, mBrowserToolbar);
|
||||
refreshActionBar();
|
||||
} else {
|
||||
mBrowserToolbar = (BrowserToolbar) findViewById(R.id.browser_toolbar);
|
||||
}
|
||||
@ -1639,6 +1657,7 @@ abstract public class GeckoApp
|
||||
GeckoAppShell.registerGeckoEventListener("CharEncoding:Data", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("CharEncoding:State", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Update:Restart", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Tab:HasTouchListener", GeckoApp.mAppContext);
|
||||
|
||||
mConnectivityFilter = new IntentFilter();
|
||||
mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
@ -1899,6 +1918,13 @@ abstract public class GeckoApp
|
||||
// Undo whatever we did in onPause.
|
||||
super.onResume();
|
||||
|
||||
int newOrientation = getResources().getConfiguration().orientation;
|
||||
|
||||
if (mOrientation != newOrientation) {
|
||||
mOrientation = newOrientation;
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
// Just in case. Normally we start in onNewIntent
|
||||
if (checkLaunchState(LaunchState.Launching))
|
||||
onNewIntent(getIntent());
|
||||
@ -1978,6 +2004,7 @@ abstract public class GeckoApp
|
||||
GeckoAppShell.unregisterGeckoEventListener("Downloads:Done", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("CharEncoding:Data", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("CharEncoding:State", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Tab:HasTouchListener", GeckoApp.mAppContext);
|
||||
|
||||
mFavicons.close();
|
||||
|
||||
@ -2012,23 +2039,7 @@ abstract public class GeckoApp
|
||||
if (mOrientation != newConfig.orientation) {
|
||||
mOrientation = newConfig.orientation;
|
||||
mAutoCompletePopup.hide();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.browser_toolbar, null);
|
||||
|
||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
if (tab != null) {
|
||||
mBrowserToolbar.setTitle(tab.getDisplayTitle());
|
||||
mBrowserToolbar.setFavicon(tab.getFavicon());
|
||||
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
|
||||
mBrowserToolbar.setProgressVisibility(tab.isLoading());
|
||||
mBrowserToolbar.setShadowVisibility(!(tab.getURL().startsWith("about:")));
|
||||
mBrowserToolbar.updateTabs(Tabs.getInstance().getCount());
|
||||
}
|
||||
|
||||
GeckoActionBar.setBackgroundDrawable(this, getResources().getDrawable(R.drawable.gecko_actionbar_bg));
|
||||
GeckoActionBar.setCustomView(mAppContext, mBrowserToolbar);
|
||||
}
|
||||
refreshActionBar();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1147,12 +1147,17 @@ public class GeckoAppShell
|
||||
}
|
||||
|
||||
public static void setSelectedLocale(String localeCode) {
|
||||
/* We're not using this, not need to save it (see bug 635342)
|
||||
SharedPreferences settings =
|
||||
/* Bug 713464: This method is still called from Gecko side.
|
||||
Earlier we had an option to run Firefox in a language other than system's language.
|
||||
However, this is not supported as of now.
|
||||
Gecko resets the locale to en-US by calling this function with an empty string.
|
||||
This affects GeckoPreferences activity in multi-locale builds.
|
||||
|
||||
//We're not using this, not need to save it (see bug 635342)
|
||||
SharedPreferences settings =
|
||||
GeckoApp.mAppContext.getPreferences(Activity.MODE_PRIVATE);
|
||||
settings.edit().putString(GeckoApp.mAppContext.getPackageName() + ".locale",
|
||||
localeCode).commit();
|
||||
*/
|
||||
Locale locale;
|
||||
int index;
|
||||
if ((index = localeCode.indexOf('-')) != -1 ||
|
||||
@ -1169,6 +1174,7 @@ public class GeckoAppShell
|
||||
Configuration config = res.getConfiguration();
|
||||
config.locale = locale;
|
||||
res.updateConfiguration(config, res.getDisplayMetrics());
|
||||
*/
|
||||
}
|
||||
|
||||
public static int[] getSystemColors() {
|
||||
|
@ -293,7 +293,7 @@ public class Tabs implements GeckoEventListener {
|
||||
final Tab tab = iterator.next();
|
||||
GeckoAppShell.getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
GeckoApp.mAppContext.getAndProcessThumbnailForTab(tab);
|
||||
GeckoApp.mAppContext.getAndProcessThumbnailForTab(tab, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -112,6 +112,9 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
// inside a transaction, so no synchronization is needed.
|
||||
private boolean mUpdateViewportOnEndDraw;
|
||||
|
||||
/* Used by robocop for testing purposes */
|
||||
private DrawListener mDrawListener;
|
||||
|
||||
private static Pattern sColorPattern;
|
||||
|
||||
public GeckoSoftwareLayerClient(Context context) {
|
||||
@ -325,6 +328,11 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
}
|
||||
}
|
||||
Log.i(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - endDrawing");
|
||||
|
||||
/* Used by robocop for testing purposes */
|
||||
if (mDrawListener != null) {
|
||||
mDrawListener.drawFinished(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public ViewportMetrics getGeckoViewportMetrics() {
|
||||
@ -536,5 +544,15 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
int b = Integer.parseInt(matcher.group(3));
|
||||
return Color.rgb(r, g, b);
|
||||
}
|
||||
|
||||
/** Used by robocop for testing purposes. Not for production use! This is called via reflection by robocop. */
|
||||
public void setDrawListener(DrawListener listener) {
|
||||
mDrawListener = listener;
|
||||
}
|
||||
|
||||
/** Used by robocop for testing purposes. Not for production use! This is used via reflection by robocop. */
|
||||
public interface DrawListener {
|
||||
public void drawFinished(int x, int y, int width, int height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,13 @@ public class LayerController {
|
||||
|
||||
// Page size is owned by the LayerClient, so no need to notify it of
|
||||
// this change.
|
||||
mView.requestRender();
|
||||
|
||||
mView.post(new Runnable() {
|
||||
public void run() {
|
||||
mPanZoomController.pageSizeUpdated();
|
||||
mView.requestRender();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,7 @@ import android.util.Log;
|
||||
import android.view.WindowManager;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
/**
|
||||
* The layer renderer implements the rendering logic for a layer view.
|
||||
@ -95,6 +95,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
||||
private int mCurrentFrame, mFrameTimingsSum, mDroppedFrames;
|
||||
private boolean mShowFrameRate;
|
||||
|
||||
/* Used by robocop for testing purposes */
|
||||
private IntBuffer mPixelBuffer;
|
||||
|
||||
public LayerRenderer(LayerView view) {
|
||||
mView = view;
|
||||
|
||||
@ -246,6 +249,31 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
||||
mView.requestRender();
|
||||
|
||||
PanningPerfAPI.recordFrameTime();
|
||||
|
||||
/* Used by robocop for testing purposes */
|
||||
IntBuffer pixelBuffer = mPixelBuffer;
|
||||
if (updated && pixelBuffer != null) {
|
||||
synchronized (pixelBuffer) {
|
||||
pixelBuffer.position(0);
|
||||
gl.glReadPixels(0, 0, (int)screenContext.viewport.width(), (int)screenContext.viewport.height(), GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixelBuffer);
|
||||
pixelBuffer.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Used by robocop for testing purposes. Not for production use! */
|
||||
IntBuffer getPixels() {
|
||||
IntBuffer pixelBuffer = IntBuffer.allocate(mView.getWidth() * mView.getHeight());
|
||||
synchronized (pixelBuffer) {
|
||||
mPixelBuffer = pixelBuffer;
|
||||
mView.requestRender();
|
||||
try {
|
||||
pixelBuffer.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
mPixelBuffer = null;
|
||||
}
|
||||
return pixelBuffer;
|
||||
}
|
||||
|
||||
private RenderContext createScreenContext() {
|
||||
|
@ -52,6 +52,7 @@ import android.view.MotionEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.util.Log;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -237,5 +238,10 @@ public class LayerView extends GLSurfaceView
|
||||
public int getMaxTextureSize() {
|
||||
return mRenderer.getMaxTextureSize();
|
||||
}
|
||||
|
||||
/** Used by robocop for testing purposes. Not for production use! This is called via reflection by robocop. */
|
||||
public IntBuffer getPixels() {
|
||||
return mRenderer.getPixels();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
<item android:right="34dp">
|
||||
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/address_bar_texture"
|
||||
android:tileMode="mirror"
|
||||
android:tileMode="repeat"
|
||||
android:dither="false"/>
|
||||
</item>
|
||||
|
||||
|
17
mobile/android/base/tests/robocop_boxes.html
Normal file
17
mobile/android/base/tests/robocop_boxes.html
Normal file
@ -0,0 +1,17 @@
|
||||
<html style="margin: 0; padding: 0">
|
||||
<title>Browser Box test</title>
|
||||
<body style="margin: 0; padding: 0">
|
||||
<script type="text/javascript">
|
||||
for (var y = 0; y < 2000; y += 100) {
|
||||
document.write("<div style='width: 2000px; height: 100px; margin: 0; padding: 0; border: none'>\n");
|
||||
for (var x = 0; x < 2000; x += 100) {
|
||||
var r = (y + x) % 255;
|
||||
var g = 255 - (y / 10);
|
||||
var b = 255 - (x / 10);
|
||||
document.write("<div style='float: left; width: 100px; height: 100px; margin: 0; padding: 0; border: none; background-color: rgb(" + r + "," + g + "," + b + ")'> </div>\n");
|
||||
}
|
||||
document.write("</div>\n");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user