зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
b0b24241b4
|
@ -50,7 +50,7 @@ let inputTests = [
|
|||
{
|
||||
input: "testDOMException()",
|
||||
output: 'DOMException [SyntaxError: "An invalid or illegal string was specified"',
|
||||
printOutput: '[Exception... "An invalid or illegal string was specified"',
|
||||
printOutput: '[object XrayWrapper [object DOMException]]"',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "SyntaxError",
|
||||
},
|
||||
|
|
|
@ -44,8 +44,9 @@ else
|
|||
;;
|
||||
esac
|
||||
ac_add_options "--with-compiler-wrapper=python2.7 $topsrcdir/sccache/sccache.py"
|
||||
mk_add_options MOZ_PREFLIGHT+=build/sccache.mk
|
||||
mk_add_options MOZ_POSTFLIGHT+=build/sccache.mk
|
||||
mk_add_options MOZ_PREFLIGHT_ALL+=build/sccache.mk
|
||||
mk_add_options MOZ_POSTFLIGHT_ALL+=build/sccache.mk
|
||||
UPLOAD_EXTRA_FILES="sccache.log.gz"
|
||||
case "$platform" in
|
||||
win*)
|
||||
# sccache supports a special flag to create depfiles.
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
preflight:
|
||||
# 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/.
|
||||
|
||||
ifdef OBJDIR
|
||||
BASE_DIR = $(OBJDIR)
|
||||
else
|
||||
# OSX Universal builds only do upload in the first MOZ_BUILD_PROJECTS
|
||||
BASE_DIR = $(MOZ_OBJDIR)/$(firstword $(MOZ_BUILD_PROJECTS))
|
||||
endif
|
||||
|
||||
preflight_all:
|
||||
# Terminate any sccache server that might still be around
|
||||
-python2.7 $(TOPSRCDIR)/sccache/sccache.py > /dev/null 2>&1
|
||||
|
||||
postflight:
|
||||
postflight_all:
|
||||
# Terminate sccache server. This prints sccache stats.
|
||||
-python2.7 $(TOPSRCDIR)/sccache/sccache.py
|
||||
-python2.7 $(TOPSRCDIR)/sccache/sccache.py 2>&1 | gzip > $(BASE_DIR)/dist/sccache.log.gz
|
||||
|
|
|
@ -11,7 +11,7 @@ interface nsIChannel;
|
|||
interface nsIDocShell;
|
||||
interface nsIDomainPolicy;
|
||||
|
||||
[scriptable, uuid(4c087cc3-e0cc-4ec3-88df-8d68f3023b45)]
|
||||
[scriptable, uuid(2565769a-eaec-47a1-a076-605f5294d286)]
|
||||
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||
{
|
||||
/**
|
||||
|
@ -99,12 +99,6 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
[noscript,notxpcom] boolean scriptAllowed(in JSObjectPtr aGlobal);
|
||||
|
||||
///////////////// Principals ///////////////////////
|
||||
/**
|
||||
* Return the principal of the innermost frame of the currently
|
||||
* executing script. Will return null if there is no script
|
||||
* currently executing.
|
||||
*/
|
||||
[noscript] nsIPrincipal getSubjectPrincipal();
|
||||
|
||||
/**
|
||||
* Return the all-powerful system principal.
|
||||
|
@ -150,12 +144,6 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
*/
|
||||
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
|
||||
|
||||
/**
|
||||
* Returns true if the principal of the currently running script is the
|
||||
* system principal, false otherwise.
|
||||
*/
|
||||
[noscript] boolean subjectPrincipalIsSystem();
|
||||
|
||||
/**
|
||||
* Returns OK if aJSContext and target have the same "origin"
|
||||
* (scheme, host, and port).
|
||||
|
@ -193,14 +181,6 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
}
|
||||
%}
|
||||
|
||||
/**
|
||||
* Same as getSubjectPrincipal(), only faster. cx must *never* be
|
||||
* passed null, and it must be the context on the top of the
|
||||
* context stack. Does *not* reference count the returned
|
||||
* principal.
|
||||
*/
|
||||
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipal(in JSContextPtr cx);
|
||||
|
||||
const unsigned long NO_APP_ID = 0;
|
||||
const unsigned long UNKNOWN_APP_ID = 4294967295; // UINT32_MAX
|
||||
const unsigned long SAFEBROWSING_APP_ID = 4294967294; // UINT32_MAX - 1
|
||||
|
|
|
@ -52,6 +52,9 @@ public:
|
|||
static nsScriptSecurityManager*
|
||||
GetScriptSecurityManager();
|
||||
|
||||
// Invoked exactly once, by XPConnect.
|
||||
static void InitStatics();
|
||||
|
||||
static nsSystemPrincipal*
|
||||
SystemPrincipalSingletonConstructor();
|
||||
|
||||
|
@ -118,11 +121,6 @@ private:
|
|||
// should error out at that point.
|
||||
static nsIPrincipal* doGetObjectPrincipal(JSObject* obj);
|
||||
|
||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no JS running.
|
||||
nsIPrincipal*
|
||||
doGetSubjectPrincipal(nsresult* rv);
|
||||
|
||||
nsresult
|
||||
GetCodebasePrincipalInternal(nsIURI* aURI, uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
|
@ -132,12 +130,6 @@ private:
|
|||
CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
|
||||
nsIPrincipal** result);
|
||||
|
||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no script for the
|
||||
// context. Callers MUST pass in a non-null rv here.
|
||||
nsIPrincipal*
|
||||
GetSubjectPrincipal(JSContext* cx, nsresult* rv);
|
||||
|
||||
nsresult
|
||||
Init();
|
||||
|
||||
|
|
|
@ -81,11 +81,7 @@ bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
|
|||
bool
|
||||
nsScriptSecurityManager::SubjectIsPrivileged()
|
||||
{
|
||||
JSContext *cx = GetCurrentJSContext();
|
||||
if (cx && xpc::IsUniversalXPConnectEnabled(cx))
|
||||
return true;
|
||||
bool isSystem = false;
|
||||
return NS_SUCCEEDED(SubjectPrincipalIsSystem(&isSystem)) && isSystem;
|
||||
return nsContentUtils::IsCallerChrome();
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
|
@ -318,20 +314,6 @@ nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsIPrincipal *)
|
||||
nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext *cx)
|
||||
{
|
||||
NS_ASSERTION(cx == GetCurrentJSContext(),
|
||||
"Uh, cx is not the current JS context!");
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIPrincipal *principal = GetSubjectPrincipal(cx, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return nullptr;
|
||||
|
||||
return principal;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// nsScriptSecurityManager //
|
||||
/////////////////////////////
|
||||
|
@ -354,26 +336,10 @@ NS_IMPL_ISUPPORTS(nsScriptSecurityManager,
|
|||
bool
|
||||
nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
|
||||
{
|
||||
// Get the security manager
|
||||
nsScriptSecurityManager *ssm =
|
||||
nsScriptSecurityManager::GetScriptSecurityManager();
|
||||
|
||||
NS_ASSERTION(ssm, "Failed to get security manager service");
|
||||
if (!ssm)
|
||||
return false;
|
||||
|
||||
nsresult rv;
|
||||
nsIPrincipal* subjectPrincipal = ssm->GetSubjectPrincipal(cx, &rv);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get nsIPrincipal from js context");
|
||||
if (NS_FAILED(rv))
|
||||
return false; // Not just absence of principal, but failure.
|
||||
|
||||
if (!subjectPrincipal)
|
||||
return true;
|
||||
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::GetSubjectPrincipal();
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
nsresult rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get CSP from principal.");
|
||||
|
||||
// don't do anything unless there's a CSP
|
||||
|
@ -424,27 +390,10 @@ NS_IMETHODIMP
|
|||
nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
|
||||
nsIURI* aTargetURI)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Get a context if necessary
|
||||
if (!cx)
|
||||
{
|
||||
cx = GetCurrentJSContext();
|
||||
if (!cx)
|
||||
return NS_OK; // No JS context, so allow access
|
||||
}
|
||||
MOZ_ASSERT_IF(cx, cx == nsContentUtils::GetCurrentJSContext());
|
||||
|
||||
// Get a principal from the context
|
||||
nsIPrincipal* sourcePrincipal = GetSubjectPrincipal(cx, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!sourcePrincipal)
|
||||
{
|
||||
NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal* sourcePrincipal = nsContentUtils::GetSubjectPrincipal();
|
||||
if (sourcePrincipal == mSystemPrincipal)
|
||||
{
|
||||
// This is a system (chrome) script, so allow access
|
||||
|
@ -520,17 +469,10 @@ NS_IMETHODIMP
|
|||
nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI)
|
||||
{
|
||||
// Get principal of currently executing script.
|
||||
nsresult rv;
|
||||
nsIPrincipal* principal = GetSubjectPrincipal(cx, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Native code can load all URIs.
|
||||
if (!principal)
|
||||
return NS_OK;
|
||||
|
||||
rv = CheckLoadURIWithPrincipal(principal, aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
nsIPrincipal* principal = nsContentUtils::GetSubjectPrincipal();
|
||||
nsresult rv = CheckLoadURIWithPrincipal(principal, aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// OK to load
|
||||
return NS_OK;
|
||||
|
@ -939,28 +881,6 @@ nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal)
|
|||
}
|
||||
|
||||
///////////////// Principals ///////////////////////
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal **aSubjectPrincipal)
|
||||
{
|
||||
nsresult rv;
|
||||
*aSubjectPrincipal = doGetSubjectPrincipal(&rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
NS_IF_ADDREF(*aSubjectPrincipal);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::doGetSubjectPrincipal(nsresult* rv)
|
||||
{
|
||||
NS_PRECONDITION(rv, "Null out param");
|
||||
JSContext *cx = GetCurrentJSContext();
|
||||
if (!cx)
|
||||
{
|
||||
*rv = NS_OK;
|
||||
return nullptr;
|
||||
}
|
||||
return GetSubjectPrincipal(cx, rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
|
||||
|
@ -970,31 +890,6 @@ nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::SubjectPrincipalIsSystem(bool* aIsSystem)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSystem);
|
||||
*aIsSystem = false;
|
||||
|
||||
if (!mSystemPrincipal)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subject;
|
||||
nsresult rv = GetSubjectPrincipal(getter_AddRefs(subject));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if(!subject)
|
||||
{
|
||||
// No subject principal means no JS is running;
|
||||
// this is the equivalent of system principal code
|
||||
*aIsSystem = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mSystemPrincipal->Equals(subject, aIsSystem);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
|
@ -1103,21 +998,6 @@ nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI *aURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
|
||||
nsresult* rv)
|
||||
{
|
||||
*rv = NS_OK;
|
||||
JSCompartment *compartment = js::GetContextCompartment(cx);
|
||||
|
||||
// The context should always be in a compartment, either one it has entered
|
||||
// or the one associated with its global.
|
||||
MOZ_ASSERT(!!compartment);
|
||||
|
||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
||||
return nsJSPrincipals::get(principals);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
||||
|
@ -1158,11 +1038,8 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
|
|||
//-- Access denied, report an error
|
||||
NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied");
|
||||
nsAutoCString origin;
|
||||
nsresult rv2;
|
||||
nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2);
|
||||
if (NS_SUCCEEDED(rv2) && subjectPrincipal) {
|
||||
GetPrincipalDomainOrigin(subjectPrincipal, origin);
|
||||
}
|
||||
nsIPrincipal* subjectPrincipal = nsContentUtils::GetSubjectPrincipal();
|
||||
GetPrincipalDomainOrigin(subjectPrincipal, origin);
|
||||
NS_ConvertUTF8toUTF16 originUnicode(origin);
|
||||
NS_ConvertUTF8toUTF16 classInfoName(objClassInfo.GetName());
|
||||
const char16_t* formatStrings[] = {
|
||||
|
@ -1176,14 +1053,11 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
|
|||
strName.AppendLiteral("ForOrigin");
|
||||
}
|
||||
nsXPIDLString errorMsg;
|
||||
// We need to keep our existing failure rv and not override it
|
||||
// with a likely success code from the following string bundle
|
||||
// call in order to throw the correct security exception later.
|
||||
rv2 = sStrBundle->FormatStringFromName(strName.get(),
|
||||
formatStrings,
|
||||
length,
|
||||
getter_Copies(errorMsg));
|
||||
NS_ENSURE_SUCCESS(rv2, rv2);
|
||||
nsresult rv = sStrBundle->FormatStringFromName(strName.get(),
|
||||
formatStrings,
|
||||
length,
|
||||
getter_Copies(errorMsg));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
SetPendingException(cx, errorMsg.get());
|
||||
return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
|
||||
|
@ -1368,29 +1242,22 @@ nsScriptSecurityManager::Shutdown()
|
|||
nsScriptSecurityManager *
|
||||
nsScriptSecurityManager::GetScriptSecurityManager()
|
||||
{
|
||||
if (!gScriptSecMan && nsXPConnect::XPConnect())
|
||||
{
|
||||
nsRefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager();
|
||||
|
||||
nsresult rv;
|
||||
rv = ssManager->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rv = nsXPConnect::XPConnect()->
|
||||
SetDefaultSecurityManager(ssManager);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to install xpconnect security manager!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ClearOnShutdown(&gScriptSecMan);
|
||||
gScriptSecMan = ssManager;
|
||||
}
|
||||
return gScriptSecMan;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsScriptSecurityManager::InitStatics()
|
||||
{
|
||||
nsRefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager();
|
||||
nsresult rv = ssManager->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
ClearOnShutdown(&gScriptSecMan);
|
||||
gScriptSecMan = ssManager;
|
||||
}
|
||||
|
||||
// Currently this nsGenericFactory constructor is used only from FastLoad
|
||||
// (XPCOM object deserialization) code, when "creating" the system principal
|
||||
// singleton.
|
||||
|
|
|
@ -1305,12 +1305,6 @@ DIST_FILES_FLAGS := $(XULAPP_DEFINES)
|
|||
PP_TARGETS += DIST_FILES
|
||||
endif
|
||||
|
||||
ifneq ($(DIST_FILES_NO_PP),)
|
||||
_DIST_FILES := $(DIST_FILES_NO_PP)
|
||||
_DIST_DEST := $(FINAL_TARGET)
|
||||
INSTALL_TARGETS += _DIST
|
||||
endif
|
||||
|
||||
ifneq ($(XPI_PKGNAME),)
|
||||
tools realchrome::
|
||||
ifdef STRIP_XPI
|
||||
|
|
|
@ -164,7 +164,13 @@ all.h
|
|||
alloca.h
|
||||
alloc.h
|
||||
alsa/asoundlib.h
|
||||
#ifdef ANDROID
|
||||
android/ashmem.h
|
||||
android/log.h
|
||||
android/looper.h
|
||||
android/native_window.h
|
||||
android_audio/AudioSystem.h
|
||||
#endif
|
||||
ansi_parms.h
|
||||
a.out.h
|
||||
app/Cursor.h
|
||||
|
@ -177,6 +183,7 @@ app/Message.h
|
|||
app/MessageRunner.h
|
||||
arpa/inet.h
|
||||
arpa/nameser.h
|
||||
asm/page.h
|
||||
asm/sigcontext.h
|
||||
asm/signal.h
|
||||
ASRegistry.h
|
||||
|
@ -192,6 +199,12 @@ atlimpl.cpp
|
|||
atlwin.cpp
|
||||
ATSTypes.h
|
||||
ATSUnicode.h
|
||||
#ifdef ANDROID
|
||||
AudioParameter.h
|
||||
AudioSystem.h
|
||||
AudioTrack.h
|
||||
avc_utils.h
|
||||
#endif
|
||||
Balloons.h
|
||||
base/pblock.h
|
||||
base/PCR_Base.h
|
||||
|
@ -202,6 +215,18 @@ Beep.h
|
|||
be/kernel/image.h
|
||||
be/kernel/OS.h
|
||||
bfd.h
|
||||
#ifdef ANDROID
|
||||
binder/Binder.h
|
||||
binder/BinderService.h
|
||||
binder/IBinder.h
|
||||
binder/IInterface.h
|
||||
binder/IMemory.h
|
||||
binder/IPCThreadState.h
|
||||
binder/IPermissionController.h
|
||||
binder/IServiceManager.h
|
||||
binder/Parcel.h
|
||||
binder/ProcessState.h
|
||||
#endif
|
||||
Bitmap.h
|
||||
bitset
|
||||
blapi.h
|
||||
|
@ -283,6 +308,10 @@ dfb_types.h
|
|||
directfb_strings.h
|
||||
directfb_keyboard.h
|
||||
callconv.h
|
||||
#ifdef ANDROID
|
||||
camera/Camera.h
|
||||
camera/CameraParameters.h
|
||||
#endif
|
||||
Carbon/Carbon.h
|
||||
CarbonEvents.h
|
||||
Carbon.h
|
||||
|
@ -308,6 +337,9 @@ Clipboard.h
|
|||
cmplrs/stsupport.h
|
||||
Cocoa/Cocoa.h
|
||||
CodeFragments.h
|
||||
#ifdef ANDROID
|
||||
ColorConverter.h
|
||||
#endif
|
||||
comdef.h
|
||||
commctrl.h
|
||||
COMMCTRL.H
|
||||
|
@ -340,6 +372,15 @@ ctype.h
|
|||
curl/curl.h
|
||||
curl/easy.h
|
||||
curses.h
|
||||
#ifdef ANDROID
|
||||
cutils/android_reboot.h
|
||||
cutils/atomic.h
|
||||
cutils/compiler.h
|
||||
cutils/log.h
|
||||
cutils/native_handle.h
|
||||
cutils/properties.h
|
||||
cutils/sockets.h
|
||||
#endif
|
||||
cxxabi.h
|
||||
DateTimeUtils.h
|
||||
dbus/dbus.h
|
||||
|
@ -366,6 +407,9 @@ DriverServices.h
|
|||
DriverSynchronization.h
|
||||
DropInPanel.h
|
||||
dvidef.h
|
||||
#ifdef ANDROID
|
||||
EffectApi.h
|
||||
#endif
|
||||
elf.h
|
||||
endian.h
|
||||
Entry.h
|
||||
|
@ -396,6 +440,19 @@ fontconfig/fontconfig.h
|
|||
fontconfig/fcfreetype.h
|
||||
Font.h
|
||||
Fonts.h
|
||||
#ifdef ANDROID
|
||||
foundation/ABase.h
|
||||
foundation/ABitReader.h
|
||||
foundation/ABuffer.h
|
||||
foundation/ADebug.h
|
||||
foundation/AHandler.h
|
||||
foundation/AHandlerReflector.h
|
||||
foundation/ALooper.h
|
||||
foundation/AMessage.h
|
||||
foundation/AString.h
|
||||
foundation/base64.h
|
||||
foundation/hexdump.h
|
||||
#endif
|
||||
fp.h
|
||||
fpieee.h
|
||||
frame/log.h
|
||||
|
@ -458,9 +515,41 @@ gtk/gtkx.h
|
|||
gtk/gtkprinter.h
|
||||
gtk/gtkprintjob.h
|
||||
gtk/gtkprintunixdialog.h
|
||||
#ifdef ANDROID
|
||||
gui/GraphicBufferAlloc.h
|
||||
gui/IConsumerListener.h
|
||||
gui/IGraphicBufferAlloc.h
|
||||
gui/IGraphicBufferProducer.h
|
||||
gui/ISurfaceComposer.h
|
||||
gui/ISurfaceComposerClient.h
|
||||
gui/ISurfaceTexture.h
|
||||
gui/Surface.h
|
||||
gui/SurfaceComposerClient.h
|
||||
gui/SurfaceTextureClient.h
|
||||
hardware/audio.h
|
||||
hardware/gralloc.h
|
||||
hardware/hardware.h
|
||||
hardware/hwcomposer.h
|
||||
hardware/lights.h
|
||||
hardware/power.h
|
||||
hardware_legacy/power.h
|
||||
hardware_legacy/uevent.h
|
||||
hardware_legacy/vibrator.h
|
||||
#endif
|
||||
HIToolbox/HIToolbox.h
|
||||
hlink.h
|
||||
#ifdef ANDROID
|
||||
HTTPBase.h
|
||||
#endif
|
||||
ia64/sys/inline.h
|
||||
#ifdef ANDROID
|
||||
IAudioFlingerClient.h
|
||||
IAudioFlinger.h
|
||||
IAudioRecord.h
|
||||
IAudioTrack.h
|
||||
IEffect.h
|
||||
IEffectClient.h
|
||||
#endif
|
||||
Icons.h
|
||||
iconv.h
|
||||
ieeefp.h
|
||||
|
@ -560,6 +649,11 @@ lib$routines.h
|
|||
limits
|
||||
limits.h
|
||||
link.h
|
||||
#ifdef ANDROID
|
||||
linux/android_alarm.h
|
||||
linux/ashmem.h
|
||||
#endif
|
||||
linux/ioprio.h
|
||||
linux/kernel.h
|
||||
linux/limits.h
|
||||
linux/rtc.h
|
||||
|
@ -646,6 +740,47 @@ mapix.h
|
|||
Math64.h
|
||||
math.h
|
||||
mbstring.h
|
||||
#ifdef ANDROID
|
||||
media/ICrypto.h
|
||||
media/IOMX.h
|
||||
media/MediaProfiles.h
|
||||
media/MediaRecorderBase.h
|
||||
media/openmax/OMX_Audio.h
|
||||
media/stagefright/AACWriter.h
|
||||
media/stagefright/AMRWriter.h
|
||||
media/stagefright/AudioSource.h
|
||||
media/stagefright/DataSource.h
|
||||
media/stagefright/foundation/ABase.h
|
||||
media/stagefright/foundation/ABitReader.h
|
||||
media/stagefright/foundation/ABuffer.h
|
||||
media/stagefright/foundation/ADebug.h
|
||||
media/stagefright/foundation/AHandler.h
|
||||
media/stagefright/foundation/AHandlerReflector.h
|
||||
media/stagefright/foundation/ALooper.h
|
||||
media/stagefright/foundation/AMessage.h
|
||||
media/stagefright/foundation/AString.h
|
||||
media/stagefright/foundation/base64.h
|
||||
media/stagefright/foundation/hexdump.h
|
||||
media/stagefright/MediaBuffer.h
|
||||
media/stagefright/MediaBufferGroup.h
|
||||
media/stagefright/MediaCodec.h
|
||||
media/stagefright/MediaDefs.h
|
||||
media/stagefright/MediaErrors.h
|
||||
media/stagefright/MediaExtractor.h
|
||||
media/stagefright/MediaSource.h
|
||||
media/stagefright/MediaWriter.h
|
||||
media/stagefright/MetaData.h
|
||||
media/stagefright/MPEG2TSWriter.h
|
||||
media/stagefright/MPEG4Writer.h
|
||||
media/stagefright/OMXClient.h
|
||||
media/stagefright/OMXCodec.h
|
||||
media/stagefright/openmax/OMX_Core.h
|
||||
media/stagefright/openmax/OMX_Index.h
|
||||
media/stagefright/openmax/OMX_IVCommon.h
|
||||
media/stagefright/openmax/OMX_Types.h
|
||||
media/stagefright/openmax/OMX_Video.h
|
||||
media/stagefright/Utils.h
|
||||
#endif
|
||||
mem.h
|
||||
memory
|
||||
memory.h
|
||||
|
@ -687,6 +822,10 @@ Objsafe.h
|
|||
ojiapitests.h
|
||||
ole2.h
|
||||
oleidl.h
|
||||
#ifdef ANDROID
|
||||
OMX.h
|
||||
OMX_Component.h
|
||||
#endif
|
||||
OpenGL/OpenGL.h
|
||||
OpenTptInternet.h
|
||||
OpenTransport.h
|
||||
|
@ -733,7 +872,10 @@ PP_Resources.h
|
|||
PP_Types.h
|
||||
Printing.h
|
||||
Print/PMPrintingDialogExtensions.h
|
||||
#ifdef ANDROID
|
||||
private/android_filesystem_config.h
|
||||
private/qucomextra_p.h
|
||||
#endif
|
||||
Processes.h
|
||||
process.h
|
||||
Process.h
|
||||
|
@ -783,6 +925,7 @@ set
|
|||
setjmp.h
|
||||
SFNTLayoutTypes.h
|
||||
SFNTTypes.h
|
||||
sha1.h
|
||||
share.h
|
||||
shellapi.h
|
||||
shlguid.h
|
||||
|
@ -800,6 +943,43 @@ sqlite3.h
|
|||
ssdef.h
|
||||
sstream
|
||||
stack
|
||||
#ifdef ANDROID
|
||||
stagefright/AACWriter.h
|
||||
stagefright/AMRWriter.h
|
||||
stagefright/AudioSource.h
|
||||
stagefright/DataSource.h
|
||||
stagefright/foundation/ABase.h
|
||||
stagefright/foundation/ABitReader.h
|
||||
stagefright/foundation/ABuffer.h
|
||||
stagefright/foundation/ADebug.h
|
||||
stagefright/foundation/AHandler.h
|
||||
stagefright/foundation/AHandlerReflector.h
|
||||
stagefright/foundation/ALooper.h
|
||||
stagefright/foundation/AMessage.h
|
||||
stagefright/foundation/AString.h
|
||||
stagefright/foundation/base64.h
|
||||
stagefright/foundation/hexdump.h
|
||||
stagefright/MediaBuffer.h
|
||||
stagefright/MediaBufferGroup.h
|
||||
stagefright/MediaCodec.h
|
||||
stagefright/MediaDefs.h
|
||||
stagefright/MediaErrors.h
|
||||
stagefright/MediaExtractor.h
|
||||
stagefright/MediaSource.h
|
||||
stagefright/MediaWriter.h
|
||||
stagefright/MetaData.h
|
||||
stagefright/MPEG2TSWriter.h
|
||||
stagefright/MPEG4Writer.h
|
||||
stagefright/OMXCodec.h
|
||||
stagefright/OMXClient.h
|
||||
stagefright/openmax/OMX_Component.h
|
||||
stagefright/openmax/OMX_Core.h
|
||||
stagefright/openmax/OMX_Index.h
|
||||
stagefright/openmax/OMX_IVCommon.h
|
||||
stagefright/openmax/OMX_Types.h
|
||||
stagefright/openmax/OMX_Video.h
|
||||
stagefright/Utils.h
|
||||
#endif
|
||||
StandardFile.h
|
||||
starlet.h
|
||||
stat.h
|
||||
|
@ -828,6 +1008,9 @@ SupportDefs.h
|
|||
support/String.h
|
||||
support/SupportDefs.h
|
||||
support/TLS.h
|
||||
#ifdef ANDROID
|
||||
suspend/autosuspend.h
|
||||
#endif
|
||||
svrcore.h
|
||||
symconst.h
|
||||
sym.h
|
||||
|
@ -841,6 +1024,7 @@ sys/cdefs.h
|
|||
sys/cfgodm.h
|
||||
sys/elf.h
|
||||
sys/endian.h
|
||||
sys/epoll.h
|
||||
sys/errno.h
|
||||
sys/fault.h
|
||||
sys/fcntl.h
|
||||
|
@ -848,10 +1032,12 @@ sys/file.h
|
|||
sys/filio.h
|
||||
sys/frame.h
|
||||
sys/immu.h
|
||||
sys/inotify.h
|
||||
sys/inttypes.h
|
||||
sys/ioccom.h
|
||||
sys/ioctl.h
|
||||
sys/ipc.h
|
||||
sys/klog.h
|
||||
sys/ldr.h
|
||||
sys/link.h
|
||||
sys/locking.h
|
||||
|
@ -910,6 +1096,12 @@ sys/unistd.h
|
|||
sys/utsname.h
|
||||
sys/vfs.h
|
||||
sys/wait.h
|
||||
#ifdef ANDROID
|
||||
sysutils/NetlinkEvent.h
|
||||
system/audio.h
|
||||
system/graphics.h
|
||||
system/window.h
|
||||
#endif
|
||||
tables.h
|
||||
TArray.h
|
||||
TArrayIterator.h
|
||||
|
@ -952,6 +1144,15 @@ UEventMgr.h
|
|||
UException.h
|
||||
UExtractFromAEDesc.h
|
||||
UGWorld.h
|
||||
#ifdef ANDROID
|
||||
ui/ANativeObjectBase.h
|
||||
ui/egl/android_natives.h
|
||||
ui/Fence.h
|
||||
ui/FramebufferNativeWindow.h
|
||||
ui/GraphicBuffer.h
|
||||
ui/Rect.h
|
||||
ui/Region.h
|
||||
#endif
|
||||
UKeyFilters.h
|
||||
ulocks.h
|
||||
ulserrno.h
|
||||
|
@ -975,6 +1176,28 @@ URegions.h
|
|||
URegistrar.h
|
||||
UResourceMgr.h
|
||||
utility
|
||||
#ifdef ANDROID
|
||||
utils/BitSet.h
|
||||
utils/CallStack.h
|
||||
utils/Errors.h
|
||||
utils/FileMap.h
|
||||
utils/KeyedVector.h
|
||||
utils/List.h
|
||||
utils/Log.h
|
||||
utils/Looper.h
|
||||
utils/PropertyMap.h
|
||||
utils/RefBase.h
|
||||
utils/String16.h
|
||||
utils/String8.h
|
||||
utils/threads.h
|
||||
utils/TextOutput.h
|
||||
utils/Timers.h
|
||||
utils/Trace.h
|
||||
utils/TypeHelpers.h
|
||||
utils/Unicode.h
|
||||
utils/Vector.h
|
||||
utils/VectorImpl.h
|
||||
#endif
|
||||
urlhist.h
|
||||
urlmon.h
|
||||
UScrap.h
|
||||
|
|
|
@ -8983,6 +8983,8 @@ else
|
|||
fi
|
||||
AC_SUBST(JS_SHARED_LIBRARY)
|
||||
|
||||
AC_SUBST(UPLOAD_EXTRA_FILES)
|
||||
|
||||
MOZ_CREATE_CONFIG_STATUS()
|
||||
|
||||
# No need to run subconfigures when building with LIBXUL_SDK_DIR
|
||||
|
|
|
@ -2170,6 +2170,7 @@ private:
|
|||
static nsIXPConnect *sXPConnect;
|
||||
|
||||
static nsIScriptSecurityManager *sSecurityManager;
|
||||
static nsIPrincipal *sSystemPrincipal;
|
||||
|
||||
static nsIParserService *sParserService;
|
||||
|
||||
|
|
|
@ -386,29 +386,10 @@ DOMParser::Constructor(const GlobalObject& aOwner,
|
|||
DOMParser::Constructor(const GlobalObject& aOwner,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> prin;
|
||||
nsCOMPtr<nsIURI> documentURI;
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
// No arguments; use the subject principal
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
if (!secMan) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rv = secMan->GetSubjectPrincipal(getter_AddRefs(prin));
|
||||
if (rv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We're called from JS; there better be a subject principal, really.
|
||||
if (!prin) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<DOMParser> domParser = new DOMParser(aOwner.GetAsSupports());
|
||||
rv = domParser->InitInternal(aOwner.GetAsSupports(), prin, documentURI, baseURI);
|
||||
rv = domParser->InitInternal(aOwner.GetAsSupports(),
|
||||
nsContentUtils::GetSubjectPrincipal(),
|
||||
nullptr, nullptr);
|
||||
if (rv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -464,24 +445,8 @@ DOMParser::Init(nsIPrincipal* aPrincipal, nsIURI* aDocumentURI,
|
|||
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
|
||||
|
||||
if (!principal && !aDocumentURI) {
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
if (!secMan) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
|
||||
if (rv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We're called from JS; there better be a subject principal, really.
|
||||
if (!principal) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
principal = nsContentUtils::GetSubjectPrincipal();
|
||||
}
|
||||
|
||||
rv = Init(principal, aDocumentURI, aBaseURI,
|
||||
|
|
|
@ -195,6 +195,7 @@ const char kLoadAsData[] = "loadAsData";
|
|||
|
||||
nsIXPConnect *nsContentUtils::sXPConnect;
|
||||
nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
|
||||
nsIPrincipal *nsContentUtils::sSystemPrincipal;
|
||||
nsIParserService *nsContentUtils::sParserService = nullptr;
|
||||
nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
|
||||
nsIIOService *nsContentUtils::sIOService;
|
||||
|
@ -376,8 +377,8 @@ nsContentUtils::Init()
|
|||
return NS_ERROR_FAILURE;
|
||||
NS_ADDREF(sSecurityManager);
|
||||
|
||||
// Getting the first context can trigger GC, so do this non-lazily.
|
||||
sXPConnect->InitSafeJSContext();
|
||||
sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
|
||||
MOZ_ASSERT(sSystemPrincipal);
|
||||
|
||||
nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -1434,6 +1435,7 @@ nsContentUtils::Shutdown()
|
|||
NS_IF_RELEASE(sConsoleService);
|
||||
sXPConnect = nullptr;
|
||||
NS_IF_RELEASE(sSecurityManager);
|
||||
NS_IF_RELEASE(sSystemPrincipal);
|
||||
NS_IF_RELEASE(sParserService);
|
||||
NS_IF_RELEASE(sIOService);
|
||||
NS_IF_RELEASE(sLineBreaker);
|
||||
|
@ -1514,14 +1516,7 @@ nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
|
|||
{
|
||||
MOZ_ASSERT(aTrustedNode);
|
||||
MOZ_ASSERT(unTrustedNode);
|
||||
|
||||
bool isSystem = false;
|
||||
nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&isSystem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isSystem) {
|
||||
// we're running as system, grant access to the node.
|
||||
|
||||
if (IsCallerChrome()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1578,45 +1573,19 @@ nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
|
|||
bool
|
||||
nsContentUtils::CanCallerAccess(nsINode* aNode)
|
||||
{
|
||||
// XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
|
||||
// with the system principal games? But really, there should be a simpler
|
||||
// API here, dammit.
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
||||
nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!subjectPrincipal) {
|
||||
// we're running as system, grant access to the node.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return CanCallerAccess(subjectPrincipal, aNode->NodePrincipal());
|
||||
return CanCallerAccess(GetSubjectPrincipal(), aNode->NodePrincipal());
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::CanCallerAccess(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
// XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
|
||||
// with the system principal games? But really, there should be a simpler
|
||||
// API here, dammit.
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
||||
nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!subjectPrincipal) {
|
||||
// we're running as system, grant access to the node.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptObject =
|
||||
do_QueryInterface(aWindow->IsOuterWindow() ?
|
||||
aWindow->GetCurrentInnerWindow() : aWindow);
|
||||
NS_ENSURE_TRUE(scriptObject, false);
|
||||
|
||||
return CanCallerAccess(subjectPrincipal, scriptObject->GetPrincipal());
|
||||
return CanCallerAccess(GetSubjectPrincipal(), scriptObject->GetPrincipal());
|
||||
}
|
||||
|
||||
//static
|
||||
|
@ -1718,12 +1687,7 @@ bool
|
|||
nsContentUtils::IsCallerChrome()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
bool is_caller_chrome = false;
|
||||
nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&is_caller_chrome);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
if (is_caller_chrome) {
|
||||
if (GetSubjectPrincipal() == sSystemPrincipal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2353,14 +2317,15 @@ nsContentUtils::GenerateStateKey(nsIContent* aContent,
|
|||
nsIPrincipal*
|
||||
nsContentUtils::GetSubjectPrincipal()
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> subject;
|
||||
sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subject));
|
||||
JSContext* cx = GetCurrentJSContext();
|
||||
if (!cx) {
|
||||
return GetSystemPrincipal();
|
||||
}
|
||||
|
||||
// When the ssm says the subject is null, that means system principal.
|
||||
if (!subject)
|
||||
sSecurityManager->GetSystemPrincipal(getter_AddRefs(subject));
|
||||
|
||||
return subject;
|
||||
JSCompartment* compartment = js::GetContextCompartment(cx);
|
||||
MOZ_ASSERT(compartment);
|
||||
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
|
||||
return nsJSPrincipals::get(principals);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -3141,11 +3106,7 @@ nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
|
|||
if (!aDocument) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> systemPrincipal;
|
||||
sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
|
||||
|
||||
return aDocument->NodePrincipal() == systemPrincipal;
|
||||
return aDocument->NodePrincipal() == sSystemPrincipal;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4351,10 +4312,7 @@ nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
|||
{
|
||||
NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal here");
|
||||
|
||||
bool isSystemPrin = false;
|
||||
if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(aLoadingPrincipal,
|
||||
&isSystemPrin)) &&
|
||||
isSystemPrin) {
|
||||
if (aLoadingPrincipal == sSystemPrincipal) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4393,9 +4351,7 @@ nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
|||
bool
|
||||
nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
bool isSystem;
|
||||
nsresult rv = sSecurityManager->IsSystemPrincipal(aPrincipal, &isSystem);
|
||||
return NS_SUCCEEDED(rv) && isSystem;
|
||||
return aPrincipal == sSystemPrincipal;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4408,11 +4364,7 @@ nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal)
|
|||
nsIPrincipal*
|
||||
nsContentUtils::GetSystemPrincipal()
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> sysPrin;
|
||||
DebugOnly<nsresult> rv =
|
||||
sSecurityManager->GetSystemPrincipal(getter_AddRefs(sysPrin));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) && sysPrin);
|
||||
return sysPrin;
|
||||
return sSystemPrincipal;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4434,7 +4386,7 @@ nsContentUtils::CombineResourcePrincipals(nsCOMPtr<nsIPrincipal>* aResourcePrinc
|
|||
subsumes) {
|
||||
return false;
|
||||
}
|
||||
sSecurityManager->GetSystemPrincipal(getter_AddRefs(*aResourcePrincipal));
|
||||
*aResourcePrincipal = sSystemPrincipal;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6106,20 +6058,10 @@ nsContentUtils::GetContentSecurityPolicy(JSContext* aCx,
|
|||
nsIContentSecurityPolicy** aCSP)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Get the security manager
|
||||
nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
|
||||
|
||||
if (!ssm) {
|
||||
NS_ERROR("Failed to get security manager service");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = ssm->GetCxSubjectPrincipal(aCx);
|
||||
NS_ASSERTION(subjectPrincipal, "Failed to get subjectPrincipal");
|
||||
MOZ_ASSERT(aCx == GetCurrentJSContext());
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
nsresult rv = GetSubjectPrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("CSP: Failed to get CSP from principal.");
|
||||
return false;
|
||||
|
|
|
@ -6335,23 +6335,13 @@ nsIDocument::LoadBindingDocument(const nsAString& aURI, ErrorResult& rv)
|
|||
return;
|
||||
}
|
||||
|
||||
// Figure out the right principal to use
|
||||
nsCOMPtr<nsIPrincipal> subject;
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
if (secMan) {
|
||||
rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
|
||||
if (rv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!subject) {
|
||||
// Fall back to our principal. Or should we fall back to the null
|
||||
// principal? The latter would just mean no binding loads....
|
||||
subject = NodePrincipal();
|
||||
}
|
||||
|
||||
BindingManager()->LoadBindingDocument(this, uri, subject);
|
||||
// Note - This computation of subjectPrincipal isn't necessarily sensical.
|
||||
// It's just designed to preserve the old semantics during a mass-conversion
|
||||
// patch.
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal =
|
||||
nsContentUtils::GetCurrentJSContext() ? nsContentUtils::GetSubjectPrincipal()
|
||||
: NodePrincipal();
|
||||
BindingManager()->LoadBindingDocument(this, uri, subjectPrincipal);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -118,7 +118,7 @@ function next_text() {
|
|||
}
|
||||
|
||||
function frame_loaded() {
|
||||
// We must delay to wait for the plugin sources to be loaded :(
|
||||
SimpleTest.requestFlakyTimeout("We must delay to wait for the plugin sources to be loaded :(");
|
||||
setTimeout(next_text, 500);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout("This test needs to generate artificial pauses, hence it uses timeouts. There is no way around it, unfortunately. :(");
|
||||
|
||||
window.addEventListener("message", function(e) {
|
||||
gen.send(e.data);
|
||||
|
|
|
@ -179,7 +179,7 @@ function forcegc()
|
|||
setTimeout(function()
|
||||
{
|
||||
SpecialPowers.gc();
|
||||
}, 1);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function doTest(number)
|
||||
|
@ -1498,6 +1498,8 @@ function testWebSocket ()
|
|||
doTest(first_test);
|
||||
}
|
||||
|
||||
SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
|
||||
"Expect all sorts of flakiness in this test...");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
|
|
|
@ -467,6 +467,7 @@ function start() {
|
|||
}
|
||||
|
||||
SimpleTest.requestLongerTimeout(requestLongerTimeoutLen);
|
||||
SimpleTest.requestFlakyTimeout("We're embedding the WebGL test harness, which uses timeouts internally, so we have to abide. :(");
|
||||
|
||||
var statusElem = document.getElementById("status");
|
||||
var statusTextNode = document.createTextNode('');
|
||||
|
|
|
@ -243,6 +243,25 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue, bool aNotify)
|
||||
{
|
||||
if (aNameSpaceID == kNameSpaceID_None &&
|
||||
aName == nsGkAtoms::value && Selected()) {
|
||||
// Since this option is selected, changing value
|
||||
// may have changed missing validity state of the
|
||||
// Select element
|
||||
HTMLSelectElement* select = GetSelect();
|
||||
if (select) {
|
||||
select->UpdateValueMissingValidityState();
|
||||
}
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLOptionElement::GetText(nsAString& aText)
|
||||
{
|
||||
|
|
|
@ -51,6 +51,8 @@ public:
|
|||
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
||||
const nsAttrValueOrString* aValue,
|
||||
bool aNotify) MOZ_OVERRIDE;
|
||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
|
||||
|
||||
void SetSelectedInternal(bool aValue, bool aNotify);
|
||||
|
||||
|
|
|
@ -395,6 +395,7 @@ public:
|
|||
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
||||
ValidityStateType aType) MOZ_OVERRIDE;
|
||||
|
||||
void UpdateValueMissingValidityState();
|
||||
/**
|
||||
* Insert aElement before the node given by aBefore
|
||||
*/
|
||||
|
@ -511,7 +512,6 @@ protected:
|
|||
// nsIConstraintValidation
|
||||
void UpdateBarredFromConstraintValidation();
|
||||
bool IsValueMissing();
|
||||
void UpdateValueMissingValidityState();
|
||||
|
||||
/**
|
||||
* Find out how deep this content is from the select (1=direct child)
|
||||
|
|
|
@ -74,6 +74,7 @@ skip-if = e10s
|
|||
[test_restore_form_elements.html]
|
||||
[test_save_restore_radio_groups.html]
|
||||
[test_select_selectedOptions.html]
|
||||
[test_select_validation.html]
|
||||
[test_set_range_text.html]
|
||||
[test_step_attribute.html]
|
||||
skip-if = e10s
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=942321
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 942321</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=942321">Mozilla Bug 942321</a>
|
||||
<p id="display"></p>
|
||||
<form id="form" href="">
|
||||
<select required id="testselect">
|
||||
<option id="placeholder" value="" selected>placeholder</option>
|
||||
<option value="test" id="actualvalue">test</option>
|
||||
<select>
|
||||
<input type="submit" />
|
||||
</form>
|
||||
<script class="testbody" type="text/javascript">
|
||||
/** Test for Bug 942321 **/
|
||||
var option = document.getElementById("actualvalue");
|
||||
option.selected = true;
|
||||
is(form.checkValidity(), true, "Select is required and should be valid");
|
||||
|
||||
var placeholder = document.getElementById("placeholder");
|
||||
placeholder.selected = true;
|
||||
is(form.checkValidity(), false, "Select is required and should be invalid");
|
||||
|
||||
placeholder.value = "not-invalid-anymore";
|
||||
is(form.checkValidity(), true, "Select is required and should be valid when option's value is changed by javascript");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -2849,27 +2849,10 @@ nsHTMLDocument::SetDesignMode(const nsAString & aDesignMode)
|
|||
void
|
||||
nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode, ErrorResult& rv)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
nsCOMPtr<nsIPrincipal> subject;
|
||||
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
|
||||
rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
|
||||
if (rv.Failed()) {
|
||||
return;
|
||||
}
|
||||
if (subject) {
|
||||
bool subsumes;
|
||||
rv = subject->Subsumes(NodePrincipal(), &subsumes);
|
||||
if (rv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!subsumes) {
|
||||
rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!nsContentUtils::GetSubjectPrincipal()->Subsumes(NodePrincipal())) {
|
||||
rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
bool editableMode = HasFlag(NODE_IS_EDITABLE);
|
||||
if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
|
||||
SetEditableFlag(!editableMode);
|
||||
|
|
|
@ -1449,7 +1449,7 @@ void MediaDecoderStateMachine::Seek(const SeekTarget& aTarget)
|
|||
mSeekTarget = SeekTarget(seekTime, aTarget.mType);
|
||||
|
||||
mBasePosition = seekTime - mStartTime;
|
||||
DECODER_LOG(PR_LOG_DEBUG, "Changed state to SEEKING (to %ld)", mSeekTarget.mTime);
|
||||
DECODER_LOG(PR_LOG_DEBUG, "Changed state to SEEKING (to %lld)", mSeekTarget.mTime);
|
||||
mState = DECODER_STATE_SEEKING;
|
||||
if (mDecoder->GetDecodedStream()) {
|
||||
mDecoder->RecreateDecodedStream(seekTime - mStartTime);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
namespace android {
|
||||
class OmxDecoder;
|
||||
class MediaExtractor;
|
||||
class MOZ_EXPORT MediaExtractor;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
|
||||
#include <android/native_window.h>
|
||||
#include <IOMX.h>
|
||||
#include <media/IOMX.h>
|
||||
#include <stagefright/MediaBuffer.h>
|
||||
#include <stagefright/MediaSource.h>
|
||||
#include <utils/threads.h>
|
||||
|
|
|
@ -323,8 +323,8 @@ nsresult MediaPluginReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aE
|
|||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
|
||||
mVideoQueue.Erase();
|
||||
mAudioQueue.Erase();
|
||||
mVideoQueue.Reset();
|
||||
mAudioQueue.Reset();
|
||||
|
||||
mAudioSeekTimeUs = mVideoSeekTimeUs = aTarget;
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ nsresult RawReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, in
|
|||
nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, offset.value());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mVideoQueue.Erase();
|
||||
mVideoQueue.Reset();
|
||||
|
||||
while(mVideoQueue.GetSize() == 0) {
|
||||
bool keyframeSkip = false;
|
||||
|
|
|
@ -1555,8 +1555,7 @@ nsDocShell::LoadURI(nsIURI * aURI,
|
|||
}
|
||||
if (!owner && !inheritOwner && !ownerIsExplicit) {
|
||||
// See if there's system or chrome JS code running
|
||||
inheritOwner = nsContentUtils::IsSystemPrincipal(
|
||||
nsContentUtils::GetSubjectPrincipal());
|
||||
inheritOwner = nsContentUtils::IsCallerChrome();
|
||||
}
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_OWNER) {
|
||||
|
@ -8645,7 +8644,7 @@ nsDocShell::CheckLoadingPermissions()
|
|||
// frames in the new window through window.frames[] (which is
|
||||
// allAccess for historic reasons), so we still need to do this
|
||||
// check on load.
|
||||
nsresult rv = NS_OK, sameOrigin = NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!gValidateOrigin || !IsFrame()) {
|
||||
// Origin validation was turned off, or we're not a frame.
|
||||
|
@ -8654,16 +8653,10 @@ nsDocShell::CheckLoadingPermissions()
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We're a frame. Check that the caller has write permission to
|
||||
// the parent before allowing it to load anything into this
|
||||
// docshell.
|
||||
nsCOMPtr<nsIPrincipal> subjPrincipal;
|
||||
rv = securityManager->GetSubjectPrincipal(getter_AddRefs(subjPrincipal));
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && subjPrincipal, rv);
|
||||
// Note - The check for a current JSContext here isn't necessarily sensical.
|
||||
// It's just designed to preserve the old semantics during a mass-conversion
|
||||
// patch.
|
||||
NS_ENSURE_TRUE(nsContentUtils::GetCurrentJSContext(), NS_OK);
|
||||
|
||||
// Check if the caller is from the same origin as this docshell,
|
||||
// or any of its ancestors.
|
||||
|
@ -8677,17 +8670,9 @@ nsDocShell::CheckLoadingPermissions()
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Compare origins
|
||||
bool subsumes;
|
||||
sameOrigin = subjPrincipal->Subsumes(p, &subsumes);
|
||||
if (NS_SUCCEEDED(sameOrigin)) {
|
||||
if (subsumes) {
|
||||
// Same origin, permit load
|
||||
|
||||
return sameOrigin;
|
||||
}
|
||||
|
||||
sameOrigin = NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||
if (nsContentUtils::GetSubjectPrincipal()->Subsumes(p)) {
|
||||
// Same origin, permit load
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> tmp;
|
||||
|
@ -8695,7 +8680,7 @@ nsDocShell::CheckLoadingPermissions()
|
|||
item.swap(tmp);
|
||||
} while (item);
|
||||
|
||||
return sameOrigin;
|
||||
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
|
|
|
@ -1629,8 +1629,7 @@ OpenEntryForRead(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
|
||||
void
|
||||
CloseEntryForRead(JS::Handle<JSObject*> global,
|
||||
size_t aSize,
|
||||
CloseEntryForRead(size_t aSize,
|
||||
const uint8_t* aMemory,
|
||||
intptr_t aFile)
|
||||
{
|
||||
|
@ -1683,8 +1682,7 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
|
||||
void
|
||||
CloseEntryForWrite(JS::Handle<JSObject*> global,
|
||||
size_t aSize,
|
||||
CloseEntryForWrite(size_t aSize,
|
||||
uint8_t* aMemory,
|
||||
intptr_t aFile)
|
||||
{
|
||||
|
|
|
@ -109,8 +109,7 @@ OpenEntryForRead(nsIPrincipal* aPrincipal,
|
|||
const uint8_t** aMemory,
|
||||
intptr_t *aHandle);
|
||||
void
|
||||
CloseEntryForRead(JS::Handle<JSObject*> aGlobal,
|
||||
size_t aSize,
|
||||
CloseEntryForRead(size_t aSize,
|
||||
const uint8_t* aMemory,
|
||||
intptr_t aHandle);
|
||||
bool
|
||||
|
@ -122,8 +121,7 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal,
|
|||
uint8_t** aMemory,
|
||||
intptr_t* aHandle);
|
||||
void
|
||||
CloseEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
size_t aSize,
|
||||
CloseEntryForWrite(size_t aSize,
|
||||
uint8_t* aMemory,
|
||||
intptr_t aHandle);
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
|
||||
aRv = mURI->SetSpec(href);
|
||||
mURI = uri;
|
||||
UpdateURLSearchParams();
|
||||
}
|
||||
|
||||
|
|
|
@ -2014,9 +2014,6 @@ nsGlobalWindow::SetInitialPrincipalToSubject()
|
|||
|
||||
// First, grab the subject principal.
|
||||
nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::GetSubjectPrincipal();
|
||||
if (!newWindowPrincipal) {
|
||||
newWindowPrincipal = nsContentUtils::GetSystemPrincipal();
|
||||
}
|
||||
|
||||
// Now, if we're about to use the system principal or an nsExpandedPrincipal,
|
||||
// make sure we're not using it for a content docshell.
|
||||
|
@ -6055,53 +6052,42 @@ nsGlobalWindow::MakeScriptDialogTitle(nsAString &aOutTitle)
|
|||
// Try to get a host from the running principal -- this will do the
|
||||
// right thing for javascript: and data: documents.
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
NS_ASSERTION(nsContentUtils::GetSecurityManager(),
|
||||
"Global Window has no security manager!");
|
||||
if (nsContentUtils::GetSecurityManager()) {
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
GetSubjectPrincipal(getter_AddRefs(principal));
|
||||
nsCOMPtr<nsIPrincipal> principal = nsContentUtils::GetSubjectPrincipal();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = principal->GetURI(getter_AddRefs(uri));
|
||||
// Note - The check for the current JSContext here isn't necessarily sensical.
|
||||
// It's just designed to preserve existing behavior during a mass-conversion
|
||||
// patch.
|
||||
if (NS_SUCCEEDED(rv) && uri && nsContentUtils::GetCurrentJSContext()) {
|
||||
// remove user:pass for privacy and spoof prevention
|
||||
|
||||
if (NS_SUCCEEDED(rv) && principal) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = principal->GetURI(getter_AddRefs(uri));
|
||||
nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID));
|
||||
if (fixup) {
|
||||
nsCOMPtr<nsIURI> fixedURI;
|
||||
rv = fixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
|
||||
if (NS_SUCCEEDED(rv) && fixedURI) {
|
||||
nsAutoCString host;
|
||||
fixedURI->GetHost(host);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && uri) {
|
||||
// remove user:pass for privacy and spoof prevention
|
||||
if (!host.IsEmpty()) {
|
||||
// if this URI has a host we'll show it. For other
|
||||
// schemes (e.g. file:) we fall back to the localized
|
||||
// generic string
|
||||
|
||||
nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID));
|
||||
if (fixup) {
|
||||
nsCOMPtr<nsIURI> fixedURI;
|
||||
rv = fixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
|
||||
if (NS_SUCCEEDED(rv) && fixedURI) {
|
||||
nsAutoCString host;
|
||||
fixedURI->GetHost(host);
|
||||
nsAutoCString prepath;
|
||||
fixedURI->GetPrePath(prepath);
|
||||
|
||||
if (!host.IsEmpty()) {
|
||||
// if this URI has a host we'll show it. For other
|
||||
// schemes (e.g. file:) we fall back to the localized
|
||||
// generic string
|
||||
|
||||
nsAutoCString prepath;
|
||||
fixedURI->GetPrePath(prepath);
|
||||
|
||||
NS_ConvertUTF8toUTF16 ucsPrePath(prepath);
|
||||
const char16_t *formatStrings[] = { ucsPrePath.get() };
|
||||
nsXPIDLString tempString;
|
||||
nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
|
||||
"ScriptDlgHeading",
|
||||
formatStrings,
|
||||
tempString);
|
||||
aOutTitle = tempString;
|
||||
}
|
||||
}
|
||||
NS_ConvertUTF8toUTF16 ucsPrePath(prepath);
|
||||
const char16_t *formatStrings[] = { ucsPrePath.get() };
|
||||
nsXPIDLString tempString;
|
||||
nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
|
||||
"ScriptDlgHeading",
|
||||
formatStrings,
|
||||
tempString);
|
||||
aOutTitle = tempString;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // failed to get subject principal
|
||||
NS_WARNING("No script principal? Who is calling alert/confirm/prompt?!");
|
||||
}
|
||||
}
|
||||
|
||||
if (aOutTitle.IsEmpty()) {
|
||||
|
@ -11693,28 +11679,14 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
|||
// If our principals subsume the subject principal then use the subject
|
||||
// principal. Otherwise, use our principal to avoid running script in
|
||||
// elevated principals.
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
||||
nsresult rv;
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool subsumes = false;
|
||||
nsCOMPtr<nsIPrincipal> ourPrincipal = GetPrincipal();
|
||||
|
||||
//
|
||||
// Note the direction of this test: We don't allow setTimeouts running with
|
||||
// chrome privileges on content windows, but we do allow setTimeouts running
|
||||
// with content privileges on chrome windows (where they can't do very much,
|
||||
// of course).
|
||||
rv = ourPrincipal->Subsumes(subjectPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (subsumes) {
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::GetSubjectPrincipal();
|
||||
nsCOMPtr<nsIPrincipal> ourPrincipal = GetPrincipal();
|
||||
if (ourPrincipal->Subsumes(subjectPrincipal)) {
|
||||
timeout->mPrincipal = subjectPrincipal;
|
||||
} else {
|
||||
timeout->mPrincipal = ourPrincipal;
|
||||
|
@ -11730,6 +11702,7 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
|||
|
||||
timeout->mWhen = TimeStamp::Now() + delta;
|
||||
|
||||
nsresult rv;
|
||||
timeout->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
|
|
|
@ -2089,12 +2089,12 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults)
|
|||
}
|
||||
|
||||
NS_NAMED_MULTILINE_LITERAL_STRING(kFmt,
|
||||
MOZ_UTF16("CC(T+%.1f) max pause: %lums, total time: %lums, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu waiting for GC)%s\n")
|
||||
MOZ_UTF16("CC(T+%.1f) max pause: %lums, total time: %lums, slices: %lu, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu waiting for GC)%s\n")
|
||||
MOZ_UTF16("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, max sync: %lu ms, removed: %lu"));
|
||||
nsString msg;
|
||||
msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC,
|
||||
gCCStats.mMaxSliceTime, gCCStats.mTotalSliceTime,
|
||||
gCCStats.mSuspected,
|
||||
aResults.mNumSlices, gCCStats.mSuspected,
|
||||
aResults.mVisitedRefCounted, aResults.mVisitedGCed, mergeMsg.get(),
|
||||
aResults.mFreedRefCounted, aResults.mFreedGCed,
|
||||
sCCollectedWaitingForGC, sLikelyShortLivingObjectsNeedingGC,
|
||||
|
|
|
@ -160,7 +160,7 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
|
|||
}
|
||||
}
|
||||
|
||||
owner = do_QueryInterface(ssm->GetCxSubjectPrincipal(cx));
|
||||
owner = nsContentUtils::GetSubjectPrincipal();
|
||||
}
|
||||
|
||||
// Create load info
|
||||
|
|
|
@ -2328,6 +2328,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
parentProtoType = "Rooted"
|
||||
if self.descriptor.interface.getExtendedAttribute("ArrayClass"):
|
||||
getParentProto = "aCx, JS_GetArrayPrototype(aCx, aGlobal)"
|
||||
elif self.descriptor.interface.getExtendedAttribute("ExceptionClass"):
|
||||
getParentProto = "aCx, JS_GetErrorPrototype(aCx)"
|
||||
else:
|
||||
getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
|
||||
else:
|
||||
|
|
|
@ -18,26 +18,6 @@
|
|||
#include "WorkerPrivate.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// We can't use nsContentUtils::IsCallerChrome because it might not exist in
|
||||
// xpcshell.
|
||||
bool
|
||||
IsCallerChrome()
|
||||
{
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan;
|
||||
secMan = XPCWrapper::GetSecurityManager();
|
||||
|
||||
if (!secMan) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isChrome;
|
||||
return NS_SUCCEEDED(secMan->SubjectPrincipalIsSystem(&isChrome)) && isChrome;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -80,7 +60,7 @@ ThrowExceptionObject(JSContext* aCx, Exception* aException)
|
|||
// (i.e., not chrome), rethrow the original value. This only applies to JS
|
||||
// implemented components so we only need to check for this on the main
|
||||
// thread.
|
||||
if (NS_IsMainThread() && !IsCallerChrome() &&
|
||||
if (NS_IsMainThread() && !nsContentUtils::IsCallerChrome() &&
|
||||
aException->StealJSVal(thrown.address())) {
|
||||
if (!JS_WrapValue(aCx, &thrown)) {
|
||||
return false;
|
||||
|
@ -173,14 +153,8 @@ GetCurrentJSStack()
|
|||
JSContext* cx = nullptr;
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
// Note, in xpcshell nsContentUtils is never initialized, but we still need
|
||||
// to report exceptions.
|
||||
if (nsContentUtils::XPConnect()) {
|
||||
cx = nsContentUtils::XPConnect()->GetCurrentJSContext();
|
||||
} else {
|
||||
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
|
||||
cx = xpc->GetCurrentJSContext();
|
||||
}
|
||||
MOZ_ASSERT(nsContentUtils::XPConnect());
|
||||
cx = nsContentUtils::GetCurrentJSContext();
|
||||
} else {
|
||||
cx = workers::GetCurrentThreadJSContext();
|
||||
}
|
||||
|
|
|
@ -269,6 +269,14 @@ class IDLScope(IDLObject):
|
|||
% (identifier.name,
|
||||
originalObject.location, newObject.location), [])
|
||||
|
||||
if (isinstance(originalObject, IDLDictionary) or
|
||||
isinstance(newObject, IDLDictionary)):
|
||||
raise WebIDLError(
|
||||
"Name collision between dictionary declarations for "
|
||||
"identifier '%s'.\n%s\n%s"
|
||||
% (identifier.name,
|
||||
originalObject.location, newObject.location), [])
|
||||
|
||||
# We do the merging of overloads here as opposed to in IDLInterface
|
||||
# because we need to merge overloads of NamedConstructors and we need to
|
||||
# detect conflicts in those across interfaces. See also the comment in
|
||||
|
@ -968,6 +976,14 @@ class IDLInterface(IDLObjectWithScope):
|
|||
raise WebIDLError("[ArrayClass] must not be specified on "
|
||||
"an interface with inherited interfaces",
|
||||
[attr.location, self.location])
|
||||
elif (identifier == "ExceptionClass"):
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[ExceptionClass] must take no arguments",
|
||||
[attr.location])
|
||||
if self.parent:
|
||||
raise WebIDLError("[ExceptionClass] must not be specified on "
|
||||
"an interface with inherited interfaces",
|
||||
[attr.location, self.location])
|
||||
elif identifier == "Global":
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[Global] must take no arguments",
|
||||
|
|
|
@ -31,11 +31,11 @@
|
|||
namespace android {
|
||||
|
||||
class GonkCameraSource;
|
||||
struct MediaSource;
|
||||
struct MediaWriter;
|
||||
class MetaData;
|
||||
struct AudioSource;
|
||||
class MediaProfiles;
|
||||
struct MOZ_EXPORT MediaSource;
|
||||
struct MOZ_EXPORT MediaWriter;
|
||||
class MOZ_EXPORT MetaData;
|
||||
struct MOZ_EXPORT AudioSource;
|
||||
class MOZ_EXPORT MediaProfiles;
|
||||
class GonkCameraHardware;
|
||||
|
||||
struct GonkRecorder {
|
||||
|
|
|
@ -594,9 +594,7 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
|
|||
(mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP &&
|
||||
mEventType != NS_PASTE &&
|
||||
!nsContentUtils::IsCallerChrome())) {
|
||||
nsresult rv = NS_OK;
|
||||
principal = GetCurrentPrincipal(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
principal = nsContentUtils::GetSubjectPrincipal();
|
||||
}
|
||||
|
||||
uint32_t count = item.Length();
|
||||
|
@ -625,9 +623,9 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
|
|||
MOZ_ASSERT(sp, "This cannot fail on the main thread.");
|
||||
nsIPrincipal* dataPrincipal = sp->GetPrincipal();
|
||||
NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
|
||||
NS_ENSURE_TRUE(principal || (principal = GetCurrentPrincipal(&rv)),
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!principal) {
|
||||
principal = nsContentUtils::GetSubjectPrincipal();
|
||||
}
|
||||
bool equals = false;
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(principal->Equals(dataPrincipal, &equals)) && equals,
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
@ -697,11 +695,8 @@ DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsIPrincipal* principal = GetCurrentPrincipal(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return SetDataWithPrincipal(aFormat, aData, aIndex, principal);
|
||||
return SetDataWithPrincipal(aFormat, aData, aIndex,
|
||||
nsContentUtils::GetSubjectPrincipal());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -754,12 +749,7 @@ DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
|
|||
nsAutoString format;
|
||||
GetRealFormat(aFormat, format);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsIPrincipal* principal = GetCurrentPrincipal(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv = rv;
|
||||
return;
|
||||
}
|
||||
nsIPrincipal* principal = nsContentUtils::GetSubjectPrincipal();
|
||||
|
||||
// if the format is empty, clear all formats
|
||||
bool clearall = format.IsEmpty();
|
||||
|
@ -1089,21 +1079,6 @@ DataTransfer::SetDataWithPrincipal(const nsAString& aFormat,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
DataTransfer::GetCurrentPrincipal(nsresult* rv)
|
||||
{
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> currentPrincipal;
|
||||
*rv = ssm->GetSubjectPrincipal(getter_AddRefs(currentPrincipal));
|
||||
NS_ENSURE_SUCCESS(*rv, nullptr);
|
||||
|
||||
if (!currentPrincipal)
|
||||
ssm->GetSystemPrincipal(getter_AddRefs(currentPrincipal));
|
||||
|
||||
return currentPrincipal.get();
|
||||
}
|
||||
|
||||
void
|
||||
DataTransfer::GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat)
|
||||
{
|
||||
|
|
|
@ -219,9 +219,6 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
// returns a weak reference to the current principal
|
||||
nsIPrincipal* GetCurrentPrincipal(nsresult* rv);
|
||||
|
||||
// converts some formats used for compatibility in aInFormat into aOutFormat.
|
||||
// Text and text/unicode become text/plain, and URL becomes text/uri-list
|
||||
void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
"DOMException exception: existence and properties of exception interface prototype object": true,
|
||||
"DOMException exception: existence and properties of exception interface prototype object's \"name\" property": true,
|
||||
"CustomEvent interface: existence and properties of interface object": true,
|
||||
"EventListener interface: existence and properties of interface prototype object": true,
|
||||
|
|
|
@ -3,11 +3,8 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIST_FILES = \
|
||||
install.rdf \
|
||||
$(NULL)
|
||||
|
||||
DIST_FILES_NO_PP = \
|
||||
bootstrap.js \
|
||||
install.rdf \
|
||||
$(NULL)
|
||||
|
||||
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
|
||||
|
|
|
@ -121,6 +121,7 @@ TabChildBase::TabChildBase()
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal)
|
||||
|
@ -975,8 +976,7 @@ TabChild::NotifyTabContextUpdated()
|
|||
}
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(TabChild)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
|
||||
|
@ -989,10 +989,10 @@ NS_INTERFACE_MAP_BEGIN(TabChild)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_INTERFACE_MAP_END_INHERITING(TabChildBase)
|
||||
|
||||
NS_IMPL_ADDREF(TabChild)
|
||||
NS_IMPL_RELEASE(TabChild)
|
||||
NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase);
|
||||
NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase);
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
|
||||
|
|
|
@ -220,7 +220,8 @@ protected:
|
|||
mozilla::layout::ScrollingBehavior mScrolling;
|
||||
};
|
||||
|
||||
class TabChild : public PBrowserChild,
|
||||
class TabChild : public TabChildBase,
|
||||
public PBrowserChild,
|
||||
public nsIWebBrowserChrome2,
|
||||
public nsIEmbeddingSiteWindow,
|
||||
public nsIWebBrowserChromeFocus,
|
||||
|
@ -232,8 +233,7 @@ class TabChild : public PBrowserChild,
|
|||
public nsITabChild,
|
||||
public nsIObserver,
|
||||
public TabContext,
|
||||
public nsITooltipListener,
|
||||
public TabChildBase
|
||||
public nsITooltipListener
|
||||
{
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
typedef mozilla::layout::RenderFrameChild RenderFrameChild;
|
||||
|
@ -256,7 +256,7 @@ public:
|
|||
|
||||
bool IsRootContentDocument();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIWEBBROWSERCHROME
|
||||
NS_DECL_NSIWEBBROWSERCHROME2
|
||||
NS_DECL_NSIEMBEDDINGSITEWINDOW
|
||||
|
|
|
@ -241,18 +241,12 @@ DOMStorage::CanUseStorage(DOMStorage* aStorage)
|
|||
}
|
||||
|
||||
// chrome can always use aStorage regardless of permission preferences
|
||||
if (nsContentUtils::IsCallerChrome()) {
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal =
|
||||
nsContentUtils::GetSubjectPrincipal();
|
||||
if (nsContentUtils::IsSystemPrincipal(subjectPrincipal)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->
|
||||
GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// if subjectPrincipal were null we'd have returned after
|
||||
// IsCallerChrome().
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
services::GetPermissionManager();
|
||||
if (!permissionManager) {
|
||||
|
|
|
@ -18,13 +18,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=
|
|||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
/** Test for Bug **/
|
||||
let Ci = Components.interfaces;
|
||||
var obs = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
.getService(Ci.nsIObserverService);
|
||||
var didCall = false;
|
||||
var observer = {
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIObserver) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
if (aIID.equals(Ci.nsIObserver) ||
|
||||
aIID.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
|
@ -35,9 +36,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=
|
|||
}
|
||||
};
|
||||
|
||||
// Make sure that we call the observer even if we're in the middle
|
||||
// of an ICC when we add the observer. See bug 981033.
|
||||
// XXX This will assert if we try to start an ICC during a IGC.
|
||||
//SpecialPowers.finishCC();
|
||||
//SpecialPowers.ccSlice(1);
|
||||
|
||||
obs.addObserver(observer, "cycle-collector-begin", false);
|
||||
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils).cycleCollect();
|
||||
|
||||
SpecialPowers.DOMWindowUtils.cycleCollect();
|
||||
|
||||
ok(didCall, "Observer should have been called!");
|
||||
]]>
|
||||
|
|
|
@ -18,11 +18,18 @@ interface StackFrame;
|
|||
[NoInterfaceObject]
|
||||
interface ExceptionMembers
|
||||
{
|
||||
// A custom message set by the thrower.
|
||||
// A custom message set by the thrower. LenientThis so it can be
|
||||
// gotten on the prototype, which Error.prototype.toString will do
|
||||
// if someone tries to stringify DOMException.prototype.
|
||||
[LenientThis]
|
||||
readonly attribute DOMString message;
|
||||
// The nsresult associated with this exception.
|
||||
readonly attribute unsigned long result;
|
||||
// The name of the error code (ie, a string repr of |result|)
|
||||
// The name of the error code (ie, a string repr of |result|).
|
||||
// LenientThis so it can be gotten on the prototype, which
|
||||
// Error.prototype.toString will do if someone tries to stringify
|
||||
// DOMException.prototype.
|
||||
[LenientThis]
|
||||
readonly attribute DOMString name;
|
||||
|
||||
// Filename location. This is the location that caused the
|
||||
|
@ -49,19 +56,19 @@ interface ExceptionMembers
|
|||
|
||||
// Arbitary data for the implementation.
|
||||
readonly attribute nsISupports? data;
|
||||
|
||||
// A generic formatter - make it suitable to print, etc.
|
||||
stringifier;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface Exception {
|
||||
// A generic formatter - make it suitable to print, etc.
|
||||
stringifier;
|
||||
};
|
||||
|
||||
Exception implements ExceptionMembers;
|
||||
|
||||
// XXXkhuey this is an 'exception', not an interface, but we don't have any
|
||||
// parser or codegen mechanisms for dealing with exceptions.
|
||||
[ExceptionClass]
|
||||
interface DOMException {
|
||||
const unsigned short INDEX_SIZE_ERR = 1;
|
||||
const unsigned short DOMSTRING_SIZE_ERR = 2; // historical
|
||||
|
|
|
@ -3717,6 +3717,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
|
|||
using namespace mozilla::dom::workers::scriptloader;
|
||||
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT_IF(NS_IsMainThread(), aCx == nsContentUtils::GetCurrentJSContext());
|
||||
|
||||
if (aWindow) {
|
||||
AssertIsOnMainThread();
|
||||
|
@ -3913,10 +3914,6 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
|
|||
MOZ_ASSERT(loadInfo.mPrincipal);
|
||||
MOZ_ASSERT(isChrome || !loadInfo.mDomain.IsEmpty());
|
||||
|
||||
// XXXbent Use subject principal here instead of the one we already have?
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = ssm->GetCxSubjectPrincipal(aCx);
|
||||
MOZ_ASSERT(subjectPrincipal);
|
||||
|
||||
if (!nsContentUtils::GetContentSecurityPolicy(aCx,
|
||||
getter_AddRefs(loadInfo.mCSP))) {
|
||||
NS_WARNING("Failed to get CSP!");
|
||||
|
|
|
@ -3,11 +3,8 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIST_FILES = \
|
||||
install.rdf \
|
||||
$(NULL)
|
||||
|
||||
DIST_FILES_NO_PP = \
|
||||
bootstrap.js \
|
||||
install.rdf \
|
||||
worker.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
|
||||
DIST_FILES = \
|
||||
install.rdf \
|
||||
$(NULL)
|
||||
|
||||
DIST_FILES_NO_PP = \
|
||||
worker.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -1252,15 +1252,8 @@ NS_IMETHODIMP
|
|||
txMozillaXSLTProcessor::Initialize(nsISupports* aOwner, JSContext* cx,
|
||||
JSObject* obj, const JS::CallArgs& args)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> prin;
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ENSURE_TRUE(secMan, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(prin));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(prin, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return Init(prin);
|
||||
MOZ_ASSERT(nsContentUtils::GetCurrentJSContext());
|
||||
return Init(nsContentUtils::GetSubjectPrincipal());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
|
@ -236,22 +237,6 @@ nsCommandManager::DoCommand(const char *aCommandName,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCommandManager::IsCallerChrome(bool *is_caller_chrome)
|
||||
{
|
||||
*is_caller_chrome = false;
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!secMan)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv = secMan->SubjectPrincipalIsSystem(is_caller_chrome);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCommandManager::GetControllerForCommand(const char *aCommand,
|
||||
nsIDOMWindow *aTargetWindow,
|
||||
|
@ -262,12 +247,7 @@ nsCommandManager::GetControllerForCommand(const char *aCommand,
|
|||
|
||||
// check if we're in content or chrome
|
||||
// if we're not chrome we must have a target window or we bail
|
||||
bool isChrome = false;
|
||||
rv = IsCallerChrome(&isChrome);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!isChrome) {
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
if (!aTargetWindow)
|
||||
return rv;
|
||||
|
||||
|
|
|
@ -43,8 +43,6 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
|
||||
nsresult IsCallerChrome(bool *aIsCallerChrome);
|
||||
nsresult GetControllerForCommand(const char * aCommand,
|
||||
nsIDOMWindow *aDirectedToThisWindow,
|
||||
nsIController** outController);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "mozilla/Services.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#if DEBUG
|
||||
#include "nsIWebNavigation.h"
|
||||
|
@ -660,21 +661,8 @@ nsresult nsWebBrowserFind::SearchInFrame(nsIDOMWindow* aWindow,
|
|||
nsCOMPtr<nsIDocument> theDoc = do_QueryInterface(domDoc);
|
||||
if (!theDoc) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subject;
|
||||
rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (subject) {
|
||||
bool subsumes;
|
||||
rv = subject->Subsumes(theDoc->NodePrincipal(), &subsumes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!subsumes) {
|
||||
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||
}
|
||||
if (!nsContentUtils::GetSubjectPrincipal()->Subsumes(theDoc->NodePrincipal())) {
|
||||
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFind> find = do_CreateInstance(NS_FIND_CONTRACTID, &rv);
|
||||
|
|
|
@ -785,15 +785,14 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent,
|
|||
|
||||
// Now we have to set the right opener principal on the new window. Note
|
||||
// that we have to do this _before_ starting any URI loads, thanks to the
|
||||
// sync nature of javascript: loads. Since this is the only place where we
|
||||
// set said opener principal, we need to do it for all URIs, including
|
||||
// chrome ones. So to deal with the mess that is bug 79775, just press on in
|
||||
// a reasonable way even if GetSubjectPrincipal fails. In that case, just
|
||||
// use a null subjectPrincipal.
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
||||
if (NS_FAILED(sm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)))) {
|
||||
subjectPrincipal = nullptr;
|
||||
}
|
||||
// sync nature of javascript: loads.
|
||||
//
|
||||
// Note: The check for the current JSContext isn't necessarily sensical.
|
||||
// It's just designed to preserve old semantics during a mass-conversion
|
||||
// patch.
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal =
|
||||
nsContentUtils::GetCurrentJSContext() ? nsContentUtils::GetSubjectPrincipal()
|
||||
: nullptr;
|
||||
|
||||
if (windowIsNew) {
|
||||
// Now set the opener principal on the new window. Note that we need to do
|
||||
|
|
|
@ -303,6 +303,19 @@ GLContext::~GLContext() {
|
|||
#endif
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
GLContext::StaticDebugCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
const GLvoid* userParam)
|
||||
{
|
||||
GLContext* gl = (GLContext*)userParam;
|
||||
gl->DebugCallback(source, type, id, severity, length, message);
|
||||
}
|
||||
|
||||
bool
|
||||
GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
{
|
||||
|
@ -1159,6 +1172,17 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
mTexGarbageBin = new TextureGarbageBin(this);
|
||||
|
||||
MOZ_ASSERT(IsCurrent());
|
||||
|
||||
if (DebugMode() && IsExtensionSupported(KHR_debug)) {
|
||||
fEnable(LOCAL_GL_DEBUG_OUTPUT);
|
||||
fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
fDebugMessageCallback(&StaticDebugCallback, (void*)this);
|
||||
fDebugMessageControl(LOCAL_GL_DONT_CARE,
|
||||
LOCAL_GL_DONT_CARE,
|
||||
LOCAL_GL_DONT_CARE,
|
||||
0, nullptr,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
if (mInitialized)
|
||||
|
@ -1174,6 +1198,95 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
return mInitialized;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DebugCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message)
|
||||
{
|
||||
nsAutoCString sourceStr;
|
||||
switch (source) {
|
||||
case LOCAL_GL_DEBUG_SOURCE_API:
|
||||
sourceStr = NS_LITERAL_CSTRING("SOURCE_API");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
|
||||
sourceStr = NS_LITERAL_CSTRING("SOURCE_WINDOW_SYSTEM");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
|
||||
sourceStr = NS_LITERAL_CSTRING("SOURCE_SHADER_COMPILER");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
|
||||
sourceStr = NS_LITERAL_CSTRING("SOURCE_THIRD_PARTY");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
|
||||
sourceStr = NS_LITERAL_CSTRING("SOURCE_APPLICATION");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SOURCE_OTHER:
|
||||
sourceStr = NS_LITERAL_CSTRING("SOURCE_OTHER");
|
||||
break;
|
||||
default:
|
||||
sourceStr = nsPrintfCString("<source 0x%04x>", source);
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString typeStr;
|
||||
switch (type) {
|
||||
case LOCAL_GL_DEBUG_TYPE_ERROR:
|
||||
typeStr = NS_LITERAL_CSTRING("TYPE_ERROR");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
||||
typeStr = NS_LITERAL_CSTRING("TYPE_DEPRECATED_BEHAVIOR");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
||||
typeStr = NS_LITERAL_CSTRING("TYPE_UNDEFINED_BEHAVIOR");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
|
||||
typeStr = NS_LITERAL_CSTRING("TYPE_PORTABILITY");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
|
||||
typeStr = NS_LITERAL_CSTRING("TYPE_PERFORMANCE");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_TYPE_OTHER:
|
||||
typeStr = NS_LITERAL_CSTRING("TYPE_OTHER");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_TYPE_MARKER:
|
||||
typeStr = NS_LITERAL_CSTRING("TYPE_MARKER");
|
||||
break;
|
||||
default:
|
||||
typeStr = nsPrintfCString("<type 0x%04x>", type);
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString sevStr;
|
||||
switch (severity) {
|
||||
case LOCAL_GL_DEBUG_SEVERITY_HIGH:
|
||||
sevStr = NS_LITERAL_CSTRING("SEVERITY_HIGH");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
|
||||
sevStr = NS_LITERAL_CSTRING("SEVERITY_MEDIUM");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SEVERITY_LOW:
|
||||
sevStr = NS_LITERAL_CSTRING("SEVERITY_LOW");
|
||||
break;
|
||||
case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
|
||||
sevStr = NS_LITERAL_CSTRING("SEVERITY_NOTIFICATION");
|
||||
break;
|
||||
default:
|
||||
sevStr = nsPrintfCString("<severity 0x%04x>", severity);
|
||||
break;
|
||||
}
|
||||
|
||||
printf_stderr("[KHR_debug: 0x%x] ID %u: %s %s %s:\n %s",
|
||||
(uintptr_t)this,
|
||||
id,
|
||||
sourceStr.BeginReading(),
|
||||
typeStr.BeginReading(),
|
||||
sevStr.BeginReading(),
|
||||
message);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::InitExtensions()
|
||||
{
|
||||
|
|
|
@ -582,6 +582,20 @@ private:
|
|||
GLenum mGLError;
|
||||
#endif // DEBUG
|
||||
|
||||
static void GLAPIENTRY StaticDebugCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
const GLvoid* userParam);
|
||||
void DebugCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MOZ_GL_DEBUG implementation
|
||||
|
|
|
@ -205,6 +205,14 @@ public:
|
|||
return mCompositionBounds / GetZoomToParent();
|
||||
}
|
||||
|
||||
CSSSize CalculateBoundedCompositedSizeInCssPixels() const
|
||||
{
|
||||
CSSSize size = CalculateCompositedSizeInCssPixels();
|
||||
size.width = std::min(size.width, mRootCompositionSize.width);
|
||||
size.height = std::min(size.height, mRootCompositionSize.height);
|
||||
return size;
|
||||
}
|
||||
|
||||
void ScrollBy(const CSSPoint& aPoint)
|
||||
{
|
||||
mScrollOffset += aPoint;
|
||||
|
|
|
@ -1485,11 +1485,7 @@ const LayerMargin AsyncPanZoomController::CalculatePendingDisplayPort(
|
|||
const ScreenPoint& aVelocity,
|
||||
double aEstimatedPaintDuration)
|
||||
{
|
||||
CSSSize compositionBounds = aFrameMetrics.CalculateCompositedSizeInCssPixels();
|
||||
CSSSize compositionSize = aFrameMetrics.GetRootCompositionSize();
|
||||
compositionSize =
|
||||
CSSSize(std::min(compositionBounds.width, compositionSize.width),
|
||||
std::min(compositionBounds.height, compositionSize.height));
|
||||
CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels();
|
||||
CSSPoint velocity = aVelocity / aFrameMetrics.GetZoom();
|
||||
CSSPoint scrollOffset = aFrameMetrics.GetScrollOffset();
|
||||
CSSRect scrollableRect = aFrameMetrics.GetExpandedScrollableRect();
|
||||
|
@ -1595,10 +1591,7 @@ GetDisplayPortRect(const FrameMetrics& aFrameMetrics)
|
|||
// This computation is based on what happens in CalculatePendingDisplayPort. If that
|
||||
// changes then this might need to change too
|
||||
CSSRect baseRect(aFrameMetrics.GetScrollOffset(),
|
||||
CSSSize(std::min(aFrameMetrics.CalculateCompositedSizeInCssPixels().width,
|
||||
aFrameMetrics.GetRootCompositionSize().width),
|
||||
std::min(aFrameMetrics.CalculateCompositedSizeInCssPixels().height,
|
||||
aFrameMetrics.GetRootCompositionSize().height)));
|
||||
aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels());
|
||||
baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.LayersPixelsPerCSSPixel());
|
||||
return baseRect;
|
||||
}
|
||||
|
|
|
@ -241,7 +241,11 @@ bool
|
|||
SharedFrameMetricsHelper::AboutToCheckerboard(const FrameMetrics& aContentMetrics,
|
||||
const FrameMetrics& aCompositorMetrics)
|
||||
{
|
||||
return !aContentMetrics.mDisplayPort.Contains(aCompositorMetrics.CalculateCompositedRectInCssPixels() - aCompositorMetrics.GetScrollOffset());
|
||||
CSSRect painted =
|
||||
(aContentMetrics.mCriticalDisplayPort.IsEmpty() ? aContentMetrics.mDisplayPort : aContentMetrics.mCriticalDisplayPort)
|
||||
+ aContentMetrics.GetScrollOffset();
|
||||
CSSRect showing = CSSRect(aCompositorMetrics.GetScrollOffset(), aCompositorMetrics.CalculateBoundedCompositedSizeInCssPixels());
|
||||
return !painted.Contains(showing);
|
||||
}
|
||||
|
||||
ClientTiledLayerBuffer::ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
|
||||
|
|
|
@ -33,11 +33,10 @@ struct nsIntRect;
|
|||
* loaded data fire before the call returns. If FLAG_SYNC_DECODE is not passed,
|
||||
* all, some, or none of the notifications may fire before the call returns.
|
||||
*/
|
||||
class imgDecoderObserver : public mozilla::RefCounted<imgDecoderObserver>
|
||||
class imgDecoderObserver
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(imgDecoderObserver)
|
||||
virtual ~imgDecoderObserver() = 0;
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(imgDecoderObserver);
|
||||
|
||||
/**
|
||||
* Load notification.
|
||||
|
@ -126,6 +125,9 @@ public:
|
|||
* Called when an image is realized to be in error state.
|
||||
*/
|
||||
virtual void OnError() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~imgDecoderObserver() = 0;
|
||||
};
|
||||
|
||||
// We must define a destructor because derived classes call our destructor from
|
||||
|
|
|
@ -29,8 +29,6 @@ public:
|
|||
MOZ_ASSERT(aTracker);
|
||||
}
|
||||
|
||||
virtual ~imgStatusTrackerObserver() {}
|
||||
|
||||
void SetTracker(imgStatusTracker* aTracker)
|
||||
{
|
||||
MOZ_ASSERT(aTracker);
|
||||
|
@ -143,6 +141,9 @@ public:
|
|||
tracker->RecordError();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~imgStatusTrackerObserver() {}
|
||||
|
||||
private:
|
||||
WeakPtr<imgStatusTracker> mTracker;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
var lfcode = new Array();
|
||||
lfcode.push = loadFile;
|
||||
lfcode.push("\
|
||||
var g = newGlobal();\
|
||||
g.debuggeeGlobal = this;\
|
||||
g.eval(\"(\" + function () {\
|
||||
dbg = new Debugger(debuggeeGlobal);\
|
||||
} + \")();\");\
|
||||
");
|
||||
lfcode.push("gc();");
|
||||
lfcode.push("\
|
||||
var g = newGlobal();\
|
||||
g.debuggeeGlobal = this;\
|
||||
g.eval(\"(\" + function () {\
|
||||
dbg = new Debugger(debuggeeGlobal);\
|
||||
} + \")();\");\
|
||||
");
|
||||
function loadFile(lfVarx) {
|
||||
function newFunc(x) { new Function(x)(); }; newFunc(lfVarx);
|
||||
}
|
|
@ -25,9 +25,10 @@ withJitOptions(Opts_Ion2NoParallelCompilation, function () {
|
|||
}
|
||||
};
|
||||
|
||||
g.eval("" + function f(d, x) { g(d, x); });
|
||||
g.eval("" + function f(d, x) { "use strict"; g(d, x); });
|
||||
|
||||
g.eval("" + function g(d, x) {
|
||||
"use strict";
|
||||
for (var i = 0; i < 200; i++);
|
||||
// Hack to prevent inlining.
|
||||
function inner() { i = 42; };
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
var i = 0;
|
||||
var expectedmatch = '';
|
||||
var expectedmatches = new Array();
|
||||
addThis();
|
||||
expectedmatch = null;
|
||||
addThis();
|
||||
function addThis() {
|
||||
Array(-2147483648, -2147483648);
|
||||
expectedmatches[i] = expectedmatch;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
(function(x) {
|
||||
for (var y = 0; y < 1; y++) {
|
||||
assertEq(Array.prototype.shift.call(arguments.callee.arguments), 0);
|
||||
}
|
||||
})(0)
|
|
@ -167,10 +167,10 @@ InvokeFromAsmJS_ToNumber(JSContext *cx, int32_t exitIndex, int32_t argc, Value *
|
|||
#if defined(JS_CODEGEN_ARM)
|
||||
extern "C" {
|
||||
|
||||
extern int64_t
|
||||
extern MOZ_EXPORT int64_t
|
||||
__aeabi_idivmod(int, int);
|
||||
|
||||
extern int64_t
|
||||
extern MOZ_EXPORT int64_t
|
||||
__aeabi_uidivmod(int, int);
|
||||
|
||||
}
|
||||
|
@ -1246,7 +1246,7 @@ struct ScopedCacheEntryOpenedForWrite
|
|||
|
||||
~ScopedCacheEntryOpenedForWrite() {
|
||||
if (memory)
|
||||
cx->asmJSCacheOps().closeEntryForWrite(cx->global(), serializedSize, memory, handle);
|
||||
cx->asmJSCacheOps().closeEntryForWrite(serializedSize, memory, handle);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1303,7 +1303,7 @@ struct ScopedCacheEntryOpenedForRead
|
|||
|
||||
~ScopedCacheEntryOpenedForRead() {
|
||||
if (memory)
|
||||
cx->asmJSCacheOps().closeEntryForRead(cx->global(), serializedSize, memory, handle);
|
||||
cx->asmJSCacheOps().closeEntryForRead(serializedSize, memory, handle);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -93,6 +93,10 @@ struct DebugModeOSREntry
|
|||
frameKind == ICEntry::Kind_DebugEpilogue);
|
||||
}
|
||||
|
||||
bool recompiled() const {
|
||||
return oldBaselineScript != script->baselineScript();
|
||||
}
|
||||
|
||||
BaselineDebugModeOSRInfo *takeRecompInfo() {
|
||||
MOZ_ASSERT(recompInfo);
|
||||
BaselineDebugModeOSRInfo *tmp = recompInfo;
|
||||
|
@ -208,9 +212,8 @@ SpewPatchBaselineFrame(uint8_t *oldReturnAddress, uint8_t *newReturnAddress,
|
|||
JSScript *script, ICEntry::Kind frameKind, jsbytecode *pc)
|
||||
{
|
||||
IonSpew(IonSpew_BaselineDebugModeOSR,
|
||||
"Patch return %#016llx -> %#016llx to BaselineJS (%s:%d) from %s at %s",
|
||||
uintptr_t(oldReturnAddress), uintptr_t(newReturnAddress),
|
||||
script->filename(), script->lineno(),
|
||||
"Patch return %p -> %p on BaselineJS frame (%s:%d) from %s at %s",
|
||||
oldReturnAddress, newReturnAddress, script->filename(), script->lineno(),
|
||||
ICEntryKindToString(frameKind), js_CodeName[(JSOp)*pc]);
|
||||
}
|
||||
|
||||
|
@ -218,8 +221,8 @@ static void
|
|||
SpewPatchStubFrame(ICStub *oldStub, ICStub *newStub)
|
||||
{
|
||||
IonSpew(IonSpew_BaselineDebugModeOSR,
|
||||
"Patch stub %#016llx -> %#016llx to BaselineStub (%s)",
|
||||
uintptr_t(oldStub), uintptr_t(newStub), ICStub::KindString(newStub->kind()));
|
||||
"Patch stub %p -> %p on BaselineStub frame (%s)",
|
||||
oldStub, newStub, ICStub::KindString(newStub->kind()));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -254,8 +257,15 @@ PatchBaselineFramesForDebugMode(JSContext *cx, const JitActivationIterator &acti
|
|||
|
||||
for (JitFrameIterator iter(activation); !iter.done(); ++iter) {
|
||||
DebugModeOSREntry &entry = entries[entryIndex];
|
||||
|
||||
switch (iter.type()) {
|
||||
case JitFrame_BaselineJS: {
|
||||
// If the script wasn't recompiled, there's nothing to patch.
|
||||
if (!entry.recompiled()) {
|
||||
entryIndex++;
|
||||
break;
|
||||
}
|
||||
|
||||
JSScript *script = entry.script;
|
||||
uint32_t pcOffset = entry.pcOffset;
|
||||
jsbytecode *pc = script->offsetToPC(pcOffset);
|
||||
|
@ -351,6 +361,10 @@ PatchBaselineFramesForDebugMode(JSContext *cx, const JitActivationIterator &acti
|
|||
}
|
||||
|
||||
case JitFrame_BaselineStub: {
|
||||
// If the script wasn't recompiled, there's nothing to patch.
|
||||
if (!entry.recompiled())
|
||||
break;
|
||||
|
||||
IonBaselineStubFrameLayout *layout =
|
||||
reinterpret_cast<IonBaselineStubFrameLayout *>(iter.fp());
|
||||
MOZ_ASSERT(entry.script->baselineScript()->debugMode() == expectedDebugMode);
|
||||
|
@ -539,7 +553,7 @@ UndoRecompileBaselineScriptsForDebugMode(JSContext *cx,
|
|||
for (size_t i = 0; i < entries.length(); i++) {
|
||||
JSScript *script = entries[i].script;
|
||||
BaselineScript *baselineScript = script->baselineScript();
|
||||
if (baselineScript != entries[i].oldBaselineScript) {
|
||||
if (entries[i].recompiled()) {
|
||||
script->setBaselineScript(cx, entries[i].oldBaselineScript);
|
||||
BaselineScript::Destroy(cx->runtime()->defaultFreeOp(), baselineScript);
|
||||
}
|
||||
|
@ -587,8 +601,10 @@ jit::RecompileOnStackBaselineScriptsForDebugMode(JSContext *cx, JSCompartment *c
|
|||
//
|
||||
// After this point the function must be infallible.
|
||||
|
||||
for (size_t i = 0; i < entries.length(); i++)
|
||||
BaselineScript::Destroy(cx->runtime()->defaultFreeOp(), entries[i].oldBaselineScript);
|
||||
for (size_t i = 0; i < entries.length(); i++) {
|
||||
if (entries[i].recompiled())
|
||||
BaselineScript::Destroy(cx->runtime()->defaultFreeOp(), entries[i].oldBaselineScript);
|
||||
}
|
||||
|
||||
size_t processed = 0;
|
||||
for (JitActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
|
||||
|
|
|
@ -1271,6 +1271,14 @@ static bool
|
|||
DoTypeMonitorFallback(JSContext *cx, BaselineFrame *frame, ICTypeMonitor_Fallback *stub,
|
||||
HandleValue value, MutableHandleValue res)
|
||||
{
|
||||
// It's possible that we arrived here from bailing out of Ion, and that
|
||||
// Ion proved that the value is dead and optimized out. In such cases, do
|
||||
// nothing.
|
||||
if (value.isMagic(JS_OPTIMIZED_OUT)) {
|
||||
res.set(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedScript script(cx, frame->script());
|
||||
jsbytecode *pc = stub->icEntry()->pc(script);
|
||||
TypeFallbackICSpew(cx, stub, "TypeMonitor");
|
||||
|
|
|
@ -6834,6 +6834,7 @@ CodeGenerator::visitCallsiteCloneCache(LCallsiteCloneCache *ins)
|
|||
Register output = ToRegister(ins->output());
|
||||
|
||||
CallsiteCloneIC cache(callee, mir->block()->info().script(), mir->callPc(), output);
|
||||
cache.setProfilerLeavePC(mir->profilerLeavePc());
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
|
||||
|
@ -6867,6 +6868,7 @@ CodeGenerator::visitGetNameCache(LGetNameCache *ins)
|
|||
bool isTypeOf = ins->mir()->accessKind() != MGetNameCache::NAME;
|
||||
|
||||
NameIC cache(liveRegs, isTypeOf, scopeChain, ins->mir()->name(), output);
|
||||
cache.setProfilerLeavePC(ins->mir()->profilerLeavePc());
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
|
||||
|
@ -6893,15 +6895,17 @@ CodeGenerator::visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic)
|
|||
bool
|
||||
CodeGenerator::addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
PropertyName *name, TypedOrValueRegister output,
|
||||
bool monitoredResult)
|
||||
bool monitoredResult, jsbytecode *profilerLeavePc)
|
||||
{
|
||||
switch (gen->info().executionMode()) {
|
||||
case SequentialExecution: {
|
||||
GetPropertyIC cache(liveRegs, objReg, name, output, monitoredResult);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
case ParallelExecution: {
|
||||
GetPropertyParIC cache(objReg, name, output);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
default:
|
||||
|
@ -6912,15 +6916,17 @@ CodeGenerator::addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Regi
|
|||
bool
|
||||
CodeGenerator::addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
PropertyName *name, ConstantOrRegister value, bool strict,
|
||||
bool needsTypeBarrier)
|
||||
bool needsTypeBarrier, jsbytecode *profilerLeavePc)
|
||||
{
|
||||
switch (gen->info().executionMode()) {
|
||||
case SequentialExecution: {
|
||||
SetPropertyIC cache(liveRegs, objReg, name, value, strict, needsTypeBarrier);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
case ParallelExecution: {
|
||||
SetPropertyParIC cache(objReg, name, value, strict, needsTypeBarrier);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
default:
|
||||
|
@ -6931,17 +6937,20 @@ CodeGenerator::addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Regi
|
|||
bool
|
||||
CodeGenerator::addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex,
|
||||
Register temp, FloatRegister tempFloat, ValueOperand index,
|
||||
ConstantOrRegister value, bool strict, bool guardHoles)
|
||||
ConstantOrRegister value, bool strict, bool guardHoles,
|
||||
jsbytecode *profilerLeavePc)
|
||||
{
|
||||
switch (gen->info().executionMode()) {
|
||||
case SequentialExecution: {
|
||||
SetElementIC cache(obj, unboxIndex, temp, tempFloat, index, value, strict,
|
||||
guardHoles);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
case ParallelExecution: {
|
||||
SetElementParIC cache(obj, unboxIndex, temp, tempFloat, index, value, strict,
|
||||
guardHoles);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
default:
|
||||
|
@ -6958,7 +6967,8 @@ CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV *ins)
|
|||
bool monitoredResult = ins->mir()->monitoredResult();
|
||||
TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
|
||||
|
||||
return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult);
|
||||
return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult,
|
||||
ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -6970,7 +6980,8 @@ CodeGenerator::visitGetPropertyCacheT(LGetPropertyCacheT *ins)
|
|||
bool monitoredResult = ins->mir()->monitoredResult();
|
||||
TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->getDef(0)));
|
||||
|
||||
return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult);
|
||||
return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult,
|
||||
ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
typedef bool (*GetPropertyICFn)(JSContext *, size_t, HandleObject, MutableHandleValue);
|
||||
|
@ -7026,16 +7037,18 @@ CodeGenerator::visitGetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr<GetPrope
|
|||
bool
|
||||
CodeGenerator::addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
|
||||
TypedOrValueRegister output, bool monitoredResult,
|
||||
bool allowDoubleResult)
|
||||
bool allowDoubleResult, jsbytecode *profilerLeavePc)
|
||||
{
|
||||
switch (gen->info().executionMode()) {
|
||||
case SequentialExecution: {
|
||||
RegisterSet liveRegs = ins->safepoint()->liveRegs();
|
||||
GetElementIC cache(liveRegs, obj, index, output, monitoredResult, allowDoubleResult);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
case ParallelExecution: {
|
||||
GetElementParIC cache(obj, index, output, monitoredResult, allowDoubleResult);
|
||||
cache.setProfilerLeavePC(profilerLeavePc);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
default:
|
||||
|
@ -7051,7 +7064,8 @@ CodeGenerator::visitGetElementCacheV(LGetElementCacheV *ins)
|
|||
TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
|
||||
const MGetElementCache *mir = ins->mir();
|
||||
|
||||
return addGetElementCache(ins, obj, index, output, mir->monitoredResult(), mir->allowDoubleResult());
|
||||
return addGetElementCache(ins, obj, index, output, mir->monitoredResult(),
|
||||
mir->allowDoubleResult(), mir->profilerLeavePc());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -7062,7 +7076,8 @@ CodeGenerator::visitGetElementCacheT(LGetElementCacheT *ins)
|
|||
TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->output()));
|
||||
const MGetElementCache *mir = ins->mir();
|
||||
|
||||
return addGetElementCache(ins, obj, index, output, mir->monitoredResult(), mir->allowDoubleResult());
|
||||
return addGetElementCache(ins, obj, index, output, mir->monitoredResult(),
|
||||
mir->allowDoubleResult(), mir->profilerLeavePc());
|
||||
}
|
||||
|
||||
typedef bool (*GetElementICFn)(JSContext *, size_t, HandleObject, HandleValue, MutableHandleValue);
|
||||
|
@ -7098,7 +7113,8 @@ CodeGenerator::visitSetElementCacheV(LSetElementCacheV *ins)
|
|||
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetElementCacheV::Value));
|
||||
|
||||
return addSetElementCache(ins, obj, unboxIndex, temp, tempFloat, index, value,
|
||||
ins->mir()->strict(), ins->mir()->guardHoles());
|
||||
ins->mir()->strict(), ins->mir()->guardHoles(),
|
||||
ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -7117,7 +7133,8 @@ CodeGenerator::visitSetElementCacheT(LSetElementCacheT *ins)
|
|||
value = TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(tmp));
|
||||
|
||||
return addSetElementCache(ins, obj, unboxIndex, temp, tempFloat, index, value,
|
||||
ins->mir()->strict(), ins->mir()->guardHoles());
|
||||
ins->mir()->strict(), ins->mir()->guardHoles(),
|
||||
ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
typedef bool (*SetElementICFn)(JSContext *, size_t, HandleObject, HandleValue, HandleValue);
|
||||
|
@ -7193,6 +7210,7 @@ CodeGenerator::visitBindNameCache(LBindNameCache *ins)
|
|||
Register scopeChain = ToRegister(ins->scopeChain());
|
||||
Register output = ToRegister(ins->output());
|
||||
BindNameIC cache(scopeChain, ins->mir()->name(), output);
|
||||
cache.setProfilerLeavePC(ins->mir()->profilerLeavePc());
|
||||
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
|
@ -7287,7 +7305,8 @@ CodeGenerator::visitSetPropertyCacheV(LSetPropertyCacheV *ins)
|
|||
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetPropertyCacheV::Value));
|
||||
|
||||
return addSetPropertyCache(ins, liveRegs, objReg, ins->mir()->name(), value,
|
||||
ins->mir()->strict(), ins->mir()->needsTypeBarrier());
|
||||
ins->mir()->strict(), ins->mir()->needsTypeBarrier(),
|
||||
ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -7303,7 +7322,8 @@ CodeGenerator::visitSetPropertyCacheT(LSetPropertyCacheT *ins)
|
|||
value = TypedOrValueRegister(ins->valueType(), ToAnyRegister(ins->getOperand(1)));
|
||||
|
||||
return addSetPropertyCache(ins, liveRegs, objReg, ins->mir()->name(), value,
|
||||
ins->mir()->strict(), ins->mir()->needsTypeBarrier());
|
||||
ins->mir()->strict(), ins->mir()->needsTypeBarrier(),
|
||||
ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
typedef bool (*SetPropertyICFn)(JSContext *, size_t, HandleObject, HandleValue);
|
||||
|
|
|
@ -353,16 +353,16 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
private:
|
||||
bool addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
PropertyName *name, TypedOrValueRegister output,
|
||||
bool monitoredResult);
|
||||
bool monitoredResult, jsbytecode *profilerLeavePc);
|
||||
bool addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
|
||||
TypedOrValueRegister output, bool monitoredResult,
|
||||
bool allowDoubleResult);
|
||||
bool allowDoubleResult, jsbytecode *profilerLeavePc);
|
||||
bool addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
PropertyName *name, ConstantOrRegister value, bool strict,
|
||||
bool needsTypeBarrier);
|
||||
bool needsTypeBarrier, jsbytecode *profilerLeavePc);
|
||||
bool addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex, Register temp,
|
||||
FloatRegister tempFloat, ValueOperand index, ConstantOrRegister value,
|
||||
bool strict, bool guardHoles);
|
||||
bool strict, bool guardHoles, jsbytecode *profilerLeavePc);
|
||||
bool checkForAbortPar(LInstruction *lir);
|
||||
|
||||
bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr);
|
||||
|
|
|
@ -80,6 +80,15 @@ class InlineScriptTree {
|
|||
return caller_;
|
||||
}
|
||||
|
||||
bool isOutermostCaller() const {
|
||||
return caller_ == nullptr;
|
||||
}
|
||||
InlineScriptTree *outermostCaller() {
|
||||
if (isOutermostCaller())
|
||||
return this;
|
||||
return caller_->outermostCaller();
|
||||
}
|
||||
|
||||
jsbytecode *callerPc() const {
|
||||
return callerPc_;
|
||||
}
|
||||
|
@ -392,6 +401,15 @@ class CompileInfo
|
|||
return executionMode_ == ParallelExecution;
|
||||
}
|
||||
|
||||
bool canOptimizeOutSlot(uint32_t i) const {
|
||||
if (script()->strict())
|
||||
return true;
|
||||
|
||||
// Function.arguments can be used to access all arguments in
|
||||
// non-strict scripts, so we can't optimize out any arguments.
|
||||
return !(firstArgSlot() <= i && i - firstArgSlot() < nargs());
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned nimplicit_;
|
||||
unsigned nargs_;
|
||||
|
|
|
@ -143,16 +143,12 @@ jit::EliminateDeadResumePointOperands(MIRGenerator *mir, MIRGraph &graph)
|
|||
continue;
|
||||
}
|
||||
|
||||
// Function.arguments can be used to access all arguments in
|
||||
// non-strict scripts, so we can't optimize out any arguments.
|
||||
CompileInfo &info = block->info();
|
||||
if (!info.script()->strict()) {
|
||||
uint32_t slot = uses->index();
|
||||
uint32_t firstArgSlot = info.firstArgSlot();
|
||||
if (firstArgSlot <= slot && slot - firstArgSlot < info.nargs()) {
|
||||
uses++;
|
||||
continue;
|
||||
}
|
||||
// The operand is an uneliminable slot. This currently
|
||||
// includes argument slots in non-strict scripts (due to being
|
||||
// observable via Function.arguments).
|
||||
if (!block->info().canOptimizeOutSlot(uses->index())) {
|
||||
uses++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store an optimized out magic value in place of all dead
|
||||
|
@ -254,18 +250,11 @@ IsPhiObservable(MPhi *phi, Observability observe)
|
|||
return true;
|
||||
}
|
||||
|
||||
// If the Phi is one of the formal argument, and we are using an argument
|
||||
// object in the function. The phi might be observable after a bailout.
|
||||
// For inlined frames this is not needed, as they are captured in the inlineResumePoint.
|
||||
if (fun && info.hasArguments()) {
|
||||
uint32_t first = info.firstArgSlot();
|
||||
if (first <= slot && slot - first < info.nargs()) {
|
||||
// If arguments obj aliases formals, then the arg slots will never be used.
|
||||
if (info.argsObjAliasesFormals())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// The Phi is an uneliminable slot. Currently this includes argument slots
|
||||
// in non-strict scripts (due to being observable via Function.arguments).
|
||||
if (fun && !info.canOptimizeOutSlot(slot))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ using namespace js::jit;
|
|||
|
||||
using mozilla::tl::FloorLog2;
|
||||
|
||||
typedef Rooted<TypedArrayObject *> RootedTypedArrayObject;
|
||||
|
||||
void
|
||||
CodeLocationJump::repoint(JitCode *code, MacroAssembler *masm)
|
||||
{
|
||||
|
@ -1195,11 +1197,13 @@ GetPropertyIC::allowArrayLength(Context cx, HandleObject obj) const
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachNative(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr, bool *emitted)
|
||||
GetPropertyIC::tryAttachNative(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted)
|
||||
{
|
||||
JS_ASSERT(canAttachStub());
|
||||
JS_ASSERT(!*emitted);
|
||||
JS_ASSERT(outerScript->ionScript() == ion);
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
|
@ -1211,7 +1215,7 @@ GetPropertyIC::tryAttachNative(JSContext *cx, IonScript *ion, HandleObject obj,
|
|||
|
||||
*emitted = true;
|
||||
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
const char *attachKind;
|
||||
|
@ -1244,8 +1248,8 @@ GetPropertyIC::tryAttachNative(JSContext *cx, IonScript *ion, HandleObject obj,
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachTypedArrayLength(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, bool *emitted)
|
||||
GetPropertyIC::tryAttachTypedArrayLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, bool *emitted)
|
||||
{
|
||||
JS_ASSERT(canAttachStub());
|
||||
JS_ASSERT(!*emitted);
|
||||
|
@ -1270,7 +1274,7 @@ GetPropertyIC::tryAttachTypedArrayLength(JSContext *cx, IonScript *ion, HandleOb
|
|||
|
||||
*emitted = true;
|
||||
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateTypedArrayLength(cx, masm, attacher, obj, object(), output());
|
||||
|
||||
|
@ -1353,7 +1357,7 @@ EmitCallProxyGet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachDOMProxyShadowed(JSContext *cx, IonScript *ion,
|
||||
GetPropertyIC::tryAttachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, void *returnAddr,
|
||||
bool *emitted)
|
||||
{
|
||||
|
@ -1369,7 +1373,7 @@ GetPropertyIC::tryAttachDOMProxyShadowed(JSContext *cx, IonScript *ion,
|
|||
*emitted = true;
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
// Guard on the shape of the object.
|
||||
|
@ -1399,9 +1403,9 @@ GetPropertyIC::tryAttachDOMProxyShadowed(JSContext *cx, IonScript *ion,
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, bool resetNeeded,
|
||||
void *returnAddr, bool *emitted)
|
||||
GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
bool resetNeeded, void *returnAddr, bool *emitted)
|
||||
{
|
||||
JS_ASSERT(canAttachStub());
|
||||
JS_ASSERT(!*emitted);
|
||||
|
@ -1438,7 +1442,7 @@ GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, Handle
|
|||
}
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
// Guard on the shape of the object.
|
||||
|
@ -1499,9 +1503,9 @@ GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, Handle
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachProxy(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr,
|
||||
bool *emitted)
|
||||
GetPropertyIC::tryAttachProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted)
|
||||
{
|
||||
JS_ASSERT(canAttachStub());
|
||||
JS_ASSERT(!*emitted);
|
||||
|
@ -1521,13 +1525,13 @@ GetPropertyIC::tryAttachProxy(JSContext *cx, IonScript *ion, HandleObject obj,
|
|||
if (shadows == ShadowCheckFailed)
|
||||
return false;
|
||||
if (shadows == Shadows)
|
||||
return tryAttachDOMProxyShadowed(cx, ion, obj, returnAddr, emitted);
|
||||
return tryAttachDOMProxyShadowed(cx, outerScript, ion, obj, returnAddr, emitted);
|
||||
|
||||
return tryAttachDOMProxyUnshadowed(cx, ion, obj, name, shadows == DoesntShadowUnique,
|
||||
returnAddr, emitted);
|
||||
return tryAttachDOMProxyUnshadowed(cx, outerScript, ion, obj, name,
|
||||
shadows == DoesntShadowUnique, returnAddr, emitted);
|
||||
}
|
||||
|
||||
return tryAttachGenericProxy(cx, ion, obj, name, returnAddr, emitted);
|
||||
return tryAttachGenericProxy(cx, outerScript, ion, obj, name, returnAddr, emitted);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1541,8 +1545,8 @@ GenerateProxyClassGuards(MacroAssembler &masm, Register object, Register scratch
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr,
|
||||
GetPropertyIC::tryAttachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, void *returnAddr,
|
||||
bool *emitted)
|
||||
{
|
||||
JS_ASSERT(canAttachStub());
|
||||
|
@ -1560,7 +1564,7 @@ GetPropertyIC::tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject
|
|||
*emitted = true;
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
Register scratchReg = output().valueReg().scratchReg();
|
||||
|
@ -1590,8 +1594,8 @@ GetPropertyIC::tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachArgumentsLength(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, bool *emitted)
|
||||
GetPropertyIC::tryAttachArgumentsLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, bool *emitted)
|
||||
{
|
||||
JS_ASSERT(canAttachStub());
|
||||
JS_ASSERT(!*emitted);
|
||||
|
@ -1613,7 +1617,7 @@ GetPropertyIC::tryAttachArgumentsLength(JSContext *cx, IonScript *ion, HandleObj
|
|||
JS_ASSERT(!idempotent());
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
Register tmpReg;
|
||||
|
@ -1660,24 +1664,25 @@ GetPropertyIC::tryAttachArgumentsLength(JSContext *cx, IonScript *ion, HandleObj
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachStub(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr, bool *emitted)
|
||||
GetPropertyIC::tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted)
|
||||
{
|
||||
JS_ASSERT(!*emitted);
|
||||
|
||||
if (!canAttachStub())
|
||||
return true;
|
||||
|
||||
if (!*emitted && !tryAttachArgumentsLength(cx, ion, obj, name, emitted))
|
||||
if (!*emitted && !tryAttachArgumentsLength(cx, outerScript, ion, obj, name, emitted))
|
||||
return false;
|
||||
|
||||
if (!*emitted && !tryAttachProxy(cx, ion, obj, name, returnAddr, emitted))
|
||||
if (!*emitted && !tryAttachProxy(cx, outerScript, ion, obj, name, returnAddr, emitted))
|
||||
return false;
|
||||
|
||||
if (!*emitted && !tryAttachNative(cx, ion, obj, name, returnAddr, emitted))
|
||||
if (!*emitted && !tryAttachNative(cx, outerScript, ion, obj, name, returnAddr, emitted))
|
||||
return false;
|
||||
|
||||
if (!*emitted && !tryAttachTypedArrayLength(cx, ion, obj, name, emitted))
|
||||
if (!*emitted && !tryAttachTypedArrayLength(cx, outerScript, ion, obj, name, emitted))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -1688,8 +1693,8 @@ GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
|
|||
HandleObject obj, MutableHandleValue vp)
|
||||
{
|
||||
void *returnAddr;
|
||||
RootedScript topScript(cx, GetTopIonJSScript(cx, &returnAddr));
|
||||
IonScript *ion = topScript->ionScript();
|
||||
RootedScript outerScript(cx, GetTopIonJSScript(cx, &returnAddr));
|
||||
IonScript *ion = outerScript->ionScript();
|
||||
|
||||
GetPropertyIC &cache = ion->getCache(cacheIndex).toGetProperty();
|
||||
RootedPropertyName name(cx, cache.name());
|
||||
|
@ -1707,7 +1712,7 @@ GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
|
|||
// limit. Once we can make calls from within generated stubs, a new call
|
||||
// stub will be generated instead and the previous stubs unlinked.
|
||||
bool emitted = false;
|
||||
if (!cache.tryAttachStub(cx, ion, obj, name, returnAddr, &emitted))
|
||||
if (!cache.tryAttachStub(cx, outerScript, ion, obj, name, returnAddr, &emitted))
|
||||
return false;
|
||||
|
||||
if (cache.idempotent() && !emitted) {
|
||||
|
@ -1718,15 +1723,15 @@ GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
|
|||
// be complicated since (due to GVN) there can be multiple pc's
|
||||
// associated with a single idempotent cache.
|
||||
IonSpew(IonSpew_InlineCaches, "Invalidating from idempotent cache %s:%d",
|
||||
topScript->filename(), topScript->lineno());
|
||||
outerScript->filename(), outerScript->lineno());
|
||||
|
||||
topScript->setInvalidatedIdempotentCache();
|
||||
outerScript->setInvalidatedIdempotentCache();
|
||||
|
||||
// Do not re-invalidate if the lookup already caused invalidation.
|
||||
if (!topScript->hasIonScript())
|
||||
if (!outerScript->hasIonScript())
|
||||
return true;
|
||||
|
||||
return Invalidate(cx, topScript);
|
||||
return Invalidate(cx, outerScript);
|
||||
}
|
||||
|
||||
RootedId id(cx, NameToId(name));
|
||||
|
@ -1814,8 +1819,8 @@ GetPropertyParIC::reset()
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj,
|
||||
JSObject *holder, Shape *shape)
|
||||
GetPropertyParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
HandleObject holder, HandleShape shape)
|
||||
{
|
||||
// Ready to generate the read slot stub.
|
||||
DispatchStubPrepender attacher(*this);
|
||||
|
@ -1826,7 +1831,7 @@ GetPropertyParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyParIC::attachArrayLength(LockedJSContext &cx, IonScript *ion, JSObject *obj)
|
||||
GetPropertyParIC::attachArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
DispatchStubPrepender attacher(*this);
|
||||
|
@ -1837,7 +1842,7 @@ GetPropertyParIC::attachArrayLength(LockedJSContext &cx, IonScript *ion, JSObjec
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropertyParIC::attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, JSObject *obj)
|
||||
GetPropertyParIC::attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
DispatchStubPrepender attacher(*this);
|
||||
|
@ -2005,10 +2010,10 @@ GenerateSetSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyIC::attachSetSlot(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandleShape shape, bool checkTypeset)
|
||||
SetPropertyIC::attachSetSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleShape shape, bool checkTypeset)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateSetSlot(cx, masm, attacher, obj, shape, object(), value(), needsTypeBarrier(),
|
||||
checkTypeset);
|
||||
|
@ -2124,11 +2129,12 @@ EmitCallProxySet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyIC::attachGenericProxy(JSContext *cx, IonScript *ion, void *returnAddr)
|
||||
SetPropertyIC::attachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
void *returnAddr)
|
||||
{
|
||||
JS_ASSERT(!hasGenericProxyStub());
|
||||
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
Label failures;
|
||||
|
@ -2179,13 +2185,13 @@ SetPropertyIC::attachGenericProxy(JSContext *cx, IonScript *ion, void *returnAdd
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyIC::attachDOMProxyShadowed(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
void *returnAddr)
|
||||
SetPropertyIC::attachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, void *returnAddr)
|
||||
{
|
||||
JS_ASSERT(IsCacheableDOMProxy(obj));
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
// Guard on the shape of the object.
|
||||
|
@ -2406,13 +2412,13 @@ IsCacheableDOMProxyUnshadowedSetterCall(JSContext *cx, HandleObject obj, HandleP
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyIC::attachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
void *returnAddr)
|
||||
SetPropertyIC::attachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, void *returnAddr)
|
||||
{
|
||||
JS_ASSERT(IsCacheableDOMProxy(obj));
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
// Guard on the shape of the object.
|
||||
|
@ -2461,13 +2467,13 @@ SetPropertyIC::attachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObj
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyIC::attachCallSetter(JSContext *cx, IonScript *ion,
|
||||
SetPropertyIC::attachCallSetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleObject holder, HandleShape shape,
|
||||
void *returnAddr)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
Label failure;
|
||||
|
@ -2574,12 +2580,12 @@ GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyIC::attachAddSlot(JSContext *cx, IonScript *ion, JSObject *obj, HandleShape oldShape,
|
||||
bool checkTypeset)
|
||||
SetPropertyIC::attachAddSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleShape oldShape, bool checkTypeset)
|
||||
{
|
||||
JS_ASSERT_IF(!needsTypeBarrier(), !checkTypeset);
|
||||
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateAddSlot(cx, masm, attacher, obj, oldShape, object(), value(), checkTypeset);
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "adding");
|
||||
|
@ -2770,21 +2776,21 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
|||
if (shadows == ShadowCheckFailed)
|
||||
return false;
|
||||
if (shadows == Shadows) {
|
||||
if (!cache.attachDOMProxyShadowed(cx, ion, obj, returnAddr))
|
||||
if (!cache.attachDOMProxyShadowed(cx, script, ion, obj, returnAddr))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
} else {
|
||||
JS_ASSERT(shadows == DoesntShadow || shadows == DoesntShadowUnique);
|
||||
if (shadows == DoesntShadowUnique)
|
||||
cache.reset();
|
||||
if (!cache.attachDOMProxyUnshadowed(cx, ion, obj, returnAddr))
|
||||
if (!cache.attachDOMProxyUnshadowed(cx, script, ion, obj, returnAddr))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!addedSetterStub && !cache.hasGenericProxyStub()) {
|
||||
if (!cache.attachGenericProxy(cx, ion, returnAddr))
|
||||
if (!cache.attachGenericProxy(cx, script, ion, returnAddr))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
}
|
||||
|
@ -2803,13 +2809,13 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
|||
&holder, &shape, &checkTypeset);
|
||||
|
||||
if (!addedSetterStub && canCache == CanAttachSetSlot) {
|
||||
if (!cache.attachSetSlot(cx, ion, obj, shape, checkTypeset))
|
||||
if (!cache.attachSetSlot(cx, script, ion, obj, shape, checkTypeset))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
}
|
||||
|
||||
if (!addedSetterStub && canCache == CanAttachCallSetter) {
|
||||
if (!cache.attachCallSetter(cx, ion, obj, holder, shape, returnAddr))
|
||||
if (!cache.attachCallSetter(cx, script, ion, obj, holder, shape, returnAddr))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
}
|
||||
|
@ -2828,7 +2834,7 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
|||
IsPropertyAddInlineable(obj, id, cache.value(), oldSlots, oldShape, cache.needsTypeBarrier(),
|
||||
&checkTypeset))
|
||||
{
|
||||
if (!cache.attachAddSlot(cx, ion, obj, oldShape, checkTypeset))
|
||||
if (!cache.attachAddSlot(cx, script, ion, obj, oldShape, checkTypeset))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2921,8 +2927,8 @@ SetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject ob
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyParIC::attachSetSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, Shape *shape,
|
||||
bool checkTypeset)
|
||||
SetPropertyParIC::attachSetSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
HandleShape shape, bool checkTypeset)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
DispatchStubPrepender attacher(*this);
|
||||
|
@ -2932,8 +2938,8 @@ SetPropertyParIC::attachSetSlot(LockedJSContext &cx, IonScript *ion, JSObject *o
|
|||
}
|
||||
|
||||
bool
|
||||
SetPropertyParIC::attachAddSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, Shape *oldShape,
|
||||
bool checkTypeset)
|
||||
SetPropertyParIC::attachAddSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
HandleShape oldShape, bool checkTypeset)
|
||||
{
|
||||
JS_ASSERT_IF(!needsTypeBarrier(), !checkTypeset);
|
||||
|
||||
|
@ -2969,8 +2975,8 @@ EqualStringsHelper(JSString *str1, JSString *str2)
|
|||
}
|
||||
|
||||
bool
|
||||
GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
const Value &idval, HandlePropertyName name,
|
||||
GetElementIC::attachGetProp(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval, HandlePropertyName name,
|
||||
void *returnAddr)
|
||||
{
|
||||
JS_ASSERT(index().reg().hasValue());
|
||||
|
@ -2995,7 +3001,7 @@ GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
|
|||
JS_ASSERT(idval.toString()->length() == name->length());
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
|
||||
// Ensure the index is a string.
|
||||
ValueOperand val = index().reg().valueReg();
|
||||
|
@ -3128,9 +3134,10 @@ GenerateDenseElement(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher
|
|||
}
|
||||
|
||||
bool
|
||||
GetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval)
|
||||
GetElementIC::attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateDenseElement(cx, masm, attacher, obj, idval, object(), index(), output()))
|
||||
return false;
|
||||
|
@ -3179,7 +3186,7 @@ GetElementIC::canAttachTypedArrayElement(JSObject *obj, const Value &idval,
|
|||
|
||||
static void
|
||||
GenerateGetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
TypedArrayObject *tarr, const Value &idval, Register object,
|
||||
HandleTypedArrayObject tarr, const Value &idval, Register object,
|
||||
ConstantOrRegister index, TypedOrValueRegister output,
|
||||
bool allowDoubleResult)
|
||||
{
|
||||
|
@ -3282,10 +3289,10 @@ GenerateGetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::Stub
|
|||
}
|
||||
|
||||
bool
|
||||
GetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr,
|
||||
const Value &idval)
|
||||
GetElementIC::attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleTypedArrayObject tarr, const Value &idval)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateGetTypedArrayElement(cx, masm, attacher, tarr, idval, object(), index(), output(),
|
||||
allowDoubleResult());
|
||||
|
@ -3293,12 +3300,13 @@ GetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayO
|
|||
}
|
||||
|
||||
bool
|
||||
GetElementIC::attachArgumentsElement(JSContext *cx, IonScript *ion, JSObject *obj)
|
||||
GetElementIC::attachArgumentsElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj)
|
||||
{
|
||||
JS_ASSERT(obj->is<ArgumentsObject>());
|
||||
|
||||
Label failures;
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
Register tmpReg = output().scratchReg().gpr();
|
||||
|
@ -3406,7 +3414,8 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
|||
HandleValue idval, MutableHandleValue res)
|
||||
{
|
||||
void *returnAddr;
|
||||
IonScript *ion = GetTopIonJSScript(cx, &returnAddr)->ionScript();
|
||||
RootedScript outerScript(cx, GetTopIonJSScript(cx, &returnAddr));
|
||||
IonScript *ion = outerScript->ionScript();
|
||||
GetElementIC &cache = ion->getCache(cacheIndex).toGetElement();
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
|
@ -3438,24 +3447,24 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
|||
cache.index().reg().type() == MIRType_Int32) &&
|
||||
(cache.output().hasValue() || !cache.output().typedReg().isFloat()))
|
||||
{
|
||||
if (!cache.attachArgumentsElement(cx, ion, obj))
|
||||
if (!cache.attachArgumentsElement(cx, outerScript, ion, obj))
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
if (!attachedStub && cache.monitoredResult() && canAttachGetProp(obj, idval, id)) {
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
if (!cache.attachGetProp(cx, ion, obj, idval, name, returnAddr))
|
||||
if (!cache.attachGetProp(cx, outerScript, ion, obj, idval, name, returnAddr))
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
if (!attachedStub && !cache.hasDenseStub() && canAttachDenseElement(obj, idval)) {
|
||||
if (!cache.attachDenseElement(cx, ion, obj, idval))
|
||||
if (!cache.attachDenseElement(cx, outerScript, ion, obj, idval))
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
if (!attachedStub && canAttachTypedArrayElement(obj, idval, cache.output())) {
|
||||
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
|
||||
if (!cache.attachTypedArrayElement(cx, ion, tarr, idval))
|
||||
if (!cache.attachTypedArrayElement(cx, outerScript, ion, tarr, idval))
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
|
@ -3677,9 +3686,10 @@ GenerateSetDenseElement(JSContext *cx, MacroAssembler &masm, IonCache::StubAttac
|
|||
}
|
||||
|
||||
bool
|
||||
SetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval)
|
||||
SetElementIC::attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateSetDenseElement(cx, masm, attacher, obj, idval,
|
||||
guardHoles(), object(), index(),
|
||||
|
@ -3698,7 +3708,7 @@ SetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, c
|
|||
|
||||
static bool
|
||||
GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
TypedArrayObject *tarr, Register object,
|
||||
HandleTypedArrayObject tarr, Register object,
|
||||
ValueOperand indexVal, ConstantOrRegister value,
|
||||
Register tempUnbox, Register temp, FloatRegister tempFloat)
|
||||
{
|
||||
|
@ -3780,9 +3790,10 @@ GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::Stub
|
|||
}
|
||||
|
||||
bool
|
||||
SetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr)
|
||||
SetElementIC::attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleTypedArrayObject tarr)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateSetTypedArrayElement(cx, masm, attacher, tarr,
|
||||
object(), index(), value(),
|
||||
|
@ -3798,19 +3809,20 @@ bool
|
|||
SetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
HandleValue idval, HandleValue value)
|
||||
{
|
||||
IonScript *ion = GetTopIonJSScript(cx)->ionScript();
|
||||
RootedScript outerScript(cx, GetTopIonJSScript(cx));
|
||||
IonScript *ion = outerScript->ionScript();
|
||||
SetElementIC &cache = ion->getCache(cacheIndex).toSetElement();
|
||||
|
||||
bool attachedStub = false;
|
||||
if (cache.canAttachStub()) {
|
||||
if (!cache.hasDenseStub() && IsDenseElementSetInlineable(obj, idval)) {
|
||||
if (!cache.attachDenseElement(cx, ion, obj, idval))
|
||||
if (!cache.attachDenseElement(cx, outerScript, ion, obj, idval))
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
if (!attachedStub && IsTypedArrayElementSetInlineable(obj, idval, value)) {
|
||||
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
|
||||
if (!cache.attachTypedArrayElement(cx, ion, tarr))
|
||||
RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
|
||||
if (!cache.attachTypedArrayElement(cx, outerScript, ion, tarr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3828,7 +3840,7 @@ SetElementIC::reset()
|
|||
}
|
||||
|
||||
bool
|
||||
SetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObject *obj,
|
||||
SetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
const Value &idval)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
|
@ -3850,7 +3862,7 @@ SetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObjec
|
|||
|
||||
bool
|
||||
SetElementParIC::attachTypedArrayElement(LockedJSContext &cx, IonScript *ion,
|
||||
TypedArrayObject *tarr)
|
||||
HandleTypedArrayObject tarr)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
DispatchStubPrepender attacher(*this);
|
||||
|
@ -3892,7 +3904,7 @@ SetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
|
|||
attachedStub = true;
|
||||
}
|
||||
if (!attachedStub && IsTypedArrayElementSetInlineable(obj, idval, value)) {
|
||||
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
|
||||
RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
|
||||
if (!cache.attachTypedArrayElement(ncx, ion, tarr))
|
||||
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
|
||||
}
|
||||
|
@ -3903,9 +3915,9 @@ SetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
|
|||
}
|
||||
|
||||
bool
|
||||
GetElementParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj,
|
||||
const Value &idval, PropertyName *name, JSObject *holder,
|
||||
Shape *shape)
|
||||
GetElementParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
const Value &idval, HandlePropertyName name, HandleObject holder,
|
||||
HandleShape shape)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
DispatchStubPrepender attacher(*this);
|
||||
|
@ -3922,7 +3934,7 @@ GetElementParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *o
|
|||
}
|
||||
|
||||
bool
|
||||
GetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObject *obj,
|
||||
GetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
const Value &idval)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
|
@ -3935,7 +3947,7 @@ GetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObjec
|
|||
|
||||
bool
|
||||
GetElementParIC::attachTypedArrayElement(LockedJSContext &cx, IonScript *ion,
|
||||
TypedArrayObject *tarr, const Value &idval)
|
||||
HandleTypedArrayObject tarr, const Value &idval)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
DispatchStubPrepender attacher(*this);
|
||||
|
@ -4004,7 +4016,8 @@ GetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
|
|||
if (!attachedStub &&
|
||||
GetElementIC::canAttachTypedArrayElement(obj, idval, cache.output()))
|
||||
{
|
||||
if (!cache.attachTypedArrayElement(ncx, ion, &obj->as<TypedArrayObject>(), idval))
|
||||
RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
|
||||
if (!cache.attachTypedArrayElement(ncx, ion, tarr, idval))
|
||||
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
|
||||
attachedStub = true;
|
||||
}
|
||||
|
@ -4015,11 +4028,12 @@ GetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj
|
|||
}
|
||||
|
||||
bool
|
||||
BindNameIC::attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain)
|
||||
BindNameIC::attachGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject scopeChain)
|
||||
{
|
||||
JS_ASSERT(scopeChain->is<GlobalObject>());
|
||||
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
// Guard on the scope chain.
|
||||
|
@ -4090,11 +4104,12 @@ GenerateScopeChainGuards(MacroAssembler &masm, JSObject *scopeChain, JSObject *h
|
|||
}
|
||||
|
||||
bool
|
||||
BindNameIC::attachNonGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain, JSObject *holder)
|
||||
BindNameIC::attachNonGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject scopeChain, HandleObject holder)
|
||||
{
|
||||
JS_ASSERT(IsCacheableNonGlobalScope(scopeChain));
|
||||
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
// Guard on the shape of the scope chain.
|
||||
|
@ -4153,7 +4168,8 @@ BindNameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain)
|
|||
{
|
||||
AutoFlushCache afc ("BindNameCache", cx->runtime()->jitRuntime());
|
||||
|
||||
IonScript *ion = GetTopIonJSScript(cx)->ionScript();
|
||||
RootedScript outerScript(cx, GetTopIonJSScript(cx));
|
||||
IonScript *ion = outerScript->ionScript();
|
||||
BindNameIC &cache = ion->getCache(cacheIndex).toBindName();
|
||||
HandlePropertyName name = cache.name();
|
||||
|
||||
|
@ -4169,10 +4185,10 @@ BindNameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain)
|
|||
// GetPropertyCache.
|
||||
if (cache.canAttachStub()) {
|
||||
if (scopeChain->is<GlobalObject>()) {
|
||||
if (!cache.attachGlobal(cx, ion, scopeChain))
|
||||
if (!cache.attachGlobal(cx, outerScript, ion, scopeChain))
|
||||
return nullptr;
|
||||
} else if (IsCacheableScopeChain(scopeChain, holder)) {
|
||||
if (!cache.attachNonGlobal(cx, ion, scopeChain, holder))
|
||||
if (!cache.attachNonGlobal(cx, outerScript, ion, scopeChain, holder))
|
||||
return nullptr;
|
||||
} else {
|
||||
IonSpew(IonSpew_InlineCaches, "BINDNAME uncacheable scope chain");
|
||||
|
@ -4183,11 +4199,11 @@ BindNameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain)
|
|||
}
|
||||
|
||||
bool
|
||||
NameIC::attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain,
|
||||
HandleObject holderBase, HandleObject holder,
|
||||
HandleShape shape)
|
||||
NameIC::attachReadSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject scopeChain, HandleObject holderBase,
|
||||
HandleObject holder, HandleShape shape)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
Label failures;
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
|
@ -4247,10 +4263,11 @@ IsCacheableNameReadSlot(JSContext *cx, HandleObject scopeChain, HandleObject obj
|
|||
}
|
||||
|
||||
bool
|
||||
NameIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
HandleShape shape, void *returnAddr)
|
||||
NameIC::attachCallGetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleObject holder, HandleShape shape,
|
||||
void *returnAddr)
|
||||
{
|
||||
MacroAssembler masm(cx, ion, script_, pc_);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
|
@ -4283,7 +4300,8 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
|
|||
AutoFlushCache afc ("GetNameCache", cx->runtime()->jitRuntime());
|
||||
|
||||
void *returnAddr;
|
||||
IonScript *ion = GetTopIonJSScript(cx, &returnAddr)->ionScript();
|
||||
RootedScript outerScript(cx, GetTopIonJSScript(cx, &returnAddr));
|
||||
IonScript *ion = outerScript->ionScript();
|
||||
|
||||
NameIC &cache = ion->getCache(cacheIndex).toName();
|
||||
RootedPropertyName name(cx, cache.name());
|
||||
|
@ -4300,10 +4318,10 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
|
|||
|
||||
if (cache.canAttachStub()) {
|
||||
if (IsCacheableNameReadSlot(cx, scopeChain, obj, holder, shape, pc, cache.outputReg())) {
|
||||
if (!cache.attachReadSlot(cx, ion, scopeChain, obj, holder, shape))
|
||||
if (!cache.attachReadSlot(cx, outerScript, ion, scopeChain, obj, holder, shape))
|
||||
return false;
|
||||
} else if (IsCacheableNameCallGetter(scopeChain, obj, holder, shape)) {
|
||||
if (!cache.attachCallGetter(cx, ion, obj, holder, shape, returnAddr))
|
||||
if (!cache.attachCallGetter(cx, outerScript, ion, obj, holder, shape, returnAddr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4323,10 +4341,10 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
|
|||
}
|
||||
|
||||
bool
|
||||
CallsiteCloneIC::attach(JSContext *cx, IonScript *ion, HandleFunction original,
|
||||
HandleFunction clone)
|
||||
CallsiteCloneIC::attach(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleFunction original, HandleFunction clone)
|
||||
{
|
||||
MacroAssembler masm(cx, ion);
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
// Guard against object identity on the original.
|
||||
|
@ -4351,7 +4369,8 @@ CallsiteCloneIC::update(JSContext *cx, size_t cacheIndex, HandleObject callee)
|
|||
if (!fun->hasScript() || !fun->nonLazyScript()->shouldCloneAtCallsite())
|
||||
return fun;
|
||||
|
||||
IonScript *ion = GetTopIonJSScript(cx)->ionScript();
|
||||
RootedScript outerScript(cx, GetTopIonJSScript(cx));
|
||||
IonScript *ion = outerScript->ionScript();
|
||||
CallsiteCloneIC &cache = ion->getCache(cacheIndex).toCallsiteClone();
|
||||
|
||||
RootedFunction clone(cx, CloneFunctionAtCallsite(cx, fun, cache.callScript(), cache.callPc()));
|
||||
|
@ -4359,7 +4378,7 @@ CallsiteCloneIC::update(JSContext *cx, size_t cacheIndex, HandleObject callee)
|
|||
return nullptr;
|
||||
|
||||
if (cache.canAttachStub()) {
|
||||
if (!cache.attach(cx, ion, fun, clone))
|
||||
if (!cache.attach(cx, outerScript, ion, fun, clone))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace js {
|
|||
class LockedJSContext;
|
||||
class TypedArrayObject;
|
||||
|
||||
typedef Handle<TypedArrayObject *> HandleTypedArrayObject;
|
||||
|
||||
namespace jit {
|
||||
|
||||
#define IONCACHE_KIND_LIST(_) \
|
||||
|
@ -168,6 +170,10 @@ class IonCache
|
|||
JSScript *script_;
|
||||
jsbytecode *pc_;
|
||||
|
||||
// Location to use when updating profiler pseudostack when leaving this
|
||||
// IC code to enter a callee.
|
||||
jsbytecode *profilerLeavePc_;
|
||||
|
||||
private:
|
||||
static const size_t MAX_STUBS;
|
||||
void incrementStubCount() {
|
||||
|
@ -185,7 +191,8 @@ class IonCache
|
|||
stubCount_(0),
|
||||
fallbackLabel_(),
|
||||
script_(nullptr),
|
||||
pc_(nullptr)
|
||||
pc_(nullptr),
|
||||
profilerLeavePc_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -201,6 +208,11 @@ class IonCache
|
|||
fallbackLabel_ = fallbackLabel;
|
||||
}
|
||||
|
||||
void setProfilerLeavePC(jsbytecode *pc) {
|
||||
JS_ASSERT(pc != nullptr);
|
||||
profilerLeavePc_ = pc;
|
||||
}
|
||||
|
||||
virtual void emitInitialJump(MacroAssembler &masm, AddCacheState &addState) = 0;
|
||||
virtual void bindInitialJump(MacroAssembler &masm, AddCacheState &addState) = 0;
|
||||
virtual void updateBaseAddress(JitCode *code, MacroAssembler &masm);
|
||||
|
@ -614,24 +626,34 @@ class GetPropertyIC : public RepatchIonCache
|
|||
}
|
||||
|
||||
// Attach the proper stub, if possible
|
||||
bool tryAttachStub(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr, bool *emitted);
|
||||
bool tryAttachProxy(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr, bool *emitted);
|
||||
bool tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr, bool *emitted);
|
||||
bool tryAttachDOMProxyShadowed(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
void *returnAddr, bool *emitted);
|
||||
bool tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, bool resetNeeded,
|
||||
void *returnAddr, bool *emitted);
|
||||
bool tryAttachNative(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, void *returnAddr, bool *emitted);
|
||||
bool tryAttachTypedArrayLength(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, bool *emitted);
|
||||
bool tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachArgumentsLength(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandlePropertyName name, bool *emitted);
|
||||
bool tryAttachProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, bool resetNeeded,
|
||||
void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachNative(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachTypedArrayLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, bool *emitted);
|
||||
|
||||
bool tryAttachArgumentsLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, bool *emitted);
|
||||
|
||||
static bool update(JSContext *cx, size_t cacheIndex, HandleObject obj, MutableHandleValue vp);
|
||||
};
|
||||
|
@ -694,20 +716,26 @@ class SetPropertyIC : public RepatchIonCache
|
|||
CanAttachCallSetter
|
||||
};
|
||||
|
||||
bool attachSetSlot(JSContext *cx, IonScript *ion, HandleObject obj, HandleShape shape,
|
||||
bool checkTypeset);
|
||||
bool attachCallSetter(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandleObject holder, HandleShape shape, void *returnAddr);
|
||||
bool attachAddSlot(JSContext *cx, IonScript *ion, JSObject *obj, HandleShape oldShape,
|
||||
bool checkTypeset);
|
||||
bool attachGenericProxy(JSContext *cx, IonScript *ion, void *returnAddr);
|
||||
bool attachDOMProxyShadowed(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
void *returnAddr);
|
||||
bool attachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
void *returnAddr);
|
||||
bool attachSetSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleShape shape, bool checkTypeset);
|
||||
|
||||
static bool
|
||||
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue value);
|
||||
bool attachCallSetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleObject holder, HandleShape shape,
|
||||
void *returnAddr);
|
||||
|
||||
bool attachAddSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleShape oldShape, bool checkTypeset);
|
||||
|
||||
bool attachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
void *returnAddr);
|
||||
|
||||
bool attachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, void *returnAddr);
|
||||
|
||||
bool attachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, void *returnAddr);
|
||||
|
||||
static bool update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue value);
|
||||
};
|
||||
|
||||
class GetElementIC : public RepatchIonCache
|
||||
|
@ -788,12 +816,18 @@ class GetElementIC : public RepatchIonCache
|
|||
static bool canAttachTypedArrayElement(JSObject *obj, const Value &idval,
|
||||
TypedOrValueRegister output);
|
||||
|
||||
bool attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj, const Value &idval,
|
||||
HandlePropertyName name, void *returnAddr);
|
||||
bool attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
|
||||
bool attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr,
|
||||
const Value &idval);
|
||||
bool attachArgumentsElement(JSContext *cx, IonScript *ion, JSObject *obj);
|
||||
bool attachGetProp(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval, HandlePropertyName name,
|
||||
void *returnAddr);
|
||||
|
||||
bool attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval);
|
||||
|
||||
bool attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleTypedArrayObject tarr, const Value &idval);
|
||||
|
||||
bool attachArgumentsElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj);
|
||||
|
||||
static bool
|
||||
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,
|
||||
|
@ -878,8 +912,11 @@ class SetElementIC : public RepatchIonCache
|
|||
hasDenseStub_ = true;
|
||||
}
|
||||
|
||||
bool attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
|
||||
bool attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr);
|
||||
bool attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval);
|
||||
|
||||
bool attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleTypedArrayObject tarr);
|
||||
|
||||
static bool
|
||||
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,
|
||||
|
@ -913,8 +950,11 @@ class BindNameIC : public RepatchIonCache
|
|||
return output_;
|
||||
}
|
||||
|
||||
bool attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain);
|
||||
bool attachNonGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain, JSObject *holder);
|
||||
bool attachGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject scopeChain);
|
||||
|
||||
bool attachNonGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject scopeChain, HandleObject holder);
|
||||
|
||||
static JSObject *
|
||||
update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain);
|
||||
|
@ -959,10 +999,13 @@ class NameIC : public RepatchIonCache
|
|||
return typeOf_;
|
||||
}
|
||||
|
||||
bool attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain,
|
||||
HandleObject holderBase, HandleObject holder, HandleShape shape);
|
||||
bool attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
HandleShape shape, void *returnAddr);
|
||||
bool attachReadSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject scopeChain, HandleObject holderBase,
|
||||
HandleObject holder, HandleShape shape);
|
||||
|
||||
bool attachCallGetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleObject holder, HandleShape shape,
|
||||
void *returnAddr);
|
||||
|
||||
static bool
|
||||
update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain, MutableHandleValue vp);
|
||||
|
@ -1000,7 +1043,8 @@ class CallsiteCloneIC : public RepatchIonCache
|
|||
return output_;
|
||||
}
|
||||
|
||||
bool attach(JSContext *cx, IonScript *ion, HandleFunction original, HandleFunction clone);
|
||||
bool attach(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleFunction original, HandleFunction clone);
|
||||
|
||||
static JSObject *update(JSContext *cx, size_t cacheIndex, HandleObject callee);
|
||||
};
|
||||
|
@ -1072,10 +1116,10 @@ class GetPropertyParIC : public ParallelIonCache
|
|||
bool allowGetters() const { return false; }
|
||||
bool allowArrayLength(Context, HandleObject) const { return true; }
|
||||
|
||||
bool attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
Shape *shape);
|
||||
bool attachArrayLength(LockedJSContext &cx, IonScript *ion, JSObject *obj);
|
||||
bool attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, JSObject *obj);
|
||||
bool attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj, HandleObject holder,
|
||||
HandleShape shape);
|
||||
bool attachArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj);
|
||||
bool attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj);
|
||||
|
||||
static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
MutableHandleValue vp);
|
||||
|
@ -1132,10 +1176,11 @@ class GetElementParIC : public ParallelIonCache
|
|||
bool allowGetters() const { return false; }
|
||||
bool allowArrayLength(Context, HandleObject) const { return false; }
|
||||
|
||||
bool attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, const Value &idval,
|
||||
PropertyName *name, JSObject *holder, Shape *shape);
|
||||
bool attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObject *obj, const Value &idval);
|
||||
bool attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, TypedArrayObject *tarr,
|
||||
bool attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj, const Value &idval,
|
||||
HandlePropertyName name, HandleObject holder, HandleShape shape);
|
||||
bool attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
const Value &idval);
|
||||
bool attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, HandleTypedArrayObject tarr,
|
||||
const Value &idval);
|
||||
|
||||
static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,
|
||||
|
@ -1187,9 +1232,9 @@ class SetPropertyParIC : public ParallelIonCache
|
|||
return needsTypeBarrier_;
|
||||
}
|
||||
|
||||
bool attachSetSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, Shape *shape,
|
||||
bool attachSetSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj, HandleShape shape,
|
||||
bool checkTypeset);
|
||||
bool attachAddSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, Shape *oldShape,
|
||||
bool attachAddSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj, HandleShape oldShape,
|
||||
bool checkTypeset);
|
||||
|
||||
static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
|
@ -1256,8 +1301,9 @@ class SetElementParIC : public ParallelIonCache
|
|||
return guardHoles_;
|
||||
}
|
||||
|
||||
bool attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObject *obj, const Value &idval);
|
||||
bool attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, TypedArrayObject *tarr);
|
||||
bool attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj,
|
||||
const Value &idval);
|
||||
bool attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, HandleTypedArrayObject tarr);
|
||||
|
||||
static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
HandleValue idval, HandleValue value);
|
||||
|
|
|
@ -952,6 +952,10 @@ class LRecoverInfo : public TempObject
|
|||
bool operator !=(const OperandIter &where) const {
|
||||
return it_ != where.it_ || op_ != where.op_;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool canOptimizeOutIfUnused();
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1621,7 +1621,7 @@ MAdd::fallible() const
|
|||
{
|
||||
// the add is fallible if range analysis does not say that it is finite, AND
|
||||
// either the truncation analysis shows that there are non-truncated uses.
|
||||
if (truncateKind() >= IndirectTruncate)
|
||||
if (isTruncated())
|
||||
return false;
|
||||
if (range() && range()->hasInt32Bounds())
|
||||
return false;
|
||||
|
@ -1632,7 +1632,7 @@ bool
|
|||
MSub::fallible() const
|
||||
{
|
||||
// see comment in MAdd::fallible()
|
||||
if (truncateKind() >= IndirectTruncate)
|
||||
if (isTruncated())
|
||||
return false;
|
||||
if (range() && range()->hasInt32Bounds())
|
||||
return false;
|
||||
|
|
161
js/src/jit/MIR.h
161
js/src/jit/MIR.h
|
@ -378,13 +378,34 @@ class MDefinition : public MNode
|
|||
const BytecodeSite &trackedSite() const {
|
||||
return trackedSite_;
|
||||
}
|
||||
jsbytecode *trackedPc() {
|
||||
jsbytecode *trackedPc() const {
|
||||
return trackedSite_.pc();
|
||||
}
|
||||
InlineScriptTree *trackedTree() {
|
||||
InlineScriptTree *trackedTree() const {
|
||||
return trackedSite_.tree();
|
||||
}
|
||||
|
||||
JSScript *profilerLeaveScript() const {
|
||||
return trackedTree()->outermostCaller()->script();
|
||||
}
|
||||
|
||||
jsbytecode *profilerLeavePc() const {
|
||||
// If this is in a top-level function, use the pc directly.
|
||||
if (trackedTree()->isOutermostCaller())
|
||||
return trackedPc();
|
||||
|
||||
// Walk up the InlineScriptTree chain to find the top-most callPC
|
||||
InlineScriptTree *curTree = trackedTree();
|
||||
InlineScriptTree *callerTree = curTree->caller();
|
||||
while (!callerTree->isOutermostCaller()) {
|
||||
curTree = callerTree;
|
||||
callerTree = curTree->caller();
|
||||
}
|
||||
|
||||
// Return the callPc of the topmost inlined script.
|
||||
return curTree->callerPc();
|
||||
}
|
||||
|
||||
// Return the range of this value, *before* any bailout checks. Contrast
|
||||
// this with the type() method, and the Range constructor which takes an
|
||||
// MDefinition*, which describe the value *after* any bailout checks.
|
||||
|
@ -412,44 +433,8 @@ class MDefinition : public MNode
|
|||
virtual void analyzeEdgeCasesForward();
|
||||
virtual void analyzeEdgeCasesBackward();
|
||||
|
||||
// When a floating-point value is used by nodes which would prefer to
|
||||
// recieve integer inputs, we may be able to help by computing our result
|
||||
// into an integer directly.
|
||||
//
|
||||
// A value can be truncated in 4 differents ways:
|
||||
// 1. Ignore Infinities (x / 0 --> 0).
|
||||
// 2. Ignore overflow (INT_MIN / -1 == (INT_MAX + 1) --> INT_MIN)
|
||||
// 3. Ignore negative zeros. (-0 --> 0)
|
||||
// 4. Ignore remainder. (3 / 4 --> 0)
|
||||
//
|
||||
// Indirect truncation is used to represent that we are interested in the
|
||||
// truncated result, but only if it can safely flow into operations which
|
||||
// are computed modulo 2^32, such as (2) and (3). Infinities are not safe,
|
||||
// as they would have absorbed other math operations. Remainders are not
|
||||
// safe, as fractions can be scaled up by multiplication.
|
||||
//
|
||||
// Division is a particularly interesting node here because it covers all 4
|
||||
// cases even when its own operands are integers.
|
||||
//
|
||||
// Note that these enum values are ordered from least value-modifying to
|
||||
// most value-modifying, and code relies on this ordering.
|
||||
enum TruncateKind {
|
||||
// No correction.
|
||||
NoTruncate = 0,
|
||||
// An integer is desired, but we can't skip bailout checks.
|
||||
TruncateAfterBailouts = 1,
|
||||
// The value will be truncated after some arithmetic (see above).
|
||||
IndirectTruncate = 2,
|
||||
// Direct and infallible truncation to int32.
|
||||
Truncate = 3
|
||||
};
|
||||
|
||||
// Apply the given truncate to this node itself.
|
||||
virtual bool truncate(TruncateKind kind);
|
||||
|
||||
// Determine what kind of truncate this node prefers for the operand at the
|
||||
// given index.
|
||||
virtual TruncateKind operandTruncateKind(size_t index) const;
|
||||
virtual bool truncate();
|
||||
virtual bool isOperandTruncated(size_t index) const;
|
||||
|
||||
// Compute an absolute or symbolic range for the value of this node.
|
||||
virtual void computeRange(TempAllocator &alloc) {
|
||||
|
@ -1013,7 +998,7 @@ class MConstant : public MNullaryInstruction
|
|||
}
|
||||
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool truncate(TruncateKind kind);
|
||||
bool truncate();
|
||||
|
||||
bool canProduceFloat32() const;
|
||||
};
|
||||
|
@ -2411,8 +2396,8 @@ class MCompare
|
|||
|
||||
void trySpecializeFloat32(TempAllocator &alloc);
|
||||
bool isFloat32Commutative() const { return true; }
|
||||
bool truncate(TruncateKind kind);
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool truncate();
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
# ifdef DEBUG
|
||||
bool isConsistentFloat32Use(MUse *use) const {
|
||||
|
@ -2941,10 +2926,8 @@ class MToDouble
|
|||
private:
|
||||
ConversionKind conversion_;
|
||||
|
||||
TruncateKind implicitTruncate_;
|
||||
|
||||
MToDouble(MDefinition *def, ConversionKind conversion = NonStringPrimitives)
|
||||
: MUnaryInstruction(def), conversion_(conversion), implicitTruncate_(NoTruncate)
|
||||
: MUnaryInstruction(def), conversion_(conversion)
|
||||
{
|
||||
setResultType(MIRType_Double);
|
||||
setMovable();
|
||||
|
@ -2984,19 +2967,12 @@ class MToDouble
|
|||
}
|
||||
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool truncate(TruncateKind kind);
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool truncate();
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool isConsistentFloat32Use(MUse *use) const { return true; }
|
||||
#endif
|
||||
|
||||
TruncateKind truncateKind() const {
|
||||
return implicitTruncate_;
|
||||
}
|
||||
void setTruncateKind(TruncateKind kind) {
|
||||
implicitTruncate_ = Max(implicitTruncate_, kind);
|
||||
}
|
||||
};
|
||||
|
||||
// Converts a primitive (either typed or untyped) to a float32. If the input is
|
||||
|
@ -3216,7 +3192,7 @@ class MTruncateToInt32 : public MUnaryInstruction
|
|||
}
|
||||
|
||||
void computeRange(TempAllocator &alloc);
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
# ifdef DEBUG
|
||||
bool isConsistentFloat32Use(MUse *use) const {
|
||||
return true;
|
||||
|
@ -3394,7 +3370,7 @@ class MBinaryBitwiseInstruction
|
|||
return AliasSet::None();
|
||||
}
|
||||
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
};
|
||||
|
||||
class MBitAnd : public MBinaryBitwiseInstruction
|
||||
|
@ -3569,14 +3545,14 @@ class MBinaryArithInstruction
|
|||
// This optimization happens when the multiplication cannot be truncated
|
||||
// even if all uses are truncating its result, such as when the range
|
||||
// analysis detect a precision loss in the multiplication.
|
||||
TruncateKind implicitTruncate_;
|
||||
bool implicitTruncate_;
|
||||
|
||||
void inferFallback(BaselineInspector *inspector, jsbytecode *pc);
|
||||
|
||||
public:
|
||||
MBinaryArithInstruction(MDefinition *left, MDefinition *right)
|
||||
: MBinaryInstruction(left, right),
|
||||
implicitTruncate_(NoTruncate)
|
||||
implicitTruncate_(false)
|
||||
{
|
||||
setMovable();
|
||||
}
|
||||
|
@ -3611,13 +3587,10 @@ class MBinaryArithInstruction
|
|||
}
|
||||
|
||||
bool isTruncated() const {
|
||||
return implicitTruncate_ == Truncate;
|
||||
}
|
||||
TruncateKind truncateKind() const {
|
||||
return implicitTruncate_;
|
||||
}
|
||||
void setTruncateKind(TruncateKind kind) {
|
||||
implicitTruncate_ = Max(implicitTruncate_, kind);
|
||||
void setTruncated(bool truncate) {
|
||||
implicitTruncate_ = truncate;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4065,7 +4038,7 @@ class MAdd : public MBinaryArithInstruction
|
|||
add->specialization_ = type;
|
||||
add->setResultType(type);
|
||||
if (type == MIRType_Int32) {
|
||||
add->setTruncateKind(Truncate);
|
||||
add->setTruncated(true);
|
||||
add->setCommutative();
|
||||
}
|
||||
return add;
|
||||
|
@ -4079,8 +4052,8 @@ class MAdd : public MBinaryArithInstruction
|
|||
|
||||
bool fallible() const;
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool truncate(TruncateKind kind);
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool truncate();
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
bool writeRecoverData(CompactBufferWriter &writer) const;
|
||||
bool canRecoverOnBailout() const {
|
||||
|
@ -4108,7 +4081,7 @@ class MSub : public MBinaryArithInstruction
|
|||
sub->specialization_ = type;
|
||||
sub->setResultType(type);
|
||||
if (type == MIRType_Int32)
|
||||
sub->setTruncateKind(Truncate);
|
||||
sub->setTruncated(true);
|
||||
return sub;
|
||||
}
|
||||
|
||||
|
@ -4120,8 +4093,8 @@ class MSub : public MBinaryArithInstruction
|
|||
|
||||
bool fallible() const;
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool truncate(TruncateKind kind);
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool truncate();
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
};
|
||||
|
||||
class MMul : public MBinaryArithInstruction
|
||||
|
@ -4148,7 +4121,7 @@ class MMul : public MBinaryArithInstruction
|
|||
// This implements the required behavior for Math.imul, which
|
||||
// can never fail and always truncates its output to int32.
|
||||
canBeNegativeZero_ = false;
|
||||
setTruncateKind(Truncate);
|
||||
setTruncated(true);
|
||||
setCommutative();
|
||||
}
|
||||
JS_ASSERT_IF(mode != Integer, mode == Normal);
|
||||
|
@ -4213,8 +4186,8 @@ class MMul : public MBinaryArithInstruction
|
|||
bool isFloat32Commutative() const { return true; }
|
||||
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool truncate(TruncateKind kind);
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool truncate();
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
Mode mode() const { return mode_; }
|
||||
};
|
||||
|
@ -4227,13 +4200,32 @@ class MDiv : public MBinaryArithInstruction
|
|||
bool canBeNegativeDividend_;
|
||||
bool unsigned_;
|
||||
|
||||
// A Division can be truncated in 4 differents ways:
|
||||
// 1. Ignore Infinities (x / 0 --> 0).
|
||||
// 2. Ignore overflow (INT_MIN / -1 == (INT_MAX + 1) --> INT_MIN)
|
||||
// 3. Ignore negative zeros. (-0 --> 0)
|
||||
// 4. Ignore remainder. (3 / 4 --> 0)
|
||||
//
|
||||
// isTruncatedIndirectly is used to represent that we are interested in the
|
||||
// truncated result, but only if they it can safely flow in operations which
|
||||
// are computed modulo 2^32, such as (2) and (3).
|
||||
//
|
||||
// A division can return either Infinities (1) or a remainder (4) when both
|
||||
// operands are integers. Infinities are not safe, as they would have
|
||||
// absorbed other math operations. Remainders are not safe, as multiple can
|
||||
// add up to integers. This implies that we need to distinguish between a
|
||||
// division which is truncated directly (isTruncated) or which flow into
|
||||
// truncated operations (isTruncatedIndirectly).
|
||||
bool isTruncatedIndirectly_;
|
||||
|
||||
MDiv(MDefinition *left, MDefinition *right, MIRType type)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
canBeNegativeZero_(true),
|
||||
canBeNegativeOverflow_(true),
|
||||
canBeDivideByZero_(true),
|
||||
canBeNegativeDividend_(true),
|
||||
unsigned_(false)
|
||||
unsigned_(false),
|
||||
isTruncatedIndirectly_(false)
|
||||
{
|
||||
if (type != MIRType_Value)
|
||||
specialization_ = type;
|
||||
|
@ -4254,7 +4246,7 @@ class MDiv : public MBinaryArithInstruction
|
|||
MDiv *div = new(alloc) MDiv(left, right, type);
|
||||
div->unsigned_ = unsignd;
|
||||
if (type == MIRType_Int32)
|
||||
div->setTruncateKind(Truncate);
|
||||
div->setTruncated(true);
|
||||
return div;
|
||||
}
|
||||
|
||||
|
@ -4290,7 +4282,10 @@ class MDiv : public MBinaryArithInstruction
|
|||
}
|
||||
|
||||
bool isTruncatedIndirectly() const {
|
||||
return truncateKind() >= IndirectTruncate;
|
||||
return isTruncatedIndirectly_;
|
||||
}
|
||||
void setTruncatedIndirectly(bool truncate) {
|
||||
isTruncatedIndirectly_ = truncate;
|
||||
}
|
||||
|
||||
bool canTruncateInfinities() const {
|
||||
|
@ -4310,7 +4305,7 @@ class MDiv : public MBinaryArithInstruction
|
|||
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool fallible() const;
|
||||
bool truncate(TruncateKind kind);
|
||||
bool truncate();
|
||||
void collectRangeInfoPreTrunc();
|
||||
};
|
||||
|
||||
|
@ -4340,7 +4335,7 @@ class MMod : public MBinaryArithInstruction
|
|||
MMod *mod = new(alloc) MMod(left, right, type);
|
||||
mod->unsigned_ = unsignd;
|
||||
if (type == MIRType_Int32)
|
||||
mod->setTruncateKind(Truncate);
|
||||
mod->setTruncated(true);
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
@ -4364,7 +4359,7 @@ class MMod : public MBinaryArithInstruction
|
|||
bool fallible() const;
|
||||
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool truncate(TruncateKind kind);
|
||||
bool truncate();
|
||||
void collectRangeInfoPreTrunc();
|
||||
};
|
||||
|
||||
|
@ -6569,7 +6564,7 @@ class MLoadTypedArrayElementStatic
|
|||
}
|
||||
|
||||
void computeRange(TempAllocator &alloc);
|
||||
bool truncate(TruncateKind kind);
|
||||
bool truncate();
|
||||
bool canProduceFloat32() const { return typedArray_->type() == ScalarTypeDescr::TYPE_FLOAT32; }
|
||||
};
|
||||
|
||||
|
@ -6634,7 +6629,7 @@ class MStoreTypedArrayElement
|
|||
void setRacy() {
|
||||
racy_ = true;
|
||||
}
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
bool canConsumeFloat32(MUse *use) const {
|
||||
return use->index() == 2 && arrayType_ == ScalarTypeDescr::TYPE_FLOAT32;
|
||||
|
@ -6702,7 +6697,7 @@ class MStoreTypedArrayElementHole
|
|||
AliasSet getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::TypedArrayElement);
|
||||
}
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
bool canConsumeFloat32(MUse *use) const {
|
||||
return use->index() == 3 && arrayType_ == ScalarTypeDescr::TYPE_FLOAT32;
|
||||
|
@ -6749,7 +6744,7 @@ class MStoreTypedArrayElementStatic :
|
|||
AliasSet getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::TypedArrayElement);
|
||||
}
|
||||
TruncateKind operandTruncateKind(size_t index) const;
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
bool canConsumeFloat32(MUse *use) const {
|
||||
return use->index() == 1 && typedArray_->type() == ScalarTypeDescr::TYPE_FLOAT32;
|
||||
|
|
|
@ -2136,14 +2136,14 @@ Range::wrapAroundToBoolean()
|
|||
}
|
||||
|
||||
bool
|
||||
MDefinition::truncate(TruncateKind kind)
|
||||
MDefinition::truncate()
|
||||
{
|
||||
// No procedure defined for truncating this instruction.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MConstant::truncate(TruncateKind kind)
|
||||
MConstant::truncate()
|
||||
{
|
||||
if (!value_.isDouble())
|
||||
return false;
|
||||
|
@ -2158,15 +2158,15 @@ MConstant::truncate(TruncateKind kind)
|
|||
}
|
||||
|
||||
bool
|
||||
MAdd::truncate(TruncateKind kind)
|
||||
MAdd::truncate()
|
||||
{
|
||||
// Remember analysis, needed for fallible checks.
|
||||
setTruncateKind(kind);
|
||||
setTruncated(true);
|
||||
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
if (kind >= IndirectTruncate && range())
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
}
|
||||
|
@ -2175,15 +2175,15 @@ MAdd::truncate(TruncateKind kind)
|
|||
}
|
||||
|
||||
bool
|
||||
MSub::truncate(TruncateKind kind)
|
||||
MSub::truncate()
|
||||
{
|
||||
// Remember analysis, needed for fallible checks.
|
||||
setTruncateKind(kind);
|
||||
setTruncated(true);
|
||||
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
if (kind >= IndirectTruncate && range())
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
}
|
||||
|
@ -2192,19 +2192,17 @@ MSub::truncate(TruncateKind kind)
|
|||
}
|
||||
|
||||
bool
|
||||
MMul::truncate(TruncateKind kind)
|
||||
MMul::truncate()
|
||||
{
|
||||
// Remember analysis, needed to remove negative zero checks.
|
||||
setTruncateKind(kind);
|
||||
setTruncated(true);
|
||||
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
if (kind >= IndirectTruncate) {
|
||||
setCanBeNegativeZero(false);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
}
|
||||
setCanBeNegativeZero(false);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2212,19 +2210,36 @@ MMul::truncate(TruncateKind kind)
|
|||
}
|
||||
|
||||
bool
|
||||
MDiv::truncate(TruncateKind kind)
|
||||
MDiv::truncate()
|
||||
{
|
||||
setTruncateKind(kind);
|
||||
// Remember analysis, needed to remove negative zero checks.
|
||||
setTruncatedIndirectly(true);
|
||||
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
// Check if this division only flows in bitwise instructions.
|
||||
if (!isTruncated()) {
|
||||
bool allUsesExplictlyTruncate = true;
|
||||
for (MUseDefIterator use(this); allUsesExplictlyTruncate && use; use++) {
|
||||
switch (use.def()->op()) {
|
||||
case MDefinition::Op_BitAnd:
|
||||
case MDefinition::Op_BitOr:
|
||||
case MDefinition::Op_BitXor:
|
||||
case MDefinition::Op_Lsh:
|
||||
case MDefinition::Op_Rsh:
|
||||
case MDefinition::Op_Ursh:
|
||||
break;
|
||||
default:
|
||||
allUsesExplictlyTruncate = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Divisions where the lhs and rhs are unsigned and the result is
|
||||
// truncated can be lowered more efficiently.
|
||||
if (tryUseUnsignedOperands())
|
||||
unsigned_ = true;
|
||||
if (allUsesExplictlyTruncate)
|
||||
setTruncated(true);
|
||||
}
|
||||
|
||||
// Divisions where the lhs and rhs are unsigned and the result is
|
||||
// truncated can be lowered more efficiently.
|
||||
if (specialization() == MIRType_Int32 && tryUseUnsignedOperands()) {
|
||||
unsigned_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2233,19 +2248,14 @@ MDiv::truncate(TruncateKind kind)
|
|||
}
|
||||
|
||||
bool
|
||||
MMod::truncate(TruncateKind kind)
|
||||
MMod::truncate()
|
||||
{
|
||||
// Remember analysis, needed to remove negative zero checks.
|
||||
setTruncateKind(kind);
|
||||
setTruncated(true);
|
||||
|
||||
// As for division, handle unsigned modulus with a truncated result.
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
|
||||
if (tryUseUnsignedOperands())
|
||||
unsigned_ = true;
|
||||
|
||||
if (specialization() == MIRType_Int32 && tryUseUnsignedOperands()) {
|
||||
unsigned_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2254,103 +2264,90 @@ MMod::truncate(TruncateKind kind)
|
|||
}
|
||||
|
||||
bool
|
||||
MToDouble::truncate(TruncateKind kind)
|
||||
MToDouble::truncate()
|
||||
{
|
||||
JS_ASSERT(type() == MIRType_Double);
|
||||
|
||||
setTruncateKind(kind);
|
||||
|
||||
// We use the return type to flag that this MToDouble should be replaced by
|
||||
// a MTruncateToInt32 when modifying the graph.
|
||||
setResultType(MIRType_Int32);
|
||||
if (kind >= IndirectTruncate) {
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
}
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MLoadTypedArrayElementStatic::truncate(TruncateKind kind)
|
||||
MLoadTypedArrayElementStatic::truncate()
|
||||
{
|
||||
setInfallible();
|
||||
return false;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MDefinition::operandTruncateKind(size_t index) const
|
||||
bool
|
||||
MDefinition::isOperandTruncated(size_t index) const
|
||||
{
|
||||
// Generic routine: We don't know anything.
|
||||
return NoTruncate;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MTruncateToInt32::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// This operator is an explicit truncate to int32.
|
||||
return Truncate;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MBinaryBitwiseInstruction::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// The bitwise operators truncate to int32.
|
||||
return Truncate;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MAdd::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// This operator is doing some arithmetic. If its result is truncated,
|
||||
// it's an indirect truncate for its operands.
|
||||
return Min(truncateKind(), IndirectTruncate);
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MSub::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// See the comment in MAdd::operandTruncateKind.
|
||||
return Min(truncateKind(), IndirectTruncate);
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MMul::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// See the comment in MAdd::operandTruncateKind.
|
||||
return Min(truncateKind(), IndirectTruncate);
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MToDouble::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// MToDouble propagates its truncate kind to its operand.
|
||||
return truncateKind();
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MStoreTypedArrayElement::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// An integer store truncates the stored value.
|
||||
return index == 2 && !isFloatArray() ? Truncate : NoTruncate;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MStoreTypedArrayElementHole::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// An integer store truncates the stored value.
|
||||
return index == 3 && !isFloatArray() ? Truncate : NoTruncate;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MStoreTypedArrayElementStatic::operandTruncateKind(size_t index) const
|
||||
{
|
||||
// An integer store truncates the stored value.
|
||||
return index == 1 && !isFloatArray() ? Truncate : NoTruncate;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MCompare::truncate(TruncateKind kind)
|
||||
MTruncateToInt32::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MBinaryBitwiseInstruction::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MAdd::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return isTruncated();
|
||||
}
|
||||
|
||||
bool
|
||||
MSub::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return isTruncated();
|
||||
}
|
||||
|
||||
bool
|
||||
MMul::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return isTruncated();
|
||||
}
|
||||
|
||||
bool
|
||||
MToDouble::isOperandTruncated(size_t index) const
|
||||
{
|
||||
// The return type is used to flag that we are replacing this Double by a
|
||||
// Truncate of its operand if needed.
|
||||
return type() == MIRType_Int32;
|
||||
}
|
||||
|
||||
bool
|
||||
MStoreTypedArrayElement::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return index == 2 && !isFloatArray();
|
||||
}
|
||||
|
||||
bool
|
||||
MStoreTypedArrayElementHole::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return index == 3 && !isFloatArray();
|
||||
}
|
||||
|
||||
bool
|
||||
MStoreTypedArrayElementStatic::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return index == 1 && !isFloatArray();
|
||||
}
|
||||
|
||||
bool
|
||||
MCompare::truncate()
|
||||
{
|
||||
if (!isDoubleComparison())
|
||||
return false;
|
||||
|
@ -2362,34 +2359,32 @@ MCompare::truncate(TruncateKind kind)
|
|||
|
||||
compareType_ = Compare_Int32;
|
||||
|
||||
// Truncating the operands won't change their value because we don't force a
|
||||
// truncation, but it will change their type, which we need because we
|
||||
// now expect integer inputs.
|
||||
// Truncating the operands won't change their value, but it will change
|
||||
// their type, which we need because we now expect integer inputs.
|
||||
truncateOperands_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind
|
||||
MCompare::operandTruncateKind(size_t index) const
|
||||
bool
|
||||
MCompare::isOperandTruncated(size_t index) const
|
||||
{
|
||||
// If we're doing an int32 comparison on operands which were previously
|
||||
// floating-point, convert them!
|
||||
JS_ASSERT_IF(truncateOperands_, isInt32Comparison());
|
||||
return truncateOperands_ ? TruncateAfterBailouts : NoTruncate;
|
||||
return truncateOperands_;
|
||||
}
|
||||
|
||||
// Examine all the users of |candidate| and determine the most aggressive
|
||||
// truncate kind that satisfies all of them.
|
||||
static MDefinition::TruncateKind
|
||||
ComputeRequestedTruncateKind(MInstruction *candidate)
|
||||
// Ensure that all observables uses can work with a truncated
|
||||
// version of the |candidate|'s result.
|
||||
static bool
|
||||
AllUsesTruncate(MInstruction *candidate)
|
||||
{
|
||||
// If the value naturally produces an int32 value (before bailout checks)
|
||||
// that needs no conversion, we don't have to worry about resume points
|
||||
// seeing truncated values.
|
||||
bool needsConversion = !candidate->range() || !candidate->range()->isInt32();
|
||||
|
||||
MDefinition::TruncateKind kind = MDefinition::Truncate;
|
||||
for (MUseIterator use(candidate->usesBegin()); use != candidate->usesEnd(); use++) {
|
||||
if (!use->consumer()->isDefinition()) {
|
||||
// We can only skip testing resume points, if all original uses are
|
||||
|
@ -2398,27 +2393,24 @@ ComputeRequestedTruncateKind(MInstruction *candidate)
|
|||
// value, and any bailout with a truncated value might lead an
|
||||
// incorrect value.
|
||||
if (candidate->isUseRemoved() && needsConversion)
|
||||
kind = Min(kind, MDefinition::TruncateAfterBailouts);
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
MDefinition *consumer = use->consumer()->toDefinition();
|
||||
MDefinition::TruncateKind consumerKind = consumer->operandTruncateKind(use->index());
|
||||
kind = Min(kind, consumerKind);
|
||||
if (kind == MDefinition::NoTruncate)
|
||||
break;
|
||||
if (!use->consumer()->toDefinition()->isOperandTruncated(use->index()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return kind;
|
||||
return true;
|
||||
}
|
||||
|
||||
static MDefinition::TruncateKind
|
||||
ComputeTruncateKind(MInstruction *candidate)
|
||||
static bool
|
||||
CanTruncate(MInstruction *candidate)
|
||||
{
|
||||
// Compare operations might coerce its inputs to int32 if the ranges are
|
||||
// correct. So we do not need to check if all uses are coerced.
|
||||
if (candidate->isCompare())
|
||||
return MDefinition::TruncateAfterBailouts;
|
||||
return true;
|
||||
|
||||
// Set truncated flag if range analysis ensure that it has no
|
||||
// rounding errors and no fractional part. Note that we can't use
|
||||
|
@ -2433,10 +2425,10 @@ ComputeTruncateKind(MInstruction *candidate)
|
|||
canHaveRoundingErrors = false;
|
||||
|
||||
if (canHaveRoundingErrors)
|
||||
return MDefinition::NoTruncate;
|
||||
return false;
|
||||
|
||||
// Ensure all observable uses are truncated.
|
||||
return ComputeRequestedTruncateKind(candidate);
|
||||
return AllUsesTruncate(candidate);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2463,7 +2455,7 @@ AdjustTruncatedInputs(TempAllocator &alloc, MInstruction *truncated)
|
|||
{
|
||||
MBasicBlock *block = truncated->block();
|
||||
for (size_t i = 0, e = truncated->numOperands(); i < e; i++) {
|
||||
if (truncated->operandTruncateKind(i) == MDefinition::NoTruncate)
|
||||
if (!truncated->isOperandTruncated(i))
|
||||
continue;
|
||||
|
||||
MDefinition *input = truncated->getOperand(i);
|
||||
|
@ -2523,12 +2515,11 @@ RangeAnalysis::truncate()
|
|||
default:;
|
||||
}
|
||||
|
||||
MDefinition::TruncateKind kind = ComputeTruncateKind(*iter);
|
||||
if (kind == MDefinition::NoTruncate)
|
||||
if (!CanTruncate(*iter))
|
||||
continue;
|
||||
|
||||
// Truncate this instruction if possible.
|
||||
if (!iter->truncate(kind))
|
||||
if (!iter->truncate())
|
||||
continue;
|
||||
|
||||
// Delay updates of inputs/outputs to avoid creating node which
|
||||
|
|
|
@ -71,7 +71,7 @@ ICCompare_Double::Compiler::generateStubCode(MacroAssembler &masm)
|
|||
// ICBinaryArith_Int32
|
||||
|
||||
extern "C" {
|
||||
extern int64_t __aeabi_idivmod(int,int);
|
||||
extern MOZ_EXPORT int64_t __aeabi_idivmod(int,int);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -619,8 +619,8 @@ CodeGeneratorARM::visitDivI(LDivI *ins)
|
|||
}
|
||||
|
||||
extern "C" {
|
||||
extern int64_t __aeabi_idivmod(int,int);
|
||||
extern int64_t __aeabi_uidivmod(int,int);
|
||||
extern MOZ_EXPORT int64_t __aeabi_idivmod(int,int);
|
||||
extern MOZ_EXPORT int64_t __aeabi_uidivmod(int,int);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -138,7 +138,7 @@ ToStackIndex(LAllocation *a)
|
|||
|
||||
bool
|
||||
CodeGeneratorShared::encodeAllocation(LSnapshot *snapshot, MDefinition *mir,
|
||||
uint32_t *allocIndex)
|
||||
uint32_t *allocIndex)
|
||||
{
|
||||
if (mir->isBox())
|
||||
mir = mir->toBox()->getOperand(0);
|
||||
|
|
|
@ -70,6 +70,25 @@ LIRGeneratorShared::getRecoverInfo(MResumePoint *rp)
|
|||
return recoverInfo;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
LRecoverInfo::OperandIter::canOptimizeOutIfUnused()
|
||||
{
|
||||
MDefinition *ins = **this;
|
||||
|
||||
// We check ins->type() in addition to ins->isUnused() because
|
||||
// EliminateDeadResumePointOperands may replace nodes with the constant
|
||||
// MagicValue(JS_OPTIMIZED_OUT).
|
||||
if ((ins->isUnused() || ins->type() == MIRType_MagicOptimizedOut) &&
|
||||
(*it_)->isResumePoint())
|
||||
{
|
||||
return (*it_)->block()->info().canOptimizeOutSlot(op_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JS_NUNBOX32
|
||||
LSnapshot *
|
||||
LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
|
||||
|
@ -86,7 +105,11 @@ LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKi
|
|||
LRecoverInfo::OperandIter it(recoverInfo->begin());
|
||||
LRecoverInfo::OperandIter end(recoverInfo->end());
|
||||
for (; it != end; ++it) {
|
||||
// Check that optimized out operands are in eliminable slots.
|
||||
MOZ_ASSERT(it.canOptimizeOutIfUnused());
|
||||
|
||||
MDefinition *ins = *it;
|
||||
|
||||
if (ins->isRecoveredOnBailout())
|
||||
continue;
|
||||
|
||||
|
@ -98,12 +121,12 @@ LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKi
|
|||
ins = ins->toBox()->getOperand(0);
|
||||
|
||||
// Guards should never be eliminated.
|
||||
JS_ASSERT_IF(ins->isUnused(), !ins->isGuard());
|
||||
MOZ_ASSERT_IF(ins->isUnused(), !ins->isGuard());
|
||||
|
||||
// Snapshot operands other than constants should never be
|
||||
// emitted-at-uses. Try-catch support depends on there being no
|
||||
// code between an instruction and the LOsiPoint that follows it.
|
||||
JS_ASSERT_IF(!ins->isConstant(), !ins->isEmittedAtUses());
|
||||
MOZ_ASSERT_IF(!ins->isConstant(), !ins->isEmittedAtUses());
|
||||
|
||||
// The register allocation will fill these fields in with actual
|
||||
// register/stack assignments. During code generation, we can restore
|
||||
|
@ -142,6 +165,9 @@ LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKi
|
|||
LRecoverInfo::OperandIter it(recoverInfo->begin());
|
||||
LRecoverInfo::OperandIter end(recoverInfo->end());
|
||||
for (; it != end; ++it) {
|
||||
// Check that optimized out operands are in eliminable slots.
|
||||
MOZ_ASSERT(it.canOptimizeOutIfUnused());
|
||||
|
||||
MDefinition *def = *it;
|
||||
|
||||
if (def->isRecoveredOnBailout())
|
||||
|
@ -151,12 +177,12 @@ LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKi
|
|||
def = def->toBox()->getOperand(0);
|
||||
|
||||
// Guards should never be eliminated.
|
||||
JS_ASSERT_IF(def->isUnused(), !def->isGuard());
|
||||
MOZ_ASSERT_IF(def->isUnused(), !def->isGuard());
|
||||
|
||||
// Snapshot operands other than constants should never be
|
||||
// emitted-at-uses. Try-catch support depends on there being no
|
||||
// code between an instruction and the LOsiPoint that follows it.
|
||||
JS_ASSERT_IF(!def->isConstant(), !def->isEmittedAtUses());
|
||||
MOZ_ASSERT_IF(!def->isConstant(), !def->isEmittedAtUses());
|
||||
|
||||
LAllocation *a = snapshot->getEntry(index++);
|
||||
|
||||
|
|
|
@ -1384,6 +1384,14 @@ JS_GetArrayPrototype(JSContext *cx, HandleObject forObj)
|
|||
return GlobalObject::getOrCreateArrayPrototype(cx, global);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetErrorPrototype(JSContext *cx)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
Rooted<GlobalObject*> global(cx, cx->global());
|
||||
return GlobalObject::getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
|
|
|
@ -1826,6 +1826,13 @@ JS_GetObjectPrototype(JSContext *cx, JS::HandleObject forObj);
|
|||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetArrayPrototype(JSContext *cx, JS::HandleObject forObj);
|
||||
|
||||
/*
|
||||
* Returns the original value of |Error.prototype| from the global
|
||||
* object of the current compartment of cx.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetErrorPrototype(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
|
@ -4906,8 +4913,7 @@ typedef bool
|
|||
(* OpenAsmJSCacheEntryForReadOp)(HandleObject global, const jschar *begin, const jschar *limit,
|
||||
size_t *size, const uint8_t **memory, intptr_t *handle);
|
||||
typedef void
|
||||
(* CloseAsmJSCacheEntryForReadOp)(HandleObject global, size_t size, const uint8_t *memory,
|
||||
intptr_t handle);
|
||||
(* CloseAsmJSCacheEntryForReadOp)(size_t size, const uint8_t *memory, intptr_t handle);
|
||||
|
||||
/*
|
||||
* This callback represents a request by the JS engine to open for writing a
|
||||
|
@ -4929,8 +4935,7 @@ typedef bool
|
|||
const jschar *begin, const jschar *end,
|
||||
size_t size, uint8_t **memory, intptr_t *handle);
|
||||
typedef void
|
||||
(* CloseAsmJSCacheEntryForWriteOp)(HandleObject global, size_t size, uint8_t *memory,
|
||||
intptr_t handle);
|
||||
(* CloseAsmJSCacheEntryForWriteOp)(size_t size, uint8_t *memory, intptr_t handle);
|
||||
|
||||
typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
|
||||
|
||||
|
|
|
@ -661,6 +661,7 @@ JSCompartment::clearTables()
|
|||
JS_ASSERT(!gcWeakMapList);
|
||||
JS_ASSERT(enumerators->next() == enumerators);
|
||||
|
||||
types.clearTables();
|
||||
if (baseShapes.initialized())
|
||||
baseShapes.clear();
|
||||
if (initialShapes.initialized())
|
||||
|
|
|
@ -706,8 +706,8 @@ IsDuckTypedErrorObject(JSContext *cx, HandleObject exnObject, const char **filen
|
|||
|
||||
const char *filename_str = *filename_strp;
|
||||
if (!JS_HasProperty(cx, exnObject, filename_str, &found) || !found) {
|
||||
/* DOMException duck quacks "filename" (all lowercase) */
|
||||
filename_str = "filename";
|
||||
/* Now try "fileName", in case this quacks like an Error */
|
||||
filename_str = js_fileName_str;
|
||||
if (!JS_HasProperty(cx, exnObject, filename_str, &found) || !found)
|
||||
return false;
|
||||
}
|
||||
|
@ -778,8 +778,13 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
|
||||
// If js_ErrorFromException didn't get us a JSErrorReport, then the object
|
||||
// was not an ErrorObject, security-wrapped or otherwise. However, it might
|
||||
// still quack like one. Give duck-typing a chance.
|
||||
const char *filename_str = js_fileName_str;
|
||||
// still quack like one. Give duck-typing a chance. We start by looking for
|
||||
// "filename" (all lowercase), since that's where DOMExceptions store their
|
||||
// filename. Then we check "fileName", which is where Errors store it. We
|
||||
// have to do it in that order, because DOMExceptions have Error.prototype
|
||||
// on their proto chain, and hence also have a "fileName" property, but its
|
||||
// value is "".
|
||||
const char *filename_str = "filename";
|
||||
JSAutoByteString filename;
|
||||
if (!reportp && exnObject && IsDuckTypedErrorObject(cx, exnObject, &filename_str))
|
||||
{
|
||||
|
|
|
@ -1192,7 +1192,7 @@ types::FinishCompilation(JSContext *cx, HandleScript script, ExecutionMode execu
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE void
|
||||
static void
|
||||
CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTypeSet *actual)
|
||||
{
|
||||
// The definite properties analysis happens on the main thread, so no new
|
||||
|
@ -3621,7 +3621,8 @@ JSScript::makeTypes(JSContext *cx)
|
|||
|
||||
unsigned count = TypeScript::NumTypeSets(this);
|
||||
|
||||
TypeScript *typeScript = (TypeScript *) cx->calloc_(sizeof(TypeScript) + (sizeof(StackTypeSet) * count));
|
||||
TypeScript *typeScript = (TypeScript *)
|
||||
cx->calloc_(TypeScript::SizeIncludingTypeArray(count));
|
||||
if (!typeScript)
|
||||
return false;
|
||||
|
||||
|
@ -4169,6 +4170,17 @@ TypeObject::sweep(FreeOp *fop, bool *oom)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
TypeCompartment::clearTables()
|
||||
{
|
||||
if (allocationSiteTable && allocationSiteTable->initialized())
|
||||
allocationSiteTable->clear();
|
||||
if (arrayTypeTable && arrayTypeTable->initialized())
|
||||
arrayTypeTable->clear();
|
||||
if (objectTypeTable && objectTypeTable->initialized())
|
||||
objectTypeTable->clear();
|
||||
}
|
||||
|
||||
void
|
||||
TypeCompartment::sweep(FreeOp *fop)
|
||||
{
|
||||
|
|
|
@ -1267,9 +1267,24 @@ class TypeScript
|
|||
{
|
||||
friend class ::JSScript;
|
||||
|
||||
// Variable-size array
|
||||
StackTypeSet typeArray_[1];
|
||||
|
||||
public:
|
||||
/* Array of type type sets for variables and JOF_TYPESET ops. */
|
||||
StackTypeSet *typeArray() const { return (StackTypeSet *) (uintptr_t(this) + sizeof(TypeScript)); }
|
||||
StackTypeSet *typeArray() const {
|
||||
// Ensure typeArray_ is the last data member of TypeScript.
|
||||
JS_STATIC_ASSERT(sizeof(TypeScript) ==
|
||||
sizeof(typeArray_) + offsetof(TypeScript, typeArray_));
|
||||
return const_cast<StackTypeSet *>(typeArray_);
|
||||
}
|
||||
|
||||
static inline size_t SizeIncludingTypeArray(size_t arraySize) {
|
||||
// Ensure typeArray_ is the last data member of TypeScript.
|
||||
JS_STATIC_ASSERT(sizeof(TypeScript) ==
|
||||
sizeof(StackTypeSet) + offsetof(TypeScript, typeArray_));
|
||||
return offsetof(TypeScript, typeArray_) + arraySize * sizeof(StackTypeSet);
|
||||
}
|
||||
|
||||
static inline unsigned NumTypeSets(JSScript *script);
|
||||
|
||||
|
@ -1587,6 +1602,7 @@ struct TypeCompartment
|
|||
/* Mark any type set containing obj as having a generic object type. */
|
||||
void markSetsUnknown(JSContext *cx, TypeObject *obj);
|
||||
|
||||
void clearTables();
|
||||
void sweep(FreeOp *fop);
|
||||
void finalizeObjects();
|
||||
|
||||
|
|
|
@ -5514,8 +5514,7 @@ ShellOpenAsmJSCacheEntryForRead(HandleObject global, const jschar *begin, const
|
|||
}
|
||||
|
||||
static void
|
||||
ShellCloseAsmJSCacheEntryForRead(HandleObject global, size_t serializedSize, const uint8_t *memory,
|
||||
intptr_t handle)
|
||||
ShellCloseAsmJSCacheEntryForRead(size_t serializedSize, const uint8_t *memory, intptr_t handle)
|
||||
{
|
||||
// Undo the cookie adjustment done when opening the file.
|
||||
memory -= sizeof(uint32_t);
|
||||
|
@ -5603,8 +5602,7 @@ ShellOpenAsmJSCacheEntryForWrite(HandleObject global, bool installed,
|
|||
}
|
||||
|
||||
static void
|
||||
ShellCloseAsmJSCacheEntryForWrite(HandleObject global, size_t serializedSize, uint8_t *memory,
|
||||
intptr_t handle)
|
||||
ShellCloseAsmJSCacheEntryForWrite(size_t serializedSize, uint8_t *memory, intptr_t handle)
|
||||
{
|
||||
// Undo the cookie adjustment done when opening the file.
|
||||
memory -= sizeof(uint32_t);
|
||||
|
|
|
@ -100,7 +100,26 @@
|
|||
*/ \
|
||||
macro(JSOP_UNDEFINED, 1, js_undefined_str, "", 1, 0, 1, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED2, 2, "unused2", NULL, 1, 1, 0, JOF_BYTE) \
|
||||
/*
|
||||
* Pops the top of stack value, converts it to an object, and adds a
|
||||
* 'DynamicWithObject' wrapping that object to the scope chain.
|
||||
*
|
||||
* There is a matching JSOP_LEAVEWITH instruction later. All name
|
||||
* lookups between the two that may need to consult the With object
|
||||
* are deoptimized.
|
||||
* Category: Statements
|
||||
* Type: With Statement
|
||||
* Operands: uint32_t staticWithIndex
|
||||
* Stack: val =>
|
||||
*/ \
|
||||
macro(JSOP_ENTERWITH, 3, "enterwith", NULL, 5, 1, 0, JOF_OBJECT) \
|
||||
/*
|
||||
* Pops the scope chain object pushed by JSOP_ENTERWITH.
|
||||
* Category: Statements
|
||||
* Type: With Statement
|
||||
* Operands:
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_LEAVEWITH, 4, "leavewith", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
/*
|
||||
* Pops the top of stack value as 'rval', stops interpretation of current
|
||||
|
@ -111,8 +130,35 @@
|
|||
* Stack: rval =>
|
||||
*/ \
|
||||
macro(JSOP_RETURN, 5, "return", NULL, 1, 1, 0, JOF_BYTE) \
|
||||
/*
|
||||
* Jumps to a 32-bit offset from the current bytecode.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: int32_t offset
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_GOTO, 6, "goto", NULL, 5, 0, 0, JOF_JUMP) \
|
||||
/*
|
||||
* Pops the top of stack value, converts it into a boolean, if the result is
|
||||
* 'false', jumps to a 32-bit offset from the current bytecode.
|
||||
*
|
||||
* The idea is that a sequence like
|
||||
* JSOP_ZERO; JSOP_ZERO; JSOP_EQ; JSOP_IFEQ; JSOP_RETURN;
|
||||
* reads like a nice linear sequence that will execute the return.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: int32_t offset
|
||||
* Stack: cond =>
|
||||
*/ \
|
||||
macro(JSOP_IFEQ, 7, "ifeq", NULL, 5, 1, 0, JOF_JUMP|JOF_DETECTING) \
|
||||
/*
|
||||
* Pops the top of stack value, converts it into a boolean, if the result is
|
||||
* 'true', jumps to a 32-bit offset from the current bytecode.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: int32_t offset
|
||||
* Stack: cond =>
|
||||
*/ \
|
||||
macro(JSOP_IFNE, 8, "ifne", NULL, 5, 1, 0, JOF_JUMP) \
|
||||
\
|
||||
/*
|
||||
|
@ -491,10 +537,38 @@
|
|||
*/ \
|
||||
macro(JSOP_FALSE, 66, js_false_str, js_false_str, 1, 0, 1, JOF_BYTE) \
|
||||
macro(JSOP_TRUE, 67, js_true_str, js_true_str, 1, 0, 1, JOF_BYTE) \
|
||||
/*
|
||||
* Converts the top of stack value into a boolean, if the result is 'true',
|
||||
* jumps to a 32-bit offset from the current bytecode.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: int32_t offset
|
||||
* Stack: cond => cond
|
||||
*/ \
|
||||
macro(JSOP_OR, 68, "or", NULL, 5, 1, 1, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC) \
|
||||
/*
|
||||
* Converts the top of stack value into a boolean, if the result is 'false',
|
||||
* jumps to a 32-bit offset from the current bytecode.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: int32_t offset
|
||||
* Stack: cond => cond
|
||||
*/ \
|
||||
macro(JSOP_AND, 69, "and", NULL, 5, 1, 1, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC) \
|
||||
\
|
||||
/* The switch bytecodes have variable length. */ \
|
||||
/*
|
||||
* Pops the top of stack value as 'i', if 'low <= i <= high',
|
||||
* jumps to a 32-bit offset: 'offset[i - low]' from the current bytecode,
|
||||
* jumps to a 32-bit offset: 'len' from the current bytecode if not.
|
||||
*
|
||||
* This opcode has variable length.
|
||||
* Category: Statements
|
||||
* Type: Switch Statement
|
||||
* Operands: int32_t len, int32_t low, int32_t high,
|
||||
* int32_t offset[0], ..., int32_t offset[high-low]
|
||||
* Stack: i =>
|
||||
* len: len
|
||||
*/ \
|
||||
macro(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, JOF_TABLESWITCH|JOF_DETECTING) \
|
||||
\
|
||||
/*
|
||||
|
@ -531,20 +605,48 @@
|
|||
macro(JSOP_SETCALL, 74, "setcall", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
* JSOP_ITER sets up a for-in or for-each-in loop using the JSITER_* flag bits
|
||||
* in this op's uint8_t immediate operand. It replaces the top of stack value
|
||||
* with an iterator for that value.
|
||||
*
|
||||
* JSOP_MOREITER stores the next iterated value into cx->iterValue and pushes
|
||||
* true if another value is available, and false otherwise. It is followed
|
||||
* immediately by JSOP_IFNE.
|
||||
*
|
||||
* JSOP_ENDITER cleans up after the loop. It uses the slot above the iterator
|
||||
* for temporary GC rooting.
|
||||
* Sets up a for-in or for-each-in loop using the JSITER_* flag bits in
|
||||
* this op's uint8_t immediate operand. It pops the top of stack value as
|
||||
* 'val' and pushes 'iter' which is an iterator for 'val'.
|
||||
* Category: Statements
|
||||
* Type: For-In Statement
|
||||
* Operands: uint8_t flags
|
||||
* Stack: val => iter
|
||||
*/ \
|
||||
macro(JSOP_ITER, 75, "iter", NULL, 2, 1, 1, JOF_UINT8) \
|
||||
/*
|
||||
* Stores the next iterated value into 'cx->iterValue' and pushes 'true'
|
||||
* onto the stack if another value is available, and 'false' otherwise.
|
||||
* It is followed immediately by JSOP_IFNE.
|
||||
*
|
||||
* This opcode increments iterator cursor if current iteration has
|
||||
* JSITER_FOREACH flag.
|
||||
* Category: Statements
|
||||
* Type: For-In Statement
|
||||
* Operands:
|
||||
* Stack: iter => iter, cond
|
||||
*/ \
|
||||
macro(JSOP_MOREITER, 76, "moreiter", NULL, 1, 1, 2, JOF_BYTE) \
|
||||
/*
|
||||
* Pushes the value produced by the preceding JSOP_MOREITER operation
|
||||
* ('cx->iterValue') onto the stack
|
||||
*
|
||||
* This opcode increments iterator cursor if current iteration does not have
|
||||
* JSITER_FOREACH flag.
|
||||
* Category: Statements
|
||||
* Type: For-In Statement
|
||||
* Operands:
|
||||
* Stack: iter => iter, val
|
||||
*/ \
|
||||
macro(JSOP_ITERNEXT, 77, "iternext", "<next>", 1, 0, 1, JOF_BYTE) \
|
||||
/*
|
||||
* Exits a for-in loop by popping the iterator object from the stack and
|
||||
* closing it.
|
||||
* Category: Statements
|
||||
* Type: For-In Statement
|
||||
* Operands:
|
||||
* Stack: iter =>
|
||||
*/ \
|
||||
macro(JSOP_ENDITER, 78, "enditer", NULL, 1, 1, 0, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
|
@ -799,7 +901,16 @@
|
|||
macro(JSOP_UNUSED104, 104, "unused104", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED105, 105, "unused105", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/* The argument is the offset to the next statement and is used by IonMonkey. */ \
|
||||
/*
|
||||
* This opcode precedes every labeled statement. It's a no-op.
|
||||
*
|
||||
* 'offset' is the offset to the next instruction after this statement,
|
||||
* the one 'break LABEL;' would jump to. IonMonkey uses this.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: int32_t offset
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_LABEL, 106,"label", NULL, 5, 0, 0, JOF_JUMP) \
|
||||
\
|
||||
macro(JSOP_UNUSED107, 107,"unused107", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
|
@ -822,7 +933,15 @@
|
|||
*/ \
|
||||
macro(JSOP_FUNCALL, 108,"funcall", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \
|
||||
\
|
||||
/* This opcode is the target of the backwards jump for some loop. */ \
|
||||
/*
|
||||
* Another no-op.
|
||||
*
|
||||
* This opcode is the target of the backwards jump for some loop.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands:
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_LOOPHEAD, 109,"loophead", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/* ECMA-compliant assignment ops. */ \
|
||||
|
@ -847,6 +966,14 @@
|
|||
macro(JSOP_SETNAME, 111,"setname", NULL, 5, 2, 1, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING) \
|
||||
\
|
||||
/* Exception handling ops. */ \
|
||||
/*
|
||||
* Pops the top of stack value as 'v', sets pending exception as 'v', then
|
||||
* raises error.
|
||||
* Category: Statements
|
||||
* Type: Exception Handling
|
||||
* Operands:
|
||||
* Stack: v =>
|
||||
*/ \
|
||||
macro(JSOP_THROW, 112,js_throw_str, NULL, 1, 1, 0, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
|
@ -880,11 +1007,41 @@
|
|||
*/ \
|
||||
macro(JSOP_DEBUGGER, 115,"debugger", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/* gosub/retsub for finally handling */ \
|
||||
/*
|
||||
* Pushes 'false' and next bytecode's PC onto the stack, and jumps to
|
||||
* a 32-bit offset from the current bytecode.
|
||||
*
|
||||
* This opcode is used for entering 'finally' block.
|
||||
* Category: Statements
|
||||
* Type: Exception Handling
|
||||
* Operands: int32_t offset
|
||||
* Stack: => false, (next bytecode's PC)
|
||||
*/ \
|
||||
macro(JSOP_GOSUB, 116,"gosub", NULL, 5, 0, 0, JOF_JUMP) \
|
||||
/*
|
||||
* Pops the top two values on the stack as 'rval' and 'lval', converts
|
||||
* 'lval' into a boolean, raises error if the result is 'true',
|
||||
* jumps to a 32-bit absolute PC: 'rval' if 'false'.
|
||||
*
|
||||
* This opcode is used for returning from 'finally' block.
|
||||
* Category: Statements
|
||||
* Type: Exception Handling
|
||||
* Operands:
|
||||
* Stack: lval, rval =>
|
||||
*/ \
|
||||
macro(JSOP_RETSUB, 117,"retsub", NULL, 1, 2, 0, JOF_BYTE) \
|
||||
\
|
||||
/* More exception handling ops. */ \
|
||||
/*
|
||||
* Pushes the current pending exception onto the stack and clears the
|
||||
* pending exception. This is only emitted at the beginning of code for a
|
||||
* catch-block, so it is known that an exception is pending. It is used to
|
||||
* implement catch-blocks and 'yield*'.
|
||||
* Category: Statements
|
||||
* Type: Exception Handling
|
||||
* Operands:
|
||||
* Stack: => exception
|
||||
*/ \
|
||||
macro(JSOP_EXCEPTION, 118,"exception", NULL, 1, 0, 1, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
|
@ -896,12 +1053,58 @@
|
|||
macro(JSOP_LINENO, 119,"lineno", NULL, 3, 0, 0, JOF_UINT16) \
|
||||
\
|
||||
/*
|
||||
* ECMA-compliant switch statement ops.
|
||||
* CONDSWITCH is a decompilable NOP; CASE is ===, POP, jump if true, re-push
|
||||
* lval if false; and DEFAULT is POP lval and GOTO.
|
||||
* This no-op appears after the bytecode for EXPR in 'switch (EXPR) {...}'
|
||||
* if the switch cannot be optimized using JSOP_TABLESWITCH.
|
||||
* For a non-optimized switch statement like this:
|
||||
*
|
||||
* switch (EXPR) {
|
||||
* case V0:
|
||||
* C0;
|
||||
* ...
|
||||
* default:
|
||||
* D;
|
||||
* }
|
||||
*
|
||||
* the bytecode looks like this:
|
||||
*
|
||||
* (EXPR)
|
||||
* condswitch
|
||||
* (V0)
|
||||
* case ->C0
|
||||
* ...
|
||||
* default ->D
|
||||
* (C0)
|
||||
* ...
|
||||
* (D)
|
||||
*
|
||||
* Note that code for all case-labels is emitted first, then code for
|
||||
* the body of each case clause.
|
||||
* Category: Statements
|
||||
* Type: Switch Statement
|
||||
* Operands:
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_CONDSWITCH,120,"condswitch", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
/*
|
||||
* Pops the top two values on the stack as 'rval' and 'lval', compare them
|
||||
* with '===', if the result is 'true', jumps to a 32-bit offset from the
|
||||
* current bytecode, re-pushes 'lval' onto the stack if 'false'.
|
||||
* Category: Statements
|
||||
* Type: Switch Statement
|
||||
* Operands: int32_t offset
|
||||
* Stack: lval, rval => lval(if lval !== rval)
|
||||
*/ \
|
||||
macro(JSOP_CASE, 121,"case", NULL, 5, 2, 1, JOF_JUMP) \
|
||||
/*
|
||||
* This appears after all cases in a JSOP_CONDSWITCH, whether there is a
|
||||
* 'default:' label in the switch statement or not. Pop the switch operand
|
||||
* from the stack and jump to a 32-bit offset from the current bytecode.
|
||||
* offset from the current bytecode.
|
||||
* Category: Statements
|
||||
* Type: Switch Statement
|
||||
* Operands: int32_t offset
|
||||
* Stack: lval =>
|
||||
*/ \
|
||||
macro(JSOP_DEFAULT, 122,"default", NULL, 5, 1, 0, JOF_JUMP) \
|
||||
\
|
||||
/* ECMA-compliant call to eval op. */ \
|
||||
|
@ -1000,10 +1203,24 @@
|
|||
macro(JSOP_PICK, 133, "pick", NULL, 2, 0, 0, JOF_UINT8|JOF_TMPSLOT2) \
|
||||
\
|
||||
/*
|
||||
* Exception handling no-op, for more economical byte-coding than SRC_TRYFIN
|
||||
* srcnote-annotated JSOP_NOPs and to simply stack balance handling.
|
||||
* This no-op appears at the top of the bytecode for a 'TryStatement'.
|
||||
*
|
||||
* Location information for catch/finally blocks is stored in a
|
||||
* side table, 'script->trynotes()'.
|
||||
* Category: Statements
|
||||
* Type: Exception Handling
|
||||
* Operands:
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_TRY, 134,"try", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
/*
|
||||
* This opcode has a def count of 2, but these values are already on the
|
||||
* stack (they're pushed by JSOP_GOSUB).
|
||||
* Category: Statements
|
||||
* Type: Exception Handling
|
||||
* Operands:
|
||||
* Stack: => false, (next bytecode's PC)
|
||||
*/ \
|
||||
macro(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
|
@ -1080,11 +1297,27 @@
|
|||
macro(JSOP_UNUSED147, 147,"unused147", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED148, 148,"unused148", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/* Placeholders for a real jump opcode set during backpatch chain fixup. */ \
|
||||
/*
|
||||
* Placeholder opcode used during bytecode generation. This never
|
||||
* appears in a finished script. FIXME: bug 473671.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: int32_t offset
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_BACKPATCH, 149,"backpatch", NULL, 5, 0, 0, JOF_JUMP) \
|
||||
macro(JSOP_UNUSED150, 150,"unused150", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/* Set pending exception from the stack, to trigger rethrow. */ \
|
||||
/*
|
||||
* Pops the top of stack value as 'v', sets pending exception as 'v',
|
||||
* to trigger rethrow.
|
||||
*
|
||||
* This opcode is used in conditional catch clauses.
|
||||
* Category: Statements
|
||||
* Type: Exception Handling
|
||||
* Operands:
|
||||
* Stack: v =>
|
||||
*/ \
|
||||
macro(JSOP_THROWING, 151,"throwing", NULL, 1, 1, 0, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
|
@ -1411,6 +1644,10 @@
|
|||
* loops all have the same value. The upper bit is set if Ion should be
|
||||
* able to OSR at this point, which is true unless there is non-loop state
|
||||
* on the stack.
|
||||
* Category: Statements
|
||||
* Type: Jumps
|
||||
* Operands: uint8_t BITFIELD
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_LOOPENTRY, 227, "loopentry", NULL, 2, 0, 0, JOF_UINT8)
|
||||
|
||||
|
|
|
@ -274,7 +274,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
|||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
%}
|
||||
|
||||
[noscript, uuid(3d5a6320-8764-11e3-baa7-0800200c9a66)]
|
||||
[noscript, uuid(47fbe8ff-0507-4647-9ea7-e0e1fc76c995)]
|
||||
interface nsIXPConnect : nsISupports
|
||||
{
|
||||
%{ C++
|
||||
|
@ -422,12 +422,6 @@ interface nsIXPConnect : nsISupports
|
|||
getNativeOfWrapper(in JSContextPtr aJSContext,
|
||||
in JSObjectPtr aJSObj);
|
||||
|
||||
/**
|
||||
* The security manager to use when the current JSContext has no security
|
||||
* manager.
|
||||
*/
|
||||
void setDefaultSecurityManager(in nsIXPCSecurityManager aManager);
|
||||
|
||||
nsIStackFrame
|
||||
createStackFrameLocation(in uint32_t aLanguage,
|
||||
in string aFilename,
|
||||
|
@ -437,7 +431,6 @@ interface nsIXPConnect : nsISupports
|
|||
|
||||
|
||||
[noscript,notxpcom,nostdcall] JSContextPtr getCurrentJSContext();
|
||||
[noscript,notxpcom,nostdcall] JSContextPtr initSafeJSContext();
|
||||
[noscript,notxpcom,nostdcall] JSContextPtr getSafeJSContext();
|
||||
|
||||
readonly attribute nsIStackFrame CurrentJSStack;
|
||||
|
|
|
@ -121,7 +121,7 @@ interface ScheduledGCCallback : nsISupports
|
|||
/**
|
||||
* interface of Components.utils
|
||||
*/
|
||||
[scriptable, uuid(45b80e00-fb0d-439e-b7bf-54f24af0c4a6)]
|
||||
[scriptable, uuid(c9b6f5a0-cfe8-11e3-9c1a-0800200c9a66)]
|
||||
interface nsIXPCComponents_Utils : nsISupports
|
||||
{
|
||||
|
||||
|
@ -260,6 +260,22 @@ interface nsIXPCComponents_Utils : nsISupports
|
|||
*/
|
||||
void forceCC();
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
* If any incremental CC is in progress, finish it. For testing.
|
||||
*/
|
||||
void finishCC();
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
* Do some cycle collector work, with the given work budget.
|
||||
* The cost of calling Traverse() on a single object is set as 1.
|
||||
* For testing.
|
||||
*/
|
||||
void ccSlice(in long long budget);
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
|
|
|
@ -534,26 +534,7 @@ mozJSComponentLoader::FindTargetObject(JSContext* aCx,
|
|||
// instance).
|
||||
if (!targetObject) {
|
||||
// Our targetObject is the caller's global object. Let's get it.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(kXPConnectServiceContractID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAXPCNativeCallContext *cc = nullptr;
|
||||
rv = xpc->GetCurrentNativeCallContext(&cc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wn;
|
||||
rv = cc->GetCalleeWrapper(getter_AddRefs(wn));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
targetObject = wn->GetJSObject();
|
||||
if (!targetObject) {
|
||||
NS_ERROR("null calling object");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
targetObject = JS_GetGlobalForObject(aCx, targetObject);
|
||||
targetObject = CurrentGlobalOrNull(aCx);
|
||||
}
|
||||
|
||||
aTargetObject.set(targetObject);
|
||||
|
|
|
@ -19,7 +19,6 @@ class nsAXPCNativeCallContext
|
|||
public:
|
||||
NS_IMETHOD GetCallee(nsISupports **aResult) = 0;
|
||||
NS_IMETHOD GetCalleeMethodIndex(uint16_t *aResult) = 0;
|
||||
NS_IMETHOD GetCalleeWrapper(nsIXPConnectWrappedNative **aResult) = 0;
|
||||
NS_IMETHOD GetJSContext(JSContext **aResult) = 0;
|
||||
NS_IMETHOD GetArgc(uint32_t *aResult) = 0;
|
||||
NS_IMETHOD GetArgvPtr(JS::Value **aResult) = 0;
|
||||
|
|
|
@ -199,14 +199,6 @@ CreateXMLHttpRequest(JSContext *cx, unsigned argc, jsval *vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm)
|
||||
return false;
|
||||
|
||||
nsIPrincipal *subjectPrincipal = ssm->GetCxSubjectPrincipal(cx);
|
||||
if (!subjectPrincipal)
|
||||
return false;
|
||||
|
||||
RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
|
||||
MOZ_ASSERT(global);
|
||||
|
||||
|
@ -215,7 +207,8 @@ CreateXMLHttpRequest(JSContext *cx, unsigned argc, jsval *vp)
|
|||
nsCOMPtr<nsIGlobalObject> iglobal = do_QueryInterface(sop);
|
||||
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = new nsXMLHttpRequest();
|
||||
nsresult rv = xhr->Init(subjectPrincipal, nullptr, iglobal, nullptr);
|
||||
nsresult rv = xhr->Init(nsContentUtils::GetSubjectPrincipal(), nullptr,
|
||||
iglobal, nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
|
@ -1050,10 +1043,6 @@ xpc::CreateSandboxObject(JSContext *cx, MutableHandleValue vp, nsISupports *prin
|
|||
{
|
||||
// Create the sandbox global object
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(prinOrSop);
|
||||
if (!principal) {
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(prinOrSop);
|
||||
|
@ -1297,8 +1286,6 @@ GetExpandedPrincipal(JSContext *cx, HandleObject arrayObj, nsIExpandedPrincipal
|
|||
|
||||
nsTArray< nsCOMPtr<nsIPrincipal> > allowedDomains(length);
|
||||
allowedDomains.SetLength(length);
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
NS_ENSURE_TRUE(ssm, false);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
RootedValue allowed(cx);
|
||||
|
@ -1329,7 +1316,7 @@ GetExpandedPrincipal(JSContext *cx, HandleObject arrayObj, nsIExpandedPrincipal
|
|||
|
||||
// We do not allow ExpandedPrincipals to contain any system principals.
|
||||
bool isSystem;
|
||||
rv = ssm->IsSystemPrincipal(principal, &isSystem);
|
||||
rv = nsXPConnect::SecurityManager()->IsSystemPrincipal(principal, &isSystem);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
if (isSystem) {
|
||||
JS_ReportError(cx, "System principal is not allowed in an expanded principal");
|
||||
|
@ -1651,7 +1638,7 @@ ContextHolder::ContextHolder(JSContext *aOuterCx,
|
|||
{
|
||||
if (mJSContext) {
|
||||
bool isChrome;
|
||||
DebugOnly<nsresult> rv = XPCWrapper::GetSecurityManager()->
|
||||
DebugOnly<nsresult> rv = nsXPConnect::SecurityManager()->
|
||||
IsSystemPrincipal(mPrincipal, &isChrome);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
|
|||
mXPCContext(nullptr),
|
||||
mJSContext(cx),
|
||||
mCallerLanguage(callerLanguage),
|
||||
mFlattenedJSObject(cx),
|
||||
mWrapper(nullptr),
|
||||
mTearOff(nullptr),
|
||||
mName(cx)
|
||||
|
@ -77,14 +76,10 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
|
|||
}
|
||||
}
|
||||
if (mWrapper) {
|
||||
mFlattenedJSObject = mWrapper->GetFlatJSObject();
|
||||
|
||||
if (mTearOff)
|
||||
mScriptableInfo = nullptr;
|
||||
else
|
||||
mScriptableInfo = mWrapper->GetScriptableInfo();
|
||||
} else {
|
||||
MOZ_ASSERT(!mFlattenedJSObject, "What object do we have?");
|
||||
}
|
||||
|
||||
if (!JSID_IS_VOID(name))
|
||||
|
@ -258,15 +253,6 @@ XPCCallContext::GetCalleeMethodIndex(uint16_t *aCalleeMethodIndex)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIXPConnectWrappedNative CalleeWrapper; */
|
||||
NS_IMETHODIMP
|
||||
XPCCallContext::GetCalleeWrapper(nsIXPConnectWrappedNative * *aCalleeWrapper)
|
||||
{
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> rval = mWrapper;
|
||||
rval.forget(aCalleeWrapper);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute XPCNativeInterface CalleeInterface; */
|
||||
NS_IMETHODIMP
|
||||
XPCCallContext::GetCalleeInterface(nsIInterfaceInfo * *aCalleeInterface)
|
||||
|
|
|
@ -1486,8 +1486,7 @@ nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
|
|||
|
||||
// Do the security check if necessary
|
||||
|
||||
nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager();
|
||||
if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsJSID::GetCID()))) {
|
||||
if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(cx, nsJSID::GetCID()))) {
|
||||
// the security manager vetoed. It should have set an exception.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
|
@ -1850,8 +1849,7 @@ nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
|
|||
|
||||
// Do the security check if necessary
|
||||
|
||||
nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
|
||||
if (sm && NS_FAILED(sm->CanCreateInstance(cx, Exception::GetCID()))) {
|
||||
if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(cx, Exception::GetCID()))) {
|
||||
// the security manager vetoed. It should have set an exception.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
|
@ -2359,8 +2357,7 @@ nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
|
|||
|
||||
// Do the security check if necessary
|
||||
|
||||
nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
|
||||
if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCConstructor::GetCID()))) {
|
||||
if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(cx, nsXPCConstructor::GetCID()))) {
|
||||
// the security manager vetoed. It should have set an exception.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
|
@ -2786,6 +2783,22 @@ nsXPCComponents_Utils::ForceCC()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void finishCC(); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::FinishCC()
|
||||
{
|
||||
nsCycleCollector_finishAnyCurrentCollection();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void ccSlice(long long budget); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::CcSlice(int64_t budget)
|
||||
{
|
||||
nsCycleCollector_collectSliceWork(budget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void forceShrinkingGC (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceShrinkingGC()
|
||||
|
|
|
@ -81,22 +81,13 @@ XPCCallContext::GetPrevCallContext() const
|
|||
return mPrevCallContext;
|
||||
}
|
||||
|
||||
inline JSObject*
|
||||
XPCCallContext::GetFlattenedJSObject() const
|
||||
{
|
||||
CHECK_STATE(HAVE_OBJECT);
|
||||
return mFlattenedJSObject;
|
||||
}
|
||||
|
||||
inline nsISupports*
|
||||
XPCCallContext::GetIdentityObject() const
|
||||
{
|
||||
CHECK_STATE(HAVE_OBJECT);
|
||||
if (mWrapper)
|
||||
return mWrapper->GetIdentityObject();
|
||||
return mFlattenedJSObject ?
|
||||
static_cast<nsISupports*>(xpc_GetJSPrivate(mFlattenedJSObject)) :
|
||||
nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline XPCWrappedNative*
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче