merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-06-17 14:04:56 +02:00
Родитель 82463f11e1 9c7515313c
Коммит 6efee7d862
218 изменённых файлов: 2678 добавлений и 15055 удалений

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

@ -38,6 +38,7 @@
#include "nsTableOuterFrame.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
@ -869,15 +870,10 @@ HTMLTableAccessible::Description(nsString& aDescription)
bool
HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
{
nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));
NS_ENSURE_TRUE(tableElt, false);
nsCOMPtr<nsIHTMLCollection> elements =
mContent->AsElement()->GetElementsByTagName(aTagName);
nsCOMPtr<nsIDOMHTMLCollection> nodeList;
tableElt->GetElementsByTagName(aTagName, getter_AddRefs(nodeList));
NS_ENSURE_TRUE(nodeList, false);
nsCOMPtr<nsIDOMNode> foundItem;
nodeList->Item(0, getter_AddRefs(foundItem));
Element* foundItem = elements->Item(0);
if (!foundItem)
return false;
@ -886,11 +882,10 @@ HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
// Make sure that the item we found has contents and either has multiple
// children or the found item is not a whitespace-only text node.
nsCOMPtr<nsIContent> foundItemContent = do_QueryInterface(foundItem);
if (foundItemContent->GetChildCount() > 1)
if (foundItem->GetChildCount() > 1)
return true; // Treat multiple child nodes as non-empty
nsIContent *innerItemContent = foundItemContent->GetFirstChild();
nsIContent *innerItemContent = foundItem->GetFirstChild();
if (innerItemContent && !innerItemContent->TextIsOnlyWhitespace())
return true;
@ -901,8 +896,7 @@ HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
// caption element only. On another hand we create accessible object for
// the first entry of caption element (see
// HTMLTableAccessible::CacheChildren).
nodeList->Item(1, getter_AddRefs(foundItem));
return !!foundItem;
return !!elements->Item(1);
}
bool

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

@ -112,6 +112,11 @@ var tests = {
iconURL: "chrome://browser/skin/Info.png",
counter: 1
};
// Disable the transition
let panel = document.getElementById("social-notification-panel");
panel.setAttribute("animate", "false");
// click on panel to open and wait for visibility
let provider = Social._getProviderFromOrigin(manifest2.origin);
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);
@ -131,8 +136,8 @@ var tests = {
case "got-social-panel-visibility":
ok(true, "got the panel message " + e.data.result);
if (e.data.result == "shown") {
let panel = document.getElementById("social-notification-panel");
panel.hidePopup();
panel.removeAttribute("animate");
} else {
port.postMessage({topic: "test-ambient-notification", data: icon});
port.close();

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

@ -63,11 +63,14 @@ function checkProviderPrefsEmpty(isError) {
}
function defaultFinishChecks() {
PopupNotifications.transitionsEnabled = true;
checkProviderPrefsEmpty(true);
finish();
}
function runSocialTestWithProvider(manifest, callback, finishcallback) {
PopupNotifications.transitionsEnabled = false;
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
let manifests = Array.isArray(manifest) ? manifest : [manifest];
@ -158,6 +161,8 @@ function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
let providersAtStart = Social.providers.length;
info("runSocialTests: start test run with " + providersAtStart + " providers");
PopupNotifications.transitionsEnabled = false;
if (cbPreTest === undefined) {
cbPreTest = function(cb) {cb()};
}

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

@ -7,7 +7,6 @@
type="arrow"
hidden="true"
flip="slide"
animate="false"
position="bottomcenter topright"
noautofocus="true">
<panelmultiview id="PanelUI-multiView" mainViewId="PanelUI-mainView">

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

@ -54,6 +54,7 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
JAR_MANIFEST \
JAVA_JAR_TARGETS \
JS_MODULES_PATH \
LD_VERSION_SCRIPT \
LIBRARY_NAME \
MODULE \
MSVC_ENABLE_PGO \

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

@ -510,6 +510,10 @@ ifeq ($(OS_ARCH),Linux)
ifdef IS_COMPONENT
EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
endif
ifdef LD_VERSION_SCRIPT
EXTRA_DSO_LDOPTS += -Wl,--version-script,$(LD_VERSION_SCRIPT)
EXTRA_DEPS += $(LD_VERSION_SCRIPT)
endif
endif
#
@ -1020,6 +1024,10 @@ $(filter %.s,$(CPPSRCS:%.cc=%.s)): %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(filter %.s,$(CPPSRCS:%.cxx=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(filter %.s,$(CSRCS:%.c=%.s)): %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(CC) -S $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
@ -1035,6 +1043,7 @@ ifneq (,$(filter %.i,$(MAKECMDGOALS)))
_group_srcs = $(sort $(patsubst %.$1,%.i,$(filter %.$1,$2 $(notdir $2))))
_PREPROCESSED_CPP_FILES := $(call _group_srcs,cpp,$(CPPSRCS))
_PREPROCESSED_CC_FILES := $(call _group_srcs,cc,$(CPPSRCS))
_PREPROCESSED_CXX_FILES := $(call _group_srcs,cxx,$(CPPSRCS))
_PREPROCESSED_C_FILES := $(call _group_srcs,c,$(CSRCS))
_PREPROCESSED_CMM_FILES := $(call _group_srcs,mm,$(CMMSRCS))
@ -1044,7 +1053,7 @@ VPATH += $(addprefix $(srcdir)/,$(sort $(dir $(CPPSRCS) $(CSRCS) $(CMMSRCS))))
# Make preprocessed files PHONY so they are always executed, since they are
# manual targets and we don't necessarily write to $@.
.PHONY: $(_PREPROCESSED_CPP_FILES) $(_PREPROCESSED_CC_FILES) $(_PREPROCESSED_C_FILES) $(_PREPROCESSED_CMM_FILES)
.PHONY: $(_PREPROCESSED_CPP_FILES) $(_PREPROCESSED_CC_FILES) $(_PREPROCESSED_CXX_FILES) $(_PREPROCESSED_C_FILES) $(_PREPROCESSED_CMM_FILES)
$(_PREPROCESSED_CPP_FILES): %.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
@ -1056,6 +1065,11 @@ $(_PREPROCESSED_CC_FILES): %.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
$(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
$(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(_PREPROCESSED_CXX_FILES): %.i: %.cxx $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
$(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(_PREPROCESSED_C_FILES): %.i: %.c $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
@ -1074,7 +1088,7 @@ PP_UNIFIED ?= 1
# infinite loop if the filename doesn't exist in the unified source files.
ifndef PP_REINVOKE
MATCH_cpp = \(cpp\|cc\)
MATCH_cpp = \(cpp\|cc|cxx\)
UPPER_c = C
UPPER_cpp = CPP
UPPER_mm = CMM

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

@ -2928,7 +2928,7 @@ dnl Checks for library functions.
dnl ========================================================
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_CHECK_FUNCS(stat64 lstat64 truncate64 statvfs64 statvfs statfs64 statfs getpagesize localtime_r)
AC_CHECK_FUNCS(stat64 lstat64 truncate64 statvfs64 statvfs statfs64 statfs getpagesize localtime_r arc4random arc4random_buf)
dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
@ -3589,7 +3589,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
_USE_SYSTEM_NSS=1 )
if test -n "$_USE_SYSTEM_NSS"; then
AM_PATH_NSS(3.16, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
AM_PATH_NSS(3.16.1, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
fi
if test -n "$MOZ_NATIVE_NSS"; then
@ -8803,6 +8803,7 @@ AC_SUBST(CPU_ARCH)
AC_SUBST(INTEL_ARCHITECTURE)
AC_SUBST(HAVE_TOOLCHAIN_SUPPORT_MSSSE3)
AC_SUBST(HAVE_TOOLCHAIN_SUPPORT_MSSE4_1)
AC_SUBST(GCC_USE_GNU_LD)
AC_SUBST(MOZ_CHROME_FILE_FORMAT)

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

@ -1350,6 +1350,8 @@ private:
// Set if the element has a parser insertion mode other than "in body",
// per the HTML5 "Parse state" section.
ElementHasWeirdParserInsertionMode,
// Parser sets this flag if it has notified about the node.
ParserHasNotified,
// Guard value
BooleanFlagCount
};
@ -1490,6 +1492,8 @@ public:
bool IsScopedStyleRoot() { return GetBoolFlag(ElementIsScopedStyleRoot); }
bool HasRelevantHoverRules() const { return GetBoolFlag(NodeHasRelevantHoverRules); }
void SetHasRelevantHoverRules() { SetBoolFlag(NodeHasRelevantHoverRules); }
void SetParserHasNotified() { SetBoolFlag(ParserHasNotified); };
bool HasParserNotified() { return GetBoolFlag(ParserHasNotified); }
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
void SetInDocument() { SetBoolFlag(IsInDocument); }

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

@ -559,7 +559,7 @@ WebSocket::Constructor(const GlobalObject& aGlobal,
}
nsRefPtr<WebSocket> webSocket = new WebSocket(ownerWindow);
nsresult rv = webSocket->Init(aGlobal.GetContext(), principal,
nsresult rv = webSocket->Init(aGlobal.Context(), principal,
aUrl, protocolArray);
if (NS_FAILED(rv)) {
aRv.Throw(rv);

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

@ -52,8 +52,8 @@ ImageData::Constructor(const GlobalObject& aGlobal,
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return nullptr;
}
js::AssertSameCompartment(aGlobal.GetContext(), aGlobal.Get());
JSObject* data = Uint8ClampedArray::Create(aGlobal.GetContext(),
js::AssertSameCompartment(aGlobal.Context(), aGlobal.Get());
JSObject* data = Uint8ClampedArray::Create(aGlobal.Context(),
length.value());
if (!data) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);

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

@ -13,14 +13,16 @@
#include "nsDOMSettableTokenList.h"
#include "nsFormSubmission.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Output)
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
namespace mozilla {
namespace dom {
HTMLOutputElement::HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
HTMLOutputElement::HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLFormElement(aNodeInfo)
, mValueModeFlag(eModeDefault)
, mIsDoneAddingChildren(!aFromParser)
{
AddMutationObserver(this);
@ -93,6 +95,12 @@ HTMLOutputElement::ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
aValue, aResult);
}
void
HTMLOutputElement::DoneAddingChildren(bool aHaveNotified)
{
mIsDoneAddingChildren = true;
}
EventStates
HTMLOutputElement::IntrinsicState() const
{
@ -170,7 +178,7 @@ HTMLOutputElement::HtmlFor()
void HTMLOutputElement::DescendantsChanged()
{
if (mValueModeFlag == eModeDefault) {
if (mIsDoneAddingChildren && mValueModeFlag == eModeDefault) {
if (!nsContentUtils::GetNodeTextContent(this, true, mDefaultValue)) {
NS_RUNTIMEABORT("OOM");
}

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

@ -21,7 +21,8 @@ class HTMLOutputElement MOZ_FINAL : public nsGenericHTMLFormElement,
public:
using nsIConstraintValidation::GetValidationMessage;
HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo);
HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
FromParser aFromParser = NOT_FROM_PARSER);
virtual ~HTMLOutputElement();
// nsISupports
@ -39,6 +40,8 @@ public:
bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
virtual void DoneAddingChildren(bool aHaveNotified) MOZ_OVERRIDE;
EventStates IntrinsicState() const MOZ_OVERRIDE;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -101,6 +104,7 @@ protected:
};
ValueModeFlag mValueModeFlag;
bool mIsDoneAddingChildren;
nsString mDefaultValue;
nsRefPtr<nsDOMSettableTokenList> mTokenList;
};

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

@ -1966,6 +1966,25 @@ void MediaDecoderStateMachine::DecodeSeek()
video = mReader->FindStartTime(nextSampleStartTime);
}
if (seekTime > mediaTime &&
nextSampleStartTime < mediaTime &&
mSeekTarget.mType == SeekTarget::PrevSyncPoint) {
// We are doing a fastSeek, but we ended up *before* the previous
// playback position. This is surprising UX, so switch to an accurate
// seek and decode to the seek target. This is not conformant to the
// spec, fastSeek should always be fast, but until we get the time to
// change all Readers to seek to the keyframe after the currentTime
// in this case, we'll just decode forward. Bug 1026330.
ResetPlayback();
{
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
res = mReader->DecodeToTarget(seekTime);
if (NS_SUCCEEDED(res)) {
video = mReader->FindStartTime(nextSampleStartTime);
}
}
}
// Setup timestamp state.
if (seekTime == mEndTime) {
newCurrentTime = mAudioStartTime = seekTime;

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

@ -86,9 +86,9 @@ MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal,
if (aEventInitDict.mMessage.WasPassed()) {
const auto& a = aEventInitDict.mMessage.Value();
a.ComputeLengthAndData();
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
e->mMessage = Uint8Array::Create(aGlobal.Context(), owner, a.Length(), a.Data());
} else {
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, 0, nullptr);
e->mMessage = Uint8Array::Create(aGlobal.Context(), owner, 0, nullptr);
}
if (!e->mMessage) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);

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

@ -78,7 +78,7 @@ MediaKeyNeededEvent::Constructor(const GlobalObject& aGlobal,
!aEventInitDict.mInitData.Value().IsNull()) {
const auto& a = aEventInitDict.mInitData.Value().Value();
a.ComputeLengthAndData();
e->mInitData = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
e->mInitData = Uint8Array::Create(aGlobal.Context(), owner, a.Length(), a.Data());
if (!e->mInitData) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;

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

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
</head>
<body>
<!-- This video file has a timescale of 0 in the mdhd atom -->
<video src="0-timescale.mp4"
onerror="document.documentElement.className=undefined"
onloadedmetadata="document.documentElement.className=undefined">
</video>
</body>
</html>

Двоичные данные
content/media/test/crashtests/0-timescale.mp4 Normal file

Двоичный файл не отображается.

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

@ -1,3 +1,4 @@
skip-if(B2G) load 0-timescale.html
skip-if(B2G) load 459439-1.html # bug 888557
load 466607-1.html
load 466945-1.html

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

@ -347,6 +347,7 @@ skip-if = buildapp == 'b2g' # bug 1021676
[test_error_in_video_document.html]
[test_error_on_404.html]
[test_fastSeek.html]
[test_fastSeek-forwards.html]
[test_info_leak.html]
[test_invalid_reject.html]
[test_load.html]

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

@ -0,0 +1,74 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1022913
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1022913</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
<script type="application/javascript">
// Test that if we're doing a fastSeek() forwards that we don't end up
// seeking backwards. This can happen if the keyframe before the seek
// target is before the current playback position. We'd prefer to seek to
// the keyframe after the seek target in this case, but we don't implement
// this yet (bug 1026330).
var manager = new MediaTestManager;
var onSecondSeekComplete = function(event) {
var v = event.target;
ok(v.currentTime >= v.firstSeekTarget, v.name + " seek never go backwards. time=" + v.currentTime + " firstSeekTarget=" + v.firstSeekTarget + " secondSeekTarget=" + v.secondSeekTarget);
manager.finished(v.token);
};
var onFirstSeekComplete = function(event) {
var v = event.target;
v.removeEventListener("seeked", onFirstSeekComplete);
// Seek to 75% of the way between the start and the first keyframe
// using fastSeek. We then test that the currentTime doesn't drop back
// to the previous keyframe, currentTime should go forwards.
v.addEventListener("seeked", onSecondSeekComplete);
v.secondSeekTarget = v.keyframes[1] * 0.75;
v.fastSeek(v.secondSeekTarget);
}
var onLoadedMetadata = function(event) {
// Seek to the mid-point between the start and the first keyframe.
var v = event.target;
v.addEventListener("seeked", onFirstSeekComplete);
v.firstSeekTarget = v.keyframes[1] * 0.5;
v.currentTime = v.firstSeekTarget;
}
function startTest(test, token) {
manager.started(token);
v = document.createElement("video");
v.src = test.name;
v.name = test.name;
v.preload = "metadata";
v.token = token;
v.target = 0;
v.keyframes = test.keyframes;
v.keyframeIndex = 0;
ok(v.keyframes.length >= 2, v.name + " - video should have at least two sync points");
v.addEventListener("loadedmetadata", onLoadedMetadata);
document.body.appendChild(v);
}
manager.runTests(gFastSeekTests, startTest);
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1022913">Mozilla Bug 1022913</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -5,6 +5,8 @@
LIB_IS_C_ONLY = 1
include $(topsrcdir)/config/config.mk
ifeq ($(OS_ARCH),WINNT)
DEFFILE = $(CURDIR)/sqlite-processed.def
@ -20,10 +22,25 @@ sqlite-version.h: sqlite-version.py sqlite3.h
# We have to preprocess our def file because we need different symbols in debug
# builds exposed that are not built in non-debug builds.
$(DEFFILE): sqlite.def
@$(call py_action,preprocessor,$(DEFINES) \
@$(call py_action,preprocessor,$(DEFINES) $(XULPPFLAGS) \
$(srcdir)/sqlite.def -o $(DEFFILE))
export:: sqlite-version.h
else
ifndef MOZ_FOLD_LIBS
ifdef GCC_USE_GNU_LD
GARBAGE += \
$(LD_VERSION_SCRIPT) \
$(NULL)
# Convert to the format we need for ld.
$(LD_VERSION_SCRIPT): $(srcdir)/sqlite.def
@$(call py_action,convert_def_file, \
$(DEFINES) $(ACDEFINES) $(XULPPFLAGS) -o $@ $^)
endif
endif
endif
ifeq (Darwin,$(OS_TARGET))

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

@ -74,6 +74,11 @@ if CONFIG['OS_ARCH'] == 'WINNT':
RCFILE = 'sqlite.rc'
RESFILE = 'sqlite.res'
if CONFIG['OS_ARCH'] == 'Linux' and \
not CONFIG['MOZ_FOLD_LIBS'] and \
CONFIG['GCC_USE_GNU_LD']:
LD_VERSION_SCRIPT = 'sqlite-processed.def'
# Suppress warnings in third-party code.
if CONFIG['GNU_CC']:
CFLAGS += [

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

@ -126,6 +126,9 @@ EXPORTS
sqlite3_step
sqlite3_stmt_readonly
sqlite3_stmt_status
#ifdef XP_UNIX
sqlite3_temp_directory
#endif
sqlite3_thread_cleanup
sqlite3_total_changes
sqlite3_trace
@ -151,7 +154,7 @@ EXPORTS
sqlite3_vfs_unregister
sqlite3_vfs_register
sqlite3_vmprintf
#ifdef SQLITE_DEBUG
#ifdef DEBUG
sqlite3_mutex_held
sqlite3_mutex_notheld
#endif

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

@ -25,7 +25,6 @@ public:
static already_AddRefed<Activity>
Constructor(const GlobalObject& aOwner,
JSContext* aCx,
const ActivityOptions& aOptions,
ErrorResult& aRv)
{
@ -36,7 +35,7 @@ public:
}
nsRefPtr<Activity> activity = new Activity(window);
aRv = activity->Initialize(window, aCx, aOptions);
aRv = activity->Initialize(window, aOwner.Context(), aOptions);
return activity.forget();
}

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

@ -910,7 +910,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
ErrorResult rv;
nsRefPtr<nsPerformance> performance = win->GetPerformance(rv);
if (rv.Failed()) {
if (rv.Failed() || !performance) {
return;
}

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

@ -70,7 +70,7 @@ public:
// The context that this returns is not guaranteed to be in the compartment of
// the object returned from Get(), in fact it's generally in the caller's
// compartment.
JSContext* GetContext() const
JSContext* Context() const
{
return mCx;
}

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

@ -1835,6 +1835,7 @@ GlobalObject::GlobalObject(JSContext* aCx, JSObject* aObject)
mCx(aCx),
mGlobalObject(nullptr)
{
MOZ_ASSERT(mCx);
JS::Rooted<JSObject*> obj(aCx, aObject);
if (js::IsWrapper(obj)) {
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
@ -2437,7 +2438,7 @@ ConvertExceptionToPromise(JSContext* cx,
JS_ClearPendingException(cx);
ErrorResult rv;
nsRefPtr<Promise> promise = Promise::Reject(global, cx, exn, rv);
nsRefPtr<Promise> promise = Promise::Reject(global, exn, rv);
if (rv.Failed()) {
// We just give up. Make sure to not leak memory on the
// ErrorResult, but then just put the original exception back.

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

@ -5726,8 +5726,9 @@ def isResultAlreadyAddRefed(extendedAttributes):
return 'resultNotAddRefed' not in extendedAttributes
def needCx(returnType, arguments, extendedAttributes, considerTypes):
return (considerTypes and
def needCx(returnType, arguments, extendedAttributes, considerTypes,
static=False):
return (not static and considerTypes and
(typeNeedsCx(returnType, True) or
any(typeNeedsCx(a.type) for a in arguments)) or
'implicitJSContext' in extendedAttributes)
@ -6057,10 +6058,11 @@ class CGPerSignatureCall(CGThing):
# For JS-implemented interfaces we do not want to base the
# needsCx decision on the types involved, just on our extended
# attributes.
# attributes. Also, JSContext is not needed for the static case
# since GlobalObject already contains the context.
needsCx = needCx(returnType, arguments, self.extendedAttributes,
not descriptor.interface.isJSImplemented())
if needsCx and not (static and descriptor.workers):
not descriptor.interface.isJSImplemented(), static)
if needsCx:
argsPre.append("cx")
needsUnwrap = False
@ -11708,7 +11710,7 @@ class CGNativeMember(ClassMethod):
args.insert(0, Argument("JS::Value", "aThisVal"))
# And jscontext bits.
if needCx(returnType, argList, self.extendedAttrs,
self.passJSBitsAsNeeded):
self.passJSBitsAsNeeded, self.member.isStatic()):
args.insert(0, Argument("JSContext*", "cx"))
if needScopeObject(returnType, argList, self.extendedAttrs,
self.descriptorProvider.wrapperCache,
@ -13647,7 +13649,7 @@ class CGEventMethod(CGNativeMember):
self.args.insert(0, Argument("mozilla::dom::EventTarget*", "aOwner"))
constructorForNativeCaller = CGNativeMember.declare(self, cgClass)
self.args = list(self.originalArgs)
if needCx(None, self.arguments(), [], True):
if needCx(None, self.arguments(), [], considerTypes=True, static=True):
self.args.insert(0, Argument("JSContext*", "aCx"))
self.args.insert(0, Argument("const GlobalObject&", "aGlobal"))
self.args.append(Argument('ErrorResult&', 'aRv'))
@ -13698,7 +13700,7 @@ class CGEventMethod(CGNativeMember):
""",
arg0=self.args[0].name,
arg1=self.args[1].name)
if needCx(None, self.arguments(), [], True):
if needCx(None, self.arguments(), [], considerTypes=True, static=True):
self.args.insert(0, Argument("JSContext*", "aCx"))
self.args.insert(0, Argument("const GlobalObject&", "aGlobal"))
self.args.append(Argument('ErrorResult&', 'aRv'))

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

@ -151,7 +151,6 @@ public:
static
already_AddRefed<TestInterface> Test2(const GlobalObject&,
JSContext*,
const DictForConstructor&,
JS::Handle<JS::Value>,
JS::Handle<JSObject*>,
@ -682,8 +681,7 @@ public:
// Static methods and attributes
static void StaticMethod(const GlobalObject&, bool);
static void StaticMethodWithContext(const GlobalObject&, JSContext*,
JS::Value);
static void StaticMethodWithContext(const GlobalObject&, JS::Value);
static bool StaticAttribute(const GlobalObject&);
static void SetStaticAttribute(const GlobalObject&, bool);

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

@ -196,7 +196,3 @@ disabled = bug 774100
# Disabled due to focus issues (no bug that I'm aware of)
[test_browserElement_oop_KeyEvents.html]
disabled =
# Disable due to certificate issue (no bug that I'm aware of)
[test_browserElement_inproc_ErrorSecurity.html]
skip-if = buildapp=='b2g'
disabled =

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

@ -523,6 +523,7 @@ void
Event::SetEventType(const nsAString& aEventTypeArg)
{
if (mIsMainThreadEvent) {
mEvent->typeString.Truncate();
mEvent->userType =
nsContentUtils::GetEventIdAndAtom(aEventTypeArg, mEvent->eventStructType,
&(mEvent->message));

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

@ -114,7 +114,7 @@ MessageEvent::GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const
/* static */ already_AddRefed<MessageEvent>
MessageEvent::Constructor(const GlobalObject& aGlobal,
JSContext* aCx, const nsAString& aType,
const nsAString& aType,
const MessageEventInit& aParam,
ErrorResult& aRv)
{

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

@ -70,7 +70,7 @@ public:
}
static already_AddRefed<MessageEvent>
Constructor(const GlobalObject& aGlobal, JSContext* aCx,
Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const MessageEventInit& aEventInit,
ErrorResult& aRv);

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

@ -157,3 +157,4 @@ skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
skip-if = buildapp == 'b2g' || e10s
[test_bug985988.html]
[test_dom_storage_event.html]
[test_bug998809.html]

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

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=998809
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 998809</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 998809 **/
var event1 = document.createEvent("Event");
event1.initEvent("a", false, false);
event1.initEvent("b", false, false);
is(event1.type, "b");
var event2 = document.createEvent("Event");
event2.initEvent("a", false, false);
is(event2.type, "a");
event2.initEvent("b", false, false);
is(event2.type, "b");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=998809">Mozilla Bug 998809</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -214,7 +214,7 @@ IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::Only(const GlobalObject& aGlobal, JSContext* aCx,
IDBKeyRange::Only(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
@ -222,7 +222,7 @@ IDBKeyRange::Only(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), false, false, true);
aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Lower());
aRv = GetKeyFromJSVal(aGlobal.Context(), aValue, keyRange->Lower());
if (aRv.Failed()) {
return nullptr;
}
@ -232,7 +232,7 @@ IDBKeyRange::Only(const GlobalObject& aGlobal, JSContext* aCx,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::LowerBound(const GlobalObject& aGlobal, JSContext* aCx,
IDBKeyRange::LowerBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen,
ErrorResult& aRv)
{
@ -241,7 +241,7 @@ IDBKeyRange::LowerBound(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), aOpen, true, false);
aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Lower());
aRv = GetKeyFromJSVal(aGlobal.Context(), aValue, keyRange->Lower());
if (aRv.Failed()) {
return nullptr;
}
@ -251,7 +251,7 @@ IDBKeyRange::LowerBound(const GlobalObject& aGlobal, JSContext* aCx,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::UpperBound(const GlobalObject& aGlobal, JSContext* aCx,
IDBKeyRange::UpperBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen,
ErrorResult& aRv)
{
@ -260,7 +260,7 @@ IDBKeyRange::UpperBound(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), true, aOpen, false);
aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Upper());
aRv = GetKeyFromJSVal(aGlobal.Context(), aValue, keyRange->Upper());
if (aRv.Failed()) {
return nullptr;
}
@ -270,7 +270,7 @@ IDBKeyRange::UpperBound(const GlobalObject& aGlobal, JSContext* aCx,
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::Bound(const GlobalObject& aGlobal, JSContext* aCx,
IDBKeyRange::Bound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv)
{
@ -279,12 +279,12 @@ IDBKeyRange::Bound(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<IDBKeyRange> keyRange =
new IDBKeyRange(aGlobal.GetAsSupports(), aLowerOpen, aUpperOpen, false);
aRv = GetKeyFromJSVal(aCx, aLower, keyRange->Lower());
aRv = GetKeyFromJSVal(aGlobal.Context(), aLower, keyRange->Lower());
if (aRv.Failed()) {
return nullptr;
}
aRv = GetKeyFromJSVal(aCx, aUpper, keyRange->Upper());
aRv = GetKeyFromJSVal(aGlobal.Context(), aUpper, keyRange->Upper());
if (aRv.Failed()) {
return nullptr;
}

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

@ -177,19 +177,19 @@ public:
}
static already_AddRefed<IDBKeyRange>
Only(const GlobalObject& aGlobal, JSContext* aCx,
Only(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
LowerBound(const GlobalObject& aGlobal, JSContext* aCx,
LowerBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
UpperBound(const GlobalObject& aGlobal, JSContext* aCx,
UpperBound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
static already_AddRefed<IDBKeyRange>
Bound(const GlobalObject& aGlobal, JSContext* aCx,
Bound(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv);

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

@ -79,7 +79,7 @@ MozNDEFRecord::Constructor(const GlobalObject& aGlobal,
return nullptr;
}
nsRefPtr<MozNDEFRecord> ndefrecord = new MozNDEFRecord(aGlobal.GetContext(),
nsRefPtr<MozNDEFRecord> ndefrecord = new MozNDEFRecord(aGlobal.Context(),
win, aTnf, aType, aId,
aPayload);
if (!ndefrecord) {

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

@ -593,7 +593,7 @@ Promise::CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTas
Promise::Constructor(const GlobalObject& aGlobal,
PromiseInit& aInit, ErrorResult& aRv)
{
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
nsCOMPtr<nsIGlobalObject> global;
global = do_QueryInterface(aGlobal.GetAsSupports());
@ -641,12 +641,12 @@ Promise::Constructor(const GlobalObject& aGlobal,
}
/* static */ already_AddRefed<Promise>
Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
Promise::Resolve(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
{
// If a Promise was passed, just return it.
if (aValue.isObject()) {
JS::Rooted<JSObject*> valueObj(aCx, &aValue.toObject());
JS::Rooted<JSObject*> valueObj(aGlobal.Context(), &aValue.toObject());
Promise* nextPromise;
nsresult rv = UNWRAP_OBJECT(Promise, valueObj, nextPromise);
@ -663,7 +663,7 @@ Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
return nullptr;
}
return Resolve(global, aCx, aValue, aRv);
return Resolve(global, aGlobal.Context(), aValue, aRv);
}
/* static */ already_AddRefed<Promise>
@ -677,7 +677,7 @@ Promise::Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
}
/* static */ already_AddRefed<Promise>
Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
Promise::Reject(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global =
@ -687,7 +687,7 @@ Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
return nullptr;
}
return Reject(global, aCx, aValue, aRv);
return Reject(global, aGlobal.Context(), aValue, aRv);
}
/* static */ already_AddRefed<Promise>
@ -744,9 +744,9 @@ public:
: mPromise(aPromise), mCountdown(aCountdown)
{
MOZ_ASSERT(aCountdown != 0);
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
// The only time aGlobal.GetContext() and aGlobal.Get() are not
// The only time aGlobal.Context() and aGlobal.Get() are not
// same-compartment is when we're called via Xrays, and in that situation we
// in fact want to create the array in the callee compartment
@ -864,7 +864,7 @@ NS_INTERFACE_MAP_END_INHERITING(PromiseNativeHandler)
NS_IMPL_CYCLE_COLLECTION(AllResolveHandler, mCountdownHolder)
/* static */ already_AddRefed<Promise>
Promise::All(const GlobalObject& aGlobal, JSContext* aCx,
Promise::All(const GlobalObject& aGlobal,
const Sequence<JS::Value>& aIterable, ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global =
@ -874,21 +874,23 @@ Promise::All(const GlobalObject& aGlobal, JSContext* aCx,
return nullptr;
}
JSContext* cx = aGlobal.Context();
if (aIterable.Length() == 0) {
JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0));
JS::Rooted<JSObject*> empty(cx, JS_NewArrayObject(cx, 0));
if (!empty) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*empty));
return Promise::Resolve(aGlobal, aCx, value, aRv);
JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*empty));
return Promise::Resolve(aGlobal, value, aRv);
}
nsRefPtr<Promise> promise = new Promise(global);
nsRefPtr<CountdownHolder> holder =
new CountdownHolder(aGlobal, promise, aIterable.Length());
JS::Rooted<JSObject*> obj(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Rooted<JSObject*> obj(cx, JS::CurrentGlobalOrNull(cx));
if (!obj) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
@ -897,8 +899,8 @@ Promise::All(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise, obj);
for (uint32_t i = 0; i < aIterable.Length(); ++i) {
JS::Rooted<JS::Value> value(aCx, aIterable.ElementAt(i));
nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, value, aRv);
JS::Rooted<JS::Value> value(cx, aIterable.ElementAt(i));
nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, value, aRv);
MOZ_ASSERT(!aRv.Failed());
@ -916,7 +918,7 @@ Promise::All(const GlobalObject& aGlobal, JSContext* aCx,
}
/* static */ already_AddRefed<Promise>
Promise::Race(const GlobalObject& aGlobal, JSContext* aCx,
Promise::Race(const GlobalObject& aGlobal,
const Sequence<JS::Value>& aIterable, ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global =
@ -926,7 +928,9 @@ Promise::Race(const GlobalObject& aGlobal, JSContext* aCx,
return nullptr;
}
JS::Rooted<JSObject*> obj(aCx, JS::CurrentGlobalOrNull(aCx));
JSContext* cx = aGlobal.Context();
JS::Rooted<JSObject*> obj(cx, JS::CurrentGlobalOrNull(cx));
if (!obj) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
@ -940,8 +944,8 @@ Promise::Race(const GlobalObject& aGlobal, JSContext* aCx,
nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise, obj);
for (uint32_t i = 0; i < aIterable.Length(); ++i) {
JS::Rooted<JS::Value> value(aCx, aIterable.ElementAt(i));
nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, value, aRv);
JS::Rooted<JS::Value> value(cx, aIterable.ElementAt(i));
nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, value, aRv);
// According to spec, Resolve can throw, but our implementation never does.
// Well it does when window isn't passed on the main thread, but that is an
// implementation detail which should never be reached since we are checking

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

@ -121,7 +121,7 @@ public:
ErrorResult& aRv);
static already_AddRefed<Promise>
Resolve(const GlobalObject& aGlobal, JSContext* aCx,
Resolve(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
static already_AddRefed<Promise>
@ -129,7 +129,7 @@ public:
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
static already_AddRefed<Promise>
Reject(const GlobalObject& aGlobal, JSContext* aCx,
Reject(const GlobalObject& aGlobal,
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
static already_AddRefed<Promise>
@ -144,11 +144,11 @@ public:
Catch(JSContext* aCx, AnyCallback* aRejectCallback);
static already_AddRefed<Promise>
All(const GlobalObject& aGlobal, JSContext* aCx,
All(const GlobalObject& aGlobal,
const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
static already_AddRefed<Promise>
Race(const GlobalObject& aGlobal, JSContext* aCx,
Race(const GlobalObject& aGlobal,
const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
void AppendNativeHandler(PromiseNativeHandler* aRunnable);

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

@ -1502,15 +1502,11 @@ this.PushService = {
},
/**
* Get mobile network information to decide if the client is capable of being
* woken up by UDP (which currently just means having an mcc and mnc along
* with an IP).
* Returns information about MCC-MNC and the IP of the current connection.
*/
_getNetworkState: function(callback) {
if (typeof callback !== 'function') {
throw new Error("No callback method. Aborting push agent !");
}
debug("getNetworkState()");
_getNetworkInformation: function() {
debug("getNetworkInformation()");
try {
if (!prefs.get("udp.wakeupEnabled")) {
debug("UDP support disabled, we do not send any carrier info");
@ -1534,16 +1530,11 @@ this.PushService = {
let prefixLengths = {};
nm.active.getAddresses(ips, prefixLengths);
this._getMobileNetworkId(function(netid) {
debug("Recovered netID = " + netid);
callback({
mcc: iccInfo.mcc,
mnc: iccInfo.mnc,
ip: ips.value[0],
netid: netid
});
});
return;
return {
mcc: iccInfo.mcc,
mnc: iccInfo.mnc,
ip: ips.value[0]
}
}
}
} catch (e) {
@ -1551,11 +1542,40 @@ this.PushService = {
}
debug("Running on wifi");
callback({
return {
mcc: 0,
mnc: 0,
ip: undefined
});
};
},
/**
* Get mobile network information to decide if the client is capable of being
* woken up by UDP (which currently just means having an mcc and mnc along
* with an IP, and optionally a netid).
*/
_getNetworkState: function(callback) {
debug("getNetworkState()");
if (typeof callback !== 'function') {
throw new Error("No callback method. Aborting push agent !");
}
var networkInfo = this._getNetworkInformation();
if (networkInfo.ip) {
this._getMobileNetworkId(function(netid) {
debug("Recovered netID = " + netid);
callback({
mcc: networkInfo.mcc,
mnc: networkInfo.mnc,
ip: networkInfo.ip,
netid: netid
});
});
} else {
callback(networkInfo);
}
},
// utility function used to add/remove observers in init() and shutdown()

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

@ -46,7 +46,7 @@ public:
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aPromise);
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
JSAutoCompartment ac(cx, mGlobal);
mNotifications = JS_NewArrayObject(cx, 0);
HoldData();

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

@ -3,6 +3,10 @@
* 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/. */
// XXX: This must be done prior to including cert.h (directly or indirectly).
// CERT_AddTempCertToPerm is exposed as __CERT_AddTempCertToPerm.
#define CERT_AddTempCertToPerm __CERT_AddTempCertToPerm
#include "WifiCertService.h"
#include "mozilla/ClearOnShutdown.h"

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

@ -2123,7 +2123,7 @@ RuntimeService::CreateSharedWorkerInternal(const GlobalObject& aGlobal,
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(window);
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
WorkerPrivate::LoadInfo loadInfo;
nsresult rv = WorkerPrivate::GetLoadInfo(cx, window, nullptr, aScriptURL,

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

@ -475,7 +475,7 @@ URL*
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
URL& aBase, ErrorResult& aRv)
{
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
nsRefPtr<ConstructorRunnable> runnable =
@ -499,7 +499,7 @@ URL*
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
const nsAString& aBase, ErrorResult& aRv)
{
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
nsRefPtr<ConstructorRunnable> runnable =
@ -844,7 +844,7 @@ URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject* aBlob,
const mozilla::dom::objectURLOptions& aOptions,
nsString& aResult, mozilla::ErrorResult& aRv)
{
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
nsCOMPtr<nsIDOMBlob> blob = file::GetDOMBlobFromJSObject(aBlob);
@ -878,7 +878,7 @@ URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject& aBlob,
void
URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl)
{
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
nsRefPtr<RevokeURLRunnable> runnable =

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

@ -3629,7 +3629,7 @@ WorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsACString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv)
{
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
return Constructor(cx, aScriptURL, aIsChromeWorker, aWorkerType,
aSharedWorkerName, aLoadInfo, aRv);
}
@ -5771,7 +5771,7 @@ WorkerPrivate::ConnectMessagePort(JSContext* aCx, uint64_t aMessagePortSerial)
ErrorResult rv;
nsRefPtr<MessageEvent> event =
MessageEvent::Constructor(globalObject, aCx,
MessageEvent::Constructor(globalObject,
NS_LITERAL_STRING("connect"), init, rv);
event->SetTrusted(true);

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

@ -1627,7 +1627,7 @@ XMLHttpRequest::Constructor(const GlobalObject& aGlobal,
const MozXMLHttpRequestParameters& aParams,
ErrorResult& aRv)
{
JSContext* cx = aGlobal.GetContext();
JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
MOZ_ASSERT(workerPrivate);

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

@ -88,7 +88,7 @@ public:
{
// Pretend like someone passed null, so we can pick up the default values
MozXMLHttpRequestParameters params;
if (!params.Init(aGlobal.GetContext(), JS::NullHandleValue)) {
if (!params.Init(aGlobal.Context(), JS::NullHandleValue)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}

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

@ -60,6 +60,9 @@ In this order:
angle-d3dcc47.patch:
Tell ANGLE about d3dcompiler_47.dll from WinSDK 8.1.
angle-fix-issue-651.patch:
Fixes crash in TSymbolTableLevel::~TSymbolTableLevel with GCC 4.9
In addition to these patches, the Makefile.in and moz.build build files are ours,
they're not present in upsteam ANGLE. Therefore, changes made to the build files
should not be stored in the local .patch files.

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

@ -0,0 +1,27 @@
Fix for https://code.google.com/p/angleproject/issues/detail?id=651
See https://bugzilla.mozilla.org/show_bug.cgi?id=1025576 for details.
diff --git a/gfx/angle/src/compiler/SymbolTable.cpp b/gfx/angle/src/compiler/SymbolTable.cpp
--- a/gfx/angle/src/compiler/SymbolTable.cpp
+++ b/gfx/angle/src/compiler/SymbolTable.cpp
@@ -166,17 +166,18 @@ TFunction::~TFunction()
}
//
// Symbol table levels are a map of pointers to symbols that have to be deleted.
//
TSymbolTableLevel::~TSymbolTableLevel()
{
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
- delete (*it).second;
+ if ((*it).first == (*it).second->getMangledName())
+ delete (*it).second;
}
//
// Change all function entries in the table with the non-mangled name
// to be related to the provided built-in operation. This is a low
// performance operation, and only intended for symbol tables that
// live across a large number of compiles.
//

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

@ -171,7 +171,8 @@ TFunction::~TFunction()
TSymbolTableLevel::~TSymbolTableLevel()
{
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
delete (*it).second;
if ((*it).first == (*it).second->getMangledName())
delete (*it).second;
}
//

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

@ -9,6 +9,7 @@
#include "gfxPlatform.h"
#include "gfxUtils.h"
#include "gfx2DGlue.h"
#include "gfxImageSurface.h"
#include "ScopedGLHelpers.h"
#include "GLUploadHelpers.h"

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

@ -220,6 +220,10 @@ GrallocImage::GetAsSourceSurface()
RefPtr<gfx::DataSourceSurface> surface
= gfx::Factory::CreateDataSourceSurface(GetSize(), gfx::SurfaceFormat::R5G6B5);
if (!surface) {
NS_WARNING("Failed to create SourceSurface.");
return nullptr;
}
uint32_t width = GetSize().width;
uint32_t height = GetSize().height;

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

@ -575,6 +575,10 @@ PlanarYCbCrImage::GetAsSourceSurface()
}
RefPtr<gfx::DataSourceSurface> surface = gfx::Factory::CreateDataSourceSurface(size, format);
if (!surface) {
NS_WARNING("Failed to create SourceSurface.");
return nullptr;
}
gfx::ConvertYCbCrToRGB(mData, format, size, surface->GetData(), surface->Stride());
@ -590,6 +594,10 @@ RemoteBitmapImage::GetAsSourceSurface()
? gfx::SurfaceFormat::B8G8R8X8
: gfx::SurfaceFormat::B8G8R8A8;
RefPtr<gfx::DataSourceSurface> newSurf = gfx::Factory::CreateDataSourceSurface(mSize, fmt);
if (!newSurf) {
NS_WARNING("Failed to create SourceSurface.");
return nullptr;
}
for (int y = 0; y < mSize.height; y++) {
memcpy(newSurf->GetData() + newSurf->Stride() * y,

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

@ -17,6 +17,7 @@
#include "gfxPlatform.h" // for gfxPlatform
#include "gfxUtils.h" // for gfxUtils, etc
#include "gfx2DGlue.h"
#include "gfxImageSurface.h"
#include "mozilla/DebugOnly.h" // for DebugOnly
#include "mozilla/Telemetry.h" // for Accumulate
#include "mozilla/gfx/2D.h" // for DrawTarget

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

@ -276,6 +276,10 @@ YCbCrImageDataDeserializer::ToDataSourceSurface()
{
RefPtr<DataSourceSurface> result =
Factory::CreateDataSourceSurface(GetYSize(), gfx::SurfaceFormat::B8G8R8X8);
if (!result) {
NS_WARNING("Failed to create SourceSurface.");
return nullptr;
}
DataSourceSurface::MappedSurface map;
result->Map(DataSourceSurface::MapType::WRITE, &map);

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

@ -8,11 +8,9 @@
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "inIDOMUtils.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventTarget.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "mozilla/dom/Element.h"
#define AEM_LOG(...)
// #define AEM_LOG(...) printf_stderr("AEM: " __VA_ARGS__)
@ -40,7 +38,7 @@ ActiveElementManager::ActiveElementManager()
ActiveElementManager::~ActiveElementManager() {}
void
ActiveElementManager::SetTargetElement(nsIDOMEventTarget* aTarget)
ActiveElementManager::SetTargetElement(dom::EventTarget* aTarget)
{
if (mTarget) {
// Multiple fingers on screen (since HandleTouchEnd clears mTarget).
@ -126,11 +124,12 @@ ActiveElementManager::HandleTouchEnd(bool aWasClick)
}
void
ActiveElementManager::SetActive(nsIDOMElement* aTarget)
ActiveElementManager::SetActive(dom::Element* aTarget)
{
AEM_LOG("Setting active %p\n", aTarget);
if (mDomUtils) {
mDomUtils->SetContentState(aTarget, NS_EVENT_STATE_ACTIVE.GetInternalValue());
nsCOMPtr<nsIDOMElement> target = do_QueryInterface(aTarget);
mDomUtils->SetContentState(target, NS_EVENT_STATE_ACTIVE.GetInternalValue());
}
}
@ -141,15 +140,10 @@ ActiveElementManager::ResetActive()
// Clear the :active flag from mTarget by setting it on the document root.
if (mTarget) {
nsCOMPtr<nsIDOMDocument> doc;
mTarget->GetOwnerDocument(getter_AddRefs(doc));
if (doc) {
nsCOMPtr<nsIDOMElement> root;
doc->GetDocumentElement(getter_AddRefs(root));
if (root) {
AEM_LOG("Found root %p, making active\n", root.get());
SetActive(root);
}
dom::Element* root = mTarget->OwnerDoc()->GetDocumentElement();
if (root) {
AEM_LOG("Found root %p, making active\n", root.get());
SetActive(root);
}
}
}
@ -162,7 +156,7 @@ ActiveElementManager::ResetTouchBlockState()
}
void
ActiveElementManager::SetActiveTask(nsIDOMElement* aTarget)
ActiveElementManager::SetActiveTask(dom::Element* aTarget)
{
AEM_LOG("mSetActiveTask %p running\n", mSetActiveTask);

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

@ -10,11 +10,14 @@
#include "nsISupportsImpl.h"
class inIDOMUtils;
class nsIDOMEventTarget;
class nsIDOMElement;
class CancelableTask;
namespace mozilla {
namespace dom {
class Element;
class EventTarget;
}
namespace layers {
/**
@ -35,7 +38,7 @@ public:
* HandleTouchStart().
* |aTarget| may be nullptr.
*/
void SetTargetElement(nsIDOMEventTarget* aTarget);
void SetTargetElement(dom::EventTarget* aTarget);
/**
* Handle a touch-start event.
* @param aCanBePan whether the touch can be a pan
@ -55,7 +58,7 @@ private:
/**
* The target of the first touch point in the current touch block.
*/
nsCOMPtr<nsIDOMElement> mTarget;
nsCOMPtr<dom::Element> mTarget;
/**
* Whether the current touch block can be a pan. Set in HandleTouchStart().
*/
@ -73,10 +76,10 @@ private:
// Helpers
void TriggerElementActivation();
void SetActive(nsIDOMElement* aTarget);
void SetActive(dom::Element* aTarget);
void ResetActive();
void ResetTouchBlockState();
void SetActiveTask(nsIDOMElement* aTarget);
void SetActiveTask(dom::Element* aTarget);
void CancelTask();
};

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

@ -85,6 +85,9 @@ TextRenderer::RenderText(const string& aText, const IntPoint& aOrigin,
// Create a surface to draw our glyphs to.
RefPtr<DataSourceSurface> textSurf =
Factory::CreateDataSourceSurface(IntSize(maxWidth, numLines * sCellHeight), sTextureFormat);
if (!textSurf) {
return;
}
DataSourceSurface::MappedSurface map;
textSurf->Map(DataSourceSurface::MapType::READ_WRITE, &map);
@ -144,6 +147,10 @@ TextRenderer::EnsureInitialized()
}
mGlyphBitmaps = Factory::CreateDataSourceSurface(IntSize(sTextureWidth, sTextureHeight), sTextureFormat);
if (!mGlyphBitmaps) {
NS_WARNING("Failed to create SourceSurface.");
return;
}
mGlyphBitmaps->Map(DataSourceSurface::MapType::READ_WRITE, &mMap);

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

@ -684,7 +684,9 @@ CompositorParent::ForceComposeToTarget(DrawTarget* aTarget, const nsIntRect* aRe
bool
CompositorParent::CanComposite()
{
return !(mPaused || !mLayerManager || !mLayerManager->GetRoot());
return mLayerManager &&
mLayerManager->GetRoot() &&
!mPaused;
}
// Go down the composite layer tree, setting properties to match their

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

@ -1455,6 +1455,10 @@ CompositorOGL::CopyToTarget(DrawTarget* aTarget, const nsIntPoint& aTopLeft, con
RefPtr<DataSourceSurface> source =
Factory::CreateDataSourceSurface(rect.Size(), gfx::SurfaceFormat::B8G8R8A8);
if (!source) {
NS_WARNING("Failed to create SourceSurface.");
return;
}
ReadPixelsIntoDataSurface(mGLContext, source);

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

@ -29,6 +29,10 @@ typedef uint32_t nscolor;
#define NS_RGBA(_r,_g,_b,_a) \
((nscolor) (((_a) << 24) | ((_b)<<16) | ((_g)<<8) | (_r)))
// Make a color out of a gfxRGBA.
#define NS_RGBA_FROM_GFXRGBA(gfxColor) \
((nscolor) (gfxColor.Packed()))
// Extract color components from nscolor
#define NS_GET_R(_rgba) ((uint8_t) ((_rgba) & 0xff))
#define NS_GET_G(_rgba) ((uint8_t) (((_rgba) >> 8) & 0xff))

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

@ -7,12 +7,10 @@
#include "nsISupports.idl"
%{C++
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "gfxMatrix.h"
#include "gfxRect.h"
#include "GraphicsFilter.h"
#include "gfxASurface.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "nsRect.h"
@ -41,9 +39,6 @@ class Orientation;
%}
[ptr] native gfxImageSurface(gfxImageSurface);
[ptr] native gfxASurface(gfxASurface);
native gfxImageFormat(gfxASurface::gfxImageFormat);
[ptr] native gfxContext(gfxContext);
[ref] native gfxMatrix(gfxMatrix);
[ref] native gfxRect(gfxRect);
@ -176,8 +171,7 @@ interface imgIContainer : nsISupports
/**
* Get a surface for the given frame. This may be a platform-native,
* optimized surface, so you cannot inspect its pixel data. If you
* need that, use gfxASurface::GetAsReadableARGB32ImageSurface or
* gfxASurface::CopyToARGB32ImageSurface.
* need that, use SourceSurface::GetDataSurface.
*
* @param aWhichFrame Frame specifier of the FRAME_* variety.
* @param aFlags Flags of the FLAG_* variety

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

@ -211,13 +211,16 @@ public:
bool success = false;
if (!dstLocked) {
// We need to hold a lock onto the RasterImage object itself so that
// it (and its associated imgFrames) aren't marked as discardable.
bool imgLocked = NS_SUCCEEDED(image->LockImage());
bool srcLocked = NS_SUCCEEDED(srcFrame->LockImageData());
srcSurface = srcFrame->GetSurface();
dstLocked = NS_SUCCEEDED(dstFrame->LockImageData());
dstSurface = dstFrame->GetSurface();
success = srcLocked && dstLocked && srcSurface && dstSurface;
success = imgLocked && srcLocked && dstLocked && srcSurface && dstSurface;
if (success) {
srcData = srcFrame->GetImageData();
@ -253,6 +256,7 @@ public:
if (DiscardingEnabled())
dstFrame->SetDiscardable();
success = NS_SUCCEEDED(dstFrame->UnlockImageData());
success = success && NS_SUCCEEDED(image->UnlockImage());
dstLocked = false;
srcData = nullptr;
@ -346,9 +350,9 @@ public:
ScaleRequest* request = mScaleRequest;
if (!request->stopped) {
request->done = mozilla::gfx::Scale(request->srcData, request->srcRect.width, request->srcRect.height, request->srcStride,
request->dstData, request->dstSize.width, request->dstSize.height, request->dstStride,
request->srcFormat);
request->done = gfx::Scale(request->srcData, request->srcRect.width, request->srcRect.height, request->srcStride,
request->dstData, request->dstSize.width, request->dstSize.height, request->dstStride,
request->srcFormat);
} else {
request->done = false;
}
@ -535,7 +539,7 @@ RasterImage::Init(const char* aMimeType,
//******************************************************************************
// [notxpcom] void requestRefresh ([const] in TimeStamp aTime);
NS_IMETHODIMP_(void)
RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
RasterImage::RequestRefresh(const TimeStamp& aTime)
{
if (HadRecentRefresh(aTime)) {
return;
@ -1568,7 +1572,7 @@ RasterImage::ResetAnimation()
//******************************************************************************
// [notxpcom] void setAnimationStartTime ([const] in TimeStamp aTime);
NS_IMETHODIMP_(void)
RasterImage::SetAnimationStartTime(const mozilla::TimeStamp& aTime)
RasterImage::SetAnimationStartTime(const TimeStamp& aTime)
{
if (mError || mAnimationMode == kDontAnimMode || mAnimating || !mAnim)
return;
@ -3232,7 +3236,7 @@ RasterImage::DecodePool::DecodePool()
}
#endif
nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
if (obsSvc) {
obsSvc->AddObserver(this, "xpcom-shutdown-threads", false);
}

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

@ -176,8 +176,8 @@ public:
/* The total number of frames in this image. */
uint32_t GetNumFrames() const;
virtual size_t HeapSizeOfSourceWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const;
virtual size_t HeapSizeOfDecodedWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const;
virtual size_t HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const;
virtual size_t HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const;
virtual size_t NonHeapSizeOfDecoded() const;
virtual size_t OutOfProcessSizeOfDecoded() const;
@ -497,7 +497,7 @@ private:
// mThreadPoolMutex protects mThreadPool. For all RasterImages R,
// R::mDecodingMonitor must be acquired before mThreadPoolMutex
// if both are acquired; the other order may cause deadlock.
mozilla::Mutex mThreadPoolMutex;
Mutex mThreadPoolMutex;
nsCOMPtr<nsIThreadPool> mThreadPool;
};
@ -577,7 +577,7 @@ private:
uint32_t GetCurrentImgFrameIndex() const;
size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation,
mozilla::MallocSizeOf aMallocSizeOf) const;
MallocSizeOf aMallocSizeOf) const;
void EnsureAnimExists();
@ -660,10 +660,10 @@ private: // data
int mRequestedSampleSize;
// Cached value for GetImageContainer.
nsRefPtr<mozilla::layers::ImageContainer> mImageContainer;
nsRefPtr<layers::ImageContainer> mImageContainer;
// If not cached in mImageContainer, this might have our image container
WeakPtr<mozilla::layers::ImageContainer> mImageContainerCache;
WeakPtr<layers::ImageContainer> mImageContainerCache;
#ifdef DEBUG
uint32_t mFramesNotified;
@ -673,7 +673,7 @@ private: // data
// at once, and hence need to be locked by mDecodingMonitor.
// BEGIN LOCKED MEMBER VARIABLES
mozilla::ReentrantMonitor mDecodingMonitor;
ReentrantMonitor mDecodingMonitor;
FallibleTArray<char> mSourceData;

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

@ -17,7 +17,6 @@
#include "mozilla/StaticPtr.h"
#include "nsIMemoryReporter.h"
#include "gfx2DGlue.h"
#include "gfxASurface.h"
#include "gfxPattern.h" // Workaround for flaw in bug 921753 part 2.
#include "gfxDrawable.h"
#include "gfxPlatform.h"

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

@ -16,7 +16,6 @@
static bool gDisableOptimize = false;
#include "cairo.h"
#include "GeckoProfiler.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"

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

@ -25,7 +25,7 @@ public:
imgFrame();
~imgFrame();
nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, mozilla::gfx::SurfaceFormat aFormat, uint8_t aPaletteDepth = 0);
nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, SurfaceFormat aFormat, uint8_t aPaletteDepth = 0);
nsresult Optimize();
bool Draw(gfxContext *aContext, GraphicsFilter aFilter,
@ -36,7 +36,7 @@ public:
nsresult ImageUpdated(const nsIntRect &aUpdateRect);
nsIntRect GetRect() const;
mozilla::gfx::SurfaceFormat GetFormat() const;
SurfaceFormat GetFormat() const;
bool GetNeedsBackground() const;
uint32_t GetImageBytesPerRow() const;
uint32_t GetImageDataLength() const;

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

@ -10,8 +10,6 @@
#include "mozilla/NullPtr.h"
#include "js/HeapAPI.h"
#include "js/RootingAPI.h"
#include "js/Value.h"
namespace js {
namespace gc {
@ -432,47 +430,6 @@ class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertOnGC
explicit AutoCheckCannotGC(JSRuntime *rt) : AutoAssertOnGC(rt) {}
};
class JS_PUBLIC_API(ObjectPtr)
{
Heap<JSObject *> value;
public:
ObjectPtr() : value(nullptr) {}
explicit ObjectPtr(JSObject *obj) : value(obj) {}
/* Always call finalize before the destructor. */
~ObjectPtr() { MOZ_ASSERT(!value); }
void finalize(JSRuntime *rt) {
if (IsIncrementalBarrierNeeded(rt))
IncrementalObjectBarrier(value);
value = nullptr;
}
void init(JSObject *obj) { value = obj; }
JSObject *get() const { return value; }
void writeBarrierPre(JSRuntime *rt) {
IncrementalObjectBarrier(value);
}
bool isAboutToBeFinalized();
ObjectPtr &operator=(JSObject *obj) {
IncrementalObjectBarrier(value);
value = obj;
return *this;
}
void trace(JSTracer *trc, const char *name);
JSObject &operator*() const { return *value; }
JSObject *operator->() const { return value; }
operator JSObject *() const { return value; }
};
/*
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
* JSTRACE_SHAPE. |thing| should be non-null.
@ -507,13 +464,6 @@ ExposeGCThingToActiveJS(void *thing, JSGCTraceKind kind)
UnmarkGrayGCThingRecursively(thing, kind);
}
static MOZ_ALWAYS_INLINE void
ExposeValueToActiveJS(const Value &v)
{
if (v.isMarkable())
ExposeGCThingToActiveJS(v.toGCThing(), v.gcKind());
}
static MOZ_ALWAYS_INLINE void
ExposeObjectToActiveJS(JSObject *obj)
{

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

@ -349,7 +349,6 @@ struct RuntimeSizes
macro(_, _, contexts) \
macro(_, _, dtoa) \
macro(_, _, temporary) \
macro(_, _, regexpData) \
macro(_, _, interpreterStack) \
macro(_, _, mathCache) \
macro(_, _, sourceDataCache) \

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

@ -15,6 +15,7 @@
#include "jspubtd.h"
#include "js/GCAPI.h"
#include "js/HeapAPI.h"
#include "js/TypeDecls.h"
#include "js/Utility.h"
@ -1165,6 +1166,47 @@ class PersistentRooted : private mozilla::LinkedListElement<PersistentRooted<T>
T ptr;
};
class JS_PUBLIC_API(ObjectPtr)
{
Heap<JSObject *> value;
public:
ObjectPtr() : value(nullptr) {}
explicit ObjectPtr(JSObject *obj) : value(obj) {}
/* Always call finalize before the destructor. */
~ObjectPtr() { MOZ_ASSERT(!value); }
void finalize(JSRuntime *rt) {
if (IsIncrementalBarrierNeeded(rt))
IncrementalObjectBarrier(value);
value = nullptr;
}
void init(JSObject *obj) { value = obj; }
JSObject *get() const { return value; }
void writeBarrierPre(JSRuntime *rt) {
IncrementalObjectBarrier(value);
}
bool isAboutToBeFinalized();
ObjectPtr &operator=(JSObject *obj) {
IncrementalObjectBarrier(value);
value = obj;
return *this;
}
void trace(JSTracer *trc, const char *name);
JSObject &operator*() const { return *value; }
JSObject *operator->() const { return value; }
operator JSObject *() const { return value; }
};
} /* namespace JS */
namespace js {

462
js/public/UbiNode.h Normal file
Просмотреть файл

@ -0,0 +1,462 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 js_UbiNode_h
#define js_UbiNode_h
#include "mozilla/Alignment.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
#include "jspubtd.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/TypeDecls.h"
// JS::ubi::Node
//
// JS::ubi::Node is a pointer-like type designed for internal use by heap
// analysis tools. A ubi::Node can refer to:
//
// - a JS value, like a string or object;
// - an internal SpiderMonkey structure, like a shape or a scope chain object
// - an instance of some embedding-provided type: in Firefox, an XPCOM
// object, or an internal DOM node class instance
//
// A ubi::Node instance provides metadata about its referent, and can
// enumerate its referent's outgoing edges, so you can implement heap analysis
// algorithms that walk the graph - finding paths between objects, or
// computing heap dominator trees, say - using ubi::Node, while remaining
// ignorant of the details of the types you're operating on.
//
// Of course, when it comes to presenting the results in a developer-facing
// tool, you'll need to stop being ignorant of those details, because you have
// to discuss the ubi::Nodes' referents with the developer. Here, ubi::Node
// can hand you dynamically checked, properly typed pointers to the original
// objects via the as<T> method, or generate descriptions of the referent
// itself.
//
// ubi::Node instances are lightweight (two-word) value types. Instances:
// - compare equal if and only if they refer to the same object;
// - have hash values that respect their equality relation; and
// - have serializations that are only equal if the ubi::Nodes are equal.
//
// A ubi::Node is only valid for as long as its referent is alive; if its
// referent goes away, the ubi::Node becomes a dangling pointer. A ubi::Node
// that refers to a GC-managed object is not automatically a GC root; if the
// GC frees or relocates its referent, the ubi::Node becomes invalid. A
// ubi::Node that refers to a reference-counted object does not bump the
// reference count.
//
// ubi::Node values require no supporting data structures, making them
// feasible for use in memory-constrained devices --- ideally, the memory
// requirements of the algorithm which uses them will be the limiting factor,
// not the demands of ubi::Node itself.
//
// One can construct a ubi::Node value given a pointer to a type that ubi::Node
// supports. In the other direction, one can convert a ubi::Node back to a
// pointer; these downcasts are checked dynamically. In particular, one can
// convert a 'JSRuntime *' to a ubi::Node, yielding a node with an outgoing edge
// for every root registered with the runtime; starting from this, one can walk
// the entire heap. (Of course, one could also start traversal at any other kind
// of type to which one has a pointer.)
//
//
// Extending ubi::Node To Handle Your Embedding's Types
//
// To add support for a new ubi::Node referent type R, you must define a
// specialization of the ubi::Concrete template, ubi::Concrete<R>, which
// inherits from ubi::Base. ubi::Node itself uses the specialization for
// compile-time information (i.e. the checked conversions between R * and
// ubi::Node), and the inheritance for run-time dispatching.
//
//
// ubi::Node Exposes Implementation Details
//
// In many cases, a JavaScript developer's view of their data differs
// substantially from its actual implementation. For example, while the
// ECMAScript specification describes objects as maps from property names to
// sets of attributes (like ECMAScript's [[Value]]), in practice many objects
// have only a pointer to a shape, shared with other similar objects, and
// indexed slots that contain the [[Value]] attributes. As another example, a
// string produced by concatenating two other strings may sometimes be
// represented by a "rope", a structure that points to the two original
// strings.
//
// We intend to use ubi::Node to write tools that report memory usage, so it's
// important that ubi::Node accurately portray how much memory nodes consume.
// Thus, for example, when data that apparently belongs to multiple nodes is
// in fact shared in a common structure, ubi::Node's graph uses a separate
// node for that shared structure, and presents edges to it from the data's
// apparent owners. For example, ubi::Node exposes SpiderMonkey objects'
// shapes and base shapes, and exposes rope string and substring structure,
// because these optimizations become visible when a tool reports how much
// memory a structure consumes.
//
// However, fine granularity is not a goal. When a particular object is the
// exclusive owner of a separate block of memory, ubi::Node may present the
// object and its block as a single node, and add their sizes together when
// reporting the node's size, as there is no meaningful loss of data in this
// case. Thus, for example, a ubi::Node referring to a JavaScript object, when
// asked for the object's size in bytes, includes the object's slot and
// element arrays' sizes in the total. There is no separate ubi::Node value
// representing the slot and element arrays, since they are owned exclusively
// by the object.
//
//
// Presenting Analysis Results To JavaScript Developers
//
// If an analysis provides its results in terms of ubi::Node values, a user
// interface presenting those results will generally need to clean them up
// before they can be understood by JavaScript developers. For example,
// JavaScript developers should not need to understand shapes, only JavaScript
// objects. Similarly, they should not need to understand the distinction
// between DOM nodes and the JavaScript shadow objects that represent them.
//
//
// Rooting Restrictions
//
// At present there is no way to root ubi::Node instances, so instances can't be
// live across any operation that might GC. Analyses using ubi::Node must either
// run to completion and convert their results to some other rootable type, or
// save their intermediate state in some rooted structure if they must GC before
// they complete. (For algorithms like path-finding and dominator tree
// computation, we implement the algorithm avoiding any operation that could
// cause a GC --- and use AutoCheckCannotGC to verify this.)
//
// If this restriction prevents us from implementing interesting tools, we may
// teach the GC how to root ubi::Nodes, fix up hash tables that use them as
// keys, etc.
// Forward declarations of SpiderMonkey's ubi::Node reference types.
namespace js {
class LazyScript;
class Shape;
class BaseShape;
namespace jit {
class JitCode;
}
namespace types {
struct TypeObject;
}
}
namespace JS {
namespace ubi {
class Edge;
class EdgeRange;
// The base class implemented by each ubi::Node referent type. Subclasses must
// not add data members to this class.
class Base {
friend class Node;
// For performance's sake, we'd prefer to avoid a virtual destructor; and
// an empty constructor seems consistent with the 'lightweight value type'
// visible behavior we're trying to achieve. But if the destructor isn't
// virtual, and a subclass overrides it, the subclass's destructor will be
// ignored. Is there a way to make the compiler catch that error?
protected:
// Space for the actual pointer. Concrete subclasses should define a
// properly typed 'get' member function to access this.
void *ptr;
Base(void *ptr) : ptr(ptr) { }
public:
bool operator==(const Base &rhs) const {
// Some compilers will indeed place objects of different types at
// the same address, so technically, we should include the vtable
// in this comparison. But it seems unlikely to cause problems in
// practice.
return ptr == rhs.ptr;
}
bool operator!=(const Base &rhs) const { return !(*this == rhs); }
// Return a human-readable name for the referent's type. The result should
// be statically allocated. (You can use MOZ_UTF16("strings") for this.)
//
// This must always return Concrete<T>::concreteTypeName; we use that
// pointer as a tag for this particular referent type.
virtual const jschar *typeName() const = 0;
// Return the size of this node, in bytes. Include any structures that this
// node owns exclusively that are not exposed as their own ubi::Nodes.
virtual size_t size() const = 0;
// Return an EdgeRange that initially contains all the referent's outgoing
// edges. The EdgeRange should be freed with 'js_delete'. (You could use
// ScopedDJSeletePtr<EdgeRange> to manage it.) On OOM, report an exception
// on |cx| and return nullptr.
virtual EdgeRange *edges(JSContext *cx) const = 0;
private:
Base(const Base &rhs) MOZ_DELETE;
Base &operator=(const Base &rhs) MOZ_DELETE;
};
// A traits template with a specialization for each referent type that
// ubi::Node supports. The specialization must be the concrete subclass of
// Base that represents a pointer to the referent type. It must also
// include the members described here.
template<typename Referent>
struct Concrete {
// The specific jschar array returned by Concrete<T>::typeName.
static const jschar concreteTypeName[];
// Construct an instance of this concrete class in |storage| referring
// to |referent|. Implementations typically use a placement 'new'.
//
// In some cases, |referent| will contain dynamic type information that
// identifies it a some more specific subclass of |Referent|. For example,
// when |Referent| is |JSObject|, then |referent->getClass()| could tell us
// that it's actually a JSFunction. Similarly, if |Referent| is
// |nsISupports|, we would like a ubi::Node that knows its final
// implementation type.
//
// So, we delegate the actual construction to this specialization, which
// knows Referent's details.
static void construct(void *storage, Referent *referent);
};
// A container for a Base instance; all members simply forward to the contained instance.
// This container allows us to pass ubi::Node instances by value.
class Node {
// Storage in which we allocate Base subclasses.
mozilla::AlignedStorage2<Base> storage;
Base *base() { return storage.addr(); }
const Base *base() const { return storage.addr(); }
template<typename T>
void construct(T *ptr) {
static_assert(sizeof(Concrete<T>) == sizeof(*base()),
"ubi::Base specializations must be the same size as ubi::Base");
Concrete<T>::construct(base(), ptr);
}
typedef void (Node::* ConvertibleToBool)();
void nonNull() {}
public:
Node() { construct<void>(nullptr); }
template<typename T>
Node(T *ptr) {
construct(ptr);
}
template<typename T>
Node &operator=(T *ptr) {
construct(ptr);
return *this;
}
// We can construct and assign from rooted forms of pointers.
template<typename T>
Node(const Rooted<T *> &root) {
construct(root.get());
}
template<typename T>
Node &operator=(const Rooted<T *> &root) {
construct(root.get());
return *this;
}
// Constructors accepting SpiderMonkey's other generic-pointer-ish types.
Node(JS::Value value);
Node(JSGCTraceKind kind, void *ptr);
// copy construction and copy assignment just use memcpy, since we know
// instances contain nothing but a vtable pointer and a data pointer.
//
// To be completely correct, concrete classes could provide a virtual
// 'construct' member function, which we could invoke on rhs to construct an
// instance in our storage. But this is good enough; there's no need to jump
// through vtables for copying and assignment that are just going to move
// two words around. The compiler knows how to optimize memcpy.
Node(const Node &rhs) {
memcpy(storage.u.mBytes, rhs.storage.u.mBytes, sizeof(storage.u));
}
Node &operator=(const Node &rhs) {
memcpy(storage.u.mBytes, rhs.storage.u.mBytes, sizeof(storage.u));
return *this;
}
bool operator==(const Node &rhs) const { return *base() == *rhs.base(); }
bool operator!=(const Node &rhs) const { return *base() != *rhs.base(); }
operator ConvertibleToBool() const {
return base()->ptr ? &Node::nonNull : 0;
}
template<typename T>
bool is() const {
return base()->typeName() == Concrete<T>::concreteTypeName;
}
template<typename T>
T *as() const {
MOZ_ASSERT(is<T>());
return static_cast<T *>(base()->ptr);
}
template<typename T>
T *asOrNull() const {
return is<T>() ? static_cast<T *>(base()->ptr) : nullptr;
}
// If this node refers to something that can be represented as a
// JavaScript value that is safe to expose to JavaScript code, return that
// value. Otherwise return UndefinedValue(). JSStrings and some (but not
// all!) JSObjects can be exposed.
JS::Value exposeToJS() const;
const jschar *typeName() const { return base()->typeName(); }
size_t size() const { return base()->size(); }
EdgeRange *edges(JSContext *cx) const { return base()->edges(cx); }
// A hash policy for ubi::Nodes.
// This simply uses the stock PointerHasher on the ubi::Node's pointer.
// We specialize DefaultHasher below to make this the default.
class HashPolicy {
typedef js::PointerHasher<void *, mozilla::tl::FloorLog2<sizeof(void *)>::value> PtrHash;
public:
typedef Node Lookup;
static js::HashNumber hash(const Lookup &l) { return PtrHash::hash(l.base()->ptr); }
static bool match(const Node &k, const Lookup &l) { return k == l; }
static void rekey(Node &k, const Node &newKey) { k = newKey; }
};
};
// Edge is the abstract base class representing an outgoing edge of a node.
// Edges are owned by EdgeRanges, and need not have assignment operators or copy
// constructors.
//
// Each Edge class should inherit from this base class, overriding as
// appropriate.
class Edge {
protected:
Edge() : name(nullptr), referent() { }
virtual ~Edge() { }
public:
// This edge's name.
//
// The storage is owned by this Edge, and will be freed when this Edge is
// destructed.
//
// (In real life we'll want a better representation for names, to avoid
// creating tons of strings when the names follow a pattern; and we'll need
// to think about lifetimes carefully to ensure traversal stays cheap.)
const jschar *name;
// This edge's referent.
Node referent;
private:
Edge(const Edge &) MOZ_DELETE;
Edge &operator=(const Edge &) MOZ_DELETE;
};
// EdgeRange is an abstract base class for iterating over a node's outgoing
// edges. (This is modeled after js::HashTable<K,V>::Range.)
//
// Concrete instances of this class need not be as lightweight as Node itself,
// since they're usually only instantiated while iterating over a particular
// object's edges. For example, a dumb implementation for JS Cells might use
// JS_TraceChildren to to get the outgoing edges, and then store them in an
// array internal to the EdgeRange.
class EdgeRange {
protected:
// The current front edge of this range, or nullptr if this range is empty.
Edge *front_;
EdgeRange() : front_(nullptr) { }
public:
virtual ~EdgeRange() { };
// True if there are no more edges in this range.
bool empty() const { return !front_; }
// The front edge of this range. This is owned by the EdgeRange, and is
// only guaranteed to live until the next call to popFront, or until
// the EdgeRange is destructed.
const Edge &front() { return *front_; }
// Remove the front edge from this range. This should only be called if
// !empty().
virtual void popFront() = 0;
private:
EdgeRange(const EdgeRange &) MOZ_DELETE;
EdgeRange &operator=(const EdgeRange &) MOZ_DELETE;
};
// Concrete classes for ubi::Node referent types.
// A reusable ubi::Concrete specialization base class for types supported by
// JS_TraceChildren.
template<typename Referent>
class TracerConcrete : public Base {
const jschar *typeName() const MOZ_OVERRIDE { return concreteTypeName; }
size_t size() const MOZ_OVERRIDE { return 0; } // not implemented yet; bug 1011300
EdgeRange *edges(JSContext *) const MOZ_OVERRIDE;
TracerConcrete(Referent *ptr) : Base(ptr) { }
public:
static const jschar concreteTypeName[];
static void construct(void *storage, Referent *ptr) { new (storage) TracerConcrete(ptr); };
};
template<> struct Concrete<JSObject> : TracerConcrete<JSObject> { };
template<> struct Concrete<JSString> : TracerConcrete<JSString> { };
template<> struct Concrete<JSScript> : TracerConcrete<JSScript> { };
template<> struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> { };
template<> struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> { };
template<> struct Concrete<js::Shape> : TracerConcrete<js::Shape> { };
template<> struct Concrete<js::BaseShape> : TracerConcrete<js::BaseShape> { };
template<> struct Concrete<js::types::TypeObject> : TracerConcrete<js::types::TypeObject> { };
// The ubi::Node null pointer. Any attempt to operate on a null ubi::Node asserts.
template<>
class Concrete<void> : public Base {
const jschar *typeName() const MOZ_OVERRIDE;
size_t size() const MOZ_OVERRIDE;
EdgeRange *edges(JSContext *cx) const MOZ_OVERRIDE;
Concrete(void *ptr) : Base(ptr) { }
public:
static void construct(void *storage, void *ptr) { new (storage) Concrete(ptr); }
static const jschar concreteTypeName[];
};
} // namespace ubi
} // namespace JS
namespace js {
// Make ubi::Node::HashPolicy the default hash policy for ubi::Node.
template<> struct DefaultHasher<JS::ubi::Node> : JS::ubi::Node::HashPolicy { };
} // namespace js
#endif // js_UbiNode_h

208
js/public/UbiNodeTraverse.h Normal file
Просмотреть файл

@ -0,0 +1,208 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 js_UbiNodeTraverse_h
#define js_UbiNodeTraverse_h
#include "js/UbiNode.h"
#include "js/Utility.h"
#include "js/Vector.h"
namespace JS {
namespace ubi {
// A breadth-first traversal template for graphs of ubi::Nodes.
//
// No GC may occur while an instance of this template is live.
//
// The provided Handler type should have two members:
//
// typename NodeData;
//
// The value type of |BreadthFirst<Handler>::visited|, the HashMap of
// ubi::Nodes that have been visited so far. Since the algorithm needs a
// hash table like this for its own use anyway, it is simple to let
// Handler store its own metadata about each node in the same table.
//
// For example, if you want to find a shortest path to each node from any
// traversal starting point, your |NodeData| type could record the first
// edge to reach each node, and the node from which it originates. Then,
// when the traversal is complete, you can walk backwards from any node
// to some starting point, and the path recorded will be a shortest path.
//
// This type must have a default constructor. If this type owns any other
// resources, move constructors and assignment operators are probably a
// good idea, too.
//
// bool operator() (BreadthFirst &traversal,
// Node origin, const Edge &edge,
// Handler::NodeData *referentData, bool first);
//
// The visitor function, called to report that we have traversed
// |edge| from |origin|. This is called once for each edge we traverse.
// As this is a breadth-first search, any prior calls to the visitor function
// were for origin nodes not further from the start nodes than |origin|.
//
// |traversal| is this traversal object, passed along for convenience.
//
// |referentData| is a pointer to the value of the entry in
// |traversal.visited| for |edge.referent|; the visitor function can
// store whatever metadata it likes about |edge.referent| there.
//
// |first| is true if this is the first time we have visited an edge
// leading to |edge.referent|. This could be stored in NodeData, but
// the algorithm knows whether it has just created the entry in
// |traversal.visited|, so it passes it along for convenience.
//
// The visitor function may call |traversal.stop()| if it doesn't want
// to visit any more nodes.
//
// The visitor function may consult |traversal.visited| for information
// about other nodes, but it should not add or remove entries.
//
// The visitor function should return true on success, or false if an
// error occurs. A false return value terminates the traversal
// immediately, and causes BreadthFirst<Handler>::traverse to return
// false.
template<typename Handler>
struct BreadthFirst {
// Construct a breadth-first traversal object that reports the nodes it
// reaches to |handler|. The traversal object reports OOM on |cx|, and
// asserts that no GC happens in |cx|'s runtime during its lifetime.
//
// We do nothing with noGC, other than require it to exist, with a lifetime
// that encloses our own.
BreadthFirst(JSContext *cx, Handler &handler, const JS::AutoCheckCannotGC &noGC)
: cx(cx), visited(cx), handler(handler), pending(cx),
traversalBegun(false), stopRequested(false)
{ }
// Initialize this traversal object. Return false on OOM.
bool init() { return visited.init(); }
// Add |node| as a starting point for the traversal. You may add
// as many starting points as you like. Return false on OOM.
bool addStart(Node node) { return pending.append(node); }
// Traverse the graph in breadth-first order, starting at the given
// start nodes, applying |handler::operator()| for each edge traversed
// as described above.
//
// This should be called only once per instance of this class.
//
// Return false on OOM or error return from |handler::operator()|.
bool traverse()
{
MOZ_ASSERT(!traversalBegun);
traversalBegun = true;
// While there are pending nodes, visit them, until we've found a path to the target.
while (!pending.empty()) {
Node origin = pending.front();
pending.popFront();
// Get a range containing all origin's outgoing edges.
js::ScopedJSDeletePtr<EdgeRange> range(origin.edges(cx));
if (!range)
return false;
// Traverse each edge.
for (; !range->empty(); range->popFront()) {
MOZ_ASSERT(!stopRequested);
const Edge &edge = range->front();
typename NodeMap::AddPtr a = visited.lookupForAdd(edge.referent);
bool first = !a;
if (first) {
// This is the first time we've reached |edge.referent|.
// Create an entry for it in |visited|, and arrange to
// traverse its outgoing edges later.
if (!visited.add(a, edge.referent, typename Handler::NodeData()) ||
!pending.append(edge.referent)) {
return false;
}
}
MOZ_ASSERT(a);
// Report this edge to the visitor function.
if (!handler(*this, origin, edge, &a->value(), first))
return false;
if (stopRequested)
return true;
}
}
return true;
}
// Stop traversal, and return true from |traverse| without visiting any
// more nodes. Only |handler::operator()| should call this function; it
// may do so to stop the traversal early, without returning false and
// then making |traverse|'s caller disambiguate that result from a real
// error.
void stop() { stopRequested = true; }
// The context with which we were constructed.
JSContext *cx;
// A map associating each node N that we have reached with a
// Handler::NodeData, for |handler|'s use. This is public, so that
// |handler| can access it to see the traversal thus far.
typedef js::HashMap<Node, typename Handler::NodeData> NodeMap;
NodeMap visited;
private:
// Our handler object.
Handler &handler;
// A queue template. Appending and popping the front are constant time.
// Wasted space is never more than some recent actual population plus the
// current population.
template <typename T>
class Queue {
js::Vector<T, 0> head, tail;
size_t frontIndex;
public:
Queue(JSContext *cx) : head(cx), tail(cx), frontIndex(0) { }
bool empty() { return frontIndex >= head.length(); }
T &front() {
MOZ_ASSERT(!empty());
return head[frontIndex];
}
void popFront() {
MOZ_ASSERT(!empty());
frontIndex++;
if (frontIndex >= head.length()) {
head.clearAndFree();
head.swap(tail);
frontIndex = 0;
}
}
bool append(const T &elt) {
return frontIndex == 0 ? head.append(elt) : tail.append(elt);
}
};
// A queue of nodes that we have reached, but whose outgoing edges we
// have not yet traversed. Nodes reachable in fewer edges are enqueued
// earlier.
Queue<Node> pending;
// True if our traverse function has been called.
bool traversalBegun;
// True if we've been asked to stop the traversal.
bool stopRequested;
};
} // namespace ubi
} // namespace JS
#endif // js_UbiNodeTraverse.h

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

@ -19,6 +19,7 @@
#include "jstypes.h"
#include "js/Anchor.h"
#include "js/GCAPI.h"
#include "js/RootingAPI.h"
#include "js/Utility.h"
@ -1288,6 +1289,13 @@ IsOptimizedPlaceholderMagicValue(const Value &v)
return false;
}
static MOZ_ALWAYS_INLINE void
ExposeValueToActiveJS(const Value &v)
{
if (v.isMarkable())
ExposeGCThingToActiveJS(v.toGCThing(), v.gcKind());
}
/************************************************************************/
static inline Value

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

@ -10,10 +10,7 @@
#include "jscntxt.h"
#ifndef JS_YARR
#include "irregexp/RegExpParser.h"
#endif
#include "vm/RegExpStatics.h"
#include "vm/StringBuffer.h"
@ -94,28 +91,12 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs
static RegExpRunStatus
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
HandleLinearString input, const jschar *chars, size_t length,
size_t *lastIndex, MatchConduit &matches)
size_t *lastIndex, MatchPairs &matches)
{
RegExpRunStatus status;
/* Switch between MatchOnly and IncludeSubpatterns modes. */
if (matches.isPair) {
#ifdef JS_YARR
size_t lastIndex_orig = *lastIndex;
/* Only one MatchPair slot provided: execute short-circuiting regexp. */
status = re.executeMatchOnly(cx, chars, length, lastIndex, *matches.u.pair);
if (status == RegExpRunStatus_Success && res)
res->updateLazily(cx, input, &re, lastIndex_orig);
#else
MOZ_CRASH();
#endif
} else {
/* Vector of MatchPairs provided: execute full regexp. */
status = re.execute(cx, chars, length, lastIndex, *matches.u.pairs);
if (status == RegExpRunStatus_Success && res) {
if (!res->updateFromMatchPairs(cx, input, *matches.u.pairs))
return RegExpRunStatus_Error;
}
RegExpRunStatus status = re.execute(cx, chars, length, lastIndex, matches);
if (status == RegExpRunStatus_Success && res) {
if (!res->updateFromMatchPairs(cx, input, matches))
return RegExpRunStatus_Error;
}
return status;
}
@ -131,10 +112,9 @@ js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
return false;
ScopedMatchPairs matches(&cx->tempLifoAlloc());
MatchConduit conduit(&matches);
RegExpRunStatus status =
ExecuteRegExpImpl(cx, res, *shared, input_, chars, length, lastIndex, conduit);
ExecuteRegExpImpl(cx, res, *shared, input_, chars, length, lastIndex, matches);
if (status == RegExpRunStatus_Error)
return false;
@ -308,16 +288,11 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
if (!escapedSourceStr)
return false;
#ifdef JS_YARR
if (!RegExpShared::checkSyntax(cx, nullptr, escapedSourceStr))
return false;
#else // JS_YARR
CompileOptions options(cx);
frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), escapedSourceStr))
return false;
#endif // JS_YARR
RegExpStatics *res = cx->global()->getRegExpStatics(cx);
if (!res)
@ -557,7 +532,7 @@ js_InitRegExpClass(JSContext *cx, HandleObject obj)
RegExpRunStatus
js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string,
MatchConduit &matches, RegExpStaticsUpdate staticsUpdate)
MatchPairs &matches, RegExpStaticsUpdate staticsUpdate)
{
/* Step 1 (b) was performed by CallNonGenericMethod. */
Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
@ -633,7 +608,7 @@ js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string,
/* ES5 15.10.6.2 (and 15.10.6.3, which calls 15.10.6.2). */
static RegExpRunStatus
ExecuteRegExp(JSContext *cx, CallArgs args, MatchConduit &matches)
ExecuteRegExp(JSContext *cx, CallArgs args, MatchPairs &matches)
{
/* Step 1 (a) was performed by CallNonGenericMethod. */
RootedObject regexp(cx, &args.thisv().toObject());
@ -653,9 +628,8 @@ regexp_exec_impl(JSContext *cx, HandleObject regexp, HandleString string,
{
/* Execute regular expression and gather matches. */
ScopedMatchPairs matches(&cx->tempLifoAlloc());
MatchConduit conduit(&matches);
RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, conduit, staticsUpdate);
RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, matches, staticsUpdate);
if (status == RegExpRunStatus_Error)
return false;
@ -711,14 +685,8 @@ js::regexp_exec_no_statics(JSContext *cx, unsigned argc, Value *vp)
static bool
regexp_test_impl(JSContext *cx, CallArgs args)
{
#ifdef JS_YARR
MatchPair match;
MatchConduit conduit(&match);
#else
ScopedMatchPairs matches(&cx->tempLifoAlloc());
MatchConduit conduit(&matches);
#endif
RegExpRunStatus status = ExecuteRegExp(cx, args, conduit);
RegExpRunStatus status = ExecuteRegExp(cx, args, matches);
args.rval().setBoolean(status == RegExpRunStatus_Success);
return status != RegExpRunStatus_Error;
}
@ -727,14 +695,8 @@ regexp_test_impl(JSContext *cx, CallArgs args)
bool
js::regexp_test_raw(JSContext *cx, HandleObject regexp, HandleString input, bool *result)
{
#ifdef JS_YARR
MatchPair match;
MatchConduit conduit(&match);
#else
ScopedMatchPairs matches(&cx->tempLifoAlloc());
MatchConduit conduit(&matches);
#endif
RegExpRunStatus status = ExecuteRegExp(cx, regexp, input, conduit, UpdateRegExpStatics);
RegExpRunStatus status = ExecuteRegExp(cx, regexp, input, matches, UpdateRegExpStatics);
*result = (status == RegExpRunStatus_Success);
return status != RegExpRunStatus_Error;
}
@ -757,14 +719,8 @@ js::regexp_test_no_statics(JSContext *cx, unsigned argc, Value *vp)
RootedObject regexp(cx, &args[0].toObject());
RootedString string(cx, args[1].toString());
#ifdef JS_YARR
MatchPair match;
MatchConduit conduit(&match);
#else
ScopedMatchPairs matches(&cx->tempLifoAlloc());
MatchConduit conduit(&matches);
#endif
RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, conduit, DontUpdateRegExpStatics);
RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, matches, DontUpdateRegExpStatics);
args.rval().setBoolean(status == RegExpRunStatus_Success);
return status != RegExpRunStatus_Error;
}

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

@ -19,15 +19,13 @@ js_InitRegExpClass(JSContext *cx, js::HandleObject obj);
namespace js {
class MatchConduit;
// Whether RegExp statics should be updated with the input and results of a
// regular expression execution.
enum RegExpStaticsUpdate { UpdateRegExpStatics, DontUpdateRegExpStatics };
RegExpRunStatus
ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string,
MatchConduit &matches, RegExpStaticsUpdate staticsUpdate);
MatchPairs &matches, RegExpStaticsUpdate staticsUpdate);
/*
* Legacy behavior of ExecuteRegExp(), which is baked into the JSAPI.

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

@ -6,6 +6,9 @@
#include "builtin/TestingFunctions.h"
#include "mozilla/Move.h"
#include "mozilla/Scoped.h"
#include "jsapi.h"
#include "jscntxt.h"
#include "jsfriendapi.h"
@ -18,7 +21,11 @@
#include "jit/AsmJS.h"
#include "jit/AsmJSLink.h"
#include "js/HashTable.h"
#include "js/StructuredClone.h"
#include "js/UbiNode.h"
#include "js/UbiNodeTraverse.h"
#include "js/Vector.h"
#include "vm/ForkJoin.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
@ -33,6 +40,8 @@ using namespace js;
using namespace JS;
using mozilla::ArrayLength;
using mozilla::Move;
using mozilla::ScopedFreePtr;
// If fuzzingSafe is set, remove functionality that could cause problems with
// fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
@ -1651,6 +1660,214 @@ ReportLargeAllocationFailure(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
namespace heaptools {
// An edge to a node from its predecessor in a path through the graph.
class BackEdge {
// The node from which this edge starts.
JS::ubi::Node predecessor_;
// The name of this edge. We own this storage.
ScopedFreePtr<jschar> name_;
public:
BackEdge() : name_(nullptr) { }
// Construct an initialized back edge. Take ownership of |name|.
BackEdge(JS::ubi::Node predecessor, jschar *name)
: predecessor_(predecessor), name_(name) { }
BackEdge(BackEdge &&rhs) : predecessor_(rhs.predecessor_), name_(rhs.name_.forget()) { }
BackEdge &operator=(BackEdge &&rhs) {
MOZ_ASSERT(&rhs != this);
this->~BackEdge();
new(this) BackEdge(Move(rhs));
return *this;
}
jschar *forgetName() { return name_.forget(); }
JS::ubi::Node predecessor() const { return predecessor_; }
private:
// No copy constructor or copying assignment.
BackEdge(const BackEdge &) MOZ_DELETE;
BackEdge &operator=(const BackEdge &) MOZ_DELETE;
};
// A path-finding handler class for use with JS::ubi::BreadthFirst.
struct FindPathHandler {
typedef BackEdge NodeData;
typedef JS::ubi::BreadthFirst<FindPathHandler> Traversal;
FindPathHandler(JS::ubi::Node start, JS::ubi::Node target,
AutoValueVector &nodes, Vector<ScopedFreePtr<jschar> > &edges)
: start(start), target(target), foundPath(false),
nodes(nodes), edges(edges) { }
bool
operator()(Traversal &traversal, JS::ubi::Node origin, const JS::ubi::Edge &edge,
BackEdge *backEdge, bool first)
{
// We take care of each node the first time we visit it, so there's
// nothing to be done on subsequent visits.
if (!first)
return true;
// Record how we reached this node. This is the last edge on a
// shortest path to this node.
jschar *edgeName = js_strdup(traversal.cx, edge.name);
if (!edgeName)
return false;
*backEdge = mozilla::Move(BackEdge(origin, edgeName));
// Have we reached our final target node?
if (edge.referent == target) {
// Record the path that got us here, which must be a shortest path.
if (!recordPath(traversal))
return false;
foundPath = true;
traversal.stop();
}
return true;
}
// We've found a path to our target. Walk the backlinks to produce the
// (reversed) path, saving the path in |nodes| and |edges|. |nodes| is
// rooted, so it can hold the path's nodes as we leave the scope of
// the AutoCheckCannotGC.
bool recordPath(Traversal &traversal) {
JS::ubi::Node here = target;
do {
Traversal::NodeMap::Ptr p = traversal.visited.lookup(here);
MOZ_ASSERT(p);
JS::ubi::Node predecessor = p->value().predecessor();
if (!nodes.append(predecessor.exposeToJS()) ||
!edges.append(p->value().forgetName()))
return false;
here = predecessor;
} while (here != start);
return true;
}
// The node we're starting from.
JS::ubi::Node start;
// The node we're looking for.
JS::ubi::Node target;
// True if we found a path to target, false if we didn't.
bool foundPath;
// The nodes and edges of the path --- should we find one. The path is
// stored in reverse order, because that's how it's easiest for us to
// construct it:
// - edges[i] is the name of the edge from nodes[i] to nodes[i-1].
// - edges[0] is the name of the edge from nodes[0] to the target.
// - The last node, nodes[n-1], is the start node.
AutoValueVector &nodes;
Vector<ScopedFreePtr<jschar> > &edges;
};
} // namespace heaptools
static bool
FindPath(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (argc < 2) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
"findPath", "1", "");
return false;
}
// We don't ToString non-objects given as 'start' or 'target'. We can't
// see edges to non-string primitive values, and it doesn't make much
// sense to ask for paths to or from a freshly allocated string, so
// if a non-string primitive appears here it's probably a mistake.
if (!args[0].isObject() && !args[0].isString()) {
js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
JSDVG_SEARCH_STACK, args[0], JS::NullPtr(),
"neither an object nor a string", NULL);
return false;
}
if (!args[1].isObject() && !args[1].isString()) {
js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
JSDVG_SEARCH_STACK, args[0], JS::NullPtr(),
"neither an object nor a string", NULL);
return false;
}
AutoValueVector nodes(cx);
Vector<ScopedFreePtr<jschar> > edges(cx);
{
// We can't tolerate the GC moving things around while we're searching
// the heap. Check that nothing we do causes a GC.
JS::AutoCheckCannotGC autoCannotGC;
JS::ubi::Node start(args[0]), target(args[1]);
heaptools::FindPathHandler handler(start, target, nodes, edges);
heaptools::FindPathHandler::Traversal traversal(cx, handler, autoCannotGC);
if (!traversal.init() || !traversal.addStart(start))
return false;
if (!traversal.traverse())
return false;
if (!handler.foundPath) {
// We didn't find any paths from the start to the target.
args.rval().setUndefined();
return true;
}
}
// |nodes| and |edges| contain the path from |start| to |target|, reversed.
// Construct a JavaScript array describing the path from the start to the
// target. Each element has the form:
//
// { node: <object or string>, edge: <string describing outgoing edge from node> }
//
// or, if the node is some internal thing, that isn't a proper
// JavaScript value:
//
// { node: undefined, edge: <string> }
size_t length = nodes.length();
RootedObject result(cx, NewDenseAllocatedArray(cx, length));
if (!result)
return false;
result->ensureDenseInitializedLength(cx, 0, length);
// Walk |nodes| and |edges| in the stored order, and construct the result
// array in start-to-target order.
for (size_t i = 0; i < length; i++) {
// Build an object describing the node and edge.
RootedObject obj(cx, NewBuiltinClassInstance<JSObject>(cx));
if (!obj)
return false;
if (!JS_DefineProperty(cx, obj, "node", nodes[i],
JSPROP_ENUMERATE, nullptr, nullptr))
return false;
RootedString edge(cx, js_NewString<CanGC>(cx, edges[i].get(), js_strlen(edges[i])));
if (!edge)
return false;
edges[i].forget();
RootedValue edgeString(cx, StringValue(edge));
if (!JS_DefineProperty(cx, obj, "edge", edgeString,
JSPROP_ENUMERATE, nullptr, nullptr))
return false;
result->setDenseElement(length - i - 1, ObjectValue(*obj));
}
args.rval().setObject(*result);
return true;
}
static const JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gc", ::GC, 0, 0,
"gc([obj] | 'compartment')",
@ -1931,6 +2148,19 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
" then return undefined. In Gecko, this sends a memory pressure notification, which\n"
" can free up some memory."),
JS_FN_HELP("findPath", FindPath, 2, 0,
"findPath(start, target)",
" Return an array describing one of the shortest paths of GC heap edges from\n"
" |start| to |target|, or |undefined| if |target| is unreachable from |start|.\n"
" Each element of the array is either of the form:\n"
" { node: <object or string>, edge: <string describing edge from node> }\n"
" if the node is a JavaScript object or value; or of the form:\n"
" { type: <string describing node>, edge: <string describing edge> }\n"
" if the node is some internal thing that is not a proper JavaScript value\n"
" (like a shape or a scope chain element). The destination of the i'th array\n"
" element's edge is the node of the i+1'th array element; the destination of\n"
" the last array element is implicitly |target|.\n"),
#ifdef DEBUG
JS_FN_HELP("dumpObject", DumpObject, 1, 0,
"dumpObject()",

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

@ -3004,20 +3004,6 @@ if test "$ENABLE_TRACE_LOGGING"; then
AC_DEFINE(JS_TRACE_LOGGING)
fi
dnl ========================================================
dnl = Enable yarr regexp engine
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(yarr,
[ --enable-yarr Enable yarr regexp engine],
ENABLE_YARR=1,
ENABLE_YARR= )
AC_SUBST(ENABLE_YARR)
if test "$ENABLE_YARR"; then
AC_DEFINE(JS_YARR)
fi
dnl ========================================================
dnl = Enable any treating of compile warnings as errors
dnl ========================================================

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

@ -0,0 +1,44 @@
load(libdir + "match.js")
// At the moment, findPath just returns the names as provided by ubi::Node,
// which just uses JS_TraceChildren for now. However, we have various plans
// to improve the quality of ubi::Node's metadata, to improve the precision
// and clarity of the results here.
var o = { w: { x: { y: { z: {} } } } };
Match.Pattern([{node: {}, edge: "w"},
{node: {}, edge: "x"},
{node: {}, edge: "y"},
{node: {}, edge: "z"}])
.assert(findPath(o, o.w.x.y.z));
print(uneval(findPath(o, o.w.x.y.z)));
var a = [ , o ];
Match.Pattern([{node: {}, edge: "objectElements[1]"}])
.assert(findPath(a, o));
print(uneval(findPath(a, o)));
function C() {}
C.prototype.obj = {};
var c = new C;
Match.Pattern([{node: {}, edge: "type"},
{node: Match.Pattern.ANY, edge: "type_proto"},
{node: { constructor: Match.Pattern.ANY }, edge: "obj"}])
.assert(findPath(c, c.obj));
print(uneval(findPath(c, c.obj)));
function f(x) { return function g(y) { return x+y; }; }
var o = {}
var gc = f(o);
Match.Pattern([{node: gc, edge: "fun_callscope"},
{node: Match.Pattern.ANY, edge: "x"}])
.assert(findPath(gc, o));
print(uneval(findPath(gc, o)));
Match.Pattern([{node: {}, edge: "shape"},
{node: Match.Pattern.ANY, edge: "base"},
{node: Match.Pattern.ANY, edge: "parent"},
{node: {}, edge: "o"}])
.assert(findPath(o, o));
print(findPath(o, o).map((e) => e.edge).toString());

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

@ -21,21 +21,9 @@
(js::jit::Simulator::Current()->call( \
JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 8, p0, p1, p2, p3, p4, p5, p6, p7) & 0xffffffff)
#ifdef JS_YARR
#define CALL_GENERATED_YARR_CODE3(entry, p0, p1, p2) \
js::jit::Simulator::Current()->call(JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 3, p0, p1, p2)
#define CALL_GENERATED_YARR_CODE4(entry, p0, p1, p2, p3) \
js::jit::Simulator::Current()->call(JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 4, p0, p1, p2, p3)
#else // JS_YARR
#define CALL_GENERATED_REGEXP(entry, p0) \
js::jit::Simulator::Current()->call(JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 1, p0)
#endif // JS_YARR
#define CALL_GENERATED_ASMJS(entry, p0, p1) \
(Simulator::Current()->call(JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 2, p0, p1) & 0xffffffff)
@ -45,21 +33,9 @@
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
entry(p0, p1, p2, p3, p4, p5, p6, p7)
#ifdef JS_YARR
#define CALL_GENERATED_YARR_CODE3(entry, p0, p1, p2) \
entry(p0, p1, p2)
#define CALL_GENERATED_YARR_CODE4(entry, p0, p1, p2, p3) \
entry(p0, p1, p2, p3)
#else // JS_YARR
#define CALL_GENERATED_REGEXP(entry, p0) \
entry(p0)
#endif // JS_YARR
#define CALL_GENERATED_ASMJS(entry, p0, p1) \
entry(p0, p1)

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

@ -541,9 +541,6 @@ Assembler::finish()
JS_ASSERT(!isFinished);
isFinished = true;
for (size_t i = 0; i < jumps_.length(); i++)
jumps_[i].fixOffset(m_buffer);
for (unsigned int i = 0; i < tmpDataRelocations_.length(); i++) {
int offset = tmpDataRelocations_[i].getOffset();
int real_offset = offset + m_buffer.poolSizeBefore(offset);

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

@ -1242,18 +1242,10 @@ class Assembler : public AssemblerShared
// gets moved (executable copy, gc, etc.)
struct RelativePatch
{
// the offset within the code buffer where the value is loaded that
// we want to fix-up
BufferOffset offset;
void *target;
Relocation::Kind kind;
void fixOffset(ARMBuffer &m_buffer) {
offset = BufferOffset(offset.getOffset() + m_buffer.poolSizeBefore(offset.getOffset()));
}
RelativePatch(BufferOffset offset, void *target, Relocation::Kind kind)
: offset(offset),
target(target),
kind(kind)
RelativePatch(void *target, Relocation::Kind kind)
: target(target), kind(kind)
{ }
};
@ -1652,7 +1644,7 @@ class Assembler : public AssemblerShared
protected:
void addPendingJump(BufferOffset src, ImmPtr target, Relocation::Kind kind) {
enoughMemory_ &= jumps_.append(RelativePatch(src, target.value, kind));
enoughMemory_ &= jumps_.append(RelativePatch(target.value, kind));
if (kind == Relocation::JITCODE)
writeRelocation(src);
}

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

@ -1109,7 +1109,7 @@ Simulator::FlushICache(void *start_addr, size_t size)
IonSpewCont(IonSpew_CacheFlush, "[%p %zx]", start_addr, size);
if (!Simulator::ICacheCheckingEnabled)
return;
SimulatorRuntime *srt = Simulator::Current()->srt_;
SimulatorRuntime *srt = TlsPerThreadData.get()->simulatorRuntime();
AutoLockSimulatorRuntime alsr(srt);
js::jit::FlushICache(srt->icache(), start_addr, size);
}
@ -1188,14 +1188,12 @@ class Redirection
{
friend class SimulatorRuntime;
Redirection(void *nativeFunction, ABIFunctionType type)
Redirection(void *nativeFunction, ABIFunctionType type, SimulatorRuntime *srt)
: nativeFunction_(nativeFunction),
swiInstruction_(Assembler::AL | (0xf * (1 << 24)) | kCallRtRedirected),
type_(type),
next_(nullptr)
{
Simulator *sim = Simulator::Current();
SimulatorRuntime *srt = sim->srt_;
next_ = srt->redirection();
if (Simulator::ICacheCheckingEnabled)
FlushICache(srt->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
@ -1208,10 +1206,13 @@ class Redirection
ABIFunctionType type() const { return type_; }
static Redirection *Get(void *nativeFunction, ABIFunctionType type) {
Simulator *sim = Simulator::Current();
AutoLockSimulatorRuntime alsr(sim->srt_);
PerThreadData *pt = TlsPerThreadData.get();
SimulatorRuntime *srt = pt->simulatorRuntime();
AutoLockSimulatorRuntime alsr(srt);
Redirection *current = sim->srt_->redirection();
JS_ASSERT_IF(pt->simulator(), pt->simulator()->srt_ == srt);
Redirection *current = srt->redirection();
for (; current != nullptr; current = current->next_) {
if (current->nativeFunction_ == nativeFunction) {
MOZ_ASSERT(current->type() == type);
@ -1225,7 +1226,7 @@ class Redirection
__FILE__, __LINE__);
MOZ_CRASH();
}
new(redir) Redirection(nativeFunction, type);
new(redir) Redirection(nativeFunction, type, srt);
return redir;
}

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

@ -1278,7 +1278,7 @@ SimulatorRuntime::ICacheHasher::match(const Key &k, const Lookup &l)
void
Simulator::FlushICache(void *start_addr, size_t size)
{
SimulatorRuntime *srt = Simulator::Current()->srt_;
SimulatorRuntime *srt = TlsPerThreadData.get()->simulatorRuntime();
AutoLockSimulatorRuntime alsr(srt);
js::jit::FlushICache(srt->icache(), start_addr, size);
}
@ -1345,14 +1345,12 @@ class Redirection
{
friend class SimulatorRuntime;
Redirection(void* nativeFunction, ABIFunctionType type)
Redirection(void* nativeFunction, ABIFunctionType type, SimulatorRuntime *srt)
: nativeFunction_(nativeFunction),
swiInstruction_(kCallRedirInstr),
type_(type),
next_(nullptr)
{
Simulator *sim = Simulator::Current();
SimulatorRuntime *srt = sim->srt_;
next_ = srt->redirection();
if (Simulator::ICacheCheckingEnabled)
FlushICache(srt->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
@ -1365,10 +1363,13 @@ class Redirection
ABIFunctionType type() const { return type_; }
static Redirection *Get(void *nativeFunction, ABIFunctionType type) {
Simulator *sim = Simulator::Current();
AutoLockSimulatorRuntime alsr(sim->srt_);
PerThreadData *pt = TlsPerThreadData.get();
SimulatorRuntime *srt = pt->simulatorRuntime();
AutoLockSimulatorRuntime alsr(srt);
Redirection *current = sim->srt_->redirection();
JS_ASSERT_IF(pt->simulator(), pt->simulator()->srt_ == srt);
Redirection *current = srt->redirection();
for (; current != nullptr; current = current->next_) {
if (current->nativeFunction_ == nativeFunction) {
MOZ_ASSERT(current->type() == type);
@ -1382,7 +1383,7 @@ class Redirection
__FILE__, __LINE__);
MOZ_CRASH();
}
new(redir) Redirection(nativeFunction, type);
new(redir) Redirection(nativeFunction, type, srt);
return redir;
}

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

@ -47,7 +47,7 @@ PreWrap(JSContext *cx, JS::HandleObject scope, JS::HandleObject obj, unsigned fl
static JSObject *
Wrap(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj,
JS::HandleObject proto, JS::HandleObject parent, unsigned flags)
JS::HandleObject parent, unsigned flags)
{
return js::Wrapper::New(cx, obj, parent, &js::CrossCompartmentWrapper::singleton);
}

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

@ -34,6 +34,7 @@
#include "js/StructuredClone.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
#include "js/UbiNode.h"
#include "js/Utility.h"
#include "js/Value.h"
#include "js/Vector.h"

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

@ -758,8 +758,7 @@ typedef bool
*/
typedef JSObject *
(* JSWrapObjectCallback)(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj,
JS::HandleObject proto, JS::HandleObject parent,
unsigned flags);
JS::HandleObject parent, unsigned flags);
/*
* Callback used by the wrap hook to ask the embedding to prepare an object

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

@ -402,7 +402,6 @@ JSCompartment::wrap(JSContext *cx, MutableHandleObject obj, HandleObject existin
return true;
}
RootedObject proto(cx, TaggedProto::LazyProto);
RootedObject existing(cx, existingArg);
if (existing) {
// Is it possible to reuse |existing|?
@ -416,7 +415,7 @@ JSCompartment::wrap(JSContext *cx, MutableHandleObject obj, HandleObject existin
}
}
obj.set(cb->wrap(cx, existing, obj, proto, global, flags));
obj.set(cb->wrap(cx, existing, obj, global, flags));
if (!obj)
return false;

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

@ -2254,11 +2254,7 @@ DoMatchGlobal(JSContext *cx, CallArgs args, RegExpStatics *res, HandleLinearStri
// techniques from the spec to implement step 8f's loop.
// Step 8f.
#ifdef JS_YARR
MatchPair match;
#else
ScopedMatchPairs matches(&cx->tempLifoAlloc());
#endif
size_t charsLen = input->length();
const jschar *chars = input->chars();
RegExpShared &re = g.regExp();
@ -2268,11 +2264,7 @@ DoMatchGlobal(JSContext *cx, CallArgs args, RegExpStatics *res, HandleLinearStri
// Steps 8f(i-ii), minus "lastIndex" updates (see above).
size_t nextSearchIndex = searchIndex;
#ifdef JS_YARR
RegExpRunStatus status = re.executeMatchOnly(cx, chars, charsLen, &nextSearchIndex, match);
#else
RegExpRunStatus status = re.execute(cx, chars, charsLen, &nextSearchIndex, matches);
#endif
if (status == RegExpRunStatus_Error)
return false;
@ -2281,10 +2273,7 @@ DoMatchGlobal(JSContext *cx, CallArgs args, RegExpStatics *res, HandleLinearStri
break;
lastSuccessfulStart = searchIndex;
#ifndef JS_YARR
MatchPair &match = matches[0];
#endif
// Steps 8f(iii)(1-3).
searchIndex = match.isEmpty() ? nextSearchIndex + 1 : nextSearchIndex;
@ -2423,25 +2412,15 @@ js::str_search(JSContext *cx, unsigned argc, Value *vp)
/* Per ECMAv5 15.5.4.12 (5) The last index property is ignored and left unchanged. */
size_t i = 0;
#ifdef JS_YARR
MatchPair match;
RegExpRunStatus status = g.regExp().executeMatchOnly(cx, chars, length, &i, match);
#else
ScopedMatchPairs matches(&cx->tempLifoAlloc());
RegExpRunStatus status = g.regExp().execute(cx, chars, length, &i, matches);
#endif
if (status == RegExpRunStatus_Error)
return false;
if (status == RegExpRunStatus_Success)
res->updateLazily(cx, linearStr, &g.regExp(), 0);
#ifdef JS_YARR
JS_ASSERT_IF(status == RegExpRunStatus_Success_NotFound, match.start == -1);
args.rval().setInt32(match.start);
#else
args.rval().setInt32(status == RegExpRunStatus_Success_NotFound ? -1 : matches[0].start);
#endif
return true;
}
@ -3100,11 +3079,7 @@ StrReplaceRegexpRemove(JSContext *cx, HandleString str, RegExpShared &re, Mutabl
size_t charsLen = flatStr->length();
#ifdef JS_YARR
MatchPair match;
#else
ScopedMatchPairs matches(&cx->tempLifoAlloc());
#endif
size_t startIndex = 0; /* Index used for iterating through the string. */
size_t lastIndex = 0; /* Index after last successful match. */
size_t lazyIndex = 0; /* Index before last successful match. */
@ -3114,19 +3089,12 @@ StrReplaceRegexpRemove(JSContext *cx, HandleString str, RegExpShared &re, Mutabl
if (!CheckForInterrupt(cx))
return false;
#ifdef JS_YARR
RegExpRunStatus status = re.executeMatchOnly(cx, flatStr->chars(), charsLen, &startIndex, match);
#else
RegExpRunStatus status = re.execute(cx, flatStr->chars(), charsLen, &startIndex, matches);
#endif
if (status == RegExpRunStatus_Error)
return false;
if (status == RegExpRunStatus_Success_NotFound)
break;
#ifndef JS_YARR
MatchPair &match = matches[0];
#endif
/* Include the latest unmatched substring. */
if (size_t(match.start) > lastIndex) {

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

@ -145,12 +145,10 @@ JSObject *Wrapper::defaultProto = TaggedProto::LazyProto;
extern JSObject *
js::TransparentObjectWrapper(JSContext *cx, HandleObject existing, HandleObject obj,
HandleObject wrappedProto, HandleObject parent,
unsigned flags)
HandleObject parent, unsigned flags)
{
// Allow wrapping outer window proxies.
JS_ASSERT(!obj->is<WrapperObject>() || obj->getClass()->ext.innerObject);
JS_ASSERT(wrappedProto == TaggedProto::LazyProto);
return Wrapper::New(cx, obj, parent, &CrossCompartmentWrapper::singleton);
}

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

@ -245,8 +245,7 @@ class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
extern JSObject *
TransparentObjectWrapper(JSContext *cx, HandleObject existing, HandleObject obj,
HandleObject wrappedProto, HandleObject parent,
unsigned flags);
HandleObject parent, unsigned flags);
// Proxy family for wrappers. Public so that IsWrapper() can be fully inlined by
// jsfriendapi users.

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

@ -86,6 +86,8 @@ EXPORTS.js += [
'../public/StructuredClone.h',
'../public/TracingAPI.h',
'../public/TypeDecls.h',
'../public/UbiNode.h',
'../public/UbiNodeTraverse.h',
'../public/Utility.h',
'../public/Value.h',
'../public/Vector.h',
@ -123,6 +125,12 @@ UNIFIED_SOURCES += [
'gc/Tracer.cpp',
'gc/Verifier.cpp',
'gc/Zone.cpp',
'irregexp/RegExpAST.cpp',
'irregexp/RegExpEngine.cpp',
'irregexp/RegExpInterpreter.cpp',
'irregexp/RegExpMacroAssembler.cpp',
'irregexp/RegExpParser.cpp',
'irregexp/RegExpStack.cpp',
'jsalloc.cpp',
'jsapi.cpp',
'jsbool.cpp',
@ -191,6 +199,7 @@ UNIFIED_SOURCES += [
'vm/StructuredClone.cpp',
'vm/ThreadPool.cpp',
'vm/TypedArrayObject.cpp',
'vm/UbiNode.cpp',
'vm/Unicode.cpp',
'vm/Value.cpp',
'vm/WeakMapPtr.cpp',
@ -231,42 +240,9 @@ if CONFIG['ENABLE_TRACE_LOGGING']:
'vm/TraceLogging.cpp',
]
if CONFIG['ENABLE_YARR']:
UNIFIED_SOURCES += [
'yarr/PageBlock.cpp',
'yarr/YarrCanonicalizeUCS2.cpp',
'yarr/YarrInterpreter.cpp',
'yarr/YarrPattern.cpp',
'yarr/YarrSyntaxChecker.cpp',
]
if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [
'yarr/OSAllocatorWin.cpp',
]
else:
SOURCES += [
'yarr/OSAllocatorPosix.cpp',
]
if CONFIG['ENABLE_ION']:
SOURCES += [
'yarr/YarrJIT.cpp'
]
else:
UNIFIED_SOURCES += [
'irregexp/RegExpAST.cpp',
'irregexp/RegExpEngine.cpp',
'irregexp/RegExpInterpreter.cpp',
'irregexp/RegExpMacroAssembler.cpp',
'irregexp/RegExpParser.cpp',
'irregexp/RegExpStack.cpp',
]
if CONFIG['ENABLE_ION']:
UNIFIED_SOURCES += [
'irregexp/NativeRegExpMacroAssembler.cpp',
]
if CONFIG['ENABLE_ION']:
UNIFIED_SOURCES += [
'irregexp/NativeRegExpMacroAssembler.cpp',
'jit/AliasAnalysis.cpp',
'jit/AsmJS.cpp',
'jit/AsmJSLink.cpp',

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

@ -83,6 +83,10 @@ var Match =
return (x !== null) && (typeof x === "object");
}
function isFunction(x) {
return typeof x === "function";
}
function isArrayLike(x) {
return isObject(x) && ("length" in x);
}
@ -134,6 +138,15 @@ var Match =
return true;
}
function matchFunction(act, exp) {
if (!isFunction(act))
throw new MatchError("expected function, got " + quote(act));
if (act !== exp)
throw new MatchError("expected function: " + exp +
"\nbut got different function: " + act);
}
function matchArray(act, exp) {
if (!isObject(act) || !("length" in act))
throw new MatchError("expected array-like object, got " + quote(act));
@ -166,6 +179,9 @@ var Match =
if (isArrayLike(exp))
return matchArray(act, exp);
if (isFunction(exp))
return matchFunction(act, exp);
return matchObject(act, exp);
}

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

@ -28,3 +28,4 @@ user_pref("browser.safebrowsing.malware.enabled", false);
user_pref("browser.snippets.enabled", false);
user_pref("browser.snippets.syncPromo.enabled", false);
user_pref("general.useragent.updates.enabled", false);
user_pref("browser.webapps.checkForUpdates", 0);

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

@ -150,28 +150,6 @@ class VectorMatchPairs : public MatchPairs
bool allocOrExpandArray(size_t pairCount);
};
/*
* Passes either MatchPair or MatchPairs through ExecuteRegExp()
* to avoid duplication of generic code.
*/
struct MatchConduit
{
union {
MatchPair *pair;
MatchPairs *pairs;
} u;
bool isPair;
explicit MatchConduit(MatchPair *pair) {
isPair = true;
u.pair = pair;
}
explicit MatchConduit(MatchPairs *pairs) {
isPair = false;
u.pairs = pairs;
}
};
} /* namespace js */
#endif /* vm_MatchPairs_h */

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

@ -11,17 +11,12 @@
#include "jsstr.h"
#include "frontend/TokenStream.h"
#ifndef JS_YARR
#include "irregexp/RegExpParser.h"
#endif
#include "vm/MatchPairs.h"
#include "vm/RegExpStatics.h"
#include "vm/StringBuffer.h"
#include "vm/TraceLogging.h"
#include "vm/Xdr.h"
#ifdef JS_YARR
#include "yarr/YarrSyntaxChecker.h"
#endif
#include "jsobjinlines.h"
@ -306,10 +301,6 @@ RegExpObject *
RegExpObject::createNoStatics(ExclusiveContext *cx, HandleAtom source, RegExpFlag flags,
TokenStream *tokenStream, LifoAlloc &alloc)
{
#ifdef JS_YARR
if (!RegExpShared::checkSyntax(cx, tokenStream, source))
return nullptr;
#else // JS_YARR
Maybe<CompileOptions> dummyOptions;
Maybe<TokenStream> dummyTokenStream;
if (!tokenStream) {
@ -322,7 +313,6 @@ RegExpObject::createNoStatics(ExclusiveContext *cx, HandleAtom source, RegExpFla
if (!irregexp::ParsePatternSyntax(*tokenStream, alloc, source))
return nullptr;
#endif
RegExpObjectBuilder builder(cx);
return builder.build(source, flags);
@ -437,25 +427,13 @@ RegExpObject::toString(JSContext *cx) const
/* RegExpShared */
RegExpShared::RegExpShared(JSAtom *source, RegExpFlag flags)
: source(source), flags(flags), parenCount(0), canStringMatch(false), marked_(false)
{
#ifdef JS_YARR
bytecode = nullptr;
#else
byteCode = nullptr;
#endif
}
: source(source), flags(flags), parenCount(0), canStringMatch(false), marked_(false),
byteCode(nullptr)
{}
RegExpShared::~RegExpShared()
{
#ifdef JS_YARR
#ifdef JS_ION
codeBlock.release();
#endif
js_delete<BytecodePattern>(bytecode);
#else // JS_YARR
js_free(byteCode);
#endif // JS_YARR
for (size_t i = 0; i < tables.length(); i++)
js_delete(tables[i]);
@ -470,68 +448,21 @@ RegExpShared::trace(JSTracer *trc)
if (source)
MarkString(trc, &source, "RegExpShared source");
#if !defined(JS_YARR) && defined(JS_ION)
#ifdef JS_ION
if (jitCode)
MarkJitCode(trc, &jitCode, "RegExpShared code");
#endif
}
#ifdef JS_YARR
void
RegExpShared::reportYarrError(ExclusiveContext *cx, TokenStream *ts, ErrorCode error)
{
switch (error) {
case JSC::Yarr::NoError:
MOZ_ASSUME_UNREACHABLE("Called reportYarrError with value for no error");
#define COMPILE_EMSG(__code, __msg) \
case JSC::Yarr::__code: \
if (ts) \
ts->reportError(__msg); \
else \
JS_ReportErrorFlagsAndNumberUC(cx->asJSContext(), \
JSREPORT_ERROR, js_GetErrorMessage, nullptr, __msg); \
return
COMPILE_EMSG(PatternTooLarge, JSMSG_REGEXP_TOO_COMPLEX);
COMPILE_EMSG(QuantifierOutOfOrder, JSMSG_BAD_QUANTIFIER);
COMPILE_EMSG(QuantifierWithoutAtom, JSMSG_BAD_QUANTIFIER);
COMPILE_EMSG(MissingParentheses, JSMSG_MISSING_PAREN);
COMPILE_EMSG(ParenthesesUnmatched, JSMSG_UNMATCHED_RIGHT_PAREN);
COMPILE_EMSG(ParenthesesTypeInvalid, JSMSG_BAD_QUANTIFIER); /* "(?" with bad next char */
COMPILE_EMSG(CharacterClassUnmatched, JSMSG_BAD_CLASS_RANGE);
COMPILE_EMSG(CharacterClassInvalidRange, JSMSG_BAD_CLASS_RANGE);
COMPILE_EMSG(CharacterClassOutOfOrder, JSMSG_BAD_CLASS_RANGE);
COMPILE_EMSG(QuantifierTooLarge, JSMSG_BAD_QUANTIFIER);
COMPILE_EMSG(EscapeUnterminated, JSMSG_TRAILING_SLASH);
COMPILE_EMSG(RuntimeError, JSMSG_REGEXP_RUNTIME_ERROR);
#undef COMPILE_EMSG
default:
MOZ_ASSUME_UNREACHABLE("Unknown Yarr error code");
}
}
bool
RegExpShared::checkSyntax(ExclusiveContext *cx, TokenStream *tokenStream, JSLinearString *source)
{
ErrorCode error = JSC::Yarr::checkSyntax(*source);
if (error == JSC::Yarr::NoError)
return true;
reportYarrError(cx, tokenStream, error);
return false;
}
#endif // JS_YARR
bool
RegExpShared::compile(JSContext *cx, bool matchOnly, const jschar *sampleChars, size_t sampleLength)
RegExpShared::compile(JSContext *cx, const jschar *sampleChars, size_t sampleLength)
{
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
AutoTraceLog logCompile(logger, TraceLogger::IrregexpCompile);
if (!sticky()) {
RootedAtom pattern(cx, source);
return compile(cx, pattern, matchOnly, sampleChars, sampleLength);
return compile(cx, pattern, sampleChars, sampleLength);
}
/*
@ -554,11 +485,11 @@ RegExpShared::compile(JSContext *cx, bool matchOnly, const jschar *sampleChars,
if (!fakeySource)
return false;
return compile(cx, fakeySource, matchOnly, sampleChars, sampleLength);
return compile(cx, fakeySource, sampleChars, sampleLength);
}
bool
RegExpShared::compile(JSContext *cx, HandleAtom pattern, bool matchOnly, const jschar *sampleChars, size_t sampleLength)
RegExpShared::compile(JSContext *cx, HandleAtom pattern, const jschar *sampleChars, size_t sampleLength)
{
if (!ignoreCase() && !StringHasRegExpMetaChars(pattern->chars(), pattern->length())) {
canStringMatch = true;
@ -566,47 +497,6 @@ RegExpShared::compile(JSContext *cx, HandleAtom pattern, bool matchOnly, const j
return true;
}
#ifdef JS_YARR
ErrorCode yarrError;
YarrPattern yarrPattern(*pattern, ignoreCase(), multiline(), &yarrError);
if (yarrError) {
reportYarrError(cx, nullptr, yarrError);
return false;
}
this->parenCount = yarrPattern.m_numSubpatterns;
#ifdef JS_ION
if (isJITRuntimeEnabled(cx) && !yarrPattern.m_containsBackreferences) {
JSC::ExecutableAllocator *execAlloc = cx->runtime()->getExecAlloc(cx);
if (!execAlloc)
return false;
JSGlobalData globalData(execAlloc);
YarrJITCompileMode compileMode = matchOnly ? JSC::Yarr::MatchOnly
: JSC::Yarr::IncludeSubpatterns;
jitCompile(yarrPattern, JSC::Yarr::Char16, &globalData, codeBlock, compileMode);
/* Unset iff the Yarr JIT compilation was successful. */
if (!codeBlock.isFallBack())
return true;
}
codeBlock.setFallBack(true);
#endif
WTF::BumpPointerAllocator *bumpAlloc = cx->runtime()->getBumpPointerAllocator(cx);
if (!bumpAlloc) {
js_ReportOutOfMemory(cx);
return false;
}
bytecode = byteCompile(yarrPattern, bumpAlloc).get();
#else // JS_YARR
JS_ASSERT(!matchOnly);
CompileOptions options(cx);
TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
@ -632,29 +522,17 @@ RegExpShared::compile(JSContext *cx, HandleAtom pattern, bool matchOnly, const j
byteCode = code.byteCode;
#endif // JS_YARR
return true;
}
bool
RegExpShared::compileIfNecessary(JSContext *cx, const jschar *sampleChars, size_t sampleLength)
{
if (isCompiled(false) || canStringMatch)
if (isCompiled() || canStringMatch)
return true;
return compile(cx, false, sampleChars, sampleLength);
return compile(cx, sampleChars, sampleLength);
}
#ifdef JS_YARR
bool
RegExpShared::compileMatchOnlyIfNecessary(JSContext *cx)
{
if (isCompiled(true) || canStringMatch)
return true;
return compile(cx, true, nullptr, 0);
}
#endif // JS_YARR
RegExpRunStatus
RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length,
size_t *lastIndex, MatchPairs &matches)
@ -684,10 +562,8 @@ RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length,
start = 0;
}
#ifndef JS_YARR
// Reset the Irregexp backtrack stack if it grows during execution.
irregexp::RegExpStackScope stackScope(cx->runtime());
#endif
if (canStringMatch) {
int res = StringFindPattern(chars+start, length-start, source->chars(), source->length());
@ -703,39 +579,6 @@ RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length,
return RegExpRunStatus_Success;
}
#ifdef JS_YARR
unsigned result;
// Yarr wants plain integers for its output buffer (whatever).
JS_STATIC_ASSERT(sizeof(int32_t) == sizeof(int));
JS_STATIC_ASSERT(sizeof(int32_t) == sizeof(unsigned));
#ifdef JS_ION
if (codeBlock.isFallBack()) {
AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret);
result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, (unsigned *) matches.pairsRaw());
} else {
AutoTraceLog logJIT(logger, TraceLogger::YarrJIT);
result = codeBlock.execute(chars, start, length, (int *) matches.pairsRaw()).start;
}
#else // JS_ION
{
AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret);
result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, (unsigned *) matches.pairsRaw());
}
#endif // JS_ION
if (result == JSC::Yarr::offsetError) {
reportYarrError(cx, nullptr, JSC::Yarr::RuntimeError);
return RegExpRunStatus_Error;
}
if (result == JSC::Yarr::offsetNoMatch)
return RegExpRunStatus_Success_NotFound;
#else // JS_YARR
if (hasByteCode()) {
AutoTraceLog logInterpreter(logger, TraceLogger::IrregexpExecute);
RegExpRunStatus result =
@ -786,111 +629,19 @@ RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length,
MOZ_CRASH();
#endif // JS_ION
#endif // JS_YARR
matches.displace(displacement);
matches.checkAgainst(origLength);
*lastIndex = matches[0].limit;
return RegExpRunStatus_Success;
}
#ifdef JS_YARR
RegExpRunStatus
RegExpShared::executeMatchOnly(JSContext *cx, const jschar *chars, size_t length,
size_t *lastIndex, MatchPair &match)
{
TraceLogger *logger = js::TraceLoggerForMainThread(cx->runtime());
/* Compile the code at point-of-use. */
if (!compileMatchOnlyIfNecessary(cx))
return RegExpRunStatus_Error;
#ifdef DEBUG
const size_t origLength = length;
#endif
size_t start = *lastIndex;
size_t displacement = 0;
if (sticky()) {
displacement = start;
chars += displacement;
length -= displacement;
start = 0;
}
if (canStringMatch) {
int res = StringFindPattern(chars+start, length-start, source->chars(), source->length());
if (res == -1)
return RegExpRunStatus_Success_NotFound;
match = MatchPair(res + start, res + start + source->length());
match.displace(displacement);
*lastIndex = match.limit;
return RegExpRunStatus_Success;
}
#ifdef JS_ION
if (!codeBlock.isFallBack()) {
AutoTraceLog logJIT(logger, TraceLogger::YarrJIT);
MatchResult result = codeBlock.execute(chars, start, length);
if (!result)
return RegExpRunStatus_Success_NotFound;
match = MatchPair(result.start, result.end);
match.displace(displacement);
*lastIndex = match.limit;
return RegExpRunStatus_Success;
}
#endif
/*
* The JIT could not be used, so fall back to the Yarr interpreter.
* Unfortunately, the interpreter does not have a MatchOnly mode, so a
* temporary output vector must be provided.
*/
JS_ASSERT(hasBytecode());
ScopedMatchPairs matches(&cx->tempLifoAlloc());
if (!matches.initArray(pairCount()))
return RegExpRunStatus_Error;
unsigned result;
{
AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret);
result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, (unsigned *) matches.pairsRaw());
}
if (result == JSC::Yarr::offsetError) {
reportYarrError(cx, nullptr, JSC::Yarr::RuntimeError);
return RegExpRunStatus_Error;
}
if (result == JSC::Yarr::offsetNoMatch)
return RegExpRunStatus_Success_NotFound;
match = MatchPair(result, matches[0].limit);
match.displace(displacement);
#ifdef DEBUG
matches.displace(displacement);
matches.checkAgainst(origLength);
#endif
*lastIndex = match.limit;
return RegExpRunStatus_Success;
}
#endif // JS_YARR
size_t
RegExpShared::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
size_t n = mallocSizeOf(this);
#ifndef JS_YARR
if (byteCode)
n += mallocSizeOf(byteCode);
#endif
n += tables.sizeOfExcludingThis(mallocSizeOf);
for (size_t i = 0; i < tables.length(); i++)
@ -979,7 +730,7 @@ RegExpCompartment::sweep(JSRuntime *rt)
// the RegExpShared if it was accidentally marked earlier but wasn't
// marked by the current trace.
bool keep = shared->marked() && !IsStringAboutToBeFinalized(shared->source.unsafeGet());
#if !defined(JS_YARR) && defined(JS_ION)
#ifdef JS_ION
if (keep && shared->jitCode)
keep = !IsJitCodeAboutToBeFinalized(shared->jitCode.unsafeGet());
#endif

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

@ -17,13 +17,6 @@
#include "gc/Zone.h"
#include "vm/Shape.h"
#ifdef JS_YARR
#ifdef JS_ION
#include "yarr/YarrJIT.h"
#endif
#include "yarr/YarrInterpreter.h"
#endif // JS_YARR
/*
* JavaScript Regular Expressions
*
@ -111,17 +104,6 @@ class RegExpShared
typedef frontend::TokenStream TokenStream;
#ifdef JS_YARR
typedef JSC::Yarr::BytecodePattern BytecodePattern;
typedef JSC::Yarr::ErrorCode ErrorCode;
typedef JSC::Yarr::YarrPattern YarrPattern;
#ifdef JS_ION
typedef JSC::Yarr::JSGlobalData JSGlobalData;
typedef JSC::Yarr::YarrCodeBlock YarrCodeBlock;
typedef JSC::Yarr::YarrJITCompileMode YarrJITCompileMode;
#endif
#endif
/* Source to the RegExp, for lazy compilation. */
HeapPtrAtom source;
@ -130,69 +112,28 @@ class RegExpShared
bool canStringMatch;
bool marked_;
#ifdef JS_YARR
#ifdef JS_ION
/* Note: Native code is valid only if |codeBlock.isFallBack() == false|. */
YarrCodeBlock codeBlock;
#endif
BytecodePattern *bytecode;
#else // JS_YARR
#ifdef JS_ION
HeapPtrJitCode jitCode;
#endif
uint8_t *byteCode;
#endif // JS_YARR
// Tables referenced by JIT code.
Vector<uint8_t *, 0, SystemAllocPolicy> tables;
/* Internal functions. */
bool compile(JSContext *cx, bool matchOnly, const jschar *sampleChars, size_t sampleLength);
bool compile(JSContext *cx, HandleAtom pattern, bool matchOnly, const jschar *sampleChars, size_t sampleLength);
bool compile(JSContext *cx, const jschar *sampleChars, size_t sampleLength);
bool compile(JSContext *cx, HandleAtom pattern, const jschar *sampleChars, size_t sampleLength);
bool compileIfNecessary(JSContext *cx, const jschar *sampleChars, size_t sampleLength);
#ifdef JS_YARR
bool compileMatchOnlyIfNecessary(JSContext *cx);
#endif
public:
RegExpShared(JSAtom *source, RegExpFlag flags);
~RegExpShared();
#ifdef JS_YARR
/* Static functions to expose some Yarr logic. */
// This function should be deleted once bad Android platforms phase out. See bug 604774.
static bool isJITRuntimeEnabled(JSContext *cx) {
#ifdef JS_ION
# if defined(ANDROID)
return !cx->jitIsBroken;
# else
return true;
# endif
#else
return false;
#endif
}
static void reportYarrError(ExclusiveContext *cx, TokenStream *ts, ErrorCode error);
static bool checkSyntax(ExclusiveContext *cx, TokenStream *tokenStream, JSLinearString *source);
#endif // JS_YARR
/* Primary interface: run this regular expression on the given string. */
RegExpRunStatus execute(JSContext *cx, const jschar *chars, size_t length,
size_t *lastIndex, MatchPairs &matches);
#ifdef JS_YARR
/* Run the regular expression without collecting matches, for test(). */
RegExpRunStatus executeMatchOnly(JSContext *cx, const jschar *chars, size_t length,
size_t *lastIndex, MatchPair &match);
#endif
// Register a table with this RegExpShared, and take ownership.
bool addTable(uint8_t *table) {
return tables.append(table);
@ -201,7 +142,7 @@ class RegExpShared
/* Accessors */
size_t getParenCount() const {
JS_ASSERT(isCompiled(true) || isCompiled(false) || canStringMatch);
JS_ASSERT(isCompiled() || canStringMatch);
return parenCount;
}
@ -215,24 +156,6 @@ class RegExpShared
bool multiline() const { return flags & MultilineFlag; }
bool sticky() const { return flags & StickyFlag; }
#ifdef JS_YARR
bool hasCode(bool matchOnly) const {
#ifdef JS_ION
return matchOnly ? codeBlock.has16BitCodeMatchOnly() : codeBlock.has16BitCode();
#else
return false;
#endif
}
bool hasBytecode() const {
return bytecode != nullptr;
}
bool isCompiled(bool matchOnly) const {
return hasBytecode() || hasCode(matchOnly);
}
#else // JS_YARR
bool hasJitCode() const {
#ifdef JS_ION
return jitCode != nullptr;
@ -244,12 +167,10 @@ class RegExpShared
return byteCode != nullptr;
}
bool isCompiled(bool matchOnly) const {
bool isCompiled() const {
return hasJitCode() || hasByteCode();
}
#endif // JS_YARR
void trace(JSTracer *trc);
bool marked() const { return marked_; }

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

@ -39,9 +39,6 @@
#include "jit/PcScriptCache.h"
#include "js/MemoryMetrics.h"
#include "js/SliceBudget.h"
#ifdef JS_YARR
#include "yarr/BumpPointerAllocator.h"
#endif
#include "jscntxtinlines.h"
#include "jsgcinlines.h"
@ -110,10 +107,8 @@ PerThreadData::init()
if (!dtoaState)
return false;
#ifndef JS_YARR
if (!regexpStack.init())
return false;
#endif
return true;
}
@ -157,9 +152,6 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime)
tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
freeLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
execAlloc_(nullptr),
#ifdef JS_YARR
bumpAlloc_(nullptr),
#endif
jitRuntime_(nullptr),
selfHostingGlobal_(nullptr),
nativeStackBase(0),
@ -439,9 +431,6 @@ JSRuntime::~JSRuntime()
atomsCompartment_ = nullptr;
js_free(defaultLocale);
#ifdef JS_YARR
js_delete(bumpAlloc_);
#endif
js_delete(mathCache_);
#ifdef JS_ION
js_delete(jitRuntime_);
@ -518,10 +507,6 @@ JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Runtim
rtSizes->temporary += tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
#ifdef JS_YARR
rtSizes->regexpData += bumpAlloc_ ? bumpAlloc_->sizeOfNonHeapData() : 0;
#endif
rtSizes->interpreterStack += interpreterStack_.sizeOfExcludingThis(mallocSizeOf);
rtSizes->mathCache += mathCache_ ? mathCache_->sizeOfIncludingThis(mallocSizeOf) : 0;
@ -604,22 +589,6 @@ JSRuntime::createExecutableAllocator(JSContext *cx)
return execAlloc_;
}
#ifdef JS_YARR
WTF::BumpPointerAllocator *
JSRuntime::createBumpPointerAllocator(JSContext *cx)
{
JS_ASSERT(!bumpAlloc_);
JS_ASSERT(cx->runtime() == this);
bumpAlloc_ = js_new<WTF::BumpPointerAllocator>();
if (!bumpAlloc_)
js_ReportOutOfMemory(cx);
return bumpAlloc_;
}
#endif // JS_YARR
MathCache *
JSRuntime::createMathCache(JSContext *cx)
{

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

@ -28,9 +28,7 @@
#include "frontend/ParseMaps.h"
#include "gc/GCRuntime.h"
#include "gc/Tracer.h"
#ifndef JS_YARR
#include "irregexp/RegExpStack.h"
#endif
#ifdef XP_MACOSX
# include "jit/AsmJSSignalHandlers.h"
#endif
@ -75,10 +73,6 @@ js_ReportOverRecursed(js::ThreadSafeContext *cx);
namespace JSC { class ExecutableAllocator; }
#ifdef JS_YARR
namespace WTF { class BumpPointerAllocator; }
#endif
namespace js {
class Activation;
@ -499,10 +493,8 @@ class PerThreadData : public PerThreadDataFriendFields
inline void setJitStackLimit(uintptr_t limit);
#ifndef JS_YARR
// Information about the heap allocated backtrack stack used by RegExp JIT code.
irregexp::RegExpStack regexpStack;
#endif
#ifdef JS_TRACE_LOGGING
TraceLogger *traceLogger;
@ -610,10 +602,21 @@ class PerThreadData : public PerThreadDataFriendFields
{
JS_ASSERT(!pt->runtime_);
pt->runtime_ = rt;
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
// The simulator has a pointer to its SimulatorRuntime, but helper threads
// don't have a simulator as they don't run JIT code so this pointer need not
// be updated. All the paths that the helper threads use access the
// SimulatorRuntime via the PerThreadData.
JS_ASSERT(!pt->simulator_);
#endif
}
~AutoEnterRuntime() {
pt->runtime_ = nullptr;
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
// Check that helper threads have not run JIT code and/or added a simulator.
JS_ASSERT(!pt->simulator_);
#endif
}
};
@ -809,9 +812,6 @@ struct JSRuntime : public JS::shadow::Runtime,
* thread-data level.
*/
JSC::ExecutableAllocator *execAlloc_;
#ifdef JS_YARR
WTF::BumpPointerAllocator *bumpAlloc_;
#endif
js::jit::JitRuntime *jitRuntime_;
/*
@ -824,9 +824,6 @@ struct JSRuntime : public JS::shadow::Runtime,
js::InterpreterStack interpreterStack_;
JSC::ExecutableAllocator *createExecutableAllocator(JSContext *cx);
#ifdef JS_YARR
WTF::BumpPointerAllocator *createBumpPointerAllocator(JSContext *cx);
#endif
js::jit::JitRuntime *createJitRuntime(JSContext *cx);
public:
@ -840,11 +837,6 @@ struct JSRuntime : public JS::shadow::Runtime,
JSC::ExecutableAllocator *maybeExecAlloc() {
return execAlloc_;
}
#ifdef JS_YARR
WTF::BumpPointerAllocator *getBumpPointerAllocator(JSContext *cx) {
return bumpAlloc_ ? bumpAlloc_ : createBumpPointerAllocator(cx);
}
#endif
js::jit::JitRuntime *getJitRuntime(JSContext *cx) {
return jitRuntime_ ? jitRuntime_ : createJitRuntime(cx);
}

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

@ -832,14 +832,8 @@ TraceLogging::lazyInit()
enabledTextIds[TraceLogger::ParserCompileFunction] = true;
enabledTextIds[TraceLogger::ParserCompileLazy] = true;
enabledTextIds[TraceLogger::ParserCompileScript] = true;
#ifdef JS_YARR
enabledTextIds[TraceLogger::YarrCompile] = true;
enabledTextIds[TraceLogger::YarrInterpret] = true;
enabledTextIds[TraceLogger::YarrJIT] = true;
#else
enabledTextIds[TraceLogger::IrregexpCompile] = true;
enabledTextIds[TraceLogger::IrregexpExecute] = true;
#endif
}
if (ContainsFlag(env, "IonCompiler") || strlen(env) == 0) {

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