merge fx-team to m-c

This commit is contained in:
Rob Campbell 2011-11-24 11:44:28 -04:00
commit 44be5ce2e3
556 changed files with 5139 additions and 69262 deletions

View File

@ -1587,6 +1587,13 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
// Fire MSAA event for client area window. // Fire MSAA event for client area window.
NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID); NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
// JAWS announces collapsed combobox navigation based on focus events.
if (eventType == nsIAccessibleEvent::EVENT_SELECTION &&
accessible->Role() == nsIAccessibleRole::ROLE_COMBOBOX_OPTION &&
nsWinUtils::IsWindowEmulationFor(kJAWSModuleHandle)) {
NotifyWinEvent(EVENT_OBJECT_FOCUS, hWnd, OBJID_CLIENT, childID);
}
return NS_OK; return NS_OK;
} }

View File

@ -61,30 +61,6 @@ DEFINES += -DAB_CD=$(AB_CD)
APP_VERSION = $(shell cat $(srcdir)/../config/version.txt) APP_VERSION = $(shell cat $(srcdir)/../config/version.txt)
DEFINES += -DAPP_VERSION="$(APP_VERSION)" DEFINES += -DAPP_VERSION="$(APP_VERSION)"
DIST_FILES = application.ini
GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build BuildID)
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
MOZ_SOURCE_STAMP ?= $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null)
ifdef MOZ_SOURCE_STAMP
DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
endif
SOURCE_REPO := $(shell hg -R $(topsrcdir) showconfig paths.default 2>/dev/null | sed -e "s/^ssh:/http:/")
ifdef SOURCE_REPO
DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
endif
DEFINES += -DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \
-DMOZ_APP_VENDOR="$(MOZ_APP_VENDOR)"
ifdef MOZ_APP_PROFILE
DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)"
endif
ifdef LIBXUL_SDK ifdef LIBXUL_SDK
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
else else
@ -97,6 +73,7 @@ CPPSRCS = nsBrowserApp.cpp
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
LOCAL_INCLUDES += -I$(DEPTH)/build
DEFINES += -DXPCOM_GLUE DEFINES += -DXPCOM_GLUE
STL_FLAGS= STL_FLAGS=
@ -187,10 +164,6 @@ endif # LIBXUL_SDK
DEFINES += -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\" DEFINES += -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\"
ifdef MOZILLA_OFFICIAL
DEFINES += -DMOZILLA_OFFICIAL
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
libs:: libs::
$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(DIST)/bin/icons $(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(DIST)/bin/icons
@ -228,7 +201,7 @@ else
APPFILES = MacOS APPFILES = MacOS
endif endif
libs repackage:: $(PROGRAM) application.ini libs repackage:: $(PROGRAM)
$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/MacOS $(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/MacOS
rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj $(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj

View File

@ -36,8 +36,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "application.ini.h"
#include "nsXPCOMGlue.h" #include "nsXPCOMGlue.h"
#include "nsXULAppAPI.h"
#if defined(XP_WIN) #if defined(XP_WIN)
#include <windows.h> #include <windows.h>
#include <stdlib.h> #include <stdlib.h>
@ -140,20 +140,7 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
static int do_main(const char *exePath, int argc, char* argv[]) static int do_main(const char *exePath, int argc, char* argv[])
{ {
nsCOMPtr<nsILocalFile> appini; nsCOMPtr<nsILocalFile> appini;
#ifdef XP_WIN nsresult rv;
// exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
// encoded path, so it is safe to convert it
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
getter_AddRefs(appini));
#else
nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
getter_AddRefs(appini));
#endif
if (NS_FAILED(rv)) {
return 255;
}
appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));
// Allow firefox.exe to launch XULRunner apps via -app <application.ini> // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
// Note that -app must be the *first* argument. // Note that -app must be the *first* argument.
@ -188,15 +175,32 @@ static int do_main(const char *exePath, int argc, char* argv[])
argc -= 2; argc -= 2;
} }
nsXREAppData *appData; int result;
rv = XRE_CreateAppData(appini, &appData); if (appini) {
if (NS_FAILED(rv)) { nsXREAppData *appData;
Output("Couldn't read application.ini"); rv = XRE_CreateAppData(appini, &appData);
return 255; if (NS_FAILED(rv)) {
Output("Couldn't read application.ini");
return 255;
}
result = XRE_main(argc, argv, appData);
XRE_FreeAppData(appData);
} else {
#ifdef XP_WIN
// exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
// encoded path, so it is safe to convert it
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), PR_FALSE,
getter_AddRefs(appini));
#else
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_FALSE,
getter_AddRefs(appini));
#endif
if (NS_FAILED(rv)) {
return 255;
}
result = XRE_main(argc, argv, &sAppData);
} }
int result = XRE_main(argc, argv, appData);
XRE_FreeAppData(appData);
return result; return result;
} }
@ -240,6 +244,8 @@ int main(int argc, char* argv[])
Output("Couldn't load XPCOM.\n"); Output("Couldn't load XPCOM.\n");
return 255; return 255;
} }
// Reset exePath so that it is the directory name and not the xpcom dll name
*lastSlash = 0;
rv = XPCOMGlueLoadXULFunctions(kXULFuncs); rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

View File

@ -1,8 +1,8 @@
ac_add_options --enable-debug ac_add_options --enable-debug
ac_add_options --enable-trace-malloc ac_add_options --enable-trace-malloc
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -3,5 +3,5 @@ ac_add_options --enable-official-branding
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging ac_add_options --enable-update-packaging
CC=/tools/gcc-4.3.3/installed/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.3.3/installed/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++

View File

@ -5,8 +5,8 @@ ac_add_options --enable-codesighs
# Nightlies only since this has a cost in performance # Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics ac_add_options --enable-js-diagnostics
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -1,8 +1,8 @@
ac_add_options --enable-update-packaging ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs ac_add_options --enable-codesighs
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -2,8 +2,8 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding ac_add_options --enable-official-branding
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -9,8 +9,8 @@ ac_add_options --disable-updater
ac_add_options --prefix=$PREFIX ac_add_options --prefix=$PREFIX
ac_add_options --libdir=$LIBDIR ac_add_options --libdir=$LIBDIR
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -1,8 +1,8 @@
ac_add_options --enable-debug ac_add_options --enable-debug
ac_add_options --enable-trace-malloc ac_add_options --enable-trace-malloc
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -3,5 +3,5 @@ ac_add_options --enable-official-branding
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging ac_add_options --enable-update-packaging
CC=/tools/gcc/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++

View File

@ -5,8 +5,8 @@ ac_add_options --enable-codesighs
# Nightlies only since this has a cost in performance # Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics ac_add_options --enable-js-diagnostics
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -2,8 +2,8 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding ac_add_options --enable-official-branding
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -9,8 +9,8 @@ ac_add_options --disable-updater
ac_add_options --prefix=$PREFIX ac_add_options --prefix=$PREFIX
ac_add_options --libdir=$LIBDIR ac_add_options --libdir=$LIBDIR
CC=/tools/gcc-4.5/bin/gcc CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5/bin/g++ CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5 # Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat ac_add_options --enable-stdcxx-compat

View File

@ -51,3 +51,7 @@ MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
# because branding dependencies are broken. # because branding dependencies are broken.
MOZ_BRANDING_DIRECTORY=browser/branding/nightly MOZ_BRANDING_DIRECTORY=browser/branding/nightly
MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
MOZ_PROFILE_MIGRATOR=1
MOZ_EXTENSION_MANAGER=1
MOZ_APP_STATIC_INI=1

View File

@ -14,6 +14,7 @@
@DLL_PREFIX@mozjs@DLL_SUFFIX@ @DLL_PREFIX@mozjs@DLL_SUFFIX@
#endif #endif
LICENSE LICENSE
update.locale
browserconfig.properties browserconfig.properties
chrome/US.jar chrome/US.jar
chrome/app-chrome.manifest chrome/app-chrome.manifest

View File

@ -66,6 +66,60 @@ ifeq (android,$(MOZ_WIDGET_TOOLKIT))
endif endif
endif endif
ifdef MOZ_APP_BASENAME
DIST_FILES = application.ini
ifdef LIBXUL_SDK
GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
APP_INI_DEPS = $(LIBXUL_DIST)/bin/platform.ini
else
GRE_MILESTONE = $(shell tail -n 1 $(topsrcdir)/config/milestone.txt 2>/dev/null || tail -1 $(topsrcdir)/config/milestone.txt)
APP_INI_DEPS = $(topsrcdir)/config/milestone.txt
endif
APP_BUILDID := $(shell cat $(DEPTH)/config/buildid)
APP_INI_DEPS += $(DEPTH)/config/buildid
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DAPP_BUILDID=$(APP_BUILDID)
DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
MOZ_SOURCE_STAMP ?= $(firstword $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null))
ifdef MOZ_SOURCE_STAMP
DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
endif
_dollar=$$
SOURCE_REPO := $(shell cd $(topsrcdir) && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
ifdef SOURCE_REPO
DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
endif
DEFINES += \
-DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \
-DMOZ_APP_VENDOR="$(MOZ_APP_VENDOR)" \
-DMOZ_APP_ID="$(MOZ_APP_ID)" \
$(NULL)
ifdef MOZ_APP_PROFILE
DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)"
endif
ifdef MOZILLA_OFFICIAL
DEFINES += -DMOZILLA_OFFICIAL
endif
ifdef MOZ_PROFILE_MIGRATOR
DEFINES += -DMOZ_PROFILE_MIGRATOR
endif
ifdef MOZ_EXTENSION_MANAGER
DEFINES += -DMOZ_EXTENSION_MANAGER
endif
endif
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
# we install to _leaktest/ # we install to _leaktest/
@ -100,6 +154,19 @@ leaktest.py: leaktest.py.in
chmod +x $@ chmod +x $@
GARBAGE += leaktest.py GARBAGE += leaktest.py
ifdef MOZ_APP_BASENAME
application.ini: application.ini.in $(APP_INI_DEPS)
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
GARBAGE += application.ini
ifdef MOZ_APP_STATIC_INI
application.ini.h: appini_header.py application.ini
$(PYTHON) $^ > $@
export:: application.ini.h
GARBAGE += application.ini.h
endif
endif
libs:: $(_LEAKTEST_FILES) libs:: $(_LEAKTEST_FILES)
$(INSTALL) $^ $(_LEAKTEST_DIR) $(INSTALL) $^ $(_LEAKTEST_DIR)

86
build/appini_header.py Normal file
View File

@ -0,0 +1,86 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is a build helper for libraries
#
# The Initial Developer of the Original Code is
# the Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Mike Hommey <mh@glandium.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
'''Parses a given application.ini file and outputs the corresponding
XULAppData structure as a C++ header file'''
import ConfigParser
import sys
def main(file):
config = ConfigParser.RawConfigParser()
config.read(file)
flags = set()
try:
if config.getint('XRE', 'EnableExtensionManager') == 1:
flags.add('NS_XRE_ENABLE_EXTENSION_MANAGER')
except: pass
try:
if config.getint('XRE', 'EnableProfileMigrator') == 1:
flags.add('NS_XRE_ENABLE_PROFILE_MIGRATOR')
except: pass
try:
if config.getint('Crash Reporter', 'Enabled') == 1:
flags.add('NS_XRE_ENABLE_CRASH_REPORTER')
except: pass
appdata = dict(("%s:%s" % (s, o), config.get(s, o)) for s in config.sections() for o in config.options(s))
appdata['flags'] = ' | '.join(flags) if flags else '0'
appdata['App:profile'] = '"%s"' % appdata['App:profile'] if 'App:profile' in appdata else 'NULL'
print '''#include "nsXULAppAPI.h"
static const nsXREAppData sAppData = {
sizeof(nsXREAppData),
NULL, // directory
"%(App:vendor)s",
"%(App:name)s",
"%(App:version)s",
"%(App:buildid)s",
"%(App:id)s",
NULL, // copyright
%(flags)s,
NULL, // xreDirectory
"%(Gecko:minversion)s",
"%(Gecko:maxversion)s",
"%(Crash Reporter:serverurl)s",
%(App:profile)s
};''' % appdata
if __name__ == '__main__':
if len(sys.argv) != 1:
main(sys.argv[1])
else:
print >>sys.stderr, "Usage: %s /path/to/application.ini" % sys.argv[0]

View File

@ -1,3 +1,9 @@
#if MOZ_APP_STATIC_INI
; This file is not used. If you modify it and want the application to use
; your modifications, start with the "-app /path/to/application.ini"
; argument.
#endif
#if 0
; ***** BEGIN LICENSE BLOCK ***** ; ***** BEGIN LICENSE BLOCK *****
; Version: MPL 1.1/GPL 2.0/LGPL 2.1 ; Version: MPL 1.1/GPL 2.0/LGPL 2.1
; ;
@ -34,34 +40,38 @@
; the terms of any one of the MPL, the GPL or the LGPL. ; the terms of any one of the MPL, the GPL or the LGPL.
; ;
; ***** END LICENSE BLOCK ***** ; ***** END LICENSE BLOCK *****
#endif
#filter substitution #filter substitution
[App] [App]
Vendor=@MOZ_APP_VENDOR@ Vendor=@MOZ_APP_VENDOR@
Name=@MOZ_APP_BASENAME@ Name=@MOZ_APP_BASENAME@
Version=@APP_VERSION@ Version=@MOZ_APP_VERSION@
#ifdef MOZ_APP_PROFILE #ifdef MOZ_APP_PROFILE
Profile=@MOZ_APP_PROFILE@ Profile=@MOZ_APP_PROFILE@
#endif #endif
BuildID=@GRE_BUILDID@ BuildID=@APP_BUILDID@
#ifdef MOZ_SOURCE_REPO #ifdef MOZ_SOURCE_REPO
SourceRepository=@MOZ_SOURCE_REPO@ SourceRepository=@MOZ_SOURCE_REPO@
#endif #endif
#ifdef MOZ_SOURCE_STAMP #ifdef MOZ_SOURCE_STAMP
SourceStamp=@MOZ_SOURCE_STAMP@ SourceStamp=@MOZ_SOURCE_STAMP@
#endif #endif
ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} ID=@MOZ_APP_ID@
[Gecko] [Gecko]
MinVersion=@GRE_MILESTONE@ MinVersion=@GRE_MILESTONE@
MaxVersion=@GRE_MILESTONE@ MaxVersion=@GRE_MILESTONE@
[XRE] [XRE]
#ifdef MOZ_PROFILE_MIGRATOR
EnableProfileMigrator=1 EnableProfileMigrator=1
#endif
#ifdef MOZ_EXTENSION_MANAGER
EnableExtensionManager=1 EnableExtensionManager=1
#endif
[Crash Reporter] [Crash Reporter]
#if MOZILLA_OFFICIAL #if MOZILLA_OFFICIAL
Enabled=1 Enabled=1
#endif #endif
ServerURL=https://crash-reports.mozilla.com/submit?id=ec8030f7-c20a-464f-9b0e-13a3a9e97384&version=@APP_VERSION@&buildid=@GRE_BUILDID@ ServerURL=https://crash-reports.mozilla.com/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSION@&buildid=@APP_BUILDID@

View File

@ -340,6 +340,7 @@ user_pref("browser.ui.layout.tablet", 0); // force tablet UI off
user_pref("dom.allow_scripts_to_close_windows", true); user_pref("dom.allow_scripts_to_close_windows", true);
user_pref("dom.disable_open_during_load", false); user_pref("dom.disable_open_during_load", false);
user_pref("dom.max_script_run_time", 0); // no slow script dialogs user_pref("dom.max_script_run_time", 0); // no slow script dialogs
user_pref("hangmonitor.timeout", 0); // no hang monitor
user_pref("dom.max_chrome_script_run_time", 0); user_pref("dom.max_chrome_script_run_time", 0);
user_pref("dom.popup_maximum", -1); user_pref("dom.popup_maximum", -1);
user_pref("dom.send_after_paint_to_content", true); user_pref("dom.send_after_paint_to_content", true);
@ -366,6 +367,9 @@ user_pref("app.update.enabled", false);
user_pref("browser.panorama.experienced_first_run", true); // Assume experienced user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
user_pref("dom.w3c_touch_events.enabled", true); user_pref("dom.w3c_touch_events.enabled", true);
user_pref("toolkit.telemetry.prompted", 2); user_pref("toolkit.telemetry.prompted", 2);
// Existing tests assume there is no font size inflation.
user_pref("font.size.inflation.emPerLine", 0);
user_pref("font.size.inflation.minTwips", 0);
// Only load extensions from the application and user profile // Only load extensions from the application and user profile
// AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION

View File

@ -52,9 +52,13 @@ MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@
MOZ_APP_BASENAME = @MOZ_APP_BASENAME@ MOZ_APP_BASENAME = @MOZ_APP_BASENAME@
MOZ_APP_VENDOR = @MOZ_APP_VENDOR@ MOZ_APP_VENDOR = @MOZ_APP_VENDOR@
MOZ_APP_PROFILE = @MOZ_APP_PROFILE@ MOZ_APP_PROFILE = @MOZ_APP_PROFILE@
MOZ_APP_ID = @MOZ_APP_ID@
MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@
MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@ MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
MOZ_APP_VERSION = @MOZ_APP_VERSION@ MOZ_APP_VERSION = @MOZ_APP_VERSION@
MOZ_UA_BUILDID = @MOZ_UA_BUILDID@ MOZ_UA_BUILDID = @MOZ_UA_BUILDID@
MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@ MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@

View File

@ -64,8 +64,6 @@ ifdef SDK_HEADERS
EXPORTS += $(SDK_HEADERS) EXPORTS += $(SDK_HEADERS)
endif endif
REPORT_BUILD = @echo $(notdir $<)
ifeq ($(OS_ARCH),OS2) ifeq ($(OS_ARCH),OS2)
EXEC = EXEC =
else else
@ -1150,32 +1148,25 @@ endif # MOZ_AUTO_DEPS
# Rules for building native targets must come first because of the host_ prefix # Rules for building native targets must come first because of the host_ prefix
host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
%:: %.c $(GLOBAL_DEPS) %:: %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS) $(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) %.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
@ -1186,7 +1177,6 @@ moc_%.cpp: %.h $(GLOBAL_DEPS)
$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@ $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
moc_%.cc: %.cc $(GLOBAL_DEPS) moc_%.cc: %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@ $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
ifdef ASFILES ifdef ASFILES
@ -1207,12 +1197,10 @@ endif
# Please keep the next two rules in sync. # Please keep the next two rules in sync.
# #
%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) %.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) %.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
ifdef STRICT_CPLUSPLUS_SUFFIX ifdef STRICT_CPLUSPLUS_SUFFIX
echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
@ -1223,12 +1211,10 @@ else
endif #STRICT_CPLUSPLUS_SUFFIX endif #STRICT_CPLUSPLUS_SUFFIX
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
@ -1478,7 +1464,6 @@ XPIDL_DEPS = \
$(NULL) $(NULL)
$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \ $(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \ -I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \ -I$(topsrcdir)/xpcom/idl-parser \
@ -1490,7 +1475,6 @@ ifndef NO_GEN_XPT
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components. # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \ $(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \ -I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \ -I$(topsrcdir)/xpcom/idl-parser \
@ -1779,15 +1763,12 @@ define MAKE_DEPS_NOAUTO
endef endef
$(MDDEPDIR)/%.pp: %.c $(MDDEPDIR)/%.pp: %.c
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO) @$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.cpp $(MDDEPDIR)/%.pp: %.cpp
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO) @$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.s $(MDDEPDIR)/%.pp: %.s
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO) @$(MAKE_DEPS_NOAUTO)
ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))

View File

@ -8503,10 +8503,15 @@ AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
# - MOZ_APP_DISPLAYNAME: Used in user-visible fields (DLL properties, # - MOZ_APP_DISPLAYNAME: Used in user-visible fields (DLL properties,
# Mac Bundle name, Updater, Installer), it is typically used for nightly # Mac Bundle name, Updater, Installer), it is typically used for nightly
# builds (e.g. Aurora for Firefox). # builds (e.g. Aurora for Firefox).
# - MOZ_APP_VERSION: Defines the application version number.
# - MOZ_APP_NAME: Used for e.g. the binary program file name. If not set, # - MOZ_APP_NAME: Used for e.g. the binary program file name. If not set,
# defaults to a lowercase form of MOZ_APP_BASENAME. # defaults to a lowercase form of MOZ_APP_BASENAME.
# - MOZ_APP_PROFILE: When set, used for application.ini's # - MOZ_APP_PROFILE: When set, used for application.ini's
# "Profile" field, which controls profile location. # "Profile" field, which controls profile location.
# - MOZ_APP_ID: When set, used for application.ini's "ID" field, and
# crash reporter server url.
# - MOZ_PROFILE_MIGRATOR: When set, enables profile migrator.
# - MOZ_EXTENSION_MANAGER: When set, enabled extension manager.
if test -z "$MOZ_APP_NAME"; then if test -z "$MOZ_APP_NAME"; then
MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z` MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z`
@ -8517,6 +8522,9 @@ AC_SUBST(MOZ_APP_DISPLAYNAME)
AC_SUBST(MOZ_APP_BASENAME) AC_SUBST(MOZ_APP_BASENAME)
AC_SUBST(MOZ_APP_VENDOR) AC_SUBST(MOZ_APP_VENDOR)
AC_SUBST(MOZ_APP_PROFILE) AC_SUBST(MOZ_APP_PROFILE)
AC_SUBST(MOZ_APP_ID)
AC_SUBST(MOZ_PROFILE_MIGRATOR)
AC_SUBST(MOZ_EXTENSION_MANAGER)
AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME") AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
AC_SUBST(MOZ_APP_UA_NAME) AC_SUBST(MOZ_APP_UA_NAME)
AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION") AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION")
@ -8527,6 +8535,13 @@ AC_SUBST(FIREFOX_VERSION)
AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID") AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
AC_SUBST(MOZ_UA_BUILDID) AC_SUBST(MOZ_UA_BUILDID)
# We can't use the static application.ini data when building against
# a libxul SDK.
if test -n "$LIBXUL_SDK"; then
MOZ_APP_STATIC_INI=
fi
AC_SUBST(MOZ_APP_STATIC_INI)
AC_SUBST(MOZ_PKG_SPECIAL) AC_SUBST(MOZ_PKG_SPECIAL)
AC_SUBST(MOZILLA_OFFICIAL) AC_SUBST(MOZILLA_OFFICIAL)

View File

@ -100,3 +100,4 @@ load 693212.xhtml
load 698974-1.html load 698974-1.html
load 700090-1.html load 700090-1.html
load 700090-2.html load 700090-2.html
load xhr_html_nullresponse.html

View File

@ -0,0 +1,5 @@
<!DOCTYPE html>
<html class="reftest-wait">
<script>
var xhr=new XMLHttpRequest();xhr.open("GET",window.location);xhr.overrideMimeType("text/html");xhr.onprogress=function(){if(xhr.readyState!=3)return;xhr.abort();document.documentElement.removeAttribute('class');};xhr.onabort=function(){xhr.responseText;};xhr.send();
</script>

View File

@ -124,8 +124,8 @@ class Element;
} // namespace mozilla } // namespace mozilla
#define NS_IDOCUMENT_IID \ #define NS_IDOCUMENT_IID \
{ 0xc3e40e8e, 0x8b91, 0x424c, \ { 0x184e0a3c, 0x1899, 0x417d, \
{ 0xbe, 0x9c, 0x9c, 0xc1, 0x76, 0xa7, 0xf7, 0x24 } } { 0xbf, 0xf4, 0x5a, 0x15, 0xe6, 0xe8, 0xaa, 0x94 } }
// Flag for AddStyleSheet(). // Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0) #define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -1562,7 +1562,15 @@ public:
virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) = 0; virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) = 0;
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0; virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
// Called to notify the document that a listener on the "mozaudioavailable"
// event has been added. Media elements in the document need to ensure they
// fire the event.
virtual void NotifyAudioAvailableListener() = 0;
// Returns true if the document has "mozaudioavailable" event listeners.
virtual bool HasAudioAvailableListeners() = 0;
// Add aLink to the set of links that need their status resolved. // Add aLink to the set of links that need their status resolved.
void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink); void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink);

View File

@ -8237,6 +8237,25 @@ nsDocument::AddImage(imgIRequest* aImage)
return rv; return rv;
} }
static void
NotifyAudioAvailableListener(nsIContent *aContent, void *aUnused)
{
#ifdef MOZ_MEDIA
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
if (domMediaElem) {
nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aContent);
mediaElem->NotifyAudioAvailableListener();
}
#endif
}
void
nsDocument::NotifyAudioAvailableListener()
{
mHasAudioAvailableListener = true;
EnumerateFreezableElements(::NotifyAudioAvailableListener, nsnull);
}
nsresult nsresult
nsDocument::RemoveImage(imgIRequest* aImage) nsDocument::RemoveImage(imgIRequest* aImage)
{ {

View File

@ -949,6 +949,13 @@ public:
virtual Element* FindImageMap(const nsAString& aNormalizedMapName); virtual Element* FindImageMap(const nsAString& aNormalizedMapName);
virtual void NotifyAudioAvailableListener();
bool HasAudioAvailableListeners()
{
return mHasAudioAvailableListener;
}
virtual Element* GetFullScreenElement(); virtual Element* GetFullScreenElement();
virtual void AsyncRequestFullScreen(Element* aElement); virtual void AsyncRequestFullScreen(Element* aElement);
virtual void CancelFullScreen(); virtual void CancelFullScreen();
@ -1157,6 +1164,10 @@ protected:
// Whether we currently require our images to animate // Whether we currently require our images to animate
bool mAnimatingImages:1; bool mAnimatingImages:1;
// Whether some node in this document has a listener for the
// "mozaudioavailable" event.
bool mHasAudioAvailableListener:1;
// Whether we are currently in full-screen mode, as per the DOM API. // Whether we are currently in full-screen mode, as per the DOM API.
bool mIsFullScreen:1; bool mIsFullScreen:1;

View File

@ -2167,9 +2167,9 @@ static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback,
continue; continue;
// overlapping with the offset we want // overlapping with the offset we want
f->EnsureTextRun(); f->EnsureTextRun(nsTextFrame::eInflated);
NS_ENSURE_TRUE(f->GetTextRun(), NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(f->GetTextRun(nsTextFrame::eInflated), NS_ERROR_OUT_OF_MEMORY);
bool rtl = f->GetTextRun()->IsRightToLeft(); bool rtl = f->GetTextRun(nsTextFrame::eInflated)->IsRightToLeft();
nsRect r(f->GetOffsetTo(relativeTo), f->GetSize()); nsRect r(f->GetOffsetTo(relativeTo), f->GetSize());
if (fstart < aStartOffset) { if (fstart < aStartOffset) {
// aStartOffset is within this frame // aStartOffset is within this frame

View File

@ -43,6 +43,8 @@
#ifndef nsTextFragment_h___ #ifndef nsTextFragment_h___
#define nsTextFragment_h___ #define nsTextFragment_h___
#include "mozilla/Attributes.h"
#include "nsString.h" #include "nsString.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsTraceRefcnt.h" #include "nsTraceRefcnt.h"
@ -80,7 +82,7 @@ class nsCString;
* This class does not have a virtual destructor therefore it is not * This class does not have a virtual destructor therefore it is not
* meant to be subclassed. * meant to be subclassed.
*/ */
class NS_FINAL_CLASS nsTextFragment { class nsTextFragment MOZ_FINAL {
public: public:
static nsresult Init(); static nsresult Init();
static void Shutdown(); static void Shutdown();

View File

@ -164,7 +164,8 @@ nsWebSocket::CloseConnection()
if (mReadyState == nsIMozWebSocket::CONNECTING) { if (mReadyState == nsIMozWebSocket::CONNECTING) {
SetReadyState(nsIMozWebSocket::CLOSED); SetReadyState(nsIMozWebSocket::CLOSED);
mWebSocketChannel->Close(mClientReasonCode, mClientReason); if (mWebSocketChannel)
mWebSocketChannel->Close(mClientReasonCode, mClientReason);
Disconnect(); Disconnect();
return NS_OK; return NS_OK;
} }

View File

@ -1476,7 +1476,7 @@ nsXMLHttpRequest::IsSystemXHR()
bool bool
nsXMLHttpRequest::IsWaitingForHTMLCharset() nsXMLHttpRequest::IsWaitingForHTMLCharset()
{ {
if (!mIsHtml) { if (!mIsHtml || !mResponseXML) {
return false; return false;
} }
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mResponseXML); nsCOMPtr<nsIDocument> doc = do_QueryInterface(mResponseXML);

View File

@ -614,7 +614,8 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
PRInt32 status; PRInt32 status;
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
if (mOptions.antialias && if (mOptions.antialias &&
gfxInfo &&
NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_MSAA, &status))) { NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_MSAA, &status))) {
if (status == nsIGfxInfo::FEATURE_NO_INFO || forceMSAA) { if (status == nsIGfxInfo::FEATURE_NO_INFO || forceMSAA) {
PRUint32 msaaLevel = Preferences::GetUint("webgl.msaa-level", 2); PRUint32 msaaLevel = Preferences::GetUint("webgl.msaa-level", 2);

View File

@ -2544,7 +2544,8 @@ GetScrollableLineHeight(nsIFrame* aTargetFrame)
// Fall back to the font height of the target frame. // Fall back to the font height of the target frame.
nsRefPtr<nsFontMetrics> fm; nsRefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(aTargetFrame, getter_AddRefs(fm)); nsLayoutUtils::GetFontMetricsForFrame(aTargetFrame, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(aTargetFrame));
NS_ASSERTION(fm, "FontMetrics is null!"); NS_ASSERTION(fm, "FontMetrics is null!");
if (fm) if (fm)
return fm->MaxHeight(); return fm->MaxHeight();

View File

@ -178,6 +178,13 @@ public:
// (no data has arrived for a while). // (no data has arrived for a while).
void DownloadStalled(); void DownloadStalled();
// Called when a "MozAudioAvailable" event listener is added. The media
// element will then notify its decoder that it needs to make a copy of
// the audio data sent to hardware and dispatch it in "mozaudioavailable"
// events. This allows us to not perform the copy and thus reduce overhead
// in the common case where we don't have a "MozAudioAvailable" listener.
void NotifyAudioAvailableListener();
// Called by the media decoder and the video frame to get the // Called by the media decoder and the video frame to get the
// ImageContainer containing the video data. // ImageContainer containing the video data.
ImageContainer* GetImageContainer(); ImageContainer* GetImageContainer();
@ -301,12 +308,6 @@ public:
void NotifyAudioAvailable(float* aFrameBuffer, PRUint32 aFrameBufferLength, void NotifyAudioAvailable(float* aFrameBuffer, PRUint32 aFrameBufferLength,
float aTime); float aTime);
/**
* Called in order to check whether some node (this window, its document,
* or content in that document) has a MozAudioAvailable event listener.
*/
bool MayHaveAudioAvailableEventListener();
virtual bool IsNodeOfType(PRUint32 aFlags) const; virtual bool IsNodeOfType(PRUint32 aFlags) const;
/** /**

View File

@ -2008,13 +2008,16 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
// if it was cancelled and a radio button, then set the old // if it was cancelled and a radio button, then set the old
// selected btn to TRUE. if it is a checkbox then set it to its // selected btn to TRUE. if it is a checkbox then set it to its
// original value // original value
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton = if (oldType == NS_FORM_INPUT_RADIO) {
do_QueryInterface(aVisitor.mItemData); nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton =
if (selectedRadioButton) { do_QueryInterface(aVisitor.mItemData);
selectedRadioButton->SetChecked(true); if (selectedRadioButton) {
// If this one is no longer a radio button we must reset it back to selectedRadioButton->SetChecked(true);
// false to cancel the action. See how the web of hack grows? }
if (mType != NS_FORM_INPUT_RADIO) { // If there was no checked radio button or this one is no longer a
// radio button we must reset it back to false to cancel the action.
// See how the web of hack grows?
if (!selectedRadioButton || mType != NS_FORM_INPUT_RADIO) {
DoSetChecked(false, true, true); DoSetChecked(false, true, true);
} }
} else if (oldType == NS_FORM_INPUT_CHECKBOX) { } else if (oldType == NS_FORM_INPUT_CHECKBOX) {

View File

@ -702,24 +702,6 @@ void nsHTMLMediaElement::NotifyAudioAvailable(float* aFrameBuffer,
DispatchAudioAvailableEvent(frameBuffer.forget(), aFrameBufferLength, aTime); DispatchAudioAvailableEvent(frameBuffer.forget(), aFrameBufferLength, aTime);
} }
bool nsHTMLMediaElement::MayHaveAudioAvailableEventListener()
{
// Determine if the current element is focused, if it is not focused
// then we should not try to blur. Note: we allow for the case of
// |var a = new Audio()| with no parent document.
nsIDocument *document = GetDocument();
if (!document) {
return true;
}
nsPIDOMWindow *window = document->GetInnerWindow();
if (!window) {
return true;
}
return window->HasAudioAvailableEventListeners();
}
void nsHTMLMediaElement::LoadFromSourceChildren() void nsHTMLMediaElement::LoadFromSourceChildren()
{ {
NS_ASSERTION(mDelayingLoadEvent, NS_ASSERTION(mDelayingLoadEvent,
@ -1498,6 +1480,13 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar
// The preload action depends on the value of the autoplay attribute. // The preload action depends on the value of the autoplay attribute.
// It's value may have changed, so update it. // It's value may have changed, so update it.
UpdatePreloadAction(); UpdatePreloadAction();
if (aDocument->HasAudioAvailableListeners()) {
// The document already has listeners for the "MozAudioAvailable"
// event, so the decoder must be notified so it initiates
// "MozAudioAvailable" event dispatch.
NotifyAudioAvailableListener();
}
} }
return rv; return rv;
@ -1914,6 +1903,10 @@ nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
} }
} }
if (OwnerDoc()->HasAudioAvailableListeners()) {
NotifyAudioAvailableListener();
}
mBegun = true; mBegun = true;
return rv; return rv;
} }
@ -2714,3 +2707,10 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMozFragmentEnd(double *aTime)
*aTime = (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd; *aTime = (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd;
return NS_OK; return NS_OK;
} }
void nsHTMLMediaElement::NotifyAudioAvailableListener()
{
if (mDecoder) {
mDecoder->NotifyAudioAvailableListener();
}
}

View File

@ -84,7 +84,8 @@ nsAudioAvailableEventManager::nsAudioAvailableEventManager(nsBuiltinDecoder* aDe
mSignalBufferLength(mDecoder->GetFrameBufferLength()), mSignalBufferLength(mDecoder->GetFrameBufferLength()),
mNewSignalBufferLength(mSignalBufferLength), mNewSignalBufferLength(mSignalBufferLength),
mSignalBufferPosition(0), mSignalBufferPosition(0),
mReentrantMonitor("media.audioavailableeventmanager") mReentrantMonitor("media.audioavailableeventmanager"),
mHasListener(false)
{ {
MOZ_COUNT_CTOR(nsAudioAvailableEventManager); MOZ_COUNT_CTOR(nsAudioAvailableEventManager);
} }
@ -104,6 +105,10 @@ void nsAudioAvailableEventManager::DispatchPendingEvents(PRUint64 aCurrentTime)
{ {
ReentrantMonitorAutoEnter mon(mReentrantMonitor); ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mHasListener) {
return;
}
while (mPendingEvents.Length() > 0) { while (mPendingEvents.Length() > 0) {
nsAudioAvailableEventRunner* e = nsAudioAvailableEventRunner* e =
(nsAudioAvailableEventRunner*)mPendingEvents[0].get(); (nsAudioAvailableEventRunner*)mPendingEvents[0].get();
@ -122,6 +127,10 @@ void nsAudioAvailableEventManager::QueueWrittenAudioData(AudioDataValue* aAudioD
{ {
ReentrantMonitorAutoEnter mon(mReentrantMonitor); ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mHasListener) {
return;
}
PRUint32 currentBufferSize = mNewSignalBufferLength; PRUint32 currentBufferSize = mNewSignalBufferLength;
if (currentBufferSize == 0) { if (currentBufferSize == 0) {
NS_WARNING("Decoder framebuffer length not set."); NS_WARNING("Decoder framebuffer length not set.");
@ -212,6 +221,10 @@ void nsAudioAvailableEventManager::Drain(PRUint64 aEndTime)
{ {
ReentrantMonitorAutoEnter mon(mReentrantMonitor); ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (!mHasListener) {
return;
}
// Force all pending events to go now. // Force all pending events to go now.
for (PRUint32 i = 0; i < mPendingEvents.Length(); ++i) { for (PRUint32 i = 0; i < mPendingEvents.Length(); ++i) {
nsCOMPtr<nsIRunnable> event = mPendingEvents[i]; nsCOMPtr<nsIRunnable> event = mPendingEvents[i];
@ -245,3 +258,9 @@ void nsAudioAvailableEventManager::SetSignalBufferLength(PRUint32 aLength)
mNewSignalBufferLength = aLength; mNewSignalBufferLength = aLength;
} }
void nsAudioAvailableEventManager::NotifyAudioAvailableListener()
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mHasListener = true;
}

View File

@ -80,6 +80,11 @@ public:
// Called from the main and the state machine thread. // Called from the main and the state machine thread.
void SetSignalBufferLength(PRUint32 aLength); void SetSignalBufferLength(PRUint32 aLength);
// Called by the media element to notify the manager that there is a
// listener on the "MozAudioAvailable" event, and that we need to dispatch
// such events. Called from the main thread.
void NotifyAudioAvailableListener();
private: private:
// The decoder associated with the event manager. The event manager shares // The decoder associated with the event manager. The event manager shares
// the same lifetime as the decoder (the decoder holds a reference to the // the same lifetime as the decoder (the decoder holds a reference to the
@ -108,6 +113,11 @@ private:
// ReentrantMonitor for shared access to mPendingEvents queue or // ReentrantMonitor for shared access to mPendingEvents queue or
// buffer length. // buffer length.
ReentrantMonitor mReentrantMonitor; ReentrantMonitor mReentrantMonitor;
// True if something in the owning document has a listener on the
// "MozAudioAvailable" event. If not, we don't need to bother copying played
// audio data and dispatching the event. Synchronized by mReentrantMonitor.
bool mHasListener;
}; };
#endif #endif

View File

@ -397,14 +397,9 @@ void nsBuiltinDecoder::AudioAvailable(float* aFrameBuffer,
// to HTMLMediaElement::NotifyAudioAvailable(). // to HTMLMediaElement::NotifyAudioAvailable().
nsAutoArrayPtr<float> frameBuffer(aFrameBuffer); nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
if (mShuttingDown) { if (mShuttingDown || !mElement) {
return; return;
} }
if (!mElement || !mElement->MayHaveAudioAvailableEventListener()) {
return;
}
mElement->NotifyAudioAvailable(frameBuffer.forget(), aFrameBufferLength, aTime); mElement->NotifyAudioAvailable(frameBuffer.forget(), aFrameBufferLength, aTime);
} }
@ -1005,6 +1000,16 @@ void nsBuiltinDecoder::UpdatePlaybackOffset(PRInt64 aOffset)
mPlaybackPosition = NS_MAX(aOffset, mPlaybackPosition); mPlaybackPosition = NS_MAX(aOffset, mPlaybackPosition);
} }
bool nsBuiltinDecoder::OnStateMachineThread() const { bool nsBuiltinDecoder::OnStateMachineThread() const
{
return IsCurrentThread(nsBuiltinDecoderStateMachine::GetStateMachineThread()); return IsCurrentThread(nsBuiltinDecoderStateMachine::GetStateMachineThread());
} }
void nsBuiltinDecoder::NotifyAudioAvailableListener()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
if (mDecoderStateMachine) {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mDecoderStateMachine->NotifyAudioAvailableListener();
}
}

View File

@ -344,6 +344,10 @@ public:
// Sets the current size of the framebuffer used in MozAudioAvailable events. // Sets the current size of the framebuffer used in MozAudioAvailable events.
// Called on the state machine thread and the main thread. // Called on the state machine thread and the main thread.
virtual void SetFrameBufferLength(PRUint32 aLength) = 0; virtual void SetFrameBufferLength(PRUint32 aLength) = 0;
// Called when a "MozAudioAvailable" event listener is added to the media
// element. Called on the main thread.
virtual void NotifyAudioAvailableListener() = 0;
}; };
class nsBuiltinDecoder : public nsMediaDecoder class nsBuiltinDecoder : public nsMediaDecoder
@ -610,6 +614,10 @@ class nsBuiltinDecoder : public nsMediaDecoder
// Drop reference to state machine. Only called during shutdown dance. // Drop reference to state machine. Only called during shutdown dance.
void ReleaseStateMachine() { mDecoderStateMachine = nsnull; } void ReleaseStateMachine() { mDecoderStateMachine = nsnull; }
// Called when a "MozAudioAvailable" event listener is added to the media
// element. Called on the main thread.
virtual void NotifyAudioAvailableListener();
public: public:
// Notifies the element that decoding has failed. // Notifies the element that decoding has failed.
void DecodeError(); void DecodeError();

View File

@ -2201,4 +2201,8 @@ nsIThread* nsBuiltinDecoderStateMachine::GetStateMachineThread()
return StateMachineTracker::Instance().GetGlobalStateMachineThread(); return StateMachineTracker::Instance().GetGlobalStateMachineThread();
} }
void nsBuiltinDecoderStateMachine::NotifyAudioAvailableListener()
{
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
mEventManager.NotifyAudioAvailableListener();
}

View File

@ -265,6 +265,10 @@ public:
// Drop reference to decoder. Only called during shutdown dance. // Drop reference to decoder. Only called during shutdown dance.
void ReleaseDecoder() { mDecoder = nsnull; } void ReleaseDecoder() { mDecoder = nsnull; }
// Called when a "MozAudioAvailable" event listener is added to the media
// element. Called on the main thread.
void NotifyAudioAvailableListener();
protected: protected:
// Returns true if we've got less than aAudioUsecs microseconds of decoded // Returns true if we've got less than aAudioUsecs microseconds of decoded

View File

@ -158,6 +158,11 @@ public:
// Call in the main thread only. // Call in the main thread only.
virtual bool IsEnded() const = 0; virtual bool IsEnded() const = 0;
// Called when a "MozAudioAvailable" event listener is added. This enables
// the decoder to only dispatch "MozAudioAvailable" events when a
// handler exists, reducing overhead. Called on the main thread.
virtual void NotifyAudioAvailableListener() = 0;
struct Statistics { struct Statistics {
// Estimate of the current playback rate (bytes/second). // Estimate of the current playback rate (bytes/second).
double mPlaybackRate; double mPlaybackRate;

View File

@ -766,7 +766,6 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(false), mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(false),
mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nsnull), mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nsnull),
mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false), mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
mMayHaveAudioAvailableEventListener(false),
mMayHaveMouseEnterLeaveEventListener(false), mMayHaveMouseEnterLeaveEventListener(false),
mIsModalContentWindow(false), mIsModalContentWindow(false),
mIsActive(false), mIsBackground(false), mIsActive(false), mIsBackground(false),
@ -10676,6 +10675,14 @@ nsGlobalModalWindow::SetNewDocument(nsIDocument *aDocument,
aForceReuseInnerWindow); aForceReuseInnerWindow);
} }
void
nsGlobalWindow::SetHasAudioAvailableEventListeners()
{
if (mDoc) {
mDoc->NotifyAudioAvailableListener();
}
}
//***************************************************************************** //*****************************************************************************
// nsGlobalWindow: Creator Function (This should go away) // nsGlobalWindow: Creator Function (This should go away)
//***************************************************************************** //*****************************************************************************

View File

@ -447,6 +447,8 @@ public:
// Prevent further dialogs in this (top level) window // Prevent further dialogs in this (top level) window
void PreventFurtherDialogs(); void PreventFurtherDialogs();
virtual void SetHasAudioAvailableEventListeners();
nsIScriptContext *GetContextInternal() nsIScriptContext *GetContextInternal()
{ {
if (mOuterWindow) { if (mOuterWindow) {

View File

@ -927,8 +927,6 @@ static const char js_zeal_option_str[] = JS_OPTIONS_DOT_STR "gczeal";
static const char js_zeal_frequency_str[] = JS_OPTIONS_DOT_STR "gczeal.frequency"; static const char js_zeal_frequency_str[] = JS_OPTIONS_DOT_STR "gczeal.frequency";
static const char js_zeal_compartment_str[] = JS_OPTIONS_DOT_STR "gczeal.compartment_gc"; static const char js_zeal_compartment_str[] = JS_OPTIONS_DOT_STR "gczeal.compartment_gc";
#endif #endif
static const char js_tracejit_content_str[] = JS_OPTIONS_DOT_STR "tracejit.content";
static const char js_tracejit_chrome_str[] = JS_OPTIONS_DOT_STR "tracejit.chrome";
static const char js_methodjit_content_str[] = JS_OPTIONS_DOT_STR "methodjit.content"; static const char js_methodjit_content_str[] = JS_OPTIONS_DOT_STR "methodjit.content";
static const char js_methodjit_chrome_str[] = JS_OPTIONS_DOT_STR "methodjit.chrome"; static const char js_methodjit_chrome_str[] = JS_OPTIONS_DOT_STR "methodjit.chrome";
static const char js_profiling_content_str[] = JS_OPTIONS_DOT_STR "jitprofiling.content"; static const char js_profiling_content_str[] = JS_OPTIONS_DOT_STR "jitprofiling.content";
@ -960,9 +958,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
// XXX components be covered by the chrome pref instead of the content one? // XXX components be covered by the chrome pref instead of the content one?
nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(global)); nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(global));
bool useTraceJIT = Preferences::GetBool(chromeWindow ?
js_tracejit_chrome_str :
js_tracejit_content_str);
bool useMethodJIT = Preferences::GetBool(chromeWindow ? bool useMethodJIT = Preferences::GetBool(chromeWindow ?
js_methodjit_chrome_str : js_methodjit_chrome_str :
js_methodjit_content_str); js_methodjit_content_str);
@ -980,7 +975,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
bool safeMode = false; bool safeMode = false;
xr->GetInSafeMode(&safeMode); xr->GetInSafeMode(&safeMode);
if (safeMode) { if (safeMode) {
useTraceJIT = false;
useMethodJIT = false; useMethodJIT = false;
useProfiling = false; useProfiling = false;
usePCCounts = false; usePCCounts = false;
@ -990,11 +984,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
} }
} }
if (useTraceJIT)
newDefaultJSOptions |= JSOPTION_JIT;
else
newDefaultJSOptions &= ~JSOPTION_JIT;
if (useMethodJIT) if (useMethodJIT)
newDefaultJSOptions |= JSOPTION_METHODJIT; newDefaultJSOptions |= JSOPTION_METHODJIT;
else else

View File

@ -80,8 +80,8 @@ class nsIArray;
class nsPIWindowRoot; class nsPIWindowRoot;
#define NS_PIDOMWINDOW_IID \ #define NS_PIDOMWINDOW_IID \
{ 0x8ce567b5, 0xcc8d, 0x410b, \ { 0x9db588f7, 0x3472, 0x45d0, \
{ 0xa2, 0x7b, 0x07, 0xaf, 0x31, 0xc0, 0x33, 0xb8 } } { 0x9f, 0x9b, 0x95, 0xca, 0xf6, 0x4d, 0x1a, 0xb1 } }
class nsPIDOMWindow : public nsIDOMWindowInternal class nsPIDOMWindow : public nsIDOMWindowInternal
{ {
@ -457,23 +457,11 @@ public:
return mMayHaveTouchEventListener; return mMayHaveTouchEventListener;
} }
/**
* Call this to check whether some node (this window, its document,
* or content in that document) has a MozAudioAvailable event listener.
*/
bool HasAudioAvailableEventListeners()
{
return mMayHaveAudioAvailableEventListener;
}
/** /**
* Call this to indicate that some node (this window, its document, * Call this to indicate that some node (this window, its document,
* or content in that document) has a MozAudioAvailable event listener. * or content in that document) has a "MozAudioAvailable" event listener.
*/ */
void SetHasAudioAvailableEventListeners() virtual void SetHasAudioAvailableEventListeners() = 0;
{
mMayHaveAudioAvailableEventListener = true;
}
/** /**
* Call this to check whether some node (this window, its document, * Call this to check whether some node (this window, its document,
@ -657,7 +645,6 @@ protected:
bool mIsInnerWindow; bool mIsInnerWindow;
bool mMayHavePaintEventListener; bool mMayHavePaintEventListener;
bool mMayHaveTouchEventListener; bool mMayHaveTouchEventListener;
bool mMayHaveAudioAvailableEventListener;
bool mMayHaveMouseEnterLeaveEventListener; bool mMayHaveMouseEnterLeaveEventListener;
// This variable is used on both inner and outer windows (and they // This variable is used on both inner and outer windows (and they

View File

@ -408,7 +408,8 @@ AsyncConnectionHelper::Init()
already_AddRefed<nsDOMEvent> already_AddRefed<nsDOMEvent>
AsyncConnectionHelper::CreateSuccessEvent() AsyncConnectionHelper::CreateSuccessEvent()
{ {
return CreateGenericEvent(NS_LITERAL_STRING(SUCCESS_EVT_STR)); return CreateGenericEvent(NS_LITERAL_STRING(SUCCESS_EVT_STR),
eDoesNotBubble, eNotCancelable);
} }
nsresult nsresult
@ -453,7 +454,8 @@ AsyncConnectionHelper::OnError()
// Make an error event and fire it at the target. // Make an error event and fire it at the target.
nsRefPtr<nsDOMEvent> event = nsRefPtr<nsDOMEvent> event =
CreateGenericEvent(NS_LITERAL_STRING(ERROR_EVT_STR), true); CreateGenericEvent(NS_LITERAL_STRING(ERROR_EVT_STR), eDoesBubble,
eCancelable);
if (!event) { if (!event) {
NS_ERROR("Failed to create event!"); NS_ERROR("Failed to create event!");
return; return;

View File

@ -379,12 +379,14 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBDatabase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase,
nsDOMEventTargetHelper) nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnAbortListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnVersionChangeListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnVersionChangeListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase, NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase,
nsDOMEventTargetHelper) nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnAbortListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnVersionChangeListener) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnVersionChangeListener)
@ -725,6 +727,19 @@ IDBDatabase::Close()
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
IDBDatabase::SetOnabort(nsIDOMEventListener* aAbortListener)
{
return RemoveAddEventListener(NS_LITERAL_STRING(ABORT_EVT_STR),
mOnAbortListener, aAbortListener);
}
NS_IMETHODIMP
IDBDatabase::GetOnabort(nsIDOMEventListener** aAbortListener)
{
return GetInnerEventListener(mOnAbortListener, aAbortListener);
}
NS_IMETHODIMP NS_IMETHODIMP
IDBDatabase::SetOnerror(nsIDOMEventListener* aErrorListener) IDBDatabase::SetOnerror(nsIDOMEventListener* aErrorListener)
{ {
@ -764,7 +779,8 @@ IDBDatabase::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (type.EqualsLiteral(ERROR_EVT_STR)) { if (type.EqualsLiteral(ERROR_EVT_STR)) {
nsRefPtr<nsDOMEvent> duplicateEvent = CreateGenericEvent(type); nsRefPtr<nsDOMEvent> duplicateEvent =
CreateGenericEvent(type, eDoesNotBubble, eNotCancelable);
NS_ENSURE_STATE(duplicateEvent); NS_ENSURE_STATE(duplicateEvent);
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mOwner)); nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mOwner));

View File

@ -161,6 +161,7 @@ private:
bool mRunningVersionChange; bool mRunningVersionChange;
// Only touched on the main thread. // Only touched on the main thread.
nsRefPtr<nsDOMEventListenerWrapper> mOnAbortListener;
nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener; nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
nsRefPtr<nsDOMEventListenerWrapper> mOnVersionChangeListener; nsRefPtr<nsDOMEventListenerWrapper> mOnVersionChangeListener;
}; };

View File

@ -78,11 +78,13 @@ private:
already_AddRefed<nsDOMEvent> already_AddRefed<nsDOMEvent>
mozilla::dom::indexedDB::CreateGenericEvent(const nsAString& aType, mozilla::dom::indexedDB::CreateGenericEvent(const nsAString& aType,
bool aBubblesAndCancelable) Bubbles aBubbles,
Cancelable aCancelable)
{ {
nsRefPtr<nsDOMEvent> event(new nsDOMEvent(nsnull, nsnull)); nsRefPtr<nsDOMEvent> event(new nsDOMEvent(nsnull, nsnull));
nsresult rv = event->InitEvent(aType, aBubblesAndCancelable, nsresult rv = event->InitEvent(aType,
aBubblesAndCancelable); aBubbles == eDoesBubble ? true : false,
aCancelable == eCancelable ? true : false);
NS_ENSURE_SUCCESS(rv, nsnull); NS_ENSURE_SUCCESS(rv, nsnull);
rv = event->SetTrusted(true); rv = event->SetTrusted(true);
@ -91,17 +93,6 @@ mozilla::dom::indexedDB::CreateGenericEvent(const nsAString& aType,
return event.forget(); return event.forget();
} }
already_AddRefed<nsIRunnable>
mozilla::dom::indexedDB::CreateGenericEventRunnable(const nsAString& aType,
nsIDOMEventTarget* aTarget)
{
nsCOMPtr<nsIDOMEvent> event(CreateGenericEvent(aType));
NS_ENSURE_TRUE(event, nsnull);
nsCOMPtr<nsIRunnable> runnable(new EventFiringRunnable(aTarget, event));
return runnable.forget();
}
// static // static
already_AddRefed<nsDOMEvent> already_AddRefed<nsDOMEvent>
IDBVersionChangeEvent::CreateInternal(const nsAString& aType, IDBVersionChangeEvent::CreateInternal(const nsAString& aType,

View File

@ -59,13 +59,20 @@
BEGIN_INDEXEDDB_NAMESPACE BEGIN_INDEXEDDB_NAMESPACE
enum Bubbles {
eDoesNotBubble,
eDoesBubble
};
enum Cancelable {
eNotCancelable,
eCancelable
};
already_AddRefed<nsDOMEvent> already_AddRefed<nsDOMEvent>
CreateGenericEvent(const nsAString& aType, CreateGenericEvent(const nsAString& aType,
bool aBubblesAndCancelable = false); Bubbles aBubbles,
Cancelable aCancelable);
already_AddRefed<nsIRunnable>
CreateGenericEventRunnable(const nsAString& aType,
nsIDOMEventTarget* aTarget);
class IDBVersionChangeEvent : public nsDOMEvent, class IDBVersionChangeEvent : public nsDOMEvent,
public nsIIDBVersionChangeEvent public nsIIDBVersionChangeEvent

View File

@ -1160,12 +1160,12 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart); queryStart);
mRangeKey = mKeyRange->Upper(); mRangeKey = mKeyRange->Upper();
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( value = :") + mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
currentKey + NS_LITERAL_CSTRING(" AND ") + keyColumn + currentKey + NS_LITERAL_CSTRING(" AND ( value > :") +
currentKey + NS_LITERAL_CSTRING(" OR ") + keyColumn +
NS_LITERAL_CSTRING(" > :") + objectKey + NS_LITERAL_CSTRING(" > :") + objectKey +
NS_LITERAL_CSTRING(" ) OR ( value > :") + currentKey + NS_LITERAL_CSTRING(" )") + directionClause +
NS_LITERAL_CSTRING(" ) )") + directionClause + NS_LITERAL_CSTRING(" LIMIT ");
NS_LITERAL_CSTRING(" LIMIT 1");
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") + mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
currentKey + NS_LITERAL_CSTRING(" LIMIT "); currentKey + NS_LITERAL_CSTRING(" LIMIT ");
break; break;
@ -1178,7 +1178,7 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value > :") + mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value > :") +
currentKey + directionClause + currentKey + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1"); NS_LITERAL_CSTRING(" LIMIT ");
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") + mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
currentKey + directionClause + currentKey + directionClause +
NS_LITERAL_CSTRING(" LIMIT "); NS_LITERAL_CSTRING(" LIMIT ");
@ -1190,12 +1190,13 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart); queryStart);
mRangeKey = mKeyRange->Lower(); mRangeKey = mKeyRange->Lower();
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( value = :") +
currentKey + NS_LITERAL_CSTRING(" AND ") + keyColumn + mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
currentKey + NS_LITERAL_CSTRING(" AND ( value < :") +
currentKey + NS_LITERAL_CSTRING(" OR ") + keyColumn +
NS_LITERAL_CSTRING(" < :") + objectKey + NS_LITERAL_CSTRING(" < :") + objectKey +
NS_LITERAL_CSTRING(" ) OR ( value < :") + currentKey + NS_LITERAL_CSTRING(" ) ") + directionClause +
NS_LITERAL_CSTRING(" ) )") + directionClause + NS_LITERAL_CSTRING(" LIMIT ");
NS_LITERAL_CSTRING(" LIMIT 1");
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") + mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
currentKey + NS_LITERAL_CSTRING(" LIMIT "); currentKey + NS_LITERAL_CSTRING(" LIMIT ");
break; break;
@ -1208,7 +1209,7 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value < :") + mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value < :") +
currentKey + directionClause + currentKey + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1"); NS_LITERAL_CSTRING(" LIMIT ");
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") + mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
currentKey + directionClause + currentKey + directionClause +
NS_LITERAL_CSTRING(" LIMIT "); NS_LITERAL_CSTRING(" LIMIT ");
@ -1251,7 +1252,7 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
if (mIndex->IsAutoIncrement()) { if (mIndex->IsAutoIncrement()) {
objectTable.AssignLiteral("ai_object_data"); objectTable.AssignLiteral("ai_object_data");
objectDataIdColumn.AssignLiteral("ai_object_data_id"); objectDataIdColumn.AssignLiteral("ai_object_data_id");
keyValueColumn.AssignLiteral("id"); keyValueColumn.AssignLiteral("ai_object_data_id");
if (mIndex->IsUnique()) { if (mIndex->IsUnique()) {
indexTable.AssignLiteral("ai_unique_index_data"); indexTable.AssignLiteral("ai_unique_index_data");
} }
@ -1262,7 +1263,7 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
else { else {
objectTable.AssignLiteral("object_data"); objectTable.AssignLiteral("object_data");
objectDataIdColumn.AssignLiteral("object_data_id"); objectDataIdColumn.AssignLiteral("object_data_id");
keyValueColumn.AssignLiteral("key_value"); keyValueColumn.AssignLiteral("object_data_key");
if (mIndex->IsUnique()) { if (mIndex->IsUnique()) {
indexTable.AssignLiteral("unique_index_data"); indexTable.AssignLiteral("unique_index_data");
} }
@ -1271,11 +1272,8 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
} }
} }
NS_NAMED_LITERAL_CSTRING(id, "id");
nsCString value = indexTable + NS_LITERAL_CSTRING(".value"); nsCString value = indexTable + NS_LITERAL_CSTRING(".value");
nsCString data = objectTable + NS_LITERAL_CSTRING(".data"); nsCString keyValue = indexTable + NS_LITERAL_CSTRING(".") + keyValueColumn;
nsCString keyValue = objectTable + NS_LITERAL_CSTRING(".") + keyValueColumn;
nsCString keyRangeClause; nsCString keyRangeClause;
if (mKeyRange) { if (mKeyRange) {
@ -1304,16 +1302,21 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_NOTREACHED("Unknown direction!"); NS_NOTREACHED("Unknown direction!");
} }
nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + value + NS_NAMED_LITERAL_CSTRING(id, "id");
NS_LITERAL_CSTRING(", ") + keyValue + NS_NAMED_LITERAL_CSTRING(dot, ".");
NS_LITERAL_CSTRING(", ") + data + NS_NAMED_LITERAL_CSTRING(commaspace, ", ");
NS_LITERAL_CSTRING(" FROM ") + objectTable +
NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable + nsCString data = objectTable + NS_LITERAL_CSTRING(".data");
NS_LITERAL_CSTRING(" ON ") + indexTable +
NS_LITERAL_CSTRING(".") + objectDataIdColumn + nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + value + commaspace +
NS_LITERAL_CSTRING(" = ") + objectTable + keyValue + commaspace + data +
NS_LITERAL_CSTRING(".id WHERE ") + indexTable + NS_LITERAL_CSTRING(" FROM ") + indexTable +
NS_LITERAL_CSTRING(".index_id = :id") + NS_LITERAL_CSTRING(" INNER JOIN ") + objectTable +
NS_LITERAL_CSTRING(" ON ") + indexTable + dot +
objectDataIdColumn + NS_LITERAL_CSTRING(" = ") +
objectTable + dot + id +
NS_LITERAL_CSTRING(" WHERE ") + indexTable +
NS_LITERAL_CSTRING(".index_id = :") + id +
keyRangeClause + directionClause + keyRangeClause + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1"); NS_LITERAL_CSTRING(" LIMIT 1");
@ -1352,20 +1355,29 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
// Now we need to make the query to get the next match. // Now we need to make the query to get the next match.
nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT ") + value + nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT ") + value +
NS_LITERAL_CSTRING(", ") + keyValue + commaspace + keyValue + commaspace + data +
NS_LITERAL_CSTRING(", ") + data + NS_LITERAL_CSTRING(" FROM ") + indexTable +
NS_LITERAL_CSTRING(" FROM ") + objectTable + NS_LITERAL_CSTRING(" INNER JOIN ") + objectTable +
NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable + NS_LITERAL_CSTRING(" ON ") + indexTable + dot +
NS_LITERAL_CSTRING(" ON ") + indexTable + objectDataIdColumn + NS_LITERAL_CSTRING(" = ") +
NS_LITERAL_CSTRING(".") + objectDataIdColumn + objectTable + dot + id +
NS_LITERAL_CSTRING(" = ") + objectTable + NS_LITERAL_CSTRING(" WHERE ") + indexTable +
NS_LITERAL_CSTRING(".id WHERE ") + indexTable + NS_LITERAL_CSTRING(".index_id = :") + id;
NS_LITERAL_CSTRING(".index_id = :id");
NS_NAMED_LITERAL_CSTRING(currentKey, "current_key"); NS_NAMED_LITERAL_CSTRING(currentKey, "current_key");
NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key"); NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
NS_NAMED_LITERAL_CSTRING(objectKey, "object_key"); NS_NAMED_LITERAL_CSTRING(objectKey, "object_key");
NS_NAMED_LITERAL_CSTRING(andStr, " AND ");
NS_NAMED_LITERAL_CSTRING(orStr, " OR ");
NS_NAMED_LITERAL_CSTRING(ge, " >= :");
NS_NAMED_LITERAL_CSTRING(gt, " > :");
NS_NAMED_LITERAL_CSTRING(le, " <= :");
NS_NAMED_LITERAL_CSTRING(lt, " < :");
NS_NAMED_LITERAL_CSTRING(openparen, " ( ");
NS_NAMED_LITERAL_CSTRING(closeparen, " ) ");
NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
switch (mDirection) { switch (mDirection) {
case nsIIDBCursor::NEXT: case nsIIDBCursor::NEXT:
if (mKeyRange && !mKeyRange->Upper().IsUnset()) { if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
@ -1373,18 +1385,11 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart); queryStart);
mRangeKey = mKeyRange->Upper(); mRangeKey = mKeyRange->Upper();
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") + mContinueQuery = queryStart + andStr + value + ge + currentKey + andStr +
value + NS_LITERAL_CSTRING(" = :") + currentKey + openparen + value + gt + currentKey + orStr + keyValue +
NS_LITERAL_CSTRING(" AND ") + keyValue + gt + objectKey + closeparen + directionClause + limit;
NS_LITERAL_CSTRING(" > :") + objectKey + mContinueToQuery = queryStart + andStr + value + ge + currentKey +
NS_LITERAL_CSTRING(" ) OR ( ") + value + directionClause + limit;
NS_LITERAL_CSTRING(" > :") + currentKey +
NS_LITERAL_CSTRING(" ) )") + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1");
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
NS_LITERAL_CSTRING(" >= :") +
currentKey + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1");
break; break;
case nsIIDBCursor::NEXT_NO_DUPLICATE: case nsIIDBCursor::NEXT_NO_DUPLICATE:
@ -1393,12 +1398,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart); queryStart);
mRangeKey = mKeyRange->Upper(); mRangeKey = mKeyRange->Upper();
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + mContinueQuery = queryStart + andStr + value + gt + currentKey +
NS_LITERAL_CSTRING(" > :") + currentKey + directionClause + limit;
directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + andStr + value + ge + currentKey +
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + directionClause + limit;
NS_LITERAL_CSTRING(" >= :") + currentKey +
directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
break; break;
case nsIIDBCursor::PREV: case nsIIDBCursor::PREV:
@ -1407,18 +1410,11 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart); queryStart);
mRangeKey = mKeyRange->Lower(); mRangeKey = mKeyRange->Lower();
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") + mContinueQuery = queryStart + andStr + value + le + currentKey + andStr +
value + NS_LITERAL_CSTRING(" = :") + currentKey + openparen + value + lt + currentKey + orStr + keyValue +
NS_LITERAL_CSTRING(" AND ") + keyValue + lt + objectKey + closeparen + directionClause + limit;
NS_LITERAL_CSTRING(" < :") + objectKey + mContinueToQuery = queryStart + andStr + value + le + currentKey +
NS_LITERAL_CSTRING(" ) OR ( ") + value + directionClause + limit;
NS_LITERAL_CSTRING(" < :") + currentKey +
NS_LITERAL_CSTRING(" ) )") + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1");
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
NS_LITERAL_CSTRING(" <= :") +
currentKey + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1");
break; break;
case nsIIDBCursor::PREV_NO_DUPLICATE: case nsIIDBCursor::PREV_NO_DUPLICATE:
@ -1427,12 +1423,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart); queryStart);
mRangeKey = mKeyRange->Lower(); mRangeKey = mKeyRange->Lower();
} }
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + mContinueQuery = queryStart + andStr + value + lt + currentKey +
NS_LITERAL_CSTRING(" < :") + currentKey + directionClause +limit;
directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + andStr + value + le + currentKey +
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + directionClause + limit;
NS_LITERAL_CSTRING(" <= :") + currentKey +
directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
break; break;
default: default:

View File

@ -428,7 +428,9 @@ GetKeyFromValue(JSContext* aCx,
Key& aKey) Key& aKey)
{ {
NS_ASSERTION(aCx, "Null pointer!"); NS_ASSERTION(aCx, "Null pointer!");
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(aVal), "Why are we here!?"); // aVal can be primitive iff the key path is empty.
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(aVal) || aKeyPath.IsEmpty(),
"Why are we here!?");
NS_ASSERTION(IDBObjectStore::IsValidKeyPath(aCx, aKeyPath), NS_ASSERTION(IDBObjectStore::IsValidKeyPath(aCx, aKeyPath),
"This will explode!"); "This will explode!");
@ -580,7 +582,6 @@ IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
{ {
NS_ASSERTION(aData, "Null pointer!"); NS_ASSERTION(aData, "Null pointer!");
NS_ASSERTION(aDataLength, "Empty data!"); NS_ASSERTION(aDataLength, "Empty data!");
NS_ASSERTION(!aKeyPath.IsEmpty(), "Empty keyPath!");
NS_ASSERTION(aCx, "Null pointer!"); NS_ASSERTION(aCx, "Null pointer!");
JSAutoRequest ar(aCx); JSAutoRequest ar(aCx);
@ -592,7 +593,7 @@ IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
return NS_ERROR_DOM_DATA_CLONE_ERR; return NS_ERROR_DOM_DATA_CLONE_ERR;
} }
if (JSVAL_IS_PRIMITIVE(clone)) { if (JSVAL_IS_PRIMITIVE(clone) && !aKeyPath.IsEmpty()) {
// This isn't an object, so just leave the key unset. // This isn't an object, so just leave the key unset.
aValue.Unset(); aValue.Unset();
return NS_OK; return NS_OK;
@ -614,7 +615,7 @@ IDBObjectStore::GetIndexUpdateInfo(ObjectStoreInfo* aObjectStoreInfo,
JSObject* cloneObj = nsnull; JSObject* cloneObj = nsnull;
PRUint32 count = aObjectStoreInfo->indexes.Length(); PRUint32 count = aObjectStoreInfo->indexes.Length();
if (count && !JSVAL_IS_PRIMITIVE(aObject)) { if (count) {
if (!aUpdateInfoArray.SetCapacity(count)) { if (!aUpdateInfoArray.SetCapacity(count)) {
NS_ERROR("Out of memory!"); NS_ERROR("Out of memory!");
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -623,6 +624,10 @@ IDBObjectStore::GetIndexUpdateInfo(ObjectStoreInfo* aObjectStoreInfo,
for (PRUint32 indexesIndex = 0; indexesIndex < count; indexesIndex++) { for (PRUint32 indexesIndex = 0; indexesIndex < count; indexesIndex++) {
const IndexInfo& indexInfo = aObjectStoreInfo->indexes[indexesIndex]; const IndexInfo& indexInfo = aObjectStoreInfo->indexes[indexesIndex];
if (JSVAL_IS_PRIMITIVE(aObject) && !indexInfo.keyPath.IsEmpty()) {
continue;
}
Key value; Key value;
nsresult rv = GetKeyFromValue(aCx, aObject, indexInfo.keyPath, value); nsresult rv = GetKeyFromValue(aCx, aObject, indexInfo.keyPath, value);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -664,7 +669,6 @@ IDBObjectStore::UpdateIndexes(IDBTransaction* aTransaction,
#endif #endif
PRUint32 indexCount = aUpdateInfoArray.Length(); PRUint32 indexCount = aUpdateInfoArray.Length();
NS_ASSERTION(indexCount, "Don't call me!");
nsCOMPtr<mozIStorageStatement> stmt; nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv; nsresult rv;
@ -702,34 +706,59 @@ IDBObjectStore::UpdateIndexes(IDBTransaction* aTransaction,
NS_ASSERTION(aObjectDataId != LL_MININT, "Bad objectData id!"); NS_ASSERTION(aObjectDataId != LL_MININT, "Bad objectData id!");
for (PRUint32 indexIndex = 0; indexIndex < indexCount; indexIndex++) { NS_NAMED_LITERAL_CSTRING(indexId, "index_id");
const IndexUpdateInfo& updateInfo = aUpdateInfoArray[indexIndex]; NS_NAMED_LITERAL_CSTRING(objectDataId, "object_data_id");
NS_NAMED_LITERAL_CSTRING(objectDataKey, "object_data_key");
NS_NAMED_LITERAL_CSTRING(value, "value");
stmt = aTransaction->IndexUpdateStatement(updateInfo.info.autoIncrement, if (aOverwrite) {
updateInfo.info.unique, stmt = aTransaction->IndexDataDeleteStatement(aAutoIncrement, false);
aOverwrite);
NS_ENSURE_TRUE(stmt, NS_ERROR_FAILURE); NS_ENSURE_TRUE(stmt, NS_ERROR_FAILURE);
mozStorageStatementScoper scoper2(stmt); mozStorageStatementScoper scoper2(stmt);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"), rv = stmt->BindInt64ByName(objectDataId, aObjectDataId);
updateInfo.info.id);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("object_data_id"), rv = stmt->Execute();
aObjectDataId); NS_ENSURE_SUCCESS(rv, rv);
stmt = aTransaction->IndexDataDeleteStatement(aAutoIncrement, true);
NS_ENSURE_TRUE(stmt, NS_ERROR_FAILURE);
mozStorageStatementScoper scoper3(stmt);
rv = stmt->BindInt64ByName(objectDataId, aObjectDataId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
}
for (PRUint32 indexIndex = 0; indexIndex < indexCount; indexIndex++) {
const IndexUpdateInfo& updateInfo = aUpdateInfoArray[indexIndex];
NS_ASSERTION(updateInfo.info.autoIncrement == aAutoIncrement, "Huh?!");
// Insert new values.
stmt = aTransaction->IndexDataInsertStatement(aAutoIncrement,
updateInfo.info.unique);
NS_ENSURE_TRUE(stmt, NS_ERROR_FAILURE);
mozStorageStatementScoper scoper4(stmt);
rv = stmt->BindInt64ByName(indexId, updateInfo.info.id);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64ByName(objectDataId, aObjectDataId);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (!updateInfo.info.autoIncrement) { if (!updateInfo.info.autoIncrement) {
rv = rv = aObjectStoreKey.BindToStatement(stmt, objectDataKey);
aObjectStoreKey.BindToStatement(stmt,
NS_LITERAL_CSTRING("object_data_key"));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
rv = rv = updateInfo.value.BindToStatement(stmt, value);
updateInfo.value.BindToStatementAllowUnset(stmt,
NS_LITERAL_CSTRING("value"));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute(); rv = stmt->Execute();
@ -1310,10 +1339,6 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
{ {
NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
if (aKeyPath.IsEmpty()) {
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
}
if (!IsValidKeyPath(aCx, aKeyPath)) { if (!IsValidKeyPath(aCx, aKeyPath)) {
return NS_ERROR_DOM_SYNTAX_ERR; return NS_ERROR_DOM_SYNTAX_ERR;
} }
@ -1718,7 +1743,7 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
} }
// Update our indexes if needed. // Update our indexes if needed.
if (!mIndexUpdateInfo.IsEmpty()) { if (mOverwrite || !mIndexUpdateInfo.IsEmpty()) {
PRInt64 objectDataId = autoIncrement ? mKey.ToInteger() : LL_MININT; PRInt64 objectDataId = autoIncrement ? mKey.ToInteger() : LL_MININT;
rv = IDBObjectStore::UpdateIndexes(mTransaction, osid, mKey, rv = IDBObjectStore::UpdateIndexes(mTransaction, osid, mKey,
autoIncrement, mOverwrite, autoIncrement, mOverwrite,
@ -1930,7 +1955,8 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn + nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn +
NS_LITERAL_CSTRING(", data FROM ") + table + NS_LITERAL_CSTRING(", data FROM ") + table +
NS_LITERAL_CSTRING(" WHERE object_store_id = :") + NS_LITERAL_CSTRING(" WHERE object_store_id = :") +
id + keyRangeClause + directionClause; id + keyRangeClause + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1");
nsCOMPtr<mozIStorageStatement> stmt = nsCOMPtr<mozIStorageStatement> stmt =
mTransaction->GetCachedStatement(firstQuery); mTransaction->GetCachedStatement(firstQuery);
@ -2009,7 +2035,7 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_LITERAL_CSTRING(", data FROM ") + table + NS_LITERAL_CSTRING(", data FROM ") + table +
NS_LITERAL_CSTRING(" WHERE object_store_id = :") + id + NS_LITERAL_CSTRING(" WHERE object_store_id = :") + id +
keyRangeClause + directionClause + keyRangeClause + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1"); NS_LITERAL_CSTRING(" LIMIT ");
mContinueToQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn + mContinueToQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn +
NS_LITERAL_CSTRING(", data FROM ") + table + NS_LITERAL_CSTRING(", data FROM ") + table +
@ -2215,8 +2241,8 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
bool hasResult; bool hasResult;
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) { while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
nsCOMPtr<mozIStorageStatement> insertStmt = nsCOMPtr<mozIStorageStatement> insertStmt =
mTransaction->IndexUpdateStatement(mIndex->IsAutoIncrement(), mTransaction->IndexDataInsertStatement(mIndex->IsAutoIncrement(),
mIndex->IsUnique(), false); mIndex->IsUnique());
NS_ENSURE_TRUE(insertStmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ENSURE_TRUE(insertStmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
mozStorageStatementScoper scoper2(insertStmt); mozStorageStatementScoper scoper2(insertStmt);

View File

@ -394,28 +394,13 @@ IDBTransaction::AddStatement(bool aCreate,
} }
already_AddRefed<mozIStorageStatement> already_AddRefed<mozIStorageStatement>
IDBTransaction::IndexUpdateStatement(bool aAutoIncrement, IDBTransaction::IndexDataInsertStatement(bool aAutoIncrement,
bool aUnique, bool aUnique)
bool aOverwrite)
{ {
if (aAutoIncrement) { if (aAutoIncrement) {
if (aUnique) { if (aUnique) {
if (aOverwrite) {
return GetCachedStatement(
"INSERT OR REPLACE INTO ai_unique_index_data "
"(index_id, ai_object_data_id, value) "
"VALUES (:index_id, :object_data_id, :value)"
);
}
return GetCachedStatement( return GetCachedStatement(
"INSERT INTO ai_unique_index_data " "INSERT INTO ai_unique_index_data "
"(index_id, aI_object_data_id, value) "
"VALUES (:index_id, :object_data_id, :value)"
);
}
if (aOverwrite) {
return GetCachedStatement(
"INSERT OR REPLACE INTO ai_index_data "
"(index_id, ai_object_data_id, value) " "(index_id, ai_object_data_id, value) "
"VALUES (:index_id, :object_data_id, :value)" "VALUES (:index_id, :object_data_id, :value)"
); );
@ -427,26 +412,12 @@ IDBTransaction::IndexUpdateStatement(bool aAutoIncrement,
); );
} }
if (aUnique) { if (aUnique) {
if (aOverwrite) {
return GetCachedStatement(
"INSERT OR REPLACE INTO unique_index_data "
"(index_id, object_data_id, object_data_key, value) "
"VALUES (:index_id, :object_data_id, :object_data_key, :value)"
);
}
return GetCachedStatement( return GetCachedStatement(
"INSERT INTO unique_index_data " "INSERT INTO unique_index_data "
"(index_id, object_data_id, object_data_key, value) " "(index_id, object_data_id, object_data_key, value) "
"VALUES (:index_id, :object_data_id, :object_data_key, :value)" "VALUES (:index_id, :object_data_id, :object_data_key, :value)"
); );
} }
if (aOverwrite) {
return GetCachedStatement(
"INSERT INTO index_data ("
"index_id, object_data_id, object_data_key, value) "
"VALUES (:index_id, :object_data_id, :object_data_key, :value)"
);
}
return GetCachedStatement( return GetCachedStatement(
"INSERT INTO index_data (" "INSERT INTO index_data ("
"index_id, object_data_id, object_data_key, value) " "index_id, object_data_id, object_data_key, value) "
@ -454,6 +425,34 @@ IDBTransaction::IndexUpdateStatement(bool aAutoIncrement,
); );
} }
already_AddRefed<mozIStorageStatement>
IDBTransaction::IndexDataDeleteStatement(bool aAutoIncrement,
bool aUnique)
{
if (aAutoIncrement) {
if (aUnique) {
return GetCachedStatement(
"DELETE FROM ai_unique_index_data "
"WHERE ai_object_data_id = :object_data_id"
);
}
return GetCachedStatement(
"DELETE FROM ai_index_data "
"WHERE ai_object_data_id = :object_data_id"
);
}
if (aUnique) {
return GetCachedStatement(
"DELETE FROM unique_index_data "
"WHERE object_data_id = :object_data_id"
);
}
return GetCachedStatement(
"DELETE FROM index_data "
"WHERE object_data_id = :object_data_id"
);
}
already_AddRefed<mozIStorageStatement> already_AddRefed<mozIStorageStatement>
IDBTransaction::GetCachedStatement(const nsACString& aQuery) IDBTransaction::GetCachedStatement(const nsACString& aQuery)
{ {
@ -854,10 +853,12 @@ CommitHelper::Run()
} }
} }
event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR)); event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR),
eDoesBubble, eNotCancelable);
} }
else { else {
event = CreateGenericEvent(NS_LITERAL_STRING(COMPLETE_EVT_STR)); event = CreateGenericEvent(NS_LITERAL_STRING(COMPLETE_EVT_STR),
eDoesNotBubble, eNotCancelable);
} }
NS_ENSURE_TRUE(event, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ENSURE_TRUE(event, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

View File

@ -118,9 +118,12 @@ public:
bool aAutoIncrement); bool aAutoIncrement);
already_AddRefed<mozIStorageStatement> already_AddRefed<mozIStorageStatement>
IndexUpdateStatement(bool aAutoIncrement, IndexDataInsertStatement(bool aAutoIncrement,
bool aUnique, bool aUnique);
bool aOverwrite);
already_AddRefed<mozIStorageStatement>
IndexDataDeleteStatement(bool aAutoIncrement,
bool aUnique);
already_AddRefed<mozIStorageStatement> already_AddRefed<mozIStorageStatement>
GetCachedStatement(const nsACString& aQuery); GetCachedStatement(const nsACString& aQuery);

View File

@ -51,7 +51,7 @@
#include "nsStringGlue.h" #include "nsStringGlue.h"
#include "nsTArray.h" #include "nsTArray.h"
#define DB_SCHEMA_VERSION 5 #define DB_SCHEMA_VERSION 6
#define BEGIN_INDEXEDDB_NAMESPACE \ #define BEGIN_INDEXEDDB_NAMESPACE \
namespace mozilla { namespace dom { namespace indexedDB { namespace mozilla { namespace dom { namespace indexedDB {

View File

@ -248,19 +248,6 @@ public:
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
nsresult BindToStatementAllowUnset(mozIStorageStatement* aStatement,
const nsACString& aParamName) const
{
nsresult rv;
if (IsUnset()) {
rv = aStatement->BindStringByName(aParamName, EmptyString());
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
return BindToStatement(aStatement, aParamName);
}
nsresult SetFromStatement(mozIStorageStatement* aStatement, nsresult SetFromStatement(mozIStorageStatement* aStatement,
PRUint32 aIndex) PRUint32 aIndex)
{ {

View File

@ -121,11 +121,10 @@ CreateTables(mozIStorageConnection* aDBConn)
// Table `object_store` // Table `object_store`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE object_store (" "CREATE TABLE object_store ("
"id INTEGER, " "id INTEGER PRIMARY KEY, "
"name TEXT NOT NULL, " "name TEXT NOT NULL, "
"key_path TEXT NOT NULL, " "key_path TEXT NOT NULL, "
"auto_increment INTEGER NOT NULL DEFAULT 0, " "auto_increment INTEGER NOT NULL DEFAULT 0, "
"PRIMARY KEY (id), "
"UNIQUE (name)" "UNIQUE (name)"
");" ");"
)); ));
@ -134,41 +133,30 @@ CreateTables(mozIStorageConnection* aDBConn)
// Table `object_data` // Table `object_data`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE object_data (" "CREATE TABLE object_data ("
"id INTEGER, " "id INTEGER PRIMARY KEY, "
"object_store_id INTEGER NOT NULL, " "object_store_id INTEGER NOT NULL, "
"key_value DEFAULT NULL, "
"data BLOB NOT NULL, " "data BLOB NOT NULL, "
"key_value DEFAULT NULL, " // NONE affinity "UNIQUE (object_store_id, key_value), "
"PRIMARY KEY (id), "
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE " "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
"CASCADE" "CASCADE"
");" ");"
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE UNIQUE INDEX key_index "
"ON object_data (key_value, object_store_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
// Table `ai_object_data` // Table `ai_object_data`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE ai_object_data (" "CREATE TABLE ai_object_data ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, " "id INTEGER PRIMARY KEY AUTOINCREMENT, "
"object_store_id INTEGER NOT NULL, " "object_store_id INTEGER NOT NULL, "
"data BLOB NOT NULL, " "data BLOB NOT NULL, "
"UNIQUE (object_store_id, id), "
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE " "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
"CASCADE" "CASCADE"
");" ");"
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE UNIQUE INDEX ai_key_index "
"ON ai_object_data (id, object_store_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
// Table `index` // Table `index`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE object_store_index (" "CREATE TABLE object_store_index ("
@ -189,12 +177,11 @@ CreateTables(mozIStorageConnection* aDBConn)
// Table `index_data` // Table `index_data`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE index_data (" "CREATE TABLE index_data ("
"id INTEGER, "
"index_id INTEGER NOT NULL, " "index_id INTEGER NOT NULL, "
"object_data_id INTEGER NOT NULL, "
"object_data_key NOT NULL, " // NONE affinity
"value NOT NULL, " "value NOT NULL, "
"PRIMARY KEY (id), " "object_data_key NOT NULL, "
"object_data_id INTEGER NOT NULL, "
"PRIMARY KEY (index_id, value, object_data_key), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE " "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE, " "CASCADE, "
"FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE " "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
@ -203,21 +190,21 @@ CreateTables(mozIStorageConnection* aDBConn)
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Need this to make cascading deletes from object_data and object_store fast.
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX value_index " "CREATE INDEX index_data_object_data_id_index "
"ON index_data (index_id, value);" "ON index_data (object_data_id);"
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Table `unique_index_data` // Table `unique_index_data`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE unique_index_data (" "CREATE TABLE unique_index_data ("
"id INTEGER, "
"index_id INTEGER NOT NULL, " "index_id INTEGER NOT NULL, "
"object_data_id INTEGER NOT NULL, "
"object_data_key NOT NULL, " // NONE affinity
"value NOT NULL, " "value NOT NULL, "
"PRIMARY KEY (id), " "object_data_key NOT NULL, " // NONE affinity
"object_data_id INTEGER NOT NULL, "
"PRIMARY KEY (index_id, value, object_data_key), "
"UNIQUE (index_id, value), " "UNIQUE (index_id, value), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE " "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE " "CASCADE "
@ -227,14 +214,20 @@ CreateTables(mozIStorageConnection* aDBConn)
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Need this to make cascading deletes from object_data and object_store fast.
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX unique_index_data_object_data_id_index "
"ON unique_index_data (object_data_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
// Table `ai_index_data` // Table `ai_index_data`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE ai_index_data (" "CREATE TABLE ai_index_data ("
"id INTEGER, "
"index_id INTEGER NOT NULL, " "index_id INTEGER NOT NULL, "
"ai_object_data_id INTEGER NOT NULL, "
"value NOT NULL, " "value NOT NULL, "
"PRIMARY KEY (id), " "ai_object_data_id INTEGER NOT NULL, "
"PRIMARY KEY (index_id, value, ai_object_data_id), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE " "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE, " "CASCADE, "
"FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE " "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
@ -243,21 +236,22 @@ CreateTables(mozIStorageConnection* aDBConn)
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Need this to make cascading deletes from ai_object_data and object_store
// fast.
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX ai_value_index " "CREATE INDEX ai_index_data_ai_object_data_id_index "
"ON ai_index_data (index_id, value);" "ON ai_index_data (ai_object_data_id);"
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Table `ai_unique_index_data` // Table `ai_unique_index_data`
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE ai_unique_index_data (" "CREATE TABLE ai_unique_index_data ("
"id INTEGER, "
"index_id INTEGER NOT NULL, " "index_id INTEGER NOT NULL, "
"ai_object_data_id INTEGER NOT NULL, "
"value NOT NULL, " "value NOT NULL, "
"PRIMARY KEY (id), " "ai_object_data_id INTEGER NOT NULL, "
"UNIQUE (index_id, value), " "UNIQUE (index_id, value), "
"PRIMARY KEY (index_id, value, ai_object_data_id), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE " "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE, " "CASCADE, "
"FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE " "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
@ -266,6 +260,14 @@ CreateTables(mozIStorageConnection* aDBConn)
)); ));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Need this to make cascading deletes from ai_object_data and object_store
// fast.
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX ai_unique_index_data_ai_object_data_id_index "
"ON ai_unique_index_data (ai_object_data_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aDBConn->SetSchemaVersion(DB_SCHEMA_VERSION); rv = aDBConn->SetSchemaVersion(DB_SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -377,7 +379,372 @@ UpgradeSchemaFrom4To5(mozIStorageConnection* aConnection)
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
rv = aConnection->SetSchemaVersion(DB_SCHEMA_VERSION); rv = aConnection->SetSchemaVersion(5);
NS_ENSURE_SUCCESS(rv, rv);
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
UpgradeSchemaFrom5To6(mozIStorageConnection* aConnection)
{
mozStorageTransaction transaction(aConnection, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
// Turn off foreign key constraints before we do anything here.
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"PRAGMA foreign_keys = OFF;"
));
NS_ENSURE_SUCCESS(rv, rv);
// First, drop all the indexes we're no longer going to use.
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP INDEX key_index;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP INDEX ai_key_index;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP INDEX value_index;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP INDEX ai_value_index;"
));
NS_ENSURE_SUCCESS(rv, rv);
// Now, reorder the columns of object_data to put the blob data last. We do
// this by copying into a temporary table, dropping the original, then copying
// back into a newly created table.
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"id INTEGER PRIMARY KEY, "
"object_store_id, "
"key_value, "
"data "
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO temp_upgrade "
"SELECT id, object_store_id, key_value, data "
"FROM object_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE object_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE object_data ("
"id INTEGER PRIMARY KEY, "
"object_store_id INTEGER NOT NULL, "
"key_value DEFAULT NULL, "
"data BLOB NOT NULL, "
"UNIQUE (object_store_id, key_value), "
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
"CASCADE"
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO object_data "
"SELECT id, object_store_id, key_value, data "
"FROM temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
// We need to add a unique constraint to our ai_object_data table. Copy all
// the data out of it using a temporary table as before.
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"id INTEGER PRIMARY KEY, "
"object_store_id, "
"data "
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO temp_upgrade "
"SELECT id, object_store_id, data "
"FROM ai_object_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE ai_object_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE ai_object_data ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"object_store_id INTEGER NOT NULL, "
"data BLOB NOT NULL, "
"UNIQUE (object_store_id, id), "
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
"CASCADE"
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO ai_object_data "
"SELECT id, object_store_id, data "
"FROM temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
// Fix up the index_data table. We're reordering the columns as well as
// changing the primary key from being a simple id to being a composite.
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"index_id, "
"value, "
"object_data_key, "
"object_data_id "
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO temp_upgrade "
"SELECT index_id, value, object_data_key, object_data_id "
"FROM index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE index_data ("
"index_id INTEGER NOT NULL, "
"value NOT NULL, "
"object_data_key NOT NULL, "
"object_data_id INTEGER NOT NULL, "
"PRIMARY KEY (index_id, value, object_data_key), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE, "
"FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
"CASCADE"
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT OR IGNORE INTO index_data "
"SELECT index_id, value, object_data_key, object_data_id "
"FROM temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX index_data_object_data_id_index "
"ON index_data (object_data_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
// Fix up the unique_index_data table. We're reordering the columns as well as
// changing the primary key from being a simple id to being a composite.
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"index_id, "
"value, "
"object_data_key, "
"object_data_id "
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO temp_upgrade "
"SELECT index_id, value, object_data_key, object_data_id "
"FROM unique_index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE unique_index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE unique_index_data ("
"index_id INTEGER NOT NULL, "
"value NOT NULL, "
"object_data_key NOT NULL, "
"object_data_id INTEGER NOT NULL, "
"PRIMARY KEY (index_id, value, object_data_key), "
"UNIQUE (index_id, value), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE "
"FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
"CASCADE"
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO unique_index_data "
"SELECT index_id, value, object_data_key, object_data_id "
"FROM temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX unique_index_data_object_data_id_index "
"ON unique_index_data (object_data_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
// Fix up the ai_index_data table. We're reordering the columns as well as
// changing the primary key from being a simple id to being a composite.
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"index_id, "
"value, "
"ai_object_data_id "
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO temp_upgrade "
"SELECT index_id, value, ai_object_data_id "
"FROM ai_index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE ai_index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE ai_index_data ("
"index_id INTEGER NOT NULL, "
"value NOT NULL, "
"ai_object_data_id INTEGER NOT NULL, "
"PRIMARY KEY (index_id, value, ai_object_data_id), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE, "
"FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
"CASCADE"
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT OR IGNORE INTO ai_index_data "
"SELECT index_id, value, ai_object_data_id "
"FROM temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX ai_index_data_ai_object_data_id_index "
"ON ai_index_data (ai_object_data_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
// Fix up the ai_unique_index_data table. We're reordering the columns as well
// as changing the primary key from being a simple id to being a composite.
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"index_id, "
"value, "
"ai_object_data_id "
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO temp_upgrade "
"SELECT index_id, value, ai_object_data_id "
"FROM ai_unique_index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE ai_unique_index_data;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE ai_unique_index_data ("
"index_id INTEGER NOT NULL, "
"value NOT NULL, "
"ai_object_data_id INTEGER NOT NULL, "
"UNIQUE (index_id, value), "
"PRIMARY KEY (index_id, value, ai_object_data_id), "
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
"CASCADE, "
"FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
"CASCADE"
");"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO ai_unique_index_data "
"SELECT index_id, value, ai_object_data_id "
"FROM temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE temp_upgrade;"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX ai_unique_index_data_ai_object_data_id_index "
"ON ai_unique_index_data (ai_object_data_id);"
));
NS_ENSURE_SUCCESS(rv, rv);
rv = aConnection->SetSchemaVersion(6);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = transaction.Commit(); rv = transaction.Commit();
@ -393,14 +760,6 @@ CreateDatabaseConnection(const nsAString& aName,
{ {
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIFile> dbDirectory;
nsresult rv = aDBFile->GetParent(getter_AddRefs(dbDirectory));
NS_ENSURE_SUCCESS(rv, rv);
bool exists;
rv = aDBFile->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_CSTRING(quotaVFSName, "quota"); NS_NAMED_LITERAL_CSTRING(quotaVFSName, "quota");
nsCOMPtr<mozIStorageServiceQuotaManagement> ss = nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
@ -408,15 +767,13 @@ CreateDatabaseConnection(const nsAString& aName,
NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE); NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
nsCOMPtr<mozIStorageConnection> connection; nsCOMPtr<mozIStorageConnection> connection;
rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName, nsresult rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
getter_AddRefs(connection)); getter_AddRefs(connection));
if (rv == NS_ERROR_FILE_CORRUPTED) { if (rv == NS_ERROR_FILE_CORRUPTED) {
// Nuke the database file. The web services can recreate their data. // Nuke the database file. The web services can recreate their data.
rv = aDBFile->Remove(false); rv = aDBFile->Remove(false);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
exists = false;
rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName, rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
getter_AddRefs(connection)); getter_AddRefs(connection));
} }
@ -427,42 +784,49 @@ CreateDatabaseConnection(const nsAString& aName,
rv = connection->GetSchemaVersion(&schemaVersion); rv = connection->GetSchemaVersion(&schemaVersion);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (schemaVersion != DB_SCHEMA_VERSION) { if (!schemaVersion) {
// Brand new file, initialize our tables.
mozStorageTransaction transaction(connection, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
rv = CreateTables(connection);
NS_ENSURE_SUCCESS(rv, rv);
rv = CreateMetaData(connection, aName);
NS_ENSURE_SUCCESS(rv, rv);
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(NS_SUCCEEDED(connection->GetSchemaVersion(&schemaVersion)) &&
schemaVersion == DB_SCHEMA_VERSION,
"CreateTables set a bad schema version!");
}
else if (schemaVersion != DB_SCHEMA_VERSION) {
// This logic needs to change next time we change the schema! // This logic needs to change next time we change the schema!
PR_STATIC_ASSERT(DB_SCHEMA_VERSION == 5); PR_STATIC_ASSERT(DB_SCHEMA_VERSION == 6);
if (schemaVersion == 4) {
rv = UpgradeSchemaFrom4To5(connection);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
// Nuke it from orbit, it's the only way to be sure.
if (exists) {
// If the connection is not at the right schema version, nuke it.
rv = aDBFile->Remove(false);
NS_ENSURE_SUCCESS(rv, rv);
rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName, #define UPGRADE_SCHEMA_CASE(_from, _to) \
getter_AddRefs(connection)); if (schemaVersion == _from) { \
NS_ENSURE_SUCCESS(rv, rv); rv = UpgradeSchemaFrom##_from##To##_to (connection); \
} NS_ENSURE_SUCCESS(rv, rv); \
\
mozStorageTransaction transaction(connection, false, rv = connection->GetSchemaVersion(&schemaVersion); \
mozIStorageConnection::TRANSACTION_IMMEDIATE); NS_ENSURE_SUCCESS(rv, rv); \
rv = CreateTables(connection); \
NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(schemaVersion == _to, "Bad upgrade function!"); \
rv = CreateMetaData(connection, aName);
NS_ENSURE_SUCCESS(rv, rv);
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
}
} }
// Check to make sure that the database schema is correct again. UPGRADE_SCHEMA_CASE(4, 5)
NS_ASSERTION(NS_SUCCEEDED(connection->GetSchemaVersion(&schemaVersion)) && UPGRADE_SCHEMA_CASE(5, 6)
schemaVersion == DB_SCHEMA_VERSION,
"CreateTables failed!"); #undef UPGRADE_SCHEMA_CASE
if (schemaVersion != DB_SCHEMA_VERSION) {
NS_WARNING("Unable to open IndexedDB database, schema doesn't match");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
// Turn on foreign key constraints. // Turn on foreign key constraints.
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
@ -1143,7 +1507,8 @@ void
OpenDatabaseHelper::DispatchSuccessEvent() OpenDatabaseHelper::DispatchSuccessEvent()
{ {
nsRefPtr<nsDOMEvent> event = nsRefPtr<nsDOMEvent> event =
CreateGenericEvent(NS_LITERAL_STRING(SUCCESS_EVT_STR)); CreateGenericEvent(NS_LITERAL_STRING(SUCCESS_EVT_STR),
eDoesNotBubble, eNotCancelable);
if (!event) { if (!event) {
NS_ERROR("Failed to create event!"); NS_ERROR("Failed to create event!");
return; return;
@ -1157,7 +1522,8 @@ void
OpenDatabaseHelper::DispatchErrorEvent() OpenDatabaseHelper::DispatchErrorEvent()
{ {
nsRefPtr<nsDOMEvent> event = nsRefPtr<nsDOMEvent> event =
CreateGenericEvent(NS_LITERAL_STRING(ERROR_EVT_STR)); CreateGenericEvent(NS_LITERAL_STRING(ERROR_EVT_STR),
eDoesBubble, eCancelable);
if (!event) { if (!event) {
NS_ERROR("Failed to create event!"); NS_ERROR("Failed to create event!");
return; return;

View File

@ -50,7 +50,7 @@ interface nsIDOMEventListener;
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase
* for more information. * for more information.
*/ */
[scriptable, builtinclass, uuid(7ad626df-3328-476f-ba10-8ccec4924340)] [scriptable, builtinclass, uuid(bb877dff-ab5b-4ebb-9b3c-a7fa97cd4b51)]
interface nsIIDBDatabase : nsISupports interface nsIIDBDatabase : nsISupports
{ {
readonly attribute DOMString name; readonly attribute DOMString name;
@ -83,6 +83,8 @@ interface nsIIDBDatabase : nsISupports
void void
close(); close();
attribute nsIDOMEventListener onabort;
attribute nsIDOMEventListener onerror; attribute nsIDOMEventListener onerror;
attribute nsIDOMEventListener onversionchange; attribute nsIDOMEventListener onversionchange;

View File

@ -75,9 +75,11 @@ TEST_FILES = \
test_exceptions_in_success_events.html \ test_exceptions_in_success_events.html \
test_getAll.html \ test_getAll.html \
test_global_data.html \ test_global_data.html \
test_index_empty_keyPath.html \
test_index_getAll.html \ test_index_getAll.html \
test_index_getAllObjects.html \ test_index_getAllObjects.html \
test_index_object_cursors.html \ test_index_object_cursors.html \
test_index_update_delete.html \
test_indexes.html \ test_indexes.html \
test_indexes_bad_values.html \ test_indexes_bad_values.html \
test_key_requirements.html \ test_key_requirements.html \
@ -108,6 +110,7 @@ TEST_FILES = \
test_setVersion_abort.html \ test_setVersion_abort.html \
test_setVersion_events.html \ test_setVersion_events.html \
test_setVersion_exclusion.html \ test_setVersion_exclusion.html \
test_unique_index_update.html \
test_writer_starvation.html \ test_writer_starvation.html \
third_party_iframe1.html \ third_party_iframe1.html \
third_party_iframe2.html \ third_party_iframe2.html \

View File

@ -0,0 +1,95 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const objectStoreData = [
{ key: "1", value: "foo" },
{ key: "2", value: "bar" },
{ key: "3", value: "baz" }
];
let request = mozIndexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield; // upgradeneeded
let db = event.target.result;
let objectStore = db.createObjectStore("data", { keyPath: null });
// First, add all our data to the object store.
let addedData = 0;
for (let i in objectStoreData) {
request = objectStore.add(objectStoreData[i].value,
objectStoreData[i].key);
request.onerror = errorHandler;
request.onsuccess = function(event) {
if (++addedData == objectStoreData.length) {
testGenerator.send(event);
}
}
}
event = yield; // testGenerator.send
// Now create the index.
objectStore.createIndex("set", "", { unique: true });
yield; // success
let trans = db.transaction("data", IDBTransaction.READ_WRITE);
objectStore = trans.objectStore("data");
index = objectStore.index("set");
let request = index.get("bar");
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.target.result, "bar", "Got correct result");
let request = objectStore.add("foopy", 4);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
yield;
let request = index.get("foopy");
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.target.result, "foopy", "Got correct result");
let request = objectStore.add("foopy", 5);
request.onerror = new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
request.onsuccess = unexpectedSuccessHandler;
trans.oncomplete = grabEventAndContinueHandler;
yield;
yield;
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,180 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
let request = mozIndexedDB.open(window.location.pathname, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
db.onerror = errorHandler;
for each (let autoIncrement in [false, true]) {
let objectStore =
db.createObjectStore(autoIncrement, { keyPath: "id",
autoIncrement: autoIncrement });
for (let i = 0; i < 10; i++) {
objectStore.add({ id: i, index: i });
}
for each (let unique in [false, true]) {
objectStore.createIndex(unique, "index", { unique: unique });
}
for (let i = 10; i < 20; i++) {
objectStore.add({ id: i, index: i });
}
}
event = yield;
is(event.type, "success", "expect a success event");
for each (let autoIncrement in [false, true]) {
let objectStore = db.transaction(autoIncrement)
.objectStore(autoIncrement);
objectStore.count().onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.target.result, 20, "Correct number of entries in objectStore");
let objectStoreCount = event.target.result;
let indexCount = event.target.result;
for each (let unique in [false, true]) {
let index = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
.objectStore(autoIncrement)
.index(unique);
index.count().onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.target.result, indexCount,
"Correct number of entries in index");
let modifiedEntry = unique ? 5 : 10;
let keyRange = IDBKeyRange.only(modifiedEntry);
let sawEntry = false;
index.openCursor(keyRange).onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
sawEntry = true;
is(cursor.key, modifiedEntry, "Correct key");
cursor.value.index = unique ? 30 : 35;
cursor.update(cursor.value).onsuccess = function(event) {
cursor.continue();
}
}
else {
continueToNextStep();
}
}
yield;
is(sawEntry, true, "Saw entry for key value " + modifiedEntry);
// Recount index. Shouldn't change.
index = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
.objectStore(autoIncrement)
.index(unique);
index.count().onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, indexCount,
"Correct number of entries in index");
modifiedEntry = unique ? 30 : 35;
keyRange = IDBKeyRange.only(modifiedEntry);
sawEntry = false;
index.openCursor(keyRange).onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
sawEntry = true;
is(cursor.key, modifiedEntry, "Correct key");
delete cursor.value.index;
cursor.update(cursor.value).onsuccess = function(event) {
indexCount--;
cursor.continue();
}
}
else {
continueToNextStep();
}
}
yield;
is(sawEntry, true, "Saw entry for key value " + modifiedEntry);
// Recount objectStore. Should be unchanged.
objectStore = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
.objectStore(autoIncrement);
objectStore.count().onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreCount,
"Correct number of entries in objectStore");
// Recount index. Should be one item less.
index = objectStore.index(unique);
index.count().onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, indexCount,
"Correct number of entries in index");
modifiedEntry = objectStoreCount - 1;
objectStore.delete(modifiedEntry).onsuccess =
grabEventAndContinueHandler;
event = yield;
objectStoreCount--;
indexCount--;
objectStore.count().onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreCount,
"Correct number of entries in objectStore");
index.count().onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, indexCount,
"Correct number of entries in index");
}
}
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -10,6 +10,10 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7"> <script type="text/javascript;version=1.7">
var abortFired = false;
function abortListener() { abortFired = true; }
function testSteps() function testSteps()
{ {
const Ci = Components.interfaces; const Ci = Components.interfaces;
@ -33,6 +37,7 @@
let event = yield; let event = yield;
let db = event.target.result; let db = event.target.result;
db.onabort = abortListener;
let transaction; let transaction;
let objectStore; let objectStore;
@ -398,6 +403,8 @@
is(event.type, "abort", "transaction should fail"); is(event.type, "abort", "transaction should fail");
is(event.target, transaction, "transaction should fail"); is(event.target, transaction, "transaction should fail");
ok(abortFired, "Abort should have fired!");
finishTest(); finishTest();
yield; yield;
} }

View File

@ -0,0 +1,79 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
let request = mozIndexedDB.open(window.location.pathname, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
for each (let autoIncrement in [false, true]) {
let objectStore =
db.createObjectStore(autoIncrement, { keyPath: "id",
autoIncrement: autoIncrement });
objectStore.createIndex("", "index", { unique: true });
for (let i = 0; i < 10; i++) {
objectStore.add({ id: i, index: i });
}
}
event = yield;
is(event.type, "success", "expect a success event");
for each (let autoIncrement in [false, true]) {
objectStore = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
.objectStore(autoIncrement);
request = objectStore.put({ id: 5, index: 6 });
request.onsuccess = unexpectedSuccessHandler;
request.onerror = new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
event = yield;
event.preventDefault();
let keyRange = IDBKeyRange.only(5);
objectStore.index("").openCursor(keyRange).onsuccess = function(event) {
let cursor = event.target.result;
ok(cursor, "Must have a cursor here");
is(cursor.value.index, 5, "Still have the right index value");
cursor.value.index = 6;
request = cursor.update(cursor.value);
request.onsuccess = unexpectedSuccessHandler;
request.onerror =
new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
};
yield;
}
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -51,7 +51,7 @@
* http://www.w3.org/TR/DOM-Level-2-Style * http://www.w3.org/TR/DOM-Level-2-Style
*/ */
[builtinclass, scriptable, uuid(519ae4fa-0fee-4aaa-bcb9-34b503236801)] [builtinclass, scriptable, uuid(0a6fc4c6-a62a-4f52-9ab6-3d398b958843)]
interface nsIDOMCSS2Properties : nsISupports interface nsIDOMCSS2Properties : nsISupports
{ {
attribute DOMString background; attribute DOMString background;
@ -764,4 +764,7 @@ interface nsIDOMCSS2Properties : nsISupports
attribute DOMString MozAnimation; attribute DOMString MozAnimation;
// raises(DOMException) on setting // raises(DOMException) on setting
attribute DOMString MozTextSizeAdjust;
// raises(DOMException) on setting
}; };

View File

@ -654,9 +654,6 @@ nsresult nsPluginHost::GetURLWithHeaders(nsNPAPIPluginInstance* pluginInst,
PRUint32 getHeadersLength, PRUint32 getHeadersLength,
const char* getHeaders) const char* getHeaders)
{ {
nsAutoString string;
string.AssignWithConversion(url);
// we can only send a stream back to the plugin (as specified by a // we can only send a stream back to the plugin (as specified by a
// null target) if we also have a nsIPluginStreamListener to talk to // null target) if we also have a nsIPluginStreamListener to talk to
if (!target && !streamListener) if (!target && !streamListener)
@ -681,7 +678,8 @@ nsresult nsPluginHost::GetURLWithHeaders(nsNPAPIPluginInstance* pluginInst,
} }
if (streamListener) if (streamListener)
rv = NewPluginURLStream(string, pluginInst, streamListener, nsnull, rv = NewPluginURLStream(NS_ConvertUTF8toUTF16(url), pluginInst,
streamListener, nsnull,
getHeaders, getHeadersLength); getHeaders, getHeadersLength);
return rv; return rv;
@ -700,11 +698,8 @@ nsresult nsPluginHost::PostURL(nsISupports* pluginInst,
PRUint32 postHeadersLength, PRUint32 postHeadersLength,
const char* postHeaders) const char* postHeaders)
{ {
nsAutoString string;
nsresult rv; nsresult rv;
string.AssignWithConversion(url);
// we can only send a stream back to the plugin (as specified // we can only send a stream back to the plugin (as specified
// by a null target) if we also have a nsIPluginStreamListener // by a null target) if we also have a nsIPluginStreamListener
// to talk to also // to talk to also
@ -775,7 +770,8 @@ nsresult nsPluginHost::PostURL(nsISupports* pluginInst,
// if we don't have a target, just create a stream. This does // if we don't have a target, just create a stream. This does
// NS_OpenURI()! // NS_OpenURI()!
if (streamListener) if (streamListener)
rv = NewPluginURLStream(string, instance, streamListener, rv = NewPluginURLStream(NS_ConvertUTF8toUTF16(url), instance,
streamListener,
postStream, postHeaders, postHeadersLength); postStream, postHeaders, postHeadersLength);
return rv; return rv;

View File

@ -150,7 +150,6 @@ enum {
PREF_strict = 0, PREF_strict = 0,
PREF_werror, PREF_werror,
PREF_relimit, PREF_relimit,
PREF_tracejit,
PREF_methodjit, PREF_methodjit,
PREF_jitprofiling, PREF_jitprofiling,
PREF_methodjit_always, PREF_methodjit_always,
@ -168,7 +167,6 @@ const char* gPrefsToWatch[] = {
JS_OPTIONS_DOT_STR "strict", JS_OPTIONS_DOT_STR "strict",
JS_OPTIONS_DOT_STR "werror", JS_OPTIONS_DOT_STR "werror",
JS_OPTIONS_DOT_STR "relimit", JS_OPTIONS_DOT_STR "relimit",
JS_OPTIONS_DOT_STR "tracejit.content",
JS_OPTIONS_DOT_STR "methodjit.content", JS_OPTIONS_DOT_STR "methodjit.content",
JS_OPTIONS_DOT_STR "jitprofiling.content", JS_OPTIONS_DOT_STR "jitprofiling.content",
JS_OPTIONS_DOT_STR "methodjit_always" JS_OPTIONS_DOT_STR "methodjit_always"
@ -201,9 +199,6 @@ PrefCallback(const char* aPrefName, void* aClosure)
if (Preferences::GetBool(gPrefsToWatch[PREF_relimit])) { if (Preferences::GetBool(gPrefsToWatch[PREF_relimit])) {
newOptions |= JSOPTION_RELIMIT; newOptions |= JSOPTION_RELIMIT;
} }
if (Preferences::GetBool(gPrefsToWatch[PREF_tracejit])) {
newOptions |= JSOPTION_JIT;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_methodjit])) { if (Preferences::GetBool(gPrefsToWatch[PREF_methodjit])) {
newOptions |= JSOPTION_METHODJIT; newOptions |= JSOPTION_METHODJIT;
} }

View File

@ -87,7 +87,6 @@ abstract public class GeckoApp
public Handler mMainHandler; public Handler mMainHandler;
private IntentFilter mConnectivityFilter; private IntentFilter mConnectivityFilter;
private BroadcastReceiver mConnectivityReceiver; private BroadcastReceiver mConnectivityReceiver;
private IntentFilter mBatteryFilter;
private BroadcastReceiver mBatteryReceiver; private BroadcastReceiver mBatteryReceiver;
enum LaunchState {PreLaunch, Launching, WaitForDebugger, enum LaunchState {PreLaunch, Launching, WaitForDebugger,
@ -409,9 +408,10 @@ abstract public class GeckoApp
mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mConnectivityReceiver = new GeckoConnectivityReceiver(); mConnectivityReceiver = new GeckoConnectivityReceiver();
mBatteryFilter = new IntentFilter(); IntentFilter batteryFilter = new IntentFilter();
mBatteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED); batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
mBatteryReceiver = new GeckoBatteryManager(); mBatteryReceiver = new GeckoBatteryManager();
registerReceiver(mBatteryReceiver, batteryFilter);
if (!checkAndSetLaunchState(LaunchState.PreLaunch, if (!checkAndSetLaunchState(LaunchState.PreLaunch,
LaunchState.Launching)) LaunchState.Launching))
@ -505,7 +505,6 @@ abstract public class GeckoApp
super.onPause(); super.onPause();
unregisterReceiver(mConnectivityReceiver); unregisterReceiver(mConnectivityReceiver);
unregisterReceiver(mBatteryReceiver);
} }
@Override @Override
@ -524,7 +523,6 @@ abstract public class GeckoApp
onNewIntent(getIntent()); onNewIntent(getIntent());
registerReceiver(mConnectivityReceiver, mConnectivityFilter); registerReceiver(mConnectivityReceiver, mConnectivityFilter);
registerReceiver(mBatteryReceiver, mBatteryFilter);
} }
@Override @Override
@ -573,6 +571,8 @@ abstract public class GeckoApp
GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_SHUTDOWN)); GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_SHUTDOWN));
super.onDestroy(); super.onDestroy();
unregisterReceiver(mBatteryReceiver);
} }
@Override @Override
@ -618,10 +618,6 @@ abstract public class GeckoApp
// This file may not be there, so just log any errors and move on // This file may not be there, so just log any errors and move on
Log.w(LOG_FILE_NAME, "error removing files", ex); Log.w(LOG_FILE_NAME, "error removing files", ex);
} }
unpackFile(zip, buf, null, "application.ini");
try {
unpackFile(zip, buf, null, "update.locale");
} catch (Exception e) {/* this is non-fatal */}
// copy any .xpi file into an extensions/ directory // copy any .xpi file into an extensions/ directory
Enumeration<? extends ZipEntry> zipEntries = zip.entries(); Enumeration<? extends ZipEntry> zipEntries = zip.entries();

View File

@ -185,16 +185,13 @@ endif # GNU_CC
# special rule for pixman-mmx to get the right cflags # special rule for pixman-mmx to get the right cflags
pixman-mmx.$(OBJ_SUFFIX): pixman-mmx.c $(GLOBAL_DEPS) pixman-mmx.$(OBJ_SUFFIX): pixman-mmx.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(MMX_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(MMX_CFLAGS) $(_VPATH_SRCS)
pixman-sse2.$(OBJ_SUFFIX): pixman-sse2.c $(GLOBAL_DEPS) pixman-sse2.$(OBJ_SUFFIX): pixman-sse2.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_CFLAGS) $(_VPATH_SRCS)
pixman-arm-neon.$(OBJ_SUFFIX): pixman-arm-neon.c $(GLOBAL_DEPS) pixman-arm-neon.$(OBJ_SUFFIX): pixman-arm-neon.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(ARM_NEON_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(ARM_NEON_CFLAGS) $(_VPATH_SRCS)

View File

@ -621,21 +621,21 @@ struct PairPosFormat1
inline bool apply (hb_apply_context_t *c) const inline bool apply (hb_apply_context_t *c) const
{ {
TRACE_APPLY (); TRACE_APPLY ();
unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); unsigned int j = c->buffer->i;
if (unlikely (c->buffer->i + 2 > end)) unsigned int end = MIN (c->buffer->len, j + c->context_length);
if (unlikely (j >= end))
return false; return false;
unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint); unsigned int index = (this+coverage) (c->buffer->info[j].codepoint);
if (likely (index == NOT_COVERED)) if (likely (index == NOT_COVERED))
return false; return false;
unsigned int j = c->buffer->i + 1; do
while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
{ {
if (unlikely (j == end))
return false;
j++; j++;
} if (unlikely (j == end))
return false;
} while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL));
return (this+pairSet[index]).apply (c, &valueFormat1, j); return (this+pairSet[index]).apply (c, &valueFormat1, j);
} }
@ -683,21 +683,21 @@ struct PairPosFormat2
inline bool apply (hb_apply_context_t *c) const inline bool apply (hb_apply_context_t *c) const
{ {
TRACE_APPLY (); TRACE_APPLY ();
unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); unsigned int j = c->buffer->i;
if (unlikely (c->buffer->i + 2 > end)) unsigned int end = MIN (c->buffer->len, j + c->context_length);
if (unlikely (j >= end))
return false; return false;
unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint); unsigned int index = (this+coverage) (c->buffer->info[j].codepoint);
if (likely (index == NOT_COVERED)) if (likely (index == NOT_COVERED))
return false; return false;
unsigned int j = c->buffer->i + 1; do
while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
{ {
j++;
if (unlikely (j == end)) if (unlikely (j == end))
return false; return false;
j++; } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL));
}
unsigned int len1 = valueFormat1.get_len (); unsigned int len1 = valueFormat1.get_len ();
unsigned int len2 = valueFormat2.get_len (); unsigned int len2 = valueFormat2.get_len ();
@ -836,21 +836,21 @@ struct CursivePosFormat1
if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)
return false; return false;
unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); unsigned int j = c->buffer->i;
if (unlikely (c->buffer->i + 2 > end)) unsigned int end = MIN (c->buffer->len, j + c->context_length);
if (unlikely (j >= end))
return false; return false;
const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->info[c->buffer->i].codepoint)]; const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->info[j].codepoint)];
if (!this_record.exitAnchor) if (!this_record.exitAnchor)
return false; return false;
unsigned int j = c->buffer->i + 1; do
while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
{ {
j++;
if (unlikely (j == end)) if (unlikely (j == end))
return false; return false;
j++; } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL));
}
const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[j].codepoint)]; const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[j].codepoint)];
if (!next_record.entryAnchor) if (!next_record.entryAnchor)

View File

@ -342,24 +342,25 @@ struct Ligature
inline bool apply (hb_apply_context_t *c) const inline bool apply (hb_apply_context_t *c) const
{ {
TRACE_APPLY (); TRACE_APPLY ();
unsigned int i, j; unsigned int i;
unsigned int j = c->buffer->i;
unsigned int count = component.len; unsigned int count = component.len;
unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); unsigned int end = MIN (c->buffer->len, j + c->context_length);
if (unlikely (c->buffer->i + count > end)) if (unlikely (j >= end))
return false; return false;
bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
bool found_non_mark = false; bool found_non_mark = false;
for (i = 1, j = c->buffer->i + 1; i < count; i++, j++) for (i = 1; i < count; i++)
{ {
unsigned int property; unsigned int property;
while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, &property)) do
{ {
if (unlikely (j + count - i == end))
return false;
j++; j++;
} if (unlikely (j == end))
return false;
} while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, &property));
found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);

View File

@ -126,25 +126,26 @@ static inline bool match_input (hb_apply_context_t *c,
const void *match_data, const void *match_data,
unsigned int *context_length_out) unsigned int *context_length_out)
{ {
unsigned int i, j; unsigned int i;
unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); unsigned int j = c->buffer->i;
if (unlikely (c->buffer->i + count > end)) unsigned int end = MIN (c->buffer->len, j + c->context_length);
if (unlikely (j + count > end))
return false; return false;
for (i = 1, j = c->buffer->i + 1; i < count; i++, j++) for (i = 1; i < count; i++)
{ {
while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL)) do
{ {
if (unlikely (j + count - i == end))
return false;
j++; j++;
} if (unlikely (j >= end))
return false;
} while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL));
if (likely (!match_func (c->buffer->info[j].codepoint, input[i - 1], match_data))) if (likely (!match_func (c->buffer->info[j].codepoint, input[i - 1], match_data)))
return false; return false;
} }
*context_length_out = j - c->buffer->i; *context_length_out = j - c->buffer->i + 1;
return true; return true;
} }
@ -155,17 +156,16 @@ static inline bool match_backtrack (hb_apply_context_t *c,
match_func_t match_func, match_func_t match_func,
const void *match_data) const void *match_data)
{ {
if (unlikely (c->buffer->backtrack_len () < count)) unsigned int j = c->buffer->backtrack_len ();
return false;
for (unsigned int i = 0, j = c->buffer->backtrack_len () - 1; i < count; i++, j--) for (unsigned int i = 0; i < count; i++)
{ {
while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->out_info[j], c->lookup_props, NULL)) do
{ {
if (unlikely (j + 1 == count - i)) if (unlikely (!j))
return false; return false;
j--; j--;
} } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->out_info[j], c->lookup_props, NULL));
if (likely (!match_func (c->buffer->out_info[j].codepoint, backtrack[i], match_data))) if (likely (!match_func (c->buffer->out_info[j].codepoint, backtrack[i], match_data)))
return false; return false;
@ -181,19 +181,18 @@ static inline bool match_lookahead (hb_apply_context_t *c,
const void *match_data, const void *match_data,
unsigned int offset) unsigned int offset)
{ {
unsigned int i, j; unsigned int i;
unsigned int j = c->buffer->i + offset - 1;
unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
if (unlikely (c->buffer->i + offset + count > end))
return false;
for (i = 0, j = c->buffer->i + offset; i < count; i++, j++) for (i = 0; i < count; i++)
{ {
while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL)) do
{ {
if (unlikely (j + count - i == end))
return false;
j++; j++;
} if (unlikely (j >= end))
return false;
} while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL));
if (likely (!match_func (c->buffer->info[j].codepoint, lookahead[i], match_data))) if (likely (!match_func (c->buffer->info[j].codepoint, lookahead[i], match_data)))
return false; return false;

View File

@ -36,6 +36,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "mozilla/Attributes.h"
#include "gfxSharedImageSurface.h" #include "gfxSharedImageSurface.h"
#include "mozilla/layers/PLayerChild.h" #include "mozilla/layers/PLayerChild.h"
@ -43,8 +45,6 @@
#include "mozilla/layers/PLayersParent.h" #include "mozilla/layers/PLayersParent.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/Types.h"
#include "ipc/ShadowLayerChild.h" #include "ipc/ShadowLayerChild.h"
#include "BasicLayers.h" #include "BasicLayers.h"

View File

@ -68,11 +68,9 @@ endif # GNU_CC
# special rules for transform-sse*.c to get the right cflags. (taken from pixman/src/Makefile.in) # special rules for transform-sse*.c to get the right cflags. (taken from pixman/src/Makefile.in)
transform-sse1.$(OBJ_SUFFIX): transform-sse1.c $(GLOBAL_DEPS) transform-sse1.$(OBJ_SUFFIX): transform-sse1.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE1_FLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE1_FLAGS) $(_VPATH_SRCS)
transform-sse2.$(OBJ_SUFFIX): transform-sse2.c $(GLOBAL_DEPS) transform-sse2.$(OBJ_SUFFIX): transform-sse2.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_FLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_FLAGS) $(_VPATH_SRCS)

View File

@ -66,7 +66,7 @@ CPPSRCS = \
SandboxHal.cpp \ SandboxHal.cpp \
$(NULL) $(NULL)
ifeq (Android,$(OS_TARGET)) ifeq (android,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += AndroidHal.cpp CPPSRCS += AndroidHal.cpp
else ifeq (Linux,$(OS_TARGET)) else ifeq (Linux,$(OS_TARGET))
CPPSRCS += LinuxHal.cpp CPPSRCS += LinuxHal.cpp

View File

@ -384,8 +384,6 @@ UPowerClient::UpdateSavedInfo(GHashTable* aHashTable)
{ {
bool isFull = false; bool isFull = false;
mLevel = g_value_get_double(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "Percentage")))*0.01;
/* /*
* State values are confusing... * State values are confusing...
* First of all, after looking at upower sources (0.9.13), it seems that * First of all, after looking at upower sources (0.9.13), it seems that
@ -420,6 +418,17 @@ UPowerClient::UpdateSavedInfo(GHashTable* aHashTable)
break; break;
} }
/*
* The battery level might be very close to 100% (like 99.xxxx%) without
* increasing. It seems that upower sets the battery state as 'full' in that
* case so we should trust it and not even try to get the value.
*/
if (isFull) {
mLevel = 1.0;
} else {
mLevel = g_value_get_double(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "Percentage")))*0.01;
}
if (isFull) { if (isFull) {
mRemainingTime = 0; mRemainingTime = 0;
} else { } else {

View File

@ -41,6 +41,8 @@
#ifndef mozilla_ipc_Shmem_h #ifndef mozilla_ipc_Shmem_h
#define mozilla_ipc_Shmem_h #define mozilla_ipc_Shmem_h
#include "mozilla/Attributes.h"
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/process.h" #include "base/process.h"
@ -87,7 +89,7 @@
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
class NS_FINAL_CLASS Shmem class Shmem MOZ_FINAL
{ {
friend struct IPC::ParamTraits<mozilla::ipc::Shmem>; friend struct IPC::ParamTraits<mozilla::ipc::Shmem>;

View File

@ -92,6 +92,7 @@ Types = (
Includes = ( Includes = (
'mozilla/Attributes.h',
'base/basictypes.h', 'base/basictypes.h',
'prtime.h', 'prtime.h',
'nscore.h', 'nscore.h',

View File

@ -161,9 +161,9 @@ class CxxCodeGen(CodePrinter, Visitor):
if c.abstract: if c.abstract:
# FIXME/cjones: turn this "on" when we get the analysis # FIXME/cjones: turn this "on" when we get the analysis
self.write(' /*NS_ABSTRACT_CLASS*/') self.write(' /*NS_ABSTRACT_CLASS*/')
if c.final:
self.write(' NS_FINAL_CLASS')
self.write(' '+ c.name) self.write(' '+ c.name)
if c.final:
self.write(' MOZ_FINAL')
if c.specializes is not None: if c.specializes is not None:
self.write(' <') self.write(' <')

View File

@ -220,7 +220,6 @@ INSTALLED_HEADERS = \
jsreflect.h \ jsreflect.h \
jsstdint.h \ jsstdint.h \
jsstr.h \ jsstr.h \
jstracer.h \
jstypedarray.h \ jstypedarray.h \
jstypes.h \ jstypes.h \
jsutil.h \ jsutil.h \
@ -283,6 +282,7 @@ VPATH += \
EXPORTS_NAMESPACES += mozilla EXPORTS_NAMESPACES += mozilla
EXPORTS_mozilla = \ EXPORTS_mozilla = \
Attributes.h \
GuardObjects.h \ GuardObjects.h \
RangedPtr.h \ RangedPtr.h \
RefPtr.h \ RefPtr.h \
@ -290,53 +290,6 @@ EXPORTS_mozilla = \
Util.h \ Util.h \
$(NULL) $(NULL)
ifdef ENABLE_TRACEJIT
VPATH += \
$(srcdir)/tracejit \
$(srcdir)/nanojit \
INSTALLED_HEADERS += \
jsbuiltins.h \
Assembler.h \
Allocator.h \
CodeAlloc.h \
Containers.h \
LIR.h \
LIRopcode.tbl \
avmplus.h \
Fragmento.h \
Native.h \
NativeCommon.h \
Native$(NANOJIT_ARCH).h \
njconfig.h \
njcpudetect.h \
RegAlloc.h \
nanojit.h \
VMPI.h \
Writer.h \
$(NULL)
CPPSRCS += \
jstracer.cpp \
Assembler.cpp \
Allocator.cpp \
CodeAlloc.cpp \
Containers.cpp \
Fragmento.cpp \
LIR.cpp \
njconfig.cpp \
avmplus.cpp \
Native$(NANOJIT_ARCH).cpp \
jsbuiltins.cpp \
VMPI.cpp \
Writer.cpp \
$(NULL)
ifdef MOZ_DEBUG
CPPSRCS += RegAlloc.cpp
endif
endif # ENABLE_TRACEJIT
ifdef ENABLE_METHODJIT ifdef ENABLE_METHODJIT
############################################### ###############################################
@ -691,7 +644,7 @@ ifneq ($(OS_ARCH),WINNT) # FIXME: this should be made work on Windows too.
#check:: check-malloc-function-usage FIXME: disable on JM until closer to merge time. #check:: check-malloc-function-usage FIXME: disable on JM until closer to merge time.
endif endif
JITFLAGS = ,m,j,mj,mjp,am,amj,amjp,amd,n,mn,jn,mjn,mjpn,amn,amjn,amjpn,amdn JITFLAGS = ,m,am,amd,n,mn,amn,amdn,mdn
check-jit-test:: check-jit-test::
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \ $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \
--valgrind --no-slow --no-progress --tinderbox --jitflags=$(JITFLAGS) $(DIST)/bin/js$(BIN_SUFFIX) --valgrind --no-slow --no-progress --tinderbox --jitflags=$(JITFLAGS) $(DIST)/bin/js$(BIN_SUFFIX)
@ -729,9 +682,6 @@ check-jstests:
ifeq ($(OS_ARCH),WINNT) ifeq ($(OS_ARCH),WINNT)
ifdef ENABLE_METHODJIT ifdef ENABLE_METHODJIT
ifdef ENABLE_TRACEJIT
#check:: check-jstests
endif
endif endif
else else
ifndef HAVE_DTRACE ifndef HAVE_DTRACE
@ -851,7 +801,6 @@ ifdef SOLARIS_SUNPRO_CXX
ifeq ($(TARGET_CPU),sparc) ifeq ($(TARGET_CPU),sparc)
# Sun Studio SPARC doesn't work well with gcc inline asm, use lock_SunOS_sparc*.il # Sun Studio SPARC doesn't work well with gcc inline asm, use lock_SunOS_sparc*.il
jslock.o: jslock.cpp Makefile.in lock_sparcv8plus.il lock_sparcv9.il jslock.o: jslock.cpp Makefile.in lock_sparcv8plus.il lock_sparcv9.il
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
ifeq (sparcv9,$(findstring sparcv9,$(OS_TEST))) ifeq (sparcv9,$(findstring sparcv9,$(OS_TEST)))
$(CXX) -o $@ -c $(COMPILE_CFLAGS) $(srcdir)/lock_sparcv9.il $< $(CXX) -o $@ -c $(COMPILE_CFLAGS) $(srcdir)/lock_sparcv9.il $<
@ -865,11 +814,9 @@ endif # SOLARIS_SUNPRO_CXX
# This suppresses optimization for this single compilation unit. # This suppresses optimization for this single compilation unit.
ifeq ($(OS_ARCH),AIX) ifeq ($(OS_ARCH),AIX)
jsatom.o: jsatom.cpp Makefile.in jsatom.o: jsatom.cpp Makefile.in
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $< $(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
jsdtoa.o: jsdtoa.cpp Makefile.in jsdtoa.o: jsdtoa.cpp Makefile.in
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $< $(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
endif endif
@ -975,41 +922,6 @@ $(CURDIR)/javascript-trace.h: $(srcdir)/javascript-trace.d
$(addsuffix .$(OBJ_SUFFIX),jsprobes jsinterp jsobj): $(CURDIR)/javascript-trace.h $(addsuffix .$(OBJ_SUFFIX),jsprobes jsinterp jsobj): $(CURDIR)/javascript-trace.h
endif endif
ifdef ENABLE_TRACEJIT
# Imacro compilation.
$(CURDIR)/imacros.c.out: $(srcdir)/imacro_asm.py $(srcdir)/imacros.jsasm jsopcode.tbl
$(PYTHON) $< $(srcdir)/imacros.jsasm $(CURDIR)/imacros.c.out
$(addsuffix .$(OBJ_SUFFIX),jstracer): $(CURDIR)/imacros.c.out
# Code for importing the nanojit subtree from its repository.
NANOJIT_CENTRAL_REV=$(shell cat $(srcdir)/nanojit-import-rev)
NANOJIT_CENTRAL_REPO=http://hg.mozilla.org/projects/nanojit-central
NANOJIT_CENTRAL_LOCAL=$(CURDIR)/nanojit-central
CUR_REPO=$(srcdir)/../..
update-nanojit:
$(RM) -r $(NANOJIT_CENTRAL_LOCAL) import-splicemap import-revmap
hg clone $(NANOJIT_CENTRAL_REPO) $(NANOJIT_CENTRAL_LOCAL)
python $(srcdir)/find-child.py \
--src=$(NANOJIT_CENTRAL_LOCAL) \
--dst=$(CUR_REPO) \
--start=$(NANOJIT_CENTRAL_REV) \
--filemap=$(srcdir)/nanojit-import-filemap \
>import-splicemap
hg convert --config convert.hg.saverev=True \
--config convert.hg.startrev=`cut -d ' ' -f 1 import-splicemap` \
--filemap=$(srcdir)/nanojit-import-filemap \
--splicemap=import-splicemap \
$(NANOJIT_CENTRAL_LOCAL) \
$(CUR_REPO) \
import-revmap
(cd $(srcdir) && hg up)
(cd $(NANOJIT_CENTRAL_LOCAL) && hg log -r tip --template "{node}\n") >$(srcdir)/nanojit-import-rev
(cd $(srcdir) && hg commit --message="Update nanojit-import-rev stamp." nanojit-import-rev)
.PHONY: update-nanojit
endif
############################################### ###############################################
# BEGIN kludges for the Nitro assembler # BEGIN kludges for the Nitro assembler
# #
@ -1019,7 +931,7 @@ endif
# the code in js/src/assembler. # the code in js/src/assembler.
CXXFLAGS += -DUSE_SYSTEM_MALLOC=1 -DENABLE_ASSEMBLER=1 CXXFLAGS += -DUSE_SYSTEM_MALLOC=1 -DENABLE_ASSEMBLER=1
ifneq (,$(ENABLE_YARR_JIT)$(ENABLE_TRACEJIT)$(ENABLE_METHODJIT)) ifneq (,$(ENABLE_YARR_JIT)$(ENABLE_METHODJIT))
CXXFLAGS += -DENABLE_JIT=1 CXXFLAGS += -DENABLE_JIT=1
endif endif

View File

@ -331,9 +331,7 @@ HAVE_DTRACE= @HAVE_DTRACE@
VISIBILITY_FLAGS = @VISIBILITY_FLAGS@ VISIBILITY_FLAGS = @VISIBILITY_FLAGS@
WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@ WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@
ENABLE_TRACEJIT = @ENABLE_TRACEJIT@
ENABLE_METHODJIT = @ENABLE_METHODJIT@ ENABLE_METHODJIT = @ENABLE_METHODJIT@
NANOJIT_ARCH = @NANOJIT_ARCH@
HAVE_ARM_SIMD= @HAVE_ARM_SIMD@ HAVE_ARM_SIMD= @HAVE_ARM_SIMD@
JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@ JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@

View File

@ -64,8 +64,6 @@ ifdef SDK_HEADERS
EXPORTS += $(SDK_HEADERS) EXPORTS += $(SDK_HEADERS)
endif endif
REPORT_BUILD = @echo $(notdir $<)
ifeq ($(OS_ARCH),OS2) ifeq ($(OS_ARCH),OS2)
EXEC = EXEC =
else else
@ -1150,32 +1148,25 @@ endif # MOZ_AUTO_DEPS
# Rules for building native targets must come first because of the host_ prefix # Rules for building native targets must come first because of the host_ prefix
host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
%:: %.c $(GLOBAL_DEPS) %:: %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS) $(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) %.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
@ -1186,7 +1177,6 @@ moc_%.cpp: %.h $(GLOBAL_DEPS)
$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@ $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
moc_%.cc: %.cc $(GLOBAL_DEPS) moc_%.cc: %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@ $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
ifdef ASFILES ifdef ASFILES
@ -1207,12 +1197,10 @@ endif
# Please keep the next two rules in sync. # Please keep the next two rules in sync.
# #
%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) %.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) %.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
ifdef STRICT_CPLUSPLUS_SUFFIX ifdef STRICT_CPLUSPLUS_SUFFIX
echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
@ -1223,12 +1211,10 @@ else
endif #STRICT_CPLUSPLUS_SUFFIX endif #STRICT_CPLUSPLUS_SUFFIX
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX) @$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC) @$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS) $(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
@ -1478,7 +1464,6 @@ XPIDL_DEPS = \
$(NULL) $(NULL)
$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \ $(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \ -I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \ -I$(topsrcdir)/xpcom/idl-parser \
@ -1490,7 +1475,6 @@ ifndef NO_GEN_XPT
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components. # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \ $(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \ -I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \ -I$(topsrcdir)/xpcom/idl-parser \
@ -1779,15 +1763,12 @@ define MAKE_DEPS_NOAUTO
endef endef
$(MDDEPDIR)/%.pp: %.c $(MDDEPDIR)/%.pp: %.c
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO) @$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.cpp $(MDDEPDIR)/%.pp: %.cpp
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO) @$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.s $(MDDEPDIR)/%.pp: %.s
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO) @$(MAKE_DEPS_NOAUTO)
ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))

View File

@ -2790,7 +2790,6 @@ dnl Configure JIT support
case "$target" in case "$target" in
i?86-*) i?86-*)
NANOJIT_ARCH=i386
ENABLE_METHODJIT=1 ENABLE_METHODJIT=1
ENABLE_MONOIC=1 ENABLE_MONOIC=1
ENABLE_POLYIC=1 ENABLE_POLYIC=1
@ -2799,7 +2798,6 @@ i?86-*)
AC_DEFINE(JS_NUNBOX32) AC_DEFINE(JS_NUNBOX32)
;; ;;
x86_64*-*) x86_64*-*)
NANOJIT_ARCH=X64
ENABLE_METHODJIT=1 ENABLE_METHODJIT=1
ENABLE_MONOIC=1 ENABLE_MONOIC=1
ENABLE_POLYIC=1 ENABLE_POLYIC=1
@ -2808,7 +2806,6 @@ x86_64*-*)
AC_DEFINE(JS_PUNBOX64) AC_DEFINE(JS_PUNBOX64)
;; ;;
arm*-*) arm*-*)
NANOJIT_ARCH=ARM
ENABLE_METHODJIT=1 ENABLE_METHODJIT=1
ENABLE_MONOIC=1 ENABLE_MONOIC=1
ENABLE_POLYIC=1 ENABLE_POLYIC=1
@ -2817,7 +2814,6 @@ arm*-*)
AC_DEFINE(JS_NUNBOX32) AC_DEFINE(JS_NUNBOX32)
;; ;;
sparc*-*) sparc*-*)
NANOJIT_ARCH=Sparc
ENABLE_METHODJIT=1 ENABLE_METHODJIT=1
ENABLE_MONOIC=1 ENABLE_MONOIC=1
ENABLE_POLYIC=1 ENABLE_POLYIC=1
@ -2840,8 +2836,8 @@ MOZ_ARG_DISABLE_BOOL(polyic,
ENABLE_POLYIC= ) ENABLE_POLYIC= )
MOZ_ARG_ENABLE_BOOL(tracejit, MOZ_ARG_ENABLE_BOOL(tracejit,
[ --enable-tracejit Enable tracing JIT support], [ --enable-tracejit Deprecated, does nothing],
ENABLE_TRACEJIT=1, ENABLE_TRACEJIT=,
ENABLE_TRACEJIT= ) ENABLE_TRACEJIT= )
MOZ_ARG_ENABLE_BOOL(methodjit-spew, MOZ_ARG_ENABLE_BOOL(methodjit-spew,
@ -2871,62 +2867,6 @@ if test "$ENABLE_METHODJIT_SPEW"; then
AC_DEFINE(JS_METHODJIT_SPEW) AC_DEFINE(JS_METHODJIT_SPEW)
fi fi
if test "$ENABLE_TRACEJIT"; then
AC_DEFINE(FEATURE_NANOJIT)
AC_DEFINE(JS_TRACER)
case "$target" in
i?86-*)
AC_DEFINE(AVMPLUS_IA32)
;;
x86_64*-*)
AC_DEFINE(AVMPLUS_AMD64)
AC_DEFINE(AVMPLUS_64BIT)
;;
arm*-*)
AC_DEFINE(AVMPLUS_ARM)
;;
sparc-*)
AC_DEFINE(AVMPLUS_SPARC)
;;
esac
case "$target" in
*-linux*|*-android*|*-linuxandroid*)
AC_DEFINE(AVMPLUS_UNIX)
AC_DEFINE(AVMPLUS_LINUX)
;;
*-darwin*)
AC_DEFINE(AVMPLUS_UNIX)
;;
*-solaris*)
AC_DEFINE(AVMPLUS_UNIX)
;;
*-freebsd*|*-kfreebsd*)
AC_DEFINE(AVMPLUS_UNIX)
;;
*-openbsd*)
AC_DEFINE(AVMPLUS_UNIX)
;;
*-gnu*)
AC_DEFINE(AVMPLUS_UNIX)
;;
*-mingw*)
AC_DEFINE(AVMPLUS_WIN32)
;;
*-os2*)
AC_DEFINE(AVMPLUS_OS2)
;;
*)
AC_MSG_ERROR([Unrecognized nanojit platform. Use --disable-tracejit to build without tracing JIT support.])
esac
fi # ENABLE_TRACEJIT
AC_SUBST(ENABLE_TRACEJIT)
AC_SUBST(NANOJIT_ARCH)
if test -z "$SKIP_COMPILER_CHECKS"; then if test -z "$SKIP_COMPILER_CHECKS"; then
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
dnl ======================================================== dnl ========================================================
@ -4503,20 +4443,6 @@ if test -n "$MOZ_TRACE_JSCALLS"; then
AC_DEFINE(MOZ_TRACE_JSCALLS) AC_DEFINE(MOZ_TRACE_JSCALLS)
fi fi
dnl ========================================================
dnl = Use TraceVis
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(tracevis,
[ --enable-tracevis Enable TraceVis tracing tool (default=no)],
MOZ_TRACEVIS=1,
MOZ_TRACEVIS= )
if test -n "$MOZ_TRACEVIS"; then
AC_DEFINE(MOZ_TRACEVIS)
if test -z "$ENABLE_TRACEJIT"; then
AC_MSG_ERROR([--enable-tracevis is incompatible with --disable-tracejit])
fi
fi
dnl ======================================================== dnl ========================================================
dnl = Use incremental GC dnl = Use incremental GC
dnl ======================================================== dnl ========================================================

View File

@ -89,10 +89,6 @@ using namespace js;
using namespace js::gc; using namespace js::gc;
using namespace js::frontend; using namespace js::frontend;
#ifdef JS_TRACER
extern uint8 js_opcode2extra[];
#endif
static JSBool static JSBool
NewTryNote(JSContext *cx, BytecodeEmitter *bce, JSTryNoteKind kind, uintN stackDepth, NewTryNote(JSContext *cx, BytecodeEmitter *bce, JSTryNoteKind kind, uintN stackDepth,
size_t start, size_t end); size_t start, size_t end);
@ -204,21 +200,15 @@ UpdateDepth(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
jsbytecode *pc; jsbytecode *pc;
JSOp op; JSOp op;
const JSCodeSpec *cs; const JSCodeSpec *cs;
uintN extra, nuses; uintN nuses;
intN ndefs; intN ndefs;
pc = bce->code(target); pc = bce->code(target);
op = (JSOp) *pc; op = (JSOp) *pc;
cs = &js_CodeSpec[op]; cs = &js_CodeSpec[op];
#ifdef JS_TRACER if ((cs->format & JOF_TMPSLOT_MASK)) {
extra = js_opcode2extra[op];
#else
extra = 0;
#endif
if ((cs->format & JOF_TMPSLOT_MASK) || extra) {
uintN depth = (uintN) bce->stackDepth + uintN depth = (uintN) bce->stackDepth +
((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT) + ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT);
extra;
if (depth > bce->maxStackDepth) if (depth > bce->maxStackDepth)
bce->maxStackDepth = depth; bce->maxStackDepth = depth;
} }

View File

@ -335,7 +335,7 @@ class HeapValue
bool toBoolean() const { return value.toBoolean(); } bool toBoolean() const { return value.toBoolean(); }
double toNumber() const { return value.toNumber(); } double toNumber() const { return value.toNumber(); }
unsigned gcKind() const { return value.gcKind(); } JSGCTraceKind gcKind() const { return value.gcKind(); }
inline void boxNonDoubleFrom(JSValueType type, uint64 *out); inline void boxNonDoubleFrom(JSValueType type, uint64 *out);

View File

@ -1,467 +0,0 @@
#!/usr/bin/env python
# -*- Mode: Python; tab-width: 4; indent-tabs-mode: nil -*-
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the TraceMonkey IMacro Assembler.
#
# The Initial Developer of the Original Code is
# Brendan Eich <brendan@mozilla.org>.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
# An imacro (interpreter-macro) assembler in Python.
#
# Filename suffix conventions, used by Makefile.in rules:
# .jsasm SpiderMonkey JS assembly source, which could be input to other
# assemblers than imacro_asm.js, hence the generic suffix!
# .c.out C source output by imacro_asm.js
import re
import os
class Op:
def __init__(self, jsop, opcode, opname, opsrc, oplen, pops, pushes, precedence, flags):
self.jsop = jsop
self.opcode = opcode
self.opname = opname
self.opsrc = opsrc
self.oplen = oplen
self.pops = pops
self.pushes = pushes
self.precedence = precedence
self.flags = flags
def readFileLines(filename):
f = open(filename)
try:
return f.readlines()
finally:
f.close()
def load_ops(filename):
opdef_regexp = re.compile(r'''(?x)
^ OPDEF \( (JSOP_\w+), \s* # op
([0-9]+), \s* # val
("[^"]+" | [\w_]+), \s* # name
("[^"]+" | [\w_]+), \s* # image
(-1|[0-9]+), \s* # len
(-1|[0-9]+), \s* # uses
(-1|[0-9]+), \s* # defs
([0-9]+), \s* # prec
([\w_| ]+) \s* # format
\) \s* $''')
def decode_string_expr(expr):
if expr == 'NULL':
return None
if expr[0] == '"':
assert expr[-1] == '"'
return expr[1:-1]
assert expr.startswith('js_') and expr.endswith('_str')
return expr[3:-4]
opinfo = []
for lineno, line in enumerate(readFileLines(filename)):
if line.startswith('OPDEF'):
m = opdef_regexp.match(line)
if m is None:
raise ValueError("OPDEF line of wrong format in jsopcode.tbl at line %d" % (lineno + 1))
jsop, opcode, opname, opsrc, oplen, pops, pushes, precedence, flags = m.groups()
assert int(opcode) == len(opinfo)
opinfo.append(Op(jsop, int(opcode), decode_string_expr(opname),
decode_string_expr(opsrc), int(oplen), int(pops), int(pushes),
int(precedence), flags.replace(' ', '').split('|')))
return opinfo
opinfo = load_ops(os.path.join(os.path.dirname(__file__), "jsopcode.tbl"))
opname2info = dict((info.opname, info) for info in opinfo)
jsop2opcode = dict((info.jsop, info.opcode) for info in opinfo)
def to_uint8(s):
try:
n = int(s)
except ValueError:
n = -1
if 0 <= n < (1<<8):
return n
raise ValueError("invalid 8-bit operand: " + s)
def to_uint16(s):
try:
n = int(s)
except ValueError:
n = -1
if 0 <= n < (1<<16):
return n
raise ValueError("invalid 16-bit operand: " + s)
def immediate(op):
info = op.info
imm1Expr = op.imm1.startswith('(')
if 'JOF_ATOM' in info.flags:
if op.imm1 in ('void', 'object', 'function', 'string', 'number', 'boolean'):
return "0, COMMON_TYPE_ATOM_INDEX(JSTYPE_%s)" % op.imm1.upper()
return "0, COMMON_ATOM_INDEX(%s)" % op.imm1
if 'JOF_JUMP' in info.flags:
assert not imm1Expr
return "%d, %d" % ((op.target >> 8) & 0xff, op.target & 0xff)
if 'JOF_UINT8' in info.flags or 'JOF_INT8' in info.flags:
if imm1Expr:
return op.imm1
return str(to_uint8(op.imm1))
if 'JOF_UINT16' in info.flags:
if imm1Expr:
return '(%s & 0xff00) >> 8, (%s & 0xff)' % (op.imm1, op.imm1)
v = to_uint16(op.imm1)
return "%d, %d" % ((v & 0xff00) >> 8, v & 0xff)
raise NotImplementedError(info.jsop + " format not yet implemented")
def simulate_cfg(igroup, imacro, depth, i):
any_group_opcode = None
expected_depth = None
for opcode in igroup.ops:
opi = opinfo[opcode]
if any_group_opcode is None:
any_group_opcode = opcode
if opi.pops < 0:
expected_depth = None
else:
expected_depth = opi.pushes - opi.pops
elif expected_depth is None:
if opi.pops >= 0:
raise ValueError("imacro shared by constant- and variable-stack-defs/uses instructions")
else:
if opi.pops < 0:
raise ValueError("imacro shared by constant- and variable-stack-defs/uses instructions")
if opi.pushes - opi.pops != expected_depth:
raise ValueError("imacro shared by instructions with different stack depths")
for i in range(i, len(imacro.code)):
op = imacro.code[i]
opi = op.info
if opi.opname == 'imacop':
opi = opinfo[any_group_opcode]
if opi.pops < 0:
depth -= 2 + int(op.imm1)
else:
depth -= opi.pops
depth += opi.pushes
if i in imacro.depths and imacro.depths[i] != depth:
raise ValueError("Mismatched depth at %s:%d" % (imacro.filename, op.line))
# Underflowing depth isn't necessarily fatal; most of the imacros
# assume they are called with N>0 args so some assume it's ok to go
# to some depth <N. We simulate starting from 0, as we've no idea
# what else to do.
#
# if depth < 0:
# raise ValueError("Negative static-stack depth at %s:%d" % (imacro.filename, op.line))
if depth > imacro.maxdepth:
imacro.maxdepth = depth
imacro.depths[i] = depth
if hasattr(op, "target_index"):
if op.target_index <= i:
raise ValueError("Backward jump at %s:%d" % (imacro.filename, op.line))
simulate_cfg(igroup, imacro, depth, op.target_index)
if op.info.opname in ('goto', 'gotox'):
return
if expected_depth is not None and depth != expected_depth:
raise ValueError("Expected depth %d, got %d" % (expected_depth, depth))
# Syntax (spaces are significant only to delimit tokens):
#
# Assembly ::= (Directive? '\n')*
# Directive ::= (name ':')? Operation
# Operation ::= opname Operands?
# Operands ::= Operand (',' Operand)*
# Operand ::= name | number | '(' Expr ')'
# Expr ::= a constant-expression in the C++ language
# containing no parentheses
#
# We simplify given line structure and the maximum of one immediate operand,
# by parsing using split and regexps. For ease of parsing, parentheses are
# banned in an Expr for now, even in quotes or a C++ comment.
#
# Pseudo-ops start with . and include .igroup and .imacro, terminated by .end.
# .imacro must nest in .igroup, neither nests in itself. See imacros.jsasm for
# examples.
#
line_regexp = re.compile(r'''(?x)
^
(?: (\w+): )? # optional label at start of line
\s* (\.?\w+) # optional spaces, (pseudo-)opcode
(?: \s+ ([+-]?\w+ | \([^)]*\)) )? # optional first immediate operand
(?: \s+ ([\w,-]+ | \([^)]*\)) )? # optional second immediate operand
(?: \s* (?:\#.*) )? # optional spaces and comment
$''')
oprange_regexp = re.compile(r'^\w+(?:-\w+)?(?:,\w+(?:-\w+)?)*$')
class IGroup(object):
def __init__(self, name, ops):
self.name = name
self.ops = ops
self.imacros = []
class IMacro(object):
def __init__(self, name, filename):
self.name = name
self.offset = 0
self.code = []
self.labeldefs = {}
self.labeldef_indexes = {}
self.labelrefs = {}
self.filename = filename
self.depths = {}
self.initdepth = 0
class Instruction(object):
def __init__(self, offset, info, imm1, imm2, lineno):
self.offset = offset
self.info = info
self.imm1 = imm1
self.imm2 = imm2
self.lineno = lineno
def assemble(filename, outfile):
write = outfile.write
igroup = None
imacro = None
opcode2extra = {}
igroups = []
write("/* GENERATED BY imacro_asm.js -- DO NOT EDIT!!! */\n")
def fail(msg, *args):
raise ValueError("%s at %s:%d" % (msg % args, filename, lineno + 1))
for lineno, line in enumerate(readFileLines(filename)):
# strip comments
line = re.sub(r'#.*', '', line).rstrip()
if line == "":
continue
m = line_regexp.match(line)
if m is None:
fail(line)
label, opname, imm1, imm2 = m.groups()
if opname.startswith('.'):
if label is not None:
fail("invalid label %s before %s" % (label, opname))
if opname == '.igroup':
if imm1 is None:
fail("missing .igroup name")
if igroup is not None:
fail("nested .igroup " + imm1)
if oprange_regexp.match(imm2) is None:
fail("invalid igroup operator range " + imm2)
ops = set()
for current in imm2.split(","):
split = current.split('-')
opcode = jsop2opcode[split[0]]
if len(split) == 1:
lastopcode = opcode
else:
assert len(split) == 2
lastopcode = jsop2opcode[split[1]]
if opcode >= lastopcode:
fail("invalid opcode range: " + current)
for opcode in range(opcode, lastopcode + 1):
if opcode in ops:
fail("repeated opcode " + opinfo[opcode].jsop)
ops.add(opcode)
igroup = IGroup(imm1, ops)
elif opname == '.imacro':
if igroup is None:
fail(".imacro outside of .igroup")
if imm1 is None:
fail("missing .imacro name")
if imacro:
fail("nested .imacro " + imm1)
imacro = IMacro(imm1, filename)
elif opname == '.fixup':
if imacro is None:
fail(".fixup outside of .imacro")
if len(imacro.code) != 0:
fail(".fixup must be first item in .imacro")
if imm1 is None:
fail("missing .fixup argument")
try:
fixup = int(imm1)
except ValueError:
fail(".fixup argument must be a nonzero integer")
if fixup == 0:
fail(".fixup argument must be a nonzero integer")
if imacro.initdepth != 0:
fail("more than one .fixup in .imacro")
imacro.initdepth = fixup
elif opname == '.end':
if imacro is None:
if igroup is None:
fail(".end without prior .igroup or .imacro")
if imm1 is not None and (imm1 != igroup.name or imm2 is not None):
fail(".igroup/.end name mismatch")
maxdepth = 0
write("static struct {\n")
for imacro in igroup.imacros:
write(" jsbytecode %s[%d];\n" % (imacro.name, imacro.offset))
write("} %s_imacros = {\n" % igroup.name)
for imacro in igroup.imacros:
depth = 0
write(" {\n")
for op in imacro.code:
operand = ""
if op.imm1 is not None:
operand = ", " + immediate(op)
write("/*%2d*/ %s%s,\n" % (op.offset, op.info.jsop, operand))
imacro.maxdepth = imacro.initdepth
simulate_cfg(igroup, imacro, imacro.initdepth, 0)
if imacro.maxdepth > maxdepth:
maxdepth = imacro.maxdepth
write(" },\n")
write("};\n")
for opcode in igroup.ops:
opcode2extra[opcode] = maxdepth
igroups.append(igroup)
igroup = None
else:
assert igroup is not None
if imm1 is not None and imm1 != imacro.name:
fail(".imacro/.end name mismatch")
# Backpatch the forward references to labels that must now be defined.
for label in imacro.labelrefs:
if label not in imacro.labeldefs:
fail("label " + label + " used but not defined")
link = imacro.labelrefs[label]
assert link >= 0
while True:
op = imacro.code[link]
next = op.target
op.target = imacro.labeldefs[label] - op.offset
op.target_index = imacro.labeldef_indexes[label]
if next < 0:
break
link = next
igroup.imacros.append(imacro)
imacro = None
else:
fail("unknown pseudo-op " + opname)
continue
if opname not in opname2info:
fail("unknown opcode " + opname)
info = opname2info[opname]
if info.oplen == -1:
fail("unimplemented opcode " + opname)
if imacro is None:
fail("opcode %s outside of .imacro", opname)
# Blacklist ops that may or must use an atomized double immediate.
if info.opname in ('double', 'lookupswitch', 'lookupswitchx'):
fail(op.opname + " opcode not yet supported")
if label:
imacro.labeldefs[label] = imacro.offset
imacro.labeldef_indexes[label] = len(imacro.code)
op = Instruction(imacro.offset, info, imm1, imm2, lineno + 1)
if 'JOF_JUMP' in info.flags:
if imm1 in imacro.labeldefs:
# Backward reference can be resolved right away, no backpatching needed.
op.target = imacro.labeldefs[imm1] - op.offset
op.target_index = imacro.labeldef_indexes[imm1]
else:
# Link op into the .target-linked backpatch chain at labelrefs[imm1].
# The linked list terminates with a -1 sentinel.
if imm1 in imacro.labelrefs:
op.target = imacro.labelrefs[imm1]
else:
op.target = -1
imacro.labelrefs[imm1] = len(imacro.code)
imacro.code.append(op)
imacro.offset += info.oplen
write("uint8 js_opcode2extra[JSOP_LIMIT] = {\n")
for i in range(len(opinfo)):
write(" %d, /* %s */\n" % (opcode2extra.get(i, 0), opinfo[i].jsop))
write("};\n")
write("#define JSOP_IS_IMACOP(x) (0 \\\n")
for i in sorted(opcode2extra):
write(" || x == %s \\\n" % opinfo[i].jsop)
write(")\n")
write("jsbytecode*\njs_GetImacroStart(jsbytecode* pc) {\n")
for g in igroups:
for m in g.imacros:
start = g.name + "_imacros." + m.name
write(" if (size_t(pc - %s) < %d) return %s;\n" % (start, m.offset, start))
write(" return NULL;\n")
write("}\n")
if __name__ == '__main__':
import sys
if len(sys.argv) != 3:
print "usage: python imacro_asm.py infile.jsasm outfile.c.out"
sys.exit(1)
f = open(sys.argv[2], 'w')
try:
assemble(sys.argv[1], f)
finally:
f.close()

View File

@ -1,697 +0,0 @@
# -*- indent-tabs-mode: nil; -*-
# vim: set sw=4 ts=8 et tw=78 ft=asm:
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the TraceMonkey IMacro Assembler.
#
# The Initial Developer of the Original Code is
# Brendan Eich <brendan@mozilla.org>.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
.igroup equality JSOP_EQ-JSOP_NE
.imacro any_obj # any obj
dup # any obj obj
dup # any obj obj obj
getprop valueOf # any obj obj valueOf
ifcantcalltop 1 # any obj obj valueOf
swap # any obj valueOf obj
call 0 # any obj rval
ifcantcalltop 3 # any obj rval
pop # any obj
dup # any obj obj
goto 2
1: pop # any obj obj
2: callprop toString # any obj toString obj
call 0 # any obj rval
primtop (JSTYPE_NUMBER) # any obj rval
3: swap # any rval obj
pop # any rval
imacop # eqval
stop
.end
.imacro obj_any # obj any
swap # any obj
dup # any obj obj
dup # any obj obj obj
getprop valueOf # any obj obj valueOf
ifcantcalltop 1 # any obj obj valueOf
swap # any obj valueOf obj
call 0 # any obj lval
ifcantcalltop 3 # any obj lval
pop # any obj
dup # any obj obj
goto 2
1: pop # any obj obj
2: callprop toString # any obj toString obj
call 0 # any obj lval
primtop (JSTYPE_NUMBER) # any obj rval
3: swap # any lval obj
pop # any lval
swap # lval any
imacop # eqval
stop
.end
.end equality
# A single range, split up like so to test groups over multiple ranges of ops
.igroup binary JSOP_BITOR-JSOP_BITAND,JSOP_EQ-JSOP_DIV,JSOP_MOD
.imacro any_obj # any obj
dup # any obj obj
dup # any obj obj obj
getprop valueOf # any obj obj valueOf
ifcantcalltop 1 # any obj obj valueOf
swap # any obj valueOf obj
call 0 # any obj rval
ifcantcalltop 3 # any obj rval
pop # any obj
dup # any obj obj
goto 2
1: pop # any obj obj
2: callprop toString # any obj toString obj
call 0 # any obj rval
primtop (JSTYPE_NUMBER) # any obj rval
3: swap # any rval obj
pop # any rval
imacop # bval
stop
.end
.imacro obj_any # obj any
swap # any obj
dup # any obj obj
dup # any obj obj obj
getprop valueOf # any obj obj valueOf
ifcantcalltop 1 # any obj obj valueOf
swap # any obj valueOf obj
call 0 # any obj lval
ifcantcalltop 3 # any obj lval
pop # any obj
dup # any obj obj
goto 2
1: pop # any obj obj
2: callprop toString # any obj toString obj
call 0 # any obj lval
primtop (JSTYPE_NUMBER) # any obj lval
3: swap # any lval obj
pop # any lval
swap # lval any
imacop # bval
stop
.end
.imacro obj_obj # obj1 obj2
swap # obj2 obj1
dup # obj2 obj1 obj1
dup # obj2 obj1 obj1 obj1
getprop valueOf # obj2 obj1 obj1 valueOf
ifcantcalltop 1 # obj2 obj1 obj1 valueOf
swap # obj2 obj1 valueOf obj1
call 0 # obj2 obj1 lval
ifcantcalltop 3 # obj2 obj1 lval
pop # obj2 obj1
dup # obj2 obj1 obj1
goto 2
1: pop # obj2 obj1 obj1
2: callprop toString # obj2 obj1 toString obj1
call 0 # obj2 obj1 lval
primtop (JSTYPE_NUMBER) # obj2 obj1 lval
3: swap # obj2 lval obj1
pop # obj2 lval
swap # lval obj2
dup # lval obj1 obj1
dup # lval obj obj obj
getprop valueOf # lval obj obj valueOf
ifcantcalltop 4 # lval obj obj valueOf
swap # lval obj valueOf obj
call 0 # lval obj rval
ifcantcalltop 6 # lval obj rval
pop # lval obj
dup # lval obj obj
goto 5
4: pop # lval obj obj
5: callprop toString # lval obj toString obj
call 0 # lval obj rval
primtop (JSTYPE_NUMBER) # lval obj rval
6: swap # lval rval obj
pop # lval rval
imacop # bval
stop
.end
.end binary
.igroup add JSOP_ADD
.imacro any_obj # any obj
dup # any obj obj
dup # any obj obj obj
getprop valueOf # any obj obj valueOf
ifcantcalltop 1 # any obj obj valueOf
swap # any obj valueOf obj
call 0 # any obj rval
ifcantcalltop 3 # any obj rval
pop # any obj
dup # any obj obj
goto 2
1: pop # any obj obj
2: callprop toString # any obj toString obj
call 0 # any obj rval
primtop (JSTYPE_VOID) # any obj rval
3: swap # any rval obj
pop # any rval
add # aval
stop
.end
.imacro obj_any # obj any
swap # any obj
dup # any obj obj
dup # any obj obj obj
getprop valueOf # any obj obj valueOf
ifcantcalltop 1 # any obj obj valueOf
swap # any obj valueOf obj
call 0 # any obj lval
ifcantcalltop 3 # any obj lval
pop # any obj
dup # any obj obj
goto 2
1: pop # any obj obj
2: callprop toString # any obj toString obj
call 0 # any obj lval
primtop (JSTYPE_VOID) # any obj lval
3: swap # any lval obj
pop # any lval
swap # lval any
add # aval
stop
.end
.imacro obj_obj # obj1 obj2
swap # obj2 obj1
dup # obj2 obj1 obj1
dup # obj2 obj1 obj1 obj1
getprop valueOf # obj2 obj1 obj1 valueOf
ifcantcalltop 1 # obj2 obj1 obj1 valueOf
swap # obj2 obj1 valueOf obj1
call 0 # obj2 obj1 lval
ifcantcalltop 3 # obj2 obj1 lval
pop # obj2 obj1
dup # obj2 obj1 obj1
goto 2
1: pop # obj2 obj1 obj1
2: callprop toString # obj2 obj1 toString obj1
call 0 # obj2 obj1 lval
primtop (JSTYPE_VOID) # obj2 obj1 lval
3: swap # obj2 lval obj1
pop # obj2 lval
swap # lval obj2
dup # lval obj obj
dup # lval obj obj obj
getprop valueOf # lval obj obj valueOf
ifcantcalltop 4 # lval obj obj valueOf
swap # lval obj valueOf obj
call 0 # lval obj rval
ifcantcalltop 6 # lval obj rval
pop # lval obj
dup # lval obj obj
goto 5
4: pop # lval obj obj
5: callprop toString # lval obj toString obj
call 0 # lval obj rval
primtop (JSTYPE_VOID) # lval obj rval
6: swap # lval rval obj
pop # lval rval
add # aval
stop
.end
.end add
.igroup unary JSOP_NEG-JSOP_POS
.imacro sign # obj
dup # obj obj
dup # obj obj obj
getprop valueOf # obj obj valueOf
ifcantcalltop 2 # obj obj valueOf
swap # obj valueOf obj
call 0 # obj lval
ifcantcalltop 1 # obj lval
pop # obj
dup # obj obj
goto 3
1: swap # lval obj
pop # lval
goto 4
2: pop # obj obj
3: callprop toString # obj toString obj
call 0 # obj lval
primtop (JSTYPE_NUMBER) # obj lval
swap # lval obj
pop # lval
4: imacop # aval
stop
.end
.end unary
.igroup incelem JSOP_INCELEM,JSOP_ELEMINC
.imacro incelem # obj id
dup2 # obj id obj id
getelem # obj id val
pos # obj id n
one # obj id n 1
add # obj id m
setelem # m
stop
.end
.imacro eleminc # obj id
dup2 # obj id obj id
getelem # obj id val
pos # obj id n
dup # obj id n n
one # obj id n n 1
add # obj id n m
pick 3 # id n m obj
pick 3 # n m obj id
pick 2 # n obj id m
setelem # n m
pop # n
stop
.end
.end incelem
.igroup decelem JSOP_DECELEM,JSOP_ELEMDEC
.imacro decelem # obj id
dup2 # obj id obj id
getelem # obj id val
pos # obj id n
one # obj id n 1
sub # obj id m
setelem # m
stop
.end
.imacro elemdec # obj id
dup2 # obj id obj id
getelem # obj id val
pos # obj id n
dup # obj id n n
one # obj id n n 1
sub # obj id n m
pick 3 # id n m obj
pick 3 # n m obj id
pick 2 # n obj id m
setelem # n m
pop # n
stop
.end
.end decelem
.igroup call JSOP_CALL
.imacro String # String this obj
dup # String this obj obj
dup # String this obj obj obj
getprop toString # String this obj obj toString
ifcantcalltop 1 # String this obj obj toString
swap # String this obj toString obj
call 0 # String this obj rval
ifcantcalltop 3 # String this obj rval
pop # String this obj
dup # String this obj obj
goto 2
1: pop # String this obj obj
2: callprop valueOf # String this obj valueOf obj
call 0 # String this obj rval
primtop (JSTYPE_STRING) # String this obj rval
3: swap # String this rval obj
pop # String this rval
call 1 # str
stop # str
.end
.end call
.igroup new JSOP_NEW
.imacro String # String this obj
dup # String this obj obj
dup # String this obj obj obj
getprop toString # String this obj obj toString
ifcantcalltop 1 # String this obj obj toString
swap # String this obj toString obj
call 0 # String this obj rval
ifcantcalltop 3 # String this obj rval
pop # String this obj
dup # String this obj obj
goto 2
1: pop # String this obj obj
2: callprop valueOf # String this obj valueOf obj
call 0 # String this obj rval
primtop (JSTYPE_STRING) # String this obj rval
3: swap # String this rval obj
pop # String this rval
new 1 # strobj
stop # strobj
.end
.end new
.igroup funapply JSOP_FUNAPPLY
.imacro apply0 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
pop # fun this
call 0 #
stop #
.end #
.imacro apply1 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
pop # fun this arg0
call 1 #
stop #
.end #
.imacro apply2 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
dup # fun this arg0 arr arr
one # fun this arg0 arr arr 1
getelem # fun this arg0 arr arg1
swap # fun this arg0 arg1 arr
pop # fun this arg0 arg1
call 2 #
stop #
.end #
.imacro apply3 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
dup # fun this arg0 arr arr
one # fun this arg0 arr arr 1
getelem # fun this arg0 arr arg1
swap # fun this arg0 arg1 arr
dup # fun this arg0 arg1 arr arr
int8 2 # fun this arg0 arg1 arr arr 2
getelem # fun this arg0 arg1 arr arg2
swap # fun this arg0 arg1 arg2 arr
pop # fun this arg0 arg1 arg2
call 3 #
stop #
.end #
.imacro apply4 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
dup # fun this arg0 arr arr
one # fun this arg0 arr arr 1
getelem # fun this arg0 arr arg1
swap # fun this arg0 arg1 arr
dup # fun this arg0 arg1 arr arr
int8 2 # fun this arg0 arg1 arr arr 2
getelem # fun this arg0 arg1 arr arg2
swap # fun this arg0 arg1 arg2 arr
dup # fun this arg0 arg1 arg2 arr arr
int8 3 # fun this arg0 arg1 arg2 arr arr 3
getelem # fun this arg0 arg1 arg2 arr arg3
swap # fun this arg0 arg1 arg2 arg3 arr
pop # fun this arg0 arg1 arg2 arg3
call 4 #
stop #
.end #
.imacro apply5 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
dup # fun this arg0 arr arr
one # fun this arg0 arr arr 1
getelem # fun this arg0 arr arg1
swap # fun this arg0 arg1 arr
dup # fun this arg0 arg1 arr arr
int8 2 # fun this arg0 arg1 arr arr 2
getelem # fun this arg0 arg1 arr arg2
swap # fun this arg0 arg1 arg2 arr
dup # fun this arg0 arg1 arg2 arr arr
int8 3 # fun this arg0 arg1 arg2 arr arr 3
getelem # fun this arg0 arg1 arg2 arr arg3
swap # fun this arg0 arg1 arg2 arg3 arr
dup # fun this arg0 arg1 arg2 arg3 arr arr
int8 4 # fun this arg0 arg1 arg2 arg3 arr arr 4
getelem # fun this arg0 arg1 arg2 arg3 arr arg4
swap # fun this arg0 arg1 arg2 arg3 arg4 arr
pop # fun this arg0 arg1 arg2 arg3 arg4
call 5 #
stop #
.end #
.imacro apply6 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
dup # fun this arg0 arr arr
one # fun this arg0 arr arr 1
getelem # fun this arg0 arr arg1
swap # fun this arg0 arg1 arr
dup # fun this arg0 arg1 arr arr
int8 2 # fun this arg0 arg1 arr arr 2
getelem # fun this arg0 arg1 arr arg2
swap # fun this arg0 arg1 arg2 arr
dup # fun this arg0 arg1 arg2 arr arr
int8 3 # fun this arg0 arg1 arg2 arr arr 3
getelem # fun this arg0 arg1 arg2 arr arg3
swap # fun this arg0 arg1 arg2 arg3 arr
dup # fun this arg0 arg1 arg2 arg3 arr arr
int8 4 # fun this arg0 arg1 arg2 arg3 arr arr 4
getelem # fun this arg0 arg1 arg2 arg3 arr arg4
swap # fun this arg0 arg1 arg2 arg3 arg4 arr
dup # fun this arg0 arg1 arg2 arg3 arg4 arr arr
int8 5 # fun this arg0 arg1 arg2 arg3 arg4 arr arr 5
getelem # fun this arg0 arg1 arg2 arg3 arg4 arr arg5
swap # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr
pop # fun this arg0 arg1 arg2 arg3 arg4 arg5
call 6 #
stop #
.end #
.imacro apply7 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
dup # fun this arg0 arr arr
one # fun this arg0 arr arr 1
getelem # fun this arg0 arr arg1
swap # fun this arg0 arg1 arr
dup # fun this arg0 arg1 arr arr
int8 2 # fun this arg0 arg1 arr arr 2
getelem # fun this arg0 arg1 arr arg2
swap # fun this arg0 arg1 arg2 arr
dup # fun this arg0 arg1 arg2 arr arr
int8 3 # fun this arg0 arg1 arg2 arr arr 3
getelem # fun this arg0 arg1 arg2 arr arg3
swap # fun this arg0 arg1 arg2 arg3 arr
dup # fun this arg0 arg1 arg2 arg3 arr arr
int8 4 # fun this arg0 arg1 arg2 arg3 arr arr 4
getelem # fun this arg0 arg1 arg2 arg3 arr arg4
swap # fun this arg0 arg1 arg2 arg3 arg4 arr
dup # fun this arg0 arg1 arg2 arg3 arg4 arr arr
int8 5 # fun this arg0 arg1 arg2 arg3 arg4 arr arr 5
getelem # fun this arg0 arg1 arg2 arg3 arg4 arr arg5
swap # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr
dup # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr
int8 6 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr 6
getelem # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arg6
swap # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr
pop # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6
call 7 #
stop #
.end #
.imacro apply8 # apply fun this arr
pick 3 # fun this arr apply
pop # fun this arr
dup # fun this arr arr
zero # fun this arr arr 0
getelem # fun this arr arg0
swap # fun this arg0 arr
dup # fun this arg0 arr arr
one # fun this arg0 arr arr 1
getelem # fun this arg0 arr arg1
swap # fun this arg0 arg1 arr
dup # fun this arg0 arg1 arr arr
int8 2 # fun this arg0 arg1 arr arr 2
getelem # fun this arg0 arg1 arr arg2
swap # fun this arg0 arg1 arg2 arr
dup # fun this arg0 arg1 arg2 arr arr
int8 3 # fun this arg0 arg1 arg2 arr arr 3
getelem # fun this arg0 arg1 arg2 arr arg3
swap # fun this arg0 arg1 arg2 arg3 arr
dup # fun this arg0 arg1 arg2 arg3 arr arr
int8 4 # fun this arg0 arg1 arg2 arg3 arr arr 4
getelem # fun this arg0 arg1 arg2 arg3 arr arg4
swap # fun this arg0 arg1 arg2 arg3 arg4 arr
dup # fun this arg0 arg1 arg2 arg3 arg4 arr arr
int8 5 # fun this arg0 arg1 arg2 arg3 arg4 arr arr 5
getelem # fun this arg0 arg1 arg2 arg3 arg4 arr arg5
swap # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr
dup # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr
int8 6 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arr 6
getelem # fun this arg0 arg1 arg2 arg3 arg4 arg5 arr arg6
swap # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr
dup # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr arr
int8 7 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr arr 7
getelem # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arr arg7
swap # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7 arr
pop # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7
call 8 #
stop #
.end #
.end funapply
.igroup funcall JSOP_FUNCALL
.imacro call0 # call fun
swap # fun call
pop # fun
null # fun this
call 0 #
stop #
.end #
.imacro call1 # call fun this
pick 2 # fun this call
pop # fun this
call 0 #
stop #
.end #
.imacro call2 # call fun this arg0
pick 3 # fun this arg0 call
pop # fun this arg0
call 1 #
stop #
.end #
.imacro call3 # call fun this arg0 arg1
pick 4 # fun this arg0 arg1 call
pop # fun this arg0 arg1
call 2 #
stop #
.end #
.imacro call4 # call fun this arg0 arg1 arg2
pick 5 # fun this arg0 arg1 arg2 call
pop # fun this arg0 arg1 arg2
call 3 #
stop #
.end #
.imacro call5 # call fun this arg0 arg1 arg2 arg3
pick 6 # fun this arg0 arg1 arg2 arg3 call
pop # fun this arg0 arg1 arg2 arg3
call 4 #
stop #
.end #
.imacro call6 # call fun this arg0 arg1 arg2 arg3 arg4
pick 7 # fun this arg0 arg1 arg2 arg3 arg4 call
pop # fun this arg0 arg1 arg2 arg3 arg4
call 5 #
stop #
.end #
.imacro call7 # call fun this arg0 arg1 arg2 arg3 arg4 arg5
pick 8 # fun this arg0 arg1 arg2 arg3 arg4 arg5 call
pop # fun this arg0 arg1 arg2 arg3 arg4 arg5
call 6 #
stop #
.end #
.imacro call8 # call fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6
pick 9 # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6 call
pop # fun this arg0 arg1 arg2 arg3 arg4 arg5 arg6
call 7 #
stop #
.end #
.end funcall
.igroup getprop JSOP_GETPROP
.imacro scriptgetter # obj
.fixup +1 # getter obj
call 0 # val
stop
.end
.end getprop
.igroup callprop JSOP_CALLPROP
.imacro scriptgetter # obj
.fixup +2 # obj getter obj
call 0 # obj method
swap # method obj
stop
.end
.end callprop

View File

@ -356,7 +356,7 @@ def parse_jitflags():
for flags in OPTIONS.jitflags.split(',') ] for flags in OPTIONS.jitflags.split(',') ]
for flags in jitflags: for flags in jitflags:
for flag in flags: for flag in flags:
if flag not in ('-j', '-m', '-a', '-p', '-d', '-n'): if flag not in ('-m', '-a', '-p', '-d', '-n'):
print('Invalid jit flag: "%s"'%flag) print('Invalid jit flag: "%s"'%flag)
sys.exit(1) sys.exit(1)
return jitflags return jitflags
@ -420,8 +420,8 @@ def main(argv):
help='Enable the |valgrind| flag, if valgrind is in $PATH.') help='Enable the |valgrind| flag, if valgrind is in $PATH.')
op.add_option('--valgrind-all', dest='valgrind_all', action='store_true', op.add_option('--valgrind-all', dest='valgrind_all', action='store_true',
help='Run all tests with valgrind, if valgrind is in $PATH.') help='Run all tests with valgrind, if valgrind is in $PATH.')
op.add_option('--jitflags', dest='jitflags', default='mjp', op.add_option('--jitflags', dest='jitflags', default='m,mn',
help='Example: --jitflags=j,mj,mjp to run each test with -j, -m -j, -m -j -p [default=%default]') help='Example: --jitflags=m,mn to run each test with -m, -m -n [default=%default]')
op.add_option('--avoid-stdio', dest='avoid_stdio', action='store_true', op.add_option('--avoid-stdio', dest='avoid_stdio', action='store_true',
help='Use js-shell file indirection instead of piping stdio.') help='Use js-shell file indirection instead of piping stdio.')
op.add_option('--write-failure-output', dest='write_failure_output', action='store_true', op.add_option('--write-failure-output', dest='write_failure_output', action='store_true',

View File

@ -91,9 +91,8 @@
#undef JS_INTPTR_TYPE #undef JS_INTPTR_TYPE
#undef JS_BYTES_PER_WORD #undef JS_BYTES_PER_WORD
/* Some mozilla code uses JS-friend APIs that depend on JS_TRACER and /* Some mozilla code uses JS-friend APIs that depend on JS_METHODJIT being
JS_METHODJIT being correct. */ correct. */
#undef JS_TRACER
#undef JS_METHODJIT #undef JS_METHODJIT
#endif /* js_config_h___ */ #endif /* js_config_h___ */

View File

@ -2,8 +2,6 @@
#include "jsfun.h" #include "jsfun.h"
#include "jscntxt.h" #include "jscntxt.h"
// For TRACING_ENABLED
#include "jstracer.h"
#include "jsobjinlines.h" #include "jsobjinlines.h"
#ifdef MOZ_TRACE_JSCALLS #ifdef MOZ_TRACE_JSCALLS
@ -103,15 +101,6 @@ BEGIN_TEST(testFuncCallback_bug507012)
CHECK_EQUAL(leaves, 1+50); CHECK_EQUAL(leaves, 1+50);
CHECK_EQUAL(depth, 0); CHECK_EQUAL(depth, 0);
// If this fails, it means that the code was interpreted rather
// than trace-JITted, and so is not testing what it's supposed to
// be testing. Which doesn't necessarily imply that the
// functionality is broken.
#ifdef JS_TRACER
if (TRACING_ENABLED(cx))
CHECK(interpreted < enters);
#endif
// Test nesting callbacks via JS_GetFunctionCallback() // Test nesting callbacks via JS_GetFunctionCallback()
JS_SetFunctionCallback(cx, funcTransition); JS_SetFunctionCallback(cx, funcTransition);
innerCallback = JS_GetFunctionCallback(cx); innerCallback = JS_GetFunctionCallback(cx);

View File

@ -56,7 +56,6 @@
#include "jsarray.h" #include "jsarray.h"
#include "jsatom.h" #include "jsatom.h"
#include "jsbool.h" #include "jsbool.h"
#include "jsbuiltins.h"
#include "jsclone.h" #include "jsclone.h"
#include "jscntxt.h" #include "jscntxt.h"
#include "jsversion.h" #include "jsversion.h"
@ -78,7 +77,6 @@
#include "jsscope.h" #include "jsscope.h"
#include "jsscript.h" #include "jsscript.h"
#include "jsstr.h" #include "jsstr.h"
#include "jstracer.h"
#include "prmjtime.h" #include "prmjtime.h"
#include "jsweakmap.h" #include "jsweakmap.h"
#include "jswrapper.h" #include "jswrapper.h"
@ -657,6 +655,7 @@ JSRuntime::JSRuntime()
gcMaxBytes(0), gcMaxBytes(0),
gcMaxMallocBytes(0), gcMaxMallocBytes(0),
gcEmptyArenaPoolLifespan(0), gcEmptyArenaPoolLifespan(0),
gcNumFreeArenas(0),
gcNumber(0), gcNumber(0),
gcIncrementalTracer(NULL), gcIncrementalTracer(NULL),
gcVerifyData(NULL), gcVerifyData(NULL),
@ -751,10 +750,6 @@ JSRuntime::init(uint32 maxbytes)
JMCheckLogging(); JMCheckLogging();
#endif #endif
#ifdef JS_TRACER
InitJIT();
#endif
if (!js_InitGC(this, maxbytes)) if (!js_InitGC(this, maxbytes))
return false; return false;
@ -813,10 +808,6 @@ JSRuntime::~JSRuntime()
} }
#endif #endif
#ifdef JS_TRACER
FinishJIT();
#endif
FinishRuntimeNumberState(this); FinishRuntimeNumberState(this);
js_FinishThreads(this); js_FinishThreads(this);
js_FinishAtomState(this); js_FinishAtomState(this);
@ -917,10 +908,6 @@ JS_ShutDown(void)
{ {
Probes::shutdown(); Probes::shutdown();
#ifdef MOZ_TRACEVIS
StopTraceVis();
#endif
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
js_CleanupLocks(); js_CleanupLocks();
#endif #endif
@ -983,8 +970,6 @@ StopRequest(JSContext *cx)
if (t->data.requestDepth != 1) { if (t->data.requestDepth != 1) {
t->data.requestDepth--; t->data.requestDepth--;
} else { } else {
LeaveTrace(cx); /* for GC safety */
t->data.conservativeGC.updateForRequestEnd(t->suspendCount); t->data.conservativeGC.updateForRequestEnd(t->suspendCount);
/* Lock before clearing to interlock with ClaimScope, in jslock.c. */ /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
@ -2747,8 +2732,6 @@ JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
/* We cannot GC the atoms compartment alone; use a full GC instead. */ /* We cannot GC the atoms compartment alone; use a full GC instead. */
JS_ASSERT(comp != cx->runtime->atomsCompartment); JS_ASSERT(comp != cx->runtime->atomsCompartment);
LeaveTrace(cx);
js::gc::VerifyBarriers(cx, true); js::gc::VerifyBarriers(cx, true);
js_GC(cx, comp, GC_NORMAL, gcstats::PUBLIC_API); js_GC(cx, comp, GC_NORMAL, gcstats::PUBLIC_API);
} }
@ -2762,8 +2745,6 @@ JS_GC(JSContext *cx)
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_MaybeGC(JSContext *cx) JS_MaybeGC(JSContext *cx)
{ {
LeaveTrace(cx);
MaybeGC(cx); MaybeGC(cx);
} }
@ -2842,29 +2823,18 @@ JS_PUBLIC_API(void)
JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32 value) JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32 value)
{ {
JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES); JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
#ifdef JS_TRACER
SetMaxCodeCacheBytes(cx, value);
#endif
} }
JS_PUBLIC_API(uint32) JS_PUBLIC_API(uint32)
JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key) JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
{ {
JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES); JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
#ifdef JS_TRACER
return JS_THREAD_DATA(cx)->maxCodeCacheBytes;
#else
return 0; return 0;
#endif
} }
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_FlushCaches(JSContext *cx) JS_FlushCaches(JSContext *cx)
{ {
#ifdef JS_TRACER
if (cx->compartment->hasTraceMonitor())
FlushJITCache(cx, cx->compartment->traceMonitor());
#endif
} }
JS_PUBLIC_API(intN) JS_PUBLIC_API(intN)
@ -4527,14 +4497,7 @@ js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
/* Clear the last parameter in case too few arguments were passed. */ /* Clear the last parameter in case too few arguments were passed. */
vp[2 + --argc].setUndefined(); vp[2 + --argc].setUndefined();
Native native = return fs->call(cx, argc, vp);
#ifdef JS_TRACER
(fs->flags & JSFUN_TRCINFO)
? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, fs->call)->native
:
#endif
fs->call;
return native(cx, argc, vp);
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
@ -4570,7 +4533,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
fun = js_DefineFunction(cx, ctor, ATOM_TO_JSID(atom), fun = js_DefineFunction(cx, ctor, ATOM_TO_JSID(atom),
js_generic_native_method_dispatcher, js_generic_native_method_dispatcher,
fs->nargs + 1, fs->nargs + 1,
flags & ~JSFUN_TRCINFO); flags);
if (!fun) if (!fun)
return JS_FALSE; return JS_FALSE;
@ -5325,10 +5288,6 @@ JS_IsRunning(JSContext *cx)
return false; return false;
#endif #endif
#ifdef JS_TRACER
JS_ASSERT_IF(JS_ON_TRACE(cx) && JS_TRACE_MONITOR_ON_TRACE(cx)->tracecx == cx, cx->hasfp());
#endif
StackFrame *fp = cx->maybefp(); StackFrame *fp = cx->maybefp();
while (fp && fp->isDummyFrame()) while (fp && fp->isDummyFrame())
fp = fp->prev(); fp = fp->prev();
@ -5339,7 +5298,6 @@ JS_PUBLIC_API(JSBool)
JS_SaveFrameChain(JSContext *cx) JS_SaveFrameChain(JSContext *cx)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
LeaveTrace(cx);
return cx->stack.saveFrameChain(); return cx->stack.saveFrameChain();
} }
@ -5347,7 +5305,6 @@ JS_PUBLIC_API(void)
JS_RestoreFrameChain(JSContext *cx) JS_RestoreFrameChain(JSContext *cx)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
JS_ASSERT_NOT_ON_TRACE(cx);
cx->stack.restoreFrameChain(); cx->stack.restoreFrameChain();
} }

View File

@ -2157,7 +2157,7 @@ JS_StringToVersion(const char *string);
of the input string */ of the input string */
/* JS_BIT(10) is currently unused. */ /* JS_BIT(10) is currently unused. */
#define JSOPTION_JIT JS_BIT(11) /* Enable JIT compilation. */ #define JSOPTION_JIT JS_BIT(11) /* Deprecated; does nothing */
#define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12) /* A promise to the compiler #define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12) /* A promise to the compiler
that a null rval out-param that a null rval out-param

View File

@ -110,7 +110,6 @@
#include "jsarray.h" #include "jsarray.h"
#include "jsatom.h" #include "jsatom.h"
#include "jsbool.h" #include "jsbool.h"
#include "jsbuiltins.h"
#include "jscntxt.h" #include "jscntxt.h"
#include "jsversion.h" #include "jsversion.h"
#include "jsfun.h" #include "jsfun.h"
@ -123,7 +122,6 @@
#include "jsobj.h" #include "jsobj.h"
#include "jsscope.h" #include "jsscope.h"
#include "jsstr.h" #include "jsstr.h"
#include "jstracer.h"
#include "jswrapper.h" #include "jswrapper.h"
#include "methodjit/MethodJIT.h" #include "methodjit/MethodJIT.h"
#include "methodjit/StubCalls.h" #include "methodjit/StubCalls.h"
@ -507,25 +505,6 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, const Value &v)
return obj->setGeneric(cx, idr.id(), &tmp, true); return obj->setGeneric(cx, idr.id(), &tmp, true);
} }
#ifdef JS_TRACER
JSBool JS_FASTCALL
js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i)
{
#ifdef DEBUG
Class *origObjClasp = obj->getClass();
#endif
jsuint u = jsuint(i);
JSBool ret = (obj->ensureDenseArrayElements(cx, u, 1) == JSObject::ED_OK);
/* Partially check the CallInfo's storeAccSet is correct. */
JS_ASSERT(obj->getClass() == origObjClasp);
return ret;
}
/* This function and its callees do not touch any object's .clasp field. */
JS_DEFINE_CALLINFO_3(extern, BOOL, js_EnsureDenseArrayCapacity, CONTEXT, OBJECT, INT32,
0, nanojit::ACCSET_STORE_ANY & ~tjit::ACCSET_OBJ_CLASP)
#endif
/* /*
* Delete the element |index| from |obj|. If |strict|, do a strict * Delete the element |index| from |obj|. If |strict|, do a strict
* deletion: throw if the property is not configurable. * deletion: throw if the property is not configurable.
@ -1718,7 +1697,6 @@ array_toString(JSContext *cx, uintN argc, Value *vp)
return true; return true;
} }
LeaveTrace(cx);
InvokeArgsGuard ag; InvokeArgsGuard ag;
if (!cx->stack.pushInvokeArgs(cx, 0, &ag)) if (!cx->stack.pushInvokeArgs(cx, 0, &ag))
return false; return false;
@ -1770,16 +1748,22 @@ InitArrayTypes(JSContext *cx, TypeObject *type, const Value *vector, unsigned co
return true; return true;
} }
static JSBool enum ShouldUpdateTypes
InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, const Value *vector, bool updateTypes) {
UpdateTypes = true,
DontUpdateTypes = false
};
static bool
InitArrayElements(JSContext *cx, JSObject *obj, uint32 start, uint32 count, const Value *vector, ShouldUpdateTypes updateTypes)
{ {
JS_ASSERT(count <= MAX_ARRAY_INDEX); JS_ASSERT(count <= MAX_ARRAY_INDEX);
if (count == 0) if (count == 0)
return JS_TRUE; return true;
if (updateTypes && !InitArrayTypes(cx, obj->getType(cx), vector, count)) if (updateTypes && !InitArrayTypes(cx, obj->getType(cx), vector, count))
return JS_FALSE; return false;
/* /*
* Optimize for dense arrays so long as adding the given set of elements * Optimize for dense arrays so long as adding the given set of elements
@ -1812,16 +1796,16 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, cons
while (vector < end && start <= MAX_ARRAY_INDEX) { while (vector < end && start <= MAX_ARRAY_INDEX) {
if (!JS_CHECK_OPERATION_LIMIT(cx) || if (!JS_CHECK_OPERATION_LIMIT(cx) ||
!SetArrayElement(cx, obj, start++, *vector++)) { !SetArrayElement(cx, obj, start++, *vector++)) {
return JS_FALSE; return false;
} }
} }
if (vector == end) if (vector == end)
return JS_TRUE; return true;
/* Finish out any remaining elements past the max array index. */ /* Finish out any remaining elements past the max array index. */
if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx)) if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx))
return JS_FALSE; return false;
JS_ASSERT(start == MAX_ARRAY_INDEX + 1); JS_ASSERT(start == MAX_ARRAY_INDEX + 1);
AutoValueRooter tvr(cx); AutoValueRooter tvr(cx);
@ -1831,12 +1815,12 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, cons
*tvr.addr() = *vector++; *tvr.addr() = *vector++;
if (!js_ValueToStringId(cx, idval, idr.addr()) || if (!js_ValueToStringId(cx, idval, idr.addr()) ||
!obj->setGeneric(cx, idr.id(), tvr.addr(), true)) { !obj->setGeneric(cx, idr.id(), tvr.addr(), true)) {
return JS_FALSE; return false;
} }
idval.getDoubleRef() += 1; idval.getDoubleRef() += 1;
} while (vector != end); } while (vector != end);
return JS_TRUE; return true;
} }
#if 0 #if 0
@ -2240,7 +2224,7 @@ js::array_sort(JSContext *cx, uintN argc, Value *vp)
* InitArrayElements easier. * InitArrayElements easier.
*/ */
vec.resize(n); vec.resize(n);
if (!InitArrayElements(cx, obj, 0, jsuint(n), vec.begin(), false)) if (!InitArrayElements(cx, obj, 0, jsuint(n), vec.begin(), DontUpdateTypes))
return false; return false;
} }
@ -2270,7 +2254,7 @@ array_push_slowly(JSContext *cx, JSObject *obj, CallArgs &args)
if (!js_GetLengthProperty(cx, obj, &length)) if (!js_GetLengthProperty(cx, obj, &length))
return false; return false;
if (!InitArrayElements(cx, obj, length, args.length(), args.array(), true)) if (!InitArrayElements(cx, obj, length, args.length(), args.array(), UpdateTypes))
return false; return false;
/* Per ECMA-262, return the new array length. */ /* Per ECMA-262, return the new array length. */
@ -2333,23 +2317,6 @@ js_NewbornArrayPush(JSContext *cx, JSObject *obj, const Value &vp)
return NewbornArrayPushImpl(cx, obj, vp); return NewbornArrayPushImpl(cx, obj, vp);
} }
#ifdef JS_TRACER
JSBool JS_FASTCALL
js_NewbornArrayPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
{
TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
if (!NewbornArrayPushImpl(cx, obj, ValueArgToConstRef(v))) {
SetBuiltinError(tm);
return JS_FALSE;
}
return WasBuiltinSuccessful(tm);
}
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_NewbornArrayPush_tn, CONTEXT, OBJECT,
VALUE, 0, nanojit::ACCSET_STORE_ANY)
#endif
JSBool JSBool
js::array_push(JSContext *cx, uintN argc, Value *vp) js::array_push(JSContext *cx, uintN argc, Value *vp)
{ {
@ -2436,7 +2403,6 @@ mjit::stubs::ArrayShift(VMFrame &f)
{ {
JSObject *obj = &f.regs.sp[-1].toObject(); JSObject *obj = &f.regs.sp[-1].toObject();
JS_ASSERT(obj->isDenseArray()); JS_ASSERT(obj->isDenseArray());
JS_ASSERT(!js_PrototypeHasIndexedProperties(f.cx, obj));
/* /*
* At this point the length and initialized length have already been * At this point the length and initialized length have already been
@ -2555,7 +2521,7 @@ array_unshift(JSContext *cx, uintN argc, Value *vp)
} }
/* Copy from args to the bottom of the array. */ /* Copy from args to the bottom of the array. */
if (!InitArrayElements(cx, obj, 0, args.length(), args.array(), true)) if (!InitArrayElements(cx, obj, 0, args.length(), args.array(), UpdateTypes))
return JS_FALSE; return JS_FALSE;
newlen += args.length(); newlen += args.length();
@ -3753,19 +3719,6 @@ NewDenseCopiedArray(JSContext *cx, uint32 length, const Value *vp, JSObject *pro
return obj; return obj;
} }
#ifdef JS_TRACER
JS_DEFINE_CALLINFO_2(extern, OBJECT, NewDenseEmptyArray, CONTEXT, OBJECT, 0,
nanojit::ACCSET_STORE_ANY)
JS_DEFINE_CALLINFO_3(extern, OBJECT, NewDenseAllocatedArray, CONTEXT, UINT32, OBJECT, 0,
nanojit::ACCSET_STORE_ANY)
JS_DEFINE_CALLINFO_3(extern, OBJECT, NewDenseAllocatedEmptyArray, CONTEXT, UINT32, OBJECT, 0,
nanojit::ACCSET_STORE_ANY)
JS_DEFINE_CALLINFO_3(extern, OBJECT, NewDenseUnallocatedArray, CONTEXT, UINT32, OBJECT, 0,
nanojit::ACCSET_STORE_ANY)
#endif
JSObject * JSObject *
NewSlowEmptyArray(JSContext *cx) NewSlowEmptyArray(JSContext *cx)
{ {

View File

@ -1,330 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Andreas Gal <gal@mozilla.com>
*
* Contributor(s):
* Brendan Eich <brendan@mozilla.org>
* Mike Shaver <shaver@mozilla.org>
* David Anderson <danderson@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <math.h>
#include "jsapi.h"
#include "jsstdint.h"
#include "jsarray.h"
#include "jsbool.h"
#include "jscntxt.h"
#include "jsgc.h"
#include "jsiter.h"
#include "jsnum.h"
#include "jslibmath.h"
#include "jsmath.h"
#include "jsnum.h"
#include "prmjtime.h"
#include "jsdate.h"
#include "jsscope.h"
#include "jsstr.h"
#include "jsbuiltins.h"
#include "jstracer.h"
#include "jsatominlines.h"
#include "jscntxtinlines.h"
#include "jsnuminlines.h"
#include "jsobjinlines.h"
#include "jsscopeinlines.h"
using namespace avmplus;
using namespace nanojit;
using namespace js;
JS_FRIEND_API(void)
js_SetTraceableNativeFailed(JSContext *cx)
{
/*
* We might not be on trace (we might have deep bailed) so we hope
* cx->compartment is correct.
*/
SetBuiltinError(JS_TRACE_MONITOR_FROM_CONTEXT(cx));
}
/*
* NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
* Do not use bool FASTCALL, use JSBool only!
*/
jsdouble FASTCALL
js_dmod(jsdouble a, jsdouble b)
{
if (b == 0.0) {
jsdpun u;
u.s.hi = JSDOUBLE_HI32_NAN;
u.s.lo = JSDOUBLE_LO32_NAN;
return u.d;
}
return js_fmod(a, b);
}
JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_dmod, DOUBLE, DOUBLE, 1, ACCSET_NONE)
int32 FASTCALL
js_imod(int32 a, int32 b)
{
if (a < 0 || b <= 0)
return -1;
int r = a % b;
return r;
}
JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, ACCSET_NONE)
#if JS_BITS_PER_WORD == 32
jsdouble FASTCALL
js_UnboxNumberAsDouble(uint32 tag, uint32 payload)
{
if (tag == JSVAL_TAG_INT32)
return (double)(int32)payload;
JS_ASSERT(tag <= JSVAL_TAG_CLEAR);
jsval_layout l;
l.s.tag = (JSValueTag)tag;
l.s.payload.u32 = payload;
return l.asDouble;
}
JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_UnboxNumberAsDouble, UINT32, UINT32, 1, ACCSET_NONE)
int32 FASTCALL
js_UnboxNumberAsInt32(uint32 tag, uint32 payload)
{
if (tag == JSVAL_TAG_INT32)
return (int32)payload;
JS_ASSERT(tag <= JSVAL_TAG_CLEAR);
jsval_layout l;
l.s.tag = (JSValueTag)tag;
l.s.payload.u32 = payload;
return js_DoubleToECMAInt32(l.asDouble);
}
JS_DEFINE_CALLINFO_2(extern, INT32, js_UnboxNumberAsInt32, UINT32, UINT32, 1, ACCSET_NONE)
#elif JS_BITS_PER_WORD == 64
jsdouble FASTCALL
js_UnboxNumberAsDouble(Value v)
{
if (v.isInt32())
return (jsdouble)v.toInt32();
JS_ASSERT(v.isDouble());
return v.toDouble();
}
JS_DEFINE_CALLINFO_1(extern, DOUBLE, js_UnboxNumberAsDouble, JSVAL, 1, ACCSET_NONE)
int32 FASTCALL
js_UnboxNumberAsInt32(Value v)
{
if (v.isInt32())
return v.toInt32();
JS_ASSERT(v.isDouble());
return js_DoubleToECMAInt32(v.toDouble());
}
JS_DEFINE_CALLINFO_1(extern, INT32, js_UnboxNumberAsInt32, VALUE, 1, ACCSET_NONE)
#endif
int32 FASTCALL
js_DoubleToInt32(jsdouble d)
{
return js_DoubleToECMAInt32(d);
}
JS_DEFINE_CALLINFO_1(extern, INT32, js_DoubleToInt32, DOUBLE, 1, ACCSET_NONE)
uint32 FASTCALL
js_DoubleToUint32(jsdouble d)
{
return js_DoubleToECMAUint32(d);
}
JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, ACCSET_NONE)
/*
* js_StringToNumber and js_StringToInt32 store into their second argument, so
* they need to be annotated accordingly. To be future-proof, we use
* ACCSET_STORE_ANY so that new callers don't have to remember to update the
* annotation.
*/
jsdouble FASTCALL
js_StringToNumber(JSContext* cx, JSString* str, JSBool *ok)
{
double out = 0; /* silence warnings. */
*ok = StringToNumberType<jsdouble>(cx, str, &out);
return out;
}
JS_DEFINE_CALLINFO_3(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, BOOLPTR,
0, ACCSET_STORE_ANY)
int32 FASTCALL
js_StringToInt32(JSContext* cx, JSString* str, JSBool *ok)
{
int32 out = 0; /* silence warnings. */
*ok = StringToNumberType<int32>(cx, str, &out);
return out;
}
JS_DEFINE_CALLINFO_3(extern, INT32, js_StringToInt32, CONTEXT, STRING, BOOLPTR,
0, ACCSET_STORE_ANY)
/* Nb: it's always safe to set isDefinitelyAtom to false if you're unsure or don't know. */
static inline JSBool
AddPropertyHelper(JSContext* cx, JSObject* obj, Shape* shape, bool isDefinitelyAtom)
{
JS_ASSERT(shape->previous() == obj->lastProperty());
if (obj->nativeEmpty()) {
if (!obj->ensureClassReservedSlotsForEmptyObject(cx))
return false;
}
uint32 slot;
slot = shape->slot;
JS_ASSERT(slot == obj->slotSpan());
if (slot < obj->numSlots()) {
JS_ASSERT(obj->getSlot(slot).isUndefined());
} else {
if (!obj->allocSlot(cx, &slot))
return false;
JS_ASSERT(slot == shape->slot);
}
obj->extend(cx, shape, isDefinitelyAtom);
return !js_IsPropertyCacheDisabled(cx);
}
JSBool FASTCALL
js_AddProperty(JSContext* cx, JSObject* obj, Shape* shape)
{
return AddPropertyHelper(cx, obj, shape, /* isDefinitelyAtom = */false);
}
JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SHAPE, 0, ACCSET_STORE_ANY)
JSBool FASTCALL
js_AddAtomProperty(JSContext* cx, JSObject* obj, Shape* shape)
{
return AddPropertyHelper(cx, obj, shape, /* isDefinitelyAtom = */true);
}
JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddAtomProperty, CONTEXT, OBJECT, SHAPE, 0, ACCSET_STORE_ANY)
static JSBool
HasProperty(JSContext* cx, JSObject* obj, jsid id)
{
// Check that we know how the lookup op will behave.
for (JSObject* pobj = obj; pobj; pobj = pobj->getProto()) {
if (pobj->getOps()->lookupProperty)
return JS_NEITHER;
Class* clasp = pobj->getClass();
if (clasp->resolve != JS_ResolveStub && clasp != &StringClass)
return JS_NEITHER;
}
JSObject* obj2;
JSProperty* prop;
if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
return JS_NEITHER;
return prop != NULL;
}
JSBool FASTCALL
js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
{
JSAtom *atom = js_AtomizeString(cx, idstr);
if (!atom)
return JS_NEITHER;
return HasProperty(cx, obj, ATOM_TO_JSID(atom));
}
JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING,
0, ACCSET_STORE_ANY)
JSBool FASTCALL
js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
{
jsid id;
if (!js_Int32ToId(cx, index, &id))
return JS_NEITHER;
return HasProperty(cx, obj, id);
}
JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32,
0, ACCSET_STORE_ANY)
JSString* FASTCALL
js_TypeOfObject(JSContext* cx, JSObject* obj)
{
JS_ASSERT(obj);
return cx->runtime->atomState.typeAtoms[obj->typeOf(cx)];
}
JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, ACCSET_NONE)
JSString* FASTCALL
js_BooleanIntToString(JSContext *cx, int32 unboxed)
{
JS_ASSERT(uint32(unboxed) <= 1);
return cx->runtime->atomState.booleanAtoms[unboxed];
}
JS_DEFINE_CALLINFO_2(extern, STRING, js_BooleanIntToString, CONTEXT, INT32, 1, ACCSET_NONE)
JSObject* FASTCALL
js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* parent)
{
JS_ASSERT(funobj->isFunction());
JS_ASSERT(proto->isFunction());
JS_ASSERT(JS_ON_TRACE(cx));
JSFunction *fun = (JSFunction*) funobj;
JS_ASSERT(funobj->getFunctionPrivate() == fun);
types::TypeObject *type = proto->getNewType(cx);
if (!type)
return NULL;
JSObject* closure = js_NewGCObject(cx, gc::FINALIZE_OBJECT2);
if (!closure)
return NULL;
if (!closure->initSharingEmptyShape(cx, &FunctionClass, type, parent,
fun, gc::FINALIZE_OBJECT2)) {
return NULL;
}
return closure;
}
JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT, OBJECT,
0, ACCSET_STORE_ANY)

View File

@ -1,653 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
*
* Contributor(s):
* Jason Orendorff <jorendorff@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef jsbuiltins_h___
#define jsbuiltins_h___
#ifdef JS_TRACER
// nanojit.h includes windows.h, so undo the obnoxious #defines, if needed
#include "nanojit/nanojit.h"
#include "jswin.h"
#include "jsprvtd.h"
enum JSTNErrType { INFALLIBLE, FAIL_STATUS, FAIL_NULL, FAIL_NEG, FAIL_NEITHER };
enum {
JSTN_ERRTYPE_MASK = 0x07,
JSTN_UNBOX_AFTER = 0x08,
JSTN_MORE = 0x10,
JSTN_CONSTRUCTOR = 0x20,
JSTN_RETURN_NULLABLE_STR = 0x40,
JSTN_RETURN_NULLABLE_OBJ = 0x80
};
#define JSTN_ERRTYPE(jstn) ((jstn)->flags & JSTN_ERRTYPE_MASK)
/*
* Type describing a type specialization of a js::Native.
*
* |prefix| and |argtypes| declare what arguments should be passed to the
* native function. |prefix| can contain the following characters:
*
* 'C': a JSContext* argument
* 'T': |this| as a JSObject* argument (bails if |this| is not an object)
* 'S': |this| as a JSString* argument (bails if |this| is not a string)
* 'R': a JSRuntime* argument
* 'P': the pc as a jsbytecode*
* 'D': |this| as a number (jsdouble)
* 'f': the function being called, as a JSObject*
* 'p': the .prototype of the function, as a JSObject*
*
* The corresponding things will get passed as arguments to the builtin in
* reverse order (so TC means JSContext* as the first arg, and the
* JSObject* for |this| as the second arg).
*
* |argtypes| can contain the following characters:
* 'd': a number (double) argument
* 'i': an integer argument
* 's': a JSString* argument
* 'o': a JSObject* argument
* 'r': a JSObject* argument that is of class RegExpClass
* 'f': a JSObject* argument that is of class FunctionClass
* 'v': a value argument: on 32-bit, a Value*, on 64-bit, a jsval
*/
struct JSSpecializedNative {
const nanojit::CallInfo *builtin;
const char *prefix;
const char *argtypes;
uintN flags; /* JSTNErrType | JSTN_UNBOX_AFTER | JSTN_MORE |
JSTN_CONSTRUCTOR */
};
/*
* Type holding extra trace-specific information about a fast native.
*
* 'specializations' points to a static array of available specializations
* terminated by the lack of having the JSTN_MORE flag set.
*/
struct JSNativeTraceInfo {
js::Native native;
JSSpecializedNative *specializations;
};
/* Macros used by JS_DEFINE_CALLINFOn. */
#ifdef DEBUG
#define _JS_CI_NAME(op) ,#op
#else
#define _JS_CI_NAME(op)
#endif
#define _JS_I32_ARGTYPE nanojit::ARGTYPE_I
#define _JS_I32_RETTYPE nanojit::ARGTYPE_I
#define _JS_U64_ARGTYPE nanojit::ARGTYPE_Q
#define _JS_U64_RETTYPE nanojit::ARGTYPE_Q
#define _JS_F64_ARGTYPE nanojit::ARGTYPE_D
#define _JS_F64_RETTYPE nanojit::ARGTYPE_D
#define _JS_PTR_ARGTYPE nanojit::ARGTYPE_P
#define _JS_PTR_RETTYPE nanojit::ARGTYPE_P
struct ClosureVarInfo;
/*
* Supported types for builtin functions.
*
* Types with -- for the two string fields are not permitted as argument types
* in JS_DEFINE_TRCINFO.
*
* There are three kinds of traceable-native error handling.
*
* - If a traceable native's return type ends with _FAIL, it always runs to
* completion. It can either succeed or fail with an error or exception;
* on success, it may or may not stay on trace. There may be side effects
* in any case. If the call succeeds but bails off trace, we resume in the
* interpreter at the next opcode.
*
* _FAIL builtins indicate failure or bailing off trace by setting bits in
* cx->interpState->builtinStatus.
*
* - If a traceable native's return type contains _RETRY, it can either
* succeed, fail with a JS exception, or tell the caller to bail off trace
* and retry the call from the interpreter. The last case happens if the
* builtin discovers that it can't do its job without examining the JS
* stack, reentering the interpreter, accessing properties of the global
* object, etc.
*
* The builtin must detect the need to retry before committing any side
* effects. If a builtin can't do this, it must use a _FAIL return type
* instead of _RETRY.
*
* _RETRY builtins indicate failure with a special return value that
* depends on the return type:
*
* BOOL_RETRY: JS_NEITHER
* INT32_RETRY: any negative value
* STRING_RETRY: NULL
* OBJECT_RETRY_NULL: NULL
*
* _RETRY function calls are faster than _FAIL calls. Each _RETRY call
* saves two writes to tm->bailExit and a read from state->builtinStatus.
*
* - All other traceable natives are infallible (e.g. Date.now, Math.log).
*
* Special builtins known to the tracer can have their own idiosyncratic
* error codes.
*
* When a traceable native returns a value indicating failure, we fall off
* trace. If an exception is pending, it is thrown; otherwise, we assume the
* builtin had no side effects and retry the current bytecode in the
* interpreter.
*
* So a builtin must not return a value indicating failure after causing side
* effects (such as reporting an error), without setting an exception pending.
* The operation would be retried, despite the first attempt's observable
* effects.
*/
#define _JS_CTYPE(ctype, size, pch, ach, flags) (ctype, size, pch, ach, flags)
#define _JS_CTYPE_CONTEXT _JS_CTYPE(JSContext *, _JS_PTR,"C", "", INFALLIBLE)
#define _JS_CTYPE_RUNTIME _JS_CTYPE(JSRuntime *, _JS_PTR,"R", "", INFALLIBLE)
#define _JS_CTYPE_MATHCACHE _JS_CTYPE(js::MathCache *, _JS_PTR,"M", "", INFALLIBLE)
#define _JS_CTYPE_THIS _JS_CTYPE(JSObject *, _JS_PTR,"T", "", INFALLIBLE)
#define _JS_CTYPE_THIS_DOUBLE _JS_CTYPE(jsdouble, _JS_F64,"D", "", INFALLIBLE)
#define _JS_CTYPE_THIS_STRING _JS_CTYPE(JSString *, _JS_PTR,"S", "", INFALLIBLE)
#define _JS_CTYPE_CALLEE _JS_CTYPE(JSObject *, _JS_PTR,"f", "", INFALLIBLE)
#define _JS_CTYPE_CALLEE_PROTOTYPE _JS_CTYPE(JSObject *, _JS_PTR,"p", "", INFALLIBLE)
#define _JS_CTYPE_FUNCTION _JS_CTYPE(JSFunction *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_PC _JS_CTYPE(jsbytecode *, _JS_PTR,"P", "", INFALLIBLE)
#define _JS_CTYPE_VALUEPTR _JS_CTYPE(js::Value *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CVALUEPTR _JS_CTYPE(const js::Value *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_JSID _JS_CTYPE(jsid, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_JSVAL _JS_CTYPE(js::Value, _JS_U64, --, --, INFALLIBLE)
#define _JS_CTYPE_BOOL _JS_CTYPE(JSBool, _JS_I32, "","i", INFALLIBLE)
#define _JS_CTYPE_BOOL_RETRY _JS_CTYPE(JSBool, _JS_I32, --, --, FAIL_NEITHER)
#define _JS_CTYPE_BOOL_FAIL _JS_CTYPE(JSBool, _JS_I32, --, --, FAIL_STATUS)
#define _JS_CTYPE_BOOLPTR _JS_CTYPE(JSBool *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_INT32 _JS_CTYPE(int32, _JS_I32, "","i", INFALLIBLE)
#define _JS_CTYPE_INT32_RETRY _JS_CTYPE(int32, _JS_I32, --, --, FAIL_NEG)
#define _JS_CTYPE_INT32_FAIL _JS_CTYPE(int32, _JS_I32, --, --, FAIL_STATUS)
#define _JS_CTYPE_INT32PTR _JS_CTYPE(int32 *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_UINT32 _JS_CTYPE(uint32, _JS_I32, "","i", INFALLIBLE)
#define _JS_CTYPE_UINT32_RETRY _JS_CTYPE(uint32, _JS_I32, --, --, FAIL_NEG)
#define _JS_CTYPE_UINT32_FAIL _JS_CTYPE(uint32, _JS_I32, --, --, FAIL_STATUS)
#define _JS_CTYPE_DOUBLE _JS_CTYPE(jsdouble, _JS_F64, "","d", INFALLIBLE)
#define _JS_CTYPE_DOUBLE_FAIL _JS_CTYPE(jsdouble, _JS_F64, --, --, FAIL_STATUS)
#define _JS_CTYPE_STRING _JS_CTYPE(JSString *, _JS_PTR, "","s", INFALLIBLE)
#define _JS_CTYPE_STRING_RETRY _JS_CTYPE(JSString *, _JS_PTR, --, --, FAIL_NULL)
#define _JS_CTYPE_STRING_FAIL _JS_CTYPE(JSString *, _JS_PTR, --, --, FAIL_STATUS)
#define _JS_CTYPE_STRING_OR_NULL_FAIL _JS_CTYPE(JSString *, _JS_PTR, --, --, FAIL_STATUS | \
JSTN_RETURN_NULLABLE_STR)
#define _JS_CTYPE_STRINGPTR _JS_CTYPE(JSString **, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_OBJECT _JS_CTYPE(JSObject *, _JS_PTR, "","o", INFALLIBLE)
#define _JS_CTYPE_OBJECT_RETRY _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_NULL)
#define _JS_CTYPE_OBJECT_FAIL _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_STATUS)
#define _JS_CTYPE_OBJECT_OR_NULL_FAIL _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_STATUS | \
JSTN_RETURN_NULLABLE_OBJ)
#define _JS_CTYPE_OBJECTPTR _JS_CTYPE(JSObject **, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CONSTRUCTOR_RETRY _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_NULL | \
JSTN_CONSTRUCTOR)
#define _JS_CTYPE_REGEXP _JS_CTYPE(JSObject *, _JS_PTR, "","r", INFALLIBLE)
#define _JS_CTYPE_SHAPE _JS_CTYPE(js::Shape *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_TRACERSTATE _JS_CTYPE(TracerState *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CLASS _JS_CTYPE(js::Class *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_DOUBLEPTR _JS_CTYPE(double *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CHARPTR _JS_CTYPE(char *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CVIPTR _JS_CTYPE(const ClosureVarInfo *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_FRAMEINFO _JS_CTYPE(FrameInfo *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_UINTN _JS_CTYPE(uintN, _JS_PTR, --, --, INFALLIBLE)
/*
* The "VALUE" type is used to indicate that a native takes a js::Value
* parameter by value. Unfortunately, for technical reasons, we can't simply
* have the parameter type be js::Value. Furthermore, the right thing to pass
* differs based on word size. Thus, a native that declares a parameter of type
* VALUE should have the corresponding argument type be:
* - on 32-bit: const Value*
* - on 64-bit: jsval (which is a uint64)
*
* To write code that just does the right thing, use the pattern:
* void foo(js::ValueArgType arg) {
* const js::Value &v = js::ValueArgToConstRef(arg);
*/
#if JS_BITS_PER_WORD == 32
# define _JS_CTYPE_VALUE _JS_CTYPE(js::ValueArgType, _JS_PTR, "","v", INFALLIBLE)
#elif JS_BITS_PER_WORD == 64
# define _JS_CTYPE_VALUE _JS_CTYPE(js::ValueArgType, _JS_U64, "","v", INFALLIBLE)
#endif
namespace js {
#if JS_BITS_PER_WORD == 32
typedef const js::Value *ValueArgType;
static JS_ALWAYS_INLINE const js::Value &
ValueArgToConstRef(const js::Value *arg)
{
return *arg;
}
#elif JS_BITS_PER_WORD == 64
typedef js::Value ValueArgType;
static JS_ALWAYS_INLINE const Value &
ValueArgToConstRef(const Value &v)
{
return v;
}
#endif
} /* namespace js */
#define _JS_EXPAND(tokens) tokens
#define _JS_CTYPE_TYPE2(t,s,p,a,f) t
#define _JS_CTYPE_TYPE(tyname) _JS_EXPAND(_JS_CTYPE_TYPE2 _JS_CTYPE_##tyname)
#define _JS_CTYPE_RETTYPE2(t,s,p,a,f) s##_RETTYPE
#define _JS_CTYPE_RETTYPE(tyname) _JS_EXPAND(_JS_CTYPE_RETTYPE2 _JS_CTYPE_##tyname)
#define _JS_CTYPE_ARGTYPE2(t,s,p,a,f) s##_ARGTYPE
#define _JS_CTYPE_ARGTYPE(tyname) _JS_EXPAND(_JS_CTYPE_ARGTYPE2 _JS_CTYPE_##tyname)
#define _JS_CTYPE_PCH2(t,s,p,a,f) p
#define _JS_CTYPE_PCH(tyname) _JS_EXPAND(_JS_CTYPE_PCH2 _JS_CTYPE_##tyname)
#define _JS_CTYPE_ACH2(t,s,p,a,f) a
#define _JS_CTYPE_ACH(tyname) _JS_EXPAND(_JS_CTYPE_ACH2 _JS_CTYPE_##tyname)
#define _JS_CTYPE_FLAGS2(t,s,p,a,f) f
#define _JS_CTYPE_FLAGS(tyname) _JS_EXPAND(_JS_CTYPE_FLAGS2 _JS_CTYPE_##tyname)
#define _JS_static_TN(t) static t
#define _JS_static_CI static
#define _JS_extern_TN(t) extern t
#define _JS_extern_CI
#define _JS_FRIEND_TN(t) extern JS_FRIEND_API(t)
#define _JS_FRIEND_CI
#define _JS_TN_LINKAGE(linkage, t) _JS_##linkage##_TN(t)
#define _JS_CI_LINKAGE(linkage) _JS_##linkage##_CI
#define _JS_CALLINFO(name) name##_ci
#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \
_JS_TN_LINKAGE(linkage, crtype) name cargtypes; \
_JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
{ (intptr_t) &name, argtypes, nanojit::ABI_CDECL, isPure, storeAccSet _JS_CI_NAME(name) };\
JS_STATIC_ASSERT_IF(isPure, (storeAccSet) == nanojit::ACCSET_NONE);
#else
#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \
_JS_TN_LINKAGE(linkage, crtype) FASTCALL name cargtypes; \
_JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
{ (uintptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \
JS_STATIC_ASSERT_IF(isPure, (storeAccSet) == nanojit::ACCSET_NONE);
#endif
/*
* This macro is used for builtin functions that can be called from JITted
* code. It declares a C function named <op> and a CallInfo struct named
* <op>_ci so the tracer can call it. The <N> in JS_DEFINE_CALLINFO_<N> is
* the number of arguments the builtin takes. Builtins with no arguments
* are not supported. Using a macro is clunky but ensures that the types
* for each C function matches those for the corresponding CallInfo struct;
* mismatched types can cause subtle problems.
*
* The macro arguments are:
*
* - The linkage for the function and the associated CallInfo global. It
* can be extern, static, or FRIEND, which specifies JS_FRIEND_API linkage
* for the function.
*
* - The return type. This identifier must name one of the _JS_TYPEINFO_*
* macros defined in jsbuiltins.h.
*
* - The builtin name.
*
* - The parameter types.
*
* - The isPure flag. Set to 1 if:
* (a) the function's return value is determined solely by its arguments
* (ie. no hidden state, no implicit inputs used such as global
* variables or the result of an I/O operation); and
* (b) the function causes no observable side-effects (ie. no writes to
* global variables, no I/O output).
* Multiple calls to a pure function can be merged during CSE.
*
* - The storeAccSet. This indicates which memory access regions the function
* accesses. It must be ACCSET_NONE if the function is pure; use
* ACCSET_STORE_ANY if you're not sure. Used to determine if each call site
* of the function aliases any loads.
*/
#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, isPure, storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0)), \
nanojit::CallInfo::typeSig1(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0)), \
isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, isPure, storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0), \
_JS_CTYPE_TYPE(at1)), \
nanojit::CallInfo::typeSig2(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0), \
_JS_CTYPE_ARGTYPE(at1)), \
isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, isPure, storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0), \
_JS_CTYPE_TYPE(at1), \
_JS_CTYPE_TYPE(at2)), \
nanojit::CallInfo::typeSig3(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0), \
_JS_CTYPE_ARGTYPE(at1), \
_JS_CTYPE_ARGTYPE(at2)), \
isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, isPure, storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0), \
_JS_CTYPE_TYPE(at1), \
_JS_CTYPE_TYPE(at2), \
_JS_CTYPE_TYPE(at3)), \
nanojit::CallInfo::typeSig4(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0), \
_JS_CTYPE_ARGTYPE(at1), \
_JS_CTYPE_ARGTYPE(at2), \
_JS_CTYPE_ARGTYPE(at3)), \
isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, isPure, storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0), \
_JS_CTYPE_TYPE(at1), \
_JS_CTYPE_TYPE(at2), \
_JS_CTYPE_TYPE(at3), \
_JS_CTYPE_TYPE(at4)), \
nanojit::CallInfo::typeSig5(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0), \
_JS_CTYPE_ARGTYPE(at1), \
_JS_CTYPE_ARGTYPE(at2), \
_JS_CTYPE_ARGTYPE(at3), \
_JS_CTYPE_ARGTYPE(at4)), \
isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, isPure, storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0), \
_JS_CTYPE_TYPE(at1), \
_JS_CTYPE_TYPE(at2), \
_JS_CTYPE_TYPE(at3), \
_JS_CTYPE_TYPE(at4), \
_JS_CTYPE_TYPE(at5)), \
nanojit::CallInfo::typeSig6(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0), \
_JS_CTYPE_ARGTYPE(at1), \
_JS_CTYPE_ARGTYPE(at2), \
_JS_CTYPE_ARGTYPE(at3), \
_JS_CTYPE_ARGTYPE(at4), \
_JS_CTYPE_ARGTYPE(at5)), \
isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, isPure, \
storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0), \
_JS_CTYPE_TYPE(at1), \
_JS_CTYPE_TYPE(at2), \
_JS_CTYPE_TYPE(at3), \
_JS_CTYPE_TYPE(at4), \
_JS_CTYPE_TYPE(at5), \
_JS_CTYPE_TYPE(at6)), \
nanojit::CallInfo::typeSig7(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0), \
_JS_CTYPE_ARGTYPE(at1), \
_JS_CTYPE_ARGTYPE(at2), \
_JS_CTYPE_ARGTYPE(at3), \
_JS_CTYPE_ARGTYPE(at4), \
_JS_CTYPE_ARGTYPE(at5), \
_JS_CTYPE_ARGTYPE(at6)), \
isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, isPure, \
storeAccSet) \
_JS_DEFINE_CALLINFO(linkage, op, \
_JS_CTYPE_TYPE(rt), \
(_JS_CTYPE_TYPE(at0), \
_JS_CTYPE_TYPE(at1), \
_JS_CTYPE_TYPE(at2), \
_JS_CTYPE_TYPE(at3), \
_JS_CTYPE_TYPE(at4), \
_JS_CTYPE_TYPE(at5), \
_JS_CTYPE_TYPE(at6), \
_JS_CTYPE_TYPE(at7)), \
nanojit::CallInfo::typeSig8(_JS_CTYPE_RETTYPE(rt), \
_JS_CTYPE_ARGTYPE(at0), \
_JS_CTYPE_ARGTYPE(at1), \
_JS_CTYPE_ARGTYPE(at2), \
_JS_CTYPE_ARGTYPE(at3), \
_JS_CTYPE_ARGTYPE(at4), \
_JS_CTYPE_ARGTYPE(at5), \
_JS_CTYPE_ARGTYPE(at6), \
_JS_CTYPE_ARGTYPE(at7)), \
isPure, storeAccSet)
#define JS_DECLARE_CALLINFO(name) extern const nanojit::CallInfo _JS_CALLINFO(name);
#define _JS_TN_INIT_HELPER_n(n, args) _JS_TN_INIT_HELPER_##n args
#define _JS_TN_INIT_HELPER_1(linkage, rt, op, at0, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define _JS_TN_INIT_HELPER_2(linkage, rt, op, at0, at1, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define _JS_TN_INIT_HELPER_3(linkage, rt, op, at0, at1, at2, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define _JS_TN_INIT_HELPER_4(linkage, rt, op, at0, at1, at2, at3, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at3) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define _JS_TN_INIT_HELPER_5(linkage, rt, op, at0, at1, at2, at3, at4, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) \
_JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at4) _JS_CTYPE_ACH(at3) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) \
_JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define _JS_TN_INIT_HELPER_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at5) _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) \
_JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at5) _JS_CTYPE_ACH(at4) _JS_CTYPE_ACH(at3) _JS_CTYPE_ACH(at2) \
_JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define _JS_TN_INIT_HELPER_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at6) _JS_CTYPE_PCH(at5) _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) \
_JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at6) _JS_CTYPE_ACH(at5) _JS_CTYPE_ACH(at4) _JS_CTYPE_ACH(at3) \
_JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define _JS_TN_INIT_HELPER_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, isPure, storeAccSet) \
&_JS_CALLINFO(op), \
_JS_CTYPE_PCH(at7) _JS_CTYPE_PCH(at6) _JS_CTYPE_PCH(at5) _JS_CTYPE_PCH(at4) \
_JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
_JS_CTYPE_ACH(at7) _JS_CTYPE_ACH(at6) _JS_CTYPE_ACH(at5) _JS_CTYPE_ACH(at4) \
_JS_CTYPE_ACH(at3) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \
_JS_CTYPE_FLAGS(rt)
#define JS_DEFINE_TRCINFO_1(name, tn0) \
_JS_DEFINE_CALLINFO_n tn0 \
JSSpecializedNative name##_sns[] = { \
{ _JS_TN_INIT_HELPER_n tn0 } \
}; \
JSNativeTraceInfo name##_trcinfo = { name, name##_sns };
#define JS_DEFINE_TRCINFO_2(name, tn0, tn1) \
_JS_DEFINE_CALLINFO_n tn0 \
_JS_DEFINE_CALLINFO_n tn1 \
JSSpecializedNative name##_sns[] = { \
{ _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
{ _JS_TN_INIT_HELPER_n tn1 } \
}; \
JSNativeTraceInfo name##_trcinfo = { name, name##_sns };
#define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2) \
_JS_DEFINE_CALLINFO_n tn0 \
_JS_DEFINE_CALLINFO_n tn1 \
_JS_DEFINE_CALLINFO_n tn2 \
JSSpecializedNative name##_sns[] = { \
{ _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
{ _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
{ _JS_TN_INIT_HELPER_n tn2 } \
}; \
JSNativeTraceInfo name##_trcinfo = { name, name##_sns };
#define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3) \
_JS_DEFINE_CALLINFO_n tn0 \
_JS_DEFINE_CALLINFO_n tn1 \
_JS_DEFINE_CALLINFO_n tn2 \
_JS_DEFINE_CALLINFO_n tn3 \
JSSpecializedNative name##_sns[] = { \
{ _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
{ _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
{ _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE }, \
{ _JS_TN_INIT_HELPER_n tn3 } \
}; \
JSNativeTraceInfo name##_trcinfo = { name, name##_sns };
#define _JS_DEFINE_CALLINFO_n(n, args) JS_DEFINE_CALLINFO_##n args
jsdouble FASTCALL
js_StringToNumber(JSContext* cx, JSString* str, JSBool *ok);
/* Extern version of SetBuiltinError. */
extern JS_FRIEND_API(void)
js_SetTraceableNativeFailed(JSContext *cx);
extern jsdouble FASTCALL
js_dmod(jsdouble a, jsdouble b);
#else
#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, isPure, storeAccSet)
#define JS_DEFINE_CALLINFO_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, isPure, storeAccSet)
#define JS_DECLARE_CALLINFO(name)
#define JS_DEFINE_TRCINFO_1(name, tn0)
#define JS_DEFINE_TRCINFO_2(name, tn0, tn1)
#define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)
#define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)
#endif /* !JS_TRACER */
/* Defined in jsarray.cpp. */
namespace js {
JS_DECLARE_CALLINFO(NewDenseEmptyArray)
JS_DECLARE_CALLINFO(NewDenseAllocatedArray)
JS_DECLARE_CALLINFO(NewDenseUnallocatedArray)
JS_DECLARE_CALLINFO(NewDenseAllocatedEmptyArray)
}
JS_DECLARE_CALLINFO(js_NewbornArrayPush_tn)
JS_DECLARE_CALLINFO(js_EnsureDenseArrayCapacity)
/* Defined in jsbuiltins.cpp. */
JS_DECLARE_CALLINFO(js_UnboxNumberAsDouble)
JS_DECLARE_CALLINFO(js_UnboxNumberAsInt32)
JS_DECLARE_CALLINFO(js_dmod)
JS_DECLARE_CALLINFO(js_imod)
JS_DECLARE_CALLINFO(js_DoubleToInt32)
JS_DECLARE_CALLINFO(js_DoubleToUint32)
JS_DECLARE_CALLINFO(js_StringToNumber)
JS_DECLARE_CALLINFO(js_StringToInt32)
JS_DECLARE_CALLINFO(js_AddProperty)
JS_DECLARE_CALLINFO(js_AddAtomProperty)
JS_DECLARE_CALLINFO(js_HasNamedProperty)
JS_DECLARE_CALLINFO(js_HasNamedPropertyInt32)
JS_DECLARE_CALLINFO(js_TypeOfObject)
JS_DECLARE_CALLINFO(js_BooleanIntToString)
JS_DECLARE_CALLINFO(js_NewNullClosure)
/* Defined in jsfun.cpp. */
JS_DECLARE_CALLINFO(js_AllocFlatClosure)
JS_DECLARE_CALLINFO(js_PutArgumentsOnTrace)
JS_DECLARE_CALLINFO(js_PutCallObjectOnTrace)
JS_DECLARE_CALLINFO(js_SetCallVar)
JS_DECLARE_CALLINFO(js_SetCallArg)
JS_DECLARE_CALLINFO(js_CloneFunctionObject)
JS_DECLARE_CALLINFO(js_CreateCallObjectOnTrace)
JS_DECLARE_CALLINFO(js_NewArgumentsOnTrace)
/* Defined in jsnum.cpp. */
JS_DECLARE_CALLINFO(js_NumberToString)
/* Defined in jsobj.cpp. */
JS_DECLARE_CALLINFO(js_Object_tn)
JS_DECLARE_CALLINFO(js_CreateThisFromTrace)
JS_DECLARE_CALLINFO(js_InitializerObject)
/* Defined in vm/RegExpObject.cpp. */
JS_DECLARE_CALLINFO(js_CloneRegExpObject)
/* Defined in jsstr.cpp. */
JS_DECLARE_CALLINFO(js_String_tn)
JS_DECLARE_CALLINFO(js_CompareStringsOnTrace)
JS_DECLARE_CALLINFO(js_ConcatStrings)
JS_DECLARE_CALLINFO(js_EqualStringsOnTrace)
JS_DECLARE_CALLINFO(js_FlattenOnTrace)
/* Defined in jstypedarray.cpp. */
JS_DECLARE_CALLINFO(js_TypedArray_uint8_clamp_double)
#endif /* jsbuiltins_h___ */

View File

@ -80,7 +80,6 @@
#include "jsscope.h" #include "jsscope.h"
#include "jsscript.h" #include "jsscript.h"
#include "jsstr.h" #include "jsstr.h"
#include "jstracer.h"
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
# include "assembler/assembler/MacroAssembler.h" # include "assembler/assembler/MacroAssembler.h"
@ -104,12 +103,6 @@ ThreadData::ThreadData(JSRuntime *rt)
interruptFlags(0), interruptFlags(0),
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
requestDepth(0), requestDepth(0),
#endif
#ifdef JS_TRACER
onTraceCompartment(NULL),
recordingCompartment(NULL),
profilingCompartment(NULL),
maxCodeCacheBytes(DEFAULT_JIT_CACHE_SIZE),
#endif #endif
waiveGCQuota(false), waiveGCQuota(false),
tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
@ -220,13 +213,6 @@ ThreadData::purgeRegExpPrivateCache()
JSScript * JSScript *
js_GetCurrentScript(JSContext *cx) js_GetCurrentScript(JSContext *cx)
{ {
#ifdef JS_TRACER
VOUCH_DOES_NOT_REQUIRE_STACK();
if (JS_ON_TRACE(cx)) {
VMSideExit *bailExit = JS_TRACE_MONITOR_ON_TRACE(cx)->bailExit;
return bailExit ? bailExit->script : NULL;
}
#endif
return cx->hasfp() ? cx->fp()->maybeScript() : NULL; return cx->hasfp() ? cx->fp()->maybeScript() : NULL;
} }
@ -749,15 +735,6 @@ PopulateReportBlame(JSContext *cx, JSErrorReport *report)
void void
js_ReportOutOfMemory(JSContext *cx) js_ReportOutOfMemory(JSContext *cx)
{ {
#ifdef JS_TRACER
/*
* If we are in a builtin called directly from trace, don't report an
* error. We will retry in the interpreter instead.
*/
if (JS_ON_TRACE(cx) && !JS_TRACE_MONITOR_ON_TRACE(cx)->bailExit)
return;
#endif
cx->runtime->hadOutOfMemory = true; cx->runtime->hadOutOfMemory = true;
JSErrorReport report; JSErrorReport report;
@ -1347,41 +1324,7 @@ js_GetScriptedCaller(JSContext *cx, StackFrame *fp)
jsbytecode* jsbytecode*
js_GetCurrentBytecodePC(JSContext* cx) js_GetCurrentBytecodePC(JSContext* cx)
{ {
jsbytecode *pc, *imacpc; return cx->hasfp() ? cx->regs().pc : NULL;
#ifdef JS_TRACER
if (JS_ON_TRACE(cx)) {
pc = JS_TRACE_MONITOR_ON_TRACE(cx)->bailExit->pc;
imacpc = JS_TRACE_MONITOR_ON_TRACE(cx)->bailExit->imacpc;
} else
#endif
{
JS_ASSERT_NOT_ON_TRACE(cx); /* for static analysis */
pc = cx->hasfp() ? cx->regs().pc : NULL;
if (!pc)
return NULL;
imacpc = cx->fp()->maybeImacropc();
}
/*
* If we are inside GetProperty_tn or similar, return a pointer to the
* current instruction in the script, not the CALL instruction in the
* imacro, for the benefit of callers doing bytecode inspection.
*/
return (*pc == JSOP_CALL && imacpc) ? imacpc : pc;
}
bool
js_CurrentPCIsInImacro(JSContext *cx)
{
#ifdef JS_TRACER
VOUCH_DOES_NOT_REQUIRE_STACK();
if (JS_ON_TRACE(cx))
return JS_TRACE_MONITOR_ON_TRACE(cx)->bailExit->imacpc != NULL;
return cx->fp()->hasImacropc();
#else
return false;
#endif
} }
void void
@ -1449,12 +1392,8 @@ JSContext::JSContext(JSRuntime *rt)
resolveFlags(0), resolveFlags(0),
rngSeed(0), rngSeed(0),
iterValue(MagicValue(JS_NO_ITER_VALUE)), iterValue(MagicValue(JS_NO_ITER_VALUE)),
#ifdef JS_TRACER
traceJitEnabled(false),
#endif
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
methodJitEnabled(false), methodJitEnabled(false),
profilingEnabled(false),
#endif #endif
inferenceEnabled(false), inferenceEnabled(false),
#ifdef MOZ_TRACE_JSCALLS #ifdef MOZ_TRACE_JSCALLS
@ -1629,7 +1568,7 @@ JSContext::purge()
} }
} }
#if defined(JS_TRACER) || defined(JS_METHODJIT) #if defined(JS_METHODJIT)
static bool static bool
ComputeIsJITBroken() ComputeIsJITBroken()
{ {
@ -1705,15 +1644,6 @@ IsJITBrokenHere()
void void
JSContext::updateJITEnabled() JSContext::updateJITEnabled()
{ {
#ifdef JS_TRACER
traceJitEnabled = ((runOptions & JSOPTION_JIT) &&
!IsJITBrokenHere() &&
compartment &&
!compartment->debugMode() &&
(debugHooks == &js_NullDebugHooks ||
(debugHooks == &runtime->globalDebugHooks &&
!runtime->debuggerInhibitsJIT())));
#endif
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
methodJitEnabled = (runOptions & JSOPTION_METHODJIT) && methodJitEnabled = (runOptions & JSOPTION_METHODJIT) &&
!IsJITBrokenHere() !IsJITBrokenHere()
@ -1722,34 +1652,11 @@ JSContext::updateJITEnabled()
JSC::MacroAssemblerX86Common::HasSSE2 JSC::MacroAssemblerX86Common::HasSSE2
# endif # endif
; ;
#ifdef JS_TRACER
profilingEnabled = (runOptions & JSOPTION_PROFILING) && traceJitEnabled && methodJitEnabled;
#endif
#endif #endif
} }
namespace js { namespace js {
JS_FORCES_STACK JS_FRIEND_API(void)
LeaveTrace(JSContext *cx)
{
#ifdef JS_TRACER
if (JS_ON_TRACE(cx))
DeepBail(cx);
#endif
}
bool
CanLeaveTrace(JSContext *cx)
{
JS_ASSERT(JS_ON_TRACE(cx));
#ifdef JS_TRACER
return JS_TRACE_MONITOR_ON_TRACE(cx)->bailExit != NULL;
#else
return false;
#endif
}
AutoEnumStateRooter::~AutoEnumStateRooter() AutoEnumStateRooter::~AutoEnumStateRooter()
{ {
if (!stateValue.isNull()) { if (!stateValue.isNull()) {

View File

@ -70,18 +70,6 @@
#pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */ #pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */
#endif #endif
/* Forward declarations of nanojit types. */
namespace nanojit {
class Assembler;
class CodeAlloc;
class Fragment;
template<typename K> struct DefaultHash;
template<typename K, typename V, typename H> class HashMap;
template<typename T> class Seq;
} /* namespace nanojit */
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C
struct DtoaState; struct DtoaState;
JS_END_EXTERN_C JS_END_EXTERN_C
@ -94,35 +82,12 @@ struct JSSharpObjectMap {
namespace js { namespace js {
/* Tracer constants. */
static const size_t MONITOR_N_GLOBAL_STATES = 4;
static const size_t FRAGMENT_TABLE_SIZE = 512;
static const size_t MAX_GLOBAL_SLOTS = 4096;
static const size_t GLOBAL_SLOTS_BUFFER_SIZE = MAX_GLOBAL_SLOTS + 1;
/* Forward declarations of tracer types. */
class VMAllocator;
class FrameInfoCache;
struct FrameInfo;
struct VMSideExit;
struct TreeFragment;
struct TracerState;
template<typename T> class Queue;
typedef Queue<uint16> SlotList;
class TypeMap;
class LoopProfile;
class InterpreterFrames;
#if defined(JS_JIT_SPEW) || defined(DEBUG)
struct FragPI;
typedef nanojit::HashMap<uint32, FragPI, nanojit::DefaultHash<uint32> > FragStatsMap;
#endif
namespace mjit { namespace mjit {
class JaegerCompartment; class JaegerCompartment;
} }
class WeakMapBase; class WeakMapBase;
class InterpreterFrames;
/* /*
* GetSrcNote cache to avoid O(n^2) growth in finding a source note for a * GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
@ -167,25 +132,6 @@ struct ThreadData {
unsigned requestDepth; unsigned requestDepth;
#endif #endif
#ifdef JS_TRACER
/*
* During trace execution (or during trace recording or
* profiling), these fields point to the compartment doing the
* execution on this thread. At other times, they are NULL. If a
* thread tries to execute/record/profile one trace while another
* is still running, the initial one will abort. Therefore, we
* only need to track one at a time.
*/
JSCompartment *onTraceCompartment;
JSCompartment *recordingCompartment;
JSCompartment *profilingCompartment;
/* Maximum size of the tracer's code cache before we start flushing. */
uint32 maxCodeCacheBytes;
static const uint32 DEFAULT_JIT_CACHE_SIZE = 16 * 1024 * 1024;
#endif
/* Keeper of the contiguous stack used by all contexts in this thread. */ /* Keeper of the contiguous stack used by all contexts in this thread. */
StackSpace stackSpace; StackSpace stackSpace;
@ -615,14 +561,6 @@ struct JSRuntime
/* Had an out-of-memory error which did not populate an exception. */ /* Had an out-of-memory error which did not populate an exception. */
JSBool hadOutOfMemory; JSBool hadOutOfMemory;
#ifdef JS_TRACER
/* True if any debug hooks not supported by the JIT are enabled. */
bool debuggerInhibitsJIT() const {
return (globalDebugHooks.interruptHook ||
globalDebugHooks.callHook);
}
#endif
/* /*
* Linked list of all js::Debugger objects. This may be accessed by the GC * Linked list of all js::Debugger objects. This may be accessed by the GC
* thread, if any, or a thread that is in a request and holds gcLock. * thread, if any, or a thread that is in a request and holds gcLock.
@ -1188,23 +1126,8 @@ struct JSContext
/* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */ /* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */
js::Value iterValue; js::Value iterValue;
#ifdef JS_TRACER
/*
* True if traces may be executed. Invariant: The value of traceJitenabled
* is always equal to the expression in updateJITEnabled below.
*
* This flag and the fields accessed by updateJITEnabled are written only
* in runtime->gcLock, to avoid race conditions that would leave the wrong
* value in traceJitEnabled. (But the interpreter reads this without
* locking. That can race against another thread setting debug hooks, but
* we always read cx->debugHooks without locking anyway.)
*/
bool traceJitEnabled;
#endif
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
bool methodJitEnabled; bool methodJitEnabled;
bool profilingEnabled;
inline js::mjit::JaegerCompartment *jaegerCompartment(); inline js::mjit::JaegerCompartment *jaegerCompartment();
#endif #endif
@ -2185,17 +2108,8 @@ js_GetCurrentBytecodePC(JSContext* cx);
extern JSScript * extern JSScript *
js_GetCurrentScript(JSContext* cx); js_GetCurrentScript(JSContext* cx);
extern bool
js_CurrentPCIsInImacro(JSContext *cx);
namespace js { namespace js {
extern JS_FORCES_STACK JS_FRIEND_API(void)
LeaveTrace(JSContext *cx);
extern bool
CanLeaveTrace(JSContext *cx);
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
namespace mjit { namespace mjit {
void ExpandInlineFrames(JSCompartment *compartment); void ExpandInlineFrames(JSCompartment *compartment);

View File

@ -373,38 +373,10 @@ CallSetter(JSContext *cx, JSObject *obj, jsid id, StrictPropertyOp op, uintN att
return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp); return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
} }
#ifdef JS_TRACER
/*
* Reconstruct the JS stack and clear cx->tracecx. We must be currently in a
* _FAIL builtin from trace on cx or another context on the same thread. The
* machine code for the trace remains on the C stack when js_DeepBail returns.
*
* Implemented in jstracer.cpp.
*/
JS_FORCES_STACK JS_FRIEND_API(void)
DeepBail(JSContext *cx);
#endif
static JS_INLINE void
LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj)
{
if (!obj->getParent())
LeaveTrace(cx);
}
static JS_INLINE void
LeaveTraceIfArgumentsObject(JSContext *cx, JSObject *obj)
{
if (obj->isArguments())
LeaveTrace(cx);
}
static inline JSAtom ** static inline JSAtom **
FrameAtomBase(JSContext *cx, js::StackFrame *fp) FrameAtomBase(JSContext *cx, js::StackFrame *fp)
{ {
return fp->hasImacropc() return fp->script()->atoms;
? cx->runtime->atomState.commonAtomsStart()
: fp->script()->atoms;
} }
} /* namespace js */ } /* namespace js */
@ -525,14 +497,10 @@ JSContext::ensureParseMapPool()
/* /*
* Get the current frame, first lazily instantiating stack frames if needed. * Get the current frame, first lazily instantiating stack frames if needed.
* (Do not access cx->fp() directly except in JS_REQUIRES_STACK code.) * (Do not access cx->fp() directly except in JS_REQUIRES_STACK code.)
*
* LeaveTrace is defined in jstracer.cpp if JS_TRACER is defined.
*/ */
static JS_FORCES_STACK JS_INLINE js::StackFrame * static JS_FORCES_STACK JS_INLINE js::StackFrame *
js_GetTopStackFrame(JSContext *cx, FrameExpandKind expand) js_GetTopStackFrame(JSContext *cx, FrameExpandKind expand)
{ {
js::LeaveTrace(cx);
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
if (expand) if (expand)
js::mjit::ExpandInlineFrames(cx->compartment); js::mjit::ExpandInlineFrames(cx->compartment);

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