cherry-picked upstream changes:

bug886205, bug870103, bug886611, bug886241, bug878142, bug857334, bug886128, bug885596, bug887068, bug868302, bug886575, bug809969, bug860782, bug886285, bug848592, bug877748, bug886647, bug879079, bug886827, bug884648, bug866638, bug885463, bug826124, bug844805, bug886551, bug884407, bug884369, bug887002, bug886632, 572efc8fea86, bug886230, bug886689, bug884124
This commit is contained in:
2018-08-05 00:36:34 +08:00
parent 5b3dec5013
commit 8d816ab963
149 changed files with 2360 additions and 2187 deletions
+1 -1
View File
@@ -685,7 +685,7 @@ struct AttrCharacteristics
static const AttrCharacteristics gWAIUnivAttrMap[] = {
{&nsGkAtoms::aria_activedescendant, ATTR_BYPASSOBJ },
{&nsGkAtoms::aria_atomic, ATTR_VALTOKEN | ATTR_GLOBAL },
{&nsGkAtoms::aria_atomic, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
{&nsGkAtoms::aria_busy, ATTR_VALTOKEN | ATTR_GLOBAL },
{&nsGkAtoms::aria_checked, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, /* exposes checkable obj attr */
{&nsGkAtoms::aria_controls, ATTR_BYPASSOBJ | ATTR_GLOBAL },
+6 -5
View File
@@ -130,7 +130,7 @@ nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
nsIContent *aStartContent,
nsIContent *aTopContent)
{
nsAutoString atomic, live, relevant, busy;
nsAutoString live, relevant, busy;
nsIContent *ancestor = aStartContent;
while (ancestor) {
@@ -159,10 +159,11 @@ nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
}
// container-atomic attribute
if (atomic.IsEmpty() &&
HasDefinedARIAToken(ancestor, nsGkAtoms::aria_atomic) &&
ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_atomic, atomic))
SetAccAttr(aAttributes, nsGkAtoms::containerAtomic, atomic);
if (ancestor->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_atomic,
nsGkAtoms::_true, eCaseMatters)) {
SetAccAttr(aAttributes, nsGkAtoms::containerAtomic,
NS_LITERAL_STRING("true"));
}
// container-busy attribute
if (busy.IsEmpty() &&
@@ -830,6 +830,10 @@ already_AddRefed<nsFrameSelection>
XULTextFieldAccessible::FrameSelection()
{
nsCOMPtr<nsIContent> inputContent(GetInputField());
NS_ASSERTION(inputContent, "No input content");
if (!inputContent)
return nullptr;
nsIFrame* frame = inputContent->GetPrimaryFrame();
return frame ? frame->GetFrameSelection() : nullptr;
}
@@ -22,7 +22,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
function doTest()
{
// aria
testAttrs("atomic", {"atomic" : "true"}, true);
testAttrs("atomic", {"atomic" : "true", "container-atomic" : "true"}, true);
testAttrs(getNode("atomic").firstChild, {"container-atomic" : "true"}, true);
testAbsentAttrs("atomic_false", {"atomic" : "false", "container-atomic" : "false"});
testAbsentAttrs(getNode("atomic_false").firstChild, {"container-atomic" : "false"});
testAttrs("autocomplete", {"autocomplete" : "true"}, true);
testAttrs("checkbox", {"checkable" : "true"}, true);
testAttrs("checkedCheckbox", {"checkable" : "true"}, true);
@@ -174,7 +178,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
</pre>
<!-- aria -->
<div id="atomic" aria-atomic="true"></div>
<div id="atomic" aria-atomic="true">live region</div>
<div id="atomic_false" aria-atomic="false">live region</div>
<div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
<div id="checkbox" role="checkbox"></div>
<div id="checkedCheckbox" role="checkbox" aria-checked="true"></div>
@@ -117,6 +117,9 @@
testRelation("listitem1", RELATION_NODE_PARENT_OF,
[ "listitem1.1", "listitem1.2" ]);
// aria-atomic
testRelation(getNode("atomic").firstChild, RELATION_MEMBER_OF, "atomic");
// aria-controls
getAccessible("tab");
todo(false,
@@ -317,6 +320,8 @@
<input type="button" id="button" aria-controls="lr1 lr2"
onclick="getNode('lr1').textContent += '1'; getNode('lr2').textContent += 'a';"/>
<div id="atomic" aria-atomic="true">live region</div>
<span id="flowto" aria-flowto="flowfrom">flow to</span>
<span id="flowfrom">flow from</span>
+1 -1
View File
@@ -464,7 +464,7 @@ var PlacesCommandHook = {
"", "chrome,toolbar=yes,dialog=no,resizable", aLeftPaneRoot);
}
else {
organizer.PlacesOrganizer.selectLeftPaneQuery(aLeftPaneRoot);
organizer.PlacesOrganizer.selectLeftPaneContainerByHierarchy(aLeftPaneRoot);
organizer.focus();
}
}
@@ -212,10 +212,17 @@ History.prototype = {
for (let entry of entries) {
if (entry.has("lastVisitedDate")) {
let visitDate = this._parseCocoaDate(entry.get("lastVisitedDate"));
places.push({ uri: NetUtil.newURI(entry.get("")),
title: entry.get("title"),
visits: [{ transitionType: transType,
visitDate: visitDate }] });
try {
places.push({ uri: NetUtil.newURI(entry.get("")),
title: entry.get("title"),
visits: [{ transitionType: transType,
visitDate: visitDate }] });
}
catch(ex) {
// Safari's History file may contain malformed URIs which
// will be ignored.
Cu.reportError(ex)
}
}
}
if (places.length > 0) {
+47 -2
View File
@@ -37,6 +37,50 @@ var PlacesOrganizer = {
PlacesUtils.asContainer(this._places.selectedNode).containerOpen = true;
},
/**
* Opens a given hierarchy in the left pane, stopping at the last reachable
* container.
*
* @param aHierarchy A single container or an array of containers, sorted from
* the outmost to the innermost in the hierarchy. Each
* container may be either an item id, a Places URI string,
* or a named query.
* @see PlacesUIUtils.leftPaneQueries for supported named queries.
*/
selectLeftPaneContainerByHierarchy:
function PO_selectLeftPaneContainerByHierarchy(aHierarchy) {
if (!aHierarchy)
throw new Error("Invalid containers hierarchy");
let hierarchy = [].concat(aHierarchy);
let selectWasSuppressed = this._places.view.selection.selectEventsSuppressed;
if (!selectWasSuppressed)
this._places.view.selection.selectEventsSuppressed = true;
try {
for (let container of hierarchy) {
switch (typeof container) {
case "number":
this._places.selectItems([container]);
break;
case "string":
if (container.substr(0, 6) == "place:")
this._places.selectPlaceURI(container);
else if (container in PlacesUIUtils.leftPaneQueries)
this.selectLeftPaneQuery(container);
else
throw new Error("Invalid container found: " + container);
break;
default:
throw new Error("Invalid container type found: " + container);
break;
}
PlacesUtils.asContainer(this._places.selectedNode).containerOpen = true;
}
} finally {
if (!selectWasSuppressed)
this._places.view.selection.selectEventsSuppressed = false;
}
},
init: function PO_init() {
ContentArea.init();
@@ -47,12 +91,13 @@ var PlacesOrganizer = {
if (window.arguments && window.arguments[0])
leftPaneSelection = window.arguments[0];
this.selectLeftPaneQuery(leftPaneSelection);
if (leftPaneSelection == "History") {
this.selectLeftPaneContainerByHierarchy(leftPaneSelection);
if (leftPaneSelection === "History") {
let historyNode = this._places.selectedNode;
if (historyNode.childCount > 0)
this._places.selectNode(historyNode.getChild(0));
}
// clear the back-stack
this._backHistory.splice(0, this._backHistory.length);
document.getElementById("OrganizerCommand:Back").setAttribute("disabled", true);
@@ -3334,6 +3334,9 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_ASYNC_DECODE_IMAGES) {
renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES;
}
if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH) {
renderDocFlags |= nsIPresShell::RENDER_DRAWWINDOW_NOT_FLUSHING;
}
// gfxContext-over-Azure may modify the DrawTarget's transform, so
// save and restore it
@@ -0,0 +1,50 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsDOMClassInfoID.h"
#include "SpeechRecognitionError.h"
namespace mozilla {
namespace dom {
SpeechRecognitionError::SpeechRecognitionError(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, nsEvent* aEvent)
: nsDOMEvent(aOwner, aPresContext, aEvent),
mError()
{}
SpeechRecognitionError::~SpeechRecognitionError() {}
already_AddRefed<SpeechRecognitionError>
SpeechRecognitionError::Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const SpeechRecognitionErrorInit& aParam,
ErrorResult& aRv)
{
nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.Get());
nsRefPtr<SpeechRecognitionError> e = new SpeechRecognitionError(t, nullptr, nullptr);
bool trusted = e->Init(t);
e->InitSpeechRecognitionError(aType, aParam.mBubbles, aParam.mCancelable, aParam.mError, aParam.mMessage, aRv);
e->SetTrusted(trusted);
return e.forget();
}
void
SpeechRecognitionError::InitSpeechRecognitionError(const nsAString& aType,
bool aCanBubble,
bool aCancelable,
SpeechRecognitionErrorCode aError,
const nsAString& aMessage,
ErrorResult& aRv)
{
aRv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode());
mError = aError;
mMessage = aMessage;
return;
}
} // namespace dom
} // namespace mozilla
@@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef SpeechRecognitionError_h__
#define SpeechRecognitionError_h__
#include "nsDOMEvent.h"
#include "mozilla/dom/SpeechRecognitionErrorBinding.h"
namespace mozilla {
namespace dom {
class SpeechRecognitionError : public nsDOMEvent
{
public:
SpeechRecognitionError(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext,
nsEvent* aEvent);
virtual ~SpeechRecognitionError();
static already_AddRefed<SpeechRecognitionError> Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const SpeechRecognitionErrorInit& aParam,
ErrorResult& aRv);
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
{
return mozilla::dom::SpeechRecognitionErrorBinding::Wrap(aCx, aScope, this);
}
void
GetMessage(nsAString& aString)
{
aString = mMessage;
}
SpeechRecognitionErrorCode
Error()
{
return mError;
}
void
InitSpeechRecognitionError(const nsAString& aType,
bool aCanBubble,
bool aCancelable,
SpeechRecognitionErrorCode aError,
const nsAString& aMessage,
ErrorResult& aRv);
protected:
SpeechRecognitionErrorCode mError;
nsString mMessage;
};
}
}
#endif // SpeechRecognitionError_h__
+2
View File
@@ -16,6 +16,7 @@ EXPORTS += [
]
EXPORTS.mozilla.dom += [
'SpeechRecognitionError.h',
'Touch.h',
]
@@ -59,4 +60,5 @@ CPP_SOURCES += [
'nsIMEStateManager.cpp',
'nsPaintRequest.cpp',
'nsPrivateTextRange.cpp',
'SpeechRecognitionError.cpp',
]
@@ -521,11 +521,10 @@ SpeechRecognition::AbortError(SpeechEvent* aEvent)
void
SpeechRecognition::NotifyError(SpeechEvent* aEvent)
{
nsCOMPtr<nsIDOMEvent> domEvent = do_QueryInterface(aEvent->mError);
domEvent->SetTrusted(true);
aEvent->mError->SetTrusted(true);
bool defaultActionEnabled;
this->DispatchEvent(domEvent, &defaultActionEnabled);
this->DispatchEvent(aEvent->mError, &defaultActionEnabled);
return;
}
@@ -576,7 +575,7 @@ SpeechRecognition::Observe(nsISupports* aSubject, const char* aTopic,
StateBetween(STATE_IDLE, STATE_WAITING_FOR_SPEECH)) {
DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR,
nsIDOMSpeechRecognitionError::NO_SPEECH,
SpeechRecognitionErrorCode::No_speech,
NS_LITERAL_STRING("No speech detected (timeout)"));
} else if (!strcmp(aTopic, SPEECH_RECOGNITION_TEST_END_TOPIC)) {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@@ -602,7 +601,7 @@ SpeechRecognition::ProcessTestEventRequest(nsISupports* aSubject, const nsAStrin
Abort();
} else if (aEventName.EqualsLiteral("EVENT_AUDIO_ERROR")) {
DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR,
nsIDOMSpeechRecognitionError::AUDIO_CAPTURE, // TODO different codes?
SpeechRecognitionErrorCode::Audio_capture, // TODO different codes?
NS_LITERAL_STRING("AUDIO_ERROR test event"));
} else if (aEventName.EqualsLiteral("EVENT_AUDIO_DATA")) {
StartRecording(static_cast<DOMMediaStream*>(aSubject));
@@ -748,19 +747,21 @@ SpeechRecognition::Abort()
}
void
SpeechRecognition::DispatchError(EventType aErrorType, int aErrorCode,
SpeechRecognition::DispatchError(EventType aErrorType,
SpeechRecognitionErrorCode aErrorCode,
const nsAString& aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aErrorType == EVENT_RECOGNITIONSERVICE_ERROR ||
aErrorType == EVENT_AUDIO_ERROR, "Invalid error type!");
nsCOMPtr<nsIDOMEvent> domEvent;
NS_NewDOMSpeechRecognitionError(getter_AddRefs(domEvent), nullptr, nullptr, nullptr);
nsRefPtr<SpeechRecognitionError> srError =
new SpeechRecognitionError(nullptr, nullptr, nullptr);
nsCOMPtr<nsIDOMSpeechRecognitionError> srError = do_QueryInterface(domEvent);
ErrorResult err;
srError->InitSpeechRecognitionError(NS_LITERAL_STRING("error"), true, false,
aErrorCode, aMessage);
aErrorCode, aMessage, err);
nsRefPtr<SpeechEvent> event = new SpeechEvent(this, aErrorType);
event->mError = srError;
NS_DispatchToMainThread(event);
@@ -1002,12 +1003,12 @@ NS_IMPL_ISUPPORTS1(SpeechRecognition::GetUserMediaErrorCallback, nsIDOMGetUserMe
NS_IMETHODIMP
SpeechRecognition::GetUserMediaErrorCallback::OnError(const nsAString& aError)
{
int errorCode;
SpeechRecognitionErrorCode errorCode;
if (aError.Equals(NS_LITERAL_STRING("PERMISSION_DENIED"))) {
errorCode = nsIDOMSpeechRecognitionError::NOT_ALLOWED;
errorCode = SpeechRecognitionErrorCode::Not_allowed;
} else {
errorCode = nsIDOMSpeechRecognitionError::AUDIO_CAPTURE;
errorCode = SpeechRecognitionErrorCode::Audio_capture;
}
mRecognition->DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR, errorCode,
@@ -28,7 +28,7 @@
#include "nsISpeechRecognitionService.h"
#include "endpointer.h"
#include "nsIDOMSpeechRecognitionError.h"
#include "mozilla/dom/SpeechRecognitionError.h"
struct JSContext;
class nsIDOMWindow;
@@ -127,7 +127,7 @@ public:
EVENT_COUNT
};
void DispatchError(EventType aErrorType, int aErrorCode, const nsAString& aMessage);
void DispatchError(EventType aErrorType, SpeechRecognitionErrorCode aErrorCode, const nsAString& aMessage);
uint32_t FillSamplesBuffer(const int16_t* aSamples, uint32_t aSampleCount);
uint32_t SplitSamplesBuffer(const int16_t* aSamplesBuffer, uint32_t aSampleCount, nsTArray<already_AddRefed<SharedBuffer> >& aResult);
AudioSegment* CreateAudioSegment(nsTArray<already_AddRefed<SharedBuffer> >& aChunks);
@@ -284,7 +284,7 @@ public:
NS_IMETHOD Run() MOZ_OVERRIDE;
AudioSegment* mAudioSegment;
nsRefPtr<SpeechRecognitionResultList> mRecognitionResultList; // TODO: make this a session being passed which also has index and stuff
nsCOMPtr<nsIDOMSpeechRecognitionError> mError;
nsRefPtr<SpeechRecognitionError> mError;
friend class SpeechRecognition;
private:
@@ -8,7 +8,6 @@ MODULE = 'content'
XPIDL_MODULE = 'dom_webspeechrecognition'
XPIDL_SOURCES = [
'nsIDOMSpeechRecognitionError.idl',
'nsIDOMSpeechRecognitionEvent.idl',
'nsISpeechRecognitionService.idl'
]
@@ -1,39 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
#include "nsIDOMEvent.idl"
[scriptable, builtinclass, uuid(5ddc5a46-e7db-4c5c-8ed4-80cf5d88fca3)]
interface nsIDOMSpeechRecognitionError : nsIDOMEvent {
const unsigned long NO_SPEECH = 0;
const unsigned long ABORTED = 1;
const unsigned long AUDIO_CAPTURE = 2;
const unsigned long NETWORK = 3;
const unsigned long NOT_ALLOWED = 4;
const unsigned long SERVICE_NOT_ALLOWED = 5;
const unsigned long BAD_GRAMMAR = 6;
const unsigned long LANGUAGE_NOT_SUPPORTED = 7;
[noscript] void initSpeechRecognitionError(in DOMString eventTypeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in unsigned long error,
in DOMString message);
readonly attribute unsigned long error;
readonly attribute DOMString message;
};
dictionary SpeechRecognitionErrorInit : EventInit {
unsigned long error;
DOMString message;
};
@@ -74,7 +74,7 @@ FakeSpeechRecognitionService::Observe(nsISupports* aSubject, const char* aTopic,
if (eventName.EqualsLiteral("EVENT_RECOGNITIONSERVICE_ERROR")) {
mRecognition->DispatchError(SpeechRecognition::EVENT_RECOGNITIONSERVICE_ERROR,
nsIDOMSpeechRecognitionError::NETWORK, // TODO different codes?
SpeechRecognitionErrorCode::Network, // TODO different codes?
NS_LITERAL_STRING("RECOGNITIONSERVICE_ERROR test event"));
} else if (eventName.EqualsLiteral("EVENT_RECOGNITIONSERVICE_FINAL_RESULT")) {
@@ -5,14 +5,14 @@ const SPEECH_RECOGNITION_TEST_REQUEST_EVENT_TOPIC = "SpeechRecognitionTest:Reque
const SPEECH_RECOGNITION_TEST_END_TOPIC = "SpeechRecognitionTest:End";
var errorCodes = {
NO_SPEECH : 0,
ABORTED : 1,
AUDIO_CAPTURE : 2,
NETWORK : 3,
NOT_ALLOWED : 4,
SERVICE_NOT_ALLOWED : 5,
BAD_GRAMMAR : 6,
LANGUAGE_NOT_SUPPORTED : 7
NO_SPEECH : "no-speech",
ABORTED : "aborted",
AUDIO_CAPTURE : "audio-capture",
NETWORK : "network",
NOT_ALLOWED : "not-allowed",
SERVICE_NOT_ALLOWED : "service-not-allowed",
BAD_GRAMMAR : "bad-grammar",
LANGUAGE_NOT_SUPPORTED : "language-not-supported"
};
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+1
View File
@@ -80,6 +80,7 @@ MOCHITEST_FILES = \
switch-helper.svg \
test_text.html \
test_text_2.html \
test_text_dirty.html \
test_text_scaled.html \
test_text_selection.html \
test_text_update.html \
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=886230
-->
<head>
<title>Test for Bug 886230</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style type="text/css">
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=886230">Mozilla Bug 886230</a>
<p id="display">
<svg>
<mask id="m"><text id="t">x</text></mask>
<rect width="600" height="400" mask="url(#m)"/>
</svg>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
function runTest() {
var svgText = document.getElementById("t");
// Recreate the frames for the <text> with the pref set.
svgText.style.display = "none";
svgText.getComputedTextLength();
svgText.style.display = "inline";
svgText.getComputedTextLength();
// Dirty the frames.
document.getElementById("display").style.width = "700px";
svgText.removeChild(svgText.firstChild);
// Paint without flushing layout. If the test fails, we'll trigger
// an assertion.
SpecialPowers.snapshotWindowWithOptions(window, undefined, undefined, { DRAWWINDOW_DO_NOT_FLUSH: true });
ok(true);
SimpleTest.finish();
}
window.addEventListener("load", function() {
SpecialPowers.pushPrefEnv({'set': [['svg.text.css-frames.enabled', true]]}, runTest);
}, false);
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>
+11 -2
View File
@@ -258,6 +258,8 @@ this.DOMApplicationRegistry = {
// Install the permissions for this app, as if we were updating
// to cleanup the old ones if needed.
// TODO It's not clear what this should do when there are multiple profiles.
#ifdef MOZ_B2G
this._readManifests([{ id: aId }], (function(aResult) {
let data = aResult[0];
PermissionsInstaller.installPermissions({
@@ -268,6 +270,7 @@ this.DOMApplicationRegistry = {
debug("Error installing permissions for " + aId);
});
}).bind(this));
#endif
},
updateOfflineCacheForApp: function updateOfflineCacheForApp(aId) {
@@ -1237,11 +1240,13 @@ this.DOMApplicationRegistry = {
this._saveApps((function() {
// Update the handlers and permissions for this app.
this.updateAppHandlers(aOldManifest, aData, app);
#ifdef MOZ_B2G
PermissionsInstaller.installPermissions(
{ manifest: aData,
origin: app.origin,
manifestURL: app.manifestURL },
true);
#endif
this.broadcastMessage("Webapps:PackageEvent",
{ type: "applied",
manifestURL: app.manifestURL,
@@ -1462,13 +1467,14 @@ this.DOMApplicationRegistry = {
this._writeFile(manFile, JSON.stringify(aNewManifest), function() { });
manifest = new ManifestHelper(aNewManifest, app.origin);
#ifdef MOZ_B2G
// Update the permissions for this app.
PermissionsInstaller.installPermissions({
manifest: app.manifest,
origin: app.origin,
manifestURL: aData.manifestURL
}, true);
#endif
app.name = manifest.name;
app.csp = manifest.csp || "";
app.updateTime = Date.now();
@@ -2012,12 +2018,14 @@ this.DOMApplicationRegistry = {
// For package apps, the permissions are not in the mini-manifest, so
// don't update the permissions yet.
if (!aData.isPackage) {
#ifdef MOZ_B2G
PermissionsInstaller.installPermissions({ origin: appObject.origin,
manifestURL: appObject.manifestURL,
manifest: jsonManifest },
isReinstall, (function() {
this.uninstall(aData, aData.mm);
}).bind(this));
#endif
}
["installState", "downloadAvailable",
@@ -2075,12 +2083,13 @@ this.DOMApplicationRegistry = {
app.downloadAvailable = false;
this._saveApps((function() {
this.updateAppHandlers(null, aManifest, appObject);
#ifdef MOZ_B2G
// Update the permissions for this app.
PermissionsInstaller.installPermissions({ manifest: aManifest,
origin: appObject.origin,
manifestURL: appObject.manifestURL },
true);
#endif
debug("About to fire Webapps:PackageEvent 'installed'");
this.broadcastMessage("Webapps:PackageEvent",
{ type: "installed",
+1 -1
View File
@@ -364,7 +364,7 @@ this.PushService = {
// just for it
if (this._ws) {
debug("Had a connection, so telling the server");
this._request("unregister", {channelID: records[i].channelID});
this._sendRequest("unregister", {channelID: records[i].channelID});
}
}
}.bind(this), function() {
+1 -1
View File
@@ -28,7 +28,7 @@ MOCHITEST_BROWSER_FILES := \
page_privatestorageevent.html
$(NULL)
ifeq (,$(filter-out Linux WINNT,$(OS_ARCH)))
ifdef MOZ_B2G
MOCHITEST_BROWSER_FILES += \
browser_webapps_permissions.js \
test-webapp.webapp \
+14 -12
View File
@@ -4,24 +4,26 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[Constructor(DOMString type, optional SpeechRecognitionErrorInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
enum SpeechRecognitionErrorCode {
"no-speech",
"aborted",
"audio-capture",
"network",
"not-allowed",
"service-not-allowed",
"bad-grammar",
"language-not-supported"
};
[Constructor(DOMString type, optional SpeechRecognitionErrorInit eventInitDict)]
interface SpeechRecognitionError : Event
{
const unsigned long NO_SPEECH = 0;
const unsigned long ABORTED = 1;
const unsigned long AUDIO_CAPTURE = 2;
const unsigned long NETWORK = 3;
const unsigned long NOT_ALLOWED = 4;
const unsigned long SERVICE_NOT_ALLOWED = 5;
const unsigned long BAD_GRAMMAR = 6;
const unsigned long LANGUAGE_NOT_SUPPORTED = 7;
readonly attribute unsigned long error;
readonly attribute SpeechRecognitionErrorCode error;
readonly attribute DOMString? message;
};
dictionary SpeechRecognitionErrorInit : EventInit
{
unsigned long error = 0;
SpeechRecognitionErrorCode error = "no-speech";
DOMString message = "";
};
+24 -8
View File
@@ -701,49 +701,63 @@ NS_IMETHODIMP nsWebBrowser::SetProperty(uint32_t aId, uint32_t aValue)
case nsIWebBrowserSetup::SETUP_ALLOW_PLUGINS:
{
NS_ENSURE_STATE(mDocShell);
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
mDocShell->SetAllowPlugins(!!aValue);
}
break;
case nsIWebBrowserSetup::SETUP_ALLOW_JAVASCRIPT:
{
NS_ENSURE_STATE(mDocShell);
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
mDocShell->SetAllowJavascript(!!aValue);
}
break;
case nsIWebBrowserSetup::SETUP_ALLOW_META_REDIRECTS:
{
NS_ENSURE_STATE(mDocShell);
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
mDocShell->SetAllowMetaRedirects(!!aValue);
}
break;
case nsIWebBrowserSetup::SETUP_ALLOW_SUBFRAMES:
{
NS_ENSURE_STATE(mDocShell);
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
mDocShell->SetAllowSubframes(!!aValue);
}
break;
case nsIWebBrowserSetup::SETUP_ALLOW_IMAGES:
{
NS_ENSURE_STATE(mDocShell);
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
mDocShell->SetAllowImages(!!aValue);
}
break;
case nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH:
{
NS_ENSURE_STATE(mDocShell);
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
mDocShell->SetAllowDNSPrefetch(!!aValue);
}
break;
case nsIWebBrowserSetup::SETUP_USE_GLOBAL_HISTORY:
{
NS_ENSURE_STATE(mDocShell);
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
rv = EnableGlobalHistory(!!aValue);
mShouldEnableHistory = aValue;
}
@@ -755,7 +769,9 @@ NS_IMETHODIMP nsWebBrowser::SetProperty(uint32_t aId, uint32_t aValue)
break;
case nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER:
{
NS_ENSURE_TRUE((aValue == true || aValue == false), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) ||
aValue == static_cast<uint32_t>(false)),
NS_ERROR_INVALID_ARG);
SetItemType(aValue ? static_cast<int32_t>(typeChromeWrapper)
: static_cast<int32_t>(typeContentWrapper));
}
-7
View File
@@ -10,13 +10,6 @@ EXPORT_LIBRARY = 1
DEFINES += -D_IMPL_NS_GFX
ifeq (arm,$(findstring arm,$(OS_TEST)))
ifdef HAVE_ARM_NEON
ASFILES = yuv_row_arm.$(ASM_SUFFIX) \
$(NULL)
endif
endif
include $(topsrcdir)/config/rules.mk
# These files use MMX and SSE2 intrinsics, so they need special compile flags
+4 -1
View File
@@ -61,7 +61,10 @@ else:
'yuv_row_other.cpp',
]
if CONFIG['OS_TEST'].startswith('arm') and CONFIG['HAVE_ARM_NEON']:
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['HAVE_ARM_NEON']:
ASFILES += [
'yuv_row_arm.s',
]
CPP_SOURCES += [
'yuv_convert_arm.cpp',
]
+10 -7
View File
@@ -535,7 +535,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
#ifdef JS_THREADSAFE
MOZ_ASSERT(js::IsInRequest(cxArg));
#endif
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
js::ContextFriendFields *cx = js::ContextFriendFields::get(cxArg);
commonInit(cx->thingGCRooters);
#endif
@@ -543,7 +543,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
void init(js::PerThreadDataFriendFields *pt) {
MOZ_ASSERT(pt);
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
commonInit(pt->thingGCRooters);
#endif
}
@@ -598,13 +598,13 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
}
~Rooted() {
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
JS_ASSERT(*stack == reinterpret_cast<Rooted<void*>*>(this));
*stack = prev;
#endif
}
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
Rooted<T> *previous() { return prev; }
#endif
@@ -640,7 +640,10 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
private:
void commonInit(Rooted<void*> **thingGCRooters) {
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
scanned = false;
#endif
#ifdef JSGC_TRACK_EXACT_ROOTS
js::ThingRootKind kind = js::GCMethods<T>::kind();
this->stack = &thingGCRooters[kind];
this->prev = *stack;
@@ -650,11 +653,11 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
#endif
}
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
Rooted<void*> **stack, *prev;
#endif
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
#ifdef JSGC_ROOT_ANALYSIS
/* Has the rooting analysis ever scanned this Rooted's stack location? */
friend void JS::CheckStackRoots(JSContext*);
bool scanned;
+1 -1
View File
@@ -480,7 +480,7 @@ js::PrincipalsForCompiledCode(const CallReceiver &call, JSContext *cx)
{
JSObject &callee = call.callee();
JS_ASSERT(IsAnyBuiltinEval(&callee.as<JSFunction>()) ||
IsBuiltinFunctionConstructor(&callee.as<JSFunction>()));
callee.as<JSFunction>().isBuiltinFunctionConstructor());
// To compute the principals of the compiled eval/Function code, we simply
// use the callee's principals. To see why the caller's principals are
+4
View File
@@ -21,6 +21,10 @@
#include "jscntxtinlines.h"
#ifdef JSGC_GENERATIONAL
#include "vm/Shape-inl.h"
#endif
using namespace js;
using mozilla::ArrayLength;
+1
View File
@@ -16,6 +16,7 @@
#include "jit/AsmJS.h"
#include "vm/ForkJoin.h"
#include "vm/Interpreter.h"
#include "vm/ObjectImpl-inl.h"
+16 -40
View File
@@ -1862,21 +1862,11 @@ EmitElemOpBase(JSContext *cx, BytecodeEmitter *bce, JSOp op)
}
static bool
EmitPropLHS(JSContext *cx, ParseNode *pn, JSOp *op, BytecodeEmitter *bce, bool callContext)
EmitPropLHS(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(pn->isKind(PNK_DOT));
ParseNode *pn2 = pn->maybeExpr();
if (callContext) {
JS_ASSERT(pn->isKind(PNK_DOT));
JS_ASSERT(*op == JSOP_GETPROP);
*op = JSOP_CALLPROP;
} else if (*op == JSOP_GETPROP && pn->isKind(PNK_DOT)) {
if (pn2->isKind(PNK_NAME)) {
if (!BindNameToSlot(cx, bce, pn2))
return false;
}
}
/*
* If the object operand is also a dotted property reference, reverse the
* list linked via pn_expr temporarily so we can iterate over it from the
@@ -1904,7 +1894,7 @@ EmitPropLHS(JSContext *cx, ParseNode *pn, JSOp *op, BytecodeEmitter *bce, bool c
do {
/* Walk back up the list, emitting annotated name ops. */
if (!EmitAtomOp(cx, pndot, pndot->getOp(), bce))
if (!EmitAtomOp(cx, pndot, JSOP_GETPROP, bce))
return false;
/* Reverse the pn_expr link again. */
@@ -1912,20 +1902,19 @@ EmitPropLHS(JSContext *cx, ParseNode *pn, JSOp *op, BytecodeEmitter *bce, bool c
pndot->pn_expr = pndown;
pndown = pndot;
} while ((pndot = pnup) != NULL);
} else {
if (!EmitTree(cx, bce, pn2))
return false;
return true;
}
return true;
// The non-optimized case.
return EmitTree(cx, bce, pn2);
}
static bool
EmitPropOp(JSContext *cx, ParseNode *pn, JSOp requested, BytecodeEmitter *bce, bool callContext)
EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
{
JS_ASSERT(pn->isArity(PN_NAME));
JSOp op = requested;
if (!EmitPropLHS(cx, pn, &op, bce, callContext))
if (!EmitPropLHS(cx, pn, op, bce))
return false;
if (op == JSOP_CALLPROP && Emit1(cx, bce, JSOP_DUP) < 0)
@@ -1952,9 +1941,8 @@ EmitPropIncDec(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
JSOp binop = GetIncDecInfo(pn->getKind(), &post);
JSOp get = JSOP_GETPROP;
if (!EmitPropLHS(cx, pn->pn_kid, &get, bce, false)) // OBJ
if (!EmitPropLHS(cx, pn->pn_kid, get, bce)) // OBJ
return false;
JS_ASSERT(get == JSOP_GETPROP);
if (Emit1(cx, bce, JSOP_DUP) < 0) // OBJ OBJ
return false;
if (!EmitAtomOp(cx, pn->pn_kid, JSOP_GETPROP, bce)) // OBJ V
@@ -3413,7 +3401,7 @@ EmitAssignment(JSContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp op, Par
return false;
}
/* If += etc., emit the binary operator with a decompiler note. */
/* If += etc., emit the binary operator with a source note. */
if (op != JSOP_NOP) {
/*
* Take care to avoid SRC_ASSIGNOP if the left-hand side is a const
@@ -3447,7 +3435,7 @@ EmitAssignment(JSContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp op, Par
}
break;
case PNK_DOT:
if (!EmitIndexOp(cx, lhs->getOp(), atomIndex, bce))
if (!EmitIndexOp(cx, JSOP_SETPROP, atomIndex, bce))
return false;
break;
case PNK_CALL:
@@ -4934,7 +4922,7 @@ EmitDelete(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break;
}
case PNK_DOT:
if (!EmitPropOp(cx, pn2, JSOP_DELPROP, bce, false))
if (!EmitPropOp(cx, pn2, JSOP_DELPROP, bce))
return false;
break;
case PNK_ELEM:
@@ -5042,11 +5030,10 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
break;
case PNK_DOT:
if (!EmitPropOp(cx, pn2, pn2->getOp(), bce, callop))
if (!EmitPropOp(cx, pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP, bce))
return false;
break;
case PNK_ELEM:
JS_ASSERT(pn2->isOp(JSOP_GETELEM));
if (!EmitElemOp(cx, pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM, bce))
return false;
break;
@@ -5932,22 +5919,11 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break;
case PNK_DOT:
/*
* Pop a stack operand, convert it to object, get a property named by
* this bytecode's immediate-indexed atom operand, and push its value
* (not a reference to it).
*/
ok = EmitPropOp(cx, pn, pn->getOp(), bce, false);
ok = EmitPropOp(cx, pn, JSOP_GETPROP, bce);
break;
case PNK_ELEM:
/*
* Pop two operands, convert the left one to object and the right one
* to property name (atom or tagged int), get the named property, and
* push its value. Set the "obj" register to the result of ToObject
* on the left operand.
*/
ok = EmitElemOp(cx, pn, pn->getOp(), bce);
ok = EmitElemOp(cx, pn, JSOP_GETELEM, bce);
break;
case PNK_NEW:
+46
View File
@@ -698,6 +698,52 @@ FoldConstants<FullParseHandler>(JSContext *cx, ParseNode **pnp,
}
break;
case PNK_ELEM: {
// An indexed expression, pn1[pn2]. A few cases can be improved.
PropertyName *name = NULL;
if (pn2->isKind(PNK_STRING)) {
JSAtom *atom = pn2->pn_atom;
uint32_t index;
if (atom->isIndex(&index)) {
// Optimization 1: We have something like pn1["100"]. This is
// equivalent to pn1[100] which is faster.
pn2->setKind(PNK_NUMBER);
pn2->setOp(JSOP_DOUBLE);
pn2->pn_dval = index;
} else {
name = atom->asPropertyName();
}
} else if (pn2->isKind(PNK_NUMBER)) {
double number = pn2->pn_dval;
if (number != ToUint32(number)) {
// Optimization 2: We have something like pn1[3.14]. The number
// is not an array index. This is equivalent to pn1["3.14"]
// which enables optimization 3 below.
JSAtom *atom = ToAtom<NoGC>(cx, DoubleValue(number));
if (!atom)
return false;
name = atom->asPropertyName();
}
}
if (name) {
// Optimization 3: We have pn1["foo"] where foo is not an index.
// Convert to a property access (like pn1.foo) which we optimize
// better downstream.
ParseNode *expr = parser->handler.newPropertyAccess(pn->pn_left, name, pn->pn_pos.end);
if (!expr)
return false;
ReplaceNode(pnp, expr);
pn->pn_left = NULL;
pn->pn_right = NULL;
parser->handler.freeTree(pn);
pn = expr;
}
break;
}
default:;
}
-50
View File
@@ -317,57 +317,7 @@ class FullParseHandler
return new_<PropertyAccess>(pn, name, pn->pn_pos.begin, end);
}
private:
/*
* Examine the RHS of a MemberExpression obj[pn], to optimize expressions
* like obj["name"] or obj["0"].
*
* If pn is a number or string constant that's not an index, store the
* corresponding PropertyName in *namep. Otherwise store NULL in *namep.
*
* Also, if pn is a string constant whose value is the ToString of an
* index, morph it to a number.
*
* Return false on OOM.
*/
bool foldConstantIndex(ParseNode *pn, PropertyName **namep) {
if (pn->isKind(PNK_STRING)) {
JSAtom *atom = pn->pn_atom;
uint32_t index;
if (atom->isIndex(&index)) {
pn->setKind(PNK_NUMBER);
pn->setOp(JSOP_DOUBLE);
pn->pn_dval = index;
} else {
*namep = atom->asPropertyName();
return true;
}
} else if (pn->isKind(PNK_NUMBER)) {
double number = pn->pn_dval;
if (number != ToUint32(number)) {
JSContext *cx = tokenStream.getContext();
JSAtom *atom = ToAtom<NoGC>(cx, DoubleValue(number));
if (!atom)
return false;
*namep = atom->asPropertyName();
return true;
}
}
*namep = NULL;
return true;
}
public:
ParseNode *newPropertyByValue(ParseNode *lhs, ParseNode *index, uint32_t end) {
if (foldConstants) {
PropertyName *name;
if (!foldConstantIndex(index, &name))
return null();
if (name)
return newPropertyAccess(lhs, name, end);
}
return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
}
+1 -1
View File
@@ -12,7 +12,7 @@ struct JSContext;
namespace js {
namespace frontend {
struct ParseNode;
class ParseNode;
bool
NameFunctions(JSContext *cx, ParseNode *pn);
+3 -4
View File
@@ -416,9 +416,8 @@ class ConditionalExpression;
class PropertyAccess;
class ModuleBox;
struct ParseNode
class ParseNode
{
private:
uint32_t pn_type : 16, /* PNK_* type */
pn_op : 8, /* see JSOp enum and jsopcode.tbl */
pn_arity : 5, /* see ParseNodeArity enum */
@@ -1166,7 +1165,7 @@ class PropertyAccess : public ParseNode
{
public:
PropertyAccess(ParseNode *lhs, PropertyName *name, uint32_t begin, uint32_t end)
: ParseNode(PNK_DOT, JSOP_GETPROP, PN_NAME, TokenPos(begin, end))
: ParseNode(PNK_DOT, JSOP_NOP, PN_NAME, TokenPos(begin, end))
{
JS_ASSERT(lhs != NULL);
JS_ASSERT(name != NULL);
@@ -1193,7 +1192,7 @@ class PropertyByValue : public ParseNode
{
public:
PropertyByValue(ParseNode *lhs, ParseNode *propExpr, uint32_t begin, uint32_t end)
: ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos(begin, end))
: ParseNode(PNK_ELEM, JSOP_NOP, PN_BINARY, TokenPos(begin, end))
{
pn_u.binary.left = lhs;
pn_u.binary.right = propExpr;
+6 -10
View File
@@ -4435,6 +4435,11 @@ Parser<ParseHandler>::returnStatementOrYieldExpression()
(isYield && (next == TOK_YIELD || next == TOK_RB || next == TOK_RP ||
next == TOK_COLON || next == TOK_COMMA)))
{
if (isYield) {
if (!reportWithOffset(ParseWarning, false, pos().begin, JSMSG_YIELD_WITHOUT_OPERAND))
return null();
}
exprNode = null();
if (!isYield)
pc->funHasReturnVoid = true;
@@ -5337,9 +5342,7 @@ Parser<ParseHandler>::unaryExpr()
return null();
// Per spec, deleting any unary expression is valid -- it simply returns
// true -- except for a few cases that are illegal in strict mode.
if (foldConstants && !FoldConstants(context, &expr, this))
return null();
// true -- except for one case that is illegal in strict mode.
if (handler.isName(expr)) {
if (!report(ParseStrictError, pc->sc->strict, expr, JSMSG_DEPRECATED_DELETE_OPERAND))
return null();
@@ -6236,13 +6239,6 @@ Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax)
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
/*
* Do folding so we don't have roundtrip changes for cases like:
* function (obj) { return obj["a" + "b"] }
*/
if (foldConstants && !FoldConstants(context, &propExpr, this))
return null();
nextMember = handler.newPropertyByValue(lhs, propExpr, pos().end);
if (!nextMember)
return null();
+3 -3
View File
@@ -36,7 +36,6 @@ typedef HashSet<JSAtom *> FuncStmtSet;
class SharedContext;
typedef Vector<Definition *, 16> DeclVector;
typedef Vector<JSFunction *, 4> FunctionVector;
struct GenericParseContext
{
@@ -201,7 +200,7 @@ struct ParseContext : public GenericParseContext
the same name. */
// All inner functions in this context. Only filled in when parsing syntax.
FunctionVector innerFunctions;
AutoFunctionVector innerFunctions;
// Set when parsing a declaration-like destructuring pattern. This flag
// causes PrimaryExpr to create PN_NAME parse nodes for variable references
@@ -258,8 +257,9 @@ enum VarContext { HoistVars, DontHoistVars };
enum FunctionType { Getter, Setter, Normal };
template <typename ParseHandler>
struct Parser : private AutoGCRooter, public StrictModeGetter
class Parser : private AutoGCRooter, public StrictModeGetter
{
public:
JSContext *const context; /* FIXME Bug 551291: use AutoGCRooter::context? */
TokenStream tokenStream;
LifoAlloc::Mark tempPoolMark;
-14
View File
@@ -56,20 +56,6 @@ EncapsulatedValue::~EncapsulatedValue()
pre();
}
inline void
EncapsulatedValue::init(const Value &v)
{
JS_ASSERT(!IsPoisonedValue(v));
value = v;
}
inline void
EncapsulatedValue::init(JSRuntime *rt, const Value &v)
{
JS_ASSERT(!IsPoisonedValue(v));
value = v;
}
inline EncapsulatedValue &
EncapsulatedValue::operator=(const Value &v)
{
+8 -2
View File
@@ -384,8 +384,14 @@ class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
}
inline ~EncapsulatedValue();
inline void init(const Value &v);
inline void init(JSRuntime *rt, const Value &v);
void init(const Value &v) {
JS_ASSERT(!IsPoisonedValue(v));
value = v;
}
void init(JSRuntime *rt, const Value &v) {
JS_ASSERT(!IsPoisonedValue(v));
value = v;
}
inline EncapsulatedValue &operator=(const Value &v);
inline EncapsulatedValue &operator=(const EncapsulatedValue &v);
+10 -1
View File
@@ -8,10 +8,13 @@
#include "mozilla/DebugOnly.h"
#include "jstypedarray.h"
#include "jit/IonCode.h"
#include "vm/Shape.h"
#include "jscompartmentinlines.h"
#include "jsinferinlines.h"
#include "gc/Nursery-inl.h"
#include "vm/Shape-inl.h"
@@ -599,6 +602,12 @@ gc::IsValueAboutToBeFinalized(Value *v)
/*** Slot Marking ***/
bool
gc::IsSlotMarked(HeapSlot *s)
{
return IsMarked(s);
}
void
gc::MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
{
@@ -1245,7 +1254,7 @@ GCMarker::restoreValueArray(JSObject *obj, void **vpp, void **endp)
HeapSlot::Kind kind = (HeapSlot::Kind) stack.pop();
if (kind == HeapSlot::Element) {
if (obj->getClass() != &ArrayClass)
if (!obj->is<ArrayObject>())
return false;
uint32_t initlen = obj->getDenseInitializedLength();
+3
View File
@@ -192,6 +192,9 @@ IsValueAboutToBeFinalized(Value *v);
/*** Slot Marking ***/
bool
IsSlotMarked(HeapSlot *s);
void
MarkSlot(JSTracer *trc, HeapSlot *s, const char *name);
+1 -1
View File
@@ -22,7 +22,7 @@ namespace gc {
*/
class RelocationOverlay
{
friend struct MinorCollectionTracer;
friend class MinorCollectionTracer;
/* The low bit is set so this should never equal a normal pointer. */
const static uintptr_t Relocated = uintptr_t(0xbad0bad1);
+24 -4
View File
@@ -48,7 +48,7 @@ js::Nursery::init()
// were marked as uncommitted, but it's a little complicated to avoid
// clobbering pre-existing unrelated mappings.
while (IsPoisonedPtr(heap) || IsPoisonedPtr((void*)(uintptr_t(heap) + NurserySize)))
heap = MapAlignedPages(NurserySize, Alignment);
heap = MapAlignedPages(runtime(), NurserySize, Alignment);
#endif
if (!heap)
return false;
@@ -58,7 +58,9 @@ js::Nursery::init()
rt->gcNurseryEnd_ = chunk(LastNurseryChunk).end();
numActiveChunks_ = 1;
setCurrentChunk(0);
#ifdef DEBUG
JS_POISON(heap, FreshNursery, NurserySize);
#endif
for (int i = 0; i < NumNurseryChunks; ++i)
chunk(i).runtime = rt;
@@ -108,7 +110,9 @@ js::Nursery::allocate(size_t size)
void *thing = (void *)position();
position_ = position() + size;
#ifdef DEBUG
JS_POISON(thing, AllocatedThing, size);
#endif
return thing;
}
@@ -216,6 +220,7 @@ class MinorCollectionTracer : public JSTracer
RelocationOverlay **tail;
/* Save and restore all of the runtime state we use during MinorGC. */
bool savedRuntimeNeedBarrier;
AutoDisableProxyCheck disableStrictProxyChecking;
/* Insert the given relocation entry into the list of things to visit. */
@@ -232,11 +237,26 @@ class MinorCollectionTracer : public JSTracer
tenuredSize(0),
head(NULL),
tail(&head),
savedRuntimeNeedBarrier(rt->needsBarrier()),
disableStrictProxyChecking(rt)
{
JS_TracerInit(this, rt, Nursery::MinorGCCallback);
eagerlyTraceWeakMaps = TraceWeakMapKeysValues;
rt->gcNumber++;
/*
* We disable the runtime needsBarrier() check so that pre-barriers do
* not fire on objects that have been relocated. The pre-barrier's
* call to obj->zone() will try to look through shape_, which is now
* the relocation magic and will crash. However, zone->needsBarrier()
* must still be set correctly so that allocations we make in minor
* GCs between incremental slices will allocate their objects marked.
*/
rt->setNeedsBarrier(false);
}
~MinorCollectionTracer() {
runtime->setNeedsBarrier(savedRuntimeNeedBarrier);
}
};
@@ -246,7 +266,7 @@ class MinorCollectionTracer : public JSTracer
static AllocKind
GetObjectAllocKindForCopy(JSRuntime *rt, JSObject *obj)
{
if (obj->isArray()) {
if (obj->is<ArrayObject>()) {
JS_ASSERT(obj->numFixedSlots() == 0);
/* Use minimal size object if we are just going to copy the pointer. */
@@ -305,7 +325,7 @@ js::Nursery::moveObjectToTenured(JSObject *dst, JSObject *src, AllocKind dstKind
* We deal with this by copying elements manually, possibly re-inlining
* them if there is adequate room inline in dst.
*/
if (src->isArray())
if (src->is<ArrayObject>())
srcSize = sizeof(ObjectImpl);
js_memcpy(dst, src, srcSize);
@@ -374,7 +394,7 @@ js::Nursery::moveElementsToTenured(JSObject *dst, JSObject *src, AllocKind dstKi
size_t nslots = ObjectElements::VALUES_PER_HEADER + srcHeader->capacity;
/* Unlike other objects, Arrays can have fixed elements. */
if (src->isArray() && nslots <= GetGCKindSlots(dstKind)) {
if (src->is<ArrayObject>() && nslots <= GetGCKindSlots(dstKind)) {
dst->setFixedElements();
dstHeader = dst->getElementsHeader();
js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot));
+6
View File
@@ -449,6 +449,12 @@ AutoGCRooter::trace(JSTracer *trc)
return;
}
case FUNVECTOR: {
AutoFunctionVector::VectorImpl &vector = static_cast<AutoFunctionVector *>(this)->vector;
MarkObjectRootRange(trc, vector.length(), vector.begin(), "js::AutoFunctionVector.vector");
return;
}
case STRINGVECTOR: {
AutoStringVector::VectorImpl &vector = static_cast<AutoStringVector *>(this)->vector;
MarkStringRootRange(trc, vector.length(), vector.begin(), "js::AutoStringVector.vector");
+9 -3
View File
@@ -6,11 +6,13 @@
#ifdef JSGC_GENERATIONAL
#include "jsgc.h"
#include "gc/StoreBuffer.h"
#include "mozilla/Assertions.h"
#include "vm/ForkJoin.h"
#include "gc/Barrier-inl.h"
#include "gc/StoreBuffer.h"
#include "vm/ForkJoin.h"
#include "vm/ObjectImpl-inl.h"
using namespace js;
@@ -64,8 +66,12 @@ StoreBuffer::WholeCellEdges::mark(JSTracer *trc)
MarkChildren(trc, static_cast<JSObject *>(tenured));
return;
}
#ifdef JS_ION
JS_ASSERT(kind == JSTRACE_IONCODE);
static_cast<jit::IonCode *>(tenured)->trace(trc);
#else
MOZ_NOT_REACHED("Only objects can be in the wholeCellBuffer if IonMonkey is disabled.");
#endif
}
/*** MonoTypeBuffer ***/
+3 -1
View File
@@ -13,10 +13,12 @@
# error "Generational GC requires exact rooting."
#endif
#include "jsgc.h"
#include "jsalloc.h"
#include "jsgc.h"
#include "jsobj.h"
#include "gc/Nursery.h"
namespace js {
namespace gc {
+61
View File
@@ -21,6 +21,67 @@ if (typeof assertThrowsInstanceOf === 'undefined') {
};
}
if (typeof assertWarning === 'undefined') {
var assertWarning = function assertWarning(f, errorClass, msg) {
var hadWerror = options().split(",").indexOf("werror") !== -1;
// Ensure the "werror" option is disabled.
if (hadWerror)
options("werror");
try {
f();
} catch (exc) {
if (hadWerror)
options("werror");
// print() rather than throw a different exception value, in case
// the caller wants exc.stack.
if (msg)
print("assertWarning: " + msg);
print("assertWarning: Unexpected exception calling " + f +
" with warnings-as-errors disabled");
throw exc;
}
// Enable the "werror" option.
options("werror");
try {
assertThrowsInstanceOf(f, errorClass, msg);
} catch (exc) {
if (msg)
print("assertWarning: " + msg);
throw exc;
} finally {
if (!hadWerror)
options("werror");
}
};
}
if (typeof assertNoWarning === 'undefined') {
var assertNoWarning = function assertWarning(f, msg) {
// Ensure the "werror" option is enabled.
var hadWerror = options().split(",").indexOf("werror") !== -1;
if (!hadWerror)
options("werror");
try {
f();
} catch (exc) {
if (msg)
print("assertNoWarning: " + msg);
print("assertNoWarning: Unexpected exception calling " + f +
"with warnings-as-errors enabled");
throw exc;
} finally {
if (!hadWerror)
options("werror");
}
};
}
if (typeof assertThrowsValue === 'undefined') {
var assertThrowsValue = function assertThrowsValue(f, val, msg) {
var fullmsg;
@@ -3,6 +3,8 @@ load(libdir + 'asm.js');
assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=0; e=d; return +e } return f');
assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=1e1; e=d; return +e } return f');
assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=+0; e=d; return +e } return f');
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var e=-0; return +e } return f'))(-0), -0);
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var e=-0.0; return +e } return f'))(-0), -0);
assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=0.0; e=d; return +e } return f'))(0.1), 0.1);
assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-0.0; e=d; return +e } return f'))(0.1), 0.1);
assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=10.0; e=d; return +e } return f'))(0.1), 0.1);
+14
View File
@@ -0,0 +1,14 @@
var x = {};
function f() { y.prop; }
x.toStr = function () { f(); };
try {
f();
} catch (e) { }
try {
x.toStr();
} catch (e) { }
try {
function f() { which = 2; }
x.toStr();
} catch (e) { which = 1; }
assertEq(which, 2);
+8
View File
@@ -0,0 +1,8 @@
if (this.hasOwnProperty('Intl')) {
gc();
gcslice(0);
var thisValues = [ "x" ];
thisValues.forEach(function (value) {
var format = Intl.DateTimeFormat.call(value);
});
}
+7
View File
@@ -0,0 +1,7 @@
gc();
gcslice(0);
function isClone(a, b) {
var rmemory = new WeakMap();
rmemory.set(a,b);
}
isClone([]);
@@ -0,0 +1 @@
if (Math["key"]) {}
@@ -0,0 +1,22 @@
// yield without an operand causes a warning. See bug 885463.
load(libdir + "asserts.js");
assertWarning(() => Function("yield"), SyntaxError,
"yield followed by EOF should cause a warning");
assertWarning(() => Function("yield;"), SyntaxError,
"yield followed by semicolon should cause a warning");
assertWarning(() => Function("yield\n print('ok');"), SyntaxError,
"yield followed by newline should cause a warning");
assertWarning(() => eval("(function () { yield; })"), SyntaxError,
"yield followed by semicolon in eval code should cause a warning");
assertWarning(() => eval("(function () { yield })"), SyntaxError,
"yield followed by } in eval code should cause a warning");
assertNoWarning(() => Function("yield 0;"),
"yield with an operand should be fine");
assertNoWarning(() => Function("yield 0"),
"yield with an operand should be fine, even without a semicolon");
print("\npassed - all those warnings are normal and there's no real way to suppress them");
+1 -3
View File
@@ -697,12 +697,10 @@ ExtractNumericLiteral(ParseNode *pn)
d = NumberNodeValue(numberNode);
}
if (NumberNodeHasFrac(numberNode))
if (NumberNodeHasFrac(numberNode) || IsNegativeZero(d))
return NumLit(NumLit::Double, DoubleValue(d));
int64_t i64 = int64_t(d);
if (d != double(i64))
return NumLit(NumLit::OutOfRangeInt, UndefinedValue());
if (i64 >= 0) {
if (i64 <= INT32_MAX)
+1 -1
View File
@@ -17,7 +17,7 @@ namespace js {
class ScriptSource;
class SPSProfiler;
class AsmJSModule;
namespace frontend { struct TokenStream; struct ParseNode; }
namespace frontend { class TokenStream; class ParseNode; }
namespace jit { class MIRGenerator; class LIRGraph; }
// Called after parsing a function 'fn' which contains the "use asm" directive.
-5
View File
@@ -2744,11 +2744,6 @@ BaselineCompiler::emit_JSOP_REST()
{
frame.syncStack(0);
RootedTypeObject type(cx, types::TypeScript::InitObject(cx, script, pc, JSProto_Array));
if (!type)
return false;
masm.movePtr(ImmGCPtr(type), R0.scratchReg());
ICRest_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
+5 -13
View File
@@ -2352,7 +2352,7 @@ DoToNumberFallback(JSContext *cx, ICToNumber_Fallback *stub, HandleValue arg, Mu
{
FallbackICSpew(cx, stub, "ToNumber");
ret.set(arg);
return ToNumber(cx, ret.address());
return ToNumber(cx, ret);
}
typedef bool (*DoToNumberFallbackFn)(JSContext *, ICToNumber_Fallback *, HandleValue, MutableHandleValue);
@@ -5176,7 +5176,7 @@ TryAttachLengthStub(JSContext *cx, HandleScript script, ICGetProp_Fallback *stub
RootedObject obj(cx, &val.toObject());
if (obj->isArray() && res.isInt32()) {
if (obj->is<ArrayObject>() && res.isInt32()) {
IonSpew(IonSpew_BaselineIC, " Generating GetProp(Array.length) stub");
ICGetProp_ArrayLength::Compiler compiler(cx);
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
@@ -5531,7 +5531,7 @@ ICGetProp_ArrayLength::Compiler::generateStubCode(MacroAssembler &masm)
// Unbox R0 and guard it's an array.
Register obj = masm.extractObject(R0, ExtractTemp0);
masm.branchTestObjClass(Assembler::NotEqual, obj, scratch, &ArrayClass, &failure);
masm.branchTestObjClass(Assembler::NotEqual, obj, scratch, &ArrayObject::class_, &failure);
// Load obj->elements->length.
masm.loadPtr(Address(obj, JSObject::offsetOfElements()), scratch);
@@ -8158,7 +8158,7 @@ ICTypeOf_Typed::Compiler::generateStubCode(MacroAssembler &masm)
static bool
DoCreateRestParameter(JSContext *cx, BaselineFrame *frame, ICRest_Fallback *stub,
HandleTypeObject type, MutableHandleValue res)
MutableHandleValue res)
{
FallbackICSpew(cx, stub, "Rest");
@@ -8170,19 +8170,12 @@ DoCreateRestParameter(JSContext *cx, BaselineFrame *frame, ICRest_Fallback *stub
JSObject *obj = NewDenseCopiedArray(cx, numRest, rest, NULL);
if (!obj)
return false;
obj->setType(type);
// Ensure that values in the rest array are represented in the type of the
// array.
for (unsigned i = 0; i < numRest; i++)
types::AddTypePropertyId(cx, obj, JSID_VOID, rest[i]);
res.setObject(*obj);
return true;
}
typedef bool(*DoCreateRestParameterFn)(JSContext *cx, BaselineFrame *, ICRest_Fallback *,
HandleTypeObject, MutableHandleValue);
MutableHandleValue);
static const VMFunction DoCreateRestParameterInfo =
FunctionInfo<DoCreateRestParameterFn>(DoCreateRestParameter);
@@ -8191,7 +8184,6 @@ ICRest_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
{
EmitRestoreTailCallReg(masm);
masm.push(R0.scratchReg()); // type
masm.push(BaselineStubReg); // stub
masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg()); // frame pointer
+1 -1
View File
@@ -24,7 +24,7 @@ namespace js {
namespace jit {
class StackValue;
struct ICEntry;
class ICEntry;
class ICStub;
class PCMappingSlotInfo
+1 -1
View File
@@ -22,7 +22,7 @@
#include "builtin/Eval.h"
#include "gc/Nursery.h"
#include "vm/ForkJoin.h"
#include "ParallelArrayAnalysis.h"
#include "ParallelSafetyAnalysis.h"
#include "jsscriptinlines.h"
+7 -7
View File
@@ -21,7 +21,7 @@
#include "EdgeCaseAnalysis.h"
#include "RangeAnalysis.h"
#include "LinearScan.h"
#include "ParallelArrayAnalysis.h"
#include "ParallelSafetyAnalysis.h"
#include "jscompartment.h"
#include "vm/ThreadPool.h"
#include "vm/ForkJoin.h"
@@ -1008,6 +1008,12 @@ OptimizeMIR(MIRGenerator *mir)
if (mir->shouldCancel("Apply types"))
return false;
if (graph.entryBlock()->info().executionMode() == ParallelExecution) {
ParallelSafetyAnalysis analysis(mir, graph);
if (!analysis.analyze())
return false;
}
// Alias analysis is required for LICM and GVN so that we don't move
// loads across stores.
if (js_IonOptions.licm || js_IonOptions.gvn) {
@@ -1146,12 +1152,6 @@ OptimizeMIR(MIRGenerator *mir)
IonSpewPass("Bounds Check Elimination");
AssertGraphCoherency(graph);
if (graph.entryBlock()->info().executionMode() == ParallelExecution) {
ParallelArrayAnalysis analysis(mir, graph);
if (!analysis.analyze())
return false;
}
return true;
}
+49 -55
View File
@@ -4153,10 +4153,7 @@ IonBuilder::inlineCalls(CallInfo &callInfo, AutoObjectVector &targets,
return false;
// Create a function MConstant to use in the entry ResumePoint.
// Note that guarding is on the original function pointer even
// if there is a clone, since cloning occurs at the callsite.
JSFunction *original = &originals[i]->as<JSFunction>();
MConstant *funcDef = MConstant::New(ObjectValue(*original));
MConstant *funcDef = MConstant::New(ObjectValue(*target));
funcDef->setFoldedUnchecked();
dispatchBlock->add(funcDef);
@@ -4203,7 +4200,10 @@ IonBuilder::inlineCalls(CallInfo &callInfo, AutoObjectVector &targets,
setCurrent(dispatchBlock);
// Connect the inline path to the returnBlock.
dispatch->addCase(original, inlineBlock);
//
// Note that guarding is on the original function pointer even
// if there is a clone, since cloning occurs at the callsite.
dispatch->addCase(&originals[i]->as<JSFunction>(), inlineBlock);
MDefinition *retVal = inlineReturnBlock->peek(-1);
retPhi->addInput(retVal);
@@ -6899,7 +6899,7 @@ IonBuilder::jsop_length_fastPath()
types::StackTypeSet *objTypes = obj->resultTypeSet();
if (objTypes &&
objTypes->getKnownClass() == &ArrayClass &&
objTypes->getKnownClass() == &ArrayObject::class_ &&
!objTypes->hasObjectFlags(cx, types::OBJECT_FLAG_LENGTH_OVERFLOW))
{
current->pop();
@@ -6959,33 +6959,55 @@ IonBuilder::jsop_arguments_length()
bool
IonBuilder::jsop_arguments_getelem()
{
if (inliningDepth_ != 0)
return abort("NYI inlined get argument element");
JS_ASSERT(!info().argsObjAliasesFormals());
// Get the argument id
MDefinition *idx = current->pop();
// Type Inference has guaranteed this is an optimized arguments object.
MDefinition *args = current->pop();
args->setFoldedUnchecked();
// To ensure that we are not looking above the number of actual arguments.
MArgumentsLength *length = MArgumentsLength::New();
current->add(length);
// Ensure idx is an integer.
MInstruction *index = MToInt32::New(idx);
current->add(index);
// When we are not inlining, we can just get the arguments from the stack.
if (inliningDepth_ == 0) {
// To ensure that we are not looking above the number of actual arguments.
MArgumentsLength *length = MArgumentsLength::New();
current->add(length);
// Bailouts if we read more than the number of actual arguments.
index = addBoundsCheck(index, length);
// Ensure idx is an integer.
MInstruction *index = MToInt32::New(idx);
current->add(index);
// Load the argument from the actual arguments.
MGetArgument *load = MGetArgument::New(index);
current->add(load);
current->push(load);
// Bailouts if we read more than the number of actual arguments.
index = addBoundsCheck(index, length);
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
return pushTypeBarrier(load, types, true);
// Load the argument from the actual arguments.
MGetArgument *load = MGetArgument::New(index);
current->add(load);
current->push(load);
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
return pushTypeBarrier(load, types, true);
}
// When the id is constant, we can just return the corresponding inlined argument
if (idx->isConstant() && idx->toConstant()->value().isInt32()) {
JS_ASSERT(inliningDepth_ > 0);
int32_t id = idx->toConstant()->value().toInt32();
idx->setFoldedUnchecked();
if (id < (int32_t)inlineCallInfo_->argc() && id >= 0)
current->push(inlineCallInfo_->getArg(id));
else
pushConstant(UndefinedValue());
return true;
}
// inlined not constant not supported, yet.
return abort("NYI inlined not constant get argument element");
}
bool
@@ -6999,8 +7021,8 @@ IonBuilder::jsop_rest()
{
// We don't know anything about the callee.
if (inliningDepth_ == 0) {
// Get an empty template array.
JSObject *templateObject = getNewArrayTemplateObject(0);
// Get an empty template array that doesn't have a pc-tracked type.
JSObject *templateObject = NewDenseUnallocatedArray(cx, 0, NULL, TenuredObject);
if (!templateObject)
return false;
@@ -7019,7 +7041,7 @@ IonBuilder::jsop_rest()
unsigned numActuals = inlineCallInfo_->argv().length();
unsigned numFormals = info().nargs() - 1;
unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
JSObject *templateObject = getNewArrayTemplateObject(numRest);
JSObject *templateObject = NewDenseUnallocatedArray(cx, numRest, NULL, TenuredObject);
MNewArray *array = new MNewArray(numRest, templateObject, MNewArray::NewArray_Allocating);
current->add(array);
@@ -7032,15 +7054,6 @@ IonBuilder::jsop_rest()
MElements *elements = MElements::New(array);
current->add(elements);
types::TypeObject *arrayType = templateObject->type();
types::HeapTypeSet *elemTypes = NULL;
Vector<MInstruction *> setElemCalls(cx);
if (!arrayType->unknownProperties()) {
elemTypes = arrayType->getProperty(cx, JSID_VOID, false);
if (!elemTypes)
return false;
}
// Unroll the argument copy loop. We don't need to do any bounds or hole
// checking here.
MConstant *index;
@@ -7048,35 +7061,16 @@ IonBuilder::jsop_rest()
index = MConstant::New(Int32Value(i - numFormals));
current->add(index);
MInstruction *store;
MDefinition *arg = inlineCallInfo_->argv()[i];
if (elemTypes && !TypeSetIncludes(elemTypes, arg->type(), arg->resultTypeSet())) {
elemTypes->addFreeze(cx);
store = MCallSetElement::New(array, index, arg);
if (!setElemCalls.append(store))
return false;
} else {
store = MStoreElement::New(elements, index, arg, /* needsHoleCheck = */ false);
}
MStoreElement *store = MStoreElement::New(elements, index, arg,
/* needsHoleCheck = */ false);
current->add(store);
}
MSetInitializedLength *initLength = MSetInitializedLength::New(elements, index);
current->add(initLength);
current->push(array);
// The reason this loop of resumeAfters is here and not above is because
// resume points check the stack depth at its callsite in IonBuilder
// matches the expected stack depth at the point where we would bail back
// to in the interpreter. So we can't call resumeAfter until after we have
// pushed the array onto the stack.
for (unsigned i = 0; i < setElemCalls.length(); i++) {
if (!resumeAfter(setElemCalls[i]))
return false;
}
return true;
}
+1 -1
View File
@@ -720,7 +720,7 @@ class CallInfo
return args_;
}
MDefinition *getArg(uint32_t i) {
MDefinition *getArg(uint32_t i) const {
JS_ASSERT(i < argc());
return args_[i];
}
+5 -6
View File
@@ -1176,7 +1176,7 @@ GetPropertyIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj,
bool
GetPropertyIC::attachArrayLength(JSContext *cx, IonScript *ion, JSObject *obj)
{
JS_ASSERT(obj->isArray());
JS_ASSERT(obj->is<ArrayObject>());
JS_ASSERT(!idempotent());
Label failures;
@@ -1440,7 +1440,7 @@ TryAttachNativeGetPropStub(JSContext *cx, IonScript *ion,
if (readSlot)
return cache.attachReadSlot(cx, ion, obj, holder, shape);
else if (obj->isArray() && !cache.hasArrayLengthStub() && cx->names().length == name)
else if (obj->is<ArrayObject>() && !cache.hasArrayLengthStub() && cx->names().length == name)
return cache.attachArrayLength(cx, ion, obj);
return cache.attachCallGetter(cx, ion, obj, holder, shape, safepointIndex, returnAddr);
}
@@ -2613,7 +2613,7 @@ GetElementIC::reset()
static bool
IsElementSetInlineable(HandleObject obj, HandleValue index)
{
if (!obj->isArray())
if (!obj->is<ArrayObject>())
return false;
if (obj->watched())
@@ -3057,11 +3057,10 @@ CallsiteCloneIC::attach(JSContext *cx, IonScript *ion, HandleFunction original,
RepatchStubAppender attacher(*this);
// Guard against object identity on the original.
attacher.branchNextStub(masm, Assembler::NotEqual, calleeReg(),
ImmWord(uintptr_t(original.get())));
attacher.branchNextStub(masm, Assembler::NotEqual, calleeReg(), ImmGCPtr(original));
// Load the clone.
masm.movePtr(ImmWord(uintptr_t(clone.get())), outputReg());
masm.movePtr(ImmGCPtr(clone), outputReg());
attacher.jumpRejoin(masm);
+1 -1
View File
@@ -66,7 +66,7 @@ typedef Vector<IonBuilder*, 0, SystemAllocPolicy> OffThreadCompilationVector;
// Optimized stubs are allocated per-compartment and are always purged when
// JIT-code is discarded. Fallback stubs are allocated per BaselineScript and
// are only destroyed when the BaselineScript is destroyed.
struct ICStubSpace
class ICStubSpace
{
protected:
LifoAlloc allocator_;
+2 -2
View File
@@ -580,7 +580,7 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
storePtr(ImmGCPtr(templateObject->type()), Address(obj, JSObject::offsetOfType()));
storePtr(ImmWord((void *)NULL), Address(obj, JSObject::offsetOfSlots()));
if (templateObject->isArray()) {
if (templateObject->is<ArrayObject>()) {
JS_ASSERT(!templateObject->getDenseInitializedLength());
int elementsOffset = JSObject::offsetOfFixedElements();
@@ -594,7 +594,7 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
Address(obj, elementsOffset + ObjectElements::offsetOfCapacity()));
store32(Imm32(templateObject->getDenseInitializedLength()),
Address(obj, elementsOffset + ObjectElements::offsetOfInitializedLength()));
store32(Imm32(templateObject->getArrayLength()),
store32(Imm32(templateObject->as<ArrayObject>().length()),
Address(obj, elementsOffset + ObjectElements::offsetOfLength()));
store32(Imm32(templateObject->shouldConvertDoubleElements()
? ObjectElements::CONVERT_DOUBLE_ELEMENTS
+4 -4
View File
@@ -310,7 +310,7 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
types::OBJECT_FLAG_ITERATED;
types::StackTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
if (!thisTypes || thisTypes->getKnownClass() != &ArrayClass)
if (!thisTypes || thisTypes->getKnownClass() != &ArrayObject::class_)
return InliningStatus_NotInlined;
if (thisTypes->hasObjectFlags(cx, unhandledFlags))
return InliningStatus_NotInlined;
@@ -361,7 +361,7 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
return InliningStatus_NotInlined;
types::StackTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
if (!thisTypes || thisTypes->getKnownClass() != &ArrayClass)
if (!thisTypes || thisTypes->getKnownClass() != &ArrayObject::class_)
return InliningStatus_NotInlined;
if (thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES |
types::OBJECT_FLAG_LENGTH_OVERFLOW))
@@ -419,7 +419,7 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
if (!thisTypes || !argTypes)
return InliningStatus_NotInlined;
if (thisTypes->getKnownClass() != &ArrayClass)
if (thisTypes->getKnownClass() != &ArrayObject::class_)
return InliningStatus_NotInlined;
if (thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES |
types::OBJECT_FLAG_LENGTH_OVERFLOW))
@@ -427,7 +427,7 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
return InliningStatus_NotInlined;
}
if (argTypes->getKnownClass() != &ArrayClass)
if (argTypes->getKnownClass() != &ArrayObject::class_)
return InliningStatus_NotInlined;
if (argTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES |
types::OBJECT_FLAG_LENGTH_OVERFLOW))
+1 -1
View File
@@ -175,7 +175,7 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
// Replaces an edge for a given block with a new block. This is
// used for critical edge splitting and also for inserting
// bailouts during ParallelArrayAnalysis.
// bailouts during ParallelSafetyAnalysis.
//
// Note: If successorWithPhis is set, you must not be replacing it.
void replacePredecessor(MBasicBlock *old, MBasicBlock *split);
+1 -2
View File
@@ -466,10 +466,9 @@ jit::InitRestParameter(ForkJoinSlice *slice, uint32_t length, Value *rest,
// before this point. We can do the allocation here like in the sequential
// path, but duplicating the initGCThing logic is too tedious.
JS_ASSERT(res);
JS_ASSERT(res->isArray());
JS_ASSERT(res->is<ArrayObject>());
JS_ASSERT(!res->getDenseInitializedLength());
JS_ASSERT(res->type() == templateObj->type());
// See note in visitRest in ParallelArrayAnalysis.
JS_ASSERT(res->type()->unknownProperties());
if (length) {
@@ -9,15 +9,15 @@
#include "Ion.h"
#include "MIR.h"
#include "MIRGraph.h"
#include "ParallelArrayAnalysis.h"
#include "ParallelSafetyAnalysis.h"
#include "IonSpewer.h"
#include "UnreachableCodeElimination.h"
#include "IonAnalysis.h"
#include "vm/Stack.h"
namespace js {
namespace jit {
using namespace js;
using namespace jit;
using parallel::Spew;
using parallel::SpewMIR;
@@ -63,9 +63,8 @@ using parallel::SpewCompile;
return insertWriteGuard(prop, prop->obj()); \
}
class ParallelArrayVisitor : public MInstructionVisitor
class ParallelSafetyVisitor : public MInstructionVisitor
{
JSContext *cx_;
MIRGraph &graph_;
bool unsafe_;
MDefinition *parSlice_;
@@ -91,9 +90,8 @@ class ParallelArrayVisitor : public MInstructionVisitor
}
public:
ParallelArrayVisitor(JSContext *cx, MIRGraph &graph)
: cx_(cx),
graph_(graph),
ParallelSafetyVisitor(MIRGraph &graph)
: graph_(graph),
unsafe_(false),
parSlice_(NULL)
{ }
@@ -116,7 +114,7 @@ class ParallelArrayVisitor : public MInstructionVisitor
SAFE_OP(Callee)
SAFE_OP(TableSwitch)
SAFE_OP(Goto)
CUSTOM_OP(Test)
SAFE_OP(Test)
SAFE_OP(Compare)
SAFE_OP(Phi)
SAFE_OP(Beta)
@@ -300,7 +298,7 @@ class ParallelArrayVisitor : public MInstructionVisitor
};
bool
ParallelArrayAnalysis::analyze()
ParallelSafetyAnalysis::analyze()
{
// Walk the basic blocks in a DFS. When we encounter a block with an
// unsafe instruction, then we know that this block will bailout when
@@ -309,12 +307,11 @@ ParallelArrayAnalysis::analyze()
// We don't need a worklist, though, because the graph is sorted
// in RPO. Therefore, we just use the marked flags to tell us
// when we visited some predecessor of the current block.
JSContext *cx = GetIonContext()->cx;
ParallelArrayVisitor visitor(cx, graph_);
ParallelSafetyVisitor visitor(graph_);
graph_.entryBlock()->mark(); // Note: in par. exec., we never enter from OSR.
uint32_t marked = 0;
for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
if (mir_->shouldCancel("ParallelArrayAnalysis"))
if (mir_->shouldCancel("ParallelSafetyAnalysis"))
return false;
if (block->isMarked()) {
@@ -326,7 +323,7 @@ ParallelArrayAnalysis::analyze()
for (MInstructionIterator ins(block->begin());
ins != block->end() && !visitor.unsafe();)
{
if (mir_->shouldCancel("ParallelArrayAnalysis"))
if (mir_->shouldCancel("ParallelSafetyAnalysis"))
return false;
// We may be removing or replacing the current
@@ -370,12 +367,12 @@ ParallelArrayAnalysis::analyze()
}
Spew(SpewCompile, "Safe");
IonSpewPass("ParallelArrayAnalysis");
IonSpewPass("ParallelSafetyAnalysis");
UnreachableCodeElimination uce(mir_, graph_);
if (!uce.removeUnmarkedBlocks(marked))
return false;
IonSpewPass("UCEAfterParallelArrayAnalysis");
IonSpewPass("UCEAfterParallelSafetyAnalysis");
AssertExtendedGraphCoherency(graph_);
if (!removeResumePointOperands())
@@ -383,16 +380,11 @@ ParallelArrayAnalysis::analyze()
IonSpewPass("RemoveResumePointOperands");
AssertExtendedGraphCoherency(graph_);
if (!EliminateDeadCode(mir_, graph_))
return false;
IonSpewPass("DCEAfterParallelArrayAnalysis");
AssertExtendedGraphCoherency(graph_);
return true;
}
bool
ParallelArrayAnalysis::removeResumePointOperands()
ParallelSafetyAnalysis::removeResumePointOperands()
{
// In parallel exec mode, nothing is effectful, therefore we do
// not need to reconstruct interpreter state and can simply
@@ -432,21 +424,15 @@ ParallelArrayAnalysis::removeResumePointOperands()
}
void
ParallelArrayAnalysis::replaceOperandsOnResumePoint(MResumePoint *resumePoint,
MDefinition *withDef)
ParallelSafetyAnalysis::replaceOperandsOnResumePoint(MResumePoint *resumePoint,
MDefinition *withDef)
{
for (size_t i = 0; i < resumePoint->numOperands(); i++)
resumePoint->replaceOperand(i, withDef);
}
bool
ParallelArrayVisitor::visitTest(MTest *)
{
return true;
}
bool
ParallelArrayVisitor::convertToBailout(MBasicBlock *block, MInstruction *ins)
ParallelSafetyVisitor::convertToBailout(MBasicBlock *block, MInstruction *ins)
{
JS_ASSERT(unsafe()); // `block` must have contained unsafe items
JS_ASSERT(block->isMarked()); // `block` must have been reachable to get here
@@ -506,7 +492,7 @@ ParallelArrayVisitor::convertToBailout(MBasicBlock *block, MInstruction *ins)
// These allocations will take place using per-helper-thread arenas.
bool
ParallelArrayVisitor::visitNewParallelArray(MNewParallelArray *ins)
ParallelSafetyVisitor::visitNewParallelArray(MNewParallelArray *ins)
{
MParNew *parNew = new MParNew(parSlice(), ins->templateObject());
replace(ins, parNew);
@@ -514,7 +500,7 @@ ParallelArrayVisitor::visitNewParallelArray(MNewParallelArray *ins)
}
bool
ParallelArrayVisitor::visitNewCallObject(MNewCallObject *ins)
ParallelSafetyVisitor::visitNewCallObject(MNewCallObject *ins)
{
// fast path: replace with ParNewCallObject op
MParNewCallObject *parNewCallObjectInstruction =
@@ -524,7 +510,7 @@ ParallelArrayVisitor::visitNewCallObject(MNewCallObject *ins)
}
bool
ParallelArrayVisitor::visitLambda(MLambda *ins)
ParallelSafetyVisitor::visitLambda(MLambda *ins)
{
if (ins->fun()->hasSingletonType() ||
types::UseNewTypeForClone(ins->fun()))
@@ -540,7 +526,7 @@ ParallelArrayVisitor::visitLambda(MLambda *ins)
}
bool
ParallelArrayVisitor::visitNewObject(MNewObject *newInstruction)
ParallelSafetyVisitor::visitNewObject(MNewObject *newInstruction)
{
if (newInstruction->shouldUseVM()) {
SpewMIR(newInstruction, "should use VM");
@@ -552,7 +538,7 @@ ParallelArrayVisitor::visitNewObject(MNewObject *newInstruction)
}
bool
ParallelArrayVisitor::visitNewArray(MNewArray *newInstruction)
ParallelSafetyVisitor::visitNewArray(MNewArray *newInstruction)
{
if (newInstruction->shouldUseVM()) {
SpewMIR(newInstruction, "should use VM");
@@ -564,24 +550,14 @@ ParallelArrayVisitor::visitNewArray(MNewArray *newInstruction)
}
bool
ParallelArrayVisitor::visitRest(MRest *ins)
ParallelSafetyVisitor::visitRest(MRest *ins)
{
// Construct a new template object that has a generic type object and not
// a pc-tracked one. This is because we cannot ensure that the arguments
// array's element types to contain the argument types in a threadsafe
// manner, so we might as well just not track its element types so that we
// can stay parallel.
JSObject *templateObj = NewDenseUnallocatedArray(cx_, 0, NULL, TenuredObject);
if (!templateObj)
return false;
return replace(ins, MParRest::New(parSlice(), ins->numActuals(),
ins->numFormals(), templateObj));
return replace(ins, MParRest::New(parSlice(), ins));
}
bool
ParallelArrayVisitor::replaceWithParNew(MInstruction *newInstruction,
JSObject *templateObject)
ParallelSafetyVisitor::replaceWithParNew(MInstruction *newInstruction,
JSObject *templateObject)
{
MParNew *parNewInstruction = new MParNew(parSlice(), templateObject);
replace(newInstruction, parNewInstruction);
@@ -589,8 +565,8 @@ ParallelArrayVisitor::replaceWithParNew(MInstruction *newInstruction,
}
bool
ParallelArrayVisitor::replace(MInstruction *oldInstruction,
MInstruction *replacementInstruction)
ParallelSafetyVisitor::replace(MInstruction *oldInstruction,
MInstruction *replacementInstruction)
{
MBasicBlock *block = oldInstruction->block();
block->insertBefore(oldInstruction, replacementInstruction);
@@ -610,8 +586,8 @@ ParallelArrayVisitor::replace(MInstruction *oldInstruction,
// per-thread-arena or not.
bool
ParallelArrayVisitor::insertWriteGuard(MInstruction *writeInstruction,
MDefinition *valueBeingWritten)
ParallelSafetyVisitor::insertWriteGuard(MInstruction *writeInstruction,
MDefinition *valueBeingWritten)
{
// Many of the write operations do not take the JS object
// but rather something derived from it, such as the elements.
@@ -689,7 +665,7 @@ ParallelArrayVisitor::insertWriteGuard(MInstruction *writeInstruction,
// Ion compiled. If a function has no IonScript, we bail out.
bool
ParallelArrayVisitor::visitCall(MCall *ins)
ParallelSafetyVisitor::visitCall(MCall *ins)
{
// DOM? Scary.
if (ins->isDOMFunction()) {
@@ -697,7 +673,7 @@ ParallelArrayVisitor::visitCall(MCall *ins)
return markUnsafe();
}
RootedFunction target(cx_, ins->getSingleTarget());
JSFunction *target = ins->getSingleTarget();
if (target) {
// Native? Scary.
if (target->isNative()) {
@@ -724,14 +700,14 @@ ParallelArrayVisitor::visitCall(MCall *ins)
// Similar considerations apply to checking for interrupts.
bool
ParallelArrayVisitor::visitCheckOverRecursed(MCheckOverRecursed *ins)
ParallelSafetyVisitor::visitCheckOverRecursed(MCheckOverRecursed *ins)
{
MParCheckOverRecursed *replacement = new MParCheckOverRecursed(parSlice());
return replace(ins, replacement);
}
bool
ParallelArrayVisitor::visitInterruptCheck(MInterruptCheck *ins)
ParallelSafetyVisitor::visitInterruptCheck(MInterruptCheck *ins)
{
MParCheckInterrupt *replacement = new MParCheckInterrupt(parSlice());
return replace(ins, replacement);
@@ -747,8 +723,8 @@ ParallelArrayVisitor::visitInterruptCheck(MInterruptCheck *ins)
// if the operands are not both integers/floats.
bool
ParallelArrayVisitor::visitSpecializedInstruction(MInstruction *ins, MIRType spec,
uint32_t flags)
ParallelSafetyVisitor::visitSpecializedInstruction(MInstruction *ins, MIRType spec,
uint32_t flags)
{
uint32_t flag = 1 << spec;
if (flags & flag)
@@ -762,7 +738,7 @@ ParallelArrayVisitor::visitSpecializedInstruction(MInstruction *ins, MIRType spe
// Throw
bool
ParallelArrayVisitor::visitThrow(MThrow *thr)
ParallelSafetyVisitor::visitThrow(MThrow *thr)
{
MBasicBlock *block = thr->block();
JS_ASSERT(block->lastIns() == thr);
@@ -790,7 +766,7 @@ static bool
AddCallTarget(HandleScript script, CallTargetVector &targets);
bool
AddPossibleCallees(MIRGraph &graph, CallTargetVector &targets)
jit::AddPossibleCallees(MIRGraph &graph, CallTargetVector &targets)
{
JSContext *cx = GetIonContext()->cx;
@@ -889,6 +865,3 @@ AddCallTarget(HandleScript script, CallTargetVector &targets)
return true;
}
}
}
@@ -4,8 +4,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_ParallelArrayAnalysis_h
#define jit_ParallelArrayAnalysis_h
#ifndef ion_ParallelSafetyAnalysis_h
#define ion_ParallelSafetyAnalysis_h
#include "MIR.h"
#include "CompileInfo.h"
@@ -22,7 +22,7 @@ class AutoDestroyAllocator;
// Determines whether a function is compatible for parallel execution.
// Removes basic blocks containing unsafe MIR operations from the
// graph and replaces them with MParBailout blocks.
class ParallelArrayAnalysis
class ParallelSafetyAnalysis
{
MIRGenerator *mir_;
MIRGraph &graph_;
@@ -31,8 +31,8 @@ class ParallelArrayAnalysis
void replaceOperandsOnResumePoint(MResumePoint *resumePoint, MDefinition *withDef);
public:
ParallelArrayAnalysis(MIRGenerator *mir,
MIRGraph &graph)
ParallelSafetyAnalysis(MIRGenerator *mir,
MIRGraph &graph)
: mir_(mir),
graph_(graph)
{}
@@ -52,4 +52,4 @@ bool AddPossibleCallees(MIRGraph &graph, CallTargetVector &targets);
} // namespace jit
} // namespace js
#endif /* jit_ParallelArrayAnalysis_h */
#endif /* ion_ParallelSafetyAnalysis_h */
+25 -35
View File
@@ -10,6 +10,7 @@
#include "jit/BaselineIC.h"
#include "jit/IonFrames.h"
#include "vm/ArrayObject.h"
#include "vm/Debugger.h"
#include "vm/Interpreter.h"
#include "vm/StringObject-inl.h"
@@ -309,7 +310,7 @@ NewInitObjectWithClassPrototype(JSContext *cx, HandleObject templateObject)
bool
ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
{
JS_ASSERT(obj->isArray());
JS_ASSERT(obj->is<ArrayObject>());
AutoDetectInvalidation adi(cx, rval.address());
@@ -329,7 +330,7 @@ ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
bool
ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length)
{
JS_ASSERT(obj->isArray());
JS_ASSERT(obj->is<ArrayObject>());
Value argv[] = { UndefinedValue(), ObjectValue(*obj), v };
AutoValueArray ava(cx, argv, 3);
@@ -343,7 +344,7 @@ ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length)
bool
ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
{
JS_ASSERT(obj->isArray());
JS_ASSERT(obj->is<ArrayObject>());
AutoDetectInvalidation adi(cx, rval.address());
@@ -361,20 +362,20 @@ ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
}
JSObject *
ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject res)
ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject objRes)
{
JS_ASSERT(obj1->isArray());
JS_ASSERT(obj2->isArray());
JS_ASSERT_IF(res, res->isArray());
Rooted<ArrayObject*> arr1(cx, &obj1->as<ArrayObject>());
Rooted<ArrayObject*> arr2(cx, &obj2->as<ArrayObject>());
Rooted<ArrayObject*> arrRes(cx, objRes ? &objRes->as<ArrayObject>() : NULL);
if (res) {
if (arrRes) {
// Fast path if we managed to allocate an object inline.
if (!js::array_concat_dense(cx, obj1, obj2, res))
if (!js::array_concat_dense(cx, arr1, arr2, arrRes))
return NULL;
return res;
return arrRes;
}
Value argv[] = { UndefinedValue(), ObjectValue(*obj1), ObjectValue(*obj2) };
Value argv[] = { UndefinedValue(), ObjectValue(*arr1), ObjectValue(*arr2) };
AutoValueArray ava(cx, argv, 3);
if (!js::array_concat(cx, 1, argv))
return NULL;
@@ -700,39 +701,28 @@ NewArgumentsObject(JSContext *cx, BaselineFrame *frame, MutableHandleValue res)
JSObject *
InitRestParameter(JSContext *cx, uint32_t length, Value *rest, HandleObject templateObj,
HandleObject res)
HandleObject objRes)
{
if (res) {
JS_ASSERT(res->isArray());
JS_ASSERT(!res->getDenseInitializedLength());
JS_ASSERT(res->type() == templateObj->type());
if (objRes) {
Rooted<ArrayObject*> arrRes(cx, &objRes->as<ArrayObject>());
JS_ASSERT(!arrRes->getDenseInitializedLength());
JS_ASSERT(arrRes->type() == templateObj->type());
JS_ASSERT(arrRes->type()->unknownProperties());
// Fast path: we managed to allocate the array inline; initialize the
// slots.
if (length > 0) {
if (!res->ensureElements(cx, length))
if (!arrRes->ensureElements(cx, length))
return NULL;
res->setDenseInitializedLength(length);
res->initDenseElements(0, rest, length);
res->setArrayLengthInt32(length);
// Ensure that values in the rest array are represented in the
// type of the array.
for (unsigned i = 0; i < length; i++)
types::AddTypePropertyId(cx, res, JSID_VOID, rest[i]);
arrRes->setDenseInitializedLength(length);
arrRes->initDenseElements(0, rest, length);
arrRes->setLengthInt32(length);
}
return res;
return arrRes;
}
JSObject *obj = NewDenseCopiedArray(cx, length, rest, NULL);
if (!obj)
return NULL;
obj->setType(templateObj->type());
for (unsigned i = 0; i < length; i++)
types::AddTypePropertyId(cx, obj, JSID_VOID, rest[i]);
return obj;
return NewDenseCopiedArray(cx, length, rest, NULL);
}
bool
+1 -1
View File
@@ -322,7 +322,7 @@ MSG_DEF(JSMSG_INVALID_FOR_IN_INIT, 268, 0, JSEXN_SYNTAXERR, "for-in loop let
MSG_DEF(JSMSG_CLEARED_SCOPE, 269, 0, JSEXN_TYPEERR, "attempt to run compile-and-go script on a cleared scope")
MSG_DEF(JSMSG_MALFORMED_ESCAPE, 270, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence")
MSG_DEF(JSMSG_BAD_GENEXP_BODY, 271, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression")
MSG_DEF(JSMSG_UNUSED272, 272, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_YIELD_WITHOUT_OPERAND, 272, 0, JSEXN_SYNTAXERR, "yield without a value is deprecated, and illegal in ES6 (use 'yield undefined' instead)")
MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 273, 0, JSEXN_SYNTAXERR, "function statement requires a name")
MSG_DEF(JSMSG_CCW_REQUIRED, 274, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment")
MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 275, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null")
+16 -14
View File
@@ -64,7 +64,9 @@
#include "jit/AsmJS.h"
#include "jit/PcScriptCache.h"
#include "js/CharacterEncoding.h"
#include "vm/DateObject.h"
#include "vm/Debugger.h"
#include "vm/ErrorObject.h"
#include "vm/Interpreter.h"
#include "vm/NumericConversions.h"
#include "vm/Shape.h"
@@ -621,7 +623,7 @@ JS_IsBuiltinEvalFunction(JSFunction *fun)
JS_PUBLIC_API(JSBool)
JS_IsBuiltinFunctionConstructor(JSFunction *fun)
{
return IsBuiltinFunctionConstructor(fun);
return fun->isBuiltinFunctionConstructor();
}
/************************************************************************/
@@ -1717,13 +1719,13 @@ StdNameToPropertyName(JSContext *cx, const JSStdName *stdn)
static const JSStdName standard_class_atoms[] = {
{js_InitFunctionClass, EAGER_CLASS_ATOM(Function), &JSFunction::class_},
{js_InitObjectClass, EAGER_ATOM_AND_CLASP(Object)},
{js_InitArrayClass, EAGER_ATOM_AND_CLASP(Array)},
{js_InitArrayClass, EAGER_ATOM_AND_OCLASP(Array)},
{js_InitBooleanClass, EAGER_ATOM_AND_OCLASP(Boolean)},
{js_InitDateClass, EAGER_ATOM_AND_CLASP(Date)},
{js_InitDateClass, EAGER_ATOM_AND_OCLASP(Date)},
{js_InitMathClass, EAGER_ATOM_AND_CLASP(Math)},
{js_InitNumberClass, EAGER_ATOM_AND_OCLASP(Number)},
{js_InitStringClass, EAGER_ATOM_AND_OCLASP(String)},
{js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)},
{js_InitExceptionClasses, EAGER_ATOM_AND_OCLASP(Error)},
{js_InitRegExpClass, EAGER_ATOM_AND_OCLASP(RegExp)},
#if JS_HAS_GENERATORS
{js_InitIteratorClasses, EAGER_ATOM_AND_OCLASP(StopIteration)},
@@ -1771,14 +1773,14 @@ static const JSStdName standard_class_names[] = {
#endif
/* Exception constructors. */
{js_InitExceptionClasses, EAGER_CLASS_ATOM(Error), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(InternalError), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(EvalError), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(RangeError), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(Error), OCLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(InternalError), OCLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(EvalError), OCLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(RangeError), OCLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(ReferenceError), OCLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(SyntaxError), OCLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(TypeError), OCLASP(Error)},
{js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), OCLASP(Error)},
{js_InitIteratorClasses, EAGER_CLASS_ATOM(Iterator), &PropertyIteratorObject::class_},
@@ -2954,7 +2956,7 @@ JS_IdArrayGet(JSContext *cx, JSIdArray *ida, int index)
JS_PUBLIC_API(void)
JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
{
DestroyIdArray(cx->runtime()->defaultFreeOp(), ida);
cx->runtime()->defaultFreeOp()->free_(ida);
}
JS_PUBLIC_API(JSBool)
@@ -4431,7 +4433,7 @@ prop_iter_finalize(FreeOp *fop, JSObject *obj)
if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
/* Non-native case: destroy the ida enumerated when obj was created. */
JSIdArray *ida = (JSIdArray *) pdata;
DestroyIdArray(fop, ida);
fop->free_(ida);
}
}
+16 -1
View File
@@ -132,7 +132,8 @@ class JS_PUBLIC_API(AutoGCRooter) {
OBJU32HASHMAP=-24, /* js::AutoObjectUnsigned32HashMap */
OBJHASHSET = -25, /* js::AutoObjectHashSet */
JSONPARSER = -26, /* js::JSONParser */
CUSTOM = -27 /* js::CustomAutoRooter */
CUSTOM = -27, /* js::CustomAutoRooter */
FUNVECTOR = -28 /* js::AutoFunctionVector */
};
private:
@@ -574,6 +575,19 @@ class AutoObjectVector : public AutoVectorRooter<JSObject *>
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoFunctionVector : public AutoVectorRooter<JSFunction *>
{
public:
explicit AutoFunctionVector(JSContext *cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooter<JSFunction *>(cx, FUNVECTOR)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoScriptVector : public AutoVectorRooter<JSScript *>
{
public:
@@ -5217,6 +5231,7 @@ using JS::Latin1CharsZ;
using JS::AutoIdVector;
using JS::AutoValueVector;
using JS::AutoObjectVector;
using JS::AutoFunctionVector;
using JS::AutoScriptVector;
using JS::AutoIdArray;
+185 -168
View File
@@ -33,6 +33,7 @@
#include "jscntxtinlines.h"
#include "jsstrinlines.h"
#include "vm/ArrayObject-inl.h"
#include "vm/ArgumentsObject-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/ObjectImpl-inl.h"
@@ -50,8 +51,8 @@ using mozilla::PointerRangeSize;
JSBool
js::GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp)
{
if (obj->isArray()) {
*lengthp = obj->getArrayLength();
if (obj->is<ArrayObject>()) {
*lengthp = obj->as<ArrayObject>().length();
return true;
}
@@ -235,7 +236,7 @@ GetElementsSlow(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
bool
js::GetElements(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
{
if (aobj->isArray() && length <= aobj->getDenseInitializedLength() &&
if (aobj->is<ArrayObject>() && length <= aobj->getDenseInitializedLength() &&
!ObjectMayHaveExtraIndexedProperties(aobj))
{
/* No other indexed properties so hole = undefined */
@@ -266,24 +267,25 @@ SetArrayElement(JSContext *cx, HandleObject obj, double index, HandleValue v)
{
JS_ASSERT(index >= 0);
if (obj->isArray() && !obj->isIndexed()) {
if (obj->is<ArrayObject>() && !obj->isIndexed()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
/* Predicted/prefetched code should favor the remains-dense case. */
JSObject::EnsureDenseResult result = JSObject::ED_SPARSE;
do {
if (index > uint32_t(-1))
break;
uint32_t idx = uint32_t(index);
if (idx >= obj->getArrayLength() && !obj->arrayLengthIsWritable()) {
if (idx >= arr->length() && !arr->lengthIsWritable()) {
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
return false;
}
result = obj->ensureDenseElements(cx, idx, 1);
result = arr->ensureDenseElements(cx, idx, 1);
if (result != JSObject::ED_OK)
break;
if (idx >= obj->getArrayLength())
obj->setArrayLengthInt32(idx + 1);
JSObject::setDenseElementWithType(cx, obj, idx, v);
if (idx >= arr->length())
arr->setLengthInt32(idx + 1);
JSObject::setDenseElementWithType(cx, arr, idx, v);
return true;
} while (false);
@@ -318,7 +320,7 @@ DeleteArrayElement(JSContext *cx, HandleObject obj, double index, JSBool *succee
JS_ASSERT(index >= 0);
JS_ASSERT(floor(index) == index);
if (obj->isArray() && !obj->isIndexed()) {
if (obj->is<ArrayObject>() && !obj->isIndexed()) {
if (index <= UINT32_MAX) {
uint32_t idx = uint32_t(index);
if (idx < obj->getDenseInitializedLength()) {
@@ -375,8 +377,8 @@ array_length_getter(JSContext *cx, HandleObject obj_, HandleId id, MutableHandle
{
RootedObject obj(cx, obj_);
do {
if (obj->isArray()) {
vp.setNumber(obj->getArrayLength());
if (obj->is<ArrayObject>()) {
vp.setNumber(obj->as<ArrayObject>().length());
return true;
}
if (!JSObject::getProto(cx, obj, &obj))
@@ -388,14 +390,15 @@ array_length_getter(JSContext *cx, HandleObject obj_, HandleId id, MutableHandle
static JSBool
array_length_setter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)
{
if (!obj->isArray()) {
if (!obj->is<ArrayObject>()) {
return JSObject::defineProperty(cx, obj, cx->names().length, vp,
NULL, NULL, JSPROP_ENUMERATE);
}
MOZ_ASSERT(obj->arrayLengthIsWritable(),
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
MOZ_ASSERT(arr->lengthIsWritable(),
"setter shouldn't be called if property is non-writable");
return ArraySetLength(cx, obj, id, JSPROP_PERMANENT, vp, strict);
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, strict);
}
struct ReverseIndexComparator
@@ -425,10 +428,9 @@ js::CanonicalizeArrayLengthValue(JSContext *cx, HandleValue v, uint32_t *newLen)
/* ES6 20130308 draft 8.4.2.4 ArraySetLength */
bool
js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
js::ArraySetLength(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, unsigned attrs,
HandleValue value, bool setterIsStrict)
{
MOZ_ASSERT(obj->isArray());
MOZ_ASSERT(id == NameToId(cx->names().length));
MOZ_ASSERT(attrs & JSPROP_PERMANENT);
MOZ_ASSERT(!(attrs & JSPROP_ENUMERATE));
@@ -441,16 +443,16 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
return false;
/* Steps 6-7. */
bool lengthIsWritable = obj->arrayLengthIsWritable();
bool lengthIsWritable = arr->lengthIsWritable();
#ifdef DEBUG
{
RootedShape lengthShape(cx, obj->nativeLookup(cx, id));
RootedShape lengthShape(cx, arr->nativeLookup(cx, id));
MOZ_ASSERT(lengthShape);
MOZ_ASSERT(lengthShape->writable() == lengthIsWritable);
}
#endif
uint32_t oldLen = obj->getArrayLength();
uint32_t oldLen = arr->length();
/* Steps 8-9 for arrays with non-writable length. */
if (!lengthIsWritable) {
@@ -484,14 +486,14 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
// that element must prevent any deletions below it. Bug 586842 should
// fix this inefficiency by moving indexed storage to be entirely
// separate from non-indexed storage.
if (!obj->isIndexed()) {
uint32_t oldCapacity = obj->getDenseCapacity();
uint32_t oldInitializedLength = obj->getDenseInitializedLength();
if (!arr->isIndexed()) {
uint32_t oldCapacity = arr->getDenseCapacity();
uint32_t oldInitializedLength = arr->getDenseInitializedLength();
MOZ_ASSERT(oldCapacity >= oldInitializedLength);
if (oldInitializedLength > newLen)
obj->setDenseInitializedLength(newLen);
arr->setDenseInitializedLength(newLen);
if (oldCapacity > newLen)
obj->shrinkElements(cx, newLen);
arr->shrinkElements(cx, newLen);
// We've done the work of deleting any dense elements needing
// deletion, and there are no sparse elements. Thus we can skip
@@ -530,7 +532,7 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
/* Steps 15b-d. */
JSBool deleteSucceeded;
if (!JSObject::deleteElement(cx, obj, oldLen, &deleteSucceeded))
if (!JSObject::deleteElement(cx, arr, oldLen, &deleteSucceeded))
return false;
if (!deleteSucceeded) {
newLen = oldLen + 1;
@@ -554,7 +556,7 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
Vector<uint32_t> indexes(cx);
{
AutoIdVector props(cx);
if (!GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &props))
if (!GetPropertyNames(cx, arr, JSITER_OWNONLY | JSITER_HIDDEN, &props))
return false;
for (size_t i = 0; i < props.length(); i++) {
@@ -590,7 +592,7 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
/* Steps 15b-d. */
JSBool deleteSucceeded;
if (!JSObject::deleteElement(cx, obj, index, &deleteSucceeded))
if (!JSObject::deleteElement(cx, arr, index, &deleteSucceeded))
return false;
if (!deleteSucceeded) {
newLen = index + 1;
@@ -607,8 +609,8 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
// API call on the floor here. Given that getter/setter will go away in
// the long run, with accessors replacing them both internally and at the
// API level, just run with this.
RootedShape lengthShape(cx, obj->nativeLookup(cx, id));
if (!JSObject::changeProperty(cx, obj, lengthShape, attrs,
RootedShape lengthShape(cx, arr->nativeLookup(cx, id));
if (!JSObject::changeProperty(cx, arr, lengthShape, attrs,
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED,
array_length_getter, array_length_setter))
{
@@ -616,8 +618,8 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
}
RootedValue v(cx, NumberValue(newLen));
AddTypePropertyId(cx, obj, id, v);
JSObject::setArrayLength(cx, obj, newLen);
AddTypePropertyId(cx, arr, id, v);
ArrayObject::setLength(cx, arr, newLen);
// All operations past here until the |!succeeded| code must be infallible,
// so that all element fields remain properly synchronized.
@@ -625,7 +627,7 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
// Trim the initialized length, if needed, to preserve the <= length
// invariant. (Capacity was already reduced during element deletion, if
// necessary.)
ObjectElements *header = obj->getElementsHeader();
ObjectElements *header = arr->getElementsHeader();
header->initializedLength = Min(header->initializedLength, newLen);
if (attrs & JSPROP_READONLY) {
@@ -637,9 +639,9 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
// But in JIT code every check counts -- so we piggyback the check on
// the already-required range check for |index < capacity| by making
// capacity of arrays with non-writable length never exceed the length.
if (obj->getDenseCapacity() > newLen) {
obj->shrinkElements(cx, newLen);
obj->getElementsHeader()->capacity = newLen;
if (arr->getDenseCapacity() > newLen) {
arr->shrinkElements(cx, newLen);
arr->getElementsHeader()->capacity = newLen;
}
}
@@ -647,7 +649,7 @@ js::ArraySetLength(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs,
RootedId elementId(cx);
if (!IndexToId(cx, newLen - 1, &elementId))
return false;
return obj->reportNotConfigurable(cx, elementId);
return arr->reportNotConfigurable(cx, elementId);
}
return true;
@@ -657,18 +659,19 @@ bool
js::WouldDefinePastNonwritableLength(JSContext *cx, HandleObject obj, uint32_t index, bool strict,
bool *definesPast)
{
if (!obj->isArray()) {
if (!obj->is<ArrayObject>()) {
*definesPast = false;
return true;
}
uint32_t length = obj->getArrayLength();
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
uint32_t length = arr->length();
if (index < length) {
*definesPast = false;
return true;
}
if (obj->arrayLengthIsWritable()) {
if (arr->lengthIsWritable()) {
*definesPast = false;
return true;
}
@@ -688,15 +691,17 @@ static JSBool
array_addProperty(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp)
{
uint32_t index, length;
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
uint32_t index;
if (!js_IdIsIndex(id, &index))
return true;
length = obj->getArrayLength();
uint32_t length = arr->length();
if (index >= length) {
MOZ_ASSERT(obj->arrayLengthIsWritable(),
MOZ_ASSERT(arr->lengthIsWritable(),
"how'd this element get added if length is non-writable?");
JSObject::setArrayLength(cx, obj, index + 1);
ArrayObject::setLength(cx, arr, index + 1);
}
return true;
}
@@ -737,7 +742,7 @@ js::ObjectMayHaveExtraIndexedProperties(JSObject *obj)
return false;
}
Class js::ArrayClass = {
Class ArrayObject::class_ = {
"Array",
JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
array_addProperty,
@@ -783,7 +788,7 @@ AddLengthProperty(JSContext *cx, HandleObject obj)
JS_ALWAYS_INLINE bool
IsArray(const Value &v)
{
return v.isObject() && v.toObject().isArray();
return v.isObject() && v.toObject().is<ArrayObject>();
}
JS_ALWAYS_INLINE bool
@@ -896,7 +901,7 @@ ArrayJoinKernel(JSContext *cx, SeparatorOp sepOp, HandleObject obj, uint32_t len
{
uint32_t i = 0;
if (!Locale && obj->isArray() && !ObjectMayHaveExtraIndexedProperties(obj)) {
if (!Locale && obj->is<ArrayObject>() && !ObjectMayHaveExtraIndexedProperties(obj)) {
// This loop handles all elements up to initializedLength. If
// length > initLength we rely on the second loop to add the
// other elements.
@@ -1145,7 +1150,7 @@ InitArrayElements(JSContext *cx, HandleObject obj, uint32_t start, uint32_t coun
* length.
*/
do {
if (!obj->isArray())
if (!obj->is<ArrayObject>())
break;
if (ObjectMayHaveExtraIndexedProperties(obj))
break;
@@ -1153,10 +1158,12 @@ InitArrayElements(JSContext *cx, HandleObject obj, uint32_t start, uint32_t coun
if (obj->shouldConvertDoubleElements())
break;
if (!obj->arrayLengthIsWritable() && start + count > obj->getArrayLength())
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (!arr->lengthIsWritable() && start + count > arr->length())
break;
JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, start, count);
JSObject::EnsureDenseResult result = arr->ensureDenseElements(cx, start, count);
if (result != JSObject::ED_OK) {
if (result == JSObject::ED_FAILED)
return false;
@@ -1165,12 +1172,12 @@ InitArrayElements(JSContext *cx, HandleObject obj, uint32_t start, uint32_t coun
}
uint32_t newlen = start + count;
if (newlen > obj->getArrayLength())
obj->setArrayLengthInt32(newlen);
if (newlen > arr->length())
arr->setLengthInt32(newlen);
JS_ASSERT(count < UINT32_MAX / sizeof(Value));
obj->copyDenseElements(start, vector, count);
JS_ASSERT_IF(count != 0, !obj->getDenseElement(newlen - 1).isMagic(JS_ELEMENTS_HOLE));
arr->copyDenseElements(start, vector, count);
JS_ASSERT_IF(count != 0, !arr->getDenseElement(newlen - 1).isMagic(JS_ELEMENTS_HOLE));
return true;
} while (false);
@@ -1217,7 +1224,7 @@ array_reverse(JSContext *cx, unsigned argc, Value *vp)
return false;
do {
if (!obj->isArray())
if (!obj->is<ArrayObject>())
break;
if (ObjectMayHaveExtraIndexedProperties(obj))
break;
@@ -1635,7 +1642,7 @@ MergeSortByKey(K keys, size_t len, K scratch, C comparator, AutoValueVector *vec
* necessary each inner iteration moves some number of unsorted elements
* (including |i|) directly to sorted position. Thus on completion |*vec|
* is sorted, and out-of-position elements have moved once. Complexity is
* Θ(len) + O(len) == O(2*len), with each element visited at most twice.
* ?(len) + O(len) == O(2*len), with each element visited at most twice.
*/
for (size_t i = 0; i < len; i++) {
size_t j = keys[i].elementIndex;
@@ -1912,18 +1919,20 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
JS_ALWAYS_INLINE JSBool
NewbornArrayPushImpl(JSContext *cx, HandleObject obj, const Value &v)
{
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
JS_ASSERT(!v.isMagic());
JS_ASSERT(obj->arrayLengthIsWritable());
JS_ASSERT(arr->lengthIsWritable());
uint32_t length = obj->getArrayLength();
JS_ASSERT(length <= obj->getDenseCapacity());
uint32_t length = arr->length();
JS_ASSERT(length <= arr->getDenseCapacity());
if (!obj->ensureElements(cx, length + 1))
if (!arr->ensureElements(cx, length + 1))
return false;
obj->setDenseInitializedLength(length + 1);
obj->setArrayLengthInt32(length + 1);
JSObject::initDenseElementWithType(cx, obj, length, v);
arr->setDenseInitializedLength(length + 1);
arr->setLengthInt32(length + 1);
JSObject::initDenseElementWithType(cx, arr, length, v);
return true;
}
@@ -1945,25 +1954,25 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp)
return false;
/* Fast path for the fully-dense case. */
if (obj->isArray() &&
obj->arrayLengthIsWritable() &&
!ObjectMayHaveExtraIndexedProperties(obj))
{
uint32_t length = obj->getArrayLength();
uint32_t argCount = args.length();
JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, length, argCount);
if (result == JSObject::ED_FAILED)
return false;
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (arr->lengthIsWritable() && !ObjectMayHaveExtraIndexedProperties(arr)) {
uint32_t length = arr->length();
uint32_t argCount = args.length();
JSObject::EnsureDenseResult result = arr->ensureDenseElements(cx, length, argCount);
if (result == JSObject::ED_FAILED)
return false;
if (result == JSObject::ED_OK) {
obj->setArrayLengthInt32(length + argCount);
for (uint32_t i = 0, index = length; i < argCount; index++, i++)
JSObject::setDenseElementWithType(cx, obj, index, args[i]);
args.rval().setNumber(obj->getArrayLength());
return true;
if (result == JSObject::ED_OK) {
arr->setLengthInt32(length + argCount);
for (uint32_t i = 0, index = length; i < argCount; index++, i++)
JSObject::setDenseElementWithType(cx, arr, index, args[i]);
args.rval().setNumber(arr->length());
return true;
}
MOZ_ASSERT(result == JSObject::ED_SPARSE);
}
MOZ_ASSERT(result == JSObject::ED_SPARSE);
}
/* Steps 2-3. */
@@ -2028,8 +2037,8 @@ js::array_pop(JSContext *cx, unsigned argc, Value *vp)
void
js::ArrayShiftMoveElements(JSObject *obj)
{
JS_ASSERT(obj->isArray());
JS_ASSERT(obj->arrayLengthIsWritable());
JS_ASSERT(obj->is<ArrayObject>());
JS_ASSERT(obj->as<ArrayObject>().lengthIsWritable());
/*
* At this point the length and initialized length have already been
@@ -2070,7 +2079,7 @@ js::array_shift(JSContext *cx, unsigned argc, Value *vp)
uint32_t newlen = len - 1;
/* Fast paths. */
if (obj->isArray() &&
if (obj->is<ArrayObject>() &&
obj->getDenseInitializedLength() > 0 &&
newlen < obj->getDenseCapacity() &&
!ObjectMayHaveExtraIndexedProperties(obj))
@@ -2135,11 +2144,11 @@ array_unshift(JSContext *cx, unsigned argc, Value *vp)
if (length > 0) {
bool optimized = false;
do {
if (!obj->isArray())
if (!obj->is<ArrayObject>())
break;
if (ObjectMayHaveExtraIndexedProperties(obj))
break;
if (!obj->arrayLengthIsWritable())
if (!obj->as<ArrayObject>().lengthIsWritable())
break;
JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, length, args.length());
if (result != JSObject::ED_OK) {
@@ -2191,18 +2200,17 @@ array_unshift(JSContext *cx, unsigned argc, Value *vp)
}
static inline void
TryReuseArrayType(JSObject *obj, JSObject *nobj)
TryReuseArrayType(JSObject *obj, ArrayObject *narr)
{
/*
* Try to change the type of a newly created array nobj to the same type
* Try to change the type of a newly created array narr to the same type
* as obj. This can only be performed if the original object is an array
* and has the same prototype.
*/
JS_ASSERT(nobj->isArray());
JS_ASSERT(nobj->getProto()->hasNewType(&ArrayClass, nobj->type()));
JS_ASSERT(narr->getProto()->hasNewType(&ArrayObject::class_, narr->type()));
if (obj->isArray() && !obj->hasSingletonType() && obj->getProto() == nobj->getProto())
nobj->setType(obj->type());
if (obj->is<ArrayObject>() && !obj->hasSingletonType() && obj->getProto() == narr->getProto())
narr->setType(obj->type());
}
/*
@@ -2220,7 +2228,7 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co
return false;
/* There's no optimizing possible if it's not an array. */
if (!arr->isArray())
if (!arr->is<ArrayObject>())
return false;
/*
@@ -2295,7 +2303,7 @@ array_splice(JSContext *cx, unsigned argc, Value *vp)
JS_ASSERT(len - actualStart >= actualDeleteCount);
/* Steps 2, 8-9. */
RootedObject arr(cx);
Rooted<ArrayObject*> arr(cx);
if (CanOptimizeForDenseStorage(obj, actualStart, actualDeleteCount, cx)) {
arr = NewDenseCopiedArray(cx, actualDeleteCount, obj, actualStart);
if (!arr)
@@ -2404,11 +2412,14 @@ array_splice(JSContext *cx, unsigned argc, Value *vp)
* path may validly *not* throw -- if all the elements being moved are
* holes.)
*/
if (obj->isArray() && obj->arrayLengthIsWritable()) {
JSObject::EnsureDenseResult res =
obj->ensureDenseElements(cx, len, itemCount - actualDeleteCount);
if (res == JSObject::ED_FAILED)
return false;
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (arr->lengthIsWritable()) {
JSObject::EnsureDenseResult res =
arr->ensureDenseElements(cx, arr->length(), itemCount - actualDeleteCount);
if (res == JSObject::ED_FAILED)
return false;
}
}
if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
@@ -2463,15 +2474,14 @@ array_splice(JSContext *cx, unsigned argc, Value *vp)
#ifdef JS_ION
bool
js::array_concat_dense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject result)
js::array_concat_dense(JSContext *cx, Handle<ArrayObject*> arr1, Handle<ArrayObject*> arr2,
Handle<ArrayObject*> result)
{
JS_ASSERT(result->isArray() && obj1->isArray() && obj2->isArray());
uint32_t initlen1 = arr1->getDenseInitializedLength();
JS_ASSERT(initlen1 == arr1->length());
uint32_t initlen1 = obj1->getDenseInitializedLength();
JS_ASSERT(initlen1 == obj1->getArrayLength());
uint32_t initlen2 = obj2->getDenseInitializedLength();
JS_ASSERT(initlen2 == obj2->getArrayLength());
uint32_t initlen2 = arr2->getDenseInitializedLength();
JS_ASSERT(initlen2 == arr2->length());
/* No overflow here due to nelements limit. */
uint32_t len = initlen1 + initlen2;
@@ -2482,9 +2492,9 @@ js::array_concat_dense(JSContext *cx, HandleObject obj1, HandleObject obj2, Hand
JS_ASSERT(!result->getDenseInitializedLength());
result->setDenseInitializedLength(len);
result->initDenseElements(0, obj1->getDenseElements(), initlen1);
result->initDenseElements(initlen1, obj2->getDenseElements(), initlen2);
result->setArrayLengthInt32(len);
result->initDenseElements(0, arr1->getDenseElements(), initlen1);
result->initDenseElements(initlen1, arr2->getDenseElements(), initlen2);
result->setLengthInt32(len);
return true;
}
#endif /* JS_ION */
@@ -2514,8 +2524,8 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
* Step 5. This may also inline the first iteration of Step 6 if it is
* possible to perform a fast, dense copy.
*/
RootedObject arr(cx);
if (obj->isArray() && !obj->isIndexed()) {
Rooted<ArrayObject*> arr(cx);
if (obj->is<ArrayObject>() && !obj->isIndexed()) {
uint32_t initlen = obj->getDenseInitializedLength();
arr = NewDenseCopiedArray(cx, initlen, obj, 0);
if (!arr)
@@ -2622,23 +2632,23 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
if (begin > end)
begin = end;
RootedObject nobj(cx);
Rooted<ArrayObject*> narr(cx);
if (obj->isArray() && end <= obj->getDenseInitializedLength() &&
if (obj->is<ArrayObject>() && end <= obj->getDenseInitializedLength() &&
!ObjectMayHaveExtraIndexedProperties(obj))
{
nobj = NewDenseCopiedArray(cx, end - begin, obj, begin);
if (!nobj)
narr = NewDenseCopiedArray(cx, end - begin, obj, begin);
if (!narr)
return false;
TryReuseArrayType(obj, nobj);
args.rval().setObject(*nobj);
TryReuseArrayType(obj, narr);
args.rval().setObject(*narr);
return true;
}
nobj = NewDenseAllocatedArray(cx, end - begin);
if (!nobj)
narr = NewDenseAllocatedArray(cx, end - begin);
if (!narr)
return false;
TryReuseArrayType(obj, nobj);
TryReuseArrayType(obj, narr);
RootedValue value(cx);
for (slot = begin; slot < end; slot++) {
@@ -2646,11 +2656,11 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
!GetElement(cx, obj, slot, &hole, &value)) {
return false;
}
if (!hole && !SetArrayElement(cx, nobj, slot - begin, value))
if (!hole && !SetArrayElement(cx, narr, slot - begin, value))
return false;
}
args.rval().setObject(*nobj);
args.rval().setObject(*narr);
return true;
}
@@ -2916,13 +2926,15 @@ js_Array(JSContext *cx, unsigned argc, Value *vp)
if (!obj)
return false;
obj->setType(type);
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
arr->setType(type);
/* If the length calculation overflowed, make sure that is marked for the new type. */
if (obj->getArrayLength() > INT32_MAX)
JSObject::setArrayLength(cx, obj, obj->getArrayLength());
if (arr->length() > INT32_MAX)
ArrayObject::setLength(cx, arr, arr->length());
args.rval().setObject(*obj);
args.rval().setObject(*arr);
return true;
}
@@ -2937,7 +2949,7 @@ js_InitArrayClass(JSContext *cx, HandleObject obj)
if (!proto)
return NULL;
RootedTypeObject type(cx, proto->getNewType(cx, &ArrayClass));
RootedTypeObject type(cx, proto->getNewType(cx, &ArrayObject::class_));
if (!type)
return NULL;
@@ -2945,7 +2957,7 @@ js_InitArrayClass(JSContext *cx, HandleObject obj)
if (!NewObjectMetadata(cx, &metadata))
return NULL;
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayClass, TaggedProto(proto),
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayObject::class_, TaggedProto(proto),
proto->getParent(), metadata,
gc::FINALIZE_OBJECT0));
@@ -2964,7 +2976,7 @@ js_InitArrayClass(JSContext *cx, HandleObject obj)
* arrays in JSON and script literals and allows setDenseArrayElement to
* be used without updating the indexed type set for such default arrays.
*/
if (!JSObject::setNewTypeUnknown(cx, &ArrayClass, arrayProto))
if (!JSObject::setNewTypeUnknown(cx, &ArrayObject::class_, arrayProto))
return NULL;
if (!LinkConstructorAndPrototype(cx, ctor, arrayProto))
@@ -3004,11 +3016,11 @@ EnsureNewArrayElements(JSContext *cx, JSObject *obj, uint32_t length)
}
template<bool allocateCapacity>
static JS_ALWAYS_INLINE JSObject *
static JS_ALWAYS_INLINE ArrayObject *
NewArray(JSContext *cx, uint32_t length, JSObject *protoArg, NewObjectKind newKind = GenericObject)
{
gc::AllocKind allocKind = GuessArrayGCKind(length);
JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayClass));
JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
allocKind = GetBackgroundAllocKind(allocKind);
NewObjectCache &cache = cx->runtime()->newObjectCache;
@@ -3016,16 +3028,18 @@ NewArray(JSContext *cx, uint32_t length, JSObject *protoArg, NewObjectKind newKi
NewObjectCache::EntryIndex entry = -1;
if (newKind == GenericObject &&
!cx->compartment()->objectMetadataCallback &&
cache.lookupGlobal(&ArrayClass, cx->global(), allocKind, &entry))
cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry))
{
RootedObject obj(cx, cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, &ArrayClass)));
RootedObject obj(cx, cache.newObjectFromHit(cx, entry,
GetInitialHeap(newKind, &ArrayObject::class_)));
if (obj) {
/* Fixup the elements pointer and length, which may be incorrect. */
obj->setFixedElements();
JSObject::setArrayLength(cx, obj, length);
if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
arr->setFixedElements();
ArrayObject::setLength(cx, arr, length);
if (allocateCapacity && !EnsureNewArrayElements(cx, arr, length))
return NULL;
return obj;
return arr;
}
}
@@ -3033,10 +3047,10 @@ NewArray(JSContext *cx, uint32_t length, JSObject *protoArg, NewObjectKind newKi
if (protoArg)
JS::PoisonPtr(&protoArg);
if (!proto && !FindProto(cx, &ArrayClass, &proto))
if (!proto && !FindProto(cx, &ArrayObject::class_, &proto))
return NULL;
RootedTypeObject type(cx, proto->getNewType(cx, &ArrayClass));
RootedTypeObject type(cx, proto->getNewType(cx, &ArrayObject::class_));
if (!type)
return NULL;
@@ -3048,95 +3062,98 @@ NewArray(JSContext *cx, uint32_t length, JSObject *protoArg, NewObjectKind newKi
* Get a shape with zero fixed slots, regardless of the size class.
* See JSObject::createArray.
*/
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayClass, TaggedProto(proto),
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayObject::class_, TaggedProto(proto),
cx->global(), metadata, gc::FINALIZE_OBJECT0));
if (!shape)
return NULL;
RootedObject obj(cx, JSObject::createArray(cx, allocKind, GetInitialHeap(newKind, &ArrayClass),
RootedObject obj(cx, JSObject::createArray(cx, allocKind,
GetInitialHeap(newKind, &ArrayObject::class_),
shape, type, length));
if (!obj)
return NULL;
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (shape->isEmptyShape()) {
if (!AddLengthProperty(cx, obj))
if (!AddLengthProperty(cx, arr))
return NULL;
shape = obj->lastProperty();
shape = arr->lastProperty();
EmptyShape::insertInitialShape(cx, shape, proto);
}
if (newKind == SingletonObject && !JSObject::setSingletonType(cx, obj))
if (newKind == SingletonObject && !JSObject::setSingletonType(cx, arr))
return NULL;
if (entry != -1)
cache.fillGlobal(entry, &ArrayClass, cx->global(), allocKind, obj);
cache.fillGlobal(entry, &ArrayObject::class_, cx->global(), allocKind, arr);
if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
if (allocateCapacity && !EnsureNewArrayElements(cx, arr, length))
return NULL;
Probes::createObject(cx, obj);
return obj;
Probes::createObject(cx, arr);
return arr;
}
JSObject * JS_FASTCALL
ArrayObject * JS_FASTCALL
js::NewDenseEmptyArray(JSContext *cx, JSObject *proto /* = NULL */,
NewObjectKind newKind /* = GenericObject */)
{
return NewArray<false>(cx, 0, proto, newKind);
}
JSObject * JS_FASTCALL
ArrayObject * JS_FASTCALL
js::NewDenseAllocatedArray(JSContext *cx, uint32_t length, JSObject *proto /* = NULL */,
NewObjectKind newKind /* = GenericObject */)
{
return NewArray<true>(cx, length, proto, newKind);
}
JSObject * JS_FASTCALL
ArrayObject * JS_FASTCALL
js::NewDenseUnallocatedArray(JSContext *cx, uint32_t length, JSObject *proto /* = NULL */,
NewObjectKind newKind /* = GenericObject */)
{
return NewArray<false>(cx, length, proto, newKind);
}
JSObject *
ArrayObject *
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t elementOffset,
JSObject *proto /* = NULL */)
{
JS_ASSERT(!src->isIndexed());
JSObject* obj = NewArray<true>(cx, length, proto);
if (!obj)
ArrayObject* arr = NewArray<true>(cx, length, proto);
if (!arr)
return NULL;
JS_ASSERT(obj->getDenseCapacity() >= length);
JS_ASSERT(arr->getDenseCapacity() >= length);
const Value* vp = src->getDenseElements() + elementOffset;
obj->setDenseInitializedLength(vp ? length : 0);
arr->setDenseInitializedLength(vp ? length : 0);
if (vp)
obj->initDenseElements(0, vp, length);
arr->initDenseElements(0, vp, length);
return obj;
return arr;
}
// values must point at already-rooted Value objects
JSObject *
ArrayObject *
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
JSObject *proto /* = NULL */, NewObjectKind newKind /* = GenericObject */)
{
JSObject* obj = NewArray<true>(cx, length, proto);
if (!obj)
ArrayObject* arr = NewArray<true>(cx, length, proto);
if (!arr)
return NULL;
JS_ASSERT(obj->getDenseCapacity() >= length);
JS_ASSERT(arr->getDenseCapacity() >= length);
obj->setDenseInitializedLength(values ? length : 0);
arr->setDenseInitializedLength(values ? length : 0);
if (values)
obj->initDenseElements(0, values, length);
arr->initDenseElements(0, values, length);
return obj;
return arr;
}
#ifdef DEBUG
@@ -3144,7 +3161,7 @@ JSBool
js_ArrayInfo(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *array;
JSObject *obj;
for (unsigned i = 0; i < args.length(); i++) {
RootedValue arg(cx, args[i]);
@@ -3153,13 +3170,13 @@ js_ArrayInfo(JSContext *cx, unsigned argc, Value *vp)
if (!bytes)
return false;
if (arg.isPrimitive() ||
!(array = arg.toObjectOrNull())->isArray()) {
!(obj = arg.toObjectOrNull())->is<ArrayObject>()) {
fprintf(stderr, "%s: not array\n", bytes);
js_free(bytes);
continue;
}
fprintf(stderr, "%s: (len %u", bytes, array->getArrayLength());
fprintf(stderr, ", capacity %u", array->getDenseCapacity());
fprintf(stderr, "%s: (len %u", bytes, obj->as<ArrayObject>().length());
fprintf(stderr, ", capacity %u", obj->getDenseCapacity());
fputs(")\n", stderr);
js_free(bytes);
}
+9 -6
View File
@@ -41,13 +41,15 @@ js_InitContextBusyArrayTable(JSContext *cx);
namespace js {
class ArrayObject;
/* Create a dense array with no capacity allocated, length set to 0. */
extern JSObject * JS_FASTCALL
extern ArrayObject * JS_FASTCALL
NewDenseEmptyArray(JSContext *cx, JSObject *proto = NULL,
NewObjectKind newKind = GenericObject);
/* Create a dense array with length and capacity == 'length', initialized length set to 0. */
extern JSObject * JS_FASTCALL
extern ArrayObject * JS_FASTCALL
NewDenseAllocatedArray(JSContext *cx, uint32_t length, JSObject *proto = NULL,
NewObjectKind newKind = GenericObject);
@@ -55,16 +57,16 @@ NewDenseAllocatedArray(JSContext *cx, uint32_t length, JSObject *proto = NULL,
* Create a dense array with a set length, but without allocating space for the
* contents. This is useful, e.g., when accepting length from the user.
*/
extern JSObject * JS_FASTCALL
extern ArrayObject * JS_FASTCALL
NewDenseUnallocatedArray(JSContext *cx, uint32_t length, JSObject *proto = NULL,
NewObjectKind newKind = GenericObject);
/* Create a dense array with a copy of the dense array elements in src. */
extern JSObject *
extern ArrayObject *
NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t elementOffset, JSObject *proto = NULL);
/* Create a dense array from the given array values, which must be rooted */
extern JSObject *
extern ArrayObject *
NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, JSObject *proto = NULL,
NewObjectKind newKind = GenericObject);
@@ -117,7 +119,8 @@ extern JSBool
array_concat(JSContext *cx, unsigned argc, js::Value *vp);
extern bool
array_concat_dense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject result);
array_concat_dense(JSContext *cx, Handle<ArrayObject*> arr1, Handle<ArrayObject*> arr2,
Handle<ArrayObject*> result);
extern void
ArrayShiftMoveElements(JSObject *obj);
+4 -2
View File
@@ -7,7 +7,7 @@
/*
* JS atom table.
*/
#include "jsatom.h"
#include "jsatominlines.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/Util.h"
@@ -22,9 +22,11 @@
#include "gc/Marking.h"
#include "vm/Xdr.h"
#include "jsatominlines.h"
#include "jscompartmentinlines.h"
#ifdef JSGC_GENERATIONAL
#include "vm/Shape-inl.h"
#endif
#include "vm/String-inl.h"
using namespace js;
+7 -2
View File
@@ -21,6 +21,10 @@ class PropertyName;
class SpecialId;
class PropertyId;
// This is equal to JSFunction::class_. Use it in places where you don't want
// to #include jsfun.h.
extern JS_FRIEND_DATA(js::Class*) FunctionClassPtr;
static JS_ALWAYS_INLINE jsid
SPECIALID_TO_JSID(const SpecialId &sid);
@@ -312,8 +316,9 @@ struct Class
return flags & JSCLASS_EMULATES_UNDEFINED;
}
/* Defined in jsfuninlines.h */
inline bool isCallable() const;
bool isCallable() const {
return this == js::FunctionClassPtr || call;
}
static size_t offsetOfFlags() { return offsetof(Class, flags); }
};
+3 -3
View File
@@ -641,7 +641,7 @@ JSStructuredCloneWriter::traverseObject(HandleObject obj)
checkStack();
/* Write the header for obj. */
return out.writePair(obj->isArray() ? SCTAG_ARRAY_OBJECT : SCTAG_OBJECT_OBJECT, 0);
return out.writePair(obj->is<ArrayObject>() ? SCTAG_ARRAY_OBJECT : SCTAG_OBJECT_OBJECT, 0);
}
bool
@@ -682,14 +682,14 @@ JSStructuredCloneWriter::startWrite(const Value &v)
RegExpObject &reobj = obj->as<RegExpObject>();
return out.writePair(SCTAG_REGEXP_OBJECT, reobj.getFlags()) &&
writeString(SCTAG_STRING, reobj.getSource());
} else if (obj->isDate()) {
} else if (obj->is<DateObject>()) {
double d = js_DateGetMsecSinceEpoch(obj);
return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(d);
} else if (obj->isTypedArray()) {
return writeTypedArray(obj);
} else if (obj->is<ArrayBufferObject>() && obj->as<ArrayBufferObject>().hasData()) {
return writeArrayBuffer(obj);
} else if (obj->isObject() || obj->isArray()) {
} else if (obj->isObject() || obj->is<ArrayObject>()) {
return traverseObject(obj);
} else if (obj->is<BooleanObject>()) {
return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->as<BooleanObject>().unbox());
+1 -1
View File
@@ -1205,7 +1205,7 @@ JSContext::JSContext(JSRuntime *rt)
JS_ASSERT(static_cast<ContextFriendFields*>(this) ==
ContextFriendFields::get(this));
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
PodArrayZero(thingGCRooters);
#endif
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
+235 -341
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -1325,6 +1325,9 @@ JSAbstractFramePtr::evaluateUCInStackFrame(JSContext *cx,
const char *filename, unsigned lineno,
MutableHandleValue rval)
{
/* Protect inlined chars from root analysis poisoning. */
SkipRoot skipChars(cx, &chars);
if (!CheckDebugMode(cx))
return false;
+23 -29
View File
@@ -24,6 +24,7 @@
#include "jsscript.h"
#include "gc/Marking.h"
#include "vm/ErrorObject.h"
#include "vm/GlobalObject.h"
#include "vm/StringBuffer.h"
@@ -37,7 +38,7 @@ using mozilla::ArrayLength;
using mozilla::PodArrayZero;
using mozilla::PodZero;
/* Forward declarations for ErrorClass's initializer. */
/* Forward declarations for ErrorObject::class_'s initializer. */
static JSBool
Exception(JSContext *cx, unsigned argc, Value *vp);
@@ -51,7 +52,7 @@ static JSBool
exn_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
MutableHandleObject objp);
Class js::ErrorClass = {
Class ErrorObject::class_ = {
js_Error_str,
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
@@ -240,14 +241,14 @@ struct SuppressErrorsGuard
};
static void
SetExnPrivate(JSObject *exnObject, JSExnPrivate *priv);
SetExnPrivate(ErrorObject &exnObject, JSExnPrivate *priv);
static bool
InitExnPrivate(JSContext *cx, HandleObject exnObject, HandleString message,
HandleString filename, unsigned lineno, unsigned column,
JSErrorReport *report, int exnType)
{
JS_ASSERT(exnObject->isError());
JS_ASSERT(exnObject->is<ErrorObject>());
JS_ASSERT(!exnObject->getPrivate());
JSCheckAccessOp checkAccess = cx->runtime()->securityCallbacks->checkObjectAccess;
@@ -329,21 +330,14 @@ InitExnPrivate(JSContext *cx, HandleObject exnObject, HandleString message,
priv->stackElems[i].ulineno = frames[i].ulineno;
}
SetExnPrivate(exnObject, priv);
SetExnPrivate(exnObject->as<ErrorObject>(), priv);
return true;
}
static inline JSExnPrivate *
GetExnPrivate(JSObject *obj)
{
JS_ASSERT(obj->isError());
return (JSExnPrivate *) obj->getPrivate();
}
static void
exn_trace(JSTracer *trc, JSObject *obj)
{
if (JSExnPrivate *priv = GetExnPrivate(obj)) {
if (JSExnPrivate *priv = obj->as<ErrorObject>().getExnPrivate()) {
if (priv->message)
MarkString(trc, &priv->message, "exception message");
if (priv->filename)
@@ -359,21 +353,20 @@ exn_trace(JSTracer *trc, JSObject *obj)
/* NB: An error object's private must be set through this function. */
static void
SetExnPrivate(JSObject *exnObject, JSExnPrivate *priv)
SetExnPrivate(ErrorObject &exnObject, JSExnPrivate *priv)
{
JS_ASSERT(!exnObject->getPrivate());
JS_ASSERT(exnObject->isError());
JS_ASSERT(!exnObject.getExnPrivate());
if (JSErrorReport *report = priv->errorReport) {
if (JSPrincipals *prin = report->originPrincipals)
JS_HoldPrincipals(prin);
}
exnObject->setPrivate(priv);
exnObject.setPrivate(priv);
}
static void
exn_finalize(FreeOp *fop, JSObject *obj)
{
if (JSExnPrivate *priv = GetExnPrivate(obj)) {
if (JSExnPrivate *priv = obj->as<ErrorObject>().getExnPrivate()) {
if (JSErrorReport *report = priv->errorReport) {
/* HOLD called by SetExnPrivate. */
if (JSPrincipals *prin = report->originPrincipals)
@@ -396,7 +389,7 @@ exn_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
unsigned attrs;
objp.set(NULL);
priv = GetExnPrivate(obj);
priv = obj->as<ErrorObject>().getExnPrivate();
if (priv && JSID_IS_ATOM(id)) {
RootedString str(cx, JSID_TO_STRING(id));
@@ -475,10 +468,10 @@ js_ErrorFromException(jsval exn)
// JSErrorReport's principal or also tries to do toString on our object and
// will fail if they can't unwrap it.
JSObject *obj = UncheckedUnwrap(JSVAL_TO_OBJECT(exn));
if (!obj->isError())
if (!obj->is<ErrorObject>())
return NULL;
JSExnPrivate *priv = GetExnPrivate(obj);
JSExnPrivate *priv = obj->as<ErrorObject>().getExnPrivate();
if (!priv)
return NULL;
@@ -550,7 +543,8 @@ Exception(JSContext *cx, unsigned argc, Value *vp)
return false;
}
RootedObject obj(cx, NewObjectWithGivenProto(cx, &ErrorClass, &protov.toObject(), NULL));
RootedObject obj(cx, NewObjectWithGivenProto(cx, &ErrorObject::class_, &protov.toObject(),
NULL));
if (!obj)
return false;
@@ -783,7 +777,8 @@ InitErrorClass(JSContext *cx, Handle<GlobalObject*> global, int type, HandleObje
{
JSProtoKey key = GetExceptionProtoKey(type);
RootedAtom name(cx, ClassName(key, cx));
RootedObject errorProto(cx, global->createBlankPrototypeInheriting(cx, &ErrorClass, *proto));
RootedObject errorProto(cx, global->createBlankPrototypeInheriting(cx, &ErrorObject::class_,
*proto));
if (!errorProto)
return NULL;
@@ -956,7 +951,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
return false;
tv[0] = OBJECT_TO_JSVAL(errProto);
RootedObject errObject(cx, NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL));
RootedObject errObject(cx, NewObjectWithGivenProto(cx, &ErrorObject::class_, errProto, NULL));
if (!errObject)
return false;
tv[1] = OBJECT_TO_JSVAL(errObject);
@@ -1047,8 +1042,7 @@ js_ReportUncaughtException(JSContext *cx)
const char *filename_str = js_fileName_str;
JSAutoByteString filename;
if (!reportp && exnObject &&
(exnObject->isError() ||
IsDuckTypedErrorObject(cx, exnObject, &filename_str)))
(exnObject->is<ErrorObject>() || IsDuckTypedErrorObject(cx, exnObject, &filename_str)))
{
RootedString name(cx);
if (JS_GetProperty(cx, exnObject, js_name_str, &roots[2]) &&
@@ -1139,7 +1133,7 @@ extern JSObject *
js_CopyErrorObject(JSContext *cx, HandleObject errobj, HandleObject scope)
{
assertSameCompartment(cx, scope);
JSExnPrivate *priv = GetExnPrivate(errobj);
JSExnPrivate *priv = errobj->as<ErrorObject>().getExnPrivate();
size_t size = offsetof(JSExnPrivate, stackElems) +
priv->stackDepth * sizeof(JSStackTraceElem);
@@ -1174,10 +1168,10 @@ js_CopyErrorObject(JSContext *cx, HandleObject errobj, HandleObject scope)
RootedObject proto(cx, scope->global().getOrCreateCustomErrorPrototype(cx, copy->exnType));
if (!proto)
return NULL;
RootedObject copyobj(cx, NewObjectWithGivenProto(cx, &ErrorClass, proto, NULL));
RootedObject copyobj(cx, NewObjectWithGivenProto(cx, &ErrorObject::class_, proto, NULL));
if (!copyobj)
return NULL;
SetExnPrivate(copyobj, copy);
SetExnPrivate(copyobj->as<ErrorObject>(), copy);
copy.forget();
autoFreeErrorReport.forget();
return copyobj;
-4
View File
@@ -395,10 +395,6 @@ struct Atom {
} /* namespace shadow */
// This is equal to JSFunction::class_. Use it in places where you don't want
// to #include jsfun.h.
extern JS_FRIEND_DATA(js::Class*) FunctionClassPtr;
extern JS_FRIEND_DATA(js::Class) FunctionProxyClass;
extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
+5 -2
View File
@@ -1520,6 +1520,9 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
const jschar *chars = linear->chars();
size_t length = linear->length();
/* Protect inlined chars from root analysis poisoning. */
SkipRoot skip(cx, &chars);
/*
* NB: (new Function) is not lexically closed by its caller, it's just an
* anonymous function in the top-level scope that its constructor inhabits.
@@ -1542,9 +1545,9 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
}
bool
js::IsBuiltinFunctionConstructor(JSFunction *fun)
JSFunction::isBuiltinFunctionConstructor()
{
return fun->maybeNative() == Function;
return maybeNative() == Function;
}
JSFunction *
+75 -8
View File
@@ -11,6 +11,7 @@
*/
#include "jsprvtd.h"
#include "jsobj.h"
#include "jsscript.h"
#include "gc/Barrier.h"
@@ -82,7 +83,17 @@ class JSFunction : public JSObject
public:
/* Call objects must be created for each invocation of a heavyweight function. */
inline bool isHeavyweight() const;
bool isHeavyweight() const {
JS_ASSERT(!isInterpretedLazy());
if (isNative())
return false;
// Note: this should be kept in sync with FunctionBox::isHeavyweight().
return nonLazyScript()->bindings.hasAnyAliasedBindings() ||
nonLazyScript()->funHasExtensibleScope ||
nonLazyScript()->funNeedsDeclEnvObject;
}
/* A function can be classified as either native (C++) or interpreted (JS): */
bool isInterpreted() const { return flags & (INTERPRETED | INTERPRETED_LAZY); }
@@ -128,12 +139,16 @@ class JSFunction : public JSObject
return isInterpreted() && !isFunctionPrototype() &&
(!isSelfHostedBuiltin() || isSelfHostedConstructor());
}
bool isNamedLambda() const {
bool isNamedLambda() const {
return isLambda() && atom_ && !hasGuessedAtom();
}
bool isBuiltinFunctionConstructor();
/* Returns the strictness of this function, which must be interpreted. */
inline bool strict() const;
bool strict() const {
return nonLazyScript()->strict;
}
// Can be called multiple times by the parser.
void setArgCount(uint16_t nargs) {
@@ -190,7 +205,10 @@ class JSFunction : public JSObject
* For an interpreted function, accessors for the initial scope object of
* activations (stack frames) of the function.
*/
inline JSObject *environment() const;
JSObject *environment() const {
JS_ASSERT(isInterpreted());
return u.i.env_;
}
inline void setEnvironment(JSObject *obj);
inline void initEnvironment(JSObject *obj);
@@ -258,7 +276,12 @@ class JSFunction : public JSObject
inline void setScript(JSScript *script_);
inline void initScript(JSScript *script_);
inline void initLazyScript(js::LazyScript *script);
void initLazyScript(js::LazyScript *lazy) {
JS_ASSERT(isInterpreted());
flags &= ~INTERPRETED;
flags |= INTERPRETED_LAZY;
u.i.s.lazy_ = lazy;
}
JSNative native() const {
JS_ASSERT(isNative());
@@ -269,9 +292,21 @@ class JSFunction : public JSObject
return isInterpreted() ? NULL : native();
}
inline void initNative(js::Native native, const JSJitInfo *jitinfo);
inline const JSJitInfo *jitInfo() const;
inline void setJitInfo(const JSJitInfo *data);
void initNative(js::Native native, const JSJitInfo *jitinfo) {
JS_ASSERT(native);
u.n.native = native;
u.n.jitinfo = jitinfo;
}
const JSJitInfo *jitInfo() const {
JS_ASSERT(isNative());
return u.n.jitinfo;
}
void setJitInfo(const JSJitInfo *data) {
JS_ASSERT(isNative());
u.n.jitinfo = data;
}
static unsigned offsetOfNativeOrScript() {
JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.s.script_));
@@ -347,6 +382,31 @@ JSAPIToJSFunctionFlags(unsigned flags)
namespace js {
/* Valueified JS_IsConstructing. */
static JS_ALWAYS_INLINE bool
IsConstructing(const Value *vp)
{
#ifdef DEBUG
JSObject *callee = &JS_CALLEE(cx, vp).toObject();
if (callee->is<JSFunction>()) {
JSFunction *fun = &callee->as<JSFunction>();
JS_ASSERT(fun->isNativeConstructor());
} else {
JS_ASSERT(callee->getClass()->construct != NULL);
}
#endif
return vp[1].isMagic();
}
inline bool
IsConstructing(CallReceiver call)
{
return IsConstructing(call.base());
}
extern JSBool
Function(JSContext *cx, unsigned argc, Value *vp);
extern JSFunction *
NewFunction(JSContext *cx, HandleObject funobj, JSNative native, unsigned nargs,
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
@@ -400,6 +460,13 @@ JSFunction::toExtended() const
return static_cast<const js::FunctionExtended *>(this);
}
inline const js::Value &
JSFunction::getExtendedSlot(size_t which) const
{
JS_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots));
return toExtended()->extendedSlots[which];
}
namespace js {
JSString *FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen);
-109
View File
@@ -16,12 +16,6 @@
#include "vm/ScopeObject-inl.h"
#include "vm/String-inl.h"
inline bool
JSFunction::strict() const
{
return nonLazyScript()->strict;
}
inline void
JSFunction::initAtom(JSAtom *atom)
{
@@ -38,13 +32,6 @@ JSFunction::setGuessedAtom(JSAtom *atom)
flags |= HAS_GUESSED_ATOM;
}
inline JSObject *
JSFunction::environment() const
{
JS_ASSERT(isInterpreted());
return u.i.env_;
}
inline void
JSFunction::setEnvironment(JSObject *obj)
{
@@ -59,28 +46,6 @@ JSFunction::initEnvironment(JSObject *obj)
((js::HeapPtrObject *)&u.i.env_)->init(obj);
}
inline void
JSFunction::initNative(js::Native native, const JSJitInfo *data)
{
JS_ASSERT(native);
u.n.native = native;
u.n.jitinfo = data;
}
inline const JSJitInfo *
JSFunction::jitInfo() const
{
JS_ASSERT(isNative());
return u.n.jitinfo;
}
inline void
JSFunction::setJitInfo(const JSJitInfo *data)
{
JS_ASSERT(isNative());
u.n.jitinfo = data;
}
inline void
JSFunction::initializeExtended()
{
@@ -105,45 +70,8 @@ JSFunction::setExtendedSlot(size_t which, const js::Value &val)
toExtended()->extendedSlots[which] = val;
}
inline const js::Value &
JSFunction::getExtendedSlot(size_t which) const
{
JS_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots));
return toExtended()->extendedSlots[which];
}
namespace js {
extern JS_ALWAYS_INLINE bool
SameTraceType(const Value &lhs, const Value &rhs)
{
return SameType(lhs, rhs) &&
(lhs.isPrimitive() ||
lhs.toObject().is<JSFunction>() == rhs.toObject().is<JSFunction>());
}
/* Valueified JS_IsConstructing. */
static JS_ALWAYS_INLINE bool
IsConstructing(const Value *vp)
{
#ifdef DEBUG
JSObject *callee = &JS_CALLEE(cx, vp).toObject();
if (callee->is<JSFunction>()) {
JSFunction *fun = &callee->as<JSFunction>();
JS_ASSERT(fun->isNativeConstructor());
} else {
JS_ASSERT(callee->getClass()->construct != NULL);
}
#endif
return vp[1].isMagic();
}
inline bool
IsConstructing(CallReceiver call)
{
return IsConstructing(call.base());
}
inline const char *
GetFunctionNameBytes(JSContext *cx, JSFunction *fun, JSAutoByteString *bytes)
{
@@ -153,12 +81,6 @@ GetFunctionNameBytes(JSContext *cx, JSFunction *fun, JSAutoByteString *bytes)
return js_anonymous_str;
}
extern JSBool
Function(JSContext *cx, unsigned argc, Value *vp);
extern bool
IsBuiltinFunctionConstructor(JSFunction *fun);
static inline JSObject *
SkipScopeParent(JSObject *parent)
{
@@ -224,20 +146,6 @@ CloneFunctionObjectIfNotSingleton(JSContext *cx, HandleFunction fun, HandleObjec
} /* namespace js */
inline bool
JSFunction::isHeavyweight() const
{
JS_ASSERT(!isInterpretedLazy());
if (isNative())
return false;
// Note: this should be kept in sync with FunctionBox::isHeavyweight().
return nonLazyScript()->bindings.hasAnyAliasedBindings() ||
nonLazyScript()->funHasExtensibleScope ||
nonLazyScript()->funNeedsDeclEnvObject;
}
inline JSScript *
JSFunction::existingScript()
{
@@ -272,17 +180,6 @@ JSFunction::initScript(JSScript *script_)
mutableScript().init(script_);
}
inline void
JSFunction::initLazyScript(js::LazyScript *lazy)
{
JS_ASSERT(isInterpreted());
flags &= ~INTERPRETED;
flags |= INTERPRETED_LAZY;
u.i.s.lazy_ = lazy;
}
inline JSObject *
JSFunction::getBoundFunctionTarget() const
{
@@ -292,10 +189,4 @@ JSFunction::getBoundFunctionTarget() const
return getParent();
}
inline bool
js::Class::isCallable() const
{
return this == &JSFunction::class_ || call;
}
#endif /* jsfuninlines_h */
+6 -7
View File
@@ -25,11 +25,11 @@
#include "js/HashTable.h"
#include "js/Vector.h"
struct JSAtom;
class JSAtom;
struct JSCompartment;
struct JSFunction;
struct JSFlatString;
struct JSLinearString;
class JSFunction;
class JSFlatString;
class JSLinearString;
namespace js {
@@ -258,9 +258,8 @@ struct ArenaList {
void insert(ArenaHeader *arena);
};
struct ArenaLists
class ArenaLists
{
private:
/*
* For each arena kind its free list is represented as the first span with
* free things. Initially all the spans are initialized as empty. After we
@@ -684,7 +683,7 @@ class GCHelperThread {
bool backgroundAllocation;
friend struct js::gc::ArenaLists;
friend class js::gc::ArenaLists;
void
replenishAndFreeLater(void *ptr);
+4 -4
View File
@@ -2087,7 +2087,7 @@ StackTypeSet::convertDoubleElements(JSContext *cx)
// double in their element types (as the conversion may render the type
// information incorrect), nor for non-array objects (as their elements
// may point to emptyObjectElements, which cannot be converted).
if (!types->hasType(Type::DoubleType()) || type->clasp != &ArrayClass) {
if (!types->hasType(Type::DoubleType()) || type->clasp != &ArrayObject::class_) {
dontConvert = true;
alwaysConvert = false;
continue;
@@ -3181,7 +3181,7 @@ TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
* If the array is heterogenous, keep the existing type object, which has
* unknown properties.
*/
JS_ASSERT(obj->isArray());
JS_ASSERT(obj->is<ArrayObject>());
unsigned len = obj->getDenseInitializedLength();
if (len == 0)
@@ -3210,7 +3210,7 @@ TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
Rooted<Type> origType(cx, type);
/* Make a new type to use for future arrays with the same elements. */
RootedObject objProto(cx, obj->getProto());
Rooted<TypeObject*> objType(cx, newTypeObject(cx, &ArrayClass, objProto));
Rooted<TypeObject*> objType(cx, newTypeObject(cx, &ArrayObject::class_, objProto));
if (!objType) {
cx->compartment()->types.setPendingNukeTypes(cx);
return;
@@ -6010,7 +6010,7 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
if (obj->isIndexed())
type->flags |= OBJECT_FLAG_SPARSE_INDEXES;
if (obj->isArray() && obj->getArrayLength() > INT32_MAX)
if (obj->is<ArrayObject>() && obj->as<ArrayObject>().length() > INT32_MAX)
type->flags |= OBJECT_FLAG_LENGTH_OVERFLOW;
obj->type_ = type;
+2 -1
View File
@@ -19,6 +19,7 @@
#include "builtin/ParallelArray.h"
#include "jit/IonFrames.h"
#include "js/RootingAPI.h"
#include "vm/ArrayObject.h"
#include "vm/BooleanObject.h"
#include "vm/GlobalObject.h"
#include "vm/NumberObject.h"
@@ -465,7 +466,7 @@ GetClassForProtoKey(JSProtoKey key)
case JSProto_Object:
return &ObjectClass;
case JSProto_Array:
return &ArrayClass;
return &ArrayObject::class_;
case JSProto_Number:
return &NumberObject::class_;
+1 -1
View File
@@ -175,7 +175,7 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
CompartmentStats *cStats = GetCompartmentStats(obj->compartment());
if (obj->is<JSFunction>())
cStats->gcHeapObjectsFunction += thingSize;
else if (obj->isArray())
else if (obj->is<ArrayObject>())
cStats->gcHeapObjectsDenseArray += thingSize;
else if (obj->isCrossCompartmentWrapper())
cStats->gcHeapObjectsCrossCompartmentWrapper += thingSize;
+10 -8
View File
@@ -418,24 +418,26 @@ Class NumberObject::class_ = {
static JSBool
Number(JSContext *cx, unsigned argc, Value *vp)
{
/* Sample JS_CALLEE before clobbering. */
bool isConstructing = IsConstructing(vp);
CallArgs args = CallArgsFromVp(argc, vp);
if (argc > 0) {
if (!ToNumber(cx, &vp[2]))
/* Sample JS_CALLEE before clobbering. */
bool isConstructing = IsConstructing(args);
if (args.length() > 0) {
if (!ToNumber(cx, args.handleAt(0)))
return false;
vp[0] = vp[2];
args.rval().set(args[0]);
} else {
vp[0].setInt32(0);
args.rval().setInt32(0);
}
if (!isConstructing)
return true;
JSObject *obj = NumberObject::create(cx, vp[0].toNumber());
JSObject *obj = NumberObject::create(cx, args.rval().toNumber());
if (!obj)
return false;
vp->setObject(*obj);
args.rval().setObject(*obj);
return true;
}
+6 -9
View File
@@ -148,23 +148,20 @@ GetPrefixInteger(JSContext *cx, const jschar *start, const jschar *end, int base
/* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
JS_ALWAYS_INLINE bool
ToNumber(JSContext *cx, Value *vp)
ToNumber(JSContext *cx, JS::MutableHandleValue vp)
{
#ifdef DEBUG
{
SkipRoot skip(cx, vp);
MaybeCheckStackRoots(cx);
}
MaybeCheckStackRoots(cx);
#endif
if (vp->isNumber())
if (vp.isNumber())
return true;
double d;
extern bool ToNumberSlow(JSContext *cx, js::Value v, double *dp);
if (!ToNumberSlow(cx, *vp, &d))
extern bool ToNumberSlow(JSContext *cx, Value v, double *dp);
if (!ToNumberSlow(cx, vp, &d))
return false;
vp->setNumber(d);
vp.setNumber(d);
return true;
}
+41 -30
View File
@@ -37,6 +37,7 @@
#include "jit/BaselineJIT.h"
#include "js/MemoryMetrics.h"
#include "vm/Interpreter.h"
#include "vm/RegExpStaticsObject.h"
#include "vm/Shape.h"
#include "jsatominlines.h"
@@ -45,6 +46,7 @@
#include "jscompartmentinlines.h"
#include "jstypedarrayinlines.h"
#include "builtin/Iterator-inl.h"
#include "vm/ArrayObject-inl.h"
#include "vm/BooleanObject-inl.h"
#include "vm/NumberObject-inl.h"
#include "vm/RegExpStatics-inl.h"
@@ -968,11 +970,9 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
/* ES6 20130308 draft 8.4.2.1 [[DefineOwnProperty]] */
static JSBool
DefinePropertyOnArray(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
DefinePropertyOnArray(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, const PropDesc &desc,
bool throwError, bool *rval)
{
JS_ASSERT(obj->isArray());
/* Step 2. */
if (id == NameToId(cx->names().length)) {
// Canonicalize value, if necessary, before proceeding any further. It
@@ -989,7 +989,7 @@ DefinePropertyOnArray(JSContext *cx, HandleObject obj, HandleId id, const PropDe
return false;
v.setNumber(newLen);
} else {
v.setNumber(obj->getArrayLength());
v.setNumber(arr->length());
}
if (desc.hasConfigurable() && desc.configurable())
@@ -1000,8 +1000,8 @@ DefinePropertyOnArray(JSContext *cx, HandleObject obj, HandleId id, const PropDe
if (desc.isAccessorDescriptor())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
unsigned attrs = obj->nativeLookup(cx, id)->attributes();
if (!obj->arrayLengthIsWritable()) {
unsigned attrs = arr->nativeLookup(cx, id)->attributes();
if (!arr->lengthIsWritable()) {
if (desc.hasWritable() && desc.writable())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
} else {
@@ -1009,33 +1009,35 @@ DefinePropertyOnArray(JSContext *cx, HandleObject obj, HandleId id, const PropDe
attrs = attrs | JSPROP_READONLY;
}
return ArraySetLength(cx, obj, id, attrs, v, throwError);
return ArraySetLength(cx, arr, id, attrs, v, throwError);
}
/* Step 3. */
uint32_t index;
if (js_IdIsIndex(id, &index)) {
/* Step 3b. */
uint32_t oldLen = obj->getArrayLength();
uint32_t oldLen = arr->length();
/* Steps 3a, 3e. */
if (index >= oldLen && !obj->arrayLengthIsWritable())
return Reject(cx, obj, JSMSG_CANT_APPEND_TO_ARRAY, throwError, rval);
if (index >= oldLen && !arr->lengthIsWritable())
return Reject(cx, arr, JSMSG_CANT_APPEND_TO_ARRAY, throwError, rval);
/* Steps 3f-j. */
return DefinePropertyOnObject(cx, obj, id, desc, throwError, rval);
return DefinePropertyOnObject(cx, arr, id, desc, throwError, rval);
}
/* Step 4. */
return DefinePropertyOnObject(cx, obj, id, desc, throwError, rval);
return DefinePropertyOnObject(cx, arr, id, desc, throwError, rval);
}
bool
js::DefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
bool throwError, bool *rval)
{
if (obj->isArray())
return DefinePropertyOnArray(cx, obj, id, desc, throwError, rval);
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
return DefinePropertyOnArray(cx, arr, id, desc, throwError, rval);
}
if (obj->getOps()->lookupGeneric) {
/*
@@ -1228,7 +1230,7 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
// arrays with non-writable length. We don't need to do anything special
// for that, because capacity was zeroed out by preventExtensions. (See
// the assertion before the if-else above.)
if (it == FREEZE && obj->isArray())
if (it == FREEZE && obj->is<ArrayObject>())
obj->getElementsHeader()->setNonwritableArrayLength();
return true;
@@ -1291,7 +1293,7 @@ JSObject::className(JSContext *cx, HandleObject obj)
static inline gc::AllocKind
NewObjectGCKind(js::Class *clasp)
{
if (clasp == &ArrayClass)
if (clasp == &ArrayObject::class_)
return gc::FINALIZE_OBJECT8;
if (clasp == &JSFunction::class_)
return gc::FINALIZE_OBJECT2;
@@ -1302,7 +1304,7 @@ static inline JSObject *
NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *parent,
gc::AllocKind kind, NewObjectKind newKind)
{
JS_ASSERT(clasp != &ArrayClass);
JS_ASSERT(clasp != &ArrayObject::class_);
JS_ASSERT_IF(clasp == &JSFunction::class_,
kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
JS_ASSERT_IF(parent, &parent->global() == cx->compartment()->maybeGlobal());
@@ -2073,7 +2075,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
JS_ASSERT(!a->is<RegExpObject>() && !b->is<RegExpObject>());
/* Arrays can use their fixed storage for elements. */
JS_ASSERT(!a->isArray() && !b->isArray());
JS_ASSERT(!a->is<ArrayObject>() && !b->is<ArrayObject>());
/*
* Callers should not try to swap ArrayBuffer objects,
@@ -2891,8 +2893,6 @@ bool
JSObject::growElements(ThreadSafeContext *tcx, uint32_t newcap)
{
JS_ASSERT(isExtensible());
JS_ASSERT_IF(isArray() && !arrayLengthIsWritable(),
newcap <= getArrayLength());
/*
* When an object with CAPACITY_DOUBLING_MAX or fewer elements needs to
@@ -2912,7 +2912,8 @@ JSObject::growElements(ThreadSafeContext *tcx, uint32_t newcap)
: oldcap + (oldcap >> 3);
uint32_t actualCapacity;
if (isArray() && !arrayLengthIsWritable()) {
if (is<ArrayObject>() && !as<ArrayObject>().lengthIsWritable()) {
JS_ASSERT(newcap <= as<ArrayObject>().length());
// Preserve the |capacity <= length| invariant for arrays with
// non-writable length. See also js::ArraySetLength which initially
// enforces this requirement.
@@ -3387,10 +3388,11 @@ CallAddPropertyHookDense(JSContext *cx, Class *clasp, HandleObject obj, uint32_t
HandleValue nominal)
{
/* Inline addProperty for array objects. */
if (obj->isArray()) {
uint32_t length = obj->getArrayLength();
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
uint32_t length = arr->length();
if (index >= length)
JSObject::setArrayLength(cx, obj, index + 1);
ArrayObject::setLength(cx, arr, index + 1);
return true;
}
@@ -3438,14 +3440,15 @@ DefinePropertyOrElement(JSContext *cx, HandleObject obj, HandleId id,
}
}
if (obj->isArray()) {
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (id == NameToId(cx->names().length))
return ArraySetLength(cx, obj, id, attrs, value, setterIsStrict);
return ArraySetLength(cx, arr, id, attrs, value, setterIsStrict);
uint32_t index;
if (js_IdIsIndex(id, &index)) {
bool definesPast;
if (!WouldDefinePastNonwritableLength(cx, obj, index, setterIsStrict, &definesPast))
if (!WouldDefinePastNonwritableLength(cx, arr, index, setterIsStrict, &definesPast))
return false;
if (definesPast)
return true;
@@ -4535,8 +4538,10 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
return true;
}
if (obj->isArray() && id == NameToId(cx->names().length))
return ArraySetLength(cx, obj, id, attrs, vp, strict);
if (obj->is<ArrayObject>() && id == NameToId(cx->names().length)) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
return ArraySetLength(cx, arr, id, attrs, vp, strict);
}
if (!shape) {
if (!obj->isExtensible()) {
@@ -5239,6 +5244,12 @@ DumpProperty(JSObject *obj, Shape &shape)
fprintf(stderr, "\n");
}
bool
JSObject::isProxySlow() const
{
return isProxy();
}
void
JSObject::dump()
{
@@ -5449,7 +5460,7 @@ JSObject::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ObjectsExt
// Note that sizes->private_ is measured elsewhere.
if (is<ArgumentsObject>()) {
sizes->argumentsData = as<ArgumentsObject>().sizeOfMisc(mallocSizeOf);
} else if (isRegExpStatics()) {
} else if (is<RegExpStaticsObject>()) {
sizes->regExpStatics = js::SizeOfRegExpStaticsData(this, mallocSizeOf);
} else if (is<PropertyIteratorObject>()) {
sizes->propertyIteratorData = as<PropertyIteratorObject>().sizeOfMisc(mallocSizeOf);
+246 -123
View File
@@ -188,15 +188,11 @@ DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, JSBool *succeeded);
} /* namespace js::baseops */
extern Class ArrayClass;
extern Class DateClass;
extern Class ErrorClass;
extern Class IntlClass;
extern Class JSONClass;
extern Class MathClass;
extern Class ObjectClass;
extern Class ProxyClass;
extern Class RegExpStaticsClass;
class ArrayBufferObject;
class GlobalObject;
@@ -333,13 +329,15 @@ class JSObject : public js::ObjectImpl
/* Accessors for properties. */
/* Whether a slot is at a fixed offset from this object. */
inline bool isFixedSlot(size_t slot);
bool isFixedSlot(size_t slot) {
return slot < numFixedSlots();
}
/* Index into the dynamic slots array to use for a dynamic slot. */
inline size_t dynamicSlotIndex(size_t slot);
/* Get a raw pointer to the object's properties. */
inline const js::HeapSlot *getRawSlots();
size_t dynamicSlotIndex(size_t slot) {
JS_ASSERT(slot >= numFixedSlots());
return slot - numFixedSlots();
}
/*
* Grow or shrink slots immediately before changing the slot span.
@@ -409,7 +407,11 @@ class JSObject : public js::ObjectImpl
* If obj is a proxy and the proto is lazy, this code may allocate or
* GC in order to compute the proto. Currently, it will not run JS code.
*/
inline JSObject *getProto() const;
bool isProxySlow() const;
JSObject *getProto() const {
JS_ASSERT(!isProxySlow());
return js::ObjectImpl::getProto();
}
static inline bool getProto(JSContext *cx, js::HandleObject obj,
js::MutableHandleObject protop);
@@ -529,9 +531,18 @@ class JSObject : public js::ObjectImpl
inline bool ensureElements(JSContext *cx, uint32_t cap);
bool growElements(js::ThreadSafeContext *tcx, uint32_t newcap);
void shrinkElements(JSContext *cx, uint32_t cap);
inline void setDynamicElements(js::ObjectElements *header);
void setDynamicElements(js::ObjectElements *header) {
JS_ASSERT(!hasDynamicElements());
elements = header->elements();
JS_ASSERT(hasDynamicElements());
}
uint32_t getDenseCapacity() {
JS_ASSERT(isNativeSlow());
JS_ASSERT(getElementsHeader()->capacity >= getElementsHeader()->initializedLength);
return getElementsHeader()->capacity;
}
inline uint32_t getDenseCapacity();
inline void setDenseInitializedLength(uint32_t length);
inline void ensureDenseInitializedLength(JSContext *cx, uint32_t index, uint32_t extra);
inline void setDenseElement(uint32_t index, const js::Value &val);
@@ -548,7 +559,12 @@ class JSObject : public js::ObjectImpl
inline void initDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count);
inline void moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count);
inline void moveDenseElementsUnbarriered(uint32_t dstStart, uint32_t srcStart, uint32_t count);
inline bool shouldConvertDoubleElements();
bool shouldConvertDoubleElements() {
JS_ASSERT(isNativeSlow());
return getElementsHeader()->shouldConvertDoubleElements();
}
inline void setShouldConvertDoubleElements();
/* Packed information for this object's elements. */
@@ -596,41 +612,6 @@ class JSObject : public js::ObjectImpl
*/
static EnsureDenseResult maybeDensifySparseElements(JSContext *cx, js::HandleObject obj);
/* Array specific accessors. */
inline bool arrayLengthIsWritable() const;
inline uint32_t getArrayLength() const;
static inline void setArrayLength(JSContext *cx, js::HandleObject obj, uint32_t length);
inline void setArrayLengthInt32(uint32_t length);
public:
/*
* Date-specific getters and setters.
*/
static const uint32_t JSSLOT_DATE_UTC_TIME = 0;
static const uint32_t JSSLOT_DATE_TZA = 1;
/*
* Cached slots holding local properties of the date.
* These are undefined until the first actual lookup occurs
* and are reset to undefined whenever the date's time is modified.
*/
static const uint32_t JSSLOT_DATE_COMPONENTS_START = 2;
static const uint32_t JSSLOT_DATE_LOCAL_TIME = JSSLOT_DATE_COMPONENTS_START + 0;
static const uint32_t JSSLOT_DATE_LOCAL_YEAR = JSSLOT_DATE_COMPONENTS_START + 1;
static const uint32_t JSSLOT_DATE_LOCAL_MONTH = JSSLOT_DATE_COMPONENTS_START + 2;
static const uint32_t JSSLOT_DATE_LOCAL_DATE = JSSLOT_DATE_COMPONENTS_START + 3;
static const uint32_t JSSLOT_DATE_LOCAL_DAY = JSSLOT_DATE_COMPONENTS_START + 4;
static const uint32_t JSSLOT_DATE_LOCAL_HOURS = JSSLOT_DATE_COMPONENTS_START + 5;
static const uint32_t JSSLOT_DATE_LOCAL_MINUTES = JSSLOT_DATE_COMPONENTS_START + 6;
static const uint32_t JSSLOT_DATE_LOCAL_SECONDS = JSSLOT_DATE_COMPONENTS_START + 7;
static const uint32_t DATE_CLASS_RESERVED_SLOTS = JSSLOT_DATE_LOCAL_SECONDS + 1;
inline const js::Value &getDateUTCTime() const;
inline void setDateUTCTime(const js::Value &pthis);
public:
/*
* Iterator-specific getters and setters.
@@ -641,7 +622,9 @@ class JSObject : public js::ObjectImpl
/*
* Back to generic stuff.
*/
inline bool isCallable();
bool isCallable() {
return getClass()->isCallable();
}
inline void finish(js::FreeOp *fop);
JS_ALWAYS_INLINE void finalize(js::FreeOp *fop);
@@ -751,91 +734,196 @@ class JSObject : public js::ObjectImpl
/* Clear the scope, making it empty. */
static void clear(JSContext *cx, js::HandleObject obj);
static inline JSBool lookupGeneric(JSContext *cx, js::HandleObject obj,
js::HandleId id,
js::MutableHandleObject objp, js::MutableHandleShape propp);
static inline JSBool lookupProperty(JSContext *cx, js::HandleObject obj,
js::PropertyName *name,
js::MutableHandleObject objp, js::MutableHandleShape propp);
static inline JSBool lookupElement(JSContext *cx, js::HandleObject obj,
uint32_t index,
js::MutableHandleObject objp, js::MutableHandleShape propp);
static inline JSBool lookupSpecial(JSContext *cx, js::HandleObject obj,
js::SpecialId sid,
js::MutableHandleObject objp, js::MutableHandleShape propp);
static JSBool lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
/* NB: The logic of lookupGeneric is implicitly reflected in IonBuilder.cpp's
* |CanEffectlesslyCallLookupGenericOnObject| logic.
* If this changes, please remember to update the logic there as well.
*/
js::LookupGenericOp op = obj->getOps()->lookupGeneric;
if (op)
return op(cx, obj, id, objp, propp);
return js::baseops::LookupProperty<js::CanGC>(cx, obj, id, objp, propp);
}
static inline JSBool defineGeneric(JSContext *cx, js::HandleObject obj,
static JSBool lookupProperty(JSContext *cx, js::HandleObject obj, js::PropertyName *name,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
JS::RootedId id(cx, js::NameToId(name));
return lookupGeneric(cx, obj, id, objp, propp);
}
static JSBool lookupElement(JSContext *cx, js::HandleObject obj, uint32_t index,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
js::LookupElementOp op = obj->getOps()->lookupElement;
return (op ? op : js::baseops::LookupElement)(cx, obj, index, objp, propp);
}
static JSBool lookupSpecial(JSContext *cx, js::HandleObject obj, js::SpecialId sid,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return lookupGeneric(cx, obj, id, objp, propp);
}
static JSBool defineGeneric(JSContext *cx, js::HandleObject obj,
js::HandleId id, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE);
static inline JSBool defineProperty(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE);
unsigned attrs = JSPROP_ENUMERATE)
{
JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
js::DefineGenericOp op = obj->getOps()->defineGeneric;
return (op ? op : js::baseops::DefineGeneric)(cx, obj, id, value, getter, setter, attrs);
}
static inline JSBool defineElement(JSContext *cx, js::HandleObject obj,
uint32_t index, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE);
static inline JSBool defineSpecial(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE);
static JSBool defineProperty(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE)
{
JS::RootedId id(cx, js::NameToId(name));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
static inline JSBool getGeneric(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver,
js::HandleId id, js::MutableHandleValue vp);
static inline JSBool getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
jsid id, js::Value *vp);
static inline JSBool getProperty(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver,
js::PropertyName *name, js::MutableHandleValue vp);
static inline JSBool getPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
js::PropertyName *name, js::Value *vp);
static inline JSBool getElement(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver,
static JSBool defineElement(JSContext *cx, js::HandleObject obj,
uint32_t index, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE)
{
js::DefineElementOp op = obj->getOps()->defineElement;
return (op ? op : js::baseops::DefineElement)(cx, obj, index, value, getter, setter, attrs);
}
static JSBool defineSpecial(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, js::HandleValue value,
JSPropertyOp getter = JS_PropertyStub,
JSStrictPropertyOp setter = JS_StrictPropertyStub,
unsigned attrs = JSPROP_ENUMERATE)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
static JSBool getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::HandleId id, js::MutableHandleValue vp)
{
js::GenericIdOp op = obj->getOps()->getGeneric;
if (op) {
if (!op(cx, obj, receiver, id, vp))
return false;
} else {
if (!js::baseops::GetProperty(cx, obj, receiver, id, vp))
return false;
}
return true;
}
static JSBool getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
jsid id, js::Value *vp)
{
js::GenericIdOp op = obj->getOps()->getGeneric;
if (op)
return false;
return js::baseops::GetPropertyNoGC(cx, obj, receiver, id, vp);
}
static JSBool getProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::PropertyName *name, js::MutableHandleValue vp)
{
JS::RootedId id(cx, js::NameToId(name));
return getGeneric(cx, obj, receiver, id, vp);
}
static JSBool getPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
js::PropertyName *name, js::Value *vp)
{
return getGenericNoGC(cx, obj, receiver, js::NameToId(name), vp);
}
static inline JSBool getElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
uint32_t index, js::MutableHandleValue vp);
static inline JSBool getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
uint32_t index, js::Value *vp);
/* If element is not present (e.g. array hole) *present is set to
false and the contents of *vp are unusable garbage. */
static inline JSBool getElementIfPresent(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver, uint32_t index,
js::MutableHandleValue vp, bool *present);
static inline JSBool getSpecial(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver, js::SpecialId sid,
js::MutableHandleValue vp);
static inline JSBool setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::HandleId id,
js::MutableHandleValue vp, JSBool strict);
static inline JSBool setProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::PropertyName *name,
js::MutableHandleValue vp, JSBool strict);
static inline JSBool setElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
uint32_t index,
js::MutableHandleValue vp, JSBool strict);
static inline JSBool setSpecial(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::SpecialId sid,
js::MutableHandleValue vp, JSBool strict);
static JSBool getSpecial(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver, js::SpecialId sid,
js::MutableHandleValue vp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return getGeneric(cx, obj, receiver, id, vp);
}
static JSBool setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::HandleId id, js::MutableHandleValue vp, JSBool strict)
{
if (obj->getOps()->setGeneric)
return nonNativeSetProperty(cx, obj, id, vp, strict);
return js::baseops::SetPropertyHelper(cx, obj, receiver, id, 0, vp, strict);
}
static JSBool setProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::PropertyName *name,
js::MutableHandleValue vp, JSBool strict)
{
JS::RootedId id(cx, js::NameToId(name));
return setGeneric(cx, obj, receiver, id, vp, strict);
}
static JSBool setElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
uint32_t index, js::MutableHandleValue vp, JSBool strict)
{
if (obj->getOps()->setElement)
return nonNativeSetElement(cx, obj, index, vp, strict);
return js::baseops::SetElementHelper(cx, obj, receiver, index, 0, vp, strict);
}
static JSBool setSpecial(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::SpecialId sid, js::MutableHandleValue vp, JSBool strict)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return setGeneric(cx, obj, receiver, id, vp, strict);
}
static JSBool nonNativeSetProperty(JSContext *cx, js::HandleObject obj,
js::HandleId id, js::MutableHandleValue vp, JSBool strict);
static JSBool nonNativeSetElement(JSContext *cx, js::HandleObject obj,
uint32_t index, js::MutableHandleValue vp, JSBool strict);
static inline JSBool getGenericAttributes(JSContext *cx, js::HandleObject obj,
js::HandleId id, unsigned *attrsp);
static inline JSBool getPropertyAttributes(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, unsigned *attrsp);
static JSBool getGenericAttributes(JSContext *cx, js::HandleObject obj,
js::HandleId id, unsigned *attrsp)
{
js::GenericAttributesOp op = obj->getOps()->getGenericAttributes;
return (op ? op : js::baseops::GetAttributes)(cx, obj, id, attrsp);
}
static JSBool getPropertyAttributes(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, unsigned *attrsp)
{
JS::RootedId id(cx, js::NameToId(name));
return getGenericAttributes(cx, obj, id, attrsp);
}
static inline JSBool getElementAttributes(JSContext *cx, js::HandleObject obj,
uint32_t index, unsigned *attrsp);
static inline JSBool getSpecialAttributes(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, unsigned *attrsp);
static JSBool getSpecialAttributes(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, unsigned *attrsp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return getGenericAttributes(cx, obj, id, attrsp);
}
static inline JSBool setGenericAttributes(JSContext *cx, js::HandleObject obj,
js::HandleId id, unsigned *attrsp);
@@ -856,11 +944,31 @@ class JSObject : public js::ObjectImpl
static bool deleteByValue(JSContext *cx, js::HandleObject obj,
const js::Value &property, JSBool *succeeded);
static inline bool enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop,
JS::MutableHandleValue statep, JS::MutableHandleId idp);
static inline bool defaultValue(JSContext *cx, js::HandleObject obj,
JSType hint, js::MutableHandleValue vp);
static inline JSObject *thisObject(JSContext *cx, js::HandleObject obj);
static bool enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop,
JS::MutableHandleValue statep, JS::MutableHandleId idp)
{
JSNewEnumerateOp op = obj->getOps()->enumerate;
return (op ? op : JS_EnumerateState)(cx, obj, iterop, statep, idp);
}
static bool defaultValue(JSContext *cx, js::HandleObject obj, JSType hint,
js::MutableHandleValue vp)
{
JSConvertOp op = obj->getClass()->convert;
bool ok;
if (op == JS_ConvertStub)
ok = js::DefaultValue(cx, obj, hint, vp);
else
ok = op(cx, obj, hint, vp);
JS_ASSERT_IF(ok, vp.isPrimitive());
return ok;
}
static JSObject *thisObject(JSContext *cx, js::HandleObject obj)
{
JSObjectOp op = obj->getOps()->thisObject;
return op ? op(cx, obj) : obj;
}
static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp);
@@ -912,12 +1020,8 @@ class JSObject : public js::ObjectImpl
}
/* Direct subtypes of JSObject: */
inline bool isArray() const { return hasClass(&js::ArrayClass); }
inline bool isDate() const { return hasClass(&js::DateClass); }
inline bool isError() const { return hasClass(&js::ErrorClass); }
inline bool isObject() const { return hasClass(&js::ObjectClass); }
using js::ObjectImpl::isProxy;
inline bool isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
inline bool isTypedArray() const;
/* Subtypes of Proxy. */
@@ -969,6 +1073,28 @@ struct JSObject_Slots8 : JSObject { js::Value fslots[8]; };
struct JSObject_Slots12 : JSObject { js::Value fslots[12]; };
struct JSObject_Slots16 : JSObject { js::Value fslots[16]; };
static inline bool
js_IsCallable(const js::Value &v)
{
return v.isObject() && v.toObject().isCallable();
}
inline JSObject *
GetInnerObject(JSContext *cx, js::HandleObject obj)
{
if (JSObjectOp op = obj->getClass()->ext.innerObject)
return op(cx, obj);
return obj;
}
inline JSObject *
GetOuterObject(JSContext *cx, js::HandleObject obj)
{
if (JSObjectOp op = obj->getClass()->ext.outerObject)
return op(cx, obj);
return obj;
}
class JSValueArray {
public:
jsval *array;
@@ -1361,9 +1487,6 @@ NonNullObject(JSContext *cx, const Value &v);
extern const char *
InformalValueTypeName(const Value &v);
inline void
DestroyIdArray(FreeOp *fop, JSIdArray *ida);
extern bool
GetFirstArgumentAsObject(JSContext *cx, const CallArgs &args, const char *method,
MutableHandleObject objp);
+8 -376
View File
@@ -11,6 +11,8 @@
#include "jswrapper.h"
#include "vm/ArrayObject.h"
#include "vm/DateObject.h"
#include "vm/NumberObject.h"
#include "vm/Probes.h"
#include "vm/StringObject.h"
@@ -20,68 +22,6 @@
#include "vm/ObjectImpl-inl.h"
/* static */ inline bool
JSObject::enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop,
JS::MutableHandleValue statep, JS::MutableHandleId idp)
{
JSNewEnumerateOp op = obj->getOps()->enumerate;
return (op ? op : JS_EnumerateState)(cx, obj, iterop, statep, idp);
}
/* static */ inline bool
JSObject::defaultValue(JSContext *cx, js::HandleObject obj, JSType hint, js::MutableHandleValue vp)
{
JSConvertOp op = obj->getClass()->convert;
bool ok;
if (op == JS_ConvertStub)
ok = js::DefaultValue(cx, obj, hint, vp);
else
ok = op(cx, obj, hint, vp);
JS_ASSERT_IF(ok, vp.isPrimitive());
return ok;
}
/* static */ inline JSObject *
JSObject::thisObject(JSContext *cx, js::HandleObject obj)
{
JSObjectOp op = obj->getOps()->thisObject;
return op ? op(cx, obj) : obj;
}
/* static */ inline JSBool
JSObject::setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::HandleId id, js::MutableHandleValue vp, JSBool strict)
{
if (obj->getOps()->setGeneric)
return nonNativeSetProperty(cx, obj, id, vp, strict);
return js::baseops::SetPropertyHelper(cx, obj, receiver, id, 0, vp, strict);
}
/* static */ inline JSBool
JSObject::setProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::PropertyName *name, js::MutableHandleValue vp, JSBool strict)
{
JS::RootedId id(cx, js::NameToId(name));
return setGeneric(cx, obj, receiver, id, vp, strict);
}
/* static */ inline JSBool
JSObject::setElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
uint32_t index, js::MutableHandleValue vp, JSBool strict)
{
if (obj->getOps()->setElement)
return nonNativeSetElement(cx, obj, index, vp, strict);
return js::baseops::SetElementHelper(cx, obj, receiver, index, 0, vp, strict);
}
/* static */ inline JSBool
JSObject::setSpecial(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::SpecialId sid, js::MutableHandleValue vp, JSBool strict)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return setGeneric(cx, obj, receiver, id, vp, strict);
}
/* static */ inline JSBool
JSObject::setGenericAttributes(JSContext *cx, js::HandleObject obj,
js::HandleId id, unsigned *attrsp)
@@ -122,46 +62,6 @@ JSObject::changePropertyAttributes(JSContext *cx, js::HandleObject obj,
return !!changeProperty(cx, obj, shape, attrs, 0, shape->getter(), shape->setter());
}
/* static */ inline JSBool
JSObject::getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::HandleId id, js::MutableHandleValue vp)
{
js::GenericIdOp op = obj->getOps()->getGeneric;
if (op) {
if (!op(cx, obj, receiver, id, vp))
return false;
} else {
if (!js::baseops::GetProperty(cx, obj, receiver, id, vp))
return false;
}
return true;
}
/* static */ inline JSBool
JSObject::getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
jsid id, js::Value *vp)
{
js::GenericIdOp op = obj->getOps()->getGeneric;
if (op)
return false;
return js::baseops::GetPropertyNoGC(cx, obj, receiver, id, vp);
}
/* static */ inline JSBool
JSObject::getProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::PropertyName *name, js::MutableHandleValue vp)
{
JS::RootedId id(cx, js::NameToId(name));
return getGeneric(cx, obj, receiver, id, vp);
}
/* static */ inline JSBool
JSObject::getPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
js::PropertyName *name, js::Value *vp)
{
return getGenericNoGC(cx, obj, receiver, js::NameToId(name), vp);
}
/* static */ inline bool
JSObject::deleteProperty(JSContext *cx, js::HandleObject obj, js::HandlePropertyName name,
JSBool *succeeded)
@@ -227,19 +127,6 @@ JSObject::getMetadata() const
return lastProperty()->getObjectMetadata();
}
inline bool
JSObject::isFixedSlot(size_t slot)
{
return slot < numFixedSlots();
}
inline size_t
JSObject::dynamicSlotIndex(size_t slot)
{
JS_ASSERT(slot >= numFixedSlots());
return slot - numFixedSlots();
}
inline void
JSObject::setLastPropertyInfallible(js::Shape *shape)
{
@@ -278,13 +165,6 @@ JSObject::canRemoveLastProperty()
&& previous->getObjectFlags() == lastProperty()->getObjectFlags();
}
inline const js::HeapSlot *
JSObject::getRawSlots()
{
JS_ASSERT(is<js::GlobalObject>());
return slots;
}
inline void
JSObject::setReservedSlot(uint32_t index, const js::Value &v)
{
@@ -314,48 +194,6 @@ JSObject::prepareElementRangeForOverwrite(size_t start, size_t end)
elements[i].js::HeapSlot::~HeapSlot();
}
inline uint32_t
JSObject::getArrayLength() const
{
JS_ASSERT(isArray());
return getElementsHeader()->length;
}
inline bool
JSObject::arrayLengthIsWritable() const
{
JS_ASSERT(isArray());
return !getElementsHeader()->hasNonwritableArrayLength();
}
/* static */ inline void
JSObject::setArrayLength(JSContext *cx, js::HandleObject obj, uint32_t length)
{
JS_ASSERT(obj->isArray());
JS_ASSERT(obj->arrayLengthIsWritable());
if (length > INT32_MAX) {
/* Track objects with overflowing lengths in type information. */
js::types::MarkTypeObjectFlags(cx, obj,
js::types::OBJECT_FLAG_LENGTH_OVERFLOW);
jsid lengthId = js::NameToId(cx->names().length);
js::types::AddTypePropertyId(cx, obj, lengthId,
js::types::Type::DoubleType());
}
obj->getElementsHeader()->length = length;
}
inline void
JSObject::setArrayLengthInt32(uint32_t length)
{
/* Variant of setArrayLength for use on arrays where the length cannot overflow int32_t. */
JS_ASSERT(isArray());
JS_ASSERT(arrayLengthIsWritable());
JS_ASSERT(length <= INT32_MAX);
getElementsHeader()->length = length;
}
inline void
JSObject::setDenseInitializedLength(uint32_t length)
{
@@ -365,25 +203,10 @@ JSObject::setDenseInitializedLength(uint32_t length)
getElementsHeader()->initializedLength = length;
}
inline uint32_t
JSObject::getDenseCapacity()
{
JS_ASSERT(isNative());
JS_ASSERT(getElementsHeader()->capacity >= getElementsHeader()->initializedLength);
return getElementsHeader()->capacity;
}
inline bool
JSObject::shouldConvertDoubleElements()
{
JS_ASSERT(isNative());
return getElementsHeader()->shouldConvertDoubleElements();
}
inline void
JSObject::setShouldConvertDoubleElements()
{
JS_ASSERT(isArray() && !hasEmptyElements());
JS_ASSERT(is<js::ArrayObject>() && !hasEmptyElements());
getElementsHeader()->setShouldConvertDoubleElements();
}
@@ -395,14 +218,6 @@ JSObject::ensureElements(JSContext *cx, uint32_t capacity)
return true;
}
inline void
JSObject::setDynamicElements(js::ObjectElements *header)
{
JS_ASSERT(!hasDynamicElements());
elements = header->elements();
JS_ASSERT(hasDynamicElements());
}
inline void
JSObject::setDenseElement(uint32_t index, const js::Value &val)
{
@@ -603,7 +418,7 @@ inline JSObject::EnsureDenseResult
JSObject::parExtendDenseElements(js::ThreadSafeContext *tcx, js::Value *v, uint32_t extra)
{
JS_ASSERT(isNative());
JS_ASSERT_IF(isArray(), arrayLengthIsWritable());
JS_ASSERT_IF(is<js::ArrayObject>(), as<js::ArrayObject>().lengthIsWritable());
js::ObjectElements *header = getElementsHeader();
uint32_t initializedLength = header->initializedLength;
@@ -676,34 +491,6 @@ JSObject::ensureDenseElements(JSContext *cx, uint32_t index, uint32_t extra)
return ED_OK;
}
namespace js {
/*
* Any name atom for a function which will be added as a DeclEnv object to the
* scope chain above call objects for fun.
*/
static inline JSAtom *
CallObjectLambdaName(JSFunction &fun)
{
return fun.isNamedLambda() ? fun.atom() : NULL;
}
} /* namespace js */
inline const js::Value &
JSObject::getDateUTCTime() const
{
JS_ASSERT(isDate());
return getFixedSlot(JSSLOT_DATE_UTC_TIME);
}
inline void
JSObject::setDateUTCTime(const js::Value &time)
{
JS_ASSERT(isDate());
setFixedSlot(JSSLOT_DATE_UTC_TIME, time);
}
/* static */ inline bool
JSObject::setSingletonType(JSContext *cx, js::HandleObject obj)
{
@@ -758,13 +545,6 @@ JSObject::setType(js::types::TypeObject *newType)
type_ = newType;
}
inline JSObject *
JSObject::getProto() const
{
JS_ASSERT(!isProxy());
return js::ObjectImpl::getProto();
}
/* static */ inline bool
JSObject::getProto(JSContext *cx, js::HandleObject obj, js::MutableHandleObject protop)
{
@@ -853,7 +633,7 @@ JSObject::create(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap
*/
JS_ASSERT(shape && type);
JS_ASSERT(type->clasp == shape->getObjectClass());
JS_ASSERT(type->clasp != &js::ArrayClass);
JS_ASSERT(type->clasp != &js::ArrayObject::class_);
JS_ASSERT(js::gc::GetGCKindSlots(kind, type->clasp) == shape->numFixedSlots());
JS_ASSERT_IF(type->clasp->flags & JSCLASS_BACKGROUND_FINALIZE, IsBackgroundFinalized(kind));
JS_ASSERT_IF(type->clasp->finalize, heap == js::gc::TenuredHeap);
@@ -903,7 +683,7 @@ JSObject::createArray(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap
{
JS_ASSERT(shape && type);
JS_ASSERT(type->clasp == shape->getObjectClass());
JS_ASSERT(type->clasp == &js::ArrayClass);
JS_ASSERT(type->clasp == &js::ArrayObject::class_);
JS_ASSERT_IF(type->clasp->finalize, heap == js::gc::TenuredHeap);
/*
@@ -965,12 +745,6 @@ JSObject::hasProperty(JSContext *cx, js::HandleObject obj,
return true;
}
inline bool
JSObject::isCallable()
{
return getClass()->isCallable();
}
inline void
JSObject::nativeSetSlot(uint32_t slot, const js::Value &value)
{
@@ -1005,88 +779,6 @@ JSObject::hasShapeTable() const
return lastProperty()->hasTable();
}
/* static */ inline JSBool
JSObject::lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
/* NB: The logic of lookupGeneric is implicitly reflected in IonBuilder.cpp's
* |CanEffectlesslyCallLookupGenericOnObject| logic.
* If this changes, please remember to update the logic there as well.
*/
js::LookupGenericOp op = obj->getOps()->lookupGeneric;
if (op)
return op(cx, obj, id, objp, propp);
return js::baseops::LookupProperty<js::CanGC>(cx, obj, id, objp, propp);
}
/* static */ inline JSBool
JSObject::lookupProperty(JSContext *cx, js::HandleObject obj, js::PropertyName *name,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
JS::RootedId id(cx, js::NameToId(name));
return lookupGeneric(cx, obj, id, objp, propp);
}
/* static */ inline JSBool
JSObject::defineGeneric(JSContext *cx, js::HandleObject obj,
js::HandleId id, js::HandleValue value,
JSPropertyOp getter /* = JS_PropertyStub */,
JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
unsigned attrs /* = JSPROP_ENUMERATE */)
{
JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
js::DefineGenericOp op = obj->getOps()->defineGeneric;
return (op ? op : js::baseops::DefineGeneric)(cx, obj, id, value, getter, setter, attrs);
}
/* static */ inline JSBool
JSObject::defineProperty(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, js::HandleValue value,
JSPropertyOp getter /* = JS_PropertyStub */,
JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
unsigned attrs /* = JSPROP_ENUMERATE */)
{
JS::RootedId id(cx, js::NameToId(name));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
/* static */ inline JSBool
JSObject::defineElement(JSContext *cx, js::HandleObject obj,
uint32_t index, js::HandleValue value,
JSPropertyOp getter /* = JS_PropertyStub */,
JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
unsigned attrs /* = JSPROP_ENUMERATE */)
{
js::DefineElementOp op = obj->getOps()->defineElement;
return (op ? op : js::baseops::DefineElement)(cx, obj, index, value, getter, setter, attrs);
}
/* static */ inline JSBool
JSObject::defineSpecial(JSContext *cx, js::HandleObject obj, js::SpecialId sid, js::HandleValue value,
JSPropertyOp getter /* = JS_PropertyStub */,
JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
unsigned attrs /* = JSPROP_ENUMERATE */)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
/* static */ inline JSBool
JSObject::lookupElement(JSContext *cx, js::HandleObject obj, uint32_t index,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
js::LookupElementOp op = obj->getOps()->lookupElement;
return (op ? op : js::baseops::LookupElement)(cx, obj, index, objp, propp);
}
/* static */ inline JSBool
JSObject::lookupSpecial(JSContext *cx, js::HandleObject obj, js::SpecialId sid,
js::MutableHandleObject objp, js::MutableHandleShape propp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return lookupGeneric(cx, obj, id, objp, propp);
}
/* static */ inline JSBool
JSObject::getElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
uint32_t index, js::MutableHandleValue vp)
@@ -1147,30 +839,6 @@ JSObject::getElementIfPresent(JSContext *cx, js::HandleObject obj, js::HandleObj
return getGeneric(cx, obj, receiver, id, vp);
}
/* static */ inline JSBool
JSObject::getSpecial(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
js::SpecialId sid, js::MutableHandleValue vp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return getGeneric(cx, obj, receiver, id, vp);
}
/* static */ inline JSBool
JSObject::getGenericAttributes(JSContext *cx, js::HandleObject obj,
js::HandleId id, unsigned *attrsp)
{
js::GenericAttributesOp op = obj->getOps()->getGenericAttributes;
return (op ? op : js::baseops::GetAttributes)(cx, obj, id, attrsp);
}
/* static */ inline JSBool
JSObject::getPropertyAttributes(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, unsigned *attrsp)
{
JS::RootedId id(cx, js::NameToId(name));
return getGenericAttributes(cx, obj, id, attrsp);
}
/* static */ inline JSBool
JSObject::getElementAttributes(JSContext *cx, js::HandleObject obj,
uint32_t index, unsigned *attrsp)
@@ -1181,14 +849,6 @@ JSObject::getElementAttributes(JSContext *cx, js::HandleObject obj,
return getGenericAttributes(cx, obj, id, attrsp);
}
/* static */ inline JSBool
JSObject::getSpecialAttributes(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, unsigned *attrsp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return getGenericAttributes(cx, obj, id, attrsp);
}
inline bool
JSObject::isCrossCompartmentWrapper() const
{
@@ -1212,12 +872,6 @@ JSObject::global() const
return *compartment()->maybeGlobal();
}
static inline bool
js_IsCallable(const js::Value &v)
{
return v.isObject() && v.toObject().isCallable();
}
namespace js {
PropDesc::PropDesc(const Value &getter, const Value &setter,
@@ -1236,22 +890,6 @@ PropDesc::PropDesc(const Value &getter, const Value &setter,
MOZ_ASSERT(setter.isUndefined() || js_IsCallable(setter));
}
inline JSObject *
GetInnerObject(JSContext *cx, HandleObject obj)
{
if (JSObjectOp op = obj->getClass()->ext.innerObject)
return op(cx, obj);
return obj;
}
inline JSObject *
GetOuterObject(JSContext *cx, HandleObject obj)
{
if (JSObjectOp op = obj->getClass()->ext.outerObject)
return op(cx, obj);
return obj;
}
static JS_ALWAYS_INLINE bool
IsFunctionObject(const js::Value &v)
{
@@ -1624,13 +1262,13 @@ ObjectClassIs(HandleObject obj, ESClassValue classValue, JSContext *cx)
return Proxy::objectClassIs(obj, classValue, cx);
switch (classValue) {
case ESClass_Array: return obj->isArray();
case ESClass_Array: return obj->is<ArrayObject>();
case ESClass_Number: return obj->is<NumberObject>();
case ESClass_String: return obj->is<StringObject>();
case ESClass_Boolean: return obj->is<BooleanObject>();
case ESClass_RegExp: return obj->is<RegExpObject>();
case ESClass_ArrayBuffer: return obj->is<ArrayBufferObject>();
case ESClass_Date: return obj->isDate();
case ESClass_Date: return obj->is<DateObject>();
}
JS_NOT_REACHED("bad classValue");
return false;
@@ -1709,10 +1347,4 @@ js_PurgeScopeChain(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
return true;
}
inline void
js::DestroyIdArray(FreeOp *fop, JSIdArray *ida)
{
fop->free_(ida);
}
#endif /* jsobjinlines_h */
+1 -1
View File
@@ -563,7 +563,7 @@ js_Stringify(JSContext *cx, MutableHandleValue vp, JSObject *replacer_, Value sp
/* Step 4b(ii). */
uint32_t len;
JS_ALWAYS_TRUE(GetLengthProperty(cx, replacer, &len));
if (replacer->isArray() && !replacer->isIndexed())
if (replacer->is<ArrayObject>() && !replacer->isIndexed())
len = Min(len, replacer->getDenseInitializedLength());
// Cap the initial size to a moderately small value. This avoids
+2 -2
View File
@@ -148,10 +148,10 @@ struct Token;
struct TokenPos;
class TokenStream;
class ParseMapPool;
struct ParseNode;
class ParseNode;
template <typename ParseHandler>
struct Parser;
class Parser;
} /* namespace frontend */
+6 -2
View File
@@ -14,6 +14,10 @@
#include "jsprototypes.h"
#include "jstypes.h"
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) || defined(DEBUG)
# define JSGC_TRACK_EXACT_ROOTS
#endif
namespace JS {
/*
@@ -296,7 +300,7 @@ struct ContextFriendFields
return reinterpret_cast<ContextFriendFields *>(cx);
}
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
@@ -344,7 +348,7 @@ struct PerThreadDataFriendFields
PerThreadDataFriendFields();
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
#ifdef JSGC_TRACK_EXACT_ROOTS
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.

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