From 87fe96d0dc655d8159f3ed2ebd0cf395426f0ca9 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Thu, 10 Nov 2011 14:02:22 +0200 Subject: [PATCH 01/38] Bug 92264 - Implement outerHTML. Part of the patch by Ms2ger. r=smaug. --- content/base/public/nsIDocumentEncoder.idl | 3 +- content/base/src/nsDocumentEncoder.cpp | 8 ++ .../html/content/src/nsGenericHTMLElement.cpp | 114 +++++++++++++++--- .../html/content/src/nsGenericHTMLElement.h | 12 ++ .../html/nsIDOMHTMLAnchorElement.idl | 2 +- .../html/nsIDOMHTMLAppletElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLAreaElement.idl | 2 +- .../html/nsIDOMHTMLAudioElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBRElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBaseElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBodyElement.idl | 2 +- .../html/nsIDOMHTMLButtonElement.idl | 2 +- .../html/nsIDOMHTMLCanvasElement.idl | 2 +- .../html/nsIDOMHTMLCommandElement.idl | 2 +- .../html/nsIDOMHTMLDListElement.idl | 2 +- .../html/nsIDOMHTMLDataListElement.idl | 2 +- .../html/nsIDOMHTMLDirectoryElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLDivElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLElement.idl | 3 +- .../html/nsIDOMHTMLEmbedElement.idl | 2 +- .../html/nsIDOMHTMLFieldSetElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLFontElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLFormElement.idl | 2 +- .../html/nsIDOMHTMLFrameElement.idl | 2 +- .../html/nsIDOMHTMLFrameSetElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHRElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHeadElement.idl | 2 +- .../html/nsIDOMHTMLHeadingElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHtmlElement.idl | 2 +- .../html/nsIDOMHTMLIFrameElement.idl | 2 +- .../html/nsIDOMHTMLImageElement.idl | 2 +- .../html/nsIDOMHTMLInputElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLLIElement.idl | 2 +- .../html/nsIDOMHTMLLabelElement.idl | 2 +- .../html/nsIDOMHTMLLegendElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLLinkElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMapElement.idl | 2 +- .../html/nsIDOMHTMLMediaElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMenuElement.idl | 2 +- .../html/nsIDOMHTMLMenuItemElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMetaElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLModElement.idl | 2 +- .../html/nsIDOMHTMLOListElement.idl | 2 +- .../html/nsIDOMHTMLObjectElement.idl | 2 +- .../html/nsIDOMHTMLOptGroupElement.idl | 2 +- .../html/nsIDOMHTMLOptionElement.idl | 2 +- .../html/nsIDOMHTMLOutputElement.idl | 2 +- .../html/nsIDOMHTMLParagraphElement.idl | 2 +- .../html/nsIDOMHTMLParamElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLPreElement.idl | 2 +- .../html/nsIDOMHTMLProgressElement.idl | 2 +- .../html/nsIDOMHTMLQuoteElement.idl | 2 +- .../html/nsIDOMHTMLScriptElement.idl | 2 +- .../html/nsIDOMHTMLSelectElement.idl | 2 +- .../html/nsIDOMHTMLSourceElement.idl | 2 +- .../html/nsIDOMHTMLStyleElement.idl | 2 +- .../html/nsIDOMHTMLTableCaptionElem.idl | 2 +- .../html/nsIDOMHTMLTableCellElement.idl | 2 +- .../html/nsIDOMHTMLTableColElement.idl | 2 +- .../html/nsIDOMHTMLTableElement.idl | 2 +- .../html/nsIDOMHTMLTableRowElement.idl | 2 +- .../html/nsIDOMHTMLTableSectionElem.idl | 2 +- .../html/nsIDOMHTMLTextAreaElement.idl | 2 +- .../html/nsIDOMHTMLTitleElement.idl | 2 +- .../html/nsIDOMHTMLUListElement.idl | 2 +- .../html/nsIDOMHTMLUnknownElement.idl | 2 +- .../html/nsIDOMHTMLVideoElement.idl | 2 +- dom/tests/mochitest/general/Makefile.in | 2 + .../mochitest/general/test_outerHTML.html | 73 +++++++++++ .../mochitest/general/test_outerHTML.xhtml | 74 ++++++++++++ 70 files changed, 331 insertions(+), 82 deletions(-) create mode 100644 dom/tests/mochitest/general/test_outerHTML.html create mode 100644 dom/tests/mochitest/general/test_outerHTML.xhtml diff --git a/content/base/public/nsIDocumentEncoder.idl b/content/base/public/nsIDocumentEncoder.idl index 13cadc20e924..6da4fbda80e5 100644 --- a/content/base/public/nsIDocumentEncoder.idl +++ b/content/base/public/nsIDocumentEncoder.idl @@ -51,7 +51,7 @@ class nsIDocument; [ptr] native nsINodePtr(nsINode); [ptr] native nsIDocumentPtr(nsIDocument); -[scriptable, uuid(c0da5b87-0ba7-4d7c-8cb3-fcb02af4253d)] +[scriptable, uuid(82adaeca-63ee-44eb-830a-e1678bb8745e)] interface nsIDocumentEncoderNodeFixup : nsISupports { /** @@ -272,6 +272,7 @@ interface nsIDocumentEncoder : nsISupports * @param aNode The node to encode. */ void setNode(in nsIDOMNode aNode); + [noscript] void setNativeNode(in nsINodePtr aNode); /** * If the container is set to a non-null value, then its diff --git a/content/base/src/nsDocumentEncoder.cpp b/content/base/src/nsDocumentEncoder.cpp index aa583313bdca..8b69baea6c3b 100644 --- a/content/base/src/nsDocumentEncoder.cpp +++ b/content/base/src/nsDocumentEncoder.cpp @@ -301,6 +301,14 @@ nsDocumentEncoder::SetNode(nsIDOMNode* aNode) return NS_OK; } +NS_IMETHODIMP +nsDocumentEncoder::SetNativeNode(nsINode* aNode) +{ + mNodeIsContainer = false; + mNode = aNode; + return NS_OK; +} + NS_IMETHODIMP nsDocumentEncoder::SetContainerNode(nsIDOMNode *aContainer) { diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index c764eaeb5b69..88c84bc5c26c 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -120,6 +120,7 @@ #include "nsPLDOMEvent.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/FromParser.h" using namespace mozilla; using namespace mozilla::dom; @@ -666,14 +667,12 @@ nsGenericHTMLElement::GetOffsetParent(nsIDOMElement** aOffsetParent) } NS_IMETHODIMP -nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) +nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup) { - aInnerHTML.Truncate(); + aMarkup.Truncate(); nsIDocument* doc = OwnerDoc(); - nsresult rv = NS_OK; - nsAutoString contentType; if (IsInHTMLDocument()) { contentType.AssignLiteral("text/html"); @@ -698,21 +697,37 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - rv = docEncoder->NativeInit(doc, contentType, - nsIDocumentEncoder::OutputEncodeBasicEntities | - // Output DOM-standard newlines - nsIDocumentEncoder::OutputLFLineBreak | - // Don't do linebreaking that's not present in - // the source - nsIDocumentEncoder::OutputRaw); + nsresult rv = docEncoder->NativeInit(doc, contentType, + nsIDocumentEncoder::OutputEncodeBasicEntities | + // Output DOM-standard newlines + nsIDocumentEncoder::OutputLFLineBreak | + // Don't do linebreaking that's not present in + // the source + nsIDocumentEncoder::OutputRaw); NS_ENSURE_SUCCESS(rv, rv); - docEncoder->SetNativeContainerNode(this); - rv = docEncoder->EncodeToString(aInnerHTML); - doc->SetCachedEncoder(docEncoder.forget()); + if (aIncludeSelf) { + docEncoder->SetNativeNode(this); + } else { + docEncoder->SetNativeContainerNode(this); + } + rv = docEncoder->EncodeToString(aMarkup); + if (!aIncludeSelf) { + doc->SetCachedEncoder(docEncoder.forget()); + } return rv; } +nsresult +nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) { + return GetMarkup(false, aInnerHTML); +} + +NS_IMETHODIMP +nsGenericHTMLElement::GetOuterHTML(nsAString& aOuterHTML) { + return GetMarkup(true, aOuterHTML); +} + void nsGenericHTMLElement::FireMutationEventsForDirectParsing(nsIDocument* aDoc, nsIContent* aDest, @@ -740,8 +755,6 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) { nsIDocument* doc = OwnerDoc(); - nsresult rv = NS_OK; - // Batch possible DOMSubtreeModified events. mozAutoSubtreeModified subtree(doc, nsnull); @@ -758,8 +771,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) nsAutoScriptLoaderDisabler sld(doc); - nsCOMPtr df; - + nsresult rv = NS_OK; if (doc->IsHTML()) { PRInt32 oldChildCount = GetChildCount(); rv = nsContentUtils::ParseFragmentHTML(aInnerHTML, @@ -772,6 +784,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) // HTML5 parser has notified, but not fired mutation events. FireMutationEventsForDirectParsing(doc, this, oldChildCount); } else { + nsCOMPtr df; rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML, true, getter_AddRefs(df)); @@ -789,6 +802,71 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) return rv; } +NS_IMETHODIMP +nsGenericHTMLElement::SetOuterHTML(const nsAString& aOuterHTML) +{ + nsINode* parent = GetNodeParent(); + if (!parent) { + return NS_OK; + } + + if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) { + return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; + } + + if (OwnerDoc()->IsHTML()) { + nsIAtom* localName; + PRInt32 namespaceID; + if (parent->IsElement()) { + localName = static_cast(parent)->Tag(); + namespaceID = static_cast(parent)->GetNameSpaceID(); + } else { + NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, + "How come the parent isn't a document, a fragment or an element?"); + localName = nsGkAtoms::body; + namespaceID = kNameSpaceID_XHTML; + } + nsCOMPtr df; + nsresult rv = NS_NewDocumentFragment(getter_AddRefs(df), + OwnerDoc()->NodeInfoManager()); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr fragment = do_QueryInterface(df); + nsContentUtils::ParseFragmentHTML(aOuterHTML, + fragment, + localName, + namespaceID, + OwnerDoc()->GetCompatibilityMode() == + eCompatibility_NavQuirks, + PR_TRUE); + parent->ReplaceChild(fragment, this, &rv); + return rv; + } + + nsCOMPtr context; + if (parent->IsElement()) { + context = parent; + } else { + NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, + "How come the parent isn't a document, a fragment or an element?"); + nsCOMPtr info = + OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body, + nsnull, + kNameSpaceID_XHTML, + nsIDOMNode::ELEMENT_NODE); + context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT); + } + + nsCOMPtr df; + nsresult rv = nsContentUtils::CreateContextualFragment(context, + aOuterHTML, + PR_TRUE, + getter_AddRefs(df)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr fragment = do_QueryInterface(df); + parent->ReplaceChild(fragment, this, &rv); + return rv; +} + enum nsAdjacentPosition { eBeforeBegin, eAfterBegin, diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 41641a2edc03..9172bc10438e 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -132,6 +132,8 @@ public: nsresult GetOffsetParent(nsIDOMElement** aOffsetParent); NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML); NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML); + NS_IMETHOD GetOuterHTML(nsAString& aOuterHTML); + NS_IMETHOD SetOuterHTML(const nsAString& aOuterHTML); NS_IMETHOD InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText); nsresult ScrollIntoView(bool aTop, PRUint8 optional_argc); @@ -161,6 +163,10 @@ public: nsresult ClearDataset(); nsresult GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu); +protected: + nsresult GetMarkup(bool aIncludeSelf, nsAString& aMarkup); + +public: // Implementation for nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -1571,6 +1577,12 @@ protected: NS_SCRIPTABLE NS_IMETHOD SetSpellcheck(bool aSpellcheck) { \ return _to SetSpellcheck(aSpellcheck); \ } \ + NS_SCRIPTABLE NS_IMETHOD GetOuterHTML(nsAString& aOuterHTML) { \ + return _to GetOuterHTML(aOuterHTML); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetOuterHTML(const nsAString& aOuterHTML) { \ + return _to SetOuterHTML(aOuterHTML); \ + } \ NS_SCRIPTABLE NS_IMETHOD InsertAdjacentHTML(const nsAString& position, const nsAString& text) { \ return _to InsertAdjacentHTML(position, text); \ } \ diff --git a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl b/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl index cc493a375dfa..040f5c8f15f1 100644 --- a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(2da904fa-83da-426d-a320-a6868192583e)] +[scriptable, uuid(bcb54394-d9f8-4bcb-bbbb-eca9826cdbca)] interface nsIDOMHTMLAnchorElement : nsIDOMHTMLElement { attribute DOMString href; diff --git a/dom/interfaces/html/nsIDOMHTMLAppletElement.idl b/dom/interfaces/html/nsIDOMHTMLAppletElement.idl index 2295977f495e..74a5f0c0ab89 100644 --- a/dom/interfaces/html/nsIDOMHTMLAppletElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAppletElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c874e500-a185-4d69-96dd-474d1137e21f)] +[scriptable, uuid(a06bca18-791f-474e-a031-bf6c2bd14994)] interface nsIDOMHTMLAppletElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLAreaElement.idl b/dom/interfaces/html/nsIDOMHTMLAreaElement.idl index b5bdfaf74e2b..07cd39176569 100644 --- a/dom/interfaces/html/nsIDOMHTMLAreaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAreaElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d88c8515-5a27-4955-8ca5-18c908433cfd)] +[scriptable, uuid(7e607c36-aecc-4dee-a93a-95e22a374bfb)] interface nsIDOMHTMLAreaElement : nsIDOMHTMLElement { attribute DOMString alt; diff --git a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl index 95d99c8ab847..4ebee6b48374 100644 --- a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl @@ -52,7 +52,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(f4115c13-bc51-4c3b-a5c0-9106af9f7368)] +[scriptable, uuid(756e2792-b937-4a70-bd1f-9d6820473e7e)] interface nsIDOMHTMLAudioElement : nsIDOMHTMLMediaElement { // Setup the audio stream for writing diff --git a/dom/interfaces/html/nsIDOMHTMLBRElement.idl b/dom/interfaces/html/nsIDOMHTMLBRElement.idl index 8c8bb6d785ea..bef88132df01 100644 --- a/dom/interfaces/html/nsIDOMHTMLBRElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBRElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a4f319d7-442d-4154-8c60-b9acdca87523)] +[scriptable, uuid(7eefd466-7c4d-499a-a076-e33204e69dc3)] interface nsIDOMHTMLBRElement : nsIDOMHTMLElement { attribute DOMString clear; diff --git a/dom/interfaces/html/nsIDOMHTMLBaseElement.idl b/dom/interfaces/html/nsIDOMHTMLBaseElement.idl index 2b6bdfd407fe..1de84be9b9be 100644 --- a/dom/interfaces/html/nsIDOMHTMLBaseElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBaseElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(1ba4957f-629e-4410-b5fd-64f2b7eeb32c)] +[scriptable, uuid(e55cd224-b603-4976-892a-20b11d469394)] interface nsIDOMHTMLBaseElement : nsIDOMHTMLElement { attribute DOMString href; diff --git a/dom/interfaces/html/nsIDOMHTMLBodyElement.idl b/dom/interfaces/html/nsIDOMHTMLBodyElement.idl index b4623b175cd7..5f4e595e166f 100644 --- a/dom/interfaces/html/nsIDOMHTMLBodyElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBodyElement.idl @@ -54,7 +54,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(dcf343a9-fa7f-4e16-b122-0ece0d8bdea9)] +[scriptable, uuid(6c377d44-a5d1-4f0f-860a-9858d2cb5679)] interface nsIDOMHTMLBodyElement : nsIDOMHTMLElement { attribute DOMString aLink; diff --git a/dom/interfaces/html/nsIDOMHTMLButtonElement.idl b/dom/interfaces/html/nsIDOMHTMLButtonElement.idl index b38f649b53fe..b454007d275f 100644 --- a/dom/interfaces/html/nsIDOMHTMLButtonElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLButtonElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(4b48e075-a05b-480f-9e37-fcd88e7aebdd)] +[scriptable, uuid(79f034f0-5c13-4101-9598-412e1eac1986)] interface nsIDOMHTMLButtonElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl index 8d01e765548a..f19a8f46d18a 100644 --- a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl @@ -55,7 +55,7 @@ interface nsIDOMFile; interface nsIVariant; -[scriptable, uuid(e1ea26e6-4141-487f-a9cf-d7e9344b571c)] +[scriptable, uuid(dbbeeba1-3c20-4d9d-ac82-98b69fd819a9)] interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement { attribute unsigned long width; diff --git a/dom/interfaces/html/nsIDOMHTMLCommandElement.idl b/dom/interfaces/html/nsIDOMHTMLCommandElement.idl index 527f0d596e26..e8efab96b5f8 100644 --- a/dom/interfaces/html/nsIDOMHTMLCommandElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLCommandElement.idl @@ -46,7 +46,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(4c466da8-5c6d-427f-95f5-bba96ab99c96)] +[scriptable, uuid(13032f74-4150-4768-ab5e-51f4de39a300)] interface nsIDOMHTMLCommandElement : nsIDOMHTMLElement { attribute DOMString type; diff --git a/dom/interfaces/html/nsIDOMHTMLDListElement.idl b/dom/interfaces/html/nsIDOMHTMLDListElement.idl index f4d6c282169f..e3ad0fcc13f7 100644 --- a/dom/interfaces/html/nsIDOMHTMLDListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(f3e65e2b-e079-4970-bb5d-f96ac9cd18c5)] +[scriptable, uuid(50e9ff30-0982-4074-bc65-313f41be8624)] interface nsIDOMHTMLDListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLDataListElement.idl b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl index 0a92f6b07880..4496b81c73b6 100644 --- a/dom/interfaces/html/nsIDOMHTMLDataListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl @@ -49,7 +49,7 @@ interface nsIDOMHTMLCollection; -[scriptable, uuid(312ed7c1-8c62-4d80-bbd9-99d7ea4377e6)] +[scriptable, uuid(3bace78b-9eca-4990-a5d6-9c2b8c32cc8a)] interface nsIDOMHTMLDataListElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLCollection options; diff --git a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl index aed3d77dc1f6..184e6bb54151 100644 --- a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(1e04cd43-edc0-4658-bd77-d67661af6c9c)] +[scriptable, uuid(a99e86ae-7761-4145-b8a4-5a91186051f1)] interface nsIDOMHTMLDirectoryElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLDivElement.idl b/dom/interfaces/html/nsIDOMHTMLDivElement.idl index b0fdcb046fa2..c8369f740813 100644 --- a/dom/interfaces/html/nsIDOMHTMLDivElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDivElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(771be9ee-b883-4556-bf90-2d7c904fe94d)] +[scriptable, uuid(6815b902-8e04-49dd-977b-0a8785e5ffaf)] interface nsIDOMHTMLDivElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLElement.idl b/dom/interfaces/html/nsIDOMHTMLElement.idl index 12397ba470f9..78cd0756eb16 100644 --- a/dom/interfaces/html/nsIDOMHTMLElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLElement.idl @@ -53,7 +53,7 @@ interface nsIDOMHTMLMenuElement; * with changes from the work-in-progress WHATWG HTML specification: * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(0a21bb68-d8bd-4b2a-a3db-048a02e81c62)] +[scriptable, uuid(4eccf8a3-8bf5-43f3-a728-f5b632f7db3a)] interface nsIDOMHTMLElement : nsIDOMElement { // metadata attributes @@ -86,6 +86,7 @@ interface nsIDOMHTMLElement : nsIDOMElement // DOM Parsing and Serialization attribute DOMString innerHTML; + attribute DOMString outerHTML; void insertAdjacentHTML(in DOMString position, in DOMString text); diff --git a/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl b/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl index 76ba843a7c43..9546df2aaadf 100644 --- a/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl @@ -47,7 +47,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/#the-embed-element */ -[scriptable, uuid(d6309fc7-e9d2-4087-b452-490ed84f2dc2)] +[scriptable, uuid(940a15c2-0d48-4186-b4d8-067fa1ce5675)] interface nsIDOMHTMLEmbedElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl b/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl index 8f37aabdbcbf..d5905ebc6b46 100644 --- a/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(e153c20e-7a3d-4184-865c-ee7c6d9b65df)] +[scriptable, uuid(781ae103-b030-4aad-b2d5-96e5c2317dec)] interface nsIDOMHTMLFieldSetElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLFontElement.idl b/dom/interfaces/html/nsIDOMHTMLFontElement.idl index 994a74ddb4c1..7648bf8961a0 100644 --- a/dom/interfaces/html/nsIDOMHTMLFontElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFontElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(8a205975-86cb-44db-b20e-df7f2d200580)] +[scriptable, uuid(1c9778ee-a49c-40ee-9b93-c0ff15630431)] interface nsIDOMHTMLFontElement : nsIDOMHTMLElement { attribute DOMString color; diff --git a/dom/interfaces/html/nsIDOMHTMLFormElement.idl b/dom/interfaces/html/nsIDOMHTMLFormElement.idl index a93cc376626a..65fb4dfccaae 100644 --- a/dom/interfaces/html/nsIDOMHTMLFormElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFormElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(8fe67952-6f7b-4d6e-b17b-79a454687e5f)] +[scriptable, uuid(d873b251-6f96-4e70-baf5-aaa935aabe59)] interface nsIDOMHTMLFormElement : nsIDOMHTMLElement { attribute DOMString acceptCharset; diff --git a/dom/interfaces/html/nsIDOMHTMLFrameElement.idl b/dom/interfaces/html/nsIDOMHTMLFrameElement.idl index 90752d2e8e06..dab1a4de2aeb 100644 --- a/dom/interfaces/html/nsIDOMHTMLFrameElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFrameElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6de9d59d-42fd-44df-bb41-22cd64a85d4f)] +[scriptable, uuid(318fdc4a-3fca-4099-94aa-c9a1c30ca2b9)] interface nsIDOMHTMLFrameElement : nsIDOMHTMLElement { attribute DOMString frameBorder; diff --git a/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl b/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl index 7bff911baa94..5747a276db79 100644 --- a/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl @@ -54,7 +54,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a9423392-0f92-4b25-8700-49d28752c092)] +[scriptable, uuid(6eefbe6d-182c-42e9-9850-af1892b6f2e4)] interface nsIDOMHTMLFrameSetElement : nsIDOMHTMLElement { attribute DOMString cols; diff --git a/dom/interfaces/html/nsIDOMHTMLHRElement.idl b/dom/interfaces/html/nsIDOMHTMLHRElement.idl index b5977327bf80..ac338fdc7d2b 100644 --- a/dom/interfaces/html/nsIDOMHTMLHRElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHRElement.idl @@ -51,7 +51,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a6950d69-a376-4ad5-a911-8f91abb2b15d)] +[scriptable, uuid(b94bff8f-dfa7-4dd8-8d97-c301dd9de729)] interface nsIDOMHTMLHRElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLHeadElement.idl b/dom/interfaces/html/nsIDOMHTMLHeadElement.idl index c017ac292fe4..4d7600fe9bfc 100644 --- a/dom/interfaces/html/nsIDOMHTMLHeadElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHeadElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6d049c37-2cee-4c04-816c-270973e58ccf)] +[scriptable, uuid(628fe597-6408-4387-9fcb-75381e2b2dd0)] interface nsIDOMHTMLHeadElement : nsIDOMHTMLElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl index e3bf581f6d3c..0d7265080c2e 100644 --- a/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c3c30a05-1dc0-413a-85f6-3c4d5af5f2b6)] +[scriptable, uuid(964c94b0-5571-44e7-9b29-f81c6ea7828a)] interface nsIDOMHTMLHeadingElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl b/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl index 420570c389b8..f7459ab2ac0d 100644 --- a/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(84825a7d-d5c7-4b1a-9d2a-b3e5df055824)] +[scriptable, uuid(4bafbc15-aa88-4021-9ad6-e14189b7227b)] interface nsIDOMHTMLHtmlElement : nsIDOMHTMLElement { attribute DOMString version; diff --git a/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl b/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl index bcfdd797ba41..759a5f481a56 100644 --- a/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(166c1cdb-9af5-4217-9a2f-f9dae0923e85)] +[scriptable, uuid(5ef30718-fe45-43a2-a478-a9e3cbf3a118)] interface nsIDOMHTMLIFrameElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLImageElement.idl b/dom/interfaces/html/nsIDOMHTMLImageElement.idl index d5d039494b4e..9c04b214e060 100644 --- a/dom/interfaces/html/nsIDOMHTMLImageElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLImageElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(02dbe3c7-e75e-4a35-989c-b6f6d7a3108f)] +[scriptable, uuid(56d9191f-5a94-432f-af70-6fccdeaf614b)] interface nsIDOMHTMLImageElement : nsIDOMHTMLElement { attribute DOMString alt; diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 6ecc4215c119..2b81463e4097 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -54,7 +54,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(81cc1b30-02e1-4779-ac9e-0091933478a4)] +[scriptable, uuid(7330cd35-c930-4f45-ae61-f5380c30222d)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; diff --git a/dom/interfaces/html/nsIDOMHTMLLIElement.idl b/dom/interfaces/html/nsIDOMHTMLLIElement.idl index a4c3180708a8..5b8b0135a51c 100644 --- a/dom/interfaces/html/nsIDOMHTMLLIElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLIElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(cb9bbac6-3198-4159-9ee9-262eef35f265)] +[scriptable, uuid(85b15d13-be6d-4653-9c70-22a13d510247)] interface nsIDOMHTMLLIElement : nsIDOMHTMLElement { attribute DOMString type; diff --git a/dom/interfaces/html/nsIDOMHTMLLabelElement.idl b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl index 0557647b51cc..3cb02ca6c3f1 100644 --- a/dom/interfaces/html/nsIDOMHTMLLabelElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(0c36c887-04e3-4926-a916-8e3596130f9a)] +[scriptable, uuid(ddbca449-625d-467c-a22d-7887474f9eb9)] interface nsIDOMHTMLLabelElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLLegendElement.idl b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl index f9b33d773375..b3a57b6f2905 100644 --- a/dom/interfaces/html/nsIDOMHTMLLegendElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(cabacc5f-5179-4c97-be60-0af8feafb4c9)] +[scriptable, uuid(dac72753-6919-414b-b771-9e1e86e7749c)] interface nsIDOMHTMLLegendElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl b/dom/interfaces/html/nsIDOMHTMLLinkElement.idl index dc79e285df4a..f1f56d7ed9f2 100644 --- a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLinkElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(2f238f84-1b45-4ef9-9cda-bd1430ce9304)] +[scriptable, uuid(2ece79f4-83d7-499c-946f-ae9ab93147b7)] interface nsIDOMHTMLLinkElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLMapElement.idl b/dom/interfaces/html/nsIDOMHTMLMapElement.idl index da0736fb208c..904847b7e0d5 100644 --- a/dom/interfaces/html/nsIDOMHTMLMapElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMapElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(3fb8ec10-8778-418d-9c83-556e46f115a9)] +[scriptable, uuid(c919bc49-bd49-4b89-ba70-5c74c4ef504a)] interface nsIDOMHTMLMapElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLCollection areas; diff --git a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl index d9f673156659..785550892d0a 100644 --- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl @@ -57,7 +57,7 @@ #endif %} -[scriptable, uuid(85baaa10-73ab-4a48-a57a-b3951b67e494)] +[scriptable, uuid(642a3b85-4edb-4c01-a162-06b5d88171e7)] interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement { // error state diff --git a/dom/interfaces/html/nsIDOMHTMLMenuElement.idl b/dom/interfaces/html/nsIDOMHTMLMenuElement.idl index 1e227250daff..d4eb205997be 100644 --- a/dom/interfaces/html/nsIDOMHTMLMenuElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMenuElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(12de9196-b164-43e0-9347-f23e1bffbede)] +[scriptable, uuid(06d48250-45e0-4f26-9a07-d9b5a3f08bb6)] interface nsIDOMHTMLMenuElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl b/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl index 7b11b7c3a037..1cc730b87a69 100644 --- a/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl @@ -43,7 +43,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(e0469d92-a137-4329-9d4b-9f2ba5ce8e77)] +[scriptable, uuid(4680ec24-94f0-4eb7-9413-98f9a857de72)] interface nsIDOMHTMLMenuItemElement : nsIDOMHTMLCommandElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLMetaElement.idl b/dom/interfaces/html/nsIDOMHTMLMetaElement.idl index 28d737c2ed33..b74cfc89cc64 100644 --- a/dom/interfaces/html/nsIDOMHTMLMetaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMetaElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c883b92b-5ae0-4563-894a-fa7f0e9aacda)] +[scriptable, uuid(db476657-5f59-4e29-84a6-50afe6f85ac7)] interface nsIDOMHTMLMetaElement : nsIDOMHTMLElement { attribute DOMString content; diff --git a/dom/interfaces/html/nsIDOMHTMLModElement.idl b/dom/interfaces/html/nsIDOMHTMLModElement.idl index c10055044de7..fcb9e99895c9 100644 --- a/dom/interfaces/html/nsIDOMHTMLModElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLModElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(417626fa-191c-41e5-aed5-f6157b408e72)] +[scriptable, uuid(170733d4-aad5-4f6e-86c0-94845ea6116d)] interface nsIDOMHTMLModElement : nsIDOMHTMLElement { attribute DOMString cite; diff --git a/dom/interfaces/html/nsIDOMHTMLOListElement.idl b/dom/interfaces/html/nsIDOMHTMLOListElement.idl index b8c9c184cb6c..989aa350570e 100644 --- a/dom/interfaces/html/nsIDOMHTMLOListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(11e66686-b1ef-47be-9025-ffc20b875e4a)] +[scriptable, uuid(31a5f083-59a6-41c3-8a0b-e58e484c6516)] interface nsIDOMHTMLOListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLObjectElement.idl b/dom/interfaces/html/nsIDOMHTMLObjectElement.idl index ff86e566c61b..ae2c09b996e2 100644 --- a/dom/interfaces/html/nsIDOMHTMLObjectElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLObjectElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(5d873128-d4e3-4e89-8900-599155167105)] +[scriptable, uuid(40037f4a-5bae-476f-977b-bbd8e78aaefe)] interface nsIDOMHTMLObjectElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl b/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl index 9865c534bc2b..77c3f6e863fa 100644 --- a/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(7b585d49-1da3-4fc6-a50c-b661063c2edc)] +[scriptable, uuid(ab55d67a-aabb-4441-b182-8ff2bd7d157e)] interface nsIDOMHTMLOptGroupElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLOptionElement.idl b/dom/interfaces/html/nsIDOMHTMLOptionElement.idl index c5451316161a..814046266eac 100644 --- a/dom/interfaces/html/nsIDOMHTMLOptionElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOptionElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c20ead8a-cb89-43b1-89ed-8f4713bf8452)] +[scriptable, uuid(7c5bf0ac-6230-4ee0-8b82-e7ebf211af03)] interface nsIDOMHTMLOptionElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLOutputElement.idl b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl index c348a5b23146..9e3d17cbb43c 100644 --- a/dom/interfaces/html/nsIDOMHTMLOutputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl @@ -50,7 +50,7 @@ interface nsIDOMDOMSettableTokenList; interface nsIDOMValidityState; -[scriptable, uuid(7d1fb2a9-7678-409e-8eb5-9216c47c233b)] +[scriptable, uuid(f2074cdb-19cb-447a-935c-9f4402dc1b5e)] interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement { readonly attribute nsIDOMDOMSettableTokenList htmlFor; diff --git a/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl b/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl index 3dd0608addbc..6ff31c369ae4 100644 --- a/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d5d3eb33-0925-4555-be2f-4078dec49f59)] +[scriptable, uuid(e4f498f4-e3c5-46fe-92d0-c9957ccab530)] interface nsIDOMHTMLParagraphElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLParamElement.idl b/dom/interfaces/html/nsIDOMHTMLParamElement.idl index f39e07ede768..fc76ad88c9d9 100644 --- a/dom/interfaces/html/nsIDOMHTMLParamElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLParamElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(ccffedb8-f234-474e-9af4-576eba766023)] +[scriptable, uuid(d832b1ac-9bb6-4df0-9d9e-f7c040759672)] interface nsIDOMHTMLParamElement : nsIDOMHTMLElement { attribute DOMString name; diff --git a/dom/interfaces/html/nsIDOMHTMLPreElement.idl b/dom/interfaces/html/nsIDOMHTMLPreElement.idl index 78440bd96973..462d9b91c251 100644 --- a/dom/interfaces/html/nsIDOMHTMLPreElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLPreElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c9d9b45a-e7d9-4dfb-abae-f3b9e6addbaa)] +[scriptable, uuid(f4088dff-649c-4eff-a3a4-dbd6333cdc44)] interface nsIDOMHTMLPreElement : nsIDOMHTMLElement { attribute long width; diff --git a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl index aa1db31233cf..24b584d78466 100644 --- a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl @@ -47,7 +47,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(aa830aa2-a4ea-455e-8285-8344cadb4c6d)] +[scriptable, uuid(9b1d2263-b60f-4d18-b4d1-66e8c3867c79)] interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement { attribute double value; diff --git a/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl b/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl index 20e0ef6c4949..c100f9090e3d 100644 --- a/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(820ccd14-2479-4e4a-99d3-76d138caf7ec)] +[scriptable, uuid(55643647-2eda-4a45-af55-b2ba6c40c5f5)] interface nsIDOMHTMLQuoteElement : nsIDOMHTMLElement { attribute DOMString cite; diff --git a/dom/interfaces/html/nsIDOMHTMLScriptElement.idl b/dom/interfaces/html/nsIDOMHTMLScriptElement.idl index 8e7cf55a5a6e..02a52c1486ab 100644 --- a/dom/interfaces/html/nsIDOMHTMLScriptElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLScriptElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e6252d3b-521a-4f79-9d57-2721a81e7cc2)] +[scriptable, uuid(4b6a0957-5466-4134-8a0a-dd7e4675c106)] interface nsIDOMHTMLScriptElement : nsIDOMHTMLElement { attribute DOMString src; diff --git a/dom/interfaces/html/nsIDOMHTMLSelectElement.idl b/dom/interfaces/html/nsIDOMHTMLSelectElement.idl index 2a71f9f2df2a..8034c29a916a 100644 --- a/dom/interfaces/html/nsIDOMHTMLSelectElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLSelectElement.idl @@ -53,7 +53,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(30a948a3-61a0-453c-a1e4-de67a1664746)] +[scriptable, uuid(98f111e0-2b7e-4abd-984b-2cc1d174fe44)] interface nsIDOMHTMLSelectElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLSourceElement.idl b/dom/interfaces/html/nsIDOMHTMLSourceElement.idl index 0cc0a6b1ca1a..4cf5f82416da 100644 --- a/dom/interfaces/html/nsIDOMHTMLSourceElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLSourceElement.idl @@ -48,7 +48,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(dcac4414-37e2-409f-b0a6-8231007e585b)] +[scriptable, uuid(c49d9a78-fa02-49c9-b239-9cd51e99f866)] interface nsIDOMHTMLSourceElement : nsIDOMHTMLElement { attribute DOMString src; diff --git a/dom/interfaces/html/nsIDOMHTMLStyleElement.idl b/dom/interfaces/html/nsIDOMHTMLStyleElement.idl index 41d4741d039e..2ce7924082e6 100644 --- a/dom/interfaces/html/nsIDOMHTMLStyleElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLStyleElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e72a6069-4987-480b-a349-ffd5fbebd59f)] +[scriptable, uuid(247fc8c4-92f3-427b-af6f-41b13f28287d)] interface nsIDOMHTMLStyleElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl b/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl index 19dd09797264..fecd4818488a 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(cbd44d29-3120-470d-a7fb-fac4730c8b4b)] +[scriptable, uuid(db0e641f-ba2b-4c67-8da1-4e418cc5fbf7)] interface nsIDOMHTMLTableCaptionElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl index 43a9133ffea3..2f91ade14a13 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(03dd5118-7eaf-4bd3-a4a7-77f3f7eb8539)] +[scriptable, uuid(4caa7af0-fec4-44c1-9a81-e1f14166e60c)] interface nsIDOMHTMLTableCellElement : nsIDOMHTMLElement { readonly attribute long cellIndex; diff --git a/dom/interfaces/html/nsIDOMHTMLTableColElement.idl b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl index 2573a0c9ccd7..e82b5b5fb214 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableColElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d221534a-d13c-43b2-9ba0-7e0dd7452856)] +[scriptable, uuid(9a4d1f6a-fb19-4886-b0d8-dcd201566580)] interface nsIDOMHTMLTableColElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTableElement.idl b/dom/interfaces/html/nsIDOMHTMLTableElement.idl index 3614a17a74ec..e7724f3d98f3 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(bba4b8b2-d01c-4c9b-abc8-3df28d048e68)] +[scriptable, uuid(0f809b97-9311-45c4-a44e-7145f354438b)] interface nsIDOMHTMLTableElement : nsIDOMHTMLElement { // Modified in DOM Level 2: diff --git a/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl index f9aeed647f6d..e6748b0cf673 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(b0199f36-9e76-4ec6-867f-850e388d6244)] +[scriptable, uuid(d24a80d4-491d-4e36-9349-afd3c6999b3e)] interface nsIDOMHTMLTableRowElement : nsIDOMHTMLElement { // Modified in DOM Level 2: diff --git a/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl b/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl index 96facb0877c0..037f300de7dd 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(ac2e2719-71f1-4485-ac1e-694e7e49bd2a)] +[scriptable, uuid(6acc106e-96a2-4519-8f3a-142ebbdc1bb1)] interface nsIDOMHTMLTableSectionElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl b/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl index fc78d04cf516..ec65b72c4e19 100644 --- a/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl @@ -53,7 +53,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(88d09917-d2da-4737-a887-277a2f9750c7)] +[scriptable, uuid(16db703d-4816-440c-bcb3-c1ae0cae6532)] interface nsIDOMHTMLTextAreaElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLTitleElement.idl b/dom/interfaces/html/nsIDOMHTMLTitleElement.idl index 18345f1421ad..305b773467c2 100644 --- a/dom/interfaces/html/nsIDOMHTMLTitleElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTitleElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(5cb8cfaf-7551-422b-9b03-58d756e54339)] +[scriptable, uuid(e20fd651-6240-4f20-b8f0-6cc25cb699b7)] interface nsIDOMHTMLTitleElement : nsIDOMHTMLElement { attribute DOMString text; diff --git a/dom/interfaces/html/nsIDOMHTMLUListElement.idl b/dom/interfaces/html/nsIDOMHTMLUListElement.idl index 313c2a16fa10..8ecf76e00e6c 100644 --- a/dom/interfaces/html/nsIDOMHTMLUListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLUListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(1f409357-8cea-4f69-9f0c-4149886b63a1)] +[scriptable, uuid(2467d39c-2c30-407e-9b67-ea5f231b7809)] interface nsIDOMHTMLUListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl index 508930fd0d30..97809dbd594c 100644 --- a/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl @@ -43,7 +43,7 @@ * * @see */ -[scriptable, uuid(0d69049f-8181-47f1-a7f7-e5417dd54136)] +[scriptable, uuid(5f922c13-c2c1-4c49-b7c2-0e4e5c8e6860)] interface nsIDOMHTMLUnknownElement : nsIDOMHTMLElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl index 622eafe52946..02c2bbbf8a2b 100644 --- a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl @@ -48,7 +48,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(5e1e4453-96fe-4cc0-9c32-7e9355b4f917)] +[scriptable, uuid(390b974b-1c3a-4700-8001-5ef832c4b4bf)] interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement { attribute long width; diff --git a/dom/tests/mochitest/general/Makefile.in b/dom/tests/mochitest/general/Makefile.in index d548a8ebfbff..e35c278fad62 100644 --- a/dom/tests/mochitest/general/Makefile.in +++ b/dom/tests/mochitest/general/Makefile.in @@ -45,6 +45,8 @@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _TEST_FILES = \ + test_outerHTML.html \ + test_outerHTML.xhtml \ 497633.html \ 489127.html \ historyframes.html \ diff --git a/dom/tests/mochitest/general/test_outerHTML.html b/dom/tests/mochitest/general/test_outerHTML.html new file mode 100644 index 000000000000..dba259844232 --- /dev/null +++ b/dom/tests/mochitest/general/test_outerHTML.html @@ -0,0 +1,73 @@ + + + + + Test for Bug 92264 + + + + +Mozilla Bug 92264 +

+ +
+
+
+ + diff --git a/dom/tests/mochitest/general/test_outerHTML.xhtml b/dom/tests/mochitest/general/test_outerHTML.xhtml new file mode 100644 index 000000000000..46013deb0af9 --- /dev/null +++ b/dom/tests/mochitest/general/test_outerHTML.xhtml @@ -0,0 +1,74 @@ + + + + + Test for Bug 92264 + + + + +Mozilla Bug 92264 +

+ +
+
+
+ + From 2c1e020e872110791dddd0dd3ba2803ad7dfffee Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Thu, 10 Nov 2011 14:49:54 +0200 Subject: [PATCH 02/38] Back out changeset 0fb81504b0aa due to Windows build breaking. --- content/base/public/nsIDocumentEncoder.idl | 3 +- content/base/src/nsDocumentEncoder.cpp | 8 -- .../html/content/src/nsGenericHTMLElement.cpp | 114 +++--------------- .../html/content/src/nsGenericHTMLElement.h | 12 -- .../html/nsIDOMHTMLAnchorElement.idl | 2 +- .../html/nsIDOMHTMLAppletElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLAreaElement.idl | 2 +- .../html/nsIDOMHTMLAudioElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBRElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBaseElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBodyElement.idl | 2 +- .../html/nsIDOMHTMLButtonElement.idl | 2 +- .../html/nsIDOMHTMLCanvasElement.idl | 2 +- .../html/nsIDOMHTMLCommandElement.idl | 2 +- .../html/nsIDOMHTMLDListElement.idl | 2 +- .../html/nsIDOMHTMLDataListElement.idl | 2 +- .../html/nsIDOMHTMLDirectoryElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLDivElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLElement.idl | 3 +- .../html/nsIDOMHTMLEmbedElement.idl | 2 +- .../html/nsIDOMHTMLFieldSetElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLFontElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLFormElement.idl | 2 +- .../html/nsIDOMHTMLFrameElement.idl | 2 +- .../html/nsIDOMHTMLFrameSetElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHRElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHeadElement.idl | 2 +- .../html/nsIDOMHTMLHeadingElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHtmlElement.idl | 2 +- .../html/nsIDOMHTMLIFrameElement.idl | 2 +- .../html/nsIDOMHTMLImageElement.idl | 2 +- .../html/nsIDOMHTMLInputElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLLIElement.idl | 2 +- .../html/nsIDOMHTMLLabelElement.idl | 2 +- .../html/nsIDOMHTMLLegendElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLLinkElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMapElement.idl | 2 +- .../html/nsIDOMHTMLMediaElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMenuElement.idl | 2 +- .../html/nsIDOMHTMLMenuItemElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMetaElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLModElement.idl | 2 +- .../html/nsIDOMHTMLOListElement.idl | 2 +- .../html/nsIDOMHTMLObjectElement.idl | 2 +- .../html/nsIDOMHTMLOptGroupElement.idl | 2 +- .../html/nsIDOMHTMLOptionElement.idl | 2 +- .../html/nsIDOMHTMLOutputElement.idl | 2 +- .../html/nsIDOMHTMLParagraphElement.idl | 2 +- .../html/nsIDOMHTMLParamElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLPreElement.idl | 2 +- .../html/nsIDOMHTMLProgressElement.idl | 2 +- .../html/nsIDOMHTMLQuoteElement.idl | 2 +- .../html/nsIDOMHTMLScriptElement.idl | 2 +- .../html/nsIDOMHTMLSelectElement.idl | 2 +- .../html/nsIDOMHTMLSourceElement.idl | 2 +- .../html/nsIDOMHTMLStyleElement.idl | 2 +- .../html/nsIDOMHTMLTableCaptionElem.idl | 2 +- .../html/nsIDOMHTMLTableCellElement.idl | 2 +- .../html/nsIDOMHTMLTableColElement.idl | 2 +- .../html/nsIDOMHTMLTableElement.idl | 2 +- .../html/nsIDOMHTMLTableRowElement.idl | 2 +- .../html/nsIDOMHTMLTableSectionElem.idl | 2 +- .../html/nsIDOMHTMLTextAreaElement.idl | 2 +- .../html/nsIDOMHTMLTitleElement.idl | 2 +- .../html/nsIDOMHTMLUListElement.idl | 2 +- .../html/nsIDOMHTMLUnknownElement.idl | 2 +- .../html/nsIDOMHTMLVideoElement.idl | 2 +- dom/tests/mochitest/general/Makefile.in | 2 - .../mochitest/general/test_outerHTML.html | 73 ----------- .../mochitest/general/test_outerHTML.xhtml | 74 ------------ 70 files changed, 82 insertions(+), 331 deletions(-) delete mode 100644 dom/tests/mochitest/general/test_outerHTML.html delete mode 100644 dom/tests/mochitest/general/test_outerHTML.xhtml diff --git a/content/base/public/nsIDocumentEncoder.idl b/content/base/public/nsIDocumentEncoder.idl index 6da4fbda80e5..13cadc20e924 100644 --- a/content/base/public/nsIDocumentEncoder.idl +++ b/content/base/public/nsIDocumentEncoder.idl @@ -51,7 +51,7 @@ class nsIDocument; [ptr] native nsINodePtr(nsINode); [ptr] native nsIDocumentPtr(nsIDocument); -[scriptable, uuid(82adaeca-63ee-44eb-830a-e1678bb8745e)] +[scriptable, uuid(c0da5b87-0ba7-4d7c-8cb3-fcb02af4253d)] interface nsIDocumentEncoderNodeFixup : nsISupports { /** @@ -272,7 +272,6 @@ interface nsIDocumentEncoder : nsISupports * @param aNode The node to encode. */ void setNode(in nsIDOMNode aNode); - [noscript] void setNativeNode(in nsINodePtr aNode); /** * If the container is set to a non-null value, then its diff --git a/content/base/src/nsDocumentEncoder.cpp b/content/base/src/nsDocumentEncoder.cpp index 8b69baea6c3b..aa583313bdca 100644 --- a/content/base/src/nsDocumentEncoder.cpp +++ b/content/base/src/nsDocumentEncoder.cpp @@ -301,14 +301,6 @@ nsDocumentEncoder::SetNode(nsIDOMNode* aNode) return NS_OK; } -NS_IMETHODIMP -nsDocumentEncoder::SetNativeNode(nsINode* aNode) -{ - mNodeIsContainer = false; - mNode = aNode; - return NS_OK; -} - NS_IMETHODIMP nsDocumentEncoder::SetContainerNode(nsIDOMNode *aContainer) { diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 88c84bc5c26c..c764eaeb5b69 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -120,7 +120,6 @@ #include "nsPLDOMEvent.h" #include "mozilla/Preferences.h" -#include "mozilla/dom/FromParser.h" using namespace mozilla; using namespace mozilla::dom; @@ -667,12 +666,14 @@ nsGenericHTMLElement::GetOffsetParent(nsIDOMElement** aOffsetParent) } NS_IMETHODIMP -nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup) +nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) { - aMarkup.Truncate(); + aInnerHTML.Truncate(); nsIDocument* doc = OwnerDoc(); + nsresult rv = NS_OK; + nsAutoString contentType; if (IsInHTMLDocument()) { contentType.AssignLiteral("text/html"); @@ -697,37 +698,21 @@ nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup) NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - nsresult rv = docEncoder->NativeInit(doc, contentType, - nsIDocumentEncoder::OutputEncodeBasicEntities | - // Output DOM-standard newlines - nsIDocumentEncoder::OutputLFLineBreak | - // Don't do linebreaking that's not present in - // the source - nsIDocumentEncoder::OutputRaw); + rv = docEncoder->NativeInit(doc, contentType, + nsIDocumentEncoder::OutputEncodeBasicEntities | + // Output DOM-standard newlines + nsIDocumentEncoder::OutputLFLineBreak | + // Don't do linebreaking that's not present in + // the source + nsIDocumentEncoder::OutputRaw); NS_ENSURE_SUCCESS(rv, rv); - if (aIncludeSelf) { - docEncoder->SetNativeNode(this); - } else { - docEncoder->SetNativeContainerNode(this); - } - rv = docEncoder->EncodeToString(aMarkup); - if (!aIncludeSelf) { - doc->SetCachedEncoder(docEncoder.forget()); - } + docEncoder->SetNativeContainerNode(this); + rv = docEncoder->EncodeToString(aInnerHTML); + doc->SetCachedEncoder(docEncoder.forget()); return rv; } -nsresult -nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) { - return GetMarkup(false, aInnerHTML); -} - -NS_IMETHODIMP -nsGenericHTMLElement::GetOuterHTML(nsAString& aOuterHTML) { - return GetMarkup(true, aOuterHTML); -} - void nsGenericHTMLElement::FireMutationEventsForDirectParsing(nsIDocument* aDoc, nsIContent* aDest, @@ -755,6 +740,8 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) { nsIDocument* doc = OwnerDoc(); + nsresult rv = NS_OK; + // Batch possible DOMSubtreeModified events. mozAutoSubtreeModified subtree(doc, nsnull); @@ -771,7 +758,8 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) nsAutoScriptLoaderDisabler sld(doc); - nsresult rv = NS_OK; + nsCOMPtr df; + if (doc->IsHTML()) { PRInt32 oldChildCount = GetChildCount(); rv = nsContentUtils::ParseFragmentHTML(aInnerHTML, @@ -784,7 +772,6 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) // HTML5 parser has notified, but not fired mutation events. FireMutationEventsForDirectParsing(doc, this, oldChildCount); } else { - nsCOMPtr df; rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML, true, getter_AddRefs(df)); @@ -802,71 +789,6 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) return rv; } -NS_IMETHODIMP -nsGenericHTMLElement::SetOuterHTML(const nsAString& aOuterHTML) -{ - nsINode* parent = GetNodeParent(); - if (!parent) { - return NS_OK; - } - - if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) { - return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; - } - - if (OwnerDoc()->IsHTML()) { - nsIAtom* localName; - PRInt32 namespaceID; - if (parent->IsElement()) { - localName = static_cast(parent)->Tag(); - namespaceID = static_cast(parent)->GetNameSpaceID(); - } else { - NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, - "How come the parent isn't a document, a fragment or an element?"); - localName = nsGkAtoms::body; - namespaceID = kNameSpaceID_XHTML; - } - nsCOMPtr df; - nsresult rv = NS_NewDocumentFragment(getter_AddRefs(df), - OwnerDoc()->NodeInfoManager()); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr fragment = do_QueryInterface(df); - nsContentUtils::ParseFragmentHTML(aOuterHTML, - fragment, - localName, - namespaceID, - OwnerDoc()->GetCompatibilityMode() == - eCompatibility_NavQuirks, - PR_TRUE); - parent->ReplaceChild(fragment, this, &rv); - return rv; - } - - nsCOMPtr context; - if (parent->IsElement()) { - context = parent; - } else { - NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, - "How come the parent isn't a document, a fragment or an element?"); - nsCOMPtr info = - OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body, - nsnull, - kNameSpaceID_XHTML, - nsIDOMNode::ELEMENT_NODE); - context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT); - } - - nsCOMPtr df; - nsresult rv = nsContentUtils::CreateContextualFragment(context, - aOuterHTML, - PR_TRUE, - getter_AddRefs(df)); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr fragment = do_QueryInterface(df); - parent->ReplaceChild(fragment, this, &rv); - return rv; -} - enum nsAdjacentPosition { eBeforeBegin, eAfterBegin, diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 9172bc10438e..41641a2edc03 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -132,8 +132,6 @@ public: nsresult GetOffsetParent(nsIDOMElement** aOffsetParent); NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML); NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML); - NS_IMETHOD GetOuterHTML(nsAString& aOuterHTML); - NS_IMETHOD SetOuterHTML(const nsAString& aOuterHTML); NS_IMETHOD InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText); nsresult ScrollIntoView(bool aTop, PRUint8 optional_argc); @@ -163,10 +161,6 @@ public: nsresult ClearDataset(); nsresult GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu); -protected: - nsresult GetMarkup(bool aIncludeSelf, nsAString& aMarkup); - -public: // Implementation for nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -1577,12 +1571,6 @@ protected: NS_SCRIPTABLE NS_IMETHOD SetSpellcheck(bool aSpellcheck) { \ return _to SetSpellcheck(aSpellcheck); \ } \ - NS_SCRIPTABLE NS_IMETHOD GetOuterHTML(nsAString& aOuterHTML) { \ - return _to GetOuterHTML(aOuterHTML); \ - } \ - NS_SCRIPTABLE NS_IMETHOD SetOuterHTML(const nsAString& aOuterHTML) { \ - return _to SetOuterHTML(aOuterHTML); \ - } \ NS_SCRIPTABLE NS_IMETHOD InsertAdjacentHTML(const nsAString& position, const nsAString& text) { \ return _to InsertAdjacentHTML(position, text); \ } \ diff --git a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl b/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl index 040f5c8f15f1..cc493a375dfa 100644 --- a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(bcb54394-d9f8-4bcb-bbbb-eca9826cdbca)] +[scriptable, uuid(2da904fa-83da-426d-a320-a6868192583e)] interface nsIDOMHTMLAnchorElement : nsIDOMHTMLElement { attribute DOMString href; diff --git a/dom/interfaces/html/nsIDOMHTMLAppletElement.idl b/dom/interfaces/html/nsIDOMHTMLAppletElement.idl index 74a5f0c0ab89..2295977f495e 100644 --- a/dom/interfaces/html/nsIDOMHTMLAppletElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAppletElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a06bca18-791f-474e-a031-bf6c2bd14994)] +[scriptable, uuid(c874e500-a185-4d69-96dd-474d1137e21f)] interface nsIDOMHTMLAppletElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLAreaElement.idl b/dom/interfaces/html/nsIDOMHTMLAreaElement.idl index 07cd39176569..b5bdfaf74e2b 100644 --- a/dom/interfaces/html/nsIDOMHTMLAreaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAreaElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(7e607c36-aecc-4dee-a93a-95e22a374bfb)] +[scriptable, uuid(d88c8515-5a27-4955-8ca5-18c908433cfd)] interface nsIDOMHTMLAreaElement : nsIDOMHTMLElement { attribute DOMString alt; diff --git a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl index 4ebee6b48374..95d99c8ab847 100644 --- a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl @@ -52,7 +52,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(756e2792-b937-4a70-bd1f-9d6820473e7e)] +[scriptable, uuid(f4115c13-bc51-4c3b-a5c0-9106af9f7368)] interface nsIDOMHTMLAudioElement : nsIDOMHTMLMediaElement { // Setup the audio stream for writing diff --git a/dom/interfaces/html/nsIDOMHTMLBRElement.idl b/dom/interfaces/html/nsIDOMHTMLBRElement.idl index bef88132df01..8c8bb6d785ea 100644 --- a/dom/interfaces/html/nsIDOMHTMLBRElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBRElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(7eefd466-7c4d-499a-a076-e33204e69dc3)] +[scriptable, uuid(a4f319d7-442d-4154-8c60-b9acdca87523)] interface nsIDOMHTMLBRElement : nsIDOMHTMLElement { attribute DOMString clear; diff --git a/dom/interfaces/html/nsIDOMHTMLBaseElement.idl b/dom/interfaces/html/nsIDOMHTMLBaseElement.idl index 1de84be9b9be..2b6bdfd407fe 100644 --- a/dom/interfaces/html/nsIDOMHTMLBaseElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBaseElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e55cd224-b603-4976-892a-20b11d469394)] +[scriptable, uuid(1ba4957f-629e-4410-b5fd-64f2b7eeb32c)] interface nsIDOMHTMLBaseElement : nsIDOMHTMLElement { attribute DOMString href; diff --git a/dom/interfaces/html/nsIDOMHTMLBodyElement.idl b/dom/interfaces/html/nsIDOMHTMLBodyElement.idl index 5f4e595e166f..b4623b175cd7 100644 --- a/dom/interfaces/html/nsIDOMHTMLBodyElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBodyElement.idl @@ -54,7 +54,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6c377d44-a5d1-4f0f-860a-9858d2cb5679)] +[scriptable, uuid(dcf343a9-fa7f-4e16-b122-0ece0d8bdea9)] interface nsIDOMHTMLBodyElement : nsIDOMHTMLElement { attribute DOMString aLink; diff --git a/dom/interfaces/html/nsIDOMHTMLButtonElement.idl b/dom/interfaces/html/nsIDOMHTMLButtonElement.idl index b454007d275f..b38f649b53fe 100644 --- a/dom/interfaces/html/nsIDOMHTMLButtonElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLButtonElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(79f034f0-5c13-4101-9598-412e1eac1986)] +[scriptable, uuid(4b48e075-a05b-480f-9e37-fcd88e7aebdd)] interface nsIDOMHTMLButtonElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl index f19a8f46d18a..8d01e765548a 100644 --- a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl @@ -55,7 +55,7 @@ interface nsIDOMFile; interface nsIVariant; -[scriptable, uuid(dbbeeba1-3c20-4d9d-ac82-98b69fd819a9)] +[scriptable, uuid(e1ea26e6-4141-487f-a9cf-d7e9344b571c)] interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement { attribute unsigned long width; diff --git a/dom/interfaces/html/nsIDOMHTMLCommandElement.idl b/dom/interfaces/html/nsIDOMHTMLCommandElement.idl index e8efab96b5f8..527f0d596e26 100644 --- a/dom/interfaces/html/nsIDOMHTMLCommandElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLCommandElement.idl @@ -46,7 +46,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(13032f74-4150-4768-ab5e-51f4de39a300)] +[scriptable, uuid(4c466da8-5c6d-427f-95f5-bba96ab99c96)] interface nsIDOMHTMLCommandElement : nsIDOMHTMLElement { attribute DOMString type; diff --git a/dom/interfaces/html/nsIDOMHTMLDListElement.idl b/dom/interfaces/html/nsIDOMHTMLDListElement.idl index e3ad0fcc13f7..f4d6c282169f 100644 --- a/dom/interfaces/html/nsIDOMHTMLDListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(50e9ff30-0982-4074-bc65-313f41be8624)] +[scriptable, uuid(f3e65e2b-e079-4970-bb5d-f96ac9cd18c5)] interface nsIDOMHTMLDListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLDataListElement.idl b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl index 4496b81c73b6..0a92f6b07880 100644 --- a/dom/interfaces/html/nsIDOMHTMLDataListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl @@ -49,7 +49,7 @@ interface nsIDOMHTMLCollection; -[scriptable, uuid(3bace78b-9eca-4990-a5d6-9c2b8c32cc8a)] +[scriptable, uuid(312ed7c1-8c62-4d80-bbd9-99d7ea4377e6)] interface nsIDOMHTMLDataListElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLCollection options; diff --git a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl index 184e6bb54151..aed3d77dc1f6 100644 --- a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a99e86ae-7761-4145-b8a4-5a91186051f1)] +[scriptable, uuid(1e04cd43-edc0-4658-bd77-d67661af6c9c)] interface nsIDOMHTMLDirectoryElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLDivElement.idl b/dom/interfaces/html/nsIDOMHTMLDivElement.idl index c8369f740813..b0fdcb046fa2 100644 --- a/dom/interfaces/html/nsIDOMHTMLDivElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDivElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6815b902-8e04-49dd-977b-0a8785e5ffaf)] +[scriptable, uuid(771be9ee-b883-4556-bf90-2d7c904fe94d)] interface nsIDOMHTMLDivElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLElement.idl b/dom/interfaces/html/nsIDOMHTMLElement.idl index 78cd0756eb16..12397ba470f9 100644 --- a/dom/interfaces/html/nsIDOMHTMLElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLElement.idl @@ -53,7 +53,7 @@ interface nsIDOMHTMLMenuElement; * with changes from the work-in-progress WHATWG HTML specification: * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(4eccf8a3-8bf5-43f3-a728-f5b632f7db3a)] +[scriptable, uuid(0a21bb68-d8bd-4b2a-a3db-048a02e81c62)] interface nsIDOMHTMLElement : nsIDOMElement { // metadata attributes @@ -86,7 +86,6 @@ interface nsIDOMHTMLElement : nsIDOMElement // DOM Parsing and Serialization attribute DOMString innerHTML; - attribute DOMString outerHTML; void insertAdjacentHTML(in DOMString position, in DOMString text); diff --git a/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl b/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl index 9546df2aaadf..76ba843a7c43 100644 --- a/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl @@ -47,7 +47,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/#the-embed-element */ -[scriptable, uuid(940a15c2-0d48-4186-b4d8-067fa1ce5675)] +[scriptable, uuid(d6309fc7-e9d2-4087-b452-490ed84f2dc2)] interface nsIDOMHTMLEmbedElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl b/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl index d5905ebc6b46..8f37aabdbcbf 100644 --- a/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(781ae103-b030-4aad-b2d5-96e5c2317dec)] +[scriptable, uuid(e153c20e-7a3d-4184-865c-ee7c6d9b65df)] interface nsIDOMHTMLFieldSetElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLFontElement.idl b/dom/interfaces/html/nsIDOMHTMLFontElement.idl index 7648bf8961a0..994a74ddb4c1 100644 --- a/dom/interfaces/html/nsIDOMHTMLFontElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFontElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(1c9778ee-a49c-40ee-9b93-c0ff15630431)] +[scriptable, uuid(8a205975-86cb-44db-b20e-df7f2d200580)] interface nsIDOMHTMLFontElement : nsIDOMHTMLElement { attribute DOMString color; diff --git a/dom/interfaces/html/nsIDOMHTMLFormElement.idl b/dom/interfaces/html/nsIDOMHTMLFormElement.idl index 65fb4dfccaae..a93cc376626a 100644 --- a/dom/interfaces/html/nsIDOMHTMLFormElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFormElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d873b251-6f96-4e70-baf5-aaa935aabe59)] +[scriptable, uuid(8fe67952-6f7b-4d6e-b17b-79a454687e5f)] interface nsIDOMHTMLFormElement : nsIDOMHTMLElement { attribute DOMString acceptCharset; diff --git a/dom/interfaces/html/nsIDOMHTMLFrameElement.idl b/dom/interfaces/html/nsIDOMHTMLFrameElement.idl index dab1a4de2aeb..90752d2e8e06 100644 --- a/dom/interfaces/html/nsIDOMHTMLFrameElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFrameElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(318fdc4a-3fca-4099-94aa-c9a1c30ca2b9)] +[scriptable, uuid(6de9d59d-42fd-44df-bb41-22cd64a85d4f)] interface nsIDOMHTMLFrameElement : nsIDOMHTMLElement { attribute DOMString frameBorder; diff --git a/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl b/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl index 5747a276db79..7bff911baa94 100644 --- a/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl @@ -54,7 +54,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6eefbe6d-182c-42e9-9850-af1892b6f2e4)] +[scriptable, uuid(a9423392-0f92-4b25-8700-49d28752c092)] interface nsIDOMHTMLFrameSetElement : nsIDOMHTMLElement { attribute DOMString cols; diff --git a/dom/interfaces/html/nsIDOMHTMLHRElement.idl b/dom/interfaces/html/nsIDOMHTMLHRElement.idl index ac338fdc7d2b..b5977327bf80 100644 --- a/dom/interfaces/html/nsIDOMHTMLHRElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHRElement.idl @@ -51,7 +51,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(b94bff8f-dfa7-4dd8-8d97-c301dd9de729)] +[scriptable, uuid(a6950d69-a376-4ad5-a911-8f91abb2b15d)] interface nsIDOMHTMLHRElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLHeadElement.idl b/dom/interfaces/html/nsIDOMHTMLHeadElement.idl index 4d7600fe9bfc..c017ac292fe4 100644 --- a/dom/interfaces/html/nsIDOMHTMLHeadElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHeadElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(628fe597-6408-4387-9fcb-75381e2b2dd0)] +[scriptable, uuid(6d049c37-2cee-4c04-816c-270973e58ccf)] interface nsIDOMHTMLHeadElement : nsIDOMHTMLElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl index 0d7265080c2e..e3bf581f6d3c 100644 --- a/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(964c94b0-5571-44e7-9b29-f81c6ea7828a)] +[scriptable, uuid(c3c30a05-1dc0-413a-85f6-3c4d5af5f2b6)] interface nsIDOMHTMLHeadingElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl b/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl index f7459ab2ac0d..420570c389b8 100644 --- a/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(4bafbc15-aa88-4021-9ad6-e14189b7227b)] +[scriptable, uuid(84825a7d-d5c7-4b1a-9d2a-b3e5df055824)] interface nsIDOMHTMLHtmlElement : nsIDOMHTMLElement { attribute DOMString version; diff --git a/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl b/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl index 759a5f481a56..bcfdd797ba41 100644 --- a/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(5ef30718-fe45-43a2-a478-a9e3cbf3a118)] +[scriptable, uuid(166c1cdb-9af5-4217-9a2f-f9dae0923e85)] interface nsIDOMHTMLIFrameElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLImageElement.idl b/dom/interfaces/html/nsIDOMHTMLImageElement.idl index 9c04b214e060..d5d039494b4e 100644 --- a/dom/interfaces/html/nsIDOMHTMLImageElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLImageElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(56d9191f-5a94-432f-af70-6fccdeaf614b)] +[scriptable, uuid(02dbe3c7-e75e-4a35-989c-b6f6d7a3108f)] interface nsIDOMHTMLImageElement : nsIDOMHTMLElement { attribute DOMString alt; diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 2b81463e4097..6ecc4215c119 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -54,7 +54,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(7330cd35-c930-4f45-ae61-f5380c30222d)] +[scriptable, uuid(81cc1b30-02e1-4779-ac9e-0091933478a4)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; diff --git a/dom/interfaces/html/nsIDOMHTMLLIElement.idl b/dom/interfaces/html/nsIDOMHTMLLIElement.idl index 5b8b0135a51c..a4c3180708a8 100644 --- a/dom/interfaces/html/nsIDOMHTMLLIElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLIElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(85b15d13-be6d-4653-9c70-22a13d510247)] +[scriptable, uuid(cb9bbac6-3198-4159-9ee9-262eef35f265)] interface nsIDOMHTMLLIElement : nsIDOMHTMLElement { attribute DOMString type; diff --git a/dom/interfaces/html/nsIDOMHTMLLabelElement.idl b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl index 3cb02ca6c3f1..0557647b51cc 100644 --- a/dom/interfaces/html/nsIDOMHTMLLabelElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(ddbca449-625d-467c-a22d-7887474f9eb9)] +[scriptable, uuid(0c36c887-04e3-4926-a916-8e3596130f9a)] interface nsIDOMHTMLLabelElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLLegendElement.idl b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl index b3a57b6f2905..f9b33d773375 100644 --- a/dom/interfaces/html/nsIDOMHTMLLegendElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(dac72753-6919-414b-b771-9e1e86e7749c)] +[scriptable, uuid(cabacc5f-5179-4c97-be60-0af8feafb4c9)] interface nsIDOMHTMLLegendElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl b/dom/interfaces/html/nsIDOMHTMLLinkElement.idl index f1f56d7ed9f2..dc79e285df4a 100644 --- a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLinkElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(2ece79f4-83d7-499c-946f-ae9ab93147b7)] +[scriptable, uuid(2f238f84-1b45-4ef9-9cda-bd1430ce9304)] interface nsIDOMHTMLLinkElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLMapElement.idl b/dom/interfaces/html/nsIDOMHTMLMapElement.idl index 904847b7e0d5..da0736fb208c 100644 --- a/dom/interfaces/html/nsIDOMHTMLMapElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMapElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c919bc49-bd49-4b89-ba70-5c74c4ef504a)] +[scriptable, uuid(3fb8ec10-8778-418d-9c83-556e46f115a9)] interface nsIDOMHTMLMapElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLCollection areas; diff --git a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl index 785550892d0a..d9f673156659 100644 --- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl @@ -57,7 +57,7 @@ #endif %} -[scriptable, uuid(642a3b85-4edb-4c01-a162-06b5d88171e7)] +[scriptable, uuid(85baaa10-73ab-4a48-a57a-b3951b67e494)] interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement { // error state diff --git a/dom/interfaces/html/nsIDOMHTMLMenuElement.idl b/dom/interfaces/html/nsIDOMHTMLMenuElement.idl index d4eb205997be..1e227250daff 100644 --- a/dom/interfaces/html/nsIDOMHTMLMenuElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMenuElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(06d48250-45e0-4f26-9a07-d9b5a3f08bb6)] +[scriptable, uuid(12de9196-b164-43e0-9347-f23e1bffbede)] interface nsIDOMHTMLMenuElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl b/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl index 1cc730b87a69..7b11b7c3a037 100644 --- a/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl @@ -43,7 +43,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(4680ec24-94f0-4eb7-9413-98f9a857de72)] +[scriptable, uuid(e0469d92-a137-4329-9d4b-9f2ba5ce8e77)] interface nsIDOMHTMLMenuItemElement : nsIDOMHTMLCommandElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLMetaElement.idl b/dom/interfaces/html/nsIDOMHTMLMetaElement.idl index b74cfc89cc64..28d737c2ed33 100644 --- a/dom/interfaces/html/nsIDOMHTMLMetaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMetaElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(db476657-5f59-4e29-84a6-50afe6f85ac7)] +[scriptable, uuid(c883b92b-5ae0-4563-894a-fa7f0e9aacda)] interface nsIDOMHTMLMetaElement : nsIDOMHTMLElement { attribute DOMString content; diff --git a/dom/interfaces/html/nsIDOMHTMLModElement.idl b/dom/interfaces/html/nsIDOMHTMLModElement.idl index fcb9e99895c9..c10055044de7 100644 --- a/dom/interfaces/html/nsIDOMHTMLModElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLModElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(170733d4-aad5-4f6e-86c0-94845ea6116d)] +[scriptable, uuid(417626fa-191c-41e5-aed5-f6157b408e72)] interface nsIDOMHTMLModElement : nsIDOMHTMLElement { attribute DOMString cite; diff --git a/dom/interfaces/html/nsIDOMHTMLOListElement.idl b/dom/interfaces/html/nsIDOMHTMLOListElement.idl index 989aa350570e..b8c9c184cb6c 100644 --- a/dom/interfaces/html/nsIDOMHTMLOListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(31a5f083-59a6-41c3-8a0b-e58e484c6516)] +[scriptable, uuid(11e66686-b1ef-47be-9025-ffc20b875e4a)] interface nsIDOMHTMLOListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLObjectElement.idl b/dom/interfaces/html/nsIDOMHTMLObjectElement.idl index ae2c09b996e2..ff86e566c61b 100644 --- a/dom/interfaces/html/nsIDOMHTMLObjectElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLObjectElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(40037f4a-5bae-476f-977b-bbd8e78aaefe)] +[scriptable, uuid(5d873128-d4e3-4e89-8900-599155167105)] interface nsIDOMHTMLObjectElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl b/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl index 77c3f6e863fa..9865c534bc2b 100644 --- a/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(ab55d67a-aabb-4441-b182-8ff2bd7d157e)] +[scriptable, uuid(7b585d49-1da3-4fc6-a50c-b661063c2edc)] interface nsIDOMHTMLOptGroupElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLOptionElement.idl b/dom/interfaces/html/nsIDOMHTMLOptionElement.idl index 814046266eac..c5451316161a 100644 --- a/dom/interfaces/html/nsIDOMHTMLOptionElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOptionElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(7c5bf0ac-6230-4ee0-8b82-e7ebf211af03)] +[scriptable, uuid(c20ead8a-cb89-43b1-89ed-8f4713bf8452)] interface nsIDOMHTMLOptionElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLOutputElement.idl b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl index 9e3d17cbb43c..c348a5b23146 100644 --- a/dom/interfaces/html/nsIDOMHTMLOutputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl @@ -50,7 +50,7 @@ interface nsIDOMDOMSettableTokenList; interface nsIDOMValidityState; -[scriptable, uuid(f2074cdb-19cb-447a-935c-9f4402dc1b5e)] +[scriptable, uuid(7d1fb2a9-7678-409e-8eb5-9216c47c233b)] interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement { readonly attribute nsIDOMDOMSettableTokenList htmlFor; diff --git a/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl b/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl index 6ff31c369ae4..3dd0608addbc 100644 --- a/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e4f498f4-e3c5-46fe-92d0-c9957ccab530)] +[scriptable, uuid(d5d3eb33-0925-4555-be2f-4078dec49f59)] interface nsIDOMHTMLParagraphElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLParamElement.idl b/dom/interfaces/html/nsIDOMHTMLParamElement.idl index fc76ad88c9d9..f39e07ede768 100644 --- a/dom/interfaces/html/nsIDOMHTMLParamElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLParamElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d832b1ac-9bb6-4df0-9d9e-f7c040759672)] +[scriptable, uuid(ccffedb8-f234-474e-9af4-576eba766023)] interface nsIDOMHTMLParamElement : nsIDOMHTMLElement { attribute DOMString name; diff --git a/dom/interfaces/html/nsIDOMHTMLPreElement.idl b/dom/interfaces/html/nsIDOMHTMLPreElement.idl index 462d9b91c251..78440bd96973 100644 --- a/dom/interfaces/html/nsIDOMHTMLPreElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLPreElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(f4088dff-649c-4eff-a3a4-dbd6333cdc44)] +[scriptable, uuid(c9d9b45a-e7d9-4dfb-abae-f3b9e6addbaa)] interface nsIDOMHTMLPreElement : nsIDOMHTMLElement { attribute long width; diff --git a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl index 24b584d78466..aa1db31233cf 100644 --- a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl @@ -47,7 +47,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(9b1d2263-b60f-4d18-b4d1-66e8c3867c79)] +[scriptable, uuid(aa830aa2-a4ea-455e-8285-8344cadb4c6d)] interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement { attribute double value; diff --git a/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl b/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl index c100f9090e3d..20e0ef6c4949 100644 --- a/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(55643647-2eda-4a45-af55-b2ba6c40c5f5)] +[scriptable, uuid(820ccd14-2479-4e4a-99d3-76d138caf7ec)] interface nsIDOMHTMLQuoteElement : nsIDOMHTMLElement { attribute DOMString cite; diff --git a/dom/interfaces/html/nsIDOMHTMLScriptElement.idl b/dom/interfaces/html/nsIDOMHTMLScriptElement.idl index 02a52c1486ab..8e7cf55a5a6e 100644 --- a/dom/interfaces/html/nsIDOMHTMLScriptElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLScriptElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(4b6a0957-5466-4134-8a0a-dd7e4675c106)] +[scriptable, uuid(e6252d3b-521a-4f79-9d57-2721a81e7cc2)] interface nsIDOMHTMLScriptElement : nsIDOMHTMLElement { attribute DOMString src; diff --git a/dom/interfaces/html/nsIDOMHTMLSelectElement.idl b/dom/interfaces/html/nsIDOMHTMLSelectElement.idl index 8034c29a916a..2a71f9f2df2a 100644 --- a/dom/interfaces/html/nsIDOMHTMLSelectElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLSelectElement.idl @@ -53,7 +53,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(98f111e0-2b7e-4abd-984b-2cc1d174fe44)] +[scriptable, uuid(30a948a3-61a0-453c-a1e4-de67a1664746)] interface nsIDOMHTMLSelectElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLSourceElement.idl b/dom/interfaces/html/nsIDOMHTMLSourceElement.idl index 4cf5f82416da..0cc0a6b1ca1a 100644 --- a/dom/interfaces/html/nsIDOMHTMLSourceElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLSourceElement.idl @@ -48,7 +48,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(c49d9a78-fa02-49c9-b239-9cd51e99f866)] +[scriptable, uuid(dcac4414-37e2-409f-b0a6-8231007e585b)] interface nsIDOMHTMLSourceElement : nsIDOMHTMLElement { attribute DOMString src; diff --git a/dom/interfaces/html/nsIDOMHTMLStyleElement.idl b/dom/interfaces/html/nsIDOMHTMLStyleElement.idl index 2ce7924082e6..41d4741d039e 100644 --- a/dom/interfaces/html/nsIDOMHTMLStyleElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLStyleElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(247fc8c4-92f3-427b-af6f-41b13f28287d)] +[scriptable, uuid(e72a6069-4987-480b-a349-ffd5fbebd59f)] interface nsIDOMHTMLStyleElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl b/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl index fecd4818488a..19dd09797264 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(db0e641f-ba2b-4c67-8da1-4e418cc5fbf7)] +[scriptable, uuid(cbd44d29-3120-470d-a7fb-fac4730c8b4b)] interface nsIDOMHTMLTableCaptionElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl index 2f91ade14a13..43a9133ffea3 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(4caa7af0-fec4-44c1-9a81-e1f14166e60c)] +[scriptable, uuid(03dd5118-7eaf-4bd3-a4a7-77f3f7eb8539)] interface nsIDOMHTMLTableCellElement : nsIDOMHTMLElement { readonly attribute long cellIndex; diff --git a/dom/interfaces/html/nsIDOMHTMLTableColElement.idl b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl index e82b5b5fb214..2573a0c9ccd7 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableColElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(9a4d1f6a-fb19-4886-b0d8-dcd201566580)] +[scriptable, uuid(d221534a-d13c-43b2-9ba0-7e0dd7452856)] interface nsIDOMHTMLTableColElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTableElement.idl b/dom/interfaces/html/nsIDOMHTMLTableElement.idl index e7724f3d98f3..3614a17a74ec 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(0f809b97-9311-45c4-a44e-7145f354438b)] +[scriptable, uuid(bba4b8b2-d01c-4c9b-abc8-3df28d048e68)] interface nsIDOMHTMLTableElement : nsIDOMHTMLElement { // Modified in DOM Level 2: diff --git a/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl index e6748b0cf673..f9aeed647f6d 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d24a80d4-491d-4e36-9349-afd3c6999b3e)] +[scriptable, uuid(b0199f36-9e76-4ec6-867f-850e388d6244)] interface nsIDOMHTMLTableRowElement : nsIDOMHTMLElement { // Modified in DOM Level 2: diff --git a/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl b/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl index 037f300de7dd..96facb0877c0 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6acc106e-96a2-4519-8f3a-142ebbdc1bb1)] +[scriptable, uuid(ac2e2719-71f1-4485-ac1e-694e7e49bd2a)] interface nsIDOMHTMLTableSectionElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl b/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl index ec65b72c4e19..fc78d04cf516 100644 --- a/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl @@ -53,7 +53,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(16db703d-4816-440c-bcb3-c1ae0cae6532)] +[scriptable, uuid(88d09917-d2da-4737-a887-277a2f9750c7)] interface nsIDOMHTMLTextAreaElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLTitleElement.idl b/dom/interfaces/html/nsIDOMHTMLTitleElement.idl index 305b773467c2..18345f1421ad 100644 --- a/dom/interfaces/html/nsIDOMHTMLTitleElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTitleElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e20fd651-6240-4f20-b8f0-6cc25cb699b7)] +[scriptable, uuid(5cb8cfaf-7551-422b-9b03-58d756e54339)] interface nsIDOMHTMLTitleElement : nsIDOMHTMLElement { attribute DOMString text; diff --git a/dom/interfaces/html/nsIDOMHTMLUListElement.idl b/dom/interfaces/html/nsIDOMHTMLUListElement.idl index 8ecf76e00e6c..313c2a16fa10 100644 --- a/dom/interfaces/html/nsIDOMHTMLUListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLUListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(2467d39c-2c30-407e-9b67-ea5f231b7809)] +[scriptable, uuid(1f409357-8cea-4f69-9f0c-4149886b63a1)] interface nsIDOMHTMLUListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl index 97809dbd594c..508930fd0d30 100644 --- a/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl @@ -43,7 +43,7 @@ * * @see */ -[scriptable, uuid(5f922c13-c2c1-4c49-b7c2-0e4e5c8e6860)] +[scriptable, uuid(0d69049f-8181-47f1-a7f7-e5417dd54136)] interface nsIDOMHTMLUnknownElement : nsIDOMHTMLElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl index 02c2bbbf8a2b..622eafe52946 100644 --- a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl @@ -48,7 +48,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(390b974b-1c3a-4700-8001-5ef832c4b4bf)] +[scriptable, uuid(5e1e4453-96fe-4cc0-9c32-7e9355b4f917)] interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement { attribute long width; diff --git a/dom/tests/mochitest/general/Makefile.in b/dom/tests/mochitest/general/Makefile.in index e35c278fad62..d548a8ebfbff 100644 --- a/dom/tests/mochitest/general/Makefile.in +++ b/dom/tests/mochitest/general/Makefile.in @@ -45,8 +45,6 @@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _TEST_FILES = \ - test_outerHTML.html \ - test_outerHTML.xhtml \ 497633.html \ 489127.html \ historyframes.html \ diff --git a/dom/tests/mochitest/general/test_outerHTML.html b/dom/tests/mochitest/general/test_outerHTML.html deleted file mode 100644 index dba259844232..000000000000 --- a/dom/tests/mochitest/general/test_outerHTML.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - Test for Bug 92264 - - - - -Mozilla Bug 92264 -

- -
-
-
- - diff --git a/dom/tests/mochitest/general/test_outerHTML.xhtml b/dom/tests/mochitest/general/test_outerHTML.xhtml deleted file mode 100644 index 46013deb0af9..000000000000 --- a/dom/tests/mochitest/general/test_outerHTML.xhtml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - Test for Bug 92264 - - - - -Mozilla Bug 92264 -

- -
-
-
- - From 3db3f98d07d266f27e9201c87ab9cfde6b5cf2d0 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Thu, 10 Nov 2011 14:02:22 +0200 Subject: [PATCH 03/38] Bug 92264 - Implement outerHTML. Part of the patch by Ms2ger. r=smaug. --- content/base/public/nsIDocumentEncoder.idl | 3 +- content/base/src/nsDocumentEncoder.cpp | 8 ++ .../html/content/src/nsGenericHTMLElement.cpp | 116 +++++++++++++++--- .../html/content/src/nsGenericHTMLElement.h | 12 ++ .../html/nsIDOMHTMLAnchorElement.idl | 2 +- .../html/nsIDOMHTMLAppletElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLAreaElement.idl | 2 +- .../html/nsIDOMHTMLAudioElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBRElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBaseElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLBodyElement.idl | 2 +- .../html/nsIDOMHTMLButtonElement.idl | 2 +- .../html/nsIDOMHTMLCanvasElement.idl | 2 +- .../html/nsIDOMHTMLCommandElement.idl | 2 +- .../html/nsIDOMHTMLDListElement.idl | 2 +- .../html/nsIDOMHTMLDataListElement.idl | 2 +- .../html/nsIDOMHTMLDirectoryElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLDivElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLElement.idl | 3 +- .../html/nsIDOMHTMLEmbedElement.idl | 2 +- .../html/nsIDOMHTMLFieldSetElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLFontElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLFormElement.idl | 2 +- .../html/nsIDOMHTMLFrameElement.idl | 2 +- .../html/nsIDOMHTMLFrameSetElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHRElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHeadElement.idl | 2 +- .../html/nsIDOMHTMLHeadingElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLHtmlElement.idl | 2 +- .../html/nsIDOMHTMLIFrameElement.idl | 2 +- .../html/nsIDOMHTMLImageElement.idl | 2 +- .../html/nsIDOMHTMLInputElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLLIElement.idl | 2 +- .../html/nsIDOMHTMLLabelElement.idl | 2 +- .../html/nsIDOMHTMLLegendElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLLinkElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMapElement.idl | 2 +- .../html/nsIDOMHTMLMediaElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMenuElement.idl | 2 +- .../html/nsIDOMHTMLMenuItemElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLMetaElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLModElement.idl | 2 +- .../html/nsIDOMHTMLOListElement.idl | 2 +- .../html/nsIDOMHTMLObjectElement.idl | 2 +- .../html/nsIDOMHTMLOptGroupElement.idl | 2 +- .../html/nsIDOMHTMLOptionElement.idl | 2 +- .../html/nsIDOMHTMLOutputElement.idl | 2 +- .../html/nsIDOMHTMLParagraphElement.idl | 2 +- .../html/nsIDOMHTMLParamElement.idl | 2 +- dom/interfaces/html/nsIDOMHTMLPreElement.idl | 2 +- .../html/nsIDOMHTMLProgressElement.idl | 2 +- .../html/nsIDOMHTMLQuoteElement.idl | 2 +- .../html/nsIDOMHTMLScriptElement.idl | 2 +- .../html/nsIDOMHTMLSelectElement.idl | 2 +- .../html/nsIDOMHTMLSourceElement.idl | 2 +- .../html/nsIDOMHTMLStyleElement.idl | 2 +- .../html/nsIDOMHTMLTableCaptionElem.idl | 2 +- .../html/nsIDOMHTMLTableCellElement.idl | 2 +- .../html/nsIDOMHTMLTableColElement.idl | 2 +- .../html/nsIDOMHTMLTableElement.idl | 2 +- .../html/nsIDOMHTMLTableRowElement.idl | 2 +- .../html/nsIDOMHTMLTableSectionElem.idl | 2 +- .../html/nsIDOMHTMLTextAreaElement.idl | 2 +- .../html/nsIDOMHTMLTitleElement.idl | 2 +- .../html/nsIDOMHTMLUListElement.idl | 2 +- .../html/nsIDOMHTMLUnknownElement.idl | 2 +- .../html/nsIDOMHTMLVideoElement.idl | 2 +- dom/tests/mochitest/general/Makefile.in | 2 + .../mochitest/general/test_outerHTML.html | 73 +++++++++++ .../mochitest/general/test_outerHTML.xhtml | 74 +++++++++++ 70 files changed, 332 insertions(+), 83 deletions(-) create mode 100644 dom/tests/mochitest/general/test_outerHTML.html create mode 100644 dom/tests/mochitest/general/test_outerHTML.xhtml diff --git a/content/base/public/nsIDocumentEncoder.idl b/content/base/public/nsIDocumentEncoder.idl index 13cadc20e924..6da4fbda80e5 100644 --- a/content/base/public/nsIDocumentEncoder.idl +++ b/content/base/public/nsIDocumentEncoder.idl @@ -51,7 +51,7 @@ class nsIDocument; [ptr] native nsINodePtr(nsINode); [ptr] native nsIDocumentPtr(nsIDocument); -[scriptable, uuid(c0da5b87-0ba7-4d7c-8cb3-fcb02af4253d)] +[scriptable, uuid(82adaeca-63ee-44eb-830a-e1678bb8745e)] interface nsIDocumentEncoderNodeFixup : nsISupports { /** @@ -272,6 +272,7 @@ interface nsIDocumentEncoder : nsISupports * @param aNode The node to encode. */ void setNode(in nsIDOMNode aNode); + [noscript] void setNativeNode(in nsINodePtr aNode); /** * If the container is set to a non-null value, then its diff --git a/content/base/src/nsDocumentEncoder.cpp b/content/base/src/nsDocumentEncoder.cpp index aa583313bdca..8b69baea6c3b 100644 --- a/content/base/src/nsDocumentEncoder.cpp +++ b/content/base/src/nsDocumentEncoder.cpp @@ -301,6 +301,14 @@ nsDocumentEncoder::SetNode(nsIDOMNode* aNode) return NS_OK; } +NS_IMETHODIMP +nsDocumentEncoder::SetNativeNode(nsINode* aNode) +{ + mNodeIsContainer = false; + mNode = aNode; + return NS_OK; +} + NS_IMETHODIMP nsDocumentEncoder::SetContainerNode(nsIDOMNode *aContainer) { diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index c764eaeb5b69..2b2f345bcc84 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -120,6 +120,7 @@ #include "nsPLDOMEvent.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/FromParser.h" using namespace mozilla; using namespace mozilla::dom; @@ -665,15 +666,13 @@ nsGenericHTMLElement::GetOffsetParent(nsIDOMElement** aOffsetParent) return NS_OK; } -NS_IMETHODIMP -nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) +nsresult +nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup) { - aInnerHTML.Truncate(); + aMarkup.Truncate(); nsIDocument* doc = OwnerDoc(); - nsresult rv = NS_OK; - nsAutoString contentType; if (IsInHTMLDocument()) { contentType.AssignLiteral("text/html"); @@ -698,21 +697,37 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - rv = docEncoder->NativeInit(doc, contentType, - nsIDocumentEncoder::OutputEncodeBasicEntities | - // Output DOM-standard newlines - nsIDocumentEncoder::OutputLFLineBreak | - // Don't do linebreaking that's not present in - // the source - nsIDocumentEncoder::OutputRaw); + nsresult rv = docEncoder->NativeInit(doc, contentType, + nsIDocumentEncoder::OutputEncodeBasicEntities | + // Output DOM-standard newlines + nsIDocumentEncoder::OutputLFLineBreak | + // Don't do linebreaking that's not present in + // the source + nsIDocumentEncoder::OutputRaw); NS_ENSURE_SUCCESS(rv, rv); - docEncoder->SetNativeContainerNode(this); - rv = docEncoder->EncodeToString(aInnerHTML); - doc->SetCachedEncoder(docEncoder.forget()); + if (aIncludeSelf) { + docEncoder->SetNativeNode(this); + } else { + docEncoder->SetNativeContainerNode(this); + } + rv = docEncoder->EncodeToString(aMarkup); + if (!aIncludeSelf) { + doc->SetCachedEncoder(docEncoder.forget()); + } return rv; } +nsresult +nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) { + return GetMarkup(false, aInnerHTML); +} + +NS_IMETHODIMP +nsGenericHTMLElement::GetOuterHTML(nsAString& aOuterHTML) { + return GetMarkup(true, aOuterHTML); +} + void nsGenericHTMLElement::FireMutationEventsForDirectParsing(nsIDocument* aDoc, nsIContent* aDest, @@ -740,8 +755,6 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) { nsIDocument* doc = OwnerDoc(); - nsresult rv = NS_OK; - // Batch possible DOMSubtreeModified events. mozAutoSubtreeModified subtree(doc, nsnull); @@ -758,8 +771,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) nsAutoScriptLoaderDisabler sld(doc); - nsCOMPtr df; - + nsresult rv = NS_OK; if (doc->IsHTML()) { PRInt32 oldChildCount = GetChildCount(); rv = nsContentUtils::ParseFragmentHTML(aInnerHTML, @@ -772,6 +784,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) // HTML5 parser has notified, but not fired mutation events. FireMutationEventsForDirectParsing(doc, this, oldChildCount); } else { + nsCOMPtr df; rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML, true, getter_AddRefs(df)); @@ -789,6 +802,71 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) return rv; } +NS_IMETHODIMP +nsGenericHTMLElement::SetOuterHTML(const nsAString& aOuterHTML) +{ + nsINode* parent = GetNodeParent(); + if (!parent) { + return NS_OK; + } + + if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) { + return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; + } + + if (OwnerDoc()->IsHTML()) { + nsIAtom* localName; + PRInt32 namespaceID; + if (parent->IsElement()) { + localName = static_cast(parent)->Tag(); + namespaceID = static_cast(parent)->GetNameSpaceID(); + } else { + NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, + "How come the parent isn't a document, a fragment or an element?"); + localName = nsGkAtoms::body; + namespaceID = kNameSpaceID_XHTML; + } + nsCOMPtr df; + nsresult rv = NS_NewDocumentFragment(getter_AddRefs(df), + OwnerDoc()->NodeInfoManager()); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr fragment = do_QueryInterface(df); + nsContentUtils::ParseFragmentHTML(aOuterHTML, + fragment, + localName, + namespaceID, + OwnerDoc()->GetCompatibilityMode() == + eCompatibility_NavQuirks, + PR_TRUE); + parent->ReplaceChild(fragment, this, &rv); + return rv; + } + + nsCOMPtr context; + if (parent->IsElement()) { + context = parent; + } else { + NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, + "How come the parent isn't a document, a fragment or an element?"); + nsCOMPtr info = + OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body, + nsnull, + kNameSpaceID_XHTML, + nsIDOMNode::ELEMENT_NODE); + context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT); + } + + nsCOMPtr df; + nsresult rv = nsContentUtils::CreateContextualFragment(context, + aOuterHTML, + PR_TRUE, + getter_AddRefs(df)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr fragment = do_QueryInterface(df); + parent->ReplaceChild(fragment, this, &rv); + return rv; +} + enum nsAdjacentPosition { eBeforeBegin, eAfterBegin, diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 41641a2edc03..9172bc10438e 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -132,6 +132,8 @@ public: nsresult GetOffsetParent(nsIDOMElement** aOffsetParent); NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML); NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML); + NS_IMETHOD GetOuterHTML(nsAString& aOuterHTML); + NS_IMETHOD SetOuterHTML(const nsAString& aOuterHTML); NS_IMETHOD InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText); nsresult ScrollIntoView(bool aTop, PRUint8 optional_argc); @@ -161,6 +163,10 @@ public: nsresult ClearDataset(); nsresult GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu); +protected: + nsresult GetMarkup(bool aIncludeSelf, nsAString& aMarkup); + +public: // Implementation for nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -1571,6 +1577,12 @@ protected: NS_SCRIPTABLE NS_IMETHOD SetSpellcheck(bool aSpellcheck) { \ return _to SetSpellcheck(aSpellcheck); \ } \ + NS_SCRIPTABLE NS_IMETHOD GetOuterHTML(nsAString& aOuterHTML) { \ + return _to GetOuterHTML(aOuterHTML); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetOuterHTML(const nsAString& aOuterHTML) { \ + return _to SetOuterHTML(aOuterHTML); \ + } \ NS_SCRIPTABLE NS_IMETHOD InsertAdjacentHTML(const nsAString& position, const nsAString& text) { \ return _to InsertAdjacentHTML(position, text); \ } \ diff --git a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl b/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl index cc493a375dfa..040f5c8f15f1 100644 --- a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(2da904fa-83da-426d-a320-a6868192583e)] +[scriptable, uuid(bcb54394-d9f8-4bcb-bbbb-eca9826cdbca)] interface nsIDOMHTMLAnchorElement : nsIDOMHTMLElement { attribute DOMString href; diff --git a/dom/interfaces/html/nsIDOMHTMLAppletElement.idl b/dom/interfaces/html/nsIDOMHTMLAppletElement.idl index 2295977f495e..74a5f0c0ab89 100644 --- a/dom/interfaces/html/nsIDOMHTMLAppletElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAppletElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c874e500-a185-4d69-96dd-474d1137e21f)] +[scriptable, uuid(a06bca18-791f-474e-a031-bf6c2bd14994)] interface nsIDOMHTMLAppletElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLAreaElement.idl b/dom/interfaces/html/nsIDOMHTMLAreaElement.idl index b5bdfaf74e2b..07cd39176569 100644 --- a/dom/interfaces/html/nsIDOMHTMLAreaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAreaElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d88c8515-5a27-4955-8ca5-18c908433cfd)] +[scriptable, uuid(7e607c36-aecc-4dee-a93a-95e22a374bfb)] interface nsIDOMHTMLAreaElement : nsIDOMHTMLElement { attribute DOMString alt; diff --git a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl index 95d99c8ab847..4ebee6b48374 100644 --- a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl @@ -52,7 +52,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(f4115c13-bc51-4c3b-a5c0-9106af9f7368)] +[scriptable, uuid(756e2792-b937-4a70-bd1f-9d6820473e7e)] interface nsIDOMHTMLAudioElement : nsIDOMHTMLMediaElement { // Setup the audio stream for writing diff --git a/dom/interfaces/html/nsIDOMHTMLBRElement.idl b/dom/interfaces/html/nsIDOMHTMLBRElement.idl index 8c8bb6d785ea..bef88132df01 100644 --- a/dom/interfaces/html/nsIDOMHTMLBRElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBRElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a4f319d7-442d-4154-8c60-b9acdca87523)] +[scriptable, uuid(7eefd466-7c4d-499a-a076-e33204e69dc3)] interface nsIDOMHTMLBRElement : nsIDOMHTMLElement { attribute DOMString clear; diff --git a/dom/interfaces/html/nsIDOMHTMLBaseElement.idl b/dom/interfaces/html/nsIDOMHTMLBaseElement.idl index 2b6bdfd407fe..1de84be9b9be 100644 --- a/dom/interfaces/html/nsIDOMHTMLBaseElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBaseElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(1ba4957f-629e-4410-b5fd-64f2b7eeb32c)] +[scriptable, uuid(e55cd224-b603-4976-892a-20b11d469394)] interface nsIDOMHTMLBaseElement : nsIDOMHTMLElement { attribute DOMString href; diff --git a/dom/interfaces/html/nsIDOMHTMLBodyElement.idl b/dom/interfaces/html/nsIDOMHTMLBodyElement.idl index b4623b175cd7..5f4e595e166f 100644 --- a/dom/interfaces/html/nsIDOMHTMLBodyElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLBodyElement.idl @@ -54,7 +54,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(dcf343a9-fa7f-4e16-b122-0ece0d8bdea9)] +[scriptable, uuid(6c377d44-a5d1-4f0f-860a-9858d2cb5679)] interface nsIDOMHTMLBodyElement : nsIDOMHTMLElement { attribute DOMString aLink; diff --git a/dom/interfaces/html/nsIDOMHTMLButtonElement.idl b/dom/interfaces/html/nsIDOMHTMLButtonElement.idl index b38f649b53fe..b454007d275f 100644 --- a/dom/interfaces/html/nsIDOMHTMLButtonElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLButtonElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(4b48e075-a05b-480f-9e37-fcd88e7aebdd)] +[scriptable, uuid(79f034f0-5c13-4101-9598-412e1eac1986)] interface nsIDOMHTMLButtonElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl index 8d01e765548a..f19a8f46d18a 100644 --- a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl @@ -55,7 +55,7 @@ interface nsIDOMFile; interface nsIVariant; -[scriptable, uuid(e1ea26e6-4141-487f-a9cf-d7e9344b571c)] +[scriptable, uuid(dbbeeba1-3c20-4d9d-ac82-98b69fd819a9)] interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement { attribute unsigned long width; diff --git a/dom/interfaces/html/nsIDOMHTMLCommandElement.idl b/dom/interfaces/html/nsIDOMHTMLCommandElement.idl index 527f0d596e26..e8efab96b5f8 100644 --- a/dom/interfaces/html/nsIDOMHTMLCommandElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLCommandElement.idl @@ -46,7 +46,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(4c466da8-5c6d-427f-95f5-bba96ab99c96)] +[scriptable, uuid(13032f74-4150-4768-ab5e-51f4de39a300)] interface nsIDOMHTMLCommandElement : nsIDOMHTMLElement { attribute DOMString type; diff --git a/dom/interfaces/html/nsIDOMHTMLDListElement.idl b/dom/interfaces/html/nsIDOMHTMLDListElement.idl index f4d6c282169f..e3ad0fcc13f7 100644 --- a/dom/interfaces/html/nsIDOMHTMLDListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(f3e65e2b-e079-4970-bb5d-f96ac9cd18c5)] +[scriptable, uuid(50e9ff30-0982-4074-bc65-313f41be8624)] interface nsIDOMHTMLDListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLDataListElement.idl b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl index 0a92f6b07880..4496b81c73b6 100644 --- a/dom/interfaces/html/nsIDOMHTMLDataListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl @@ -49,7 +49,7 @@ interface nsIDOMHTMLCollection; -[scriptable, uuid(312ed7c1-8c62-4d80-bbd9-99d7ea4377e6)] +[scriptable, uuid(3bace78b-9eca-4990-a5d6-9c2b8c32cc8a)] interface nsIDOMHTMLDataListElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLCollection options; diff --git a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl index aed3d77dc1f6..184e6bb54151 100644 --- a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(1e04cd43-edc0-4658-bd77-d67661af6c9c)] +[scriptable, uuid(a99e86ae-7761-4145-b8a4-5a91186051f1)] interface nsIDOMHTMLDirectoryElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLDivElement.idl b/dom/interfaces/html/nsIDOMHTMLDivElement.idl index b0fdcb046fa2..c8369f740813 100644 --- a/dom/interfaces/html/nsIDOMHTMLDivElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLDivElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(771be9ee-b883-4556-bf90-2d7c904fe94d)] +[scriptable, uuid(6815b902-8e04-49dd-977b-0a8785e5ffaf)] interface nsIDOMHTMLDivElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLElement.idl b/dom/interfaces/html/nsIDOMHTMLElement.idl index 12397ba470f9..78cd0756eb16 100644 --- a/dom/interfaces/html/nsIDOMHTMLElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLElement.idl @@ -53,7 +53,7 @@ interface nsIDOMHTMLMenuElement; * with changes from the work-in-progress WHATWG HTML specification: * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(0a21bb68-d8bd-4b2a-a3db-048a02e81c62)] +[scriptable, uuid(4eccf8a3-8bf5-43f3-a728-f5b632f7db3a)] interface nsIDOMHTMLElement : nsIDOMElement { // metadata attributes @@ -86,6 +86,7 @@ interface nsIDOMHTMLElement : nsIDOMElement // DOM Parsing and Serialization attribute DOMString innerHTML; + attribute DOMString outerHTML; void insertAdjacentHTML(in DOMString position, in DOMString text); diff --git a/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl b/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl index 76ba843a7c43..9546df2aaadf 100644 --- a/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLEmbedElement.idl @@ -47,7 +47,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/#the-embed-element */ -[scriptable, uuid(d6309fc7-e9d2-4087-b452-490ed84f2dc2)] +[scriptable, uuid(940a15c2-0d48-4186-b4d8-067fa1ce5675)] interface nsIDOMHTMLEmbedElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl b/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl index 8f37aabdbcbf..d5905ebc6b46 100644 --- a/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(e153c20e-7a3d-4184-865c-ee7c6d9b65df)] +[scriptable, uuid(781ae103-b030-4aad-b2d5-96e5c2317dec)] interface nsIDOMHTMLFieldSetElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLFontElement.idl b/dom/interfaces/html/nsIDOMHTMLFontElement.idl index 994a74ddb4c1..7648bf8961a0 100644 --- a/dom/interfaces/html/nsIDOMHTMLFontElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFontElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(8a205975-86cb-44db-b20e-df7f2d200580)] +[scriptable, uuid(1c9778ee-a49c-40ee-9b93-c0ff15630431)] interface nsIDOMHTMLFontElement : nsIDOMHTMLElement { attribute DOMString color; diff --git a/dom/interfaces/html/nsIDOMHTMLFormElement.idl b/dom/interfaces/html/nsIDOMHTMLFormElement.idl index a93cc376626a..65fb4dfccaae 100644 --- a/dom/interfaces/html/nsIDOMHTMLFormElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFormElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(8fe67952-6f7b-4d6e-b17b-79a454687e5f)] +[scriptable, uuid(d873b251-6f96-4e70-baf5-aaa935aabe59)] interface nsIDOMHTMLFormElement : nsIDOMHTMLElement { attribute DOMString acceptCharset; diff --git a/dom/interfaces/html/nsIDOMHTMLFrameElement.idl b/dom/interfaces/html/nsIDOMHTMLFrameElement.idl index 90752d2e8e06..dab1a4de2aeb 100644 --- a/dom/interfaces/html/nsIDOMHTMLFrameElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFrameElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6de9d59d-42fd-44df-bb41-22cd64a85d4f)] +[scriptable, uuid(318fdc4a-3fca-4099-94aa-c9a1c30ca2b9)] interface nsIDOMHTMLFrameElement : nsIDOMHTMLElement { attribute DOMString frameBorder; diff --git a/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl b/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl index 7bff911baa94..5747a276db79 100644 --- a/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl @@ -54,7 +54,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a9423392-0f92-4b25-8700-49d28752c092)] +[scriptable, uuid(6eefbe6d-182c-42e9-9850-af1892b6f2e4)] interface nsIDOMHTMLFrameSetElement : nsIDOMHTMLElement { attribute DOMString cols; diff --git a/dom/interfaces/html/nsIDOMHTMLHRElement.idl b/dom/interfaces/html/nsIDOMHTMLHRElement.idl index b5977327bf80..ac338fdc7d2b 100644 --- a/dom/interfaces/html/nsIDOMHTMLHRElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHRElement.idl @@ -51,7 +51,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(a6950d69-a376-4ad5-a911-8f91abb2b15d)] +[scriptable, uuid(b94bff8f-dfa7-4dd8-8d97-c301dd9de729)] interface nsIDOMHTMLHRElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLHeadElement.idl b/dom/interfaces/html/nsIDOMHTMLHeadElement.idl index c017ac292fe4..4d7600fe9bfc 100644 --- a/dom/interfaces/html/nsIDOMHTMLHeadElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHeadElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(6d049c37-2cee-4c04-816c-270973e58ccf)] +[scriptable, uuid(628fe597-6408-4387-9fcb-75381e2b2dd0)] interface nsIDOMHTMLHeadElement : nsIDOMHTMLElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl index e3bf581f6d3c..0d7265080c2e 100644 --- a/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c3c30a05-1dc0-413a-85f6-3c4d5af5f2b6)] +[scriptable, uuid(964c94b0-5571-44e7-9b29-f81c6ea7828a)] interface nsIDOMHTMLHeadingElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl b/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl index 420570c389b8..f7459ab2ac0d 100644 --- a/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLHtmlElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(84825a7d-d5c7-4b1a-9d2a-b3e5df055824)] +[scriptable, uuid(4bafbc15-aa88-4021-9ad6-e14189b7227b)] interface nsIDOMHTMLHtmlElement : nsIDOMHTMLElement { attribute DOMString version; diff --git a/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl b/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl index bcfdd797ba41..759a5f481a56 100644 --- a/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(166c1cdb-9af5-4217-9a2f-f9dae0923e85)] +[scriptable, uuid(5ef30718-fe45-43a2-a478-a9e3cbf3a118)] interface nsIDOMHTMLIFrameElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLImageElement.idl b/dom/interfaces/html/nsIDOMHTMLImageElement.idl index d5d039494b4e..9c04b214e060 100644 --- a/dom/interfaces/html/nsIDOMHTMLImageElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLImageElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(02dbe3c7-e75e-4a35-989c-b6f6d7a3108f)] +[scriptable, uuid(56d9191f-5a94-432f-af70-6fccdeaf614b)] interface nsIDOMHTMLImageElement : nsIDOMHTMLElement { attribute DOMString alt; diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 6ecc4215c119..2b81463e4097 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -54,7 +54,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(81cc1b30-02e1-4779-ac9e-0091933478a4)] +[scriptable, uuid(7330cd35-c930-4f45-ae61-f5380c30222d)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; diff --git a/dom/interfaces/html/nsIDOMHTMLLIElement.idl b/dom/interfaces/html/nsIDOMHTMLLIElement.idl index a4c3180708a8..5b8b0135a51c 100644 --- a/dom/interfaces/html/nsIDOMHTMLLIElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLIElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(cb9bbac6-3198-4159-9ee9-262eef35f265)] +[scriptable, uuid(85b15d13-be6d-4653-9c70-22a13d510247)] interface nsIDOMHTMLLIElement : nsIDOMHTMLElement { attribute DOMString type; diff --git a/dom/interfaces/html/nsIDOMHTMLLabelElement.idl b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl index 0557647b51cc..3cb02ca6c3f1 100644 --- a/dom/interfaces/html/nsIDOMHTMLLabelElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(0c36c887-04e3-4926-a916-8e3596130f9a)] +[scriptable, uuid(ddbca449-625d-467c-a22d-7887474f9eb9)] interface nsIDOMHTMLLabelElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLLegendElement.idl b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl index f9b33d773375..b3a57b6f2905 100644 --- a/dom/interfaces/html/nsIDOMHTMLLegendElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(cabacc5f-5179-4c97-be60-0af8feafb4c9)] +[scriptable, uuid(dac72753-6919-414b-b771-9e1e86e7749c)] interface nsIDOMHTMLLegendElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl b/dom/interfaces/html/nsIDOMHTMLLinkElement.idl index dc79e285df4a..f1f56d7ed9f2 100644 --- a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLLinkElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(2f238f84-1b45-4ef9-9cda-bd1430ce9304)] +[scriptable, uuid(2ece79f4-83d7-499c-946f-ae9ab93147b7)] interface nsIDOMHTMLLinkElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLMapElement.idl b/dom/interfaces/html/nsIDOMHTMLMapElement.idl index da0736fb208c..904847b7e0d5 100644 --- a/dom/interfaces/html/nsIDOMHTMLMapElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMapElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(3fb8ec10-8778-418d-9c83-556e46f115a9)] +[scriptable, uuid(c919bc49-bd49-4b89-ba70-5c74c4ef504a)] interface nsIDOMHTMLMapElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLCollection areas; diff --git a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl index d9f673156659..785550892d0a 100644 --- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl @@ -57,7 +57,7 @@ #endif %} -[scriptable, uuid(85baaa10-73ab-4a48-a57a-b3951b67e494)] +[scriptable, uuid(642a3b85-4edb-4c01-a162-06b5d88171e7)] interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement { // error state diff --git a/dom/interfaces/html/nsIDOMHTMLMenuElement.idl b/dom/interfaces/html/nsIDOMHTMLMenuElement.idl index 1e227250daff..d4eb205997be 100644 --- a/dom/interfaces/html/nsIDOMHTMLMenuElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMenuElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(12de9196-b164-43e0-9347-f23e1bffbede)] +[scriptable, uuid(06d48250-45e0-4f26-9a07-d9b5a3f08bb6)] interface nsIDOMHTMLMenuElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl b/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl index 7b11b7c3a037..1cc730b87a69 100644 --- a/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMenuItemElement.idl @@ -43,7 +43,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(e0469d92-a137-4329-9d4b-9f2ba5ce8e77)] +[scriptable, uuid(4680ec24-94f0-4eb7-9413-98f9a857de72)] interface nsIDOMHTMLMenuItemElement : nsIDOMHTMLCommandElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLMetaElement.idl b/dom/interfaces/html/nsIDOMHTMLMetaElement.idl index 28d737c2ed33..b74cfc89cc64 100644 --- a/dom/interfaces/html/nsIDOMHTMLMetaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMetaElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c883b92b-5ae0-4563-894a-fa7f0e9aacda)] +[scriptable, uuid(db476657-5f59-4e29-84a6-50afe6f85ac7)] interface nsIDOMHTMLMetaElement : nsIDOMHTMLElement { attribute DOMString content; diff --git a/dom/interfaces/html/nsIDOMHTMLModElement.idl b/dom/interfaces/html/nsIDOMHTMLModElement.idl index c10055044de7..fcb9e99895c9 100644 --- a/dom/interfaces/html/nsIDOMHTMLModElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLModElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(417626fa-191c-41e5-aed5-f6157b408e72)] +[scriptable, uuid(170733d4-aad5-4f6e-86c0-94845ea6116d)] interface nsIDOMHTMLModElement : nsIDOMHTMLElement { attribute DOMString cite; diff --git a/dom/interfaces/html/nsIDOMHTMLOListElement.idl b/dom/interfaces/html/nsIDOMHTMLOListElement.idl index b8c9c184cb6c..989aa350570e 100644 --- a/dom/interfaces/html/nsIDOMHTMLOListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(11e66686-b1ef-47be-9025-ffc20b875e4a)] +[scriptable, uuid(31a5f083-59a6-41c3-8a0b-e58e484c6516)] interface nsIDOMHTMLOListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLObjectElement.idl b/dom/interfaces/html/nsIDOMHTMLObjectElement.idl index ff86e566c61b..ae2c09b996e2 100644 --- a/dom/interfaces/html/nsIDOMHTMLObjectElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLObjectElement.idl @@ -52,7 +52,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(5d873128-d4e3-4e89-8900-599155167105)] +[scriptable, uuid(40037f4a-5bae-476f-977b-bbd8e78aaefe)] interface nsIDOMHTMLObjectElement : nsIDOMHTMLElement { readonly attribute nsIDOMHTMLFormElement form; diff --git a/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl b/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl index 9865c534bc2b..77c3f6e863fa 100644 --- a/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOptGroupElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(7b585d49-1da3-4fc6-a50c-b661063c2edc)] +[scriptable, uuid(ab55d67a-aabb-4441-b182-8ff2bd7d157e)] interface nsIDOMHTMLOptGroupElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLOptionElement.idl b/dom/interfaces/html/nsIDOMHTMLOptionElement.idl index c5451316161a..814046266eac 100644 --- a/dom/interfaces/html/nsIDOMHTMLOptionElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOptionElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c20ead8a-cb89-43b1-89ed-8f4713bf8452)] +[scriptable, uuid(7c5bf0ac-6230-4ee0-8b82-e7ebf211af03)] interface nsIDOMHTMLOptionElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLOutputElement.idl b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl index c348a5b23146..9e3d17cbb43c 100644 --- a/dom/interfaces/html/nsIDOMHTMLOutputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl @@ -50,7 +50,7 @@ interface nsIDOMDOMSettableTokenList; interface nsIDOMValidityState; -[scriptable, uuid(7d1fb2a9-7678-409e-8eb5-9216c47c233b)] +[scriptable, uuid(f2074cdb-19cb-447a-935c-9f4402dc1b5e)] interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement { readonly attribute nsIDOMDOMSettableTokenList htmlFor; diff --git a/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl b/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl index 3dd0608addbc..6ff31c369ae4 100644 --- a/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLParagraphElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d5d3eb33-0925-4555-be2f-4078dec49f59)] +[scriptable, uuid(e4f498f4-e3c5-46fe-92d0-c9957ccab530)] interface nsIDOMHTMLParagraphElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLParamElement.idl b/dom/interfaces/html/nsIDOMHTMLParamElement.idl index f39e07ede768..fc76ad88c9d9 100644 --- a/dom/interfaces/html/nsIDOMHTMLParamElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLParamElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(ccffedb8-f234-474e-9af4-576eba766023)] +[scriptable, uuid(d832b1ac-9bb6-4df0-9d9e-f7c040759672)] interface nsIDOMHTMLParamElement : nsIDOMHTMLElement { attribute DOMString name; diff --git a/dom/interfaces/html/nsIDOMHTMLPreElement.idl b/dom/interfaces/html/nsIDOMHTMLPreElement.idl index 78440bd96973..462d9b91c251 100644 --- a/dom/interfaces/html/nsIDOMHTMLPreElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLPreElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(c9d9b45a-e7d9-4dfb-abae-f3b9e6addbaa)] +[scriptable, uuid(f4088dff-649c-4eff-a3a4-dbd6333cdc44)] interface nsIDOMHTMLPreElement : nsIDOMHTMLElement { attribute long width; diff --git a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl index aa1db31233cf..24b584d78466 100644 --- a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl @@ -47,7 +47,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(aa830aa2-a4ea-455e-8285-8344cadb4c6d)] +[scriptable, uuid(9b1d2263-b60f-4d18-b4d1-66e8c3867c79)] interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement { attribute double value; diff --git a/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl b/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl index 20e0ef6c4949..c100f9090e3d 100644 --- a/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLQuoteElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(820ccd14-2479-4e4a-99d3-76d138caf7ec)] +[scriptable, uuid(55643647-2eda-4a45-af55-b2ba6c40c5f5)] interface nsIDOMHTMLQuoteElement : nsIDOMHTMLElement { attribute DOMString cite; diff --git a/dom/interfaces/html/nsIDOMHTMLScriptElement.idl b/dom/interfaces/html/nsIDOMHTMLScriptElement.idl index 8e7cf55a5a6e..02a52c1486ab 100644 --- a/dom/interfaces/html/nsIDOMHTMLScriptElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLScriptElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e6252d3b-521a-4f79-9d57-2721a81e7cc2)] +[scriptable, uuid(4b6a0957-5466-4134-8a0a-dd7e4675c106)] interface nsIDOMHTMLScriptElement : nsIDOMHTMLElement { attribute DOMString src; diff --git a/dom/interfaces/html/nsIDOMHTMLSelectElement.idl b/dom/interfaces/html/nsIDOMHTMLSelectElement.idl index 2a71f9f2df2a..8034c29a916a 100644 --- a/dom/interfaces/html/nsIDOMHTMLSelectElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLSelectElement.idl @@ -53,7 +53,7 @@ interface nsIDOMValidityState; -[scriptable, uuid(30a948a3-61a0-453c-a1e4-de67a1664746)] +[scriptable, uuid(98f111e0-2b7e-4abd-984b-2cc1d174fe44)] interface nsIDOMHTMLSelectElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLSourceElement.idl b/dom/interfaces/html/nsIDOMHTMLSourceElement.idl index 0cc0a6b1ca1a..4cf5f82416da 100644 --- a/dom/interfaces/html/nsIDOMHTMLSourceElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLSourceElement.idl @@ -48,7 +48,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(dcac4414-37e2-409f-b0a6-8231007e585b)] +[scriptable, uuid(c49d9a78-fa02-49c9-b239-9cd51e99f866)] interface nsIDOMHTMLSourceElement : nsIDOMHTMLElement { attribute DOMString src; diff --git a/dom/interfaces/html/nsIDOMHTMLStyleElement.idl b/dom/interfaces/html/nsIDOMHTMLStyleElement.idl index 41d4741d039e..2ce7924082e6 100644 --- a/dom/interfaces/html/nsIDOMHTMLStyleElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLStyleElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e72a6069-4987-480b-a349-ffd5fbebd59f)] +[scriptable, uuid(247fc8c4-92f3-427b-af6f-41b13f28287d)] interface nsIDOMHTMLStyleElement : nsIDOMHTMLElement { attribute boolean disabled; diff --git a/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl b/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl index 19dd09797264..fecd4818488a 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(cbd44d29-3120-470d-a7fb-fac4730c8b4b)] +[scriptable, uuid(db0e641f-ba2b-4c67-8da1-4e418cc5fbf7)] interface nsIDOMHTMLTableCaptionElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl index 43a9133ffea3..2f91ade14a13 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(03dd5118-7eaf-4bd3-a4a7-77f3f7eb8539)] +[scriptable, uuid(4caa7af0-fec4-44c1-9a81-e1f14166e60c)] interface nsIDOMHTMLTableCellElement : nsIDOMHTMLElement { readonly attribute long cellIndex; diff --git a/dom/interfaces/html/nsIDOMHTMLTableColElement.idl b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl index 2573a0c9ccd7..e82b5b5fb214 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableColElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(d221534a-d13c-43b2-9ba0-7e0dd7452856)] +[scriptable, uuid(9a4d1f6a-fb19-4886-b0d8-dcd201566580)] interface nsIDOMHTMLTableColElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTableElement.idl b/dom/interfaces/html/nsIDOMHTMLTableElement.idl index 3614a17a74ec..e7724f3d98f3 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(bba4b8b2-d01c-4c9b-abc8-3df28d048e68)] +[scriptable, uuid(0f809b97-9311-45c4-a44e-7145f354438b)] interface nsIDOMHTMLTableElement : nsIDOMHTMLElement { // Modified in DOM Level 2: diff --git a/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl index f9aeed647f6d..e6748b0cf673 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(b0199f36-9e76-4ec6-867f-850e388d6244)] +[scriptable, uuid(d24a80d4-491d-4e36-9349-afd3c6999b3e)] interface nsIDOMHTMLTableRowElement : nsIDOMHTMLElement { // Modified in DOM Level 2: diff --git a/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl b/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl index 96facb0877c0..037f300de7dd 100644 --- a/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl +++ b/dom/interfaces/html/nsIDOMHTMLTableSectionElem.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(ac2e2719-71f1-4485-ac1e-694e7e49bd2a)] +[scriptable, uuid(6acc106e-96a2-4519-8f3a-142ebbdc1bb1)] interface nsIDOMHTMLTableSectionElement : nsIDOMHTMLElement { attribute DOMString align; diff --git a/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl b/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl index fc78d04cf516..ec65b72c4e19 100644 --- a/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl @@ -53,7 +53,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(88d09917-d2da-4737-a887-277a2f9750c7)] +[scriptable, uuid(16db703d-4816-440c-bcb3-c1ae0cae6532)] interface nsIDOMHTMLTextAreaElement : nsIDOMHTMLElement { attribute boolean autofocus; diff --git a/dom/interfaces/html/nsIDOMHTMLTitleElement.idl b/dom/interfaces/html/nsIDOMHTMLTitleElement.idl index 18345f1421ad..305b773467c2 100644 --- a/dom/interfaces/html/nsIDOMHTMLTitleElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLTitleElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(5cb8cfaf-7551-422b-9b03-58d756e54339)] +[scriptable, uuid(e20fd651-6240-4f20-b8f0-6cc25cb699b7)] interface nsIDOMHTMLTitleElement : nsIDOMHTMLElement { attribute DOMString text; diff --git a/dom/interfaces/html/nsIDOMHTMLUListElement.idl b/dom/interfaces/html/nsIDOMHTMLUListElement.idl index 313c2a16fa10..8ecf76e00e6c 100644 --- a/dom/interfaces/html/nsIDOMHTMLUListElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLUListElement.idl @@ -50,7 +50,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(1f409357-8cea-4f69-9f0c-4149886b63a1)] +[scriptable, uuid(2467d39c-2c30-407e-9b67-ea5f231b7809)] interface nsIDOMHTMLUListElement : nsIDOMHTMLElement { attribute boolean compact; diff --git a/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl index 508930fd0d30..97809dbd594c 100644 --- a/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl @@ -43,7 +43,7 @@ * * @see */ -[scriptable, uuid(0d69049f-8181-47f1-a7f7-e5417dd54136)] +[scriptable, uuid(5f922c13-c2c1-4c49-b7c2-0e4e5c8e6860)] interface nsIDOMHTMLUnknownElement : nsIDOMHTMLElement { }; diff --git a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl index 622eafe52946..02c2bbbf8a2b 100644 --- a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl @@ -48,7 +48,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(5e1e4453-96fe-4cc0-9c32-7e9355b4f917)] +[scriptable, uuid(390b974b-1c3a-4700-8001-5ef832c4b4bf)] interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement { attribute long width; diff --git a/dom/tests/mochitest/general/Makefile.in b/dom/tests/mochitest/general/Makefile.in index d548a8ebfbff..e35c278fad62 100644 --- a/dom/tests/mochitest/general/Makefile.in +++ b/dom/tests/mochitest/general/Makefile.in @@ -45,6 +45,8 @@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _TEST_FILES = \ + test_outerHTML.html \ + test_outerHTML.xhtml \ 497633.html \ 489127.html \ historyframes.html \ diff --git a/dom/tests/mochitest/general/test_outerHTML.html b/dom/tests/mochitest/general/test_outerHTML.html new file mode 100644 index 000000000000..dba259844232 --- /dev/null +++ b/dom/tests/mochitest/general/test_outerHTML.html @@ -0,0 +1,73 @@ + + + + + Test for Bug 92264 + + + + +Mozilla Bug 92264 +

+ +
+
+
+ + diff --git a/dom/tests/mochitest/general/test_outerHTML.xhtml b/dom/tests/mochitest/general/test_outerHTML.xhtml new file mode 100644 index 000000000000..46013deb0af9 --- /dev/null +++ b/dom/tests/mochitest/general/test_outerHTML.xhtml @@ -0,0 +1,74 @@ + + + + + Test for Bug 92264 + + + + +Mozilla Bug 92264 +

+ +
+
+
+ + From 207912d4cd7211ffc9183bf653ebc9dee2446105 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Thu, 10 Nov 2011 14:55:07 +0100 Subject: [PATCH 04/38] Bug 700566 - Pressing enter or copying URL on an http:// site whose hostname begins with "ftp" results in incorrect URL being loaded/copied. r=gavin --- browser/base/content/test/browser_urlbarTrimURLs.js | 6 ++++++ browser/base/content/utilityOverlay.js | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/browser/base/content/test/browser_urlbarTrimURLs.js b/browser/base/content/test/browser_urlbarTrimURLs.js index 74ee78a0a38e..095ccc4a633f 100644 --- a/browser/base/content/test/browser_urlbarTrimURLs.js +++ b/browser/base/content/test/browser_urlbarTrimURLs.js @@ -32,7 +32,13 @@ function test() { testVal("http://mozilla.org/sub/", "mozilla.org/sub/"); testVal("http://ftp.mozilla.org/", "http://ftp.mozilla.org"); + testVal("http://ftp1.mozilla.org/", "http://ftp1.mozilla.org"); + testVal("http://ftp42.mozilla.org/", "http://ftp42.mozilla.org"); + testVal("http://ftpx.mozilla.org/", "ftpx.mozilla.org"); testVal("ftp://ftp.mozilla.org/", "ftp://ftp.mozilla.org"); + testVal("ftp://ftp1.mozilla.org/", "ftp://ftp1.mozilla.org"); + testVal("ftp://ftp42.mozilla.org/", "ftp://ftp42.mozilla.org"); + testVal("ftp://ftpx.mozilla.org/", "ftp://ftpx.mozilla.org"); testVal("https://user:pass@mozilla.org/", "https://user:pass@mozilla.org"); testVal("http://user:pass@mozilla.org/", "http://user:pass@mozilla.org"); diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index f1f7e40292bd..dfd5f15cab1b 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -635,8 +635,10 @@ function openPrefsHelp() { } function trimURL(aURL) { + // This function must not modify the given URL such that calling + // nsIURIFixup::createFixupURI with the result will produce a different URI. return aURL /* remove single trailing slash for http/https/ftp URLs */ .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1") - /* remove http:// unless the host starts with "ftp." or contains "@" */ - .replace(/^http:\/\/((?!ftp\.)[^\/@]+(?:\/|$))/, "$1"); + /* remove http:// unless the host starts with "ftp\d*\." or contains "@" */ + .replace(/^http:\/\/((?!ftp\d*\.)[^\/@]+(?:\/|$))/, "$1"); } From 8f0353652d2f3085df301e389da3522a6f1f3af3 Mon Sep 17 00:00:00 2001 From: Oonishi Atsushi Date: Thu, 10 Nov 2011 15:01:11 +0100 Subject: [PATCH 05/38] Bug 311007 - Add aFlags arg to onLocationChange(...), to distinguish between same-document and different-document. r=smaug, sr=bzbarsky --- accessible/src/base/nsAccDocManager.cpp | 3 +- browser/base/content/browser.js | 5 +- browser/base/content/tabbrowser.xml | 9 +- .../content/test/browser_alltabslistener.js | 5 +- browser/base/content/web-panels.js | 2 +- .../browser/browser_library_middleclick.js | 3 +- .../shell/src/nsMacShellService.cpp | 3 +- .../html/content/src/nsHTMLDNSPrefetch.cpp | 3 +- .../html/content/src/nsHTMLFormElement.cpp | 3 +- content/xslt/tests/buster/buster-test.js | 2 +- docshell/base/nsDocShell.cpp | 43 ++-- docshell/base/nsDocShell.h | 9 +- docshell/test/chrome/Makefile.in | 2 + docshell/test/chrome/bug311007_window.xul | 186 ++++++++++++++++++ docshell/test/chrome/test_bug311007.xul | 43 ++++ docshell/test/chrome/window.template.txt | 2 +- editor/composer/src/nsEditingSession.cpp | 3 +- editor/composer/test/test_bug434998.xul | 2 +- .../libeditor/html/tests/test_bug607584.xul | 2 +- .../libeditor/html/tests/test_bug616590.xul | 2 +- .../webBrowser/nsDocShellTreeOwner.cpp | 3 +- embedding/browser/webBrowser/nsWebBrowser.cpp | 6 +- .../printingui/src/mac/nsPrintProgress.cpp | 4 +- .../src/mac/nsPrintingPromptServiceX.mm | 4 +- .../printingui/src/os2/nsPrintProgress.cpp | 4 +- .../src/os2/nsPrintingPromptService.cpp | 6 +- .../src/unixshared/nsPrintProgress.cpp | 4 +- .../unixshared/nsPrintingPromptService.cpp | 6 +- .../printingui/src/win/nsPrintProgress.cpp | 4 +- .../src/win/nsPrintingPromptService.cpp | 6 +- embedding/tests/winEmbed/WebBrowserChrome.cpp | 3 +- .../chrome/printpreview_bug396024_helper.xul | 2 +- .../chrome/printpreview_bug482976_helper.xul | 2 +- .../base/tests/chrome/printpreview_helper.xul | 2 +- .../layout-debug/ui/content/layoutdebug.js | 2 +- mobile/chrome/content/bindings/browser.js | 2 +- .../boot/src/nsSecureBrowserUIImpl.cpp | 10 +- .../downloads/nsDownloadManager.cpp | 3 +- .../components/downloads/nsDownloadProxy.h | 5 +- toolkit/components/help/content/help.js | 2 +- .../printing/content/printPreviewProgress.js | 2 +- .../printing/content/printProgress.js | 2 +- .../statusfilter/nsBrowserStatusFilter.cpp | 6 +- toolkit/mozapps/downloads/nsHelperAppDlg.js | 2 +- .../mozapps/extensions/content/extensions.js | 2 +- uriloader/base/nsDocLoader.cpp | 7 +- uriloader/base/nsDocLoader.h | 3 +- uriloader/base/nsIWebProgressListener.idl | 18 +- .../prefetch/nsOfflineCacheUpdateService.cpp | 3 +- uriloader/prefetch/nsPrefetchService.cpp | 3 +- widget/tests/TestWinTSF.cpp | 3 +- xpfe/appshell/src/nsChromeTreeOwner.cpp | 3 +- xpfe/appshell/src/nsWebShellWindow.cpp | 3 +- 53 files changed, 381 insertions(+), 88 deletions(-) create mode 100644 docshell/test/chrome/bug311007_window.xul create mode 100644 docshell/test/chrome/test_bug311007.xul diff --git a/accessible/src/base/nsAccDocManager.cpp b/accessible/src/base/nsAccDocManager.cpp index 5372c14dd3ce..07a8cb9c00b2 100644 --- a/accessible/src/base/nsAccDocManager.cpp +++ b/accessible/src/base/nsAccDocManager.cpp @@ -238,7 +238,8 @@ nsAccDocManager::OnProgressChange(nsIWebProgress *aWebProgress, NS_IMETHODIMP nsAccDocManager::OnLocationChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, nsIURI *aLocation) + nsIRequest *aRequest, nsIURI *aLocation, + PRUint32 aFlags) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index ae06684d7a9d..91392b7a095d 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4586,7 +4586,7 @@ var XULBrowserWindow = { } }, - onLocationChange: function (aWebProgress, aRequest, aLocationURI) { + onLocationChange: function (aWebProgress, aRequest, aLocationURI, aFlags) { var location = aLocationURI ? aLocationURI.spec : ""; this._hostChanged = true; @@ -5052,7 +5052,8 @@ var TabsProgressListener = { } }, - onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) { + onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI, + aFlags) { // Filter out any sub-frame loads if (aBrowser.contentWindow == aWebProgress.DOMWindow) FullZoom.onLocationChange(aLocationURI, false, aBrowser); diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 418f2b31e631..d4df769127cf 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -608,7 +608,8 @@ this.mStatus = aStatus; }, - onLocationChange: function (aWebProgress, aRequest, aLocation) { + onLocationChange: function (aWebProgress, aRequest, aLocation, + aFlags) { // OnLocationChange is called for both the top-level content // and the subframes. let topLevel = aWebProgress.DOMWindow == this.mBrowser.contentWindow; @@ -641,7 +642,8 @@ if (!this.mBlank) { this._callProgressListeners("onLocationChange", - [aWebProgress, aRequest, aLocation]); + [aWebProgress, aRequest, aLocation, + aFlags]); } if (topLevel) @@ -890,7 +892,8 @@ var securityUI = this.mCurrentBrowser.securityUI; this._callProgressListeners(null, "onLocationChange", - [webProgress, null, loc], true, false); + [webProgress, null, loc, 0], true, + false); if (securityUI) { this._callProgressListeners(null, "onSecurityChange", diff --git a/browser/base/content/test/browser_alltabslistener.js b/browser/base/content/test/browser_alltabslistener.js index 70b1337c3656..4d7d11435169 100644 --- a/browser/base/content/test/browser_alltabslistener.js +++ b/browser/base/content/test/browser_alltabslistener.js @@ -17,7 +17,7 @@ var gFrontProgressListener = { gFrontNotificationsPos++; }, - onLocationChange: function (aWebProgress, aRequest, aLocationURI) { + onLocationChange: function (aWebProgress, aRequest, aLocationURI, aFlags) { var state = "onLocationChange"; info("FrontProgress: " + state + " " + aLocationURI.spec); ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener"); @@ -53,7 +53,8 @@ var gAllProgressListener = { } }, - onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) { + onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI, + aFlags) { var state = "onLocationChange"; info("AllProgress: " + state + " " + aLocationURI.spec); ok(aBrowser == gTestBrowser, state + " notification came from the correct browser"); diff --git a/browser/base/content/web-panels.js b/browser/base/content/web-panels.js index 56c3fe2da5c6..d6686f2c1d48 100644 --- a/browser/base/content/web-panels.js +++ b/browser/base/content/web-panels.js @@ -72,7 +72,7 @@ var panelProgressListener = { } , - onLocationChange : function(aWebProgress, aRequest, aLocation) { + onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { UpdateBackForwardCommands(getPanelBrowser().webNavigation); }, diff --git a/browser/components/places/tests/browser/browser_library_middleclick.js b/browser/components/places/tests/browser/browser_library_middleclick.js index 8e864830918a..5f47790ea99f 100644 --- a/browser/components/places/tests/browser/browser_library_middleclick.js +++ b/browser/components/places/tests/browser/browser_library_middleclick.js @@ -64,7 +64,8 @@ var gTabsListener = { "Tab has been opened in current browser window"); }, - onLocationChange: function(aBrowser, aWebProgress, aRequest, aLocationURI) { + onLocationChange: function(aBrowser, aWebProgress, aRequest, aLocationURI, + aFlags) { var spec = aLocationURI.spec; ok(true, spec); // When a new tab is opened, location is first set to "about:blank", so diff --git a/browser/components/shell/src/nsMacShellService.cpp b/browser/components/shell/src/nsMacShellService.cpp index ad1297556868..6d4ca5ab8fd2 100644 --- a/browser/components/shell/src/nsMacShellService.cpp +++ b/browser/components/shell/src/nsMacShellService.cpp @@ -235,7 +235,8 @@ nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress, NS_IMETHODIMP nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI* aLocation) + nsIURI* aLocation, + PRUint32 aFlags) { return NS_OK; } diff --git a/content/html/content/src/nsHTMLDNSPrefetch.cpp b/content/html/content/src/nsHTMLDNSPrefetch.cpp index d4fd536e4ad3..9541b78556ca 100644 --- a/content/html/content/src/nsHTMLDNSPrefetch.cpp +++ b/content/html/content/src/nsHTMLDNSPrefetch.cpp @@ -395,7 +395,8 @@ nsHTMLDNSPrefetch::nsDeferrals::OnProgressChange(nsIWebProgress *aProgress, NS_IMETHODIMP nsHTMLDNSPrefetch::nsDeferrals::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI *location) + nsIURI *location, + PRUint32 aFlags) { return NS_OK; } diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index aa05016f0719..da2f792604f1 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -1843,7 +1843,8 @@ nsHTMLFormElement::OnProgressChange(nsIWebProgress* aWebProgress, NS_IMETHODIMP nsHTMLFormElement::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI* location) + nsIURI* location, + PRUint32 aFlags) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; diff --git a/content/xslt/tests/buster/buster-test.js b/content/xslt/tests/buster/buster-test.js index 0bf51a40cfd5..3bf552228383 100644 --- a/content/xslt/tests/buster/buster-test.js +++ b/content/xslt/tests/buster/buster-test.js @@ -221,7 +221,7 @@ runItem.prototype = onProgressChange: function(aProg, b,c,d,e,f) { }, - onLocationChange: function(aProg, aRequest, aURI) + onLocationChange: function(aProg, aRequest, aURI, aFlags) { }, onStatusChange: function(aProg, aRequest, aStatus, aMessage) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 2dd5a188c0bd..647c71877089 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -1770,17 +1770,19 @@ nsDocShell::GetChromeEventHandler(nsIDOMEventTarget** aChromeEventHandler) return NS_OK; } -/* [noscript] void setCurrentURI (in nsIURI uri); */ +/* void setCurrentURI (in nsIURI uri); */ NS_IMETHODIMP nsDocShell::SetCurrentURI(nsIURI *aURI) { - SetCurrentURI(aURI, nsnull, true); + // Note that securityUI will set STATE_IS_INSECURE, even if + // the scheme of |aURI| is "https". + SetCurrentURI(aURI, nsnull, true, 0); return NS_OK; } bool nsDocShell::SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest, - bool aFireOnLocationChange) + bool aFireOnLocationChange, PRUint32 aLocationFlags) { #ifdef PR_LOGGING if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) { @@ -1824,7 +1826,7 @@ nsDocShell::SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest, } if (aFireOnLocationChange) { - FireOnLocationChange(this, aRequest, aURI); + FireOnLocationChange(this, aRequest, aURI, aLocationFlags); } return !aFireOnLocationChange; } @@ -5928,7 +5930,7 @@ nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest, // a new DOM here. rv = AddToSessionHistory(uri, wcwgChannel, nsnull, false, getter_AddRefs(mLSHE)); - SetCurrentURI(uri, aRequest, true); + SetCurrentURI(uri, aRequest, true, 0); // Save history state of the previous page rv = PersistLayoutHistoryState(); // We'll never get an Embed() for this load, so just go ahead @@ -5984,8 +5986,8 @@ nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest, } NS_IMETHODIMP -nsDocShell::OnLocationChange(nsIWebProgress * aProgress, - nsIRequest * aRequest, nsIURI * aURI) +nsDocShell::OnLocationChange(nsIWebProgress * aProgress, nsIRequest * aRequest, + nsIURI * aURI, PRUint32 aFlags) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; @@ -6515,7 +6517,7 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal, viewer->SetContainer(static_cast(this)); Embed(viewer, "", 0); - SetCurrentURI(blankDoc->GetDocumentURI(), nsnull, true); + SetCurrentURI(blankDoc->GetDocumentURI(), nsnull, true, 0); rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK; } } @@ -7166,7 +7168,7 @@ nsDocShell::RestoreFromHistory() // is still mLSHE or whether it's now mOSHE. nsCOMPtr uri; origLSHE->GetURI(getter_AddRefs(uri)); - SetCurrentURI(uri, document->GetChannel(), true); + SetCurrentURI(uri, document->GetChannel(), true, 0); } // This is the end of our CreateContentViewer() replacement. @@ -7505,7 +7507,7 @@ nsDocShell::CreateContentViewer(const char *aContentType, } if (onLocationChangeNeeded) { - FireOnLocationChange(this, request, mCurrentURI); + FireOnLocationChange(this, request, mCurrentURI, 0); } return NS_OK; @@ -8365,6 +8367,11 @@ nsDocShell::InternalLoad(nsIURI * aURI, // Pass true for aCloneSHChildren, since we're not // changing documents here, so all of our subframes are // still relevant to the new session history entry. + // + // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT + // flag on firing onLocationChange(...). + // Anyway, aCloneSHChildren param is simply reflecting + // doShortCircuitedLoad in this scope. OnNewURI(aURI, nsnull, owner, mLoadType, true, true, true); nsCOMPtr postData; @@ -9418,8 +9425,14 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner, #endif } } + + // aCloneSHChildren exactly means "we are not loading a new document". + PRUint32 locationFlags = aCloneSHChildren? + PRUint32(LOCATION_CHANGE_SAME_DOCUMENT) : 0; + bool onLocationChangeNeeded = SetCurrentURI(aURI, aChannel, - aFireOnLocationChange); + aFireOnLocationChange, + locationFlags); // Make sure to store the referrer from the channel, if any SetupReferrerFromChannel(aChannel); return onLocationChangeNeeded; @@ -9727,8 +9740,14 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle, // gets updated and the back button is enabled, but we only need to // explicitly call FireOnLocationChange if we're not calling SetCurrentURI, // since SetCurrentURI will call FireOnLocationChange for us. + // + // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass + // nsnull for aRequest param to FireOnLocationChange(...). Such an update + // notification is allowed only when we know docshell is not loading a new + // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise, + // FireOnLocationChange(...) breaks security UI. if (!equalURIs) { - SetCurrentURI(newURI, nsnull, true); + SetCurrentURI(newURI, nsnull, true, LOCATION_CHANGE_SAME_DOCUMENT); document->SetDocumentURI(newURI); AddURIVisit(newURI, oldURI, oldURI, 0); diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 934cf808ca7f..a840ad1397c2 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -269,10 +269,12 @@ public: friend class OnLinkClickEvent; - // We need dummy OnLocationChange in some cases to update the UI. + // We need dummy OnLocationChange in some cases to update the UI without + // updating security info. void FireDummyOnLocationChange() { - FireOnLocationChange(this, nsnull, mCurrentURI); + FireOnLocationChange(this, nsnull, mCurrentURI, + LOCATION_CHANGE_SAME_DOCUMENT); } nsresult HistoryTransactionRemoved(PRInt32 aIndex); @@ -593,7 +595,8 @@ protected: // FireOnLocationChange is called. // In all other cases false is returned. bool SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest, - bool aFireOnLocationChange); + bool aFireOnLocationChange, + PRUint32 aLocationFlags); // The following methods deal with saving and restoring content viewers // in session history. diff --git a/docshell/test/chrome/Makefile.in b/docshell/test/chrome/Makefile.in index b92291c281fd..6a0a5b623104 100644 --- a/docshell/test/chrome/Makefile.in +++ b/docshell/test/chrome/Makefile.in @@ -122,6 +122,8 @@ _TEST_FILES = \ 662200c.html \ test_bug690056.xul \ bug690056_window.xul \ + test_bug311007.xul \ + bug311007_window.xul \ $(NULL) _DOCSHELL_SUBHARNESS = \ diff --git a/docshell/test/chrome/bug311007_window.xul b/docshell/test/chrome/bug311007_window.xul new file mode 100644 index 000000000000..2db7a4bbc9e8 --- /dev/null +++ b/docshell/test/chrome/bug311007_window.xul @@ -0,0 +1,186 @@ + + + + + + + + + + diff --git a/docshell/test/chrome/test_bug311007.xul b/docshell/test/chrome/test_bug311007.xul new file mode 100644 index 000000000000..73b1e8fcb57c --- /dev/null +++ b/docshell/test/chrome/test_bug311007.xul @@ -0,0 +1,43 @@ + + + + + + + Test for Bug 311007 + + + + + + Mozilla Bug 311007 +

+ +
+
+ + + + +
diff --git a/docshell/test/chrome/window.template.txt b/docshell/test/chrome/window.template.txt index e07b47006bf9..76eb72c652b9 100644 --- a/docshell/test/chrome/window.template.txt +++ b/docshell/test/chrome/window.template.txt @@ -1,7 +1,7 @@ - domWindow; nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWindow)); diff --git a/editor/composer/test/test_bug434998.xul b/editor/composer/test/test_bug434998.xul index 3a5f50faa778..bf2ac8db9fd6 100644 --- a/editor/composer/test/test_bug434998.xul +++ b/editor/composer/test/test_bug434998.xul @@ -78,7 +78,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=434998 { }, - onLocationChange : function(aWebProgress, aRequest, aLocation) + onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { }, diff --git a/editor/libeditor/html/tests/test_bug607584.xul b/editor/libeditor/html/tests/test_bug607584.xul index a5f1527932c8..dec88720550d 100644 --- a/editor/libeditor/html/tests/test_bug607584.xul +++ b/editor/libeditor/html/tests/test_bug607584.xul @@ -83,7 +83,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607584 { }, - onLocationChange : function(aWebProgress, aRequest, aLocation) + onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { }, diff --git a/editor/libeditor/html/tests/test_bug616590.xul b/editor/libeditor/html/tests/test_bug616590.xul index 51bbf33bf82b..edf0fd76ab52 100644 --- a/editor/libeditor/html/tests/test_bug616590.xul +++ b/editor/libeditor/html/tests/test_bug616590.xul @@ -73,7 +73,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=616590 { }, - onLocationChange : function(aWebProgress, aRequest, aLocation) + onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { }, diff --git a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index 83194ce3983d..f99bf4f7fe47 100644 --- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -723,7 +723,8 @@ nsDocShellTreeOwner::OnStateChange(nsIWebProgress* aProgress, NS_IMETHODIMP nsDocShellTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI* aURI) + nsIURI* aURI, + PRUint32 aFlags) { return NS_OK; } diff --git a/embedding/browser/webBrowser/nsWebBrowser.cpp b/embedding/browser/webBrowser/nsWebBrowser.cpp index ac2c84850349..87c4f3354edc 100644 --- a/embedding/browser/webBrowser/nsWebBrowser.cpp +++ b/embedding/browser/webBrowser/nsWebBrowser.cpp @@ -852,12 +852,12 @@ NS_IMETHODIMP nsWebBrowser::OnProgressChange(nsIWebProgress *aWebProgress, nsIRe return NS_OK; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ -NS_IMETHODIMP nsWebBrowser::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ +NS_IMETHODIMP nsWebBrowser::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { if (mProgressListener) { - return mProgressListener->OnLocationChange(aWebProgress, aRequest, location); + return mProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags); } return NS_OK; } diff --git a/embedding/components/printingui/src/mac/nsPrintProgress.cpp b/embedding/components/printingui/src/mac/nsPrintProgress.cpp index c7c69c3544bb..7c07816ddcfe 100644 --- a/embedding/components/printingui/src/mac/nsPrintProgress.cpp +++ b/embedding/components/printingui/src/mac/nsPrintProgress.cpp @@ -257,8 +257,8 @@ NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, ns return rv; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ -NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ +NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { return NS_OK; } diff --git a/embedding/components/printingui/src/mac/nsPrintingPromptServiceX.mm b/embedding/components/printingui/src/mac/nsPrintingPromptServiceX.mm index 0431c57721ee..b35aac6d53a6 100644 --- a/embedding/components/printingui/src/mac/nsPrintingPromptServiceX.mm +++ b/embedding/components/printingui/src/mac/nsPrintingPromptServiceX.mm @@ -136,9 +136,9 @@ nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIReque return NS_OK; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ NS_IMETHODIMP -nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { return NS_OK; } diff --git a/embedding/components/printingui/src/os2/nsPrintProgress.cpp b/embedding/components/printingui/src/os2/nsPrintProgress.cpp index 99a8429396ba..8586e442e05d 100644 --- a/embedding/components/printingui/src/os2/nsPrintProgress.cpp +++ b/embedding/components/printingui/src/os2/nsPrintProgress.cpp @@ -254,8 +254,8 @@ NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, ns return rv; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ -NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ +NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { return NS_OK; } diff --git a/embedding/components/printingui/src/os2/nsPrintingPromptService.cpp b/embedding/components/printingui/src/os2/nsPrintingPromptService.cpp index 97b3981fd804..2fbc209abde7 100644 --- a/embedding/components/printingui/src/os2/nsPrintingPromptService.cpp +++ b/embedding/components/printingui/src/os2/nsPrintingPromptService.cpp @@ -289,12 +289,12 @@ nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIReque return NS_OK; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ NS_IMETHODIMP -nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { if (mWebProgressListener) { - return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location); + return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags); } return NS_OK; } diff --git a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp index ba52fa19ea1c..663eaa13ff89 100644 --- a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp +++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp @@ -257,8 +257,8 @@ NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, ns return rv; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ -NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ +NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp index 6185550ae2e1..d4a03849eac9 100644 --- a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp +++ b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp @@ -308,12 +308,12 @@ nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIReque return NS_OK; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ NS_IMETHODIMP -nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { if (mWebProgressListener) { - return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location); + return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags); } return NS_OK; } diff --git a/embedding/components/printingui/src/win/nsPrintProgress.cpp b/embedding/components/printingui/src/win/nsPrintProgress.cpp index 9cde50826c75..786096c4098c 100644 --- a/embedding/components/printingui/src/win/nsPrintProgress.cpp +++ b/embedding/components/printingui/src/win/nsPrintProgress.cpp @@ -285,8 +285,8 @@ NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, ns return rv; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ -NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ +NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { return NS_OK; } diff --git a/embedding/components/printingui/src/win/nsPrintingPromptService.cpp b/embedding/components/printingui/src/win/nsPrintingPromptService.cpp index f8432c003be1..e8344598d966 100644 --- a/embedding/components/printingui/src/win/nsPrintingPromptService.cpp +++ b/embedding/components/printingui/src/win/nsPrintingPromptService.cpp @@ -357,13 +357,13 @@ nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIReque return NS_ERROR_FAILURE; } -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ NS_IMETHODIMP -nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags) { if (mWebProgressListener) { - return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location); + return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags); } return NS_ERROR_FAILURE; } diff --git a/embedding/tests/winEmbed/WebBrowserChrome.cpp b/embedding/tests/winEmbed/WebBrowserChrome.cpp index eb3e9eb217db..e05692dcf9ed 100644 --- a/embedding/tests/winEmbed/WebBrowserChrome.cpp +++ b/embedding/tests/winEmbed/WebBrowserChrome.cpp @@ -276,7 +276,8 @@ NS_IMETHODIMP WebBrowserChrome::OnStateChange(nsIWebProgress *progress, nsIReque NS_IMETHODIMP WebBrowserChrome::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI *location) + nsIURI *location, + PRUint32 aFlags) { bool isSubFrameLoad = false; // Is this a subframe load if (aWebProgress) { diff --git a/layout/base/tests/chrome/printpreview_bug396024_helper.xul b/layout/base/tests/chrome/printpreview_bug396024_helper.xul index bfb6bcdf98eb..8fe2609f5bf8 100644 --- a/layout/base/tests/chrome/printpreview_bug396024_helper.xul +++ b/layout/base/tests/chrome/printpreview_bug396024_helper.xul @@ -20,7 +20,7 @@ function printpreview() { gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebBrowserPrint); var listener = { - onLocationChange: function(webProgress, request, location) { }, + onLocationChange: function(webProgress, request, location, flags) { }, onProgressChange: function(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { }, diff --git a/layout/base/tests/chrome/printpreview_bug482976_helper.xul b/layout/base/tests/chrome/printpreview_bug482976_helper.xul index 01b26f093283..34c2d658ec74 100644 --- a/layout/base/tests/chrome/printpreview_bug482976_helper.xul +++ b/layout/base/tests/chrome/printpreview_bug482976_helper.xul @@ -20,7 +20,7 @@ function printpreview() { gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebBrowserPrint); var listener = { - onLocationChange: function(webProgress, request, location) { }, + onLocationChange: function(webProgress, request, location, flags) { }, onProgressChange: function(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { }, diff --git a/layout/base/tests/chrome/printpreview_helper.xul b/layout/base/tests/chrome/printpreview_helper.xul index 0d5716d20ae8..3ad11f5bc31a 100644 --- a/layout/base/tests/chrome/printpreview_helper.xul +++ b/layout/base/tests/chrome/printpreview_helper.xul @@ -27,7 +27,7 @@ function printpreview() { gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebBrowserPrint); var listener = { - onLocationChange: function(webProgress, request, location) { }, + onLocationChange: function(webProgress, request, location, flags) { }, onProgressChange: function(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { }, diff --git a/layout/tools/layout-debug/ui/content/layoutdebug.js b/layout/tools/layout-debug/ui/content/layoutdebug.js index 0965a9e18ca7..a8ab730164fd 100644 --- a/layout/tools/layout-debug/ui/content/layoutdebug.js +++ b/layout/tools/layout-debug/ui/content/layoutdebug.js @@ -105,7 +105,7 @@ nsLDBBrowserContentListener.prototype = { { }, - onLocationChange : function(aWebProgress, aRequest, aLocation) + onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { this.mURLBar.value = aLocation.spec; this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward); diff --git a/mobile/chrome/content/bindings/browser.js b/mobile/chrome/content/bindings/browser.js index cacb4fb2ac69..b39995597953 100644 --- a/mobile/chrome/content/bindings/browser.js +++ b/mobile/chrome/content/bindings/browser.js @@ -35,7 +35,7 @@ let WebProgressListener = { _firstPaint: false, - onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI) { + onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) { if (content != aWebProgress.DOMWindow) return; diff --git a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp index 770bc930586f..1e62e243bcda 100644 --- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp +++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp @@ -1511,7 +1511,8 @@ nsresult nsSecureBrowserUIImpl::TellTheWorld(bool showWarning, NS_IMETHODIMP nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI* aLocation) + nsIURI* aLocation, + PRUint32 aFlags) { #ifdef DEBUG nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection); @@ -1551,9 +1552,10 @@ nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress, NS_ASSERTION(window, "Window has gone away?!"); } - // If the location change does not have a corresponding request, then we - // assume that it does not impact the security state. - if (!aRequest) + // When |aRequest| is null, basically we don't trust that document. But if + // docshell insists that the document has not changed at all, we will reuse + // the previous security state, no matter what |aRequest| may be. + if (aFlags & LOCATION_CHANGE_SAME_DOCUMENT) return NS_OK; // The location bar has changed, so we must update the security state. The diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp index 00a6e7d5b341..27e82d2cfc31 100644 --- a/toolkit/components/downloads/nsDownloadManager.cpp +++ b/toolkit/components/downloads/nsDownloadManager.cpp @@ -2482,7 +2482,8 @@ nsDownload::OnProgressChange(nsIWebProgress *aWebProgress, NS_IMETHODIMP nsDownload::OnLocationChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, nsIURI *aLocation) + nsIRequest *aRequest, nsIURI *aLocation, + PRUint32 aFlags) { return NS_OK; } diff --git a/toolkit/components/downloads/nsDownloadProxy.h b/toolkit/components/downloads/nsDownloadProxy.h index 0d4b37221bd4..ad7529a91e4e 100644 --- a/toolkit/components/downloads/nsDownloadProxy.h +++ b/toolkit/components/downloads/nsDownloadProxy.h @@ -123,10 +123,11 @@ public: } NS_IMETHODIMP OnLocationChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, nsIURI *aLocation) + nsIRequest *aRequest, nsIURI *aLocation, + PRUint32 aFlags) { NS_ENSURE_TRUE(mInner, NS_ERROR_NOT_INITIALIZED); - return mInner->OnLocationChange(aWebProgress, aRequest, aLocation); + return mInner->OnLocationChange(aWebProgress, aRequest, aLocation, aFlags); } NS_IMETHODIMP OnProgressChange(nsIWebProgress *aWebProgress, diff --git a/toolkit/components/help/content/help.js b/toolkit/components/help/content/help.js index 4a49bfb9b7c7..a86198fab504 100644 --- a/toolkit/components/help/content/help.js +++ b/toolkit/components/help/content/help.js @@ -543,7 +543,7 @@ nsHelpStatusHandler.prototype = { aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {}, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {}, onSecurityChange : function(aWebProgress, aRequest, state) {}, - onLocationChange : function(aWebProgress, aRequest, aLocation) { + onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { UpdateBackForwardButtons(); }, QueryInterface : function(aIID) { diff --git a/toolkit/components/printing/content/printPreviewProgress.js b/toolkit/components/printing/content/printPreviewProgress.js index 7c92958bb85c..2677c3ce8239 100644 --- a/toolkit/components/printing/content/printPreviewProgress.js +++ b/toolkit/components/printing/content/printPreviewProgress.js @@ -91,7 +91,7 @@ var progressListener = { } }, - onLocationChange: function (aWebProgress, aRequest, aLocation) {}, + onLocationChange: function (aWebProgress, aRequest, aLocation, aFlags) {}, onSecurityChange: function (aWebProgress, aRequest, state) {}, onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) diff --git a/toolkit/components/printing/content/printProgress.js b/toolkit/components/printing/content/printProgress.js index 87046b5364b7..395bfa5bfd15 100644 --- a/toolkit/components/printing/content/printProgress.js +++ b/toolkit/components/printing/content/printProgress.js @@ -180,7 +180,7 @@ var progressListener = { } }, - onLocationChange: function(aWebProgress, aRequest, aLocation) + onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) { // we can ignore this notification }, diff --git a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp index 1158f6fa728e..34dfd8bac1f7 100644 --- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp @@ -223,12 +223,14 @@ nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress, NS_IMETHODIMP nsBrowserStatusFilter::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - nsIURI *aLocation) + nsIURI *aLocation, + PRUint32 aFlags) { if (!mListener) return NS_OK; - return mListener->OnLocationChange(aWebProgress, aRequest, aLocation); + return mListener->OnLocationChange(aWebProgress, aRequest, aLocation, + aFlags); } NS_IMETHODIMP diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js index f525cd94e960..c592af3eab77 100644 --- a/toolkit/mozapps/downloads/nsHelperAppDlg.js +++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js @@ -109,7 +109,7 @@ nsUnkownContentTypeDialogProgressListener.prototype = { onStateChange: function( aWebProgress, aRequest, aStateFlags, aStatus ) { }, - onLocationChange: function( aWebProgress, aRequest, aLocation ) { + onLocationChange: function( aWebProgress, aRequest, aLocation, aFlags ) { }, onSecurityChange: function( aWebProgress, aRequest, state ) { diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 590af44e3d8f..ee7a87a9eda4 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -1909,7 +1909,7 @@ var gDiscoverView = { this._browser.loadURIWithFlags(aURL, flags); }, - onLocationChange: function(aWebProgress, aRequest, aLocation) { + onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) { // Ignore the about:blank load if (aLocation.spec == "about:blank") return; diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp index 7a15a7c5ddff..1eb8aa38e3a8 100644 --- a/uriloader/base/nsDocLoader.cpp +++ b/uriloader/base/nsDocLoader.cpp @@ -1391,7 +1391,8 @@ void nsDocLoader::DoFireOnStateChange(nsIWebProgress * const aProgress, void nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI *aUri) + nsIURI *aUri, + PRUint32 aFlags) { /* * First notify any listeners of the new state info... @@ -1418,14 +1419,14 @@ nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress, continue; } - listener->OnLocationChange(aWebProgress, aRequest, aUri); + listener->OnLocationChange(aWebProgress, aRequest, aUri, aFlags); } mListenerInfoList.Compact(); // Pass the notification up to the parent... if (mParent) { - mParent->FireOnLocationChange(aWebProgress, aRequest, aUri); + mParent->FireOnLocationChange(aWebProgress, aRequest, aUri, aFlags); } } diff --git a/uriloader/base/nsDocLoader.h b/uriloader/base/nsDocLoader.h index f730a65a4f62..d469e690ba7a 100644 --- a/uriloader/base/nsDocLoader.h +++ b/uriloader/base/nsDocLoader.h @@ -185,7 +185,8 @@ protected: void FireOnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI *aUri); + nsIURI *aUri, + PRUint32 aFlags); bool RefreshAttempted(nsIWebProgress* aWebProgress, nsIURI *aURI, diff --git a/uriloader/base/nsIWebProgressListener.idl b/uriloader/base/nsIWebProgressListener.idl index 010bef874ca9..2aeffbc65748 100644 --- a/uriloader/base/nsIWebProgressListener.idl +++ b/uriloader/base/nsIWebProgressListener.idl @@ -51,7 +51,7 @@ interface nsIURI; * nsIWebProgress instances. nsIWebProgress.idl describes the parent-child * relationship of nsIWebProgress instances. */ -[scriptable, uuid(570F39D1-EFD0-11d3-B093-00A024FFC08C)] +[scriptable, uuid(a0cda7e4-c6ca-11e0-b6a5-001320257da5)] interface nsIWebProgressListener : nsISupports { /** @@ -302,6 +302,16 @@ interface nsIWebProgressListener : nsISupports in long aCurTotalProgress, in long aMaxTotalProgress); + /** + * Flags for onLocationChange + * + * LOCATION_CHANGE_SAME_DOCUMENT + * This flag is on when |aWebProgress| did not load a new document. + * For example, the location change is due to an anchor scroll or a + * pushState/popState/replaceState. + */ + const unsigned long LOCATION_CHANGE_SAME_DOCUMENT = 0x00000001; + /** * Called when the location of the window being watched changes. This is not * when a load is requested, but rather once it is verified that the load is @@ -316,10 +326,14 @@ interface nsIWebProgressListener : nsISupports * The associated nsIRequest. This may be null in some cases. * @param aLocation * The URI of the location that is being loaded. + * @param aFlags + * This is a value which explains the situation or the reason why + * the location has changed. */ void onLocationChange(in nsIWebProgress aWebProgress, in nsIRequest aRequest, - in nsIURI aLocation); + in nsIURI aLocation, + [optional] in unsigned long aFlags); /** * Notification that the status of a request has changed. The status message diff --git a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp index ea7ef0c0de5b..39be1b2f1054 100644 --- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp +++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp @@ -206,7 +206,8 @@ nsOfflineCachePendingUpdate::OnStateChange(nsIWebProgress* aWebProgress, NS_IMETHODIMP nsOfflineCachePendingUpdate::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI *location) + nsIURI *location, + PRUint32 aFlags) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; diff --git a/uriloader/prefetch/nsPrefetchService.cpp b/uriloader/prefetch/nsPrefetchService.cpp index 99555627d13d..3fe73e96bf89 100644 --- a/uriloader/prefetch/nsPrefetchService.cpp +++ b/uriloader/prefetch/nsPrefetchService.cpp @@ -898,7 +898,8 @@ nsPrefetchService::OnStateChange(nsIWebProgress* aWebProgress, NS_IMETHODIMP nsPrefetchService::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI *location) + nsIURI *location, + PRUint32 aFlags) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; diff --git a/widget/tests/TestWinTSF.cpp b/widget/tests/TestWinTSF.cpp index 86eefcf4c923..dfeb4c7f8f82 100644 --- a/widget/tests/TestWinTSF.cpp +++ b/widget/tests/TestWinTSF.cpp @@ -189,7 +189,8 @@ TestApp::OnProgressChange(nsIWebProgress *aWebProgress, NS_IMETHODIMP TestApp::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - nsIURI *aLocation) + nsIURI *aLocation, + PRUint32 aFlags) { return NS_OK; } diff --git a/xpfe/appshell/src/nsChromeTreeOwner.cpp b/xpfe/appshell/src/nsChromeTreeOwner.cpp index 69f433e6ef50..89170e4fc401 100644 --- a/xpfe/appshell/src/nsChromeTreeOwner.cpp +++ b/xpfe/appshell/src/nsChromeTreeOwner.cpp @@ -535,7 +535,8 @@ nsChromeTreeOwner::OnStateChange(nsIWebProgress* aWebProgress, NS_IMETHODIMP nsChromeTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - nsIURI* aLocation) + nsIURI* aLocation, + PRUint32 aFlags) { bool itsForYou = true; diff --git a/xpfe/appshell/src/nsWebShellWindow.cpp b/xpfe/appshell/src/nsWebShellWindow.cpp index 7911697d6d14..73bb7b465f8e 100644 --- a/xpfe/appshell/src/nsWebShellWindow.cpp +++ b/xpfe/appshell/src/nsWebShellWindow.cpp @@ -595,7 +595,8 @@ nsWebShellWindow::OnStateChange(nsIWebProgress *aProgress, NS_IMETHODIMP nsWebShellWindow::OnLocationChange(nsIWebProgress *aProgress, nsIRequest *aRequest, - nsIURI *aURI) + nsIURI *aURI, + PRUint32 aFlags) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; From 5256c20b37832ee1a43e154bb74bb1b83a22f078 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Thu, 10 Nov 2011 08:20:47 -0800 Subject: [PATCH 06/38] Bug 700741 - Add and implement nsIFocusManager.elementIsFocusable r=Enn --- dom/base/nsFocusManager.cpp | 13 +++++++++++++ dom/interfaces/base/nsIFocusManager.idl | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index 21674d577cc9..4f4ffb2c830d 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -465,6 +465,19 @@ nsFocusManager::SetFocus(nsIDOMElement* aElement, PRUint32 aFlags) return NS_OK; } +NS_IMETHODIMP +nsFocusManager::ElementIsFocusable(nsIDOMElement* aElement, PRUint32 aFlags, + bool* aIsFocusable) +{ + NS_ENSURE_TRUE(aElement, NS_ERROR_INVALID_ARG); + + nsCOMPtr aContent = do_QueryInterface(aElement); + + *aIsFocusable = CheckIfFocusable(aContent, aFlags) != nsnull; + + return NS_OK; +} + NS_IMETHODIMP nsFocusManager::MoveFocus(nsIDOMWindow* aWindow, nsIDOMElement* aStartElement, PRUint32 aType, PRUint32 aFlags, nsIDOMElement** aElement) diff --git a/dom/interfaces/base/nsIFocusManager.idl b/dom/interfaces/base/nsIFocusManager.idl index 6de2b32bc25c..89ff9043334b 100644 --- a/dom/interfaces/base/nsIFocusManager.idl +++ b/dom/interfaces/base/nsIFocusManager.idl @@ -166,6 +166,11 @@ interface nsIFocusManager : nsISupports */ void moveCaretToFocus(in nsIDOMWindow aWindow); + /*** + * Check if given element is focusable. + */ + boolean elementIsFocusable(in nsIDOMElement aElement, in unsigned long aFlags); + /* * Raise the window when switching focus */ From 213017df5162c3f99d6af3870fb541ba9f98a408 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Tue, 25 Oct 2011 16:07:42 -0700 Subject: [PATCH 07/38] Bug 641027 - Add snapshot-at-the-beginning write barriers for incremental GC (r=luke,bhackett) --- configure.in | 11 + .../html/content/src/nsHTMLCanvasElement.cpp | 4 +- js/public/HashTable.h | 14 +- js/src/Makefile.in | 1 + js/src/configure.in | 11 + js/src/frontend/BytecodeEmitter-inl.h | 73 +++ js/src/frontend/BytecodeEmitter.cpp | 6 +- js/src/frontend/BytecodeEmitter.h | 20 +- js/src/frontend/Parser.cpp | 4 +- js/src/frontend/SemanticAnalysis.cpp | 1 + js/src/gc/Barrier-inl.h | 259 ++++++++++ js/src/gc/Barrier.h | 450 ++++++++++++++++++ js/src/jsapi-tests/testArgumentsObject.cpp | 2 + js/src/jsapi-tests/testBug604087.cpp | 2 + js/src/jsapi-tests/testConservativeGC.cpp | 10 +- js/src/jsapi-tests/testIndexToString.cpp | 2 + js/src/jsapi.cpp | 118 ++++- js/src/jsapi.h | 93 +++- js/src/jsarray.cpp | 46 +- js/src/jsarray.h | 2 +- js/src/jsarrayinlines.h | 13 +- js/src/jsatom.cpp | 6 +- js/src/jsatom.h | 6 + js/src/jscell.h | 8 +- js/src/jscntxt.h | 24 +- js/src/jscntxtinlines.h | 6 +- js/src/jscompartment.cpp | 44 +- js/src/jscompartment.h | 36 +- js/src/jsexn.cpp | 28 +- js/src/jsfun.cpp | 84 ++-- js/src/jsfun.h | 18 +- js/src/jsfuninlines.h | 14 + js/src/jsgc.cpp | 100 ++-- js/src/jsgc.h | 7 +- js/src/jsgcinlines.h | 19 +- js/src/jsgcmark.cpp | 356 +++++++++----- js/src/jsgcmark.h | 136 +++--- js/src/jsgcstats.cpp | 1 + js/src/jsinfer.cpp | 54 ++- js/src/jsinfer.h | 57 ++- js/src/jsinferinlines.h | 68 ++- js/src/jsinterp.cpp | 4 +- js/src/jsiter.cpp | 90 +++- js/src/jsiter.h | 17 +- js/src/jslock.cpp | 2 + js/src/jsobj.cpp | 79 +-- js/src/jsobj.h | 128 ++--- js/src/jsobjinlines.h | 293 ++++++++++-- js/src/jsprobes.cpp | 5 +- js/src/jspropertytree.cpp | 24 +- js/src/jsproxy.cpp | 28 +- js/src/jsprvtd.h | 3 +- js/src/jsscope.cpp | 52 +- js/src/jsscope.h | 51 +- js/src/jsscopeinlines.h | 84 +++- js/src/jsscript.cpp | 33 +- js/src/jsscript.h | 49 +- js/src/jsscriptinlines.h | 33 +- js/src/jstracer.cpp | 104 ++-- js/src/jstracer.h | 11 +- js/src/jstypedarray.cpp | 16 +- js/src/jstypedarray.h | 2 + js/src/jswatchpoint.cpp | 10 +- js/src/jswatchpoint.h | 10 +- js/src/jsweakmap.cpp | 6 +- js/src/jsweakmap.h | 182 +++---- js/src/jswrapper.cpp | 5 +- js/src/jsxdrapi.cpp | 2 +- js/src/jsxml.cpp | 408 +++++++++------- js/src/jsxml.h | 94 ++-- js/src/methodjit/BaseAssembler.h | 6 +- js/src/methodjit/Compiler.cpp | 77 ++- js/src/methodjit/Compiler.h | 2 +- js/src/methodjit/FastBuiltins.cpp | 20 +- js/src/methodjit/FastOps.cpp | 55 ++- js/src/methodjit/FrameState-inl.h | 20 +- js/src/methodjit/FrameState.h | 4 + js/src/methodjit/LoopState.cpp | 2 +- js/src/methodjit/MethodJIT.h | 6 +- js/src/methodjit/NunboxAssembler.h | 8 + js/src/methodjit/PolyIC.cpp | 15 + js/src/methodjit/PolyIC.h | 1 + js/src/methodjit/PunboxAssembler.h | 10 + js/src/methodjit/StubCalls.cpp | 15 + js/src/methodjit/StubCalls.h | 3 + js/src/shell/jsheaptools.cpp | 3 +- js/src/tracejit/Writer.cpp | 9 +- js/src/tracejit/Writer.h | 2 +- js/src/vm/ArgumentsObject-inl.h | 13 +- js/src/vm/ArgumentsObject.h | 8 +- js/src/vm/CallObject-inl.h | 42 +- js/src/vm/CallObject.cpp | 4 +- js/src/vm/CallObject.h | 10 +- js/src/vm/Debugger.cpp | 85 ++-- js/src/vm/Debugger.h | 28 +- js/src/vm/GlobalObject-inl.h | 102 ++++ js/src/vm/GlobalObject.cpp | 15 +- js/src/vm/GlobalObject.h | 41 +- js/src/vm/RegExpObject-inl.h | 61 ++- js/src/vm/RegExpObject.cpp | 1 + js/src/vm/RegExpObject.h | 25 +- js/src/vm/RegExpStatics-inl.h | 84 +++- js/src/vm/RegExpStatics.cpp | 4 +- js/src/vm/RegExpStatics.h | 79 +-- js/src/vm/String-inl.h | 30 ++ js/src/vm/String.cpp | 47 +- js/src/vm/String.h | 8 + js/xpconnect/src/XPCWrappedNative.cpp | 65 ++- js/xpconnect/src/XPCWrappedNativeProto.cpp | 2 +- js/xpconnect/src/XPCWrappedNativeScope.cpp | 6 +- js/xpconnect/src/dombindings.cpp | 2 +- js/xpconnect/src/xpcprivate.h | 18 +- 112 files changed, 3686 insertions(+), 1391 deletions(-) create mode 100644 js/src/frontend/BytecodeEmitter-inl.h create mode 100644 js/src/gc/Barrier-inl.h create mode 100644 js/src/gc/Barrier.h create mode 100644 js/src/vm/GlobalObject-inl.h diff --git a/configure.in b/configure.in index b300a2e8e956..e516ea49b248 100644 --- a/configure.in +++ b/configure.in @@ -7227,6 +7227,17 @@ if test -n "$MOZ_TRACEVIS"; then AC_DEFINE(MOZ_TRACEVIS) fi +dnl ======================================================== +dnl = Use incremental GC +dnl ======================================================== +JSGC_INCREMENTAL=1 +MOZ_ARG_DISABLE_BOOL(gcincremental, +[ --disable-gcincremental Disable incremental GC], + JSGC_INCREMENTAL= ) +if test -n "$JSGC_INCREMENTAL"; then + AC_DEFINE(JSGC_INCREMENTAL) +fi + dnl ======================================================== dnl ETW - Event Tracing for Windows dnl ======================================================== diff --git a/content/html/content/src/nsHTMLCanvasElement.cpp b/content/html/content/src/nsHTMLCanvasElement.cpp index 8258e6dba820..b5d22d642c2b 100644 --- a/content/html/content/src/nsHTMLCanvasElement.cpp +++ b/content/html/content/src/nsHTMLCanvasElement.cpp @@ -501,8 +501,8 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId, JSObject *opts = JSVAL_TO_OBJECT(aContextOptions); JSIdArray *props = JS_Enumerate(cx, opts); - for (int i = 0; props && i < props->length; ++i) { - jsid propid = props->vector[i]; + for (int i = 0; props && i < JS_IdArrayLength(cx, props); ++i) { + jsid propid = JS_IdArrayGet(cx, props, i); jsval propname, propval; if (!JS_IdToValue(cx, propid, &propname) || !JS_GetPropertyById(cx, opts, propid, &propval)) diff --git a/js/public/HashTable.h b/js/public/HashTable.h index c2e2f4eea9fa..4356eedd55bf 100644 --- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -912,7 +912,10 @@ class HashMapEntry public: HashMapEntry() : key(), value() {} - HashMapEntry(const Key &k, const Value &v) : key(k), value(v) {} + + template + HashMapEntry(const KeyInput &k, const ValueInput &v) : key(k), value(v) {} + HashMapEntry(MoveRef rhs) : key(Move(rhs->key)), value(Move(rhs->value)) { } void operator=(MoveRef rhs) { @@ -1048,7 +1051,8 @@ class HashMap return impl.lookupForAdd(l); } - bool add(AddPtr &p, const Key &k, const Value &v) { + template + bool add(AddPtr &p, const KeyInput &k, const ValueInput &v) { Entry *pentry; if (!impl.add(p, &pentry)) return false; @@ -1074,7 +1078,8 @@ class HashMap return true; } - bool relookupOrAdd(AddPtr &p, const Key &k, const Value &v) { + template + bool relookupOrAdd(AddPtr &p, const KeyInput &k, const ValueInput &v) { return impl.relookupOrAdd(p, k, Entry(k, v)); } @@ -1137,7 +1142,8 @@ class HashMap } /* Overwrite existing value with v. Return NULL on oom. */ - Entry *put(const Key &k, const Value &v) { + template + Entry *put(const KeyInput &k, const ValueInput &v) { AddPtr p = lookupForAdd(k); if (p) { p->value = v; diff --git a/js/src/Makefile.in b/js/src/Makefile.in index fc48cbd6c665..e0e4bfbf01e7 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -250,6 +250,7 @@ EXPORTS_ds = \ EXPORTS_gc = \ Statistics.h \ + Barrier.h \ $(NULL) ###################################################### diff --git a/js/src/configure.in b/js/src/configure.in index f4a836b45d64..621334aa63c9 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -4442,6 +4442,17 @@ if test -n "$MOZ_TRACEVIS"; then fi fi +dnl ======================================================== +dnl = Use incremental GC +dnl ======================================================== +JSGC_INCREMENTAL=1 +MOZ_ARG_DISABLE_BOOL(gcincremental, +[ --disable-gcincremental Disable incremental GC], + JSGC_INCREMENTAL= ) +if test -n "$JSGC_INCREMENTAL"; then + AC_DEFINE(JSGC_INCREMENTAL) +fi + dnl ======================================================== dnl = Use Valgrind dnl ======================================================== diff --git a/js/src/frontend/BytecodeEmitter-inl.h b/js/src/frontend/BytecodeEmitter-inl.h new file mode 100644 index 000000000000..5f3d7b0e9286 --- /dev/null +++ b/js/src/frontend/BytecodeEmitter-inl.h @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=99: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef BytecodeEmitter_inl_h__ +#define BytecodeEmitter_inl_h__ + +#include "frontend/ParseNode.h" +#include "frontend/TokenStream.h" + +namespace js { + +inline +TreeContext::TreeContext(Parser *prs) + : flags(0), bodyid(0), blockidGen(0), parenDepth(0), yieldCount(0), argumentsCount(0), + topStmt(NULL), topScopeStmt(NULL), blockChainBox(NULL), blockNode(NULL), + decls(prs->context), parser(prs), yieldNode(NULL), argumentsNode(NULL), scopeChain_(NULL), + lexdeps(prs->context), parent(prs->tc), staticLevel(0), funbox(NULL), functionList(NULL), + innermostWith(NULL), bindings(prs->context), sharpSlotBase(-1) +{ + prs->tc = this; +} + +/* + * For functions the tree context is constructed and destructed a second + * time during code generation. To avoid a redundant stats update in such + * cases, we store uint16(-1) in maxScopeDepth. + */ +inline +TreeContext::~TreeContext() +{ + parser->tc = this->parent; +} + +} /* namespace js */ + +#endif /* BytecodeEmitter_inl_h__ */ diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index b04dce1e1f01..71ee009136b5 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -71,10 +71,10 @@ #include "vm/RegExpObject.h" #include "jsatominlines.h" -#include "jsobjinlines.h" #include "jsscopeinlines.h" #include "jsscriptinlines.h" +#include "frontend/BytecodeEmitter-inl.h" #include "frontend/ParseMaps-inl.h" /* Allocation chunk counts, must be powers of two in general. */ @@ -7777,7 +7777,7 @@ CGObjectList::finish(JSObjectArray *array) JS_ASSERT(length <= INDEX_LIMIT); JS_ASSERT(length == array->length); - JSObject **cursor = array->vector + array->length; + js::HeapPtrObject *cursor = array->vector + array->length; ObjectBox *objbox = lastbox; do { --cursor; @@ -7792,7 +7792,7 @@ GCConstList::finish(JSConstArray *array) { JS_ASSERT(array->length == list.length()); Value *src = list.begin(), *srcend = list.end(); - Value *dst = array->vector; + HeapValue *dst = array->vector; for (; src != srcend; ++src, ++dst) *dst = *src; } diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 5993da9a93eb..1493ca47ce6c 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -359,24 +359,8 @@ struct TreeContext { /* tree context for semantic checks */ void trace(JSTracer *trc); - TreeContext(Parser *prs) - : flags(0), bodyid(0), blockidGen(0), parenDepth(0), yieldCount(0), argumentsCount(0), - topStmt(NULL), topScopeStmt(NULL), blockChainBox(NULL), blockNode(NULL), - decls(prs->context), parser(prs), yieldNode(NULL), argumentsNode(NULL), scopeChain_(NULL), - lexdeps(prs->context), parent(prs->tc), staticLevel(0), funbox(NULL), functionList(NULL), - innermostWith(NULL), bindings(prs->context), sharpSlotBase(-1) - { - prs->tc = this; - } - - /* - * For functions the tree context is constructed and destructed a second - * time during code generation. To avoid a redundant stats update in such - * cases, we store uint16(-1) in maxScopeDepth. - */ - ~TreeContext() { - parser->tc = this->parent; - } + inline TreeContext(Parser *prs); + inline ~TreeContext(); /* * js::BytecodeEmitter derives from js::TreeContext; however, only the diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 9afe3ad5ddbe..8b203d5bb9ec 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -92,9 +92,9 @@ #endif #include "jsatominlines.h" -#include "jsobjinlines.h" #include "jsscriptinlines.h" +#include "frontend/BytecodeEmitter-inl.h" #include "frontend/ParseMaps-inl.h" #include "frontend/ParseNode-inl.h" #include "vm/RegExpObject-inl.h" @@ -246,7 +246,7 @@ Parser::trace(JSTracer *trc) { ObjectBox *objbox = traceListHead; while (objbox) { - MarkObject(trc, *objbox->object, "parser.object"); + MarkRoot(trc, objbox->object, "parser.object"); if (objbox->isFunctionBox) static_cast(objbox)->bindings.trace(trc); objbox = objbox->traceLink; diff --git a/js/src/frontend/SemanticAnalysis.cpp b/js/src/frontend/SemanticAnalysis.cpp index f75164e1d7c5..03eabc26bcd5 100644 --- a/js/src/frontend/SemanticAnalysis.cpp +++ b/js/src/frontend/SemanticAnalysis.cpp @@ -45,6 +45,7 @@ #include "frontend/BytecodeEmitter.h" #include "frontend/Parser.h" +#include "jsobjinlines.h" #include "jsfuninlines.h" using namespace js; diff --git a/js/src/gc/Barrier-inl.h b/js/src/gc/Barrier-inl.h new file mode 100644 index 000000000000..d7a496df7f5e --- /dev/null +++ b/js/src/gc/Barrier-inl.h @@ -0,0 +1,259 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=78: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is SpiderMonkey global object code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "jsgcmark.h" + +#include "gc/Barrier.h" + +#ifndef jsgc_barrier_inl_h___ +#define jsgc_barrier_inl_h___ + +namespace js { + +static JS_ALWAYS_INLINE void +ClearValueRange(JSCompartment *comp, HeapValue *vec, uintN len, bool useHoles) +{ + if (useHoles) { + for (uintN i = 0; i < len; i++) + vec[i].set(comp, MagicValue(JS_ARRAY_HOLE)); + } else { + for (uintN i = 0; i < len; i++) + vec[i].set(comp, UndefinedValue()); + } +} + +static JS_ALWAYS_INLINE void +InitValueRange(HeapValue *vec, uintN len, bool useHoles) +{ + if (useHoles) { + for (uintN i = 0; i < len; i++) + vec[i].init(MagicValue(JS_ARRAY_HOLE)); + } else { + for (uintN i = 0; i < len; i++) + vec[i].init(UndefinedValue()); + } +} + +static JS_ALWAYS_INLINE void +DestroyValueRange(HeapValue *vec, uintN len) +{ + for (uintN i = 0; i < len; i++) + vec[i].~HeapValue(); +} + +inline +HeapValue::HeapValue(const Value &v) + : value(v) +{ + post(); +} + +inline +HeapValue::HeapValue(const HeapValue &v) + : value(v.value) +{ + post(); +} + +inline +HeapValue::~HeapValue() +{ + pre(); +} + +inline void +HeapValue::init(const Value &v) +{ + value = v; + post(); +} + +inline void +HeapValue::writeBarrierPre(const Value &value) +{ +#ifdef JSGC_INCREMENTAL + if (value.isMarkable()) { + js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing(); + writeBarrierPre(cell->compartment(), value); + } +#endif +} + +inline void +HeapValue::writeBarrierPost(const Value &value, void *addr) +{ +} + +inline void +HeapValue::writeBarrierPre(JSCompartment *comp, const Value &value) +{ +#ifdef JSGC_INCREMENTAL + if (comp->needsBarrier()) + js::gc::MarkValueUnbarriered(comp->barrierTracer(), value, "write barrier"); +#endif +} + +inline void +HeapValue::writeBarrierPost(JSCompartment *comp, const Value &value, void *addr) +{ +} + +inline void +HeapValue::pre() +{ + writeBarrierPre(value); +} + +inline void +HeapValue::post() +{ +} + +inline void +HeapValue::pre(JSCompartment *comp) +{ + writeBarrierPre(comp, value); +} + +inline void +HeapValue::post(JSCompartment *comp) +{ +} + +inline HeapValue & +HeapValue::operator=(const Value &v) +{ + pre(); + value = v; + post(); + return *this; +} + +inline HeapValue & +HeapValue::operator=(const HeapValue &v) +{ + pre(); + value = v.value; + post(); + return *this; +} + +inline void +HeapValue::set(JSCompartment *comp, const Value &v) +{ +#ifdef DEBUG + if (value.isMarkable()) { + js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing(); + JS_ASSERT(cell->compartment() == comp || + cell->compartment() == comp->rt->atomsCompartment); + } +#endif + + pre(comp); + value = v; + post(comp); +} + +inline void +HeapValue::boxNonDoubleFrom(JSValueType type, uint64 *out) +{ + pre(); + value.boxNonDoubleFrom(type, out); + post(); +} + +inline +HeapId::HeapId(jsid id) + : value(id) +{ + post(); +} + +inline +HeapId::~HeapId() +{ + pre(); +} + +inline void +HeapId::init(jsid id) +{ + value = id; + post(); +} + +inline void +HeapId::pre() +{ +#ifdef JSGC_INCREMENTAL + if (JS_UNLIKELY(JSID_IS_OBJECT(value))) { + JSObject *obj = JSID_TO_OBJECT(value); + JSCompartment *comp = obj->compartment(); + if (comp->needsBarrier()) + js::gc::MarkObjectUnbarriered(comp->barrierTracer(), obj, "write barrier"); + } +#endif +} + +inline void +HeapId::post() +{ +} + +inline HeapId & +HeapId::operator=(jsid id) +{ + pre(); + value = id; + post(); + return *this; +} + +inline HeapId & +HeapId::operator=(const HeapId &v) +{ + pre(); + value = v.value; + post(); + return *this; +} + +} /* namespace js */ + +#endif /* jsgc_barrier_inl_h___ */ diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h new file mode 100644 index 000000000000..a410eea6759e --- /dev/null +++ b/js/src/gc/Barrier.h @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=78: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is SpiderMonkey global object code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef jsgc_barrier_h___ +#define jsgc_barrier_h___ + +#include "jsapi.h" +#include "jscell.h" + +#include "js/HashTable.h" + +/* + * A write barrier is a mechanism used by incremental or generation GCs to + * ensure that every value that needs to be marked is marked. In general, the + * write barrier should be invoked whenever a write can cause the set of things + * traced through by the GC to change. This includes: + * - writes to object properties + * - writes to array slots + * - writes to fields like JSObject::lastProp that we trace through + * - writes to fields in private data, like JSGenerator::obj + * - writes to non-markable fields like JSObject::private that point to + * markable data + * The last category is the trickiest. Even though the private pointers does not + * point to a GC thing, changing the private pointer may change the set of + * objects that are traced by the GC. Therefore it needs a write barrier. + * + * Every barriered write should have the following form: + * + * obj->field = value; // do the actual write + * + * The pre-barrier is used for incremental GC and the post-barrier is for + * generational GC. + * + * PRE-BARRIER + * + * To understand the pre-barrier, let's consider how incremental GC works. The + * GC itself is divided into "slices". Between each slice, JS code is allowed to + * run. Each slice should be short so that the user doesn't notice the + * interruptions. In our GC, the structure of the slices is as follows: + * + * 1. ... JS work, which leads to a request to do GC ... + * 2. [first GC slice, which performs all root marking and possibly more marking] + * 3. ... more JS work is allowed to run ... + * 4. [GC mark slice, which runs entirely in drainMarkStack] + * 5. ... more JS work ... + * 6. [GC mark slice, which runs entirely in drainMarkStack] + * 7. ... more JS work ... + * 8. [GC marking finishes; sweeping done non-incrementally; GC is done] + * 9. ... JS continues uninterrupted now that GC is finishes ... + * + * Of course, there may be a different number of slices depending on how much + * marking is to be done. + * + * The danger inherent in this scheme is that the JS code in steps 3, 5, and 7 + * might change the heap in a way that causes the GC to collect an object that + * is actually reachable. The write barrier prevents this from happening. We use + * a variant of incremental GC called "snapshot at the beginning." This approach + * guarantees the invariant that if an object is reachable in step 2, then we + * will mark it eventually. The name comes from the idea that we take a + * theoretical "snapshot" of all reachable objects in step 2; all objects in + * that snapshot should eventually be marked. (Note that the write barrier + * verifier code takes an actual snapshot.) + * + * The basic correctness invariant of a snapshot-at-the-beginning collector is + * that any object reachable at the end of the GC (step 9) must either: + * (1) have been reachable at the beginning (step 2) and thus in the snapshot + * (2) or must have been newly allocated, in steps 3, 5, or 7. + * To deal with case (2), any objects allocated during an incremental GC are + * automatically marked black. + * + * This strategy is actually somewhat conservative: if an object becomes + * unreachable between steps 2 and 8, it would be safe to collect it. We won't, + * mainly for simplicity. (Also, note that the snapshot is entirely + * theoretical. We don't actually do anything special in step 2 that we wouldn't + * do in a non-incremental GC. + * + * It's the pre-barrier's job to maintain the snapshot invariant. Consider the + * write "obj->field = value". Let the prior value of obj->field be + * value0. Since it's possible that value0 may have been what obj->field + * contained in step 2, when the snapshot was taken, the barrier marks + * value0. Note that it only does this if we're in the middle of an incremental + * GC. Since this is rare, the cost of the write barrier is usually just an + * extra branch. + * + * In practice, we implement the pre-barrier differently based on the type of + * value0. E.g., see JSObject::writeBarrierPre, which is used if obj->field is + * a JSObject*. It takes value0 as a parameter. + * + * POST-BARRIER + * + * These are not yet implemented. Once we get generational GC, they will allow + * us to keep track of pointers from non-nursery space into the nursery. + * + * IMPLEMENTATION DETAILS + * + * Since it would be awkward to change every write to memory into a function + * call, this file contains a bunch of C++ classes and templates that use + * operator overloading to take care of barriers automatically. In many cases, + * all that's necessary to make some field be barriered is to replace + * Type *field; + * with + * HeapPtr field; + * There are also special classes HeapValue and HeapId, which barrier js::Value + * and jsid, respectively. + * + * One additional note: not all object writes need to be barriered. Writes to + * newly allocated objects do not need a barrier as long as the GC is not + * allowed to run in between the allocation and the write. In these cases, we + * use the "obj->field.init(value)" method instead of "obj->field = value". + * We use the init naming idiom in many places to signify that a field is being + * assigned for the first time, and that no GCs have taken place between the + * object allocation and the assignment. + */ + +namespace js { + +/* + * Ideally, we would like to make the argument to functions like MarkShape be a + * HeapPtr. That would ensure that we don't forget to + * barrier any fields that we mark through. However, that would prohibit us from + * passing in a derived class like HeapPtr. + * + * To overcome the problem, we make the argument to MarkShape be a + * MarkablePtr. And we allow conversions from HeapPtr + * to MarkablePtr as long as T can be converted to U. + */ +template +class MarkablePtr +{ + public: + T *value; + + explicit MarkablePtr(T *value) : value(value) {} +}; + +template +class HeapPtr +{ + union { + T *value; + Unioned other; + }; + + public: + HeapPtr() : value(NULL) {} + explicit HeapPtr(T *v) : value(v) { post(); } + explicit HeapPtr(const HeapPtr &v) : value(v.value) { post(); } + + ~HeapPtr() { pre(); } + + /* Use this to install a ptr into a newly allocated object. */ + void init(T *v) { + value = v; + post(); + } + + /* Use to set the pointer to NULL. */ + void clear() { + pre(); + value = NULL; + } + + /* Use this if the automatic coercion to T* isn't working. */ + T *get() const { return value; } + + /* + * Use these if you want to change the value without invoking the barrier. + * Obviously this is dangerous unless you know the barrier is not needed. + */ + T **unsafeGet() { return &value; } + void unsafeSet(T *v) { value = v; } + + Unioned *unsafeGetUnioned() { return &other; } + + HeapPtr &operator=(T *v) { + pre(); + value = v; + post(); + return *this; + } + + HeapPtr &operator=(const HeapPtr &v) { + pre(); + value = v.value; + post(); + return *this; + } + + T &operator*() const { return *value; } + T *operator->() const { return value; } + + operator T*() const { return value; } + + /* + * This coerces to MarkablePtr as long as T can coerce to U. See the + * comment for MarkablePtr above. + */ + template + operator MarkablePtr() const { return MarkablePtr(value); } + + private: + void pre() { T::writeBarrierPre(value); } + void post() { T::writeBarrierPost(value, (void *)&value); } + + /* Make this friend so it can access pre() and post(). */ + template + friend inline void + BarrieredSetPair(JSCompartment *comp, + HeapPtr &v1, T1 *val1, + HeapPtr &v2, T2 *val2); +}; + +/* + * This is a hack for RegExpStatics::updateFromMatch. It allows us to do two + * barriers with only one branch to check if we're in an incremental GC. + */ +template +static inline void +BarrieredSetPair(JSCompartment *comp, + HeapPtr &v1, T1 *val1, + HeapPtr &v2, T2 *val2) +{ + if (T1::needWriteBarrierPre(comp)) { + v1.pre(); + v2.pre(); + } + v1.unsafeSet(val1); + v2.unsafeSet(val2); + v1.post(); + v2.post(); +} + +typedef HeapPtr HeapPtrObject; +typedef HeapPtr HeapPtrFunction; +typedef HeapPtr HeapPtrString; +typedef HeapPtr HeapPtrScript; +typedef HeapPtr HeapPtrShape; +typedef HeapPtr HeapPtrConstShape; +typedef HeapPtr HeapPtrXML; + +/* Useful for hashtables with a HeapPtr as key. */ +template +struct HeapPtrHasher +{ + typedef HeapPtr Key; + typedef T *Lookup; + + static HashNumber hash(Lookup obj) { return DefaultHasher::hash(obj); } + static bool match(const Key &k, Lookup l) { return k.get() == l; } +}; + +/* Specialized hashing policy for HeapPtrs. */ +template +struct DefaultHasher< HeapPtr >: HeapPtrHasher { }; + +class HeapValue +{ + Value value; + + public: + explicit HeapValue() : value(UndefinedValue()) {} + explicit inline HeapValue(const Value &v); + explicit inline HeapValue(const HeapValue &v); + + inline ~HeapValue(); + + inline void init(const Value &v); + + inline HeapValue &operator=(const Value &v); + inline HeapValue &operator=(const HeapValue &v); + + /* + * This is a faster version of operator=. Normally, operator= has to + * determine the compartment of the value before it can decide whether to do + * the barrier. If you already know the compartment, it's faster to pass it + * in. + */ + inline void set(JSCompartment *comp, const Value &v); + + const Value &get() const { return value; } + operator const Value &() const { return value; } + + bool isMarkable() const { return value.isMarkable(); } + bool isMagic(JSWhyMagic why) const { return value.isMagic(why); } + bool isUndefined() const { return value.isUndefined(); } + bool isObject() const { return value.isObject(); } + bool isGCThing() const { return value.isGCThing(); } + bool isTrue() const { return value.isTrue(); } + bool isFalse() const { return value.isFalse(); } + bool isInt32() const { return value.isInt32(); } + bool isNull() const { return value.isNull(); } + + JSObject &toObject() const { return value.toObject(); } + JSObject *toObjectOrNull() const { return value.toObjectOrNull(); } + void *toGCThing() const { return value.toGCThing(); } + double toDouble() const { return value.toDouble(); } + int32 toInt32() const { return value.toInt32(); } + JSString *toString() const { return value.toString(); } + bool toBoolean() const { return value.toBoolean(); } + double toNumber() const { return value.toNumber(); } + + unsigned gcKind() const { return value.gcKind(); } + + inline void boxNonDoubleFrom(JSValueType type, uint64 *out); + + uint64 asRawBits() const { return value.asRawBits(); } + +#ifdef DEBUG + JSWhyMagic whyMagic() const { return value.whyMagic(); } +#endif + + static inline void writeBarrierPre(const Value &v); + static inline void writeBarrierPost(const Value &v, void *addr); + + static inline void writeBarrierPre(JSCompartment *comp, const Value &v); + static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr); + + private: + inline void pre(); + inline void post(); + + inline void pre(JSCompartment *comp); + inline void post(JSCompartment *comp); +}; + +static inline const Value * +Valueify(const HeapValue *array) +{ + JS_ASSERT(sizeof(HeapValue) == sizeof(Value)); + return (const Value *)array; +} + +class HeapValueArray +{ + HeapValue *array; + + public: + HeapValueArray(HeapValue *array) : array(array) {} + + operator const Value *() const { return Valueify(array); } + operator HeapValue *() const { return array; } + + HeapValueArray operator +(int offset) const { return HeapValueArray(array + offset); } + HeapValueArray operator +(uint32 offset) const { return HeapValueArray(array + offset); } +}; + +class HeapId +{ + jsid value; + + public: + explicit HeapId() : value(JSID_VOID) {} + explicit inline HeapId(jsid id); + + inline ~HeapId(); + + inline void init(jsid id); + + inline HeapId &operator=(jsid id); + inline HeapId &operator=(const HeapId &v); + + bool operator==(jsid id) const { return value == id; } + bool operator!=(jsid id) const { return value != id; } + + jsid get() const { return value; } + operator jsid() const { return value; } + + private: + inline void pre(); + inline void post(); + + HeapId(const HeapId &v); +}; + +/* + * Incremental GC requires that weak pointers have read barriers. This is mostly + * an issue for empty shapes stored in JSCompartment. The problem happens when, + * during an incremental GC, some JS code stores one of the compartment's empty + * shapes into an object already marked black. Normally, this would not be a + * problem, because the empty shape would have been part of the initial snapshot + * when the GC started. However, since this is a weak pointer, it isn't. So we + * may collect the empty shape even though a live object points to it. To fix + * this, we mark these empty shapes black whenever they get read out. + */ +template +class ReadBarriered +{ + T *value; + + public: + ReadBarriered(T *value) : value(value) {} + + T *get() const { + if (!value) + return NULL; + T::readBarrier(value); + return value; + } + + operator T*() const { return get(); } + + T *unsafeGet() { return value; } + + void set(T *v) { value = v; } + + operator bool() { return !!value; } + + template + operator MarkablePtr() const { return MarkablePtr(value); } +}; + +} + +#endif /* jsgc_barrier_h___ */ diff --git a/js/src/jsapi-tests/testArgumentsObject.cpp b/js/src/jsapi-tests/testArgumentsObject.cpp index 83587c56fbd5..359852f50a2c 100644 --- a/js/src/jsapi-tests/testArgumentsObject.cpp +++ b/js/src/jsapi-tests/testArgumentsObject.cpp @@ -6,6 +6,8 @@ #include "vm/Stack-inl.h" +#include "jsobjinlines.h" + using namespace js; static const char NORMAL_ZERO[] = diff --git a/js/src/jsapi-tests/testBug604087.cpp b/js/src/jsapi-tests/testBug604087.cpp index 27b7e0b54aa8..63a43c2978ca 100644 --- a/js/src/jsapi-tests/testBug604087.cpp +++ b/js/src/jsapi-tests/testBug604087.cpp @@ -8,6 +8,8 @@ #include "jsobj.h" #include "jswrapper.h" +#include "jsobjinlines.h" + struct OuterWrapper : js::Wrapper { OuterWrapper() : Wrapper(0) {} diff --git a/js/src/jsapi-tests/testConservativeGC.cpp b/js/src/jsapi-tests/testConservativeGC.cpp index 0286060b157a..45eb898e8885 100644 --- a/js/src/jsapi-tests/testConservativeGC.cpp +++ b/js/src/jsapi-tests/testConservativeGC.cpp @@ -7,7 +7,8 @@ BEGIN_TEST(testConservativeGC) jsval v2; EVAL("({foo: 'bar'});", &v2); CHECK(JSVAL_IS_OBJECT(v2)); - JSObject objCopy = *JSVAL_TO_OBJECT(v2); + char objCopy[sizeof(JSObject)]; + memcpy(&objCopy, JSVAL_TO_OBJECT(v2), sizeof(JSObject)); jsval v3; EVAL("String(Math.PI);", &v3); @@ -18,7 +19,8 @@ BEGIN_TEST(testConservativeGC) EVAL("({foo2: 'bar2'});", &tmp); CHECK(JSVAL_IS_OBJECT(tmp)); JSObject *obj2 = JSVAL_TO_OBJECT(tmp); - JSObject obj2Copy = *obj2; + char obj2Copy[sizeof(JSObject)]; + memcpy(&obj2Copy, obj2, sizeof(JSObject)); EVAL("String(Math.sqrt(3));", &tmp); CHECK(JSVAL_IS_STRING(tmp)); @@ -36,10 +38,10 @@ BEGIN_TEST(testConservativeGC) JS_GC(cx); - checkObjectFields(&objCopy, JSVAL_TO_OBJECT(v2)); + checkObjectFields((JSObject *)objCopy, JSVAL_TO_OBJECT(v2)); CHECK(!memcmp(&strCopy, JSVAL_TO_STRING(v3), sizeof(strCopy))); - checkObjectFields(&obj2Copy, obj2); + checkObjectFields((JSObject *)obj2Copy, obj2); CHECK(!memcmp(&str2Copy, str2, sizeof(str2Copy))); return true; diff --git a/js/src/jsapi-tests/testIndexToString.cpp b/js/src/jsapi-tests/testIndexToString.cpp index c93410f59554..f240b601ac72 100644 --- a/js/src/jsapi-tests/testIndexToString.cpp +++ b/js/src/jsapi-tests/testIndexToString.cpp @@ -9,6 +9,8 @@ #include "jsnum.h" #include "jsstr.h" +#include "jsobjinlines.h" + #include "vm/String-inl.h" using namespace mozilla; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 3926bf2b9252..db4fe2c6095e 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -96,6 +96,7 @@ #include "jsscriptinlines.h" #include "vm/RegExpObject-inl.h" +#include "vm/RegExpStatics-inl.h" #include "vm/Stack-inl.h" #include "vm/String-inl.h" @@ -657,7 +658,7 @@ JSRuntime::JSRuntime() gcMaxMallocBytes(0), gcEmptyArenaPoolLifespan(0), gcNumber(0), - gcMarkingTracer(NULL), + gcIncrementalTracer(NULL), gcChunkAllocationSinceLastGC(false), gcNextFullGCTime(0), gcJitReleaseTime(0), @@ -1327,7 +1328,7 @@ JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target) { CHECK_REQUEST(cx); JS_ASSERT(!target->isCachedEval); - GlobalObject *global = target->u.globalObject; + GlobalObject *global = target->globalObject; if (!global) { SwitchToCompartment sc(cx, target->compartment()); global = GlobalObject::create(cx, &dummy_class); @@ -1952,9 +1953,7 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) return JS_TRUE; } -namespace js { - -JSIdArray * +static JSIdArray * NewIdArray(JSContext *cx, jsint length) { JSIdArray *ida; @@ -1966,8 +1965,6 @@ NewIdArray(JSContext *cx, jsint length) return ida; } -} - /* * Unlike realloc(3), this function frees ida on failure. */ @@ -2000,7 +1997,7 @@ AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip) return NULL; JS_ASSERT(i < ida->length); } - ida->vector[i] = ATOM_TO_JSID(atom); + ida->vector[i].init(ATOM_TO_JSID(atom)); *ip = i + 1; return ida; } @@ -2330,11 +2327,16 @@ JS_TraceRuntime(JSTracer *trc) TraceRuntime(trc); } +JS_PUBLIC_API(void) +JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind) +{ + js::TraceChildren(trc, thing, kind); +} + JS_PUBLIC_API(void) JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind) { - JS_ASSERT(thing); - MarkKind(trc, thing, kind); + js::CallTracer(trc, thing, kind); } #ifdef DEBUG @@ -2782,8 +2784,8 @@ JS_PUBLIC_API(JSBool) JS_IsAboutToBeFinalized(JSContext *cx, void *thing) { JS_ASSERT(thing); - JS_ASSERT(!cx->runtime->gcMarkingTracer); - return IsAboutToBeFinalized(cx, thing); + JS_ASSERT(!cx->runtime->gcIncrementalTracer); + return IsAboutToBeFinalized(cx, (gc::Cell *)thing); } JS_PUBLIC_API(void) @@ -2942,6 +2944,19 @@ JS_SetNativeStackQuota(JSContext *cx, size_t stackSize) /************************************************************************/ +JS_PUBLIC_API(jsint) +JS_IdArrayLength(JSContext *cx, JSIdArray *ida) +{ + return ida->length; +} + +JS_PUBLIC_API(jsid) +JS_IdArrayGet(JSContext *cx, JSIdArray *ida, jsint index) +{ + JS_ASSERT(index >= 0 && index < ida->length); + return ida->vector[index]; +} + JS_PUBLIC_API(void) JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) { @@ -4105,12 +4120,16 @@ prop_iter_trace(JSTracer *trc, JSObject *obj) return; if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) { - /* Native case: just mark the next property to visit. */ - MarkShape(trc, (Shape *)pdata, "prop iter shape"); + /* + * Native case: just mark the next property to visit. We don't need a + * barrier here because the pointer is updated via setPrivate, which + * always takes a barrier. + */ + MarkShapeUnbarriered(trc, (Shape *)pdata, "prop iter shape"); } else { /* Non-native case: mark each id in the JSIdArray private. */ JSIdArray *ida = (JSIdArray *) pdata; - MarkIdRange(trc, ida->length, ida->vector, "prop iter"); + MarkIdRange(trc, ida->vector, ida->vector + ida->length, "prop iter"); } } @@ -4138,7 +4157,7 @@ JS_PUBLIC_API(JSObject *) JS_NewPropertyIterator(JSContext *cx, JSObject *obj) { JSObject *iterobj; - const void *pdata; + void *pdata; jsint index; JSIdArray *ida; @@ -4150,7 +4169,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj) if (obj->isNative()) { /* Native case: start with the last property in obj. */ - pdata = obj->lastProperty(); + pdata = (void *)obj->lastProperty(); index = -1; } else { /* @@ -4168,7 +4187,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj) } /* iterobj cannot escape to other threads here. */ - iterobj->setPrivate(const_cast(pdata)); + iterobj->setPrivate(pdata); iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index)); return iterobj; } @@ -4431,7 +4450,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) Value v; if (!obj->getGeneric(cx, r.front().propid, &v)) return NULL; - clone->getFlatClosureUpvars()[i] = v; + clone->setFlatClosureUpvar(i, v); } return clone; @@ -4882,9 +4901,9 @@ JS_PUBLIC_API(JSObject *) JS_GetGlobalFromScript(JSScript *script) { JS_ASSERT(!script->isCachedEval); - JS_ASSERT(script->u.globalObject); + JS_ASSERT(script->globalObject); - return script->u.globalObject; + return script->globalObject; } static JSFunction * @@ -6367,6 +6386,63 @@ js_GetCompartmentPrivate(JSCompartment *compartment) /************************************************************************/ +JS_PUBLIC_API(void) +JS_RegisterReference(void **ref) +{ +} + +JS_PUBLIC_API(void) +JS_ModifyReference(void **ref, void *newval) +{ + // XPConnect uses the lower bits of its JSObject refs for evil purposes, + // so we need to fix this. + void *thing = *ref; + *ref = newval; + thing = (void *)((uintptr_t)thing & ~7); + if (!thing) + return; + uint32 kind = GetGCThingTraceKind(thing); + if (kind == JSTRACE_OBJECT) + JSObject::writeBarrierPre((JSObject *) thing); + else if (kind == JSTRACE_STRING) + JSString::writeBarrierPre((JSString *) thing); + else + JS_NOT_REACHED("invalid trace kind"); +} + +JS_PUBLIC_API(void) +JS_UnregisterReference(void **ref) +{ + // For now we just want to trigger a write barrier. + JS_ModifyReference(ref, NULL); +} + +JS_PUBLIC_API(void) +JS_RegisterValue(jsval *val) +{ +} + +JS_PUBLIC_API(void) +JS_ModifyValue(jsval *val, jsval newval) +{ + HeapValue::writeBarrierPre(*val); + *val = newval; +} + +JS_PUBLIC_API(void) +JS_UnregisterValue(jsval *val) +{ + JS_ModifyValue(val, JSVAL_VOID); +} + +JS_PUBLIC_API(JSTracer *) +JS_GetIncrementalGCTracer(JSRuntime *rt) +{ + return rt->gcIncrementalTracer; +} + +/************************************************************************/ + #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) #include "jswin.h" diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 35a98febd641..c86f6bc92245 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2698,6 +2698,7 @@ typedef void (* JSTraceCallback)(JSTracer *trc, void *thing, JSGCTraceKind kind); struct JSTracer { + JSRuntime *runtime; JSContext *context; JSTraceCallback callback; JSTraceNamePrinter debugPrinter; @@ -2798,6 +2799,7 @@ JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind); */ # define JS_TRACER_INIT(trc, cx_, callback_) \ JS_BEGIN_MACRO \ + (trc)->runtime = (cx_)->runtime; \ (trc)->context = (cx_); \ (trc)->callback = (callback_); \ (trc)->debugPrinter = NULL; \ @@ -2842,6 +2844,88 @@ JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, JSGCTraceKind kind, #endif +/* + * Write barrier API. + * + * This API is used to inform SpiderMonkey of pointers to JS GC things in the + * malloc heap. There is no need to use this API unless incremental GC is + * enabled. When they are, the requirements for using the API are as follows: + * + * All pointers to JS GC things from the malloc heap must be registered and + * unregistered with the API functions below. This is *in addition* to the + * normal rooting and tracing that must be done normally--these functions will + * not take care of rooting for you. + * + * Besides registration, the JS_ModifyReference function must be called to + * change the value of these references. You should not change them using + * assignment. + * + * To avoid the headache of using these API functions, the JSBarrieredObjectPtr + * C++ class is provided--simply replace your JSObject* with a + * JSBarrieredObjectPtr. It will take care of calling the registration and + * modification APIs. + * + * For more explanation, see the comment in gc/Barrier.h. + */ + +/* These functions are to be used for objects and strings. */ +extern JS_PUBLIC_API(void) +JS_RegisterReference(void **ref); + +extern JS_PUBLIC_API(void) +JS_ModifyReference(void **ref, void *newval); + +extern JS_PUBLIC_API(void) +JS_UnregisterReference(void **ref); + +/* These functions are for values. */ +extern JS_PUBLIC_API(void) +JS_RegisterValue(jsval *val); + +extern JS_PUBLIC_API(void) +JS_ModifyValue(jsval *val, jsval newval); + +extern JS_PUBLIC_API(void) +JS_UnregisterValue(jsval *val); + +extern JS_PUBLIC_API(JSTracer *) +JS_GetIncrementalGCTracer(JSRuntime *rt); + +#ifdef __cplusplus +JS_END_EXTERN_C + +namespace JS { + +class HeapPtrObject +{ + JSObject *value; + + public: + HeapPtrObject() : value(NULL) { JS_RegisterReference((void **) &value); } + + HeapPtrObject(JSObject *obj) : value(obj) { JS_RegisterReference((void **) &value); } + + ~HeapPtrObject() { JS_UnregisterReference((void **) &value); } + + void init(JSObject *obj) { value = obj; } + + JSObject *get() const { return value; } + + HeapPtrObject &operator=(JSObject *obj) { + JS_ModifyReference((void **) &value, obj); + return *this; + } + + JSObject &operator*() const { return *value; } + JSObject *operator->() const { return value; } + operator JSObject *() const { return value; } +}; + +} /* namespace JS */ + +JS_BEGIN_EXTERN_C +#endif + /* * Garbage collector API. */ @@ -3115,10 +3199,11 @@ struct JSClass { #define JSCLASS_NO_INTERNAL_MEMBERS 0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} #define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS -struct JSIdArray { - jsint length; - jsid vector[1]; /* actually, length jsid words */ -}; +extern JS_PUBLIC_API(jsint) +JS_IdArrayLength(JSContext *cx, JSIdArray *ida); + +extern JS_PUBLIC_API(jsid) +JS_IdArrayGet(JSContext *cx, JSIdArray *ida, jsint index); extern JS_PUBLIC_API(void) JS_DestroyIdArray(JSContext *cx, JSIdArray *ida); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 8cb3677edc81..369978197ad5 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -649,14 +649,13 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value * the initialized capacity. */ jsuint oldcap = obj->getDenseArrayCapacity(); + jsuint oldinit = obj->getDenseArrayInitializedLength(); + if (oldinit > newlen) + obj->setDenseArrayInitializedLength(newlen); if (oldcap > newlen) obj->shrinkDenseArrayElements(cx, newlen); - jsuint oldinit = obj->getDenseArrayInitializedLength(); - if (oldinit > newlen) { - obj->setDenseArrayInitializedLength(newlen); - if (!cx->typeInferenceEnabled()) - obj->backfillDenseArrayHoles(cx); - } + if (oldinit > newlen && !cx->typeInferenceEnabled()) + obj->backfillDenseArrayHoles(cx); } else if (oldlen - newlen < (1 << 24)) { do { --oldlen; @@ -1340,8 +1339,11 @@ JSObject::makeDenseArraySlow(JSContext *cx) /* Create a native scope. */ gc::AllocKind kind = getAllocKind(); - if (!InitScopeForObject(cx, this, &SlowArrayClass, getProto()->getNewType(cx), kind)) + js::EmptyShape *empty = InitScopeForObject(cx, this, &SlowArrayClass, + getProto()->getNewType(cx), kind); + if (!empty) return false; + setMap(empty); backfillDenseArrayHoles(cx); @@ -1367,10 +1369,10 @@ JSObject::makeDenseArraySlow(JSContext *cx) * Root all values in the array during conversion, as SlowArrayClass only * protects up to its slot span. */ - AutoValueArray autoArray(cx, slots, arrayInitialized); + AutoValueArray autoArray(cx, Valueify(slots), arrayInitialized); /* The initialized length is used iff this is a dense array. */ - initializedLength = 0; + initializedLength() = 0; JS_ASSERT(newType == NULL); /* @@ -1380,7 +1382,7 @@ JSObject::makeDenseArraySlow(JSContext *cx) if (!AddLengthProperty(cx, this)) { setMap(oldMap); capacity = arrayCapacity; - initializedLength = arrayInitialized; + initializedLength() = arrayInitialized; clasp = &ArrayClass; return false; } @@ -1403,7 +1405,7 @@ JSObject::makeDenseArraySlow(JSContext *cx) if (!addDataProperty(cx, id, next, JSPROP_ENUMERATE)) { setMap(oldMap); capacity = arrayCapacity; - initializedLength = arrayInitialized; + initializedLength() = arrayInitialized; clasp = &ArrayClass; return false; } @@ -2497,7 +2499,7 @@ NewbornArrayPushImpl(JSContext *cx, JSObject *obj, const Value &v) if (cx->typeInferenceEnabled()) obj->setDenseArrayInitializedLength(length + 1); obj->setDenseArrayLength(length + 1); - obj->setDenseArrayElementWithType(cx, length, v); + obj->initDenseArrayElementWithType(cx, length, v); return true; } @@ -2893,16 +2895,16 @@ array_splice(JSContext *cx, uintN argc, Value *vp) /* Steps 12(a)-(b). */ obj->moveDenseArrayElements(targetIndex, sourceIndex, len - sourceIndex); - /* Steps 12(c)-(d). */ - obj->shrinkDenseArrayElements(cx, finalLength); - /* - * The array's initialized length is now out of sync with the array - * elements: resynchronize it. + * Update the initialized length. Do so before shrinking so that we + * can apply the write barrier to the old slots. */ if (cx->typeInferenceEnabled()) obj->setDenseArrayInitializedLength(finalLength); + /* Steps 12(c)-(d). */ + obj->shrinkDenseArrayElements(cx, finalLength); + /* Fix running enumerators for the deleted items. */ if (!js_SuppressDeletedElements(cx, obj, finalLength, len)) return false; @@ -3019,10 +3021,12 @@ mjit::stubs::ArrayConcatTwoArrays(VMFrame &f) if (!result->ensureSlots(f.cx, len)) THROW(); - result->copyDenseArrayElements(0, obj1->getDenseArrayElements(), initlen1); - result->copyDenseArrayElements(initlen1, obj2->getDenseArrayElements(), initlen2); - + JS_ASSERT(!result->getDenseArrayInitializedLength()); result->setDenseArrayInitializedLength(len); + + result->initDenseArrayElements(0, obj1->getDenseArrayElements(), initlen1); + result->initDenseArrayElements(initlen1, obj2->getDenseArrayElements(), initlen2); + result->setDenseArrayLength(len); } #endif /* JS_METHODJIT */ @@ -3920,7 +3924,7 @@ NewDenseCopiedArray(JSContext *cx, uint32 length, const Value *vp, JSObject *pro obj->setDenseArrayInitializedLength(vp ? length : 0); if (vp) - obj->copyDenseArrayElements(0, vp, length); + obj->initDenseArrayElements(0, vp, length); return obj; } diff --git a/js/src/jsarray.h b/js/src/jsarray.h index b775cfe2ee5a..9db642634368 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -55,7 +55,7 @@ inline uint32 JSObject::getDenseArrayInitializedLength() { JS_ASSERT(isDenseArray()); - return initializedLength; + return initializedLength(); } inline bool diff --git a/js/src/jsarrayinlines.h b/js/src/jsarrayinlines.h index c30af8f79762..c347f1751802 100644 --- a/js/src/jsarrayinlines.h +++ b/js/src/jsarrayinlines.h @@ -48,7 +48,9 @@ JSObject::setDenseArrayInitializedLength(uint32 length) { JS_ASSERT(isDenseArray()); JS_ASSERT(length <= getDenseArrayCapacity()); - initializedLength = length; + uint32 cur = initializedLength(); + prepareSlotRangeForOverwrite(length, cur); + initializedLength() = length; } inline void @@ -77,12 +79,13 @@ JSObject::ensureDenseArrayInitializedLength(JSContext *cx, uint32 index, uint32 * for a write. */ JS_ASSERT(index + extra <= capacity); - if (initializedLength < index) { + if (initializedLength() < index) markDenseArrayNotPacked(cx); - js::ClearValueRange(slots + initializedLength, index - initializedLength, true); + + if (initializedLength() < index + extra) { + js::InitValueRange(slots + initializedLength(), index + extra - initializedLength(), true); + initializedLength() = index + extra; } - if (initializedLength < index + extra) - initializedLength = index + extra; } inline JSObject::EnsureDenseResult diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 829b6c7c2561..3e01b01adbe0 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -389,7 +389,7 @@ js_FinishCommonAtoms(JSContext *cx) void js_TraceAtomState(JSTracer *trc) { - JSRuntime *rt = trc->context->runtime; + JSRuntime *rt = trc->runtime; JSAtomState *state = &rt->atomState; #ifdef DEBUG @@ -399,7 +399,7 @@ js_TraceAtomState(JSTracer *trc) if (rt->gcKeepAtoms) { for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront()) { JS_SET_TRACING_INDEX(trc, "locked_atom", number++); - MarkString(trc, r.front().asPtr()); + MarkAtom(trc, r.front().asPtr()); } } else { for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront()) { @@ -408,7 +408,7 @@ js_TraceAtomState(JSTracer *trc) continue; JS_SET_TRACING_INDEX(trc, "interned_atom", number++); - MarkString(trc, entry.asPtr()); + MarkAtom(trc, entry.asPtr()); } } } diff --git a/js/src/jsatom.h b/js/src/jsatom.h index dc7740ef92f0..4370c33250bc 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -49,9 +49,15 @@ #include "jspubtd.h" #include "jslock.h" +#include "gc/Barrier.h" #include "js/HashTable.h" #include "vm/String.h" +struct JSIdArray { + jsint length; + js::HeapId vector[1]; /* actually, length jsid words */ +}; + /* Engine-internal extensions of jsid */ static JS_ALWAYS_INLINE jsid diff --git a/js/src/jscell.h b/js/src/jscell.h index 3477e7c3358f..0af5fa60f50f 100644 --- a/js/src/jscell.h +++ b/js/src/jscell.h @@ -66,7 +66,6 @@ enum AllocKind { FINALIZE_OBJECT16_BACKGROUND, FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND, FINALIZE_FUNCTION, - FINALIZE_FUNCTION_AND_OBJECT_LAST = FINALIZE_FUNCTION, FINALIZE_SCRIPT, FINALIZE_SHAPE, FINALIZE_TYPE_OBJECT, @@ -75,11 +74,12 @@ enum AllocKind { #endif FINALIZE_SHORT_STRING, FINALIZE_STRING, - FINALIZE_EXTERNAL_STRING, - FINALIZE_LAST = FINALIZE_EXTERNAL_STRING + FINALIZE_EXTERNAL_STRING }; -const size_t FINALIZE_LIMIT = FINALIZE_LAST + 1; +static const unsigned FINALIZE_LIMIT = FINALIZE_EXTERNAL_STRING + 1; +static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT16_BACKGROUND + 1; +static const unsigned FINALIZE_FUNCTION_AND_OBJECT_LIMIT = FINALIZE_FUNCTION + 1; /* * Live objects are marked black. How many other additional colors are available diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index ca974673acf6..8b91e1f2df1d 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -460,11 +460,12 @@ struct JSRuntime /* We access this without the GC lock, however a race will not affect correctness */ volatile uint32 gcNumFreeArenas; uint32 gcNumber; - js::GCMarker *gcMarkingTracer; + js::GCMarker *gcIncrementalTracer; bool gcChunkAllocationSinceLastGC; int64 gcNextFullGCTime; int64 gcJitReleaseTime; JSGCMode gcMode; + volatile jsuword gcBarrierFailed; volatile jsuword gcIsNeeded; js::WeakMapBase *gcWeakMapList; js::gcstats::Statistics gcStats; @@ -2215,18 +2216,6 @@ namespace js { /************************************************************************/ -static JS_ALWAYS_INLINE void -ClearValueRange(Value *vec, uintN len, bool useHoles) -{ - if (useHoles) { - for (uintN i = 0; i < len; i++) - vec[i].setMagic(JS_ARRAY_HOLE); - } else { - for (uintN i = 0; i < len; i++) - vec[i].setUndefined(); - } -} - static JS_ALWAYS_INLINE void MakeRangeGCSafe(Value *vec, size_t len) { @@ -2416,26 +2405,23 @@ class AutoShapeVector : public AutoVectorRooter class AutoValueArray : public AutoGCRooter { - js::Value *start_; + const js::Value *start_; unsigned length_; public: - AutoValueArray(JSContext *cx, js::Value *start, unsigned length + AutoValueArray(JSContext *cx, const js::Value *start, unsigned length JS_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, VALARRAY), start_(start), length_(length) { JS_GUARD_OBJECT_NOTIFIER_INIT; } - Value *start() const { return start_; } + const Value *start() const { return start_; } unsigned length() const { return length_; } JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; -JSIdArray * -NewIdArray(JSContext *cx, jsint length); - /* * Allocation policy that uses JSRuntime::malloc_ and friends, so that * memory pressure is properly accounted for. This is suitable for diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index f9c36dc62ce2..78221d807c66 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -115,7 +115,7 @@ class AutoNamespaceArray : protected AutoGCRooter { public: friend void AutoGCRooter::trace(JSTracer *trc); - JSXMLArray array; + JSXMLArray array; }; #ifdef DEBUG @@ -208,8 +208,8 @@ class CompartmentChecker void check(JSScript *script) { if (script) { check(script->compartment()); - if (!script->isCachedEval && script->u.globalObject) - check(script->u.globalObject); + if (!script->isCachedEval && script->globalObject) + check(script->globalObject); } } diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 182f14b7b004..4a52f7ef5597 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -58,6 +58,7 @@ #include "vm/Debugger.h" #include "jsgcinlines.h" +#include "jsobjinlines.h" #include "jsscopeinlines.h" #if ENABLE_YARR_JIT @@ -71,6 +72,8 @@ using namespace js::gc; JSCompartment::JSCompartment(JSRuntime *rt) : rt(rt), principals(NULL), + needsBarrier_(false), + gcIncrementalTracer(NULL), gcBytes(0), gcTriggerBytes(0), gcLastBytes(0), @@ -348,6 +351,16 @@ JSCompartment::wrap(JSContext *cx, JSString **strp) return true; } +bool +JSCompartment::wrap(JSContext *cx, HeapPtrString *strp) +{ + AutoValueRooter tvr(cx, StringValue(*strp)); + if (!wrap(cx, tvr.addr())) + return false; + *strp = tvr.value().toString(); + return true; +} + bool JSCompartment::wrap(JSContext *cx, JSObject **objp) { @@ -420,10 +433,10 @@ JSCompartment::wrap(JSContext *cx, AutoIdVector &props) void JSCompartment::markCrossCompartmentWrappers(JSTracer *trc) { - JS_ASSERT(trc->context->runtime->gcCurrentCompartment); + JS_ASSERT(trc->runtime->gcCurrentCompartment); for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) - MarkValue(trc, e.front().key, "cross-compartment wrapper"); + MarkRoot(trc, e.front().key, "cross-compartment wrapper"); } void @@ -438,21 +451,21 @@ JSCompartment::markTypes(JSTracer *trc) for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); - MarkScript(trc, script, "mark_types_script"); + MarkRoot(trc, script, "mark_types_script"); } for (size_t thingKind = FINALIZE_OBJECT0; - thingKind <= FINALIZE_FUNCTION_AND_OBJECT_LAST; + thingKind < FINALIZE_FUNCTION_AND_OBJECT_LIMIT; thingKind++) { for (CellIterUnderGC i(this, AllocKind(thingKind)); !i.done(); i.next()) { JSObject *object = i.get(); if (!object->isNewborn() && object->hasSingletonType()) - MarkObject(trc, *object, "mark_types_singleton"); + MarkRoot(trc, object, "mark_types_singleton"); } } for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next()) - MarkTypeObject(trc, i.get(), "mark_types_scan"); + MarkRoot(trc, i.get(), "mark_types_scan"); } void @@ -460,11 +473,11 @@ JSCompartment::sweep(JSContext *cx, bool releaseTypes) { /* Remove dead wrappers from the table. */ for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { - JS_ASSERT_IF(IsAboutToBeFinalized(cx, e.front().key.toGCThing()) && - !IsAboutToBeFinalized(cx, e.front().value.toGCThing()), + JS_ASSERT_IF(IsAboutToBeFinalized(cx, e.front().key) && + !IsAboutToBeFinalized(cx, e.front().value), e.front().key.isString()); - if (IsAboutToBeFinalized(cx, e.front().key.toGCThing()) || - IsAboutToBeFinalized(cx, e.front().value.toGCThing())) { + if (IsAboutToBeFinalized(cx, e.front().key) || + IsAboutToBeFinalized(cx, e.front().value)) { e.removeFront(); } } @@ -584,7 +597,7 @@ JSCompartment::purge(JSContext *cx) JSScript *script = *listHeadp; JS_ASSERT(GetGCThingTraceKind(script) == JSTRACE_SCRIPT); *listHeadp = NULL; - listHeadp = &script->u.evalHashLink; + listHeadp = &script->evalHashLink(); } } @@ -827,7 +840,7 @@ JSCompartment::markTrapClosuresIteratively(JSTracer *trc) // Put off marking trap state until we know the script is live. if (site->trapHandler && !IsAboutToBeFinalized(cx, site->script)) { if (site->trapClosure.isMarkable() && - IsAboutToBeFinalized(cx, site->trapClosure.toGCThing())) + IsAboutToBeFinalized(cx, site->trapClosure)) { markedAny = true; } @@ -858,3 +871,10 @@ JSCompartment::sweepBreakpoints(JSContext *cx) site->clearTrap(cx, &e); } } + +GCMarker * +JSCompartment::createBarrierTracer() +{ + JS_ASSERT(!gcIncrementalTracer); + return NULL; +} diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 52403eab6658..c01476833be4 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -397,6 +397,20 @@ struct JS_FRIEND_API(JSCompartment) { js::gc::ArenaLists arenas; + bool needsBarrier_; + js::GCMarker *gcIncrementalTracer; + + bool needsBarrier() { + return needsBarrier_; + } + + js::GCMarker *barrierTracer() { + JS_ASSERT(needsBarrier_); + if (gcIncrementalTracer) + return gcIncrementalTracer; + return createBarrierTracer(); + } + uint32 gcBytes; uint32 gcTriggerBytes; size_t gcLastBytes; @@ -474,16 +488,19 @@ struct JS_FRIEND_API(JSCompartment) { jsrefcount liveDictModeNodes; #endif + typedef js::ReadBarriered BarrieredEmptyShape; + typedef js::ReadBarriered BarrieredShape; + /* * Runtime-shared empty scopes for well-known built-in objects that lack * class prototypes (the usual locus of an emptyShape). Mnemonic: ABCDEW */ - js::EmptyShape *emptyArgumentsShape; - js::EmptyShape *emptyBlockShape; - js::EmptyShape *emptyCallShape; - js::EmptyShape *emptyDeclEnvShape; - js::EmptyShape *emptyEnumeratorShape; - js::EmptyShape *emptyWithShape; + BarrieredEmptyShape emptyArgumentsShape; + BarrieredEmptyShape emptyBlockShape; + BarrieredEmptyShape emptyCallShape; + BarrieredEmptyShape emptyDeclEnvShape; + BarrieredEmptyShape emptyEnumeratorShape; + BarrieredEmptyShape emptyWithShape; typedef js::HashSet, @@ -500,8 +517,8 @@ struct JS_FRIEND_API(JSCompartment) { * dictionary mode). But because all the initial properties are * non-configurable, they will always map to fixed slots. */ - const js::Shape *initialRegExpShape; - const js::Shape *initialStringShape; + BarrieredShape initialRegExpShape; + BarrieredShape initialStringShape; private: enum { DebugFromC = 1, DebugFromJS = 2 }; @@ -526,6 +543,7 @@ struct JS_FRIEND_API(JSCompartment) { bool wrap(JSContext *cx, js::Value *vp); bool wrap(JSContext *cx, JSString **strp); + bool wrap(JSContext *cx, js::HeapPtrString *strp); bool wrap(JSContext *cx, JSObject **objp); bool wrapId(JSContext *cx, jsid *idp); bool wrap(JSContext *cx, js::PropertyOp *op); @@ -624,6 +642,8 @@ struct JS_FRIEND_API(JSCompartment) { private: void sweepBreakpoints(JSContext *cx); + js::GCMarker *createBarrierTracer(); + public: js::WatchpointMap *watchpointMap; }; diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index a0d9223eae72..ff0cd4f4ce70 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -69,8 +69,10 @@ #include "jsinferinlines.h" #include "jsobjinlines.h" +#include "jsstrinlines.h" #include "vm/Stack-inl.h" +#include "vm/String-inl.h" using namespace mozilla; using namespace js; @@ -113,7 +115,7 @@ Class js::ErrorClass = { }; typedef struct JSStackTraceElem { - JSString *funName; + js::HeapPtrString funName; size_t argc; const char *filename; uintN ulineno; @@ -122,8 +124,8 @@ typedef struct JSStackTraceElem { typedef struct JSExnPrivate { /* A copy of the JSErrorReport originally generated. */ JSErrorReport *errorReport; - JSString *message; - JSString *filename; + js::HeapPtrString message; + js::HeapPtrString filename; uintN lineno; size_t stackDepth; intN exnType; @@ -328,12 +330,12 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, return false; JSStackTraceElem &frame = frames.back(); if (fp->isNonEvalFunctionFrame()) { - frame.funName = fp->fun()->atom ? fp->fun()->atom : cx->runtime->emptyString; + frame.funName.init(fp->fun()->atom ? fp->fun()->atom : cx->runtime->emptyString); frame.argc = fp->numActualArgs(); if (!fp->forEachCanonicalActualArg(AppendArg(values))) return false; } else { - frame.funName = NULL; + frame.funName.init(NULL); frame.argc = 0; } if (fp->isScriptFrame()) { @@ -357,6 +359,9 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, if (!priv) return false; + /* Initialize to zero so that write barriers don't witness undefined values. */ + memset(priv, 0, nbytes); + if (report) { /* * Construct a new copy of the error report struct. We can't use the @@ -373,8 +378,8 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, priv->errorReport = NULL; } - priv->message = message; - priv->filename = filename; + priv->message.init(message); + priv->filename.init(filename); priv->lineno = lineno; priv->stackDepth = frames.length(); priv->exnType = exnType; @@ -422,8 +427,9 @@ exn_trace(JSTracer *trc, JSObject *obj) } vp = GetStackTraceValueBuffer(priv); for (i = 0; i != vcount; ++i, ++vp) { + /* This value is read-only, so it's okay for it to be Unbarriered. */ v = *vp; - JS_CALL_VALUE_TRACER(trc, v, "stack trace argument"); + MarkValueUnbarriered(trc, v, "stack trace argument"); } } } @@ -494,8 +500,6 @@ exn_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, if (!stack) return false; - /* Allow to GC all things that were used to build stack trace. */ - priv->stackDepth = 0; prop = js_stack_str; v = STRING_TO_JSVAL(stack); attrs = JSPROP_ENUMERATE; @@ -1342,11 +1346,11 @@ js_CopyErrorObject(JSContext *cx, JSObject *errobj, JSObject *scope) } else { copy->errorReport = NULL; } - copy->message = priv->message; + copy->message.init(priv->message); if (!cx->compartment->wrap(cx, ©->message)) return NULL; JS::Anchor messageAnchor(copy->message); - copy->filename = priv->filename; + copy->filename.init(priv->filename); if (!cx->compartment->wrap(cx, ©->filename)) return NULL; JS::Anchor filenameAnchor(copy->filename); diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 3cfdb115774a..fe2fc9d64f53 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -151,32 +151,35 @@ ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee) cx->malloc_(offsetof(ArgumentsData, slots) + argc * sizeof(Value)); if (!data) return NULL; - SetValueRangeToUndefined(data->slots, argc); + + data->callee.init(ObjectValue(callee)); + InitValueRange(data->slots, argc, false); /* Can't fail from here on, so initialize everything in argsobj. */ obj->init(cx, callee.getFunctionPrivate()->inStrictMode() ? &StrictArgumentsObjectClass : &NormalArgumentsObjectClass, type, proto->getParent(), NULL, false); - obj->setMap(emptyArgumentsShape); + obj->initMap(emptyArgumentsShape); ArgumentsObject *argsobj = obj->asArguments(); JS_ASSERT(UINT32_MAX > (uint64(argc) << PACKED_BITS_COUNT)); - argsobj->setInitialLength(argc); - - argsobj->setCalleeAndData(callee, data); + argsobj->initInitialLength(argc); + argsobj->initData(data); return argsobj; } struct STATIC_SKIP_INFERENCE PutArg { - PutArg(Value *dst) : dst(dst) {} - Value *dst; + PutArg(JSCompartment *comp, HeapValue *dst) : dst(dst), compartment(comp) {} + HeapValue *dst; + JSCompartment *compartment; bool operator()(uintN, Value *src) { + JS_ASSERT(dst->isMagic(JS_ARGS_HOLE) || dst->isUndefined()); if (!dst->isMagic(JS_ARGS_HOLE)) - *dst = *src; + dst->set(compartment, *src); ++dst; return true; } @@ -220,7 +223,7 @@ js_GetArgsObject(JSContext *cx, StackFrame *fp) * retrieve up-to-date parameter values. */ if (argsobj->isStrictArguments()) - fp->forEachCanonicalActualArg(PutArg(argsobj->data()->slots)); + fp->forEachCanonicalActualArg(PutArg(cx->compartment, argsobj->data()->slots)); else argsobj->setStackFrame(fp); @@ -234,7 +237,8 @@ js_PutArgsObject(StackFrame *fp) ArgumentsObject &argsobj = fp->argsObj(); if (argsobj.isNormalArguments()) { JS_ASSERT(argsobj.maybeStackFrame() == fp); - fp->forEachCanonicalActualArg(PutArg(argsobj.data()->slots)); + JSCompartment *comp = fp->scopeChain().compartment(); + fp->forEachCanonicalActualArg(PutArg(comp, argsobj.data()->slots)); argsobj.setStackFrame(NULL); } else { JS_ASSERT(!argsobj.maybeStackFrame()); @@ -282,10 +286,11 @@ js_PutArgumentsOnTrace(JSContext *cx, JSObject *obj, Value *argv) * need to worry about actual vs. formal arguments. */ Value *srcend = argv + argsobj->initialLength(); - Value *dst = argsobj->data()->slots; + HeapValue *dst = argsobj->data()->slots; + JSCompartment *comp = cx->compartment; for (Value *src = argv; src < srcend; ++src, ++dst) { if (!dst->isMagic(JS_ARGS_HOLE)) - *dst = *src; + dst->set(comp, *src); } argsobj->clearOnTrace(); @@ -601,10 +606,8 @@ MaybeMarkGenerator(JSTracer *trc, JSObject *obj) { #if JS_HAS_GENERATORS StackFrame *fp = (StackFrame *) obj->getPrivate(); - if (fp && fp->isFloatingGenerator()) { - JSObject *genobj = js_FloatingFrameToGenerator(fp)->obj; - MarkObject(trc, *genobj, "generator object"); - } + if (fp && fp->isFloatingGenerator()) + MarkObject(trc, js_FloatingFrameToGenerator(fp)->obj, "generator object"); #endif } @@ -618,8 +621,7 @@ args_trace(JSTracer *trc, JSObject *obj) } ArgumentsData *data = argsobj->data(); - if (data->callee.isObject()) - MarkObject(trc, data->callee.toObject(), js_callee_str); + MarkValue(trc, data->callee, js_callee_str); MarkValueRange(trc, argsobj->initialLength(), data->slots, js_arguments_str); MaybeMarkGenerator(trc, argsobj); @@ -707,7 +709,7 @@ NewDeclEnvObject(JSContext *cx, StackFrame *fp) if (!emptyDeclEnvShape) return NULL; envobj->init(cx, &DeclEnvClass, &emptyTypeObject, &fp->scopeChain(), fp, false); - envobj->setMap(emptyDeclEnvShape); + envobj->initMap(emptyDeclEnvShape); return envobj; } @@ -786,7 +788,7 @@ js_PutCallObject(StackFrame *fp) /* Get the arguments object to snapshot fp's actual argument values. */ if (fp->hasArgsObj()) { if (!fp->hasOverriddenArgs()) - callobj.setArguments(ObjectValue(fp->argsObj())); + callobj.initArguments(ObjectValue(fp->argsObj())); js_PutArgsObject(fp); } @@ -823,18 +825,21 @@ js_PutCallObject(StackFrame *fp) } else { /* * For each arg & var that is closed over, copy it from the stack - * into the call object. + * into the call object. We use initArg/VarUnchecked because, + * when you call a getter on a call object, js_NativeGetInline + * caches the return value in the slot, so we can't assert that + * it's undefined. */ uint32 nclosed = script->nClosedArgs; for (uint32 i = 0; i < nclosed; i++) { uint32 e = script->getClosedArg(i); - callobj.setArg(e, fp->formalArg(e)); + callobj.initArgUnchecked(e, fp->formalArg(e)); } nclosed = script->nClosedVars; for (uint32 i = 0; i < nclosed; i++) { uint32 e = script->getClosedVar(i); - callobj.setVar(e, fp->slots()[e]); + callobj.initVarUnchecked(e, fp->slots()[e]); } } @@ -1592,19 +1597,24 @@ fun_trace(JSTracer *trc, JSObject *obj) return; if (fun != obj) { - /* obj is a cloned function object, trace the clone-parent, fun. */ - MarkObject(trc, *fun, "private"); + /* + * obj is a cloned function object, trace the clone-parent, fun. + * This is safe to leave Unbarriered for incremental GC because any + * change to fun will trigger a setPrivate barrer. But we'll need to + * fix this for generational GC. + */ + MarkObjectUnbarriered(trc, fun, "private"); /* The function could be a flat closure with upvar copies in the clone. */ if (fun->isFlatClosure() && fun->script()->bindings.hasUpvars()) { MarkValueRange(trc, fun->script()->bindings.countUpvars(), - obj->getFlatClosureUpvars(), "upvars"); + obj->getFlatClosureData()->upvars, "upvars"); } return; } if (fun->atom) - MarkString(trc, fun->atom, "atom"); + MarkAtom(trc, fun->atom, "atom"); if (fun->isInterpreted() && fun->script()) MarkScript(trc, fun->script(), "script"); @@ -1849,7 +1859,7 @@ JSObject::initBoundFunction(JSContext *cx, const Value &thisArg, return false; JS_ASSERT(numSlots() >= argslen + FUN_CLASS_RESERVED_SLOTS); - copySlotRange(FUN_CLASS_RESERVED_SLOTS, args, argslen); + copySlotRange(FUN_CLASS_RESERVED_SLOTS, args, argslen, false); } return true; } @@ -2278,7 +2288,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, Native native, uintN nargs, JS_ASSERT(!native); JS_ASSERT(nargs == 0); fun->u.i.skipmin = 0; - fun->u.i.script_ = NULL; + fun->script().init(NULL); } else { fun->u.n.clasp = NULL; if (flags & JSFUN_TRCINFO) { @@ -2328,7 +2338,7 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, * definitions or read barriers, so will not get here. */ if (fun->getProto() == proto && !fun->hasSingletonType()) - clone->setType(fun->type()); + clone->initType(fun->type()); clone->setPrivate(fun); } else { @@ -2352,11 +2362,11 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, JS_ASSERT(script->compartment() == fun->compartment()); JS_ASSERT(script->compartment() != cx->compartment); - cfun->u.i.script_ = NULL; + cfun->script().init(NULL); JSScript *cscript = js_CloneScript(cx, script); if (!cscript) return NULL; - cscript->u.globalObject = cfun->getGlobal(); + cscript->globalObject = cfun->getGlobal(); cfun->setScript(cscript); if (!cscript->typeSetFunction(cx, cfun)) return NULL; @@ -2395,11 +2405,11 @@ js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain) if (nslots == 0) return closure; - Value *upvars = (Value *) cx->malloc_(nslots * sizeof(Value)); - if (!upvars) + FlatClosureData *data = (FlatClosureData *) cx->malloc_(nslots * sizeof(HeapValue)); + if (!data) return NULL; - closure->setFlatClosureUpvars(upvars); + closure->setFlatClosureData(data); return closure; } @@ -2425,12 +2435,12 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen) if (!closure || !fun->script()->bindings.hasUpvars()) return closure; - Value *upvars = closure->getFlatClosureUpvars(); + FlatClosureData *data = closure->getFlatClosureData(); uintN level = fun->script()->staticLevel; JSUpvarArray *uva = fun->script()->upvars(); for (uint32 i = 0, n = uva->length; i < n; i++) - upvars[i] = GetUpvar(cx, level, uva->vector[i]); + data->upvars[i].init(GetUpvar(cx, level, uva->vector[i])); return closure; } diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 9cf8efc5bb02..f85ba97aba79 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -50,6 +50,8 @@ #include "jsstr.h" #include "jsopcode.h" +#include "gc/Barrier.h" + /* * The high two bits of JSFunction.flags encode whether the function is native * or interpreted, and if interpreted, what kind of optimized closure form (if @@ -195,18 +197,16 @@ struct JSFunction : public JSObject_Slots2 inline void setMethodAtom(JSAtom *atom); - JSScript *script() const { + js::HeapPtrScript &script() const { JS_ASSERT(isInterpreted()); - return u.i.script_; + return *(js::HeapPtrScript *)&u.i.script_; } - void setScript(JSScript *script) { - JS_ASSERT(isInterpreted()); - u.i.script_ = script; - } + inline void setScript(JSScript *script_); + inline void initScript(JSScript *script_); JSScript *maybeScript() const { - return isInterpreted() ? script() : NULL; + return isInterpreted() ? script().get() : NULL; } JSNative native() const { @@ -269,6 +269,10 @@ JSObject::getFunctionPrivate() const namespace js { +struct FlatClosureData { + HeapValue upvars[1]; +}; + static JS_ALWAYS_INLINE bool IsFunctionObject(const js::Value &v) { diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h index 777f195fee5f..80c94ca04427 100644 --- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -97,4 +97,18 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, return js_CloneFunctionObject(cx, fun, parent, proto); } +inline void +JSFunction::setScript(JSScript *script_) +{ + JS_ASSERT(isInterpreted()); + script() = script_; +} + +inline void +JSFunction::initScript(JSScript *script_) +{ + JS_ASSERT(isInterpreted()); + script().init(script_); +} + #endif /* jsfuninlines_h___ */ diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 8f05be84343b..a0d35206ca1a 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -788,7 +788,7 @@ PickChunk(JSCompartment *comp) } JS_FRIEND_API(bool) -IsAboutToBeFinalized(JSContext *cx, const void *thing) +IsAboutToBeFinalized(JSContext *cx, const Cell *thing) { JS_ASSERT(cx); @@ -801,6 +801,13 @@ IsAboutToBeFinalized(JSContext *cx, const void *thing) return !reinterpret_cast(thing)->isMarked(); } +bool +IsAboutToBeFinalized(JSContext *cx, const Value &v) +{ + JS_ASSERT(v.isMarkable()); + return IsAboutToBeFinalized(cx, (Cell *)v.toGCThing()); +} + JS_FRIEND_API(bool) js_GCThingIsMarked(void *thing, uintN color = BLACK) { @@ -918,7 +925,7 @@ MarkIfGCThingWord(JSTracer *trc, jsuword w) Chunk *chunk = Chunk::fromAddress(addr); - if (!trc->context->runtime->gcChunkSet.has(chunk)) + if (!trc->runtime->gcChunkSet.has(chunk)) return CGCT_NOTCHUNK; /* @@ -939,7 +946,7 @@ MarkIfGCThingWord(JSTracer *trc, jsuword w) if (!aheader->allocated()) return CGCT_FREEARENA; - JSCompartment *curComp = trc->context->runtime->gcCurrentCompartment; + JSCompartment *curComp = trc->runtime->gcCurrentCompartment; if (curComp && curComp != aheader->compartment) return CGCT_OTHERCOMPARTMENT; @@ -1045,7 +1052,7 @@ MarkStackRangeConservatively(JSTracer *trc, Value *beginv, Value *endv) rt->gcCheckCompartment = NULL; } ~AutoSkipChecking() { runtime->gcCheckCompartment = savedCompartment; } - } as(trc->context->runtime); + } as(trc->runtime); const jsuword *begin = beginv->payloadWord(); const jsuword *end = endv->payloadWord(); @@ -1066,7 +1073,7 @@ void MarkConservativeStackRoots(JSTracer *trc) { #ifdef JS_THREADSAFE - for (JSThread::Map::Range r = trc->context->runtime->threads.all(); !r.empty(); r.popFront()) { + for (JSThread::Map::Range r = trc->runtime->threads.all(); !r.empty(); r.popFront()) { JSThread *thread = r.front().value; ConservativeGCThreadData *ctd = &thread->data.conservativeGC; if (ctd->hasStackToScan()) { @@ -1078,7 +1085,7 @@ MarkConservativeStackRoots(JSTracer *trc) } } #else - MarkThreadDataConservatively(trc, &trc->context->runtime->threadData); + MarkThreadDataConservatively(trc, &trc->runtime->threadData); #endif } @@ -1822,7 +1829,7 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry) ptr = vp->isGCThing() ? vp->toGCThing() : NULL; } - if (ptr && !trc->context->runtime->gcCurrentCompartment) { + if (ptr && !trc->runtime->gcCurrentCompartment) { /* * Use conservative machinery to find if ptr is a valid GC thing. * We only do this during global GCs, to preserve the invariant @@ -1841,44 +1848,45 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry) JS_ASSERT(test == CGCT_VALID); } #endif - JS_SET_TRACING_NAME(trc, entry.value.name ? entry.value.name : "root"); + const char *name = entry.value.name ? entry.value.name : "root"; if (entry.value.type == JS_GC_ROOT_GCTHING_PTR) - MarkGCThing(trc, *reinterpret_cast(entry.key)); + MarkRootGCThing(trc, *reinterpret_cast(entry.key), name); else - MarkValueRaw(trc, *reinterpret_cast(entry.key)); + MarkRoot(trc, *reinterpret_cast(entry.key), name); } static void gc_lock_traversal(const GCLocks::Entry &entry, JSTracer *trc) { JS_ASSERT(entry.value >= 1); - MarkGCThing(trc, entry.key, "locked object"); + MarkRootGCThing(trc, entry.key, "locked object"); } void js_TraceStackFrame(JSTracer *trc, StackFrame *fp) { - MarkObject(trc, fp->scopeChain(), "scope chain"); + MarkRoot(trc, &fp->scopeChain(), "scope chain"); if (fp->isDummyFrame()) return; if (fp->hasArgsObj()) - MarkObject(trc, fp->argsObj(), "arguments"); - MarkScript(trc, fp->script(), "script"); + MarkRoot(trc, &fp->argsObj(), "arguments"); + MarkRoot(trc, fp->script(), "script"); fp->script()->compartment()->active = true; - MarkValue(trc, fp->returnValue(), "rval"); + MarkRoot(trc, fp->returnValue(), "rval"); } void AutoIdArray::trace(JSTracer *trc) { JS_ASSERT(tag == IDARRAY); - gc::MarkIdRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray"); + gc::MarkIdRange(trc, idArray->vector, idArray->vector + idArray->length, + "JSAutoIdArray.idArray"); } void AutoEnumStateRooter::trace(JSTracer *trc) { - gc::MarkObject(trc, *obj, "js::AutoEnumStateRooter.obj"); + gc::MarkRoot(trc, obj, "js::AutoEnumStateRooter.obj"); } inline void @@ -1886,7 +1894,7 @@ AutoGCRooter::trace(JSTracer *trc) { switch (tag) { case JSVAL: - MarkValue(trc, static_cast(this)->val, "js::AutoValueRooter.val"); + MarkRoot(trc, static_cast(this)->val, "js::AutoValueRooter.val"); return; case PARSER: @@ -1899,7 +1907,7 @@ AutoGCRooter::trace(JSTracer *trc) case IDARRAY: { JSIdArray *ida = static_cast(this)->idArray; - MarkIdRange(trc, ida->length, ida->vector, "js::AutoIdArray.idArray"); + MarkIdRange(trc, ida->vector, ida->vector + ida->length, "js::AutoIdArray.idArray"); return; } @@ -1908,10 +1916,10 @@ AutoGCRooter::trace(JSTracer *trc) static_cast(this)->descriptors; for (size_t i = 0, len = descriptors.length(); i < len; i++) { PropDesc &desc = descriptors[i]; - MarkValue(trc, desc.pd, "PropDesc::pd"); - MarkValue(trc, desc.value, "PropDesc::value"); - MarkValue(trc, desc.get, "PropDesc::get"); - MarkValue(trc, desc.set, "PropDesc::set"); + MarkRoot(trc, desc.pd, "PropDesc::pd"); + MarkRoot(trc, desc.value, "PropDesc::value"); + MarkRoot(trc, desc.get, "PropDesc::get"); + MarkRoot(trc, desc.set, "PropDesc::set"); } return; } @@ -1919,19 +1927,18 @@ AutoGCRooter::trace(JSTracer *trc) case DESCRIPTOR : { PropertyDescriptor &desc = *static_cast(this); if (desc.obj) - MarkObject(trc, *desc.obj, "Descriptor::obj"); - MarkValue(trc, desc.value, "Descriptor::value"); + MarkRoot(trc, desc.obj, "Descriptor::obj"); + MarkRoot(trc, desc.value, "Descriptor::value"); if ((desc.attrs & JSPROP_GETTER) && desc.getter) - MarkObject(trc, *CastAsObject(desc.getter), "Descriptor::get"); + MarkRoot(trc, CastAsObject(desc.getter), "Descriptor::get"); if (desc.attrs & JSPROP_SETTER && desc.setter) - MarkObject(trc, *CastAsObject(desc.setter), "Descriptor::set"); + MarkRoot(trc, CastAsObject(desc.setter), "Descriptor::set"); return; } case NAMESPACES: { - JSXMLArray &array = static_cast(this)->array; - MarkObjectRange(trc, array.length, reinterpret_cast(array.vector), - "JSXMLArray.vector"); + JSXMLArray &array = static_cast(this)->array; + MarkObjectRange(trc, array.length, array.vector, "JSXMLArray.vector"); array.cursors->trace(trc); return; } @@ -1942,51 +1949,52 @@ AutoGCRooter::trace(JSTracer *trc) case OBJECT: if (JSObject *obj = static_cast(this)->obj) - MarkObject(trc, *obj, "js::AutoObjectRooter.obj"); + MarkRoot(trc, obj, "js::AutoObjectRooter.obj"); return; case ID: - MarkId(trc, static_cast(this)->id_, "js::AutoIdRooter.val"); + MarkRoot(trc, static_cast(this)->id_, "js::AutoIdRooter.val"); return; case VALVECTOR: { AutoValueVector::VectorImpl &vector = static_cast(this)->vector; - MarkValueRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector"); + MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector"); return; } case STRING: if (JSString *str = static_cast(this)->str) - MarkString(trc, str, "js::AutoStringRooter.str"); + MarkRoot(trc, str, "js::AutoStringRooter.str"); return; case IDVECTOR: { AutoIdVector::VectorImpl &vector = static_cast(this)->vector; - MarkIdRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector"); + MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector"); return; } case SHAPEVECTOR: { AutoShapeVector::VectorImpl &vector = static_cast(this)->vector; - MarkShapeRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector"); + MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector"); return; } case OBJVECTOR: { AutoObjectVector::VectorImpl &vector = static_cast(this)->vector; - MarkObjectRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector"); + MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector"); return; } case VALARRAY: { AutoValueArray *array = static_cast(this); - MarkValueRange(trc, array->length(), array->start(), "js::AutoValueArray"); + MarkRootRange(trc, array->length(), array->start(), "js::AutoValueArray"); return; } } JS_ASSERT(tag >= 0); - MarkValueRange(trc, tag, static_cast(this)->array, "js::AutoArrayRooter.array"); + MarkRootRange(trc, tag, static_cast(this)->array, + "js::AutoArrayRooter.array"); } namespace js { @@ -1998,9 +2006,9 @@ MarkContext(JSTracer *trc, JSContext *acx) /* Mark other roots-by-definition in acx. */ if (acx->globalObject && !acx->hasRunOption(JSOPTION_UNROOTED_GLOBAL)) - MarkObject(trc, *acx->globalObject, "global object"); + MarkRoot(trc, acx->globalObject, "global object"); if (acx->isExceptionPending()) - MarkValue(trc, acx->getPendingException(), "exception"); + MarkRoot(trc, acx->getPendingException(), "exception"); for (js::AutoGCRooter *gcr = acx->autoGCRooters; gcr; gcr = gcr->down) gcr->trace(trc); @@ -2008,13 +2016,13 @@ MarkContext(JSTracer *trc, JSContext *acx) if (acx->sharpObjectMap.depth > 0) js_TraceSharpMap(trc, &acx->sharpObjectMap); - MarkValue(trc, acx->iterValue, "iterValue"); + MarkRoot(trc, acx->iterValue, "iterValue"); } JS_REQUIRES_STACK void MarkRuntime(JSTracer *trc) { - JSRuntime *rt = trc->context->runtime; + JSRuntime *rt = trc->runtime; if (rt->state != JSRTS_LANDING) MarkConservativeStackRoots(trc); @@ -2516,7 +2524,7 @@ EndMarkPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind) gcmarker->drainMarkStack(); } - rt->gcMarkingTracer = NULL; + rt->gcIncrementalTracer = NULL; rt->gcStats.endPhase(gcstats::PHASE_MARK); @@ -2667,7 +2675,7 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind) GCMarker gcmarker(cx); JS_ASSERT(IS_GC_MARKING_TRACER(&gcmarker)); JS_ASSERT(gcmarker.getMarkColor() == BLACK); - rt->gcMarkingTracer = &gcmarker; + rt->gcIncrementalTracer = &gcmarker; BeginMarkPhase(cx, &gcmarker, gckind); gcmarker.drainMarkStack(); @@ -3041,7 +3049,7 @@ TraceRuntime(JSTracer *trc) } } #else - AutoCopyFreeListToArenas copy(trc->context->runtime); + AutoCopyFreeListToArenas copy(trc->runtime); RecordNativeStackTopForGC(trc->context); #endif diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 70c8ec678cf3..6ee1f8a94aa2 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -88,7 +88,7 @@ struct Arena; * This must be an upper bound, but we do not need the least upper bound, so * we just exclude non-background objects. */ -const size_t MAX_BACKGROUND_FINALIZE_KINDS = FINALIZE_LIMIT - (FINALIZE_OBJECT_LAST + 1) / 2; +const size_t MAX_BACKGROUND_FINALIZE_KINDS = FINALIZE_LIMIT - FINALIZE_OBJECT_LIMIT / 2; const size_t ArenaShift = 12; const size_t ArenaSize = size_t(1) << ArenaShift; @@ -1327,7 +1327,10 @@ extern void js_UnlockGCThingRT(JSRuntime *rt, void *thing); extern JS_FRIEND_API(bool) -IsAboutToBeFinalized(JSContext *cx, const void *thing); +IsAboutToBeFinalized(JSContext *cx, const js::gc::Cell *thing); + +extern bool +IsAboutToBeFinalized(JSContext *cx, const js::Value &value); extern JS_FRIEND_API(bool) js_GCThingIsMarked(void *thing, uintN color); diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index a2efdba95149..8d7ae59d8dc0 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -96,7 +96,7 @@ GetGCObjectFixedSlotsKind(size_t numFixedSlots) static inline bool IsBackgroundAllocKind(AllocKind kind) { - JS_ASSERT(kind <= FINALIZE_OBJECT_LAST); + JS_ASSERT(kind < FINALIZE_OBJECT_LIMIT); return kind % 2 == 1; } @@ -115,7 +115,7 @@ static inline bool TryIncrementAllocKind(AllocKind *kindp) { size_t next = size_t(*kindp) + 2; - if (next > size_t(FINALIZE_OBJECT_LAST)) + if (next >= size_t(FINALIZE_OBJECT_LIMIT)) return false; *kindp = AllocKind(next); return true; @@ -351,14 +351,17 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize) js::gc::RunDebugGC(cx); #endif - void *t = cx->compartment->arenas.allocateFromFreeList(kind, thingSize); - return static_cast(t ? t : js::gc::ArenaLists::refillFreeList(cx, kind)); + JSCompartment *comp = cx->compartment; + void *t = comp->arenas.allocateFromFreeList(kind, thingSize); + if (!t) + t = js::gc::ArenaLists::refillFreeList(cx, kind); + return static_cast(t); } inline JSObject * js_NewGCObject(JSContext *cx, js::gc::AllocKind kind) { - JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST); + JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind < js::gc::FINALIZE_OBJECT_LIMIT); JSObject *obj = NewGCThing(cx, kind, js::gc::Arena::thingSize(kind)); if (obj) obj->earlyInit(js::gc::GetGCKindSlots(kind)); @@ -388,10 +391,8 @@ inline JSFunction* js_NewGCFunction(JSContext *cx) { JSFunction *fun = NewGCThing(cx, js::gc::FINALIZE_FUNCTION, sizeof(JSFunction)); - if (fun) { - fun->capacity = JSObject::FUN_CLASS_RESERVED_SLOTS; - fun->lastProp = NULL; /* Stops fun from being scanned until initializated. */ - } + if (fun) + fun->earlyInit(JSObject::FUN_CLASS_RESERVED_SLOTS); return fun; } diff --git a/js/src/jsgcmark.cpp b/js/src/jsgcmark.cpp index e5bd317ef8f8..bc32d75a275c 100644 --- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -110,12 +110,12 @@ CheckMarkedThing(JSTracer *trc, T *thing) { JS_ASSERT(thing); JS_ASSERT(trc->debugPrinter || trc->debugPrintArg); - JS_ASSERT_IF(trc->context->runtime->gcCurrentCompartment, IS_GC_MARKING_TRACER(trc)); + JS_ASSERT_IF(trc->runtime->gcCurrentCompartment, IS_GC_MARKING_TRACER(trc)); JS_ASSERT(thing->isAligned()); JS_ASSERT(thing->compartment()); - JS_ASSERT(thing->compartment()->rt == trc->context->runtime); + JS_ASSERT(thing->compartment()->rt == trc->runtime); } template @@ -124,7 +124,7 @@ Mark(JSTracer *trc, T *thing) { CheckMarkedThing(trc, thing); - JSRuntime *rt = trc->context->runtime; + JSRuntime *rt = trc->runtime; JS_OPT_ASSERT_IF(rt->gcCheckCompartment, thing->compartment() == rt->gcCheckCompartment || @@ -148,51 +148,60 @@ Mark(JSTracer *trc, T *thing) } void -MarkString(JSTracer *trc, JSString *str) +MarkStringUnbarriered(JSTracer *trc, JSString *str, const char *name) { JS_ASSERT(str); + JS_SET_TRACING_NAME(trc, name); Mark(trc, str); } void -MarkString(JSTracer *trc, JSString *str, const char *name) +MarkString(JSTracer *trc, const MarkablePtr &str, const char *name) { - JS_ASSERT(str); - JS_SET_TRACING_NAME(trc, name); - MarkString(trc, str); + MarkStringUnbarriered(trc, str.value, name); } void -MarkObject(JSTracer *trc, JSObject &obj, const char *name) +MarkAtom(JSTracer *trc, JSAtom *atom) { JS_ASSERT(trc); - JS_ASSERT(&obj); - JS_SET_TRACING_NAME(trc, name); - Mark(trc, &obj); + JS_ASSERT(atom); + Mark(trc, atom); } void -MarkCrossCompartmentObject(JSTracer *trc, JSObject &obj, const char *name) +MarkAtom(JSTracer *trc, JSAtom *atom, const char *name) { - JSRuntime *rt = trc->context->runtime; - if (rt->gcCurrentCompartment && rt->gcCurrentCompartment != obj.compartment()) - return; - - MarkObject(trc, obj, name); + MarkStringUnbarriered(trc, atom, name); } void -MarkObjectWithPrinter(JSTracer *trc, JSObject &obj, JSTraceNamePrinter printer, - const void *arg, size_t index) +MarkObjectUnbarriered(JSTracer *trc, JSObject *obj, const char *name) { JS_ASSERT(trc); - JS_ASSERT(&obj); + JS_ASSERT(obj); + JS_SET_TRACING_NAME(trc, name); + Mark(trc, obj); +} + +void +MarkObjectWithPrinterUnbarriered(JSTracer *trc, JSObject *obj, JSTraceNamePrinter printer, + const void *arg, size_t index) +{ + JS_ASSERT(trc); + JS_ASSERT(obj); JS_SET_TRACING_DETAILS(trc, printer, arg, index); - Mark(trc, &obj); + Mark(trc, obj); } void -MarkScript(JSTracer *trc, JSScript *script, const char *name) +MarkObject(JSTracer *trc, const MarkablePtr &obj, const char *name) +{ + MarkObjectUnbarriered(trc, obj.value, name); +} + +void +MarkScriptUnbarriered(JSTracer *trc, JSScript *script, const char *name) { JS_ASSERT(trc); JS_ASSERT(script); @@ -201,7 +210,13 @@ MarkScript(JSTracer *trc, JSScript *script, const char *name) } void -MarkShape(JSTracer *trc, const Shape *shape, const char *name) +MarkScript(JSTracer *trc, const MarkablePtr &script, const char *name) +{ + MarkScriptUnbarriered(trc, script.value, name); +} + +void +MarkShapeUnbarriered(JSTracer *trc, const Shape *shape, const char *name) { JS_ASSERT(trc); JS_ASSERT(shape); @@ -210,7 +225,13 @@ MarkShape(JSTracer *trc, const Shape *shape, const char *name) } void -MarkTypeObject(JSTracer *trc, types::TypeObject *type, const char *name) +MarkShape(JSTracer *trc, const MarkablePtr &shape, const char *name) +{ + MarkShapeUnbarriered(trc, shape.value, name); +} + +void +MarkTypeObjectUnbarriered(JSTracer *trc, types::TypeObject *type, const char *name) { JS_ASSERT(trc); JS_ASSERT(type); @@ -227,28 +248,40 @@ MarkTypeObject(JSTracer *trc, types::TypeObject *type, const char *name) */ if (IS_GC_MARKING_TRACER(trc)) { if (type->singleton) - MarkObject(trc, *type->singleton, "type_singleton"); + MarkObject(trc, type->singleton, "type_singleton"); if (type->interpretedFunction) - MarkObject(trc, *type->interpretedFunction, "type_function"); + MarkObject(trc, type->interpretedFunction, "type_function"); } } +void +MarkTypeObject(JSTracer *trc, const MarkablePtr &type, const char *name) +{ + MarkTypeObjectUnbarriered(trc, type.value, name); +} + #if JS_HAS_XML_SUPPORT void -MarkXML(JSTracer *trc, JSXML *xml, const char *name) +MarkXMLUnbarriered(JSTracer *trc, JSXML *xml, const char *name) { JS_ASSERT(trc); JS_ASSERT(xml); JS_SET_TRACING_NAME(trc, name); Mark(trc, xml); } + +void +MarkXML(JSTracer *trc, const MarkablePtr &xml, const char *name) +{ + MarkXMLUnbarriered(trc, xml.value, name); +} #endif void PushMarkStack(GCMarker *gcmarker, JSXML *thing) { - JS_OPT_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment); + JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + thing->compartment() == gcmarker->runtime->gcCurrentCompartment); if (thing->markIfUnmarked(gcmarker->getMarkColor())) gcmarker->pushXML(thing); @@ -257,8 +290,8 @@ PushMarkStack(GCMarker *gcmarker, JSXML *thing) void PushMarkStack(GCMarker *gcmarker, JSObject *thing) { - JS_OPT_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment); + JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + thing->compartment() == gcmarker->runtime->gcCurrentCompartment); if (thing->markIfUnmarked(gcmarker->getMarkColor())) gcmarker->pushObject(thing); @@ -267,8 +300,8 @@ PushMarkStack(GCMarker *gcmarker, JSObject *thing) void PushMarkStack(GCMarker *gcmarker, JSFunction *thing) { - JS_OPT_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment); + JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + thing->compartment() == gcmarker->runtime->gcCurrentCompartment); if (thing->markIfUnmarked(gcmarker->getMarkColor())) gcmarker->pushObject(thing); @@ -277,8 +310,8 @@ PushMarkStack(GCMarker *gcmarker, JSFunction *thing) void PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing) { - JS_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment); + JS_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + thing->compartment() == gcmarker->runtime->gcCurrentCompartment); if (thing->markIfUnmarked(gcmarker->getMarkColor())) gcmarker->pushType(thing); @@ -287,8 +320,8 @@ PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing) void PushMarkStack(GCMarker *gcmarker, JSScript *thing) { - JS_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment); + JS_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + thing->compartment() == gcmarker->runtime->gcCurrentCompartment); /* * We mark scripts directly rather than pushing on the stack as they can @@ -305,8 +338,8 @@ ScanShape(GCMarker *gcmarker, const Shape *shape); void PushMarkStack(GCMarker *gcmarker, const Shape *thing) { - JS_OPT_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment); + JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + thing->compartment() == gcmarker->runtime->gcCurrentCompartment); /* We mark shapes directly rather than pushing on the stack. */ if (thing->markIfUnmarked(gcmarker->getMarkColor())) @@ -325,7 +358,7 @@ MarkAtomRange(JSTracer *trc, size_t len, JSAtom **vec, const char *name) } void -MarkObjectRange(JSTracer *trc, size_t len, JSObject **vec, const char *name) +MarkObjectRange(JSTracer *trc, size_t len, HeapPtr *vec, const char *name) { for (uint32 i = 0; i < len; i++) { if (JSObject *obj = vec[i]) { @@ -336,7 +369,7 @@ MarkObjectRange(JSTracer *trc, size_t len, JSObject **vec, const char *name) } void -MarkXMLRange(JSTracer *trc, size_t len, JSXML **vec, const char *name) +MarkXMLRange(JSTracer *trc, size_t len, HeapPtr *vec, const char *name) { for (size_t i = 0; i < len; i++) { if (JSXML *xml = vec[i]) { @@ -347,7 +380,7 @@ MarkXMLRange(JSTracer *trc, size_t len, JSXML **vec, const char *name) } void -MarkId(JSTracer *trc, jsid id) +MarkIdUnbarriered(JSTracer *trc, jsid id) { if (JSID_IS_STRING(id)) Mark(trc, JSID_TO_STRING(id)); @@ -356,25 +389,41 @@ MarkId(JSTracer *trc, jsid id) } void -MarkId(JSTracer *trc, jsid id, const char *name) +MarkIdUnbarriered(JSTracer *trc, jsid id, const char *name) { JS_SET_TRACING_NAME(trc, name); - MarkId(trc, id); + MarkIdUnbarriered(trc, id); } void -MarkIdRange(JSTracer *trc, jsid *beg, jsid *end, const char *name) +MarkId(JSTracer *trc, const HeapId &id, const char *name) +{ + JS_SET_TRACING_NAME(trc, name); + MarkIdUnbarriered(trc, id.get(), name); +} + +void +MarkIdRangeUnbarriered(JSTracer *trc, jsid *beg, jsid *end, const char *name) { for (jsid *idp = beg; idp != end; ++idp) { JS_SET_TRACING_INDEX(trc, name, (idp - beg)); - MarkId(trc, *idp); + MarkIdUnbarriered(trc, *idp); } } void -MarkIdRange(JSTracer *trc, size_t len, jsid *vec, const char *name) +MarkIdRangeUnbarriered(JSTracer *trc, size_t len, jsid *vec, const char *name) { - MarkIdRange(trc, vec, vec + len, name); + MarkIdRangeUnbarriered(trc, vec, vec + len, name); +} + +void +MarkIdRange(JSTracer *trc, HeapId *beg, HeapId *end, const char *name) +{ + for (HeapId *idp = beg; idp != end; ++idp) { + JS_SET_TRACING_INDEX(trc, name, (idp - beg)); + MarkIdUnbarriered(trc, *idp); + } } void @@ -387,7 +436,7 @@ MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind) Mark(trc, reinterpret_cast(thing)); break; case JSTRACE_STRING: - MarkString(trc, reinterpret_cast(thing)); + Mark(trc, reinterpret_cast(thing)); break; case JSTRACE_SCRIPT: Mark(trc, static_cast(thing)); @@ -396,7 +445,7 @@ MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind) Mark(trc, reinterpret_cast(thing)); break; case JSTRACE_TYPE_OBJECT: - MarkTypeObject(trc, reinterpret_cast(thing), "type_stack"); + MarkTypeObjectUnbarriered(trc, reinterpret_cast(thing), "type_stack"); break; #if JS_HAS_XML_SUPPORT case JSTRACE_XML: @@ -417,18 +466,24 @@ MarkValueRaw(JSTracer *trc, const js::Value &v) } void -MarkValue(JSTracer *trc, const js::Value &v, const char *name) +MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name) { JS_SET_TRACING_NAME(trc, name); MarkValueRaw(trc, v); } void -MarkCrossCompartmentValue(JSTracer *trc, const js::Value &v, const char *name) +MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name) +{ + MarkValueUnbarriered(trc, v, name); +} + +void +MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name) { if (v.isMarkable()) { js::gc::Cell *cell = (js::gc::Cell *)v.toGCThing(); - JSRuntime *rt = trc->context->runtime; + JSRuntime *rt = trc->runtime; if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment) return; @@ -437,35 +492,20 @@ MarkCrossCompartmentValue(JSTracer *trc, const js::Value &v, const char *name) } void -MarkValueRange(JSTracer *trc, const Value *beg, const Value *end, const char *name) +MarkValueRange(JSTracer *trc, const HeapValue *beg, const HeapValue *end, const char *name) { - for (const Value *vp = beg; vp < end; ++vp) { + for (const HeapValue *vp = beg; vp < end; ++vp) { JS_SET_TRACING_INDEX(trc, name, vp - beg); - MarkValueRaw(trc, *vp); + MarkValueRaw(trc, vp->get()); } } void -MarkValueRange(JSTracer *trc, size_t len, const Value *vec, const char *name) +MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name) { MarkValueRange(trc, vec, vec + len, name); } -void -MarkShapeRange(JSTracer *trc, const Shape **beg, const Shape **end, const char *name) -{ - for (const Shape **sp = beg; sp < end; ++sp) { - JS_SET_TRACING_INDEX(trc, name, sp - beg); - MarkShape(trc, *sp, name); - } -} - -void -MarkShapeRange(JSTracer *trc, size_t len, const Shape **vec, const char *name) -{ - MarkShapeRange(trc, vec, vec + len, name); -} - /* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */ void MarkGCThing(JSTracer *trc, void *thing, JSGCTraceKind kind) @@ -484,13 +524,6 @@ MarkGCThing(JSTracer *trc, void *thing) MarkKind(trc, thing, GetGCThingTraceKind(thing)); } -void -MarkGCThing(JSTracer *trc, void *thing, const char *name) -{ - JS_SET_TRACING_NAME(trc, name); - MarkGCThing(trc, thing); -} - void MarkGCThing(JSTracer *trc, void *thing, const char *name, size_t index) { @@ -509,37 +542,104 @@ Mark(JSTracer *trc, void *thing, JSGCTraceKind kind, const char *name) void MarkRoot(JSTracer *trc, JSObject *thing, const char *name) { - MarkObject(trc, *thing, name); + MarkObjectUnbarriered(trc, thing, name); } void MarkRoot(JSTracer *trc, JSString *thing, const char *name) { - MarkString(trc, thing, name); + MarkStringUnbarriered(trc, thing, name); } void MarkRoot(JSTracer *trc, JSScript *thing, const char *name) { - MarkScript(trc, thing, name); + MarkScriptUnbarriered(trc, thing, name); } void MarkRoot(JSTracer *trc, const Shape *thing, const char *name) { - MarkShape(trc, thing, name); + MarkShapeUnbarriered(trc, thing, name); } void MarkRoot(JSTracer *trc, types::TypeObject *thing, const char *name) { - MarkTypeObject(trc, thing, name); + MarkTypeObjectUnbarriered(trc, thing, name); } void MarkRoot(JSTracer *trc, JSXML *thing, const char *name) { - MarkXML(trc, thing, name); + MarkXMLUnbarriered(trc, thing, name); +} + +void +MarkRoot(JSTracer *trc, const Value &v, const char *name) +{ + MarkValueUnbarriered(trc, v, name); +} + +void +MarkRoot(JSTracer *trc, jsid id, const char *name) +{ + JS_SET_TRACING_NAME(trc, name); + MarkIdUnbarriered(trc, id); +} + +void +MarkRootGCThing(JSTracer *trc, void *thing, const char *name) +{ + JS_SET_TRACING_NAME(trc, name); + MarkGCThing(trc, thing); +} + +void +MarkRootRange(JSTracer *trc, size_t len, const Shape **vec, const char *name) +{ + const Shape **end = vec + len; + for (const Shape **sp = vec; sp < end; ++sp) { + JS_SET_TRACING_INDEX(trc, name, sp - vec); + MarkShapeUnbarriered(trc, *sp, name); + } +} + +void +MarkRootRange(JSTracer *trc, size_t len, JSObject **vec, const char *name) +{ + JSObject **end = vec + len; + for (JSObject **sp = vec; sp < end; ++sp) { + JS_SET_TRACING_INDEX(trc, name, sp - vec); + MarkObjectUnbarriered(trc, *sp, name); + } +} + +void +MarkRootRange(JSTracer *trc, const Value *beg, const Value *end, const char *name) +{ + for (const Value *vp = beg; vp < end; ++vp) { + JS_SET_TRACING_INDEX(trc, name, vp - beg); + MarkValueRaw(trc, *vp); + } +} + +void +MarkRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name) +{ + MarkRootRange(trc, vec, vec + len, name); +} + +void +MarkRootRange(JSTracer *trc, jsid *beg, jsid *end, const char *name) +{ + MarkIdRangeUnbarriered(trc, beg, end, name); +} + +void +MarkRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name) +{ + MarkIdRangeUnbarriered(trc, len, vec, name); } static void @@ -592,7 +692,7 @@ static void ScanShape(GCMarker *gcmarker, const Shape *shape) { restart: - JSRuntime *rt = gcmarker->context->runtime; + JSRuntime *rt = gcmarker->runtime; if (rt->gcRegenShapes) shape->shapeid = js_RegenerateShapeForGC(rt); @@ -617,9 +717,9 @@ restart: static inline void ScanRope(GCMarker *gcmarker, JSRope *rope) { - JS_OPT_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - rope->compartment() == gcmarker->context->runtime->gcCurrentCompartment - || rope->compartment() == gcmarker->context->runtime->atomsCompartment); + JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + rope->compartment() == gcmarker->runtime->gcCurrentCompartment + || rope->compartment() == gcmarker->runtime->atomsCompartment); JS_ASSERT(rope->isMarked()); JSString *leftChild = NULL; @@ -645,9 +745,9 @@ ScanRope(GCMarker *gcmarker, JSRope *rope) static inline void PushMarkStack(GCMarker *gcmarker, JSString *str) { - JS_OPT_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment, - str->compartment() == gcmarker->context->runtime->gcCurrentCompartment - || str->compartment() == gcmarker->context->runtime->atomsCompartment); + JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment, + str->compartment() == gcmarker->runtime->gcCurrentCompartment + || str->compartment() == gcmarker->runtime->atomsCompartment); if (str->isLinear()) { str->asLinear().mark(gcmarker); @@ -700,11 +800,11 @@ ScanObject(GCMarker *gcmarker, JSObject *obj) js::Shape *shape = obj->lastProp; PushMarkStack(gcmarker, shape); - if (gcmarker->context->runtime->gcRegenShapes) { + if (gcmarker->runtime->gcRegenShapes) { /* We need to regenerate our shape if hasOwnShape(). */ uint32 newShape = shape->shapeid; if (obj->hasOwnShape()) { - newShape = js_RegenerateShapeForGC(gcmarker->context->runtime); + newShape = js_RegenerateShapeForGC(gcmarker->runtime); JS_ASSERT(newShape != shape->shapeid); } obj->objShape = newShape; @@ -761,8 +861,8 @@ MarkChildren(JSTracer *trc, JSObject *obj) /* Trace universal (ops-independent) members. */ if (!obj->isDenseArray() && obj->newType) MarkTypeObject(trc, obj->newType, "new_type"); - if (JSObject *parent = obj->getParent()) - MarkObject(trc, *parent, "parent"); + if (obj->parent) + MarkObject(trc, obj->parent, "parent"); Class *clasp = obj->getClass(); if (clasp->trace) @@ -783,12 +883,16 @@ MarkChildren(JSTracer *trc, JSObject *obj) void MarkChildren(JSTracer *trc, JSString *str) { + /* + * We use custom barriers in JSString, so it's safe to use unbarriered + * marking here. + */ if (str->isDependent()) { - MarkString(trc, str->asDependent().base(), "base"); + MarkStringUnbarriered(trc, str->asDependent().base(), "base"); } else if (str->isRope()) { JSRope &rope = str->asRope(); - MarkString(trc, rope.leftChild(), "left child"); - MarkString(trc, rope.rightChild(), "right child"); + MarkStringUnbarriered(trc, rope.leftChild(), "left child"); + MarkStringUnbarriered(trc, rope.rightChild(), "right child"); } } @@ -799,10 +903,10 @@ MarkChildren(JSTracer *trc, JSScript *script) CheckScript(script, NULL); #ifdef JS_CRASH_DIAGNOSTICS - JSRuntime *rt = trc->context->runtime; + JSRuntime *rt = trc->runtime; JS_OPT_ASSERT_IF(rt->gcCheckCompartment, script->compartment() == rt->gcCheckCompartment); #endif - + MarkAtomRange(trc, script->natoms, script->atoms, "atoms"); if (JSScript::isValidOffset(script->objectsOffset)) { @@ -820,8 +924,8 @@ MarkChildren(JSTracer *trc, JSScript *script) MarkValueRange(trc, constarray->length, constarray->vector, "consts"); } - if (!script->isCachedEval && script->u.globalObject) - MarkObject(trc, *script->u.globalObject, "object"); + if (!script->isCachedEval && script->globalObject) + MarkObject(trc, script->globalObject, "object"); if (IS_GC_MARKING_TRACER(trc) && script->filename) js_MarkScriptFilename(script->filename); @@ -839,12 +943,15 @@ restart: MarkId(trc, shape->propid, "propid"); if (shape->hasGetterValue() && shape->getter()) - MarkObjectWithPrinter(trc, *shape->getterObject(), PrintPropertyGetterOrSetter, shape, 0); + MarkObjectWithPrinterUnbarriered(trc, shape->getterObject(), + PrintPropertyGetterOrSetter, shape, 0); if (shape->hasSetterValue() && shape->setter()) - MarkObjectWithPrinter(trc, *shape->setterObject(), PrintPropertyGetterOrSetter, shape, 1); + MarkObjectWithPrinterUnbarriered(trc, shape->setterObject(), + PrintPropertyGetterOrSetter, shape, 1); if (shape->isMethod()) - MarkObjectWithPrinter(trc, shape->methodObject(), PrintPropertyMethod, shape, 0); + MarkObjectWithPrinterUnbarriered(trc, &shape->methodObject(), + PrintPropertyMethod, shape, 0); shape = shape->previous(); if (shape) @@ -864,8 +971,7 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type) } if (type->emptyShapes) { - int count = FINALIZE_OBJECT_LAST - FINALIZE_OBJECT0 + 1; - for (int i = 0; i < count; i++) { + for (unsigned i = 0; i < FINALIZE_OBJECT_LIMIT; i++) { if (type->emptyShapes[i]) PushMarkStack(gcmarker, type->emptyShapes[i]); } @@ -901,26 +1007,25 @@ MarkChildren(JSTracer *trc, types::TypeObject *type) } if (type->emptyShapes) { - int count = FINALIZE_OBJECT_LAST - FINALIZE_OBJECT0 + 1; - for (int i = 0; i < count; i++) { + for (unsigned i = 0; i < FINALIZE_OBJECT_LIMIT; i++) { if (type->emptyShapes[i]) MarkShape(trc, type->emptyShapes[i], "empty_shape"); } } if (type->proto) - MarkObject(trc, *type->proto, "type_proto"); + MarkObject(trc, type->proto, "type_proto"); if (type->singleton) - MarkObject(trc, *type->singleton, "type_singleton"); + MarkObject(trc, type->singleton, "type_singleton"); if (type->newScript) { - MarkObject(trc, *type->newScript->fun, "type_new_function"); + MarkObject(trc, type->newScript->fun, "type_new_function"); MarkShape(trc, type->newScript->shape, "type_new_shape"); } if (type->interpretedFunction) - MarkObject(trc, *type->interpretedFunction, "type_function"); + MarkObject(trc, type->interpretedFunction, "type_function"); } #ifdef JS_HAS_XML_SUPPORT @@ -936,7 +1041,7 @@ MarkChildren(JSTracer *trc, JSXML *xml) void GCMarker::drainMarkStack() { - JSRuntime *rt = context->runtime; + JSRuntime *rt = runtime; rt->gcCheckCompartment = rt->gcCurrentCompartment; while (!isMarkStackEmpty()) { @@ -970,10 +1075,8 @@ GCMarker::drainMarkStack() rt->gcCheckCompartment = NULL; } -} /* namespace js */ - -JS_PUBLIC_API(void) -JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind) +void +TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind) { switch (kind) { case JSTRACE_OBJECT: @@ -1004,6 +1107,15 @@ JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind) } } +void +CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind) +{ + JS_ASSERT(thing); + MarkKind(trc, thing, kind); +} + +} /* namespace js */ + inline void JSObject::scanSlots(GCMarker *gcmarker) { @@ -1016,7 +1128,7 @@ JSObject::scanSlots(GCMarker *gcmarker) if (slots) { unsigned nfixed = numFixedSlots(); if (nslots > nfixed) { - Value *vp = fixedSlots(); + HeapValue *vp = fixedSlots(); for (i = 0; i < nfixed; i++, vp++) ScanValue(gcmarker, *vp); vp = slots; @@ -1026,7 +1138,7 @@ JSObject::scanSlots(GCMarker *gcmarker) } } JS_ASSERT(nslots <= numFixedSlots()); - Value *vp = fixedSlots(); + HeapValue *vp = fixedSlots(); for (i = 0; i < nslots; i++, vp++) ScanValue(gcmarker, *vp); } diff --git a/js/src/jsgcmark.h b/js/src/jsgcmark.h index 34cf0719392d..b9205416dae8 100644 --- a/js/src/jsgcmark.h +++ b/js/src/jsgcmark.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -45,105 +45,93 @@ #include "jscompartment.h" #include "jslock.h" - +#include "gc/Barrier.h" #include "js/TemplateLib.h" namespace js { namespace gc { void -MarkString(JSTracer *trc, JSString *str); +MarkAtom(JSTracer *trc, JSAtom *str); void -MarkString(JSTracer *trc, JSString *str, const char *name); +MarkAtom(JSTracer *trc, JSAtom *str, const char *name); void -MarkObject(JSTracer *trc, JSObject &obj, const char *name); - -/* - * Mark an object that may be in a different compartment from the compartment - * being GC'd. (Although it won't be marked if it's in the wrong compartment.) - */ -void -MarkCrossCompartmentObject(JSTracer *trc, JSObject &obj, const char *name); +MarkObjectUnbarriered(JSTracer *trc, JSObject *obj, const char *name); void -MarkObjectWithPrinter(JSTracer *trc, JSObject &obj, JSTraceNamePrinter printer, - const void *arg, size_t index); +MarkObject(JSTracer *trc, const MarkablePtr &obj, const char *name); void -MarkScript(JSTracer *trc, JSScript *script, const char *name); +MarkStringUnbarriered(JSTracer *trc, JSString *str, const char *name); void -MarkShape(JSTracer *trc, const Shape *shape, const char *name); +MarkString(JSTracer *trc, const MarkablePtr &str, const char *name); void -MarkTypeObject(JSTracer *trc, types::TypeObject *type, const char *name); +MarkScriptUnbarriered(JSTracer *trc, JSScript *script, const char *name); void -MarkXML(JSTracer *trc, JSXML *xml, const char *name); +MarkScript(JSTracer *trc, const MarkablePtr &script, const char *name); void -MarkObjectRange(JSTracer *trc, size_t len, JSObject **vec, const char *name); +MarkShapeUnbarriered(JSTracer *trc, const Shape *shape, const char *name); void -MarkXMLRange(JSTracer *trc, size_t len, JSXML **vec, const char *name); +MarkShape(JSTracer *trc, const MarkablePtr &shape, const char *name); void -MarkId(JSTracer *trc, jsid id); +MarkTypeObjectUnbarriered(JSTracer *trc, types::TypeObject *type, const char *name); void -MarkId(JSTracer *trc, jsid id, const char *name); +MarkTypeObject(JSTracer *trc, const MarkablePtr &type, const char *name); void -MarkIdRange(JSTracer *trc, jsid *beg, jsid *end, const char *name); +MarkXMLUnbarriered(JSTracer *trc, JSXML *xml, const char *name); void -MarkIdRange(JSTracer *trc, size_t len, jsid *vec, const char *name); +MarkXML(JSTracer *trc, const MarkablePtr &xml, const char *name); + +void +MarkObjectRange(JSTracer *trc, size_t len, HeapPtr *vec, const char *name); + +void +MarkXMLRange(JSTracer *trc, size_t len, HeapPtr *vec, const char *name); + +void +MarkId(JSTracer *trc, const HeapId &id, const char *name); + +void +MarkIdRange(JSTracer *trc, js::HeapId *beg, js::HeapId *end, const char *name); + +void +MarkIdRangeUnbarriered(JSTracer *trc, size_t len, jsid *vec, const char *name); + +void +MarkIdRangeUnbarriered(JSTracer *trc, jsid *beg, jsid *end, const char *name); void MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind); void -MarkValueRaw(JSTracer *trc, const js::Value &v); +MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name); void -MarkValue(JSTracer *trc, const js::Value &v, const char *name); +MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name); /* * Mark a value that may be in a different compartment from the compartment * being GC'd. (Although it won't be marked if it's in the wrong compartment.) */ void -MarkCrossCompartmentValue(JSTracer *trc, const js::Value &v, const char *name); +MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name); void -MarkValueRange(JSTracer *trc, const Value *beg, const Value *end, const char *name); +MarkValueRange(JSTracer *trc, const HeapValue *beg, const HeapValue *end, const char *name); void -MarkValueRange(JSTracer *trc, size_t len, const Value *vec, const char *name); - -void -MarkShapeRange(JSTracer *trc, const Shape **beg, const Shape **end, const char *name); - -void -MarkShapeRange(JSTracer *trc, size_t len, const Shape **vec, const char *name); - -/* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */ -void -MarkGCThing(JSTracer *trc, void *thing, uint32 kind); - -void -MarkGCThing(JSTracer *trc, void *thing); - -void -MarkGCThing(JSTracer *trc, void *thing, const char *name); - -void -MarkGCThing(JSTracer *trc, void *thing, const char *name, size_t index); - -void -Mark(JSTracer *trc, void *thing, uint32 kind, const char *name); +MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name); void MarkRoot(JSTracer *trc, JSObject *thing, const char *name); @@ -163,6 +151,33 @@ MarkRoot(JSTracer *trc, types::TypeObject *thing, const char *name); void MarkRoot(JSTracer *trc, JSXML *thing, const char *name); +void +MarkRoot(JSTracer *trc, const Value &v, const char *name); + +void +MarkRoot(JSTracer *trc, jsid id, const char *name); + +void +MarkRootGCThing(JSTracer *trc, void *thing, const char *name); + +void +MarkRootRange(JSTracer *trc, size_t len, const Shape **vec, const char *name); + +void +MarkRootRange(JSTracer *trc, size_t len, JSObject **vec, const char *name); + +void +MarkRootRange(JSTracer *trc, const Value *beg, const Value *end, const char *name); + +void +MarkRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name); + +void +MarkRootRange(JSTracer *trc, jsid *beg, jsid *end, const char *name); + +void +MarkRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name); + void MarkChildren(JSTracer *trc, JSObject *obj); @@ -184,22 +199,22 @@ MarkChildren(JSTracer *trc, JSXML *xml); * the corresponding Mark/IsMarked function. */ inline void -Mark(JSTracer *trc, const js::Value &v, const char *name) +Mark(JSTracer *trc, const js::HeapValue &v, const char *name) { MarkValue(trc, v, name); } inline void -Mark(JSTracer *trc, JSObject *o, const char *name) +Mark(JSTracer *trc, const MarkablePtr &o, const char *name) { - MarkObject(trc, *o, name); + MarkObject(trc, o, name); } inline bool IsMarked(JSContext *cx, const js::Value &v) { if (v.isMarkable()) - return !IsAboutToBeFinalized(cx, v.toGCThing()); + return !IsAboutToBeFinalized(cx, v); return true; } @@ -215,7 +230,14 @@ IsMarked(JSContext *cx, Cell *cell) return !IsAboutToBeFinalized(cx, cell); } -} -} +} /* namespace gc */ + +void +TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind); + +void +CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind); + +} /* namespace js */ #endif diff --git a/js/src/jsgcstats.cpp b/js/src/jsgcstats.cpp index 9c0b1bb44b9f..0d7ebb6f8444 100644 --- a/js/src/jsgcstats.cpp +++ b/js/src/jsgcstats.cpp @@ -47,6 +47,7 @@ #include "jscompartment.h" #include "jsgcinlines.h" +#include "jsobjinlines.h" using namespace mozilla; using namespace js; diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 71430d32d6f6..4a0ba8ff0699 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -474,6 +474,33 @@ TypeSet::print(JSContext *cx) } } +bool +TypeSet::propertyNeedsBarrier(JSContext *cx, jsid id) +{ + id = MakeTypeId(cx, id); + + if (unknownObject()) + return true; + + for (unsigned i = 0; i < getObjectCount(); i++) { + if (getSingleObject(i)) + return true; + + if (types::TypeObject *otype = getTypeObject(i)) { + if (otype->unknownProperties()) + return true; + + if (types::TypeSet *propTypes = otype->maybeGetProperty(cx, id)) { + if (propTypes->needsBarrier(cx)) + return true; + } + } + } + + addFreeze(cx); + return false; +} + ///////////////////////////////////////////////////////////////////// // TypeSet constraints ///////////////////////////////////////////////////////////////////// @@ -1919,6 +1946,17 @@ TypeSet::hasGlobalObject(JSContext *cx, JSObject *global) return true; } +bool +TypeSet::needsBarrier(JSContext *cx) +{ + bool result = unknownObject() + || getObjectCount() > 0 + || hasAnyFlag(TYPE_FLAG_STRING); + if (!result) + addFreeze(cx); + return result; +} + ///////////////////////////////////////////////////////////////////// // TypeCompartment ///////////////////////////////////////////////////////////////////// @@ -2546,7 +2584,7 @@ struct types::ObjectTableKey typedef JSObject * Lookup; static inline uint32 hash(JSObject *obj) { - return (uint32) (JSID_BITS(obj->lastProperty()->propid) ^ + return (uint32) (JSID_BITS(obj->lastProperty()->propid.get()) ^ obj->slotSpan() ^ obj->numFixedSlots() ^ ((uint32)(size_t)obj->getProto() >> 2)); } @@ -3084,8 +3122,10 @@ TypeObject::clearNewScript(JSContext *cx) } } - cx->free_(newScript); + /* We NULL out newScript *before* freeing it so the write barrier works. */ + TypeNewScript *savedNewScript = newScript; newScript = NULL; + cx->free_(savedNewScript); markStateChange(cx); } @@ -4740,7 +4780,7 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun) type->newScript->shape = baseobj->lastProperty(); type->newScript->initializerList = (TypeNewScript::Initializer *) - ((char *) type->newScript + sizeof(TypeNewScript)); + ((char *) type->newScript.get() + sizeof(TypeNewScript)); PodCopy(type->newScript->initializerList, initializerList.begin(), initializerList.length()); } @@ -5201,8 +5241,8 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope) if (!SetScope(cx, parent, scope->getParent())) return false; parent->nesting()->activeCall = scope; - parent->nesting()->argArray = call.argArray(); - parent->nesting()->varArray = call.varArray(); + parent->nesting()->argArray = Valueify(call.argArray()); + parent->nesting()->varArray = Valueify(call.varArray()); } JS_ASSERT(!script->types->nesting); @@ -5719,7 +5759,7 @@ JSObject::makeNewType(JSContext *cx, JSFunction *fun, bool unknown) if (!type) return; - newType = type; + newType.init(type); setDelegate(); if (!cx->typeInferenceEnabled()) @@ -6264,7 +6304,7 @@ JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats, J if (object->emptyShapes) { size_t usable = usf(object->emptyShapes); stats->emptyShapes += - usable ? usable : sizeof(EmptyShape*) * gc::FINALIZE_FUNCTION_AND_OBJECT_LAST; + usable ? usable : sizeof(EmptyShape*) * gc::FINALIZE_OBJECT_LIMIT; } /* diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 0f60a6a5a1ce..b760af2b8675 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -48,6 +48,7 @@ #include "jsprvtd.h" #include "ds/LifoAlloc.h" +#include "gc/Barrier.h" #include "js/HashTable.h" namespace js { @@ -508,6 +509,15 @@ class TypeSet inline void clearObjects(); + /* + * Whether a location with this TypeSet needs a write barrier (i.e., whether + * it can hold GC things). The type set is frozen if no barrier is needed. + */ + bool needsBarrier(JSContext *cx); + + /* The type set is frozen if no barrier is needed. */ + bool propertyNeedsBarrier(JSContext *cx, jsid id); + private: uint32 baseObjectCount() const { return (flags & TYPE_FLAG_OBJECT_COUNT_MASK) >> TYPE_FLAG_OBJECT_COUNT_SHIFT; @@ -621,18 +631,13 @@ struct TypeBarrier struct Property { /* Identifier for this property, JSID_VOID for the aggregate integer index property. */ - jsid id; + HeapId id; /* Possible types for this property, including types inherited from prototypes. */ TypeSet types; - Property(jsid id) - : id(id) - {} - - Property(const Property &o) - : id(o.id), types(o.types) - {} + inline Property(jsid id); + inline Property(const Property &o); static uint32 keyBits(jsid id) { return (uint32) JSID_BITS(id); } static jsid getKey(Property *p) { return p->id; } @@ -650,7 +655,7 @@ struct Property */ struct TypeNewScript { - JSFunction *fun; + HeapPtrFunction fun; /* Allocation kind to use for newly constructed objects. */ gc::AllocKind allocKind; @@ -659,7 +664,7 @@ struct TypeNewScript * Shape to use for newly constructed objects. Reflects all definite * properties the object will have. */ - const Shape *shape; + HeapPtr shape; /* * Order in which properties become initialized. We need this in case a @@ -682,6 +687,9 @@ struct TypeNewScript {} }; Initializer *initializerList; + + static inline void writeBarrierPre(TypeNewScript *newScript); + static inline void writeBarrierPost(TypeNewScript *newScript, void *addr); }; /* @@ -714,17 +722,17 @@ struct TypeNewScript struct TypeObject : gc::Cell { /* Prototype shared by objects using this type. */ - JSObject *proto; + HeapPtrObject proto; /* * Whether there is a singleton JS object with this type. That JS object * must appear in type sets instead of this; we include the back reference * here to allow reverting the JS object to a lazy type. */ - JSObject *singleton; + HeapPtrObject singleton; /* Lazily filled array of empty shapes for each size of objects with this type. */ - js::EmptyShape **emptyShapes; + HeapPtr *emptyShapes; /* Flags for this object. */ TypeObjectFlags flags; @@ -734,7 +742,7 @@ struct TypeObject : gc::Cell * 'new' on the specified script, which adds some number of properties to * the object in a definite order before the object escapes. */ - TypeNewScript *newScript; + HeapPtr newScript; /* * Estimate of the contribution of this object to the type sets it appears in. @@ -783,7 +791,7 @@ struct TypeObject : gc::Cell Property **propertySet; /* If this is an interpreted function, the function object. */ - JSFunction *interpretedFunction; + HeapPtrFunction interpretedFunction; inline TypeObject(JSObject *proto, bool isFunction, bool unknown); @@ -868,6 +876,9 @@ struct TypeObject : gc::Cell */ void finalize(JSContext *cx) {} + static inline void writeBarrierPre(TypeObject *type); + static inline void writeBarrierPost(TypeObject *type, void *addr); + private: inline uint32 basePropertyCount() const; inline void setBasePropertyCount(uint32 count); @@ -984,8 +995,8 @@ struct TypeScriptNesting * these fields can be embedded directly in JIT code (though remember to * use 'addDependency == true' when calling resolveNameAccess). */ - Value *argArray; - Value *varArray; + const Value *argArray; + const Value *varArray; /* Number of frames for this function on the stack. */ uint32 activeFrames; @@ -1010,7 +1021,7 @@ class TypeScript analyze::ScriptAnalysis *analysis; /* Function for the script, if it has one. */ - JSFunction *function; + HeapPtrFunction function; /* * Information about the scope in which a script executes. This information @@ -1020,7 +1031,7 @@ class TypeScript static const size_t GLOBAL_MISSING_SCOPE = 0x1; /* Global object for the script, if compileAndGo. */ - js::GlobalObject *global; + HeapPtr global; public: @@ -1030,12 +1041,10 @@ class TypeScript /* Dynamic types generated at points within this script. */ TypeResult *dynamicList; - TypeScript(JSFunction *fun) { - this->function = fun; - this->global = (js::GlobalObject *) GLOBAL_MISSING_SCOPE; - } + inline TypeScript(JSFunction *fun); + inline ~TypeScript(); - bool hasScope() { return size_t(global) != GLOBAL_MISSING_SCOPE; } + bool hasScope() { return size_t(global.get()) != GLOBAL_MISSING_SCOPE; } /* Array of type type sets for variables and JOF_TYPESET ops. */ TypeSet *typeArray() { return (TypeSet *) (jsuword(this) + sizeof(TypeScript)); } diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h index ea93a3ece8fd..dbec2891ab1f 100644 --- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -71,7 +71,7 @@ Type::ObjectType(JSObject *obj) Type::ObjectType(TypeObject *obj) { if (obj->singleton) - return Type((jsuword) obj->singleton | 1); + return Type((jsuword) obj->singleton.get() | 1); return Type((jsuword) obj); } @@ -459,6 +459,18 @@ UseNewTypeAtEntry(JSContext *cx, StackFrame *fp) // Script interface functions ///////////////////////////////////////////////////////////////////// +inline +TypeScript::TypeScript(JSFunction *fun) + : function(fun), + global((js::GlobalObject *) GLOBAL_MISSING_SCOPE) +{ +} + +inline +TypeScript::~TypeScript() +{ +} + /* static */ inline unsigned TypeScript::NumTypeSets(JSScript *script) { @@ -689,9 +701,9 @@ void TypeScript::trace(JSTracer *trc) { if (function) - gc::MarkObject(trc, *function, "script_fun"); + gc::MarkObject(trc, function, "script_fun"); if (hasScope() && global) - gc::MarkObject(trc, *global, "script_global"); + gc::MarkObject(trc, global, "script_global"); /* Note: nesting does not keep anything alive. */ } @@ -1252,6 +1264,56 @@ TypeObject::getGlobal() return NULL; } +inline void +TypeObject::writeBarrierPre(TypeObject *type) +{ +#ifdef JSGC_INCREMENTAL + if (!type || type == &js::types::emptyTypeObject) + return; + + JSCompartment *comp = type->compartment(); + if (comp->needsBarrier()) + MarkTypeObjectUnbarriered(comp->barrierTracer(), type, "write barrier"); +#endif +} + +inline void +TypeObject::writeBarrierPost(TypeObject *type, void *addr) +{ +} + +inline void +TypeNewScript::writeBarrierPre(TypeNewScript *newScript) +{ +#ifdef JSGC_INCREMENTAL + if (!newScript) + return; + + JSCompartment *comp = newScript->fun->compartment(); + if (comp->needsBarrier()) { + MarkObjectUnbarriered(comp->barrierTracer(), newScript->fun, "write barrier"); + MarkShapeUnbarriered(comp->barrierTracer(), newScript->shape, "write barrier"); + } +#endif +} + +inline void +TypeNewScript::writeBarrierPost(TypeNewScript *newScript, void *addr) +{ +} + +inline +Property::Property(jsid id) + : id(id) +{ +} + +inline +Property::Property(const Property &o) + : id(o.id.get()), types(o.types) +{ +} + } } /* namespace js::types */ inline bool diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 71c154694a7e..9223ca1a29a5 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -452,8 +452,8 @@ const uint32 JSSLOT_SAVED_ID = 1; static void no_such_method_trace(JSTracer *trc, JSObject *obj) { - gc::MarkValue(trc, obj->getSlot(JSSLOT_FOUND_FUNCTION), "found function"); - gc::MarkValue(trc, obj->getSlot(JSSLOT_SAVED_ID), "saved id"); + gc::MarkValue(trc, obj->getSlotRef(JSSLOT_FOUND_FUNCTION), "found function"); + gc::MarkValue(trc, obj->getSlotRef(JSSLOT_SAVED_ID), "saved id"); } Class js_NoSuchMethodClass = { diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 9f870259f002..0d90780c17ed 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -124,7 +124,7 @@ NativeIterator::mark(JSTracer *trc) { MarkIdRange(trc, begin(), end(), "props"); if (obj) - MarkObject(trc, *obj, "obj"); + MarkObject(trc, obj, "obj"); } static void @@ -134,8 +134,8 @@ iterator_finalize(JSContext *cx, JSObject *obj) NativeIterator *ni = obj->getNativeIterator(); if (ni) { + obj->setPrivate(NULL); cx->free_(ni); - obj->setNativeIterator(NULL); } } @@ -337,7 +337,9 @@ js::VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap) return false; ida->length = static_cast(len); - memcpy(ida->vector, props.begin(), idsz); + jsid *v = props.begin(); + for (jsint i = 0; i < ida->length; i++) + ida->vector[i].init(v[i]); *idap = ida; return true; } @@ -441,17 +443,19 @@ NativeIterator::allocateIterator(JSContext *cx, uint32 slength, const AutoIdVect cx->malloc_(sizeof(NativeIterator) + plength * sizeof(jsid) + slength * sizeof(uint32)); if (!ni) return NULL; - ni->props_array = ni->props_cursor = (jsid *) (ni + 1); - ni->props_end = (jsid *)ni->props_array + plength; - if (plength) - memcpy(ni->props_array, props.begin(), plength * sizeof(jsid)); + ni->props_array = ni->props_cursor = (HeapId *) (ni + 1); + ni->props_end = ni->props_array + plength; + if (plength) { + for (size_t i = 0; i < plength; i++) + ni->props_array[i].init(props[i]); + } return ni; } inline void NativeIterator::init(JSObject *obj, uintN flags, uint32 slength, uint32 key) { - this->obj = obj; + this->obj.init(obj); this->flags = flags; this->shapes_array = (uint32 *) this->props_end; this->shapes_length = slength; @@ -853,9 +857,9 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat /* This only works for identified surpressed keys, not values. */ if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) { /* Check whether id is still to come. */ - jsid *props_cursor = ni->current(); - jsid *props_end = ni->end(); - for (jsid *idp = props_cursor; idp < props_end; ++idp) { + HeapId *props_cursor = ni->current(); + HeapId *props_end = ni->end(); + for (HeapId *idp = props_cursor; idp < props_end; ++idp) { if (predicate(*idp)) { /* * Check whether another property along the prototype chain @@ -894,7 +898,8 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat if (idp == props_cursor) { ni->incCursor(); } else { - memmove(idp, idp + 1, (props_end - (idp + 1)) * sizeof(jsid)); + for (HeapId *p = idp; p + 1 != props_end; p++) + *p = *(p + 1); ni->props_end = ni->end() - 1; } @@ -1109,6 +1114,37 @@ generator_finalize(JSContext *cx, JSObject *obj) cx->free_(gen); } +static void +MarkGenerator(JSTracer *trc, JSGenerator *gen) +{ + StackFrame *fp = gen->floatingFrame(); + + /* + * MarkGenerator should only be called when regs is based on the floating frame. + * See calls to RebaseRegsFromTo. + */ + JS_ASSERT(size_t(gen->regs.sp - fp->slots()) <= fp->numSlots()); + + /* + * Currently, generators are not mjitted. Still, (overflow) args can be + * pushed by the mjit and need to be conservatively marked. Technically, the + * formal args and generator slots are safe for exact marking, but since the + * plan is to eventually mjit generators, it makes sense to future-proof + * this code and save someone an hour later. + */ + MarkStackRangeConservatively(trc, gen->floatingStack, fp->formalArgsEnd()); + js_TraceStackFrame(trc, fp); + MarkStackRangeConservatively(trc, fp->slots(), gen->regs.sp); +} + +static void +GeneratorWriteBarrierPre(JSContext *cx, JSGenerator *gen) +{ + JSCompartment *comp = cx->compartment; + if (comp->needsBarrier()) + MarkGenerator(comp->barrierTracer(), gen); +} + static void generator_trace(JSTracer *trc, JSObject *obj) { @@ -1123,19 +1159,8 @@ generator_trace(JSTracer *trc, JSObject *obj) if (gen->state == JSGEN_RUNNING || gen->state == JSGEN_CLOSING) return; - StackFrame *fp = gen->floatingFrame(); - JS_ASSERT(gen->liveFrame() == fp); - - /* - * Currently, generators are not mjitted. Still, (overflow) args can be - * pushed by the mjit and need to be conservatively marked. Technically, the - * formal args and generator slots are safe for exact marking, but since the - * plan is to eventually mjit generators, it makes sense to future-proof - * this code and save someone an hour later. - */ - MarkStackRangeConservatively(trc, gen->floatingStack, fp->formalArgsEnd()); - js_TraceStackFrame(trc, fp); - MarkStackRangeConservatively(trc, fp->slots(), gen->regs.sp); + JS_ASSERT(gen->liveFrame() == gen->floatingFrame()); + MarkGenerator(trc, gen); } Class js::GeneratorClass = { @@ -1209,7 +1234,7 @@ js_NewGenerator(JSContext *cx) StackFrame *genfp = reinterpret_cast(genvp + vplen); /* Initialize JSGenerator. */ - gen->obj = obj; + gen->obj.init(obj); gen->state = JSGEN_NEWBORN; gen->enumerators = NULL; gen->floating = genfp; @@ -1258,6 +1283,19 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj, if (!cx->ensureGeneratorStackSpace()) return JS_FALSE; + /* + * Write barrier is needed since the generator stack can be updated, + * and it's not barriered in any other way. We need to do it before + * gen->state changes, which can cause us to trace the generator + * differently. + * + * We could optimize this by setting a bit on the generator to signify + * that it has been marked. If this bit has already been set, there is no + * need to mark again. The bit would have to be reset before the next GC, + * or else some kind of epoch scheme would have to be used. + */ + GeneratorWriteBarrierPre(cx, gen); + JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN); switch (op) { case JSGENOP_NEXT: diff --git a/js/src/jsiter.h b/js/src/jsiter.h index b7396c615f18..5cf2bcdccc72 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -48,6 +48,7 @@ #include "jspubtd.h" #include "jsversion.h" +#include "gc/Barrier.h" #include "vm/Stack.h" /* @@ -60,10 +61,10 @@ namespace js { struct NativeIterator { - JSObject *obj; - jsid *props_array; - jsid *props_cursor; - jsid *props_end; + HeapPtrObject obj; + HeapId *props_array; + HeapId *props_cursor; + HeapId *props_end; uint32 *shapes_array; uint32 shapes_length; uint32 shapes_key; @@ -72,11 +73,11 @@ struct NativeIterator { bool isKeyIter() const { return (flags & JSITER_FOREACH) == 0; } - inline jsid *begin() const { + inline HeapId *begin() const { return props_array; } - inline jsid *end() const { + inline HeapId *end() const { return props_end; } @@ -84,7 +85,7 @@ struct NativeIterator { return end() - begin(); } - jsid *current() const { + HeapId *current() const { JS_ASSERT(props_cursor < props_end); return props_cursor; } @@ -170,7 +171,7 @@ typedef enum JSGeneratorState { } JSGeneratorState; struct JSGenerator { - JSObject *obj; + js::HeapPtrObject obj; JSGeneratorState state; js::FrameRegs regs; JSObject *enumerators; diff --git a/js/src/jslock.cpp b/js/src/jslock.cpp index 013bb3f4a39f..44ff1da73f55 100644 --- a/js/src/jslock.cpp +++ b/js/src/jslock.cpp @@ -61,6 +61,8 @@ #include "jsscope.h" #include "jsstr.h" +#include "jsscopeinlines.h" + using namespace js; #define ReadWord(W) (W) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 8b240da5a9b9..1b5ad439aa3c 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -463,7 +463,7 @@ js_LeaveSharpObject(JSContext *cx, JSIdArray **idap) static intN gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg) { - MarkObject((JSTracer *)arg, *(JSObject *)he->key, "sharp table entry"); + MarkRoot((JSTracer *)arg, (JSObject *)he->key, "sharp table entry"); return JS_DHASH_NEXT; } @@ -1061,8 +1061,8 @@ EvalCacheLookup(JSContext *cx, JSLinearString *str, StackFrame *caller, uintN st if (i < 0 || objarray->vector[i]->getParent() == &scopeobj) { JS_ASSERT(staticLevel == script->staticLevel); - *scriptp = script->u.evalHashLink; - script->u.evalHashLink = NULL; + *scriptp = script->evalHashLink(); + script->evalHashLink() = NULL; return script; } } @@ -1071,7 +1071,7 @@ EvalCacheLookup(JSContext *cx, JSLinearString *str, StackFrame *caller, uintN st if (++count == EVAL_CACHE_CHAIN_LIMIT) return NULL; - scriptp = &script->u.evalHashLink; + scriptp = &script->evalHashLink(); } return NULL; } @@ -1085,7 +1085,7 @@ EvalCacheLookup(JSContext *cx, JSLinearString *str, StackFrame *caller, uintN st * a jsdbgapi user's perspective, we want each eval() to create and destroy a * script. This hides implementation details and means we don't have to deal * with calls to JS_GetScriptObject for scripts in the eval cache (currently, - * script->u.object aliases script->u.evalHashLink). + * script->object aliases script->evalHashLink()). */ class EvalScriptGuard { @@ -1107,7 +1107,7 @@ class EvalScriptGuard js_CallDestroyScriptHook(cx_, script_); script_->isActiveEval = false; script_->isCachedEval = true; - script_->u.evalHashLink = *bucket_; + script_->evalHashLink() = *bucket_; *bucket_ = script_; } } @@ -3004,7 +3004,7 @@ CreateThisForFunctionWithType(JSContext *cx, types::TypeObject *type, JSObject * gc::AllocKind kind = type->newScript->allocKind; JSObject *res = NewObjectWithType(cx, type, parent, kind); if (res) - res->setMap((Shape *) type->newScript->shape); + res->initMap((Shape *) type->newScript->shape.get()); return res; } @@ -3504,7 +3504,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth) if (!emptyWithShape) return NULL; - obj->setMap(emptyWithShape); + obj->initMap(emptyWithShape); OBJ_SET_BLOCK_DEPTH(cx, obj, depth); AutoObjectRooter tvr(cx, obj); @@ -3533,7 +3533,7 @@ js_NewBlockObject(JSContext *cx) if (!emptyBlockShape) return NULL; blockObj->init(cx, &BlockClass, &emptyTypeObject, NULL, NULL, false); - blockObj->setMap(emptyBlockShape); + blockObj->initMap(emptyBlockShape); return blockObj; } @@ -3591,7 +3591,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind) if (normalUnwind) { uintN slot = JSSLOT_BLOCK_FIRST_FREE_SLOT; depth += fp->numFixed(); - obj->copySlotRange(slot, fp->slots() + depth, count); + obj->copySlotRange(slot, fp->slots() + depth, count, true); } /* We must clear the private slot even with errors. */ @@ -3794,8 +3794,8 @@ struct JSObject::TradeGutsReserved { JSContext *cx; Vector avals; Vector bvals; - Value *newaslots; - Value *newbslots; + HeapValue *newaslots; + HeapValue *newbslots; TradeGutsReserved(JSContext *cx) : cx(cx), avals(cx), bvals(cx), newaslots(NULL), newbslots(NULL) @@ -3843,12 +3843,12 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b, unsigned bfixed = b->numFixedSlots(); if (afixed < bcap) { - reserved.newaslots = (Value *) cx->malloc_(sizeof(Value) * (bcap - afixed)); + reserved.newaslots = (HeapValue *) cx->malloc_(sizeof(HeapValue) * (bcap - afixed)); if (!reserved.newaslots) return false; } if (bfixed < acap) { - reserved.newbslots = (Value *) cx->malloc_(sizeof(Value) * (acap - bfixed)); + reserved.newbslots = (HeapValue *) cx->malloc_(sizeof(HeapValue) * (acap - bfixed)); if (!reserved.newbslots) return false; } @@ -3885,6 +3885,19 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved & JS_ASSERT(!a->isDenseArray() && !b->isDenseArray()); JS_ASSERT(!a->isArrayBuffer() && !b->isArrayBuffer()); +#ifdef JSGC_INCREMENTAL + /* + * We need a write barrier here. If |a| was marked and |b| was not, then + * after the swap, |b|'s guts would never be marked. The write barrier + * solves this. + */ + JSCompartment *comp = a->compartment(); + if (comp->needsBarrier()) { + MarkChildren(comp->barrierTracer(), a); + MarkChildren(comp->barrierTracer(), b); + } +#endif + /* New types for a JSObject need to be stable when trading guts. */ TypeObject *newTypeA = a->newType; TypeObject *newTypeB = b->newType; @@ -3938,7 +3951,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved & unsigned afixed = a->numFixedSlots(); unsigned bfixed = b->numFixedSlots(); - JSObject tmp; + char tmp[sizeof(JSObject)]; memcpy(&tmp, a, sizeof tmp); memcpy(a, b, sizeof tmp); memcpy(b, &tmp, sizeof tmp); @@ -3946,13 +3959,13 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved & a->updateFixedSlots(afixed); a->slots = reserved.newaslots; a->capacity = Max(afixed, bcap); - a->copySlotRange(0, reserved.bvals.begin(), bcap); + a->copySlotRange(0, reserved.bvals.begin(), bcap, false); a->clearSlotRange(bcap, a->capacity - bcap); b->updateFixedSlots(bfixed); b->slots = reserved.newbslots; b->capacity = Max(bfixed, acap); - b->copySlotRange(0, reserved.avals.begin(), acap); + b->copySlotRange(0, reserved.avals.begin(), acap, false); b->clearSlotRange(acap, b->capacity - acap); /* Make sure the destructor for reserved doesn't free the slots. */ @@ -4448,27 +4461,31 @@ JSObject::clearSlotRange(size_t start, size_t length) { JS_ASSERT(start + length <= capacity); if (isDenseArray()) { - ClearValueRange(slots + start, length, true); + ClearValueRange(compartment(), slots + start, length, true); } else { size_t fixed = numFixedSlots(); if (start < fixed) { if (start + length < fixed) { - ClearValueRange(fixedSlots() + start, length, false); + ClearValueRange(compartment(), fixedSlots() + start, length, false); } else { size_t localClear = fixed - start; - ClearValueRange(fixedSlots() + start, localClear, false); - ClearValueRange(slots, length - localClear, false); + ClearValueRange(compartment(), fixedSlots() + start, localClear, false); + ClearValueRange(compartment(), slots, length - localClear, false); } } else { - ClearValueRange(slots + start - fixed, length, false); + ClearValueRange(compartment(), slots + start - fixed, length, false); } } } void -JSObject::copySlotRange(size_t start, const Value *vector, size_t length) +JSObject::copySlotRange(size_t start, const Value *vector, size_t length, bool valid) { JS_ASSERT(start + length <= capacity); + + if (valid) + prepareSlotRangeForOverwrite(start, start + length); + if (isDenseArray()) { memcpy(slots + start, vector, length * sizeof(Value)); } else { @@ -4522,7 +4539,7 @@ JSObject::allocSlots(JSContext *cx, size_t newcap) uint32 allocCount = numDynamicSlots(newcap); - Value *tmpslots = (Value*) cx->malloc_(allocCount * sizeof(Value)); + HeapValue *tmpslots = (HeapValue*) cx->malloc_(allocCount * sizeof(HeapValue)); if (!tmpslots) return false; /* Leave slots at inline buffer. */ slots = tmpslots; @@ -4530,12 +4547,12 @@ JSObject::allocSlots(JSContext *cx, size_t newcap) if (isDenseArray()) { /* Copy over anything from the inline buffer. */ - memcpy(slots, fixedSlots(), getDenseArrayInitializedLength() * sizeof(Value)); + memcpy(slots, fixedSlots(), getDenseArrayInitializedLength() * sizeof(HeapValue)); if (!cx->typeInferenceEnabled()) backfillDenseArrayHoles(cx); } else { /* Clear out the new slots without copying. */ - ClearValueRange(slots, allocCount, false); + InitValueRange(slots, allocCount, false); } Probes::resizeObject(cx, this, oldSize, slotsAndStructSize()); @@ -4592,8 +4609,8 @@ JSObject::growSlots(JSContext *cx, size_t newcap) uint32 oldAllocCount = numDynamicSlots(oldcap); uint32 allocCount = numDynamicSlots(actualCapacity); - Value *tmpslots = (Value*) cx->realloc_(slots, oldAllocCount * sizeof(Value), - allocCount * sizeof(Value)); + HeapValue *tmpslots = (HeapValue*) cx->realloc_(slots, oldAllocCount * sizeof(HeapValue), + allocCount * sizeof(HeapValue)); if (!tmpslots) return false; /* Leave dslots as its old size. */ @@ -4606,7 +4623,7 @@ JSObject::growSlots(JSContext *cx, size_t newcap) backfillDenseArrayHoles(cx); } else { /* Clear the new slots we added. */ - ClearValueRange(slots + oldAllocCount, allocCount - oldAllocCount, false); + InitValueRange(slots + oldAllocCount, allocCount - oldAllocCount, false); } if (changed && isGlobal()) @@ -4629,6 +4646,8 @@ JSObject::shrinkSlots(JSContext *cx, size_t newcap) if (isCall()) return; + JS_ASSERT_IF(isDenseArray(), initializedLength() <= newcap); + uint32 oldcap = numSlots(); JS_ASSERT(newcap <= oldcap); JS_ASSERT(newcap >= slotSpan()); @@ -4650,7 +4669,7 @@ JSObject::shrinkSlots(JSContext *cx, size_t newcap) newcap = Max(newcap, size_t(SLOT_CAPACITY_MIN)); newcap = Max(newcap, numFixedSlots()); - Value *tmpslots = (Value*) cx->realloc_(slots, newcap * sizeof(Value)); + HeapValue *tmpslots = (HeapValue*) cx->realloc_(slots, newcap * sizeof(HeapValue)); if (!tmpslots) return; /* Leave slots at its old size. */ diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 91cb9c4b955f..645da327946b 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -59,6 +59,7 @@ #include "jslock.h" #include "jscell.h" +#include "gc/Barrier.h" #include "vm/String.h" namespace nanojit { class ValidateWriter; } @@ -427,7 +428,7 @@ struct JSObject : js::gc::Cell { * Private pointer to the last added property and methods to manipulate the * list it links among properties in this scope. */ - js::Shape *lastProp; + js::HeapPtrShape lastProp; private: js::Class *clasp; @@ -488,25 +489,25 @@ struct JSObject : js::gc::Cell { NSLOTS_LIMIT = JS_BIT(NSLOTS_BITS) }; - uint32 flags; /* flags */ - uint32 objShape; /* copy of lastProp->shape, or override if different */ + uint32 flags; /* flags */ + uint32 objShape; /* copy of lastProp->shape, or override if different */ - union { - /* If prototype, type of values using this as their prototype. */ - js::types::TypeObject *newType; + /* + * If prototype, type of values using this as their prototype. If a dense + * array, this holds the initialized length (see jsarray.cpp). + */ + js::HeapPtr newType; - /* If dense array, the initialized length (see jsarray.cpp). */ - jsuword initializedLength; - }; + jsuword &initializedLength() { return *newType.unsafeGetUnioned(); } JS_FRIEND_API(size_t) sizeOfSlotsArray(JSUsableSizeFun usf); - JSObject *parent; /* object's parent */ - void *privateData; /* private data */ - jsuword capacity; /* total number of available slots */ + js::HeapPtrObject parent; /* object's parent */ + void *privateData; /* private data */ + jsuword capacity; /* total number of available slots */ private: - js::Value *slots; /* dynamically allocated slots, + js::HeapValue *slots; /* dynamically allocated slots, or pointer to fixedSlots() for dense arrays. */ @@ -515,13 +516,12 @@ struct JSObject : js::gc::Cell { * set, this is the prototype's default 'new' type and can only be used * to get that prototype. */ - js::types::TypeObject *type_; + js::HeapPtr type_; /* Make the type object to use for LAZY_TYPE objects. */ void makeLazyType(JSContext *cx); public: - inline bool isNative() const; inline bool isNewborn() const; @@ -537,7 +537,6 @@ struct JSObject : js::gc::Cell { return &getClass()->ops; } - inline void trace(JSTracer *trc); inline void scanSlots(js::GCMarker *gcmarker); uint32 shape() const { @@ -617,6 +616,7 @@ struct JSObject : js::gc::Cell { bool hasOwnShape() const { return !!(flags & OWN_SHAPE); } + inline void initMap(js::Shape *amap); inline void setMap(js::Shape *amap); inline void setSharedNonNativeMap(); @@ -730,13 +730,14 @@ struct JSObject : js::gc::Cell { static inline size_t getFixedSlotOffset(size_t slot); static inline size_t offsetOfCapacity() { return offsetof(JSObject, capacity); } static inline size_t offsetOfSlots() { return offsetof(JSObject, slots); } + static inline size_t offsetOfInitializedLength() { return offsetof(JSObject, newType); } /* * Get a raw pointer to the object's slots, or a slot of the object given * a previous value for its since-reallocated dynamic slots. */ - inline const js::Value *getRawSlots(); - inline const js::Value *getRawSlot(size_t slot, const js::Value *slots); + inline const js::HeapValue *getRawSlots(); + inline const js::HeapValue *getRawSlot(size_t slot, const js::HeapValue *slots); /* Whether a slot is at a fixed offset from this object. */ inline bool isFixedSlot(size_t slot); @@ -753,7 +754,7 @@ struct JSObject : js::gc::Cell { inline size_t numDynamicSlots(size_t capacity) const; private: - inline js::Value* fixedSlots() const; + inline js::HeapValue *fixedSlots() const; protected: inline bool hasContiguousSlots(size_t start, size_t count) const; @@ -772,6 +773,12 @@ struct JSObject : js::gc::Cell { return true; } + /* + * Trigger the write barrier on a range of slots that will no longer be + * reachable. + */ + inline void prepareSlotRangeForOverwrite(size_t start, size_t end); + /* * Fill a range of slots with holes or undefined, depending on whether this * is a dense array. @@ -780,9 +787,11 @@ struct JSObject : js::gc::Cell { /* * Copy a flat array of slots to this object at a start slot. Caller must - * ensure there are enough slots in this object. + * ensure there are enough slots in this object. If |valid|, then the slots + * being overwritten hold valid data and must be invalidated for the write + * barrier. */ - void copySlotRange(size_t start, const js::Value *vector, size_t length); + void copySlotRange(size_t start, const js::Value *vector, size_t length, bool valid); /* * Ensure that the object has at least JSCLASS_RESERVED_SLOTS(clasp) + @@ -817,12 +826,13 @@ struct JSObject : js::gc::Cell { void rollbackProperties(JSContext *cx, uint32 slotSpan); - js::Value *getSlotAddress(uintN slot) { + js::HeapValue *getSlotAddress(uintN slot) { /* * This can be used to get the address of the end of the slots for the * object, which may be necessary when fetching zero-length arrays of * slots (e.g. for callObjVarArray). */ + JS_ASSERT(!isDenseArray()); JS_ASSERT(slot <= capacity); size_t fixed = numFixedSlots(); if (slot < fixed) @@ -830,12 +840,12 @@ struct JSObject : js::gc::Cell { return slots + (slot - fixed); } - js::Value &getSlotRef(uintN slot) { + js::HeapValue &getSlotRef(uintN slot) { JS_ASSERT(slot < capacity); return *getSlotAddress(slot); } - inline js::Value &nativeGetSlotRef(uintN slot); + inline js::HeapValue &nativeGetSlotRef(uintN slot); const js::Value &getSlot(uintN slot) const { JS_ASSERT(slot < capacity); @@ -847,22 +857,22 @@ struct JSObject : js::gc::Cell { inline const js::Value &nativeGetSlot(uintN slot) const; - void setSlot(uintN slot, const js::Value &value) { - JS_ASSERT(slot < capacity); - getSlotRef(slot) = value; - } + inline void setSlot(uintN slot, const js::Value &value); + inline void initSlot(uintN slot, const js::Value &value); + inline void initSlotUnchecked(uintN slot, const js::Value &value); inline void nativeSetSlot(uintN slot, const js::Value &value); inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value); inline js::Value getReservedSlot(uintN index) const; + inline js::HeapValue &getReservedSlotRef(uintN index); /* Call this only after the appropriate ensure{Class,Instance}ReservedSlots call. */ inline void setReservedSlot(uintN index, const js::Value &v); /* For slots which are known to always be fixed, due to the way they are allocated. */ - js::Value &getFixedSlotRef(uintN slot) { + js::HeapValue &getFixedSlotRef(uintN slot) { JS_ASSERT(slot < numFixedSlots()); return fixedSlots()[slot]; } @@ -872,10 +882,8 @@ struct JSObject : js::gc::Cell { return fixedSlots()[slot]; } - void setFixedSlot(uintN slot, const js::Value &value) { - JS_ASSERT(slot < numFixedSlots()); - fixedSlots()[slot] = value; - } + inline void setFixedSlot(uintN slot, const js::Value &value); + inline void initFixedSlot(uintN slot, const js::Value &value); /* Defined in jsscopeinlines.h to avoid including implementation dependencies here. */ inline void updateShape(JSContext *cx); @@ -912,7 +920,7 @@ struct JSObject : js::gc::Cell { return type_; } - js::types::TypeObject *typeFromGC() const { + const js::HeapPtr &typeFromGC() const { /* Direct field access for use by GC. */ return type_; } @@ -921,13 +929,14 @@ struct JSObject : js::gc::Cell { inline void clearType(); inline void setType(js::types::TypeObject *newType); + inline void initType(js::types::TypeObject *newType); inline js::types::TypeObject *getNewType(JSContext *cx, JSFunction *fun = NULL, bool markUnknown = false); private: void makeNewType(JSContext *cx, JSFunction *fun, bool markUnknown); - public: + public: /* Set a new prototype for an object with a singleton type. */ bool splicePrototype(JSContext *cx, JSObject *proto); @@ -945,18 +954,9 @@ struct JSObject : js::gc::Cell { return parent; } - void clearParent() { - parent = NULL; - } - - void setParent(JSObject *newParent) { -#ifdef DEBUG - for (JSObject *obj = newParent; obj; obj = obj->getParent()) - JS_ASSERT(obj != this); -#endif - setDelegateNullSafe(newParent); - parent = newParent; - } + inline void clearParent(); + inline void setParent(JSObject *newParent); + inline void initParent(JSObject *newParent); JS_FRIEND_API(js::GlobalObject *) getGlobal() const; @@ -971,10 +971,8 @@ struct JSObject : js::gc::Cell { return privateData; } - void setPrivate(void *data) { - JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE); - privateData = data; - } + inline void initPrivate(void *data); + inline void setPrivate(void *data); /* N.B. Infallible: NULL means 'no principal', not an error. */ inline JSPrincipals *principals(JSContext *cx); @@ -1043,11 +1041,14 @@ struct JSObject : js::gc::Cell { inline void setDenseArrayInitializedLength(uint32 length); inline void ensureDenseArrayInitializedLength(JSContext *cx, uintN index, uintN extra); inline void backfillDenseArrayHoles(JSContext *cx); - inline const js::Value* getDenseArrayElements(); + inline js::HeapValueArray getDenseArrayElements(); inline const js::Value &getDenseArrayElement(uintN idx); inline void setDenseArrayElement(uintN idx, const js::Value &val); + inline void initDenseArrayElement(uintN idx, const js::Value &val); inline void setDenseArrayElementWithType(JSContext *cx, uintN idx, const js::Value &val); + inline void initDenseArrayElementWithType(JSContext *cx, uintN idx, const js::Value &val); inline void copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count); + inline void initDenseArrayElements(uintN dstStart, const js::Value *src, uintN count); inline void moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count); inline void shrinkDenseArrayElements(JSContext *cx, uintN cap); inline bool denseArrayHasInlineSlots() const; @@ -1156,11 +1157,11 @@ struct JSObject : js::gc::Cell { inline JSFunction *getFunctionPrivate() const; - inline js::Value *getFlatClosureUpvars() const; + inline js::FlatClosureData *getFlatClosureData() const; inline js::Value getFlatClosureUpvar(uint32 i) const; inline const js::Value &getFlatClosureUpvar(uint32 i); inline void setFlatClosureUpvar(uint32 i, const js::Value &v); - inline void setFlatClosureUpvars(js::Value *upvars); + inline void setFlatClosureData(js::FlatClosureData *data); /* See comments in fun_finalize. */ inline void finalizeUpvarsIfFlatClosure(); @@ -1240,12 +1241,7 @@ struct JSObject : js::gc::Cell { inline bool isCallable(); /* Do initialization required immediately after allocation. */ - void earlyInit(jsuword capacity) { - this->capacity = capacity; - - /* Stops obj from being scanned until initializated. */ - lastProp = NULL; - } + inline void earlyInit(jsuword capacity); /* The map field is not initialized here and should be set separately. */ void init(JSContext *cx, js::Class *aclasp, js::types::TypeObject *type, @@ -1503,6 +1499,11 @@ struct JSObject : js::gc::Cell { /*** For jit compiler: ***/ static size_t offsetOfClassPointer() { return offsetof(JSObject, clasp); } + + static inline void writeBarrierPre(JSObject *obj); + static inline void writeBarrierPost(JSObject *obj, void *addr); + inline void privateWriteBarrierPre(void **oldval); + inline void privateWriteBarrierPost(void **oldval); }; /* @@ -1522,9 +1523,10 @@ operator!=(const JSObject &lhs, const JSObject &rhs) return &lhs != &rhs; } -inline js::Value* -JSObject::fixedSlots() const { - return (js::Value*) (jsuword(this) + sizeof(JSObject)); +inline js::HeapValue* +JSObject::fixedSlots() const +{ + return (js::HeapValue *) (jsuword(this) + sizeof(JSObject)); } inline size_t diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 1611a41b1e84..9caf51c066c3 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99: * * ***** BEGIN LICENSE BLOCK ***** @@ -42,9 +42,11 @@ #define jsobjinlines_h___ #include + #include "jsarray.h" #include "jsdate.h" #include "jsfun.h" +#include "jsgcmark.h" #include "jsiter.h" #include "jslock.h" #include "jsobj.h" @@ -65,6 +67,8 @@ #include "jsscriptinlines.h" #include "jsstr.h" +#include "gc/Barrier.h" +#include "js/TemplateLib.h" #include "vm/GlobalObject.h" #include "jsatominlines.h" @@ -72,6 +76,9 @@ #include "jsgcinlines.h" #include "jsscopeinlines.h" +#include "gc/Barrier-inl.h" +#include "vm/String-inl.h" + inline bool JSObject::preventExtensions(JSContext *cx, js::AutoIdVector *props) { @@ -277,7 +284,7 @@ inline void JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent) { init(cx, &js::CallClass, &js::types::emptyTypeObject, parent, NULL, false); - lastProp = bindings.lastShape(); + lastProp.init(bindings.lastShape()); /* * If |bindings| is for a function that has extensible parents, that means @@ -317,7 +324,8 @@ JSObject::initClonedBlock(JSContext *cx, js::types::TypeObject *type, js::StackF * also need unique shapes. See js::Bindings::extensibleParents. */ inline void -JSObject::setBlockOwnShape(JSContext *cx) { +JSObject::setBlockOwnShape(JSContext *cx) +{ JS_ASSERT(isStaticBlock()); setOwnShape(js_GenerateShape(cx)); } @@ -397,15 +405,15 @@ JSObject::methodWriteBarrier(JSContext *cx, uint32 slot, const js::Value &v) return true; } -inline const js::Value * +inline const js::HeapValue * JSObject::getRawSlots() { JS_ASSERT(isGlobal()); return slots; } -inline const js::Value * -JSObject::getRawSlot(size_t slot, const js::Value *slots) +inline const js::HeapValue * +JSObject::getRawSlot(size_t slot, const js::HeapValue *slots) { JS_ASSERT(isGlobal()); size_t fixed = numFixedSlots(); @@ -447,6 +455,13 @@ JSObject::getReservedSlot(uintN index) const return (index < numSlots()) ? getSlot(index) : js::UndefinedValue(); } +inline js::HeapValue & +JSObject::getReservedSlotRef(uintN index) +{ + JS_ASSERT(index < numSlots()); + return getSlotRef(index); +} + inline void JSObject::setReservedSlot(uintN index, const js::Value &v) { @@ -493,6 +508,19 @@ JSObject::hasContiguousSlots(size_t start, size_t count) const return (start + count <= numFixedSlots()) || (start >= numFixedSlots()); } +inline void +JSObject::prepareSlotRangeForOverwrite(size_t start, size_t end) +{ + if (isDenseArray()) { + JS_ASSERT(end <= initializedLength()); + for (size_t i = start; i < end; i++) + slots[i].js::HeapValue::~HeapValue(); + } else { + for (size_t i = start; i < end; i++) + getSlotRef(i).js::HeapValue::~HeapValue(); + } +} + inline size_t JSObject::structSize() const { @@ -541,7 +569,7 @@ JSObject::setArrayLength(JSContext *cx, uint32 length) js::types::Type::DoubleType()); } - setPrivate((void*)(uintptr_t) length); + privateData = (void*)(uintptr_t) length; } inline void @@ -550,7 +578,7 @@ JSObject::setDenseArrayLength(uint32 length) /* Variant of setArrayLength for use on dense arrays where the length cannot overflow int32. */ JS_ASSERT(isDenseArray()); JS_ASSERT(length <= INT32_MAX); - setPrivate((void*)(uintptr_t) length); + privateData = (void*)(uintptr_t) length; } inline uint32 @@ -560,11 +588,11 @@ JSObject::getDenseArrayCapacity() return numSlots(); } -inline const js::Value * +inline js::HeapValueArray JSObject::getDenseArrayElements() { JS_ASSERT(isDenseArray()); - return slots; + return js::HeapValueArray(slots); } inline const js::Value & @@ -581,6 +609,13 @@ JSObject::setDenseArrayElement(uintN idx, const js::Value &val) slots[idx] = val; } +inline void +JSObject::initDenseArrayElement(uintN idx, const js::Value &val) +{ + JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength()); + slots[idx].init(val); +} + inline void JSObject::setDenseArrayElementWithType(JSContext *cx, uintN idx, const js::Value &val) { @@ -588,8 +623,24 @@ JSObject::setDenseArrayElementWithType(JSContext *cx, uintN idx, const js::Value setDenseArrayElement(idx, val); } +inline void +JSObject::initDenseArrayElementWithType(JSContext *cx, uintN idx, const js::Value &val) +{ + js::types::AddTypePropertyId(cx, this, JSID_VOID, val); + initDenseArrayElement(idx, val); +} + inline void JSObject::copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count) +{ + JS_ASSERT(isDenseArray()); + JS_ASSERT(dstStart + count <= capacity); + prepareSlotRangeForOverwrite(dstStart, dstStart + count); + memcpy(slots + dstStart, src, count * sizeof(js::Value)); +} + +inline void +JSObject::initDenseArrayElements(uintN dstStart, const js::Value *src, uintN count) { JS_ASSERT(isDenseArray()); JS_ASSERT(dstStart + count <= capacity); @@ -602,6 +653,21 @@ JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count) JS_ASSERT(isDenseArray()); JS_ASSERT(dstStart + count <= capacity); JS_ASSERT(srcStart + count <= capacity); + + /* + * Use a custom write barrier here since it's performance sensitive. We + * only want to barrier the slots that are being overwritten. + */ + uintN markStart, markEnd; + if (dstStart > srcStart) { + markStart = js::Max(srcStart + count, dstStart); + markEnd = dstStart + count; + } else { + markStart = dstStart; + markEnd = js::Min(dstStart + count, srcStart); + } + prepareSlotRangeForOverwrite(markStart, markEnd); + memmove(slots + dstStart, slots + srcStart, count * sizeof(js::Value)); } @@ -647,15 +713,15 @@ JSObject::setDateUTCTime(const js::Value &time) setFixedSlot(JSSLOT_DATE_UTC_TIME, time); } -inline js::Value * -JSObject::getFlatClosureUpvars() const +inline js::FlatClosureData * +JSObject::getFlatClosureData() const { #ifdef DEBUG JSFunction *fun = getFunctionPrivate(); JS_ASSERT(fun->isFlatClosure()); JS_ASSERT(fun->script()->bindings.countUpvars() == fun->script()->upvars()->length); #endif - return (js::Value *) getFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS).toPrivate(); + return (js::FlatClosureData *) getFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS).toPrivate(); } inline void @@ -693,29 +759,29 @@ inline js::Value JSObject::getFlatClosureUpvar(uint32 i) const { JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars()); - return getFlatClosureUpvars()[i]; + return getFlatClosureData()->upvars[i]; } inline const js::Value & JSObject::getFlatClosureUpvar(uint32 i) { JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars()); - return getFlatClosureUpvars()[i]; + return getFlatClosureData()->upvars[i]; } inline void JSObject::setFlatClosureUpvar(uint32 i, const js::Value &v) { JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars()); - getFlatClosureUpvars()[i] = v; + getFlatClosureData()->upvars[i] = v; } inline void -JSObject::setFlatClosureUpvars(js::Value *upvars) +JSObject::setFlatClosureData(js::FlatClosureData *data) { JS_ASSERT(isFunction()); JS_ASSERT(getFunctionPrivate()->isFlatClosure()); - setFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS, js::PrivateValue(upvars)); + setFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS, js::PrivateValue(data)); } inline bool @@ -840,7 +906,7 @@ JSObject::getWithThis() const inline void JSObject::setWithThis(JSObject *thisp) { - getFixedSlotRef(JSSLOT_WITH_THIS).setObject(*thisp); + setFixedSlot(JSSLOT_WITH_THIS, js::ObjectValue(*thisp)); } inline bool @@ -913,6 +979,28 @@ JSObject::setType(js::types::TypeObject *newType) type_ = newType; } +inline void +JSObject::earlyInit(jsuword capacity) +{ + this->capacity = capacity; + + /* Stops obj from being scanned until initializated. */ + lastProp.init(NULL); +} + +inline void +JSObject::initType(js::types::TypeObject *newType) +{ +#ifdef DEBUG + JS_ASSERT(newType); + for (JSObject *obj = newType->proto; obj; obj = obj->getProto()) + JS_ASSERT(obj != this); +#endif + JS_ASSERT_IF(hasSpecialEquality(), newType->hasAnyFlags(js::types::OBJECT_FLAG_SPECIAL_EQUALITY)); + JS_ASSERT(!hasSingletonType()); + type_.init(newType); +} + inline void JSObject::init(JSContext *cx, js::Class *aclasp, js::types::TypeObject *type, JSObject *parent, void *priv, bool denseArray) @@ -944,14 +1032,12 @@ JSObject::init(JSContext *cx, js::Class *aclasp, js::types::TypeObject *type, slots = fixedSlots(); flags |= PACKED_ARRAY; } else { - js::ClearValueRange(fixedSlots(), capacity, denseArray); + js::InitValueRange(fixedSlots(), capacity, denseArray); } - newType = NULL; - JS_ASSERT(initializedLength == 0); - - setType(type); - setParent(parent); + newType.init(NULL); + initType(type); + initParent(parent); } inline void @@ -977,7 +1063,7 @@ JSObject::initSharingEmptyShape(JSContext *cx, if (!empty) return false; - setMap(empty); + initMap(empty); return true; } @@ -1028,7 +1114,15 @@ JSObject::setMap(js::Shape *amap) objShape = lastProp->shapeid; } -inline js::Value & +inline void +JSObject::initMap(js::Shape *amap) +{ + JS_ASSERT(!hasOwnShape()); + lastProp.init(amap); + objShape = lastProp->shapeid; +} + +inline js::HeapValue & JSObject::nativeGetSlotRef(uintN slot) { JS_ASSERT(isNative()); @@ -1400,7 +1494,7 @@ class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescri friend void AutoGCRooter::trace(JSTracer *trc); }; -static inline bool +static inline js::EmptyShape * InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, js::types::TypeObject *type, gc::AllocKind kind) { @@ -1420,20 +1514,19 @@ InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, js::types::Ty if (!empty) goto bad; - obj->setMap(empty); - return true; + return empty; bad: /* The GC nulls map initially. It should still be null on error. */ JS_ASSERT(obj->isNewborn()); - return false; + return NULL; } static inline bool CanBeFinalizedInBackground(gc::AllocKind kind, Class *clasp) { #ifdef JS_THREADSAFE - JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST); + JS_ASSERT(kind < gc::FINALIZE_OBJECT_LIMIT); /* If the class has no finalizer or a finalizer that is safe to call on * a different thread, we change the finalize kind. For example, * FINALIZE_OBJECT0 calls the finalizer on the main thread, @@ -1461,7 +1554,7 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, { JS_ASSERT(proto); JS_ASSERT(parent); - JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST); + JS_ASSERT(kind < gc::FINALIZE_OBJECT_LIMIT); types::TypeObject *type = proto->getNewType(cx); if (!type) @@ -1487,9 +1580,8 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JS_ASSERT(type->canProvideEmptyShape(clasp)); js::EmptyShape *empty = type->getEmptyShape(cx, clasp, kind); - if (empty) - obj->setMap(empty); + obj->initMap(empty); else obj = NULL; } @@ -1660,10 +1752,12 @@ NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent, NULL, clasp == &ArrayClass); if (clasp->isNative()) { - if (!InitScopeForObject(cx, obj, clasp, type, kind)) { + js::EmptyShape *empty = InitScopeForObject(cx, obj, clasp, type, kind); + if (!empty) { obj = NULL; goto out; } + obj->initMap(empty); } else { obj->setSharedNonNativeMap(); } @@ -1749,10 +1843,13 @@ NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc:: (!parent && type->proto) ? type->proto->getParent() : parent, NULL, false); - if (!InitScopeForObject(cx, obj, &ObjectClass, type, kind)) { + js::EmptyShape *empty; + empty = InitScopeForObject(cx, obj, &ObjectClass, type, kind); + if (!empty) { obj = NULL; goto out; } + obj->initMap(empty); out: Probes::createObject(cx, obj); @@ -1997,4 +2094,126 @@ js_GetProtoIfDenseArray(JSObject *obj) return obj->isDenseArray() ? obj->getProto() : obj; } +inline void +JSObject::setSlot(uintN slot, const js::Value &value) +{ + JS_ASSERT(slot < capacity); + getSlotRef(slot).set(compartment(), value); +} + +inline void +JSObject::initSlot(uintN slot, const js::Value &value) +{ + JS_ASSERT(getSlot(slot).isUndefined() || getSlot(slot).isMagic(JS_ARRAY_HOLE)); + initSlotUnchecked(slot, value); +} + +inline void +JSObject::initSlotUnchecked(uintN slot, const js::Value &value) +{ + JS_ASSERT(slot < capacity); + getSlotRef(slot).init(value); +} + +inline void +JSObject::setFixedSlot(uintN slot, const js::Value &value) +{ + JS_ASSERT(slot < numFixedSlots()); + fixedSlots()[slot] = value; +} + +inline void +JSObject::initFixedSlot(uintN slot, const js::Value &value) +{ + JS_ASSERT(slot < numFixedSlots()); + fixedSlots()[slot].init(value); +} + +inline void +JSObject::clearParent() +{ + parent.clear(); +} + +inline void +JSObject::setParent(JSObject *newParent) +{ +#ifdef DEBUG + for (JSObject *obj = newParent; obj; obj = obj->getParent()) + JS_ASSERT(obj != this); +#endif + setDelegateNullSafe(newParent); + parent = newParent; +} + +inline void +JSObject::initParent(JSObject *newParent) +{ + JS_ASSERT(isNewborn()); +#ifdef DEBUG + for (JSObject *obj = newParent; obj; obj = obj->getParent()) + JS_ASSERT(obj != this); +#endif + setDelegateNullSafe(newParent); + parent.init(newParent); +} + +inline void +JSObject::setPrivate(void *data) +{ + JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE); + + privateWriteBarrierPre(&privateData); + privateData = data; + privateWriteBarrierPost(&privateData); +} + +inline void +JSObject::initPrivate(void *data) +{ + JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE); + privateData = data; +} + +inline void +JSObject::privateWriteBarrierPre(void **old) +{ +#ifdef JSGC_INCREMENTAL + JSCompartment *comp = compartment(); + if (comp->needsBarrier()) { + if (clasp->trace && *old) + clasp->trace(comp->barrierTracer(), this); + } +#endif +} + +inline void +JSObject::privateWriteBarrierPost(void **old) +{ +} + +inline void +JSObject::writeBarrierPre(JSObject *obj) +{ +#ifdef JSGC_INCREMENTAL + /* + * This would normally be a null test, but TypeScript::global uses 0x1 as a + * special value. + */ + if (uintptr_t(obj) < 32) + return; + + JSCompartment *comp = obj->compartment(); + if (comp->needsBarrier()) { + JS_ASSERT(!comp->rt->gcRunning); + MarkObjectUnbarriered(comp->barrierTracer(), obj, "write barrier"); + } +#endif +} + +inline void +JSObject::writeBarrierPost(JSObject *obj, void *addr) +{ +} + #endif /* jsobjinlines_h___ */ diff --git a/js/src/jsprobes.cpp b/js/src/jsprobes.cpp index 639ea6b1ac8a..5fb03e86a763 100644 --- a/js/src/jsprobes.cpp +++ b/js/src/jsprobes.cpp @@ -36,6 +36,7 @@ #ifdef MOZ_ETW #include "jswin.h" #include +#include /* Generated from ETWProvider.man */ #include "ETWProvider.h" @@ -49,11 +50,11 @@ #include "jsfun.h" #include "jsinterp.h" #include "jsobj.h" +#include "jsprobes.h" #include "jsscript.h" #include "jsstr.h" -#include "jsprobes.h" -#include +#include "jsobjinlines.h" #define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v)) diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index aa04b3976218..bec0df458083 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -159,6 +159,20 @@ Shape::removeChild(Shape *child) } } +/* + * We need a read barrier for the shape tree, since these are weak pointers. + */ +static Shape * +ReadBarrier(Shape *shape) +{ +#ifdef JSGC_INCREMENTAL + JSCompartment *comp = shape->compartment(); + if (comp->needsBarrier()) + MarkShapeUnbarriered(comp->barrierTracer(), shape, "read barrier"); +#endif + return shape; +} + Shape * PropertyTree::getChild(JSContext *cx, Shape *parent, const Shape &child) { @@ -179,11 +193,11 @@ PropertyTree::getChild(JSContext *cx, Shape *parent, const Shape &child) if (kidp->isShape()) { shape = kidp->toShape(); if (shape->matches(&child)) - return shape; + return ReadBarrier(shape); } else if (kidp->isHash()) { shape = *kidp->toHash()->lookup(&child); if (shape) - return shape; + return ReadBarrier(shape); } else { /* If kidp->isNull(), we always insert. */ } @@ -192,7 +206,7 @@ PropertyTree::getChild(JSContext *cx, Shape *parent, const Shape &child) if (!shape) return NULL; - new (shape) Shape(child.propid, child.rawGetter, child.rawSetter, child.slot, child.attrs, + new (shape) Shape(child.propid, child.getter(), child.setter(), child.slot, child.attrs, child.flags, child.shortid, js_GenerateShape(cx)); if (!insertChild(cx, parent, shape)) @@ -256,8 +270,8 @@ Shape::dump(JSContext *cx, FILE *fp) const } fprintf(fp, " g/s %p/%p slot %u attrs %x ", - JS_FUNC_TO_DATA_PTR(void *, rawGetter), - JS_FUNC_TO_DATA_PTR(void *, rawSetter), + JS_FUNC_TO_DATA_PTR(void *, getter()), + JS_FUNC_TO_DATA_PTR(void *, setter()), slot, attrs); if (attrs) { int first = 1; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index ad454c48a379..142f8864ffef 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -57,19 +57,29 @@ using namespace js; using namespace js::gc; -static inline const Value & -GetCall(JSObject *proxy) { +static inline const HeapValue & +GetCall(JSObject *proxy) +{ JS_ASSERT(IsFunctionProxy(proxy)); - return proxy->getSlot(JSSLOT_PROXY_CALL); + return proxy->getSlotRef(JSSLOT_PROXY_CALL); } static inline Value -GetConstruct(JSObject *proxy) { +GetConstruct(JSObject *proxy) +{ if (proxy->numSlots() <= JSSLOT_PROXY_CONSTRUCT) return UndefinedValue(); return proxy->getSlot(JSSLOT_PROXY_CONSTRUCT); } +static inline const HeapValue & +GetFunctionProxyConstruct(JSObject *proxy) +{ + JS_ASSERT(IsFunctionProxy(proxy)); + JS_ASSERT(proxy->numSlots() > JSSLOT_PROXY_CONSTRUCT); + return proxy->getSlotRef(JSSLOT_PROXY_CONSTRUCT); +} + static bool OperationInProgress(JSContext *cx, JSObject *proxy) { @@ -1191,12 +1201,12 @@ static void proxy_TraceObject(JSTracer *trc, JSObject *obj) { GetProxyHandler(obj)->trace(trc, obj); - MarkCrossCompartmentValue(trc, GetProxyPrivate(obj), "private"); - MarkCrossCompartmentValue(trc, GetProxyExtra(obj, 0), "extra0"); - MarkCrossCompartmentValue(trc, GetProxyExtra(obj, 1), "extra1"); + MarkCrossCompartmentValue(trc, obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private"); + MarkCrossCompartmentValue(trc, obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0"); + MarkCrossCompartmentValue(trc, obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1"); if (IsFunctionProxy(obj)) { MarkCrossCompartmentValue(trc, GetCall(obj), "call"); - MarkCrossCompartmentValue(trc, GetConstruct(obj), "construct"); + MarkCrossCompartmentValue(trc, GetFunctionProxyConstruct(obj), "construct"); } } @@ -1205,7 +1215,7 @@ proxy_TraceFunction(JSTracer *trc, JSObject *obj) { proxy_TraceObject(trc, obj); MarkCrossCompartmentValue(trc, GetCall(obj), "call"); - MarkCrossCompartmentValue(trc, GetConstruct(obj), "construct"); + MarkCrossCompartmentValue(trc, GetFunctionProxyConstruct(obj), "construct"); } static JSBool diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 10a44d0b1711..3dde9503cdba 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -93,8 +93,6 @@ typedef struct JSSubString JSSubString; typedef struct JSNativeTraceInfo JSNativeTraceInfo; typedef struct JSSpecializedNative JSSpecializedNative; typedef struct JSXML JSXML; -typedef struct JSXMLArray JSXMLArray; -typedef struct JSXMLArrayCursor JSXMLArrayCursor; /* * Template declarations. @@ -120,6 +118,7 @@ class JSWrapper; namespace js { struct ArgumentsData; +struct FlatClosureData; struct Class; class RegExpObject; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 2eb94c23ac9b..0dfd6d3d2825 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -214,7 +214,7 @@ PropertyTable::search(jsid id, bool adding) /* Hit: return entry. */ shape = SHAPE_CLEAR_COLLISION(stored); - if (shape && shape->propid == id) + if (shape && shape->propid.get() == id) return spp; /* Collision: double hash. */ @@ -248,7 +248,7 @@ PropertyTable::search(jsid id, bool adding) return (adding && firstRemoved) ? firstRemoved : spp; shape = SHAPE_CLEAR_COLLISION(stored); - if (shape && shape->propid == id) { + if (shape && shape->propid.get() == id) { JS_ASSERT(collision_flag); return spp; } @@ -322,8 +322,26 @@ PropertyTable::grow(JSContext *cx) return true; } +void +Shape::update(js::PropertyOp getter, js::StrictPropertyOp setter, uint8 attrs) +{ + if (hasGetterValue()) + JSObject::writeBarrierPre(getterObject()); + if (hasSetterValue()) + JSObject::writeBarrierPre(setterObject()); + + this->rawGetter = getter; + this->rawSetter = setter; + this->attrs = attrs; + + if (hasGetterValue()) + JSObject::writeBarrierPost(getterObject(), this); + if (hasSetterValue()) + JSObject::writeBarrierPost(setterObject(), this); +} + Shape * -Shape::getChild(JSContext *cx, const js::Shape &child, Shape **listp) +Shape::getChild(JSContext *cx, const js::Shape &child, HeapPtr *listp) { JS_ASSERT(!JSID_IS_VOID(child.propid)); JS_ASSERT(!child.inDictionary()); @@ -444,13 +462,13 @@ JSObject::getChildProperty(JSContext *cx, Shape *parent, Shape &child) } Shape * -Shape::newDictionaryShape(JSContext *cx, const Shape &child, Shape **listp) +Shape::newDictionaryShape(JSContext *cx, const Shape &child, HeapPtr *listp) { Shape *dprop = JS_PROPERTY_TREE(cx).newShape(cx); if (!dprop) return NULL; - new (dprop) Shape(child.propid, child.rawGetter, child.rawSetter, child.slot, child.attrs, + new (dprop) Shape(child.propid, child.getter(), child.setter(), child.slot, child.attrs, (child.flags & ~FROZEN) | IN_DICTIONARY, child.shortid, js_GenerateShape(cx), child.slotSpan); @@ -460,7 +478,7 @@ Shape::newDictionaryShape(JSContext *cx, const Shape &child, Shape **listp) } Shape * -Shape::newDictionaryList(JSContext *cx, Shape **listp) +Shape::newDictionaryList(JSContext *cx, HeapPtr *listp) { Shape *shape = *listp; Shape *list = shape; @@ -470,8 +488,8 @@ Shape::newDictionaryList(JSContext *cx, Shape **listp) * stack. This way, the GC doesn't see any intermediate state until we * switch listp at the end. */ - Shape *root = NULL; - Shape **childp = &root; + HeapPtrShape root(NULL); + HeapPtrShape *childp = &root; while (shape) { JS_ASSERT_IF(!shape->frozen(), !shape->inDictionary()); @@ -819,9 +837,7 @@ JSObject::putProperty(JSContext *cx, jsid id, } } - shape->rawGetter = getter; - shape->rawSetter = setter; - shape->attrs = uint8(attrs); + shape->update(getter, setter, uint8(attrs)); shape->flags = flags | Shape::IN_DICTIONARY; shape->shortid = int16(shortid); @@ -900,7 +916,7 @@ JSObject::changeProperty(JSContext *cx, const Shape *shape, uintN attrs, uintN m !(attrs & JSPROP_SHARED)); /* Don't allow method properties to be changed to have a getter. */ - JS_ASSERT_IF(getter != shape->rawGetter, !shape->isMethod()); + JS_ASSERT_IF(getter != shape->getter(), !shape->isMethod()); types::MarkTypePropertyConfigured(cx, this, shape->propid); if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) @@ -942,9 +958,7 @@ JSObject::changeProperty(JSContext *cx, const Shape *shape, uintN attrs, uintN m } } - mutableShape->rawGetter = getter; - mutableShape->rawSetter = setter; - mutableShape->attrs = uint8(attrs); + mutableShape->update(getter, setter, uint8(attrs)); updateFlags(shape); @@ -976,7 +990,7 @@ JSObject::changeProperty(JSContext *cx, const Shape *shape, uintN attrs, uintN m */ Shape child(shape->propid, getter, setter, shape->slot, attrs, shape->flags, shape->shortid); - newShape = putProperty(cx, child.propid, child.rawGetter, child.rawSetter, child.slot, + newShape = putProperty(cx, child.propid, child.getter(), child.setter(), child.slot, child.attrs, child.flags, child.shortid); } @@ -1189,16 +1203,16 @@ JSObject::methodShapeChange(JSContext *cx, const Shape &shape) JS_ASSERT(shape.methodObject() == prev.toObject()); JS_ASSERT(canHaveMethodBarrier()); JS_ASSERT(hasMethodBarrier()); - JS_ASSERT(!shape.rawSetter); + JS_ASSERT(!shape.setter()); #endif /* - * Pass null to make a stub getter, but pass along shape.rawSetter to + * Pass null to make a stub getter, but pass along shape.setter() to * preserve watchpoints. Clear Shape::METHOD from flags as we are * despecializing from a method memoized in the property tree to a * plain old function-valued property. */ - result = putProperty(cx, shape.propid, NULL, shape.rawSetter, shape.slot, + result = putProperty(cx, shape.propid, NULL, shape.setter(), shape.slot, shape.attrs, shape.getFlags() & ~Shape::METHOD, shape.shortid); diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 3494111b8d20..b29701ebfbda 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -330,7 +330,7 @@ struct Shape : public js::gc::Cell inline void freeTable(JSContext *cx); - jsid propid; + HeapId propid; protected: union { @@ -358,26 +358,27 @@ struct Shape : public js::gc::Cell int16 shortid; /* tinyid, or local arg/var index */ protected: - mutable js::Shape *parent; /* parent node, reverse for..in order */ + mutable HeapPtrShape parent; /* parent node, reverse for..in order */ /* kids is valid when !inDictionary(), listp is valid when inDictionary(). */ union { mutable js::KidsPointer kids; /* null, single child, or a tagged ptr to many-kids data structure */ - mutable js::Shape **listp; /* dictionary list starting at lastProp + mutable HeapPtrShape *listp; /* dictionary list starting at lastProp has a double-indirect back pointer, either to shape->parent if not last, else to obj->lastProp */ }; - static inline js::Shape **search(JSContext *cx, js::Shape **startp, jsid id, + static inline js::Shape **search(JSContext *cx, HeapPtr *startp, jsid id, bool adding = false); - static js::Shape *newDictionaryShape(JSContext *cx, const js::Shape &child, js::Shape **listp); - static js::Shape *newDictionaryList(JSContext *cx, js::Shape **listp); + static js::Shape *newDictionaryShape(JSContext *cx, const js::Shape &child, + HeapPtr *listp); + static js::Shape *newDictionaryList(JSContext *cx, HeapPtr *listp); inline void removeFromDictionary(JSObject *obj) const; - inline void insertIntoDictionary(js::Shape **dictp); + inline void insertIntoDictionary(HeapPtr *dictp); - js::Shape *getChild(JSContext *cx, const js::Shape &child, js::Shape **listp); + js::Shape *getChild(JSContext *cx, const js::Shape &child, HeapPtr *listp); bool hashify(JSContext *cx); @@ -574,6 +575,8 @@ struct Shape : public js::gc::Cell return hasSetterValue() && setterObj ? js::ObjectValue(*setterObj) : js::UndefinedValue(); } + void update(js::PropertyOp getter, js::StrictPropertyOp setter, uint8 attrs); + inline JSDHashNumber hash() const; inline bool matches(const js::Shape *p) const; inline bool matchesParamsAfterId(PropertyOp agetter, StrictPropertyOp asetter, @@ -647,6 +650,16 @@ struct Shape : public js::gc::Cell void finalize(JSContext *cx); void removeChild(js::Shape *child); + + inline static void writeBarrierPre(const js::Shape *shape); + inline static void writeBarrierPost(const js::Shape *shape, void *addr); + + /* + * All weak references need a read barrier for incremental GC. This getter + * method implements the read barrier. It's used to obtain initial shapes + * from the compartment. + */ + inline static void readBarrier(const js::Shape *shape); }; struct EmptyShape : public js::Shape @@ -662,18 +675,10 @@ struct EmptyShape : public js::Shape return new (eprop) EmptyShape(cx->compartment, clasp); } - static EmptyShape *ensure(JSContext *cx, js::Class *clasp, EmptyShape **shapep) { - EmptyShape *shape = *shapep; - if (!shape) { - if (!(shape = create(cx, clasp))) - return NULL; - return *shapep = shape; - } - return shape; - } + static inline EmptyShape *ensure(JSContext *cx, js::Class *clasp, + ReadBarriered *shapep); static inline EmptyShape *getEmptyArgumentsShape(JSContext *cx); - static inline EmptyShape *getEmptyBlockShape(JSContext *cx); static inline EmptyShape *getEmptyCallShape(JSContext *cx); static inline EmptyShape *getEmptyDeclEnvShape(JSContext *cx); @@ -730,7 +735,7 @@ namespace js { * |emptyShape| is the EmptyShape at the start of the shape lineage. */ JS_ALWAYS_INLINE js::Shape ** -Shape::search(JSContext *cx, js::Shape **startp, jsid id, bool adding) +Shape::search(JSContext *cx, HeapPtr *startp, jsid id, bool adding) { js::Shape *start = *startp; if (start->hasTable()) @@ -757,12 +762,12 @@ Shape::search(JSContext *cx, js::Shape **startp, jsid id, bool adding) * the end). This avoids an extra load per iteration at the cost (if the * search fails) of an extra load and id test at the end. */ - js::Shape **spp; + HeapPtr *spp; for (spp = startp; js::Shape *shape = *spp; spp = &shape->parent) { - if (shape->propid == id) - return spp; + if (shape->propid.get() == id) + return spp->unsafeGet(); } - return spp; + return spp->unsafeGet(); } } // namespace js diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 26bb1a614bf7..5ad2afb8e847 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -49,6 +49,7 @@ #include "jsobj.h" #include "jsscope.h" #include "jsgc.h" +#include "jsgcmark.h" #include "vm/ArgumentsObject.h" #include "vm/StringObject.h" @@ -79,12 +80,12 @@ js::types::TypeObject::getEmptyShape(JSContext *cx, js::Class *aclasp, */ JS_ASSERT(this == proto->newType); - JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST); + JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind < js::gc::FINALIZE_OBJECT_LIMIT); int i = kind - js::gc::FINALIZE_OBJECT0; if (!emptyShapes) { - emptyShapes = (js::EmptyShape**) - cx->calloc_(sizeof(js::EmptyShape*) * js::gc::FINALIZE_FUNCTION_AND_OBJECT_LAST); + emptyShapes = (js::HeapPtr*) + cx->calloc_(sizeof(js::HeapPtr) * js::gc::FINALIZE_OBJECT_LIMIT); if (!emptyShapes) return NULL; @@ -92,7 +93,7 @@ js::types::TypeObject::getEmptyShape(JSContext *cx, js::Class *aclasp, * Always fill in emptyShapes[0], so canProvideEmptyShape works. * Other empty shapes are filled in lazily. */ - emptyShapes[0] = js::EmptyShape::create(cx, aclasp); + emptyShapes[0].init(js::EmptyShape::create(cx, aclasp)); if (!emptyShapes[0]) { cx->free_(emptyShapes); emptyShapes = NULL; @@ -103,7 +104,7 @@ js::types::TypeObject::getEmptyShape(JSContext *cx, js::Class *aclasp, JS_ASSERT(aclasp == emptyShapes[0]->getClass()); if (!emptyShapes[i]) { - emptyShapes[i] = js::EmptyShape::create(cx, aclasp); + emptyShapes[i].init(js::EmptyShape::create(cx, aclasp)); if (!emptyShapes[i]) return NULL; } @@ -154,15 +155,16 @@ StringObject::init(JSContext *cx, JSString *str) { JS_ASSERT(nativeEmpty()); - const Shape **shapep = &cx->compartment->initialStringShape; - if (*shapep) { - setLastProperty(*shapep); + const Shape *shape = cx->compartment->initialStringShape; + if (shape) { + setLastProperty(shape); } else { - *shapep = assignInitialShape(cx); - if (!*shapep) + shape = assignInitialShape(cx); + if (!shape) return false; + cx->compartment->initialStringShape = shape; } - JS_ASSERT(*shapep == lastProperty()); + JS_ASSERT(shape == lastProperty()); JS_ASSERT(!nativeEmpty()); JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))->slot == LENGTH_SLOT); @@ -232,15 +234,15 @@ Shape::hash() const /* Accumulate from least to most random so the low bits are most random. */ JS_ASSERT_IF(isMethod(), !rawSetter); - if (rawGetter) - hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawGetter); - if (rawSetter) - hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawSetter); + if (getter()) + hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(getter()); + if (setter()) + hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(setter()); hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & PUBLIC_FLAGS); hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs; hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid; hash = JS_ROTATE_LEFT32(hash, 4) ^ slot; - hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(propid); + hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(propid.get()); return hash; } @@ -249,8 +251,8 @@ Shape::matches(const js::Shape *other) const { JS_ASSERT(!JSID_IS_VOID(propid)); JS_ASSERT(!JSID_IS_VOID(other->propid)); - return propid == other->propid && - matchesParamsAfterId(other->rawGetter, other->rawSetter, other->slot, other->attrs, + return propid.get() == other->propid.get() && + matchesParamsAfterId(other->getter(), other->setter(), other->slot, other->attrs, other->flags, other->shortid); } @@ -259,8 +261,8 @@ Shape::matchesParamsAfterId(PropertyOp agetter, StrictPropertyOp asetter, uint32 uintN aattrs, uintN aflags, intN ashortid) const { JS_ASSERT(!JSID_IS_VOID(propid)); - return rawGetter == agetter && - rawSetter == asetter && + return getter() == agetter && + setter() == asetter && slot == aslot && attrs == aattrs && ((flags ^ aflags) & PUBLIC_FLAGS) == 0 && @@ -333,7 +335,7 @@ Shape::removeFromDictionary(JSObject *obj) const } inline void -Shape::insertIntoDictionary(js::Shape **dictp) +Shape::insertIntoDictionary(HeapPtr *dictp) { /* * Don't assert inDictionaryMode() here because we may be called from @@ -361,6 +363,18 @@ EmptyShape::EmptyShape(JSCompartment *comp, js::Class *aclasp) : js::Shape(comp, aclasp) {} +/* static */ inline EmptyShape * +EmptyShape::ensure(JSContext *cx, js::Class *clasp, ReadBarriered *shapep) +{ + EmptyShape *shape = shapep->get(); + if (!shape) { + if (!(shape = create(cx, clasp))) + return NULL; + shapep->set(shape); + } + return shape; +} + /* static */ inline EmptyShape * EmptyShape::getEmptyArgumentsShape(JSContext *cx) { @@ -397,6 +411,34 @@ EmptyShape::getEmptyWithShape(JSContext *cx) return ensure(cx, &WithClass, &cx->compartment->emptyWithShape); } +inline void +Shape::writeBarrierPre(const js::Shape *shape) +{ +#ifdef JSGC_INCREMENTAL + if (!shape || shape == &sharedNonNative) + return; + + JSCompartment *comp = shape->compartment(); + if (comp->needsBarrier()) + MarkShapeUnbarriered(comp->barrierTracer(), shape, "write barrier"); +#endif +} + +inline void +Shape::writeBarrierPost(const js::Shape *shape, void *addr) +{ +} + +inline void +Shape::readBarrier(const js::Shape *shape) +{ +#ifdef JSGC_INCREMENTAL + JSCompartment *comp = shape->compartment(); + if (comp->needsBarrier()) + MarkShapeUnbarriered(comp->barrierTracer(), shape, "read barrier"); +#endif +} + } /* namespace js */ #endif /* jsscopeinlines_h___ */ diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 7d1a2b0611d2..49e1059e5622 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -91,7 +91,7 @@ Bindings::lookup(JSContext *cx, JSAtom *name, uintN *indexp) const return NONE; Shape *shape = - SHAPE_FETCH(Shape::search(cx, const_cast(&lastBinding), + SHAPE_FETCH(Shape::search(cx, const_cast *>(&lastBinding), ATOM_TO_JSID(name))); if (!shape) return NONE; @@ -195,7 +195,7 @@ Bindings::getLocalNameArray(JSContext *cx, Vector *namesp) names[i] = POISON; #endif - for (Shape::Range r = lastBinding; !r.empty(); r.popFront()) { + for (Shape::Range r = lastBinding->all(); !r.empty(); r.popFront()) { const Shape &shape = r.front(); uintN index = uint16(shape.shortid); @@ -644,7 +644,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp) * to restore the parent chain. */ for (i = 0; i != nobjects; ++i) { - JSObject **objp = &script->objects()->vector[i]; + HeapPtr *objp = &script->objects()->vector[i]; uint32 isBlock; if (xdr->mode == JSXDR_ENCODE) { Class *clasp = (*objp)->getClass(); @@ -654,22 +654,26 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp) } if (!JS_XDRUint32(xdr, &isBlock)) goto error; + JSObject *tmp = *objp; if (isBlock == 0) { - if (!js_XDRFunctionObject(xdr, objp)) + if (!js_XDRFunctionObject(xdr, &tmp)) goto error; } else { JS_ASSERT(isBlock == 1); - if (!js_XDRBlockObject(xdr, objp)) + if (!js_XDRBlockObject(xdr, &tmp)) goto error; } + *objp = tmp; } for (i = 0; i != nupvars; ++i) { if (!JS_XDRUint32(xdr, reinterpret_cast(&script->upvars()->vector[i]))) goto error; } for (i = 0; i != nregexps; ++i) { - if (!js_XDRRegExpObject(xdr, &script->regexps()->vector[i])) + JSObject *tmp = script->regexps()->vector[i]; + if (!js_XDRRegExpObject(xdr, &tmp)) goto error; + script->regexps()->vector[i] = tmp; } for (i = 0; i != nClosedArgs; ++i) { if (!JS_XDRUint32(xdr, &script->closedSlots[i])) @@ -712,8 +716,10 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp) } for (i = 0; i != nconsts; ++i) { - if (!JS_XDRValue(xdr, &script->consts()->vector[i])) + Value tmp = script->consts()->vector[i]; + if (!JS_XDRValue(xdr, &tmp)) goto error; + script->consts()->vector[i] = tmp; } xdr->script = oldscript; @@ -748,6 +754,7 @@ JSPCCounters::destroy(JSContext *cx) } } + /* * Shared script filename management. */ @@ -988,7 +995,7 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom if (nconsts != 0) { JS_ASSERT(reinterpret_cast(cursor) % sizeof(jsval) == 0); script->consts()->length = nconsts; - script->consts()->vector = reinterpret_cast(cursor); + script->consts()->vector = (HeapValue *)cursor; cursor += nconsts * sizeof(script->consts()->vector[0]); } @@ -1000,13 +1007,13 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom if (nobjects != 0) { script->objects()->length = nobjects; - script->objects()->vector = reinterpret_cast(cursor); + script->objects()->vector = (HeapPtr *)cursor; cursor += nobjects * sizeof(script->objects()->vector[0]); } if (nregexps != 0) { script->regexps()->length = nregexps; - script->regexps()->vector = reinterpret_cast(cursor); + script->regexps()->vector = (HeapPtr *)cursor; cursor += nregexps * sizeof(script->regexps()->vector[0]); } @@ -1202,14 +1209,14 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce) return NULL; fun->setScript(script); - script->u.globalObject = fun->getParent() ? fun->getParent()->getGlobal() : NULL; + script->globalObject = fun->getParent() ? fun->getParent()->getGlobal() : NULL; } else { /* * Initialize script->object, if necessary, so that the debugger has a * valid holder object. */ if (bce->flags & TCF_NEED_SCRIPT_GLOBAL) - script->u.globalObject = GetCurrentGlobal(cx); + script->globalObject = GetCurrentGlobal(cx); } /* Tell the debugger about this compiled script. */ @@ -1217,7 +1224,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce) if (!bce->parent) { GlobalObject *compileAndGoGlobal = NULL; if (script->compileAndGo) { - compileAndGoGlobal = script->u.globalObject; + compileAndGoGlobal = script->globalObject; if (!compileAndGoGlobal) compileAndGoGlobal = bce->scopeChain()->getGlobal(); } diff --git a/js/src/jsscript.h b/js/src/jsscript.h index c7c56a4bb2a3..df6898df59ac 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -49,6 +49,8 @@ #include "jsclist.h" #include "jsinfer.h" +#include "gc/Barrier.h" + /* * Type of try note associated with each catch or finally block, and also with * for-in loops. @@ -132,7 +134,7 @@ typedef struct JSTryNoteArray { } JSTryNoteArray; typedef struct JSObjectArray { - JSObject **vector; /* array of indexed objects */ + js::HeapPtrObject *vector; /* array of indexed objects */ uint32 length; /* count of indexed objects */ } JSObjectArray; @@ -142,7 +144,7 @@ typedef struct JSUpvarArray { } JSUpvarArray; typedef struct JSConstArray { - js::Value *vector; /* array of indexed constant values */ + js::HeapValue *vector; /* array of indexed constant values */ uint32 length; } JSConstArray; @@ -168,17 +170,15 @@ enum BindingKind { NONE, ARGUMENT, VARIABLE, CONSTANT, UPVAR }; * strict mode eval code, to give such code its own lexical environment). */ class Bindings { - js::Shape *lastBinding; + HeapPtr lastBinding; uint16 nargs; uint16 nvars; uint16 nupvars; bool hasExtensibleParents; public: - inline Bindings(JSContext *cx) - : lastBinding(NULL), nargs(0), nvars(0), nupvars(0), hasExtensibleParents(false) - { - } + inline Bindings(JSContext *cx); + inline ~Bindings(); /* * Transfers ownership of bindings data from bindings into this fresh @@ -556,23 +556,21 @@ struct JSScript : public js::gc::Cell { JSPrincipals *principals;/* principals for this script */ jschar *sourceMap; /* source map file or null */ - union { - /* - * A global object for the script. - * - All scripts returned by JSAPI functions (JS_CompileScript, - * JS_CompileFile, etc.) have a non-null globalObject. - * - A function script has a globalObject if the function comes from a - * compile-and-go script. - * - Temporary scripts created by obj_eval, JS_EvaluateScript, and - * similar functions never have the globalObject field set; for such - * scripts the global should be extracted from the JS frame that - * execute scripts. - */ - js::GlobalObject *globalObject; + /* + * A global object for the script. + * - All scripts returned by JSAPI functions (JS_CompileScript, + * JS_CompileFile, etc.) have a non-null globalObject. + * - A function script has a globalObject if the function comes from a + * compile-and-go script. + * - Temporary scripts created by obj_eval, JS_EvaluateScript, and + * similar functions never have the globalObject field set; for such + * scripts the global should be extracted from the JS frame that + * execute scripts. + */ + js::HeapPtr globalObject; - /* Hash table chaining for JSCompartment::evalCache. */ - JSScript *evalHashLink; - } u; + /* Hash table chaining for JSCompartment::evalCache. */ + JSScript *&evalHashLink() { return *globalObject.unsafeGetUnioned(); } uint32 *closedSlots; /* vector of closed slots; args first, then vars. */ @@ -634,7 +632,7 @@ struct JSScript : public js::gc::Cell { /* Return creation time global or null. */ js::GlobalObject *getGlobalObjectOrNull() const { - return isCachedEval ? NULL : u.globalObject; + return isCachedEval ? NULL : globalObject.get(); } private: @@ -818,6 +816,9 @@ struct JSScript : public js::gc::Cell { #endif void finalize(JSContext *cx); + + static inline void writeBarrierPre(JSScript *script); + static inline void writeBarrierPost(JSScript *script, void *addr); }; JS_STATIC_ASSERT(sizeof(JSScript) % js::gc::Cell::CellSize == 0); diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h index 4eaa0f5db024..e2db5d2d0475 100644 --- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=79 ft=cpp: * * ***** BEGIN LICENSE BLOCK ***** @@ -55,6 +55,17 @@ namespace js { +inline +Bindings::Bindings(JSContext *cx) + : nargs(0), nvars(0), nupvars(0), hasExtensibleParents(false) +{ +} + +inline +Bindings::~Bindings() +{ +} + inline void Bindings::transfer(JSContext *cx, Bindings *bindings) { @@ -215,4 +226,24 @@ JSScript::clearNesting() } } +inline void +JSScript::writeBarrierPre(JSScript *script) +{ +#ifdef JSGC_INCREMENTAL + if (!script) + return; + + JSCompartment *comp = script->compartment(); + if (comp->needsBarrier()) { + JS_ASSERT(!comp->rt->gcRunning); + MarkScriptUnbarriered(comp->barrierTracer(), script, "write barrier"); + } +#endif +} + +inline void +JSScript::writeBarrierPost(JSScript *script, void *addr) +{ +} + #endif /* jsscriptinlines_h___ */ diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index ac45a6b9313c..148690698637 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1883,7 +1883,7 @@ public: {} JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { JSValueType type = getCoercedType(*vp); if (type == JSVAL_TYPE_INT32 && (!mOracle || mOracle->isGlobalSlotUndemotable(mCx, slot))) type = JSVAL_TYPE_DOUBLE; @@ -2475,6 +2475,13 @@ TraceRecorder::w_immpIdGC(jsid id) ptrdiff_t TraceRecorder::nativeGlobalSlot(const Value* p) const +{ + JS_ASSERT(isGlobal(p)); + return ptrdiff_t(p - Valueify(globalObj->slots) + globalObj->numFixedSlots()); +} + +ptrdiff_t +TraceRecorder::nativeGlobalSlot(const HeapValue* p) const { JS_ASSERT(isGlobal(p)); return ptrdiff_t(p - globalObj->slots + globalObj->numFixedSlots()); @@ -2491,7 +2498,15 @@ TraceRecorder::nativeGlobalOffset(const Value* p) const bool TraceRecorder::isGlobal(const Value* p) const { - return (size_t(p - globalObj->slots) < globalObj->numSlots() - globalObj->numFixedSlots()); + return (size_t(p - Valueify(globalObj->slots)) < + globalObj->numSlots() - globalObj->numFixedSlots()); +} + +bool +TraceRecorder::isGlobal(const HeapValue* p) const +{ + return (size_t(p - globalObj->slots) < + globalObj->numSlots() - globalObj->numFixedSlots()); } bool @@ -2719,7 +2734,7 @@ HasUnreachableGCThings(JSContext *cx, TreeFragment *f) for (unsigned len = f->gcthings.length(); len; --len) { Value &v = *vp++; JS_ASSERT(v.isMarkable()); - if (IsAboutToBeFinalized(cx, v.toGCThing())) + if (IsAboutToBeFinalized(cx, v)) return true; } const Shape** shapep = f->shapes.data(); @@ -2861,31 +2876,46 @@ TraceMonitor::mark(JSTracer *trc) TracerState* state = tracerState; while (state) { if (state->nativeVp) - MarkValueRange(trc, state->nativeVpLen, state->nativeVp, "nativeVp"); + MarkRootRange(trc, state->nativeVpLen, state->nativeVp, "nativeVp"); state = state->prev; } } +template +static void +SetValue(JSCompartment *comp, VALUE& dst, const Value &src) +{ + dst = src; +} + +template<> +void +SetValue(JSCompartment *comp, HeapValue& dst, const Value &src) +{ + dst.set(comp, src); +} + /* * Box a value from the native stack back into the Value format. */ +template static inline void -NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot) +NativeToValue(JSContext* cx, VALUE& v, JSValueType type, double* slot) { if (type == JSVAL_TYPE_DOUBLE) { - v = NumberValue(*slot); + SetValue(cx->compartment, v, NumberValue(*slot)); } else if (JS_LIKELY(type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET)) { v.boxNonDoubleFrom(type, (uint64 *)slot); } else if (type == JSVAL_TYPE_STRORNULL) { JSString *str = *(JSString **)slot; - v = str ? StringValue(str) : NullValue(); + SetValue(cx->compartment, v, str ? StringValue(str) : NullValue()); } else if (type == JSVAL_TYPE_OBJORNULL) { JSObject *obj = *(JSObject **)slot; - v = obj ? ObjectValue(*obj) : NullValue(); + SetValue(cx->compartment, v, obj ? ObjectValue(*obj) : NullValue()); } else { JS_ASSERT(type == JSVAL_TYPE_BOXED); JS_STATIC_ASSERT(sizeof(Value) == sizeof(double)); - v = *(Value *)slot; + SetValue(cx->compartment, v, *(Value *)slot); } #ifdef DEBUG @@ -2974,7 +3004,7 @@ public: {} JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { debug_only_printf(LC_TMTracer, "global%d: ", n); ValueToNative(*vp, *mTypeMap++, &mGlobal[slot]); } @@ -3038,7 +3068,7 @@ public: {} JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { debug_only_printf(LC_TMTracer, "global%d=", n); JS_ASSERT(JS_THREAD_DATA(mCx)->waiveGCQuota); NativeToValue(mCx, *vp, *mTypeMap++, &mGlobal[slot]); @@ -3840,6 +3870,12 @@ TraceRecorder::get(const Value *p) return getImpl(p); } +JS_REQUIRES_STACK LIns* +TraceRecorder::get(const HeapValue *p) +{ + return getImpl(p); +} + #ifdef DEBUG bool TraceRecorder::isValidFrameObjPtr(void *p) @@ -3896,17 +3932,17 @@ JS_REQUIRES_STACK void TraceRecorder::checkForGlobalObjectReallocationHelper() { debug_only_print0(LC_TMTracer, "globalObj->slots relocated, updating tracker\n"); - const Value* src = global_slots; - const Value* dst = globalObj->getRawSlots(); + const HeapValue* src = global_slots; + const HeapValue* dst = globalObj->getRawSlots(); jsuint length = globalObj->capacity; LIns** map = (LIns**)alloca(sizeof(LIns*) * length); for (jsuint n = 0; n < length; ++n) { - const Value *slot = globalObj->getRawSlot(n, src); + const HeapValue *slot = globalObj->getRawSlot(n, src); map[n] = tracker.get(slot); tracker.set(slot, NULL); } for (jsuint n = 0; n < length; ++n) { - const Value *slot = globalObj->getRawSlot(n, dst); + const HeapValue *slot = globalObj->getRawSlot(n, dst); tracker.set(slot, map[n]); } global_slots = globalObj->getRawSlots(); @@ -3951,12 +3987,12 @@ public: } JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { LIns *ins = mRecorder.get(vp); bool isPromote = IsPromotedInt32(ins); if (isPromote && *mTypeMap == JSVAL_TYPE_DOUBLE) { mRecorder.w.st(mRecorder.get(vp), - EosAddress(mRecorder.eos_ins, mRecorder.nativeGlobalOffset(vp))); + EosAddress(mRecorder.eos_ins, mRecorder.nativeGlobalOffset(&vp->get()))); /* * Aggressively undo speculation so the inner tree will compile * if this fails. @@ -4039,7 +4075,7 @@ TraceRecorder::adjustCallerTypes(TreeFragment* f) } JS_REQUIRES_STACK inline JSValueType -TraceRecorder::determineSlotType(Value* vp) +TraceRecorder::determineSlotType(const Value* vp) { if (vp->isNumber()) { LIns *i = getFromTracker(vp); @@ -4074,8 +4110,8 @@ public: {} JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { - *mTypeMap++ = mRecorder.determineSlotType(vp); + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { + *mTypeMap++ = mRecorder.determineSlotType(&vp->get()); } JS_REQUIRES_STACK JS_ALWAYS_INLINE bool @@ -4528,7 +4564,7 @@ class SlotMap : public SlotVisitorBase SlotInfo() : vp(NULL), isPromotedInt32(false), lastCheck(TypeCheck_Bad) {} - SlotInfo(Value* vp, bool isPromotedInt32) + SlotInfo(const Value* vp, bool isPromotedInt32) : vp(vp), isPromotedInt32(isPromotedInt32), lastCheck(TypeCheck_Bad), type(getCoercedType(*vp)) {} @@ -4538,7 +4574,7 @@ class SlotMap : public SlotVisitorBase SlotInfo(Value* vp, JSValueType t) : vp(vp), isPromotedInt32(t == JSVAL_TYPE_INT32), lastCheck(TypeCheck_Bad), type(t) {} - void *vp; + const void *vp; bool isPromotedInt32; TypeCheckResult lastCheck; JSValueType type; @@ -4556,9 +4592,9 @@ class SlotMap : public SlotVisitorBase } JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { - addSlot(vp); + addSlot(&vp->get()); } JS_ALWAYS_INLINE SlotMap::SlotInfo& @@ -4610,7 +4646,7 @@ class SlotMap : public SlotVisitorBase } JS_REQUIRES_STACK JS_ALWAYS_INLINE void - addSlot(Value* vp) + addSlot(const Value* vp) { bool isPromotedInt32 = false; if (vp->isNumber()) { @@ -6137,7 +6173,7 @@ public: {} JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { debug_only_printf(LC_TMTracer, "global%d=", n); if (!IsEntryTypeCompatible(*vp, *mTypeMap)) { mOk = false; @@ -6242,7 +6278,7 @@ public: } JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { + visitGlobalSlot(HeapValue *vp, unsigned n, unsigned slot) { if (mOk) checkSlot(*vp, "global", n); } @@ -6478,6 +6514,8 @@ ExecuteTree(JSContext* cx, TraceMonitor* tm, TreeFragment* f, #endif JS_ASSERT(f->root == f && f->code()); + JS_ASSERT(!cx->compartment->needsBarrier()); + if (!ScopeChainCheck(cx, f) || !cx->stack.space().ensureEnoughSpaceToEnterTrace(cx)) { *lrp = NULL; @@ -6932,6 +6970,9 @@ RecordLoopEdge(JSContext* cx, TraceMonitor* tm) TraceVisStateObj tvso(cx, S_MONITOR); #endif + if (cx->compartment->needsBarrier()) + return MONITOR_NOT_RECORDING; + /* Is the recorder currently active? */ if (tm->recorder) { tm->recorder->assertInsideLoop(); @@ -12036,7 +12077,7 @@ TraceRecorder::nativeSet(JSObject* obj, LIns* obj_ins, const Shape* shape, if (obj == globalObj) { if (!lazilyImportGlobalSlot(slot)) RETURN_STOP("lazy import of global slot failed"); - set(&obj->getSlotRef(slot), v_ins); + set(&obj->getSlot(slot), v_ins); } else { LIns* slots_ins = NULL; stobj_set_slot(obj, obj_ins, slot, slots_ins, v, v_ins); @@ -13015,7 +13056,7 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) if (!idx.isPrimitive()) RETURN_STOP_A("non-primitive index"); CHECK_STATUS_A(initOrSetPropertyByName(obj_ins, &idx, &v, - *cx->regs().pc == JSOP_INITELEM)); + *cx->regs().pc == JSOP_INITELEM)); } else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) { // Fast path: assigning to element of typed array. VMSideExit* branchExit = snapshot(BRANCH_EXIT); @@ -13843,7 +13884,7 @@ TraceRecorder::name(const Value*& vp, LIns*& ins, NameResult& nr) if (!lazilyImportGlobalSlot(slot)) RETURN_STOP_A("lazy import of global slot failed"); - vp = &obj->getSlotRef(slot); + vp = &obj->getSlot(slot); ins = get(vp); nr.tracked = true; return ARECORD_CONTINUE; @@ -16366,6 +16407,9 @@ class AutoRetBlacklist JS_REQUIRES_STACK TracePointAction RecordTracePoint(JSContext* cx, TraceMonitor* tm, bool* blacklist, bool execAllowed) { + if (cx->compartment->needsBarrier()) + return TPA_Nothing; + StackFrame* fp = cx->fp(); jsbytecode* pc = cx->regs().pc; diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 381d15fa4431..6caafffd7962 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1062,14 +1062,14 @@ class TraceRecorder Tracker nativeFrameTracker; /* The start of the global object's slots we assume for the trackers. */ - const Value* global_slots; + const HeapValue* global_slots; /* The number of interpreted calls entered (and not yet left) since recording began. */ unsigned callDepth; /* The current atom table, mirroring the interpreter loop's variable of the same name. */ JSAtom** atoms; - Value* consts; + HeapValue* consts; /* An instruction yielding the current script's strict mode code flag. */ nanojit::LIns* strictModeCode_ins; @@ -1185,7 +1185,9 @@ class TraceRecorder bool isVoidPtrGlobal(const void* p) const; bool isGlobal(const Value* p) const; + bool isGlobal(const HeapValue* p) const; ptrdiff_t nativeGlobalSlot(const Value *p) const; + ptrdiff_t nativeGlobalSlot(const HeapValue *p) const; ptrdiff_t nativeGlobalOffset(const Value* p) const; JS_REQUIRES_STACK ptrdiff_t nativeStackOffsetImpl(const void* p) const; JS_REQUIRES_STACK ptrdiff_t nativeStackOffset(const Value* p) const; @@ -1228,6 +1230,7 @@ class TraceRecorder nanojit::LIns* getFromTracker(const Value* p); JS_REQUIRES_STACK nanojit::LIns* getImpl(const void* p); JS_REQUIRES_STACK nanojit::LIns* get(const Value* p); + JS_REQUIRES_STACK nanojit::LIns* get(const HeapValue* p); JS_REQUIRES_STACK nanojit::LIns* getFrameObjPtr(void* p); JS_REQUIRES_STACK nanojit::LIns* attemptImport(const Value* p); JS_REQUIRES_STACK nanojit::LIns* addr(Value* p); @@ -1528,7 +1531,7 @@ class TraceRecorder JS_REQUIRES_STACK jsatomid getFullIndex(ptrdiff_t pcoff = 0); - JS_REQUIRES_STACK JSValueType determineSlotType(Value* vp); + JS_REQUIRES_STACK JSValueType determineSlotType(const Value* vp); JS_REQUIRES_STACK RecordingStatus setUpwardTrackedVar(Value* stackVp, const Value& v, nanojit::LIns* v_ins); @@ -1616,7 +1619,7 @@ class TraceRecorder * Do slot arithmetic manually to avoid getSlotRef assertions which * do not need to be satisfied for this purpose. */ - const Value *vp = globalObj->getRawSlot(slot, globalObj->getRawSlots()); + const HeapValue *vp = globalObj->getRawSlot(slot, globalObj->getRawSlots()); /* If this global is definitely being tracked, then the write is unexpected. */ if (tracker.has(vp)) diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 0ed6c5e94c38..a329186f3862 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -164,8 +164,8 @@ JSObject::allocateArrayBufferSlots(JSContext *cx, uint32 size) JS_ASSERT(isArrayBuffer() && !hasSlotsArray()); uint32 bytes = size + sizeof(Value); - if (size > sizeof(Value) * ARRAYBUFFER_RESERVED_SLOTS - sizeof(Value) ) { - Value *tmpslots = (Value *)cx->calloc_(bytes); + if (size > sizeof(HeapValue) * ARRAYBUFFER_RESERVED_SLOTS - sizeof(HeapValue) ) { + HeapValue *tmpslots = (HeapValue *)cx->calloc_(bytes); if (!tmpslots) return false; slots = tmpslots; @@ -174,7 +174,7 @@ JSObject::allocateArrayBufferSlots(JSContext *cx, uint32 size) * |capacity * sizeof(Value)| may underestimate the size by up to * |sizeof(Value) - 1| bytes. */ - capacity = bytes / sizeof(Value); + capacity = bytes / sizeof(HeapValue); } else { slots = fixedSlots(); memset(slots, 0, bytes); @@ -232,9 +232,13 @@ ArrayBuffer::~ArrayBuffer() void ArrayBuffer::obj_trace(JSTracer *trc, JSObject *obj) { + /* + * If this object changes, it will get marked via the private data barrier, + * so it's safe to leave it Unbarriered. + */ JSObject *delegate = static_cast(obj->getPrivate()); if (delegate) - MarkObject(trc, *delegate, "arraybuffer.delegate"); + MarkObjectUnbarriered(trc, delegate, "arraybuffer.delegate"); } static JSProperty * const PROPERTY_FOUND = reinterpret_cast(1); @@ -995,9 +999,7 @@ class TypedArrayTemplate static void obj_trace(JSTracer *trc, JSObject *obj) { - JSObject *buffer = static_cast(getBuffer(obj)); - if (buffer) - MarkObject(trc, *buffer, "typedarray.buffer"); + MarkValue(trc, obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer"); } static JSBool diff --git a/js/src/jstypedarray.h b/js/src/jstypedarray.h index 4320edea10a6..f6e660a93a8c 100644 --- a/js/src/jstypedarray.h +++ b/js/src/jstypedarray.h @@ -43,6 +43,8 @@ #include "jsapi.h" #include "jsclass.h" +#include "gc/Barrier.h" + typedef struct JSProperty JSProperty; namespace js { diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp index 9c118a9f7729..d7e54a1f0038 100644 --- a/js/src/jswatchpoint.cpp +++ b/js/src/jswatchpoint.cpp @@ -48,7 +48,7 @@ using namespace js::gc; inline HashNumber DefaultHasher::hash(const Lookup &key) { - return DefaultHasher::hash(key.object) ^ HashId(key.id); + return DefaultHasher::hash(key.object.get()) ^ HashId(key.id.get()); } class AutoEntryHolder { @@ -177,7 +177,7 @@ WatchpointMap::triggerWatchpoint(JSContext *cx, JSObject *obj, jsid id, Value *v bool WatchpointMap::markAllIteratively(JSTracer *trc) { - JSRuntime *rt = trc->context->runtime; + JSRuntime *rt = trc->runtime; if (rt->gcCurrentCompartment) { WatchpointMap *wpmap = rt->gcCurrentCompartment->watchpointMap; return wpmap && wpmap->markIteratively(trc); @@ -201,16 +201,16 @@ WatchpointMap::markIteratively(JSTracer *trc) bool objectIsLive = !IsAboutToBeFinalized(cx, e.key.object); if (objectIsLive || e.value.held) { if (!objectIsLive) { - MarkObject(trc, *e.key.object, "held Watchpoint object"); + MarkObject(trc, e.key.object, "held Watchpoint object"); marked = true; } - jsid id = e.key.id; + const HeapId &id = e.key.id; JS_ASSERT(JSID_IS_STRING(id) || JSID_IS_INT(id)); MarkId(trc, id, "WatchKey::id"); if (e.value.closure && IsAboutToBeFinalized(cx, e.value.closure)) { - MarkObject(trc, *e.value.closure, "Watchpoint::closure"); + MarkObject(trc, e.value.closure, "Watchpoint::closure"); marked = true; } } diff --git a/js/src/jswatchpoint.h b/js/src/jswatchpoint.h index dd5b7d027db2..2bf8e9008213 100644 --- a/js/src/jswatchpoint.h +++ b/js/src/jswatchpoint.h @@ -44,6 +44,7 @@ #include "jsprvtd.h" #include "jsapi.h" +#include "gc/Barrier.h" #include "js/HashTable.h" namespace js { @@ -51,13 +52,14 @@ namespace js { struct WatchKey { WatchKey() {} WatchKey(JSObject *obj, jsid id) : object(obj), id(id) {} - JSObject *object; - jsid id; + WatchKey(const WatchKey &key) : object(key.object.get()), id(key.id.get()) {} + HeapPtrObject object; + HeapId id; }; struct Watchpoint { JSWatchPointHandler handler; - JSObject *closure; + HeapPtrObject closure; bool held; /* true if currently running handler */ }; @@ -67,7 +69,7 @@ struct DefaultHasher { static inline js::HashNumber hash(const Lookup &key); static bool match(const WatchKey &k, const Lookup &l) { - return k.object == l.object && k.id == l.id; + return k.object == l.object && k.id.get() == l.id.get(); } }; diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index 087fe8e19b2b..ac1faa2b8996 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -80,7 +80,7 @@ WeakMapBase::sweepAll(JSTracer *tracer) } /* namespace js */ -typedef WeakMap ObjectValueMap; +typedef WeakMap, HeapValue> ObjectValueMap; static ObjectValueMap * GetObjectMap(JSObject *obj) @@ -275,7 +275,7 @@ WeakMap_construct(JSContext *cx, uintN argc, Value *vp) if (!obj) return false; - obj->setPrivate(NULL); + obj->initPrivate(NULL); vp->setObject(*obj); return true; @@ -320,7 +320,7 @@ js_InitWeakMapClass(JSContext *cx, JSObject *obj) JSObject *weakMapProto = global->createBlankPrototype(cx, &WeakMapClass); if (!weakMapProto) return NULL; - weakMapProto->setPrivate(NULL); + weakMapProto->initPrivate(NULL); JSFunction *ctor = global->createConstructor(cx, WeakMap_construct, &WeakMapClass, CLASS_ATOM(cx, WeakMap), 0); diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 288de64fa15d..0ddaf0fe8726 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -80,59 +80,26 @@ namespace js { // - There is no AllocPolicy parameter; these are used with our garbage collector, so // RuntimeAllocPolicy is hard-wired. // -// - Optional fourth template parameter is a class MarkPolicy, with the following constructor: -// +// - Optional fourth and fifth parameters are the MarkPolicies for the key and value type. +// A MarkPolicy has the constructor: +// // MarkPolicy(JSTracer *) // // and the following member functions: // -// bool keyMarked(Key &k) -// bool valueMarked(Value &v) -// Return true if k/v has been marked as live by the garbage collector. +// bool isMarked(const Type &x) +// Return true if x has been marked as live by the garbage collector. // -// bool markEntryIfLive(Key &k, Value &v) -// If a table entry whose key is k should be retained, ensure its key and -// value are marked. Return true if any previously unmarked objects -// became marked. +// bool mark(const Type &x) +// Return false if x is already marked. Otherwise, mark x and return true. // -// To ensure that the WeakMap's behavior isn't visibly affected by -// garbage collection, this should leave k unmarked only when no key -// matching k could ever be produced after this GC cycle completes --- -// removing entries whose keys this function leaves unmarked should never -// make future lookups fail. -// -// A typical definition of markEntryIfLive would be: -// -// if (keyMarked(k) && !valueMarked(v)) { -// markObject(*v, "WeakMap entry value"); -// return true; -// } -// return false; -// -// This meets the above constraint when, for example, Key is JSObject *: -// if k isn't marked, it won't exist once the collection cycle completes, -// and thus can't be supplied as a key. -// -// Note that this may mark entries where keyMarked(k) is not initially -// true. For example, you could have a table whose keys match when the -// values of one of their properties are equal: k1.x === k2.x. An entry -// in such a table could be live even when its key is not marked. The -// markEntryIfLive function for such a table would generally mark both k and v. -// -// void markEntry(Value &v) -// Mark the table entry's value v as reachable by the collector. WeakMap -// uses this function for non-marking tracers: other code using the GC -// heap tracing functions to map the heap for some purpose or other. -// This provides a conservative approximation of the true reachability -// relation of the heap graph. -// -// If omitted, the MarkPolicy parameter defaults to js::DefaultMarkPolicy, a policy template with the obvious definitions for some typical +// If omitted, the MarkPolicy parameter defaults to js::DefaultMarkPolicy, +// a policy template with the obvious definitions for some typical // SpiderMonkey type combinations. // A policy template holding default marking algorithms for common type combinations. This // provides default types for WeakMap's MarkPolicy template parameter. -template class DefaultMarkPolicy; +template class DefaultMarkPolicy; // Common base class for all WeakMap specializations. The collector uses this to call // their markIteratively and sweep methods. @@ -188,7 +155,8 @@ class WeakMapBase { template , - class MarkPolicy = DefaultMarkPolicy > + class KeyMarkPolicy = DefaultMarkPolicy, + class ValueMarkPolicy = DefaultMarkPolicy > class WeakMap : public HashMap, public WeakMapBase { private: typedef HashMap Base; @@ -206,127 +174,121 @@ class WeakMap : public HashMap, publ } private: - void nonMarkingTrace(JSTracer *tracer) { - MarkPolicy t(tracer); + void nonMarkingTrace(JSTracer *trc) { + ValueMarkPolicy vp(trc); for (Range r = Base::all(); !r.empty(); r.popFront()) - t.markEntry(r.front().value); + vp.mark(r.front().value); } - bool markIteratively(JSTracer *tracer) { - MarkPolicy t(tracer); + bool markIteratively(JSTracer *trc) { + KeyMarkPolicy kp(trc); + ValueMarkPolicy vp(trc); bool markedAny = false; for (Range r = Base::all(); !r.empty(); r.popFront()) { + const Key &k = r.front().key; + const Value &v = r.front().value; /* If the entry is live, ensure its key and value are marked. */ - if (t.markEntryIfLive(r.front().key, r.front().value)) { - /* We revived a value with children, we have to iterate again. */ + if (kp.isMarked(k)) { + markedAny |= vp.mark(v); + } else if (kp.overrideKeyMarking(k)) { + // We always mark wrapped natives. This will cause leaks, but WeakMap+CC + // integration is currently busted anyways. When WeakMap+CC integration is + // fixed in Bug 668855, XPC wrapped natives should only be marked during + // non-BLACK marking (ie grey marking). + kp.mark(k); + vp.mark(v); markedAny = true; } - JS_ASSERT_IF(t.keyMarked(r.front().key), t.valueMarked(r.front().value)); + JS_ASSERT_IF(kp.isMarked(k), vp.isMarked(v)); } return markedAny; } - void sweep(JSTracer *tracer) { - MarkPolicy t(tracer); + void sweep(JSTracer *trc) { + KeyMarkPolicy kp(trc); /* Remove all entries whose keys remain unmarked. */ for (Enum e(*this); !e.empty(); e.popFront()) { - if (!t.keyMarked(e.front().key)) + if (!kp.isMarked(e.front().key)) e.removeFront(); } #if DEBUG - /* + ValueMarkPolicy vp(trc); + /* * Once we've swept, all remaining edges should stay within the * known-live part of the graph. */ for (Range r = Base::all(); !r.empty(); r.popFront()) { - JS_ASSERT(t.keyMarked(r.front().key)); - JS_ASSERT(t.valueMarked(r.front().value)); + JS_ASSERT(kp.isMarked(r.front().key)); + JS_ASSERT(vp.isMarked(r.front().value)); } #endif } }; -// Marking policy for maps from JSObject pointers to js::Values. -// -// We always mark wrapped natives. This will cause leaks, but WeakMap+CC -// integration is currently busted anyways. When WeakMap+CC integration is -// fixed in Bug 668855, XPC wrapped natives should only be marked during -// non-BLACK marking (ie grey marking). template <> -class DefaultMarkPolicy { +class DefaultMarkPolicy { private: JSTracer *tracer; public: DefaultMarkPolicy(JSTracer *t) : tracer(t) { } - bool keyMarked(JSObject *k) { return !IsAboutToBeFinalized(tracer->context, k); } - bool valueMarked(const Value &v) { - if (v.isMarkable()) - return !IsAboutToBeFinalized(tracer->context, v.toGCThing()); + bool isMarked(const HeapValue &x) { + if (x.isMarkable()) + return !IsAboutToBeFinalized(tracer->context, x); return true; } - private: - bool markUnmarkedValue(const Value &v) { - if (valueMarked(v)) + bool mark(const HeapValue &x) { + if (isMarked(x)) return false; - js::gc::MarkValue(tracer, v, "WeakMap entry value"); + js::gc::MarkValue(tracer, x, "WeakMap entry"); return true; } + bool overrideKeyMarking(const HeapValue &k) { return false; } +}; - // Return true if we should override the GC's default marking - // behavior for this key. - bool overrideKeyMarking(JSObject *k) { +template <> +class DefaultMarkPolicy { + private: + JSTracer *tracer; + public: + DefaultMarkPolicy(JSTracer *t) : tracer(t) { } + bool isMarked(const HeapPtrObject &x) { + return !IsAboutToBeFinalized(tracer->context, x); + } + bool mark(const HeapPtrObject &x) { + if (isMarked(x)) + return false; + js::gc::MarkObject(tracer, x, "WeakMap entry"); + return true; + } + bool overrideKeyMarking(const HeapPtrObject &k) { // We only need to worry about extra marking of keys when // we're doing a GC marking pass. if (!IS_GC_MARKING_TRACER(tracer)) return false; return k->getClass()->ext.isWrappedNative; } - public: - bool markEntryIfLive(JSObject *k, const Value &v) { - if (keyMarked(k)) - return markUnmarkedValue(v); - if (!overrideKeyMarking(k)) - return false; - js::gc::MarkObject(tracer, *k, "WeakMap entry wrapper key"); - markUnmarkedValue(v); - return true; - } - void markEntry(const Value &v) { - js::gc::MarkValue(tracer, v, "WeakMap entry value"); - } }; template <> -class DefaultMarkPolicy { - protected: +class DefaultMarkPolicy { + private: JSTracer *tracer; public: DefaultMarkPolicy(JSTracer *t) : tracer(t) { } - bool keyMarked(gc::Cell *k) { return !IsAboutToBeFinalized(tracer->context, k); } - bool valueMarked(JSObject *v) { return !IsAboutToBeFinalized(tracer->context, v); } - bool markEntryIfLive(gc::Cell *k, JSObject *v) { - if (keyMarked(k) && !valueMarked(v)) { - js::gc::MarkObject(tracer, *v, "WeakMap entry value"); - return true; - } - return false; + bool isMarked(const HeapPtrScript &x) { + return !IsAboutToBeFinalized(tracer->context, x); } - void markEntry(JSObject *v) { - js::gc::MarkObject(tracer, *v, "WeakMap entry value"); + bool mark(const HeapPtrScript &x) { + if (isMarked(x)) + return false; + js::gc::MarkScript(tracer, x, "WeakMap entry"); + return true; } + bool overrideKeyMarking(const HeapPtrScript &k) { return false; } }; -// A MarkPolicy for WeakMaps whose keys and values may be objects in arbitrary -// compartments within a runtime. -// -// With the current GC, the implementation turns out to be identical to the -// default mark policy. We give it a distinct name anyway, in case this ever -// changes. -// -typedef DefaultMarkPolicy CrossCompartmentMarkPolicy; - } extern JSObject * diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 4dea5be01989..0921b9cca05e 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -346,7 +346,7 @@ Wrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) void Wrapper::trace(JSTracer *trc, JSObject *wrapper) { - MarkObject(trc, *wrappedObject(wrapper), "wrappedObject"); + MarkValue(trc, wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "wrappedObject"); } JSObject * @@ -844,7 +844,8 @@ CrossCompartmentWrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType h void CrossCompartmentWrapper::trace(JSTracer *trc, JSObject *wrapper) { - MarkCrossCompartmentObject(trc, *wrappedObject(wrapper), "wrappedObject"); + MarkCrossCompartmentValue(trc, wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), + "wrappedObject"); } CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u); diff --git a/js/src/jsxdrapi.cpp b/js/src/jsxdrapi.cpp index d6ef5c68087f..dc6f8dc2f58d 100644 --- a/js/src/jsxdrapi.cpp +++ b/js/src/jsxdrapi.cpp @@ -739,7 +739,7 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp) if (xdr->mode == JSXDR_DECODE) { JS_ASSERT(!script->compileAndGo); - script->u.globalObject = GetCurrentGlobal(xdr->cx); + script->globalObject = GetCurrentGlobal(xdr->cx); js_CallNewScriptHook(xdr->cx, script, NULL); Debugger::onNewScript(xdr->cx, script, NULL); *scriptp = script; diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index bb69cbef9d22..8075d73cf867 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -78,6 +78,7 @@ #include "jsstrinlines.h" #include "vm/Stack-inl.h" +#include "vm/String-inl.h" #ifdef DEBUG #include /* for #ifdef DEBUG memset calls */ @@ -88,6 +89,19 @@ using namespace js; using namespace js::gc; using namespace js::types; +template +struct IdentityOp +{ + typedef JSBool (* compare)(const T *a, const U *b); +}; + +template +static JSBool +pointer_match(const T *a, const T *b) +{ + return a == b; +} + /* * NOTES * - in the js shell, you must use the -x command line option, or call @@ -302,7 +316,7 @@ DEFINE_GETTER(QNameLocalName_getter, *vp = obj->getQNameLocalNameVal()) static JSBool -qname_identity(JSObject *qna, JSObject *qnb) +qname_identity(JSObject *qna, const JSObject *qnb) { JSLinearString *uri1 = qna->getNameURI(); JSLinearString *uri2 = qnb->getNameURI(); @@ -839,10 +853,8 @@ QName(JSContext *cx, uintN argc, Value *vp) * XMLArray library functions. */ static JSBool -namespace_identity(const void *a, const void *b) +namespace_identity(const JSObject *nsa, const JSObject *nsb) { - const JSObject *nsa = (const JSObject *) a; - const JSObject *nsb = (const JSObject *) b; JSLinearString *prefixa = nsa->getNamePrefix(); JSLinearString *prefixb = nsb->getNamePrefix(); @@ -857,32 +869,51 @@ namespace_identity(const void *a, const void *b) } static JSBool -attr_identity(const void *a, const void *b) +attr_identity(const JSXML *xmla, const JSXML *xmlb) { - const JSXML *xmla = (const JSXML *) a; - const JSXML *xmlb = (const JSXML *) b; - return qname_identity(xmla->name, xmlb->name); } +template<> void -JSXMLArrayCursor::trace(JSTracer *trc) { -#ifdef DEBUG - size_t index = 0; -#endif - for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) - js::gc::MarkGCThing(trc, cursor->root, "cursor_root", index++); +JSXMLArrayCursor::trace(JSTracer *trc) +{ + for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) + MarkXML(trc, cursor->root, "cursor_root"); } +template<> +void +JSXMLArrayCursor::trace(JSTracer *trc) +{ + for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) + MarkObject(trc, cursor->root, "cursor_root"); +} + +template static void -XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor) +XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor) { cursor->trace(trc); } +template +static HeapPtr * +ReallocateVector(HeapPtr *vector, size_t count) +{ +#if JS_BITS_PER_WORD == 32 + if (count > ~(size_t)0 / sizeof(HeapPtr)) + return NULL; +#endif + + size_t size = count * sizeof(HeapPtr); + return (HeapPtr *) OffTheBooks::realloc_(vector, size); +} + /* NB: called with null cx from the GC, via xml_trace => JSXMLArray::trim. */ +template bool -JSXMLArray::setCapacity(JSContext *cx, uint32 newCapacity) +JSXMLArray::setCapacity(JSContext *cx, uint32 newCapacity) { if (newCapacity == 0) { /* We could let realloc(p, 0) free this, but purify gets confused. */ @@ -894,13 +925,8 @@ JSXMLArray::setCapacity(JSContext *cx, uint32 newCapacity) } vector = NULL; } else { - void **tmp; - - if ( -#if JS_BITS_PER_WORD == 32 - (size_t)newCapacity > ~(size_t)0 / sizeof(void *) || -#endif - !(tmp = (void **) OffTheBooks::realloc_(vector, newCapacity * sizeof(void *)))) { + HeapPtr *tmp = ReallocateVector(vector, newCapacity); + if (!tmp) { if (cx) JS_ReportOutOfMemory(cx); return false; @@ -911,8 +937,9 @@ JSXMLArray::setCapacity(JSContext *cx, uint32 newCapacity) return true; } +template void -JSXMLArray::trim() +JSXMLArray::trim() { if (capacity & JSXML_PRESET_CAPACITY) return; @@ -920,12 +947,19 @@ JSXMLArray::trim() setCapacity(NULL, length); } +template void -JSXMLArray::finish(JSContext *cx) +JSXMLArray::finish(JSContext *cx) { + if (!cx->runtime->gcRunning) { + /* We need to clear these to trigger a write barrier. */ + for (uint32 i = 0; i < length; i++) + vector[i].~HeapPtr(); + } + cx->free_(vector); - while (JSXMLArrayCursor *cursor = cursors) + while (JSXMLArrayCursor *cursor = cursors) cursor->disconnect(); #ifdef DEBUG @@ -935,24 +969,18 @@ JSXMLArray::finish(JSContext *cx) #define XML_NOT_FOUND ((uint32) -1) +template static uint32 -XMLArrayFindMember(const JSXMLArray *array, void *elt, JSIdentityOp identity) +XMLArrayFindMember(const JSXMLArray *array, U *elt, typename IdentityOp::compare identity) { - void **vector; + HeapPtr *vector; uint32 i, n; /* The identity op must not reallocate array->vector. */ vector = array->vector; - if (identity) { - for (i = 0, n = array->length; i < n; i++) { - if (identity(vector[i], elt)) - return i; - } - } else { - for (i = 0, n = array->length; i < n; i++) { - if (vector[i] == elt) - return i; - } + for (i = 0, n = array->length; i < n; i++) { + if (identity(vector[i].get(), elt)) + return i; } return XML_NOT_FOUND; } @@ -965,12 +993,13 @@ XMLArrayFindMember(const JSXMLArray *array, void *elt, JSIdentityOp identity) #define LINEAR_THRESHOLD 256 #define LINEAR_INCREMENT 32 +template static JSBool -XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt) +XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, T *elt) { uint32 capacity, i; int log2; - void **vector; + HeapPtr *vector; if (index >= array->length) { if (index >= JSXML_CAPACITY(array)) { @@ -982,20 +1011,16 @@ XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt) JS_CEILING_LOG2(log2, capacity); capacity = JS_BIT(log2); } - if ( -#if JS_BITS_PER_WORD == 32 - (size_t)capacity > ~(size_t)0 / sizeof(void *) || -#endif - !(vector = (void **) - cx->realloc_(array->vector, capacity * sizeof(void *)))) { + if (!(vector = ReallocateVector(array->vector, capacity))) { JS_ReportOutOfMemory(cx); return JS_FALSE; } array->capacity = capacity; array->vector = vector; for (i = array->length; i < index; i++) - vector[i] = NULL; + vector[i].init(NULL); } + array->vector[index].init(NULL); array->length = index + 1; } @@ -1003,17 +1028,24 @@ XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt) return JS_TRUE; } +template static JSBool -XMLArrayInsert(JSContext *cx, JSXMLArray *array, uint32 i, uint32 n) +XMLArrayInsert(JSContext *cx, JSXMLArray *array, uint32 i, uint32 n) { - uint32 j; - JSXMLArrayCursor *cursor; + uint32 j, k; + JSXMLArrayCursor *cursor; j = array->length; JS_ASSERT(i <= j); if (!array->setCapacity(cx, j + n)) return JS_FALSE; + k = j; + while (k != j + n) { + array->vector[k].init(NULL); + k++; + } + array->length = j + n; JS_ASSERT(n != (uint32)-1); while (j != i) { @@ -1028,12 +1060,14 @@ XMLArrayInsert(JSContext *cx, JSXMLArray *array, uint32 i, uint32 n) return JS_TRUE; } -static void * -XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32 index, JSBool compress) +template +static T * +XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32 index, JSBool compress) { uint32 length; - void **vector, *elt; - JSXMLArrayCursor *cursor; + HeapPtr *vector; + T *elt; + JSXMLArrayCursor *cursor; length = array->length; if (index >= length) @@ -1042,6 +1076,7 @@ XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32 index, JSBool compress) vector = array->vector; elt = vector[index]; if (compress) { + vector[length - 1].~HeapPtr(); while (++index < length) vector[index-1] = vector[index]; array->length = length - 1; @@ -1057,21 +1092,25 @@ XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32 index, JSBool compress) return elt; } +template static void -XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length) +XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length) { - void **vector; + HeapPtr *vector; JS_ASSERT(!array->cursors); if (length >= array->length) return; + for (uint32 i = length; i < array->length; i++) + array->vector[i].~HeapPtr(); + if (length == 0) { if (array->vector) cx->free_(array->vector); vector = NULL; } else { - vector = (void **) cx->realloc_(array->vector, length * sizeof(void *)); + vector = ReallocateVector(array->vector, length); if (!vector) return; } @@ -1082,21 +1121,24 @@ XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length) array->vector = vector; } -#define XMLARRAY_FIND_MEMBER(a,e,f) XMLArrayFindMember(a, (void *)(e), f) -#define XMLARRAY_HAS_MEMBER(a,e,f) (XMLArrayFindMember(a, (void *)(e), f) != \ +#define XMLARRAY_FIND_MEMBER(a,e,f) XMLArrayFindMember(a, e, f) +#define XMLARRAY_HAS_MEMBER(a,e,f) (XMLArrayFindMember(a, e, f) != \ XML_NOT_FOUND) #define XMLARRAY_MEMBER(a,i,t) (((i) < (a)->length) \ - ? (t *) (a)->vector[i] \ + ? (a)->vector[i].get() \ : NULL) #define XMLARRAY_SET_MEMBER(a,i,e) JS_BEGIN_MACRO \ - if ((a)->length <= (i)) \ + if ((a)->length <= (i)) { \ (a)->length = (i) + 1; \ - ((a)->vector[i] = (void *)(e)); \ + ((a)->vector[i].init(e)); \ + } else { \ + ((a)->vector[i] = e); \ + } \ JS_END_MACRO -#define XMLARRAY_ADD_MEMBER(x,a,i,e)XMLArrayAddMember(x, a, i, (void *)(e)) +#define XMLARRAY_ADD_MEMBER(x,a,i,e)XMLArrayAddMember(x, a, i, e) #define XMLARRAY_INSERT(x,a,i,n) XMLArrayInsert(x, a, i, n) #define XMLARRAY_APPEND(x,a,e) XMLARRAY_ADD_MEMBER(x, a, (a)->length, (e)) -#define XMLARRAY_DELETE(x,a,i,c,t) ((t *) XMLArrayDelete(x, a, i, c)) +#define XMLARRAY_DELETE(x,a,i,c,t) (XMLArrayDelete(x, a, i, c)) #define XMLARRAY_TRUNCATE(x,a,n) XMLArrayTruncate(x, a, n) /* @@ -1155,8 +1197,24 @@ HAS_NS_AFTER_XML(const jschar *chars) static const char xml_namespace_str[] = "http://www.w3.org/XML/1998/namespace"; static const char xmlns_namespace_str[] = "http://www.w3.org/2000/xmlns/"; +void +JSXML::finalize(JSContext *cx) +{ + if (JSXML_HAS_KIDS(this)) { + xml_kids.finish(cx); + if (xml_class == JSXML_CLASS_ELEMENT) { + xml_namespaces.finish(cx); + xml_attrs.finish(cx); + } + } +#ifdef DEBUG_notme + JS_REMOVE_LINK(&links); +#endif +} + static JSObject * -ParseNodeToQName(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, JSBool isAttributeName) +ParseNodeToQName(Parser *parser, ParseNode *pn, + JSXMLArray *inScopeNSes, JSBool isAttributeName) { JSContext *cx = parser->context; JSLinearString *uri, *prefix; @@ -1284,7 +1342,8 @@ ChompXMLWhitespace(JSContext *cx, JSString *str) } static JSXML * -ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN flags) +ParseNodeToXML(Parser *parser, ParseNode *pn, + JSXMLArray *inScopeNSes, uintN flags) { JSContext *cx = parser->context; JSXML *xml, *kid, *attr, *attrj; @@ -2173,7 +2232,7 @@ EscapeElementValue(JSContext *cx, StringBuffer &sb, JSString *str, uint32 toSour /* 13.3.5.4 [[GetNamespace]]([InScopeNamespaces]) */ static JSObject * -GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes) +GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes) { JSLinearString *uri, *prefix, *nsprefix; JSObject *match, *ns; @@ -2254,7 +2313,7 @@ GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes) } static JSLinearString * -GeneratePrefix(JSContext *cx, JSLinearString *uri, JSXMLArray *decls) +GeneratePrefix(JSContext *cx, JSLinearString *uri, JSXMLArray *decls) { const jschar *cp, *start, *end; size_t length, newlength, offset; @@ -2370,10 +2429,8 @@ GeneratePrefix(JSContext *cx, JSLinearString *uri, JSXMLArray *decls) } static JSBool -namespace_match(const void *a, const void *b) +namespace_match(const JSObject *nsa, const JSObject *nsb) { - const JSObject *nsa = (const JSObject *) a; - const JSObject *nsb = (const JSObject *) b; JSLinearString *prefixa, *prefixb = nsb->getNamePrefix(); if (prefixb) { @@ -2387,7 +2444,7 @@ namespace_match(const void *a, const void *b) #define TO_SOURCE_FLAG 0x80000000 static JSString * -XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, +XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, uint32 indentLevel, JSBool pretty) { JSBool indentKids; @@ -2434,9 +2491,9 @@ XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, case JSXML_CLASS_LIST: /* ECMA-357 10.2.2. */ { - JSXMLArrayCursor cursor(&xml->xml_kids); + JSXMLArrayCursor cursor(&xml->xml_kids); i = 0; - while (JSXML *kid = (JSXML *) cursor.getNext()) { + while (JSXML *kid = cursor.getNext()) { if (pretty && i != 0) { if (!sb.append('\n')) return NULL; @@ -2474,8 +2531,8 @@ XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, /* Clone in-scope namespaces not in ancestorNSes into decls. */ { - JSXMLArrayCursor cursor(&xml->xml_namespaces); - while ((ns = (JSObject *) cursor.getNext()) != NULL) { + JSXMLArrayCursor cursor(&xml->xml_namespaces); + while ((ns = cursor.getNext()) != NULL) { if (!IsDeclared(ns)) continue; if (!XMLARRAY_HAS_MEMBER(ancestorNSes, ns, namespace_identity)) { @@ -2597,8 +2654,8 @@ XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, /* Step 17(b): append attributes. */ { - JSXMLArrayCursor cursor(&xml->xml_attrs); - while (JSXML *attr = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_attrs); + while (JSXML *attr = cursor.getNext()) { if (!sb.append(' ')) goto out; ns2 = GetNamespace(cx, attr->name, &ancdecls.array); @@ -2648,8 +2705,8 @@ XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, /* Step 17(c): append XML namespace declarations. */ { - JSXMLArrayCursor cursor(&decls.array); - while (JSObject *ns3 = (JSObject *) cursor.getNext()) { + JSXMLArrayCursor cursor(&decls.array); + while (JSObject *ns3 = cursor.getNext()) { JS_ASSERT(IsDeclared(ns3)); if (!sb.append(" xmlns")) @@ -2702,8 +2759,8 @@ XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, } { - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { if (pretty && indentKids) { if (!sb.append('\n')) goto out; @@ -3067,7 +3124,7 @@ DeepCopy(JSContext *cx, JSXML *xml, JSObject *obj, uintN flags) * (iii) from's owning object must be locked if not thread-local. */ static JSBool -DeepCopySetInLRS(JSContext *cx, JSXMLArray *from, JSXMLArray *to, JSXML *parent, +DeepCopySetInLRS(JSContext *cx, JSXMLArray *from, JSXMLArray *to, JSXML *parent, uintN flags) { uint32 j, n; @@ -3078,9 +3135,9 @@ DeepCopySetInLRS(JSContext *cx, JSXMLArray *from, JSXMLArray *to, JSXML *parent, if (!to->setCapacity(cx, n)) return JS_FALSE; - JSXMLArrayCursor cursor(from); + JSXMLArrayCursor cursor(from); j = 0; - while (JSXML *kid = (JSXML *) cursor.getNext()) { + while (JSXML *kid = cursor.getNext()) { if ((flags & XSF_IGNORE_COMMENTS) && kid->xml_class == JSXML_CLASS_COMMENT) { continue; @@ -3360,11 +3417,11 @@ retry: *bp = JS_FALSE; } else { { - JSXMLArrayCursor cursor(&xml->xml_kids); - JSXMLArrayCursor vcursor(&vxml->xml_kids); + JSXMLArrayCursor cursor(&xml->xml_kids); + JSXMLArrayCursor vcursor(&vxml->xml_kids); for (;;) { - kid = (JSXML *) cursor.getNext(); - vkid = (JSXML *) vcursor.getNext(); + kid = cursor.getNext(); + vkid = vcursor.getNext(); if (!kid || !vkid) { *bp = !kid && !vkid; break; @@ -3600,7 +3657,7 @@ static void DeleteNamedProperty(JSContext *cx, JSXML *xml, JSObject *nameqn, JSBool attributes) { - JSXMLArray *array; + JSXMLArray *array; uint32 index, deleteCount; JSXML *kid; JSXMLNameMatcher matcher; @@ -3658,7 +3715,7 @@ DeleteListElement(JSContext *cx, JSXML *xml, uint32 index) DeleteNamedProperty(cx, parent, kid->name, JS_TRUE); } else { kidIndex = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, - NULL); + pointer_match); JS_ASSERT(kidIndex != XML_NOT_FOUND); DeleteByIndex(cx, parent, kidIndex); } @@ -3671,7 +3728,7 @@ DeleteListElement(JSContext *cx, JSXML *xml, uint32 index) static JSBool SyncInScopeNamespaces(JSContext *cx, JSXML *xml) { - JSXMLArray *nsarray; + JSXMLArray *nsarray; uint32 i, n; JSObject *ns; @@ -3691,13 +3748,13 @@ SyncInScopeNamespaces(JSContext *cx, JSXML *xml) static JSBool GetNamedProperty(JSContext *cx, JSXML *xml, JSObject* nameqn, JSXML *list) { - JSXMLArray *array; + JSXMLArray *array; JSXMLNameMatcher matcher; JSBool attrs; if (xml->xml_class == JSXML_CLASS_LIST) { - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { if (kid->xml_class == JSXML_CLASS_ELEMENT && !GetNamedProperty(cx, kid, nameqn, list)) { return JS_FALSE; @@ -3713,8 +3770,8 @@ GetNamedProperty(JSContext *cx, JSXML *xml, JSObject* nameqn, JSXML *list) matcher = MatchElemName; } - JSXMLArrayCursor cursor(array); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(array); + while (JSXML *kid = cursor.getNext()) { if (matcher(nameqn, kid)) { if (!attrs && kid->xml_class == JSXML_CLASS_ELEMENT && @@ -4100,7 +4157,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp) JS_ASSERT(parent != xml); if (parent) { - q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL); + q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, pointer_match); JS_ASSERT(q != XML_NOT_FOUND); ok = Replace(cx, parent, q, OBJECT_TO_JSVAL(copyobj)); if (!ok) @@ -4137,7 +4194,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp) /* 2(g). */ else if (vxml || JSXML_HAS_VALUE(kid)) { if (parent) { - q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL); + q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, pointer_match); JS_ASSERT(q != XML_NOT_FOUND); ok = Replace(cx, parent, q, *vp); if (!ok) @@ -4448,9 +4505,9 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp) /* 14. */ if (primitiveAssign) { - JSXMLArrayCursor cursor(&xml->xml_kids); + JSXMLArrayCursor cursor(&xml->xml_kids); cursor.index = matchIndex; - kid = (JSXML *) cursor.getCurrent(); + kid = cursor.getCurrent(); if (JSXML_HAS_KIDS(kid)) { kid->xml_kids.finish(cx); kid->xml_kids.init(); @@ -4463,7 +4520,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp) ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp); if (ok && !JSVAL_TO_STRING(*vp)->empty()) { roots[VAL_ROOT] = *vp; - if ((JSXML *) cursor.getCurrent() == kid) + if (cursor.getCurrent() == kid) ok = Replace(cx, kid, 0, *vp); } } @@ -4551,14 +4608,14 @@ static JSBool HasNamedProperty(JSXML *xml, JSObject *nameqn) { JSBool found; - JSXMLArray *array; + JSXMLArray *array; JSXMLNameMatcher matcher; uint32 i, n; if (xml->xml_class == JSXML_CLASS_LIST) { found = JS_FALSE; - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { found = HasNamedProperty(kid, nameqn); if (found) break; @@ -4690,17 +4747,6 @@ HasProperty(JSContext *cx, JSObject *obj, jsval id, JSBool *found) static void xml_finalize(JSContext *cx, JSObject *obj) { - JSXML *xml = (JSXML *) obj->getPrivate(); - if (!xml) - return; - if (xml->object == obj) - xml->object = NULL; -} - -static void -xml_trace_vector(JSTracer *trc, JSXML **vec, uint32 len) -{ - MarkXMLRange(trc, len, vec, "xml_vector"); } /* @@ -5074,7 +5120,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, { JSXML *xml; uint32 length, index; - JSXMLArrayCursor *cursor; + JSXMLArrayCursor *cursor; xml = (JSXML *)obj->getPrivate(); length = JSXML_LENGTH(xml); @@ -5085,7 +5131,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, if (length == 0) { statep->setInt32(0); } else { - cursor = cx->new_(&xml->xml_kids); + cursor = cx->new_< JSXMLArrayCursor >(&xml->xml_kids); if (!cursor) return JS_FALSE; statep->setPrivate(cursor); @@ -5099,7 +5145,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, statep->setNull(); break; } - cursor = (JSXMLArrayCursor *) statep->toPrivate(); + cursor = (JSXMLArrayCursor *) statep->toPrivate(); if (cursor && cursor->array && (index = cursor->index) < length) { *idp = INT_TO_JSID(index); cursor->index = index + 1; @@ -5109,7 +5155,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, case JSENUMERATE_DESTROY: if (!statep->isInt32(0)) { - cursor = (JSXMLArrayCursor *) statep->toPrivate(); + cursor = (JSXMLArrayCursor *) statep->toPrivate(); if (cursor) cx->delete_(cursor); } @@ -5135,8 +5181,12 @@ static void xml_trace(JSTracer *trc, JSObject *obj) { JSXML *xml = (JSXML *) obj->getPrivate(); + /* + * This is safe to leave Unbarriered for incremental GC, but we'll need + * to fix somehow for generational. + */ if (xml) - JS_CALL_TRACER(trc, xml, JSTRACE_XML, "private"); + MarkXMLUnbarriered(trc, xml, "private"); } static JSBool @@ -5645,8 +5695,8 @@ xml_child(JSContext *cx, uintN argc, jsval *vp) if (!list) return JS_FALSE; - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { kidobj = js_GetXMLObject(cx, kid); if (!kidobj) return JS_FALSE; @@ -5786,8 +5836,8 @@ xml_contains(JSContext *cx, uintN argc, jsval *vp) value = argc != 0 ? vp[2] : JSVAL_VOID; if (xml->xml_class == JSXML_CLASS_LIST) { eq = JS_FALSE; - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { kidobj = js_GetXMLObject(cx, kid); if (!kidobj || !js_TestXMLEquality(cx, ObjectValue(*kidobj), value, &eq)) return JS_FALSE; @@ -5852,8 +5902,8 @@ xml_elements_helper(JSContext *cx, JSObject *obj, JSXML *xml, if (xml->xml_class == JSXML_CLASS_LIST) { /* 13.5.4.6 */ - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { if (kid->xml_class == JSXML_CLASS_ELEMENT) { ok = js_EnterLocalRootScope(cx); if (!ok) @@ -5992,7 +6042,7 @@ xml_hasSimpleContent(JSContext *cx, uintN argc, jsval *vp) } static JSBool -FindInScopeNamespaces(JSContext *cx, JSXML *xml, JSXMLArray *nsarray) +FindInScopeNamespaces(JSContext *cx, JSXML *xml, JSXMLArray *nsarray) { uint32 length, i, j, n; JSObject *ns, *ns2; @@ -6037,7 +6087,7 @@ FindInScopeNamespaces(JSContext *cx, JSXML *xml, JSXMLArray *nsarray) * rval. rval must point to a rooted location. */ static bool -NamespacesToJSArray(JSContext *cx, JSXMLArray *array, jsval *rval) +NamespacesToJSArray(JSContext *cx, JSXMLArray *array, jsval *rval) { JSObject *arrayobj = NewDenseEmptyArray(cx); if (!arrayobj) @@ -6086,7 +6136,7 @@ xml_insertChildAfter(JSContext *cx, uintN argc, jsval *vp) if (!VALUE_IS_XML(arg)) return JS_TRUE; kid = (JSXML *) JSVAL_TO_OBJECT(arg)->getPrivate(); - i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL); + i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, pointer_match); if (i == XML_NOT_FOUND) return JS_TRUE; ++i; @@ -6118,7 +6168,7 @@ xml_insertChildBefore(JSContext *cx, uintN argc, jsval *vp) if (!VALUE_IS_XML(arg)) return JS_TRUE; kid = (JSXML *) JSVAL_TO_OBJECT(arg)->getPrivate(); - i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL); + i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, pointer_match); if (i == XML_NOT_FOUND) return JS_TRUE; } @@ -6397,8 +6447,8 @@ xml_processingInstructions_helper(JSContext *cx, JSObject *obj, JSXML *xml, if (xml->xml_class == JSXML_CLASS_LIST) { /* 13.5.4.17 Step 4 (misnumbered 9 -- Erratum?). */ - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { if (kid->xml_class == JSXML_CLASS_ELEMENT) { ok = js_EnterLocalRootScope(cx); if (!ok) @@ -6500,10 +6550,8 @@ xml_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp) } static JSBool -namespace_full_match(const void *a, const void *b) +namespace_full_match(const JSObject *nsa, const JSObject *nsb) { - const JSObject *nsa = (const JSObject *) a; - const JSObject *nsb = (const JSObject *) b; JSLinearString *prefixa = nsa->getNamePrefix(); JSLinearString *prefixb; @@ -6706,7 +6754,7 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp) jsval name; JSObject *nameqn; JSXML *nsowner; - JSXMLArray *nsarray; + JSXMLArray *nsarray; uint32 i, n; JSObject *ns; @@ -6769,7 +6817,7 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp) return JS_FALSE; /* XXXbe have to test membership to see whether GetNamespace added */ - if (XMLARRAY_HAS_MEMBER(&nsowner->xml_namespaces, ns, NULL)) { + if (XMLARRAY_HAS_MEMBER(&nsowner->xml_namespaces, ns, pointer_match)) { vp[0] = JSVAL_VOID; return JS_TRUE; } @@ -6812,8 +6860,9 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp) } /* Utility function used within xml_setNamespace */ -static JSBool qn_match(const void *xml, const void *qn) { - return qname_identity(((JSXML *)xml)->name, (JSObject *)qn); +static JSBool qn_match(const JSXML *xml, const JSObject *qn) +{ + return qname_identity(xml->name, qn); } /* ECMA-357 13.4.4.36 */ @@ -6855,7 +6904,7 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp) xml->parent && xml->parent->xml_class == JSXML_CLASS_ELEMENT && !qn_match(xml, qn)) { - JSXMLArray *array = &xml->parent->xml_attrs; + JSXMLArray *array = &xml->parent->xml_attrs; uint32 i = XMLArrayFindMember(array, qn, qn_match); if (i != XML_NOT_FOUND) XMLArrayDelete(cx, array, i, JS_TRUE); @@ -6953,8 +7002,8 @@ xml_toString_helper(JSContext *cx, JSXML *xml) str = cx->runtime->emptyString; if (!js_EnterLocalRootScope(cx)) return NULL; - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = (JSXML *) cursor.getNext()) { + JSXMLArrayCursor cursor(&xml->xml_kids); + while (JSXML *kid = cursor.getNext()) { if (kid->xml_class != JSXML_CLASS_COMMENT && kid->xml_class != JSXML_CLASS_PROCESSING_INSTRUCTION) { kidstr = xml_toString_helper(cx, kid); @@ -7249,19 +7298,20 @@ js_NewXML(JSContext *cx, JSXMLClass xml_class) if (!xml) return NULL; - xml->object = NULL; + xml->object.init(NULL); xml->domnode = NULL; - xml->parent = NULL; - xml->name = NULL; + xml->parent.init(NULL); + xml->name.init(NULL); xml->xml_class = xml_class; xml->xml_flags = 0; if (JSXML_CLASS_HAS_VALUE(xml_class)) { - xml->xml_value = cx->runtime->emptyString; + xml->xml_value.init(cx->runtime->emptyString); } else { + xml->xml_value.init(NULL); xml->xml_kids.init(); if (xml_class == JSXML_CLASS_LIST) { - xml->xml_target = NULL; - xml->xml_targetprop = NULL; + xml->xml_target.init(NULL); + xml->xml_targetprop.init(NULL); } else { xml->xml_namespaces.init(); xml->xml_attrs.init(); @@ -7275,15 +7325,33 @@ js_NewXML(JSContext *cx, JSXMLClass xml_class) return xml; } +void +JSXML::writeBarrierPre(JSXML *xml) +{ +#ifdef JSGC_INCREMENTAL + if (!xml) + return; + + JSCompartment *comp = xml->compartment(); + if (comp->needsBarrier()) + MarkXMLUnbarriered(comp->barrierTracer(), xml, "write barrier"); +#endif +} + +void +JSXML::writeBarrierPost(JSXML *xml, void *addr) +{ +} + void js_TraceXML(JSTracer *trc, JSXML *xml) { if (xml->object) - MarkObject(trc, *xml->object, "object"); + MarkObject(trc, xml->object, "object"); if (xml->name) - MarkObject(trc, *xml->name, "name"); + MarkObject(trc, xml->name, "name"); if (xml->parent) - JS_CALL_TRACER(trc, xml->parent, JSTRACE_XML, "xml_parent"); + MarkXML(trc, xml->parent, "xml_parent"); if (JSXML_HAS_VALUE(xml)) { if (xml->xml_value) @@ -7291,25 +7359,21 @@ js_TraceXML(JSTracer *trc, JSXML *xml) return; } - xml_trace_vector(trc, - (JSXML **) xml->xml_kids.vector, - xml->xml_kids.length); + MarkXMLRange(trc, xml->xml_kids.length, xml->xml_kids.vector, "xml_kids"); XMLArrayCursorTrace(trc, xml->xml_kids.cursors); if (xml->xml_class == JSXML_CLASS_LIST) { if (xml->xml_target) - JS_CALL_TRACER(trc, xml->xml_target, JSTRACE_XML, "target"); + MarkXML(trc, xml->xml_target, "target"); if (xml->xml_targetprop) - MarkObject(trc, *xml->xml_targetprop, "targetprop"); + MarkObject(trc, xml->xml_targetprop, "targetprop"); } else { MarkObjectRange(trc, xml->xml_namespaces.length, - (JSObject **) xml->xml_namespaces.vector, + xml->xml_namespaces.vector, "xml_namespaces"); XMLArrayCursorTrace(trc, xml->xml_namespaces.cursors); - xml_trace_vector(trc, - (JSXML **) xml->xml_attrs.vector, - xml->xml_attrs.length); + MarkXMLRange(trc, xml->xml_attrs.length, xml->xml_attrs.vector, "xml_attrs"); XMLArrayCursorTrace(trc, xml->xml_attrs.cursors); } } @@ -7500,7 +7564,7 @@ namespace js { bool GlobalObject::getFunctionNamespace(JSContext *cx, Value *vp) { - Value &v = getSlotRef(FUNCTION_NS); + HeapValue &v = getSlotRef(FUNCTION_NS); if (v.isUndefined()) { JSRuntime *rt = cx->runtime; JSLinearString *prefix = rt->atomState.typeAtoms[JSTYPE_FUNCTION]; @@ -7518,7 +7582,7 @@ GlobalObject::getFunctionNamespace(JSContext *cx, Value *vp) */ obj->clearType(); - v.setObject(*obj); + v.set(compartment(), ObjectValue(*obj)); } *vp = v; @@ -7837,12 +7901,12 @@ js_DeleteXMLListElements(JSContext *cx, JSObject *listobj) struct JSXMLFilter { - JSXML *list; - JSXML *result; - JSXML *kid; - JSXMLArrayCursor cursor; + HeapPtr list; + HeapPtr result; + HeapPtr kid; + JSXMLArrayCursor cursor; - JSXMLFilter(JSXML *list, JSXMLArray *array) + JSXMLFilter(JSXML *list, JSXMLArray *array) : list(list), result(NULL), kid(NULL), cursor(array) {} ~JSXMLFilter() {} @@ -7856,11 +7920,11 @@ xmlfilter_trace(JSTracer *trc, JSObject *obj) return; JS_ASSERT(filter->list); - JS_CALL_TRACER(trc, filter->list, JSTRACE_XML, "list"); + MarkXML(trc, filter->list, "list"); if (filter->result) - JS_CALL_TRACER(trc, filter->result, JSTRACE_XML, "result"); + MarkXML(trc, filter->result, "result"); if (filter->kid) - JS_CALL_TRACER(trc, filter->kid, JSTRACE_XML, "kid"); + MarkXML(trc, filter->kid, "kid"); /* * We do not need to trace the cursor as that would be done when @@ -7975,7 +8039,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized) } /* Do the iteration. */ - filter->kid = (JSXML *) filter->cursor.getNext(); + filter->kid = filter->cursor.getNext(); if (!filter->kid) { /* * Do not defer finishing the cursor until the next GC cycle to avoid diff --git a/js/src/jsxml.h b/js/src/jsxml.h index 2a3e3a08de8f..888c9d6bb00a 100644 --- a/js/src/jsxml.h +++ b/js/src/jsxml.h @@ -43,6 +43,8 @@ #include "jsobj.h" #include "jscell.h" +#include "gc/Barrier.h" + extern const char js_AnyName_str[]; extern const char js_AttributeName_str[]; extern const char js_isXMLName_str[]; @@ -53,14 +55,16 @@ extern const char js_gt_entity_str[]; extern const char js_lt_entity_str[]; extern const char js_quot_entity_str[]; -typedef JSBool -(* JSIdentityOp)(const void *a, const void *b); +template +struct JSXMLArrayCursor; -struct JSXMLArray { +template +struct JSXMLArray +{ uint32 length; uint32 capacity; - void **vector; - JSXMLArrayCursor *cursors; + js::HeapPtr *vector; + JSXMLArrayCursor *cursors; void init() { length = capacity = 0; @@ -74,15 +78,18 @@ struct JSXMLArray { void trim(); }; +template struct JSXMLArrayCursor { - JSXMLArray *array; - uint32 index; - JSXMLArrayCursor *next; - JSXMLArrayCursor **prevp; - void *root; + typedef js::HeapPtr HeapPtrT; - JSXMLArrayCursor(JSXMLArray *array) + JSXMLArray *array; + uint32 index; + JSXMLArrayCursor *next; + JSXMLArrayCursor **prevp; + HeapPtrT root; + + JSXMLArrayCursor(JSXMLArray *array) : array(array), index(0), next(array->cursors), prevp(&array->cursors), root(NULL) { @@ -100,15 +107,16 @@ struct JSXMLArrayCursor next->prevp = prevp; *prevp = next; array = NULL; + root.~HeapPtrT(); } - void *getNext() { + T *getNext() { if (!array || index >= array->length) return NULL; return root = array->vector[index++]; } - void *getCurrent() { + T *getCurrent() { if (!array || index >= array->length) return NULL; return root = array->vector[index]; @@ -146,24 +154,24 @@ typedef enum JSXMLClass { #endif typedef struct JSXMLListVar { - JSXMLArray kids; /* NB: must come first */ - JSXML *target; - JSObject *targetprop; + JSXMLArray kids; /* NB: must come first */ + js::HeapPtrXML target; + js::HeapPtrObject targetprop; } JSXMLListVar; typedef struct JSXMLElemVar { - JSXMLArray kids; /* NB: must come first */ - JSXMLArray namespaces; - JSXMLArray attrs; + JSXMLArray kids; /* NB: must come first */ + JSXMLArray namespaces; + JSXMLArray attrs; } JSXMLElemVar; /* union member shorthands */ -#define xml_kids u.list.kids -#define xml_target u.list.target -#define xml_targetprop u.list.targetprop -#define xml_namespaces u.elem.namespaces -#define xml_attrs u.elem.attrs -#define xml_value u.value +#define xml_kids list.kids +#define xml_target list.target +#define xml_targetprop list.targetprop +#define xml_namespaces elem.namespaces +#define xml_attrs elem.attrs +#define xml_value value /* xml_class-testing macros */ #define JSXML_HAS_KIDS(xml) JSXML_CLASS_HAS_KIDS((xml)->xml_class) @@ -178,30 +186,26 @@ struct JSXML : js::gc::Cell { JSCList links; uint32 serial; #endif - JSObject *object; + js::HeapPtrObject object; void *domnode; /* DOM node if mapped info item */ - JSXML *parent; - JSObject *name; + js::HeapPtrXML parent; + js::HeapPtrObject name; uint32 xml_class; /* discriminates u, below */ uint32 xml_flags; /* flags, see below */ - union { - JSXMLListVar list; - JSXMLElemVar elem; - JSString *value; - } u; - - void finalize(JSContext *cx) { - if (JSXML_HAS_KIDS(this)) { - xml_kids.finish(cx); - if (xml_class == JSXML_CLASS_ELEMENT) { - xml_namespaces.finish(cx); - xml_attrs.finish(cx); - } - } -#ifdef DEBUG_notme - JS_REMOVE_LINK(&links); + + JSXMLListVar list; + JSXMLElemVar elem; + js::HeapPtrString value; + +#if JS_BITS_PER_WORD == 32 + /* The size of every GC thing must be divisible by the FreeCell size. */ + void *pad; #endif - } + + void finalize(JSContext *cx); + + static void writeBarrierPre(JSXML *xml); + static void writeBarrierPost(JSXML *xml, void *addr); }; /* xml_flags values */ diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 98b0095eb152..919049561ffa 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -771,7 +771,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist JS_ASSERT(objReg != typeReg); FastArrayLoadFails fails; - fails.rangeCheck = guardArrayExtent(offsetof(JSObject, initializedLength), + fails.rangeCheck = guardArrayExtent(JSObject::offsetOfInitializedLength(), objReg, key, BelowOrEqual); RegisterID dslotsReg = objReg; @@ -1245,7 +1245,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist { gc::AllocKind allocKind = templateObject->getAllocKind(); - JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST); + JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind < gc::FINALIZE_OBJECT_LIMIT); int thingSize = (int)gc::Arena::thingSize(allocKind); JS_ASSERT(cx->typeInferenceEnabled()); @@ -1285,7 +1285,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist * slots first. */ if (templateObject->isDenseArray()) { - JS_ASSERT(!templateObject->initializedLength); + JS_ASSERT(!templateObject->initializedLength()); addPtr(Imm32(-thingSize + sizeof(JSObject)), result); storePtr(result, Address(result, -(int)sizeof(JSObject) + JSObject::offsetOfSlots())); addPtr(Imm32(-(int)sizeof(JSObject)), result); diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index c7b42568d25c..7427b45b49de 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -5132,7 +5132,21 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed ScriptAnalysis::NameAccess access = analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true); if (access.nesting) { - Address address = frame.loadNameAddress(access); + /* Use a SavedReg so it isn't clobbered by the stub call. */ + RegisterID nameReg = frame.allocReg(Registers::SavedRegs).reg(); + Address address = frame.loadNameAddress(access, nameReg); + +#ifdef JSGC_INCREMENTAL_MJ + /* Write barrier. */ + if (cx->compartment->needsBarrier()) { + stubcc.linkExit(masm.jump(), Uses(0)); + stubcc.leave(); + stubcc.masm.addPtr(Imm32(address.offset), address.base, Registers::ArgReg1); + OOL_STUBCALL(stubs::WriteBarrier, REJOIN_NONE); + stubcc.rejoin(Changes(0)); + } +#endif + frame.storeTo(rhs, address, popGuaranteed); frame.shimmy(1); frame.freeReg(address.base); @@ -5160,7 +5174,24 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed !propertyTypes->isOwnProperty(cx, object, true)) { types->addFreeze(cx); uint32 slot = propertyTypes->definiteSlot(); + RegisterID reg = frame.tempRegForData(lhs); bool isObject = lhs->isTypeKnown(); +#ifdef JSGC_INCREMENTAL_MJ + if (cx->compartment->needsBarrier() && propertyTypes->needsBarrier(cx)) { + /* Write barrier. */ + Jump j; + if (isObject) + j = masm.testGCThing(Address(reg, JSObject::getFixedSlotOffset(slot))); + else + j = masm.jump(); + stubcc.linkExit(j, Uses(0)); + stubcc.leave(); + stubcc.masm.addPtr(Imm32(JSObject::getFixedSlotOffset(slot)), + reg, Registers::ArgReg1); + OOL_STUBCALL(stubs::GCThingWriteBarrier, REJOIN_NONE); + stubcc.rejoin(Changes(0)); + } +#endif if (!isObject) { Jump notObject = frame.testObject(Assembler::NotEqual, lhs); stubcc.linkExit(notObject, Uses(2)); @@ -5168,7 +5199,6 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1); OOL_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH); } - RegisterID reg = frame.tempRegForData(lhs); frame.storeTo(rhs, Address(reg, JSObject::getFixedSlotOffset(slot)), popGuaranteed); frame.shimmy(1); if (!isObject) @@ -5177,6 +5207,14 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed } } +#ifdef JSGC_INCREMENTAL_MJ + /* Write barrier. */ + if (cx->compartment->needsBarrier() && (!types || types->propertyNeedsBarrier(cx, id))) { + jsop_setprop_slow(atom, usePropCache); + return true; + } +#endif + JSOp op = JSOp(*PC); ic::PICInfo::Kind kind = (op == JSOP_SETMETHOD) @@ -5718,6 +5756,18 @@ mjit::Compiler::iter(uintN flags) Jump overlongChain = masm.branchPtr(Assembler::NonZero, T1, T1); stubcc.linkExit(overlongChain, Uses(1)); +#ifdef JSGC_INCREMENTAL_MJ + /* + * Write barrier for stores to the iterator. We only need to take a write + * barrier if NativeIterator::obj is actually going to change. + */ + if (cx->compartment->needsBarrier()) { + Jump j = masm.branchPtr(Assembler::NotEqual, + Address(nireg, offsetof(NativeIterator, obj)), reg); + stubcc.linkExit(j, Uses(1)); + } +#endif + /* Found a match with the most recent iterator. Hooray! */ /* Mark iterator as active. */ @@ -5963,7 +6013,7 @@ mjit::Compiler::jsop_getgname(uint32 index) */ const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(atom)); if (shape && shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) { - Value *value = &globalObj->getSlotRef(shape->slot); + HeapValue *value = &globalObj->getSlotRef(shape->slot); if (!value->isUndefined() && !propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) { watchGlobalReallocation(); @@ -6193,8 +6243,18 @@ mjit::Compiler::jsop_setgname(JSAtom *atom, bool usePropertyCache, bool popGuara shape->writable() && shape->hasSlot() && !types->isOwnProperty(cx, globalObj->getType(cx), true)) { watchGlobalReallocation(); - Value *value = &globalObj->getSlotRef(shape->slot); + HeapValue *value = &globalObj->getSlotRef(shape->slot); RegisterID reg = frame.allocReg(); +#ifdef JSGC_INCREMENTAL_MJ + /* Write barrier. */ + if (cx->compartment->needsBarrier() && types->needsBarrier(cx)) { + stubcc.linkExit(masm.jump(), Uses(0)); + stubcc.leave(); + stubcc.masm.move(ImmPtr(value), Registers::ArgReg1); + OOL_STUBCALL(stubs::WriteBarrier, REJOIN_NONE); + stubcc.rejoin(Changes(0)); + } +#endif masm.move(ImmPtr(value), reg); frame.storeTo(frame.peek(-1), Address(reg), popGuaranteed); frame.shimmy(1); @@ -6203,6 +6263,14 @@ mjit::Compiler::jsop_setgname(JSAtom *atom, bool usePropertyCache, bool popGuara } } +#ifdef JSGC_INCREMENTAL_MJ + /* Write barrier. */ + if (cx->compartment->needsBarrier()) { + jsop_setgname_slow(atom, usePropertyCache); + return; + } +#endif + #if defined JS_MONOIC FrameEntry *objFe = frame.peek(-2); FrameEntry *fe = frame.peek(-1); @@ -6217,6 +6285,7 @@ mjit::Compiler::jsop_setgname(JSAtom *atom, bool usePropertyCache, bool popGuara Jump shapeGuard; RESERVE_IC_SPACE(masm); + ic.fastPathStart = masm.label(); if (objFe->isConstant()) { JSObject *obj = &objFe->getValue().toObject(); diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 349bf12f3459..486522cafe52 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -367,7 +367,7 @@ class Compiler : public BaseCompiler analyze::CrossScriptSSA ssa; GlobalObject *globalObj; - const Value *globalSlots; /* Original slots pointer. */ + const HeapValue *globalSlots; /* Original slots pointer. */ Assembler masm; FrameState frame; diff --git a/js/src/methodjit/FastBuiltins.cpp b/js/src/methodjit/FastBuiltins.cpp index cbd745099c0a..95fc40423f6c 100644 --- a/js/src/methodjit/FastBuiltins.cpp +++ b/js/src/methodjit/FastBuiltins.cpp @@ -467,7 +467,7 @@ mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg) Int32Key key = Int32Key::FromRegister(lengthReg); /* Test for 'length == initializedLength' */ - Jump initlenGuard = masm.guardArrayExtent(offsetof(JSObject, initializedLength), + Jump initlenGuard = masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), objReg, key, Assembler::NotEqual); stubcc.linkExit(initlenGuard, Uses(3)); @@ -481,7 +481,7 @@ mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg) masm.bumpKey(key, 1); masm.store32(lengthReg, Address(objReg, offsetof(JSObject, privateData))); - masm.store32(lengthReg, Address(objReg, offsetof(JSObject, initializedLength))); + masm.store32(lengthReg, Address(objReg, JSObject::offsetOfInitializedLength())); stubcc.leave(); stubcc.masm.move(Imm32(1), Registers::ArgReg1); @@ -504,6 +504,12 @@ mjit::Compiler::compileArrayPopShift(FrameEntry *thisValue, bool isPacked, bool if (thisValue->isConstant()) return Compile_InlineAbort; +#ifdef JSGC_INCREMENTAL_MJ + /* Write barrier. */ + if (cx->compartment->needsBarrier()) + return Compile_InlineAbort; +#endif + RegisterID objReg = frame.tempRegForData(thisValue); frame.pinReg(objReg); @@ -533,7 +539,7 @@ mjit::Compiler::compileArrayPopShift(FrameEntry *thisValue, bool isPacked, bool /* Test for 'length == initializedLength' */ Int32Key key = Int32Key::FromRegister(lengthReg); - Jump initlenGuard = masm.guardArrayExtent(offsetof(JSObject, initializedLength), + Jump initlenGuard = masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), objReg, key, Assembler::NotEqual); stubcc.linkExit(initlenGuard, Uses(3)); @@ -569,7 +575,7 @@ mjit::Compiler::compileArrayPopShift(FrameEntry *thisValue, bool isPacked, bool } masm.store32(lengthReg, Address(objReg, offsetof(JSObject, privateData))); - masm.store32(lengthReg, Address(objReg, offsetof(JSObject, initializedLength))); + masm.store32(lengthReg, Address(objReg, JSObject::offsetOfInitializedLength())); if (!isArrayPop) INLINE_STUBCALL(stubs::ArrayShift, REJOIN_NONE); @@ -668,13 +674,13 @@ mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *ar RegisterID objReg = frame.tempRegForData(thisValue); masm.load32(Address(objReg, offsetof(JSObject, privateData)), reg); - Jump initlenOneGuard = masm.guardArrayExtent(offsetof(JSObject, initializedLength), + Jump initlenOneGuard = masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), objReg, key, Assembler::NotEqual); stubcc.linkExit(initlenOneGuard, Uses(3)); objReg = frame.tempRegForData(argValue); masm.load32(Address(objReg, offsetof(JSObject, privateData)), reg); - Jump initlenTwoGuard = masm.guardArrayExtent(offsetof(JSObject, initializedLength), + Jump initlenTwoGuard = masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), objReg, key, Assembler::NotEqual); stubcc.linkExit(initlenTwoGuard, Uses(3)); @@ -785,7 +791,7 @@ mjit::Compiler::compileArrayWithArgs(uint32 argc) } masm.storePtr(ImmIntPtr(intptr_t(argc)), - Address(result, offsetof(JSObject, initializedLength))); + Address(result, JSObject::offsetOfInitializedLength())); stubcc.leave(); diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index e61c5e1a6de9..92b83404e899 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1102,6 +1102,8 @@ mjit::Compiler::jsop_setelem_dense() bool hoisted = loop && id->isType(JSVAL_TYPE_INT32) && loop->hoistArrayLengthCheck(DENSE_ARRAY, objv, indexv); + MaybeJump initlenExit; + if (hoisted) { FrameEntry *slotsFe = loop->invariantArraySlots(objv); slotsReg = frame.tempRegForData(slotsFe); @@ -1129,13 +1131,13 @@ mjit::Compiler::jsop_setelem_dense() // Make an OOL path for setting exactly the initialized length. Label syncTarget = stubcc.syncExitAndJump(Uses(3)); - Jump initlenGuard = masm.guardArrayExtent(offsetof(JSObject, initializedLength), + Jump initlenGuard = masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), objReg, key, Assembler::BelowOrEqual); stubcc.linkExitDirect(initlenGuard, stubcc.masm.label()); // Recheck for an exact initialized length. :TODO: would be nice to // reuse the condition bits from the previous test. - Jump exactlenGuard = stubcc.masm.guardArrayExtent(offsetof(JSObject, initializedLength), + Jump exactlenGuard = stubcc.masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), objReg, key, Assembler::NotEqual); exactlenGuard.linkTo(syncTarget, &stubcc.masm); @@ -1149,7 +1151,7 @@ mjit::Compiler::jsop_setelem_dense() stubcc.masm.bumpKey(key, 1); // Update the initialized length. - stubcc.masm.storeKey(key, Address(objReg, offsetof(JSObject, initializedLength))); + stubcc.masm.storeKey(key, Address(objReg, JSObject::offsetOfInitializedLength())); // Update the array length if needed. Jump lengthGuard = stubcc.masm.guardArrayExtent(offsetof(JSObject, privateData), @@ -1160,14 +1162,41 @@ mjit::Compiler::jsop_setelem_dense() // Restore the index. stubcc.masm.bumpKey(key, -1); - // Rejoin with the inline path. - Jump initlenExit = stubcc.masm.jump(); - stubcc.crossJump(initlenExit, masm.label()); + stubcc.masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg); + + initlenExit = stubcc.masm.jump(); masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg); slotsReg = objReg; } +#ifdef JSGC_INCREMENTAL_MJ + /* + * Write barrier. + * We skip over the barrier if we incremented initializedLength above, + * because in that case the slot we're overwriting was previously + * undefined. + */ + types::TypeSet *types = frame.extra(obj).types; + if (cx->compartment->needsBarrier() && (!types || types->propertyNeedsBarrier(cx, JSID_VOID))) { + Label barrierStart = stubcc.masm.label(); + frame.sync(stubcc.masm, Uses(3)); + stubcc.linkExitDirect(masm.jump(), barrierStart); + stubcc.masm.storePtr(slotsReg, FrameAddress(offsetof(VMFrame, scratch))); + if (key.isConstant()) + stubcc.masm.lea(Address(slotsReg, key.index() * sizeof(Value)), Registers::ArgReg1); + else + stubcc.masm.lea(BaseIndex(slotsReg, key.reg(), masm.JSVAL_SCALE), Registers::ArgReg1); + OOL_STUBCALL(stubs::WriteBarrier, REJOIN_NONE); + stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, scratch)), slotsReg); + stubcc.rejoin(Changes(0)); + } +#endif + + /* Jump over the write barrier in the initlen case. */ + if (initlenExit.isSet()) + stubcc.crossJump(initlenExit.get(), masm.label()); + // Fully store the value. :TODO: don't need to do this in the non-initlen case // if the array is packed and monomorphic. if (key.isConstant()) @@ -1501,6 +1530,14 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed) return true; } +#ifdef JSGC_INCREMENTAL_MJ + // Write barrier. + if (cx->compartment->needsBarrier()) { + jsop_setelem_slow(); + return true; + } +#endif + SetElementICInfo ic = SetElementICInfo(JSOp(*PC)); // One by one, check if the most important stack entries have registers, @@ -1588,7 +1625,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed) stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart); // Guard in range of initialized length. - Jump initlenGuard = masm.guardArrayExtent(offsetof(JSObject, initializedLength), + Jump initlenGuard = masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), ic.objReg, ic.key, Assembler::BelowOrEqual); stubcc.linkExitDirect(initlenGuard, ic.slowPathStart); @@ -1746,7 +1783,7 @@ mjit::Compiler::jsop_getelem_dense(bool isPacked) // Guard on the array's initialized length. MaybeJump initlenGuard; if (!hoisted) { - initlenGuard = masm.guardArrayExtent(offsetof(JSObject, initializedLength), + initlenGuard = masm.guardArrayExtent(JSObject::offsetOfInitializedLength(), baseReg, key, Assembler::BelowOrEqual); } @@ -2678,7 +2715,7 @@ mjit::Compiler::jsop_initelem() if (cx->typeInferenceEnabled()) { /* Update the initialized length. */ - masm.store32(Imm32(idx + 1), Address(objReg, offsetof(JSObject, initializedLength))); + masm.store32(Imm32(idx + 1), Address(objReg, JSObject::offsetOfInitializedLength())); } /* Perform the store. */ diff --git a/js/src/methodjit/FrameState-inl.h b/js/src/methodjit/FrameState-inl.h index 228376b79b7c..ed79d78f98b2 100644 --- a/js/src/methodjit/FrameState-inl.h +++ b/js/src/methodjit/FrameState-inl.h @@ -879,18 +879,24 @@ FrameState::syncAndForgetFe(FrameEntry *fe, bool markSynced) } inline JSC::MacroAssembler::Address -FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access) +FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access, RegisterID reg) { JS_ASSERT(access.script && access.nesting); - RegisterID reg = allocReg(); - Value **pbase = access.arg ? &access.nesting->argArray : &access.nesting->varArray; + const Value **pbase = access.arg ? &access.nesting->argArray : &access.nesting->varArray; masm.move(ImmPtr(pbase), reg); masm.loadPtr(Address(reg), reg); return Address(reg, access.index * sizeof(Value)); } +inline JSC::MacroAssembler::Address +FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access) +{ + RegisterID reg = allocReg(); + return loadNameAddress(access, reg); +} + inline void FrameState::forgetLoopReg(FrameEntry *fe) { @@ -1142,6 +1148,14 @@ FrameState::testObject(Assembler::Condition cond, FrameEntry *fe) return masm.testObject(cond, tempRegForType(fe)); } +inline JSC::MacroAssembler::Jump +FrameState::testGCThing(FrameEntry *fe) +{ + if (shouldAvoidTypeRemat(fe)) + return masm.testGCThing(addressOf(fe)); + return masm.testGCThing(tempRegForType(fe)); +} + inline JSC::MacroAssembler::Jump FrameState::testDouble(Assembler::Condition cond, FrameEntry *fe) { diff --git a/js/src/methodjit/FrameState.h b/js/src/methodjit/FrameState.h index e1759c579fe5..2928404b3c35 100644 --- a/js/src/methodjit/FrameState.h +++ b/js/src/methodjit/FrameState.h @@ -779,6 +779,8 @@ class FrameState */ inline Jump testObject(Assembler::Condition cond, FrameEntry *fe); + inline Jump testGCThing(FrameEntry *fe); + /* * Helper function. Tests if a slot's type is primitive. Condition must * be Equal or NotEqual. @@ -961,6 +963,8 @@ class FrameState * The compiler owns the result's base register. */ inline Address loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access); + inline Address loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access, + RegisterID reg); private: inline AnyRegisterID allocAndLoadReg(FrameEntry *fe, bool fp, RematInfo::RematType type); diff --git a/js/src/methodjit/LoopState.cpp b/js/src/methodjit/LoopState.cpp index 018b47203a1c..79b80480ec8c 100644 --- a/js/src/methodjit/LoopState.cpp +++ b/js/src/methodjit/LoopState.cpp @@ -1325,7 +1325,7 @@ LoopState::restoreInvariants(jsbytecode *pc, Assembler &masm, */ masm.loadPayload(frame.addressOf(entry.u.check.arraySlot), T0); if (entry.kind == InvariantEntry::DENSE_ARRAY_BOUNDS_CHECK) - masm.load32(Address(T0, offsetof(JSObject, initializedLength)), T0); + masm.load32(Address(T0, JSObject::offsetOfInitializedLength()), T0); else masm.loadPayload(Address(T0, TypedArray::lengthOffset()), T0); diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 6e43f1c9232c..3f823b6ab69c 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -39,6 +39,10 @@ #if !defined jsjaeger_h__ && defined JS_METHODJIT #define jsjaeger_h__ +#ifdef JSGC_INCREMENTAL +#define JSGC_INCREMENTAL_MJ +#endif + #include "jscntxt.h" #include "jscompartment.h" @@ -728,7 +732,7 @@ struct InlineFrame { InlineFrame *parent; jsbytecode *parentpc; - JSFunction *fun; + HeapPtrFunction fun; // Total distance between the start of the outer JSStackFrame and the start // of this frame, in multiples of sizeof(Value). diff --git a/js/src/methodjit/NunboxAssembler.h b/js/src/methodjit/NunboxAssembler.h index db41f966e7f0..8dc2a1fa76c1 100644 --- a/js/src/methodjit/NunboxAssembler.h +++ b/js/src/methodjit/NunboxAssembler.h @@ -402,6 +402,14 @@ class NunboxAssembler : public JSC::MacroAssembler return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_OBJECT)); } + Jump testGCThing(RegisterID reg) { + return branch32(AboveOrEqual, reg, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET)); + } + + Jump testGCThing(Address address) { + return branch32(AboveOrEqual, tagOf(address), ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET)); + } + Jump testDouble(Condition cond, RegisterID reg) { Condition opcond; if (cond == Equal) diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index bed8c8131777..167681cbe335 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -3224,6 +3224,21 @@ SetElementIC::update(VMFrame &f, const Value &objval, const Value &idval) return disable(f.cx, "unsupported object type"); } +bool +SetElementIC::shouldUpdate(JSContext *cx) +{ + if (!hit) { + hit = true; + spew(cx, "ignored", "first hit"); + return false; + } +#ifdef JSGC_INCREMENTAL_MJ + JS_ASSERT(!cx->compartment->needsBarrier()); +#endif + JS_ASSERT(stubsGenerated < MAX_PIC_STUBS); + return true; +} + template void JS_FASTCALL ic::SetElement(VMFrame &f, ic::SetElementIC *ic) diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index b70ae2c9c1c2..f54170241dbd 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -370,6 +370,7 @@ struct SetElementIC : public BaseIC { LookupStatus update(VMFrame &f, const Value &objval, const Value &idval); LookupStatus disable(JSContext *cx, const char *reason); LookupStatus error(JSContext *cx); + bool shouldUpdate(JSContext *cx); }; struct PICInfo : public BasePolyIC { diff --git a/js/src/methodjit/PunboxAssembler.h b/js/src/methodjit/PunboxAssembler.h index 7ebac0e6653b..9b59930a9520 100644 --- a/js/src/methodjit/PunboxAssembler.h +++ b/js/src/methodjit/PunboxAssembler.h @@ -338,6 +338,16 @@ class PunboxAssembler : public JSC::MacroAssembler return testObject(cond, Registers::ValueReg); } + Jump testGCThing(RegisterID reg) { + return branchPtr(AboveOrEqual, reg, ImmTag(JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET)); + } + + Jump testGCThing(Address address) { + loadValue(address, Registers::ValueReg); + return branchPtr(AboveOrEqual, Registers::ValueReg, + ImmTag(JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET)); + } + Jump testDouble(Condition cond, RegisterID reg) { cond = (cond == Equal) ? BelowOrEqual : Above; return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_MAX_DOUBLE)); diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 04c077371347..b1cca5e56258 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -43,6 +43,7 @@ #include "jsobj.h" #include "jslibmath.h" #include "jsiter.h" +#include "jsgcmark.h" #include "jsnum.h" #include "jsxml.h" #include "jsbool.h" @@ -2548,3 +2549,17 @@ stubs::ConvertToTypedFloat(JSContext *cx, Value *vp) vp->setDouble(d); } } + +void JS_FASTCALL +stubs::WriteBarrier(VMFrame &f, Value *addr) +{ + js::gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), *addr, "write barrier"); +} + +void JS_FASTCALL +stubs::GCThingWriteBarrier(VMFrame &f, Value *addr) +{ + gc::Cell *cell = (gc::Cell *)addr->toGCThing(); + if (cell && !cell->isMarked()) + gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), *addr, "write barrier"); +} diff --git a/js/src/methodjit/StubCalls.h b/js/src/methodjit/StubCalls.h index 717ae4f9ecc9..a75bb01f6243 100644 --- a/js/src/methodjit/StubCalls.h +++ b/js/src/methodjit/StubCalls.h @@ -231,6 +231,9 @@ NewDenseUnallocatedArray(VMFrame &f, uint32 length); void JS_FASTCALL ArrayConcatTwoArrays(VMFrame &f); void JS_FASTCALL ArrayShift(VMFrame &f); +void JS_FASTCALL WriteBarrier(VMFrame &f, Value *addr); +void JS_FASTCALL GCThingWriteBarrier(VMFrame &f, Value *addr); + } /* namespace stubs */ /* diff --git a/js/src/shell/jsheaptools.cpp b/js/src/shell/jsheaptools.cpp index e7fe1a35d014..96eda0751eb1 100644 --- a/js/src/shell/jsheaptools.cpp +++ b/js/src/shell/jsheaptools.cpp @@ -160,8 +160,7 @@ class HeapReverser : public JSTracer { /* Construct a HeapReverser for |context|'s heap. */ HeapReverser(JSContext *cx) : map(cx), work(cx), parent(NULL) { - context = cx; - callback = traverseEdgeWithThis; + JS_TRACER_INIT(this, cx, traverseEdgeWithThis); } bool init() { return map.init(); } diff --git a/js/src/tracejit/Writer.cpp b/js/src/tracejit/Writer.cpp index 8f6476e8429f..5d4276962e37 100644 --- a/js/src/tracejit/Writer.cpp +++ b/js/src/tracejit/Writer.cpp @@ -403,11 +403,13 @@ void ValidateWriter::checkAccSet(LOpcode op, LIns *base, int32_t disp, AccSet ac // // base = // ins = ldp.obj base[offsetof(JSObject, )] - #define OK_OBJ_FIELD(ldop, field) \ + #define OK_OBJ_FIELD_OFF(ldop, fieldoff) \ ((op == (ldop)) && \ - (disp == offsetof(JSObject, field)) && \ + (disp == fieldoff) && \ couldBeObjectOrString(base)) + #define OK_OBJ_FIELD(ldop, field) OK_OBJ_FIELD_OFF(ldop, offsetof(JSObject, field)) + case ACCSET_OBJ_CLASP: ok = OK_OBJ_FIELD(LIR_ldp, clasp); break; @@ -441,7 +443,8 @@ void ValidateWriter::checkAccSet(LOpcode op, LIns *base, int32_t disp, AccSet ac break; case ACCSET_OBJ_CAPACITY: - ok = OK_OBJ_FIELD(LIR_ldi, capacity) || OK_OBJ_FIELD(LIR_ldi, initializedLength); + ok = OK_OBJ_FIELD(LIR_ldi, capacity) || + OK_OBJ_FIELD_OFF(LIR_ldi, (int32_t)JSObject::offsetOfInitializedLength()); break; case ACCSET_OBJ_SLOTS: diff --git a/js/src/tracejit/Writer.h b/js/src/tracejit/Writer.h index ab96acca2bf4..f2dfe1d150c3 100644 --- a/js/src/tracejit/Writer.h +++ b/js/src/tracejit/Writer.h @@ -525,7 +525,7 @@ class Writer } nj::LIns *ldiDenseArrayInitializedLength(nj::LIns *array) const { - return name(lir->insLoad(nj::LIR_ldi, array, offsetof(JSObject, initializedLength), + return name(lir->insLoad(nj::LIR_ldi, array, JSObject::offsetOfInitializedLength(), ACCSET_OBJ_CAPACITY), "capacity"); } diff --git a/js/src/vm/ArgumentsObject-inl.h b/js/src/vm/ArgumentsObject-inl.h index 9103151c6fa7..e502afd1828b 100644 --- a/js/src/vm/ArgumentsObject-inl.h +++ b/js/src/vm/ArgumentsObject-inl.h @@ -46,10 +46,10 @@ namespace js { inline void -ArgumentsObject::setInitialLength(uint32 length) +ArgumentsObject::initInitialLength(uint32 length) { JS_ASSERT(getSlot(INITIAL_LENGTH_SLOT).isUndefined()); - setSlot(INITIAL_LENGTH_SLOT, Int32Value(length << PACKED_BITS_COUNT)); + initSlot(INITIAL_LENGTH_SLOT, Int32Value(length << PACKED_BITS_COUNT)); JS_ASSERT((getSlot(INITIAL_LENGTH_SLOT).toInt32() >> PACKED_BITS_COUNT) == int32(length)); JS_ASSERT(!hasOverriddenLength()); } @@ -77,11 +77,10 @@ ArgumentsObject::hasOverriddenLength() const } inline void -ArgumentsObject::setCalleeAndData(JSObject &callee, ArgumentsData *data) +ArgumentsObject::initData(ArgumentsData *data) { JS_ASSERT(getSlot(DATA_SLOT).isUndefined()); - setSlot(DATA_SLOT, PrivateValue(data)); - data->callee.setObject(callee); + initSlot(DATA_SLOT, PrivateValue(data)); } inline ArgumentsData * @@ -100,7 +99,7 @@ ArgumentsObject::element(uint32 i) const inline const js::Value * ArgumentsObject::elements() const { - return data()->slots; + return Valueify(data()->slots); } inline void @@ -150,7 +149,7 @@ NormalArgumentsObject::callee() const inline void NormalArgumentsObject::clearCallee() { - data()->callee = MagicValue(JS_ARGS_HOLE); + data()->callee.set(compartment(), MagicValue(JS_ARGS_HOLE)); } } // namespace js diff --git a/js/src/vm/ArgumentsObject.h b/js/src/vm/ArgumentsObject.h index 7b64716f1cb0..aeefbe3b6445 100644 --- a/js/src/vm/ArgumentsObject.h +++ b/js/src/vm/ArgumentsObject.h @@ -92,13 +92,13 @@ struct ArgumentsData * arguments.callee, or MagicValue(JS_ARGS_HOLE) if arguments.callee has * been modified. */ - js::Value callee; + HeapValue callee; /* * Values of the arguments for this object, or MagicValue(JS_ARGS_HOLE) if * the indexed argument has been modified. */ - js::Value slots[1]; + HeapValue slots[1]; }; /* @@ -183,9 +183,9 @@ class ArgumentsObject : public ::JSObject friend struct mjit::ic::GetElementIC; #endif - void setInitialLength(uint32 length); + void initInitialLength(uint32 length); - void setCalleeAndData(JSObject &callee, ArgumentsData *data); + void initData(ArgumentsData *data); public: /* Create an arguments object for the given callee function. */ diff --git a/js/src/vm/CallObject-inl.h b/js/src/vm/CallObject-inl.h index b869853fb5a1..5cfd7371c21f 100644 --- a/js/src/vm/CallObject-inl.h +++ b/js/src/vm/CallObject-inl.h @@ -73,6 +73,13 @@ CallObject::setCallee(JSObject *callee) setFixedSlot(CALLEE_SLOT, js::ObjectOrNullValue(callee)); } +inline void +CallObject::initCallee(JSObject *callee) +{ + JS_ASSERT_IF(callee, callee->isFunction()); + initFixedSlot(CALLEE_SLOT, js::ObjectOrNullValue(callee)); +} + inline JSObject * CallObject::getCallee() const { @@ -99,6 +106,13 @@ CallObject::setArguments(const js::Value &v) setFixedSlot(ARGUMENTS_SLOT, v); } +inline void +CallObject::initArguments(const js::Value &v) +{ + JS_ASSERT(!isForEval()); + initFixedSlot(ARGUMENTS_SLOT, v); +} + inline const js::Value & CallObject::arg(uintN i) const { @@ -113,6 +127,13 @@ CallObject::setArg(uintN i, const js::Value &v) setSlot(RESERVED_SLOTS + i, v); } +inline void +CallObject::initArgUnchecked(uintN i, const js::Value &v) +{ + JS_ASSERT(i < getCalleeFunction()->nargs); + initSlotUnchecked(RESERVED_SLOTS + i, v); +} + inline const js::Value & CallObject::var(uintN i) const { @@ -131,29 +152,38 @@ CallObject::setVar(uintN i, const js::Value &v) setSlot(RESERVED_SLOTS + fun->nargs + i, v); } +inline void +CallObject::initVarUnchecked(uintN i, const js::Value &v) +{ + JSFunction *fun = getCalleeFunction(); + JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs()); + JS_ASSERT(i < fun->script()->bindings.countVars()); + initSlotUnchecked(RESERVED_SLOTS + fun->nargs + i, v); +} + inline void CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots) { JS_ASSERT(numSlots() >= RESERVED_SLOTS + nargs + nvars); - copySlotRange(RESERVED_SLOTS, argv, nargs); - copySlotRange(RESERVED_SLOTS + nargs, slots, nvars); + copySlotRange(RESERVED_SLOTS, argv, nargs, true); + copySlotRange(RESERVED_SLOTS + nargs, slots, nvars, true); } -inline js::Value * +inline js::HeapValueArray CallObject::argArray() { js::DebugOnly fun = getCalleeFunction(); JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS, fun->nargs)); - return getSlotAddress(RESERVED_SLOTS); + return HeapValueArray(getSlotAddress(RESERVED_SLOTS)); } -inline js::Value * +inline js::HeapValueArray CallObject::varArray() { JSFunction *fun = getCalleeFunction(); JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS + fun->nargs, fun->script()->bindings.countVars())); - return getSlotAddress(RESERVED_SLOTS + fun->nargs); + return HeapValueArray(getSlotAddress(RESERVED_SLOTS + fun->nargs)); } } diff --git a/js/src/vm/CallObject.cpp b/js/src/vm/CallObject.cpp index 63174325a08b..21b8ea5fd677 100644 --- a/js/src/vm/CallObject.cpp +++ b/js/src/vm/CallObject.cpp @@ -83,7 +83,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje return NULL; #ifdef DEBUG - for (Shape::Range r = obj->lastProp; !r.empty(); r.popFront()) { + for (Shape::Range r = obj->lastProperty(); !r.empty(); r.popFront()) { const Shape &s = r.front(); if (s.slot != SHAPE_INVALID_SLOT) { JS_ASSERT(s.slot + 1 == obj->slotSpan()); @@ -93,7 +93,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje #endif CallObject &callobj = obj->asCall(); - callobj.setCallee(callee); + callobj.initCallee(callee); return &callobj; } diff --git a/js/src/vm/CallObject.h b/js/src/vm/CallObject.h index a382d25edde9..ff745d8e153f 100644 --- a/js/src/vm/CallObject.h +++ b/js/src/vm/CallObject.h @@ -78,28 +78,32 @@ class CallObject : public ::JSObject * invocation, or null if it was created for a strict mode eval frame. */ inline JSObject *getCallee() const; - inline JSFunction *getCalleeFunction() const; + inline JSFunction *getCalleeFunction() const; inline void setCallee(JSObject *callee); + inline void initCallee(JSObject *callee); /* Returns the callee's arguments object. */ inline const js::Value &getArguments() const; inline void setArguments(const js::Value &v); + inline void initArguments(const js::Value &v); /* Returns the formal argument at the given index. */ inline const js::Value &arg(uintN i) const; inline void setArg(uintN i, const js::Value &v); + inline void initArgUnchecked(uintN i, const js::Value &v); /* Returns the variable at the given index. */ inline const js::Value &var(uintN i) const; inline void setVar(uintN i, const js::Value &v); + inline void initVarUnchecked(uintN i, const js::Value &v); /* * Get the actual arrays of arguments and variables. Only call if type * inference is enabled, where we ensure that call object variables are in * contiguous slots (see NewCallObject). */ - inline js::Value *argArray(); - inline js::Value *varArray(); + inline js::HeapValueArray argArray(); + inline js::HeapValueArray varArray(); inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots); }; diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index dbaf01512a14..d2928e13edae 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -223,7 +223,7 @@ BreakpointSite::clearTrap(JSContext *cx, BreakpointSiteMap::Enum *e, *closurep = trapClosure; trapHandler = NULL; - trapClosure.setUndefined(); + trapClosure = UndefinedValue(); if (enabledCount == 0) { *pc = realOpcode; if (!cx->runtime->gcRunning) { @@ -483,12 +483,12 @@ Debugger::slowPathOnLeaveFrame(JSContext *cx) bool Debugger::wrapDebuggeeValue(JSContext *cx, Value *vp) { - assertSameCompartment(cx, object); + assertSameCompartment(cx, object.get()); if (vp->isObject()) { JSObject *obj = &vp->toObject(); - CellWeakMap::AddPtr p = objects.lookupForAdd(obj); + ObjectWeakMap::AddPtr p = objects.lookupForAdd(obj); if (p) { vp->setObject(*p->value); } else { @@ -517,7 +517,7 @@ Debugger::wrapDebuggeeValue(JSContext *cx, Value *vp) bool Debugger::unwrapDebuggeeValue(JSContext *cx, Value *vp) { - assertSameCompartment(cx, object, *vp); + assertSameCompartment(cx, object.get(), *vp); if (vp->isObject()) { JSObject *dobj = &vp->toObject(); if (dobj->getClass() != &DebuggerObject_class) { @@ -1005,9 +1005,9 @@ Debugger::onSingleStep(JSContext *cx, Value *vp) /*** Debugger JSObjects **************************************************************************/ void -Debugger::markKeysInCompartment(JSTracer *tracer, const CellWeakMap &map, bool scripts) +Debugger::markKeysInCompartment(JSTracer *tracer) { - JSCompartment *comp = tracer->context->runtime->gcCurrentCompartment; + JSCompartment *comp = tracer->runtime->gcCurrentCompartment; JS_ASSERT(comp); /* @@ -1015,19 +1015,22 @@ Debugger::markKeysInCompartment(JSTracer *tracer, const CellWeakMap &map, bool s * enumerating WeakMap keys. However in this case we need access, so we * make a base-class reference. Range is public in HashMap. */ - typedef HashMap, RuntimeAllocPolicy> Map; - const Map &storage = map; - for (Map::Range r = storage.all(); !r.empty(); r.popFront()) { - gc::Cell *key = r.front().key; - if (key->compartment() == comp && IsAboutToBeFinalized(tracer->context, key)) { - if (scripts) { - js::gc::MarkScript(tracer, static_cast(key), - "cross-compartment WeakMap key"); - } else { - js::gc::MarkObject(tracer, *static_cast(key), - "cross-compartment WeakMap key"); - } - } + typedef HashMap, RuntimeAllocPolicy> + ObjectMap; + const ObjectMap &objStorage = objects; + for (ObjectMap::Range r = objStorage.all(); !r.empty(); r.popFront()) { + const HeapPtrObject &key = r.front().key; + if (key->compartment() == comp && IsAboutToBeFinalized(tracer->context, key)) + js::gc::MarkObject(tracer, key, "cross-compartment WeakMap key"); + } + + typedef HashMap, RuntimeAllocPolicy> + ScriptMap; + const ScriptMap &scriptStorage = scripts; + for (ScriptMap::Range r = scriptStorage.all(); !r.empty(); r.popFront()) { + const HeapPtrScript &key = r.front().key; + if (key->compartment() == comp && IsAboutToBeFinalized(tracer->context, key)) + js::gc::MarkScript(tracer, key, "cross-compartment WeakMap key"); } } @@ -1057,7 +1060,7 @@ Debugger::markKeysInCompartment(JSTracer *tracer, const CellWeakMap &map, bool s void Debugger::markCrossCompartmentDebuggerObjectReferents(JSTracer *tracer) { - JSRuntime *rt = tracer->context->runtime; + JSRuntime *rt = tracer->runtime; JSCompartment *comp = rt->gcCurrentCompartment; /* @@ -1066,10 +1069,8 @@ Debugger::markCrossCompartmentDebuggerObjectReferents(JSTracer *tracer) */ for (JSCList *p = &rt->debuggerList; (p = JS_NEXT_LINK(p)) != &rt->debuggerList;) { Debugger *dbg = Debugger::fromLinks(p); - if (dbg->object->compartment() != comp) { - markKeysInCompartment(tracer, dbg->objects, false); - markKeysInCompartment(tracer, dbg->scripts, true); - } + if (dbg->object->compartment() != comp) + dbg->markKeysInCompartment(tracer); } } @@ -1128,7 +1129,7 @@ Debugger::markAllIteratively(GCMarker *trc) * - it isn't already marked * - it actually has hooks that might be called */ - JSObject *dbgobj = dbg->toJSObject(); + const HeapPtrObject &dbgobj = dbg->toJSObject(); if (comp && comp != dbgobj->compartment()) continue; @@ -1138,7 +1139,7 @@ Debugger::markAllIteratively(GCMarker *trc) * obj could be reachable only via its live, enabled * debugger hooks, which may yet be called. */ - MarkObject(trc, *dbgobj, "enabled Debugger"); + MarkObject(trc, dbgobj, "enabled Debugger"); markedAny = true; dbgMarked = true; } @@ -1151,9 +1152,9 @@ Debugger::markAllIteratively(GCMarker *trc) * The debugger and the script are both live. * Therefore the breakpoint handler is live. */ - JSObject *handler = bp->getHandler(); + const HeapPtrObject &handler = bp->getHandler(); if (IsAboutToBeFinalized(cx, handler)) { - MarkObject(trc, *bp->getHandler(), "breakpoint handler"); + MarkObject(trc, bp->getHandler(), "breakpoint handler"); markedAny = true; } } @@ -1176,7 +1177,7 @@ void Debugger::trace(JSTracer *trc) { if (uncaughtExceptionHook) - MarkObject(trc, *uncaughtExceptionHook, "hooks"); + MarkObject(trc, uncaughtExceptionHook, "hooks"); /* * Mark Debugger.Frame objects. These are all reachable from JS, because the @@ -1187,9 +1188,9 @@ Debugger::trace(JSTracer *trc) * frames.) */ for (FrameMap::Range r = frames.all(); !r.empty(); r.popFront()) { - JSObject *frameobj = r.front().value; + const HeapPtrObject &frameobj = r.front().value; JS_ASSERT(frameobj->getPrivate()); - MarkObject(trc, *frameobj, "live Debugger.Frame"); + MarkObject(trc, frameobj, "live Debugger.Frame"); } /* Trace the referent -> Debugger.Object weak map. */ @@ -1786,9 +1787,11 @@ GetScriptReferent(JSObject *obj) static void DebuggerScript_trace(JSTracer *trc, JSObject *obj) { - if (!trc->context->runtime->gcCurrentCompartment) { + if (!trc->runtime->gcCurrentCompartment) { + /* This comes from a private pointer, so no barrier needed. */ if (JSScript *script = GetScriptReferent(obj)) - MarkScript(trc, script, "Debugger.Script referent"); + MarkScriptUnbarriered(trc, script, "Debugger.Script referent"); + } } @@ -1808,15 +1811,15 @@ Class DebuggerScript_class = { JSObject * Debugger::newDebuggerScript(JSContext *cx, JSScript *script) { - assertSameCompartment(cx, object); + assertSameCompartment(cx, object.get()); JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_SCRIPT_PROTO).toObject(); JS_ASSERT(proto); JSObject *scriptobj = NewNonFunction(cx, &DebuggerScript_class, proto, NULL); if (!scriptobj || !scriptobj->ensureClassReservedSlots(cx)) return NULL; - scriptobj->setPrivate(script); scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_OWNER, ObjectValue(*object)); + scriptobj->setPrivate(script); return scriptobj; } @@ -1824,9 +1827,9 @@ Debugger::newDebuggerScript(JSContext *cx, JSScript *script) JSObject * Debugger::wrapScript(JSContext *cx, JSScript *script) { - assertSameCompartment(cx, object); + assertSameCompartment(cx, object.get()); JS_ASSERT(cx->compartment != script->compartment()); - CellWeakMap::AddPtr p = scripts.lookupForAdd(script); + ScriptWeakMap::AddPtr p = scripts.lookupForAdd(script); if (!p) { JSObject *scriptobj = newDebuggerScript(cx, script); @@ -2857,9 +2860,13 @@ static JSFunctionSpec DebuggerFrame_methods[] = { static void DebuggerObject_trace(JSTracer *trc, JSObject *obj) { - if (!trc->context->runtime->gcCurrentCompartment) { + if (!trc->runtime->gcCurrentCompartment) { + /* + * There is a barrier on private pointers, so the Unbarriered marking + * is okay. + */ if (JSObject *referent = (JSObject *) obj->getPrivate()) - MarkObject(trc, *referent, "Debugger.Object referent"); + MarkObjectUnbarriered(trc, referent, "Debugger.Object referent"); } } diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index f8bed2db2343..bd99ee85f621 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -50,6 +50,7 @@ #include "jsweakmap.h" #include "jswrapper.h" +#include "gc/Barrier.h" #include "js/HashTable.h" #include "vm/GlobalObject.h" @@ -81,9 +82,9 @@ class Debugger { private: JSCList link; /* See JSRuntime::debuggerList. */ - JSObject *object; /* The Debugger object. Strong reference. */ + HeapPtrObject object; /* The Debugger object. Strong reference. */ GlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */ - JSObject *uncaughtExceptionHook; /* Strong reference. */ + js::HeapPtrObject uncaughtExceptionHook; /* Strong reference. */ bool enabled; JSCList breakpoints; /* cyclic list of all js::Breakpoints in this debugger */ @@ -100,18 +101,17 @@ class Debugger { * that way, but since stack frames are not gc-things, the implementation * has to be different. */ - typedef HashMap, RuntimeAllocPolicy> + typedef HashMap, RuntimeAllocPolicy> FrameMap; FrameMap frames; - typedef WeakMap, CrossCompartmentMarkPolicy> - CellWeakMap; - /* The map from debuggee objects to their Debugger.Object instances. */ - CellWeakMap objects; + typedef WeakMap ObjectWeakMap; + ObjectWeakMap objects; /* An ephemeral map from JSScript* to Debugger.Script instances. */ - CellWeakMap scripts; + typedef WeakMap ScriptWeakMap; + ScriptWeakMap scripts; bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj); void removeDebuggeeGlobal(JSContext *cx, GlobalObject *global, @@ -167,7 +167,7 @@ class Debugger { static void traceObject(JSTracer *trc, JSObject *obj); void trace(JSTracer *trc); static void finalize(JSContext *cx, JSObject *obj); - static void markKeysInCompartment(JSTracer *tracer, const CellWeakMap &map, bool scripts); + void markKeysInCompartment(JSTracer *tracer); static Class jsclass; @@ -229,7 +229,7 @@ class Debugger { ~Debugger(); bool init(JSContext *cx); - inline JSObject *toJSObject() const; + inline const js::HeapPtrObject &toJSObject() const; static inline Debugger *fromJSObject(JSObject *obj); static Debugger *fromChildJSObject(JSObject *obj); @@ -363,7 +363,7 @@ class BreakpointSite { JSCList breakpoints; /* cyclic list of all js::Breakpoints at this instruction */ size_t enabledCount; /* number of breakpoints in the list that are enabled */ JSTrapHandler trapHandler; /* jsdbgapi trap state */ - Value trapClosure; + HeapValue trapClosure; bool recompile(JSContext *cx, bool forTrap); @@ -408,7 +408,7 @@ class Breakpoint { Debugger * const debugger; BreakpointSite * const site; private: - JSObject *handler; + js::HeapPtrObject handler; JSCList debuggerLinks; JSCList siteLinks; @@ -419,7 +419,7 @@ class Breakpoint { void destroy(JSContext *cx, BreakpointSiteMap::Enum *e = NULL); Breakpoint *nextInDebugger(); Breakpoint *nextInSite(); - JSObject *getHandler() const { return handler; } + const HeapPtrObject &getHandler() const { return handler; } }; Debugger * @@ -437,7 +437,7 @@ Debugger::firstBreakpoint() const return Breakpoint::fromDebuggerLinks(JS_NEXT_LINK(&breakpoints)); } -JSObject * +const js::HeapPtrObject & Debugger::toJSObject() const { JS_ASSERT(object); diff --git a/js/src/vm/GlobalObject-inl.h b/js/src/vm/GlobalObject-inl.h new file mode 100644 index 000000000000..016be678bff7 --- /dev/null +++ b/js/src/vm/GlobalObject-inl.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=78: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is SpiderMonkey global object code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Jeff Walden (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GlobalObject_inl_h___ +#define GlobalObject_inl_h___ + +namespace js { + +inline void +GlobalObject::setFlags(int32 flags) +{ + setSlot(FLAGS, Int32Value(flags)); +} + +inline void +GlobalObject::initFlags(int32 flags) +{ + initSlot(FLAGS, Int32Value(flags)); +} + +inline void +GlobalObject::setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) +{ + HeapValue &ctorVal = getSlotRef(key); + HeapValue &protoVal = getSlotRef(JSProto_LIMIT + key); + HeapValue &visibleVal = getSlotRef(2 * JSProto_LIMIT + key); + JS_ASSERT(ctorVal.isUndefined()); + JS_ASSERT(protoVal.isUndefined()); + JS_ASSERT(visibleVal.isUndefined()); + ctorVal = ObjectValue(*ctor); + protoVal = ObjectValue(*proto); + visibleVal = ctorVal; +} + +inline void +GlobalObject::setObjectClassDetails(JSFunction *ctor, JSObject *proto) +{ + setDetailsForKey(JSProto_Object, ctor, proto); +} + +inline void +GlobalObject::setFunctionClassDetails(JSFunction *ctor, JSObject *proto) +{ + setDetailsForKey(JSProto_Function, ctor, proto); +} + +void +GlobalObject::setThrowTypeError(JSFunction *fun) +{ + HeapValue &v = getSlotRef(THROWTYPEERROR); + JS_ASSERT(v.isUndefined()); + v = ObjectValue(*fun); +} + +void +GlobalObject::setOriginalEval(JSObject *evalobj) +{ + HeapValue &v = getSlotRef(EVAL); + JS_ASSERT(v.isUndefined()); + v = ObjectValue(*evalobj); +} + +} // namespace js + +#endif diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index e284cf969c86..d2a7e8c3fd81 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -47,9 +47,11 @@ #include "builtin/RegExp.h" #include "frontend/BytecodeEmitter.h" +#include "vm/GlobalObject-inl.h" #include "jsobjinlines.h" #include "vm/RegExpObject-inl.h" +#include "vm/RegExpStatics-inl.h" using namespace js; @@ -134,7 +136,7 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx) script->noScriptRval = true; script->code[0] = JSOP_STOP; script->code[1] = SRC_NULL; - functionProto->setScript(script); + functionProto->initScript(script); functionProto->getType(cx)->interpretedFunction = functionProto; script->hasFunction = true; } @@ -258,8 +260,8 @@ GlobalObject::create(JSContext *cx, Class *clasp) JSObject *res = RegExpStatics::create(cx, globalObj); if (!res) return NULL; - globalObj->setSlot(REGEXP_STATICS, ObjectValue(*res)); - globalObj->setFlags(0); + globalObj->initSlot(REGEXP_STATICS, ObjectValue(*res)); + globalObj->initFlags(0); return globalObj; } @@ -337,7 +339,7 @@ GlobalObject::clear(JSContext *cx) bool GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx) { - Value &v = getSlotRef(RUNTIME_CODEGEN_ENABLED); + HeapValue &v = getSlotRef(RUNTIME_CODEGEN_ENABLED); if (v.isUndefined()) { JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx); @@ -345,8 +347,9 @@ GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx) * If there are callbacks, make sure that the CSP callback is installed * and that it permits runtime code generation, then cache the result. */ - v = BooleanValue((!callbacks || !callbacks->contentSecurityPolicyAllows) || - callbacks->contentSecurityPolicyAllows(cx)); + v.set(compartment(), + BooleanValue((!callbacks || !callbacks->contentSecurityPolicyAllows) || + callbacks->contentSecurityPolicyAllows(cx))); } return !v.isFalse(); } diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 6363f1c7d24f..cc890b9d6c46 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -120,9 +120,8 @@ class GlobalObject : public ::JSObject { static const int32 FLAGS_CLEARED = 0x1; - void setFlags(int32 flags) { - setSlot(FLAGS, Int32Value(flags)); - } + inline void setFlags(int32 flags); + inline void initFlags(int32 flags); friend JSObject * ::js_InitObjectClass(JSContext *cx, JSObject *obj); @@ -133,37 +132,13 @@ class GlobalObject : public ::JSObject { JSObject * initFunctionAndObjectClasses(JSContext *cx); - void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) { - Value &ctorVal = getSlotRef(key); - Value &protoVal = getSlotRef(JSProto_LIMIT + key); - Value &visibleVal = getSlotRef(2 * JSProto_LIMIT + key); - JS_ASSERT(ctorVal.isUndefined()); - JS_ASSERT(protoVal.isUndefined()); - JS_ASSERT(visibleVal.isUndefined()); - ctorVal = ObjectValue(*ctor); - protoVal = ObjectValue(*proto); - visibleVal = ctorVal; - } + inline void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto); + inline void setObjectClassDetails(JSFunction *ctor, JSObject *proto); + inline void setFunctionClassDetails(JSFunction *ctor, JSObject *proto); - void setObjectClassDetails(JSFunction *ctor, JSObject *proto) { - setDetailsForKey(JSProto_Object, ctor, proto); - } + inline void setThrowTypeError(JSFunction *fun); - void setFunctionClassDetails(JSFunction *ctor, JSObject *proto) { - setDetailsForKey(JSProto_Function, ctor, proto); - } - - void setThrowTypeError(JSFunction *fun) { - Value &v = getSlotRef(THROWTYPEERROR); - JS_ASSERT(v.isUndefined()); - v.setObject(*fun); - } - - void setOriginalEval(JSObject *evalobj) { - Value &v = getSlotRef(EVAL); - JS_ASSERT(v.isUndefined()); - v.setObject(*evalobj); - } + inline void setOriginalEval(JSObject *evalobj); Value getConstructor(JSProtoKey key) const { JS_ASSERT(key <= JSProto_LIMIT); @@ -298,7 +273,7 @@ class GlobalObject : public ::JSObject { } JSObject *getOrCreateGeneratorPrototype(JSContext *cx) { - Value &v = getSlotRef(GENERATOR_PROTO); + HeapValue &v = getSlotRef(GENERATOR_PROTO); if (!v.isObject() && !js_InitIteratorClasses(cx, this)) return NULL; JS_ASSERT(v.toObject().isGenerator()); diff --git a/js/src/vm/RegExpObject-inl.h b/js/src/vm/RegExpObject-inl.h index 1a56e2bc2ce7..4abb0ea922e5 100644 --- a/js/src/vm/RegExpObject-inl.h +++ b/js/src/vm/RegExpObject-inl.h @@ -130,7 +130,7 @@ RegExpObject::purge(JSContext *cx) { if (RegExpPrivate *rep = getPrivate()) { rep->decref(cx); - setPrivate(NULL); + privateData = NULL; } } @@ -147,13 +147,14 @@ inline bool RegExpObject::init(JSContext *cx, JSLinearString *source, RegExpFlag flags) { if (nativeEmpty()) { - const js::Shape **shapep = &cx->compartment->initialRegExpShape; - if (!*shapep) { - *shapep = assignInitialShape(cx); - if (!*shapep) + const js::Shape *shape = cx->compartment->initialRegExpShape; + if (!shape) { + shape = assignInitialShape(cx); + if (!shape) return false; + cx->compartment->initialRegExpShape = shape; } - setLastProperty(*shapep); + setLastProperty(shape); JS_ASSERT(!nativeEmpty()); } @@ -177,6 +178,54 @@ RegExpObject::init(JSContext *cx, JSLinearString *source, RegExpFlag flags) return true; } +inline void +RegExpObject::setLastIndex(const Value &v) +{ + setSlot(LAST_INDEX_SLOT, v); +} + +inline void +RegExpObject::setLastIndex(double d) +{ + setSlot(LAST_INDEX_SLOT, NumberValue(d)); +} + +inline void +RegExpObject::zeroLastIndex() +{ + setSlot(LAST_INDEX_SLOT, Int32Value(0)); +} + +inline void +RegExpObject::setSource(JSLinearString *source) +{ + setSlot(SOURCE_SLOT, StringValue(source)); +} + +inline void +RegExpObject::setIgnoreCase(bool enabled) +{ + setSlot(IGNORE_CASE_FLAG_SLOT, BooleanValue(enabled)); +} + +inline void +RegExpObject::setGlobal(bool enabled) +{ + setSlot(GLOBAL_FLAG_SLOT, BooleanValue(enabled)); +} + +inline void +RegExpObject::setMultiline(bool enabled) +{ + setSlot(MULTILINE_FLAG_SLOT, BooleanValue(enabled)); +} + +inline void +RegExpObject::setSticky(bool enabled) +{ + setSlot(STICKY_FLAG_SLOT, BooleanValue(enabled)); +} + /* RegExpPrivate inlines. */ inline AlreadyIncRefed diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index 4e0ba6367aaf..d8cf59ec60e8 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -46,6 +46,7 @@ #include "jsstrinlines.h" #include "vm/RegExpObject-inl.h" +#include "vm/RegExpStatics-inl.h" #ifdef JS_TRACER #include "jstracer.h" diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index 637de1512e09..403d5bf0022a 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -113,22 +113,15 @@ class RegExpObject : public ::JSObject const Value &getLastIndex() const { return getSlot(LAST_INDEX_SLOT); } - void setLastIndex(const Value &v) { - setSlot(LAST_INDEX_SLOT, v); - } - void setLastIndex(double d) { - setSlot(LAST_INDEX_SLOT, NumberValue(d)); - } - void zeroLastIndex() { - setSlot(LAST_INDEX_SLOT, Int32Value(0)); - } + inline void setLastIndex(const Value &v); + inline void setLastIndex(double d); + inline void zeroLastIndex(); JSLinearString *getSource() const { return &getSlot(SOURCE_SLOT).toString()->asLinear(); } - void setSource(JSLinearString *source) { - setSlot(SOURCE_SLOT, StringValue(source)); - } + inline void setSource(JSLinearString *source); + RegExpFlag getFlags() const { uintN flags = 0; flags |= global() ? GlobalFlag : 0; @@ -140,10 +133,10 @@ class RegExpObject : public ::JSObject /* Flags. */ - void setIgnoreCase(bool enabled) { setSlot(IGNORE_CASE_FLAG_SLOT, BooleanValue(enabled)); } - void setGlobal(bool enabled) { setSlot(GLOBAL_FLAG_SLOT, BooleanValue(enabled)); } - void setMultiline(bool enabled) { setSlot(MULTILINE_FLAG_SLOT, BooleanValue(enabled)); } - void setSticky(bool enabled) { setSlot(STICKY_FLAG_SLOT, BooleanValue(enabled)); } + inline void setIgnoreCase(bool enabled); + inline void setGlobal(bool enabled); + inline void setMultiline(bool enabled); + inline void setSticky(bool enabled); bool ignoreCase() const { return getSlot(IGNORE_CASE_FLAG_SLOT).toBoolean(); } bool global() const { return getSlot(GLOBAL_FLAG_SLOT).toBoolean(); } bool multiline() const { return getSlot(MULTILINE_FLAG_SLOT).toBoolean(); } diff --git a/js/src/vm/RegExpStatics-inl.h b/js/src/vm/RegExpStatics-inl.h index c0c25f177e6f..feee5619cf29 100644 --- a/js/src/vm/RegExpStatics-inl.h +++ b/js/src/vm/RegExpStatics-inl.h @@ -43,8 +43,18 @@ #include "RegExpStatics.h" +#include "vm/String-inl.h" + namespace js { +inline +RegExpStatics::RegExpStatics() + : bufferLink(NULL), + copied(false) +{ + clear(); +} + inline bool RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out) const { @@ -60,7 +70,7 @@ RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *o inline bool RegExpStatics::createPendingInput(JSContext *cx, Value *out) const { - out->setString(pendingInput ? pendingInput : cx->runtime->emptyString); + out->setString(pendingInput ? pendingInput.get() : cx->runtime->emptyString); return true; } @@ -181,6 +191,78 @@ RegExpStatics::getRightContext(JSSubString *out) const out->length = matchPairsInput->length() - get(0, 1); } +inline void +RegExpStatics::copyTo(RegExpStatics &dst) +{ + dst.matchPairs.clear(); + /* 'save' has already reserved space in matchPairs */ + dst.matchPairs.infallibleAppend(matchPairs); + dst.matchPairsInput = matchPairsInput; + dst.pendingInput = pendingInput; + dst.flags = flags; +} + +inline void +RegExpStatics::aboutToWrite() +{ + if (bufferLink && !bufferLink->copied) { + copyTo(*bufferLink); + bufferLink->copied = true; + } +} + +inline void +RegExpStatics::restore() +{ + if (bufferLink->copied) + bufferLink->copyTo(*this); + bufferLink = bufferLink->bufferLink; +} + +inline bool +RegExpStatics::updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs *newPairs) +{ + JS_ASSERT(input); + aboutToWrite(); + BarrieredSetPair(cx->compartment, + pendingInput, input, + matchPairsInput, input); + + if (!matchPairs.resizeUninitialized(2 * newPairs->pairCount())) { + js_ReportOutOfMemory(cx); + return false; + } + + for (size_t i = 0; i < newPairs->pairCount(); ++i) { + matchPairs[2 * i] = newPairs->pair(i).start; + matchPairs[2 * i + 1] = newPairs->pair(i).limit; + } + + return true; +} + +inline void +RegExpStatics::clear() +{ + aboutToWrite(); + flags = RegExpFlag(0); + pendingInput = NULL; + matchPairsInput = NULL; + matchPairs.clear(); +} + +inline void +RegExpStatics::setPendingInput(JSString *newInput) +{ + aboutToWrite(); + pendingInput = newInput; +} + +PreserveRegExpStatics::~PreserveRegExpStatics() +{ + original->restore(); +} + inline void RegExpStatics::setMultiline(JSContext *cx, bool enabled) { diff --git a/js/src/vm/RegExpStatics.cpp b/js/src/vm/RegExpStatics.cpp index 972cd0469aa7..1ed77ecefb27 100644 --- a/js/src/vm/RegExpStatics.cpp +++ b/js/src/vm/RegExpStatics.cpp @@ -42,6 +42,8 @@ #include "jsobjinlines.h" +#include "vm/RegExpStatics-inl.h" + using namespace js; /* @@ -96,6 +98,6 @@ RegExpStatics::create(JSContext *cx, GlobalObject *parent) RegExpStatics *res = cx->new_(); if (!res) return NULL; - obj->setPrivate(static_cast(res)); + obj->initPrivate(static_cast(res)); return obj; } diff --git a/js/src/vm/RegExpStatics.h b/js/src/vm/RegExpStatics.h index 25b9e9c11d3f..77db01e49f6f 100644 --- a/js/src/vm/RegExpStatics.h +++ b/js/src/vm/RegExpStatics.h @@ -42,7 +42,9 @@ #define RegExpStatics_h__ #include "jscntxt.h" +#include "jsgcmark.h" +#include "gc/Barrier.h" #include "js/Vector.h" #include "vm/MatchPairs.h" @@ -52,32 +54,20 @@ namespace js { class RegExpStatics { typedef Vector Pairs; - Pairs matchPairs; + Pairs matchPairs; /* The input that was used to produce matchPairs. */ - JSLinearString *matchPairsInput; + HeapPtr matchPairsInput; /* The input last set on the statics. */ - JSString *pendingInput; - RegExpFlag flags; - RegExpStatics *bufferLink; - bool copied; + HeapPtr pendingInput; + RegExpFlag flags; + RegExpStatics *bufferLink; + bool copied; bool createDependent(JSContext *cx, size_t start, size_t end, Value *out) const; - void copyTo(RegExpStatics &dst) { - dst.matchPairs.clear(); - /* 'save' has already reserved space in matchPairs */ - dst.matchPairs.infallibleAppend(matchPairs); - dst.matchPairsInput = matchPairsInput; - dst.pendingInput = pendingInput; - dst.flags = flags; - } + inline void copyTo(RegExpStatics &dst); - void aboutToWrite() { - if (bufferLink && !bufferLink->copied) { - copyTo(*bufferLink); - bufferLink->copied = true; - } - } + inline void aboutToWrite(); bool save(JSContext *cx, RegExpStatics *buffer) { JS_ASSERT(!buffer->copied && !buffer->bufferLink); @@ -90,11 +80,7 @@ class RegExpStatics return true; } - void restore() { - if (bufferLink->copied) - bufferLink->copyTo(*this); - bufferLink = bufferLink->bufferLink; - } + inline void restore(); void checkInvariants() { #if DEBUG @@ -158,48 +144,21 @@ class RegExpStatics friend class PreserveRegExpStatics; public: - RegExpStatics() : bufferLink(NULL), copied(false) { clear(); } + inline RegExpStatics(); static JSObject *create(JSContext *cx, GlobalObject *parent); /* Mutators. */ - bool updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs *newPairs) { - JS_ASSERT(input); - aboutToWrite(); - pendingInput = input; - - if (!matchPairs.resizeUninitialized(2 * newPairs->pairCount())) { - js_ReportOutOfMemory(cx); - return false; - } - - for (size_t i = 0; i < newPairs->pairCount(); ++i) { - matchPairs[2 * i] = newPairs->pair(i).start; - matchPairs[2 * i + 1] = newPairs->pair(i).limit; - } - - matchPairsInput = input; - return true; - } - + inline bool updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs *newPairs); inline void setMultiline(JSContext *cx, bool enabled); - void clear() { - aboutToWrite(); - flags = RegExpFlag(0); - pendingInput = NULL; - matchPairsInput = NULL; - matchPairs.clear(); - } + inline void clear(); /* Corresponds to JSAPI functionality to set the pending RegExp input. */ inline void reset(JSContext *cx, JSString *newInput, bool newMultiline); - void setPendingInput(JSString *newInput) { - aboutToWrite(); - pendingInput = newInput; - } + inline void setPendingInput(JSString *newInput); /* Accessors. */ @@ -248,9 +207,9 @@ class RegExpStatics void mark(JSTracer *trc) const { if (pendingInput) - JS_CALL_STRING_TRACER(trc, pendingInput, "res->pendingInput"); + MarkString(trc, pendingInput, "res->pendingInput"); if (matchPairsInput) - JS_CALL_STRING_TRACER(trc, matchPairsInput, "res->matchPairsInput"); + MarkString(trc, matchPairsInput, "res->matchPairsInput"); } bool pairIsPresent(size_t pairNum) const { @@ -299,9 +258,7 @@ class PreserveRegExpStatics return original->save(cx, &buffer); } - ~PreserveRegExpStatics() { - original->restore(); - } + inline ~PreserveRegExpStatics(); }; } /* namespace js */ diff --git a/js/src/vm/String-inl.h b/js/src/vm/String-inl.h index b12732ae07c6..5b124c2d4227 100644 --- a/js/src/vm/String-inl.h +++ b/js/src/vm/String-inl.h @@ -44,8 +44,38 @@ #include "String.h" #include "jscntxt.h" +#include "jsgcmark.h" + #include "jsgcinlines.h" +inline void +JSString::writeBarrierPre(JSString *str) +{ +#ifdef JSGC_INCREMENTAL + if (!str) + return; + + JSCompartment *comp = str->compartment(); + if (comp->needsBarrier()) + MarkStringUnbarriered(comp->barrierTracer(), str, "write barrier"); +#endif +} + +inline void +JSString::writeBarrierPost(JSString *str, void *addr) +{ +} + +inline bool +JSString::needWriteBarrierPre(JSCompartment *comp) +{ +#ifdef JSGC_INCREMENTAL + return comp->needsBarrier(); +#else + return false; +#endif +} + JS_ALWAYS_INLINE bool JSString::validateLength(JSContext *cx, size_t length) { diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp index 19ecd82e5f20..f6a1226e3f6f 100644 --- a/js/src/vm/String.cpp +++ b/js/src/vm/String.cpp @@ -45,6 +45,8 @@ #include "String.h" #include "String-inl.h" +#include "jsobjinlines.h" + using namespace mozilla; using namespace js; @@ -149,8 +151,9 @@ AllocChars(JSContext *maybecx, size_t length, jschar **chars, size_t *capacity) return *chars != NULL; } +template JSFlatString * -JSRope::flatten(JSContext *maybecx) +JSRope::flattenInternal(JSContext *maybecx) { /* * Perform a depth-first dag traversal, splatting each node's characters @@ -194,12 +197,19 @@ JSRope::flatten(JSContext *maybecx) JSExtensibleString &left = this->leftChild()->asExtensible(); size_t capacity = left.capacity(); if (capacity >= wholeLength) { + if (b == WithBarrier) { + JSString::writeBarrierPre(d.u1.left); + JSString::writeBarrierPre(d.s.u2.right); + } + wholeCapacity = capacity; wholeChars = const_cast(left.chars()); size_t bits = left.d.lengthAndFlags; pos = wholeChars + (bits >> LENGTH_SHIFT); left.d.lengthAndFlags = bits ^ (EXTENSIBLE_FLAGS | DEPENDENT_BIT); left.d.s.u2.base = (JSLinearString *)this; /* will be true on exit */ + if (b == WithBarrier) + JSString::writeBarrierPost(this, &left.d.s.u2.base); goto visit_right_child; } } @@ -209,6 +219,11 @@ JSRope::flatten(JSContext *maybecx) pos = wholeChars; first_visit_node: { + if (b == WithBarrier) { + JSString::writeBarrierPre(str->d.u1.left); + JSString::writeBarrierPre(str->d.s.u2.right); + } + JSString &left = *str->d.u1.left; str->d.u1.chars = pos; if (left.isRope()) { @@ -245,6 +260,8 @@ JSRope::flatten(JSContext *maybecx) size_t progress = str->d.lengthAndFlags; str->d.lengthAndFlags = buildLengthAndFlags(pos - str->d.u1.chars, DEPENDENT_BIT); str->d.s.u2.base = (JSLinearString *)this; /* will be true on exit */ + if (b == WithBarrier) + JSString::writeBarrierPost(this, &str->d.s.u2.base); str = str->d.s.u3.parent; if (progress == 0x200) goto visit_right_child; @@ -253,6 +270,19 @@ JSRope::flatten(JSContext *maybecx) } } +JSFlatString * +JSRope::flatten(JSContext *maybecx) +{ +#if JSGC_INCREMENTAL + if (compartment()->needsBarrier()) + return flattenInternal(maybecx); + else + return flattenInternal(maybecx); +#else + return flattenInternal(maybecx); +#endif +} + JSString * JS_FASTCALL js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) { @@ -297,6 +327,13 @@ JSDependentString::undepend(JSContext *cx) { JS_ASSERT(JSString::isDependent()); + /* + * We destroy the base() pointer in undepend, so we need a pre-barrier. We + * don't need a post-barrier because there aren't any outgoing pointers + * afterwards. + */ + JSString::writeBarrierPre(base()); + size_t n = length(); size_t size = (n + 1) * sizeof(jschar); jschar *s = (jschar *) cx->malloc_(size); @@ -446,15 +483,17 @@ StaticStrings::trace(JSTracer *trc) if (!initialized) return; + /* These strings never change, so barriers are not needed. */ + for (uint32 i = 0; i < UNIT_STATIC_LIMIT; i++) - MarkString(trc, unitStaticTable[i], "unit-static-string"); + MarkStringUnbarriered(trc, unitStaticTable[i], "unit-static-string"); for (uint32 i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) - MarkString(trc, length2StaticTable[i], "length2-static-string"); + MarkStringUnbarriered(trc, length2StaticTable[i], "length2-static-string"); /* This may mark some strings more than once, but so be it. */ for (uint32 i = 0; i < INT_STATIC_LIMIT; i++) - MarkString(trc, intStaticTable[i], "int-static-string"); + MarkStringUnbarriered(trc, intStaticTable[i], "int-static-string"); } bool diff --git a/js/src/vm/String.h b/js/src/vm/String.h index 7dc07b6a9731..f7fa6b22177e 100644 --- a/js/src/vm/String.h +++ b/js/src/vm/String.h @@ -419,10 +419,18 @@ class JSString : public js::gc::Cell static size_t offsetOfChars() { return offsetof(JSString, d.u1.chars); } + + static inline void writeBarrierPre(JSString *str); + static inline void writeBarrierPost(JSString *str, void *addr); + static inline bool needWriteBarrierPre(JSCompartment *comp); }; class JSRope : public JSString { + enum UsingBarrier { WithBarrier, NoBarrier }; + template + JSFlatString *flattenInternal(JSContext *cx); + friend class JSString; JSFlatString *flatten(JSContext *cx); diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index 25fc18e7a1bc..050f1f7ca871 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -825,6 +825,8 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed aIdentity, NS_ASSERTION(mSet, "bad ctor param"); DEBUG_TrackNewWrapper(this); + + JS_RegisterReference((void **) &mWrapperWord); } // This ctor is used if this object will NOT have a proto. @@ -847,6 +849,8 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed aIdentity, NS_ASSERTION(aSet, "bad ctor param"); DEBUG_TrackNewWrapper(this); + + JS_RegisterReference((void **) &mWrapperWord); } XPCWrappedNative::~XPCWrappedNative() @@ -896,6 +900,36 @@ XPCWrappedNative::Destroy() } mMaybeScope = nsnull; + + JS_UnregisterReference((void **) &mWrapperWord); +} + +void +XPCWrappedNative::UpdateScriptableInfo(XPCNativeScriptableInfo *si) +{ + NS_ASSERTION(mScriptableInfo, "UpdateScriptableInfo expects an existing scriptable info"); + + // Write barrier for incremental GC. + JSRuntime* rt = GetRuntime()->GetJSRuntime(); + if (JS_GetIncrementalGCTracer(rt)) + mScriptableInfo->Mark(); + + mScriptableInfo = si; +} + +void +XPCWrappedNative::SetProto(XPCWrappedNativeProto* p) +{ + NS_ASSERTION(!IsWrapperExpired(), "bad ptr!"); + + // Write barrier for incremental GC. + if (HasProto()) { + JSRuntime* rt = GetRuntime()->GetJSRuntime(); + if (JS_GetIncrementalGCTracer(rt)) + GetProto()->TraceJS(JS_GetIncrementalGCTracer(rt)); + } + + mMaybeProto = p; } // This is factored out so that it can be called publicly @@ -1101,12 +1135,30 @@ XPCWrappedNative::Init(XPCCallContext& ccx, if (!mFlatJSObject) return JS_FALSE; + // In the current JS engine JS_SetPrivate can't fail. But if it *did* + // fail then we would not receive our finalizer call and would not be + // able to properly cleanup. So, if it fails we null out mFlatJSObject + // to indicate the invalid state of this object and return false. + if (!JS_SetPrivate(ccx, mFlatJSObject, this)) { + mFlatJSObject = nsnull; + return JS_FALSE; + } + return FinishInit(ccx); } JSBool XPCWrappedNative::Init(XPCCallContext &ccx, JSObject *existingJSObject) { + // In the current JS engine JS_SetPrivate can't fail. But if it *did* + // fail then we would not receive our finalizer call and would not be + // able to properly cleanup. So, if it fails we null out mFlatJSObject + // to indicate the invalid state of this object and return false. + if (!JS_SetPrivate(ccx, existingJSObject, this)) { + mFlatJSObject = nsnull; + return JS_FALSE; + } + // Morph the existing object. if (!JS_SetReservedSlot(ccx, existingJSObject, 0, JSVAL_VOID)) return JS_FALSE; @@ -1124,15 +1176,6 @@ XPCWrappedNative::Init(XPCCallContext &ccx, JSObject *existingJSObject) JSBool XPCWrappedNative::FinishInit(XPCCallContext &ccx) { - // In the current JS engine JS_SetPrivate can't fail. But if it *did* - // fail then we would not receive our finalizer call and would not be - // able to properly cleanup. So, if it fails we null out mFlatJSObject - // to indicate the invalid state of this object and return false. - if (!JS_SetPrivate(ccx, mFlatJSObject, this)) { - mFlatJSObject = nsnull; - return JS_FALSE; - } - // This reference will be released when mFlatJSObject is finalized. // Since this reference will push the refcount to 2 it will also root // mFlatJSObject; @@ -1480,7 +1523,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx, "Changing proto is also changing JSObject Classname or " "helper's nsIXPScriptable flags. This is not allowed!"); - wrapper->mScriptableInfo = newProto->GetScriptableInfo(); + wrapper->UpdateScriptableInfo(newProto->GetScriptableInfo()); } NS_ASSERTION(!newMap->Find(wrapper->GetIdentityObject()), @@ -3017,7 +3060,7 @@ NS_IMETHODIMP XPCWrappedNative::RefreshPrototype() SetProto(newProto); if (mScriptableInfo == oldProto->GetScriptableInfo()) - mScriptableInfo = newProto->GetScriptableInfo(); + UpdateScriptableInfo(newProto->GetScriptableInfo()); return NS_OK; } diff --git a/js/xpconnect/src/XPCWrappedNativeProto.cpp b/js/xpconnect/src/XPCWrappedNativeProto.cpp index e97dbd921272..14847982ba1e 100644 --- a/js/xpconnect/src/XPCWrappedNativeProto.cpp +++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp @@ -266,7 +266,7 @@ XPCWrappedNativeProto::DebugDump(PRInt16 depth) XPC_LOG_INDENT(); XPC_LOG_ALWAYS(("gDEBUG_LiveProtoCount is %d", gDEBUG_LiveProtoCount)); XPC_LOG_ALWAYS(("mScope @ %x", mScope)); - XPC_LOG_ALWAYS(("mJSProtoObject @ %x", mJSProtoObject)); + XPC_LOG_ALWAYS(("mJSProtoObject @ %x", mJSProtoObject.get())); XPC_LOG_ALWAYS(("mSet @ %x", mSet)); XPC_LOG_ALWAYS(("mSecurityInfo of %x", mSecurityInfo)); XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo)); diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index 66e0b909fc3a..646f259e45c6 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -947,9 +947,9 @@ XPCWrappedNativeScope::DebugDump(PRInt16 depth) XPC_LOG_ALWAYS(("mRuntime @ %x", mRuntime)); XPC_LOG_ALWAYS(("mNext @ %x", mNext)); XPC_LOG_ALWAYS(("mComponents @ %x", mComponents)); - XPC_LOG_ALWAYS(("mGlobalJSObject @ %x", mGlobalJSObject)); - XPC_LOG_ALWAYS(("mPrototypeJSObject @ %x", mPrototypeJSObject)); - XPC_LOG_ALWAYS(("mPrototypeJSFunction @ %x", mPrototypeJSFunction)); + XPC_LOG_ALWAYS(("mGlobalJSObject @ %x", mGlobalJSObject.get())); + XPC_LOG_ALWAYS(("mPrototypeJSObject @ %x", mPrototypeJSObject.get())); + XPC_LOG_ALWAYS(("mPrototypeJSFunction @ %x", mPrototypeJSFunction.get())); XPC_LOG_ALWAYS(("mPrototypeNoHelper @ %x", mPrototypeNoHelper)); XPC_LOG_ALWAYS(("mWrappedNativeMap @ %x with %d wrappers(s)", \ diff --git a/js/xpconnect/src/dombindings.cpp b/js/xpconnect/src/dombindings.cpp index f6879c50603e..f11477b95015 100644 --- a/js/xpconnect/src/dombindings.cpp +++ b/js/xpconnect/src/dombindings.cpp @@ -676,7 +676,7 @@ ListBase::ensureExpandoObject(JSContext *cx, JSObject *obj) return NULL; js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando)); - expando->setPrivate(js::GetProxyPrivate(obj).toPrivate()); + JS_SetPrivate(cx, expando, js::GetProxyPrivate(obj).toPrivate()); } return expando; } diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 1202fb2b5f84..d5130e41b41f 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -1663,12 +1663,12 @@ private: // default parent for the XPCWrappedNatives that have us as the scope, // unless a PreCreate hook overrides it. Note that this _may_ be null (see // constructor). - JSObject* mGlobalJSObject; + JS::HeapPtrObject mGlobalJSObject; // Cached value of Object.prototype - JSObject* mPrototypeJSObject; + JS::HeapPtrObject mPrototypeJSObject; // Cached value of Function.prototype - JSObject* mPrototypeJSFunction; + JS::HeapPtrObject mPrototypeJSFunction; // Prototype to use for wrappers with no helper. JSObject* mPrototypeNoHelper; @@ -2366,7 +2366,7 @@ private: } XPCWrappedNativeScope* mScope; - JSObject* mJSProtoObject; + JS::HeapPtrObject mJSProtoObject; nsCOMPtr mClassInfo; PRUint32 mClassInfoFlags; XPCNativeSet* mSet; @@ -2525,10 +2525,7 @@ public: (XPCWrappedNativeProto*) (XPC_SCOPE_WORD(mMaybeProto) & ~XPC_SCOPE_MASK) : nsnull;} - void - SetProto(XPCWrappedNativeProto* p) - {NS_ASSERTION(!IsWrapperExpired(), "bad ptr!"); - mMaybeProto = p;} + void SetProto(XPCWrappedNativeProto* p); XPCWrappedNativeScope* GetScope() const @@ -2762,7 +2759,8 @@ public: } void SetWrapper(JSObject *obj) { - mWrapperWord = PRWord(obj) | (mWrapperWord & FLAG_MASK); + PRWord newval = PRWord(obj) | (mWrapperWord & FLAG_MASK); + JS_ModifyReference((void **)&mWrapperWord, (void *)newval); } void NoteTearoffs(nsCycleCollectionTraversalCallback& cb); @@ -2797,6 +2795,8 @@ protected: virtual ~XPCWrappedNative(); void Destroy(); + void UpdateScriptableInfo(XPCNativeScriptableInfo *si); + private: enum { NEEDS_SOW = JS_BIT(0), From f8de4a3820016581ff62a2016272ab95570fc1ea Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Fri, 5 Aug 2011 10:25:23 -0700 Subject: [PATCH 08/38] Bug 641027 - Add snapshot-based verifier for JS write barriers (r=luke) --- js/src/jit-test/jit_test.py | 7 +- js/src/jsapi.cpp | 5 +- js/src/jscntxt.h | 6 +- js/src/jsfun.cpp | 8 + js/src/jsgc.cpp | 351 +++++++++++++++++++++++++++++++++ js/src/jsgc.h | 19 ++ js/src/jsgcinlines.h | 2 +- js/src/jsinterp.cpp | 5 + js/src/methodjit/Compiler.cpp | 36 ++-- js/src/methodjit/StubCalls.cpp | 2 + 10 files changed, 421 insertions(+), 20 deletions(-) diff --git a/js/src/jit-test/jit_test.py b/js/src/jit-test/jit_test.py index 61c4fb8efd26..5b7c13e0076b 100755 --- a/js/src/jit-test/jit_test.py +++ b/js/src/jit-test/jit_test.py @@ -267,11 +267,12 @@ def run_tests(tests, test_dir, lib_dir, shell_args): if not OPTIONS.hide_progress and not OPTIONS.show_cmd: try: from progressbar import ProgressBar - pb = ProgressBar('', len(tests), 16) + pb = ProgressBar('', len(tests), 24) except ImportError: pass failures = [] + timeouts = 0 complete = False doing = 'before starting' try: @@ -282,6 +283,8 @@ def run_tests(tests, test_dir, lib_dir, shell_args): if not ok: failures.append([ test, out, err, code, timed_out ]) + if timed_out: + timeouts += 1 if OPTIONS.tinderbox: if ok: @@ -297,7 +300,7 @@ def run_tests(tests, test_dir, lib_dir, shell_args): n = i + 1 if pb: - pb.label = '[%4d|%4d|%4d]'%(n - len(failures), len(failures), n) + pb.label = '[%4d|%4d|%4d|%4d]'%(n - len(failures), len(failures), timeouts, n) pb.update(n) complete = True except KeyboardInterrupt: diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index db4fe2c6095e..e5adf9d33738 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -659,6 +659,7 @@ JSRuntime::JSRuntime() gcEmptyArenaPoolLifespan(0), gcNumber(0), gcIncrementalTracer(NULL), + gcVerifyData(NULL), gcChunkAllocationSinceLastGC(false), gcNextFullGCTime(0), gcJitReleaseTime(0), @@ -2746,6 +2747,7 @@ JS_CompartmentGC(JSContext *cx, JSCompartment *comp) LeaveTrace(cx); + js::gc::VerifyBarriers(cx, true); js_GC(cx, comp, GC_NORMAL, gcstats::PUBLIC_API); } @@ -6364,9 +6366,10 @@ JS_ClearContextThread(JSContext *cx) JS_PUBLIC_API(void) JS_SetGCZeal(JSContext *cx, uint8 zeal, uint32 frequency, JSBool compartment) { + bool schedule = zeal >= js::gc::ZealAllocThreshold && zeal < js::gc::ZealVerifierThreshold; cx->runtime->gcZeal_ = zeal; cx->runtime->gcZealFrequency = frequency; - cx->runtime->gcNextScheduled = zeal >= 2 ? frequency : 0; + cx->runtime->gcNextScheduled = schedule ? frequency : 0; cx->runtime->gcDebugCompartmentGC = !!compartment; } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 8b91e1f2df1d..7b6c7505f31f 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -461,6 +461,7 @@ struct JSRuntime volatile uint32 gcNumFreeArenas; uint32 gcNumber; js::GCMarker *gcIncrementalTracer; + void *gcVerifyData; bool gcChunkAllocationSinceLastGC; int64 gcNextFullGCTime; int64 gcJitReleaseTime; @@ -523,6 +524,9 @@ struct JSRuntime * Additionally, if gzZeal_ == 1 then we perform GCs in select places * (during MaybeGC and whenever a GC poke happens). This option is mainly * useful to embedders. + * + * We use gcZeal_ == 4 to enable write barrier verification. See the comment + * in jsgc.cpp for more information about this. */ #ifdef JS_GC_ZEAL int gcZeal_; @@ -534,7 +538,7 @@ struct JSRuntime bool needZealousGC() { if (gcNextScheduled > 0 && --gcNextScheduled == 0) { - if (gcZeal() >= 2) + if (gcZeal() >= js::gc::ZealAllocThreshold && gcZeal() < js::gc::ZealVerifierThreshold) gcNextScheduled = gcZealFrequency; return true; } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index fe2fc9d64f53..793c68a5dd82 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -833,13 +833,21 @@ js_PutCallObject(StackFrame *fp) uint32 nclosed = script->nClosedArgs; for (uint32 i = 0; i < nclosed; i++) { uint32 e = script->getClosedArg(i); +#ifdef JS_GC_ZEAL + callobj.setArg(e, fp->formalArg(e)); +#else callobj.initArgUnchecked(e, fp->formalArg(e)); +#endif } nclosed = script->nClosedVars; for (uint32 i = 0; i < nclosed; i++) { uint32 e = script->getClosedVar(i); +#ifdef JS_GC_ZEAL + callobj.setVar(e, fp->slots()[e]); +#else callobj.initVarUnchecked(e, fp->slots()[e]); +#endif } } diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index a0d35206ca1a..07dc9f48bef2 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -111,6 +111,14 @@ using namespace js::gc; namespace js { namespace gc { +#ifdef JS_GC_ZEAL +static void +StartVerifyBarriers(JSContext *cx); + +static void +EndVerifyBarriers(JSContext *cx); +#endif + /* This array should be const, but that doesn't link right under GCC. */ AllocKind slotsToThingKind[] = { /* 0 */ FINALIZE_OBJECT0, FINALIZE_OBJECT2, FINALIZE_OBJECT2, FINALIZE_OBJECT4, @@ -2969,6 +2977,17 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Re return; } +#ifdef JS_GC_ZEAL + struct AutoVerifyBarriers { + JSContext *cx; + bool inVerify; + AutoVerifyBarriers(JSContext *cx) : cx(cx), inVerify(cx->runtime->gcVerifyData) { + if (inVerify) EndVerifyBarriers(cx); + } + ~AutoVerifyBarriers() { if (inVerify) StartVerifyBarriers(cx); } + } av(cx); +#endif + RecordNativeStackTopForGC(cx); gcstats::AutoGC agc(rt->gcStats, comp, reason); @@ -3234,6 +3253,338 @@ RunDebugGC(JSContext *cx) #endif } +#ifdef JS_GC_ZEAL + +/* + * Write barrier verification + * + * The next few functions are for incremental write barrier verification. When + * StartVerifyBarriers is called, a snapshot is taken of all objects in the GC + * heap and saved in an explicit graph data structure. Later, EndVerifyBarriers + * traverses the heap again. Any pointer values that were in the snapshot and + * are no longer found must be marked; otherwise an assertion triggers. Note + * that we must not GC in between starting and finishing a verification phase. + * + * The VerifyBarriers function is a shorthand. It checks if a verification phase + * is currently running. If not, it starts one. Otherwise, it ends the current + * phase and starts a new one. + * + * The user can adjust the frequency of verifications, which causes + * VerifyBarriers to be a no-op all but one out of N calls. However, if the + * |always| parameter is true, it starts a new phase no matter what. + */ + +struct EdgeValue +{ + void *thing; + JSGCTraceKind kind; + char *label; +}; + +struct VerifyNode +{ + void *thing; + JSGCTraceKind kind; + uint32 count; + EdgeValue edges[1]; +}; + +typedef HashMap NodeMap; + +/* + * The verifier data structures are simple. The entire graph is stored in a + * single block of memory. At the beginning is a VerifyNode for the root + * node. It is followed by a sequence of EdgeValues--the exact number is given + * in the node. After the edges come more nodes and their edges. + * + * The edgeptr and term fields are used to allocate out of the block of memory + * for the graph. If we run out of memory (i.e., if edgeptr goes beyond term), + * we just abandon the verification. + * + * The nodemap field is a hashtable that maps from the address of the GC thing + * to the VerifyNode that represents it. + */ +struct VerifyTracer : JSTracer { + /* The gcNumber when the verification began. */ + uint32 number; + + /* This counts up to JS_VERIFIER_FREQ to decide whether to verify. */ + uint32 count; + + /* This graph represents the initial GC "snapshot". */ + VerifyNode *curnode; + VerifyNode *root; + char *edgeptr; + char *term; + NodeMap nodemap; + + /* A dummy marker used for the write barriers; stored in gcMarkingTracer. */ + GCMarker gcmarker; + + VerifyTracer(JSContext *cx) : nodemap(cx), gcmarker(cx) {} +}; + +/* + * This function builds up the heap snapshot by adding edges to the current + * node. + */ +static void +AccumulateEdge(JSTracer *jstrc, void *thing, JSGCTraceKind kind) +{ + VerifyTracer *trc = (VerifyTracer *)jstrc; + + trc->edgeptr += sizeof(EdgeValue); + if (trc->edgeptr >= trc->term) { + trc->edgeptr = trc->term; + return; + } + + VerifyNode *node = trc->curnode; + uint32 i = node->count; + + node->edges[i].thing = thing; + node->edges[i].kind = kind; + node->edges[i].label = trc->debugPrinter ? NULL : (char *)trc->debugPrintArg; + node->count++; +} + +static VerifyNode * +MakeNode(VerifyTracer *trc, void *thing, JSGCTraceKind kind) +{ + NodeMap::AddPtr p = trc->nodemap.lookupForAdd(thing); + if (!p) { + VerifyNode *node = (VerifyNode *)trc->edgeptr; + trc->edgeptr += sizeof(VerifyNode) - sizeof(EdgeValue); + if (trc->edgeptr >= trc->term) { + trc->edgeptr = trc->term; + return NULL; + } + + node->thing = thing; + node->count = 0; + node->kind = kind; + trc->nodemap.add(p, thing, node); + return node; + } + return NULL; +} + +static +VerifyNode * +NextNode(VerifyNode *node) +{ + if (node->count == 0) + return (VerifyNode *)((char *)node + sizeof(VerifyNode) - sizeof(EdgeValue)); + else + return (VerifyNode *)((char *)node + sizeof(VerifyNode) + + sizeof(EdgeValue)*(node->count - 1)); +} + +static void +StartVerifyBarriers(JSContext *cx) +{ + JSRuntime *rt = cx->runtime; + + if (rt->gcVerifyData) + return; + + LeaveTrace(cx); + + AutoLockGC lock(rt); + AutoGCSession gcsession(cx); + +#ifdef JS_THREADSAFE + rt->gcHelperThread.waitBackgroundSweepOrAllocEnd(); +#endif + + AutoUnlockGC unlock(rt); + + AutoCopyFreeListToArenas copy(rt); + RecordNativeStackTopForGC(cx); + + for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) + r.front()->bitmap.clear(); + + /* + * Kick all frames on the stack into the interpreter, and release all JIT + * code in the compartment. + */ +#ifdef JS_METHODJIT + for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) { + mjit::ClearAllFrames(*c); + + for (CellIterUnderGC i(*c, FINALIZE_SCRIPT); !i.done(); i.next()) { + JSScript *script = i.get(); + mjit::ReleaseScriptCode(cx, script); + + /* + * Use counts for scripts are reset on GC. After discarding code we + * need to let it warm back up to get information like which opcodes + * are setting array holes or accessing getter properties. + */ + script->resetUseCount(); + } + } +#endif + + VerifyTracer *trc = new (js_malloc(sizeof(VerifyTracer))) VerifyTracer(cx); + + rt->gcNumber++; + trc->number = rt->gcNumber; + trc->count = 0; + + JS_TRACER_INIT(trc, cx, AccumulateEdge); + + const size_t size = 64 * 1024 * 1024; + trc->root = (VerifyNode *)js_malloc(size); + JS_ASSERT(trc->root); + trc->edgeptr = (char *)trc->root; + trc->term = trc->edgeptr + size; + + trc->nodemap.init(); + + /* Create the root node. */ + trc->curnode = MakeNode(trc, NULL, JSGCTraceKind(0)); + + /* Make all the roots be edges emanating from the root node. */ + MarkRuntime(trc); + + VerifyNode *node = trc->curnode; + if (trc->edgeptr == trc->term) + goto oom; + + /* For each edge, make a node for it if one doesn't already exist. */ + while ((char *)node < trc->edgeptr) { + for (uint32 i = 0; i < node->count; i++) { + EdgeValue &e = node->edges[i]; + VerifyNode *child = MakeNode(trc, e.thing, e.kind); + if (child) { + trc->curnode = child; + JS_TraceChildren(trc, e.thing, e.kind); + } + if (trc->edgeptr == trc->term) + goto oom; + } + + node = NextNode(node); + } + + rt->gcVerifyData = trc; + rt->gcIncrementalTracer = &trc->gcmarker; + for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) { + (*c)->gcIncrementalTracer = &trc->gcmarker; + (*c)->needsBarrier_ = true; + } + + return; + +oom: + js_free(trc->root); + trc->~VerifyTracer(); + js_free(trc); +} + +/* + * This function is called by EndVerifyBarriers for every heap edge. If the edge + * already existed in the original snapshot, we "cancel it out" by overwriting + * it with NULL. EndVerifyBarriers later asserts that the remaining non-NULL + * edges (i.e., the ones from the original snapshot that must have been + * modified) must point to marked objects. + */ +static void +CheckEdge(JSTracer *jstrc, void *thing, JSGCTraceKind kind) +{ + VerifyTracer *trc = (VerifyTracer *)jstrc; + VerifyNode *node = trc->curnode; + + for (uint32 i = 0; i < node->count; i++) { + if (node->edges[i].thing == thing) { + JS_ASSERT(node->edges[i].kind == kind); + node->edges[i].thing = NULL; + return; + } + } +} + +static void +EndVerifyBarriers(JSContext *cx) +{ + LeaveTrace(cx); + + JSRuntime *rt = cx->runtime; + + AutoLockGC lock(rt); + AutoGCSession gcsession(cx); + +#ifdef JS_THREADSAFE + rt->gcHelperThread.waitBackgroundSweepOrAllocEnd(); +#endif + + AutoUnlockGC unlock(rt); + + AutoCopyFreeListToArenas copy(rt); + RecordNativeStackTopForGC(cx); + + VerifyTracer *trc = (VerifyTracer *)rt->gcVerifyData; + + if (!trc) + return; + + JS_ASSERT(trc->number == rt->gcNumber); + + rt->gcIncrementalTracer->markDelayedChildren(); + + rt->gcVerifyData = NULL; + rt->gcIncrementalTracer = NULL; + for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) { + (*c)->gcIncrementalTracer = NULL; + (*c)->needsBarrier_ = false; + } + + JS_TRACER_INIT(trc, cx, CheckEdge); + + /* Start after the roots. */ + VerifyNode *node = NextNode(trc->root); + int count = 0; + + while ((char *)node < trc->edgeptr) { + trc->curnode = node; + JS_TraceChildren(trc, node->thing, node->kind); + + for (uint32 i = 0; i < node->count; i++) { + void *thing = node->edges[i].thing; + JS_ASSERT_IF(thing, static_cast(thing)->isMarked()); + } + + count++; + node = NextNode(node); + } + + js_free(trc->root); + trc->~VerifyTracer(); + js_free(trc); +} + +void +VerifyBarriers(JSContext *cx, bool always) +{ + if (cx->runtime->gcZeal() < ZealVerifierThreshold) + return; + + uint32 freq = cx->runtime->gcZealFrequency; + + JSRuntime *rt = cx->runtime; + if (VerifyTracer *trc = (VerifyTracer *)rt->gcVerifyData) { + if (++trc->count < freq && !always) + return; + + EndVerifyBarriers(cx); + } + StartVerifyBarriers(cx); +} + +#endif /* JS_GC_ZEAL */ + } /* namespace gc */ } /* namespace js */ diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 6ee1f8a94aa2..52b089468d80 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1781,6 +1781,25 @@ NewCompartment(JSContext *cx, JSPrincipals *principals); void RunDebugGC(JSContext *cx); +const int ZealPokeThreshold = 1; +const int ZealAllocThreshold = 2; +const int ZealVerifierThreshold = 4; + +#ifdef JS_GC_ZEAL + +/* Check that write barriers have been used correctly. See jsgc.cpp. */ +void +VerifyBarriers(JSContext *cx, bool always = false); + +#else + +static inline void +VerifyBarriers(JSContext *cx, bool always = false) +{ +} + +#endif + } /* namespace gc */ static inline JSCompartment * diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 8d7ae59d8dc0..6a93f59949af 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -167,7 +167,7 @@ GCPoke(JSContext *cx, Value oldval) #ifdef JS_GC_ZEAL /* Schedule a GC to happen "soon" after a GC poke. */ - if (cx->runtime->gcZeal()) + if (cx->runtime->gcZeal() >= js::gc::ZealPokeThreshold) cx->runtime->gcNextScheduled = 1; #endif } diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 9223ca1a29a5..feb876eba4a8 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1590,6 +1590,8 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) #endif JSAutoResolveFlags rf(cx, RESOLVE_INFER); + gc::VerifyBarriers(cx, true); + JS_ASSERT(!cx->compartment->activeAnalysis); #define ENABLE_PCCOUNT_INTERRUPTS() JS_BEGIN_MACRO \ @@ -1636,6 +1638,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) # define DO_OP() JS_BEGIN_MACRO \ CHECK_RECORDER(); \ CHECK_PCCOUNT_INTERRUPTS(); \ + js::gc::VerifyBarriers(cx); \ JS_EXTENSION_(goto *jumpTable[op]); \ JS_END_MACRO # define DO_NEXT_OP(n) JS_BEGIN_MACRO \ @@ -1967,6 +1970,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) do_op: CHECK_RECORDER(); CHECK_PCCOUNT_INTERRUPTS(); + js::gc::VerifyBarriers(cx); switchOp = intN(op) | switchMask; do_switch: switch (switchOp) { @@ -6128,6 +6132,7 @@ END_CASE(JSOP_ARRAYPUSH) leave_on_safe_point: #endif + gc::VerifyBarriers(cx, true); return interpReturnOK; atom_not_defined: diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 7427b45b49de..9b2314bf467b 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -3211,28 +3211,34 @@ mjit::Compiler::emitStubCall(void *ptr, DataLabelPtr *pinline) void mjit::Compiler::interruptCheckHelper() { - /* - * Bake in and test the address of the interrupt counter for the runtime. - * This is faster than doing two additional loads for the context's - * thread data, but will cause this thread to run slower if there are - * pending interrupts on some other thread. For non-JS_THREADSAFE builds - * we can skip this, as there is only one flag to poll. - */ + Jump jump; + if (cx->runtime->gcZeal() >= js::gc::ZealVerifierThreshold) { + /* For barrier verification, always take the interrupt so we can verify. */ + jump = masm.jump(); + } else { + /* + * Bake in and test the address of the interrupt counter for the runtime. + * This is faster than doing two additional loads for the context's + * thread data, but will cause this thread to run slower if there are + * pending interrupts on some other thread. For non-JS_THREADSAFE builds + * we can skip this, as there is only one flag to poll. + */ #ifdef JS_THREADSAFE - void *interrupt = (void*) &cx->runtime->interruptCounter; + void *interrupt = (void*) &cx->runtime->interruptCounter; #else - void *interrupt = (void*) &JS_THREAD_DATA(cx)->interruptFlags; + void *interrupt = (void*) &JS_THREAD_DATA(cx)->interruptFlags; #endif #if defined(JS_CPU_X86) || defined(JS_CPU_ARM) - Jump jump = masm.branch32(Assembler::NotEqual, AbsoluteAddress(interrupt), Imm32(0)); + jump = masm.branch32(Assembler::NotEqual, AbsoluteAddress(interrupt), Imm32(0)); #else - /* Handle processors that can't load from absolute addresses. */ - RegisterID reg = frame.allocReg(); - masm.move(ImmPtr(interrupt), reg); - Jump jump = masm.branchTest32(Assembler::NonZero, Address(reg, 0)); - frame.freeReg(reg); + /* Handle processors that can't load from absolute addresses. */ + RegisterID reg = frame.allocReg(); + masm.move(ImmPtr(interrupt), reg); + jump = masm.branchTest32(Assembler::NonZero, Address(reg, 0)); + frame.freeReg(reg); #endif + } stubcc.linkExitDirect(jump, stubcc.masm.label()); diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index b1cca5e56258..17ce254cbccb 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -1215,6 +1215,8 @@ stubs::DebuggerStatement(VMFrame &f, jsbytecode *pc) void JS_FASTCALL stubs::Interrupt(VMFrame &f, jsbytecode *pc) { + gc::VerifyBarriers(f.cx); + if (!js_HandleExecutionInterrupt(f.cx)) THROW(); } From 1a1f7b30aedd0fb98922e1fd94c9d94a6fcef2ae Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 1 Nov 2011 15:45:23 -0700 Subject: [PATCH 09/38] Bug 698248 - Remove unused FORCE_USE_PIC variable; r=khuey --- browser/components/about/Makefile.in | 1 - browser/components/dirprovider/Makefile.in | 1 - browser/components/feeds/src/Makefile.in | 1 - browser/components/migration/src/Makefile.in | 1 - browser/components/privatebrowsing/src/Makefile.in | 1 - browser/components/shell/src/Makefile.in | 1 - chrome/src/Makefile.in | 1 - dbm/src/Makefile.in | 1 - extensions/universalchardet/src/base/Makefile.in | 2 -- gfx/cairo/cairo/src/Makefile.in | 2 -- gfx/cairo/libpixman/src/Makefile.in | 2 -- gfx/harfbuzz/src/Makefile.in | 2 -- gfx/ots/src/Makefile.in | 2 -- gfx/qcms/Makefile.in | 2 -- gfx/src/Makefile.in | 2 -- image/decoders/icon/gtk/Makefile.in | 2 -- image/decoders/icon/qt/Makefile.in | 2 -- intl/unicharutil/util/Makefile.in | 1 - intl/unicharutil/util/internal/Makefile.in | 1 - layout/inspector/src/Makefile.in | 2 -- media/libpng/Makefile.in | 2 -- modules/libreg/src/Makefile.in | 2 -- modules/zlib/src/Makefile.in | 2 -- services/crypto/component/Makefile.in | 1 - toolkit/components/alerts/mac/growl/Makefile.in | 1 - toolkit/crashreporter/client/Makefile.in | 2 -- toolkit/crashreporter/fileid/Makefile.in | 1 - toolkit/crashreporter/google-breakpad/src/client/Makefile.in | 1 - .../src/client/linux/crash_generation/Makefile.in | 1 - .../google-breakpad/src/client/linux/handler/Makefile.in | 1 - .../src/client/linux/minidump_writer/Makefile.in | 1 - .../google-breakpad/src/client/solaris/handler/Makefile.in | 1 - toolkit/crashreporter/google-breakpad/src/common/Makefile.in | 1 - .../crashreporter/google-breakpad/src/common/linux/Makefile.in | 1 - .../google-breakpad/src/common/solaris/Makefile.in | 1 - .../google-breakpad/src/tools/linux/dump_syms/Makefile.in | 1 - .../google-breakpad/src/tools/solaris/dump_syms/Makefile.in | 1 - toolkit/library/Makefile.in | 1 - widget/src/qt/faststartupqt/Makefile.in | 1 - xpcom/base/Makefile.in | 2 -- xpcom/build/Makefile.in | 2 -- xpcom/components/Makefile.in | 2 -- xpcom/ds/Makefile.in | 2 -- xpcom/glue/Makefile.in | 2 -- xpcom/glue/nomozalloc/Makefile.in | 2 -- xpcom/glue/standalone/Makefile.in | 2 -- xpcom/io/Makefile.in | 2 -- xpcom/proxy/src/Makefile.in | 2 -- xpcom/reflect/xptcall/src/Makefile.in | 2 -- xpcom/reflect/xptcall/src/md/os2/Makefile.in | 2 -- xpcom/reflect/xptcall/src/md/unix/Makefile.in | 2 -- xpcom/reflect/xptcall/src/md/win32/Makefile.in | 2 -- xpcom/reflect/xptinfo/src/Makefile.in | 2 -- xpcom/string/src/Makefile.in | 2 -- xpcom/stub/Makefile.in | 2 -- xpcom/threads/Makefile.in | 2 -- xpcom/typelib/xpt/src/Makefile.in | 2 -- 57 files changed, 89 deletions(-) diff --git a/browser/components/about/Makefile.in b/browser/components/about/Makefile.in index ea232e319b4a..3227c3226a34 100644 --- a/browser/components/about/Makefile.in +++ b/browser/components/about/Makefile.in @@ -44,7 +44,6 @@ include $(DEPTH)/config/autoconf.mk MODULE = browserabout LIBRARY_NAME = browserabout_s FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 ifndef MOZ_MEMORY USE_STATIC_LIBS = 1 endif diff --git a/browser/components/dirprovider/Makefile.in b/browser/components/dirprovider/Makefile.in index 4175d002529c..1c9369b657aa 100644 --- a/browser/components/dirprovider/Makefile.in +++ b/browser/components/dirprovider/Makefile.in @@ -48,7 +48,6 @@ LIBRARY_NAME = browserdir_s DIRS = tests FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 # Because we are an application component, link against the CRT statically # (on Windows, but only if we're not building our own CRT for jemalloc) diff --git a/browser/components/feeds/src/Makefile.in b/browser/components/feeds/src/Makefile.in index 8d071eb769c0..9737cfdc5951 100644 --- a/browser/components/feeds/src/Makefile.in +++ b/browser/components/feeds/src/Makefile.in @@ -44,7 +44,6 @@ include $(DEPTH)/config/autoconf.mk MODULE = browser_feeds LIBRARY_NAME = browser_feeds_s FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 ifndef MOZ_MEMORY USE_STATIC_LIBS = 1 endif diff --git a/browser/components/migration/src/Makefile.in b/browser/components/migration/src/Makefile.in index 751ba7a9b8c0..9f4dda94d15d 100644 --- a/browser/components/migration/src/Makefile.in +++ b/browser/components/migration/src/Makefile.in @@ -44,7 +44,6 @@ include $(DEPTH)/config/autoconf.mk MODULE = migration LIBRARY_NAME = migration_s FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 ifndef MOZ_MEMORY USE_STATIC_LIBS = 1 endif diff --git a/browser/components/privatebrowsing/src/Makefile.in b/browser/components/privatebrowsing/src/Makefile.in index 267deb63bb34..60116206c213 100644 --- a/browser/components/privatebrowsing/src/Makefile.in +++ b/browser/components/privatebrowsing/src/Makefile.in @@ -45,7 +45,6 @@ include $(DEPTH)/config/autoconf.mk MODULE = privatebrowsing LIBRARY_NAME = privatebrowsing_s FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 ifndef MOZ_MEMORY USE_STATIC_LIBS = 1 endif diff --git a/browser/components/shell/src/Makefile.in b/browser/components/shell/src/Makefile.in index c9004a3dc3c2..0f1be090d6c5 100644 --- a/browser/components/shell/src/Makefile.in +++ b/browser/components/shell/src/Makefile.in @@ -44,7 +44,6 @@ include $(DEPTH)/config/autoconf.mk MODULE = shellservice FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 ifndef MOZ_MEMORY USE_STATIC_LIBS = 1 endif diff --git a/chrome/src/Makefile.in b/chrome/src/Makefile.in index cba35fae7f2f..8a71582190e7 100644 --- a/chrome/src/Makefile.in +++ b/chrome/src/Makefile.in @@ -46,7 +46,6 @@ MODULE = chrome LIBRARY_NAME = chrome_s LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 EXPORTS_NAMESPACES = mozilla/chrome diff --git a/dbm/src/Makefile.in b/dbm/src/Makefile.in index 2f7476d8c86f..6c0122af173c 100644 --- a/dbm/src/Makefile.in +++ b/dbm/src/Makefile.in @@ -79,7 +79,6 @@ endif # WINNT LOCAL_INCLUDES = -I$(srcdir)/../include FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/extensions/universalchardet/src/base/Makefile.in b/extensions/universalchardet/src/base/Makefile.in index 8c7f9a1e3660..46d8e0e11afb 100644 --- a/extensions/universalchardet/src/base/Makefile.in +++ b/extensions/universalchardet/src/base/Makefile.in @@ -78,7 +78,5 @@ CPPSRCS = \ FORCE_STATIC_LIB = 1 LIBXUL_LIBRARY = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/gfx/cairo/cairo/src/Makefile.in b/gfx/cairo/cairo/src/Makefile.in index d910ac606035..06db33e42712 100644 --- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -241,8 +241,6 @@ endif LOCAL_INCLUDES += -I$(srcdir) FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/gfx/cairo/libpixman/src/Makefile.in b/gfx/cairo/libpixman/src/Makefile.in index 3f3637ab55ba..8f8b2128eb6c 100644 --- a/gfx/cairo/libpixman/src/Makefile.in +++ b/gfx/cairo/libpixman/src/Makefile.in @@ -171,8 +171,6 @@ EXPORTS = pixman.h pixman-version.h LOCAL_INCLUDES += -I$(srcdir) -I$(srcdir)/../../cairo/src FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/config.mk diff --git a/gfx/harfbuzz/src/Makefile.in b/gfx/harfbuzz/src/Makefile.in index 932a09bdfd85..f4b4527f7e7e 100644 --- a/gfx/harfbuzz/src/Makefile.in +++ b/gfx/harfbuzz/src/Makefile.in @@ -73,8 +73,6 @@ EXPORTS_harfbuzz = \ LOCAL_INCLUDES += -I$(srcdir) FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/gfx/ots/src/Makefile.in b/gfx/ots/src/Makefile.in index 84b42f4a75d7..ee40cb6a182b 100644 --- a/gfx/ots/src/Makefile.in +++ b/gfx/ots/src/Makefile.in @@ -79,8 +79,6 @@ EXPORTS = \ LOCAL_INCLUDES += -I$(srcdir) FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/gfx/qcms/Makefile.in b/gfx/qcms/Makefile.in index e6612f18789e..8424b8a60262 100644 --- a/gfx/qcms/Makefile.in +++ b/gfx/qcms/Makefile.in @@ -56,8 +56,6 @@ endif CFLAGS := $(filter-out -pedantic,$(CFLAGS)) FORCE_STATIC_LIB = 1 -# This library is used by other shared libs -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/gfx/src/Makefile.in b/gfx/src/Makefile.in index 988cca885343..b7f1cbf97e3e 100644 --- a/gfx/src/Makefile.in +++ b/gfx/src/Makefile.in @@ -49,8 +49,6 @@ EXPORT_LIBRARY = 1 GRE_MODULE = 1 LIBXUL_LIBRARY = 1 IS_COMPONENT = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 XPIDLSRCS = \ nsIFontEnumerator.idl \ diff --git a/image/decoders/icon/gtk/Makefile.in b/image/decoders/icon/gtk/Makefile.in index 1dabaa0fe02f..634ca8017bec 100644 --- a/image/decoders/icon/gtk/Makefile.in +++ b/image/decoders/icon/gtk/Makefile.in @@ -56,8 +56,6 @@ endif # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/image/decoders/icon/qt/Makefile.in b/image/decoders/icon/qt/Makefile.in index c31cc1d6ceae..fe0790d93814 100644 --- a/image/decoders/icon/qt/Makefile.in +++ b/image/decoders/icon/qt/Makefile.in @@ -52,8 +52,6 @@ LOCAL_INCLUDES += $(MOZ_QT_CFLAGS) # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 DIRS = public diff --git a/intl/unicharutil/util/Makefile.in b/intl/unicharutil/util/Makefile.in index 1ca92ba30d8b..bef60a0da7af 100644 --- a/intl/unicharutil/util/Makefile.in +++ b/intl/unicharutil/util/Makefile.in @@ -71,7 +71,6 @@ CPPSRCS = \ $(NULL) FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 USE_STATIC_LIBS = 1 LOCAL_INCLUDES += -I$(srcdir)/../src diff --git a/intl/unicharutil/util/internal/Makefile.in b/intl/unicharutil/util/internal/Makefile.in index 760236048874..0e583db75b3c 100644 --- a/intl/unicharutil/util/internal/Makefile.in +++ b/intl/unicharutil/util/internal/Makefile.in @@ -64,7 +64,6 @@ LOCAL_INCLUDES += -I$(srcdir)/.. \ CPPSRCS = $(INTL_UNICHARUTIL_UTIL_LCPPSRCS) FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/layout/inspector/src/Makefile.in b/layout/inspector/src/Makefile.in index 1043be4dafb2..0fc910ae263f 100644 --- a/layout/inspector/src/Makefile.in +++ b/layout/inspector/src/Makefile.in @@ -69,8 +69,6 @@ CPPSRCS += \ endif FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 LOCAL_INCLUDES += \ -I$(srcdir)/../../style \ diff --git a/media/libpng/Makefile.in b/media/libpng/Makefile.in index 993d7a3aa2d0..3313e39b0d13 100644 --- a/media/libpng/Makefile.in +++ b/media/libpng/Makefile.in @@ -80,8 +80,6 @@ EXPORTS = png.h pngconf.h mozpngconf.h LOCAL_INCLUDES = -I$(srcdir) FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/modules/libreg/src/Makefile.in b/modules/libreg/src/Makefile.in index 58e5132fae28..53bdf99bdf37 100644 --- a/modules/libreg/src/Makefile.in +++ b/modules/libreg/src/Makefile.in @@ -55,8 +55,6 @@ PROGOBJS = $(addprefix R_,$(BIN_SRCS:.c=.o)) # We don't want a shared lib. Static lib only. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 # We do want this in the static libraries list EXPORT_LIBRARY = 1 diff --git a/modules/zlib/src/Makefile.in b/modules/zlib/src/Makefile.in index 79003fa5dcf5..7328ca7589fa 100644 --- a/modules/zlib/src/Makefile.in +++ b/modules/zlib/src/Makefile.in @@ -57,7 +57,5 @@ CSRCS = $(MODULES_ZLIB_SRC_LCSRCS) EXPORTS = zlib.h zconf.h mozzconf.h -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/services/crypto/component/Makefile.in b/services/crypto/component/Makefile.in index 73b12b22cb94..3a77beae665a 100644 --- a/services/crypto/component/Makefile.in +++ b/services/crypto/component/Makefile.in @@ -55,7 +55,6 @@ EXPORT_LIBRARY = 1 IS_COMPONENT = 1 MODULE_NAME = nsServicesCryptoModule LIBXUL_LIBRARY = 1 -FORCE_USE_PIC = 1 MOZILLA_INTERNAL_API = 1 CPPSRCS = \ diff --git a/toolkit/components/alerts/mac/growl/Makefile.in b/toolkit/components/alerts/mac/growl/Makefile.in index 79270fe87a65..10e0c7d530d6 100644 --- a/toolkit/components/alerts/mac/growl/Makefile.in +++ b/toolkit/components/alerts/mac/growl/Makefile.in @@ -44,7 +44,6 @@ include $(DEPTH)/config/autoconf.mk MODULE = alerts LIBRARY_NAME = growl_s FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 CMSRCS = \ GrowlApplicationBridge.m \ diff --git a/toolkit/crashreporter/client/Makefile.in b/toolkit/crashreporter/client/Makefile.in index 467cc5a39bc0..c5c9b6adad45 100644 --- a/toolkit/crashreporter/client/Makefile.in +++ b/toolkit/crashreporter/client/Makefile.in @@ -122,7 +122,6 @@ LIBS += \ LOCAL_INCLUDES += -I$(srcdir) OS_CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GTHREAD_CFLAGS) OS_LIBS += $(MOZ_GTK2_LIBS) $(MOZ_GTHREAD_LIBS) -FORCE_USE_PIC=1 endif ifeq ($(OS_ARCH),SunOS) @@ -133,7 +132,6 @@ LIBS += \ LOCAL_INCLUDES += -I$(srcdir) OS_CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GTHREAD_CFLAGS) OS_LIBS += $(MOZ_GTK2_LIBS) $(MOZ_GTHREAD_LIBS) -FORCE_USE_PIC=1 endif include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/fileid/Makefile.in b/toolkit/crashreporter/fileid/Makefile.in index ab0ef10cf311..52efd6c814aa 100644 --- a/toolkit/crashreporter/fileid/Makefile.in +++ b/toolkit/crashreporter/fileid/Makefile.in @@ -59,7 +59,6 @@ HOST_LIBS += \ # force C++ linking CPP_PROG_LINK = 1 -FORCE_USE_PIC = 1 #XXX: bug 554854 causes us to be unable to run binaries on the build slaves # due to them having an older libstdc++ diff --git a/toolkit/crashreporter/google-breakpad/src/client/Makefile.in b/toolkit/crashreporter/google-breakpad/src/client/Makefile.in index 041e80cc8c11..f07d7ca9aad3 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/client/Makefile.in @@ -53,6 +53,5 @@ CPPSRCS = \ # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/Makefile.in b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/Makefile.in index 3ef204a51ff2..507f78cb7381 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/Makefile.in @@ -54,7 +54,6 @@ CPPSRCS = \ # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk ifeq ($(OS_ARCH),Linux) diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in index b1471a17de54..1fbf4a4e769b 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in @@ -67,7 +67,6 @@ CPPSRCS = \ # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 ifeq ($(OS_TARGET),Android) # NDK5 workarounds diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in index 51a7cfdfd292..a4b555249a20 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in @@ -55,6 +55,5 @@ CPPSRCS = \ # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/Makefile.in b/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/Makefile.in index 87300becb30c..611342c4b88f 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/Makefile.in @@ -55,6 +55,5 @@ CPPSRCS = \ # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in index 39e7a38a97f8..ab50776f72ad 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in @@ -90,6 +90,5 @@ HOST_CSRCS = $(CSRCS) # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in index 3af0ad9cf1f3..424614c2f15d 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in @@ -64,6 +64,5 @@ HOST_CPPSRCS = \ # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/solaris/Makefile.in index 60e1ecf0e7ca..b9c5603a7fb6 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/solaris/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/Makefile.in @@ -63,6 +63,5 @@ HOST_CPPSRCS = \ # need static lib FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/Makefile.in b/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/Makefile.in index 5145faee1b1b..fed5791ab6aa 100644 --- a/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/Makefile.in @@ -60,7 +60,6 @@ HOST_LIBS += \ # force C++ linking CPP_PROG_LINK = 1 -FORCE_USE_PIC = 1 #XXX: bug 554854 causes us to be unable to run binaries on the build slaves # due to them having an older libstdc++ diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in index 10ede3290671..000b45f5fc8c 100644 --- a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in @@ -61,6 +61,5 @@ HOST_LDFLAGS += -lelf -ldemangle # force C++ linking CPP_PROG_LINK = 1 -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index d201ece36c99..4dd5252d7d66 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -49,7 +49,6 @@ include $(topsrcdir)/intl/unicharutil/util/objs.mk MODULE = libxul LIBRARY_NAME = xul -FORCE_USE_PIC = 1 FORCE_SHARED_LIB = 1 MOZILLA_INTERNAL_API = 1 diff --git a/widget/src/qt/faststartupqt/Makefile.in b/widget/src/qt/faststartupqt/Makefile.in index cbee4f4aa743..f6741be430b8 100644 --- a/widget/src/qt/faststartupqt/Makefile.in +++ b/widget/src/qt/faststartupqt/Makefile.in @@ -45,7 +45,6 @@ MODULE = faststartupqt LIBRARY_NAME = faststartupqt DIST_INSTALL = 1 FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 STL_FLAGS= EXTRA_DSO_LDOPTS = \ diff --git a/xpcom/base/Makefile.in b/xpcom/base/Makefile.in index ee2ea8cb627e..08f31396882f 100644 --- a/xpcom/base/Makefile.in +++ b/xpcom/base/Makefile.in @@ -153,8 +153,6 @@ endif # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/config.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk diff --git a/xpcom/build/Makefile.in b/xpcom/build/Makefile.in index c2c1241ffdfb..50cbc364a04d 100644 --- a/xpcom/build/Makefile.in +++ b/xpcom/build/Makefile.in @@ -125,8 +125,6 @@ EXPORTS_mozilla = \ Omnijar.h \ $(NULL) -# Force use of PIC -FORCE_USE_PIC = 1 GARBAGE += $(XPCOM_GLUE_SRC_LCPPSRCS) $(XPCOM_GLUENS_SRC_LCPPSRCS) $(wildcard *.$(OBJ_SUFFIX)) diff --git a/xpcom/components/Makefile.in b/xpcom/components/Makefile.in index e47ea5134db1..3585d46b01b6 100644 --- a/xpcom/components/Makefile.in +++ b/xpcom/components/Makefile.in @@ -92,8 +92,6 @@ LOCAL_INCLUDES = \ # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk DEFINES += -D_IMPL_NS_COM diff --git a/xpcom/ds/Makefile.in b/xpcom/ds/Makefile.in index 7e8c1354bc14..f1b65dba5ad0 100644 --- a/xpcom/ds/Makefile.in +++ b/xpcom/ds/Makefile.in @@ -162,8 +162,6 @@ EXTRA_COMPONENTS = \ # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/xpcom/glue/Makefile.in b/xpcom/glue/Makefile.in index bf65dfc16be2..d2be70aa2277 100644 --- a/xpcom/glue/Makefile.in +++ b/xpcom/glue/Makefile.in @@ -144,8 +144,6 @@ SDK_LIBRARY = \ # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 # Pretend we're statically linking the CRT, even though we might not be: this # avoids "msvcrp" and assembly dependencies from creeping into the directives diff --git a/xpcom/glue/nomozalloc/Makefile.in b/xpcom/glue/nomozalloc/Makefile.in index e190e27f3228..28267f394b34 100644 --- a/xpcom/glue/nomozalloc/Makefile.in +++ b/xpcom/glue/nomozalloc/Makefile.in @@ -70,8 +70,6 @@ GARBAGE += $(CPPSRCS) DeadlockDetector.h SSE.h arm.h # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 # Pretend we're statically linking the CRT, even though we might not be: this # avoids "msvcrp" and assembly dependencies from creeping into the directives diff --git a/xpcom/glue/standalone/Makefile.in b/xpcom/glue/standalone/Makefile.in index 8c414ae55ea0..90cfbf9cee86 100644 --- a/xpcom/glue/standalone/Makefile.in +++ b/xpcom/glue/standalone/Makefile.in @@ -94,8 +94,6 @@ SDK_LIBRARY = \ # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 # Pretend we're statically linking the CRT, even though we might not be: this # avoids "msvcrp" and assembly dependencies from creeping into the directives diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in index 94b364efcbb7..b1bd18defcde 100644 --- a/xpcom/io/Makefile.in +++ b/xpcom/io/Makefile.in @@ -181,8 +181,6 @@ EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk diff --git a/xpcom/proxy/src/Makefile.in b/xpcom/proxy/src/Makefile.in index 59a3b42c4efa..bdaf69707543 100644 --- a/xpcom/proxy/src/Makefile.in +++ b/xpcom/proxy/src/Makefile.in @@ -60,8 +60,6 @@ LOCAL_INCLUDES += -I$(top_srcdir)/xpcom/threads/ # No shared lib; Force creation of static lib FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/xpcom/reflect/xptcall/src/Makefile.in b/xpcom/reflect/xptcall/src/Makefile.in index f2a772f053c6..3f6b4fd37c2c 100644 --- a/xpcom/reflect/xptcall/src/Makefile.in +++ b/xpcom/reflect/xptcall/src/Makefile.in @@ -54,8 +54,6 @@ CPPSRCS = xptcall.cpp # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/xpcom/reflect/xptcall/src/md/os2/Makefile.in b/xpcom/reflect/xptcall/src/md/os2/Makefile.in index e755eb74dfc8..67f2e02c791b 100644 --- a/xpcom/reflect/xptcall/src/md/os2/Makefile.in +++ b/xpcom/reflect/xptcall/src/md/os2/Makefile.in @@ -57,8 +57,6 @@ LOCAL_INCLUDES = \ $(NULL) DEFINES += -DMOZ_NEED_LEADING_UNDERSCORE -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/config.mk diff --git a/xpcom/reflect/xptcall/src/md/unix/Makefile.in b/xpcom/reflect/xptcall/src/md/unix/Makefile.in index 6c508213e48a..747a3d0c1bd2 100644 --- a/xpcom/reflect/xptcall/src/md/unix/Makefile.in +++ b/xpcom/reflect/xptcall/src/md/unix/Makefile.in @@ -53,8 +53,6 @@ MOZILLA_INTERNAL_API = 1 # CPPSRCS = $(error XPTCall not implemented on this platform!) -# Force use of PIC -FORCE_USE_PIC = 1 ifeq ($(OS_ARCH),SunOS) ifneq (86,$(findstring 86,$(OS_TEST))) diff --git a/xpcom/reflect/xptcall/src/md/win32/Makefile.in b/xpcom/reflect/xptcall/src/md/win32/Makefile.in index b6df7e98754c..fdbc0b998951 100644 --- a/xpcom/reflect/xptcall/src/md/win32/Makefile.in +++ b/xpcom/reflect/xptcall/src/md/win32/Makefile.in @@ -73,8 +73,6 @@ endif LOCAL_INCLUDES += -I$(srcdir)/../../../../xptinfo/src -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/config.mk diff --git a/xpcom/reflect/xptinfo/src/Makefile.in b/xpcom/reflect/xptinfo/src/Makefile.in index 84a572d01c31..74392dfed7c3 100644 --- a/xpcom/reflect/xptinfo/src/Makefile.in +++ b/xpcom/reflect/xptinfo/src/Makefile.in @@ -57,8 +57,6 @@ CPPSRCS = \ # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/xpcom/string/src/Makefile.in b/xpcom/string/src/Makefile.in index 74c95234a9e5..47a7a2448c7b 100644 --- a/xpcom/string/src/Makefile.in +++ b/xpcom/string/src/Makefile.in @@ -67,8 +67,6 @@ CPPSRCS = \ # static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 # Are we targeting x86 or x86-64? If so, compile the SSE2 functions for # nsUTF8Utils.cpp. diff --git a/xpcom/stub/Makefile.in b/xpcom/stub/Makefile.in index 276cec7ed71a..8a5675aa37da 100644 --- a/xpcom/stub/Makefile.in +++ b/xpcom/stub/Makefile.in @@ -67,8 +67,6 @@ else SDK_LIBRARY = $(SHARED_LIBRARY) endif -# Force use of PIC -FORCE_USE_PIC = 1 FORCE_SHARED_LIB = 1 diff --git a/xpcom/threads/Makefile.in b/xpcom/threads/Makefile.in index 82214d2ab786..aa444fb583e9 100644 --- a/xpcom/threads/Makefile.in +++ b/xpcom/threads/Makefile.in @@ -86,8 +86,6 @@ LOCAL_INCLUDES = -I$(srcdir)/../components # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -# Force use of PIC -FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk diff --git a/xpcom/typelib/xpt/src/Makefile.in b/xpcom/typelib/xpt/src/Makefile.in index 0c975e5b5460..6849b027808d 100644 --- a/xpcom/typelib/xpt/src/Makefile.in +++ b/xpcom/typelib/xpt/src/Makefile.in @@ -58,8 +58,6 @@ HOST_CSRCS = $(CSRCS) FORCE_STATIC_LIB = 1 USE_STATIC_LIBS = 1 -# Force use of PIC -FORCE_USE_PIC = 1 # Don't use profile-guided optimization NO_PROFILE_GUIDED_OPTIMIZE = 1 From 5d272b372365734140e5d7b4836bd13b05b45110 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 10 Nov 2011 20:26:13 +0100 Subject: [PATCH 10/38] Bug 699041 - Remove MBool / MB_TRUE / MB_FALSE; f=Ms2ger r=sicking --- content/xslt/src/base/txCore.h | 3 -- content/xslt/src/base/txDouble.cpp | 6 +-- content/xslt/src/base/txExpandedNameMap.h | 2 +- content/xslt/src/base/txList.cpp | 28 +++++------ content/xslt/src/base/txList.h | 14 +++--- content/xslt/src/xml/txDOM.h | 28 +++++------ content/xslt/src/xml/txXMLUtils.cpp | 4 +- content/xslt/src/xml/txXMLUtils.h | 10 ++-- content/xslt/src/xpath/nsXPathExpression.cpp | 4 +- content/xslt/src/xpath/txBooleanResult.cpp | 6 +-- content/xslt/src/xpath/txCoreFunctionCall.cpp | 10 ++-- content/xslt/src/xpath/txExprParser.cpp | 2 +- content/xslt/src/xpath/txExprParser.h | 2 +- content/xslt/src/xpath/txExprResult.h | 8 ++-- content/xslt/src/xpath/txForwardContext.cpp | 2 +- content/xslt/src/xpath/txIXPathContext.h | 4 +- content/xslt/src/xpath/txNameTest.cpp | 6 +-- content/xslt/src/xpath/txNodeSetContext.cpp | 2 +- content/xslt/src/xpath/txNodeSetContext.h | 2 +- content/xslt/src/xpath/txNumberResult.cpp | 4 +- content/xslt/src/xpath/txPathExpr.cpp | 2 +- content/xslt/src/xpath/txSingleNodeContext.h | 2 +- content/xslt/src/xpath/txStringResult.cpp | 2 +- .../xslt/src/xslt/txDocumentFunctionCall.cpp | 4 +- .../src/xslt/txFormatNumberFunctionCall.cpp | 16 +++---- content/xslt/src/xslt/txNodeSorter.cpp | 6 +-- content/xslt/src/xslt/txPatternParser.cpp | 16 +++---- content/xslt/src/xslt/txStylesheet.h | 8 ++-- .../src/xslt/txStylesheetCompileHandlers.cpp | 8 ++-- .../src/xslt/txStylesheetCompileHandlers.h | 2 +- .../xslt/src/xslt/txStylesheetCompiler.cpp | 12 ++--- content/xslt/src/xslt/txTextHandler.cpp | 2 +- content/xslt/src/xslt/txTextHandler.h | 4 +- .../xslt/src/xslt/txXPathResultComparator.cpp | 6 +-- .../xslt/src/xslt/txXPathResultComparator.h | 4 +- content/xslt/src/xslt/txXSLTFunctions.h | 2 +- content/xslt/src/xslt/txXSLTNumber.cpp | 30 ++++++------ content/xslt/src/xslt/txXSLTNumber.h | 2 +- .../xslt/src/xslt/txXSLTNumberCounters.cpp | 2 +- content/xslt/src/xslt/txXSLTPatterns.cpp | 46 +++++++++---------- content/xslt/src/xslt/txXSLTPatterns.h | 4 +- content/xslt/src/xslt/txXSLTProcessor.cpp | 8 ++-- content/xslt/src/xslt/txXSLTProcessor.h | 2 +- 43 files changed, 167 insertions(+), 170 deletions(-) diff --git a/content/xslt/src/base/txCore.h b/content/xslt/src/base/txCore.h index 873b35298ea9..9d76cb5fd3ca 100644 --- a/content/xslt/src/base/txCore.h +++ b/content/xslt/src/base/txCore.h @@ -109,10 +109,7 @@ public: // XXX These should go away eventually. #define TxObject txObject typedef txDouble Double; -typedef bool MBool; -#define MB_TRUE true -#define MB_FALSE false // XXX #endif diff --git a/content/xslt/src/base/txDouble.cpp b/content/xslt/src/base/txDouble.cpp index 3bfaf21a714f..3e97a47869c7 100644 --- a/content/xslt/src/base/txDouble.cpp +++ b/content/xslt/src/base/txDouble.cpp @@ -63,7 +63,7 @@ const dpun Double::NEGATIVE_INFINITY = {{0, DOUBLE_HI32_EXPMASK | DOUBLE_HI32_SI * Determines whether the given double represents positive or negative * inifinity */ -MBool Double::isInfinite(double aDbl) +bool Double::isInfinite(double aDbl) { return ((DOUBLE_HI32(aDbl) & ~DOUBLE_HI32_SIGNBIT) == DOUBLE_HI32_EXPMASK && !DOUBLE_LO32(aDbl)); @@ -72,7 +72,7 @@ MBool Double::isInfinite(double aDbl) /* * Determines whether the given double is NaN */ -MBool Double::isNaN(double aDbl) +bool Double::isNaN(double aDbl) { return DOUBLE_IS_NaN(aDbl); } @@ -80,7 +80,7 @@ MBool Double::isNaN(double aDbl) /* * Determines whether the given double is negative */ -MBool Double::isNeg(double aDbl) +bool Double::isNeg(double aDbl) { return (DOUBLE_HI32(aDbl) & DOUBLE_HI32_SIGNBIT) != 0; } diff --git a/content/xslt/src/base/txExpandedNameMap.h b/content/xslt/src/base/txExpandedNameMap.h index 769cba4217a6..fa1d5cfd46ab 100644 --- a/content/xslt/src/base/txExpandedNameMap.h +++ b/content/xslt/src/base/txExpandedNameMap.h @@ -95,7 +95,7 @@ protected: { } - MBool next() + bool next() { return ++mCurrentPos < mMap.mItems.Length(); } diff --git a/content/xslt/src/base/txList.cpp b/content/xslt/src/base/txList.cpp index 14f578233489..53a09c0d9588 100644 --- a/content/xslt/src/base/txList.cpp +++ b/content/xslt/src/base/txList.cpp @@ -243,7 +243,7 @@ void txList::clear() txListIterator::txListIterator(txList* list) { this->list = list; currentItem = 0; - atEndOfList = MB_FALSE; + atEndOfList = false; } //-- txListIterator /** @@ -276,11 +276,11 @@ nsresult txListIterator::addBefore(void* objPtr) /** * Returns true if a successful call to the next() method can be made - * @return MB_TRUE if a successful call to the next() method can be made, - * otherwise MB_FALSE + * @return true if a successful call to the next() method can be made, + * otherwise false **/ -MBool txListIterator::hasNext() { - MBool hasNext = MB_FALSE; +bool txListIterator::hasNext() { + bool hasNext = false; if (currentItem) hasNext = (currentItem->nextItem != 0); else if (!atEndOfList) @@ -291,11 +291,11 @@ MBool txListIterator::hasNext() { /** * Returns true if a successful call to the previous() method can be made - * @return MB_TRUE if a successful call to the previous() method can be made, - * otherwise MB_FALSE + * @return true if a successful call to the previous() method can be made, + * otherwise false **/ -MBool txListIterator::hasPrevious() { - MBool hasPrevious = MB_FALSE; +bool txListIterator::hasPrevious() { + bool hasPrevious = false; if (currentItem) hasPrevious = (currentItem->prevItem != 0); else if (atEndOfList) @@ -318,7 +318,7 @@ void* txListIterator::next() { if (currentItem) obj = currentItem->objPtr; else - atEndOfList = MB_TRUE; + atEndOfList = true; return obj; } //-- next @@ -338,7 +338,7 @@ void* txListIterator::previous() { if (currentItem) obj = currentItem->objPtr; - atEndOfList = MB_FALSE; + atEndOfList = false; return obj; } //-- previous @@ -379,7 +379,7 @@ void* txListIterator::advance(int i) { for (; currentItem && i < 0; i++) currentItem = currentItem->prevItem; - atEndOfList = MB_FALSE; + atEndOfList = false; } if (currentItem) @@ -409,7 +409,7 @@ void* txListIterator::remove() { * Resets the current location within the txList to the beginning of the txList **/ void txListIterator::reset() { - atEndOfList = MB_FALSE; + atEndOfList = false; currentItem = 0; } //-- reset @@ -417,6 +417,6 @@ void txListIterator::reset() { * Move the iterator to right after the last element **/ void txListIterator::resetToEnd() { - atEndOfList = MB_TRUE; + atEndOfList = true; currentItem = 0; } //-- moveToEnd diff --git a/content/xslt/src/base/txList.h b/content/xslt/src/base/txList.h index 4bbd20663186..924404fb934d 100644 --- a/content/xslt/src/base/txList.h +++ b/content/xslt/src/base/txList.h @@ -161,17 +161,17 @@ public: /** * Returns true if a successful call to the next() method can be made - * @return MB_TRUE if a successful call to the next() method can be made, - * otherwise MB_FALSE + * @return true if a successful call to the next() method can be made, + * otherwise false **/ - MBool hasNext(); + bool hasNext(); /** * Returns true if a successful call to the previous() method can be made - * @return MB_TRUE if a successful call to the previous() method can be made, - * otherwise MB_FALSE + * @return true if a successful call to the previous() method can be made, + * otherwise false **/ - MBool hasPrevious(); + bool hasPrevious(); /** * Returns the next Object pointer from the list @@ -218,7 +218,7 @@ private: txList* list; //-- we've moved off the end of the list - MBool atEndOfList; + bool atEndOfList; }; typedef txList List; diff --git a/content/xslt/src/xml/txDOM.h b/content/xslt/src/xml/txDOM.h index d6a31b1cef4b..edfbd41d3343 100644 --- a/content/xslt/src/xml/txDOM.h +++ b/content/xslt/src/xml/txDOM.h @@ -116,7 +116,7 @@ class Node : public TxObject //Node manipulation functions virtual Node* appendChild(Node* newChild) = 0; - virtual MBool hasChildNodes() const = 0; + virtual bool hasChildNodes() const = 0; //From DOM3 26-Jan-2001 WD virtual nsresult getBaseURI(nsAString& aURI) = 0; @@ -125,7 +125,7 @@ class Node : public TxObject virtual nsresult getNamespaceURI(nsAString& aNSURI) = 0; //txXPathNode functions - virtual MBool getLocalName(nsIAtom** aLocalName) = 0; + virtual bool getLocalName(nsIAtom** aLocalName) = 0; virtual PRInt32 getNamespaceID() = 0; virtual Node* getXPathParent() = 0; virtual PRInt32 compareDocumentPosition(Node* aOther) = 0; @@ -156,7 +156,7 @@ class NodeDefinition : public Node //Child node manipulation functions virtual Node* appendChild(Node* newChild); - MBool hasChildNodes() const; + bool hasChildNodes() const; //From DOM3 26-Jan-2001 WD virtual nsresult getBaseURI(nsAString& aURI); @@ -165,7 +165,7 @@ class NodeDefinition : public Node nsresult getNamespaceURI(nsAString& aNSURI); //txXPathNode functions - virtual MBool getLocalName(nsIAtom** aLocalName); + virtual bool getLocalName(nsIAtom** aLocalName); virtual PRInt32 getNamespaceID(); virtual Node* getXPathParent(); virtual PRInt32 compareDocumentPosition(Node* aOther); @@ -299,10 +299,10 @@ class Element : public NodeDefinition //txXPathNode functions override nsresult getNodeName(nsAString& aName) const; - MBool getLocalName(nsIAtom** aLocalName); + bool getLocalName(nsIAtom** aLocalName); PRInt32 getNamespaceID(); - MBool getAttr(nsIAtom* aLocalName, PRInt32 aNSID, nsAString& aValue); - MBool hasAttr(nsIAtom* aLocalName, PRInt32 aNSID); + bool getAttr(nsIAtom* aLocalName, PRInt32 aNSID, nsAString& aValue); + bool hasAttr(nsIAtom* aLocalName, PRInt32 aNSID); // ID getter bool getIDValue(nsAString& aValue); @@ -337,7 +337,7 @@ class Attr : public NodeDefinition //txXPathNode functions override nsresult getNodeName(nsAString& aName) const; - MBool getLocalName(nsIAtom** aLocalName); + bool getLocalName(nsIAtom** aLocalName); PRInt32 getNamespaceID(); Node* getXPathParent(); bool equals(nsIAtom *aLocalName, PRInt32 aNamespaceID) @@ -373,7 +373,7 @@ class ProcessingInstruction : public NodeDefinition { public: //txXPathNode functions override - MBool getLocalName(nsIAtom** aLocalName); + bool getLocalName(nsIAtom** aLocalName); private: friend class Document; @@ -415,15 +415,15 @@ public: return NS_OK; } - static MBool init() + static bool init() { NS_ASSERTION(!mNamespaces, "called without matching shutdown()"); if (mNamespaces) - return MB_TRUE; + return true; mNamespaces = new nsStringArray(); if (!mNamespaces) - return MB_FALSE; + return false; /* * Hardwiring some Namespace IDs. * no Namespace is 0 @@ -435,10 +435,10 @@ public: !mNamespaces->AppendString(NS_LITERAL_STRING("http://www.w3.org/1999/XSL/Transform"))) { delete mNamespaces; mNamespaces = 0; - return MB_FALSE; + return false; } - return MB_TRUE; + return true; } static void shutdown() diff --git a/content/xslt/src/xml/txXMLUtils.cpp b/content/xslt/src/xml/txXMLUtils.cpp index b125490c99ab..c40eb3beb63f 100644 --- a/content/xslt/src/xml/txXMLUtils.cpp +++ b/content/xslt/src/xml/txXMLUtils.cpp @@ -51,7 +51,7 @@ nsresult txExpandedName::init(const nsAString& aQName, txNamespaceMap* aResolver, - MBool aUseDefault) + bool aUseDefault) { const nsAFlatString& qName = PromiseFlatString(aQName); const PRUnichar* colon; @@ -230,7 +230,7 @@ void XMLUtils::normalizePIValue(nsAString& piValue) } //static -MBool XMLUtils::getXMLSpacePreserve(const txXPathNode& aNode) +bool XMLUtils::getXMLSpacePreserve(const txXPathNode& aNode) { nsAutoString value; txXPathTreeWalker walker(aNode); diff --git a/content/xslt/src/xml/txXMLUtils.h b/content/xslt/src/xml/txXMLUtils.h index 9da888ef4666..c2645e95c692 100644 --- a/content/xslt/src/xml/txXMLUtils.h +++ b/content/xslt/src/xml/txXMLUtils.h @@ -75,7 +75,7 @@ public: } nsresult init(const nsAString& aQName, txNamespaceMap* aResolver, - MBool aUseDefault); + bool aUseDefault); void reset() { @@ -95,13 +95,13 @@ public: return *this; } - MBool operator == (const txExpandedName& rhs) const + bool operator == (const txExpandedName& rhs) const { return ((mLocalName == rhs.mLocalName) && (mNamespaceID == rhs.mNamespaceID)); } - MBool operator != (const txExpandedName& rhs) const + bool operator != (const txExpandedName& rhs) const { return ((mLocalName != rhs.mLocalName) || (mNamespaceID != rhs.mNamespaceID)); @@ -124,7 +124,7 @@ public: /* * Returns true if the given character is whitespace. */ - static MBool isWhitespace(const PRUnichar& aChar) + static bool isWhitespace(const PRUnichar& aChar) { return (aChar <= ' ' && (aChar == ' ' || aChar == '\r' || @@ -173,7 +173,7 @@ public: * Walks up the document tree and returns true if the closest xml:space * attribute is "preserve" */ - static MBool getXMLSpacePreserve(const txXPathNode& aNode); + static bool getXMLSpacePreserve(const txXPathNode& aNode); }; #endif diff --git a/content/xslt/src/xpath/nsXPathExpression.cpp b/content/xslt/src/xpath/nsXPathExpression.cpp index 1527e49eed06..e8f96a9a4f84 100644 --- a/content/xslt/src/xpath/nsXPathExpression.cpp +++ b/content/xslt/src/xpath/nsXPathExpression.cpp @@ -196,9 +196,9 @@ nsXPathExpression::EvalContextImpl::getVariable(PRInt32 aNamespace, return NS_ERROR_INVALID_ARG; } -MBool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode) +bool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode) { - return MB_FALSE; + return false; } void* nsXPathExpression::EvalContextImpl::getPrivateContext() diff --git a/content/xslt/src/xpath/txBooleanResult.cpp b/content/xslt/src/xpath/txBooleanResult.cpp index a8595a574e22..ee1c581bb1d1 100644 --- a/content/xslt/src/xpath/txBooleanResult.cpp +++ b/content/xslt/src/xpath/txBooleanResult.cpp @@ -43,8 +43,8 @@ #include "txExprResult.h" /** - * Creates a new BooleanResult with the value of the given MBool parameter - * @param boolean the MBool to use for initialization of this BooleanResult's value + * Creates a new BooleanResult with the value of the given bool parameter + * @param boolean the bool to use for initialization of this BooleanResult's value **/ BooleanResult::BooleanResult(bool boolean) : txAExprResult(nsnull) @@ -80,7 +80,7 @@ BooleanResult::stringValuePointer() return nsnull; } -MBool BooleanResult::booleanValue() { +bool BooleanResult::booleanValue() { return this->value; } //-- toBoolean diff --git a/content/xslt/src/xpath/txCoreFunctionCall.cpp b/content/xslt/src/xpath/txCoreFunctionCall.cpp index 00e0d6355e34..19aa26a31397 100644 --- a/content/xslt/src/xpath/txCoreFunctionCall.cpp +++ b/content/xslt/src/xpath/txCoreFunctionCall.cpp @@ -303,23 +303,23 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes)); NS_ENSURE_SUCCESS(rv, rv); - MBool addSpace = MB_FALSE; - MBool first = MB_TRUE; + bool addSpace = false; + bool first = true; strRes->mValue.SetCapacity(resultStr.Length()); PRUnichar c; PRUint32 src; for (src = 0; src < resultStr.Length(); src++) { c = resultStr.CharAt(src); if (XMLUtils::isWhitespace(c)) { - addSpace = MB_TRUE; + addSpace = true; } else { if (addSpace && !first) strRes->mValue.Append(PRUnichar(' ')); strRes->mValue.Append(c); - addSpace = MB_FALSE; - first = MB_FALSE; + addSpace = false; + first = false; } } *aResult = strRes; diff --git a/content/xslt/src/xpath/txExprParser.cpp b/content/xslt/src/xpath/txExprParser.cpp index 5094bb1e3358..222a1f5178b4 100644 --- a/content/xslt/src/xpath/txExprParser.cpp +++ b/content/xslt/src/xpath/txExprParser.cpp @@ -302,7 +302,7 @@ txExprParser::createExpr(txExprLexer& lexer, txIParseContext* aContext, *aResult = nsnull; nsresult rv = NS_OK; - MBool done = MB_FALSE; + bool done = false; nsAutoPtr expr; diff --git a/content/xslt/src/xpath/txExprParser.h b/content/xslt/src/xpath/txExprParser.h index 16f7b4b2b2ca..563e6d729c8b 100644 --- a/content/xslt/src/xpath/txExprParser.h +++ b/content/xslt/src/xpath/txExprParser.h @@ -122,7 +122,7 @@ protected: static nsresult resolveQName(const nsAString& aQName, nsIAtom** aPrefix, txIParseContext* aContext, nsIAtom** aLocalName, PRInt32& aNamespace, - bool aIsNameTest = MB_FALSE); + bool aIsNameTest = false); /** * Using the given lexer, parses the tokens if they represent a diff --git a/content/xslt/src/xpath/txExprResult.h b/content/xslt/src/xpath/txExprResult.h index 1700e3cad3b5..aad11d50eb97 100644 --- a/content/xslt/src/xpath/txExprResult.h +++ b/content/xslt/src/xpath/txExprResult.h @@ -104,10 +104,10 @@ public: virtual const nsString* stringValuePointer() = 0; /** - * Converts this ExprResult to a Boolean (MBool) value + * Converts this ExprResult to a Boolean (bool) value * @return the Boolean value **/ - virtual MBool booleanValue() = 0; + virtual bool booleanValue() = 0; /** * Converts this ExprResult to a Number (double) value @@ -131,12 +131,12 @@ private: class BooleanResult : public txAExprResult { public: - BooleanResult(MBool aValue); + BooleanResult(bool aValue); TX_DECL_EXPRRESULT private: - MBool value; + bool value; }; class NumberResult : public txAExprResult { diff --git a/content/xslt/src/xpath/txForwardContext.cpp b/content/xslt/src/xpath/txForwardContext.cpp index 9b2d94f75735..0a3f67c08119 100644 --- a/content/xslt/src/xpath/txForwardContext.cpp +++ b/content/xslt/src/xpath/txForwardContext.cpp @@ -63,7 +63,7 @@ nsresult txForwardContext::getVariable(PRInt32 aNamespace, nsIAtom* aLName, return mInner->getVariable(aNamespace, aLName, aResult); } -MBool txForwardContext::isStripSpaceAllowed(const txXPathNode& aNode) +bool txForwardContext::isStripSpaceAllowed(const txXPathNode& aNode) { NS_ASSERTION(mInner, "mInner is null!!!"); return mInner->isStripSpaceAllowed(aNode); diff --git a/content/xslt/src/xpath/txIXPathContext.h b/content/xslt/src/xpath/txIXPathContext.h index 7f9b4e31ba08..72b323e07fae 100644 --- a/content/xslt/src/xpath/txIXPathContext.h +++ b/content/xslt/src/xpath/txIXPathContext.h @@ -113,7 +113,7 @@ public: * Is whitespace stripping allowed for the given node? * See http://www.w3.org/TR/xslt#strip */ - virtual MBool isStripSpaceAllowed(const txXPathNode& aNode) = 0; + virtual bool isStripSpaceAllowed(const txXPathNode& aNode) = 0; /** * Returns a pointer to the private context @@ -131,7 +131,7 @@ public: #define TX_DECL_MATCH_CONTEXT \ nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName, \ txAExprResult*& aResult); \ - MBool isStripSpaceAllowed(const txXPathNode& aNode); \ + bool isStripSpaceAllowed(const txXPathNode& aNode); \ void* getPrivateContext(); \ txResultRecycler* recycler(); \ void receiveError(const nsAString& aMsg, nsresult aRes) diff --git a/content/xslt/src/xpath/txNameTest.cpp b/content/xslt/src/xpath/txNameTest.cpp index 72ab2f78e257..7b1c529fc320 100644 --- a/content/xslt/src/xpath/txNameTest.cpp +++ b/content/xslt/src/xpath/txNameTest.cpp @@ -69,18 +69,18 @@ bool txNameTest::matches(const txXPathNode& aNode, txIMatchContext* aContext) // Totally wild? if (mLocalName == nsGkAtoms::_asterix && !mPrefix) - return MB_TRUE; + return true; // Compare namespaces if (mNamespace != txXPathNodeUtils::getNamespaceID(aNode) && !(mNamespace == kNameSpaceID_None && txXPathNodeUtils::isHTMLElementInHTMLDocument(aNode)) ) - return MB_FALSE; + return false; // Name wild? if (mLocalName == nsGkAtoms::_asterix) - return MB_TRUE; + return true; // Compare local-names return txXPathNodeUtils::localNameEquals(aNode, mLocalName); diff --git a/content/xslt/src/xpath/txNodeSetContext.cpp b/content/xslt/src/xpath/txNodeSetContext.cpp index 0217703c23dd..a9b1cd57b6b2 100644 --- a/content/xslt/src/xpath/txNodeSetContext.cpp +++ b/content/xslt/src/xpath/txNodeSetContext.cpp @@ -62,7 +62,7 @@ nsresult txNodeSetContext::getVariable(PRInt32 aNamespace, nsIAtom* aLName, return mInner->getVariable(aNamespace, aLName, aResult); } -MBool txNodeSetContext::isStripSpaceAllowed(const txXPathNode& aNode) +bool txNodeSetContext::isStripSpaceAllowed(const txXPathNode& aNode) { NS_ASSERTION(mInner, "mInner is null!!!"); return mInner->isStripSpaceAllowed(aNode); diff --git a/content/xslt/src/xpath/txNodeSetContext.h b/content/xslt/src/xpath/txNodeSetContext.h index b8d16b0096f8..d64d898696da 100644 --- a/content/xslt/src/xpath/txNodeSetContext.h +++ b/content/xslt/src/xpath/txNodeSetContext.h @@ -52,7 +52,7 @@ public: } // Iteration over the given NodeSet - MBool hasNext() + bool hasNext() { return mPosition < size(); } diff --git a/content/xslt/src/xpath/txNumberResult.cpp b/content/xslt/src/xpath/txNumberResult.cpp index 8485a5bf7703..edea4c3ab49b 100644 --- a/content/xslt/src/xpath/txNumberResult.cpp +++ b/content/xslt/src/xpath/txNumberResult.cpp @@ -76,11 +76,11 @@ NumberResult::stringValuePointer() return nsnull; } -MBool NumberResult::booleanValue() { +bool NumberResult::booleanValue() { // OG+ // As per the XPath spec, the boolean value of a number is true if and only if // it is neither positive 0 nor negative 0 nor NaN - return (MBool)(value != 0.0 && !Double::isNaN(value)); + return (bool)(value != 0.0 && !Double::isNaN(value)); // OG- } //-- booleanValue diff --git a/content/xslt/src/xpath/txPathExpr.cpp b/content/xslt/src/xpath/txPathExpr.cpp index acd543491c35..c28ed2b1b4ed 100644 --- a/content/xslt/src/xpath/txPathExpr.cpp +++ b/content/xslt/src/xpath/txPathExpr.cpp @@ -193,7 +193,7 @@ PathExpr::evalDescendants(Expr* aStep, const txXPathNode& aNode, resNodes->addAndTransfer(newSet); - MBool filterWS = aContext->isStripSpaceAllowed(aNode); + bool filterWS = aContext->isStripSpaceAllowed(aNode); txXPathTreeWalker walker(aNode); if (!walker.moveToFirstChild()) { diff --git a/content/xslt/src/xpath/txSingleNodeContext.h b/content/xslt/src/xpath/txSingleNodeContext.h index eade9b58a778..4c2b6d2955af 100644 --- a/content/xslt/src/xpath/txSingleNodeContext.h +++ b/content/xslt/src/xpath/txSingleNodeContext.h @@ -59,7 +59,7 @@ public: return mInner->getVariable(aNamespace, aLName, aResult); } - MBool isStripSpaceAllowed(const txXPathNode& aNode) + bool isStripSpaceAllowed(const txXPathNode& aNode) { NS_ASSERTION(mInner, "mInner is null!!!"); return mInner->isStripSpaceAllowed(aNode); diff --git a/content/xslt/src/xpath/txStringResult.cpp b/content/xslt/src/xpath/txStringResult.cpp index 2f206af84f6f..a1d1362afb70 100644 --- a/content/xslt/src/xpath/txStringResult.cpp +++ b/content/xslt/src/xpath/txStringResult.cpp @@ -79,7 +79,7 @@ StringResult::stringValuePointer() return &mValue; } -MBool StringResult::booleanValue() { +bool StringResult::booleanValue() { return !mValue.IsEmpty(); } //-- booleanValue diff --git a/content/xslt/src/xslt/txDocumentFunctionCall.cpp b/content/xslt/src/xslt/txDocumentFunctionCall.cpp index 2478ac11a371..7ed4776cfef3 100644 --- a/content/xslt/src/xslt/txDocumentFunctionCall.cpp +++ b/content/xslt/src/xslt/txDocumentFunctionCall.cpp @@ -121,7 +121,7 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext, NS_ENSURE_SUCCESS(rv, rv); nsAutoString baseURI; - MBool baseURISet = MB_FALSE; + bool baseURISet = false; if (mParams.Length() == 2) { // We have 2 arguments, get baseURI from the first node @@ -134,7 +134,7 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext, // Make this true, even if nodeSet2 is empty. For relative URLs, // we'll fail to load the document with an empty base URI, and for // absolute URLs, the base URI doesn't matter - baseURISet = MB_TRUE; + baseURISet = true; if (!nodeSet2->isEmpty()) { txXPathNodeUtils::getBaseURI(nodeSet2->get(0), baseURI); diff --git a/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp b/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp index fa6c795418ac..131e3daac8e6 100644 --- a/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp +++ b/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp @@ -96,7 +96,7 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext, rv = mParams[2]->evaluateToString(aContext, formatQName); NS_ENSURE_SUCCESS(rv, rv); - rv = formatName.init(formatQName, mMappings, MB_FALSE); + rv = formatName.init(formatQName, mMappings, false); NS_ENSURE_SUCCESS(rv, rv); } @@ -139,10 +139,10 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext, PRUint32 pos = 0; PRUint32 formatLen = formatStr.Length(); - MBool inQuote; + bool inQuote; // Get right subexpression - inQuote = MB_FALSE; + inQuote = false; if (Double::isNeg(value)) { while (pos < formatLen && (inQuote || @@ -162,7 +162,7 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext, // Parse the format string FormatParseState pState = Prefix; - inQuote = MB_FALSE; + inQuote = false; PRUnichar c = 0; while (pos < formatLen && pState != Finished) { @@ -327,8 +327,8 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext, (intDigits-1)/groupSize); // group separators PRInt32 i = bufIntDigits + maxFractionSize - 1; - MBool carry = (i+1 < buflen) && (buf[i+1] >= '5'); - MBool hasFraction = MB_FALSE; + bool carry = (i+1 < buflen) && (buf[i+1] >= '5'); + bool hasFraction = false; PRUint32 resPos = res.Length()-1; @@ -348,7 +348,7 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext, } if (hasFraction || digit != 0 || i < bufIntDigits+minFractionSize) { - hasFraction = MB_TRUE; + hasFraction = true; res.SetCharAt((PRUnichar)(digit + format->mZeroDigit), resPos--); } @@ -448,7 +448,7 @@ txDecimalFormat::txDecimalFormat() : mInfinity(NS_LITERAL_STRING("Infinity")), mPatternSeparator = ';'; } -MBool txDecimalFormat::isEqual(txDecimalFormat* other) +bool txDecimalFormat::isEqual(txDecimalFormat* other) { return mDecimalSeparator == other->mDecimalSeparator && mGroupingSeparator == other->mGroupingSeparator && diff --git a/content/xslt/src/xslt/txNodeSorter.cpp b/content/xslt/src/xslt/txNodeSorter.cpp index a6f6ab2103b8..94489d105d77 100644 --- a/content/xslt/src/xslt/txNodeSorter.cpp +++ b/content/xslt/src/xslt/txNodeSorter.cpp @@ -78,14 +78,14 @@ txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr, key->mExpr = aSelectExpr; // Order - MBool ascending = MB_TRUE; + bool ascending = true; if (aOrderExpr) { nsAutoString attrValue; rv = aOrderExpr->evaluateToString(aContext, attrValue); NS_ENSURE_SUCCESS(rv, rv); if (TX_StringEqualsAtom(attrValue, nsGkAtoms::descending)) { - ascending = MB_FALSE; + ascending = false; } else if (!TX_StringEqualsAtom(attrValue, nsGkAtoms::ascending)) { // XXX ErrorReport: unknown value for order attribute @@ -112,7 +112,7 @@ txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr, } // Case-order - MBool upperFirst = false; + bool upperFirst = false; if (aCaseOrderExpr) { nsAutoString attrValue; diff --git a/content/xslt/src/xslt/txPatternParser.cpp b/content/xslt/src/xslt/txPatternParser.cpp index ec585119a0d6..38763e1c09e8 100644 --- a/content/xslt/src/xslt/txPatternParser.cpp +++ b/content/xslt/src/xslt/txPatternParser.cpp @@ -139,21 +139,21 @@ nsresult txPatternParser::createLocPathPattern(txExprLexer& aLexer, { nsresult rv = NS_OK; - MBool isChild = MB_TRUE; - MBool isAbsolute = MB_FALSE; + bool isChild = true; + bool isAbsolute = false; txPattern* stepPattern = 0; txLocPathPattern* pathPattern = 0; Token::Type type = aLexer.peek()->mType; switch (type) { case Token::ANCESTOR_OP: - isChild = MB_FALSE; - isAbsolute = MB_TRUE; + isChild = false; + isAbsolute = true; aLexer.nextToken(); break; case Token::PARENT_OP: aLexer.nextToken(); - isAbsolute = MB_TRUE; + isAbsolute = true; if (aLexer.peek()->mType == Token::END || aLexer.peek()->mType == Token::UNION_OP) { aPattern = new txRootPattern(); @@ -299,11 +299,11 @@ nsresult txPatternParser::createStepPattern(txExprLexer& aLexer, txPattern*& aPattern) { nsresult rv = NS_OK; - MBool isAttr = MB_FALSE; + bool isAttr = false; Token* tok = aLexer.peek(); if (tok->mType == Token::AXIS_IDENTIFIER) { if (TX_StringEqualsAtom(tok->Value(), nsGkAtoms::attribute)) { - isAttr = MB_TRUE; + isAttr = true; } else if (!TX_StringEqualsAtom(tok->Value(), nsGkAtoms::child)) { // all done already for CHILD_AXIS, for all others @@ -314,7 +314,7 @@ nsresult txPatternParser::createStepPattern(txExprLexer& aLexer, } else if (tok->mType == Token::AT_SIGN) { aLexer.nextToken(); - isAttr = MB_TRUE; + isAttr = true; } tok = aLexer.nextToken(); diff --git a/content/xslt/src/xslt/txStylesheet.h b/content/xslt/src/xslt/txStylesheet.h index 9fcd0d9a55b9..05825efb42fb 100644 --- a/content/xslt/src/xslt/txStylesheet.h +++ b/content/xslt/src/xslt/txStylesheet.h @@ -192,17 +192,17 @@ private: class txStripSpaceTest { public: txStripSpaceTest(nsIAtom* aPrefix, nsIAtom* aLocalName, PRInt32 aNSID, - MBool stripSpace) + bool stripSpace) : mNameTest(aPrefix, aLocalName, aNSID, txXPathNodeType::ELEMENT_NODE), mStrips(stripSpace) { } - MBool matches(const txXPathNode& aNode, txIMatchContext* aContext) { + bool matches(const txXPathNode& aNode, txIMatchContext* aContext) { return mNameTest.matches(aNode, aContext); } - MBool stripsSpace() { + bool stripsSpace() { return mStrips; } @@ -212,7 +212,7 @@ public: protected: txNameTest mNameTest; - MBool mStrips; + bool mStrips; }; /** diff --git a/content/xslt/src/xslt/txStylesheetCompileHandlers.cpp b/content/xslt/src/xslt/txStylesheetCompileHandlers.cpp index 52389f7238ac..e68e2a1baa8c 100644 --- a/content/xslt/src/xslt/txStylesheetCompileHandlers.cpp +++ b/content/xslt/src/xslt/txStylesheetCompileHandlers.cpp @@ -1367,7 +1367,7 @@ txFnText(const nsAString& aStr, txStylesheetCompilerState& aState) { TX_RETURN_IF_WHITESPACE(aStr, aState); - nsAutoPtr instr(new txText(aStr, MB_FALSE)); + nsAutoPtr instr(new txText(aStr, false)); NS_ENSURE_TRUE(instr, NS_ERROR_OUT_OF_MEMORY); nsresult rv = aState.addInstruction(instr); @@ -2413,7 +2413,7 @@ txFnStartText(PRInt32 aNamespaceID, static nsresult txFnEndText(txStylesheetCompilerState& aState) { - aState.mDOE = MB_FALSE; + aState.mDOE = false; aState.popHandlerTable(); return NS_OK; } @@ -3044,7 +3044,7 @@ txHandlerTable::find(PRInt32 aNamespaceID, nsIAtom* aLocalName) gTx##_name##Handler = nsnull // static -MBool +bool txHandlerTable::init() { nsresult rv = NS_OK; @@ -3066,7 +3066,7 @@ txHandlerTable::init() INIT_HANDLER_WITH_ELEMENT_HANDLERS(AttributeSet); INIT_HANDLER_WITH_ELEMENT_HANDLERS(Fallback); - return MB_TRUE; + return true; } // static diff --git a/content/xslt/src/xslt/txStylesheetCompileHandlers.h b/content/xslt/src/xslt/txStylesheetCompileHandlers.h index f531a8af9f7b..4de7213bbf28 100644 --- a/content/xslt/src/xslt/txStylesheetCompileHandlers.h +++ b/content/xslt/src/xslt/txStylesheetCompileHandlers.h @@ -75,7 +75,7 @@ public: const HandleTextFn mTextHandler; const txElementHandler* const mLREHandler; - static MBool init(); + static bool init(); static void shutdown(); private: diff --git a/content/xslt/src/xslt/txStylesheetCompiler.cpp b/content/xslt/src/xslt/txStylesheetCompiler.cpp index 4240fdf84ca9..bf1b90e094c6 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStylesheetCompiler.cpp @@ -227,10 +227,10 @@ txStylesheetCompiler::startElementInternal(PRInt32 aNamespaceID, NS_ENSURE_SUCCESS(rv, rv); if (TX_StringEqualsAtom(attr->mValue, nsGkAtoms::preserve)) { - mElementContext->mPreserveWhitespace = MB_TRUE; + mElementContext->mPreserveWhitespace = true; } else if (TX_StringEqualsAtom(attr->mValue, nsGkAtoms::_default)) { - mElementContext->mPreserveWhitespace = MB_FALSE; + mElementContext->mPreserveWhitespace = false; } else { return NS_ERROR_XSLT_PARSE_FAILURE; @@ -291,20 +291,20 @@ txStylesheetCompiler::startElementInternal(PRInt32 aNamespaceID, NS_ENSURE_SUCCESS(rv, rv); if (attr->mValue.EqualsLiteral("1.0")) { - mElementContext->mForwardsCompatibleParsing = MB_FALSE; + mElementContext->mForwardsCompatibleParsing = false; } else { - mElementContext->mForwardsCompatibleParsing = MB_TRUE; + mElementContext->mForwardsCompatibleParsing = true; } } } // Find the right elementhandler and execute it - MBool isInstruction = MB_FALSE; + bool isInstruction = false; PRInt32 count = mElementContext->mInstructionNamespaces.Length(); for (i = 0; i < count; ++i) { if (mElementContext->mInstructionNamespaces[i] == aNamespaceID) { - isInstruction = MB_TRUE; + isInstruction = true; break; } } diff --git a/content/xslt/src/xslt/txTextHandler.cpp b/content/xslt/src/xslt/txTextHandler.cpp index 219470878b23..1410a706aa31 100644 --- a/content/xslt/src/xslt/txTextHandler.cpp +++ b/content/xslt/src/xslt/txTextHandler.cpp @@ -39,7 +39,7 @@ #include "txTextHandler.h" #include "nsAString.h" -txTextHandler::txTextHandler(MBool aOnlyText) : mLevel(0), +txTextHandler::txTextHandler(bool aOnlyText) : mLevel(0), mOnlyText(aOnlyText) { } diff --git a/content/xslt/src/xslt/txTextHandler.h b/content/xslt/src/xslt/txTextHandler.h index be5be2f49375..8872e7277beb 100644 --- a/content/xslt/src/xslt/txTextHandler.h +++ b/content/xslt/src/xslt/txTextHandler.h @@ -45,7 +45,7 @@ class txTextHandler : public txAXMLEventHandler { public: - txTextHandler(MBool aOnlyText); + txTextHandler(bool aOnlyText); TX_DECL_TXAXMLEVENTHANDLER @@ -53,7 +53,7 @@ public: private: PRUint32 mLevel; - MBool mOnlyText; + bool mOnlyText; }; #endif diff --git a/content/xslt/src/xslt/txXPathResultComparator.cpp b/content/xslt/src/xslt/txXPathResultComparator.cpp index 2a28f1859224..6fa50c5a5635 100644 --- a/content/xslt/src/xslt/txXPathResultComparator.cpp +++ b/content/xslt/src/xslt/txXPathResultComparator.cpp @@ -50,8 +50,8 @@ #define kAscending (1<<0) #define kUpperFirst (1<<1) -txResultStringComparator::txResultStringComparator(MBool aAscending, - MBool aUpperFirst, +txResultStringComparator::txResultStringComparator(bool aAscending, + bool aUpperFirst, const nsAFlatString& aLanguage) { mSorting = 0; @@ -215,7 +215,7 @@ txResultStringComparator::StringValue::~StringValue() delete (nsString*)mCaseKey; } -txResultNumberComparator::txResultNumberComparator(MBool aAscending) +txResultNumberComparator::txResultNumberComparator(bool aAscending) { mAscending = aAscending ? 1 : -1; } diff --git a/content/xslt/src/xslt/txXPathResultComparator.h b/content/xslt/src/xslt/txXPathResultComparator.h index cd1958e20378..c70e72d69b04 100644 --- a/content/xslt/src/xslt/txXPathResultComparator.h +++ b/content/xslt/src/xslt/txXPathResultComparator.h @@ -77,7 +77,7 @@ public: class txResultStringComparator : public txXPathResultComparator { public: - txResultStringComparator(MBool aAscending, MBool aUpperFirst, + txResultStringComparator(bool aAscending, bool aUpperFirst, const nsAFlatString& aLanguage); int compareValues(TxObject* aVal1, TxObject* aVal2); @@ -110,7 +110,7 @@ private: class txResultNumberComparator : public txXPathResultComparator { public: - txResultNumberComparator(MBool aAscending); + txResultNumberComparator(bool aAscending); int compareValues(TxObject* aVal1, TxObject* aVal2); nsresult createSortableValue(Expr *aExpr, txIEvalContext *aContext, diff --git a/content/xslt/src/xslt/txXSLTFunctions.h b/content/xslt/src/xslt/txXSLTFunctions.h index f02c92b8bce7..a3f98cf8b4d1 100644 --- a/content/xslt/src/xslt/txXSLTFunctions.h +++ b/content/xslt/src/xslt/txXSLTFunctions.h @@ -127,7 +127,7 @@ public: * default values */ txDecimalFormat(); - MBool isEqual(txDecimalFormat* other); + bool isEqual(txDecimalFormat* other); PRUnichar mDecimalSeparator; PRUnichar mGroupingSeparator; diff --git a/content/xslt/src/xslt/txXSLTNumber.cpp b/content/xslt/src/xslt/txXSLTNumber.cpp index 28dfe577baf4..3056f277bc94 100644 --- a/content/xslt/src/xslt/txXSLTNumber.cpp +++ b/content/xslt/src/xslt/txXSLTNumber.cpp @@ -76,7 +76,7 @@ nsresult txXSLTNumber::createNumber(Expr* aValueExpr, txPattern* aCountPattern, // Create resulting string aResult = head; - MBool first = MB_TRUE; + bool first = true; txListIterator valueIter(&values); txListIterator counterIter(&counters); valueIter.resetToEnd(); @@ -92,7 +92,7 @@ nsresult txXSLTNumber::createNumber(Expr* aValueExpr, txPattern* aCountPattern, } counter->appendNumber(value, aResult); - first = MB_FALSE; + first = false; } aResult.Append(tail); @@ -136,13 +136,13 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, // Otherwise use count/from/level txPattern* countPattern = aCountPattern; - MBool ownsCountPattern = MB_FALSE; + bool ownsCountPattern = false; const txXPathNode& currNode = aContext->getContextNode(); // Parse count- and from-attributes if (!aCountPattern) { - ownsCountPattern = MB_TRUE; + ownsCountPattern = true; txNodeTest* nodeTest; PRUint16 nodeType = txXPathNodeUtils::getNodeType(currNode); switch (nodeType) { @@ -191,7 +191,7 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, } NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY); - countPattern = new txStepPattern(nodeTest, MB_FALSE); + countPattern = new txStepPattern(nodeTest, false); if (!countPattern) { // XXX error reporting delete nodeTest; @@ -239,12 +239,12 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, else if (aLevel == eLevelMultiple) { // find all ancestor-or-selfs that matches count until... txXPathTreeWalker walker(currNode); - MBool matchedFrom = MB_FALSE; + bool matchedFrom = false; do { if (aFromPattern && !walker.isOnNode(currNode) && aFromPattern->matches(walker.getCurrentPosition(), aContext)) { //... we find one that matches from - matchedFrom = MB_TRUE; + matchedFrom = true; break; } @@ -264,13 +264,13 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, // level = "any" else if (aLevel == eLevelAny) { PRInt32 value = 0; - MBool matchedFrom = MB_FALSE; + bool matchedFrom = false; txXPathTreeWalker walker(currNode); do { if (aFromPattern && !walker.isOnNode(currNode) && aFromPattern->matches(walker.getCurrentPosition(), aContext)) { - matchedFrom = MB_TRUE; + matchedFrom = true; break; } @@ -450,12 +450,12 @@ txXSLTNumber::getPrevInDocumentOrder(txXPathTreeWalker& aWalker) return aWalker.moveToParent(); } -#define TX_CHAR_RANGE(ch, a, b) if (ch < a) return MB_FALSE; \ - if (ch <= b) return MB_TRUE -#define TX_MATCH_CHAR(ch, a) if (ch < a) return MB_FALSE; \ - if (ch == a) return MB_TRUE +#define TX_CHAR_RANGE(ch, a, b) if (ch < a) return false; \ + if (ch <= b) return true +#define TX_MATCH_CHAR(ch, a) if (ch < a) return false; \ + if (ch == a) return true -MBool txXSLTNumber::isAlphaNumeric(PRUnichar ch) +bool txXSLTNumber::isAlphaNumeric(PRUnichar ch) { TX_CHAR_RANGE(ch, 0x0030, 0x0039); TX_CHAR_RANGE(ch, 0x0041, 0x005A); @@ -747,5 +747,5 @@ MBool txXSLTNumber::isAlphaNumeric(PRUnichar ch) TX_CHAR_RANGE(ch, 0xFFC2, 0xFFC7); TX_CHAR_RANGE(ch, 0xFFCA, 0xFFCF); TX_CHAR_RANGE(ch, 0xFFD2, 0xFFD7); - return MB_FALSE; + return false; } diff --git a/content/xslt/src/xslt/txXSLTNumber.h b/content/xslt/src/xslt/txXSLTNumber.h index d6fe96464136..3e801372b733 100644 --- a/content/xslt/src/xslt/txXSLTNumber.h +++ b/content/xslt/src/xslt/txXSLTNumber.h @@ -85,7 +85,7 @@ private: static bool getPrevInDocumentOrder(txXPathTreeWalker& aWalker); - static MBool isAlphaNumeric(PRUnichar ch); + static bool isAlphaNumeric(PRUnichar ch); }; class txFormattedCounter { diff --git a/content/xslt/src/xslt/txXSLTNumberCounters.cpp b/content/xslt/src/xslt/txXSLTNumberCounters.cpp index 7a91c1ab4e84..54c9e2f7c6f5 100644 --- a/content/xslt/src/xslt/txXSLTNumberCounters.cpp +++ b/content/xslt/src/xslt/txXSLTNumberCounters.cpp @@ -71,7 +71,7 @@ private: class txRomanCounter : public txFormattedCounter { public: - txRomanCounter(MBool aUpper) : mTableOffset(aUpper ? 30 : 0) + txRomanCounter(bool aUpper) : mTableOffset(aUpper ? 30 : 0) { } diff --git a/content/xslt/src/xslt/txXSLTPatterns.cpp b/content/xslt/src/xslt/txXSLTPatterns.cpp index 9028d5e3e587..cc54ff17917c 100644 --- a/content/xslt/src/xslt/txXSLTPatterns.cpp +++ b/content/xslt/src/xslt/txXSLTPatterns.cpp @@ -63,15 +63,15 @@ double txUnionPattern::getDefaultPriority() * This should be called on the simple patterns for xsl:template, * but is fine for xsl:key and xsl:number */ -MBool txUnionPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) +bool txUnionPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { PRUint32 i, len = mLocPathPatterns.Length(); for (i = 0; i < len; ++i) { if (mLocPathPatterns[i]->matches(aNode, aContext)) { - return MB_TRUE; + return true; } } - return MB_FALSE; + return false; } txPattern::Type @@ -134,7 +134,7 @@ nsresult txLocPathPattern::addStep(txPattern* aPattern, bool isChild) return NS_OK; } -MBool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) +bool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { NS_ASSERTION(mSteps.Length() > 1, "Internal error"); @@ -153,17 +153,17 @@ MBool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aCont PRUint32 pos = mSteps.Length(); Step* step = &mSteps[--pos]; if (!step->pattern->matches(aNode, aContext)) - return MB_FALSE; + return false; txXPathTreeWalker walker(aNode); bool hasParent = walker.moveToParent(); while (step->isChild) { if (!pos) - return MB_TRUE; // all steps matched + return true; // all steps matched step = &mSteps[--pos]; if (!hasParent || !step->pattern->matches(walker.getCurrentPosition(), aContext)) - return MB_FALSE; // no more ancestors or no match + return false; // no more ancestors or no match hasParent = walker.moveToParent(); } @@ -174,7 +174,7 @@ MBool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aCont while (pos) { if (!hasParent) - return MB_FALSE; // There are more steps in the current block + return false; // There are more steps in the current block // than ancestors of the tested node step = &mSteps[--pos]; @@ -195,7 +195,7 @@ MBool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aCont } } - return MB_TRUE; + return true; } // txLocPathPattern::matches double txLocPathPattern::getDefaultPriority() @@ -249,7 +249,7 @@ txLocPathPattern::toString(nsAString& aDest) * a txPattern matching the document node, or '/' */ -MBool txRootPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) +bool txRootPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { return txXPathNodeUtils::isRoot(aNode); } @@ -295,7 +295,7 @@ txIdPattern::txIdPattern(const nsSubstring& aString) } } -MBool txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) +bool txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { if (!txXPathNodeUtils::isElement(aNode)) { return false; @@ -351,7 +351,7 @@ txIdPattern::toString(nsAString& aDest) * argument. */ -MBool txKeyPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) +bool txKeyPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { txExecutionState* es = (txExecutionState*)aContext->getPrivateContext(); nsAutoPtr contextDoc(txXPathNodeUtils::getOwnerDocument(aNode)); @@ -404,21 +404,21 @@ txKeyPattern::toString(nsAString& aDest) * a txPattern to hold the NodeTest and the Predicates of a StepPattern */ -MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) +bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { NS_ASSERTION(mNodeTest, "Internal error"); if (!mNodeTest->matches(aNode, aContext)) - return MB_FALSE; + return false; txXPathTreeWalker walker(aNode); if ((!mIsAttr && txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) || !walker.moveToParent()) { - return MB_FALSE; + return false; } if (isEmpty()) { - return MB_TRUE; + return true; } /* @@ -431,7 +431,7 @@ MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext * if the result is a number, check the context position, * otherwise convert to bool * if result is true, copy node to newNodes - * if aNode is not member of newNodes, return MB_FALSE + * if aNode is not member of newNodes, return false * nodes = newNodes * * For the last Predicate, evaluate Predicate with aNode as @@ -442,7 +442,7 @@ MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext // Create the context node set for evaluating the predicates nsRefPtr nodes; nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes)); - NS_ENSURE_SUCCESS(rv, MB_FALSE); + NS_ENSURE_SUCCESS(rv, false); bool hasNext = mIsAttr ? walker.moveToFirstAttribute() : walker.moveToFirstChild(); @@ -457,12 +457,12 @@ MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext Expr* predicate = mPredicates[0]; nsRefPtr newNodes; rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes)); - NS_ENSURE_SUCCESS(rv, MB_FALSE); + NS_ENSURE_SUCCESS(rv, false); PRUint32 i, predLen = mPredicates.Length(); for (i = 1; i < predLen; ++i) { newNodes->clear(); - MBool contextIsInPredicate = MB_FALSE; + bool contextIsInPredicate = false; txNodeSetContext predContext(nodes, aContext); while (predContext.hasNext()) { predContext.next(); @@ -477,7 +477,7 @@ MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext exprResult->numberValue()) { const txXPathNode& tmp = predContext.getContextNode(); if (tmp == aNode) - contextIsInPredicate = MB_TRUE; + contextIsInPredicate = true; newNodes->append(tmp); } break; @@ -485,7 +485,7 @@ MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext if (exprResult->booleanValue()) { const txXPathNode& tmp = predContext.getContextNode(); if (tmp == aNode) - contextIsInPredicate = MB_TRUE; + contextIsInPredicate = true; newNodes->append(tmp); } break; @@ -495,7 +495,7 @@ MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext nodes->clear(); nodes->append(*newNodes); if (!contextIsInPredicate) { - return MB_FALSE; + return false; } predicate = mPredicates[i]; } diff --git a/content/xslt/src/xslt/txXSLTPatterns.h b/content/xslt/src/xslt/txXSLTPatterns.h index 86848d117e15..45b8d5b7b224 100644 --- a/content/xslt/src/xslt/txXSLTPatterns.h +++ b/content/xslt/src/xslt/txXSLTPatterns.h @@ -59,7 +59,7 @@ public: /* * Determines whether this Pattern matches the given node. */ - virtual MBool matches(const txXPathNode& aNode, + virtual bool matches(const txXPathNode& aNode, txIMatchContext* aContext) = 0; /* @@ -119,7 +119,7 @@ public: }; #define TX_DECL_PATTERN_BASE \ - MBool matches(const txXPathNode& aNode, txIMatchContext* aContext); \ + bool matches(const txXPathNode& aNode, txIMatchContext* aContext); \ double getDefaultPriority(); \ virtual Expr* getSubExprAt(PRUint32 aPos); \ virtual void setSubExprAt(PRUint32 aPos, Expr* aExpr); \ diff --git a/content/xslt/src/xslt/txXSLTProcessor.cpp b/content/xslt/src/xslt/txXSLTProcessor.cpp index ebaa157f0f32..1d313de35e28 100644 --- a/content/xslt/src/xslt/txXSLTProcessor.cpp +++ b/content/xslt/src/xslt/txXSLTProcessor.cpp @@ -48,19 +48,19 @@ TX_LG_IMPL /* static */ -MBool +bool txXSLTProcessor::init() { TX_LG_CREATE; if (!txHandlerTable::init()) - return MB_FALSE; + return false; extern bool TX_InitEXSLTFunction(); if (!TX_InitEXSLTFunction()) - return MB_FALSE; + return false; - return MB_TRUE; + return true; } /* static */ diff --git a/content/xslt/src/xslt/txXSLTProcessor.h b/content/xslt/src/xslt/txXSLTProcessor.h index c96f3d7b6816..94c3105c7c3b 100644 --- a/content/xslt/src/xslt/txXSLTProcessor.h +++ b/content/xslt/src/xslt/txXSLTProcessor.h @@ -48,7 +48,7 @@ public: * Initialisation and shutdown routines. Initilizes and cleansup all * dependant classes */ - static MBool init(); + static bool init(); static void shutdown(); From c67bb407596f30c668d71899e0317c368cef160a Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 10 Nov 2011 12:04:24 -0800 Subject: [PATCH 11/38] Enter compartment while initializing in CreateDedicatedWorkerGlobalScope, bug 701458. r=bent --- dom/workers/WorkerScope.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index a2210474250e..a4bd3e61d08d 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -832,6 +832,11 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx) return NULL; } + JSAutoEnterCompartment ac; + if (!ac.enter(aCx, global)) { + return NULL; + } + // Make the private slots now so that all our instance checks succeed. if (!DedicatedWorkerGlobalScope::InitPrivate(aCx, global, worker)) { return NULL; From 599f76d1d4dfe5beb41a49a5433115e79937d578 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 10 Nov 2011 12:34:24 -0800 Subject: [PATCH 12/38] Add type behavior info to script PC counts, bug 691788. r=sfink --- js/src/jsdbgapi.cpp | 34 +++ js/src/jsdbgapi.h | 6 + js/src/jsinterp.cpp | 23 +- js/src/jsopcode.cpp | 146 ++++++++++-- js/src/jsopcode.h | 132 ++++++++++- js/src/jsopcode.tbl | 46 ++-- js/src/jsscript.cpp | 58 +++-- js/src/jsscript.h | 56 ++--- js/src/jstracer.cpp | 11 - js/src/methodjit/BaseAssembler.h | 11 +- js/src/methodjit/Compiler.cpp | 358 ++++++++++++++++++++++++++++-- js/src/methodjit/Compiler.h | 5 + js/src/methodjit/FrameState-inl.h | 36 +++ js/src/methodjit/FrameState.h | 5 +- js/src/shell/js.cpp | 2 +- 15 files changed, 794 insertions(+), 135 deletions(-) diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index c6a552a0bced..88fceefb20eb 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -2139,6 +2139,23 @@ JS_DumpBytecode(JSContext *cx, JSScript *script) #endif } +extern JS_PUBLIC_API(void) +JS_DumpPCCounts(JSContext *cx, JSScript *script) +{ +#if defined(DEBUG) + JS_ASSERT(script->pcCounters); + + LifoAlloc lifoAlloc(1024); + Sprinter sprinter; + INIT_SPRINTER(cx, &sprinter, &lifoAlloc, 0); + + fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno); + js_DumpPCCounts(cx, script, &sprinter); + fputs(sprinter.base, stdout); + fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename, script->lineno); +#endif +} + static void DumpBytecodeScriptCallback(JSContext *cx, void *data, void *thing, JSGCTraceKind traceKind, size_t thingSize) @@ -2155,6 +2172,23 @@ JS_DumpCompartmentBytecode(JSContext *cx) IterateCells(cx, cx->compartment, gc::FINALIZE_SCRIPT, NULL, DumpBytecodeScriptCallback); } +static void +DumpPCCountsScriptCallback(JSContext *cx, void *data, void *thing, + JSGCTraceKind traceKind, size_t thingSize) +{ + JS_ASSERT(traceKind == JSTRACE_SCRIPT); + JS_ASSERT(!data); + JSScript *script = static_cast(thing); + if (script->pcCounters) + JS_DumpPCCounts(cx, script); +} + +JS_PUBLIC_API(void) +JS_DumpCompartmentPCCounts(JSContext *cx) +{ + IterateCells(cx, cx->compartment, gc::FINALIZE_SCRIPT, NULL, DumpPCCountsScriptCallback); +} + JS_PUBLIC_API(JSObject *) JS_UnwrapObject(JSObject *obj) { diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index 24b5e687e5b8..faffc3ea7cd5 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -612,6 +612,12 @@ JS_DumpBytecode(JSContext *cx, JSScript *script); extern JS_PUBLIC_API(void) JS_DumpCompartmentBytecode(JSContext *cx); +extern JS_PUBLIC_API(void) +JS_DumpPCCounts(JSContext *cx, JSScript *script); + +extern JS_PUBLIC_API(void) +JS_DumpCompartmentPCCounts(JSContext *cx); + extern JS_PUBLIC_API(JSObject *) JS_UnwrapObject(JSObject *obj); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index feb876eba4a8..c97d0498ac1c 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1594,15 +1594,10 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) JS_ASSERT(!cx->compartment->activeAnalysis); -#define ENABLE_PCCOUNT_INTERRUPTS() JS_BEGIN_MACRO \ - if (pcCounts) \ - ENABLE_INTERRUPTS(); \ - JS_END_MACRO - #if JS_THREADED_INTERP -#define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(pcCounts, jumpTable == interruptJumpTable) +#define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(script->pcCounters, jumpTable == interruptJumpTable) #else -#define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(pcCounts, switchMask == -1) +#define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(script->pcCounters, switchMask == -1) #endif /* @@ -1781,8 +1776,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) #define RESTORE_INTERP_VARS() \ JS_BEGIN_MACRO \ SET_SCRIPT(regs.fp()->script()); \ - pcCounts = script->pcCounters.get(JSPCCounters::INTERP); \ - ENABLE_PCCOUNT_INTERRUPTS(); \ argv = regs.fp()->maybeFormalArgs(); \ atoms = FrameAtomBase(cx, regs.fp()); \ JS_ASSERT(&cx->regs() == ®s); \ @@ -1820,6 +1813,8 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) script = (s); \ if (script->stepModeEnabled()) \ ENABLE_INTERRUPTS(); \ + if (script->pcCounters) \ + ENABLE_INTERRUPTS(); \ JS_END_MACRO #define CHECK_INTERRUPT_HANDLER() \ @@ -1842,8 +1837,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) JSRuntime *const rt = cx->runtime; JSScript *script; SET_SCRIPT(regs.fp()->script()); - double *pcCounts = script->pcCounters.get(JSPCCounters::INTERP); - ENABLE_PCCOUNT_INTERRUPTS(); Value *argv = regs.fp()->maybeFormalArgs(); CHECK_INTERRUPT_HANDLER(); @@ -1985,9 +1978,11 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) { bool moreInterrupts = false; - if (pcCounts) { - if (!regs.fp()->hasImacropc()) - ++pcCounts[regs.pc - script->code]; + if (script->pcCounters) { + if (!regs.fp()->hasImacropc()) { + OpcodeCounts counts = script->getCounts(regs.pc); + counts.get(OpcodeCounts::BASE_INTERP)++; + } moreInterrupts = true; } diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index ffc01e9bd05c..f746891db226 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -301,8 +301,132 @@ AutoScriptUntrapper::~AutoScriptUntrapper() } } +static const char * countBaseNames[] = { + "interp", + "mjit", + "mjit_calls", + "mjit_code", + "mjit_pics" +}; + +JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) == OpcodeCounts::BASE_COUNT); + +static const char * countAccessNames[] = { + "infer_mono", + "infer_di", + "infer_poly", + "infer_barrier", + "infer_nobarrier", + "observe_undefined", + "observe_null", + "observe_boolean", + "observe_int32", + "observe_double", + "observe_string", + "observe_object" +}; + +JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) + + JS_ARRAY_LENGTH(countAccessNames) == OpcodeCounts::ACCESS_COUNT); + +static const char * countElementNames[] = { + "id_int", + "id_double", + "id_other", + "id_unknown", + "elem_typed", + "elem_packed", + "elem_dense", + "elem_other" +}; + +JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) + + JS_ARRAY_LENGTH(countAccessNames) + + JS_ARRAY_LENGTH(countElementNames) == OpcodeCounts::ELEM_COUNT); + +static const char * countPropertyNames[] = { + "prop_static", + "prop_definite", + "prop_other" +}; + +JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) + + JS_ARRAY_LENGTH(countAccessNames) + + JS_ARRAY_LENGTH(countPropertyNames) == OpcodeCounts::PROP_COUNT); + +static const char * countArithNames[] = { + "arith_int", + "arith_double", + "arith_other", + "arith_unknown", +}; + +JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) + + JS_ARRAY_LENGTH(countArithNames) == OpcodeCounts::ARITH_COUNT); + +/* static */ const char * +OpcodeCounts::countName(JSOp op, size_t which) +{ + JS_ASSERT(which < numCounts(op)); + + if (which < BASE_COUNT) + return countBaseNames[which]; + + if (accessOp(op)) { + if (which < ACCESS_COUNT) + return countAccessNames[which - BASE_COUNT]; + if (elementOp(op)) + return countElementNames[which - ACCESS_COUNT]; + if (propertyOp(op)) + return countPropertyNames[which - ACCESS_COUNT]; + JS_NOT_REACHED("bad op"); + return NULL; + } + + if (arithOp(op)) + return countArithNames[which - BASE_COUNT]; + + JS_NOT_REACHED("bad op"); + return NULL; +} + #ifdef DEBUG +JS_FRIEND_API(void) +js_DumpPCCounts(JSContext *cx, JSScript *script, js::Sprinter *sp) +{ + JS_ASSERT(script->pcCounters); + + jsbytecode *pc = script->code; + while (pc < script->code + script->length) { + JSOp op = js_GetOpcode(cx, script, pc); + + int len = js_CodeSpec[op].length; + jsbytecode *next = (len != -1) ? pc + len : pc + js_GetVariableBytecodeLength(pc); + + if (!js_Disassemble1(cx, script, pc, pc - script->code, true, sp)) + return; + + size_t total = OpcodeCounts::numCounts(op); + double *raw = script->getCounts(pc).rawCounts(); + + Sprint(sp, " {"); + bool printed = false; + for (size_t i = 0; i < total; i++) { + double val = raw[i]; + if (val) { + if (printed) + Sprint(sp, ", "); + Sprint(sp, "\"%s\": %.0f", OpcodeCounts::countName(op, i), val); + printed = true; + } + } + Sprint(sp, "}\n"); + + pc = next; + } +} + /* * If pc != NULL, include a prefix indicating whether the PC is at the current line. * If counts != NULL, include a counter of the number of times each op was executed. @@ -314,17 +438,10 @@ js_DisassembleAtPC(JSContext *cx, JSScript *script, JSBool lines, jsbytecode *pc uintN len; SprintCString(sp, "loc "); - if (script->pcCounters) - Sprint(sp, "counts%*s x ", COUNTS_LEN - strlen("counts"), ""); if (lines) SprintCString(sp, "line"); SprintCString(sp, " op\n"); SprintCString(sp, "----- "); - if (script->pcCounters) { - for (int i = 0; i < COUNTS_LEN; ++i) - SprintCString(sp, "-"); - SprintCString(sp, " "); - } if (lines) SprintCString(sp, "----"); SprintCString(sp, " --\n"); @@ -476,21 +593,6 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, const JSCodeSpec *cs = &js_CodeSpec[op]; ptrdiff_t len = (ptrdiff_t) cs->length; Sprint(sp, "%05u:", loc); - if (JSPCCounters &counts = script->pcCounters) { - ptrdiff_t start = Sprint(sp, "%.0f", counts.get(0, loc)); - for (size_t i = 1; i < JSPCCounters::NUM_COUNTERS; ++i) - Sprint(sp, "/%.0f", counts.get(i, loc)); - int l = Sprint(sp, "") - start; - if (l < COUNTS_LEN) - Sprint(sp, "%*s", COUNTS_LEN - l, ""); - double mjitHits = counts.get(JSPCCounters::METHODJIT, loc); - if (mjitHits) { - Sprint(sp, " %.0f/%.0f", - counts.get(JSPCCounters::METHODJIT_CODE, loc) / mjitHits, - counts.get(JSPCCounters::METHODJIT_PICS, loc) / mjitHits); - } - Sprint(sp, " x "); - } if (lines) Sprint(sp, "%4u", JS_PCToLineNumber(cx, script, pc)); Sprint(sp, " %s", js_CodeName[op]); diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 2f483aa28326..22c551d18c1f 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -139,6 +139,7 @@ typedef enum JSOp { #define JOF_TYPESET (1U<<26) /* has an entry in a script's type sets */ #define JOF_DECOMPOSE (1U<<27) /* followed by an equivalent decomposed * version of the opcode */ +#define JOF_ARITH (1U<<28) /* unary or binary arithmetic opcode */ /* Shorthands for type from format and type from opcode. */ #define JOF_TYPE(fmt) ((fmt) & JOF_TYPEMASK) @@ -582,9 +583,135 @@ class AutoScriptUntrapper ~AutoScriptUntrapper(); }; -} +/* + * Counts accumulated for a single opcode in a script. The counts tracked vary + * between opcodes, and this structure ensures that counts are accessed in + * a coherent fashion. + */ +class OpcodeCounts +{ + friend struct ::JSScript; + double *counts; +#ifdef DEBUG + size_t capacity; #endif + public: + + enum BaseCounts { + BASE_INTERP = 0, + BASE_METHODJIT, + + BASE_METHODJIT_STUBS, + BASE_METHODJIT_CODE, + BASE_METHODJIT_PICS, + + BASE_COUNT + }; + + enum AccessCounts { + ACCESS_MONOMORPHIC = BASE_COUNT, + ACCESS_DIMORPHIC, + ACCESS_POLYMORPHIC, + + ACCESS_BARRIER, + ACCESS_NOBARRIER, + + ACCESS_UNDEFINED, + ACCESS_NULL, + ACCESS_BOOLEAN, + ACCESS_INT32, + ACCESS_DOUBLE, + ACCESS_STRING, + ACCESS_OBJECT, + + ACCESS_COUNT + }; + + static bool accessOp(JSOp op) { + /* + * Access ops include all name, element and property reads, as well as + * SETELEM and SETPROP (for ElementCounts/PropertyCounts alignment). + */ + JS_ASSERT(op != JSOP_TRAP); + if (op == JSOP_SETELEM || op == JSOP_SETPROP || op == JSOP_SETMETHOD) + return true; + int format = js_CodeSpec[op].format; + return !!(format & (JOF_NAME | JOF_GNAME | JOF_ELEM | JOF_PROP)) + && !(format & (JOF_SET | JOF_INCDEC)); + } + + enum ElementCounts { + ELEM_ID_INT = ACCESS_COUNT, + ELEM_ID_DOUBLE, + ELEM_ID_OTHER, + ELEM_ID_UNKNOWN, + + ELEM_OBJECT_TYPED, + ELEM_OBJECT_PACKED, + ELEM_OBJECT_DENSE, + ELEM_OBJECT_OTHER, + + ELEM_COUNT + }; + + static bool elementOp(JSOp op) { + return accessOp(op) && !!(js_CodeSpec[op].format & JOF_ELEM); + } + + enum PropertyCounts { + PROP_STATIC = ACCESS_COUNT, + PROP_DEFINITE, + PROP_OTHER, + + PROP_COUNT + }; + + static bool propertyOp(JSOp op) { + return accessOp(op) && !!(js_CodeSpec[op].format & JOF_PROP); + } + + enum ArithCounts { + ARITH_INT = BASE_COUNT, + ARITH_DOUBLE, + ARITH_OTHER, + ARITH_UNKNOWN, + + ARITH_COUNT + }; + + static bool arithOp(JSOp op) { + JS_ASSERT(op != JSOP_TRAP); + return !!(js_CodeSpec[op].format & (JOF_INCDEC | JOF_ARITH)); + } + + static size_t numCounts(JSOp op) + { + if (accessOp(op)) { + if (elementOp(op)) + return ELEM_COUNT; + if (propertyOp(op)) + return PROP_COUNT; + return ACCESS_COUNT; + } + if (arithOp(op)) + return ARITH_COUNT; + return BASE_COUNT; + } + + static const char *countName(JSOp op, size_t which); + + double *rawCounts() { return counts; } + + double& get(size_t which) { + JS_ASSERT(which < capacity); + return counts[which]; + } +}; + +} /* namespace js */ +#endif /* __cplusplus */ + #if defined(DEBUG) && defined(__cplusplus) /* * Disassemblers, for debugging only. @@ -595,6 +722,9 @@ js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, js::Sprinter *sp); extern JS_FRIEND_API(uintN) js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc, JSBool lines, js::Sprinter *sp); + +extern JS_FRIEND_API(void) +js_DumpPCCounts(JSContext *cx, JSScript *script, js::Sprinter *sp); #endif #endif /* jsopcode_h___ */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 49ee12776109..efd2cb5f598e 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -132,27 +132,27 @@ OPDEF(JSOP_POPN, 11, "popn", NULL, 3, -1, 0, 0, JOF_UINT16 OPDEF(JSOP_DUP, 12, "dup", NULL, 1, 1, 2, 0, JOF_BYTE) OPDEF(JSOP_DUP2, 13, "dup2", NULL, 1, 2, 4, 0, JOF_BYTE) OPDEF(JSOP_SETCONST, 14, "setconst", NULL, 3, 1, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET) -OPDEF(JSOP_BITOR, 15, "bitor", "|", 1, 2, 1, 7, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_BITXOR, 16, "bitxor", "^", 1, 2, 1, 8, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_BITAND, 17, "bitand", "&", 1, 2, 1, 9, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING) -OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING) -OPDEF(JSOP_LT, 20, "lt", "<", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_LE, 21, "le", "<=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_GT, 22, "gt", ">", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_GE, 23, "ge", ">=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_LSH, 24, "lsh", "<<", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_RSH, 25, "rsh", ">>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_URSH, 26, "ursh", ">>>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_ADD, 27, "add", "+", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_SUB, 28, "sub", "-", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_MUL, 29, "mul", "*", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_DIV, 30, "div", "/", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_MOD, 31, "mod", "%", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_NOT, 32, "not", "!", 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING) -OPDEF(JSOP_BITNOT, 33, "bitnot", "~", 1, 1, 1, 15, JOF_BYTE) -OPDEF(JSOP_NEG, 34, "neg", "- ", 1, 1, 1, 15, JOF_BYTE) -OPDEF(JSOP_POS, 35, "pos", "+ ", 1, 1, 1, 15, JOF_BYTE) +OPDEF(JSOP_BITOR, 15, "bitor", "|", 1, 2, 1, 7, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_BITXOR, 16, "bitxor", "^", 1, 2, 1, 8, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_BITAND, 17, "bitand", "&", 1, 2, 1, 9, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH|JOF_DETECTING) +OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH|JOF_DETECTING) +OPDEF(JSOP_LT, 20, "lt", "<", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_LE, 21, "le", "<=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_GT, 22, "gt", ">", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_GE, 23, "ge", ">=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_LSH, 24, "lsh", "<<", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_RSH, 25, "rsh", ">>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_URSH, 26, "ursh", ">>>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_ADD, 27, "add", "+", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_SUB, 28, "sub", "-", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_MUL, 29, "mul", "*", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_DIV, 30, "div", "/", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_MOD, 31, "mod", "%", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_NOT, 32, "not", "!", 1, 1, 1, 15, JOF_BYTE|JOF_ARITH|JOF_DETECTING) +OPDEF(JSOP_BITNOT, 33, "bitnot", "~", 1, 1, 1, 15, JOF_BYTE|JOF_ARITH) +OPDEF(JSOP_NEG, 34, "neg", "- ", 1, 1, 1, 15, JOF_BYTE|JOF_ARITH) +OPDEF(JSOP_POS, 35, "pos", "+ ", 1, 1, 1, 15, JOF_BYTE|JOF_ARITH) OPDEF(JSOP_DELNAME, 36, "delname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEL) OPDEF(JSOP_DELPROP, 37, "delprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEL) OPDEF(JSOP_DELELEM, 38, "delelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEL) @@ -195,8 +195,8 @@ OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLES OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCH|JOF_DETECTING|JOF_PARENHEAD) /* New, infallible/transitive identity ops. */ -OPDEF(JSOP_STRICTEQ, 72, "stricteq", "===", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC) -OPDEF(JSOP_STRICTNE, 73, "strictne", "!==", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC) +OPDEF(JSOP_STRICTEQ, 72, "stricteq", "===", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC|JOF_ARITH) +OPDEF(JSOP_STRICTNE, 73, "strictne", "!==", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC|JOF_ARITH) /* * Host object extension: given 'o.item(i) = j', the left-hand side compiles diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 49e1059e5622..d95b73d2723b 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -722,6 +722,9 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp) script->consts()->vector[i] = tmp; } + if (xdr->mode == JSXDR_DECODE && cx->hasRunOption(JSOPTION_PCCOUNT)) + (void) script->initCounts(cx); + xdr->script = oldscript; return JS_TRUE; @@ -735,22 +738,51 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp) #endif /* JS_HAS_XDR */ bool -JSPCCounters::init(JSContext *cx, size_t numBytecodes) +JSScript::initCounts(JSContext *cx) { - this->numBytecodes = numBytecodes; - size_t nbytes = sizeof(*counts) * numBytecodes * NUM_COUNTERS; - counts = (double*) cx->calloc_(nbytes); - if (!counts) + JS_ASSERT(!pcCounters); + + size_t count = 0; + + jsbytecode *pc, *next; + for (pc = code; pc < code + length; pc = next) { + analyze::UntrapOpcode untrap(cx, this, pc); + count += OpcodeCounts::numCounts(JSOp(*pc)); + next = pc + analyze::GetBytecodeLength(pc); + } + + size_t bytes = (length * sizeof(OpcodeCounts)) + (count * sizeof(double)); + char *cursor = (char *) cx->calloc_(bytes); + if (!cursor) return false; + + DebugOnly base = cursor; + + pcCounters.counts = (OpcodeCounts *) cursor; + cursor += length * sizeof(OpcodeCounts); + + for (pc = code; pc < code + length; pc = next) { + analyze::UntrapOpcode untrap(cx, this, pc); + pcCounters.counts[pc - code].counts = (double *) cursor; + size_t capacity = OpcodeCounts::numCounts(JSOp(*pc)); +#ifdef DEBUG + pcCounters.counts[pc - code].capacity = capacity; +#endif + cursor += capacity * sizeof(double); + next = pc + analyze::GetBytecodeLength(pc); + } + + JS_ASSERT(size_t(cursor - base) == bytes); + return true; } void -JSPCCounters::destroy(JSContext *cx) +JSScript::destroyCounts(JSContext *cx) { - if (counts) { - cx->free_(counts); - counts = NULL; + if (pcCounters) { + cx->free_(pcCounters.counts); + pcCounters.counts = NULL; } } @@ -943,9 +975,6 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom script->version = version; new (&script->bindings) Bindings(cx); - if (cx->hasRunOption(JSOPTION_PCCOUNT)) - (void) script->pcCounters.init(cx, length); - uint8 *cursor = data; if (nobjects != 0) { script->objectsOffset = (uint8)(cursor - data); @@ -1231,6 +1260,9 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce) Debugger::onNewScript(cx, script, compileAndGoGlobal); } + if (cx->hasRunOption(JSOPTION_PCCOUNT)) + (void) script->initCounts(cx); + return script; } @@ -1319,7 +1351,7 @@ JSScript::finalize(JSContext *cx) mjit::ReleaseScriptCode(cx, this); #endif - pcCounters.destroy(cx); + destroyCounts(cx); if (sourceMap) cx->free_(sourceMap); diff --git a/js/src/jsscript.h b/js/src/jsscript.h index df6898df59ac..7f3ebfc5dceb 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -379,51 +379,32 @@ enum JITScriptStatus { namespace js { namespace mjit { struct JITScript; } } #endif -namespace js { namespace analyze { class ScriptAnalysis; } } +namespace js { -class JSPCCounters { - size_t numBytecodes; - double *counts; +namespace analyze { class ScriptAnalysis; } + +class ScriptOpcodeCounts +{ + friend struct ::JSScript; + OpcodeCounts *counts; public: - enum { - INTERP = 0, - TRACEJIT, - METHODJIT, - METHODJIT_STUBS, - METHODJIT_CODE, - METHODJIT_PICS, - NUM_COUNTERS - }; - - JSPCCounters() : numBytecodes(0), counts(NULL) { + ScriptOpcodeCounts() : counts(NULL) { } - ~JSPCCounters() { + ~ScriptOpcodeCounts() { JS_ASSERT(!counts); } - bool init(JSContext *cx, size_t numBytecodes); - void destroy(JSContext *cx); - // Boolean conversion, for 'if (counters) ...' operator void*() const { return counts; } - - double *get(int runmode) { - JS_ASSERT(runmode >= 0 && runmode < NUM_COUNTERS); - return counts ? &counts[numBytecodes * runmode] : NULL; - } - - double& get(int runmode, size_t offset) { - JS_ASSERT(offset < numBytecodes); - JS_ASSERT(counts); - return get(runmode)[offset]; - } }; +} /* namespace js */ + static const uint32 JS_SCRIPT_COOKIE = 0xc00cee; struct JSScript : public js::gc::Cell { @@ -539,10 +520,8 @@ struct JSScript : public js::gc::Cell { * the script with 4 bytes. We use them to store tiny scripts like empty * scripts. */ -#if JS_BITS_PER_WORD == 64 #define JS_SCRIPT_INLINE_DATA_LIMIT 4 uint8 inlineData[JS_SCRIPT_INLINE_DATA_LIMIT]; -#endif const char *filename; /* source filename or null */ JSAtom **atoms; /* maps immediate index to literal struct */ @@ -574,8 +553,8 @@ struct JSScript : public js::gc::Cell { uint32 *closedSlots; /* vector of closed slots; args first, then vars. */ - /* array of execution counters for every JSOp in the script, by runmode */ - JSPCCounters pcCounters; + /* Execution and profiling information for JIT code in the script. */ + js::ScriptOpcodeCounts pcCounters; #ifdef JS_CRASH_DIAGNOSTICS /* All diagnostic fields must be multiples of Cell::CellSize. */ @@ -685,6 +664,15 @@ struct JSScript : public js::gc::Cell { #endif + /* Counter accessors. */ + js::OpcodeCounts getCounts(jsbytecode *pc) { + JS_ASSERT(unsigned(pc - code) < length); + return pcCounters.counts[pc - code]; + } + + bool initCounts(JSContext *cx); + void destroyCounts(JSContext *cx); + jsbytecode *main() { return code + mainOffset; } diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 148690698637..6695a8f0bf18 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -7257,17 +7257,6 @@ TraceRecorder::monitorRecording(JSOp op) AbortableRecordingStatus status; bool wasInImacro = (cx->fp()->hasImacropc()); - if (!wasInImacro && cx->hasRunOption(JSOPTION_PCCOUNT)) { - JSScript *script = cx->fp()->script(); - if (script->pcCounters) { - int offset = cx->regs().pc - script->code; - LIns *pcCounter_addr_ins = w.nameImmpNonGC(&script->pcCounters.get(JSPCCounters::TRACEJIT, offset)); - AnyAddress pcCounter_addr(pcCounter_addr_ins); - LIns *ins = w.ldd(pcCounter_addr); - ins = w.ins2(LIR_addd, ins, w.name(w.immd(1.0), "pctick")); - w.st(ins, pcCounter_addr); - } - } switch (op) { default: diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 919049561ffa..28dee721a50b 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -1328,12 +1328,19 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist storeDouble(Registers::FPConversionTemp, Address(scratch)); } + /* Add one to the accumulator 'counter'. */ + void bumpCounter(double *counter, RegisterID scratch) + { + addCounter(&oneDouble, counter, scratch); + } + /* Bump the stub call count for script/pc if they are being counted. */ void bumpStubCounter(JSScript *script, jsbytecode *pc, RegisterID scratch) { if (script->pcCounters) { - double *counter = &script->pcCounters.get(JSPCCounters::METHODJIT_STUBS, pc - script->code); - addCounter(&oneDouble, counter, scratch); + OpcodeCounts counts = script->getCounts(pc); + double *counter = &counts.get(OpcodeCounts::BASE_METHODJIT_STUBS); + bumpCounter(counter, scratch); } } diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 9b2314bf467b..198c0cbd00ab 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1591,7 +1591,7 @@ mjit::Compiler::generateMethod() Label start = masm.label(); if (!frame.syncForBranch(PC, Uses(0))) return Compile_Error; - if (pcLengths) { + if (pcLengths && lastPC) { /* Track this sync code for the previous op. */ size_t length = masm.size() - masm.distanceOf(start); uint32 offset = ssa.frameLength(a->inlineIndex) + lastPC - script->code; @@ -1649,6 +1649,28 @@ mjit::Compiler::generateMethod() Label codeStart = masm.label(); bool countersUpdated = false; + bool arithUpdated = false; + + JSValueType arithFirstUseType = JSVAL_TYPE_UNKNOWN; + JSValueType arithSecondUseType = JSVAL_TYPE_UNKNOWN; + if (script->pcCounters && !!(js_CodeSpec[op].format & JOF_ARITH)) { + if (GetUseCount(script, PC - script->code) == 1) { + FrameEntry *use = frame.peek(-1); + /* + * Pretend it's a binary operation and the second operand has + * the same type as the first one. + */ + if (use->isTypeKnown()) + arithFirstUseType = arithSecondUseType = use->getKnownType(); + } else { + FrameEntry *use = frame.peek(-1); + if (use->isTypeKnown()) + arithFirstUseType = use->getKnownType(); + use = frame.peek(-2); + if (use->isTypeKnown()) + arithSecondUseType = use->getKnownType(); + } + } /* * Update PC counters for jump opcodes at their start, so that we don't @@ -1829,6 +1851,11 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_EQ) BEGIN_CASE(JSOP_NE) { + if (script->pcCounters) { + updateArithCounters(PC, NULL, arithFirstUseType, arithSecondUseType); + arithUpdated = true; + } + /* Detect fusions. */ jsbytecode *next = &PC[JSOP_GE_LENGTH]; JSOp fused = JSOp(*next); @@ -2059,6 +2086,8 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_GETPROP) BEGIN_CASE(JSOP_GETELEM) + if (script->pcCounters) + updateElemCounters(PC, frame.peek(-2), frame.peek(-1)); if (!jsop_getelem(false)) return Compile_Error; END_CASE(JSOP_GETELEM) @@ -2069,6 +2098,8 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_SETELEM) { + if (script->pcCounters) + updateElemCounters(PC, frame.peek(-3), frame.peek(-2)); jsbytecode *next = &PC[JSOP_SETELEM_LENGTH]; bool pop = (JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next)); if (!jsop_setelem(pop)) @@ -2242,13 +2273,14 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_CASE) BEGIN_CASE(JSOP_STRICTEQ) + BEGIN_CASE(JSOP_STRICTNE) + if (script->pcCounters) { + updateArithCounters(PC, NULL, arithFirstUseType, arithSecondUseType); + arithUpdated = true; + } jsop_stricteq(op); END_CASE(JSOP_STRICTEQ) - BEGIN_CASE(JSOP_STRICTNE) - jsop_stricteq(op); - END_CASE(JSOP_STRICTNE) - BEGIN_CASE(JSOP_ITER) if (!iter(PC[1])) return Compile_Error; @@ -2403,16 +2435,42 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_DECARG) BEGIN_CASE(JSOP_ARGINC) BEGIN_CASE(JSOP_ARGDEC) + if (script->pcCounters) { + restoreVarType(); + FrameEntry *fe = frame.getArg(GET_SLOTNO(PC)); + if (fe->isTypeKnown()) + arithFirstUseType = fe->getKnownType(); + } + if (!jsop_arginc(op, GET_SLOTNO(PC))) return Compile_Retry; + + if (script->pcCounters) { + FrameEntry *fe = frame.getArg(GET_SLOTNO(PC)); + updateArithCounters(PC, fe, arithFirstUseType, JSVAL_TYPE_INT32); + arithUpdated = true; + } END_CASE(JSOP_ARGDEC) BEGIN_CASE(JSOP_INCLOCAL) BEGIN_CASE(JSOP_DECLOCAL) BEGIN_CASE(JSOP_LOCALINC) BEGIN_CASE(JSOP_LOCALDEC) + if (script->pcCounters) { + restoreVarType(); + FrameEntry *fe = frame.getLocal(GET_SLOTNO(PC)); + if (fe->isTypeKnown()) + arithFirstUseType = fe->getKnownType(); + } + if (!jsop_localinc(op, GET_SLOTNO(PC))) return Compile_Retry; + + if (script->pcCounters) { + FrameEntry *fe = frame.getLocal(GET_SLOTNO(PC)); + updateArithCounters(PC, fe, arithFirstUseType, JSVAL_TYPE_INT32); + arithUpdated = true; + } END_CASE(JSOP_LOCALDEC) BEGIN_CASE(JSOP_BINDNAME) @@ -2694,6 +2752,8 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_UINT24) BEGIN_CASE(JSOP_CALLELEM) + if (script->pcCounters) + updateElemCounters(PC, frame.peek(-2), frame.peek(-1)); jsop_getelem(true); END_CASE(JSOP_CALLELEM) @@ -2809,10 +2869,31 @@ mjit::Compiler::generateMethod() } } - if (script->pcCounters || pcLengths) { + if (script->pcCounters) { size_t length = masm.size() - masm.distanceOf(codeStart); - if (countersUpdated || length != 0) { - if (!countersUpdated && script->pcCounters) + bool typesUpdated = false; + + /* Update information about the type of value pushed by arithmetic ops. */ + if ((js_CodeSpec[op].format & JOF_ARITH) && !arithUpdated) { + FrameEntry *pushed = NULL; + if (PC == lastPC + analyze::GetBytecodeLength(lastPC)) + pushed = frame.peek(-1); + updateArithCounters(lastPC, pushed, arithFirstUseType, arithSecondUseType); + typesUpdated = true; + } + + /* Update information about the result type of access operations. */ + if (OpcodeCounts::accessOp(op) && + op != JSOP_SETPROP && op != JSOP_SETMETHOD && op != JSOP_SETELEM) { + FrameEntry *fe = (GetDefCount(script, lastPC - script->code) == 1) + ? frame.peek(-1) + : frame.peek(-2); + updatePCTypes(lastPC, fe); + typesUpdated = true; + } + + if (countersUpdated || typesUpdated || length != 0) { + if (!countersUpdated) updatePCCounters(lastPC, &codeStart, &countersUpdated); if (pcLengths) { @@ -2821,6 +2902,11 @@ mjit::Compiler::generateMethod() pcLengths[offset].codeLength += length; } } + } else if (pcLengths) { + /* Fill in the amount of inline code generated for the op. */ + size_t length = masm.size() - masm.distanceOf(codeStart); + uint32 offset = ssa.frameLength(a->inlineIndex) + lastPC - script->code; + pcLengths[offset].codeLength += length; } frame.assertValidRegisterState(); @@ -2836,6 +2922,8 @@ mjit::Compiler::generateMethod() void mjit::Compiler::updatePCCounters(jsbytecode *pc, Label *start, bool *updated) { + JS_ASSERT(script->pcCounters); + /* * Bump the METHODJIT count for the opcode, read the METHODJIT_CODE_LENGTH * and METHODJIT_PICS_LENGTH counts, indicating the amounts of inline path @@ -2853,17 +2941,18 @@ mjit::Compiler::updatePCCounters(jsbytecode *pc, Label *start, bool *updated) RegisterID reg = Registers::ReturnReg; masm.storePtr(reg, frame.addressOfTop()); - double *code = &script->pcCounters.get(JSPCCounters::METHODJIT_CODE, pc - script->code); + OpcodeCounts counts = script->getCounts(pc); + + double *code = &counts.get(OpcodeCounts::BASE_METHODJIT_CODE); double *codeLength = &pcLengths[offset].codeLength; masm.addCounter(codeLength, code, reg); - double *pics = &script->pcCounters.get(JSPCCounters::METHODJIT_PICS, pc - script->code); + double *pics = &counts.get(OpcodeCounts::BASE_METHODJIT_PICS); double *picsLength = &pcLengths[offset].picsLength; masm.addCounter(picsLength, pics, reg); - static const double oneDouble = 1.0; - double *counter = &script->pcCounters.get(JSPCCounters::METHODJIT, pc - script->code); - masm.addCounter(&oneDouble, counter, reg); + double *counter = &counts.get(OpcodeCounts::BASE_METHODJIT); + masm.bumpCounter(counter, reg); /* Reload the base register's original value. */ masm.loadPtr(frame.addressOfTop(), reg); @@ -2873,6 +2962,209 @@ mjit::Compiler::updatePCCounters(jsbytecode *pc, Label *start, bool *updated) *updated = true; } +static inline bool +HasPayloadType(types::TypeSet *types) +{ + if (types->unknown()) + return false; + + types::TypeFlags flags = types->baseFlags(); + bool objects = !!(flags & types::TYPE_FLAG_ANYOBJECT) || !!types->getObjectCount(); + + if (objects && !!(flags & types::TYPE_FLAG_STRING)) + return false; + + flags = flags & ~(types::TYPE_FLAG_ANYOBJECT | types::TYPE_FLAG_STRING); + + return (flags == types::TYPE_FLAG_UNDEFINED) + || (flags == types::TYPE_FLAG_NULL) + || (flags == types::TYPE_FLAG_BOOLEAN); +} + +void +mjit::Compiler::updatePCTypes(jsbytecode *pc, FrameEntry *fe) +{ + JS_ASSERT(script->pcCounters); + + /* + * Get a temporary register, as for updatePCCounters. Don't overlap with + * the backing store for the entry's type tag, if there is one. + */ + RegisterID reg = Registers::ReturnReg; + if (frame.peekTypeInRegister(fe) && reg == frame.tempRegForType(fe)) { + JS_STATIC_ASSERT(Registers::ReturnReg != Registers::ArgReg1); + reg = Registers::ArgReg1; + } + masm.push(reg); + + OpcodeCounts counts = script->getCounts(pc); + + /* Update the counters for pushed type tags and possible access types. */ + if (fe->isTypeKnown()) { + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_MONOMORPHIC), reg); + OpcodeCounts::AccessCounts counter = OpcodeCounts::ACCESS_OBJECT; + switch (fe->getKnownType()) { + case JSVAL_TYPE_UNDEFINED: counter = OpcodeCounts::ACCESS_UNDEFINED; break; + case JSVAL_TYPE_NULL: counter = OpcodeCounts::ACCESS_NULL; break; + case JSVAL_TYPE_BOOLEAN: counter = OpcodeCounts::ACCESS_BOOLEAN; break; + case JSVAL_TYPE_INT32: counter = OpcodeCounts::ACCESS_INT32; break; + case JSVAL_TYPE_DOUBLE: counter = OpcodeCounts::ACCESS_DOUBLE; break; + case JSVAL_TYPE_STRING: counter = OpcodeCounts::ACCESS_STRING; break; + case JSVAL_TYPE_OBJECT: counter = OpcodeCounts::ACCESS_OBJECT; break; + default:; + } + if (counter) + masm.bumpCounter(&counts.get(counter), reg); + } else { + types::TypeSet *types = frame.extra(fe).types; + if (types && HasPayloadType(types)) + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_DIMORPHIC), reg); + else + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_POLYMORPHIC), reg); + + frame.loadTypeIntoReg(fe, reg); + + Jump j = masm.testUndefined(Assembler::NotEqual, reg); + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_UNDEFINED), reg); + frame.loadTypeIntoReg(fe, reg); + j.linkTo(masm.label(), &masm); + + j = masm.testNull(Assembler::NotEqual, reg); + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_NULL), reg); + frame.loadTypeIntoReg(fe, reg); + j.linkTo(masm.label(), &masm); + + j = masm.testBoolean(Assembler::NotEqual, reg); + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_BOOLEAN), reg); + frame.loadTypeIntoReg(fe, reg); + j.linkTo(masm.label(), &masm); + + j = masm.testInt32(Assembler::NotEqual, reg); + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_INT32), reg); + frame.loadTypeIntoReg(fe, reg); + j.linkTo(masm.label(), &masm); + + j = masm.testDouble(Assembler::NotEqual, reg); + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_DOUBLE), reg); + frame.loadTypeIntoReg(fe, reg); + j.linkTo(masm.label(), &masm); + + j = masm.testString(Assembler::NotEqual, reg); + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_STRING), reg); + frame.loadTypeIntoReg(fe, reg); + j.linkTo(masm.label(), &masm); + + j = masm.testObject(Assembler::NotEqual, reg); + masm.bumpCounter(&counts.get(OpcodeCounts::ACCESS_OBJECT), reg); + frame.loadTypeIntoReg(fe, reg); + j.linkTo(masm.label(), &masm); + } + + /* Update the counter for accesses with type barriers. */ + if (js_CodeSpec[*pc].format & JOF_TYPESET) { + double *counter = &counts.get(hasTypeBarriers(pc) + ? OpcodeCounts::ACCESS_BARRIER + : OpcodeCounts::ACCESS_NOBARRIER); + masm.bumpCounter(counter, reg); + } + + /* Reload the base register's original value. */ + masm.pop(reg); +} + +void +mjit::Compiler::updateArithCounters(jsbytecode *pc, FrameEntry *fe, + JSValueType firstUseType, JSValueType secondUseType) +{ + JS_ASSERT(script->pcCounters); + + RegisterID reg = Registers::ReturnReg; + masm.push(reg); + + /* + * What counter we bump for arithmetic expressions depend on the + * known types of its operands. + * + * ARITH_INT: operands are known ints, result is int + * ARITH_OVERFLOW: operands are known ints, result is double + * ARITH_DOUBLE: either operand is a known double, result is double + * ARITH_OTHER: operands are monomorphic but not int or double + * ARITH_UNKNOWN: operands are polymorphic + */ + + OpcodeCounts::ArithCounts counter; + if (firstUseType == JSVAL_TYPE_INT32 && secondUseType == JSVAL_TYPE_INT32 && + (!fe || fe->isNotType(JSVAL_TYPE_DOUBLE))) { + counter = OpcodeCounts::ARITH_INT; + } else if (firstUseType == JSVAL_TYPE_INT32 || firstUseType == JSVAL_TYPE_DOUBLE || + secondUseType == JSVAL_TYPE_INT32 || secondUseType == JSVAL_TYPE_DOUBLE) { + counter = OpcodeCounts::ARITH_DOUBLE; + } else if (firstUseType != JSVAL_TYPE_UNKNOWN && secondUseType != JSVAL_TYPE_UNKNOWN && + (!fe || fe->isTypeKnown())) { + counter = OpcodeCounts::ARITH_OTHER; + } else { + counter = OpcodeCounts::ARITH_UNKNOWN; + } + + masm.bumpCounter(&script->getCounts(pc).get(counter), reg); + masm.pop(reg); +} + +void +mjit::Compiler::updateElemCounters(jsbytecode *pc, FrameEntry *obj, FrameEntry *id) +{ + JS_ASSERT(script->pcCounters); + + RegisterID reg = Registers::ReturnReg; + masm.push(reg); + + OpcodeCounts counts = script->getCounts(pc); + + OpcodeCounts::ElementCounts counter; + if (id->isTypeKnown()) { + switch (id->getKnownType()) { + case JSVAL_TYPE_INT32: counter = OpcodeCounts::ELEM_ID_INT; break; + case JSVAL_TYPE_DOUBLE: counter = OpcodeCounts::ELEM_ID_DOUBLE; break; + default: counter = OpcodeCounts::ELEM_ID_OTHER; break; + } + } else { + counter = OpcodeCounts::ELEM_ID_UNKNOWN; + } + masm.bumpCounter(&counts.get(counter), reg); + + if (obj->mightBeType(JSVAL_TYPE_OBJECT)) { + types::TypeSet *types = frame.extra(obj).types; + if (types && !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY) && + types->getTypedArrayType(cx) != TypedArray::TYPE_MAX) { + counter = OpcodeCounts::ELEM_OBJECT_TYPED; + } else if (types && !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY)) { + if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY)) + counter = OpcodeCounts::ELEM_OBJECT_PACKED; + else + counter = OpcodeCounts::ELEM_OBJECT_DENSE; + } else { + counter = OpcodeCounts::ELEM_OBJECT_OTHER; + } + masm.bumpCounter(&counts.get(counter), reg); + } else { + masm.bumpCounter(&counts.get(OpcodeCounts::ELEM_OBJECT_OTHER), reg); + } + + masm.pop(reg); +} + +void +mjit::Compiler::bumpPropCounter(jsbytecode *pc, int counter) +{ + /* Don't accumulate counts for property ops fused with other ops. */ + if (!(js_CodeSpec[*pc].format & JOF_PROP)) + return; + RegisterID reg = Registers::ReturnReg; + masm.push(reg); + masm.bumpCounter(&script->getCounts(pc).get(counter), reg); + masm.pop(reg); +} + JSC::MacroAssembler::Label mjit::Compiler::labelOf(jsbytecode *pc, uint32 inlineIndex) { @@ -4186,6 +4478,8 @@ mjit::Compiler::jsop_setprop_slow(JSAtom *atom, bool usePropCache) INLINE_STUBCALL(STRICT_VARIANT(stubs::SetPropNoCache), REJOIN_FALLTHROUGH); JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH); frame.shimmy(1); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_OTHER); } void @@ -4205,6 +4499,9 @@ mjit::Compiler::jsop_getprop_slow(JSAtom *atom, bool usePropCache) frame.pop(); frame.pushSynced(JSVAL_TYPE_UNKNOWN); + + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_OTHER); } bool @@ -4217,6 +4514,8 @@ mjit::Compiler::jsop_callprop_slow(JSAtom *atom) frame.pop(); pushSyncedEntry(0); pushSyncedEntry(1); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_OTHER); return true; } @@ -4291,6 +4590,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, frame.learnType(fe, JSVAL_TYPE_INT32, false); frame.pop(); frame.pushCopyOf(fe); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_STATIC); return true; } } @@ -4315,6 +4616,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, RegisterID reg = frame.tempRegForData(top); frame.pop(); frame.pushWord(Address(reg, offsetof(JSObject, privateData)), JSVAL_TYPE_INT32); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE); if (!isObject) stubcc.rejoin(Changes(1)); return true; @@ -4338,6 +4641,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, frame.pop(); masm.loadPayload(Address(reg, TypedArray::lengthOffset()), reg); frame.pushTypedPayload(JSVAL_TYPE_INT32, reg); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE); if (!isObject) stubcc.rejoin(Changes(1)); return true; @@ -4351,6 +4656,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, if (types->isLazyArguments(cx)) { frame.pop(); frame.pushWord(Address(JSFrameReg, StackFrame::offsetOfArgs()), JSVAL_TYPE_INT32); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE); return true; } } @@ -4364,6 +4671,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, frame.learnType(fe, knownType, false); frame.pop(); frame.pushCopyOf(fe); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_STATIC); return true; } } @@ -4401,6 +4710,9 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, RegisterID reg = frame.tempRegForData(top); frame.pop(); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE); + Address address(reg, JSObject::getFixedSlotOffset(slot)); BarrierState barrier = pushAddressMaybeBarrier(address, knownType, false); if (!isObject) @@ -4411,6 +4723,9 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, } } + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_OTHER); + /* * These two must be loaded first. The objReg because the string path * wants to read it, and the shapeReg because it could cause a spill that @@ -4537,6 +4852,9 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) { FrameEntry *top = frame.peek(-1); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_OTHER); + /* * These two must be loaded first. The objReg because the string path * wants to read it, and the shapeReg because it could cause a spill that @@ -4710,6 +5028,9 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) { FrameEntry *top = frame.peek(-1); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_OTHER); + PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true); JS_ASSERT(top->isTypeKnown()); @@ -5060,6 +5381,9 @@ mjit::Compiler::jsop_callprop_dispatch(JSAtom *atom) frame.shift(-2); // FUN THIS + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE); + stubcc.rejoin(Changes(2)); return true; } @@ -5094,6 +5418,9 @@ mjit::Compiler::jsop_callprop(JSAtom *atom) frame.shift(-2); // FUN THIS + if (script->pcCounters && cx->typeInferenceEnabled()) + bumpPropCounter(PC, OpcodeCounts::PROP_STATIC); + if (testObject) stubcc.rejoin(Changes(2)); @@ -5209,10 +5536,15 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed frame.shimmy(1); if (!isObject) stubcc.rejoin(Changes(1)); + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE); return true; } } + if (script->pcCounters) + bumpPropCounter(PC, OpcodeCounts::PROP_OTHER); + #ifdef JSGC_INCREMENTAL_MJ /* Write barrier. */ if (cx->compartment->needsBarrier() && (!types || types->propertyNeedsBarrier(cx, id))) { diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 486522cafe52..793a586fa21b 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -530,6 +530,11 @@ private: CompileStatus pushActiveFrame(JSScript *script, uint32 argc); void popActiveFrame(); void updatePCCounters(jsbytecode *pc, Label *start, bool *updated); + void updatePCTypes(jsbytecode *pc, FrameEntry *fe); + void updateArithCounters(jsbytecode *pc, FrameEntry *fe, + JSValueType firstUseType, JSValueType secondUseType); + void updateElemCounters(jsbytecode *pc, FrameEntry *obj, FrameEntry *id); + void bumpPropCounter(jsbytecode *pc, int counter); /* Analysis helpers. */ CompileStatus prepareInferenceTypes(JSScript *script, ActiveFrame *a); diff --git a/js/src/methodjit/FrameState-inl.h b/js/src/methodjit/FrameState-inl.h index ed79d78f98b2..a6eb90a61a6a 100644 --- a/js/src/methodjit/FrameState-inl.h +++ b/js/src/methodjit/FrameState-inl.h @@ -542,6 +542,42 @@ FrameState::tempRegForType(FrameEntry *fe) return reg; } +inline void +FrameState::loadTypeIntoReg(const FrameEntry *fe, RegisterID reg) +{ + if (fe->isCopy()) + fe = fe->copyOf(); + + JS_ASSERT(!fe->type.isConstant()); + + if (fe->type.inRegister()) { + if (fe->type.reg() == reg) + return; + masm.move(fe->type.reg(), reg); + return; + } + + masm.loadTypeTag(addressOf(fe), reg); +} + +inline void +FrameState::loadDataIntoReg(const FrameEntry *fe, RegisterID reg) +{ + if (fe->isCopy()) + fe = fe->copyOf(); + + JS_ASSERT(!fe->data.isConstant()); + + if (fe->data.inRegister()) { + if (fe->data.reg() == reg) + return; + masm.move(fe->data.reg(), reg); + return; + } + + masm.loadPayload(addressOf(fe), reg); +} + inline JSC::MacroAssembler::RegisterID FrameState::tempRegForData(FrameEntry *fe) { diff --git a/js/src/methodjit/FrameState.h b/js/src/methodjit/FrameState.h index 2928404b3c35..0ff85222d852 100644 --- a/js/src/methodjit/FrameState.h +++ b/js/src/methodjit/FrameState.h @@ -424,6 +424,9 @@ class FrameState */ inline RegisterID tempRegForType(FrameEntry *fe, RegisterID fallback); + inline void loadTypeIntoReg(const FrameEntry *fe, RegisterID reg); + inline void loadDataIntoReg(const FrameEntry *fe, RegisterID reg); + /* * Returns a register that is guaranteed to contain the frame entry's * data payload. The compiler may not modify the contents of the register. @@ -732,7 +735,7 @@ class FrameState void reset() { PodZero(this); } }; StackEntryExtra& extra(const FrameEntry *fe) { - JS_ASSERT(fe >= a->spBase && fe < a->sp); + JS_ASSERT(fe >= a->args && fe < a->sp); return extraArray[fe - entries]; } StackEntryExtra& extra(uint32 slot) { return extra(entries + slot); } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 6d23eee641f5..632ec29c500e 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -5234,7 +5234,7 @@ Shell(JSContext *cx, OptionParser *op, char **envp) #endif /* JSDEBUGGER */ if (enableDisassemblyDumps) - JS_DumpCompartmentBytecode(cx); + JS_DumpCompartmentPCCounts(cx); return result; } From 62d0c5397091d51deb27ac12f8cc82e5458a26aa Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Thu, 10 Nov 2011 12:42:58 -0800 Subject: [PATCH 13/38] Bug 700915: 64-bit RegExp domaeo_basics diagnostic. (r=billm) --- js/src/methodjit/Compiler.cpp | 28 +++++++++++++++++++--------- js/src/methodjit/Compiler.h | 1 + 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 198c0cbd00ab..86ba7445ab5c 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -6917,27 +6917,36 @@ mjit::Compiler::jsop_newinit() return true; } +bool +mjit::Compiler::jsop_regexp_stub(RegExpObject *reobj) +{ + prepareStubCall(Uses(0)); + masm.move(ImmPtr(reobj), Registers::ArgReg1); + INLINE_STUBCALL(stubs::RegExp, REJOIN_FALLTHROUGH); + frame.pushSynced(JSVAL_TYPE_OBJECT); + return true; +} + bool mjit::Compiler::jsop_regexp() { JSObject *obj = script->getRegExp(fullAtomIndex(PC)); - RegExpStatics *res = globalObj ? globalObj->getRegExpStatics() : NULL; + RegExpObject *reobj = obj->asRegExp(); + return jsop_regexp_stub(reobj); + + // FIXME diagnostic bug 700915. +#if 0 if (!globalObj || - obj->getGlobal() != globalObj || + reobj->getGlobal() != globalObj || !cx->typeInferenceEnabled() || analysis->localsAliasStack() || types::TypeSet::HasObjectFlags(cx, globalObj->getType(cx), types::OBJECT_FLAG_REGEXP_FLAGS_SET)) { - prepareStubCall(Uses(0)); - masm.move(ImmPtr(obj), Registers::ArgReg1); - INLINE_STUBCALL(stubs::RegExp, REJOIN_FALLTHROUGH); - frame.pushSynced(JSVAL_TYPE_OBJECT); - return true; + return jsop_regexp_stub(reobj); } - RegExpObject *reobj = obj->asRegExp(); - + RegExpStatics *res = globalObj ? globalObj->getRegExpStatics() : NULL; DebugOnly origFlags = reobj->getFlags(); DebugOnly staticsFlags = res->getFlags(); JS_ASSERT((origFlags & staticsFlags) == staticsFlags); @@ -7006,6 +7015,7 @@ mjit::Compiler::jsop_regexp() stubcc.rejoin(Changes(1)); return true; +#endif } bool diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 793a586fa21b..00d2f13e1950 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -707,6 +707,7 @@ private: bool jsop_arginc(JSOp op, uint32 slot); bool jsop_localinc(JSOp op, uint32 slot); bool jsop_newinit(); + bool jsop_regexp_stub(RegExpObject *reobj); bool jsop_regexp(); void jsop_initmethod(); void jsop_initprop(); From 1720e42663e5bfd6832c0dc7277c27031a9426f4 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 10 Nov 2011 13:28:55 -0800 Subject: [PATCH 14/38] Bug 684619: Make HeapReverser itself root all nodes referred to by roots. r=bhackett The comments for HeapReverser::roots explain. --- js/src/shell/jsheaptools.cpp | 46 ++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/js/src/shell/jsheaptools.cpp b/js/src/shell/jsheaptools.cpp index 96eda0751eb1..e596171a4c02 100644 --- a/js/src/shell/jsheaptools.cpp +++ b/js/src/shell/jsheaptools.cpp @@ -75,7 +75,16 @@ using namespace js; * at such objects. */ -/* A JSTracer that produces a map of the heap with edges reversed. */ +/* + * A JSTracer that produces a map of the heap with edges reversed. + * + * HeapReversers must be allocated in a stack frame. (They contain an AutoArrayRooter, + * and those must be allocated and destroyed in a stack-like order.) + * + * HeapReversers keep all the roots they find in their traversal alive until + * they are destroyed. So you don't need to worry about nodes going away while + * you're using them. + */ class HeapReverser : public JSTracer { public: struct Edge; @@ -159,7 +168,7 @@ class HeapReverser : public JSTracer { Map map; /* Construct a HeapReverser for |context|'s heap. */ - HeapReverser(JSContext *cx) : map(cx), work(cx), parent(NULL) { + HeapReverser(JSContext *cx) : map(cx), roots(cx), rooter(cx, 0, NULL), work(cx), parent(NULL) { JS_TRACER_INIT(this, cx, traverseEdgeWithThis); } @@ -169,6 +178,22 @@ class HeapReverser : public JSTracer { bool reverseHeap(); private: + /* + * Conservative scanning can, on a whim, decide that a root is no longer a + * root, and cause bits of our graph to disappear. The 'roots' vector holds + * all the roots we find alive, and 'rooter' keeps them alive until we're + * destroyed. + * + * Note that AutoArrayRooters must be constructed and destroyed in a + * stack-like order, so the same rule applies to this HeapReverser. The + * easiest way to satisfy this requirement is to only allocate HeapReversers + * as local variables in functions, or in types that themselves follow that + * rule. This is kind of dumb, but JSAPI doesn't provide any less restricted + * way to register arrays of roots. + */ + Vector roots; + AutoArrayRooter rooter; + /* * Return the name of the most recent edge this JSTracer has traversed. The * result is allocated with malloc; if we run out of memory, raise an error @@ -226,10 +251,27 @@ class HeapReverser : public JSTracer { HeapReverser *reverser = static_cast(tracer); reverser->traversalStatus = reverser->traverseEdge(cell, kind); } + + /* Return a jsval representing a node, if possible; otherwise, return JSVAL_VOID. */ + jsval nodeToValue(void *cell, int kind) { + if (kind == JSTRACE_OBJECT) { + JSObject *object = static_cast(cell); + return OBJECT_TO_JSVAL(object); + } else { + return JSVAL_VOID; + } + } }; bool HeapReverser::traverseEdge(void *cell, JSGCTraceKind kind) { + /* If this is a root, make our own root for it as well. */ + if (!parent) { + if (!roots.append(nodeToValue(cell, kind))) + return false; + rooter.changeArray(roots.begin(), roots.length()); + } + /* Capture this edge before the JSTracer members get overwritten. */ char *edgeDescription = getEdgeDescription(); if (!edgeDescription) From 1c836de8fc227114138adbcd6ff6551c22b3a50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Thu, 10 Nov 2011 13:55:11 -0800 Subject: [PATCH 15/38] Bug 701481 - App Tabs lost with current nightly [r=gavin] --- browser/components/sessionstore/src/nsSessionStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/sessionstore/src/nsSessionStore.js b/browser/components/sessionstore/src/nsSessionStore.js index a1d9578aea37..7deda88583a2 100644 --- a/browser/components/sessionstore/src/nsSessionStore.js +++ b/browser/components/sessionstore/src/nsSessionStore.js @@ -2305,7 +2305,7 @@ SessionStoreService.prototype = { if (aEntry.children) { aEntry.children.forEach(function(entry) { - this._extractHostsForCookies(entry, aHosts, aCheckPrivacy, aIsPinned); + this._extractHostsForCookiesFromEntry(entry, aHosts, aCheckPrivacy, aIsPinned); }, this); } }, From 2ba3daa0c49f85ed986bbf471bfb8b15b7236232 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Thu, 10 Nov 2011 13:38:05 -0800 Subject: [PATCH 16/38] Bug 641027 - Fix warnings-as-errors bustage --- js/src/jscell.h | 10 ++++++---- js/src/jsgcinlines.h | 4 ++-- js/src/jsobjinlines.h | 4 ++-- js/src/jsscopeinlines.h | 2 +- js/src/methodjit/BaseAssembler.h | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/js/src/jscell.h b/js/src/jscell.h index 0af5fa60f50f..2ec7ae8afdbf 100644 --- a/js/src/jscell.h +++ b/js/src/jscell.h @@ -66,6 +66,7 @@ enum AllocKind { FINALIZE_OBJECT16_BACKGROUND, FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND, FINALIZE_FUNCTION, + FINALIZE_FUNCTION_AND_OBJECT_LAST = FINALIZE_FUNCTION, FINALIZE_SCRIPT, FINALIZE_SHAPE, FINALIZE_TYPE_OBJECT, @@ -74,12 +75,13 @@ enum AllocKind { #endif FINALIZE_SHORT_STRING, FINALIZE_STRING, - FINALIZE_EXTERNAL_STRING + FINALIZE_EXTERNAL_STRING, + FINALIZE_LAST = FINALIZE_EXTERNAL_STRING }; -static const unsigned FINALIZE_LIMIT = FINALIZE_EXTERNAL_STRING + 1; -static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT16_BACKGROUND + 1; -static const unsigned FINALIZE_FUNCTION_AND_OBJECT_LIMIT = FINALIZE_FUNCTION + 1; +static const unsigned FINALIZE_LIMIT = FINALIZE_LAST + 1; +static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT_LAST + 1; +static const unsigned FINALIZE_FUNCTION_AND_OBJECT_LIMIT = FINALIZE_FUNCTION_AND_OBJECT_LAST + 1; /* * Live objects are marked black. How many other additional colors are available diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 6a93f59949af..5fe0bb2e3dcc 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -96,7 +96,7 @@ GetGCObjectFixedSlotsKind(size_t numFixedSlots) static inline bool IsBackgroundAllocKind(AllocKind kind) { - JS_ASSERT(kind < FINALIZE_OBJECT_LIMIT); + JS_ASSERT(kind <= FINALIZE_OBJECT_LAST); return kind % 2 == 1; } @@ -361,7 +361,7 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize) inline JSObject * js_NewGCObject(JSContext *cx, js::gc::AllocKind kind) { - JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind < js::gc::FINALIZE_OBJECT_LIMIT); + JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST); JSObject *obj = NewGCThing(cx, kind, js::gc::Arena::thingSize(kind)); if (obj) obj->earlyInit(js::gc::GetGCKindSlots(kind)); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 9caf51c066c3..f19d9e332db8 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -1526,7 +1526,7 @@ static inline bool CanBeFinalizedInBackground(gc::AllocKind kind, Class *clasp) { #ifdef JS_THREADSAFE - JS_ASSERT(kind < gc::FINALIZE_OBJECT_LIMIT); + JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST); /* If the class has no finalizer or a finalizer that is safe to call on * a different thread, we change the finalize kind. For example, * FINALIZE_OBJECT0 calls the finalizer on the main thread, @@ -1554,7 +1554,7 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, { JS_ASSERT(proto); JS_ASSERT(parent); - JS_ASSERT(kind < gc::FINALIZE_OBJECT_LIMIT); + JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST); types::TypeObject *type = proto->getNewType(cx); if (!type) diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 5ad2afb8e847..9dc089f56851 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -80,7 +80,7 @@ js::types::TypeObject::getEmptyShape(JSContext *cx, js::Class *aclasp, */ JS_ASSERT(this == proto->newType); - JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind < js::gc::FINALIZE_OBJECT_LIMIT); + JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST); int i = kind - js::gc::FINALIZE_OBJECT0; if (!emptyShapes) { diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 28dee721a50b..cb278ef5d7e8 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -1245,7 +1245,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist { gc::AllocKind allocKind = templateObject->getAllocKind(); - JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind < gc::FINALIZE_OBJECT_LIMIT); + JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST); int thingSize = (int)gc::Arena::thingSize(allocKind); JS_ASSERT(cx->typeInferenceEnabled()); From 51231a5a14e0060a7ee7d7d4492600cd2274bffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 10 Nov 2011 17:19:12 -0500 Subject: [PATCH 17/38] Bug 698570 - Use weak references in nsFormHistory.js. r=mak. --- toolkit/components/satchel/nsFormHistory.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/toolkit/components/satchel/nsFormHistory.js b/toolkit/components/satchel/nsFormHistory.js index 95d3468efade..540393a3146d 100644 --- a/toolkit/components/satchel/nsFormHistory.js +++ b/toolkit/components/satchel/nsFormHistory.js @@ -55,6 +55,7 @@ FormHistory.prototype = { QueryInterface : XPCOMUtils.generateQI([Ci.nsIFormHistory2, Ci.nsIObserver, Ci.nsIFrameMessageListener, + Ci.nsISupportsWeakReference, ]), debug : true, @@ -124,9 +125,7 @@ FormHistory.prototype = { init : function() { - let self = this; - - Services.prefs.addObserver("browser.formfill.", this, false); + Services.prefs.addObserver("browser.formfill.", this, true); this.updatePrefs(); @@ -138,8 +137,8 @@ FormHistory.prototype = { this.messageManager.addMessageListener("FormHistory:FormSubmitEntries", this); // Add observers - Services.obs.addObserver(this, "idle-daily", false); - Services.obs.addObserver(this, "formhistory-expire-now", false); + Services.obs.addObserver(this, "idle-daily", true); + Services.obs.addObserver(this, "formhistory-expire-now", true); }, /* ---- message listener ---- */ From 0540d30eaa32f34eda5a8ea9a4e5d791fe59e44b Mon Sep 17 00:00:00 2001 From: Geoff Lankow Date: Thu, 10 Nov 2011 12:08:48 +1300 Subject: [PATCH 18/38] Bug 701193 - xpcshell-tests for add-on manager broken when update channel is set to aurora/beta/release; r=dtownsend --- toolkit/mozapps/extensions/AddonRepository.jsm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/toolkit/mozapps/extensions/AddonRepository.jsm b/toolkit/mozapps/extensions/AddonRepository.jsm index 9a417482ce0d..f5d6eee4f98e 100644 --- a/toolkit/mozapps/extensions/AddonRepository.jsm +++ b/toolkit/mozapps/extensions/AddonRepository.jsm @@ -47,6 +47,7 @@ Components.utils.import("resource://gre/modules/FileUtils.jsm"); Components.utils.import("resource://gre/modules/NetUtil.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/AddonManager.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); var EXPORTED_SYMBOLS = [ "AddonRepository" ]; @@ -64,13 +65,14 @@ const PREF_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility"; const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi; +XPCOMUtils.defineLazyGetter(this, "PREF_CHECK_COMPATIBILITY", function () { #ifdef MOZ_COMPATIBILITY_NIGHTLY -const PREF_CHECK_COMPATIBILITY = PREF_CHECK_COMPATIBILITY_BASE + - ".nightly"; + return PREF_CHECK_COMPATIBILITY_BASE + ".nightly"; #else -const PREF_CHECK_COMPATIBILITY = PREF_CHECK_COMPATIBILITY_BASE + "." + - Services.appinfo.version.replace(BRANCH_REGEXP, "$1"); + return PREF_CHECK_COMPATIBILITY_BASE + "." + + Services.appinfo.version.replace(BRANCH_REGEXP, "$1"); #endif +}); const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml"; From 335f0043ea3d1619e96c432a1888dc0983640119 Mon Sep 17 00:00:00 2001 From: Geoff Lankow Date: Thu, 10 Nov 2011 20:59:13 +1300 Subject: [PATCH 19/38] Bug 701298 - Fix browser_searching.js when update channel is aurora/beta/release; r=dtownsend --- .../test/browser/browser_searching.js | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/browser_searching.js b/toolkit/mozapps/extensions/test/browser/browser_searching.js index 4588543f227b..2019a207c3db 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_searching.js +++ b/toolkit/mozapps/extensions/test/browser/browser_searching.js @@ -19,6 +19,22 @@ var gProvider; var gServer; var gAddonInstalled = false; +var channel = "default"; +try { + channel = Services.prefs.getCharPref("app.update.channel"); +} +catch (e) { } +if (channel != "aurora" && + channel != "beta" && + channel != "release") { + var version = "nightly"; +} +else { + version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1"); +} + +const COMPATIBILITY_PREF = "extensions.checkCompatibility." + version; + function test() { requestLongerTimeout(2); // Turn on searching for this test @@ -591,7 +607,7 @@ add_test(function() { // Tests that incompatible add-ons are shown with a warning if compatibility checking is disabled add_test(function() { - Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false); + Services.prefs.setBoolPref(COMPATIBILITY_PREF, false); search("incompatible", false, function() { var item = get_addon_item("remote5"); is_element_visible(item, "Incompatible addon should be visible"); @@ -600,7 +616,7 @@ add_test(function() { var item = get_addon_item("remote6"); is(item, null, "Addon incompatible with the product should not be visible"); - Services.prefs.clearUserPref("extensions.checkCompatibility.nightly"); + Services.prefs.clearUserPref(COMPATIBILITY_PREF); run_next_test(); }); }); From 5dd6a678456cae54e0d556c37a39176f84ff234b Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Thu, 10 Nov 2011 16:17:46 -0800 Subject: [PATCH 20/38] Bug 694206 - Add Gonk (B2G) widget backend, r=cjones --- Makefile.in | 2 +- build/Makefile.in | 2 +- configure.in | 121 ++++- docshell/build/nsDocShellModule.cpp | 20 +- dom/ipc/ContentChild.cpp | 4 +- dom/ipc/ContentParent.cpp | 8 +- dom/plugins/base/PluginPRLibrary.cpp | 12 +- dom/plugins/base/PluginPRLibrary.h | 2 +- dom/plugins/base/npfunctions.h | 4 +- dom/plugins/base/nsNPAPIPlugin.cpp | 9 +- dom/plugins/base/nsNPAPIPluginInstance.cpp | 18 +- dom/plugins/base/nsNPAPIPluginInstance.h | 8 +- dom/plugins/base/nsPluginInstanceOwner.cpp | 18 +- dom/plugins/ipc/PluginLibrary.h | 2 +- dom/plugins/ipc/PluginModuleParent.cpp | 2 +- dom/plugins/ipc/PluginModuleParent.h | 2 +- dom/src/geolocation/nsGeolocation.cpp | 4 +- embedding/Makefile.in | 2 +- gfx/cairo/cairo/src/Makefile.in | 2 +- gfx/src/Makefile.in | 4 + gfx/src/nsDeviceContext.cpp | 6 +- gfx/thebes/GLContextProviderEGL.cpp | 28 +- gfx/thebes/Makefile.in | 31 ++ image/decoders/Makefile.in | 2 +- ipc/chromium/src/base/message_loop.cc | 2 +- ipc/glue/GeckoChildProcessHost.cpp | 14 +- js/src/configure.in | 56 +++ js/src/jscntxt.cpp | 2 +- layout/build/nsLayoutModule.cpp | 14 +- layout/generic/nsObjectFrame.cpp | 2 +- media/libsydneyaudio/src/Makefile.in | 6 +- media/libsydneyaudio/src/sydney_audio_gonk.c | 315 ++++++++++++ memory/mozalloc/Makefile.in | 7 +- memory/mozutils/Makefile.in | 5 +- mobile/components/build/nsShellService.cpp | 4 +- netwerk/build/nsNetModule.cpp | 8 +- netwerk/protocol/device/Makefile.in | 2 +- netwerk/protocol/device/nsDeviceChannel.cpp | 6 +- security/manager/Makefile.in | 8 +- security/manager/android_stub.h | 2 + .../downloads/nsDownloadManager.cpp | 8 +- toolkit/library/libxul-config.mk | 10 +- toolkit/library/nsStaticXULComponents.cpp | 2 + toolkit/mozapps/installer/packager.mk | 2 +- toolkit/xre/Makefile.in | 2 +- toolkit/xre/nsAppRunner.cpp | 6 +- toolkit/xre/nsXREDirProvider.cpp | 3 + uriloader/exthandler/Makefile.in | 4 + .../exthandler/gonk/nsOSHelperAppService.cpp | 63 +++ .../exthandler/gonk/nsOSHelperAppService.h | 60 +++ .../exthandler/nsExternalHelperAppService.cpp | 4 +- widget/public/Makefile.in | 2 +- widget/src/Makefile.in | 2 +- widget/src/gonk/Makefile.in | 75 +++ widget/src/gonk/nsAppShell.cpp | 473 ++++++++++++++++++ widget/src/gonk/nsAppShell.h | 94 ++++ widget/src/gonk/nsLookAndFeel.cpp | 319 ++++++++++++ widget/src/gonk/nsLookAndFeel.h | 54 ++ widget/src/gonk/nsScreenManagerGonk.cpp | 133 +++++ widget/src/gonk/nsScreenManagerGonk.h | 71 +++ widget/src/gonk/nsWidgetFactory.cpp | 98 ++++ widget/src/gonk/nsWindow.cpp | 359 +++++++++++++ widget/src/gonk/nsWindow.h | 128 +++++ widget/src/xpwidgets/Makefile.in | 2 +- xpcom/base/nsSystemInfo.cpp | 4 +- xpcom/components/ManifestParser.cpp | 4 +- xpcom/io/nsLocalFileUnix.cpp | 4 +- 67 files changed, 2628 insertions(+), 124 deletions(-) create mode 100644 media/libsydneyaudio/src/sydney_audio_gonk.c create mode 100644 uriloader/exthandler/gonk/nsOSHelperAppService.cpp create mode 100644 uriloader/exthandler/gonk/nsOSHelperAppService.h create mode 100644 widget/src/gonk/Makefile.in create mode 100644 widget/src/gonk/nsAppShell.cpp create mode 100644 widget/src/gonk/nsAppShell.h create mode 100644 widget/src/gonk/nsLookAndFeel.cpp create mode 100644 widget/src/gonk/nsLookAndFeel.h create mode 100644 widget/src/gonk/nsScreenManagerGonk.cpp create mode 100644 widget/src/gonk/nsScreenManagerGonk.h create mode 100644 widget/src/gonk/nsWidgetFactory.cpp create mode 100644 widget/src/gonk/nsWindow.cpp create mode 100644 widget/src/gonk/nsWindow.h diff --git a/Makefile.in b/Makefile.in index 5f823293f577..3b9f3234818b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -65,7 +65,7 @@ tier_base_dirs = \ $(NULL) ifndef LIBXUL_SDK -ifeq ($(OS_TARGET),Android) +ifeq (android,$(MOZ_WIDGET_TOOLKIT)) tier_base_dirs += other-licenses/android endif diff --git a/build/Makefile.in b/build/Makefile.in index 0c056e70e418..6642ba80e405 100644 --- a/build/Makefile.in +++ b/build/Makefile.in @@ -56,7 +56,7 @@ endif DIRS += pgo ifdef ENABLE_TESTS -ifeq (Android,$(OS_TARGET)) +ifeq (android,$(MOZ_WIDGET_TOOLKIT)) DIRS += mobile/sutagent/android \ mobile/sutagent/android/watcher \ mobile/sutagent/android/ffxcp \ diff --git a/configure.in b/configure.in index e516ea49b248..89333d37dd75 100644 --- a/configure.in +++ b/configure.in @@ -289,6 +289,56 @@ arm-android-eabi) ;; esac +MOZ_ARG_WITH_STRING(gonk, +[ --with-gonk=DIR + location of gonk dir], + gonkdir=$withval) + +if test -n "$gonkdir" ; then + kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"` + gonk_toolchain="$gonkdir"/prebuilt/$kernel_name-x86/toolchain/arm-eabi-4.4.3 + + dnl set up compilers + AS="$gonk_toolchain"/bin/"$android_tool_prefix"-as + CC="$gonk_toolchain"/bin/"$android_tool_prefix"-gcc + CXX="$gonk_toolchain"/bin/"$android_tool_prefix"-g++ + CPP="$gonk_toolchain"/bin/"$android_tool_prefix"-cpp + LD="$gonk_toolchain"/bin/"$android_tool_prefix"-ld + AR="$gonk_toolchain"/bin/"$android_tool_prefix"-ar + RANLIB="$gonk_toolchain"/bin/"$android_tool_prefix"-ranlib + STRIP="$gonk_toolchain"/bin/"$android_tool_prefix"-strip + + STLPORT_CPPFLAGS="-I$gonkdir/ndk/sources/cxx-stl/stlport/stlport/" + STLPORT_LIBS="-lstlport" + + CPPFLAGS="-DANDROID -I$gonkdir/bionic/libc/include/ -I$gonkdir/bionic/libc/kernel/common -I$gonkdir/bionic/libc/arch-arm/include -I$gonkdir/bionic/libc/kernel/arch-arm -I$gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/system/core/include -I$gonkdir/bionic -I$gonkdir/frameworks/base/include $STLPORT_CPPFLAGS $CPPFLAGS" + CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS" + CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS" + LIBS="$LIBS $STLPORT_LIBS" + + dnl Add -llog by default, since we use it all over the place. + LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ -llog $LDFLAGS" + + dnl prevent cross compile section from using these flags as host flags + if test -z "$HOST_CPPFLAGS" ; then + HOST_CPPFLAGS=" " + fi + if test -z "$HOST_CFLAGS" ; then + HOST_CFLAGS=" " + fi + if test -z "$HOST_CXXFLAGS" ; then + HOST_CXXFLAGS=" " + fi + if test -z "$HOST_LDFLAGS" ; then + HOST_LDFLAGS=" " + fi + + AC_DEFINE(ANDROID) + CROSS_COMPILE=1 + MOZ_CHROME_FILE_FORMAT=omni + ZLIB_DIR=yes + direct_nspr_config=1 +else case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then @@ -419,6 +469,8 @@ case "$target" in ;; esac +fi + AC_SUBST(ANDROID_NDK) AC_SUBST(ANDROID_TOOLCHAIN) AC_SUBST(ANDROID_PLATFORM) @@ -2386,7 +2438,11 @@ ia64*-hpux*) *-android*|*-linuxandroid*) AC_DEFINE(NO_PW_GECOS) no_x=yes - _PLATFORM_DEFAULT_TOOLKIT=cairo-android + if test -n "$gonkdir"; then + _PLATFORM_DEFAULT_TOOLKIT=cairo-gonk + else + _PLATFORM_DEFAULT_TOOLKIT=cairo-android + fi TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"' MOZ_GFX_OPTIMIZE_MOBILE=1 @@ -4772,7 +4828,8 @@ MOZ_ARG_HEADER(Toolkit Options) -o "$_DEFAULT_TOOLKIT" = "cairo-os2" \ -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa" \ -o "$_DEFAULT_TOOLKIT" = "cairo-uikit" \ - -o "$_DEFAULT_TOOLKIT" = "cairo-android" + -o "$_DEFAULT_TOOLKIT" = "cairo-android" \ + -o "$_DEFAULT_TOOLKIT" = "cairo-gonk" then dnl nglayout only supports building with one toolkit, dnl so ignore everything after the first comma (","). @@ -4895,6 +4952,15 @@ cairo-android) MOZ_INSTRUMENT_EVENT_LOOP=1 ;; +cairo-gonk) + AC_DEFINE(MOZ_WIDGET_GONK) + MOZ_WIDGET_TOOLKIT=gonk + TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)' + TK_LIBS='$(MOZ_CAIRO_LIBS)' + MOZ_WEBGL=1 + MOZ_PDF_PRINTING=1 + ;; + esac AC_SUBST(MOZ_PDF_PRINTING) @@ -7175,7 +7241,9 @@ dnl We need to wrap dlopen and related functions on Android because we use dnl our own linker. if test "$OS_TARGET" = Android; then WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozutils" - WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr" + if test "$MOZ_WIDGET_TOOLKIT" = android; then + WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr" + fi fi dnl ======================================================== @@ -8856,20 +8924,22 @@ if test "$MOZ_TREE_FREETYPE"; then AC_OUTPUT_SUBDIRS(modules/freetype2) fi -dnl ======================================================== -dnl = Setup a nice relatively clean build environment for -dnl = sub-configures. -dnl ======================================================== -CC="$_SUBDIR_CC" -CXX="$_SUBDIR_CXX" -CFLAGS="$_SUBDIR_CFLAGS" -CPPFLAGS="$_SUBDIR_CPPFLAGS" -CXXFLAGS="$_SUBDIR_CXXFLAGS" -LDFLAGS="$_SUBDIR_LDFLAGS" -HOST_CC="$_SUBDIR_HOST_CC" -HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS" -HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS" -RC= +if test -z "$direct_nspr_config"; then + dnl ======================================================== + dnl = Setup a nice relatively clean build environment for + dnl = sub-configures. + dnl ======================================================== + CC="$_SUBDIR_CC" + CXX="$_SUBDIR_CXX" + CFLAGS="$_SUBDIR_CFLAGS" + CPPFLAGS="$_SUBDIR_CPPFLAGS" + CXXFLAGS="$_SUBDIR_CXXFLAGS" + LDFLAGS="$_SUBDIR_LDFLAGS" + HOST_CC="$_SUBDIR_HOST_CC" + HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS" + HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS" + RC= +fi unset MAKEFILES unset CONFIG_FILES @@ -8918,6 +8988,23 @@ if test -z "$MOZ_NATIVE_NSPR"; then rm -f config/autoconf.mk.bak fi +if test -n "$direct_nspr_config"; then + dnl ======================================================== + dnl = Setup a nice relatively clean build environment for + dnl = sub-configures. + dnl ======================================================== + CC="$_SUBDIR_CC" + CXX="$_SUBDIR_CXX" + CFLAGS="$_SUBDIR_CFLAGS" + CPPFLAGS="$_SUBDIR_CPPFLAGS" + CXXFLAGS="$_SUBDIR_CXXFLAGS" + LDFLAGS="$_SUBDIR_LDFLAGS" + HOST_CC="$_SUBDIR_HOST_CC" + HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS" + HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS" + RC= +fi + # Run the SpiderMonkey 'configure' script. dist=$MOZ_BUILD_ROOT/dist ac_configure_args="$_SUBDIR_CONFIG_ARGS" diff --git a/docshell/build/nsDocShellModule.cpp b/docshell/build/nsDocShellModule.cpp index 89030e8c4507..d5f2c1719737 100644 --- a/docshell/build/nsDocShellModule.cpp +++ b/docshell/build/nsDocShellModule.cpp @@ -57,10 +57,10 @@ #ifdef MOZ_ENABLE_DBUS #include "nsDBusHandlerApp.h" #endif -#if defined(ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) #include "nsExternalSharingAppService.h" #endif -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) #include "nsExternalURLHandlerService.h" #endif @@ -118,10 +118,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(PlatformLocalHandlerApp_t) #ifdef MOZ_ENABLE_DBUS NS_GENERIC_FACTORY_CONSTRUCTOR(nsDBusHandlerApp) #endif -#if defined(ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) NS_GENERIC_FACTORY_CONSTRUCTOR(nsExternalSharingAppService) #endif -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) NS_GENERIC_FACTORY_CONSTRUCTOR(nsExternalURLHandlerService) #endif @@ -148,10 +148,10 @@ NS_DEFINE_NAMED_CID(NS_LOCALHANDLERAPP_CID); #ifdef MOZ_ENABLE_DBUS NS_DEFINE_NAMED_CID(NS_DBUSHANDLERAPP_CID); #endif -#if defined(ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) NS_DEFINE_NAMED_CID(NS_EXTERNALSHARINGAPPSERVICE_CID); #endif -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) NS_DEFINE_NAMED_CID(NS_EXTERNALURLHANDLERSERVICE_CID); #endif NS_DEFINE_NAMED_CID(NS_SHENTRY_CID); @@ -178,10 +178,10 @@ const mozilla::Module::CIDEntry kDocShellCIDs[] = { #ifdef MOZ_ENABLE_DBUS { &kNS_DBUSHANDLERAPP_CID, false, NULL, nsDBusHandlerAppConstructor }, #endif -#if defined(ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) { &kNS_EXTERNALSHARINGAPPSERVICE_CID, false, NULL, nsExternalSharingAppServiceConstructor }, #endif -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) { &kNS_EXTERNALURLHANDLERSERVICE_CID, false, NULL, nsExternalURLHandlerServiceConstructor }, #endif { &kNS_SHENTRY_CID, false, NULL, nsSHEntryConstructor }, @@ -227,10 +227,10 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = { #ifdef MOZ_ENABLE_DBUS { NS_DBUSHANDLERAPP_CONTRACTID, &kNS_DBUSHANDLERAPP_CID }, #endif -#if defined(ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ENABLE_MEEGOTOUCHSHARE) { NS_EXTERNALSHARINGAPPSERVICE_CONTRACTID, &kNS_EXTERNALSHARINGAPPSERVICE_CID }, #endif -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) { NS_EXTERNALURLHANDLERSERVICE_CONTRACTID, &kNS_EXTERNALURLHANDLERSERVICE_CID }, #endif { NS_SHENTRY_CONTRACTID, &kNS_SHENTRY_CID }, diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index c7d339fecd4e..e3634a36a144 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -98,7 +98,7 @@ #include "nsDeviceMotion.h" -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) #include "APKOpen.h" #endif @@ -272,7 +272,7 @@ ContentChild::Init(MessageLoop* aIOLoop, #ifdef MOZ_CRASHREPORTER SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(), XRE_GetProcessType()); -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) PCrashReporterChild* crashreporter = ManagedPCrashReporterChild()[0]; InfallibleTArray mappings; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index e99ab420964c..f6dcaf9e6981 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -106,6 +106,8 @@ #ifdef ANDROID #include "gfxAndroidPlatform.h" +#endif +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #endif @@ -636,7 +638,7 @@ ContentParent::RecvClipboardHasText(bool* hasText) bool ContentParent::RecvGetSystemColors(const PRUint32& colorsCount, InfallibleTArray* colors) { -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID NS_ASSERTION(AndroidBridge::Bridge() != nsnull, "AndroidBridge is not available"); if (AndroidBridge::Bridge() == nsnull) { // Do not fail - the colors won't be right, but it's not critical @@ -655,7 +657,7 @@ ContentParent::RecvGetSystemColors(const PRUint32& colorsCount, InfallibleTArray bool ContentParent::RecvGetIconForExtension(const nsCString& aFileExt, const PRUint32& aIconSize, InfallibleTArray* bits) { -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID NS_ASSERTION(AndroidBridge::Bridge() != nsnull, "AndroidBridge is not available"); if (AndroidBridge::Bridge() == nsnull) { // Do not fail - just no icon will be shown @@ -674,7 +676,7 @@ ContentParent::RecvGetShowPasswordSetting(bool* showPassword) { // default behavior is to show the last password character *showPassword = true; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID NS_ASSERTION(AndroidBridge::Bridge() != nsnull, "AndroidBridge is not available"); if (AndroidBridge::Bridge() != nsnull) *showPassword = AndroidBridge::Bridge()->GetShowPasswordSetting(); diff --git a/dom/plugins/base/PluginPRLibrary.cpp b/dom/plugins/base/PluginPRLibrary.cpp index 7686147af671..6ff84c96ff57 100644 --- a/dom/plugins/base/PluginPRLibrary.cpp +++ b/dom/plugins/base/PluginPRLibrary.cpp @@ -51,7 +51,7 @@ static int gNotOptimized; #define CALLING_CONVENTION_HACK #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #include "android_npapi.h" #include @@ -59,7 +59,7 @@ static int gNotOptimized; #endif namespace mozilla { -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID nsresult PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) @@ -82,10 +82,16 @@ PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, mNPP_GetSitesWithData = pFuncs->getsiteswithdata; return NS_OK; } +#elif defined(MOZ_WIDGET_GONK) +nsresult +PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) +{ + return NS_OK; +} #elif defined(XP_UNIX) && !defined(XP_MACOSX) nsresult PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, - NPPluginFuncs* pFuncs, NPError* error) + NPPluginFuncs* pFuncs, NPError* error) { if (mNP_Initialize) { *error = mNP_Initialize(bFuncs, pFuncs); diff --git a/dom/plugins/base/PluginPRLibrary.h b/dom/plugins/base/PluginPRLibrary.h index e1626238bb17..38546f184b33 100644 --- a/dom/plugins/base/PluginPRLibrary.h +++ b/dom/plugins/base/PluginPRLibrary.h @@ -114,7 +114,7 @@ public: return true; } -#if defined(XP_UNIX) && !defined(XP_MACOSX) +#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK) virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error); #else diff --git a/dom/plugins/base/npfunctions.h b/dom/plugins/base/npfunctions.h index fe32ce557ee2..37c8213e585d 100644 --- a/dom/plugins/base/npfunctions.h +++ b/dom/plugins/base/npfunctions.h @@ -48,7 +48,7 @@ #include "npapi.h" #include "npruntime.h" -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include #endif @@ -311,7 +311,7 @@ NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs); typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*); NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs); #else -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*, JNIEnv* pEnv); NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, JNIEnv* pEnv); #else diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp index 2520d60db4b1..c6e93b35e600 100644 --- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -131,7 +131,7 @@ using mozilla::plugins::PluginModuleParent; #include #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "ANPBase.h" #include "AndroidBridge.h" #include @@ -488,7 +488,7 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult) return NS_ERROR_FAILURE; } -#if defined(XP_MACOSX) || defined(ANDROID) +#if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) if (!pluginLib->HasRequiredFunctions()) { NS_WARNING("Not all necessary functions exposed by plugin, it will not load."); return NS_ERROR_FAILURE; @@ -526,6 +526,7 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult) if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) { return NS_ERROR_FAILURE; } +#elif defined(MOZ_WIDGET_GONK) #else rv = pluginLib->NP_Initialize(&sBrowserFuncs, &plugin->mPluginFuncs, &pluginCallError); if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) { @@ -2298,7 +2299,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result) } #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID case kLogInterfaceV0_ANPGetValue: { LOG("get log interface"); ANPLogInterfaceV0 *i = (ANPLogInterfaceV0 *) result; @@ -2515,7 +2516,7 @@ _setvalue(NPP npp, NPPVariable variable, void *result) } } #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID case kRequestDrawingModel_ANPSetValue: if (inst) inst->SetDrawingModel(NS_PTR_TO_INT32(result)); diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index 3e990d6f78a5..21ceaf24adad 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -61,7 +61,7 @@ #include "nsNetCID.h" #include "nsIContent.h" -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "ANPBase.h" #include #include "android_npapi.h" @@ -72,7 +72,7 @@ using namespace mozilla; using namespace mozilla::plugins::parent; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include static std::map sSurfaceMap; #endif @@ -91,7 +91,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) mDrawingModel(NPDrawingModelQuickDraw), #endif #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID mSurface(nsnull), mTargetSurface(nsnull), mDrawingModel(0), @@ -127,7 +127,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) mUsePluginLayersPref = useLayersPref; } -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID mTargetSurfaceLock = new Mutex("nsNPAPIPluginInstance::SurfaceLock"); #endif @@ -143,7 +143,7 @@ nsNPAPIPluginInstance::~nsNPAPIPluginInstance() mMIMEType = nsnull; } -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID if (mSurface) { sSurfaceMap.erase(mSurface); } @@ -364,7 +364,7 @@ nsNPAPIPluginInstance::InitializePlugin() const char* const* pvalues = nsnull; if (NS_SUCCEEDED(GetParameters(pcount, pnames, pvalues))) { // Android expects an empty string as the separator instead of null -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID NS_ASSERTION(PL_strcmp(values[count], "") == 0, "attribute/parameter array not setup correctly for Android NPAPI plugins"); #else NS_ASSERTION(!values[count], "attribute/parameter array not setup correctly for NPAPI plugins"); @@ -747,7 +747,7 @@ void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel) } #endif -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) void nsNPAPIPluginInstance::SetDrawingModel(PRUint32 aModel) { mDrawingModel = aModel; @@ -859,7 +859,7 @@ nsNPAPIPluginInstance::FindByJavaSurface(void* aJavaSurface) nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel) { -#if defined(XP_MACOSX) || defined(ANDROID) +#if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) *aModel = (PRInt32)mDrawingModel; return NS_OK; #else @@ -958,7 +958,7 @@ nsNPAPIPluginInstance::DefineJavaProperties() nsresult nsNPAPIPluginInstance::IsWindowless(bool* isWindowless) { -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID // On android, pre-honeycomb, all plugins are treated as windowless. *isWindowless = true; #else diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index e2fd1e217431..aae96a81a7a3 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -93,7 +93,7 @@ public: nsresult NewStreamToPlugin(nsIPluginStreamListener** listener); nsresult NewStreamFromPlugin(const char* type, const char* target, nsIOutputStream* *result); nsresult Print(NPPrint* platformPrint); -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID nsresult PostEvent(void* event) { return 0; }; #endif nsresult HandleEvent(void* event, PRInt16* result); @@ -152,7 +152,7 @@ public: void SetEventModel(NPEventModel aModel); #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID void SetDrawingModel(PRUint32 aModel); void* GetJavaSurface(); @@ -230,7 +230,7 @@ protected: NPDrawingModel mDrawingModel; #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID PRUint32 mDrawingModel; #endif @@ -277,7 +277,7 @@ private: nsCOMPtr mURI; bool mUsePluginLayersPref; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID void InvalidateTargetRect(); void* mSurface; diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index caf2b8f7357f..0ddfeae78018 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -118,7 +118,7 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); #include "gfxXlibNativeRenderer.h" #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "ANPBase.h" #include "android_npapi.h" #include "AndroidBridge.h" @@ -1280,7 +1280,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays() // Add PARAM and null separator. mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM")); -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID // Flash expects an empty string on android mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("")); #else @@ -1672,7 +1672,7 @@ void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY) #endif } -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID void nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect) { void* javaSurface = mInstance->GetJavaSurface(); @@ -1714,7 +1714,7 @@ void nsPluginInstanceOwner::RemovePluginView() nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent) { -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID { ANPEvent event; event.inSize = sizeof(ANPEvent); @@ -2527,7 +2527,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent) rv = nsEventStatus_eConsumeNoDefault; #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID // this code supports windowless plugins { // The plugin needs focus to receive keyboard and touch events @@ -2733,7 +2733,7 @@ nsPluginInstanceOwner::PrepareToStop(bool aDelayedStop) } #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID RemovePluginView(); #endif @@ -2833,7 +2833,7 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS) } #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID void nsPluginInstanceOwner::Paint(gfxContext* aContext, const gfxRect& aFrameRect, @@ -3556,7 +3556,7 @@ void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow) if (mPluginWindowVisible && mPluginDocumentActiveState) { mPluginWindow->clipRect.right = mPluginWindow->width; mPluginWindow->clipRect.bottom = mPluginWindow->height; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID if (mInstance) { ANPEvent event; event.inSize = sizeof(ANPEvent); @@ -3568,7 +3568,7 @@ void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow) } else { mPluginWindow->clipRect.right = 0; mPluginWindow->clipRect.bottom = 0; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID if (mInstance) { ANPEvent event; event.inSize = sizeof(ANPEvent); diff --git a/dom/plugins/ipc/PluginLibrary.h b/dom/plugins/ipc/PluginLibrary.h index 9094437e23df..923afa027626 100644 --- a/dom/plugins/ipc/PluginLibrary.h +++ b/dom/plugins/ipc/PluginLibrary.h @@ -78,7 +78,7 @@ public: virtual bool HasRequiredFunctions() = 0; -#if defined(XP_UNIX) && !defined(XP_MACOSX) +#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK) virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) = 0; #else virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) = 0; diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index b84e53f1b042..5d4b1edf92a9 100644 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -735,7 +735,7 @@ PluginModuleParent::EndUpdateBackground(NPP instance, return i->EndUpdateBackground(aCtx, aRect); } -#if defined(XP_UNIX) && !defined(XP_MACOSX) +#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK) nsresult PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) { diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h index 66bb84e515ea..7910e6ab9434 100644 --- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -276,7 +276,7 @@ private: gfxContext* aCtx, const nsIntRect& aRect); -#if defined(XP_UNIX) && !defined(XP_MACOSX) +#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK) virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error); #else virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error); diff --git a/dom/src/geolocation/nsGeolocation.cpp b/dom/src/geolocation/nsGeolocation.cpp index a11f87c24d78..3071c27d816f 100644 --- a/dom/src/geolocation/nsGeolocation.cpp +++ b/dom/src/geolocation/nsGeolocation.cpp @@ -84,7 +84,7 @@ #include "QTMLocationProvider.h" #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidLocationProvider.h" #endif @@ -595,7 +595,7 @@ nsresult nsGeolocationService::Init() mProviders.AppendObject(provider); #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID provider = new AndroidLocationProvider(); if (provider) mProviders.AppendObject(provider); diff --git a/embedding/Makefile.in b/embedding/Makefile.in index 7e289dfb829c..d1329b2a1069 100644 --- a/embedding/Makefile.in +++ b/embedding/Makefile.in @@ -53,7 +53,7 @@ XPCSHELL_TESTS = tests/unit DIRS += test endif -ifeq ($(OS_TARGET),Android) +ifeq ($(MOZ_WIDGET_TOOLKIT),android) DIRS += android endif diff --git a/gfx/cairo/cairo/src/Makefile.in b/gfx/cairo/cairo/src/Makefile.in index d910ac606035..9973e3c0d73e 100644 --- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -205,7 +205,7 @@ CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) $(PS_CSRCS) EXPORTS_cairo += $(PDF_EXPORTS) $(PS_EXPORTS) endif -ifeq ($(MOZ_WIDGET_TOOLKIT),android) +ifneq (,$(filter android gonk,$(MOZ_WIDGET_TOOLKIT))) CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) EXPORTS_cairo += $(PDF_EXPORTS) endif diff --git a/gfx/src/Makefile.in b/gfx/src/Makefile.in index 988cca885343..d4d4add5c470 100644 --- a/gfx/src/Makefile.in +++ b/gfx/src/Makefile.in @@ -109,6 +109,10 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),android) CPPSRCS += nsSystemFontsAndroid.cpp endif +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +CPPSRCS += nsSystemFontsAndroid.cpp +endif + ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) CMMSRCS = nsSystemFontsMac.mm endif diff --git a/gfx/src/nsDeviceContext.cpp b/gfx/src/nsDeviceContext.cpp index b6122b16b283..f80def5c3117 100644 --- a/gfx/src/nsDeviceContext.cpp +++ b/gfx/src/nsDeviceContext.cpp @@ -76,7 +76,11 @@ static nsSystemFontsMac *gSystemFonts = nsnull; #include "nsSystemFontsQt.h" #include "gfxPDFSurface.h" static nsSystemFontsQt *gSystemFonts = nsnull; -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) +#include "nsSystemFontsAndroid.h" +#include "gfxPDFSurface.h" +static nsSystemFontsAndroid *gSystemFonts = nsnull; +#elif defined(MOZ_WIDGET_GONK) #include "nsSystemFontsAndroid.h" #include "gfxPDFSurface.h" static nsSystemFontsAndroid *gSystemFonts = nsnull; diff --git a/gfx/thebes/GLContextProviderEGL.cpp b/gfx/thebes/GLContextProviderEGL.cpp index b9c27b9365fa..3a5d4c148f4f 100644 --- a/gfx/thebes/GLContextProviderEGL.cpp +++ b/gfx/thebes/GLContextProviderEGL.cpp @@ -52,6 +52,8 @@ #define GLdouble_defined 1 // we're using default display for now #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)static_cast(aWidget->GetNativeData(NS_NATIVE_SHELLWIDGET))->winId() +#elif defined(MOZ_WIDGET_GONK) +#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW)) #endif #if defined(MOZ_X11) @@ -63,7 +65,10 @@ #if defined(ANDROID) /* from widget */ +#if defined(MOZ_WIDGET_ANDROID) #include "AndroidBridge.h" +#endif +#include #define EGL_LIB "/system/lib/libEGL.so" #define GLES2_LIB "/system/lib/libGLESv2.so" #else @@ -156,6 +161,10 @@ static bool gUseBackingSurface = true; static bool gUseBackingSurface = false; #endif +#ifdef MOZ_WIDGET_GONK +extern nsIntRect gScreenBounds; +#endif + namespace mozilla { namespace gl { @@ -300,6 +309,10 @@ public: pfnCreateImageKHR fCreateImageKHR; typedef EGLBoolean (GLAPIENTRY * pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image); pfnDestroyImageKHR fDestroyImageKHR; +#ifdef MOZ_WIDGET_GONK + typedef EGLBoolean (GLAPIENTRY * pfnSetSwapRectangleANDROID)(EGLDisplay dpy, EGLSurface surface, EGLint left, EGLint top, EGLint width, EGLint height); + pfnSetSwapRectangleANDROID fSetSwapRectangleANDROID; +#endif // New extension which allow us to lock texture and get raw image pointer typedef EGLBoolean (GLAPIENTRY * pfnLockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); @@ -396,6 +409,9 @@ public: SYMBOL(BindTexImage), SYMBOL(ReleaseTexImage), SYMBOL(QuerySurface), +#ifdef MOZ_WIDGET_GONK + SYMBOL(SetSwapRectangleANDROID), +#endif { NULL, { NULL } } }; @@ -596,7 +612,7 @@ public: fGetConfigs(mEGLDisplay, ec, nc, &nc); for (int i = 0; i < nc; ++i) { - printf_stderr ("========= EGL Config %d ========\n"); + printf_stderr ("========= EGL Config %d ========\n", i); DumpEGLConfig(ec[i]); } @@ -869,6 +885,7 @@ public: bool SwapBuffers() { if (mSurface && !mPlatformContext) { + //sEGLLibrary.fSetSwapRectangleANDROID(EGL_DISPLAY(), mSurface, 0, 0, gScreenBounds.width, gScreenBounds.height); return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), mSurface); } else { return false; @@ -1874,7 +1891,7 @@ CreateSurfaceForWindow(nsIWidget *aWidget, EGLConfig config) sEGLLibrary.DumpEGLConfig(config); #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID // On Android, we have to ask Java to make the eglCreateWindowSurface // call for us. See GLHelpers.java for a description of why. // @@ -1889,6 +1906,13 @@ CreateSurfaceForWindow(nsIWidget *aWidget, EGLConfig config) surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, GET_NATIVE_WINDOW(aWidget), 0); #endif +#ifdef MOZ_WIDGET_GONK + gScreenBounds.x = 0; + gScreenBounds.y = 0; + sEGLLibrary.fQuerySurface(EGL_DISPLAY(), surface, LOCAL_EGL_WIDTH, &gScreenBounds.width); + sEGLLibrary.fQuerySurface(EGL_DISPLAY(), surface, LOCAL_EGL_HEIGHT, &gScreenBounds.height); +#endif + return surface; } diff --git a/gfx/thebes/Makefile.in b/gfx/thebes/Makefile.in index 774b30baaa46..ed7ddd2aff41 100644 --- a/gfx/thebes/Makefile.in +++ b/gfx/thebes/Makefile.in @@ -64,6 +64,14 @@ EXPORTS += \ $(NULL) endif +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +EXPORTS += \ + gfxAndroidPlatform.h \ + gfxFT2Fonts.h \ + gfxFT2FontBase.h \ + $(NULL) +endif + ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) EXPORTS += \ gfxPlatformMac.h \ @@ -242,6 +250,21 @@ CPPSRCS += \ $(NULL) endif +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +EXPORTS += \ + gfxPDFSurface.h \ + $(NULL) +CPPSRCS += \ + gfxAndroidPlatform.cpp \ + gfxFT2Fonts.cpp \ + gfxFT2FontBase.cpp \ + gfxFT2Utils.cpp \ + gfxFT2FontList.cpp \ + gfxPDFSurface.cpp \ + nsUnicodeRange.cpp \ + $(NULL) +endif + ifeq ($(MOZ_WIDGET_TOOLKIT),os2) CPPSRCS += gfxOS2Fonts.cpp \ gfxOS2Platform.cpp \ @@ -354,6 +377,10 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),android) GL_PROVIDER = EGL endif +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +GL_PROVIDER = EGL +endif + # Mac is a special snowflake ifeq ($(GL_PROVIDER),CGL) CMMSRCS += GLContextProvider$(GL_PROVIDER).mm @@ -380,6 +407,10 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),android) CXXFLAGS += $(CAIRO_FT_CFLAGS) endif +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +CXXFLAGS += $(CAIRO_FT_CFLAGS) +endif + ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) CXXFLAGS += $(MOZ_PANGO_CFLAGS) endif diff --git a/image/decoders/Makefile.in b/image/decoders/Makefile.in index 00a10d3da860..683fd8776a9e 100644 --- a/image/decoders/Makefile.in +++ b/image/decoders/Makefile.in @@ -82,7 +82,7 @@ endif ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) DIRS = icon/mac icon endif -ifeq ($(OS_TARGET),Android) +ifeq (android,$(MOZ_WIDGET_TOOLKIT)) DIRS = icon/android icon endif diff --git a/ipc/chromium/src/base/message_loop.cc b/ipc/chromium/src/base/message_loop.cc index 7f2b444a220e..38edbd594a36 100644 --- a/ipc/chromium/src/base/message_loop.cc +++ b/ipc/chromium/src/base/message_loop.cc @@ -27,7 +27,7 @@ #include "base/message_pump_qt.h" #endif #endif -#ifdef MOZ_WIDGET_ANDROID +#ifdef ANDROID #include "base/message_pump_android.h" #endif diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index e7038d9182d4..13575a51489c 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -70,14 +70,14 @@ #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1" #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "APKOpen.h" #endif using mozilla::MonitorAutoLock; using mozilla::ipc::GeckoChildProcessHost; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID // Like its predecessor in nsExceptionHandler.cpp, this is // the magic number of a file descriptor remapping we must // preserve for the child process. @@ -446,9 +446,9 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt nsCString path; greDir->GetNativePath(path); # ifdef OS_LINUX -# ifdef ANDROID +# ifdef MOZ_WIDGET_ANDROID path += "/lib"; -# endif // ANDROID +# endif // MOZ_WIDGET_ANDROID const char *ld_library_path = PR_GetEnv("LD_LIBRARY_PATH"); nsCString new_ld_lib_path; if (ld_library_path && *ld_library_path) { @@ -489,7 +489,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt FilePath exePath; GetPathToBinary(exePath); -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID // The java wrapper unpacks this for us but can't make it executable chmod(exePath.value().c_str(), 0700); int cacheCount = 0; @@ -521,7 +521,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt snprintf(buf, sizeof(buf), "%d%s", kMagicAndroidSystemPropFd, szptr); newEnvVars["ANDROID_PROPERTY_WORKSPACE"] = buf; } -#endif // ANDROID +#endif // MOZ_WIDGET_ANDROID // remap the IPC socket fd to a well-known int, as the OS does for // STDOUT_FILENO, for example @@ -589,7 +589,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt childArgv.push_back(childProcessType); -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID childArgv.push_back(cacheStr.get()); #endif diff --git a/js/src/configure.in b/js/src/configure.in index 621334aa63c9..0dc3fc6f105d 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -281,6 +281,60 @@ i?86-*android*) ;; esac +MOZ_ARG_WITH_STRING(gonk, +[ --with-gonk=DIR + location of gonk dir], + gonkdir=$withval) + +if test -n "$gonkdir" ; then + kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"` + gonk_toolchain="$gonkdir"/prebuilt/$kernel_name-x86/toolchain/arm-eabi-4.4.3 + + dnl set up compilers + AS="$gonk_toolchain"/bin/"$android_tool_prefix"-as + CC="$gonk_toolchain"/bin/"$android_tool_prefix"-gcc + CXX="$gonk_toolchain"/bin/"$android_tool_prefix"-g++ + CPP="$gonk_toolchain"/bin/"$android_tool_prefix"-cpp + LD="$gonk_toolchain"/bin/"$android_tool_prefix"-ld + AR="$gonk_toolchain"/bin/"$android_tool_prefix"-ar + RANLIB="$gonk_toolchain"/bin/"$android_tool_prefix"-ranlib + STRIP="$gonk_toolchain"/bin/"$android_tool_prefix"-strip + + STLPORT_CPPFLAGS="-I$gonkdir/external/stlport/stlport" + STLPORT_LIBS="-lstlport" + + CPPFLAGS="-DANDROID -I$gonkdir/bionic/libc/include/ -I$gonkdir/bionic/libc/kernel/common -I$gonkdir/bionic/libc/arch-arm/include -I$gonkdir/bionic/libc/kernel/arch-arm -I$gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/system/core/include -I$gonkdir/bionic $STLPORT_CPPFLAGS $CPPFLAGS" + CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS" + CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS" + LIBS="$LIBS $STLPORT_LIBS" + + dnl Add -llog by default, since we use it all over the place. + LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ -llog $LDFLAGS" + + dnl prevent cross compile section from using these flags as host flags + if test -z "$HOST_CPPFLAGS" ; then + HOST_CPPFLAGS=" " + fi + if test -z "$HOST_CFLAGS" ; then + HOST_CFLAGS=" " + fi + if test -z "$HOST_CXXFLAGS" ; then + HOST_CXXFLAGS=" " + fi + if test -z "$HOST_LDFLAGS" ; then + HOST_LDFLAGS=" " + fi + + # save these for libffi's subconfigure, + # which doesn't know how to figure this stuff out on its own + ANDROID_CFLAGS="$CFLAGS" + ANDROID_CPPFLAGS="$CPPFLAGS" + ANDROID_LDFLAGS="$LDFLAGS" + + AC_DEFINE(ANDROID) + AC_DEFINE(GONK) + CROSS_COMPILE=1 +else case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then @@ -403,6 +457,8 @@ case "$target" in ;; esac +fi + AC_SUBST(ANDROID_NDK) AC_SUBST(ANDROID_TOOLCHAIN) AC_SUBST(ANDROID_PLATFORM) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 5cef498fcaa9..7be10ff42f4a 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1601,7 +1601,7 @@ JSContext::purge() static bool ComputeIsJITBroken() { -#ifndef ANDROID +#if !defined(ANDROID) || defined(GONK) return false; #else // ANDROID if (getenv("JS_IGNORE_JIT_BROKENNESS")) { diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index c671d728f978..335710728b15 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -147,7 +147,7 @@ using mozilla::dom::indexedDB::IndexedDatabaseManager; #include "nsNullPrincipal.h" #include "nsNetCID.h" #include "nsINodeInfo.h" -#if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_PLATFORM_MAEMO) #include "nsHapticFeedback.h" #endif @@ -276,12 +276,14 @@ static void Shutdown(); #endif #include "nsGeolocation.h" +#ifndef MOZ_WIDGET_GONK #if defined(XP_UNIX) || \ defined(_WINDOWS) || \ defined(machintosh) || \ defined(android) #include "nsDeviceMotionSystem.h" #endif +#endif #include "nsCSPService.h" // Transformiix @@ -309,16 +311,18 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDOMStorageManager, NS_GENERIC_FACTORY_CONSTRUCTOR(nsChannelPolicy) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(IndexedDatabaseManager, IndexedDatabaseManager::FactoryCreate) +#ifndef MOZ_WIDGET_GONK #if defined(XP_UNIX) || \ defined(_WINDOWS) || \ defined(machintosh) || \ defined(android) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceMotionSystem) #endif -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ThirdPartyUtil, Init) #if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHapticFeedback) #endif +#endif +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ThirdPartyUtil, Init) //----------------------------------------------------------------------------- @@ -836,6 +840,7 @@ NS_DEFINE_NAMED_CID(NS_SECURITYNAMESET_CID); NS_DEFINE_NAMED_CID(THIRDPARTYUTIL_CID); NS_DEFINE_NAMED_CID(NS_STRUCTUREDCLONECONTAINER_CID); +#ifndef MOZ_WIDGET_GONK #if defined(XP_UNIX) || \ defined(_WINDOWS) || \ defined(machintosh) || \ @@ -845,6 +850,7 @@ NS_DEFINE_NAMED_CID(NS_DEVICE_MOTION_CID); #if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) NS_DEFINE_NAMED_CID(NS_HAPTICFEEDBACK_CID); #endif +#endif static const mozilla::Module::CIDEntry kLayoutCIDs[] = { XPCONNECT_CIDENTRIES @@ -965,6 +971,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_SYSTEMPRINCIPAL_CID, false, NULL, nsSystemPrincipalConstructor }, { &kNS_NULLPRINCIPAL_CID, false, NULL, nsNullPrincipalConstructor }, { &kNS_SECURITYNAMESET_CID, false, NULL, nsSecurityNameSetConstructor }, +#ifndef MOZ_WIDGET_GONK #if defined(XP_UNIX) || \ defined(_WINDOWS) || \ defined(machintosh) || \ @@ -973,6 +980,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { #endif #if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) { &kNS_HAPTICFEEDBACK_CID, false, NULL, nsHapticFeedbackConstructor }, +#endif #endif { &kTHIRDPARTYUTIL_CID, false, NULL, ThirdPartyUtilConstructor }, { &kNS_STRUCTUREDCLONECONTAINER_CID, false, NULL, nsStructuredCloneContainerConstructor }, @@ -1092,6 +1100,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { NS_SYSTEMPRINCIPAL_CONTRACTID, &kNS_SYSTEMPRINCIPAL_CID }, { NS_NULLPRINCIPAL_CONTRACTID, &kNS_NULLPRINCIPAL_CID }, { NS_SECURITYNAMESET_CONTRACTID, &kNS_SECURITYNAMESET_CID }, +#ifndef MOZ_WIDGET_GONK #if defined(XP_UNIX) || \ defined(_WINDOWS) || \ defined(machintosh) || \ @@ -1100,6 +1109,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { #endif #if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) { "@mozilla.org/widget/hapticfeedback;1", &kNS_HAPTICFEEDBACK_CID }, +#endif #endif { THIRDPARTYUTIL_CONTRACTID, &kTHIRDPARTYUTIL_CID }, { NS_STRUCTUREDCLONECONTAINER_CONTRACTID, &kNS_STRUCTUREDCLONECONTAINER_CID }, diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index d449d4f8d724..45afede876cd 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1705,7 +1705,7 @@ nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, const nsRect& aPluginRect) { -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) if (mInstanceOwner) { NPWindow *window; mInstanceOwner->GetWindow(window); diff --git a/media/libsydneyaudio/src/Makefile.in b/media/libsydneyaudio/src/Makefile.in index 9bc528a18318..692bbea285e3 100644 --- a/media/libsydneyaudio/src/Makefile.in +++ b/media/libsydneyaudio/src/Makefile.in @@ -51,7 +51,11 @@ CSRCS = \ $(NULL) endif -ifeq ($(OS_TARGET),Android) +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +CSRCS = \ + sydney_audio_gonk.c \ + $(NULL) +else ifeq ($(MOZ_WIDGET_TOOLKIT),android) CSRCS = \ sydney_audio_android.c \ $(NULL) diff --git a/media/libsydneyaudio/src/sydney_audio_gonk.c b/media/libsydneyaudio/src/sydney_audio_gonk.c new file mode 100644 index 000000000000..3f3c6e7b27dd --- /dev/null +++ b/media/libsydneyaudio/src/sydney_audio_gonk.c @@ -0,0 +1,315 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * CSIRO + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Michael Martin + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** * + */ + +#include +#include +#include "sydney_audio.h" + +#include "android/log.h" + +#ifndef ALOG +#if defined(DEBUG) || defined(FORCE_ALOG) +#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko - SYDNEY_AUDIO" , ## args) +#else +#define ALOG(args...) +#endif +#endif + +/* Gonk implementation based on sydney_audio_mac.c */ +/* XXX This is temporary until we figure out a way to hook ALSA up */ + +#define NANOSECONDS_IN_MILLISECOND 1000000 +#define MILLISECONDS_PER_SECOND 1000 + +struct sa_stream { + unsigned int rate; + unsigned int channels; + unsigned int isPaused; + + int64_t lastStartTime; + int64_t timePlaying; + int64_t amountWritten; + unsigned int bufferSize; +}; + +/* + * ----------------------------------------------------------------------------- + * Startup and shutdown functions + * ----------------------------------------------------------------------------- + */ + +int +sa_stream_create_pcm( + sa_stream_t ** _s, + const char * client_name, + sa_mode_t mode, + sa_pcm_format_t format, + unsigned int rate, + unsigned int channels +) { + + /* + * Make sure we return a NULL stream pointer on failure. + */ + if (_s == NULL) { + return SA_ERROR_INVALID; + } + *_s = NULL; + + if (mode != SA_MODE_WRONLY) { + return SA_ERROR_NOT_SUPPORTED; + } + if (format != SA_PCM_FORMAT_S16_NE) { + return SA_ERROR_NOT_SUPPORTED; + } + if (channels != 1 && channels != 2) { + return SA_ERROR_NOT_SUPPORTED; + } + + /* + * Allocate the instance and required resources. + */ + sa_stream_t *s; + if ((s = malloc(sizeof(sa_stream_t))) == NULL) { + return SA_ERROR_OOM; + } + + s->rate = rate; + s->channels = channels; + s->isPaused = 0; + + s->lastStartTime = 0; + s->timePlaying = 0; + s->amountWritten = 0; + + s->bufferSize = rate * channels; + + *_s = s; + return SA_SUCCESS; +} + + +int +sa_stream_open(sa_stream_t *s) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + + return SA_ERROR_NO_DEVICE; +} + + +int +sa_stream_destroy(sa_stream_t *s) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } +// XXX + return SA_SUCCESS; +} + + +/* + * ----------------------------------------------------------------------------- + * Data read and write functions + * ----------------------------------------------------------------------------- + */ + +int +sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + if (nbytes == 0) { + return SA_SUCCESS; + } +// XXX + return SA_SUCCESS; +} + + +/* + * ----------------------------------------------------------------------------- + * General query and support functions + * ----------------------------------------------------------------------------- + */ + +int +sa_stream_get_write_size(sa_stream_t *s, size_t *size) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + +// XXX + return SA_SUCCESS; +} + + +int +sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + +// XXX + return SA_SUCCESS; +} + + +int +sa_stream_pause(sa_stream_t *s) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + +// XXX + return SA_SUCCESS; +} + + +int +sa_stream_resume(sa_stream_t *s) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + +// XXX + return SA_SUCCESS; +} + + +int +sa_stream_drain(sa_stream_t *s) +{ + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + +// XXX + return SA_SUCCESS; +} + + +/* + * ----------------------------------------------------------------------------- + * Extension functions + * ----------------------------------------------------------------------------- + */ + +int +sa_stream_set_volume_abs(sa_stream_t *s, float vol) { + + if (s == NULL) { + return SA_ERROR_NO_INIT; + } + +// XXX + return SA_SUCCESS; +} + +/* + * ----------------------------------------------------------------------------- + * Unsupported functions + * ----------------------------------------------------------------------------- + */ +#define UNSUPPORTED(func) func { return SA_ERROR_NOT_SUPPORTED; } + +UNSUPPORTED(int sa_stream_create_opaque(sa_stream_t **s, const char *client_name, sa_mode_t mode, const char *codec)) +UNSUPPORTED(int sa_stream_set_write_lower_watermark(sa_stream_t *s, size_t size)) +UNSUPPORTED(int sa_stream_set_read_lower_watermark(sa_stream_t *s, size_t size)) +UNSUPPORTED(int sa_stream_set_write_upper_watermark(sa_stream_t *s, size_t size)) +UNSUPPORTED(int sa_stream_set_read_upper_watermark(sa_stream_t *s, size_t size)) +UNSUPPORTED(int sa_stream_set_channel_map(sa_stream_t *s, const sa_channel_t map[], unsigned int n)) +UNSUPPORTED(int sa_stream_set_xrun_mode(sa_stream_t *s, sa_xrun_mode_t mode)) +UNSUPPORTED(int sa_stream_set_non_interleaved(sa_stream_t *s, int enable)) +UNSUPPORTED(int sa_stream_set_dynamic_rate(sa_stream_t *s, int enable)) +UNSUPPORTED(int sa_stream_set_driver(sa_stream_t *s, const char *driver)) +UNSUPPORTED(int sa_stream_start_thread(sa_stream_t *s, sa_event_callback_t callback)) +UNSUPPORTED(int sa_stream_stop_thread(sa_stream_t *s)) +UNSUPPORTED(int sa_stream_change_device(sa_stream_t *s, const char *device_name)) +UNSUPPORTED(int sa_stream_change_read_volume(sa_stream_t *s, const int32_t vol[], unsigned int n)) +UNSUPPORTED(int sa_stream_change_write_volume(sa_stream_t *s, const int32_t vol[], unsigned int n)) +UNSUPPORTED(int sa_stream_change_rate(sa_stream_t *s, unsigned int rate)) +UNSUPPORTED(int sa_stream_change_meta_data(sa_stream_t *s, const char *name, const void *data, size_t size)) +UNSUPPORTED(int sa_stream_change_user_data(sa_stream_t *s, const void *value)) +UNSUPPORTED(int sa_stream_set_adjust_rate(sa_stream_t *s, sa_adjust_t direction)) +UNSUPPORTED(int sa_stream_set_adjust_nchannels(sa_stream_t *s, sa_adjust_t direction)) +UNSUPPORTED(int sa_stream_set_adjust_pcm_format(sa_stream_t *s, sa_adjust_t direction)) +UNSUPPORTED(int sa_stream_set_adjust_watermarks(sa_stream_t *s, sa_adjust_t direction)) +UNSUPPORTED(int sa_stream_get_mode(sa_stream_t *s, sa_mode_t *access_mode)) +UNSUPPORTED(int sa_stream_get_codec(sa_stream_t *s, char *codec, size_t *size)) +UNSUPPORTED(int sa_stream_get_pcm_format(sa_stream_t *s, sa_pcm_format_t *format)) +UNSUPPORTED(int sa_stream_get_rate(sa_stream_t *s, unsigned int *rate)) +UNSUPPORTED(int sa_stream_get_nchannels(sa_stream_t *s, int *nchannels)) +UNSUPPORTED(int sa_stream_get_user_data(sa_stream_t *s, void **value)) +UNSUPPORTED(int sa_stream_get_write_lower_watermark(sa_stream_t *s, size_t *size)) +UNSUPPORTED(int sa_stream_get_read_lower_watermark(sa_stream_t *s, size_t *size)) +UNSUPPORTED(int sa_stream_get_write_upper_watermark(sa_stream_t *s, size_t *size)) +UNSUPPORTED(int sa_stream_get_read_upper_watermark(sa_stream_t *s, size_t *size)) +UNSUPPORTED(int sa_stream_get_channel_map(sa_stream_t *s, sa_channel_t map[], unsigned int *n)) +UNSUPPORTED(int sa_stream_get_xrun_mode(sa_stream_t *s, sa_xrun_mode_t *mode)) +UNSUPPORTED(int sa_stream_get_non_interleaved(sa_stream_t *s, int *enabled)) +UNSUPPORTED(int sa_stream_get_dynamic_rate(sa_stream_t *s, int *enabled)) +UNSUPPORTED(int sa_stream_get_driver(sa_stream_t *s, char *driver_name, size_t *size)) +UNSUPPORTED(int sa_stream_get_device(sa_stream_t *s, char *device_name, size_t *size)) +UNSUPPORTED(int sa_stream_get_read_volume(sa_stream_t *s, int32_t vol[], unsigned int *n)) +UNSUPPORTED(int sa_stream_get_write_volume(sa_stream_t *s, int32_t vol[], unsigned int *n)) +UNSUPPORTED(int sa_stream_get_meta_data(sa_stream_t *s, const char *name, void*data, size_t *size)) +UNSUPPORTED(int sa_stream_get_adjust_rate(sa_stream_t *s, sa_adjust_t *direction)) +UNSUPPORTED(int sa_stream_get_adjust_nchannels(sa_stream_t *s, sa_adjust_t *direction)) +UNSUPPORTED(int sa_stream_get_adjust_pcm_format(sa_stream_t *s, sa_adjust_t *direction)) +UNSUPPORTED(int sa_stream_get_adjust_watermarks(sa_stream_t *s, sa_adjust_t *direction)) +UNSUPPORTED(int sa_stream_get_state(sa_stream_t *s, sa_state_t *state)) +UNSUPPORTED(int sa_stream_get_event_error(sa_stream_t *s, sa_error_t *error)) +UNSUPPORTED(int sa_stream_get_event_notify(sa_stream_t *s, sa_notify_t *notify)) +UNSUPPORTED(int sa_stream_read(sa_stream_t *s, void *data, size_t nbytes)) +UNSUPPORTED(int sa_stream_read_ni(sa_stream_t *s, unsigned int channel, void *data, size_t nbytes)) +UNSUPPORTED(int sa_stream_write_ni(sa_stream_t *s, unsigned int channel, const void *data, size_t nbytes)) +UNSUPPORTED(int sa_stream_pwrite(sa_stream_t *s, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence)) +UNSUPPORTED(int sa_stream_pwrite_ni(sa_stream_t *s, unsigned int channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence)) +UNSUPPORTED(int sa_stream_get_read_size(sa_stream_t *s, size_t *size)) +UNSUPPORTED(int sa_stream_get_volume_abs(sa_stream_t *s, float *vol)) +UNSUPPORTED(int sa_stream_get_min_write(sa_stream_t *s, size_t *size)) + +const char *sa_strerror(int code) { return NULL; } + diff --git a/memory/mozalloc/Makefile.in b/memory/mozalloc/Makefile.in index 3f8fb942b1ec..1112af01d6d3 100644 --- a/memory/mozalloc/Makefile.in +++ b/memory/mozalloc/Makefile.in @@ -51,9 +51,14 @@ endif MODULE = mozalloc LIBRARY_NAME = mozalloc -FORCE_SHARED_LIB= 1 DIST_INSTALL = 1 +ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) +FORCE_STATIC_LIB= 1 +else +FORCE_SHARED_LIB= 1 +endif + ifeq (,$(filter-out OS2,$(OS_ARCH))) # The strndup declaration in string.h is in an ifdef __USE_GNU section DEFINES += -D_GNU_SOURCE diff --git a/memory/mozutils/Makefile.in b/memory/mozutils/Makefile.in index 30a09c3368b6..b090c6a19175 100644 --- a/memory/mozutils/Makefile.in +++ b/memory/mozutils/Makefile.in @@ -80,10 +80,13 @@ NO_INSTALL_IMPORT_LIBRARY = 1 endif endif -ifeq (Android, $(OS_TARGET)) +ifeq (android, $(MOZ_WIDGET_TOOLKIT)) # Add Android linker EXTRA_DSO_LDOPTS += $(ZLIB_LIBS) SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,android,$(DEPTH)/other-licenses/android) +endif + +ifeq (Android, $(OS_TARGET)) WRAP_LDFLAGS = endif diff --git a/mobile/components/build/nsShellService.cpp b/mobile/components/build/nsShellService.cpp index 18e5af005b25..477976477d48 100644 --- a/mobile/components/build/nsShellService.cpp +++ b/mobile/components/build/nsShellService.cpp @@ -48,7 +48,7 @@ #include #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #endif @@ -92,7 +92,7 @@ nsShellService::CreateShortcut(const nsAString& aTitle, const nsAString& aURI, c if (!aTitle.Length() || !aURI.Length() || !aIconData.Length()) return NS_ERROR_FAILURE; -#if ANDROID +#if MOZ_WIDGET_ANDROID mozilla::AndroidBridge::Bridge()->CreateShortcut(aTitle, aURI, aIconData, aIntent); return NS_OK; #else diff --git a/netwerk/build/nsNetModule.cpp b/netwerk/build/nsNetModule.cpp index f74fbd3e6fee..9385f2f1a166 100644 --- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -364,7 +364,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMaemoNetworkLinkService, Init) #elif defined(MOZ_ENABLE_QTNETWORK) #include "nsQtNetworkLinkService.h" NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsQtNetworkLinkService, Init) -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) #include "nsAndroidNetworkLinkService.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidNetworkLinkService) #endif @@ -801,7 +801,7 @@ NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); #elif defined(MOZ_ENABLE_QTNETWORK) NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); #endif NS_DEFINE_NAMED_CID(NS_SERIALIZATION_HELPER_CID); @@ -934,7 +934,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = { { &kNS_NETWORK_LINK_SERVICE_CID, false, NULL, nsMaemoNetworkLinkServiceConstructor }, #elif defined(MOZ_ENABLE_QTNETWORK) { &kNS_NETWORK_LINK_SERVICE_CID, false, NULL, nsQtNetworkLinkServiceConstructor }, -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) { &kNS_NETWORK_LINK_SERVICE_CID, false, NULL, nsAndroidNetworkLinkServiceConstructor }, #endif { &kNS_SERIALIZATION_HELPER_CID, false, NULL, nsSerializationHelperConstructor }, @@ -1072,7 +1072,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = { { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, #elif defined(MOZ_ENABLE_QTNETWORK) { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, #endif { NS_SERIALIZATION_HELPER_CONTRACTID, &kNS_SERIALIZATION_HELPER_CID }, diff --git a/netwerk/protocol/device/Makefile.in b/netwerk/protocol/device/Makefile.in index 0634fa209a23..51f56a9db0d4 100644 --- a/netwerk/protocol/device/Makefile.in +++ b/netwerk/protocol/device/Makefile.in @@ -51,7 +51,7 @@ CPPSRCS = \ nsDeviceProtocolHandler.cpp \ $(NULL) -ifeq (Android,$(OS_TARGET)) +ifeq (android,$(MOZ_WIDGET_TOOLKIT)) CPPSRCS += AndroidCaptureProvider.cpp \ CameraStreamImpl.cpp \ $(NULL) diff --git a/netwerk/protocol/device/nsDeviceChannel.cpp b/netwerk/protocol/device/nsDeviceChannel.cpp index 3d77756093d5..96a34caa1b43 100644 --- a/netwerk/protocol/device/nsDeviceChannel.cpp +++ b/netwerk/protocol/device/nsDeviceChannel.cpp @@ -41,7 +41,7 @@ #include "nsDeviceCaptureProvider.h" #include "mozilla/Preferences.h" -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidCaptureProvider.h" #endif @@ -140,7 +140,7 @@ nsDeviceChannel::OpenContentStream(bool aAsync, if (!captureParams.height) captureParams.height = 480; captureParams.bpp = 32; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID capture = GetAndroidCaptureProvider(); #endif } else if (kNotFound != spec.Find(NS_LITERAL_CSTRING("type=video/x-raw-yuv"), @@ -164,7 +164,7 @@ nsDeviceChannel::OpenContentStream(bool aAsync, captureParams.bpp = 32; captureParams.timeLimit = 0; captureParams.frameLimit = 60000; -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID // only enable if "device.camera.enabled" is true. if (mozilla::Preferences::GetBool("device.camera.enabled", false) == true) capture = GetAndroidCaptureProvider(); diff --git a/security/manager/Makefile.in b/security/manager/Makefile.in index 1c16ad7b23f7..f48964f07911 100644 --- a/security/manager/Makefile.in +++ b/security/manager/Makefile.in @@ -260,8 +260,14 @@ DEFAULT_GMAKE_FLAGS += \ OS_RELEASE="2.6" \ OS_PTHREAD= \ STANDARDS_CFLAGS="-std=gnu89" \ - ARCHFLAG="$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -DANDROID_VERSION=$(ANDROID_VERSION) -include $(ABS_topsrcdir)/security/manager/android_stub.h" \ $(NULL) + +ifeq ($(MOZ_WIDGET_TOOLKIT),android) +DEFAULT_GMAKE_FLAGS += ARCHFLAG="$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -DANDROID_VERSION=$(ANDROID_VERSION) -include $(ABS_topsrcdir)/security/manager/android_stub.h" +else +DEFAULT_GMAKE_FLAGS += ARCHFLAG="$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -include $(ABS_topsrcdir)/security/manager/android_stub.h" +endif + endif endif diff --git a/security/manager/android_stub.h b/security/manager/android_stub.h index a8690f1c9790..00b91098bdb8 100644 --- a/security/manager/android_stub.h +++ b/security/manager/android_stub.h @@ -41,6 +41,7 @@ #define ANDROID_STUB_H #include "dlfcn.h" +#ifdef ANDROID_VERSION #if ANDROID_VERSION < 8 /* because dladdr isn't supported in android 2.1 and older. * however, it exists in the android repos so.. maybe someday. */ @@ -50,6 +51,7 @@ typedef struct { #define dladdr(foo, bar) 0 #endif +#endif /* sysinfo is defined but not implemented. * we may be able to implement it ourselves. */ diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp index 27e82d2cfc31..ca87f1a965db 100644 --- a/toolkit/components/downloads/nsDownloadManager.cpp +++ b/toolkit/components/downloads/nsDownloadManager.cpp @@ -83,7 +83,7 @@ #include #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #endif @@ -1178,7 +1178,7 @@ nsDownloadManager::GetDefaultDownloadsDirectory(nsILocalFile **aResult) rv = dirService->Get(NS_UNIX_XDG_DOCUMENTS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(downloadDir)); -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) // Android doesn't have a $HOME directory, and by default we only have // write access to /data/data/org.mozilla.{$APP} and /sdcard char* downloadDirPath = getenv("DOWNLOADS_DIRECTORY"); @@ -2254,7 +2254,7 @@ nsDownload::SetState(DownloadState aState) } } -#if defined(XP_WIN) || defined(XP_MACOSX) || defined(ANDROID) +#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) nsCOMPtr fileURL = do_QueryInterface(mTarget); nsCOMPtr file; nsAutoString path; @@ -2288,7 +2288,7 @@ nsDownload::SetState(DownloadState aState) observedObject, NULL, TRUE); ::CFRelease(observedObject); #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID nsCOMPtr mimeInfo; nsCAutoString contentType; GetMIMEInfo(getter_AddRefs(mimeInfo)); diff --git a/toolkit/library/libxul-config.mk b/toolkit/library/libxul-config.mk index 13bb5cb0c2a6..14fa06380da2 100644 --- a/toolkit/library/libxul-config.mk +++ b/toolkit/library/libxul-config.mk @@ -217,7 +217,7 @@ COMPONENT_LIBS += universalchardet DEFINES += -DMOZ_UNIVERSALCHARDET endif -ifeq (,$(filter android qt os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) +ifeq (,$(filter android gonk qt os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) ifdef MOZ_XUL COMPONENT_LIBS += fileview DEFINES += -DMOZ_FILEVIEW @@ -261,6 +261,10 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),android) COMPONENT_LIBS += widget_android endif +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +COMPONENT_LIBS += widget_gonk +endif + STATIC_LIBS += thebes ycbcr ifeq ($(MOZ_WIDGET_TOOLKIT),android) @@ -365,3 +369,7 @@ endif ifeq (android,$(MOZ_WIDGET_TOOLKIT)) OS_LIBS += -lGLESv2 endif + +ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) +OS_LIBS += -lui +endif diff --git a/toolkit/library/nsStaticXULComponents.cpp b/toolkit/library/nsStaticXULComponents.cpp index 7825fe4e9d40..f040d18e1b62 100644 --- a/toolkit/library/nsStaticXULComponents.cpp +++ b/toolkit/library/nsStaticXULComponents.cpp @@ -77,6 +77,8 @@ # define WIDGET_MODULES MODULE(nsWidgetQtModule) #elif defined(MOZ_WIDGET_ANDROID) # define WIDGET_MODULES MODULE(nsWidgetAndroidModule) +#elif defined(MOZ_WIDGET_GONK) +# define WIDGET_MODULES MODULE(nsWidgetGonkModule) #else # error Unknown widget module. #endif diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk index 371e302ca6e4..dd11f0634c06 100644 --- a/toolkit/mozapps/installer/packager.mk +++ b/toolkit/mozapps/installer/packager.mk @@ -56,7 +56,7 @@ else ifeq (,$(filter-out gtk2 qt, $(MOZ_WIDGET_TOOLKIT))) MOZ_PKG_FORMAT = BZ2 else - ifeq (Android,$(OS_TARGET)) + ifeq (android,$(MOZ_WIDGET_TOOLKIT)) MOZ_PKG_FORMAT = APK else MOZ_PKG_FORMAT = TGZ diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in index 2be2760980a2..7b5996f095de 100644 --- a/toolkit/xre/Makefile.in +++ b/toolkit/xre/Makefile.in @@ -128,7 +128,7 @@ ifdef MOZ_X11 CPPSRCS += nsX11ErrorHandler.cpp endif -ifeq ($(OS_TARGET),Android) +ifeq ($(MOZ_WIDGET_TOOLKIT),android) CPPSRCS += nsAndroidStartup.cpp DEFINES += -DANDROID_PACKAGE_NAME='"$(ANDROID_PACKAGE_NAME)"' endif diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 159dd45d1a7d..487a7af70702 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -217,7 +217,7 @@ using mozilla::unused; #include "mozilla/FunctionTimer.h" -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #endif @@ -1607,7 +1607,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative, SaveToEnv("MOZ_LAUNCHED_CHILD=1"); -#if defined(ANDROID) +#if defined(MOZ_WIDGET_ANDROID) mozilla::AndroidBridge::Bridge()->ScheduleRestart(); #else #if defined(XP_MACOSX) @@ -1658,7 +1658,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative, #endif // XP_OS2 series #endif // WP_WIN #endif // WP_MACOSX -#endif // ANDROID +#endif // MOZ_WIDGET_ANDROID return NS_ERROR_LAUNCHED_CHILD_PROCESS; } diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index 45bdfb179c9b..200de65d9d2d 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -1065,6 +1065,9 @@ nsXREDirProvider::GetUserDataDirectoryHome(nsILocalFile** aFile, bool aLocal) *strrchr(appDir, '\\') = '\0'; rv = NS_NewNativeLocalFile(nsDependentCString(appDir), true, getter_AddRefs(localDir)); } +#elif defined(MOZ_WIDGET_GONK) + rv = NS_NewNativeLocalFile(NS_LITERAL_CSTRING("/data/b2g"), PR_TRUE, + getter_AddRefs(localDir)); #elif defined(XP_UNIX) const char* homeDir = getenv("HOME"); if (!homeDir || !*homeDir) diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in index 80e23f1c402c..5b29d2a52b3e 100644 --- a/uriloader/exthandler/Makefile.in +++ b/uriloader/exthandler/Makefile.in @@ -60,11 +60,15 @@ else ifeq ($(MOZ_WIDGET_TOOLKIT),android) OSDIR = android else +ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) +OSDIR = gonk +else OSDIR = unix endif endif endif endif +endif VPATH := $(srcdir) $(srcdir)/$(OSDIR) diff --git a/uriloader/exthandler/gonk/nsOSHelperAppService.cpp b/uriloader/exthandler/gonk/nsOSHelperAppService.cpp new file mode 100644 index 000000000000..f37d27cba14b --- /dev/null +++ b/uriloader/exthandler/gonk/nsOSHelperAppService.cpp @@ -0,0 +1,63 @@ +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Gonk code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsOSHelperAppService.h" + +nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService() +{ +} + +nsOSHelperAppService::~nsOSHelperAppService() +{ +} + +already_AddRefed +nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, + bool* aFound) +{ + *aFound = false; + return nsnull; +} + +nsresult +nsOSHelperAppService::OSProtocolHandlerExists(const char* aScheme, + bool* aExists) +{ + *aExists = false; + return NS_OK; +} diff --git a/uriloader/exthandler/gonk/nsOSHelperAppService.h b/uriloader/exthandler/gonk/nsOSHelperAppService.h new file mode 100644 index 000000000000..2561ef73946b --- /dev/null +++ b/uriloader/exthandler/gonk/nsOSHelperAppService.h @@ -0,0 +1,60 @@ +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Gonk code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsOSHelperAppService_h +#define nsOSHelperAppService_h + +#include "nsCExternalHandlerService.h" +#include "nsExternalHelperAppService.h" + +class nsOSHelperAppService : public nsExternalHelperAppService +{ +public: + nsOSHelperAppService(); + virtual ~nsOSHelperAppService(); + + virtual already_AddRefed + GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, + bool* aFound); + + virtual NS_HIDDEN_(nsresult) + OSProtocolHandlerExists(const char* aScheme, + bool* aExists); +}; + +#endif /* nsOSHelperAppService_h */ diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index d3045e78eae1..4831cc03b601 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -147,7 +147,7 @@ #include "nsIDocShellTreeItem.h" #include "ExternalHelperAppChild.h" -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #endif @@ -485,7 +485,7 @@ static nsExtraMimeTypeEntry extraMimeEntries [] = { APPLICATION_XPINSTALL, "xpi", "XPInstall Install" }, { APPLICATION_POSTSCRIPT, "ps,eps,ai", "Postscript File" }, { APPLICATION_XJAVASCRIPT, "js", "Javascript Source File" }, -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID { "application/vnd.android.package-archive", "apk", "Android Package" }, #endif { IMAGE_ART, "art", "ART Image" }, diff --git a/widget/public/Makefile.in b/widget/public/Makefile.in index 158930aa34a6..90eb8abf6676 100644 --- a/widget/public/Makefile.in +++ b/widget/public/Makefile.in @@ -88,7 +88,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),os2) EXPORTS += nsIDragSessionOS2.h endif -ifeq ($(MOZ_WIDGET_TOOLKIT),android) +ifneq (,$(filter android gonk,$(MOZ_WIDGET_TOOLKIT))) EXPORTS += \ nsIPrintDialogService.h \ $(NULL) diff --git a/widget/src/Makefile.in b/widget/src/Makefile.in index 2ac259e2545b..bf997103ed25 100644 --- a/widget/src/Makefile.in +++ b/widget/src/Makefile.in @@ -46,7 +46,7 @@ MODULE = widget DIRS = shared xpwidgets -ifneq (,$(filter os2 cocoa qt android,$(MOZ_WIDGET_TOOLKIT))) +ifneq (,$(filter os2 cocoa qt android gonk,$(MOZ_WIDGET_TOOLKIT))) DIRS += $(MOZ_WIDGET_TOOLKIT) endif diff --git a/widget/src/gonk/Makefile.in b/widget/src/gonk/Makefile.in new file mode 100644 index 000000000000..f449b8663693 --- /dev/null +++ b/widget/src/gonk/Makefile.in @@ -0,0 +1,75 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation +# Portions created by the Initial Developer are Copyright (C) 2009-2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Vladimir Vukicevic +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = widget +LIBRARY_NAME = widget_gonk +EXPORT_LIBRARY = 1 +IS_COMPONENT = 1 +MODULE_NAME = nsWidgetGonkModule +GRE_MODULE = 1 +LIBXUL_LIBRARY = 1 + + +CPPSRCS = \ + nsAppShell.cpp \ + nsWidgetFactory.cpp \ + nsWindow.cpp \ + nsLookAndFeel.cpp \ + nsScreenManagerGonk.cpp \ + $(NULL) + +SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a + +include $(topsrcdir)/config/rules.mk + +DEFINES += -D_IMPL_NS_WIDGET + +LOCAL_INCLUDES += \ + -I$(topsrcdir)/widget/src/xpwidgets \ + -I$(topsrcdir)/widget/src/shared \ + -I$(topsrcdir)/dom/system/android \ + -I$(srcdir) \ + $(NULL) + +include $(topsrcdir)/ipc/chromium/chromium-config.mk diff --git a/widget/src/gonk/nsAppShell.cpp b/widget/src/gonk/nsAppShell.cpp new file mode 100644 index 000000000000..02176b49008c --- /dev/null +++ b/widget/src/gonk/nsAppShell.cpp @@ -0,0 +1,473 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=4 sw=4 sts=4 tw=80 et: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Gonk. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nsAppShell.h" +#include "nsGkAtoms.h" +#include "nsGUIEvent.h" +#include "nsWindow.h" +#include "nsIObserverService.h" +#include "mozilla/Services.h" + +#include "android/log.h" + +#ifndef ABS_MT_TOUCH_MAJOR +// Taken from include/linux/input.h +// XXX update the bionic input.h so we don't have to do this! +#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ +#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ +#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */ +#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */ +#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ +#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */ +#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */ +#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ +#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */ +#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ +#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */ +#define SYN_MT_REPORT 2 +#endif + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) + +using namespace mozilla; + +bool gDrawRequest = false; +static nsAppShell *gAppShell = NULL; +static int epollfd = 0; +static int signalfds[2] = {0}; + +namespace mozilla { + +bool ProcessNextEvent() +{ + return gAppShell->ProcessNextNativeEvent(true); +} + +void NotifyEvent() +{ + gAppShell->NotifyNativeEvent(); +} + +} + +static void +pipeHandler(int fd, FdHandler *data) +{ + ssize_t len; + do { + char tmp[32]; + len = read(fd, tmp, sizeof(tmp)); + } while (len > 0); +} + +static +PRUint64 timevalToMS(const struct timeval &time) +{ + return time.tv_sec * 1000 + time.tv_usec / 1000; +} + +static void +sendMouseEvent(PRUint32 msg, struct timeval *time, int x, int y) +{ + nsMouseEvent event(true, msg, NULL, + nsMouseEvent::eReal, nsMouseEvent::eNormal); + + event.refPoint.x = x; + event.refPoint.y = y; + event.time = timevalToMS(*time); + event.isShift = false; + event.isControl = false; + event.isMeta = false; + event.isAlt = false; + event.button = nsMouseEvent::eLeftButton; + if (msg != NS_MOUSE_MOVE) + event.clickCount = 1; + + nsWindow::DispatchInputEvent(event); + //LOG("Dispatched type %d at %dx%d", msg, x, y); +} + +static void +multitouchHandler(int fd, FdHandler *data) +{ + // The Linux's input documentation (Documentation/input/input.txt) + // says that we'll always read a multiple of sizeof(input_event) bytes here. + input_event events[16]; + int event_count = read(fd, events, sizeof(events)); + if (event_count < 0) { + LOG("Error reading in multitouchHandler"); + return; + } + MOZ_ASSERT(event_count % sizeof(input_event) == 0); + + event_count /= sizeof(struct input_event); + + for (int i = 0; i < event_count; i++) { + input_event *event = &events[i]; + + if (event->type == EV_ABS) { + if (data->mtState == FdHandler::MT_IGNORE) + continue; + if (data->mtState == FdHandler::MT_START) + data->mtState = FdHandler::MT_COLLECT; + + switch (event->code) { + case ABS_MT_TOUCH_MAJOR: + data->mtMajor = event->value; + break; + case ABS_MT_TOUCH_MINOR: + case ABS_MT_WIDTH_MAJOR: + case ABS_MT_WIDTH_MINOR: + case ABS_MT_ORIENTATION: + case ABS_MT_TOOL_TYPE: + case ABS_MT_BLOB_ID: + case ABS_MT_TRACKING_ID: + case ABS_MT_PRESSURE: + break; + case ABS_MT_POSITION_X: + data->mtX = event->value; + break; + case ABS_MT_POSITION_Y: + data->mtY = event->value; + break; + default: + LOG("Got unknown event type 0x%04x with code 0x%04x and value %d", + event->type, event->code, event->value); + } + } else if (event->type == EV_SYN) { + switch (event->code) { + case SYN_MT_REPORT: + if (data->mtState == FdHandler::MT_COLLECT) + data->mtState = FdHandler::MT_IGNORE; + break; + case SYN_REPORT: + if ((!data->mtMajor || data->mtState == FdHandler::MT_START)) { + sendMouseEvent(NS_MOUSE_BUTTON_UP, &event->time, + data->mtX, data->mtY); + data->mtDown = false; + //LOG("Up mouse event"); + } else if (!data->mtDown) { + sendMouseEvent(NS_MOUSE_BUTTON_DOWN, &event->time, + data->mtX, data->mtY); + data->mtDown = true; + //LOG("Down mouse event"); + } else { + sendMouseEvent(NS_MOUSE_MOVE, &event->time, + data->mtX, data->mtY); + data->mtDown = true; + } + data->mtState = FdHandler::MT_START; + break; + default: + LOG("Got unknown event type 0x%04x with code 0x%04x and value %d", + event->type, event->code, event->value); + } + } else + LOG("Got unknown event type 0x%04x with code 0x%04x and value %d", + event->type, event->code, event->value); + } +} + +static void +sendKeyEventWithMsg(PRUint32 keyCode, PRUint32 msg, const struct timeval &time) +{ + nsKeyEvent event(true, msg, NULL); + event.keyCode = keyCode; + event.time = timevalToMS(time); + nsWindow::DispatchInputEvent(event); +} + +static void +sendKeyEvent(PRUint32 keyCode, bool keyDown, const struct timeval &time) +{ + sendKeyEventWithMsg(keyCode, keyDown ? NS_KEY_DOWN : NS_KEY_UP, time); + if (keyDown) { + // Send a key press event right after the key down event. + sendKeyEventWithMsg(keyCode, NS_KEY_PRESS, time); + } +} + +static void +sendSpecialKeyEvent(nsIAtom *command, const struct timeval &time) +{ + nsCommandEvent event(true, nsGkAtoms::onAppCommand, command, NULL); + event.time = timevalToMS(time); + nsWindow::DispatchInputEvent(event); +} + +static int screenFd = -1; +static bool sScreenOn = true; + +static void +handlePowerKeyPressed() +{ + if (screenFd == -1) { + screenFd = open("/sys/power/state", O_RDWR); + if (screenFd < 0) { + LOG("Unable to open /sys/power/state."); + return; + } + } + + // No idea why the screen-off string is "mem" rather than "off". + const char *state = sScreenOn ? "mem" : "on"; + if (write(screenFd, state, strlen(state)) < 0) { + LOG("Unable to write to /sys/power/state."); + return; + } + + sScreenOn = !sScreenOn; +} + +static void +keyHandler(int fd, FdHandler *data) +{ + input_event events[16]; + ssize_t bytesRead = read(fd, events, sizeof(events)); + if (bytesRead < 0) { + LOG("Error reading in keyHandler"); + return; + } + MOZ_ASSERT(bytesRead % sizeof(input_event) == 0); + + for (unsigned int i = 0; i < bytesRead / sizeof(struct input_event); i++) { + const input_event &e = events[i]; + + if (e.type == EV_SYN) { + // Ignore this event; it just signifies that a key was pressed. + continue; + } + + if (e.type != EV_KEY) { + LOG("Got unknown key event type. type 0x%04x code 0x%04x value %d", + e.type, e.code, e.value); + continue; + } + + if (e.value != 0 && e.value != 1) { + LOG("Got unknown key event value. type 0x%04x code 0x%04x value %d", + e.type, e.code, e.value); + continue; + } + + if (!sScreenOn && e.code != KEY_POWER) { + LOG("Ignoring key event, because the screen is off. " + "type 0x%04x code 0x%04x value %d", + e.type, e.code, e.value); + continue; + } + + bool pressed = e.value == 1; + const char* upOrDown = pressed ? "pressed" : "released"; + switch (e.code) { + case KEY_BACK: + sendKeyEvent(NS_VK_ESCAPE, pressed, e.time); + break; + case KEY_MENU: + if (!pressed) + sendSpecialKeyEvent(nsGkAtoms::Menu, e.time); + break; + case KEY_SEARCH: + if (pressed) + sendSpecialKeyEvent(nsGkAtoms::Search, e.time); + break; + case KEY_HOME: + sendKeyEvent(NS_VK_HOME, pressed, e.time); + break; + case KEY_POWER: + LOG("Power key %s", upOrDown); + // Ideally, we'd send a NS_VK_SLEEP event here and let the front-end + // sort out what to do. But for now, let's just turn off the screen + // ourselves. + if (pressed) + handlePowerKeyPressed(); + break; + case KEY_VOLUMEUP: + if (pressed) + sendSpecialKeyEvent(nsGkAtoms::VolumeUp, e.time); + break; + case KEY_VOLUMEDOWN: + if (pressed) + sendSpecialKeyEvent(nsGkAtoms::VolumeDown, e.time); + break; + default: + LOG("Got unknown key event code. type 0x%04x code 0x%04x value %d", + e.type, e.code, e.value); + } + } +} + +nsAppShell::nsAppShell() + : mNativeCallbackRequest(false) + , mHandlers() +{ + gAppShell = this; +} + +nsAppShell::~nsAppShell() +{ + gAppShell = NULL; +} + +nsresult +nsAppShell::Init() +{ + epoll_event event = { + EPOLLIN, + { 0 } + }; + + nsresult rv = nsBaseAppShell::Init(); + NS_ENSURE_SUCCESS(rv, rv); + + epollfd = epoll_create(16); + NS_ENSURE_TRUE(epollfd >= 0, NS_ERROR_UNEXPECTED); + + int ret = pipe2(signalfds, O_NONBLOCK); + NS_ENSURE_FALSE(ret, NS_ERROR_UNEXPECTED); + + FdHandler *handler = mHandlers.AppendElement(); + handler->fd = signalfds[0]; + handler->func = pipeHandler; + event.data.u32 = mHandlers.Length() - 1; + ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, signalfds[0], &event); + NS_ENSURE_FALSE(ret, NS_ERROR_UNEXPECTED); + + DIR *dir = opendir("/dev/input"); + NS_ENSURE_TRUE(dir, NS_ERROR_UNEXPECTED); + +#define BITSET(bit, flags) (flags[bit >> 3] & (1 << (bit & 0x7))) + + struct dirent *entry; + while ((entry = readdir(dir))) { + char entryName[64]; + char entryPath[MAXPATHLEN]; + if (snprintf(entryPath, sizeof(entryPath), + "/dev/input/%s", entry->d_name) < 0) { + LOG("Couldn't generate path while enumerating input devices!"); + continue; + } + int fd = open(entryPath, O_RDONLY); + if (ioctl(fd, EVIOCGNAME(sizeof(entryName)), entryName) >= 0) + LOG("Found device %s - %s", entry->d_name, entryName); + else + continue; + + FdHandlerCallback handlerFunc = NULL; + + char flags[(NS_MAX(ABS_MAX, KEY_MAX) + 1) / 8]; + if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(flags)), flags) >= 0 && + BITSET(ABS_MT_POSITION_X, flags)) { + + LOG("Found absolute input device"); + handlerFunc = multitouchHandler; + } else if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(flags)), flags) >= 0) { + LOG("Found key input device"); + handlerFunc = keyHandler; + } + + // Register the handler, if we have one. + if (!handlerFunc) + continue; + + handler = mHandlers.AppendElement(); + handler->fd = fd; + handler->func = handlerFunc; + event.data.u32 = mHandlers.Length() - 1; + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event)) + LOG("Failed to add fd to epoll fd"); + } + + return rv; +} + +void +nsAppShell::ScheduleNativeEventCallback() +{ + mNativeCallbackRequest = true; + NotifyEvent(); +} + +bool +nsAppShell::ProcessNextNativeEvent(bool mayWait) +{ + epoll_event events[16] = {{ 0 }}; + + int event_count; + if ((event_count = epoll_wait(epollfd, events, 16, mayWait ? -1 : 0)) <= 0) + return true; + + for (int i = 0; i < event_count; i++) + mHandlers[events[i].data.u32].run(); + + // NativeEventCallback always schedules more if it needs it + // so we can coalesce these. + // See the implementation in nsBaseAppShell.cpp for more info + if (mNativeCallbackRequest) { + mNativeCallbackRequest = false; + NativeEventCallback(); + } + + if (gDrawRequest) { + gDrawRequest = false; + nsWindow::DoDraw(); + } + + return true; +} + +void +nsAppShell::NotifyNativeEvent() +{ + write(signalfds[1], "w", 1); +} + diff --git a/widget/src/gonk/nsAppShell.h b/widget/src/gonk/nsAppShell.h new file mode 100644 index 000000000000..632cc44d3000 --- /dev/null +++ b/widget/src/gonk/nsAppShell.h @@ -0,0 +1,94 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Gonk. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsAppShell_h +#define nsAppShell_h + +#include "nsBaseAppShell.h" + +namespace mozilla { +bool ProcessNextEvent(); +void NotifyEvent(); +} + +extern bool gDrawRequest; + +class FdHandler; +typedef void(*FdHandlerCallback)(int, FdHandler *); + +class FdHandler { +public: + FdHandler() : mtState(MT_START), mtDown(false) { } + + int fd; + FdHandlerCallback func; + enum mtStates { + MT_START, + MT_COLLECT, + MT_IGNORE + } mtState; + int mtX, mtY; + int mtMajor; + bool mtDown; + + void run() + { + func(fd, this); + } +}; + +class nsAppShell : public nsBaseAppShell { +public: + nsAppShell(); + + nsresult Init(); + virtual bool ProcessNextNativeEvent(bool maywait); + + void NotifyNativeEvent(); + +protected: + virtual ~nsAppShell(); + + virtual void ScheduleNativeEventCallback(); + + // This is somewhat racy but is perfectly safe given how the callback works + bool mNativeCallbackRequest; + nsTArray mHandlers; +}; + +#endif /* nsAppShell_h */ + diff --git a/widget/src/gonk/nsLookAndFeel.cpp b/widget/src/gonk/nsLookAndFeel.cpp new file mode 100644 index 000000000000..7560944c2956 --- /dev/null +++ b/widget/src/gonk/nsLookAndFeel.cpp @@ -0,0 +1,319 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsLookAndFeel.h" + +nsLookAndFeel::nsLookAndFeel() + : nsXPLookAndFeel() +{ +} + +nsLookAndFeel::~nsLookAndFeel() +{ +} + +nsresult +nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor) +{ + nsresult rv = NS_OK; + +#define BASE_ACTIVE_COLOR NS_RGB(0xaa,0xaa,0xaa) +#define BASE_NORMAL_COLOR NS_RGB(0xff,0xff,0xff) +#define BASE_SELECTED_COLOR NS_RGB(0xaa,0xaa,0xaa) +#define BG_ACTIVE_COLOR NS_RGB(0xff,0xff,0xff) +#define BG_INSENSITIVE_COLOR NS_RGB(0xaa,0xaa,0xaa) +#define BG_NORMAL_COLOR NS_RGB(0xff,0xff,0xff) +#define BG_PRELIGHT_COLOR NS_RGB(0xee,0xee,0xee) +#define BG_SELECTED_COLOR NS_RGB(0x99,0x99,0x99) +#define DARK_NORMAL_COLOR NS_RGB(0x88,0x88,0x88) +#define FG_INSENSITIVE_COLOR NS_RGB(0x44,0x44,0x44) +#define FG_NORMAL_COLOR NS_RGB(0x00,0x00,0x00) +#define FG_PRELIGHT_COLOR NS_RGB(0x77,0x77,0x77) +#define FG_SELECTED_COLOR NS_RGB(0xaa,0xaa,0xaa) +#define LIGHT_NORMAL_COLOR NS_RGB(0xaa,0xaa,0xaa) +#define TEXT_ACTIVE_COLOR NS_RGB(0x99,0x99,0x99) +#define TEXT_NORMAL_COLOR NS_RGB(0x00,0x00,0x00) +#define TEXT_SELECTED_COLOR NS_RGB(0x00,0x00,0x00) + + switch (aID) { + // These colors don't seem to be used for anything anymore in Mozilla + // (except here at least TextSelectBackground and TextSelectForeground) + // The CSS2 colors below are used. + case eColorID_WindowBackground: + aColor = BASE_NORMAL_COLOR; + break; + case eColorID_WindowForeground: + aColor = TEXT_NORMAL_COLOR; + break; + case eColorID_WidgetBackground: + aColor = BG_NORMAL_COLOR; + break; + case eColorID_WidgetForeground: + aColor = FG_NORMAL_COLOR; + break; + case eColorID_WidgetSelectBackground: + aColor = BG_SELECTED_COLOR; + break; + case eColorID_WidgetSelectForeground: + aColor = FG_SELECTED_COLOR; + break; + case eColorID_Widget3DHighlight: + aColor = NS_RGB(0xa0,0xa0,0xa0); + break; + case eColorID_Widget3DShadow: + aColor = NS_RGB(0x40,0x40,0x40); + break; + case eColorID_TextBackground: + // not used? + aColor = BASE_NORMAL_COLOR; + break; + case eColorID_TextForeground: + // not used? + aColor = TEXT_NORMAL_COLOR; + break; + case eColorID_TextSelectBackground: + case eColorID_IMESelectedRawTextBackground: + case eColorID_IMESelectedConvertedTextBackground: + // still used + aColor = BASE_SELECTED_COLOR; + break; + case eColorID_TextSelectForeground: + case eColorID_IMESelectedRawTextForeground: + case eColorID_IMESelectedConvertedTextForeground: + // still used + aColor = TEXT_SELECTED_COLOR; + break; + case eColorID_IMERawInputBackground: + case eColorID_IMEConvertedTextBackground: + aColor = NS_TRANSPARENT; + break; + case eColorID_IMERawInputForeground: + case eColorID_IMEConvertedTextForeground: + aColor = NS_SAME_AS_FOREGROUND_COLOR; + break; + case eColorID_IMERawInputUnderline: + case eColorID_IMEConvertedTextUnderline: + aColor = NS_SAME_AS_FOREGROUND_COLOR; + break; + case eColorID_IMESelectedRawTextUnderline: + case eColorID_IMESelectedConvertedTextUnderline: + aColor = NS_TRANSPARENT; + break; + case eColorID_SpellCheckerUnderline: + aColor = NS_RGB(0xff, 0, 0); + break; + + // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors + case eColorID_activeborder: + // active window border + aColor = BG_NORMAL_COLOR; + break; + case eColorID_activecaption: + // active window caption background + aColor = BG_NORMAL_COLOR; + break; + case eColorID_appworkspace: + // MDI background color + aColor = BG_NORMAL_COLOR; + break; + case eColorID_background: + // desktop background + aColor = BG_NORMAL_COLOR; + break; + case eColorID_captiontext: + // text in active window caption, size box, and scrollbar arrow box (!) + aColor = FG_NORMAL_COLOR; + break; + case eColorID_graytext: + // disabled text in windows, menus, etc. + aColor = FG_INSENSITIVE_COLOR; + break; + case eColorID_highlight: + // background of selected item + aColor = BASE_SELECTED_COLOR; + break; + case eColorID_highlighttext: + // text of selected item + aColor = TEXT_SELECTED_COLOR; + break; + case eColorID_inactiveborder: + // inactive window border + aColor = BG_NORMAL_COLOR; + break; + case eColorID_inactivecaption: + // inactive window caption + aColor = BG_INSENSITIVE_COLOR; + break; + case eColorID_inactivecaptiontext: + // text in inactive window caption + aColor = FG_INSENSITIVE_COLOR; + break; + case eColorID_infobackground: + // tooltip background color + aColor = BG_NORMAL_COLOR; + break; + case eColorID_infotext: + // tooltip text color + aColor = TEXT_NORMAL_COLOR; + break; + case eColorID_menu: + // menu background + aColor = BG_NORMAL_COLOR; + break; + case eColorID_menutext: + // menu text + aColor = TEXT_NORMAL_COLOR; + break; + case eColorID_scrollbar: + // scrollbar gray area + aColor = BG_ACTIVE_COLOR; + break; + + case eColorID_threedface: + case eColorID_buttonface: + // 3-D face color + aColor = BG_NORMAL_COLOR; + break; + + case eColorID_buttontext: + // text on push buttons + aColor = TEXT_NORMAL_COLOR; + break; + + case eColorID_buttonhighlight: + // 3-D highlighted edge color + case eColorID_threedhighlight: + // 3-D highlighted outer edge color + aColor = LIGHT_NORMAL_COLOR; + break; + + case eColorID_threedlightshadow: + // 3-D highlighted inner edge color + aColor = BG_NORMAL_COLOR; + break; + + case eColorID_buttonshadow: + // 3-D shadow edge color + case eColorID_threedshadow: + // 3-D shadow inner edge color + aColor = DARK_NORMAL_COLOR; + break; + + case eColorID_threeddarkshadow: + // 3-D shadow outer edge color + aColor = NS_RGB(0,0,0); + break; + + case eColorID_window: + case eColorID_windowframe: + aColor = BG_NORMAL_COLOR; + break; + + case eColorID_windowtext: + aColor = FG_NORMAL_COLOR; + break; + + case eColorID__moz_eventreerow: + case eColorID__moz_field: + aColor = BASE_NORMAL_COLOR; + break; + case eColorID__moz_fieldtext: + aColor = TEXT_NORMAL_COLOR; + break; + case eColorID__moz_dialog: + aColor = BG_NORMAL_COLOR; + break; + case eColorID__moz_dialogtext: + aColor = FG_NORMAL_COLOR; + break; + case eColorID__moz_dragtargetzone: + aColor = BG_SELECTED_COLOR; + break; + case eColorID__moz_buttondefault: + // default button border color + aColor = NS_RGB(0,0,0); + break; + case eColorID__moz_buttonhoverface: + aColor = BG_PRELIGHT_COLOR; + break; + case eColorID__moz_buttonhovertext: + aColor = FG_PRELIGHT_COLOR; + break; + case eColorID__moz_cellhighlight: + case eColorID__moz_html_cellhighlight: + aColor = BASE_ACTIVE_COLOR; + break; + case eColorID__moz_cellhighlighttext: + case eColorID__moz_html_cellhighlighttext: + aColor = TEXT_ACTIVE_COLOR; + break; + case eColorID__moz_menuhover: + aColor = BG_PRELIGHT_COLOR; + break; + case eColorID__moz_menuhovertext: + aColor = FG_PRELIGHT_COLOR; + break; + case eColorID__moz_oddtreerow: + aColor = NS_TRANSPARENT; + break; + case eColorID__moz_nativehyperlinktext: + aColor = NS_SAME_AS_FOREGROUND_COLOR; + break; + case eColorID__moz_comboboxtext: + aColor = TEXT_NORMAL_COLOR; + break; + case eColorID__moz_combobox: + aColor = BG_NORMAL_COLOR; + break; + case eColorID__moz_menubartext: + aColor = TEXT_NORMAL_COLOR; + break; + case eColorID__moz_menubarhovertext: + aColor = FG_PRELIGHT_COLOR; + break; + default: + /* default color is BLACK */ + aColor = 0; + rv = NS_ERROR_FAILURE; + break; + } + + return rv; +} + + diff --git a/widget/src/gonk/nsLookAndFeel.h b/widget/src/gonk/nsLookAndFeel.h new file mode 100644 index 000000000000..7d3b8d02beed --- /dev/null +++ b/widget/src/gonk/nsLookAndFeel.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Lars Knoll + * John C. Griggs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef __nsLookAndFeel +#define __nsLookAndFeel + +#include "nsXPLookAndFeel.h" + +class nsLookAndFeel : public nsXPLookAndFeel +{ +public: + nsLookAndFeel(); + virtual ~nsLookAndFeel(); + +protected: + virtual nsresult NativeGetColor(ColorID aID, nscolor &aColor); +}; + +#endif diff --git a/widget/src/gonk/nsScreenManagerGonk.cpp b/widget/src/gonk/nsScreenManagerGonk.cpp new file mode 100644 index 000000000000..1a7744acd29e --- /dev/null +++ b/widget/src/gonk/nsScreenManagerGonk.cpp @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsScreenManagerGonk.h" +#include "nsWindow.h" + +using namespace mozilla; + +NS_IMPL_ISUPPORTS2(nsScreenGonk, nsIScreen, nsIScreen) + +nsScreenGonk::nsScreenGonk(void *nativeScreen) +{ +} + +nsScreenGonk::~nsScreenGonk() +{ +} + +NS_IMETHODIMP +nsScreenGonk::GetRect(PRInt32 *outLeft, PRInt32 *outTop, + PRInt32 *outWidth, PRInt32 *outHeight) +{ + *outLeft = gScreenBounds.x; + *outTop = gScreenBounds.y; + + *outWidth = gScreenBounds.width; + *outHeight = gScreenBounds.height; + + return NS_OK; +} + + +NS_IMETHODIMP +nsScreenGonk::GetAvailRect(PRInt32 *outLeft, PRInt32 *outTop, + PRInt32 *outWidth, PRInt32 *outHeight) +{ + return GetRect(outLeft, outTop, outWidth, outHeight); +} + + + +NS_IMETHODIMP +nsScreenGonk::GetPixelDepth(PRInt32 *aPixelDepth) +{ + // XXX do we need to lie here about 16bpp? Or + // should we actually check and return the right thing? + *aPixelDepth = 24; + return NS_OK; +} + + +NS_IMETHODIMP +nsScreenGonk::GetColorDepth(PRInt32 *aColorDepth) +{ + return GetPixelDepth(aColorDepth); +} + +NS_IMPL_ISUPPORTS1(nsScreenManagerGonk, nsIScreenManager) + +nsScreenManagerGonk::nsScreenManagerGonk() +{ + mOneScreen = new nsScreenGonk(nsnull); +} + +nsScreenManagerGonk::~nsScreenManagerGonk() +{ +} + +NS_IMETHODIMP +nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen) +{ + NS_IF_ADDREF(*outScreen = mOneScreen.get()); + return NS_OK; +} + +NS_IMETHODIMP +nsScreenManagerGonk::ScreenForRect(PRInt32 inLeft, + PRInt32 inTop, + PRInt32 inWidth, + PRInt32 inHeight, + nsIScreen **outScreen) +{ + return GetPrimaryScreen(outScreen); +} + +NS_IMETHODIMP +nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) +{ + return GetPrimaryScreen(outScreen); +} + +NS_IMETHODIMP +nsScreenManagerGonk::GetNumberOfScreens(PRUint32 *aNumberOfScreens) +{ + *aNumberOfScreens = 1; + return NS_OK; +} + diff --git a/widget/src/gonk/nsScreenManagerGonk.h b/widget/src/gonk/nsScreenManagerGonk.h new file mode 100644 index 000000000000..cb6d2a61037e --- /dev/null +++ b/widget/src/gonk/nsScreenManagerGonk.h @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsScreenManagerGonk_h___ +#define nsScreenManagerGonk_h___ + +#include "nsCOMPtr.h" + +#include "nsIScreenManager.h" +#include "nsIScreen.h" +#include "WidgetUtils.h" + +class nsScreenGonk : public nsIScreen +{ +public: + nsScreenGonk(void *nativeScreen); + ~nsScreenGonk(); + + NS_DECL_ISUPPORTS + NS_DECL_NSISCREEN +}; + +class nsScreenManagerGonk : public nsIScreenManager +{ +public: + nsScreenManagerGonk(); + ~nsScreenManagerGonk(); + + NS_DECL_ISUPPORTS + NS_DECL_NSISCREENMANAGER + +protected: + nsCOMPtr mOneScreen; +}; + +#endif /* nsScreenManagerGonk_h___ */ diff --git a/widget/src/gonk/nsWidgetFactory.cpp b/widget/src/gonk/nsWidgetFactory.cpp new file mode 100644 index 000000000000..38d1ec3ddf92 --- /dev/null +++ b/widget/src/gonk/nsWidgetFactory.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2009-2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "mozilla/ModuleUtils.h" + +#include "nsCOMPtr.h" +#include "nsWidgetsCID.h" +#include "nsAppShell.h" + +#include "nsWindow.h" +#include "nsLookAndFeel.h" +#include "nsAppShellSingleton.h" +#include "nsScreenManagerGonk.h" + +#include "nsHTMLFormatConverter.h" +#include "nsXULAppAPI.h" + +NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerGonk) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) + +NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); +NS_DEFINE_NAMED_CID(NS_WINDOW_CID); +NS_DEFINE_NAMED_CID(NS_CHILD_CID); +NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); +NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID); + +static const mozilla::Module::CIDEntry kWidgetCIDs[] = { + { &kNS_WINDOW_CID, false, NULL, nsWindowConstructor }, + { &kNS_CHILD_CID, false, NULL, nsWindowConstructor }, + { &kNS_APPSHELL_CID, false, NULL, nsAppShellConstructor }, + { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerGonkConstructor }, + { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor }, + { NULL } +}; + +static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { + { "@mozilla.org/widgets/window/gonk;1", &kNS_WINDOW_CID }, + { "@mozilla.org/widgets/child_window/gonk;1", &kNS_CHILD_CID }, + { "@mozilla.org/widget/appshell/gonk;1", &kNS_APPSHELL_CID }, + { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID }, + { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID }, + { NULL } +}; + +static void +nsWidgetGonkModuleDtor() +{ + nsLookAndFeel::Shutdown(); + nsAppShellShutdown(); +} + +static const mozilla::Module kWidgetModule = { + mozilla::Module::kVersion, + kWidgetCIDs, + kWidgetContracts, + NULL, + NULL, + nsAppShellInit, + nsWidgetGonkModuleDtor +}; + +NSMODULE_DEFN(nsWidgetGonkModule) = &kWidgetModule; diff --git a/widget/src/gonk/nsWindow.cpp b/widget/src/gonk/nsWindow.cpp new file mode 100644 index 000000000000..72be2b518038 --- /dev/null +++ b/widget/src/gonk/nsWindow.cpp @@ -0,0 +1,359 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Gonk. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsAutoPtr.h" +#include "nsAppShell.h" +#include "nsTArray.h" +#include "nsWindow.h" + +#include +#include +#include "ui/FramebufferNativeWindow.h" + +#include "LayerManagerOGL.h" +#include "GLContextProvider.h" + +#include "android/log.h" + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) + +#define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) + +using namespace mozilla::gl; +using namespace mozilla::layers; + +nsIntRect gScreenBounds; + +static nsRefPtr sGLContext; +static nsTArray sTopWindows; +static nsWindow *gWindowToRedraw = nsnull; +static nsWindow *gFocusedWindow = nsnull; +static android::FramebufferNativeWindow *gNativeWindow = nsnull; + +nsWindow::nsWindow() +{ + if (!sGLContext) { + gNativeWindow = new android::FramebufferNativeWindow(); + sGLContext = GLContextProvider::CreateForWindow(this); + // CreateForWindow sets up gScreenBounds + } +} + +nsWindow::~nsWindow() +{ +} + +void +nsWindow::DoDraw(void) +{ + if (!gWindowToRedraw) + return; + + nsPaintEvent event(true, NS_PAINT, gWindowToRedraw); + event.region = gScreenBounds; + static_cast(gWindowToRedraw->GetLayerManager(nsnull))-> + SetClippingRegion(nsIntRegion(gScreenBounds)); + gWindowToRedraw->mEventCallback(&event); +} + +nsEventStatus +nsWindow::DispatchInputEvent(nsGUIEvent &aEvent) +{ + if (!gFocusedWindow) + return nsEventStatus_eIgnore; + + aEvent.widget = gFocusedWindow; + return gFocusedWindow->mEventCallback(&aEvent); +} + +NS_IMETHODIMP +nsWindow::Create(nsIWidget *aParent, + void *aNativeParent, + const nsIntRect &aRect, + EVENT_CALLBACK aHandleEventFunction, + nsDeviceContext *aContext, + nsWidgetInitData *aInitData) +{ + BaseCreate(aParent, IS_TOPLEVEL() ? gScreenBounds : aRect, + aHandleEventFunction, aContext, aInitData); + + mBounds = aRect; + + nsWindow *parent = (nsWindow *)aNativeParent; + mParent = parent; + + if (!aNativeParent) { + mBounds = gScreenBounds; + } + + if (!IS_TOPLEVEL()) + return NS_OK; + + sTopWindows.AppendElement(this); + + Resize(0, 0, gScreenBounds.width, gScreenBounds.height, false); + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::Destroy(void) +{ + sTopWindows.RemoveElement(this); + if (this == gWindowToRedraw) + gWindowToRedraw = nsnull; + if (this == gFocusedWindow) + gFocusedWindow = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::Show(bool aState) +{ + if (!IS_TOPLEVEL()) + return NS_OK; + + if (aState) + BringToTop(); + else + mVisible = false; + + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::IsVisible(bool & aState) +{ + aState = mVisible; + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::ConstrainPosition(bool aAllowSlop, + PRInt32 *aX, + PRInt32 *aY) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::Move(PRInt32 aX, + PRInt32 aY) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::Resize(PRInt32 aWidth, + PRInt32 aHeight, + bool aRepaint) +{ + return Resize(0, 0, aWidth, aHeight, aRepaint); +} + +NS_IMETHODIMP +nsWindow::Resize(PRInt32 aX, + PRInt32 aY, + PRInt32 aWidth, + PRInt32 aHeight, + bool aRepaint) +{ + nsSizeEvent event(true, NS_SIZE, this); + event.time = PR_Now() / 1000; + + nsIntRect rect(aX, aY, aWidth, aHeight); + event.windowSize = ▭ + event.mWinWidth = gScreenBounds.width; + event.mWinHeight = gScreenBounds.height; + + (*mEventCallback)(&event); + + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::Enable(bool aState) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::IsEnabled(bool *aState) +{ + *aState = true; + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::SetFocus(bool aRaise) +{ + if (aRaise) + BringToTop(); + + gFocusedWindow = this; + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::ConfigureChildren(const nsTArray&) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::Invalidate(const nsIntRect &aRect, + bool aIsSynchronous) +{ + gWindowToRedraw = this; + gDrawRequest = true; + mozilla::NotifyEvent(); + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::Update() +{ + Invalidate(gScreenBounds, false); + return NS_OK; +} + +nsIntPoint +nsWindow::WidgetToScreenOffset() +{ + nsIntPoint p(0, 0); + nsWindow *w = this; + + while (w && w->mParent) { + p.x += w->mBounds.x; + p.y += w->mBounds.y; + + w = w->mParent; + } + + return p; +} + +void* +nsWindow::GetNativeData(PRUint32 aDataType) +{ + switch (aDataType) { + case NS_NATIVE_WINDOW: + return gNativeWindow; + case NS_NATIVE_WIDGET: + return this; + } + return nsnull; +} + +NS_IMETHODIMP +nsWindow::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) +{ + return NS_OK; +} + +float +nsWindow::GetDPI() +{ + return gNativeWindow->xdpi; +} + +LayerManager * +nsWindow::GetLayerManager(PLayersChild* aShadowManager, + LayersBackend aBackendHint, + LayerManagerPersistence aPersistence, + bool* aAllowRetaining) +{ + if (aAllowRetaining) + *aAllowRetaining = true; + if (mLayerManager) + return mLayerManager; + + nsWindow *topWindow = sTopWindows[0]; + + if (!topWindow) { + LOG(" -- no topwindow\n"); + return nsnull; + } + + if (!sGLContext) { + LOG(" -- no GLContext\n"); + return nsnull; + } + + nsRefPtr layerManager = + new LayerManagerOGL(this); + + if (layerManager->Initialize(sGLContext)) + mLayerManager = layerManager; + else + LOG("Could not create LayerManager"); + + return mLayerManager; +} + +gfxASurface * +nsWindow::GetThebesSurface() +{ + /* This is really a dummy surface; this is only used when doing reflow, because + * we need a RenderingContext to measure text against. + */ + + // XXX this really wants to return already_AddRefed, but this only really gets used + // on direct assignment to a gfxASurface + return new gfxImageSurface(gfxIntSize(5,5), gfxImageSurface::ImageFormatRGB24); +} + +void +nsWindow::BringToTop() +{ + if (!sTopWindows.IsEmpty()) { + nsGUIEvent event(true, NS_DEACTIVATE, sTopWindows[0]); + (*mEventCallback)(&event); + } + + sTopWindows.RemoveElement(this); + sTopWindows.InsertElementAt(0, this); + + nsGUIEvent event(true, NS_ACTIVATE, this); + (*mEventCallback)(&event); +} + diff --git a/widget/src/gonk/nsWindow.h b/widget/src/gonk/nsWindow.h new file mode 100644 index 000000000000..a43be5b1e29b --- /dev/null +++ b/widget/src/gonk/nsWindow.h @@ -0,0 +1,128 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Gonk. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsWindow_h +#define nsWindow_h + +#include "nsBaseWidget.h" + +extern nsIntRect gScreenBounds; + +namespace mozilla { +namespace gl { +class GLContext; +} +namespace layers { +class LayersManager; +} +} + +namespace android { +class FramebufferNativeWindow; +} + +class nsWindow : public nsBaseWidget +{ +public: + nsWindow(); + virtual ~nsWindow(); + + static void DoDraw(void); + static nsEventStatus DispatchInputEvent(nsGUIEvent &aEvent); + + NS_IMETHOD Create(nsIWidget *aParent, + void *aNativeParent, + const nsIntRect &aRect, + EVENT_CALLBACK aHandleEventFunction, + nsDeviceContext *aContext, + nsWidgetInitData *aInitData); + NS_IMETHOD Destroy(void); + + NS_IMETHOD Show(bool aState); + NS_IMETHOD IsVisible(bool & aState); + NS_IMETHOD ConstrainPosition(bool aAllowSlop, + PRInt32 *aX, + PRInt32 *aY); + NS_IMETHOD Move(PRInt32 aX, + PRInt32 aY); + NS_IMETHOD Resize(PRInt32 aWidth, + PRInt32 aHeight, + bool aRepaint); + NS_IMETHOD Resize(PRInt32 aX, + PRInt32 aY, + PRInt32 aWidth, + PRInt32 aHeight, + bool aRepaint); + NS_IMETHOD Enable(bool aState); + NS_IMETHOD IsEnabled(bool *aState); + NS_IMETHOD SetFocus(bool aRaise = false); + NS_IMETHOD ConfigureChildren(const nsTArray&); + NS_IMETHOD Invalidate(const nsIntRect &aRect, + bool aIsSynchronous); + NS_IMETHOD Update(); + virtual void* GetNativeData(PRUint32 aDataType); + NS_IMETHOD SetTitle(const nsAString& aTitle) + { + return NS_OK; + } + virtual nsIntPoint WidgetToScreenOffset(); + NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus); + NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, + nsIMenuRollup *aMenuRollup, + bool aDoCapture, + bool aConsumeRollupEvent) + { + return NS_ERROR_NOT_IMPLEMENTED; + } + NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); + + virtual float GetDPI(); + virtual mozilla::layers::LayerManager* + GetLayerManager(PLayersChild* aShadowManager = nsnull, + LayersBackend aBackendHint = LayerManager::LAYERS_NONE, + LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, + bool* aAllowRetaining = nsnull); + gfxASurface* GetThebesSurface(); + +protected: + nsWindow* mParent; + bool mVisible; + + void BringToTop(); +}; + +#endif /* nsWindow_h */ diff --git a/widget/src/xpwidgets/Makefile.in b/widget/src/xpwidgets/Makefile.in index 5612a0133d10..95a2312ee578 100644 --- a/widget/src/xpwidgets/Makefile.in +++ b/widget/src/xpwidgets/Makefile.in @@ -82,7 +82,7 @@ ifneq (,$(filter os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) CPPSRCS += nsBaseClipboard.cpp endif -ifneq (,$(filter qt gtk2 os2 cocoa windows android,$(MOZ_WIDGET_TOOLKIT))) +ifneq (,$(filter qt gtk2 os2 cocoa windows android gonk,$(MOZ_WIDGET_TOOLKIT))) CPPSRCS += nsBaseFilePicker.cpp endif diff --git a/xpcom/base/nsSystemInfo.cpp b/xpcom/base/nsSystemInfo.cpp index 7dedf9d6dc88..51d455c8e05e 100644 --- a/xpcom/base/nsSystemInfo.cpp +++ b/xpcom/base/nsSystemInfo.cpp @@ -49,7 +49,7 @@ #include #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #endif @@ -174,7 +174,7 @@ nsSystemInfo::Init() } #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID if (mozilla::AndroidBridge::Bridge()) { nsAutoString str; if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", str)) diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp index 4d6464cc9abe..7cb46f8b576f 100644 --- a/xpcom/components/ManifestParser.cpp +++ b/xpcom/components/ManifestParser.cpp @@ -52,7 +52,7 @@ #include #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #endif @@ -502,7 +502,7 @@ ParseManifestCommon(NSLocationType aType, nsILocalFile* aFile, nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), gtk_major_version, gtk_minor_version); -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) if (mozilla::AndroidBridge::Bridge()) { mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion); } diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp index 8554f23392bc..9f51762b6410 100644 --- a/xpcom/io/nsLocalFileUnix.cpp +++ b/xpcom/io/nsLocalFileUnix.cpp @@ -113,7 +113,7 @@ static nsresult MacErrorMapper(OSErr inErr); #include #endif -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" #include "nsIMIMEService.h" #include @@ -1885,7 +1885,7 @@ nsLocalFile::Launch() } return NS_ERROR_FAILURE; -#elif defined(ANDROID) +#elif defined(MOZ_WIDGET_ANDROID) // Try to get a mimetype, if this fails just use the file uri alone nsresult rv; nsCAutoString type; From 35c1f21300769adbd3e9657590ccd631d6df860c Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 10 Nov 2011 17:01:40 -0800 Subject: [PATCH 21/38] Bug 701563: Break out webapps sqlite overhead from sqlite_other* r=mak --- storage/src/TelemetryVFS.cpp | 1 + toolkit/components/telemetry/TelemetryHistograms.h | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/storage/src/TelemetryVFS.cpp b/storage/src/TelemetryVFS.cpp index 6bbec8183104..3d74dea45d28 100644 --- a/storage/src/TelemetryVFS.cpp +++ b/storage/src/TelemetryVFS.cpp @@ -69,6 +69,7 @@ Histograms gHistograms[] = { SQLITE_TELEMETRY("places.sqlite", PLACES), SQLITE_TELEMETRY("urlclassifier3.sqlite", URLCLASSIFIER), SQLITE_TELEMETRY("cookies.sqlite", COOKIES), + SQLITE_TELEMETRY("webappsstore.sqlite", WEBAPPS), SQLITE_TELEMETRY(NULL, OTHER) }; #undef SQLITE_TELEMETRY diff --git a/toolkit/components/telemetry/TelemetryHistograms.h b/toolkit/components/telemetry/TelemetryHistograms.h index 3f636942a293..5bfce5b984ab 100644 --- a/toolkit/components/telemetry/TelemetryHistograms.h +++ b/toolkit/components/telemetry/TelemetryHistograms.h @@ -184,7 +184,8 @@ HISTOGRAM(CHECK_JAVA_ENABLED, 1, 3000, 10, EXPONENTIAL, "Time spent checking if SQLITE_TIME_SPENT(OTHER_ ## NAME, DESC) \ SQLITE_TIME_SPENT(PLACES_ ## NAME, DESC) \ SQLITE_TIME_SPENT(COOKIES_ ## NAME, DESC) \ - SQLITE_TIME_SPENT(URLCLASSIFIER_ ## NAME, DESC) + SQLITE_TIME_SPENT(URLCLASSIFIER_ ## NAME, DESC) \ + SQLITE_TIME_SPENT(WEBAPPS_ ## NAME, DESC) SQLITE_TIME_SPENT(OPEN, "Time spent on SQLite open() (ms)") SQLITE_TIME_SPENT(TRUNCATE, "Time spent on SQLite truncate() (ms)") @@ -197,9 +198,11 @@ HISTOGRAM(MOZ_SQLITE_OTHER_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)") HISTOGRAM(MOZ_SQLITE_PLACES_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)") HISTOGRAM(MOZ_SQLITE_COOKIES_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)") HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)") +HISTOGRAM(MOZ_SQLITE_WEBAPPS_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)") HISTOGRAM(MOZ_SQLITE_PLACES_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)") HISTOGRAM(MOZ_SQLITE_COOKIES_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)") HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)") +HISTOGRAM(MOZ_SQLITE_WEBAPPS_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)") HISTOGRAM(MOZ_SQLITE_OTHER_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)") HISTOGRAM(MOZ_STORAGE_ASYNC_REQUESTS_MS, 1, 32768, 20, EXPONENTIAL, "mozStorage async requests completion (ms)") HISTOGRAM(MOZ_STORAGE_ASYNC_REQUESTS_SUCCESS, 0, 1, 2, BOOLEAN, "mozStorage async requests success") From ceadc5997ee34fded2bf3893497852eb52c9ce6f Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Thu, 10 Nov 2011 17:19:18 -0800 Subject: [PATCH 22/38] Bug 700915: Back out diagnostic changeset fe41fa77e51a. --- js/src/methodjit/Compiler.cpp | 28 +++++++++------------------- js/src/methodjit/Compiler.h | 1 - 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 86ba7445ab5c..198c0cbd00ab 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -6917,36 +6917,27 @@ mjit::Compiler::jsop_newinit() return true; } -bool -mjit::Compiler::jsop_regexp_stub(RegExpObject *reobj) -{ - prepareStubCall(Uses(0)); - masm.move(ImmPtr(reobj), Registers::ArgReg1); - INLINE_STUBCALL(stubs::RegExp, REJOIN_FALLTHROUGH); - frame.pushSynced(JSVAL_TYPE_OBJECT); - return true; -} - bool mjit::Compiler::jsop_regexp() { JSObject *obj = script->getRegExp(fullAtomIndex(PC)); - RegExpObject *reobj = obj->asRegExp(); + RegExpStatics *res = globalObj ? globalObj->getRegExpStatics() : NULL; - return jsop_regexp_stub(reobj); - - // FIXME diagnostic bug 700915. -#if 0 if (!globalObj || - reobj->getGlobal() != globalObj || + obj->getGlobal() != globalObj || !cx->typeInferenceEnabled() || analysis->localsAliasStack() || types::TypeSet::HasObjectFlags(cx, globalObj->getType(cx), types::OBJECT_FLAG_REGEXP_FLAGS_SET)) { - return jsop_regexp_stub(reobj); + prepareStubCall(Uses(0)); + masm.move(ImmPtr(obj), Registers::ArgReg1); + INLINE_STUBCALL(stubs::RegExp, REJOIN_FALLTHROUGH); + frame.pushSynced(JSVAL_TYPE_OBJECT); + return true; } - RegExpStatics *res = globalObj ? globalObj->getRegExpStatics() : NULL; + RegExpObject *reobj = obj->asRegExp(); + DebugOnly origFlags = reobj->getFlags(); DebugOnly staticsFlags = res->getFlags(); JS_ASSERT((origFlags & staticsFlags) == staticsFlags); @@ -7015,7 +7006,6 @@ mjit::Compiler::jsop_regexp() stubcc.rejoin(Changes(1)); return true; -#endif } bool diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 00d2f13e1950..793a586fa21b 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -707,7 +707,6 @@ private: bool jsop_arginc(JSOp op, uint32 slot); bool jsop_localinc(JSOp op, uint32 slot); bool jsop_newinit(); - bool jsop_regexp_stub(RegExpObject *reobj); bool jsop_regexp(); void jsop_initmethod(); void jsop_initprop(); From 4a977d624153fedc4f5e533ab9816daf8826dbf9 Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Thu, 10 Nov 2011 17:30:01 -0800 Subject: [PATCH 23/38] Bug 701332: Defensive refcount on string split. (r=Waldo) --- js/src/jsstr.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index e8b28d0c1395..5c53d891b376 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2486,13 +2486,14 @@ js::str_split(JSContext *cx, uintN argc, Value *vp) } /* Step 8. */ - RegExpPrivate *re = NULL; + AutoRefCount rep(cx); JSLinearString *sepstr = NULL; bool sepUndefined = (argc == 0 || vp[2].isUndefined()); if (!sepUndefined) { if (ValueIsRegExp(vp[2])) { - re = vp[2].toObject().asRegExp()->getOrCreatePrivate(cx); - if (!re) + RegExpObject *reobj = vp[2].toObject().asRegExp(); + rep.reset(NeedsIncRef(reobj->getOrCreatePrivate(cx))); + if (!rep) return false; } else { JSString *sep = js_ValueToString(cx, vp[2]); @@ -2532,8 +2533,9 @@ js::str_split(JSContext *cx, uintN argc, Value *vp) /* Steps 11-15. */ JSObject *aobj; - if (re) { - aobj = SplitHelper(cx, strlin, limit, SplitRegExpMatcher(re, cx->regExpStatics()), type); + if (rep) { + aobj = SplitHelper(cx, strlin, limit, + SplitRegExpMatcher(rep.get(), cx->regExpStatics()), type); } else { // NB: sepstr is anchored through its storage in vp[2]. aobj = SplitHelper(cx, strlin, limit, SplitStringMatcher(sepstr), type); From 7e995711d7e0ec65256264578ad22bc0f437c803 Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Thu, 10 Nov 2011 17:30:04 -0800 Subject: [PATCH 24/38] Bug 701332: Don't expose RegExp privates. (r=Waldo) --- js/src/builtin/RegExp.cpp | 23 ++++----- js/src/builtin/RegExp.h | 2 +- js/src/jsprvtd.h | 11 ++++- js/src/jsstr.cpp | 70 +++++++++++++-------------- js/src/methodjit/Compiler.cpp | 11 +++-- js/src/vm/MatchPairs.h | 2 +- js/src/vm/RegExpObject-inl.h | 44 +++++++++++++---- js/src/vm/RegExpObject.cpp | 2 + js/src/vm/RegExpObject.h | 90 +++++++++++++++++++++++++++++++---- 9 files changed, 176 insertions(+), 79 deletions(-) diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index 6ccc1aa030bf..f23bbf06737a 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -159,11 +159,11 @@ ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, T *re, JSLinearString *inpu } bool -js::ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpPrivate *rep, JSLinearString *input, +js::ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher *matcher, JSLinearString *input, const jschar *chars, size_t length, size_t *lastIndex, RegExpExecType type, Value *rval) { - return ExecuteRegExpImpl(cx, res, rep, input, chars, length, lastIndex, type, rval); + return ExecuteRegExpImpl(cx, res, matcher, input, chars, length, lastIndex, type, rval); } bool @@ -278,7 +278,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, if (!escapedSourceStr) return false; - if (!RegExpPrivateCode::checkSyntax(cx, NULL, escapedSourceStr)) + if (!CheckRegExpSyntax(cx, escapedSourceStr)) return false; RegExpStatics *res = cx->regExpStatics(); @@ -515,15 +515,10 @@ ExecuteRegExp(JSContext *cx, Native native, uintN argc, Value *vp) return ok; RegExpObject *reobj = obj->asRegExp(); - RegExpPrivate *rep = reobj->getOrCreatePrivate(cx); - if (!rep) - return true; - /* - * Code execution under this call could swap out the guts of |reobj|, so we - * have to take a defensive refcount here. - */ - AutoRefCount arc(cx, NeedsIncRef(rep)); + RegExpMatcher matcher(cx); + if (!matcher.reset(reobj)) + return false; RegExpStatics *res = cx->regExpStatics(); @@ -548,7 +543,7 @@ ExecuteRegExp(JSContext *cx, Native native, uintN argc, Value *vp) return false; /* Steps 6-7 (with sticky extension). */ - if (!rep->global() && !rep->sticky()) + if (!matcher.global() && !matcher.sticky()) i = 0; /* Step 9a. */ @@ -561,13 +556,13 @@ ExecuteRegExp(JSContext *cx, Native native, uintN argc, Value *vp) /* Steps 8-21. */ RegExpExecType execType = (native == regexp_test) ? RegExpTest : RegExpExec; size_t lastIndexInt(i); - if (!ExecuteRegExp(cx, res, rep, linearInput, chars, length, &lastIndexInt, execType, + if (!ExecuteRegExp(cx, res, &matcher, linearInput, chars, length, &lastIndexInt, execType, &args.rval())) { return false; } /* Step 11 (with sticky extension). */ - if (rep->global() || (!args.rval().isNull() && rep->sticky())) { + if (matcher.global() || (!args.rval().isNull() && matcher.sticky())) { if (args.rval().isNull()) reobj->zeroLastIndex(); else diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h index eca17b112efc..936ca4a8d583 100644 --- a/js/src/builtin/RegExp.h +++ b/js/src/builtin/RegExp.h @@ -64,7 +64,7 @@ ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpObject *reobj, JSLinearSt size_t *lastIndex, RegExpExecType type, Value *rval); bool -ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpPrivate *rep, JSLinearString *input, +ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher *matcher, JSLinearString *input, const jschar *chars, size_t length, size_t *lastIndex, RegExpExecType type, Value *rval); diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 3dde9503cdba..2c6c29f7674e 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -122,11 +122,18 @@ struct FlatClosureData; struct Class; class RegExpObject; -class RegExpPrivate; +class RegExpMatcher; class RegExpObjectBuilder; class RegExpStatics; class MatchPairs; +namespace detail { + +class RegExpPrivate; +class RegExpPrivateCode; + +} /* namespace detail */ + enum RegExpFlag { IgnoreCaseFlag = 0x01, @@ -232,7 +239,7 @@ typedef HashMap, Run class Debugger; class WatchpointMap; -typedef HashMap, RuntimeAllocPolicy> +typedef HashMap, RuntimeAllocPolicy> RegExpPrivateCache; typedef JSNative Native; diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 5c53d891b376..7b48a9f0925a 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1271,38 +1271,33 @@ class FlatMatch */ class RegExpPair { - JSContext *cx; - AutoRefCount rep_; - RegExpObject *reobj_; + JSContext *cx; + mutable RegExpMatcher matcher_; + RegExpObject *reobj_; - explicit RegExpPair(RegExpPair &); - void operator=(const RegExpPair &); + explicit RegExpPair(RegExpPair &) MOZ_DELETE; + void operator=(const RegExpPair &) MOZ_DELETE; public: - explicit RegExpPair(JSContext *cx) : cx(cx), rep_(cx) {} + explicit RegExpPair(JSContext *cx) : cx(cx), matcher_(cx) {} - bool resetWithObject(JSContext *cx, RegExpObject *reobj) { - JS_ASSERT(cx == this->cx); + bool reset(RegExpObject *reobj) { reobj_ = reobj; - RegExpPrivate *rep = reobj_->asRegExp()->getOrCreatePrivate(cx); - if (!rep) - return false; - rep_.reset(NeedsIncRef(rep)); - return true; + return matcher_.reset(reobj); } - void resetWithPrivate(AlreadyIncRefed rep) { + bool reset(JSLinearString *patstr, JSString *opt) { reobj_ = NULL; - rep_.reset(rep); + return matcher_.reset(patstr, opt); } - bool null() const { return rep_.null(); } + bool null() const { return matcher_.null(); } RegExpObject *reobj() const { return reobj_; } - RegExpPrivate *getPrivate() const { + RegExpMatcher *getMatcher() const { JS_ASSERT(!null()); - return rep_.get(); + return &matcher_; } }; @@ -1356,7 +1351,8 @@ class RegExpGuard init(uintN argc, Value *vp, bool convertVoid = false) { if (argc != 0 && ValueIsRegExp(vp[2])) { - rep.resetWithObject(cx, vp[2].toObject().asRegExp()); + if (!rep.reset(vp[2].toObject().asRegExp())) + return false; } else { if (convertVoid && (argc == 0 || vp[2].isUndefined())) { fm.patstr = cx->runtime->emptyString; @@ -1440,10 +1436,9 @@ class RegExpGuard } JS_ASSERT(patstr); - AlreadyIncRefed re = RegExpPrivate::create(cx, patstr, opt, NULL); - if (!re) + if (!rep.reset(patstr, opt)) return NULL; - rep.resetWithPrivate(re); + return &rep; } @@ -1480,21 +1475,21 @@ static bool DoMatch(JSContext *cx, RegExpStatics *res, JSString *str, const RegExpPair ®ExpPair, DoMatchCallback callback, void *data, MatchControlFlags flags, Value *rval) { - RegExpPrivate *rep = regExpPair.getPrivate(); + RegExpMatcher *matcher = regExpPair.getMatcher(); JSLinearString *linearStr = str->ensureLinear(cx); if (!linearStr) return false; const jschar *chars = linearStr->chars(); size_t length = linearStr->length(); - if (rep->global()) { + if (matcher->global()) { /* global matching ('g') */ RegExpExecType type = (flags & TEST_GLOBAL_BIT) ? RegExpTest : RegExpExec; if (RegExpObject *reobj = regExpPair.reobj()) reobj->zeroLastIndex(); for (size_t count = 0, i = 0, length = str->length(); i <= length; ++count) { - if (!ExecuteRegExp(cx, res, rep, linearStr, chars, length, &i, type, rval)) + if (!ExecuteRegExp(cx, res, matcher, linearStr, chars, length, &i, type, rval)) return false; if (!Matched(type, *rval)) break; @@ -1508,7 +1503,7 @@ DoMatch(JSContext *cx, RegExpStatics *res, JSString *str, const RegExpPair ®E RegExpExecType type = (flags & TEST_SINGLE_BIT) ? RegExpTest : RegExpExec; bool callbackOnSingle = !!(flags & CALLBACK_ON_SINGLE_BIT); size_t i = 0; - if (!ExecuteRegExp(cx, res, rep, linearStr, chars, length, &i, type, rval)) + if (!ExecuteRegExp(cx, res, matcher, linearStr, chars, length, &i, type, rval)) return false; if (callbackOnSingle && Matched(type, *rval) && !callback(cx, res, 0, data)) return false; @@ -1583,7 +1578,7 @@ js::str_match(JSContext *cx, uintN argc, Value *vp) if (!DoMatch(cx, res, str, *rep, MatchCallback, arg, MATCH_ARGS, &rval)) return false; - if (rep->getPrivate()->global()) + if (rep->getMatcher()->global()) vp->setObjectOrNull(array.object()); else *vp = rval; @@ -1619,7 +1614,7 @@ js::str_search(JSContext *cx, uintN argc, Value *vp) RegExpStatics *res = cx->regExpStatics(); /* Per ECMAv5 15.5.4.12 (5) The last index property is ignored and left unchanged. */ size_t i = 0; - if (!ExecuteRegExp(cx, res, rep->getPrivate(), linearStr, chars, length, &i, RegExpTest, vp)) + if (!ExecuteRegExp(cx, res, rep->getMatcher(), linearStr, chars, length, &i, RegExpTest, vp)) return false; if (vp->isTrue()) @@ -2407,11 +2402,11 @@ SplitHelper(JSContext *cx, JSLinearString *str, uint32 limit, Matcher splitMatch */ class SplitRegExpMatcher { RegExpStatics *res; - RegExpPrivate *rep; + RegExpMatcher *matcher; public: static const bool returnsCaptures = true; - SplitRegExpMatcher(RegExpPrivate *rep, RegExpStatics *res) : res(res), rep(rep) {} + SplitRegExpMatcher(RegExpMatcher *matcher, RegExpStatics *res) : res(res), matcher(matcher) {} inline bool operator()(JSContext *cx, JSLinearString *str, size_t index, SplitMatchResult *result) { @@ -2422,7 +2417,7 @@ class SplitRegExpMatcher { ; const jschar *chars = str->chars(); size_t length = str->length(); - if (!ExecuteRegExp(cx, res, rep, str, chars, length, &index, RegExpTest, &rval)) + if (!ExecuteRegExp(cx, res, matcher, str, chars, length, &index, RegExpTest, &rval)) return false; if (!rval.isTrue()) { result->setFailure(); @@ -2486,14 +2481,13 @@ js::str_split(JSContext *cx, uintN argc, Value *vp) } /* Step 8. */ - AutoRefCount rep(cx); + RegExpMatcher matcher(cx); JSLinearString *sepstr = NULL; bool sepUndefined = (argc == 0 || vp[2].isUndefined()); if (!sepUndefined) { if (ValueIsRegExp(vp[2])) { RegExpObject *reobj = vp[2].toObject().asRegExp(); - rep.reset(NeedsIncRef(reobj->getOrCreatePrivate(cx))); - if (!rep) + if (!matcher.reset(reobj)) return false; } else { JSString *sep = js_ValueToString(cx, vp[2]); @@ -2533,12 +2527,12 @@ js::str_split(JSContext *cx, uintN argc, Value *vp) /* Steps 11-15. */ JSObject *aobj; - if (rep) { - aobj = SplitHelper(cx, strlin, limit, - SplitRegExpMatcher(rep.get(), cx->regExpStatics()), type); - } else { + if (matcher.null()) { // NB: sepstr is anchored through its storage in vp[2]. aobj = SplitHelper(cx, strlin, limit, SplitStringMatcher(sepstr), type); + } else { + aobj = SplitHelper(cx, strlin, limit, + SplitRegExpMatcher(&matcher, cx->regExpStatics()), type); } if (!aobj) return false; diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 198c0cbd00ab..f322d62e2a28 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -6982,11 +6982,12 @@ mjit::Compiler::jsop_regexp() } /* - * Force creation of the RegExpPrivate in the script's RegExpObject so we take it in the - * getNewObject template copy. + * Force creation of the RegExpPrivate in the script's RegExpObject + * so that we grab it in the getNewObject template copy. Note that + * JIT code is discarded on every GC, which permits us to burn in + * the pointer to the RegExpPrivate refcount. */ - RegExpPrivate *rep = reobj->getOrCreatePrivate(cx); - if (!rep) + if (!reobj->makePrivateNow(cx)) return false; RegisterID result = frame.allocReg(); @@ -6999,7 +7000,7 @@ mjit::Compiler::jsop_regexp() OOL_STUBCALL(stubs::RegExp, REJOIN_FALLTHROUGH); /* Bump the refcount on the wrapped RegExp. */ - size_t *refcount = rep->addressOfRefCount(); + size_t *refcount = reobj->addressOfPrivateRefCount(); masm.add32(Imm32(1), AbsoluteAddress(refcount)); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, result); diff --git a/js/src/vm/MatchPairs.h b/js/src/vm/MatchPairs.h index f45ccc2cb7bd..f73ac0afa463 100644 --- a/js/src/vm/MatchPairs.h +++ b/js/src/vm/MatchPairs.h @@ -93,7 +93,7 @@ class MatchPairs int *buffer() { return buffer_; } - friend class RegExpPrivate; + friend class detail::RegExpPrivate; public: /* diff --git a/js/src/vm/RegExpObject-inl.h b/js/src/vm/RegExpObject-inl.h index 4abb0ea922e5..1f99bd32522b 100644 --- a/js/src/vm/RegExpObject-inl.h +++ b/js/src/vm/RegExpObject-inl.h @@ -89,6 +89,13 @@ HasRegExpMetaChars(const jschar *chars, size_t length) return false; } +inline size_t * +RegExpObject::addressOfPrivateRefCount() const +{ + JS_ASSERT(getPrivate()); + return getPrivate()->addressOfRefCount(); +} + inline void RegExpObject::setPrivate(RegExpPrivate *rep) { @@ -178,6 +185,16 @@ RegExpObject::init(JSContext *cx, JSLinearString *source, RegExpFlag flags) return true; } +inline bool +RegExpMatcher::reset(JSLinearString *patstr, JSString *opt) +{ + AlreadyIncRefed priv = RegExpPrivate::create(cx, patstr, opt, NULL); + if (!priv) + return false; + arc.reset(priv); + return true; +} + inline void RegExpObject::setLastIndex(const Value &v) { @@ -228,8 +245,9 @@ RegExpObject::setSticky(bool enabled) /* RegExpPrivate inlines. */ -inline AlreadyIncRefed -RegExpPrivate::create(JSContext *cx, JSLinearString *source, RegExpFlag flags, TokenStream *ts) +inline AlreadyIncRefed +detail::RegExpPrivate::create(JSContext *cx, JSLinearString *source, RegExpFlag flags, + TokenStream *ts) { typedef AlreadyIncRefed RetType; @@ -284,7 +302,7 @@ RegExpPrivate::create(JSContext *cx, JSLinearString *source, RegExpFlag flags, T /* This function should be deleted once bad Android platforms phase out. See bug 604774. */ inline bool -RegExpPrivateCode::isJITRuntimeEnabled(JSContext *cx) +detail::RegExpPrivateCode::isJITRuntimeEnabled(JSContext *cx) { #if defined(ANDROID) && defined(JS_TRACER) && defined(JS_METHODJIT) return cx->traceJitEnabled || cx->methodJitEnabled; @@ -294,8 +312,8 @@ RegExpPrivateCode::isJITRuntimeEnabled(JSContext *cx) } inline bool -RegExpPrivateCode::compile(JSContext *cx, JSLinearString &pattern, TokenStream *ts, - uintN *parenCount, RegExpFlag flags) +detail::RegExpPrivateCode::compile(JSContext *cx, JSLinearString &pattern, TokenStream *ts, + uintN *parenCount, RegExpFlag flags) { #if ENABLE_YARR_JIT /* Parse the pattern. */ @@ -344,7 +362,7 @@ RegExpPrivateCode::compile(JSContext *cx, JSLinearString &pattern, TokenStream * } inline bool -RegExpPrivate::compile(JSContext *cx, TokenStream *ts) +detail::RegExpPrivate::compile(JSContext *cx, TokenStream *ts) { if (!sticky()) return code.compile(cx, *source, ts, &parenCount, getFlags()); @@ -371,8 +389,8 @@ RegExpPrivate::compile(JSContext *cx, TokenStream *ts) } inline RegExpRunStatus -RegExpPrivateCode::execute(JSContext *cx, const jschar *chars, size_t length, size_t start, - int *output, size_t outputCount) +detail::RegExpPrivateCode::execute(JSContext *cx, const jschar *chars, size_t length, size_t start, + int *output, size_t outputCount) { int result; #if ENABLE_YARR_JIT @@ -400,13 +418,13 @@ RegExpPrivateCode::execute(JSContext *cx, const jschar *chars, size_t length, si } inline void -RegExpPrivate::incref(JSContext *cx) +detail::RegExpPrivate::incref(JSContext *cx) { ++refCount; } inline void -RegExpPrivate::decref(JSContext *cx) +detail::RegExpPrivate::decref(JSContext *cx) { #ifdef JS_THREADSAFE JS_OPT_ASSERT_IF(cx->runtime->gcHelperThread.getThread(), @@ -423,7 +441,13 @@ RegExpPrivate::decref(JSContext *cx) cache->remove(ptr); } +#ifdef DEBUG + this->~RegExpPrivate(); + memset(this, 0xcd, sizeof(*this)); + cx->free_(this); +#else cx->delete_(this); +#endif } } /* namespace js */ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index d8cf59ec60e8..2802ab5bb904 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -54,6 +54,8 @@ using namespace nanojit; #endif using namespace js; +using js::detail::RegExpPrivate; +using js::detail::RegExpPrivateCode; JS_STATIC_ASSERT(IgnoreCaseFlag == JSREG_FOLD); JS_STATIC_ASSERT(GlobalFlag == JSREG_GLOB); diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index 403d5bf0022a..8a711b6a5f69 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -65,6 +65,9 @@ enum RegExpRunStatus class RegExpObject : public ::JSObject { + typedef detail::RegExpPrivate RegExpPrivate; + typedef detail::RegExpPrivateCode RegExpPrivateCode; + static const uintN LAST_INDEX_SLOT = 0; static const uintN SOURCE_SLOT = 1; static const uintN GLOBAL_FLAG_SLOT = 2; @@ -131,6 +134,10 @@ class RegExpObject : public ::JSObject return RegExpFlag(flags); } + /* JIT only. */ + + inline size_t *addressOfPrivateRefCount() const; + /* Flags. */ inline void setIgnoreCase(bool enabled); @@ -147,6 +154,20 @@ class RegExpObject : public ::JSObject /* Clear out lazy |RegExpPrivate|. */ inline void purge(JSContext *x); + /* + * Trigger an eager creation of the associated RegExpPrivate. Note + * that a GC may purge it away. + */ + bool makePrivateNow(JSContext *cx) { + return !!makePrivate(cx); + } + + private: + friend class RegExpObjectBuilder; + friend class RegExpMatcher; + + inline bool init(JSContext *cx, JSLinearString *source, RegExpFlag flags); + RegExpPrivate *getOrCreatePrivate(JSContext *cx) { if (RegExpPrivate *rep = getPrivate()) return rep; @@ -154,11 +175,6 @@ class RegExpObject : public ::JSObject return makePrivate(cx); } - private: - friend class RegExpObjectBuilder; - - inline bool init(JSContext *cx, JSLinearString *source, RegExpFlag flags); - /* The |RegExpPrivate| is lazily created at the time of use. */ RegExpPrivate *getPrivate() const { return static_cast(JSObject::getPrivate()); @@ -189,12 +205,16 @@ class RegExpObject : public ::JSObject /* Either builds a new RegExpObject or re-initializes an existing one. */ class RegExpObjectBuilder { + typedef detail::RegExpPrivate RegExpPrivate; + JSContext *cx; RegExpObject *reobj_; bool getOrCreate(); bool getOrCreateClone(RegExpObject *proto); + RegExpObject *build(AlreadyIncRefed rep); + public: RegExpObjectBuilder(JSContext *cx, RegExpObject *reobj = NULL) : cx(cx), reobj_(reobj) @@ -202,9 +222,6 @@ class RegExpObjectBuilder RegExpObject *reobj() { return reobj_; } - /* Note: In case of failure, |rep| will be decrefed. */ - RegExpObject *build(AlreadyIncRefed rep); - RegExpObject *build(JSLinearString *str, RegExpFlag flags); RegExpObject *build(RegExpObject *other); @@ -212,6 +229,8 @@ class RegExpObjectBuilder RegExpObject *clone(RegExpObject *other, RegExpObject *proto); }; +namespace detail { + /* Abstracts away the gross |RegExpPrivate| backend details. */ class RegExpPrivateCode { @@ -356,6 +375,55 @@ class RegExpPrivate bool sticky() const { return flags & StickyFlag; } }; +} /* namespace detail */ + +/* + * Wraps the RegExpObject's internals in a recount-safe interface for + * use in RegExp execution. This is used in situations where we'd like + * to avoid creating a full-fledged RegExpObject. This interface is + * provided in lieu of exposing the RegExpPrivate directly. + * + * Note: this exposes precisely the execute interface of a RegExpObject. + */ +class RegExpMatcher +{ + typedef detail::RegExpPrivate RegExpPrivate; + + JSContext *cx; + AutoRefCount arc; + + public: + explicit RegExpMatcher(JSContext *cx) + : cx(cx), arc(cx) + { } + + bool null() const { + return arc.null(); + } + bool global() const { + return arc.get()->global(); + } + bool sticky() const { + return arc.get()->sticky(); + } + + bool reset(RegExpObject *reobj) { + RegExpPrivate *priv = reobj->getOrCreatePrivate(cx); + if (!priv) + return false; + arc.reset(NeedsIncRef(priv)); + return true; + } + + inline bool reset(JSLinearString *patstr, JSString *opt); + + RegExpRunStatus execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex, + LifoAllocScope &allocScope, MatchPairs **output) { + JS_ASSERT(!arc.null()); + return arc.get()->execute(cx, chars, length, lastIndex, allocScope, output); + } +}; + /* * Parse regexp flags. Report an error and return false if an invalid * sequence of flags is encountered (repeat/invalid flag). @@ -371,6 +439,12 @@ ValueIsRegExp(const Value &v); inline bool IsRegExpMetaChar(jschar c); +inline bool +CheckRegExpSyntax(JSContext *cx, JSLinearString *str) +{ + return detail::RegExpPrivateCode::checkSyntax(cx, NULL, str); +} + } /* namespace js */ extern JS_FRIEND_API(JSObject *) JS_FASTCALL From c0fc0d8c7502d7c24c1b60371d96980775f95d39 Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Thu, 10 Nov 2011 21:04:00 -0800 Subject: [PATCH 25/38] Bug 701332: Followup fix. --- js/src/builtin/RegExp.cpp | 6 +++--- js/src/builtin/RegExp.h | 2 +- js/src/jsstr.cpp | 18 +++++++++--------- js/src/vm/RegExpObject.h | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index f23bbf06737a..d8f0e7662baf 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -159,11 +159,11 @@ ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, T *re, JSLinearString *inpu } bool -js::ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher *matcher, JSLinearString *input, +js::ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher &matcher, JSLinearString *input, const jschar *chars, size_t length, size_t *lastIndex, RegExpExecType type, Value *rval) { - return ExecuteRegExpImpl(cx, res, matcher, input, chars, length, lastIndex, type, rval); + return ExecuteRegExpImpl(cx, res, &matcher, input, chars, length, lastIndex, type, rval); } bool @@ -556,7 +556,7 @@ ExecuteRegExp(JSContext *cx, Native native, uintN argc, Value *vp) /* Steps 8-21. */ RegExpExecType execType = (native == regexp_test) ? RegExpTest : RegExpExec; size_t lastIndexInt(i); - if (!ExecuteRegExp(cx, res, &matcher, linearInput, chars, length, &lastIndexInt, execType, + if (!ExecuteRegExp(cx, res, matcher, linearInput, chars, length, &lastIndexInt, execType, &args.rval())) { return false; } diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h index 936ca4a8d583..eeccb431b207 100644 --- a/js/src/builtin/RegExp.h +++ b/js/src/builtin/RegExp.h @@ -64,7 +64,7 @@ ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpObject *reobj, JSLinearSt size_t *lastIndex, RegExpExecType type, Value *rval); bool -ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher *matcher, JSLinearString *input, +ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher &matcher, JSLinearString *input, const jschar *chars, size_t length, size_t *lastIndex, RegExpExecType type, Value *rval); diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 7b48a9f0925a..dc2cd61a71fc 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1295,9 +1295,9 @@ class RegExpPair RegExpObject *reobj() const { return reobj_; } - RegExpMatcher *getMatcher() const { + RegExpMatcher &matcher() const { JS_ASSERT(!null()); - return &matcher_; + return matcher_; } }; @@ -1475,14 +1475,14 @@ static bool DoMatch(JSContext *cx, RegExpStatics *res, JSString *str, const RegExpPair ®ExpPair, DoMatchCallback callback, void *data, MatchControlFlags flags, Value *rval) { - RegExpMatcher *matcher = regExpPair.getMatcher(); + RegExpMatcher &matcher = regExpPair.matcher(); JSLinearString *linearStr = str->ensureLinear(cx); if (!linearStr) return false; const jschar *chars = linearStr->chars(); size_t length = linearStr->length(); - if (matcher->global()) { + if (matcher.global()) { /* global matching ('g') */ RegExpExecType type = (flags & TEST_GLOBAL_BIT) ? RegExpTest : RegExpExec; if (RegExpObject *reobj = regExpPair.reobj()) @@ -1578,7 +1578,7 @@ js::str_match(JSContext *cx, uintN argc, Value *vp) if (!DoMatch(cx, res, str, *rep, MatchCallback, arg, MATCH_ARGS, &rval)) return false; - if (rep->getMatcher()->global()) + if (rep->matcher().global()) vp->setObjectOrNull(array.object()); else *vp = rval; @@ -1614,7 +1614,7 @@ js::str_search(JSContext *cx, uintN argc, Value *vp) RegExpStatics *res = cx->regExpStatics(); /* Per ECMAv5 15.5.4.12 (5) The last index property is ignored and left unchanged. */ size_t i = 0; - if (!ExecuteRegExp(cx, res, rep->getMatcher(), linearStr, chars, length, &i, RegExpTest, vp)) + if (!ExecuteRegExp(cx, res, rep->matcher(), linearStr, chars, length, &i, RegExpTest, vp)) return false; if (vp->isTrue()) @@ -2402,11 +2402,11 @@ SplitHelper(JSContext *cx, JSLinearString *str, uint32 limit, Matcher splitMatch */ class SplitRegExpMatcher { RegExpStatics *res; - RegExpMatcher *matcher; + RegExpMatcher &matcher; public: static const bool returnsCaptures = true; - SplitRegExpMatcher(RegExpMatcher *matcher, RegExpStatics *res) : res(res), matcher(matcher) {} + SplitRegExpMatcher(RegExpMatcher &matcher, RegExpStatics *res) : res(res), matcher(matcher) {} inline bool operator()(JSContext *cx, JSLinearString *str, size_t index, SplitMatchResult *result) { @@ -2532,7 +2532,7 @@ js::str_split(JSContext *cx, uintN argc, Value *vp) aobj = SplitHelper(cx, strlin, limit, SplitStringMatcher(sepstr), type); } else { aobj = SplitHelper(cx, strlin, limit, - SplitRegExpMatcher(&matcher, cx->regExpStatics()), type); + SplitRegExpMatcher(matcher, cx->regExpStatics()), type); } if (!aobj) return false; diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index 8a711b6a5f69..9057981df4ed 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -159,7 +159,7 @@ class RegExpObject : public ::JSObject * that a GC may purge it away. */ bool makePrivateNow(JSContext *cx) { - return !!makePrivate(cx); + return getPrivate() ? true : !!makePrivate(cx); } private: From 96db2277728cbd75717e045fe02a18ddd0fb8506 Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Thu, 10 Nov 2011 21:04:04 -0800 Subject: [PATCH 26/38] Bug 701387: RegExpPrivateCache can disappear after lookup. (r=Waldo) --- js/src/jscntxt.cpp | 6 +-- js/src/jsutil.h | 4 +- js/src/vm/RegExpObject-inl.h | 91 +++++++++++++++++++++++++++--------- js/src/vm/RegExpObject.h | 5 ++ 4 files changed, 78 insertions(+), 28 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 7be10ff42f4a..5a8c1e3f70ab 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -124,6 +124,8 @@ ThreadData::ThreadData() ThreadData::~ThreadData() { + JS_ASSERT(!repCache); + if (dtoaState) js_DestroyDtoaState(dtoaState); } @@ -131,6 +133,7 @@ ThreadData::~ThreadData() bool ThreadData::init() { + JS_ASSERT(!repCache); return stackSpace.init() && !!(dtoaState = js_NewDtoaState()); } @@ -172,9 +175,6 @@ ThreadData::createRegExpPrivateCache(JSRuntime *rt) void ThreadData::purgeRegExpPrivateCache(JSRuntime *rt) { - if (!repCache) - return; - rt->delete_(repCache); repCache = NULL; } diff --git a/js/src/jsutil.h b/js/src/jsutil.h index da8328198afc..856e37cd0b63 100644 --- a/js/src/jsutil.h +++ b/js/src/jsutil.h @@ -187,7 +187,7 @@ class AlreadyIncRefed RefCountable *obj; public: - explicit AlreadyIncRefed(RefCountable *obj) : obj(obj) {} + explicit AlreadyIncRefed(RefCountable *obj = NULL) : obj(obj) {} bool null() const { return obj == NULL; } operator ConvertibleToBool() const { return (ConvertibleToBool)obj; } @@ -205,7 +205,7 @@ class NeedsIncRef RefCountable *obj; public: - explicit NeedsIncRef(RefCountable *obj) : obj(obj) {} + explicit NeedsIncRef(RefCountable *obj = NULL) : obj(obj) {} bool null() const { return obj == NULL; } operator ConvertibleToBool() const { return (ConvertibleToBool)obj; } diff --git a/js/src/vm/RegExpObject-inl.h b/js/src/vm/RegExpObject-inl.h index 1f99bd32522b..157a5a8522c4 100644 --- a/js/src/vm/RegExpObject-inl.h +++ b/js/src/vm/RegExpObject-inl.h @@ -245,6 +245,65 @@ RegExpObject::setSticky(bool enabled) /* RegExpPrivate inlines. */ +inline RegExpPrivateCache * +detail::RegExpPrivate::getOrCreateCache(JSContext *cx) +{ + if (RegExpPrivateCache *cache = cx->threadData()->getOrCreateRegExpPrivateCache(cx->runtime)) + return cache; + + js_ReportOutOfMemory(cx); + return NULL; +} + +inline bool +detail::RegExpPrivate::cacheLookup(JSContext *cx, JSAtom *atom, RegExpFlag flags, + AlreadyIncRefed *result) +{ + RegExpPrivateCache *cache = getOrCreateCache(cx); + if (!cache) + return false; + + if (RegExpPrivateCache::Ptr p = cache->lookup(atom)) { + NeedsIncRef cached(p->value); + if (cached->getFlags() == flags) { + cached->incref(cx); + *result = AlreadyIncRefed(cached.get()); + return true; + } + } + + JS_ASSERT(result->null()); + return true; +} + +inline bool +detail::RegExpPrivate::cacheInsert(JSContext *cx, JSAtom *atom, RegExpPrivate *priv) +{ + JS_ASSERT(priv); + + /* + * Note: allocation performed since lookup may cause a garbage collection, + * so we have to re-lookup the cache (and inside the cache) after the + * allocation is performed. + */ + RegExpPrivateCache *cache = getOrCreateCache(cx); + if (!cache) + return false; + + if (RegExpPrivateCache::AddPtr addPtr = cache->lookupForAdd(atom)) { + /* We clobber existing entries with the same source (but different flags). */ + JS_ASSERT(addPtr->value->getFlags() != priv->getFlags()); + addPtr->value = priv; + } else { + if (!cache->add(addPtr, atom, priv)) { + js_ReportOutOfMemory(cx); + return false; + } + } + + return true; +} + inline AlreadyIncRefed detail::RegExpPrivate::create(JSContext *cx, JSLinearString *source, RegExpFlag flags, TokenStream *ts) @@ -267,35 +326,21 @@ detail::RegExpPrivate::create(JSContext *cx, JSLinearString *source, RegExpFlag * remove itself from the cache. */ - RegExpPrivateCache *cache = cx->threadData()->getOrCreateRegExpPrivateCache(cx->runtime); - if (!cache) { - js_ReportOutOfMemory(cx); - return RetType(NULL); - } + JSAtom *sourceAtom = &source->asAtom(); - RegExpPrivateCache::AddPtr addPtr = cache->lookupForAdd(&source->asAtom()); - if (addPtr) { - RegExpPrivate *cached = addPtr->value; - if (cached->getFlags() == flags) { - cached->incref(cx); - return RetType(cached); - } - } + AlreadyIncRefed cached; + if (!cacheLookup(cx, sourceAtom, flags, &cached)) + return RetType(NULL); + + if (cached) + return cached; RegExpPrivate *priv = RegExpPrivate::createUncached(cx, source, flags, ts); if (!priv) return RetType(NULL); - if (addPtr) { - /* Note: on flag mismatch, we clobber the existing entry. */ - JS_ASSERT(addPtr->key == &priv->getSource()->asAtom()); - addPtr->value = priv; - } else { - if (!cache->add(addPtr, &source->asAtom(), priv)) { - js_ReportOutOfMemory(cx); - return RetType(NULL); - } - } + if (!cacheInsert(cx, sourceAtom, priv)) + return RetType(NULL); return RetType(priv); } diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index 9057981df4ed..0d7949b8a9ba 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -342,6 +342,11 @@ class RegExpPrivate createUncached(JSContext *cx, JSLinearString *source, RegExpFlag flags, TokenStream *tokenStream); + static RegExpPrivateCache *getOrCreateCache(JSContext *cx); + static bool cacheLookup(JSContext *cx, JSAtom *atom, RegExpFlag flags, + AlreadyIncRefed *result); + static bool cacheInsert(JSContext *cx, JSAtom *atom, RegExpPrivate *priv); + public: static AlreadyIncRefed create(JSContext *cx, JSLinearString *source, RegExpFlag flags, TokenStream *ts); From 479f7dc01dcb1ec5d4888183104879da6c2dfbb7 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 9 Nov 2011 01:35:05 -0800 Subject: [PATCH 27/38] Bug 699185 - Building SpiderMonkey with clang warns up the wazoo. Disable the warning that's the primary cause of the spew, because the workarounds are gross and the issue is a purely theoretical spec deviation which no compiler implements. r=ted --HG-- extra : rebase_source : 09469e9ca787f9dcec43cb4697034d20a61b476f --- configure.in | 111 ++++++++++++++++++++++++++------------------ js/src/configure.in | 111 ++++++++++++++++++++++++++------------------ 2 files changed, 132 insertions(+), 90 deletions(-) diff --git a/configure.in b/configure.in index 89333d37dd75..05f28ba68159 100644 --- a/configure.in +++ b/configure.in @@ -1760,6 +1760,48 @@ fi # CPU_ARCH = arm AC_SUBST(HAVE_ARM_SIMD) AC_SUBST(HAVE_ARM_NEON) +dnl ================================================================= +dnl Set up and test static assertion macros used to avoid AC_TRY_RUN, +dnl which is bad when cross compiling. +dnl ================================================================= +if test "$COMPILE_ENVIRONMENT"; then +configure_static_assert_macros=' +#define CONFIGURE_STATIC_ASSERT(condition) CONFIGURE_STATIC_ASSERT_IMPL(condition, __LINE__) +#define CONFIGURE_STATIC_ASSERT_IMPL(condition, line) CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) +#define CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) typedef int static_assert_line_##line[(condition) ? 1 : -1] +' + +dnl test that the macros actually work: +AC_MSG_CHECKING(that static assertion macros used in autoconf tests work) +AC_CACHE_VAL(ac_cv_static_assertion_macros_work, + [AC_LANG_SAVE + AC_LANG_C + ac_cv_static_assertion_macros_work="yes" + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(1)], + , + ac_cv_static_assertion_macros_work="no") + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(0)], + ac_cv_static_assertion_macros_work="no", + ) + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(1)], + , + ac_cv_static_assertion_macros_work="no") + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(0)], + ac_cv_static_assertion_macros_work="no", + ) + AC_LANG_RESTORE + ]) +AC_MSG_RESULT("$ac_cv_static_assertion_macros_work") +if test "$ac_cv_static_assertion_macros_work" = "no"; then + AC_MSG_ERROR([Compiler cannot compile macros used in autoconf tests.]) +fi +fi # COMPILE_ENVIRONMENT + dnl ======================================================== dnl Android libstdc++, placed here so it can use MOZ_ARCH dnl computed above. @@ -1906,6 +1948,27 @@ if test "$GNU_CXX"; then _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-c++0x-extensions" fi + AC_CACHE_CHECK(whether the compiler supports -Wno-extended-offsetof, + ac_has_wno_extended_offsetof, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + _SAVE_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-Wno-extended-offsetof" + AC_TRY_COMPILE([$configure_static_assert_macros + #ifndef __has_warning + #define __has_warning(x) 0 + #endif], + [CONFIGURE_STATIC_ASSERT(__has_warning("-Wextended-offsetof"))], + ac_has_wno_extended_offsetof="yes", + ac_has_wno_extended_offsetof="no") + CXXFLAGS="$_SAVE_CXXFLAGS" + AC_LANG_RESTORE + ]) + if test "$ac_has_wno_extended_offsetof" = "yes"; then + _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-extended-offsetof" + fi + AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof, ac_has_wno_invalid_offsetof, [ @@ -2004,48 +2067,6 @@ LOOP_INPUT fi # GNU_CC fi # COMPILE_ENVIRONMENT -dnl ================================================================= -dnl Set up and test static assertion macros used to avoid AC_TRY_RUN, -dnl which is bad when cross compiling. -dnl ================================================================= -if test "$COMPILE_ENVIRONMENT"; then -configure_static_assert_macros=' -#define CONFIGURE_STATIC_ASSERT(condition) CONFIGURE_STATIC_ASSERT_IMPL(condition, __LINE__) -#define CONFIGURE_STATIC_ASSERT_IMPL(condition, line) CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) -#define CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) typedef int static_assert_line_##line[(condition) ? 1 : -1] -' - -dnl test that the macros actually work: -AC_MSG_CHECKING(that static assertion macros used in autoconf tests work) -AC_CACHE_VAL(ac_cv_static_assertion_macros_work, - [AC_LANG_SAVE - AC_LANG_C - ac_cv_static_assertion_macros_work="yes" - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(1)], - , - ac_cv_static_assertion_macros_work="no") - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(0)], - ac_cv_static_assertion_macros_work="no", - ) - AC_LANG_CPLUSPLUS - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(1)], - , - ac_cv_static_assertion_macros_work="no") - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(0)], - ac_cv_static_assertion_macros_work="no", - ) - AC_LANG_RESTORE - ]) -AC_MSG_RESULT("$ac_cv_static_assertion_macros_work") -if test "$ac_cv_static_assertion_macros_work" = "no"; then - AC_MSG_ERROR([Compiler cannot compile macros used in autoconf tests.]) -fi -fi # COMPILE_ENVIRONMENT - dnl ======================================================== dnl Checking for 64-bit OS dnl ======================================================== @@ -7794,7 +7815,7 @@ MOZ_ARG_DISABLE_BOOL(pedantic, _PEDANTIC= ) if test "$_PEDANTIC"; then _SAVE_CXXFLAGS=$CXXFLAGS - CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long" + CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-pedantic ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" AC_MSG_CHECKING([whether C++ compiler has -pedantic long long bug]) AC_TRY_COMPILE([$configure_static_assert_macros], [CONFIGURE_STATIC_ASSERT(sizeof(long long) == 8)], @@ -7804,8 +7825,8 @@ if test "$_PEDANTIC"; then case "$result" in no) - _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long" - _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long" + _WARNINGS_CFLAGS="${_COMPILER_PREFIX}-pedantic ${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" + _WARNINGS_CXXFLAGS="${_COMPILER_PREFIX}-pedantic ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" ;; yes) AC_MSG_ERROR([Your compiler appears to have a known bug where long long is miscompiled when using -pedantic. Reconfigure using --disable-pedantic. ]) diff --git a/js/src/configure.in b/js/src/configure.in index 0dc3fc6f105d..5471064746ce 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -1694,6 +1694,48 @@ fi # CPU_ARCH = arm AC_SUBST(HAVE_ARM_SIMD) AC_SUBST(HAVE_ARM_NEON) +dnl ================================================================= +dnl Set up and test static assertion macros used to avoid AC_TRY_RUN, +dnl which is bad when cross compiling. +dnl ================================================================= +if test "$COMPILE_ENVIRONMENT"; then +configure_static_assert_macros=' +#define CONFIGURE_STATIC_ASSERT(condition) CONFIGURE_STATIC_ASSERT_IMPL(condition, __LINE__) +#define CONFIGURE_STATIC_ASSERT_IMPL(condition, line) CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) +#define CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) typedef int static_assert_line_##line[(condition) ? 1 : -1] +' + +dnl test that the macros actually work: +AC_MSG_CHECKING(that static assertion macros used in autoconf tests work) +AC_CACHE_VAL(ac_cv_static_assertion_macros_work, + [AC_LANG_SAVE + AC_LANG_C + ac_cv_static_assertion_macros_work="yes" + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(1)], + , + ac_cv_static_assertion_macros_work="no") + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(0)], + ac_cv_static_assertion_macros_work="no", + ) + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(1)], + , + ac_cv_static_assertion_macros_work="no") + AC_TRY_COMPILE([$configure_static_assert_macros], + [CONFIGURE_STATIC_ASSERT(0)], + ac_cv_static_assertion_macros_work="no", + ) + AC_LANG_RESTORE + ]) +AC_MSG_RESULT("$ac_cv_static_assertion_macros_work") +if test "$ac_cv_static_assertion_macros_work" = "no"; then + AC_MSG_ERROR([Compiler cannot compile macros used in autoconf tests.]) +fi +fi # COMPILE_ENVIRONMENT + dnl ======================================================== dnl Android libstdc++, placed here so it can use MOZ_ARCH dnl computed above. @@ -1841,6 +1883,27 @@ if test "$GNU_CXX"; then _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-c++0x-extensions" fi + AC_CACHE_CHECK(whether the compiler supports -Wno-extended-offsetof, + ac_has_wno_extended_offsetof, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + _SAVE_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-Wno-extended-offsetof" + AC_TRY_COMPILE([$configure_static_assert_macros + #ifndef __has_warning + #define __has_warning(x) 0 + #endif], + [CONFIGURE_STATIC_ASSERT(__has_warning("-Wextended-offsetof"))], + ac_has_wno_extended_offsetof="yes", + ac_has_wno_extended_offsetof="no") + CXXFLAGS="$_SAVE_CXXFLAGS" + AC_LANG_RESTORE + ]) + if test "$ac_has_wno_extended_offsetof" = "yes"; then + _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-extended-offsetof" + fi + AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof, ac_has_wno_invalid_offsetof, [ @@ -1939,48 +2002,6 @@ LOOP_INPUT fi # GNU_CC fi # COMPILE_ENVIRONMENT -dnl ================================================================= -dnl Set up and test static assertion macros used to avoid AC_TRY_RUN, -dnl which is bad when cross compiling. -dnl ================================================================= -if test "$COMPILE_ENVIRONMENT"; then -configure_static_assert_macros=' -#define CONFIGURE_STATIC_ASSERT(condition) CONFIGURE_STATIC_ASSERT_IMPL(condition, __LINE__) -#define CONFIGURE_STATIC_ASSERT_IMPL(condition, line) CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) -#define CONFIGURE_STATIC_ASSERT_IMPL2(condition, line) typedef int static_assert_line_##line[(condition) ? 1 : -1] -' - -dnl test that the macros actually work: -AC_MSG_CHECKING(that static assertion macros used in autoconf tests work) -AC_CACHE_VAL(ac_cv_static_assertion_macros_work, - [AC_LANG_SAVE - AC_LANG_C - ac_cv_static_assertion_macros_work="yes" - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(1)], - , - ac_cv_static_assertion_macros_work="no") - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(0)], - ac_cv_static_assertion_macros_work="no", - ) - AC_LANG_CPLUSPLUS - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(1)], - , - ac_cv_static_assertion_macros_work="no") - AC_TRY_COMPILE([$configure_static_assert_macros], - [CONFIGURE_STATIC_ASSERT(0)], - ac_cv_static_assertion_macros_work="no", - ) - AC_LANG_RESTORE - ]) -AC_MSG_RESULT("$ac_cv_static_assertion_macros_work") -if test "$ac_cv_static_assertion_macros_work" = "no"; then - AC_MSG_ERROR([Compiler cannot compile macros used in autoconf tests.]) -fi -fi # COMPILE_ENVIRONMENT - dnl ======================================================== dnl Checking for 64-bit OS dnl ======================================================== @@ -4854,7 +4875,7 @@ MOZ_ARG_DISABLE_BOOL(pedantic, _PEDANTIC= ) if test "$_PEDANTIC"; then _SAVE_CXXFLAGS=$CXXFLAGS - CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long" + CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-pedantic ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" AC_MSG_CHECKING([whether C++ compiler has -pedantic long long bug]) AC_TRY_COMPILE([$configure_static_assert_macros], [CONFIGURE_STATIC_ASSERT(sizeof(long long) == 8)], @@ -4864,8 +4885,8 @@ if test "$_PEDANTIC"; then case "$result" in no) - _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long" - _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long" + _WARNINGS_CFLAGS="${_COMPILER_PREFIX}-pedantic ${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" + _WARNINGS_CXXFLAGS="${_COMPILER_PREFIX}-pedantic ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" ;; yes) AC_MSG_ERROR([Your compiler appears to have a known bug where long long is miscompiled when using -pedantic. Reconfigure using --disable-pedantic. ]) From 3955de67f77877566ab02eedd568fd97d4a74ff3 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 2 Nov 2011 12:57:59 -0700 Subject: [PATCH 28/38] Bug 701584 - Move various offsetof uses into static offsetOf* methods. r=cdleary --HG-- extra : rebase_source : 6d453db67d872318160eee60bed3f628c1915c69 --- js/src/jsfun.h | 2 +- js/src/methodjit/BaseAssembler.h | 6 +++--- js/src/methodjit/Compiler.cpp | 8 ++++---- js/src/methodjit/InlineFrameAssembler.h | 2 +- js/src/methodjit/MethodJIT.h | 17 +++++++++++++++++ js/src/methodjit/MonoIC.cpp | 8 ++++---- js/src/vm/String.h | 3 +-- 7 files changed, 31 insertions(+), 15 deletions(-) diff --git a/js/src/jsfun.h b/js/src/jsfun.h index f85ba97aba79..65c37c576dba 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -110,7 +110,7 @@ struct JSFunction : public JSObject_Slots2 reflected as f.length/f.arity */ uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */ union U { - struct { + struct Native { js::Native native; /* native method pointer or null */ js::Class *clasp; /* class of objects constructed by this function */ diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index cb278ef5d7e8..e8af5b36afd1 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -624,7 +624,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist addPtr(Imm32(sizeof(StackFrame) + frameDepth * sizeof(jsval)), JSFrameReg, Registers::ClobberInCall); - storePtr(Registers::ClobberInCall, FrameAddress(offsetof(VMFrame, regs.sp))); + storePtr(Registers::ClobberInCall, FrameAddress(VMFrame::offsetOfRegsSp())); } } @@ -645,7 +645,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist storePtr(JSFrameReg, FrameAddress(VMFrame::offsetOfFp)); /* PC -> regs->pc :( */ - storePtr(ImmPtr(pc), FrameAddress(offsetof(VMFrame, regs.pc))); + storePtr(ImmPtr(pc), FrameAddress(VMFrame::offsetOfRegsPc())); if (inlining) { /* inlined -> regs->inlined :( */ @@ -663,7 +663,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist /* Store fp and pc */ storePtr(JSFrameReg, FrameAddress(VMFrame::offsetOfFp)); - storePtr(ImmPtr(pc), FrameAddress(offsetof(VMFrame, regs.pc))); + storePtr(ImmPtr(pc), FrameAddress(VMFrame::offsetOfRegsPc())); if (inlining) { /* ABI calls cannot be made from inlined frames. */ diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index f322d62e2a28..6b3ca2a87a50 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -3592,7 +3592,7 @@ mjit::Compiler::emitUncachedCall(uint32 argc, bool callingNew) Jump notCompiled = masm.branchTestPtr(Assembler::Zero, r0, r0); - masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.sp)), JSFrameReg); + masm.loadPtr(FrameAddress(VMFrame::offsetOfRegsSp()), JSFrameReg); callPatch.hasFastNcode = true; callPatch.fastNcodePatch = masm.storePtrWithPatch(ImmPtr(NULL), @@ -3699,7 +3699,7 @@ mjit::Compiler::checkCallApplySpeculation(uint32 callImmArgc, uint32 speculatedA */ if (*PC == JSOP_FUNAPPLY) { masm.store32(Imm32(applyTricks == LazyArgsObj), - FrameAddress(offsetof(VMFrame, u.call.lazyArgsObj))); + FrameAddress(VMFrame::offsetOfLazyArgsObj())); } } @@ -3978,8 +3978,8 @@ mjit::Compiler::inlineCallHelper(uint32 callImmArgc, bool callingNew, FrameSize if (callIC.frameSize.isStatic()) stubcc.masm.move(Imm32(callIC.frameSize.staticArgc()), JSParamReg_Argc); else - stubcc.masm.load32(FrameAddress(offsetof(VMFrame, u.call.dynamicArgc)), JSParamReg_Argc); - stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.sp)), JSFrameReg); + stubcc.masm.load32(FrameAddress(VMFrame::offsetOfDynamicArgc()), JSParamReg_Argc); + stubcc.masm.loadPtr(FrameAddress(VMFrame::offsetOfRegsSp()), JSFrameReg); callPatch.hasSlowNcode = true; callPatch.slowNcodePatch = stubcc.masm.storePtrWithPatch(ImmPtr(NULL), diff --git a/js/src/methodjit/InlineFrameAssembler.h b/js/src/methodjit/InlineFrameAssembler.h index 073c1558b2ee..e8bce636f0f1 100644 --- a/js/src/methodjit/InlineFrameAssembler.h +++ b/js/src/methodjit/InlineFrameAssembler.h @@ -137,7 +137,7 @@ class InlineFrameAssembler { * here to get the new frame pointer. */ RegisterID newfp = tempRegs.takeAnyReg().reg(); - masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.sp)), newfp); + masm.loadPtr(FrameAddress(VMFrame::offsetOfRegsSp()), newfp); Address flagsAddr(newfp, StackFrame::offsetOfFlags()); masm.store32(Imm32(flags), flagsAddr); diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 3f823b6ab69c..f8fdac4e1463 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -110,9 +110,26 @@ struct VMFrame } call; } u; + static size_t offsetOfLazyArgsObj() { + return offsetof(VMFrame, u.call.lazyArgsObj); + } + + static size_t offsetOfDynamicArgc() { + return offsetof(VMFrame, u.call.dynamicArgc); + } + VMFrame *previous; void *scratch; FrameRegs regs; + + static size_t offsetOfRegsSp() { + return offsetof(VMFrame, regs.sp); + } + + static size_t offsetOfRegsPc() { + return offsetof(VMFrame, regs.pc); + } + JSContext *cx; Value *stackLimit; StackFrame *entryfp; diff --git a/js/src/methodjit/MonoIC.cpp b/js/src/methodjit/MonoIC.cpp index be573b19009c..02ffe7550c1e 100644 --- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -768,14 +768,14 @@ class CallCompiler : public BaseCompiler masm.fallibleVMCall(cx->typeInferenceEnabled(), compilePtr, f.regs.pc, &inlined, ic.frameSize.staticLocalSlots()); } else { - masm.load32(FrameAddress(offsetof(VMFrame, u.call.dynamicArgc)), Registers::ArgReg1); + masm.load32(FrameAddress(VMFrame::offsetOfDynamicArgc()), Registers::ArgReg1); masm.fallibleVMCall(cx->typeInferenceEnabled(), compilePtr, f.regs.pc, &inlined, -1); } Jump notCompiled = masm.branchTestPtr(Assembler::Zero, Registers::ReturnReg, Registers::ReturnReg); - masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.sp)), JSFrameReg); + masm.loadPtr(FrameAddress(VMFrame::offsetOfRegsSp()), JSFrameReg); /* Compute the value of ncode to use at this call site. */ ncode = (uint8 *) f.jit()->code.m_code.executableAddress() + ic.call->codeOffset; @@ -789,7 +789,7 @@ class CallCompiler : public BaseCompiler if (ic.frameSize.isStatic()) masm.move(Imm32(ic.frameSize.staticArgc()), JSParamReg_Argc); else - masm.load32(FrameAddress(offsetof(VMFrame, u.call.dynamicArgc)), JSParamReg_Argc); + masm.load32(FrameAddress(VMFrame::offsetOfDynamicArgc()), JSParamReg_Argc); masm.jump(t0); LinkerHelper linker(masm, JSC::METHOD_CODE); @@ -1023,7 +1023,7 @@ class CallCompiler : public BaseCompiler MaybeRegisterID argcReg; if (!ic.frameSize.isStatic()) { argcReg = tempRegs.takeAnyReg().reg(); - masm.load32(FrameAddress(offsetof(VMFrame, u.call.dynamicArgc)), argcReg.reg()); + masm.load32(FrameAddress(VMFrame::offsetOfDynamicArgc()), argcReg.reg()); } /* Mark vp[1] as magic for |new|. */ diff --git a/js/src/vm/String.h b/js/src/vm/String.h index f7fa6b22177e..3ab907ce6ece 100644 --- a/js/src/vm/String.h +++ b/js/src/vm/String.h @@ -275,8 +275,7 @@ class JSString : public js::gc::Cell JS_STATIC_ASSERT(((JSString::MAX_LENGTH << JSString::LENGTH_SHIFT) >> JSString::LENGTH_SHIFT) == JSString::MAX_LENGTH); JS_STATIC_ASSERT(sizeof(JSString) == - offsetof(JSString, d.inlineStorage) + - NUM_INLINE_CHARS * sizeof(jschar)); + offsetof(JSString, d.inlineStorage) + NUM_INLINE_CHARS * sizeof(jschar)); } /* Avoid lame compile errors in JSRope::flatten */ From b6af1cfa56323483ec98b07887b48f28713de660 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 8 Nov 2011 12:10:22 -0800 Subject: [PATCH 29/38] Bug 700519 - Remove -fpascal-strings from Darwin compiler flags; r=ted --- js/src/configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/configure.in b/js/src/configure.in index e24c13657ceb..0891fec5cc5b 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -2109,8 +2109,8 @@ case "$target" in MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@' MOZ_OPTIMIZE_FLAGS="-O3 -fno-stack-protector" _PEDANTIC= - CFLAGS="$CFLAGS -fpascal-strings -fno-common" - CXXFLAGS="$CXXFLAGS -fpascal-strings -fno-common" + CFLAGS="$CFLAGS -fno-common" + CXXFLAGS="$CXXFLAGS -fno-common" DLL_SUFFIX=".dylib" DSO_LDOPTS='' STRIP="$STRIP -x -S" From 0dc3caec01cab69926dc01e25bb9ca5cd5015e94 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 10 Nov 2011 14:19:28 -0800 Subject: [PATCH 30/38] Bug 701183 - Make MOZ_DELETE use deleted function syntax in gcc when it's possible to do so without causing a warning. r=cjones --HG-- extra : rebase_source : 6f452c9cc9dcdc772991ee1056975bf7b0b4bb5b --- mfbt/RangedPtr.h | 6 +++--- mfbt/RefPtr.h | 4 ++-- mfbt/Types.h | 33 +++++++++++++++++++++------------ 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/mfbt/RangedPtr.h b/mfbt/RangedPtr.h index ce12479800a9..82726755dd16 100644 --- a/mfbt/RangedPtr.h +++ b/mfbt/RangedPtr.h @@ -268,9 +268,9 @@ class RangedPtr } private: - RangedPtr(); - T* operator&(); - operator T*() const; + RangedPtr() MOZ_DELETE; + T* operator&() MOZ_DELETE; + operator T*() const MOZ_DELETE; }; } /* namespace mozilla */ diff --git a/mfbt/RefPtr.h b/mfbt/RefPtr.h index 3c9be7ff8af9..1f480c3cccf1 100644 --- a/mfbt/RefPtr.h +++ b/mfbt/RefPtr.h @@ -269,8 +269,8 @@ private: RefPtr& refPtr; T* tmp; - OutParamRef(); - OutParamRef& operator=(const OutParamRef&); + OutParamRef() MOZ_DELETE; + OutParamRef& operator=(const OutParamRef&) MOZ_DELETE; }; /** diff --git a/mfbt/Types.h b/mfbt/Types.h index d78c87f943f0..7b0a00b239e5 100644 --- a/mfbt/Types.h +++ b/mfbt/Types.h @@ -93,19 +93,21 @@ /* * MOZ_DELETE, specified immediately prior to the ';' terminating an undefined- * method declaration, attempts to delete that method from the corresponding - * class. An attempt to use the method will produce an error *at link time*, - * not at compile time, in compilers for which this macro can be implemented. - * For example, you can use this macro to produce classes with no implicit copy - * constructor or assignment operator: + * class. An attempt to use the method will always produce an error *at compile + * time* (instead of sometimes as late as link time) when this macro can be + * implemented. For example, you can use MOZ_DELETE to produce classes with no + * implicit copy constructor or assignment operator: * - * struct NonCopyable { + * struct NonCopyable + * { * private: * NonCopyable(const NonCopyable& other) MOZ_DELETE; * void operator=(const NonCopyable& other) MOZ_DELETE; * }; * - * If MOZ_DELETE can't be implemented for the current compiler, it will still - * cause an error, but at link time rather than compile time. + * If MOZ_DELETE can't be implemented for the current compiler, use of the + * annotated method will still cause an error, but the error might occur at link + * time in some cases rather than at compile time. * * MOZ_DELETE relies on C++11 functionality not universally implemented. As a * backstop, method declarations using MOZ_DELETE should be private. @@ -113,11 +115,18 @@ #if defined(__clang__) && (__clang_major__ >= 3 || (__clang_major__ == 2 && __clang_minor__ >= 9)) # define MOZ_DELETE = delete #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -/* - * g++ >= 4.4 supports deleted functions, but it requires -std=c++0x or - * -std=gnu++0x, and for various reasons we can't use these yet. - */ -# define MOZ_DELETE /* = delete */ + /* + * g++ >= 4.4 requires -std=c++0x or -std=gnu++0x to support deleted functions + * without warnings. These modes are detectable by the experimental macro used + * below or, more standardly, by checking whether __cplusplus has a C++11 or + * greater value. Current versions of g++ do not correctly set __cplusplus, so + * we check both for forward compatibility. + */ +# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L +# define MOZ_DELETE = delete +# else +# define MOZ_DELETE /* = delete */ +# endif #else # define MOZ_DELETE /* unknown C++11 deleted function support */ #endif From c25a41851551637c825ba62100cf67193f64031f Mon Sep 17 00:00:00 2001 From: John Daggett Date: Fri, 11 Nov 2011 08:38:23 +0900 Subject: [PATCH 31/38] Bug 701262. Fix font redirect request failures. r=sicking --- layout/style/nsFontFaceLoader.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/layout/style/nsFontFaceLoader.cpp b/layout/style/nsFontFaceLoader.cpp index d2add2628ded..db32efd4bf66 100644 --- a/layout/style/nsFontFaceLoader.cpp +++ b/layout/style/nsFontFaceLoader.cpp @@ -221,7 +221,10 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader, // because HTTP responses such as 404 (Not Found) will still result in // a success code and potentially an HTML error page from the server // as the resulting data. We don't want to use that as a font. - nsCOMPtr httpChannel = do_QueryInterface(mChannel); + nsCOMPtr request; + nsCOMPtr httpChannel; + aLoader->GetRequest(getter_AddRefs(request)); + httpChannel = do_QueryInterface(request); if (httpChannel) { bool succeeded; nsresult rv = httpChannel->GetRequestSucceeded(&succeeded); From eb6d092930f0d6defa6814ffa65da4f35f3713e1 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Thu, 10 Nov 2011 16:29:34 -0800 Subject: [PATCH 32/38] Bug 687220: Add test for event handlers on the xhr.upload object in workers. r=bent --- dom/workers/test/test_xhr.html | 13 ++++++++++--- dom/workers/test/xhr_worker.js | 26 +++++++++++++++----------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/dom/workers/test/test_xhr.html b/dom/workers/test/test_xhr.html index 12ed32c93c2e..b4161f34ed82 100644 --- a/dom/workers/test/test_xhr.html +++ b/dom/workers/test/test_xhr.html @@ -23,9 +23,11 @@ Tests of DOM Worker Threads XHR(Bug 450452 ) var worker = new Worker("xhr_worker.js"); + var gotUploadLoad = false, gotLoadend = false; + worker.onmessage = function(event) { is(event.target, worker); - var args = eval(event.data); + var args = event.data; switch (args.type) { case "progress": { ok(parseInt(args.current) <= parseInt(args.total)); @@ -33,12 +35,17 @@ Tests of DOM Worker Threads XHR(Bug 450452 ) case "error": { ok(false, "XHR error: " + args.error); } break; + case "upload.load": { + gotUploadLoad = true; + } break; case "load": { - is(args.data, "A noisy noise annoys an oyster."); + ok(gotUploadLoad, "Should have gotten upload load event"); + gotLoadend = true; + is(args.data, "A noisy noise annoys an oyster.", "correct data"); document.getElementById("content").textContent = args.data; } break; case "loadend": { - ok(true, "Should have got loadend."); + ok(gotLoadend, "Should have gotten load."); SimpleTest.finish(); break; } diff --git a/dom/workers/test/xhr_worker.js b/dom/workers/test/xhr_worker.js index 4f53a522a9dc..5e3e74a3ec8c 100644 --- a/dom/workers/test/xhr_worker.js +++ b/dom/workers/test/xhr_worker.js @@ -12,12 +12,12 @@ function onload(event) { if (event.target.status != 200) { var message = { type: "error", error: event.target.status }; - postMessage(message.toSource()); + postMessage(message); } var message = { type: "load", data: xhr.responseText }; - postMessage(message.toSource()); + postMessage(message); } xhr.onload = onload; @@ -26,7 +26,7 @@ xhr.removeEventListener("load", onload, false); if (!xhr.onload) { var message = { type: "error", error: "Lost message listener!" }; - postMessage(message.toSource()); + postMessage(message); } xhr.addEventListener("error", function(event) { @@ -35,7 +35,7 @@ xhr.addEventListener("error", function(event) { } var message = { type: "error", error: event.target.status }; - postMessage(message.toSource()); + postMessage(message); }, false); function onprogress(event) { @@ -45,7 +45,7 @@ function onprogress(event) { var message = { type: "progress", current: event.loaded, total: event.total }; - postMessage(message.toSource()); + postMessage(message); } xhr.addEventListener("progress", onprogress, false); @@ -54,15 +54,19 @@ xhr.removeEventListener("doopety", function(event) {}, false); xhr.onloadend = function(event) { var message = { type: "loadend" }; - postMessage(message.toSource()); + postMessage(message); } var upload = xhr.upload; upload.onprogress = function(event) { }; -upload.addEventListener("readystatechange", function(event) { }, false); -upload.removeEventListener("readystatechange", function(event) { }, false); +upload.addEventListener("foo", function(event) { }, false); +upload.removeEventListener("foo", function(event) { }, false); upload.addEventListener("load", function(event) { }, false); -upload.removeEventListener("readystatechange", function(event) { }, false); +upload.removeEventListener("foo", function(event) { }, false); +upload.onload = function(event) { + var message = { type: "upload.load" }; + postMessage(message); +} onmessage = function(event) { if (xhr.DONE != 4 || XMLHttpRequest.DONE != 4) { @@ -71,6 +75,6 @@ onmessage = function(event) { if (xhr.readystate > xhr.UNSENT) { throw "XHR already running!"; } - xhr.open("GET", event.data); - xhr.send(null); + xhr.open("POST", event.data); + xhr.send("Data to send"); } From ffe9a3666c767a341c3a40cf2e9dcae0993ee851 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 10 Nov 2011 21:52:57 -0800 Subject: [PATCH 33/38] Bug 701244 - add back JSOP_LENGTH case to DecompileDestructuring (r=waldo) --HG-- extra : rebase_source : ddc7c80a94772b5b234a0d8f000189618051b7ff --- js/src/jit-test/tests/basic/testBug701244.js | 1 + js/src/jsopcode.cpp | 1 + 2 files changed, 2 insertions(+) create mode 100644 js/src/jit-test/tests/basic/testBug701244.js diff --git a/js/src/jit-test/tests/basic/testBug701244.js b/js/src/jit-test/tests/basic/testBug701244.js new file mode 100644 index 000000000000..4a9931f80453 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug701244.js @@ -0,0 +1 @@ +(function f({length}) {}).toString(); diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index f746891db226..e3de1a37f8b7 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1833,6 +1833,7 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc) break; case JSOP_GETPROP: + case JSOP_LENGTH: { LOAD_ATOM(0); *OFF2STR(&ss->sprinter, head) = '{'; From 7c50bc892510995a33f7b2172b4751e32d141643 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 10 Nov 2011 21:53:55 -0800 Subject: [PATCH 34/38] Bug 701227 - don't assume catch's block object has only one entry (r=waldo) --HG-- extra : rebase_source : 77673329e0841330a954a7f419d2561701c43f3c --- js/src/jit-test/tests/basic/testBug701227.js | 1 + js/src/jsopcode.cpp | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 js/src/jit-test/tests/basic/testBug701227.js diff --git a/js/src/jit-test/tests/basic/testBug701227.js b/js/src/jit-test/tests/basic/testBug701227.js new file mode 100644 index 000000000000..cf12409fea4d --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug701227.js @@ -0,0 +1 @@ +(function f() { try {} catch(e) { let x } }).toString() diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index e3de1a37f8b7..70eebdf83884 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -2951,9 +2951,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) #endif LOCAL_ASSERT(*pc == JSOP_SETLOCALPOP); pc += JSOP_SETLOCALPOP_LENGTH; - LOCAL_ASSERT(OBJ_BLOCK_COUNT(cx, obj) == 1); - atom = JSID_TO_ATOM(obj->lastProperty()->propid); - if (!QuoteString(&jp->sprinter, atom, 0)) + LOCAL_ASSERT(OBJ_BLOCK_COUNT(cx, obj) >= 1); + if (!QuoteString(&jp->sprinter, atoms[0], 0)) return NULL; #if JS_HAS_DESTRUCTURING } From 93ad21c3ca1f8b8fca6840c3c2df5b069373d01a Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 10 Nov 2011 21:55:23 -0800 Subject: [PATCH 35/38] Bug 701239 - add back arg/local-handling in DecompileDestructuringLHS (r=waldo) --HG-- extra : rebase_source : b296a3a47e4b687f773f9f5cf8bada7812ba2b81 --- js/src/jit-test/tests/basic/testBug701239.js | 1 + js/src/jsopcode.cpp | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 js/src/jit-test/tests/basic/testBug701239.js diff --git a/js/src/jit-test/tests/basic/testBug701239.js b/js/src/jit-test/tests/basic/testBug701239.js new file mode 100644 index 000000000000..665134c1d1b8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug701239.js @@ -0,0 +1 @@ +(function f(w) { for([w] in 1) {} }).toString(); diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 70eebdf83884..1e88b5454052 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1679,9 +1679,13 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc, case JSOP_SETLOCAL: LOCAL_ASSERT(pc[oplen] == JSOP_POP || pc[oplen] == JSOP_POPN); /* FALL THROUGH */ - case JSOP_SETLOCALPOP: - if (IsVarSlot(jp, pc, &i)) { + if (op == JSOP_SETARG) { + atom = GetArgOrVarAtom(jp, GET_SLOTNO(pc)); + LOCAL_ASSERT(atom); + if (!QuoteString(&ss->sprinter, atom, 0)) + return NULL; + } else if (IsVarSlot(jp, pc, &i)) { atom = GetArgOrVarAtom(jp, i); LOCAL_ASSERT(atom); if (!QuoteString(&ss->sprinter, atom, 0)) @@ -1691,6 +1695,15 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc, if (!lval || SprintCString(&ss->sprinter, lval) < 0) return NULL; } + if (op != JSOP_SETLOCALPOP) { + pc += oplen; + if (pc == endpc) + return pc; + LOAD_OP_DATA(pc); + if (op == JSOP_POPN) + return pc; + LOCAL_ASSERT(op == JSOP_POP); + } break; default: { From e465998e5d5a015f2e4cd7b59c16955b3ac6d496 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 10 Nov 2011 21:55:35 -0800 Subject: [PATCH 36/38] Bug 698299 - rm bogus assert in SecurityWrapper::nativeCall (r=mrbkap) --HG-- extra : rebase_source : 76029f08a99557061e33550165267488acf38e9b --- js/src/jswrapper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 0921b9cca05e..8d1bbc107813 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -863,9 +863,9 @@ SecurityWrapper::nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp CallArgs args) { /* Let ProxyHandler report the error. */ - bool ret = ProxyHandler::nativeCall(cx, wrapper, clasp, native, args); - JS_ASSERT(!ret && cx->isExceptionPending()); - return ret; + DebugOnly ret = ProxyHandler::nativeCall(cx, wrapper, clasp, native, args); + JS_ASSERT(!ret); + return false; } template From d50da42fcbc89468205fdbef964fc80dd773b6bf Mon Sep 17 00:00:00 2001 From: Rail Aliiev Date: Fri, 11 Nov 2011 09:55:19 -0500 Subject: [PATCH 37/38] bug 563317: Install Visual C++ 2010 on build slaves - includable vs2010 mozconfig. r=ted. DONTBUILD --- browser/config/mozconfigs/win32/vs2010-mozconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 browser/config/mozconfigs/win32/vs2010-mozconfig diff --git a/browser/config/mozconfigs/win32/vs2010-mozconfig b/browser/config/mozconfigs/win32/vs2010-mozconfig new file mode 100644 index 000000000000..8739895a1ba2 --- /dev/null +++ b/browser/config/mozconfigs/win32/vs2010-mozconfig @@ -0,0 +1,12 @@ +export INCLUDE=/d/msvs10/vc/include:/d/msvs10/vc/atlmfc/include:/d/sdks/v7.0/include:/d/sdks/v7.0/include/atl:/d/msvs8/VC/PlatformSDK/include:/d/sdks/dx10/include +export LIBPATH=/d/msvs10/vc/lib:/d/msvs10/vc/atlmfc/lib:/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727 +export LIB=/d/msvs10/vc/lib:/d/msvs10/vc/atlmfc/lib:/d/sdks/v7.0/lib:/d/msvs8/VC/PlatformSDK/lib:/d/msvs8/SDK/v2.0/lib:/d/mozilla-build/atlthunk_compat:/d/sdks/dx10/lib/x86 +export PATH="/d/msvs10/VSTSDB/Deploy:/d/msvs10/Common7/IDE/:/d/msvs10/VC/BIN:/d/msvs10/Common7/Tools:/d/msvs10/VC/VCPackages:${PATH}" +export WIN32_REDIST_DIR=/d/msvs10/VC/redist/x86/Microsoft.VC100.CRT + + +mk_add_options "export LIB=$LIB" +mk_add_options "export LIBPATH=$LIBPATH" +mk_add_options "export PATH=$PATH" +mk_add_options "export INCLUDE=$INCLUDE" +mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR" From 2d26cc32f008cf590723ef9f29704b848fec321f Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Fri, 11 Nov 2011 19:15:19 -0800 Subject: [PATCH 38/38] Bug 691847 - Always check bytecode version, r=Waldo --- js/src/jsxdrapi.cpp | 7 ++++++- js/src/jsxdrapi.h | 11 ++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/js/src/jsxdrapi.cpp b/js/src/jsxdrapi.cpp index dc6f8dc2f58d..19d7e1ffb321 100644 --- a/js/src/jsxdrapi.cpp +++ b/js/src/jsxdrapi.cpp @@ -708,18 +708,23 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp) JSScript *script; uint32 magic; + uint32 bytecodeVer; if (xdr->mode == JSXDR_DECODE) { script = NULL; *scriptp = NULL; } else { script = *scriptp; magic = JSXDR_MAGIC_SCRIPT_CURRENT; + bytecodeVer = JSXDR_BYTECODE_VERSION; } if (!JS_XDRUint32(xdr, &magic)) return false; + if (!JS_XDRUint32(xdr, &bytecodeVer)) + return false; - if (magic != JSXDR_MAGIC_SCRIPT_CURRENT) { + if (magic != JSXDR_MAGIC_SCRIPT_CURRENT || + bytecodeVer != JSXDR_BYTECODE_VERSION) { /* We do not provide binary compatibility with older scripts. */ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_BAD_SCRIPT_MAGIC); return false; diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 20861a6ecfab..a4a29bad4574 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -214,16 +214,17 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); #define JSXDR_MAGIC_SCRIPT_9 0xdead0009 #define JSXDR_MAGIC_SCRIPT_10 0xdead000a #define JSXDR_MAGIC_SCRIPT_11 0xdead000b -#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_11 +#define JSXDR_MAGIC_SCRIPT_12 0xdead000c +#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_12 /* * Bytecode version number. Increment the subtrahend whenever JS bytecode * changes incompatibly. * - * This version number should be XDR'ed once near the front of any file or - * larger storage unit containing XDR'ed bytecode and other data, and checked - * before deserialization of bytecode. If the saved version does not match - * the current version, abort deserialization and invalidate the file. + * This version number is XDR'd near the front of xdr bytecode and + * aborts deserialization if there is a mismatch between the current + * and saved versions. If deserialization fails, the data should be + * invalidated if possible. */ #define JSXDR_BYTECODE_VERSION (0xb973c0de - 98)