Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-11-22 10:48:50 +00:00
Родитель b4af68ab55 cf76cd1e8e
Коммит 5ada0548cd
160 изменённых файлов: 2289 добавлений и 1335 удалений

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

@ -38,6 +38,7 @@ MOCHITEST_BROWSER_FILES = \
browser_privatebrowsing_protocolhandler.js \
browser_privatebrowsing_protocolhandler_page.html \
browser_privatebrowsing_theming.js \
browser_privatebrowsing_ui.js \
browser_privatebrowsing_urlbarfocus.js \
browser_privatebrowsing_windowtitle.js \
browser_privatebrowsing_windowtitle_page.html \

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

@ -0,0 +1,82 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This test makes sure that the gPrivateBrowsingUI object, the Private Browsing
// menu item and its XUL <command> element work correctly.
function test() {
// initialization
waitForExplicitFinish();
let windowsToClose = [];
let testURI = "about:blank";
let pbMenuItem;
let cmd;
function doTest(aIsPrivateMode, aWindow, aCallback) {
aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
ok(aWindow.gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
pbMenuItem = aWindow.document.getElementById("menu_newPrivateWindow");
ok(pbMenuItem, "The Private Browsing menu item exists");
cmd = aWindow.document.getElementById("Tools:PrivateBrowsing");
isnot(cmd, null, "XUL command object for the private browsing service exists");
is(pbMenuItem.getAttribute("label"), "New Private Window",
"The Private Browsing menu item should read \"New Private Window\"");
is(PrivateBrowsingUtils.isWindowPrivate(aWindow), aIsPrivateMode,
"PrivateBrowsingUtils should report the correct per-window private browsing status (privateBrowsing should be " +
aIsPrivateMode + ")");
aCallback();
}, true);
aWindow.gBrowser.selectedBrowser.loadURI(testURI);
};
function openPrivateBrowsingModeByUI(aWindow, aCallback) {
Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
aSubject.addEventListener("load", function() {
aSubject.removeEventListener("load", arguments.callee);
Services.obs.removeObserver(observer, "domwindowopened");
windowsToClose.push(aSubject);
aCallback(aSubject);
}, false);
}, "domwindowopened", false);
cmd = aWindow.document.getElementById("Tools:PrivateBrowsing");
var func = new Function("", cmd.getAttribute("oncommand"));
func.call(cmd);
};
function testOnWindow(aOptions, aCallback) {
whenNewWindowLoaded(aOptions, function(aWin) {
windowsToClose.push(aWin);
// execute should only be called when need, like when you are opening
// web pages on the test. If calling executeSoon() is not necesary, then
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
executeSoon(function() aCallback(aWin));
});
};
// this function is called after calling finish() on the test.
registerCleanupFunction(function() {
windowsToClose.forEach(function(aWin) {
aWin.close();
});
});
// test first when not on private mode
testOnWindow({}, function(aWin) {
doTest(false, aWin, function() {
// then test when on private mode, opening a new private window from the
// user interface.
openPrivateBrowsingModeByUI(aWin, function(aPrivateWin) {
doTest(true, aPrivateWin, finish);
});
});
});
}

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

@ -2060,10 +2060,10 @@ private:
// XXX These belong somewhere else
nsresult
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult);
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
nsresult
NS_NewXMLDocument(nsIDocument** aInstancePtrResult);
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
nsresult
NS_NewSVGDocument(nsIDocument** aInstancePtrResult);

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

@ -1945,6 +1945,7 @@ GK_ATOM(DeleteTxnName, "Deleting")
GK_ATOM(Remote, "remote")
GK_ATOM(RemoteId, "_remote_id")
GK_ATOM(DisplayPort, "_displayport")
GK_ATOM(CriticalDisplayPort, "_critical_displayport")
// Names for system metrics
GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward")

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

@ -527,10 +527,7 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
if (aCx && wrapper) {
nsIXPConnect *xpc = nsContentUtils::XPConnect();
if (xpc) {
nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper;
rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode,
getter_AddRefs(oldWrapper));
rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode);
if (NS_FAILED(rv)) {
aNode->mNodeInfo.swap(nodeInfo);

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

@ -143,7 +143,8 @@ public:
nsHTMLCanvasElement* GetCanvas() const
{
return mCanvasElement;
// corresponds to changes to the old bindings made in bug 745025
return mCanvasElement->GetOriginalCanvas();
}
void Save();

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

@ -604,7 +604,11 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
// XXX sXBL/XBL2 issue -- do we really want the owner here? What
// if that's the XBL document?
doc = node->OwnerDoc();
global = doc->GetScriptGlobalObject();
MOZ_ASSERT(!doc->IsLoadedAsData(), "Should not get in here at all");
// We want to allow compiling an event handler even in an unloaded
// document, so use GetScopeObject here, not GetScriptHandlingObject.
global = doc->GetScopeObject();
} else {
nsCOMPtr<nsPIDOMWindow> win = GetTargetAsInnerWindow();
if (win) {
@ -623,6 +627,13 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
return NS_OK;
}
#ifdef DEBUG
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(global);
if (win) {
MOZ_ASSERT(win->IsInnerWindow(), "We should not have an outer window here!");
}
#endif
nsresult rv = NS_OK;
// return early preventing the event listener from being added
// 'doc' is fetched above

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

@ -99,6 +99,7 @@ MOCHITEST_FILES = \
test_bug716822.html \
test_bug742376.html \
test_dragstart.html \
test_bug812744.html \
$(NULL)
MOCHITEST_CHROME_FILES = \

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

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=812744
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 812744</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=812744">Mozilla Bug 812744</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id="f"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 812744 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
var f = $("f");
var el = f.contentDocument.documentElement;
f.onload = function() {
el.setAttribute("onmouseleave", "(void 0)");
is(el.onmouseleave.toString(), "function onmouseleave(event) {\n(void 0)\n}",
"Should have a function here");
SimpleTest.finish();
};
f.src = "http://www.example.com/"
});
</script>
</pre>
</body>
</html>

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

@ -173,7 +173,7 @@ protected:
void CallPrintCallback();
nsString mCurrentContextId;
nsCOMPtr<nsIDOMHTMLCanvasElement> mOriginalCanvas;
nsRefPtr<nsHTMLCanvasElement> mOriginalCanvas;
nsCOMPtr<nsIPrintCallback> mPrintCallback;
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
nsCOMPtr<nsHTMLCanvasPrintState> mPrintState;
@ -193,7 +193,7 @@ public:
void ResetPrintCallback();
nsIDOMHTMLCanvasElement* GetOriginalCanvas();
nsHTMLCanvasElement* GetOriginalCanvas();
};
inline nsISupports*

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

@ -796,7 +796,7 @@ protected:
nsCOMPtr<nsIContent> mSourceLoadCandidate;
// An audio stream for writing audio directly from JS.
nsRefPtr<AudioStream> mAudioStream;
nsAutoPtr<AudioStream> mAudioStream;
// Range of time played.
nsTimeRanges mPlayed;

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

@ -307,7 +307,7 @@ nsHTMLCanvasElement::IsPrintCallbackDone()
return mPrintState->mIsDone;
}
nsIDOMHTMLCanvasElement*
nsHTMLCanvasElement*
nsHTMLCanvasElement::GetOriginalCanvas()
{
return mOriginalCanvas ? mOriginalCanvas.get() : this;
@ -323,16 +323,16 @@ nsHTMLCanvasElement::CopyInnerTo(Element* aDest)
nsHTMLCanvasElement* self = const_cast<nsHTMLCanvasElement*>(this);
dest->mOriginalCanvas = self;
HTMLImageOrCanvasOrVideoElement element;
element.SetAsHTMLCanvasElement() = this;
nsCOMPtr<nsISupports> cxt;
dest->GetContext(NS_LITERAL_STRING("2d"), JSVAL_VOID, getter_AddRefs(cxt));
nsRefPtr<CanvasRenderingContext2D> context2d =
static_cast<CanvasRenderingContext2D*>(cxt.get());
if (context2d && !self->mPrintCallback) {
HTMLImageOrCanvasOrVideoElement element;
element.SetAsHTMLCanvasElement() = this;
ErrorResult err;
context2d->DrawImage(element,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, err);
0.0, 0.0, err);
rv = err.ErrorCode();
}
}

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

@ -172,7 +172,7 @@ RemoveFromAgentSheets(nsCOMArray<nsIStyleSheet> &aAgentSheets, const nsAString&
}
nsresult
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult)
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
{
nsHTMLDocument* doc = new nsHTMLDocument();
NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
@ -185,6 +185,7 @@ NS_NewHTMLDocument(nsIDocument** aInstancePtrResult)
}
*aInstancePtrResult = doc;
doc->SetLoadedAsData(aLoadedAsData);
return rv;
}
@ -1515,11 +1516,9 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
nsCOMPtr<nsIScriptGlobalObject> newScope(do_QueryReferent(mScopeObject));
if (oldScope && newScope != oldScope) {
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectJSObjectHolder> ignored;
rv = xpc->ReparentWrappedNativeIfFound(cx, oldScope->GetGlobalJSObject(),
newScope->GetGlobalJSObject(),
static_cast<nsINode*>(this),
getter_AddRefs(ignored));
static_cast<nsINode*>(this));
NS_ENSURE_SUCCESS(rv, rv);
rv = xpc->RescueOrphansInScope(cx, oldScope->GetGlobalJSObject());
NS_ENSURE_SUCCESS(rv, rv);

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

@ -8,7 +8,6 @@
#include "prlog.h"
#include "prmem.h"
#include "prdtoa.h"
#include "nsAutoPtr.h"
#include "AudioStream.h"
#include "nsAlgorithm.h"
#include "VideoUtils.h"
@ -17,7 +16,6 @@
extern "C" {
#include "sydneyaudio/sydney_audio.h"
}
#include "nsThreadUtils.h"
#include "mozilla/Preferences.h"
#if defined(MOZ_CUBEB)
@ -51,8 +49,6 @@ static const int64_t MS_PER_S = 1000;
class nsNativeAudioStream : public AudioStream
{
public:
NS_DECL_ISUPPORTS
~nsNativeAudioStream();
nsNativeAudioStream();
@ -209,33 +205,8 @@ void AudioStream::ShutdownLibrary()
#endif
}
nsIThread *
AudioStream::GetThread()
{
if (!mAudioPlaybackThread) {
NS_NewNamedThread("Audio Stream",
getter_AddRefs(mAudioPlaybackThread),
nullptr,
MEDIA_THREAD_STACK_SIZE);
}
return mAudioPlaybackThread;
}
class AsyncShutdownPlaybackThread : public nsRunnable
{
public:
AsyncShutdownPlaybackThread(nsIThread* aThread) : mThread(aThread) {}
NS_IMETHODIMP Run() { return mThread->Shutdown(); }
private:
nsCOMPtr<nsIThread> mThread;
};
AudioStream::~AudioStream()
{
if (mAudioPlaybackThread) {
nsCOMPtr<nsIRunnable> event = new AsyncShutdownPlaybackThread(mAudioPlaybackThread);
NS_DispatchToMainThread(event);
}
}
nsNativeAudioStream::nsNativeAudioStream() :
@ -251,8 +222,6 @@ nsNativeAudioStream::~nsNativeAudioStream()
Shutdown();
}
NS_IMPL_THREADSAFE_ISUPPORTS0(nsNativeAudioStream)
nsresult nsNativeAudioStream::Init(int32_t aNumChannels, int32_t aRate,
const dom::AudioChannelType aAudioChannelType)
{
@ -498,8 +467,6 @@ private:
class nsBufferedAudioStream : public AudioStream
{
public:
NS_DECL_ISUPPORTS
nsBufferedAudioStream();
~nsBufferedAudioStream();
@ -598,8 +565,6 @@ nsBufferedAudioStream::~nsBufferedAudioStream()
Shutdown();
}
NS_IMPL_THREADSAFE_ISUPPORTS0(nsBufferedAudioStream)
nsresult
nsBufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
const dom::AudioChannelType aAudioChannelType)

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

@ -7,9 +7,6 @@
#define AudioStream_h_
#include "nscore.h"
#include "nsISupportsImpl.h"
#include "nsIThread.h"
#include "nsAutoPtr.h"
#include "AudioSampleFormat.h"
#include "AudioChannelCommon.h"
@ -19,7 +16,7 @@ namespace mozilla {
// callers, or made from a single thread. One exception is that access to
// GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels}
// is thread-safe without external synchronization.
class AudioStream : public nsISupports
class AudioStream
{
public:
AudioStream()
@ -37,10 +34,6 @@ public:
// library after using it.
static void ShutdownLibrary();
// Thread that is shared between audio streams.
// This may return null in the child process
nsIThread *GetThread();
// AllocateStream will return either a local stream or a remoted stream
// depending on where you call it from. If you call this from a child process,
// you may receive an implementation which forwards to a compositing process.
@ -96,7 +89,6 @@ public:
int GetChannels() { return mChannels; }
protected:
nsCOMPtr<nsIThread> mAudioPlaybackThread;
int mRate;
int mChannels;
};

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

@ -611,7 +611,7 @@ private:
// This is created and destroyed on the audio thread, while holding the
// decoder monitor, so if this is used off the audio thread, you must
// first acquire the decoder monitor and check that it is non-null.
nsRefPtr<AudioStream> mAudioStream;
nsAutoPtr<AudioStream> mAudioStream;
// The reader, don't call its methods with the decoder monitor held.
// This is created in the play state machine's constructor, and destroyed

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

@ -442,7 +442,7 @@ protected:
// Amount of time that we've wanted to play silence because of the stream
// blocking.
MediaTime mBlockedAudioTime;
nsRefPtr<AudioStream> mStream;
nsAutoPtr<AudioStream> mStream;
TrackID mTrackID;
};
nsTArray<AudioOutputStream> mAudioOutputStreams;

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

@ -89,6 +89,11 @@ ssize_t MediaStreamSource::readAt(off64_t offset, void *data, size_t size)
NS_FAILED(mResource->Read(ptr, todo, &bytesRead))) {
return ERROR_IO;
}
if (bytesRead == 0) {
return size - todo;
}
offset += bytesRead;
todo -= bytesRead;
ptr += bytesRead;

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

@ -24,7 +24,7 @@ MediaPluginReader::MediaPluginReader(AbstractMediaDecoder *aDecoder) :
mAudioSeekTimeUs(-1),
mLastVideoFrame(NULL)
{
reinterpret_cast<MediaPluginDecoder *>(aDecoder)->GetContentType(mType);
static_cast<MediaPluginDecoder *>(aDecoder)->GetContentType(mType);
}
MediaPluginReader::~MediaPluginReader()

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

@ -168,7 +168,7 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
nsresult
NS_NewXMLDocument(nsIDocument** aInstancePtrResult)
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
{
nsXMLDocument* doc = new nsXMLDocument();
NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
@ -181,6 +181,7 @@ NS_NewXMLDocument(nsIDocument** aInstancePtrResult)
}
*aInstancePtrResult = doc;
doc->SetLoadedAsData(aLoadedAsData);
return rv;
}

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

@ -113,7 +113,8 @@ txMozillaTextOutput::startDocument()
}
nsresult
txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument)
txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
bool aLoadedAsData)
{
/*
* Create an XHTML document to hold the text.
@ -132,7 +133,8 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument)
*/
// Create the document
nsresult rv = NS_NewXMLDocument(getter_AddRefs(mDocument));
nsresult rv = NS_NewXMLDocument(getter_AddRefs(mDocument),
aLoadedAsData);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> source = do_QueryInterface(aSourceDocument);
NS_ENSURE_STATE(source);

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

@ -28,7 +28,8 @@ public:
TX_DECL_TXAXMLEVENTHANDLER
TX_DECL_TXAOUTPUTXMLEVENTHANDLER
nsresult createResultDocument(nsIDOMDocument* aSourceDocument);
nsresult createResultDocument(nsIDOMDocument* aSourceDocument,
bool aLoadedAsData);
private:
nsresult createXHTMLElement(nsIAtom* aName, nsIContent** aResult);

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

@ -791,19 +791,22 @@ void txMozillaXMLOutput::processHTTPEquiv(nsIAtom* aHeader, const nsString& aVal
nsresult
txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, int32_t aNsID,
nsIDOMDocument* aSourceDocument)
nsIDOMDocument* aSourceDocument,
bool aLoadedAsData)
{
nsresult rv;
// Create the document
if (mOutputFormat.mMethod == eHTMLOutput) {
rv = NS_NewHTMLDocument(getter_AddRefs(mDocument));
rv = NS_NewHTMLDocument(getter_AddRefs(mDocument),
aLoadedAsData);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
// We should check the root name/namespace here and create the
// appropriate document
rv = NS_NewXMLDocument(getter_AddRefs(mDocument));
rv = NS_NewXMLDocument(getter_AddRefs(mDocument),
aLoadedAsData);
NS_ENSURE_SUCCESS(rv, rv);
}
// This should really be handled by nsIDocument::BeginLoad

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

@ -74,7 +74,8 @@ public:
nsresult closePrevious(bool aFlushText);
nsresult createResultDocument(const nsSubstring& aName, int32_t aNsID,
nsIDOMDocument* aSourceDocument);
nsIDOMDocument* aSourceDocument,
bool aLoadedAsData);
private:
nsresult createTxWrapper();

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

@ -48,8 +48,10 @@ class txToDocHandlerFactory : public txAOutputHandlerFactory
public:
txToDocHandlerFactory(txExecutionState* aEs,
nsIDOMDocument* aSourceDocument,
nsITransformObserver* aObserver)
: mEs(aEs), mSourceDocument(aSourceDocument), mObserver(aObserver)
nsITransformObserver* aObserver,
bool aDocumentIsData)
: mEs(aEs), mSourceDocument(aSourceDocument), mObserver(aObserver),
mDocumentIsData(aDocumentIsData)
{
}
@ -59,6 +61,7 @@ private:
txExecutionState* mEs;
nsCOMPtr<nsIDOMDocument> mSourceDocument;
nsCOMPtr<nsITransformObserver> mObserver;
bool mDocumentIsData;
};
class txToFragmentHandlerFactory : public txAOutputHandlerFactory
@ -95,7 +98,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
nsresult rv = handler->createResultDocument(EmptyString(),
kNameSpaceID_None,
mSourceDocument);
mSourceDocument,
mDocumentIsData);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
@ -108,7 +112,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
nsAutoPtr<txMozillaTextOutput> handler(
new txMozillaTextOutput(mObserver));
nsresult rv = handler->createResultDocument(mSourceDocument);
nsresult rv = handler->createResultDocument(mSourceDocument,
mDocumentIsData);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
@ -143,7 +148,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
new txMozillaXMLOutput(aFormat, mObserver));
nsresult rv = handler->createResultDocument(aName, aNsID,
mSourceDocument);
mSourceDocument,
mDocumentIsData);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
@ -156,7 +162,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
nsAutoPtr<txMozillaTextOutput> handler(
new txMozillaTextOutput(mObserver));
nsresult rv = handler->createResultDocument(mSourceDocument);
nsresult rv = handler->createResultDocument(mSourceDocument,
mDocumentIsData);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
@ -522,7 +529,7 @@ public:
NS_IMETHOD Run()
{
mProcessor->TransformToDoc(nullptr);
mProcessor->TransformToDoc(nullptr, false);
return NS_OK;
}
};
@ -612,11 +619,12 @@ txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource,
mSource = aSource;
return TransformToDoc(aResult);
return TransformToDoc(aResult, true);
}
nsresult
txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult)
txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult,
bool aCreateDataDocument)
{
nsAutoPtr<txXPathNode> sourceNode(txXPathNativeNode::createXPathNode(mSource));
if (!sourceNode) {
@ -633,7 +641,9 @@ txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult)
// XXX Need to add error observers
txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, mObserver);
// If aResult is non-null, we're a data document
txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, mObserver,
aCreateDataDocument);
es.mOutputHandlerFactory = &handlerFactory;
nsresult rv = es.init(*sourceNode, &mVariables);

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

@ -96,7 +96,8 @@ public:
return mSource;
}
nsresult TransformToDoc(nsIDOMDocument **aResult);
nsresult TransformToDoc(nsIDOMDocument **aResult,
bool aCreateDataDocument);
bool IsLoadDisabled()
{

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

@ -32,6 +32,7 @@
SimpleTest.is(getDocShellType(typeContentFrame), Ci.nsIDocShellTreeItem.typeContent,
"iframe with mozFrameType='content' in chrome document is typeContent");
SimpleTest.executeSoon(function () {
// Wait for the window to be closed before finishing the test
let ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
@ -39,15 +40,14 @@
if (topic == "domwindowclosed") {
ww.unregisterNotification(windowObs);
SimpleTest.executeSoon(function () {
SimpleTest.waitForFocus(function() {
SimpleTest.finish();
}, opener);
});
}
});
window.close();
});
}
]]></script>
</window>

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

@ -30,8 +30,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=769771
/** Test for Bug 769771 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function () {
window.open("mozFrameType_window.xul", "mozFrameType",
"chrome,width=600,height=600");
});
]]>
</script>

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

@ -7,6 +7,7 @@
#include "nsContentUtils.h"
#include "nsIDOMActivityOptions.h"
#include "nsEventStateManager.h"
#include "nsIConsoleService.h"
using namespace mozilla::dom;
@ -52,11 +53,23 @@ Activity::Initialize(nsISupports* aOwner,
Init(window);
if (!nsEventStateManager::IsHandlingUserInput()) {
nsCOMPtr<nsIDocument> document = do_QueryInterface(window->GetExtantDocument());
if (!nsEventStateManager::IsHandlingUserInput() &&
!nsContentUtils::IsChromeDoc(document)) {
nsCOMPtr<nsIDOMRequestService> rs =
do_GetService("@mozilla.org/dom/dom-request-service;1");
rs->FireErrorAsync(static_cast<DOMRequest*>(this),
NS_LITERAL_STRING("NotUserInput"));
nsCOMPtr<nsIConsoleService> console(
do_GetService("@mozilla.org/consoleservice;1"));
NS_ENSURE_TRUE(console, NS_OK);
nsString message =
NS_LITERAL_STRING("Can start activity from non user input or chrome code");
console->LogStringMessage(message.get());
return NS_OK;
}

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

@ -757,7 +757,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
WINDOW_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Location, nsLocationSH,
(DOM_DEFAULT_SCRIPTABLE_FLAGS &
((DOM_DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ADDPROPERTY) &
~nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE))
NS_DEFINE_CLASSINFO_DATA(Navigator, nsNavigatorSH,
@ -7610,6 +7611,20 @@ nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
return *parentObj ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsLocationSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, bool *_retval)
{
// Shadowing protection. This will go away when nsLocation moves to the new
// bindings.
if (wrapper->HasNativeMember(id)) {
JS_ReportError(cx, "Permission denied to shadow native property");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// DOM Navigator helper
NS_IMETHODIMP

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

@ -454,6 +454,8 @@ public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
NS_IMETHODIMP AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, bool *_retval);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{

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

@ -402,6 +402,54 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetCriticalDisplayPortForElement(float aXPx, float aYPx,
float aWidthPx, float aHeightPx,
nsIDOMElement* aElement)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsIPresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
if (!aElement) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (!content) {
return NS_ERROR_INVALID_ARG;
}
if (content->GetCurrentDoc() != presShell->GetDocument()) {
return NS_ERROR_INVALID_ARG;
}
nsRect displayport;
if (!nsLayoutUtils::GetDisplayPort(content, &displayport)) {
return NS_ERROR_INVALID_ARG;
}
nsRect criticalDisplayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
nsPresContext::CSSPixelsToAppUnits(aYPx),
nsPresContext::CSSPixelsToAppUnits(aWidthPx),
nsPresContext::CSSPixelsToAppUnits(aHeightPx));
content->SetProperty(nsGkAtoms::CriticalDisplayPort, new nsRect(criticalDisplayport),
DestroyNsRect);
nsIFrame* rootFrame = presShell->GetRootFrame();
if (rootFrame) {
rootFrame->InvalidateFrame();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetResolution(float aXResolution, float aYResolution)
{

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

@ -148,6 +148,18 @@ interface nsIDOMWindowUtils : nsISupports {
in float aWidthPx, in float aHeightPx,
in nsIDOMElement aElement);
/**
* When a display port is set, this allows a sub-section of that
* display port to be marked as 'critical'. In this scenario, the
* area outside of this rectangle may be rendered at a lower
* detail (for example, by reducing its resolution), or not rendered
* at all under some circumstances.
* This call will have no effect if a display port has not been set.
*/
void setCriticalDisplayPortForElement(in float aXPx, in float aYPx,
in float aWidthPx, in float aHeightPx,
in nsIDOMElement aElement);
/**
* Get/set the resolution at which rescalable web content is drawn.
* Currently this is only (some) thebes content.

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

@ -2037,7 +2037,7 @@ this.ContentTypeValue = {
*/
encodeConstrainedMedia: function encodeConstrainedMedia(data, value) {
if (value.params) {
throw new CodeError("Constrained-media: should use general form instread");
throw new CodeError("Constrained-media: should use general form instead");
}
TypeValue.encode(data, value.media);
@ -2475,7 +2475,7 @@ this.WSP_HEADER_FIELDS = (function () {
})();
// WSP Content Type Assignments
// @see http://www.wapforum.org/wina
// @see http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx
this.WSP_WELL_KNOWN_CONTENT_TYPES = (function () {
let types = {};
@ -2484,18 +2484,115 @@ this.WSP_WELL_KNOWN_CONTENT_TYPES = (function () {
type: type,
number: number,
};
types[type] = types[number] = entry;
// For case like "text/x-vCalendar", we need toLoweCase() for generating
// the same index.
types[type.toLowerCase()] = types[number] = entry;
}
// Well Known Values
// Encoding Version: 1.1
add("*/*", 0x00);
add("text/*", 0x01);
add("text/html", 0x02);
add("text/plain", 0x03);
add("text/x-hdml", 0x04);
add("text/x-ttml", 0x05);
add("text/x-vCalendar", 0x06);
add("text/x-vCard", 0x07);
add("text/vnd.wap.wml", 0x08);
add("text/vnd.wap.wmlscript", 0x09);
add("text/vnd.wap.wta-event", 0x0A);
add("multipart/*", 0x0B);
add("multipart/mixed", 0x0C);
add("multipart/form-data", 0x0D);
add("multipart/byterantes", 0x0E);
add("multipart/alternative", 0x0F);
add("application/*", 0x10);
add("application/java-vm", 0x11);
add("application/x-www-form-urlencoded", 0x12);
add("application/x-hdmlc", 0x13);
add("application/vnd.wap.wmlc", 0x14);
add("application/vnd.wap.wmlscriptc", 0x15);
add("application/vnd.wap.wta-eventc", 0x16);
add("application/vnd.wap.uaprof", 0x17);
add("application/vnd.wap.wtls-ca-certificate", 0x18);
add("application/vnd.wap.wtls-user-certificate", 0x19);
add("application/x-x509-ca-cert", 0x1A);
add("application/x-x509-user-cert", 0x1B);
add("image/*", 0x1C);
add("image/gif", 0x1D);
add("image/jpeg", 0x1E);
add("image/tiff", 0x1F);
add("image/png", 0x20);
add("image/vnd.wap.wbmp", 0x21);
add("application/vnd.wap.multipart.*", 0x22);
add("application/vnd.wap.multipart.mixed", 0x23);
add("application/vnd.wap.multipart.form-data", 0x24);
add("application/vnd.wap.multipart.byteranges", 0x25);
add("application/vnd.wap.multipart.alternative", 0x26);
add("application/xml", 0x27);
add("text/xml", 0x28);
add("application/vnd.wap.wbxml", 0x29);
add("application/x-x968-cross-cert", 0x2A);
add("application/x-x968-ca-cert", 0x2B);
add("application/x-x968-user-cert", 0x2C);
add("text/vnd.wap.si", 0x2D);
// Encoding Version: 1.2
add("application/vnd.wap.sic", 0x2E);
add("text/vnd.wap.sl", 0x2F);
add("application/vnd.wap.slc", 0x30);
add("text/vnd.wap.co", 0x31);
add("application/vnd.wap.coc", 0x32);
add("application/vnd.wap.multipart.related", 0x33);
add("application/vnd.wap.sia", 0x34);
// Encoding Version: 1.3
add("text/vnd.wap.connectivity-xml", 0x35);
add("application/vnd.wap.connectivity-wbxml", 0x36);
// Encoding Version: 1.4
add("application/pkcs7-mime", 0x37);
add("application/vnd.wap.hashed-certificate", 0x38);
add("application/vnd.wap.signed-certificate", 0x39);
add("application/vnd.wap.cert-response", 0x3A);
add("application/xhtml+xml", 0x3B);
add("application/wml+xml", 0x3C);
add("text/css", 0x3D);
add("application/vnd.wap.mms-message", 0x3E);
add("application/vnd.wap.rollover-certificate", 0x3F);
// Encoding Version: 1.5
add("application/vnd.wap.locc+wbxml", 0x40);
add("application/vnd.wap.loc+xml", 0x41);
add("application/vnd.syncml.dm+wbxml", 0x42);
add("application/vnd.syncml.dm+xml", 0x43);
add("application/vnd.syncml.notification", 0x44);
add("application/vnd.wap.xhtml+xml", 0x45);
add("application/vnd.wv.csp.cir", 0x46);
add("application/vnd.oma.dd+xml", 0x47);
add("application/vnd.oma.drm.message", 0x48);
add("application/vnd.oma.drm.content", 0x49);
add("application/vnd.oma.drm.rights+xml", 0x4A);
add("application/vnd.oma.drm.rights+wbxml", 0x4B);
add("application/vnd.wv.csp+xml", 0x4C);
add("application/vnd.wv.csp+wbxml", 0x4D);
add("application/vnd.syncml.ds.notification", 0x4E);
// Encoding Version: 1.6
add("audio/*", 0x4F);
add("video/*", 0x50);
// Encoding Version: TBD
add("application/vnd.oma.dd2+xml", 0x51);
add("application/mikey", 0x52);
add("application/vnd.oma.dcd", 0x53);
add("application/vnd.oma.dcdc", 0x54);
add("text/x-vMessage", 0x55);
add("application/vnd.omads-email+wbxml", 0x56);
add("text/x-vBookmark", 0x57);
add("application/vnd.syncml.dm.notification", 0x58);
add("application/octet-stream", 0x5A);
return types;
})();

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

@ -718,7 +718,7 @@ add_test(function test_TypeValue_decode() {
wsp_decode_test(WSP.TypeValue, [0x33 | 0x80],
"application/vnd.wap.multipart.related");
// Test for NotWellKnownEncodingError
wsp_decode_test(WSP.TypeValue, [0x80], null, "NotWellKnownEncodingError");
wsp_decode_test(WSP.TypeValue, [0x59 | 0x80], null, "NotWellKnownEncodingError");
run_next_test();
});
@ -1046,10 +1046,12 @@ add_test(function test_ContentTypeValue_decodeConstrainedMedia() {
// Test for string-typed return value from ConstrainedEncoding
wsp_decode_test_ex(func, [65, 0], {media: "a", params: null});
// Test for number-typed return value from ConstrainedEncoding
wsp_decode_test_ex(func, [0x33 | 0x80],
{media: "application/vnd.wap.multipart.related", params: null});
for(let ix = 0; ix <WSP.WSP_WELL_KNOWN_CONTENT_TYPES.length ; ++ix){
wsp_decode_test_ex(func, [WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].number | 0x80],
{media: WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].value, params: null});
}
// Test for NotWellKnownEncodingError
wsp_decode_test_ex(func, [0x80], null, "NotWellKnownEncodingError");
wsp_decode_test_ex(func, [0x59 | 0x80], null, "NotWellKnownEncodingError");
run_next_test();
});
@ -1065,7 +1067,7 @@ add_test(function test_ContentTypeValue_decodeMedia() {
wsp_decode_test_ex(func, [65, 0], "a");
// Test for IntegerValue
wsp_decode_test_ex(func, [0x3E | 0x80], "application/vnd.wap.mms-message");
wsp_decode_test_ex(func, [0x80], null, "NotWellKnownEncodingError");
wsp_decode_test_ex(func, [0x59 | 0x80], null, "NotWellKnownEncodingError");
run_next_test();
});
@ -1126,8 +1128,12 @@ add_test(function test_ContentTypeValue_encodeConstrainedMedia() {
wsp_encode_test_ex(func, {media: "a", params: [{a: "b"}]}, null, "CodeError");
wsp_encode_test_ex(func, {media: "no/such.type"},
[110, 111, 47, 115, 117, 99, 104, 46, 116, 121, 112, 101, 0]);
wsp_encode_test_ex(func, {media: "application/vnd.wap.multipart.related"},
[0x33 | 0x80]);
for(let ix = 0; ix <WSP.WSP_WELL_KNOWN_CONTENT_TYPES.length ; ++ix){
wsp_encode_test_ex(func, {media: WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].value},
[WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].number | 0x80]);
}
wsp_encode_test_ex(func, {media: "TexT/X-hdml"}, [0x04 | 0x80]);
wsp_encode_test_ex(func, {media: "appLication/*"}, [0x10 | 0x80]);
run_next_test();
});

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

@ -10,6 +10,7 @@
SimpleTest.waitForExplicitFinish();
function runTest() {
"use strict";
var p1 = document.getElementById("plugin1");
var realOrigin = "http://mochi.test:8888";

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

@ -43,15 +43,7 @@ nsDOMDesktopNotification::PostDesktopNotification()
DOMCI_DATA(DesktopNotification, nsDOMDesktopNotification)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDesktopNotification)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDesktopNotification, nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDesktopNotification, nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMDesktopNotification)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDesktopNotification)
NS_INTERFACE_MAP_BEGIN(nsDOMDesktopNotification)
NS_INTERFACE_MAP_ENTRY(nsIDOMDesktopNotification)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DesktopNotification)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)

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

@ -72,7 +72,6 @@ class nsDOMDesktopNotification : public nsDOMEventTargetHelper,
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMDesktopNotification,nsDOMEventTargetHelper)
NS_DECL_NSIDOMDESKTOPNOTIFICATION
nsDOMDesktopNotification(const nsAString & title,

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

@ -3,63 +3,37 @@ b2g = true
browser = false
qemu = true
[test_crash_emulator.js]
[test_incoming_answer_hangup.js]
disabled = Bug 790463
[test_incoming_reject.js]
disabled = Bug 811167
[test_outgoing_answer_hangup.js]
disabled = Bug 811167
[test_incoming_answer_hangup_oncallschanged.js]
disabled = Bug 811167
[test_outgoing_answer_hangup_oncallschanged.js]
disabled = Bug 811167
[test_outgoing_hangup_alerting.js]
disabled = Bug 811167
[test_outgoing_hangup_held.js]
disabled = Bug 811167
[test_outgoing_badNumber.js]
disabled = Bug 761533
[test_outgoing_busy.js]
disabled = Bug 761533
[test_outgoing_reject.js]
disabled = Bug 811167
[test_voicemail_statuschanged.py]
disabled = Bug 806138
[test_voicemail_number.js]
disabled = Bug 811167
[test_incoming_hold_resume.js]
disabled = Bug 811167
[test_outgoing_hold_resume.js]
disabled = Bug 790463
[test_incoming_already_connected.js]
disabled = Bug 790463
[test_incoming_answer_remote_hangup.js]
disabled = Bug 811167
[test_incoming_connecting_hangup.js]
disabled = Bug 811167
[test_incoming_connecting_remote_hangup.js]
disabled = Bug 811167
[test_incoming_hangup_held.js]
disabled = Bug 790463
[test_incoming_remote_cancel.js]
disabled = Bug 811167
[test_incoming_remote_hangup_held.js]
disabled = Bug 811167
[test_outgoing_already_held.js]
disabled = Bug 790463
[test_outgoing_answer_local_hangup.js]
disabled = Bug 790463
[test_outgoing_remote_hangup_held.js]
disabled = Bug 790463
[test_incoming_already_held.js]
disabled = Bug 790463
[test_swap_held_and_active.js]
disabled = Bug 790463
[test_incoming_onstatechange.js]
disabled = Bug 811167
[test_outgoing_onstatechange.js]
disabled = Bug 811167
[test_redundant_operations.js]
disabled = Bug 811167

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

@ -0,0 +1,44 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 10000;
SpecialPowers.addPermission("telephony", true, document);
let telephony = window.navigator.mozTelephony;
let outNumber = "5555551111";
let outgoingCall;
function dial() {
log("Make an outgoing call.");
outgoingCall = telephony.dial(outNumber);
outgoingCall.onalerting = function onalerting(event) {
log("Received 'alerting' call event.");
answer();
};
}
function answer() {
log("Answering the outgoing call.");
outgoingCall.onconnected = function onconnectedOut(event) {
log("Received 'connected' call event for the original outgoing call.");
// just some code to keep call active for awhile
callStartTime = Date.now();
waitFor(cleanUp,function() {
callDuration = Date.now() - callStartTime;
log("Waiting while call is active, call duration (ms): " + callDuration);
return(callDuration >= 2000);
});
};
runEmulatorCmd("gsm accept " + outNumber);
}
function cleanUp(){
outgoingCall.hangUp();
ok("passed");
finish();
}
dial();

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

@ -80,19 +80,6 @@ try {
} catch (e) {
}
// Make sure watch works correctly.
var watchTest = {a: 42};
var watchHandler = function(prop, oldval, newval) { return 22; }
Object.prototype.watch.call(watchTest, 'a', watchHandler);
watchTest.a = 1;
is(watchTest.a, 22, "Watch works correctly");
// Now make sure we can't watch location.
try {
Object.prototype.watch.call(location, 'href', function(prop, oldval, newval) {});
ok(false, "shouldn't be able to set a watchpoint on location");
} catch (e) {}
ok(window === orig, "can't override window");
ok(window.location === origLocation, "properties are properly aliased");
ok(document.location === origLocation, "properties are properly aliased");

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

@ -33,6 +33,7 @@ public:
: mCompositionBounds(0, 0, 0, 0)
, mContentRect(0, 0, 0, 0)
, mDisplayPort(0, 0, 0, 0)
, mCriticalDisplayPort(0, 0, 0, 0)
, mViewport(0, 0, 0, 0)
, mScrollOffset(0, 0)
, mScrollId(NULL_SCROLL_ID)
@ -50,6 +51,7 @@ public:
return mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
mContentRect.IsEqualEdges(aOther.mContentRect) &&
mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
mViewport.IsEqualEdges(aOther.mViewport) &&
mScrollOffset == aOther.mScrollOffset &&
mScrollId == aOther.mScrollId &&
@ -149,6 +151,14 @@ public:
// displayport set on them. See bug 775452.
gfx::Rect mDisplayPort;
// If non-empty, the area of a frame's contents that is considered critical
// to paint. Area outside of this area (i.e. area inside mDisplayPort, but
// outside of mCriticalDisplayPort) is considered low-priority, and may be
// painted with lower precision, or not painted at all.
//
// The same restrictions for mDisplayPort apply here.
gfx::Rect mCriticalDisplayPort;
// The CSS viewport, which is the dimensions we're using to constrain the
// <html> element of this frame, relative to the top-left of the layer. Note
// that its offset is structured in such a way that it doesn't depend on the

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

@ -29,7 +29,9 @@ namespace layers {
// template pattern.
//
// Tiles are aligned to a grid with one of the grid points at (0,0) and other
// grid points spaced evenly in the x- and y-directions by GetTileLength().
// grid points spaced evenly in the x- and y-directions by GetTileLength()
// multiplied by mResolution. GetScaledTileLength() provides convenience for
// accessing these values.
//
// This tile buffer stores a valid region, which defines the areas that have
// up-to-date content. The contents of tiles within this region will be reused
@ -66,6 +68,11 @@ namespace layers {
// void SwapTiles(Tile& aTileA, Tile& aTileB);
//
// Swaps two tiles.
//
// The contents of the tile buffer will be rendered at the resolution specified
// in mResolution, which can be altered with SetResolution. The resolution
// should always be a factor of the tile length, to avoid tiles covering
// non-integer amounts of pixels.
template<typename Derived, typename Tile>
class TiledLayerBuffer
@ -74,20 +81,23 @@ public:
TiledLayerBuffer()
: mRetainedWidth(0)
, mRetainedHeight(0)
, mResolution(1)
{}
~TiledLayerBuffer() {}
// Given a tile origin aligned to a multiple of GetTileLength(),
// Given a tile origin aligned to a multiple of GetScaledTileLength,
// return the tile that describes that region.
// NOTE: To get the valid area of that tile you must intersect
// (aTileOrigin.x, aTileOrigin.y, GetTileLength(), GetTileLength())
// (aTileOrigin.x, aTileOrigin.y,
// GetScaledTileLength(), GetScaledTileLength())
// and GetValidRegion() to get the area of the tile that is valid.
Tile GetTile(const nsIntPoint& aTileOrigin) const;
// Given a tile x, y relative to the top left of the layer, this function
// will return the tile for
// (x*GetTileLength(), y*GetTileLength(), GetTileLength(), GetTileLength())
// (x*GetScaledTileLength(), y*GetScaledTileLength(),
// GetScaledTileLength(), GetScaledTileLength())
Tile GetTile(int x, int y) const;
// This operates the same as GetTile(aTileOrigin), but will also replace the
@ -101,6 +111,7 @@ public:
bool RemoveTile(int x, int y, Tile& aRemovedTile);
uint16_t GetTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE; }
uint32_t GetScaledTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE / mResolution; }
unsigned int GetTileCount() const { return mRetainedTiles.Length(); }
@ -110,13 +121,30 @@ public:
// Given a position i, this function returns the position inside the current tile.
int GetTileStart(int i) const {
return (i >= 0) ? (i % GetTileLength())
: ((GetTileLength() - (-i % GetTileLength())) % GetTileLength());
return (i >= 0) ? (i % GetScaledTileLength())
: ((GetScaledTileLength() - (-i % GetScaledTileLength())) %
GetScaledTileLength());
}
// Rounds the given coordinate down to the nearest tile boundary.
int RoundDownToTileEdge(int aX) const { return aX - GetTileStart(aX); }
// Get and set draw scaling. mResolution affects the resolution at which the
// contents of the buffer are drawn. mResolution has no effect on the
// coordinate space of the valid region, but does affect the size of an
// individual tile's rect in relation to the valid region.
// Setting the resolution will invalidate the buffer.
float GetResolution() const { return mResolution; }
void SetResolution(float aResolution) {
if (mResolution == aResolution) {
return;
}
Update(nsIntRegion(), nsIntRegion());
mResolution = aResolution;
}
bool IsLowPrecision() const { return mResolution < 1; }
protected:
// The implementor should call Update() to change
// the new valid region. This implementation will call
@ -132,11 +160,13 @@ protected:
* stored as column major with the same origin as mValidRegion.GetBounds().
* Any tile that does not intersect mValidRegion is a PlaceholderTile.
* Only the region intersecting with mValidRegion should be read from a tile,
* another other region is assumed to be uninitialized.
* another other region is assumed to be uninitialized. The contents of the
* tiles is scaled by mResolution.
*/
nsTArray<Tile> mRetainedTiles;
int mRetainedWidth; // in tiles
int mRetainedHeight; // in tiles
float mResolution;
private:
const Derived& AsDerived() const { return *static_cast<const Derived*>(this); }
@ -187,10 +217,10 @@ TiledLayerBuffer<Derived, Tile>::GetTile(const nsIntPoint& aTileOrigin) const
// TODO Cache firstTileOriginX/firstTileOriginY
// Find the tile x/y of the first tile and the target tile relative to the (0, 0)
// origin, the difference is the tile x/y relative to the start of the tile buffer.
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
return GetTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
floor_div(aTileOrigin.y, GetTileLength()) - firstTileY);
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetScaledTileLength());
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetScaledTileLength());
return GetTile(floor_div(aTileOrigin.x, GetScaledTileLength()) - firstTileX,
floor_div(aTileOrigin.y, GetScaledTileLength()) - firstTileY);
}
template<typename Derived, typename Tile> Tile
@ -204,10 +234,10 @@ template<typename Derived, typename Tile> bool
TiledLayerBuffer<Derived, Tile>::RemoveTile(const nsIntPoint& aTileOrigin,
Tile& aRemovedTile)
{
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
return RemoveTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
floor_div(aTileOrigin.y, GetTileLength()) - firstTileY,
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetScaledTileLength());
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetScaledTileLength());
return RemoveTile(floor_div(aTileOrigin.x, GetScaledTileLength()) - firstTileX,
floor_div(aTileOrigin.y, GetScaledTileLength()) - firstTileY,
aRemovedTile);
}
@ -251,14 +281,14 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
for (int32_t x = newBound.x; x < newBound.XMost(); tileX++) {
// Compute tileRect(x,y,width,height) in layer space coordinate
// giving us the rect of the tile that hits the newBounds.
int width = GetTileLength() - GetTileStart(x);
int width = GetScaledTileLength() - GetTileStart(x);
if (x + width > newBound.XMost()) {
width = newBound.x + newBound.width - x;
}
tileY = 0;
for (int32_t y = newBound.y; y < newBound.YMost(); tileY++) {
int height = GetTileLength() - GetTileStart(y);
int height = GetScaledTileLength() - GetTileStart(y);
if (y + height > newBound.y + newBound.height) {
height = newBound.y + newBound.height - y;
}
@ -268,8 +298,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
// This old tiles contains some valid area so move it to the new tile
// buffer. Replace the tile in the old buffer with a placeholder
// to leave the old buffer index unaffected.
int tileX = floor_div(x - oldBufferOrigin.x, GetTileLength());
int tileY = floor_div(y - oldBufferOrigin.y, GetTileLength());
int tileX = floor_div(x - oldBufferOrigin.x, GetScaledTileLength());
int tileY = floor_div(y - oldBufferOrigin.y, GetScaledTileLength());
int index = tileX * oldRetainedHeight + tileY;
// The tile may have been removed, skip over it in this case.
@ -328,14 +358,14 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
// Compute tileRect(x,y,width,height) in layer space coordinate
// giving us the rect of the tile that hits the newBounds.
int tileStartX = RoundDownToTileEdge(x);
int width = GetTileLength() - GetTileStart(x);
int width = GetScaledTileLength() - GetTileStart(x);
if (x + width > newBound.XMost())
width = newBound.XMost() - x;
tileY = 0;
for (int y = newBound.y; y < newBound.y + newBound.height; tileY++) {
int tileStartY = RoundDownToTileEdge(y);
int height = GetTileLength() - GetTileStart(y);
int height = GetScaledTileLength() - GetTileStart(y);
if (y + height > newBound.YMost()) {
height = newBound.YMost() - y;
}
@ -350,8 +380,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
// because we can reuse all of the content from the
// previous buffer.
#ifdef DEBUG
int currTileX = floor_div(x - newBufferOrigin.x, GetTileLength());
int currTileY = floor_div(y - newBufferOrigin.y, GetTileLength());
int currTileX = floor_div(x - newBufferOrigin.x, GetScaledTileLength());
int currTileY = floor_div(y - newBufferOrigin.y, GetScaledTileLength());
int index = currTileX * mRetainedHeight + currTileY;
NS_ABORT_IF_FALSE(!newValidRegion.Intersects(tileRect) ||
!IsPlaceholder(newRetainedTiles.
@ -362,8 +392,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
continue;
}
int tileX = floor_div(x - newBufferOrigin.x, GetTileLength());
int tileY = floor_div(y - newBufferOrigin.y, GetTileLength());
int tileX = floor_div(x - newBufferOrigin.x, GetScaledTileLength());
int tileY = floor_div(y - newBufferOrigin.y, GetScaledTileLength());
int index = tileX * mRetainedHeight + tileY;
NS_ABORT_IF_FALSE(index >= 0 &&
static_cast<unsigned>(index) < newRetainedTiles.Length(),

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

@ -1299,7 +1299,8 @@ bool
BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
gfx::Rect& aViewport,
float& aScaleX,
float& aScaleY)
float& aScaleY,
bool aDrawingCritical)
{
#ifdef MOZ_WIDGET_ANDROID
Layer* primaryScrollable = GetPrimaryScrollableLayer();
@ -1311,13 +1312,16 @@ BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesCont
const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
float devPixelRatioX = 1 / rootTransform.GetXScale();
float devPixelRatioY = 1 / rootTransform.GetYScale();
gfx::Rect displayPort((metrics.mDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
(metrics.mDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
metrics.mDisplayPort.width * devPixelRatioX,
metrics.mDisplayPort.height * devPixelRatioY);
const gfx::Rect& metricsDisplayPort =
(aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
metrics.mCriticalDisplayPort : metrics.mDisplayPort;
gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
(metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
metricsDisplayPort.width * devPixelRatioX,
metricsDisplayPort.height * devPixelRatioY);
return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
aHasPendingNewThebesContent, displayPort, devPixelRatioX,
aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
aViewport, aScaleX, aScaleY);
}
#endif

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

@ -276,6 +276,7 @@ public:
virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE;
void SetRepeatTransaction() { mRepeatTransaction = true; }
bool GetRepeatTransaction() { return mRepeatTransaction; }
bool IsRepeatTransaction() { return mIsRepeatTransaction; }
@ -283,7 +284,8 @@ public:
* Called for each iteration of a progressive tile update. Fills
* aViewport, aScaleX and aScaleY with the current scale and viewport
* being used to composite the layers in this manager, to determine what area
* intersects with the target render rectangle.
* intersects with the target render rectangle. aDrawingCritical will be
* true if the current drawing operation is using the critical displayport.
* Returns true if the update should continue, or false if it should be
* cancelled.
* This is only called if gfxPlatform::UseProgressiveTilePainting() returns
@ -292,7 +294,8 @@ public:
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
gfx::Rect& aViewport,
float& aScaleX,
float& aScaleY);
float& aScaleY,
bool aDrawingCritical);
private:
/**

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

@ -105,11 +105,15 @@ BasicTiledLayerBuffer::PaintThebes(BasicTiledThebesLayer* aLayer,
const nsIntRect bounds = aPaintRegion.GetBounds();
{
SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferAlloc");
mSinglePaintBuffer = new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), GetFormat(), !aLayer->CanUseOpaqueSurface());
mSinglePaintBuffer = new gfxImageSurface(
gfxIntSize(ceilf(bounds.width * mResolution),
ceilf(bounds.height * mResolution)),
GetFormat(), !aLayer->CanUseOpaqueSurface());
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
}
nsRefPtr<gfxContext> ctxt = new gfxContext(mSinglePaintBuffer);
ctxt->NewPath();
ctxt->Scale(mResolution, mResolution);
ctxt->Translate(gfxPoint(-bounds.x, -bounds.y));
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
if (PR_IntervalNow() - start > 3) {
@ -165,9 +169,6 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
aTile = BasicTiledLayerTile(tmpTile);
}
gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
aDirtyRect.width, aDirtyRect.height);
// Use the gfxReusableSurfaceWrapper, which will reuse the surface
// if the compositor no longer has a read lock, otherwise the surface
// will be copied into a new writable surface.
@ -176,23 +177,35 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
// Bug 742100, this gfxContext really should live on the stack.
nsRefPtr<gfxContext> ctxt = new gfxContext(writableSurface);
if (mSinglePaintBuffer) {
gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
aDirtyRect.width, aDirtyRect.height);
ctxt->SetOperator(gfxContext::OPERATOR_SOURCE);
ctxt->NewPath();
ctxt->SetSource(mSinglePaintBuffer.get(),
gfxPoint(mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x,
mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y));
gfxPoint((mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x) *
mResolution,
(mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y) *
mResolution));
drawRect.Scale(mResolution, mResolution);
ctxt->Rectangle(drawRect, true);
ctxt->Fill();
} else {
ctxt->NewPath();
ctxt->Scale(mResolution, mResolution);
ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
nsIntPoint a = aTileOrigin;
mCallback(mThebesLayer, ctxt, nsIntRegion(nsIntRect(a, nsIntSize(GetTileLength(), GetTileLength()))), nsIntRegion(), mCallbackData);
nsIntPoint a = nsIntPoint(aTileOrigin.x, aTileOrigin.y);
mCallback(mThebesLayer, ctxt,
nsIntRegion(nsIntRect(a, nsIntSize(GetScaledTileLength(),
GetScaledTileLength()))),
nsIntRegion(), mCallbackData);
}
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
DrawDebugOverlay(writableSurface, aTileOrigin.x, aTileOrigin.y);
DrawDebugOverlay(writableSurface, aTileOrigin.x * mResolution,
aTileOrigin.y * mResolution);
#endif
return aTile;
@ -251,29 +264,35 @@ RoundedTransformViewportBounds(const gfx::Rect& aViewport,
}
bool
BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(BasicTiledLayerBuffer& aTiledBuffer,
const nsIntRegion& aInvalidRegion,
const nsIntRegion& aOldValidRegion,
nsIntRegion& aRegionToPaint,
const gfx3DMatrix& aTransform,
const nsIntRect& aCompositionBounds,
const gfx::Point& aScrollOffset,
const gfxSize& aResolution,
bool aIsRepeated)
{
aRegionToPaint = aInvalidRegion;
// If this is a low precision buffer, we force progressive updates. The
// assumption is that the contents is less important, so visual coherency
// is lower priority than speed.
bool drawingLowPrecision = aTiledBuffer.IsLowPrecision();
// Find out if we have any non-stale content to update.
nsIntRegion freshRegion;
if (!mFirstPaint) {
freshRegion.And(aInvalidRegion, aOldValidRegion);
freshRegion.Sub(aInvalidRegion, freshRegion);
}
nsIntRegion staleRegion;
staleRegion.And(aInvalidRegion, aOldValidRegion);
// Find out the current view transform to determine which tiles to draw
// first, and see if we should just abort this paint. Aborting is usually
// caused by there being an incoming, more relevant paint.
gfx::Rect viewport;
float scaleX, scaleY;
if (BasicManager()->ProgressiveUpdateCallback(!freshRegion.IsEmpty(), viewport, scaleX, scaleY)) {
if (BasicManager()->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion),
viewport,
scaleX, scaleY, !drawingLowPrecision)) {
SAMPLE_MARKER("Abort painting");
aRegionToPaint.SetEmpty();
return aIsRepeated;
@ -284,10 +303,16 @@ BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
RoundedTransformViewportBounds(viewport, aScrollOffset, aResolution,
scaleX, scaleY, aTransform);
// Paint tiles that have no content before tiles that only have stale content.
bool drawingStale = freshRegion.IsEmpty();
// Paint tiles that have stale content or that intersected with the screen
// at the time of issuing the draw command in a single transaction first.
// This is to avoid rendering glitches on animated page content, and when
// layers change size/shape.
nsIntRect criticalViewportRect = roundedTransformedViewport.Intersect(aCompositionBounds);
aRegionToPaint.And(aInvalidRegion, criticalViewportRect);
aRegionToPaint.Or(aRegionToPaint, staleRegion);
bool drawingStale = !aRegionToPaint.IsEmpty();
if (!drawingStale) {
aRegionToPaint = freshRegion;
aRegionToPaint = aInvalidRegion;
}
// Prioritise tiles that are currently visible on the screen.
@ -297,32 +322,35 @@ BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
paintVisible = true;
}
// Paint area that's visible and overlaps previously valid content to avoid
// visible glitches in animated elements, such as gifs.
bool paintInSingleTransaction = paintVisible && (drawingStale || mFirstPaint);
// The following code decides what order to draw tiles in, based on the
// current scroll direction of the primary scrollable layer.
NS_ASSERTION(!aRegionToPaint.IsEmpty(), "Unexpectedly empty paint region!");
nsIntRect paintBounds = aRegionToPaint.GetBounds();
int startX, incX, startY, incY;
int tileLength = aTiledBuffer.GetScaledTileLength();
if (aScrollOffset.x >= mLastScrollOffset.x) {
startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.x);
incX = mTiledBuffer.GetTileLength();
startX = aTiledBuffer.RoundDownToTileEdge(paintBounds.x);
incX = tileLength;
} else {
startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.XMost() - 1);
incX = -mTiledBuffer.GetTileLength();
startX = aTiledBuffer.RoundDownToTileEdge(paintBounds.XMost() - 1);
incX = -tileLength;
}
if (aScrollOffset.y >= mLastScrollOffset.y) {
startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.y);
incY = mTiledBuffer.GetTileLength();
startY = aTiledBuffer.RoundDownToTileEdge(paintBounds.y);
incY = tileLength;
} else {
startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.YMost() - 1);
incY = -mTiledBuffer.GetTileLength();
startY = aTiledBuffer.RoundDownToTileEdge(paintBounds.YMost() - 1);
incY = -tileLength;
}
// Find a tile to draw.
nsIntRect tileBounds(startX, startY,
mTiledBuffer.GetTileLength(),
mTiledBuffer.GetTileLength());
nsIntRect tileBounds(startX, startY, tileLength, tileLength);
int32_t scrollDiffX = aScrollOffset.x - mLastScrollOffset.x;
int32_t scrollDiffY = aScrollOffset.y - mLastScrollOffset.y;
// This loop will always terminate, as there is at least one tile area
@ -345,23 +373,75 @@ BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
// The region needed to paint is larger then our progressive chunk size
// therefore update what we want to paint and ask for a new paint transaction.
// If we're drawing stale, visible content, make sure that it happens
// in one go by repeating this work without calling the painted
// callback. The remaining content is then drawn tile-by-tile in
// multiple transactions.
if (paintVisible && drawingStale) {
// If we need to draw more than one tile to maintain coherency, make
// sure it happens in the same transaction by requesting this work be
// repeated immediately.
// If this is unnecessary, the remaining work will be done tile-by-tile in
// subsequent transactions.
if (!drawingLowPrecision && paintInSingleTransaction) {
repeatImmediately = true;
} else {
BasicManager()->SetRepeatTransaction();
}
} else {
// The transaction is completed, store the last scroll offset.
mLastScrollOffset = aScrollOffset;
}
return repeatImmediately;
}
bool
BasicTiledThebesLayer::ProgressiveUpdate(BasicTiledLayerBuffer& aTiledBuffer,
nsIntRegion& aValidRegion,
nsIntRegion& aInvalidRegion,
const nsIntRegion& aOldValidRegion,
const gfx3DMatrix& aTransform,
const nsIntRect& aCompositionBounds,
const gfx::Point& aScrollOffset,
const gfxSize& aResolution,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{
bool repeat = false;
do {
// Compute the region that should be updated. Repeat as many times as
// is required.
nsIntRegion regionToPaint;
repeat = ComputeProgressiveUpdateRegion(aTiledBuffer,
aInvalidRegion,
aOldValidRegion,
regionToPaint,
aTransform,
aCompositionBounds,
aScrollOffset,
aResolution,
repeat);
// There's no further work to be done, return if nothing has been
// drawn, or give what has been drawn to the shadow layer to upload.
if (regionToPaint.IsEmpty()) {
if (repeat) {
break;
} else {
return false;
}
}
// Keep track of what we're about to refresh.
aValidRegion.Or(aValidRegion, regionToPaint);
// aValidRegion may have been altered by InvalidateRegion, but we still
// want to display stale content until it gets progressively updated.
// Create a region that includes stale content.
nsIntRegion validOrStale;
validOrStale.Or(aValidRegion, aOldValidRegion);
// Paint the computed region and subtract it from the invalid region.
aTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
aInvalidRegion.Sub(aInvalidRegion, regionToPaint);
} while (repeat);
return true;
}
void
BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
@ -382,23 +462,15 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
if (mTiledBuffer.HasFormatChanged(this)) {
mValidRegion = nsIntRegion();
}
if (mLowPrecisionTiledBuffer.HasFormatChanged(this)) {
mLowPrecisionValidRegion = nsIntRegion();
}
nsIntRegion invalidRegion = mVisibleRegion;
invalidRegion.Sub(invalidRegion, mValidRegion);
if (invalidRegion.IsEmpty())
return;
gfxSize resolution(1, 1);
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
const FrameMetrics& metrics = parent->GetFrameMetrics();
resolution.width *= metrics.mResolution.width;
resolution.height *= metrics.mResolution.height;
}
// Only draw progressively when the resolution is unchanged.
if (gfxPlatform::UseProgressiveTilePainting() &&
!BasicManager()->HasShadowTarget() &&
mTiledBuffer.GetResolution() == resolution) {
// Calculate the transform required to convert screen space into layer space
gfx3DMatrix transform = GetEffectiveTransform();
// XXX Not sure if this code for intermediate surfaces is correct.
@ -411,70 +483,92 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
}
transform.Invert();
// Store the old valid region, then clear it before painting.
// We clip the old valid region to the visible region, as it only gets
// used to decide stale content (currently valid and previously visible)
nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
oldValidRegion.And(oldValidRegion, mVisibleRegion);
mTiledBuffer.ClearPaintedRegion();
nsIntRect layerDisplayPort;
nsIntRegion lowPrecisionInvalidRegion;
const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort;
if (!criticalDisplayPort.IsEmpty()) {
// Calculate the invalid region for the low precision buffer
lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
// Make sure that tiles that fall outside of the visible region are
// discarded on the first update.
if (!BasicManager()->IsRepeatTransaction()) {
mValidRegion.And(mValidRegion, mVisibleRegion);
// Find the critical display port in layer space.
gfxRect transformedCriticalDisplayPort = transform.TransformBounds(
gfxRect(criticalDisplayPort.x, criticalDisplayPort.y,
criticalDisplayPort.width, criticalDisplayPort.height));
transformedCriticalDisplayPort.RoundOut();
layerDisplayPort = nsIntRect(transformedCriticalDisplayPort.x,
transformedCriticalDisplayPort.y,
transformedCriticalDisplayPort.width,
transformedCriticalDisplayPort.height);
// Clip the invalid region to the critical display-port
invalidRegion.And(invalidRegion, layerDisplayPort);
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
return;
}
}
// Calculate the scroll offset since the last transaction.
gfxSize resolution(1, 1);
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
const FrameMetrics& metrics = parent->GetFrameMetrics();
resolution.width *= metrics.mResolution.width;
resolution.height *= metrics.mResolution.height;
}
// Calculate the scroll offset since the last transaction, and the
// composition bounds.
nsIntRect compositionBounds;
gfx::Point scrollOffset(0, 0);
Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
if (primaryScrollable) {
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
scrollOffset = metrics.mScrollOffset;
gfxRect transformedViewport = transform.TransformBounds(
gfxRect(metrics.mCompositionBounds.x, metrics.mCompositionBounds.y,
metrics.mCompositionBounds.width, metrics.mCompositionBounds.height));
transformedViewport.RoundOut();
compositionBounds = nsIntRect(transformedViewport.x, transformedViewport.y,
transformedViewport.width, transformedViewport.height);
}
bool repeat = false;
do {
// Compute the region that should be updated. Repeat as many times as
// is required.
nsIntRegion regionToPaint;
repeat = ComputeProgressiveUpdateRegion(invalidRegion,
oldValidRegion,
regionToPaint,
transform,
scrollOffset,
resolution,
repeat);
if (!invalidRegion.IsEmpty()) {
bool updatedBuffer = false;
// Only draw progressively when the resolution is unchanged.
if (gfxPlatform::UseProgressiveTilePainting() &&
!BasicManager()->HasShadowTarget() &&
mTiledBuffer.GetFrameResolution() == resolution) {
// Store the old valid region, then clear it before painting.
// We clip the old valid region to the visible region, as it only gets
// used to decide stale content (currently valid and previously visible)
nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
oldValidRegion.And(oldValidRegion, mVisibleRegion);
if (!layerDisplayPort.IsEmpty()) {
oldValidRegion.And(oldValidRegion, layerDisplayPort);
}
// There's no further work to be done, return if nothing has been
// drawn, or give what has been drawn to the shadow layer to upload.
if (regionToPaint.IsEmpty()) {
if (repeat) {
break;
// Make sure that tiles that fall outside of the visible region are
// discarded on the first update.
if (!BasicManager()->IsRepeatTransaction()) {
mValidRegion.And(mValidRegion, mVisibleRegion);
if (!layerDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, layerDisplayPort);
}
}
updatedBuffer =
ProgressiveUpdate(mTiledBuffer, mValidRegion, invalidRegion,
oldValidRegion, transform, compositionBounds,
scrollOffset, resolution, aCallback, aCallbackData);
} else {
return;
}
}
// Keep track of what we're about to refresh.
mValidRegion.Or(mValidRegion, regionToPaint);
// mValidRegion would have been altered by InvalidateRegion, but we still
// want to display stale content until it gets progressively updated.
// Create a region that includes stale content.
nsIntRegion validOrStale;
validOrStale.Or(mValidRegion, oldValidRegion);
// Paint the computed region and subtract it from the invalid region.
mTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
invalidRegion.Sub(invalidRegion, regionToPaint);
} while (repeat);
} else {
mTiledBuffer.ClearPaintedRegion();
mTiledBuffer.SetResolution(resolution);
updatedBuffer = true;
mTiledBuffer.SetFrameResolution(resolution);
mValidRegion = mVisibleRegion;
if (!layerDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, layerDisplayPort);
}
mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData);
}
if (updatedBuffer) {
mTiledBuffer.ReadLock();
// Only paint the mask layer on the first transaction.
@ -490,6 +584,77 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mTiledBuffer);
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
mTiledBuffer.ClearPaintedRegion();
}
}
// If we have a critical display-port defined, render the full display-port
// progressively in the low-precision tiled buffer.
bool updatedLowPrecision = false;
if (gfxPlatform::UseLowPrecisionBuffer() &&
!criticalDisplayPort.IsEmpty() &&
!nsIntRegion(layerDisplayPort).Contains(mVisibleRegion)) {
nsIntRegion oldValidRegion = mLowPrecisionTiledBuffer.GetValidRegion();
oldValidRegion.And(oldValidRegion, mVisibleRegion);
// If the frame resolution has changed, invalidate the buffer
if (mLowPrecisionTiledBuffer.GetFrameResolution() != resolution) {
if (!mLowPrecisionValidRegion.IsEmpty()) {
updatedLowPrecision = true;
}
oldValidRegion.SetEmpty();
mLowPrecisionValidRegion.SetEmpty();
mLowPrecisionTiledBuffer.SetFrameResolution(resolution);
}
// Invalidate previously valid content that is no longer visible
if (!BasicManager()->IsRepeatTransaction()) {
mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion);
}
// Remove the valid high-precision region from the invalid low-precision
// region. We don't want to spend time drawing things twice.
nsIntRegion invalidHighPrecisionIntersect;
invalidHighPrecisionIntersect.And(lowPrecisionInvalidRegion, mValidRegion);
lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, invalidHighPrecisionIntersect);
if (!lowPrecisionInvalidRegion.IsEmpty()) {
updatedLowPrecision =
ProgressiveUpdate(mLowPrecisionTiledBuffer, mLowPrecisionValidRegion,
lowPrecisionInvalidRegion, oldValidRegion, transform,
compositionBounds, scrollOffset, resolution, aCallback,
aCallbackData);
}
// Re-add the high-precision valid region intersection so that we can
// maintain coherency when the valid region changes.
lowPrecisionInvalidRegion.Or(lowPrecisionInvalidRegion, invalidHighPrecisionIntersect);
} else if (!mLowPrecisionValidRegion.IsEmpty()) {
// Clear the low precision tiled buffer
updatedLowPrecision = true;
mLowPrecisionValidRegion.SetEmpty();
mLowPrecisionTiledBuffer.PaintThebes(this, mLowPrecisionValidRegion,
mLowPrecisionValidRegion, aCallback,
aCallbackData);
}
// We send a Painted callback if we clear the valid region of the low
// precision buffer, so that the shadow buffer's valid region can be updated
// and the associated resources can be freed.
if (updatedLowPrecision) {
mLowPrecisionTiledBuffer.ReadLock();
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mLowPrecisionTiledBuffer);
// The GL layer manager uses the buffer resolution to distinguish calls
// to PaintedTiledLayerBuffer.
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
mLowPrecisionTiledBuffer.ClearPaintedRegion();
}
// The transaction is completed, store the last scroll offset.
if (!BasicManager()->GetRepeatTransaction()) {
mLastScrollOffset = scrollOffset;
}
mFirstPaint = false;
}

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

@ -12,6 +12,8 @@
#include "BasicImplData.h"
#include <algorithm>
#define LOW_PRECISION_RESOLUTION 0.25
namespace mozilla {
namespace layers {
@ -107,8 +109,8 @@ public:
}
}
const gfxSize& GetResolution() { return mResolution; }
void SetResolution(const gfxSize& aResolution) { mResolution = aResolution; }
const gfxSize& GetFrameResolution() { return mFrameResolution; }
void SetFrameResolution(const gfxSize& aResolution) { mFrameResolution = aResolution; }
bool HasFormatChanged(BasicTiledThebesLayer* aThebesLayer) const;
protected:
@ -133,7 +135,7 @@ private:
BasicTiledThebesLayer* mThebesLayer;
LayerManager::DrawThebesLayerCallback mCallback;
void* mCallbackData;
gfxSize mResolution;
gfxSize mFrameResolution;
bool mLastPaintOpaque;
// The buffer we use when UseSinglePaintBuffer() above is true.
@ -166,6 +168,7 @@ public:
, mFirstPaint(true)
{
MOZ_COUNT_CTOR(BasicTiledThebesLayer);
mLowPrecisionTiledBuffer.SetResolution(LOW_PRECISION_RESOLUTION);
}
~BasicTiledThebesLayer()
@ -179,6 +182,7 @@ public:
virtual void InvalidateRegion(const nsIntRegion& aRegion) {
mInvalidRegion.Or(mInvalidRegion, aRegion);
mValidRegion.Sub(mValidRegion, aRegion);
mLowPrecisionValidRegion.Sub(mLowPrecisionValidRegion, aRegion);
}
// Shadow methods
@ -220,12 +224,14 @@ private:
* at once to maintain visual coherency.
*
* aInvalidRegion is the current invalid region.
* aOldValidRegion is the valid region of mTiledBuffer at the beginning of the
* aOldValidRegion is the valid region of aTiledBuffer at the beginning of the
* current transaction.
* aRegionToPaint will be filled with the region to update. This may be empty,
* which indicates that there is no more work to do.
* aTransform is the transform required to convert from screen-space to
* layer-space.
* aCompositionBounds is the composition bounds from the primary scrollable
* layer, transformed into layer coordinates.
* aScrollOffset is the current scroll offset of the primary scrollable layer.
* aResolution is the render resolution of the layer.
* aIsRepeated should be true if this function has already been called during
@ -234,16 +240,35 @@ private:
* Returns true if it should be called again, false otherwise. In the case
* that aRegionToPaint is empty, this will return aIsRepeated for convenience.
*/
bool ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
bool ComputeProgressiveUpdateRegion(BasicTiledLayerBuffer& aTiledBuffer,
const nsIntRegion& aInvalidRegion,
const nsIntRegion& aOldValidRegion,
nsIntRegion& aRegionToPaint,
const gfx3DMatrix& aTransform,
const nsIntRect& aCompositionBounds,
const gfx::Point& aScrollOffset,
const gfxSize& aResolution,
bool aIsRepeated);
/**
* Performs a progressive update of a given tiled buffer.
* See ComputeProgressiveUpdateRegion above for parameter documentation.
*/
bool ProgressiveUpdate(BasicTiledLayerBuffer& aTiledBuffer,
nsIntRegion& aValidRegion,
nsIntRegion& aInvalidRegion,
const nsIntRegion& aOldValidRegion,
const gfx3DMatrix& aTransform,
const nsIntRect& aCompositionBounds,
const gfx::Point& aScrollOffset,
const gfxSize& aResolution,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData);
// Members
BasicTiledLayerBuffer mTiledBuffer;
BasicTiledLayerBuffer mLowPrecisionTiledBuffer;
nsIntRegion mLowPrecisionValidRegion;
gfx::Point mLastScrollOffset;
bool mFirstPaint;
};

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

@ -875,7 +875,8 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
// We synchronise the viewport information with Java after sending the above
// notifications, so that Java can take these into account in its response.
// Calculate the absolute display port to send to Java
gfx::Rect displayPortLayersPixels(metrics.mDisplayPort);
gfx::Rect displayPortLayersPixels(metrics.mCriticalDisplayPort.IsEmpty() ?
metrics.mDisplayPort : metrics.mCriticalDisplayPort);
nsIntRect displayPortDevPixels(
NS_lround(displayPortLayersPixels.x * devPixelRatioX),
NS_lround(displayPortLayersPixels.y * devPixelRatioY),

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

@ -136,6 +136,9 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer,
const gfxSize& aOldResolution,
const gfxSize& aNewResolution)
{
NS_ASSERTION(aVideoMemoryTiledBuffer->GetResolution() == 1.0f,
"ReusableTileStoreOGL cannot harvest scaled tiles!");
gfxSize scaleFactor = gfxSize(aNewResolution.width / aOldResolution.width,
aNewResolution.height / aOldResolution.height);

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

@ -7,6 +7,7 @@
#include "ReusableTileStoreOGL.h"
#include "BasicTiledThebesLayer.h"
#include "gfxImageSurface.h"
#include "gfxPlatform.h"
namespace mozilla {
namespace layers {
@ -46,7 +47,7 @@ TiledLayerBufferOGL::Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
long start = PR_IntervalNow();
#endif
mResolution = aResolution;
mFrameResolution = aResolution;
mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
mContext->MakeCurrent();
Update(aNewValidRegion, aInvalidateRegion);
@ -115,7 +116,10 @@ TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
: ShadowThebesLayer(aManager, nullptr)
, LayerOGL(aManager)
, mVideoMemoryTiledBuffer(aManager->gl())
, mLowPrecisionVideoMemoryTiledBuffer(aManager->gl())
, mReusableTileStore(nullptr)
, mPendingUpload(false)
, mPendingLowPrecisionUpload(false)
{
mImplData = static_cast<LayerOGL*>(this);
}
@ -123,6 +127,7 @@ TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
TiledThebesLayerOGL::~TiledThebesLayerOGL()
{
mMainMemoryTiledBuffer.ReadUnlock();
mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
if (mReusableTileStore)
delete mReusableTileStore;
}
@ -139,18 +144,54 @@ TiledThebesLayerOGL::MemoryPressure()
void
TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
{
if (mTiledBuffer->IsLowPrecision()) {
mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
mLowPrecisionMainMemoryTiledBuffer = *mTiledBuffer;
mLowPrecisionRegionToUpload.Or(mLowPrecisionRegionToUpload,
mLowPrecisionMainMemoryTiledBuffer.GetPaintedRegion());
mLowPrecisionMainMemoryTiledBuffer.ClearPaintedRegion();
mPendingLowPrecisionUpload = true;
} else {
mMainMemoryTiledBuffer.ReadUnlock();
mMainMemoryTiledBuffer = *mTiledBuffer;
// TODO: Remove me once Bug 747811 lands.
delete mTiledBuffer;
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetPaintedRegion());
mMainMemoryTiledBuffer.ClearPaintedRegion();
mPendingUpload = true;
}
// TODO: Remove me once Bug 747811 lands.
delete mTiledBuffer;
}
void
TiledThebesLayerOGL::ProcessLowPrecisionUploadQueue()
{
if (!mPendingLowPrecisionUpload)
return;
mLowPrecisionRegionToUpload.And(mLowPrecisionRegionToUpload,
mLowPrecisionMainMemoryTiledBuffer.GetValidRegion());
// XXX The aResolution parameter of Upload is unused here - this is normally
// set so that ReusableTileStoreOGL knows the frame resolution of tiles
// it's harvesting.
mLowPrecisionVideoMemoryTiledBuffer.SetResolution(
mLowPrecisionMainMemoryTiledBuffer.GetResolution());
mLowPrecisionVideoMemoryTiledBuffer.Upload(&mLowPrecisionMainMemoryTiledBuffer,
mLowPrecisionMainMemoryTiledBuffer.GetValidRegion(),
mLowPrecisionRegionToUpload, gfxSize(1, 1));
nsIntRegion validRegion = mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion();
mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
mLowPrecisionMainMemoryTiledBuffer = BasicTiledLayerBuffer();
mLowPrecisionRegionToUpload = nsIntRegion();
mPendingLowPrecisionUpload = false;
}
void
TiledThebesLayerOGL::ProcessUploadQueue()
{
if (mRegionToUpload.IsEmpty())
if (!mPendingUpload)
return;
// We should only be retaining old tiles if we're not fixed position.
@ -159,9 +200,10 @@ TiledThebesLayerOGL::ProcessUploadQueue()
if (mReusableTileStore && mIsFixedPosition) {
delete mReusableTileStore;
mReusableTileStore = nullptr;
} else if (!mReusableTileStore && !mIsFixedPosition) {
} else if (gfxPlatform::UseReusableTileStore() &&
!mReusableTileStore && !mIsFixedPosition) {
// XXX Add a pref for reusable tile store size
mReusableTileStore = new ReusableTileStoreOGL(gl(), 2);
mReusableTileStore = new ReusableTileStoreOGL(gl(), 1);
}
gfxSize resolution(1, 1);
@ -181,7 +223,7 @@ TiledThebesLayerOGL::ProcessUploadQueue()
&mVideoMemoryTiledBuffer,
mVideoMemoryTiledBuffer.GetValidRegion(),
mMainMemoryTiledBuffer.GetValidRegion(),
mVideoMemoryTiledBuffer.GetResolution(),
mVideoMemoryTiledBuffer.GetFrameResolution(),
resolution);
}
@ -192,6 +234,7 @@ TiledThebesLayerOGL::ProcessUploadQueue()
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
mMainMemoryTiledBuffer.GetValidRegion(),
mRegionToUpload, resolution);
mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
mMainMemoryTiledBuffer.ReadUnlock();
@ -202,7 +245,7 @@ TiledThebesLayerOGL::ProcessUploadQueue()
// tile by tile.
mMainMemoryTiledBuffer = BasicTiledLayerBuffer();
mRegionToUpload = nsIntRegion();
mPendingUpload = false;
}
void
@ -240,53 +283,51 @@ TiledThebesLayerOGL::RenderTile(const TiledTexture& aTile,
}
void
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
TiledThebesLayerOGL::RenderLayerBuffer(TiledLayerBufferOGL& aLayerBuffer,
const nsIntRegion& aValidRegion,
const nsIntPoint& aOffset,
const nsIntRegion& aMaskRegion)
{
gl()->MakeCurrent();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
ProcessUploadQueue();
Layer* maskLayer = GetMaskLayer();
// Render old tiles to fill in gaps we haven't had the time to render yet.
if (mReusableTileStore) {
mReusableTileStore->DrawTiles(this,
mVideoMemoryTiledBuffer.GetValidRegion(),
mVideoMemoryTiledBuffer.GetResolution(),
GetEffectiveTransform(), aOffset, maskLayer);
}
// Render valid tiles.
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
const nsIntRect visibleRect = visibleRegion.GetBounds();
float resolution = aLayerBuffer.GetResolution();
gfx3DMatrix transform = GetEffectiveTransform();
transform.Scale(1/resolution, 1/resolution, 1);
uint32_t rowCount = 0;
uint32_t tileX = 0;
for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
rowCount++;
int32_t tileStartX = mVideoMemoryTiledBuffer.GetTileStart(x);
int16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
int32_t tileStartX = aLayerBuffer.GetTileStart(x);
int32_t w = aLayerBuffer.GetScaledTileLength() - tileStartX;
if (x + w > visibleRect.x + visibleRect.width)
w = visibleRect.x + visibleRect.width - x;
int tileY = 0;
for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
int32_t tileStartY = mVideoMemoryTiledBuffer.GetTileStart(y);
int16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
int32_t tileStartY = aLayerBuffer.GetTileStart(y);
int32_t h = aLayerBuffer.GetScaledTileLength() - tileStartY;
if (y + h > visibleRect.y + visibleRect.height)
h = visibleRect.y + visibleRect.height - y;
TiledTexture tileTexture = mVideoMemoryTiledBuffer.
GetTile(nsIntPoint(mVideoMemoryTiledBuffer.RoundDownToTileEdge(x),
mVideoMemoryTiledBuffer.RoundDownToTileEdge(y)));
if (tileTexture != mVideoMemoryTiledBuffer.GetPlaceholderTile()) {
TiledTexture tileTexture = aLayerBuffer.
GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x),
aLayerBuffer.RoundDownToTileEdge(y)));
if (tileTexture != aLayerBuffer.GetPlaceholderTile()) {
nsIntRegion tileDrawRegion = nsIntRegion(nsIntRect(x, y, w, h));
tileDrawRegion.And(tileDrawRegion, mValidRegion);
tileDrawRegion.And(tileDrawRegion, aValidRegion);
tileDrawRegion.Sub(tileDrawRegion, aMaskRegion);
nsIntPoint tileOffset(x - tileStartX, y - tileStartY);
uint16_t tileSize = mVideoMemoryTiledBuffer.GetTileLength();
RenderTile(tileTexture, GetEffectiveTransform(), aOffset, tileDrawRegion,
if (!tileDrawRegion.IsEmpty()) {
tileDrawRegion.ScaleRoundOut(resolution, resolution);
nsIntPoint tileOffset((x - tileStartX) * resolution,
(y - tileStartY) * resolution);
uint32_t tileSize = aLayerBuffer.GetTileLength();
RenderTile(tileTexture, transform, aOffset, tileDrawRegion,
tileOffset, nsIntSize(tileSize, tileSize), maskLayer);
}
}
tileY++;
y += h;
}
@ -295,5 +336,28 @@ TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOf
}
}
void
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
{
gl()->MakeCurrent();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
ProcessUploadQueue();
ProcessLowPrecisionUploadQueue();
// Render old tiles to fill in gaps we haven't had the time to render yet.
if (mReusableTileStore) {
mReusableTileStore->DrawTiles(this,
mVideoMemoryTiledBuffer.GetValidRegion(),
mVideoMemoryTiledBuffer.GetFrameResolution(),
GetEffectiveTransform(), aOffset, GetMaskLayer());
}
// Render valid tiles.
RenderLayerBuffer(mLowPrecisionVideoMemoryTiledBuffer,
mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion(),
aOffset, mValidRegion);
RenderLayerBuffer(mVideoMemoryTiledBuffer, mValidRegion, aOffset, nsIntRegion());
}
} // mozilla
} // layers

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

@ -80,7 +80,9 @@ public:
TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
const gfxSize& GetResolution() { return mResolution; }
// Stores the absolute resolution of the containing frame, calculated
// by the sum of the resolutions of all parent layers' FrameMetrics.
const gfxSize& GetFrameResolution() { return mFrameResolution; }
protected:
TiledTexture ValidateTile(TiledTexture aTile,
@ -96,7 +98,7 @@ protected:
private:
nsRefPtr<gl::GLContext> mContext;
const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
gfxSize mResolution;
gfxSize mFrameResolution;
void GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
GLenum& aOutFormat,
@ -129,6 +131,7 @@ public:
}
void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer);
void ProcessUploadQueue();
void ProcessLowPrecisionUploadQueue();
void MemoryPressure();
@ -142,10 +145,20 @@ public:
Layer* aMaskLayer);
private:
void RenderLayerBuffer(TiledLayerBufferOGL& aLayerBuffer,
const nsIntRegion& aValidRegion,
const nsIntPoint& aOffset,
const nsIntRegion& aMaskRegion);
nsIntRegion mRegionToUpload;
nsIntRegion mLowPrecisionRegionToUpload;
BasicTiledLayerBuffer mMainMemoryTiledBuffer;
BasicTiledLayerBuffer mLowPrecisionMainMemoryTiledBuffer;
TiledLayerBufferOGL mVideoMemoryTiledBuffer;
TiledLayerBufferOGL mLowPrecisionVideoMemoryTiledBuffer;
ReusableTileStoreOGL* mReusableTileStore;
bool mPendingUpload : 1;
bool mPendingLowPrecisionUpload : 1;
};
} // layers

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

@ -1246,6 +1246,38 @@ gfxPlatform::UseProgressiveTilePainting()
return sUseProgressiveTilePainting;
}
bool
gfxPlatform::UseLowPrecisionBuffer()
{
static bool sUseLowPrecisionBuffer;
static bool sUseLowPrecisionBufferPrefCached = false;
if (!sUseLowPrecisionBufferPrefCached) {
sUseLowPrecisionBufferPrefCached = true;
mozilla::Preferences::AddBoolVarCache(&sUseLowPrecisionBuffer,
"layers.low-precision-buffer",
false);
}
return sUseLowPrecisionBuffer;
}
bool
gfxPlatform::UseReusableTileStore()
{
static bool sUseReusableTileStore;
static bool sUseReusableTileStorePrefCached = false;
if (!sUseReusableTileStorePrefCached) {
sUseReusableTileStorePrefCached = true;
mozilla::Preferences::AddBoolVarCache(&sUseReusableTileStore,
"layers.reuse-invalid-tiles",
false);
}
return sUseReusableTileStore;
}
bool
gfxPlatform::OffMainThreadCompositingEnabled()
{

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

@ -405,6 +405,14 @@ public:
// Break large OMTC tiled thebes layer painting into small paints.
static bool UseProgressiveTilePainting();
// When a critical display-port is set, render the visible area outside of
// it into a buffer at a lower precision. Requires tiled buffers.
static bool UseLowPrecisionBuffer();
// Retain some invalid tiles when the valid region of a layer changes and
// excludes previously valid tiles.
static bool UseReusableTileStore();
static bool OffMainThreadCompositingEnabled();
/**

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

@ -1324,6 +1324,12 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
aCORSMode, aLoadingPrincipal))
return false;
// Never validate data URIs.
nsAutoCString scheme;
aURI->GetScheme(scheme);
if (scheme.EqualsLiteral("data"))
return true;
bool validateRequest = false;
// If the request's loadId is the same as the aCX, then it is ok to use

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

@ -965,6 +965,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
WriteParam(aMsg, aParam.mContentRect);
WriteParam(aMsg, aParam.mScrollOffset);
WriteParam(aMsg, aParam.mDisplayPort);
WriteParam(aMsg, aParam.mCriticalDisplayPort);
WriteParam(aMsg, aParam.mCompositionBounds);
WriteParam(aMsg, aParam.mScrollId);
WriteParam(aMsg, aParam.mResolution);
@ -980,6 +981,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
ReadParam(aMsg, aIter, &aResult->mScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mCriticalDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mCompositionBounds) &&
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
ReadParam(aMsg, aIter, &aResult->mResolution) &&

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

@ -1 +1,348 @@
//this space intentionally left blank
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* ES5 15.4.4.14. */
function ArrayIndexOf(searchElement/*, fromIndex*/) {
/* Step 1. */
var O = %ToObject(this);
/* Steps 2-3. */
var len = TO_UINT32(O.length);
/* Step 4. */
if (len === 0)
return -1;
/* Step 5. */
var n = arguments.length > 1 ? %ToInteger(arguments[1]) : 0;
/* Step 6. */
if (n >= len)
return -1;
var k;
/* Step 7. */
if (n >= 0)
k = n;
/* Step 8. */
else {
/* Step a. */
k = len + n;
/* Step b. */
if (k < 0)
k = 0;
}
/* Step 9. */
for (; k < len; k++) {
if (k in O && O[k] === searchElement)
return k;
}
/* Step 10. */
return -1;
}
function ArrayStaticIndexOf(list, searchElement/*, fromIndex*/) {
if (arguments.length < 1)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.indexOf');
var fromIndex = arguments.length > 2 ? arguments[2] : 0;
return %_CallFunction(list, searchElement, fromIndex, ArrayIndexOf);
}
/* ES5 15.4.4.15. */
function ArrayLastIndexOf(searchElement/*, fromIndex*/) {
/* Step 1. */
var O = %ToObject(this);
/* Steps 2-3. */
var len = TO_UINT32(O.length);
/* Step 4. */
if (len === 0)
return -1;
/* Step 5. */
var n = arguments.length > 1 ? %ToInteger(arguments[1]) : len - 1;
/* Steps 6-7. */
var k;
if (n > len - 1)
k = len - 1;
else if (n < 0)
k = len + n;
else
k = n;
/* Step 8. */
for (; k >= 0; k--) {
if (k in O && O[k] === searchElement)
return k;
}
/* Step 9. */
return -1;
}
function ArrayStaticLastIndexOf(list, searchElement/*, fromIndex*/) {
if (arguments.length < 1)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.lastIndexOf');
var fromIndex;
if (arguments.length > 2) {
fromIndex = arguments[2];
} else {
var O = %ToObject(list);
var len = TO_UINT32(O.length);
fromIndex = len - 1;
}
return %_CallFunction(list, searchElement, fromIndex, ArrayLastIndexOf);
}
/* ES5 15.4.4.16. */
function ArrayEvery(callbackfn/*, thisArg*/) {
/* Step 1. */
var O = %ToObject(this);
/* Steps 2-3. */
var len = TO_UINT32(O.length);
/* Step 4. */
if (arguments.length === 0)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.every');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
/* Step 5. */
var T = arguments.length > 1 ? arguments[1] : void 0;
/* Steps 6-7. */
/* Steps a (implicit), and d. */
for (var k = 0; k < len; k++) {
/* Step b */
if (k in O) {
/* Step c. */
if (!%_CallFunction(T, O[k], k, O, callbackfn))
return false;
}
}
/* Step 8. */
return true;
}
function ArrayStaticEvery(list, callbackfn/*, thisArg*/) {
if (arguments.length < 2)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.every');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
var T = arguments.length > 2 ? arguments[2] : void 0;
return %_CallFunction(list, callbackfn, T, ArrayEvery);
}
/* ES5 15.4.4.17. */
function ArraySome(callbackfn/*, thisArg*/) {
/* Step 1. */
var O = %ToObject(this);
/* Steps 2-3. */
var len = TO_UINT32(O.length);
/* Step 4. */
if (arguments.length === 0)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.some');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
/* Step 5. */
var T = arguments.length > 1 ? arguments[1] : void 0;
/* Steps 6-7. */
/* Steps a (implicit), and d. */
for (var k = 0; k < len; k++) {
/* Step b */
if (k in O) {
/* Step c. */
if (%_CallFunction(T, O[k], k, O, callbackfn))
return true;
}
}
/* Step 8. */
return false;
}
function ArrayStaticSome(list, callbackfn/*, thisArg*/) {
if (arguments.length < 2)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.some');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
var T = arguments.length > 2 ? arguments[2] : void 0;
return %_CallFunction(list, callbackfn, T, ArraySome);
}
/* ES5 15.4.4.18. */
function ArrayForEach(callbackfn/*, thisArg*/) {
/* Step 1. */
var O = %ToObject(this);
/* Steps 2-3. */
var len = TO_UINT32(O.length);
/* Step 4. */
if (arguments.length === 0)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.forEach');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
/* Step 5. */
var T = arguments.length > 1 ? arguments[1] : void 0;
/* Steps 6-7. */
/* Steps a (implicit), and d. */
for (var k = 0; k < len; k++) {
/* Step b */
if (k in O) {
/* Step c. */
%_CallFunction(T, O[k], k, O, callbackfn);
}
}
/* Step 8. */
return void 0;
}
function ArrayStaticForEach(list, callbackfn/*, thisArg*/) {
if (arguments.length < 2)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.forEach');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
var T = arguments.length > 2 ? arguments[2] : void 0;
%_CallFunction(list, callbackfn, T, ArrayForEach);
}
/* ES5 15.4.4.21. */
function ArrayReduce(callbackfn/*, initialValue*/) {
/* Step 1. */
var O = %ToObject(this);
/* Steps 2-3. */
var len = TO_UINT32(O.length);
/* Step 4. */
if (arguments.length === 0)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
/* Step 6. */
var k = 0;
/* Steps 5, 7-8. */
var accumulator;
if (arguments.length > 1) {
accumulator = arguments[1];
} else {
/* Step 5. */
if (len === 0)
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
var kPresent = false;
for (; k < len; k++) {
if (k in O) {
accumulator = O[k];
kPresent = true;
k++;
break;
}
}
if (!kPresent)
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
}
/* Step 9. */
/* Steps a (implicit), and d. */
for (; k < len; k++) {
/* Step b */
if (k in O) {
/* Step c. */
accumulator = callbackfn(accumulator, O[k], k, O);
}
}
/* Step 10. */
return accumulator;
}
function ArrayStaticReduce(list, callbackfn) {
if (arguments.length < 2)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduce');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
if (arguments.length > 2)
return %_CallFunction(list, callbackfn, arguments[2], ArrayReduce);
else
return %_CallFunction(list, callbackfn, ArrayReduce);
}
/* ES5 15.4.4.22. */
function ArrayReduceRight(callbackfn/*, initialValue*/) {
/* Step 1. */
var O = %ToObject(this);
/* Steps 2-3. */
var len = TO_UINT32(O.length);
/* Step 4. */
if (arguments.length === 0)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
/* Step 6. */
var k = len - 1;
/* Steps 5, 7-8. */
var accumulator;
if (arguments.length > 1) {
accumulator = arguments[1];
} else {
/* Step 5. */
if (len === 0)
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
var kPresent = false;
for (; k >= 0; k--) {
if (k in O) {
accumulator = O[k];
kPresent = true;
k--;
break;
}
}
if (!kPresent)
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
}
/* Step 9. */
/* Steps a (implicit), and d. */
for (; k >= 0; k--) {
/* Step b */
if (k in O) {
/* Step c. */
accumulator = callbackfn(accumulator, O[k], k, O);
}
}
/* Step 10. */
return accumulator;
}
function ArrayStaticReduceRight(list, callbackfn) {
if (arguments.length < 2)
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduceRight');
if (!IsCallable(callbackfn))
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
if (arguments.length > 2)
return %_CallFunction(list, callbackfn, arguments[2], ArrayReduceRight);
else
return %_CallFunction(list, callbackfn, ArrayReduceRight);
}

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

@ -85,7 +85,7 @@ GetBailedJSScript(JSContext *cx)
switch (GetCalleeTokenTag(frame->calleeToken())) {
case CalleeToken_Function: {
JSFunction *fun = CalleeTokenToFunction(frame->calleeToken());
return fun->script().get(nogc);
return fun->nonLazyScript().get(nogc);
}
case CalleeToken_Script:
return CalleeTokenToScript(frame->calleeToken());
@ -197,7 +197,7 @@ PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
const Value &calleeVal = regs.sp[-callerArgc - 2];
RootedFunction fun(cx, calleeVal.toObject().toFunction());
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
CallArgs inlineArgs = CallArgsFromSp(callerArgc, regs.sp);
// Bump the stack pointer to make it look like the inline args have been pushed, but they will

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

@ -311,7 +311,7 @@ CodeGenerator::visitLambda(LLambda *lir)
JS_STATIC_ASSERT(offsetof(JSFunction, flags) == offsetof(JSFunction, nargs) + 2);
masm.store32(Imm32(u.word), Address(output, offsetof(JSFunction, nargs)));
masm.storePtr(ImmGCPtr(fun->script().unsafeGet()),
masm.storePtr(ImmGCPtr(fun->nonLazyScript().unsafeGet()),
Address(output, JSFunction::offsetOfNativeOrScript()));
masm.storePtr(scopeChain, Address(output, JSFunction::offsetOfEnvironment()));
masm.storePtr(ImmGCPtr(fun->displayAtom()), Address(output, JSFunction::offsetOfAtom()));
@ -926,7 +926,7 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
// If the function is known to be uncompilable, only emit the call to InvokeFunction.
ExecutionMode executionMode = gen->info().executionMode();
RootedScript targetScript(cx, target->script());
RootedScript targetScript(cx, target->nonLazyScript());
if (GetIonScript(targetScript, executionMode) == ION_DISABLED_SCRIPT) {
if (!emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack))
return false;

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

@ -54,7 +54,7 @@ static inline bool CanIonCompile(JSContext *cx, HandleFunction fun, ExecutionMod
{
if (!fun->isInterpreted())
return false;
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
return CanIonCompile(script, cmode);
}

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

@ -1564,7 +1564,7 @@ ion::FastInvoke(JSContext *cx, HandleFunction fun, CallArgsList &args)
{
JS_CHECK_RECURSION(cx, return IonExec_Error);
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
IonScript *ion = script->ionScript();
IonCode *code = ion->method();
void *jitcode = code->raw();

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

@ -204,7 +204,7 @@ IonBuilder::canInlineTarget(JSFunction *target)
return false;
}
RootedScript inlineScript(cx, target->script());
RootedScript inlineScript(cx, target->nonLazyScript());
ExecutionMode executionMode = info().executionMode();
if (!CanIonCompile(inlineScript, executionMode)) {
IonSpew(IonSpew_Inlining, "Cannot inline due to disable Ion compilation");
@ -2835,7 +2835,7 @@ IonBuilder::jsop_call_inline(HandleFunction callee, uint32 argc, bool constructi
// Compilation information is allocated for the duration of the current tempLifoAlloc
// lifetime.
RootedScript calleeScript(cx, callee->script());
RootedScript calleeScript(cx, callee->nonLazyScript());
CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(calleeScript.get(), callee,
(jsbytecode *)NULL, constructing,
SequentialExecution);
@ -2930,7 +2930,7 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32 argc)
if (!target->isInterpreted())
return false;
script = target->script();
script = target->nonLazyScript();
uint32_t calleeUses = script->getUseCount();
if (target->nargs < argc) {
@ -3549,7 +3549,7 @@ IonBuilder::createThisScriptedSingleton(HandleFunction target, HandleObject prot
types::TypeObject *type = proto->getNewType(cx, target);
if (!type)
return NULL;
if (!types::TypeScript::ThisTypes(target->script().unsafeGet())->hasType(types::Type::ObjectType(type)))
if (!types::TypeScript::ThisTypes(target->nonLazyScript().unsafeGet())->hasType(types::Type::ObjectType(type)))
return NULL;
RootedObject templateObject(cx, js_CreateThisForFunctionWithProto(cx, target, proto));

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

@ -1624,7 +1624,7 @@ GenerateScopeChainGuard(MacroAssembler &masm, JSObject *scopeObj,
CallObject *callObj = &scopeObj->asCall();
if (!callObj->isForEval()) {
RawFunction fun = &callObj->callee();
RawScript script = fun->script().get(nogc);
RawScript script = fun->nonLazyScript().get(nogc);
if (!script->funHasExtensibleScope)
return;
}

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

@ -441,7 +441,7 @@ MarkIonJSFrame(JSTracer *trc, const IonFrameIterator &frame)
// is now NULL or recompiled). Manually trace it here.
IonScript::Trace(trc, ionScript);
} else if (CalleeTokenIsFunction(layout->calleeToken())) {
ionScript = CalleeTokenToFunction(layout->calleeToken())->script()->ion;
ionScript = CalleeTokenToFunction(layout->calleeToken())->nonLazyScript()->ion;
} else {
ionScript = CalleeTokenToScript(layout->calleeToken())->ion;
}
@ -926,7 +926,7 @@ InlineFrameIterator::findNextFrame()
si_.nextFrame();
callee_ = funval.toObject().toFunction();
script_ = callee_->script().get(nogc);
script_ = callee_->nonLazyScript().get(nogc);
pc_ = script_->code + si_.pcOffset();
}

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

@ -72,7 +72,7 @@ ScriptFromCalleeToken(CalleeToken token)
case CalleeToken_Script:
return CalleeTokenToScript(token);
case CalleeToken_Function:
return CalleeTokenToFunction(token)->script().get(nogc);
return CalleeTokenToFunction(token)->nonLazyScript().get(nogc);
}
JS_NOT_REACHED("invalid callee token tag");
return NULL;

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

@ -556,7 +556,7 @@ bool
TypeInferenceOracle::canEnterInlinedFunction(JSFunction *target)
{
AssertCanGC();
RootedScript script(cx, target->script());
RootedScript script(cx, target->nonLazyScript());
if (!script->hasAnalysis() || !script->analysis()->ranInference())
return false;

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

@ -41,8 +41,8 @@ static inline bool
ShouldMonitorReturnType(JSFunction *fun)
{
return fun->isInterpreted() &&
(!fun->script()->hasAnalysis() ||
!fun->script()->analysis()->ranInference());
(!fun->nonLazyScript()->hasAnalysis() ||
!fun->nonLazyScript()->analysis()->ranInference());
}
bool
@ -50,18 +50,16 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *
{
Value fval = ObjectValue(*fun);
if (fun->isInterpretedLazy()) {
Rooted<JSFunction*> rootedFun(cx, fun);
if (!InitializeLazyFunctionScript(cx, rootedFun))
return false;
}
// In order to prevent massive bouncing between Ion and JM, see if we keep
// hitting functions that are uncompilable.
if (fun->isInterpreted() && !fun->script()->canIonCompile()) {
if (fun->isInterpreted()) {
if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx).unsafeGet())
return false;
if (!fun->nonLazyScript()->canIonCompile()) {
JSScript *script = GetTopIonJSScript(cx);
if (script->hasIonScript() && ++script->ion->slowCallCount >= js_IonOptions.slowCallLimit) {
if (script->hasIonScript() &&
++script->ion->slowCallCount >= js_IonOptions.slowCallLimit)
{
AutoFlushCache afc("InvokeFunction");
// Poison the script so we don't try to run it again. This will
@ -69,6 +67,7 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *
ForbidCompilation(cx, script);
}
}
}
// TI will return false for monitorReturnTypes, meaning there is no
// TypeBarrier or Monitor instruction following this. However, we need to
@ -98,9 +97,9 @@ InvokeConstructor(JSContext *cx, JSObject *obj, uint32 argc, Value *argv, Value
bool needsMonitor;
if (obj->isFunction()) {
if (obj->toFunction()->isInterpretedLazy()) {
Rooted<JSFunction*> rootedFun(cx, obj->toFunction());
if (!InitializeLazyFunctionScript(cx, rootedFun))
if (obj->toFunction()->isInterpretedLazy() &&
!obj->toFunction()->getOrCreateScript(cx).unsafeGet())
{
return false;
}
needsMonitor = ShouldMonitorReturnType(obj->toFunction());

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

@ -4871,8 +4871,8 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobjArg, JSRawObject parentArg
* script, we cannot clone it without breaking the compiler's assumptions.
*/
RootedFunction fun(cx, funobj->toFunction());
if (fun->isInterpreted() && (fun->script()->enclosingStaticScope() ||
(fun->script()->compileAndGo && !parent->isGlobal())))
if (fun->isInterpreted() && (fun->nonLazyScript()->enclosingStaticScope() ||
(fun->nonLazyScript()->compileAndGo && !parent->isGlobal())))
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
return NULL;

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

@ -2938,228 +2938,6 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
return JS_TRUE;
}
enum IndexOfKind {
IndexOf,
LastIndexOf
};
static JSBool
array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
{
uint32_t length, i, stop;
int direction;
JSBool hole;
RootedValue tosearch(cx), elt(cx);
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return false;
if (!GetLengthProperty(cx, obj, &length))
return JS_FALSE;
if (length == 0)
goto not_found;
if (args.length() <= 1) {
i = (mode == LastIndexOf) ? length - 1 : 0;
tosearch = (args.length() != 0) ? args[0] : UndefinedValue();
} else {
double start;
tosearch = args[0];
if (!ToInteger(cx, args[1], &start))
return false;
if (start < 0) {
start += length;
if (start < 0) {
if (mode == LastIndexOf)
goto not_found;
i = 0;
} else {
i = (uint32_t)start;
}
} else if (start >= length) {
if (mode == IndexOf)
goto not_found;
i = length - 1;
} else {
i = (uint32_t)start;
}
}
if (mode == LastIndexOf) {
stop = 0;
direction = -1;
} else {
stop = length - 1;
direction = 1;
}
for (;;) {
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
!GetElement(cx, obj, (uint32_t)i, &hole, &elt)) {
return JS_FALSE;
}
if (!hole) {
bool equal;
if (!StrictlyEqual(cx, elt, tosearch, &equal))
return false;
if (equal) {
args.rval().setNumber(i);
return true;
}
}
if (i == stop)
goto not_found;
i += direction;
}
not_found:
args.rval().setInt32(-1);
return JS_TRUE;
}
static JSBool
array_indexOf(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return array_indexOfHelper(cx, IndexOf, args);
}
static JSBool
array_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return array_indexOfHelper(cx, LastIndexOf, args);
}
/* ECMA 15.4.4.16-15.4.4.18. */
class ArrayForEachBehavior
{
public:
static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval) { return false; }
static Value lateExitValue() { return UndefinedValue(); }
};
class ArrayEveryBehavior
{
public:
static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
{
if (!ToBoolean(callbackRval)) {
rval.setBoolean(false);
return true;
}
return false;
}
static Value lateExitValue() { return BooleanValue(true); }
};
class ArraySomeBehavior
{
public:
static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
{
if (ToBoolean(callbackRval)) {
rval.setBoolean(true);
return true;
}
return false;
}
static Value lateExitValue() { return BooleanValue(false); }
};
template <class Behavior>
static inline bool
array_readonlyCommon(JSContext *cx, CallArgs &args)
{
/* Step 1. */
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return false;
/* Step 2-3. */
uint32_t len;
if (!GetLengthProperty(cx, obj, &len))
return false;
/* Step 4. */
if (args.length() == 0) {
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedObject callable(cx, ValueToCallable(cx, &args[0]));
if (!callable)
return false;
/* Step 5. */
RootedValue thisv(cx, args.length() >= 2 ? args[1] : UndefinedValue());
/* Step 6. */
uint32_t k = 0;
/* Step 7. */
RootedValue kValue(cx);
FastInvokeGuard fig(cx, ObjectValue(*callable));
InvokeArgsGuard &ag = fig.args();
while (k < len) {
if (!JS_CHECK_OPERATION_LIMIT(cx))
return false;
/* Step a, b, and c.i. */
JSBool kNotPresent;
if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
return false;
/* Step c.ii-iii. */
if (!kNotPresent) {
if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag))
return false;
ag.setCallee(ObjectValue(*callable));
ag.setThis(thisv);
ag[0] = kValue;
ag[1] = NumberValue(k);
ag[2] = ObjectValue(*obj);
if (!fig.invoke(cx))
return false;
if (Behavior::shouldExit(ag.rval(), args.rval()))
return true;
}
/* Step d. */
k++;
}
/* Step 8. */
args.rval().set(Behavior::lateExitValue());
return true;
}
/* ES5 15.4.4.16. */
static JSBool
array_every(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return array_readonlyCommon<ArrayEveryBehavior>(cx, args);
}
/* ES5 15.4.4.17. */
static JSBool
array_some(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return array_readonlyCommon<ArraySomeBehavior>(cx, args);
}
/* ES5 15.4.4.18. */
static JSBool
array_forEach(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return array_readonlyCommon<ArrayForEachBehavior>(cx, args);
}
/* ES5 15.4.4.19. */
static JSBool
array_map(JSContext *cx, unsigned argc, Value *vp)
@ -3322,137 +3100,6 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
return true;
}
/* ES5 15.4.4.21-15.4.4.22. */
class ArrayReduceBehavior
{
public:
static void initialize(uint32_t len, uint32_t *start, uint32_t *end, int32_t *step)
{
*start = 0;
*step = 1;
*end = len;
}
};
class ArrayReduceRightBehavior
{
public:
static void initialize(uint32_t len, uint32_t *start, uint32_t *end, int32_t *step)
{
*start = len - 1;
*step = -1;
/*
* We rely on (well defined) unsigned integer underflow to check our
* end condition after visiting the full range (including 0).
*/
*end = UINT32_MAX;
}
};
template<class Behavior>
static inline bool
array_reduceCommon(JSContext *cx, CallArgs &args)
{
/* Step 1. */
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return false;
/* Step 2-3. */
uint32_t len;
if (!GetLengthProperty(cx, obj, &len))
return false;
/* Step 4. */
if (args.length() == 0) {
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedObject callable(cx, ValueToCallable(cx, &args[0]));
if (!callable)
return false;
/* Step 5. */
if (len == 0 && args.length() < 2) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_EMPTY_ARRAY_REDUCE);
return false;
}
/* Step 6. */
uint32_t k, end;
int32_t step;
Behavior::initialize(len, &k, &end, &step);
/* Step 7-8. */
RootedValue accumulator(cx);
if (args.length() >= 2) {
accumulator = args[1];
} else {
JSBool kNotPresent = true;
while (kNotPresent && k != end) {
if (!GetElement(cx, obj, k, &kNotPresent, &accumulator))
return false;
k += step;
}
if (kNotPresent) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_EMPTY_ARRAY_REDUCE);
return false;
}
}
/* Step 9. */
RootedValue kValue(cx);
FastInvokeGuard fig(cx, ObjectValue(*callable));
InvokeArgsGuard &ag = fig.args();
while (k != end) {
if (!JS_CHECK_OPERATION_LIMIT(cx))
return false;
/* Step a, b, and c.i. */
JSBool kNotPresent;
if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
return false;
/* Step c.ii. */
if (!kNotPresent) {
if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 4, &ag))
return false;
ag.setCallee(ObjectValue(*callable));
ag.setThis(UndefinedValue());
ag[0] = accumulator;
ag[1] = kValue;
ag[2] = NumberValue(k);
ag[3] = ObjectValue(*obj);
if (!fig.invoke(cx))
return false;
accumulator = ag.rval();
}
/* Step d. */
k += step;
}
/* Step 10. */
args.rval().set(accumulator);
return true;
}
/* ES5 15.4.4.21. */
static JSBool
array_reduce(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return array_reduceCommon<ArrayReduceBehavior>(cx, args);
}
/* ES5 15.4.4.22. */
static JSBool
array_reduceRight(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return array_reduceCommon<ArrayReduceRightBehavior>(cx, args);
}
static JSBool
array_isArray(JSContext *cx, unsigned argc, Value *vp)
{
@ -3485,15 +3132,15 @@ static JSFunctionSpec array_methods[] = {
JS_FN("concat", array_concat, 1,JSFUN_GENERIC_NATIVE),
JS_FN("slice", array_slice, 2,JSFUN_GENERIC_NATIVE),
JS_FN("indexOf", array_indexOf, 1,JSFUN_GENERIC_NATIVE),
JS_FN("lastIndexOf", array_lastIndexOf, 1,JSFUN_GENERIC_NATIVE),
JS_FN("forEach", array_forEach, 1,JSFUN_GENERIC_NATIVE),
{"lastIndexOf", {NULL, NULL}, 1,0, "ArrayLastIndexOf"},
{"indexOf", {NULL, NULL}, 1,0, "ArrayIndexOf"},
{"forEach", {NULL, NULL}, 1,0, "ArrayForEach"},
JS_FN("map", array_map, 1,JSFUN_GENERIC_NATIVE),
JS_FN("reduce", array_reduce, 1,JSFUN_GENERIC_NATIVE),
JS_FN("reduceRight", array_reduceRight, 1,JSFUN_GENERIC_NATIVE),
{"reduce", {NULL, NULL}, 1,0, "ArrayReduce"},
{"reduceRight", {NULL, NULL}, 1,0, "ArrayReduceRight"},
JS_FN("filter", array_filter, 1,JSFUN_GENERIC_NATIVE),
JS_FN("some", array_some, 1,JSFUN_GENERIC_NATIVE),
JS_FN("every", array_every, 1,JSFUN_GENERIC_NATIVE),
{"some", {NULL, NULL}, 1,0, "ArraySome"},
{"every", {NULL, NULL}, 1,0, "ArrayEvery"},
JS_FN("iterator", JS_ArrayIterator, 0,0),
JS_FS_END
@ -3501,6 +3148,13 @@ static JSFunctionSpec array_methods[] = {
static JSFunctionSpec array_static_methods[] = {
JS_FN("isArray", array_isArray, 1,0),
{"lastIndexOf", {NULL, NULL}, 2,0, "ArrayStaticLastIndexOf"},
{"indexOf", {NULL, NULL}, 2,0, "ArrayStaticIndexOf"},
{"forEach", {NULL, NULL}, 2,0, "ArrayStaticForEach"},
{"every", {NULL, NULL}, 2,0, "ArrayStaticEvery"},
{"some", {NULL, NULL}, 2,0, "ArrayStaticSome"},
{"reduce", {NULL, NULL}, 2,0, "ArrayStaticReduce"},
{"reduceRight", {NULL, NULL}, 2,0, "ArrayStaticReduceRight"},
JS_FS_END
};

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

@ -431,7 +431,7 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, Handle<PropertyName*> na
return false;
RootedFunction sourceFun(cx, funVal.toObject().toFunction());
Rooted<JSScript*> sourceScript(cx, sourceFun->script());
Rooted<JSScript*> sourceScript(cx, sourceFun->nonLazyScript());
JS_ASSERT(!sourceScript->enclosingStaticScope());
RawScript cscript = CloneScript(cx, NullPtr(), targetFun, sourceScript);
if (!cscript)

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

@ -401,13 +401,13 @@ JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
JS_PUBLIC_API(JSBool)
JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun)
{
return fun->script()->bindings.count() > 0;
return fun->nonLazyScript()->bindings.count() > 0;
}
extern JS_PUBLIC_API(uintptr_t *)
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
{
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
BindingVector bindings(cx);
if (!FillBindingVector(script, &bindings))
return NULL;
@ -449,7 +449,7 @@ JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
{
AutoAssertNoGC nogc;
return fun->maybeScript().get(nogc);
return fun->maybeNonLazyScript().get(nogc);
}
JS_PUBLIC_API(JSNative)
@ -1013,7 +1013,7 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
size_t nbytes = sizeof *fun;
nbytes += JS_GetObjectTotalSize(cx, fun);
if (fun->isInterpreted())
nbytes += JS_GetScriptTotalSize(cx, fun->script().get(nogc));
nbytes += JS_GetScriptTotalSize(cx, fun->nonLazyScript().get(nogc));
if (fun->displayAtom())
nbytes += GetAtomTotalSize(cx, fun->displayAtom());
return nbytes;

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

@ -368,7 +368,7 @@ js::IsObjectInContextCompartment(RawObject obj, const JSContext *cx)
JS_FRIEND_API(bool)
js::IsOriginalScriptFunction(JSFunction *fun)
{
return fun->script()->function() == fun;
return fun->nonLazyScript()->function() == fun;
}
JS_FRIEND_API(JSScript *)
@ -382,7 +382,7 @@ js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext *cx)
return NULL;
JSFunction *scriptedCaller = fp->fun();
RootedScript outermost(cx, scriptedCaller->script());
RootedScript outermost(cx, scriptedCaller->nonLazyScript());
for (StaticScopeIter i(scriptedCaller); !i.done(); i++) {
if (i.type() == StaticScopeIter::FUNCTION)
outermost = i.funScript();

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

@ -91,7 +91,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
* check any calls that were inlined.
*/
if (fun->isInterpreted()) {
fun->script()->uninlineable = true;
fun->getOrCreateScript(cx)->uninlineable = true;
MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
}
@ -156,7 +156,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
if (inlined) {
mjit::JITChunk *chunk = fp->prev()->jit()->chunk(prevpc);
RawFunction fun = chunk->inlineFrames()[inlined->inlineIndex].fun;
fun->script()->uninlineable = true;
fun->nonLazyScript()->uninlineable = true;
MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
}
}
@ -321,7 +321,7 @@ fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
RootedValue v(cx);
if (JSID_IS_ATOM(id, cx->names().length)) {
//FIXME: bug 810715 - deal with lazy interpreted functions with default args
uint16_t defaults = fun->hasScript() ? fun->script()->ndefaults : 0;
uint16_t defaults = fun->hasScript() ? fun->nonLazyScript()->ndefaults : 0;
v.setInt32(fun->nargs - defaults - fun->hasRest());
} else {
v.setString(fun->atom() == NULL ? cx->runtime->emptyString : fun->atom());
@ -344,7 +344,7 @@ fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
PropertyOp getter;
StrictPropertyOp setter;
unsigned attrs = JSPROP_PERMANENT;
if (fun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, fun))
if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx).unsafeGet())
return false;
if (fun->isInterpreted() ? fun->inStrictMode() : fun->isBoundFunction()) {
JSObject *throwTypeError = fun->global().getThrowTypeError();
@ -398,7 +398,7 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
firstword = !!fun->atom();
flagsword = (fun->nargs << 16) | fun->flags;
atom = fun->atom();
script = fun->script();
script = fun->nonLazyScript();
} else {
fun = js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr());
if (!fun)
@ -425,8 +425,8 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
script->setFunction(fun);
if (!JSFunction::setTypeForScriptedFunction(cx, fun))
return false;
JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
RootedScript script(cx, fun->script());
JS_ASSERT(fun->nargs == fun->nonLazyScript()->bindings.numArgs());
RootedScript script(cx, fun->nonLazyScript());
js_CallNewScriptHook(cx, script, fun);
objp.set(fun);
}
@ -452,7 +452,7 @@ js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleF
if (!clone)
return NULL;
RootedScript srcScript(cx, srcFun->script());
RootedScript srcScript(cx, srcFun->nonLazyScript());
RawScript clonedScript = CloneScript(cx, enclosingScope, clone, srcScript);
if (!clonedScript)
return NULL;
@ -465,25 +465,11 @@ js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleF
if (!JSFunction::setTypeForScriptedFunction(cx, clone))
return NULL;
RootedScript cloneScript(cx, clone->script());
RootedScript cloneScript(cx, clone->nonLazyScript());
js_CallNewScriptHook(cx, cloneScript, clone);
return clone;
}
bool
js::InitializeLazyFunctionScript(JSContext *cx, HandleFunction fun)
{
JS_ASSERT(fun->isInterpretedLazy());
JSFunctionSpec *fs = static_cast<JSFunctionSpec *>(fun->getExtendedSlot(0).toPrivate());
RootedAtom funAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
if (!funAtom)
return false;
Rooted<PropertyName *> funName(cx, funAtom->asPropertyName());
if (!cx->runtime->cloneSelfHostedFunctionScript(cx, funName, fun))
return false;
return true;
}
/*
* [[HasInstance]] internal method for Function objects: fetch the .prototype
* property of its 'this' parameter, and walks the prototype chain of v (only
@ -575,7 +561,7 @@ FindBody(JSContext *cx, HandleFunction fun, StableCharPtr chars, size_t length,
// We don't need principals, since those are only used for error reporting.
CompileOptions options(cx);
options.setFileAndLine("internal-findBody", 0)
.setVersion(fun->script()->getVersion());
.setVersion(fun->nonLazyScript()->getVersion());
TokenStream ts(cx, options, chars, length, NULL);
JS_ASSERT(chars[0] == '(');
int nest = 0;
@ -626,7 +612,7 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
RootedScript script(cx);
if (fun->hasScript()) {
script = fun->script();
script = fun->nonLazyScript();
if (script->isGeneratorExp) {
if ((!bodyOnly && !out.append("function genexp() {")) ||
!out.append("\n [generator expression]\n") ||
@ -1057,6 +1043,19 @@ JSFunction::getBoundFunctionArgumentCount() const
return getSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT).toPrivateUint32();
}
bool
JSFunction::initializeLazyScript(JSContext *cx)
{
JS_ASSERT(isInterpretedLazy());
JSFunctionSpec *fs = static_cast<JSFunctionSpec *>(getExtendedSlot(0).toPrivate());
RootedAtom funAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
if (!funAtom)
return false;
Rooted<PropertyName *> funName(cx, funAtom->asPropertyName());
Rooted<JSFunction*> self(cx, this);
return cx->runtime->cloneSelfHostedFunctionScript(cx, funName, self);
}
/* ES5 15.3.4.5.1 and 15.3.4.5.2. */
JSBool
js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp)
@ -1116,7 +1115,7 @@ fun_isGenerator(JSContext *cx, unsigned argc, Value *vp)
bool result = false;
if (fun->hasScript()) {
RawScript script = fun->script().get(nogc);
RawScript script = fun->nonLazyScript().get(nogc);
JS_ASSERT(script->length != 0);
result = script->isGenerator;
}
@ -1484,7 +1483,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
clone->nargs = fun->nargs;
clone->flags = fun->flags & ~JSFunction::EXTENDED;
if (fun->isInterpreted()) {
clone->initScript(fun->script().unsafeGet());
clone->initScript(fun->nonLazyScript().unsafeGet());
clone->initEnvironment(parent);
} else {
clone->initNative(fun->native(), fun->jitInfo());
@ -1517,7 +1516,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
* no enclosing lexical scope (only the global scope).
*/
if (clone->isInterpreted()) {
RootedScript script(cx, clone->script());
RootedScript script(cx, clone->nonLazyScript());
JS_ASSERT(script->compartment() == fun->compartment());
JS_ASSERT_IF(script->compartment() != cx->compartment,
!script->enclosingStaticScope());
@ -1535,7 +1534,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
GlobalObject *global = script->compileAndGo ? &script->global() : NULL;
script = clone->script();
script = clone->nonLazyScript();
js_CallNewScriptHook(cx, script, clone);
Debugger::onNewScript(cx, script, global);
}

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

@ -73,6 +73,8 @@ struct JSFunction : public JSObject
} u;
private:
js::HeapPtrAtom atom_; /* name for diagnostics and decompiling */
bool initializeLazyScript(JSContext *cx);
public:
/* A function can be classified as either native (C++) or interpreted (JS): */
@ -176,11 +178,36 @@ struct JSFunction : public JSObject
static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); }
static inline size_t offsetOfAtom() { return offsetof(JSFunction, atom_); }
js::Return<JSScript*> script() const {
js::Return<JSScript*> getOrCreateScript(JSContext *cx) {
JS_ASSERT(isInterpreted());
if (isInterpretedLazy()) {
js::RootedFunction self(cx, this);
js::MaybeCheckStackRoots(cx);
if (!initializeLazyScript(cx))
return js::NullPtr();
}
JS_ASSERT(hasScript());
return JS::HandleScript::fromMarkedLocation(&u.i.script_);
}
bool maybeGetOrCreateScript(JSContext *cx, js::MutableHandle<JSScript*> script) {
if (isNative()) {
script.set(NULL);
return true;
}
script.set(getOrCreateScript(cx).unsafeGet());
return hasScript();
}
js::Return<JSScript*> nonLazyScript() const {
JS_ASSERT(hasScript());
return JS::HandleScript::fromMarkedLocation(&u.i.script_);
}
js::Return<JSScript*> maybeNonLazyScript() const {
return isInterpreted() ? nonLazyScript() : JS::NullPtr();
}
js::HeapPtrScript &mutableScript() {
JS_ASSERT(isInterpreted());
return *(js::HeapPtrScript *)&u.i.script_;
@ -189,10 +216,6 @@ struct JSFunction : public JSObject
inline void setScript(JSScript *script_);
inline void initScript(JSScript *script_);
js::Return<JSScript*> maybeScript() const {
return isInterpreted() ? script() : JS::NullPtr();
}
JSNative native() const {
JS_ASSERT(isNative());
return u.n.native;
@ -344,9 +367,6 @@ XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
extern JSObject *
CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
bool
InitializeLazyFunctionScript(JSContext *cx, HandleFunction fun);
/*
* Report an error that call.thisv is not compatible with the specified class,
* assuming that the method (clasp->name).prototype.<name of callee function>

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

@ -19,7 +19,7 @@
inline bool
JSFunction::inStrictMode() const
{
return script()->strictModeCode;
return nonLazyScript()->strictModeCode;
}
inline void

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

@ -1320,13 +1320,9 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, Type type)
return;
}
if (callee->isInterpretedLazy()) {
RootedFunction fun(cx, callee);
if (!InitializeLazyFunctionScript(cx, fun))
RootedScript calleeScript(cx, callee->getOrCreateScript(cx));
if (!calleeScript)
return;
}
RootedScript calleeScript(cx, callee->script());
if (!calleeScript->ensureHasTypes(cx))
return;
@ -1403,16 +1399,10 @@ TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, Type type)
return;
}
if (callee->isInterpretedLazy()) {
RootedFunction fun(cx, callee);
if (!InitializeLazyFunctionScript(cx, fun))
return;
}
if (!callee->script()->ensureHasTypes(cx))
if (!(callee->getOrCreateScript(cx).unsafeGet() && callee->nonLazyScript()->ensureHasTypes(cx)))
return;
TypeSet *thisTypes = TypeScript::ThisTypes(callee->script().unsafeGet());
TypeSet *thisTypes = TypeScript::ThisTypes(callee->nonLazyScript().unsafeGet());
if (this->types)
this->types->addSubset(cx, thisTypes);
else
@ -3396,7 +3386,7 @@ TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
if (singleton) {
/* Make sure flags are consistent with persistent object state. */
JS_ASSERT_IF(flags & OBJECT_FLAG_UNINLINEABLE,
interpretedFunction->script()->uninlineable);
interpretedFunction->nonLazyScript()->uninlineable);
JS_ASSERT_IF(flags & OBJECT_FLAG_ITERATED,
singleton->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON));
}
@ -4636,7 +4626,7 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun,
return false;
}
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
if (!script->ensureRanAnalysis(cx) || !script->ensureRanInference(cx)) {
pbaseobj.set(NULL);
cx->compartment->types.setPendingNukeTypes(cx);
@ -4774,7 +4764,7 @@ AnalyzePoppedThis(JSContext *cx, Vector<SSAUseChain *> *pendingPoppedThis,
TypeObject *type, JSFunction *fun, MutableHandleObject pbaseobj,
Vector<TypeNewScript::Initializer> *initializerList)
{
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
ScriptAnalysis *analysis = script->analysis();
while (!pendingPoppedThis->empty()) {
@ -5219,7 +5209,7 @@ types::TypeMonitorCallSlow(JSContext *cx, HandleObject callee, const CallArgs &a
bool constructing)
{
unsigned nargs = callee->toFunction()->nargs;
RootedScript script(cx, callee->toFunction()->script());
RootedScript script(cx, callee->toFunction()->nonLazyScript());
if (!constructing)
TypeScript::SetThis(cx, script, args.thisv());
@ -5545,8 +5535,8 @@ JSScript::makeAnalysis(JSContext *cx)
/* static */ bool
JSFunction::setTypeForScriptedFunction(JSContext *cx, HandleFunction fun, bool singleton)
{
JS_ASSERT(fun->script().unsafeGet());
JS_ASSERT(fun->script()->function() == fun);
JS_ASSERT(fun->nonLazyScript().unsafeGet());
JS_ASSERT(fun->nonLazyScript()->function() == fun);
if (!cx->typeInferenceEnabled())
return true;
@ -5696,8 +5686,7 @@ JSObject::makeLazyType(JSContext *cx)
RootedObject self(cx, this);
/* De-lazification of functions can GC, so we need to do it up here. */
if (self->isFunction() && self->toFunction()->isInterpretedLazy()) {
RootedFunction fun(cx, self->toFunction());
if (!InitializeLazyFunctionScript(cx, fun))
if (!self->toFunction()->getOrCreateScript(cx).unsafeGet())
return NULL;
}
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(getClass());
@ -5724,7 +5713,7 @@ JSObject::makeLazyType(JSContext *cx)
if (self->isFunction() && self->toFunction()->isInterpreted()) {
type->interpretedFunction = self->toFunction();
if (type->interpretedFunction->script()->uninlineable)
if (type->interpretedFunction->nonLazyScript()->uninlineable)
type->flags |= OBJECT_FLAG_UNINLINEABLE;
}

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

@ -532,7 +532,7 @@ TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
if (callee->isFunction()) {
JSFunction *fun = callee->toFunction();
if (fun->isInterpreted()) {
js::RootedScript script(cx, fun->script());
js::RootedScript script(cx, fun->nonLazyScript());
if (!script->ensureRanAnalysis(cx))
return false;
if (cx->typeInferenceEnabled())
@ -703,7 +703,7 @@ UseNewTypeForClone(JSFunction *fun)
* instance a singleton type and clone the underlying script.
*/
RawScript script = fun->script().get(nogc);
RawScript script = fun->nonLazyScript().get(nogc);
if (script->length >= 50)
return false;

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

@ -368,7 +368,8 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
if (fun->isNative())
return CallJSNative(cx, fun->native(), args);
if (fun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, fun))
RootedScript script(cx, fun->getOrCreateScript(cx));
if (!script)
return false;
if (!TypeMonitorCall(cx, args, construct))
@ -380,7 +381,6 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
return false;
/* Run function until JSOP_STOP, JSOP_RETURN or error. */
RootedScript script(cx, fun->script());
JSBool ok = RunScript(cx, script, ifg.fp());
/* Propagate the return value out. */
@ -2346,9 +2346,9 @@ BEGIN_CASE(JSOP_FUNCALL)
InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
if (fun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, fun))
RawScript funScript = fun->getOrCreateScript(cx).unsafeGet();
if (!funScript)
goto error;
RawScript funScript = fun->script().unsafeGet();
if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, funScript, initial))
goto error;

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

@ -1021,7 +1021,7 @@ class FastInvokeGuard
JSFunction *fun = fval.toObject().toFunction();
if (fun->hasScript()) {
fun_ = fun;
script_ = fun->script();
script_ = fun->nonLazyScript();
}
}
}
@ -1033,7 +1033,7 @@ class FastInvokeGuard
bool invoke(JSContext *cx) {
#ifdef JS_ION
if (useIon_ && fun_) {
JS_ASSERT(fun_->script() == script_);
JS_ASSERT(fun_->nonLazyScript() == script_);
ion::MethodStatus status = ion::CanEnterUsingFastInvoke(cx, script_, args_.length());
if (status == ion::Method_Error)

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

@ -2366,7 +2366,7 @@ js_CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *
}
if (res && cx->typeInferenceEnabled()) {
RootedScript script(cx, callee->toFunction()->script());
RootedScript script(cx, callee->toFunction()->nonLazyScript());
TypeScript::SetThis(cx, script, types::Type::ObjectType(res));
}
@ -2397,7 +2397,7 @@ js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
if (!JSObject::setSingletonType(cx, nobj))
return NULL;
RootedScript calleeScript(cx, callee->toFunction()->script());
RootedScript calleeScript(cx, callee->toFunction()->nonLazyScript());
TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(nobj));
return nobj;
@ -5240,7 +5240,7 @@ dumpValue(const Value &v)
fputs("<unnamed function", stderr);
}
if (fun->hasScript()) {
JSScript *script = fun->script().get(nogc);
JSScript *script = fun->nonLazyScript().get(nogc);
fprintf(stderr, " (%s:%u)",
script->filename ? script->filename : "", script->lineno);
}

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

@ -1129,7 +1129,7 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun,
jp->localNames = NULL;
jp->decompiledOpcodes = NULL;
if (fun && fun->hasScript()) {
if (!SetPrinterLocalNames(cx, fun->script().unsafeGet(), jp)) {
if (!SetPrinterLocalNames(cx, fun->nonLazyScript().unsafeGet(), jp)) {
js_DestroyPrinter(jp);
return NULL;
}
@ -1785,7 +1785,7 @@ GetArgOrVarAtom(JSPrinter *jp, unsigned slot)
{
LOCAL_ASSERT_RV(jp->fun, NULL);
LOCAL_ASSERT_RV(slot < jp->script->bindings.count(), NULL);
LOCAL_ASSERT_RV(jp->script == jp->fun->script().unsafeGet(), NULL);
LOCAL_ASSERT_RV(jp->script == jp->fun->nonLazyScript().unsafeGet(), NULL);
JSAtom *name = (*jp->localNames)[slot].name();
#if !JS_HAS_DESTRUCTURING
LOCAL_ASSERT_RV(name, NULL);
@ -4744,10 +4744,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb)
*/
LifoAllocScope las(&cx->tempLifoAlloc());
outerLocalNames = jp->localNames;
if (!SetPrinterLocalNames(cx, fun->script().unsafeGet(), jp))
if (!SetPrinterLocalNames(cx, fun->nonLazyScript().unsafeGet(), jp))
return NULL;
inner = fun->script().unsafeGet();
inner = fun->nonLazyScript().unsafeGet();
if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner))) {
js_delete(jp->localNames);
jp->localNames = outerLocalNames;
@ -5618,7 +5618,7 @@ js_DecompileFunctionBody(JSPrinter *jp)
return JS_TRUE;
}
script = jp->fun->script().unsafeGet();
script = jp->fun->nonLazyScript().unsafeGet();
return DecompileBody(jp, script, script->code);
}
@ -5655,7 +5655,7 @@ js_DecompileFunction(JSPrinter *jp)
jp->indent -= 4;
js_printf(jp, "\t}");
} else {
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
#if JS_HAS_DESTRUCTURING
SprintStack ss(cx);
#endif

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

@ -665,7 +665,7 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
/* Code the nested function's enclosing scope. */
uint32_t funEnclosingScopeIndex = 0;
if (mode == XDR_ENCODE) {
StaticScopeIter ssi((*objp)->toFunction()->script()->enclosingStaticScope());
StaticScopeIter ssi((*objp)->toFunction()->nonLazyScript()->enclosingStaticScope());
if (ssi.done() || ssi.type() == StaticScopeIter::FUNCTION) {
JS_ASSERT(ssi.done() == !fun);
funEnclosingScopeIndex = UINT32_MAX;
@ -1872,7 +1872,7 @@ JSScript::enclosingScriptsCompiledSuccessfully() const
RawFunction fun = enclosing->toFunction();
if (!fun->hasScript())
return false;
enclosing = fun->script()->enclosingScope_;
enclosing = fun->nonLazyScript()->enclosingScope_;
} else {
enclosing = enclosing->asStaticBlock().enclosingStaticScope();
}
@ -2212,7 +2212,7 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
} else if (obj->isFunction()) {
RootedFunction innerFun(cx, obj->toFunction());
StaticScopeIter ssi(innerFun->script()->enclosingStaticScope());
StaticScopeIter ssi(innerFun->nonLazyScript()->enclosingStaticScope());
RootedObject enclosingScope(cx);
if (!ssi.done() && ssi.type() == StaticScopeIter::BLOCK)
enclosingScope = objects[FindBlockIndex(src, ssi.block())];

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

@ -2369,7 +2369,7 @@ LambdaIsGetElem(JSObject &lambda)
if (!fun->hasScript())
return NULL;
RawScript script = fun->script().get(nogc);
RawScript script = fun->nonLazyScript().get(nogc);
jsbytecode *pc = script->code;
/*

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

@ -295,7 +295,7 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
okay = false;
break;
}
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
/*
* Don't inline calls to scripts which haven't been analyzed.
@ -394,7 +394,7 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
continue;
JSFunction *fun = obj->toFunction();
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
CompileStatus status = addInlineFrame(script, nextDepth, index, pc);
if (status != Compile_Okay)

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

@ -200,7 +200,7 @@ stubs::FixupArity(VMFrame &f, uint32_t nactual)
*/
InitialFrameFlags initial = oldfp->initialFlags();
RootedFunction fun(cx, oldfp->fun());
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
void *ncode = oldfp->nativeReturnAddress();
/* Pop the inline frame. */
@ -285,11 +285,10 @@ UncachedInlineCall(VMFrame &f, InitialFrameFlags initial,
CallArgs args = CallArgsFromSp(argc, f.regs.sp);
RootedFunction newfun(cx, args.callee().toFunction());
if (newfun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, newfun))
RootedScript newscript(cx, newfun->getOrCreateScript(cx));
if (!newscript)
return false;
RootedScript newscript(cx, newfun->script());
bool construct = InitialFrameFlagsAreConstructing(initial);
RootedScript fscript(cx, f.script());

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

@ -1069,7 +1069,7 @@ VMFrame::script()
{
AutoAssertNoGC nogc;
if (regs.inlined())
return chunk()->inlineFrames()[regs.inlined()->inlineIndex].fun->script();
return chunk()->inlineFrames()[regs.inlined()->inlineIndex].fun->nonLazyScript();
return fp()->script();
}

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

@ -1001,7 +1001,7 @@ class CallCompiler : public BaseCompiler
/* Guard that it's the same script. */
Address scriptAddr(ic.funObjReg, JSFunction::offsetOfNativeOrScript());
Jump funGuard = masm.branchPtr(Assembler::NotEqual, scriptAddr,
ImmPtr(obj->toFunction()->script().get(nogc)));
ImmPtr(obj->toFunction()->nonLazyScript().get(nogc)));
Jump done = masm.jump();
LinkerHelper linker(masm, JSC::JAEGER_CODE);
@ -1250,7 +1250,7 @@ class CallCompiler : public BaseCompiler
!ic.hasIonStub() &&
ic.frameSize.isStatic() &&
ic.frameSize.staticArgc() <= ion::SNAPSHOT_MAX_NARGS &&
fun->hasScript() && fun->script()->hasIonScript())
fun->hasScript() && fun->nonLazyScript()->hasIonScript())
{
if (!generateIonStub())
THROWV(NULL);
@ -1261,7 +1261,7 @@ class CallCompiler : public BaseCompiler
AutoAssertNoGC nogc;
JS_ASSERT(fun);
JSScript *script = fun->script().get(nogc);
JSScript *script = fun->nonLazyScript().get(nogc);
JS_ASSERT(script);
uint32_t flags = callingNew ? StackFrame::CONSTRUCTING : 0;
@ -1280,7 +1280,8 @@ class CallCompiler : public BaseCompiler
} else if (ic.fastGuardedObject &&
!ic.hasJsFunCheck &&
!ic.fastGuardedNative &&
ic.fastGuardedObject->toFunction()->script() == fun->script()) {
ic.fastGuardedObject->toFunction()->nonLazyScript() == fun->nonLazyScript())
{
/*
* Note: Multiple "function guard" stubs are not yet
* supported, thus the fastGuardedNative check.
@ -1432,7 +1433,7 @@ ic::GenerateArgumentCheckStub(VMFrame &f)
JITScript *jit = f.jit();
StackFrame *fp = f.fp();
JSFunction *fun = fp->fun();
JSScript *script = fun->script().get(nogc);
JSScript *script = fun->nonLazyScript().get(nogc);
if (jit->argsCheckPool)
jit->resetArgsCheck();

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

@ -2217,7 +2217,7 @@ frameCountersOffset(VMFrame &f)
uint32_t index = cx->regs().inlined()->inlineIndex;
InlineFrame *frames = f.chunk()->inlineFrames();
for (unsigned i = 0; i < index; i++)
offset += frames[i].fun->script()->length;
offset += frames[i].fun->nonLazyScript()->length;
}
jsbytecode *pc;

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

@ -250,7 +250,7 @@ Recompiler::expandInlineFrames(JSCompartment *compartment,
uint8_t* codeStart = (uint8_t *)chunk->code.m_code.executableAddress();
InlineFrame *inner = &chunk->inlineFrames()[inlined->inlineIndex];
jsbytecode *innerpc = inner->fun->script()->code + inlined->pcOffset;
jsbytecode *innerpc = inner->fun->nonLazyScript()->code + inlined->pcOffset;
StackFrame *innerfp = expandInlineFrameChain(fp, inner);

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

@ -1623,7 +1623,7 @@ stubs::CheckArgumentTypes(VMFrame &f)
{
StackFrame *fp = f.fp();
JSFunction *fun = fp->fun();
RootedScript fscript(f.cx, fun->script());
RootedScript fscript(f.cx, fun->nonLazyScript());
RecompilationMonitor monitor(f.cx);
{
@ -1651,7 +1651,7 @@ stubs::AssertArgumentTypes(VMFrame &f)
AutoAssertNoGC nogc;
StackFrame *fp = f.fp();
JSFunction *fun = fp->fun();
RawScript script = fun->script().get(nogc);
RawScript script = fun->nonLazyScript().get(nogc);
/*
* Don't check the type of 'this' for constructor frames, the 'this' value

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

@ -301,6 +301,143 @@ GetLine(FILE *file, const char * prompt)
return NULL;
}
static size_t
GetDeflatedUTF8StringLength(JSContext *cx, const jschar *chars,
size_t nchars)
{
size_t nbytes;
const jschar *end;
unsigned c, c2;
nbytes = nchars;
for (end = chars + nchars; chars != end; chars++) {
c = *chars;
if (c < 0x80)
continue;
if (0xD800 <= c && c <= 0xDFFF) {
/* nbytes sets 1 length since this is surrogate pair. */
if (c >= 0xDC00 || (chars + 1) == end) {
nbytes += 2; /* Bad Surrogate */
continue;
}
c2 = chars[1];
if (c2 < 0xDC00 || c2 > 0xDFFF) {
nbytes += 2; /* Bad Surrogate */
continue;
}
c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
nbytes--;
chars++;
}
c >>= 11;
nbytes++;
while (c) {
c >>= 5;
nbytes++;
}
}
return nbytes;
}
static bool
PutUTF8ReplacementCharacter(char **dst, size_t *dstlenp) {
if (*dstlenp < 3)
return false;
*(*dst)++ = (char) 0xEF;
*(*dst)++ = (char) 0xBF;
*(*dst)++ = (char) 0xBD;
*dstlenp -= 3;
return true;
}
/*
* Write up to |*dstlenp| bytes into |dst|. Writes the number of bytes used
* into |*dstlenp| on success. Returns false on failure.
*/
static bool
DeflateStringToUTF8Buffer(JSContext *cx, const jschar *src, size_t srclen,
char *dst, size_t *dstlenp)
{
size_t dstlen = *dstlenp;
size_t origDstlen = dstlen;
while (srclen) {
uint32_t v;
jschar c = *src++;
srclen--;
if (c >= 0xDC00 && c <= 0xDFFF) {
if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
goto bufferTooSmall;
continue;
} else if (c < 0xD800 || c > 0xDBFF) {
v = c;
} else {
if (srclen < 1) {
if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
goto bufferTooSmall;
continue;
}
jschar c2 = *src;
if ((c2 < 0xDC00) || (c2 > 0xDFFF)) {
if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
goto bufferTooSmall;
continue;
}
src++;
srclen--;
v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
}
size_t utf8Len;
if (v < 0x0080) {
/* no encoding necessary - performance hack */
if (dstlen == 0)
goto bufferTooSmall;
*dst++ = (char) v;
utf8Len = 1;
} else {
uint8_t utf8buf[4];
utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
if (utf8Len > dstlen)
goto bufferTooSmall;
for (size_t i = 0; i < utf8Len; i++)
*dst++ = (char) utf8buf[i];
}
dstlen -= utf8Len;
}
*dstlenp = (origDstlen - dstlen);
return true;
bufferTooSmall:
*dstlenp = (origDstlen - dstlen);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BUFFER_TOO_SMALL);
return false;
}
static char *
JSStringToUTF8(JSContext *cx, JSString *str)
{
JSLinearString *linear = str->ensureLinear(cx);
if (!linear)
return NULL;
const jschar *chars = linear->chars();
size_t length = linear->length();
size_t tgtlen = GetDeflatedUTF8StringLength(cx, chars, length);
char *utf8chars = cx->pod_malloc<char>(tgtlen + 1);
if (!utf8chars)
return NULL;
bool ok = DeflateStringToUTF8Buffer(cx, chars, length, utf8chars, &tgtlen);
if (!ok) {
JS_free(cx, utf8chars);
return NULL;
}
utf8chars[tgtlen] = 0;
return utf8chars;
}
/*
* State to store as JSContext private.
*
@ -545,10 +682,12 @@ Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY)
str = JS_ValueToSource(cx, result);
ok = !!str;
if (ok) {
JSAutoByteString bytes(cx, str);
ok = !!bytes;
if (ok)
fprintf(gOutFile, "%s\n", bytes.ptr());
char *utf8chars = JSStringToUTF8(cx, str);
ok = !!utf8chars;
if (ok) {
fprintf(gOutFile, "%s\n", utf8chars);
JS_free(cx, utf8chars);
}
}
}
}
@ -1164,7 +1303,7 @@ PutStr(JSContext *cx, unsigned argc, jsval *vp)
str = JS_ValueToString(cx, argv[0]);
if (!str)
return false;
bytes = JS_EncodeString(cx, str);
bytes = JSStringToUTF8(cx, str);
if (!bytes)
return false;
fputs(bytes, gOutFile);
@ -1197,7 +1336,7 @@ PrintInternal(JSContext *cx, unsigned argc, jsval *vp, FILE *file)
str = JS_ValueToString(cx, argv[i]);
if (!str)
return false;
bytes = JS_EncodeString(cx, str);
bytes = JSStringToUTF8(cx, str);
if (!bytes)
return false;
fprintf(file, "%s%s", i ? " " : "", bytes);
@ -1317,7 +1456,8 @@ ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL)
if (!fun)
return NULL;
RootedScript script(cx, fun->maybeScript());
RootedScript script(cx);
fun->maybeGetOrCreateScript(cx, &script);
if (!script)
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_SCRIPTS_ONLY);
@ -1785,8 +1925,9 @@ DisassembleScript(JSContext *cx, JSScript *script_, JSFunction *fun, bool lines,
if (obj->isFunction()) {
Sprint(sp, "\n");
RawFunction fun = obj->toFunction();
RawScript nested = fun->maybeScript().unsafeGet();
if (!DisassembleScript(cx, nested, fun, lines, recursive, sp))
RootedScript script(cx);
fun->maybeGetOrCreateScript(cx, &script);
if (!DisassembleScript(cx, script.get(), fun, lines, recursive, sp))
return false;
}
}
@ -2212,7 +2353,7 @@ Clone(JSContext *cx, unsigned argc, jsval *vp)
}
if (funobj->compartment() != cx->compartment) {
JSFunction *fun = funobj->toFunction();
if (fun->hasScript() && fun->script()->compileAndGo) {
if (fun->hasScript() && fun->nonLazyScript()->compileAndGo) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
"function", "compile-and-go");
return false;
@ -4201,7 +4342,7 @@ Exec(JSContext *cx, unsigned argc, jsval *vp)
ok = false;
goto done;
}
nargv[i] = JS_EncodeString(cx, str);
nargv[i] = JSStringToUTF8(cx, str);
if (!nargv[i]) {
ok = false;
goto done;

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

@ -74,7 +74,7 @@ ArgumentsObject::element(uint32_t i) const
const Value &v = data()->args[i];
if (v.isMagic(JS_FORWARD_TO_CALL_OBJECT)) {
CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().asCall();
for (AliasedFormalIter fi(callobj.callee().script().get(nogc)); ; fi++) {
for (AliasedFormalIter fi(callobj.callee().nonLazyScript().get(nogc)); ; fi++) {
if (fi.frameIndex() == i)
return callobj.aliasedVar(fi);
}
@ -90,7 +90,7 @@ ArgumentsObject::setElement(uint32_t i, const Value &v)
HeapValue &lhs = data()->args[i];
if (lhs.isMagic(JS_FORWARD_TO_CALL_OBJECT)) {
CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().asCall();
for (AliasedFormalIter fi(callobj.callee().script().get(nogc)); ; fi++) {
for (AliasedFormalIter fi(callobj.callee().nonLazyScript().get(nogc)); ; fi++) {
if (fi.frameIndex() == i) {
callobj.setAliasedVar(fi, v);
return;

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

@ -2731,7 +2731,7 @@ DebuggerScript_getChildScripts(JSContext *cx, unsigned argc, Value *vp)
obj = objects->vector[i];
if (obj->isFunction()) {
fun = static_cast<JSFunction *>(obj.get());
funScript = fun->script();
funScript = fun->nonLazyScript();
s = dbg->wrapScript(cx, funScript);
if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
return false;
@ -3445,7 +3445,7 @@ DebuggerFrame_getScript(JSContext *cx, unsigned argc, Value *vp)
if (fp->isFunctionFrame() && !fp->isEvalFrame()) {
JSFunction &callee = fp->callee();
if (callee.isInterpreted()) {
RootedScript script(cx, callee.script());
RootedScript script(cx, callee.nonLazyScript());
scriptObject = debug->wrapScript(cx, script);
if (!scriptObject)
return false;
@ -3925,11 +3925,11 @@ DebuggerObject_getParameterNames(JSContext *cx, unsigned argc, Value *vp)
result->ensureDenseArrayInitializedLength(cx, 0, fun->nargs);
if (fun->isInterpreted()) {
JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
JS_ASSERT(fun->nargs == fun->nonLazyScript()->bindings.numArgs());
if (fun->nargs > 0) {
BindingVector bindings(cx);
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
if (!FillBindingVector(script, &bindings))
return false;
for (size_t i = 0; i < fun->nargs; i++) {
@ -3967,7 +3967,7 @@ DebuggerObject_getScript(JSContext *cx, unsigned argc, Value *vp)
return true;
}
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
RootedObject scriptObject(cx, dbg->wrapScript(cx, script));
if (!scriptObject)
return false;

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

@ -405,7 +405,7 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
* Notify any debuggers about the creation of the script for
* |Function.prototype| -- after all initialization, for simplicity.
*/
RootedScript functionProtoScript(cx, functionProto->script());
RootedScript functionProtoScript(cx, functionProto->nonLazyScript());
js_CallNewScriptHook(cx, functionProtoScript, functionProto);
return functionProto;
}

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

@ -367,7 +367,7 @@ SPSProfiler::discardMJITCode(mjit::JITScript *jscr,
unregisterScript(jscr->script, chunk);
for (unsigned i = 0; i < chunk->nInlineFrames; i++)
unregisterScript(chunk->inlineFrames()[i].fun->script().get(nogc), chunk);
unregisterScript(chunk->inlineFrames()[i].fun->nonLazyScript().get(nogc), chunk);
}
void

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

@ -42,7 +42,7 @@ StaticScopeIter::operator++(int)
obj = obj->asStaticBlock().enclosingStaticScope();
} else if (onNamedLambda || !obj->toFunction()->isNamedLambda()) {
onNamedLambda = false;
obj = obj->toFunction()->script()->enclosingStaticScope();
obj = obj->toFunction()->nonLazyScript()->enclosingStaticScope();
} else {
onNamedLambda = true;
}
@ -86,7 +86,7 @@ StaticScopeIter::funScript() const
{
AutoAssertNoGC nogc;
JS_ASSERT(type() == FUNCTION);
return obj->toFunction()->script().get(nogc);
return obj->toFunction()->nonLazyScript().get(nogc);
}
/*****************************************************************************/
@ -1040,7 +1040,7 @@ ScopeIter::settle()
CallObject &callobj = cur_->asCall();
type_ = callobj.isForEval() ? StrictEvalScope : Call;
hasScopeObject_ = true;
JS_ASSERT_IF(type_ == Call, callobj.callee().script() == fp_->script());
JS_ASSERT_IF(type_ == Call, callobj.callee().nonLazyScript() == fp_->script());
} else {
JS_ASSERT(!cur_->isScope());
JS_ASSERT(fp_->isGlobalFrame() || fp_->isDebuggerFrame());
@ -1122,7 +1122,7 @@ class DebugScopeProxy : public BaseProxyHandler
/* Handle unaliased formals, vars, and consts at function scope. */
if (scope->isCall() && !scope->asCall().isForEval()) {
CallObject &callobj = scope->asCall();
RootedScript script(cx, callobj.callee().script());
RootedScript script(cx, callobj.callee().nonLazyScript());
if (!script->ensureHasTypes(cx))
return false;
@ -1247,7 +1247,7 @@ class DebugScopeProxy : public BaseProxyHandler
static bool isMissingArgumentsBinding(ScopeObject &scope)
{
return isFunctionScope(scope) &&
!scope.asCall().callee().script()->argumentsHasVarBinding();
!scope.asCall().callee().nonLazyScript()->argumentsHasVarBinding();
}
/*
@ -1265,7 +1265,7 @@ class DebugScopeProxy : public BaseProxyHandler
if (!isArguments(cx, id) || !isFunctionScope(scope))
return true;
if (scope.asCall().callee().script()->needsArgsObj())
if (scope.asCall().callee().nonLazyScript()->needsArgsObj())
return true;
StackFrame *maybefp = cx->runtime->debugScopes->hasLiveFrame(scope);
@ -1399,7 +1399,7 @@ class DebugScopeProxy : public BaseProxyHandler
* they must be manually appended here.
*/
if (scope.isCall() && !scope.asCall().isForEval()) {
RootedScript script(cx, scope.asCall().callee().script());
RootedScript script(cx, scope.asCall().callee().nonLazyScript());
for (BindingIter bi(script); bi; bi++) {
if (!bi->aliased() && !props.append(NameToId(bi->name())))
return false;
@ -1438,7 +1438,7 @@ class DebugScopeProxy : public BaseProxyHandler
* a manual search is necessary.
*/
if (!found && scope->isCall() && !scope->asCall().isForEval()) {
RootedScript script(cx, scope->asCall().callee().script());
RootedScript script(cx, scope->asCall().callee().nonLazyScript());
for (BindingIter bi(script); bi; bi++) {
if (!bi->aliased() && NameToId(bi->name()) == id) {
found = true;

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

@ -139,7 +139,7 @@ StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
LOWERED_CALL_APPLY |
OVERFLOW_ARGS |
UNDERFLOW_ARGS)) == 0);
JS_ASSERT(callee.script() == script);
JS_ASSERT(callee.nonLazyScript() == script);
/* Initialize stack frame members. */
flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg;
@ -413,7 +413,7 @@ ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArg
JSFunction *fun, JSScript *script, StackFrame::Flags *flags) const
{
AssertCanGC();
JS_ASSERT(fun->script() == script);
JS_ASSERT(fun->nonLazyScript() == script);
unsigned nformal = fun->nargs;
Value *firstUnused = args.end();
@ -458,7 +458,7 @@ ContextStack::pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &ar
JS_ASSERT(onTop());
JS_ASSERT(regs.sp == args.end());
/* Cannot assert callee == args.callee() since this is called from LeaveTree. */
JS_ASSERT(callee.script() == script);
JS_ASSERT(callee.nonLazyScript() == script);
StackFrame::Flags flags = ToFrameFlags(initial);
StackFrame *fp = getCallFrame(cx, report, args, &callee, script, &flags);
@ -495,8 +495,8 @@ ContextStack::getFixupFrame(JSContext *cx, MaybeReportError report,
{
AssertCanGC();
JS_ASSERT(onTop());
JS_ASSERT(fun->script() == args.callee().toFunction()->script());
JS_ASSERT(fun->script() == script);
JS_ASSERT(fun->nonLazyScript() == args.callee().toFunction()->nonLazyScript());
JS_ASSERT(fun->nonLazyScript() == script);
StackFrame::Flags flags = ToFrameFlags(initial);
StackFrame *fp = getCallFrame(cx, report, args, fun, script, &flags);
@ -564,7 +564,7 @@ ContextStack::currentScript(jsbytecode **ppc,
mjit::JITChunk *chunk = fp->jit()->chunk(regs.pc);
JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
RawScript script = frame->fun->script().get(nogc);
RawScript script = frame->fun->nonLazyScript().get(nogc);
if (!allowCrossCompartment && script->compartment() != cx_->compartment)
return NULL;
if (ppc)

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

@ -249,7 +249,7 @@ AssertDynamicScopeMatchesStaticScope(JSScript *script, JSObject *scope)
scope = &scope->asClonedBlock().enclosingScope();
break;
case StaticScopeIter::FUNCTION:
JS_ASSERT(scope->asCall().callee().script() == i.funScript());
JS_ASSERT(scope->asCall().callee().nonLazyScript() == i.funScript());
scope = &scope->asCall().enclosingScope();
break;
case StaticScopeIter::NAMED_LAMBDA:
@ -363,7 +363,7 @@ StackFrame::epilogue(JSContext *cx)
JS_ASSERT(isNonEvalFunctionFrame());
if (fun()->isHeavyweight())
JS_ASSERT_IF(hasCallObj(), scopeChain()->asCall().callee().script() == script);
JS_ASSERT_IF(hasCallObj(), scopeChain()->asCall().callee().nonLazyScript() == script);
else
AssertDynamicScopeMatchesStaticScope(script, scopeChain());
@ -903,7 +903,7 @@ ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, unsigned nvars
if (fun) {
AutoCompartment ac(cx, fun);
fun->script()->uninlineable = true;
fun->nonLazyScript()->uninlineable = true;
types::MarkTypeObjectFlags(cx, fun, types::OBJECT_FLAG_UNINLINEABLE);
}
}
@ -991,7 +991,7 @@ ContextStack::pushInvokeFrame(JSContext *cx, MaybeReportError report,
JS_ASSERT(onTop());
JS_ASSERT(space().firstUnused() == args.end());
RootedScript script(cx, fun->script());
RootedScript script(cx, fun->nonLazyScript());
StackFrame::Flags flags = ToFrameFlags(initial);
StackFrame *fp = getCallFrame(cx, report, args, fun, script, &flags);

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

@ -612,7 +612,7 @@ class StackFrame
return isFunctionFrame()
? isEvalFrame()
? u.evalScript
: (JSScript*)fun()->script().unsafeGet()
: (JSScript*)fun()->nonLazyScript().unsafeGet()
: exec.script;
}

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

@ -67,7 +67,7 @@ interface nsIXPConnectJSObjectHolder : nsISupports
readonly attribute JSObjectPtr JSObject;
};
[uuid(f819a95a-6ab5-4a02-bda6-32861e859581)]
[uuid(92e98688-0154-4b65-971b-0d4afe8fd7cb)]
interface nsIXPConnectWrappedNative : nsIXPConnectJSObjectHolder
{
/* attribute 'JSObject' inherited from nsIXPConnectJSObjectHolder */
@ -81,6 +81,7 @@ interface nsIXPConnectWrappedNative : nsIXPConnectJSObjectHolder
readonly attribute nsIXPConnect XPConnect;
nsIInterfaceInfo FindInterfaceWithMember(in jsid nameID);
nsIInterfaceInfo FindInterfaceWithName(in jsid nameID);
[notxpcom] bool HasNativeMember(in jsid name);
void debugDump(in short depth);
@ -288,7 +289,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%}
[uuid(e28a33ce-dfe9-4816-ae20-0f1dc8077230)]
[uuid(b551afea-f38c-46d4-bc93-f1e05aebfec2)]
interface nsIXPConnect : nsISupports
{
%{ C++
@ -518,7 +519,7 @@ interface nsIXPConnect : nsISupports
setFunctionThisTranslator(in nsIIDRef aIID,
in nsIXPCFunctionThisTranslator aTranslator);
nsIXPConnectJSObjectHolder
void
reparentWrappedNativeIfFound(in JSContextPtr aJSContext,
in JSObjectPtr aScope,
in JSObjectPtr aNewParent,

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

@ -118,7 +118,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(a93e230d-e883-4ff8-9aeb-dbe5cc771059)]
[scriptable, uuid(b3290d8e-b010-4693-a261-10bbf006b8f0)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -323,12 +323,22 @@ interface nsIXPCComponents_Utils : nsISupports
* disappear at any moment.
*
* Forces a recomputation of all wrappers in and out of the compartment
* containing |obj|. If |obj| is not an object, all wrappers system-wide
* containing |vobj|. If |vobj| is not an object, all wrappers system-wide
* are recomputed.
*/
[implicit_jscontext]
void recomputeWrappers([optional] in jsval vobj);
/*
* To be called from JS only. This is for Gecko internal use only, and may
* disappear at any moment.
*
* Enables Xray vision for same-compartment access for the compartment
* indicated by |vscope|. All outgoing wrappers are recomputed.
*/
[implicit_jscontext]
void setWantXrays(in jsval vscope);
/*
* This seemingly-paradoxical API allows privileged code to explicitly give
* unprivileged code a reference to its own Components object (whereas it's

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