diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index 1f9fe2c7b637..8d8a7db4d9e3 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -507,7 +507,7 @@ function HistoryMenu(aPopupShowingEvent) { "@mozilla.org/browser/sessionstore;1", "nsISessionStore"); PlacesMenu.call(this, aPopupShowingEvent, - "place:redirectsMode=2&sort=4&maxResults=15"); + "place:sort=4&maxResults=15"); } HistoryMenu.prototype = { diff --git a/browser/components/certerror/content/aboutCertError.css b/browser/components/certerror/content/aboutCertError.css index e20977b8e186..4140fcd9aabc 100644 --- a/browser/components/certerror/content/aboutCertError.css +++ b/browser/components/certerror/content/aboutCertError.css @@ -47,6 +47,8 @@ white-space: pre-wrap; } +.expander[hidden], +.expander[hidden] + *, .expander[collapsed] + * { display: none; } diff --git a/browser/components/certerror/content/aboutCertError.xhtml b/browser/components/certerror/content/aboutCertError.xhtml index e54aba695968..ee296dfea6d5 100644 --- a/browser/components/certerror/content/aboutCertError.xhtml +++ b/browser/components/certerror/content/aboutCertError.xhtml @@ -126,10 +126,8 @@ // Disallow overrides if this is a Strict-Transport-Security // host and the cert is bad (STS Spec section 7.3) or if the // certerror is in a frame (bug 633691). - if (getCSSClass() == "badStsCert" || window != top) { - var ec = document.getElementById('expertContent'); - ec.parentNode.removeChild(ec); - } + if (getCSSClass() == "badStsCert" || window != top) + document.getElementById("expertContent").setAttribute("hidden", "true"); var tech = document.getElementById("technicalContentText"); if (tech) diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 68e720eeeb27..b60341c35ad6 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -1352,7 +1352,7 @@ BrowserGlue.prototype = { // be set to the version it has been added in, we will compare its value // to users' smartBookmarksVersion and add new smart bookmarks without // recreating old deleted ones. - const SMART_BOOKMARKS_VERSION = 3; + const SMART_BOOKMARKS_VERSION = 4; const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark"; const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion"; @@ -1380,9 +1380,7 @@ BrowserGlue.prototype = { let smartBookmarks = { MostVisited: { title: bundle.GetStringFromName("mostVisitedTitle"), - uri: NetUtil.newURI("place:redirectsMode=" + - Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET + - "&sort=" + + uri: NetUtil.newURI("place:sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING + "&maxResults=" + MAX_RESULTS), parent: PlacesUtils.toolbarFolderId, diff --git a/browser/components/places/content/browserPlacesViews.js b/browser/components/places/content/browserPlacesViews.js index 5d10987fa98c..cd42fbecb455 100644 --- a/browser/components/places/content/browserPlacesViews.js +++ b/browser/components/places/content/browserPlacesViews.js @@ -733,6 +733,8 @@ PlacesViewBase.prototype = { .direction == "rtl"; }, + get ownerWindow() window, + /** * Adds an "Open All in Tabs" menuitem to the bottom of the popup. * @param aPopup diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js index 40e7cfa1d262..a27402b59024 100644 --- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -336,7 +336,7 @@ var PlacesOrganizer = { // The command execution function will take care of seeing if the // selection is a folder or a different container type, and will // load its contents in tabs. - PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent); + PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent, currentView); } } }, @@ -363,7 +363,7 @@ var PlacesOrganizer = { openSelectedNode: function PO_openSelectedNode(aEvent) { PlacesUIUtils.openNodeWithEvent(this._content.selectedNode, aEvent, - this._content.treeBoxObject.view); + this._content); }, /** diff --git a/browser/components/places/content/sidebarUtils.js b/browser/components/places/content/sidebarUtils.js index 8f1829612b28..21682d0b692c 100644 --- a/browser/components/places/content/sidebarUtils.js +++ b/browser/components/places/content/sidebarUtils.js @@ -86,7 +86,7 @@ var SidebarUtils = { else if (!mouseInGutter && openInTabs && aEvent.originalTarget.localName == "treechildren") { tbo.view.selection.select(row.value); - PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent, tbo.view); + PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent, aTree); } else if (!mouseInGutter && !isContainer && aEvent.originalTarget.localName == "treechildren") { @@ -94,7 +94,7 @@ var SidebarUtils = { // do this *before* attempting to load the link since openURL uses // selection as an indication of which link to load. tbo.view.selection.select(row.value); - PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent, tbo.view); + PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent, aTree); } }, diff --git a/browser/components/places/content/tree.xml b/browser/components/places/content/tree.xml index 2adb3629e07e..727bc598117d 100644 --- a/browser/components/places/content/tree.xml +++ b/browser/components/places/content/tree.xml @@ -699,6 +699,10 @@ this._contextMenuShown = false; + + -# Benjamin Smedberg -# Jeff Walden -# Joey Armstrong -# -# 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 topsrcdir -$(error topsrcdir was not set)) -endif - -ifndef MOZILLA_DIR -MOZILLA_DIR = $(topsrcdir) -endif - -ifndef INCLUDED_CONFIG_MK -include $(topsrcdir)/config/config.mk -endif - -ifndef INCLUDED_VERSION_MK -include $(topsrcdir)/config/version.mk -endif - -ifdef SDK_XPIDLSRCS -XPIDLSRCS += $(SDK_XPIDLSRCS) -endif -ifdef SDK_HEADERS -EXPORTS += $(SDK_HEADERS) -endif - -REPORT_BUILD = @echo $(notdir $<) - -ifeq ($(OS_ARCH),OS2) -EXEC = -else -EXEC = exec -endif - -# Don't copy xulrunner files at install time, when using system xulrunner -ifdef SYSTEM_LIBXUL - SKIP_COPY_XULRUNNER=1 -endif - -# ELOG prints out failed command when building silently (gmake -s). -ifneq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS)))) - ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh -else - ELOG := -endif - -_VPATH_SRCS = $(abspath $<) - -# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed -VPATH += $(DIST)/lib -ifdef LIBXUL_SDK -VPATH += $(LIBXUL_SDK)/lib -endif - -ifdef EXTRA_DSO_LIBS -EXTRA_DSO_LIBS := $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS)) -endif - -################################################################################ -# Testing frameworks support -################################################################################ - -testxpcobjdir = $(DEPTH)/_tests/xpcshell - -ifdef ENABLE_TESTS - -# Add test directories to the regular directories list. TEST_DIRS should -# arguably have the same status as TOOL_DIRS and other *_DIRS variables. It is -# coded this way until Makefiles stop using the "ifdef ENABLE_TESTS; DIRS +=" -# convention. -# -# The current developer workflow expects tests to be updated when processing -# the default target. If we ever change this implementation, the behavior -# should be preserved or the change should be widely communicated. A -# consequence of not processing test dir targets during the default target is -# that changes to tests may not be updated and code could assume to pass -# locally against non-current test code. -DIRS += $(TEST_DIRS) - -ifdef XPCSHELL_TESTS -ifndef relativesrcdir -$(error Must define relativesrcdir when defining XPCSHELL_TESTS.) -endif - -define _INSTALL_TESTS -$(DIR_INSTALL) $(wildcard $(srcdir)/$(dir)/*) $(testxpcobjdir)/$(relativesrcdir)/$(dir) - -endef # do not remove the blank line! - -SOLO_FILE ?= $(error Specify a test filename in SOLO_FILE when using check-interactive or check-one) - -libs:: - $(foreach dir,$(XPCSHELL_TESTS),$(_INSTALL_TESTS)) -ifndef NO_XPCSHELL_MANIFEST_CHECK - $(PYTHON) $(MOZILLA_DIR)/build/xpccheck.py \ - $(topsrcdir) \ - $(topsrcdir)/testing/xpcshell/xpcshell.ini \ - $(addprefix $(MOZILLA_DIR)/$(relativesrcdir)/,$(XPCSHELL_TESTS)) -endif - -testxpcsrcdir = $(topsrcdir)/testing/xpcshell - -# Execute all tests in the $(XPCSHELL_TESTS) directories. -# See also testsuite-targets.mk 'xpcshell-tests' target for global execution. -xpcshell-tests: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --tests-root-dir=$(testxpcobjdir) \ - --xunit-file=$(testxpcobjdir)/$(relativesrcdir)/results.xml \ - --xunit-suite-name=xpcshell \ - $(EXTRA_TEST_ARGS) \ - $(LIBXUL_DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -xpcshell-tests-remote: DM_TRANS?=adb -xpcshell-tests-remote: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - -I$(topsrcdir)/build/mobile \ - $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - $(EXTRA_TEST_ARGS) \ - --dm_trans=$(DM_TRANS) \ - --deviceIP=${TEST_DEVICE} \ - --objdir=$(DEPTH) \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -# Execute a single test, specified in $(SOLO_FILE), but don't automatically -# start the test. Instead, present the xpcshell prompt so the user can -# attach a debugger and then start the test. -check-interactive: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --interactive \ - $(LIBXUL_DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -# Execute a single test, specified in $(SOLO_FILE) -check-one: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --verbose \ - $(EXTRA_TEST_ARGS) \ - $(LIBXUL_DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -check-one-remote: DM_TRANS?=adb -check-one-remote: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - -I$(topsrcdir)/build/mobile \ - $(testxpcsrcdir)/remotexpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --verbose \ - $(EXTRA_TEST_ARGS) \ - --dm_trans=$(DM_TRANS) \ - --deviceIP=${TEST_DEVICE} \ - --objdir=$(DEPTH) \ - --noSetup \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) -endif # XPCSHELL_TESTS - -ifdef CPP_UNIT_TESTS - -# Compile the tests to $(DIST)/bin. Make lots of niceties available by default -# through TestHarness.h, by modifying the list of includes and the libs against -# which stuff links. -CPPSRCS += $(CPP_UNIT_TESTS) -SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) -INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) - -# ...and run them the usual way -check:: - @$(EXIT_ON_ERROR) \ - for f in $(subst .cpp,$(BIN_SUFFIX),$(CPP_UNIT_TESTS)); do \ - XPCOM_DEBUG_BREAK=stack-and-abort $(RUN_TEST_PROGRAM) $(DIST)/bin/$$f; \ - done - -endif # CPP_UNIT_TESTS - -.PHONY: check xpcshell-tests check-interactive check-one - -endif # ENABLE_TESTS - - -# -# Library rules -# -# If FORCE_STATIC_LIB is set, build a static library. -# Otherwise, build a shared library. -# - -ifndef LIBRARY -ifdef STATIC_LIBRARY_NAME -REAL_LIBRARY := $(LIB_PREFIX)$(STATIC_LIBRARY_NAME).$(LIB_SUFFIX) -# Only build actual library if it is installed in DIST/lib or SDK -ifeq (,$(SDK_LIBRARY)$(DIST_INSTALL)$(NO_EXPAND_LIBS)) -LIBRARY := $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) -else -LIBRARY := $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) -endif -endif # STATIC_LIBRARY_NAME -endif # LIBRARY - -ifndef HOST_LIBRARY -ifdef HOST_LIBRARY_NAME -HOST_LIBRARY := $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX) -endif -endif - -ifdef LIBRARY -ifdef FORCE_SHARED_LIB -ifdef MKSHLIB - -ifdef LIB_IS_C_ONLY -MKSHLIB = $(MKCSHLIB) -endif - -ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) -IMPORT_LIBRARY := $(LIB_PREFIX)$(SHARED_LIBRARY_NAME).$(IMPORT_LIB_SUFFIX) -endif - -ifeq (OS2,$(OS_ARCH)) -ifdef SHORT_LIBNAME -SHARED_LIBRARY_NAME := $(SHORT_LIBNAME) -endif -endif - -ifdef MAKE_FRAMEWORK -SHARED_LIBRARY := $(SHARED_LIBRARY_NAME) -else -SHARED_LIBRARY := $(DLL_PREFIX)$(SHARED_LIBRARY_NAME)$(DLL_SUFFIX) -endif - -ifeq ($(OS_ARCH),OS2) -DEF_FILE := $(SHARED_LIBRARY:.dll=.def) -endif - -EMBED_MANIFEST_AT=2 - -endif # MKSHLIB -endif # FORCE_SHARED_LIB -endif # LIBRARY - -ifdef FORCE_STATIC_LIB -ifndef FORCE_SHARED_LIB -SHARED_LIBRARY := $(NULL) -DEF_FILE := $(NULL) -IMPORT_LIBRARY := $(NULL) -endif -endif - -ifdef FORCE_SHARED_LIB -ifndef FORCE_STATIC_LIB -LIBRARY := $(NULL) -endif -endif - -ifdef JAVA_LIBRARY_NAME -JAVA_LIBRARY := $(JAVA_LIBRARY_NAME).jar -endif - -ifeq ($(OS_ARCH),WINNT) -ifndef GNU_CC - -# -# Unless we're building SIMPLE_PROGRAMS, all C++ files share a PDB file per -# directory. For parallel builds, this PDB file is shared and locked by -# MSPDBSRV.EXE, starting with MSVC8 SP1. If you're using MSVC 7.1 or MSVC8 -# without SP1, don't do parallel builds. -# -# The final PDB for libraries and programs is created by the linker and uses -# a different name from the single PDB file created by the compiler. See -# bug 462740. -# - -ifdef SIMPLE_PROGRAMS -COMPILE_PDBFILE = $(basename $(@F)).pdb -else -COMPILE_PDBFILE = generated.pdb -endif - -LINK_PDBFILE = $(basename $(@F)).pdb -ifdef MOZ_DEBUG -CODFILE=$(basename $(@F)).cod -endif - -ifdef MOZ_MAPINFO -ifdef SHARED_LIBRARY_NAME -MAPFILE=$(SHARED_LIBRARY_NAME).map -else -MAPFILE=$(basename $(@F)).map -endif # SHARED_LIBRARY_NAME -endif # MOZ_MAPINFO - -ifdef DEFFILE -OS_LDFLAGS += -DEF:$(call normalizepath,$(DEFFILE)) -EXTRA_DEPS += $(DEFFILE) -endif - -ifdef MAPFILE -OS_LDFLAGS += -MAP:$(MAPFILE) -endif - -else #!GNU_CC - -ifdef DEFFILE -OS_LDFLAGS += $(call normalizepath,$(DEFFILE)) -EXTRA_DEPS += $(DEFFILE) -endif - -endif # !GNU_CC - -endif # WINNT - -ifeq ($(SOLARIS_SUNPRO_CXX),1) -ifeq (86,$(findstring 86,$(OS_TEST))) -OS_LDFLAGS += -M $(topsrcdir)/config/solaris_ia32.map -endif # x86 -endif # Solaris Sun Studio C++ - -ifeq ($(HOST_OS_ARCH),WINNT) -HOST_PDBFILE=$(basename $(@F)).pdb -endif - -# Don't build SIMPLE_PROGRAMS during the MOZ_PROFILE_GENERATE pass -ifdef MOZ_PROFILE_GENERATE -SIMPLE_PROGRAMS := -endif - -ifndef TARGETS -TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(JAVA_LIBRARY) -endif - -ifndef OBJS -_OBJS = \ - $(JRI_STUB_CFILES) \ - $(addsuffix .$(OBJ_SUFFIX), $(JMC_GEN)) \ - $(CSRCS:.c=.$(OBJ_SUFFIX)) \ - $(SSRCS:.S=.$(OBJ_SUFFIX)) \ - $(patsubst %.cc,%.$(OBJ_SUFFIX),$(CPPSRCS:.cpp=.$(OBJ_SUFFIX))) \ - $(CMSRCS:.m=.$(OBJ_SUFFIX)) \ - $(CMMSRCS:.mm=.$(OBJ_SUFFIX)) \ - $(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX)) -OBJS = $(strip $(_OBJS)) -endif - -ifndef HOST_OBJS -_HOST_OBJS = \ - $(addprefix host_,$(HOST_CSRCS:.c=.$(OBJ_SUFFIX))) \ - $(addprefix host_,$(patsubst %.cc,%.$(OBJ_SUFFIX),$(HOST_CPPSRCS:.cpp=.$(OBJ_SUFFIX)))) \ - $(addprefix host_,$(HOST_CMSRCS:.m=.$(OBJ_SUFFIX))) \ - $(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX))) -HOST_OBJS = $(strip $(_HOST_OBJS)) -endif - -LIBOBJS := $(addprefix \", $(OBJS)) -LIBOBJS := $(addsuffix \", $(LIBOBJS)) - -ifndef MOZ_AUTO_DEPS -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) -MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp)) -ifndef NO_GEN_XPT -MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp)) -endif -endif -endif - -ALL_TRASH = \ - $(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \ - $(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \ - $(OBJS:.$(OBJ_SUFFIX)=.i) $(OBJS:.$(OBJ_SUFFIX)=.i_o) \ - $(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\ - $(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \ - $(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \ - $(SHARED_LIBRARY:$(DLL_SUFFIX)=.exp) $(wildcard *.ilk) \ - $(PROGRAM:$(BIN_SUFFIX)=.exp) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.exp) \ - $(PROGRAM:$(BIN_SUFFIX)=.lib) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.lib) \ - $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) \ - $(wildcard gts_tmp_*) $(LIBRARY:%.a=.%.timestamp) -ALL_TRASH_DIRS = \ - $(GARBAGE_DIRS) /no-such-file - -ifdef QTDIR -GARBAGE += $(MOCSRCS) -GARBAGE += $(RCCSRCS) -endif - -ifdef SIMPLE_PROGRAMS -GARBAGE += $(SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX)) -endif - -ifdef HOST_SIMPLE_PROGRAMS -GARBAGE += $(HOST_SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX)) -endif - -# -# the Solaris WorkShop template repository cache. it occasionally can get -# out of sync, so targets like clobber should kill it. -# -ifeq ($(SOLARIS_SUNPRO_CXX),1) -GARBAGE_DIRS += SunWS_cache -endif - -XPIDL_GEN_DIR = _xpidlgen - -ifdef MOZ_UPDATE_XTERM -# Its good not to have a newline at the end of the titlebar string because it -# makes the make -s output easier to read. Echo -n does not work on all -# platforms, but we can trick sed into doing it. -UPDATE_TITLE = sed -e "s!Y!$(1) in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2)!" $(MOZILLA_DIR)/config/xterm.str; -endif - -define SUBMAKE # $(call SUBMAKE,target,directory) -+@$(UPDATE_TITLE) -+$(MAKE) $(if $(2),-C $(2)) $(1) - -endef # The extra line is important here! don't delete it - -ifneq (,$(strip $(DIRS))) -LOOP_OVER_DIRS = \ - $(foreach dir,$(DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -# we only use this for the makefiles target and other stuff that doesn't matter -ifneq (,$(strip $(PARALLEL_DIRS))) -LOOP_OVER_PARALLEL_DIRS = \ - $(foreach dir,$(PARALLEL_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -ifneq (,$(strip $(STATIC_DIRS))) -LOOP_OVER_STATIC_DIRS = \ - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -ifneq (,$(strip $(TOOL_DIRS))) -LOOP_OVER_TOOL_DIRS = \ - $(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -# -# Now we can differentiate between objects used to build a library, and -# objects used to build an executable in the same directory. -# -ifndef PROGOBJS -PROGOBJS = $(OBJS) -endif - -ifndef HOST_PROGOBJS -HOST_PROGOBJS = $(HOST_OBJS) -endif - -# MAKE_DIRS: List of directories to build while looping over directories. -# A Makefile that needs $(MDDEPDIR) created but doesn't set any of these -# variables we know to check can just set NEED_MDDEPDIR explicitly. -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)$(NEED_MDDEPDIR)) -MAKE_DIRS += $(CURDIR)/$(MDDEPDIR) -GARBAGE_DIRS += $(MDDEPDIR) -endif - -# -# Tags: emacs (etags), vi (ctags) -# TAG_PROGRAM := ctags -L - -# -TAG_PROGRAM = xargs etags -a - -# -# Turn on C++ linking if we have any .cpp or .mm files -# (moved this from config.mk so that config.mk can be included -# before the CPPSRCS are defined) -# -ifneq ($(CPPSRCS)$(CMMSRCS),) -CPP_PROG_LINK = 1 -endif -ifneq ($(HOST_CPPSRCS)$(HOST_CMMSRCS),) -HOST_CPP_PROG_LINK = 1 -endif - -# -# This will strip out symbols that the component should not be -# exporting from the .dynsym section. -# -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += $(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS) -endif # IS_COMPONENT - -# -# Enforce the requirement that MODULE_NAME must be set -# for components in static builds -# -ifdef IS_COMPONENT -ifdef EXPORT_LIBRARY -ifndef FORCE_SHARED_LIB -ifndef MODULE_NAME -$(error MODULE_NAME is required for components which may be used in static builds) -endif -endif -endif -endif - -# -# MacOS X specific stuff -# - -ifeq ($(OS_ARCH),Darwin) -ifdef SHARED_LIBRARY -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -bundle -else -EXTRA_DSO_LDOPTS += -dynamiclib -install_name @executable_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module -endif -endif -endif - -# -# On NetBSD a.out systems, use -Bsymbolic. This fixes what would otherwise be -# fatal symbol name clashes between components. -# -ifeq ($(OS_ARCH),NetBSD) -ifeq ($(DLL_SUFFIX),.so.1.0) -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -endif -endif -endif - -ifeq ($(OS_ARCH),FreeBSD) -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -endif -endif - -ifeq ($(OS_ARCH),NetBSD) -ifneq (,$(filter arc cobalt hpcmips mipsco newsmips pmax sgimips,$(OS_TEST))) -ifeq ($(MODULE),layout) -OS_CFLAGS += -Wa,-xgot -OS_CXXFLAGS += -Wa,-xgot -endif -endif -endif - -# -# HP-UXBeOS specific section: for COMPONENTS only, add -Bsymbolic flag -# which uses internal symbols first -# -ifeq ($(OS_ARCH),HP-UX) -ifdef IS_COMPONENT -ifeq ($(GNU_CC)$(GNU_CXX),) -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -ifneq ($(HAS_EXTRAEXPORTS),1) -MKSHLIB += -Wl,+eNSGetModule -Wl,+eerrno -MKCSHLIB += +eNSGetModule +eerrno -ifneq ($(OS_TEST),ia64) -MKSHLIB += -Wl,+e_shlInit -MKCSHLIB += +e_shlInit -endif # !ia64 -endif # !HAS_EXTRAEXPORTS -endif # non-gnu compilers -endif # IS_COMPONENT -endif # HP-UX - -ifeq ($(OS_ARCH),AIX) -ifdef IS_COMPONENT -ifneq ($(HAS_EXTRAEXPORTS),1) -MKSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall -MKCSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall -endif # HAS_EXTRAEXPORTS -endif # IS_COMPONENT -endif # AIX - -# -# OSF1: add -B symbolic flag for components -# -ifeq ($(OS_ARCH),OSF1) -ifdef IS_COMPONENT -ifeq ($(GNU_CC)$(GNU_CXX),) -EXTRA_DSO_LDOPTS += -B symbolic -endif -endif -endif - -# -# Linux: add -Bsymbolic flag for components -# -ifeq ($(OS_ARCH),Linux) -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -endif -endif - -# -# GNU doesn't have path length limitation -# - -ifeq ($(OS_ARCH),GNU) -OS_CPPFLAGS += -DPATH_MAX=1024 -DMAXPATHLEN=1024 -endif - -# -# MINGW32 -# -ifeq ($(OS_ARCH),WINNT) -ifdef GNU_CC -ifndef IS_COMPONENT -DSO_LDOPTS += -Wl,--out-implib -Wl,$(IMPORT_LIBRARY) -endif -endif -endif - -ifeq ($(USE_TVFS),1) -IFLAGS1 = -rb -IFLAGS2 = -rb -else -IFLAGS1 = -m 644 -IFLAGS2 = -m 755 -endif - -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) -OUTOPTION = -Fo# eol -else -OUTOPTION = -o # eol -endif # WINNT && !GNU_CC - -ifneq (,$(filter ml%,$(AS))) -ASOUTOPTION = -Fo# eol -else -ASOUTOPTION = -o # eol -endif - -ifeq (,$(CROSS_COMPILE)) -HOST_OUTOPTION = $(OUTOPTION) -else -HOST_OUTOPTION = -o # eol -endif -################################################################################ - -# SUBMAKEFILES: List of Makefiles for next level down. -# This is used to update or create the Makefiles before invoking them. -SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS)) - -# The root makefile doesn't want to do a plain export/libs, because -# of the tiers and because of libxul. Suppress the default rules in favor -# of something else. Makefiles which use this var *must* provide a sensible -# default rule before including rules.mk -ifndef SUPPRESS_DEFAULT_RULES -ifdef TIERS -default all alldep:: - $(foreach tier,$(TIERS),$(call SUBMAKE,tier_$(tier))) -else - -default all:: -ifneq (,$(strip $(STATIC_DIRS))) - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,,$(dir))) -endif - $(MAKE) export - $(MAKE) libs - $(MAKE) tools - -# Do depend as well -alldep:: - $(MAKE) export - $(MAKE) depend - $(MAKE) libs - $(MAKE) tools - -endif # TIERS -endif # SUPPRESS_DEFAULT_RULES - -ifeq ($(filter s,$(MAKEFLAGS)),) -ECHO := echo -QUIET := -else -ECHO := true -QUIET := -q -endif - -MAKE_TIER_SUBMAKEFILES = +$(if $(tier_$*_dirs),$(MAKE) $(addsuffix /Makefile,$(tier_$*_dirs))) - -$(foreach tier,$(TIERS),tier_$(tier)):: - @$(ECHO) "$@: $($@_staticdirs) $($@_dirs)" - $(foreach dir,$($@_staticdirs),$(call SUBMAKE,,$(dir))) - $(MAKE) export_$@ - $(MAKE) libs_$@ - $(MAKE) tools_$@ - -# Do everything from scratch -everything:: - $(MAKE) clean - $(MAKE) alldep - -# Add dummy depend target for tinderboxes -depend:: - -# Target to only regenerate makefiles -makefiles: $(SUBMAKEFILES) -ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS)) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) -endif - -include $(topsrcdir)/config/makefiles/target_export.mk -include $(topsrcdir)/config/makefiles/target_tools.mk - -# -# Rule to create list of libraries for final link -# -export:: -ifdef LIBRARY_NAME -ifdef EXPORT_LIBRARY -ifdef IS_COMPONENT -else # !IS_COMPONENT - $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME) -endif # IS_COMPONENT -endif # EXPORT_LIBRARY -endif # LIBRARY_NAME - -ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS))) -$(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only) -endif - -# Create dependencies on static (and shared EXTRA_DSO_LIBS) libraries -DO_EXPAND_LIBS = $(foreach f,$(1),$(if $(filter %.$(LIB_SUFFIX),$(f)),$(if $(wildcard $(f).$(LIBS_DESC_SUFFIX)),$(f).$(LIBS_DESC_SUFFIX),$(if $(wildcard $(f)),$(f))))) -LIBS_DEPS = $(call DO_EXPAND_LIBS,$(filter %.$(LIB_SUFFIX),$(LIBS) $(if $(PROGRAM)$(SIMPLE_PROGRAMS),$(MOZ_GLUE_PROGRAM_LDFLAGS)))) -SHARED_LIBRARY_LIBS_DEPS = $(call DO_EXPAND_LIBS,$(SHARED_LIBRARY_LIBS)) -HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS)) -DSO_LDOPTS_DEPS = $(call DO_EXPAND_LIBS,$(EXTRA_DSO_LIBS) $(filter %.$(LIB_SUFFIX), $(EXTRA_DSO_LDOPTS))) - -# Dependencies which, if modified, should cause everything to rebuild -GLOBAL_DEPS += Makefile Makefile.in $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk - -############################################## -include $(topsrcdir)/config/makefiles/target_libs.mk - -############################################## -ifndef NO_PROFILE_GUIDED_OPTIMIZE -ifdef MOZ_PROFILE_USE -ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_) -# When building with PGO, we have to make sure to re-link -# in the MOZ_PROFILE_USE phase if we linked in the -# MOZ_PROFILE_GENERATE phase. We'll touch this pgo.relink -# file in the link rule in the GENERATE phase to indicate -# that we need a relink. -ifdef SHARED_LIBRARY -$(SHARED_LIBRARY): pgo.relink -endif -ifdef PROGRAM -$(PROGRAM): pgo.relink -endif - -# In the second pass, we need to merge the pgc files into the pgd file. -# The compiler would do this for us automatically if they were in the right -# place, but they're in dist/bin. -ifneq (,$(SHARED_LIBRARY)$(PROGRAM)) -export:: -ifdef PROGRAM - $(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \ - $(PROGRAM:$(BIN_SUFFIX)=) $(DIST)/bin -endif -ifdef SHARED_LIBRARY - $(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \ - $(SHARED_LIBRARY_NAME) $(DIST)/bin -endif -endif # SHARED_LIBRARY || PROGRAM -endif # WINNT_ -endif # MOZ_PROFILE_USE -ifdef MOZ_PROFILE_GENERATE -# Clean up profiling data during PROFILE_GENERATE phase -export:: -ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_) - $(foreach pgd,$(wildcard *.pgd),pgomgr -clear $(pgd);) -else -ifdef GNU_CC - -$(RM) *.gcda -endif -endif -endif - -ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE)) -ifdef GNU_CC -# Force rebuilding libraries and programs in both passes because each -# pass uses different object files. -$(PROGRAM) $(SHARED_LIBRARY) $(LIBRARY): FORCE -endif -endif - -endif # NO_PROFILE_GUIDED_OPTIMIZE - -############################################## - -stdc++compat.$(OBJ_SUFFIX): CXXFLAGS+=-DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_TARGET_VERSION) -host_stdc++compat.$(OBJ_SUFFIX): CXXFLAGS+=-DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_HOST_VERSION) - -checkout: - $(MAKE) -C $(topsrcdir) -f client.mk checkout - -clean clobber realclean clobber_all:: $(SUBMAKEFILES) - -$(RM) $(ALL_TRASH) - -$(RM) -r $(ALL_TRASH_DIRS) - $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(STATIC_DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) - -distclean:: $(SUBMAKEFILES) - $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(STATIC_DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) - -$(RM) -r $(ALL_TRASH_DIRS) - -$(RM) $(ALL_TRASH) \ - Makefile .HSancillary \ - $(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \ - $(wildcard *.$(LIB_SUFFIX)) $(wildcard *$(DLL_SUFFIX)) \ - $(wildcard *.$(IMPORT_LIB_SUFFIX)) -ifeq ($(OS_ARCH),OS2) - -$(RM) $(PROGRAM:.exe=.map) -endif - -alltags: - $(RM) TAGS - find $(topsrcdir) -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' -o -name '*.idl' \) -print | $(TAG_PROGRAM) - -# -# PROGRAM = Foo -# creates OBJS, links with LIBS to create Foo -# -$(PROGRAM): $(PROGOBJS) $(LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) $(GLOBAL_DEPS) - @$(RM) $@.manifest -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) - $(EXPAND_LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS) -ifdef MSMANIFEST_TOOL - @if test -f $@.manifest; then \ - if test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest and $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" $@.manifest -OUTPUTRESOURCE:$@\;1; \ - else \ - echo "Embedding manifest from $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ - fi; \ - elif test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" -OUTPUTRESOURCE:$@\;1; \ - fi -endif # MSVC with manifest tool -ifdef MOZ_PROFILE_GENERATE -# touch it a few seconds into the future to work around FAT's -# 2-second granularity - touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink -endif -else # !WINNT || GNU_CC -ifeq ($(CPP_PROG_LINK),1) - $(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) - @$(call CHECK_STDCXX,$@) -else # ! CPP_PROG_LINK - $(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) -endif # CPP_PROG_LINK -endif # WINNT && !GNU_CC - -ifdef ENABLE_STRIP - $(STRIP) $@ -endif -ifdef MOZ_POST_PROGRAM_COMMAND - $(MOZ_POST_PROGRAM_COMMAND) $@ -endif - -$(HOST_PROGRAM): $(HOST_PROGOBJS) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS) -ifeq (_WINNT,$(GNU_CC)_$(HOST_OS_ARCH)) - $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $(HOST_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -ifdef MSMANIFEST_TOOL - @if test -f $@.manifest; then \ - if test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest and $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" $@.manifest -OUTPUTRESOURCE:$@\;1; \ - else \ - echo "Embedding manifest from $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ - fi; \ - elif test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" -OUTPUTRESOURCE:$@\;1; \ - fi -endif # MSVC with manifest tool -else -ifeq ($(HOST_CPP_PROG_LINK),1) - $(HOST_CXX) -o $@ $(HOST_CXXFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -else - $(HOST_CC) -o $@ $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -endif # HOST_CPP_PROG_LINK -endif - -# -# This is an attempt to support generation of multiple binaries -# in one directory, it assumes everything to compile Foo is in -# Foo.o (from either Foo.c or Foo.cpp). -# -# SIMPLE_PROGRAMS = Foo Bar -# creates Foo.o Bar.o, links with LIBS to create Foo, Bar. -# -$(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS) -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) - $(EXPAND_LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS) -ifdef MSMANIFEST_TOOL - @if test -f $@.manifest; then \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ - rm -f $@.manifest; \ - fi -endif # MSVC with manifest tool -else -ifeq ($(CPP_PROG_LINK),1) - $(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) - @$(call CHECK_STDCXX,$@) -else - $(EXPAND_CC) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) -endif # CPP_PROG_LINK -endif # WINNT && !GNU_CC - -ifdef ENABLE_STRIP - $(STRIP) $@ -endif -ifdef MOZ_POST_PROGRAM_COMMAND - $(MOZ_POST_PROGRAM_COMMAND) $@ -endif - -$(HOST_SIMPLE_PROGRAMS): host_%$(HOST_BIN_SUFFIX): host_%.$(OBJ_SUFFIX) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS) -ifeq (WINNT_,$(HOST_OS_ARCH)_$(GNU_CC)) - $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -else -ifneq (,$(HOST_CPPSRCS)$(USE_HOST_CXX)) - $(HOST_CXX) $(HOST_OUTOPTION)$@ $(HOST_CXXFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS) -else - $(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_CFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS) -endif -endif - -# -# Purify target. Solaris/sparc only to start. -# Purify does not recognize "egcs" or "c++" so we go with -# "gcc" and "g++" for now. -# -pure: $(PROGRAM) -ifeq ($(CPP_PROG_LINK),1) - $(PURIFY) $(CCC) -o $^.pure $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -else - $(PURIFY) $(CC) -o $^.pure $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -endif -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS2) $^.pure $(FINAL_TARGET) -endif - -quantify: $(PROGRAM) -ifeq ($(CPP_PROG_LINK),1) - $(QUANTIFY) $(CCC) -o $^.quantify $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -else - $(QUANTIFY) $(CC) -o $^.quantify $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -endif -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS2) $^.quantify $(FINAL_TARGET) -endif - -ifdef DTRACE_PROBE_OBJ -EXTRA_DEPS += $(DTRACE_PROBE_OBJ) -OBJS += $(DTRACE_PROBE_OBJ) -endif - -$(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS) - $(RM) $(LIBRARY) - $(EXPAND_AR) $(AR_FLAGS) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS) - $(RANLIB) $@ - -$(filter-out %.$(LIB_SUFFIX),$(LIBRARY)): $(filter %.$(LIB_SUFFIX),$(LIBRARY)) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS) -# When we only build a library descriptor, blow out any existing library - $(if $(filter %.$(LIB_SUFFIX),$(LIBRARY)),,$(RM) $(REAL_LIBRARY) $(EXPORT_LIBRARY:%=%/$(REAL_LIBRARY))) - $(EXPAND_LIBS_GEN) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS) > $@ - -ifeq ($(OS_ARCH),WINNT) -$(IMPORT_LIBRARY): $(SHARED_LIBRARY) -endif - -ifeq ($(OS_ARCH),OS2) -$(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS) - $(RM) $@ - echo LIBRARY $(SHARED_LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@ - echo PROTMODE >> $@ - echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@ - echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@ - echo EXPORTS >> $@ - - $(ADD_TO_DEF_FILE) - -$(IMPORT_LIBRARY): $(SHARED_LIBRARY) - $(RM) $@ - $(IMPLIB) $@ $^ - $(RANLIB) $@ -endif # OS/2 - -$(HOST_LIBRARY): $(HOST_OBJS) Makefile - $(RM) $@ - $(HOST_AR) $(HOST_AR_FLAGS) $(HOST_OBJS) - $(HOST_RANLIB) $@ - -ifdef HAVE_DTRACE -ifndef XP_MACOSX -ifdef DTRACE_PROBE_OBJ -ifndef DTRACE_LIB_DEPENDENT -NON_DTRACE_OBJS := $(filter-out $(DTRACE_PROBE_OBJ),$(OBJS)) -$(DTRACE_PROBE_OBJ): $(NON_DTRACE_OBJS) - dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(NON_DTRACE_OBJS) -endif -endif -endif -endif - -# On Darwin (Mac OS X), dwarf2 debugging uses debug info left in .o files, -# so instead of deleting .o files after repacking them into a dylib, we make -# symlinks back to the originals. The symlinks are a no-op for stabs debugging, -# so no need to conditionalize on OS version or debugging format. - -$(SHARED_LIBRARY): $(OBJS) $(LOBJS) $(DEF_FILE) $(RESFILE) $(SHARED_LIBRARY_LIBS_DEPS) $(LIBRARY) $(EXTRA_DEPS) $(DSO_LDOPTS_DEPS) $(GLOBAL_DEPS) -ifndef INCREMENTAL_LINKER - $(RM) $@ -endif -ifdef DTRACE_LIB_DEPENDENT -ifndef XP_MACOSX - dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS)) -endif - $(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) - @$(RM) $(DTRACE_PROBE_OBJ) -else # ! DTRACE_LIB_DEPENDENT - $(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) -endif # DTRACE_LIB_DEPENDENT - @$(call CHECK_STDCXX,$@) - -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) -ifdef MSMANIFEST_TOOL -ifdef EMBED_MANIFEST_AT - @if test -f $@.manifest; then \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \ - rm -f $@.manifest; \ - fi -endif # EMBED_MANIFEST_AT -endif # MSVC with manifest tool -ifdef MOZ_PROFILE_GENERATE - touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink -endif -endif # WINNT && !GCC - @$(RM) foodummyfilefoo $(DELETE_AFTER_LINK) - chmod +x $@ -ifdef ENABLE_STRIP - $(STRIP) $@ -endif -ifdef MOZ_POST_DSO_LIB_COMMAND - $(MOZ_POST_DSO_LIB_COMMAND) $@ -endif - -ifdef MOZ_AUTO_DEPS -ifdef COMPILER_DEPEND -ifeq ($(SOLARIS_SUNPRO_CC),1) -_MDDEPFILE = $(MDDEPDIR)/$(@F).pp - -define MAKE_DEPS_AUTO_CC -if test -d $(@D); then \ - echo "Building deps for $< using Sun Studio cc"; \ - $(CC) $(COMPILE_CFLAGS) -xM $< >$(_MDDEPFILE) ; \ -fi -endef -define MAKE_DEPS_AUTO_CXX -if test -d $(@D); then \ - echo "Building deps for $< using Sun Studio CC"; \ - $(CXX) $(COMPILE_CXXFLAGS) -xM $< >$(_MDDEPFILE) ; \ -fi -endef -endif # Sun Studio on Solaris -else # COMPILER_DEPEND -# -# Generate dependencies on the fly -# -_MDDEPFILE = $(MDDEPDIR)/$(@F).pp - -define MAKE_DEPS_AUTO -if test -d $(@D); then \ - echo "Building deps for $<"; \ - $(MKDEPEND) -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $(_MDDEPFILE) ; \ -fi -endef - -MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO) -MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO) - -endif # COMPILER_DEPEND - -endif # MOZ_AUTO_DEPS - -# Rules for building native targets must come first because of the host_ prefix -host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -%:: %.c $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CC) - $(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS) - -%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CC) - $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS) - -# DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs: -# 'moc' only knows about #defines it gets on the command line (-D...), not in -# included headers like mozilla-config.h -moc_%.cpp: %.h $(GLOBAL_DEPS) - $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@ - -moc_%.cc: %.cc $(GLOBAL_DEPS) - $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@ - -qrc_%.cpp: %.qrc $(GLOBAL_DEPS) - $(ELOG) $(RCC) -name $* $< $(OUTOPTION)$@ - -ifdef ASFILES -# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept -# a '-c' flag. -%.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) $(GLOBAL_DEPS) - $(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS) -endif - -%.$(OBJ_SUFFIX): %.S $(GLOBAL_DEPS) - $(AS) -o $@ $(ASFLAGS) -c $< - -%:: %.cpp $(GLOBAL_DEPS) - @$(MAKE_DEPS_AUTO_CXX) - $(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS) - -# -# Please keep the next two rules in sync. -# -%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CXX) - $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) - -%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CXX) -ifdef STRICT_CPLUSPLUS_SUFFIX - echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc - $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc - $(RM) t_$*.cc -else - $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) -endif #STRICT_CPLUSPLUS_SUFFIX - -$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CXX) - $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) - -$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CC) - $(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS) - -%.s: %.cpp - $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) - -%.s: %.cc - $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) - -%.s: %.c - $(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS) - -%.i: %.cpp - $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i - -%.i: %.cc - $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i - -%.i: %.c - $(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i - -%.i: %.mm - $(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i - -%.res: %.rc - @echo Creating Resource file: $@ -ifeq ($(OS_ARCH),OS2) - $(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@ -else -ifdef GNU_CC - $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS) -else - $(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $(_VPATH_SRCS) -endif -endif - -# need 3 separate lines for OS/2 -%:: %.pl - $(RM) $@ - cp $< $@ - chmod +x $@ - -%:: %.sh - $(RM) $@ - cp $< $@ - chmod +x $@ - -# Cancel these implicit rules -# -%: %,v - -%: RCS/%,v - -%: s.% - -%: SCCS/s.% - -############################################################################### -# Java rules -############################################################################### -ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) -SEP := ; -else -SEP := : -endif - -EMPTY := -SPACE := $(EMPTY) $(EMPTY) - -# MSYS has its own special path form, but javac expects the source and class -# paths to be in the DOS form (i.e. e:/builds/...). This function does the -# appropriate conversion on Windows, but is a noop on other systems. -ifeq ($(HOST_OS_ARCH),WINNT) -# We use 'pwd -W' to get DOS form of the path. However, since the given path -# could be a file or a non-existent path, we cannot call 'pwd -W' directly -# on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W' -# on it, then merge with the rest of the path. -root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|") -non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|") -normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1))) -else -normalizepath = $(1) -endif - -_srcdir = $(call normalizepath,$(srcdir)) -ifdef JAVA_SOURCEPATH -SP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_SOURCEPATH)))) -_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)$(SEP)$(SP)" -else -_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)" -endif - -ifdef JAVA_CLASSPATH -CP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_CLASSPATH)))) -_JAVA_CLASSPATH = ".$(SEP)$(CP)" -else -_JAVA_CLASSPATH = . -endif - -_JAVA_DIR = _java -$(_JAVA_DIR):: - $(NSINSTALL) -D $@ - -$(_JAVA_DIR)/%.class: %.java $(GLOBAL_DEPS) $(_JAVA_DIR) - $(JAVAC) $(JAVAC_FLAGS) -classpath $(_JAVA_CLASSPATH) \ - -sourcepath $(_JAVA_SOURCEPATH) -d $(_JAVA_DIR) $(_VPATH_SRCS) - -$(JAVA_LIBRARY): $(addprefix $(_JAVA_DIR)/,$(JAVA_SRCS:.java=.class)) $(GLOBAL_DEPS) - $(JAR) cf $@ -C $(_JAVA_DIR) . - -GARBAGE_DIRS += $(_JAVA_DIR) - -############################################################################### -# Update Makefiles -############################################################################### - -# Note: Passing depth to make-makefile is optional. -# It saves the script some work, though. -Makefile: Makefile.in - @$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) - -ifdef SUBMAKEFILES -# VPATH does not work on some machines in this case, so add $(srcdir) -$(SUBMAKEFILES): % : $(srcdir)/%.in - $(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) $@ -endif - -ifdef AUTOUPDATE_CONFIGURE -$(topsrcdir)/configure: $(topsrcdir)/configure.in - (cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck) -endif - -$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in - cd $(DEPTH) && CONFIG_HEADERS= CONFIG_FILES=config/autoconf.mk ./config.status - -############################################################################### -# Bunch of things that extend the 'export' rule (in order): -############################################################################### - -################################################################################ -# Copy each element of EXPORTS to $(DIST)/include - -ifneq ($(XPI_NAME),) -$(FINAL_TARGET): - $(NSINSTALL) -D $@ - -export:: $(FINAL_TARGET) -endif - -ifndef NO_DIST_INSTALL -ifneq (,$(EXPORTS)) -export:: $(EXPORTS) - $(INSTALL) $(IFLAGS1) $^ $(DIST)/include -endif -endif # NO_DIST_INSTALL - -define EXPORT_NAMESPACE_RULE -ifndef NO_DIST_INSTALL -export:: $(EXPORTS_$(namespace)) - $(INSTALL) $(IFLAGS1) $$^ $(DIST)/include/$(namespace) -endif # NO_DIST_INSTALL -endef - -$(foreach namespace,$(EXPORTS_NAMESPACES),$(eval $(EXPORT_NAMESPACE_RULE))) - -################################################################################ -# Copy each element of PREF_JS_EXPORTS - -ifdef GRE_MODULE -PREF_DIR = greprefs -else -ifneq (,$(XPI_NAME)$(LIBXUL_SDK)) -PREF_DIR = defaults/preferences -else -PREF_DIR = defaults/pref -endif -endif - -ifneq ($(PREF_JS_EXPORTS),) -# on win32, pref files need CRLF line endings... see bug 206029 -ifeq (WINNT,$(OS_ARCH)) -PREF_PPFLAGS = --line-endings=crlf -endif - -ifndef NO_DIST_INSTALL -$(FINAL_TARGET)/$(PREF_DIR): - $(NSINSTALL) -D $@ - -libs:: $(FINAL_TARGET)/$(PREF_DIR) -libs:: $(PREF_JS_EXPORTS) - $(EXIT_ON_ERROR) \ - for i in $^; do \ - dest=$(FINAL_TARGET)/$(PREF_DIR)/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done -endif -endif - -################################################################################ -# Copy each element of AUTOCFG_JS_EXPORTS to $(FINAL_TARGET)/defaults/autoconfig - -ifneq ($(AUTOCFG_JS_EXPORTS),) -$(FINAL_TARGET)/defaults/autoconfig:: - $(NSINSTALL) -D $@ - -ifndef NO_DIST_INSTALL -export:: $(AUTOCFG_JS_EXPORTS) $(FINAL_TARGET)/defaults/autoconfig - $(INSTALL) $(IFLAGS1) $^ -endif - -endif -################################################################################ -# Export the elements of $(XPIDLSRCS) -# generating .h and .xpt files and moving them to the appropriate places. - -ifneq ($(XPIDLSRCS),) - -export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) - -ifndef XPIDL_MODULE -XPIDL_MODULE = $(MODULE) -endif - -ifeq ($(XPIDL_MODULE),) # we need $(XPIDL_MODULE) to make $(XPIDL_MODULE).xpt -export:: FORCE - @echo - @echo "*** Error processing XPIDLSRCS:" - @echo "Please define MODULE or XPIDL_MODULE when defining XPIDLSRCS," - @echo "so we have a module name to use when creating MODULE.xpt." - @echo; sleep 2; false -endif - -# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include; -# warn against overriding existing .h file. -$(XPIDL_GEN_DIR)/.done: - $(MKDIR) -p $(XPIDL_GEN_DIR) - @$(TOUCH) $@ - -# don't depend on $(XPIDL_GEN_DIR), because the modification date changes -# with any addition to the directory, regenerating all .h files -> everything. - -XPIDL_DEPS = \ - $(topsrcdir)/xpcom/idl-parser/header.py \ - $(topsrcdir)/xpcom/idl-parser/typelib.py \ - $(topsrcdir)/xpcom/idl-parser/xpidl.py \ - $(NULL) - -$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done - $(REPORT_BUILD) - $(PYTHON_PATH) \ - -I$(topsrcdir)/other-licenses/ply \ - -I$(topsrcdir)/xpcom/idl-parser \ - $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ - @if test -n "$(findstring $*.h, $(EXPORTS))"; \ - then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi - -ifndef NO_GEN_XPT -# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link -# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components. -$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done - $(REPORT_BUILD) - $(PYTHON_PATH) \ - -I$(topsrcdir)/other-licenses/ply \ - -I$(topsrcdir)/xpcom/idl-parser \ - -I$(topsrcdir)/xpcom/typelib/xpt/tools \ - $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ - -# no need to link together if XPIDLSRCS contains only XPIDL_MODULE -ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS))) -$(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS) - $(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) -endif # XPIDL_MODULE.xpt != XPIDLSRCS - -libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components -ifndef NO_INTERFACES_MANIFEST - @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt" - @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest" -endif -endif - -endif # NO_GEN_XPT - -GARBAGE_DIRS += $(XPIDL_GEN_DIR) - -endif # XPIDLSRCS - -ifneq ($(XPIDLSRCS),) -# export .idl files to $(IDL_DIR) -ifndef NO_DIST_INSTALL -export:: $(XPIDLSRCS) $(IDL_DIR) - $(INSTALL) $(IFLAGS1) $^ - -export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) $(DIST)/include - $(INSTALL) $(IFLAGS1) $^ -endif # NO_DIST_INSTALL - -endif # XPIDLSRCS - - - -# General rules for exporting idl files. -$(IDL_DIR): - $(NSINSTALL) -D $@ - -export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS) - -ifneq ($(XPIDLSRCS),) -ifndef NO_DIST_INSTALL -export-idl:: $(XPIDLSRCS) $(IDL_DIR) - $(INSTALL) $(IFLAGS1) $^ -endif -endif - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -################################################################################ -# Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components -ifneq (,$(filter %.js,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))) -ifeq (,$(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))) -ifndef NO_JS_MANIFEST -$(error .js component without matching .manifest. See https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0) -endif -endif -endif - -ifdef EXTRA_COMPONENTS -libs:: $(EXTRA_COMPONENTS) -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/components -endif - -endif - -ifdef EXTRA_PP_COMPONENTS -libs:: $(EXTRA_PP_COMPONENTS) -ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(FINAL_TARGET)/components; \ - for i in $^; do \ - fname=`basename $$i`; \ - dest=$(FINAL_TARGET)/components/$${fname}; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done -endif -endif - -EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)) -ifneq (,$(EXTRA_MANIFESTS)) -libs:: - $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))) -endif - -################################################################################ -# Copy each element of EXTRA_JS_MODULES to $(FINAL_TARGET)/modules -ifdef EXTRA_JS_MODULES -libs:: $(EXTRA_JS_MODULES) -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/modules -endif - -endif - -ifdef EXTRA_PP_JS_MODULES -libs:: $(EXTRA_PP_JS_MODULES) -ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(FINAL_TARGET)/modules; \ - for i in $^; do \ - dest=$(FINAL_TARGET)/modules/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done -endif - -endif - -################################################################################ -# SDK - -ifneq (,$(SDK_LIBRARY)) -$(SDK_LIB_DIR):: - $(NSINSTALL) -D $@ - -ifndef NO_DIST_INSTALL -libs:: $(SDK_LIBRARY) $(SDK_LIB_DIR) - $(INSTALL) $(IFLAGS2) $^ -endif - -endif # SDK_LIBRARY - -ifneq (,$(strip $(SDK_BINARY))) -$(SDK_BIN_DIR):: - $(NSINSTALL) -D $@ - -ifndef NO_DIST_INSTALL -libs:: $(SDK_BINARY) $(SDK_BIN_DIR) - $(INSTALL) $(IFLAGS2) $^ -endif - -endif # SDK_BINARY - -################################################################################ -# CHROME PACKAGING - -JAR_MANIFEST := $(srcdir)/jar.mn - -chrome:: - $(MAKE) realchrome - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -$(FINAL_TARGET)/chrome: - $(NSINSTALL) -D $@ - -ifneq (,$(wildcard $(JAR_MANIFEST))) -ifndef NO_DIST_INSTALL -libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome - $(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \ - $(QUIET) -j $(FINAL_TARGET)/chrome \ - $(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \ - $(JAR_MANIFEST) -endif -endif - -ifneq ($(DIST_FILES),) -$(DIST)/bin: - $(NSINSTALL) -D $@ - -libs:: $(DIST)/bin -libs:: $(DIST_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done -endif - -ifneq ($(DIST_CHROME_FILES),) -libs:: $(DIST_CHROME_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/chrome/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done -endif - -ifneq ($(XPI_PKGNAME),) -libs realchrome:: -ifdef STRIP_XPI -ifndef MOZ_DEBUG - @echo "Stripping $(XPI_PKGNAME) package directory..." - @echo $(FINAL_TARGET) - @cd $(FINAL_TARGET) && find . ! -type d \ - ! -name "*.js" \ - ! -name "*.xpt" \ - ! -name "*.gif" \ - ! -name "*.jpg" \ - ! -name "*.png" \ - ! -name "*.xpm" \ - ! -name "*.txt" \ - ! -name "*.rdf" \ - ! -name "*.sh" \ - ! -name "*.properties" \ - ! -name "*.dtd" \ - ! -name "*.html" \ - ! -name "*.xul" \ - ! -name "*.css" \ - ! -name "*.xml" \ - ! -name "*.jar" \ - ! -name "*.dat" \ - ! -name "*.tbl" \ - ! -name "*.src" \ - ! -name "*.reg" \ - $(PLATFORM_EXCLUDE_LIST) \ - -exec $(STRIP) $(STRIP_FLAGS) {} >/dev/null 2>&1 \; -endif -endif - @echo "Packaging $(XPI_PKGNAME).xpi..." - cd $(FINAL_TARGET) && $(ZIP) -qr ../$(XPI_PKGNAME).xpi * -endif - -ifdef INSTALL_EXTENSION_ID -ifndef XPI_NAME -$(error XPI_NAME must be set for INSTALL_EXTENSION_ID) -endif - -libs:: - $(RM) -r "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)" - $(NSINSTALL) -D "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)" - cd $(FINAL_TARGET) && tar $(TAR_CREATE_FLAGS) - . | (cd "../../bin/extensions/$(INSTALL_EXTENSION_ID)" && tar -xf -) - -endif - -ifneq (,$(filter flat symlink,$(MOZ_CHROME_FILE_FORMAT))) -_JAR_REGCHROME_DISABLE_JAR=1 -else -_JAR_REGCHROME_DISABLE_JAR=0 -endif - -REGCHROME = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \ - $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \ - $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(FINAL_TARGET)/chrome/installed-chrome.txt \ - $(_JAR_REGCHROME_DISABLE_JAR) - -REGCHROME_INSTALL = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \ - $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \ - $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(DESTDIR)$(mozappdir)/chrome/installed-chrome.txt \ - $(_JAR_REGCHROME_DISABLE_JAR) - - -############################################################################# -# Dependency system -############################################################################# -ifdef COMPILER_DEPEND -depend:: - @echo "$(MAKE): No need to run depend target.\ - Using compiler-based depend." 1>&2 -ifeq ($(GNU_CC)$(GNU_CXX),) -# Non-GNU compilers - @echo "`echo '$(MAKE):'|sed 's/./ /g'`"\ - '(Compiler-based depend was turned on by "--enable-md".)' 1>&2 -else -# GNU compilers - @space="`echo '$(MAKE): '|sed 's/./ /g'`";\ - echo "$$space"'Since you are using a GNU compiler,\ - it is on by default.' 1>&2; \ - echo "$$space"'To turn it off, pass --disable-md to configure.' 1>&2 -endif - -else # ! COMPILER_DEPEND - -ifndef MOZ_AUTO_DEPS - -define MAKE_DEPS_NOAUTO - $(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@ -endef - -$(MDDEPDIR)/%.pp: %.c - $(REPORT_BUILD) - @$(MAKE_DEPS_NOAUTO) - -$(MDDEPDIR)/%.pp: %.cpp - $(REPORT_BUILD) - @$(MAKE_DEPS_NOAUTO) - -$(MDDEPDIR)/%.pp: %.s - $(REPORT_BUILD) - @$(MAKE_DEPS_NOAUTO) - -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) -depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES) -else -depend:: $(SUBMAKEFILES) -endif - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -dependclean:: $(SUBMAKEFILES) - $(RM) $(MDDEPFILES) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -endif # MOZ_AUTO_DEPS - -endif # COMPILER_DEPEND - - -############################################################################# -# MDDEPDIR is the subdirectory where all the dependency files are placed. -# This uses a make rule (instead of a macro) to support parallel -# builds (-jN). If this were done in the LOOP_OVER_DIRS macro, two -# processes could simultaneously try to create the same directory. -# -# We use $(CURDIR) in the rule's target to ensure that we don't find -# a dependency directory in the source tree via VPATH (perhaps from -# a previous build in the source tree) and thus neglect to create a -# dependency directory in the object directory, where we really need -# it. - -$(CURDIR)/$(MDDEPDIR): - $(MKDIR) -p $@ - -ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS))) -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) -MDDEPEND_FILES := $(strip $(wildcard $(MDDEPDIR)/*.pp)) - -ifneq (,$(MDDEPEND_FILES)) -# The script mddepend.pl checks the dependencies and writes to stdout -# one rule to force out-of-date objects. For example, -# foo.o boo.o: FORCE -# The script has an advantage over including the *.pp files directly -# because it handles the case when header files are removed from the build. -# 'make' would complain that there is no way to build missing headers. -ALL_PP_RESULTS = $(shell $(PERL) $(BUILD_TOOLS)/mddepend.pl - $(MDDEPEND_FILES)) -$(eval $(ALL_PP_RESULTS)) -endif - -endif -endif -############################################################################# - --include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk --include $(MY_RULES) - -# -# Generate Emacs tags in a file named TAGS if ETAGS was set in $(MY_CONFIG) -# or in $(MY_RULES) -# -ifdef ETAGS -ifneq ($(CSRCS)$(CPPSRCS)$(HEADERS),) -all:: TAGS -TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS) - $(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS) -endif -endif - -################################################################################ -# Special gmake rules. -################################################################################ - - -# -# Disallow parallel builds with MSVC < 8 -# -ifneq (,$(filter 1200 1300 1310,$(_MSC_VER))) -.NOTPARALLEL: -endif - -# -# Re-define the list of default suffixes, so gmake won't have to churn through -# hundreds of built-in suffix rules for stuff we don't need. -# -.SUFFIXES: - -# -# Fake targets. Always run these rules, even if a file/directory with that -# name already exists. -# -.PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE - -# Used as a dependency to force targets to rebuild -FORCE: - -# Delete target if error occurs when building target -.DELETE_ON_ERROR: - -# Properly set LIBPATTERNS for the platform -.LIBPATTERNS = $(if $(IMPORT_LIB_SUFFIX),$(LIB_PREFIX)%.$(IMPORT_LIB_SUFFIX)) $(LIB_PREFIX)%.$(LIB_SUFFIX) $(DLL_PREFIX)%$(DLL_SUFFIX) - -tags: TAGS - -TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h) - -etags $(CSRCS) $(CPPSRCS) $(wildcard *.h) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - -echo-variable-%: - @echo "$($*)" - -echo-tiers: - @echo $(TIERS) - -echo-tier-dirs: - @$(foreach tier,$(TIERS),echo '$(tier):'; echo ' dirs: $(tier_$(tier)_dirs)'; echo ' staticdirs: $(tier_$(tier)_staticdirs)'; ) - -echo-dirs: - @echo $(DIRS) - -echo-module: - @echo $(MODULE) - -echo-depth-path: - @$(topsrcdir)/build/unix/print-depth-path.sh - -echo-module-name: - @$(topsrcdir)/build/package/rpm/print-module-name.sh - -echo-module-filelist: - @$(topsrcdir)/build/package/rpm/print-module-filelist.sh - -showtargs: -ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS))) - @echo -------------------------------------------------------------------------------- - @echo "PROGRAM = $(PROGRAM)" - @echo "SIMPLE_PROGRAMS = $(SIMPLE_PROGRAMS)" - @echo "LIBRARY = $(LIBRARY)" - @echo "SHARED_LIBRARY = $(SHARED_LIBRARY)" - @echo "SHARED_LIBRARY_LIBS = $(SHARED_LIBRARY_LIBS)" - @echo "LIBS = $(LIBS)" - @echo "DEF_FILE = $(DEF_FILE)" - @echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)" - @echo "STATIC_LIBS = $(STATIC_LIBS)" - @echo "SHARED_LIBS = $(SHARED_LIBS)" - @echo "EXTRA_DSO_LIBS = $(EXTRA_DSO_LIBS)" - @echo "EXTRA_DSO_LDOPTS = $(EXTRA_DSO_LDOPTS)" - @echo "DEPENDENT_LIBS = $(DEPENDENT_LIBS)" - @echo -------------------------------------------------------------------------------- -endif - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - -showbuild: - @echo "MOZ_BUILD_ROOT = $(MOZ_BUILD_ROOT)" - @echo "MOZ_WIDGET_TOOLKIT = $(MOZ_WIDGET_TOOLKIT)" - @echo "CC = $(CC)" - @echo "CXX = $(CXX)" - @echo "CCC = $(CCC)" - @echo "CPP = $(CPP)" - @echo "LD = $(LD)" - @echo "AR = $(AR)" - @echo "IMPLIB = $(IMPLIB)" - @echo "FILTER = $(FILTER)" - @echo "MKSHLIB = $(MKSHLIB)" - @echo "MKCSHLIB = $(MKCSHLIB)" - @echo "RC = $(RC)" - @echo "MC = $(MC)" - @echo "CFLAGS = $(CFLAGS)" - @echo "OS_CFLAGS = $(OS_CFLAGS)" - @echo "COMPILE_CFLAGS = $(COMPILE_CFLAGS)" - @echo "CXXFLAGS = $(CXXFLAGS)" - @echo "OS_CXXFLAGS = $(OS_CXXFLAGS)" - @echo "COMPILE_CXXFLAGS = $(COMPILE_CXXFLAGS)" - @echo "COMPILE_CMFLAGS = $(COMPILE_CMFLAGS)" - @echo "COMPILE_CMMFLAGS = $(COMPILE_CMMFLAGS)" - @echo "LDFLAGS = $(LDFLAGS)" - @echo "OS_LDFLAGS = $(OS_LDFLAGS)" - @echo "DSO_LDOPTS = $(DSO_LDOPTS)" - @echo "OS_INCLUDES = $(OS_INCLUDES)" - @echo "OS_LIBS = $(OS_LIBS)" - @echo "EXTRA_LIBS = $(EXTRA_LIBS)" - @echo "BIN_FLAGS = $(BIN_FLAGS)" - @echo "INCLUDES = $(INCLUDES)" - @echo "DEFINES = $(DEFINES)" - @echo "ACDEFINES = $(ACDEFINES)" - @echo "BIN_SUFFIX = $(BIN_SUFFIX)" - @echo "LIB_SUFFIX = $(LIB_SUFFIX)" - @echo "DLL_SUFFIX = $(DLL_SUFFIX)" - @echo "IMPORT_LIB_SUFFIX = $(IMPORT_LIB_SUFFIX)" - @echo "INSTALL = $(INSTALL)" - @echo "VPATH = $(VPATH)" - -showhost: - @echo "HOST_CC = $(HOST_CC)" - @echo "HOST_CXX = $(HOST_CXX)" - @echo "HOST_CFLAGS = $(HOST_CFLAGS)" - @echo "HOST_LDFLAGS = $(HOST_LDFLAGS)" - @echo "HOST_LIBS = $(HOST_LIBS)" - @echo "HOST_EXTRA_LIBS = $(HOST_EXTRA_LIBS)" - @echo "HOST_EXTRA_DEPS = $(HOST_EXTRA_DEPS)" - @echo "HOST_PROGRAM = $(HOST_PROGRAM)" - @echo "HOST_OBJS = $(HOST_OBJS)" - @echo "HOST_PROGOBJS = $(HOST_PROGOBJS)" - @echo "HOST_LIBRARY = $(HOST_LIBRARY)" - -showbuildmods:: - @echo "Module dirs = $(BUILD_MODULE_DIRS)" - -documentation: - @cd $(DEPTH) - $(DOXYGEN) $(DEPTH)/config/doxygen.cfg - -ifdef ENABLE_TESTS -check:: $(SUBMAKEFILES) $(MAKE_DIRS) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) -endif - - -FREEZE_VARIABLES = \ - CSRCS \ - CPPSRCS \ - EXPORTS \ - XPIDLSRCS \ - DIRS \ - LIBRARY \ - MODULE \ - SHORT_LIBNAME \ - TIERS \ - EXTRA_COMPONENTS \ - EXTRA_PP_COMPONENTS \ - $(NULL) - -$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))')) - -CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \ - $(if $(subst $($(var)_FROZEN),,'$($(var))'),$(error Makefile variable '$(var)' changed value after including rules.mk. Was $($(var)_FROZEN), now $($(var)).))) - -libs export libs:: - $(CHECK_FROZEN_VARIABLES) - -default all:: - if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi diff --git a/configure.in b/configure.in index cb8107ace381..66d31340972a 100644 --- a/configure.in +++ b/configure.in @@ -8403,6 +8403,7 @@ AC_SUBST(MOZ_ANDROID_HISTORY) AC_SUBST(MOZ_WEBSMS_BACKEND) AC_SUBST(ENABLE_STRIP) AC_SUBST(PKG_SKIP_STRIP) +AC_SUBST(STRIP_FLAGS) AC_SUBST(USE_ELF_DYNSTR_GC) AC_SUBST(USE_ELF_HACK) AC_SUBST(INCREMENTAL_LINKER) diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index ad80d55fc86f..7722ee2f687b 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -135,6 +135,7 @@ #include "nsIRequest.h" #include "nsHtml5TreeOpExecutor.h" #include "nsHtml5Parser.h" +#include "nsIDOMJSWindow.h" using namespace mozilla; using namespace mozilla::dom; @@ -1326,9 +1327,10 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl, if (!window) { return NS_OK; } + nsCOMPtr win = do_QueryInterface(window); nsCOMPtr newWindow; - nsresult rv = window->Open(aContentTypeOrUrl, aReplaceOrName, aFeatures, - getter_AddRefs(newWindow)); + nsresult rv = win->OpenJS(aContentTypeOrUrl, aReplaceOrName, aFeatures, + getter_AddRefs(newWindow)); *aReturn = newWindow.forget().get(); return rv; } diff --git a/content/html/document/test/Makefile.in b/content/html/document/test/Makefile.in index 6bbebcb674ad..23d6ae90ef6f 100644 --- a/content/html/document/test/Makefile.in +++ b/content/html/document/test/Makefile.in @@ -107,6 +107,7 @@ _TEST_FILES = test_bug1682.html \ test_bug677495.html \ test_bug677495-1.html \ test_bug742261.html \ + test_bug741266.html \ $(NULL) ifneq (mobile,$(MOZ_BUILD_APP)) diff --git a/content/html/document/test/test_bug741266.html b/content/html/document/test/test_bug741266.html new file mode 100644 index 000000000000..1da30079d8ea --- /dev/null +++ b/content/html/document/test/test_bug741266.html @@ -0,0 +1,35 @@ + + + + + + Test for Bug 741266 + + + + +Mozilla Bug 741266 +

+ +
+
+
+ + diff --git a/content/xbl/src/nsXBLService.cpp b/content/xbl/src/nsXBLService.cpp index bf71a64e91ca..ebe97a1d80fb 100644 --- a/content/xbl/src/nsXBLService.cpp +++ b/content/xbl/src/nsXBLService.cpp @@ -400,7 +400,7 @@ nsXBLStreamListener::HandleEvent(nsIDOMEvent* aEvent) if (!bindingDocument->GetRootElement()) { // FIXME: How about an error console warning? - NS_WARNING("*** XBL doc with no root element! Something went horribly wrong! ***"); + NS_WARNING("XBL doc with no root element - this usually shouldn't happen"); return NS_ERROR_FAILURE; } diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index 42a124b845f4..9754c097ef90 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -1,6 +1,6 @@ # This Source Code Form is subject to the terms of the Mozilla Public -# # License, v. 2.0. If a copy of the MPL was not distributed with this file, -# # You can obtain one at http://mozilla.org/MPL/2.0/. +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. DEPTH = ../.. topsrcdir = @top_srcdir@ @@ -75,18 +75,20 @@ bindinggen_dependencies := \ $(binding_header_files): %Binding.h: $(bindinggen_dependencies) \ $(webidl_base)/%.webidl \ $(NULL) - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \ - $(srcdir)/BindingGen.py $(ACCESSOR_OPT) header $(srcdir)/Bindings.conf $*Binding \ - $(webidl_base)/$*.webidl + $(PYTHON_PATH) \ + $(PLY_INCLUDE) -I$(srcdir)/parser \ + $(srcdir)/BindingGen.py $(ACCESSOR_OPT) header \ + $(srcdir)/Bindings.conf $*Binding \ + $(webidl_base)/$*.webidl $(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \ $(webidl_base)/%.webidl \ $(NULL) - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \ - $(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp $(srcdir)/Bindings.conf $*Binding \ - $(webidl_base)/$*.webidl + $(PYTHON_PATH) \ + $(PLY_INCLUDE) -I$(srcdir)/parser \ + $(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp \ + $(srcdir)/Bindings.conf $*Binding \ + $(webidl_base)/$*.webidl $(globalgen_targets): ParserResults.pkl @@ -108,7 +110,7 @@ $(CACHE_DIR)/.done: ParserResults.pkl: $(globalgen_dependencies) \ $(addprefix $(webidl_base)/, $(webidl_files)) $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \ + $(PLY_INCLUDE) -I$(srcdir)/parser \ $(srcdir)/GlobalGen.py $(ACCESSOR_OPT) $(srcdir)/Bindings.conf $(webidl_base) \ --cachedir=$(CACHE_DIR) \ $(webidl_files) diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js index 6b7ec81fde15..4c4eaf1d1b84 100644 --- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -593,6 +593,24 @@ const PDU_MAX_USER_DATA_8BIT = 140; // User Data max length in chars const PDU_MAX_USER_DATA_UCS2 = 70; +// PID - Protocol Indicator +const PDU_PID_DEFAULT = 0x00; +const PDU_PID_TELEMATIC_INTERWORKING = 0x20; +const PDU_PID_SHORT_MESSAGE_TYPE_0 = 0x40; +const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 = 0x41; +const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_2 = 0x42; +const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_3 = 0x43; +const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_4 = 0x44; +const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_5 = 0x45; +const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_6 = 0x46; +const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7 = 0x47; +const PDU_PID_ENHANDED_MESSAGE_SERVICE = 0x5E; +const PDU_PID_RETURN_CALL_MESSAGE = 0x5F +const PDU_PID_ANSI_136_R_DATA = 0x7C; +const PDU_PID_ME_DATA_DOWNLOAD = 0x7D; +const PDU_PID_ME_DEPERSONALIZATION = 0x7E; +const PDU_PID_USIM_DATA_DOWNLOAD = 0x7F; + // DCS - Data Coding Scheme const PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00; const PDU_DCS_MSG_CODING_8BITS_ALPHABET = 0x04; diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 6481d360f7d4..60d4b93dd14e 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -1518,6 +1518,13 @@ let RIL = { return PDU_FCS_UNSPECIFIED; } + if (message.epid == PDU_PID_SHORT_MESSAGE_TYPE_0) { + // `A short message type 0 indicates that the ME must acknowledge receipt + // of the short message but shall discard its contents.` ~ 3GPP TS 23.040 + // 9.2.3.9 + return PDU_FCS_OK; + } + if (message.header && (message.header.segmentMaxSeq > 1)) { message = this._processReceivedSmsSegment(message); } else { @@ -2233,7 +2240,7 @@ RIL[REQUEST_DEVICE_IDENTITY] = null; RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = null; RIL[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) { if (options.rilRequestError) { - if (options.body) { + if (options.type == "sendSMS") { this.sendDOMMessage({ type: "sms-send-failed", envelopeId: options.envelopeId, @@ -2928,6 +2935,32 @@ let GsmPDUHelper = { return addr; }, + /** + * Read TP-Protocol-Indicator(TP-PID). + * + * @param msg + * message object for output. + * + * @see 3GPP TS 23.040 9.2.3.9 + */ + readProtocolIndicator: function readProtocolIndicator(msg) { + // `The MS shall interpret reserved, obsolete, or unsupported values as the + // value 00000000 but shall store them exactly as received.` + msg.pid = this.readHexOctet(); + + msg.epid = msg.pid; + switch (msg.epid & 0xC0) { + case 0x40: + // Bit 7..0 = 01xxxxxx + switch (msg.epid) { + case PDU_PID_SHORT_MESSAGE_TYPE_0: + return; + } + break; + } + msg.epid = PDU_PID_DEFAULT; + }, + /** * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS). * @@ -2943,14 +2976,14 @@ let GsmPDUHelper = { let timestamp = Date.UTC(year, month, day, hour, minute, second); // If the most significant bit of the least significant nibble is 1, - // the timezone offset is negative (fourth bit from the right => 0x08). + // the timezone offset is negative (fourth bit from the right => 0x08): + // localtime = UTC + tzOffset + // therefore + // UTC = localtime - tzOffset let tzOctet = this.readHexOctet(); let tzOffset = this.octetToBCD(tzOctet & ~0x08) * 15 * 60 * 1000; - if (tzOctet & 0x08) { - timestamp -= tzOffset; - } else { - timestamp += tzOffset; - } + tzOffset = (tzOctet & 0x08) ? -tzOffset : tzOffset; + timestamp -= tzOffset; return timestamp; }, @@ -3074,7 +3107,7 @@ let GsmPDUHelper = { // TP-Protocol-Identifier if (pi & PDU_PI_PROTOCOL_IDENTIFIER) { - msg.pid = this.readHexOctet(); + this.readProtocolIndicator(msg); } // TP-Data-Coding-Scheme if (pi & PDU_PI_DATA_CODING_SCHEME) { @@ -3106,6 +3139,7 @@ let GsmPDUHelper = { sender: null, // M X X X X X recipient: null, // X X M X M M pid: null, // M O M O O M + epid: null, // M O M O O M dcs: null, // M O M O O X body: null, // M O M O O O timestamp: null, // M X X X X X @@ -3157,7 +3191,7 @@ let GsmPDUHelper = { let senderAddressLength = this.readHexOctet(); msg.sender = this.readAddress(senderAddressLength); // - TP-Protocolo-Identifier - - msg.pid = this.readHexOctet(); + this.readProtocolIndicator(msg); // - TP-Data-Coding-Scheme - msg.dcs = this.readHexOctet(); // - TP-Service-Center-Time-Stamp - diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 96b87882994d..650ec2550caa 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -2802,8 +2802,7 @@ WorkerPrivate::OperationCallback(JSContext* aCx) } // Clean up before suspending. - JS_FlushCaches(aCx); - JS_GC(aCx); + JS_GC(JS_GetRuntime(aCx)); while ((mayContinue = MayContinueRunning())) { MutexAutoLock lock(mMutex); @@ -3891,12 +3890,13 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking, { AssertIsOnWorkerThread(); - js::PrepareForFullGC(JS_GetRuntime(aCx)); + JSRuntime *rt = JS_GetRuntime(aCx); + js::PrepareForFullGC(rt); if (aShrinking) { - js::ShrinkingGC(aCx, js::gcreason::DOM_WORKER); + js::ShrinkingGC(rt, js::gcreason::DOM_WORKER); } else { - js::GCForReason(aCx, js::gcreason::DOM_WORKER); + js::GCForReason(rt, js::gcreason::DOM_WORKER); } if (aCollectChildren) { diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index a954ad8edf44..14af705c5604 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -1846,7 +1846,7 @@ public class GeckoAppShell } // This is only used in Native Fennec. - public static void setPreventPanning(final boolean aPreventPanning) { } + public static void notifyDefaultPrevented(boolean defaultPrevented) { } public static short getScreenOrientation() { return GeckoScreenOrientationListener.getInstance().getScreenOrientation(); diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 4571732a0511..23eb3091d8d6 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -107,6 +107,7 @@ static const char *sExtensionNames[] = { "GL_OES_rgb8_rgba8", "GL_ARB_robustness", "GL_EXT_robustness", + "GL_ARB_sync", NULL }; @@ -450,6 +451,32 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) mSymbols.fRenderbufferStorageMultisample = nsnull; } } + + if (IsExtensionSupported(ARB_sync)) { + SymLoadStruct syncSymbols[] = { + { (PRFuncPtr*) &mSymbols.fFenceSync, { "FenceSync", nsnull } }, + { (PRFuncPtr*) &mSymbols.fIsSync, { "IsSync", nsnull } }, + { (PRFuncPtr*) &mSymbols.fDeleteSync, { "DeleteSync", nsnull } }, + { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nsnull } }, + { (PRFuncPtr*) &mSymbols.fWaitSync, { "WaitSync", nsnull } }, + { (PRFuncPtr*) &mSymbols.fGetInteger64v, { "GetInteger64v", nsnull } }, + { (PRFuncPtr*) &mSymbols.fGetSynciv, { "GetSynciv", nsnull } }, + { nsnull, { nsnull } }, + }; + + if (!LoadSymbols(&syncSymbols[0], trygl, prefix)) { + NS_ERROR("GL supports ARB_sync without supplying its functions."); + + MarkExtensionUnsupported(ARB_sync); + mSymbols.fFenceSync = nsnull; + mSymbols.fIsSync = nsnull; + mSymbols.fDeleteSync = nsnull; + mSymbols.fClientWaitSync = nsnull; + mSymbols.fWaitSync = nsnull; + mSymbols.fGetInteger64v = nsnull; + mSymbols.fGetSynciv = nsnull; + } + } // Load developer symbols, don't fail if we can't find them. SymLoadStruct auxSymbols[] = { diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index e3529e94f219..68d91cf7e870 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -1500,6 +1500,7 @@ public: OES_rgb8_rgba8, ARB_robustness, EXT_robustness, + ARB_sync, Extensions_Max }; @@ -2898,6 +2899,51 @@ public: return ret; } + GLsync GLAPIENTRY fFenceSync(GLenum condition, GLbitfield flags) { + BEFORE_GL_CALL; + GLsync ret = mSymbols.fFenceSync(condition, flags); + AFTER_GL_CALL; + return ret; + } + + realGLboolean GLAPIENTRY fIsSync(GLsync sync) { + BEFORE_GL_CALL; + realGLboolean ret = mSymbols.fIsSync(sync); + AFTER_GL_CALL; + return ret; + } + + void GLAPIENTRY fDeleteSync(GLsync sync) { + BEFORE_GL_CALL; + mSymbols.fDeleteSync(sync); + AFTER_GL_CALL; + } + + GLenum GLAPIENTRY fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { + BEFORE_GL_CALL; + GLenum ret = mSymbols.fClientWaitSync(sync, flags, timeout); + AFTER_GL_CALL; + return ret; + } + + void GLAPIENTRY fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { + BEFORE_GL_CALL; + mSymbols.fWaitSync(sync, flags, timeout); + AFTER_GL_CALL; + } + + void GLAPIENTRY fGetInteger64v(GLenum pname, GLint64 *params) { + BEFORE_GL_CALL; + mSymbols.fGetInteger64v(pname, params); + AFTER_GL_CALL; + } + + void GLAPIENTRY fGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) { + BEFORE_GL_CALL; + mSymbols.fGetSynciv(sync, pname, bufSize, length, values); + AFTER_GL_CALL; + } + #ifdef DEBUG void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName); void THEBES_API CreatedShader(GLContext *aOrigin, GLuint aName); diff --git a/gfx/gl/GLContextSymbols.h b/gfx/gl/GLContextSymbols.h index 51f6164eda4f..2bd11684fae8 100644 --- a/gfx/gl/GLContextSymbols.h +++ b/gfx/gl/GLContextSymbols.h @@ -40,6 +40,8 @@ #ifndef GLCONTEXTSYMBOLS_H_ #define GLCONTEXTSYMBOLS_H_ +#include "GLDefs.h" + /* * This file should only be included by GLContext.h, and should be * autogenerated in the future. @@ -381,6 +383,24 @@ struct GLContextSymbols typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUS) (void); PFNGLGETGRAPHICSRESETSTATUS fGetGraphicsResetStatus; + + /* + * ARB_sync extension + */ + typedef GLsync (GLAPIENTRY * PFNGLFENCESYNC) (GLenum condition, GLbitfield flags); + PFNGLFENCESYNC fFenceSync; + typedef realGLboolean (GLAPIENTRY * PFNGLISSYNC) (GLsync sync); + PFNGLISSYNC fIsSync; + typedef void (GLAPIENTRY * PFNGLDELETESYNC) (GLsync sync); + PFNGLDELETESYNC fDeleteSync; + typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNC) (GLsync sync, GLbitfield flags, GLuint64 timeout); + PFNGLCLIENTWAITSYNC fClientWaitSync; + typedef void (GLAPIENTRY * PFNGLWAITSYNC) (GLsync sync, GLbitfield flags, GLuint64 timeout); + PFNGLWAITSYNC fWaitSync; + typedef void (GLAPIENTRY * PFNGLGETINTEGER64V) (GLenum pname, GLint64 *params); + PFNGLGETINTEGER64V fGetInteger64v; + typedef void (GLAPIENTRY * PFNGLGETSYNCIV) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); + PFNGLGETSYNCIV fGetSynciv; }; } diff --git a/gfx/gl/GLDefs.h b/gfx/gl/GLDefs.h index 9cad4eaba99f..ede59e186350 100644 --- a/gfx/gl/GLDefs.h +++ b/gfx/gl/GLDefs.h @@ -37,7 +37,6 @@ * ***** END LICENSE BLOCK ***** */ #if !defined(LOCALGL_H_) - #define LOCALGL_H_ #if !defined(__gltypes_h_) && !defined(__gl_h_) @@ -72,6 +71,14 @@ typedef ptrdiff_t GLintptr; #endif /* #if !defined(__gltypes_h_) && !defined(__gl_h_) */ +#include "mozilla/StandardInteger.h" + +// ARB_sync +typedef struct __GLsync *GLsync; +typedef int64_t GLint64; +typedef uint64_t GLuint64; + + #ifndef GLAPIENTRY # ifdef WIN32 # define GLAPIENTRY APIENTRY @@ -3032,6 +3039,23 @@ typedef ptrdiff_t GLintptr; #define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC #define LOCAL_GL_WIN_swap_hint 1 +// ARB_sync +#define LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define LOCAL_GL_OBJECT_TYPE 0x9112 +#define LOCAL_GL_SYNC_CONDITION 0x9113 +#define LOCAL_GL_SYNC_STATUS 0x9114 +#define LOCAL_GL_SYNC_FLAGS 0x9115 +#define LOCAL_GL_SYNC_FENCE 0x9116 +#define LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define LOCAL_GL_UNSIGNALED 0x9118 +#define LOCAL_GL_SIGNALED 0x9119 +#define LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define LOCAL_GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define LOCAL_GL_ALREADY_SIGNALED 0x911A +#define LOCAL_GL_TIMEOUT_EXPIRED 0x911B +#define LOCAL_GL_CONDITION_SATISFIED 0x911C +#define LOCAL_GL_WAIT_FAILED 0x911D + #define LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB #define LOCAL_GL_MAX_VARYING_VECTORS 0x8DFC #define LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 4928eed3e73e..734f1119d9f0 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -375,84 +375,78 @@ gfxDWriteFontEntry::ReadCMAP() nsresult rv; // attempt this once, if errors occur leave a blank cmap - if (mCmapInitialized) + if (mCharacterMap) { return NS_OK; - mCmapInitialized = true; + } + + nsRefPtr charmap = new gfxCharacterMap(); // if loading via GDI, just use GetFontTable if (mFont && gfxDWriteFontList::PlatformFontList()->UseGDIFontTableAccess()) { - const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p'); - AutoFallibleTArray buffer; + PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p'); + nsresult rv; - if (GetFontTable(kCmapTag, buffer) != NS_OK) - return NS_ERROR_FAILURE; - PRUint8 *cmap = buffer.Elements(); + AutoFallibleTArray cmap; + rv = GetFontTable(kCMAP, cmap); - bool unicodeFont = false, symbolFont = false; - rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(), - mCharacterMap, mUVSOffset, - unicodeFont, symbolFont); -#ifdef PR_LOGGING - LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", - NS_ConvertUTF16toUTF8(mName).get(), - mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); - if (LOG_CMAPDATA_ENABLED()) { - char prefix[256]; - sprintf(prefix, "(cmapdata) name: %.220s", - NS_ConvertUTF16toUTF8(mName).get()); - mCharacterMap.Dump(prefix, eGfxLog_cmapdata); + bool unicodeFont = false, symbolFont = false; // currently ignored + + if (NS_SUCCEEDED(rv)) { + rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(), + *charmap, mUVSOffset, + unicodeFont, symbolFont); + } + } else { + // loading using dwrite, don't use GetFontTable to avoid copy + nsRefPtr fontFace; + rv = CreateFontFace(getter_AddRefs(fontFace)); + + if (NS_SUCCEEDED(rv)) { + const PRUint32 kCmapTag = DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p'); + PRUint8 *tableData; + PRUint32 len; + void *tableContext = NULL; + BOOL exists; + hr = fontFace->TryGetFontTable(kCmapTag, (const void**)&tableData, + &len, &tableContext, &exists); + + if (SUCCEEDED(hr)) { + bool isSymbol = fontFace->IsSymbolFont(); + bool isUnicode = true; + if (exists) { + rv = gfxFontUtils::ReadCMAP(tableData, len, *charmap, + mUVSOffset, isUnicode, + isSymbol); + } + fontFace->ReleaseFontTable(tableContext); + } else { + rv = NS_ERROR_FAILURE; + } } -#endif - mHasCmapTable = NS_SUCCEEDED(rv); - return rv; } - // loading using dwrite, don't use GetFontTable to avoid copy - nsRefPtr fontFace; - rv = CreateFontFace(getter_AddRefs(fontFace)); - - if (NS_FAILED(rv)) { - return rv; + mHasCmapTable = NS_SUCCEEDED(rv); + if (mHasCmapTable) { + gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); + mCharacterMap = pfl->FindCharMap(charmap); + } else { + // if error occurred, initialize to null cmap + mCharacterMap = new gfxCharacterMap(); } - PRUint8 *tableData; - PRUint32 len; - void *tableContext = NULL; - BOOL exists; - hr = fontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p'), - (const void**)&tableData, - &len, - &tableContext, - &exists); - if (FAILED(hr)) { - return NS_ERROR_FAILURE; - } - - bool isSymbol = fontFace->IsSymbolFont(); - bool isUnicode = true; - if (exists) { - rv = gfxFontUtils::ReadCMAP(tableData, - len, - mCharacterMap, - mUVSOffset, - isUnicode, - isSymbol); - } - fontFace->ReleaseFontTable(tableContext); - #ifdef PR_LOGGING - LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", + LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n", NS_ConvertUTF16toUTF8(mName).get(), - mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); + charmap->SizeOfIncludingThis(moz_malloc_size_of), + charmap->mHash, mCharacterMap == charmap ? " new" : "")); if (LOG_CMAPDATA_ENABLED()) { char prefix[256]; sprintf(prefix, "(cmapdata) name: %.220s", NS_ConvertUTF16toUTF8(mName).get()); - mCharacterMap.Dump(prefix, eGfxLog_cmapdata); + charmap->Dump(prefix, eGfxLog_cmapdata); } #endif - mHasCmapTable = NS_SUCCEEDED(rv); return rv; } diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index 82c1819f57d6..a3161fc0c81e 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -343,12 +343,11 @@ FT2FontEntry::CairoFontFace() nsresult FT2FontEntry::ReadCMAP() { - if (mCmapInitialized) { + if (mCharacterMap) { return NS_OK; } - // attempt this once, if errors occur leave a blank cmap - mCmapInitialized = true; + nsRefPtr charmap = new gfxCharacterMap(); AutoFallibleTArray buffer; nsresult rv = GetFontTable(TTAG_cmap, buffer); @@ -357,11 +356,18 @@ FT2FontEntry::ReadCMAP() bool unicodeFont; bool symbolFont; rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(), - mCharacterMap, mUVSOffset, + *charmap, mUVSOffset, unicodeFont, symbolFont); } mHasCmapTable = NS_SUCCEEDED(rv); + if (mHasCmapTable) { + gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); + mCharacterMap = pfl->FindCharMap(charmap); + } else { + // if error occurred, initialize to null cmap + mCharacterMap = new gfxCharacterMap(); + } return rv; } diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index be9dfeab53c1..57c5429de38f 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -103,6 +103,16 @@ static PRUint32 gGlyphExtentsSetupLazyTight = 0; static PRUint32 gGlyphExtentsSetupFallBackToTight = 0; #endif +void +gfxCharacterMap::NotifyReleased() +{ + gfxPlatformFontList *fontlist = gfxPlatformFontList::PlatformFontList(); + if (mShared) { + fontlist->RemoveCmap(this); + } + delete this; +} + gfxFontEntry::~gfxFontEntry() { delete mUserFontData; @@ -115,18 +125,20 @@ bool gfxFontEntry::IsSymbolFont() bool gfxFontEntry::TestCharacterMap(PRUint32 aCh) { - if (!mCmapInitialized) { + if (!mCharacterMap) { ReadCMAP(); + NS_ASSERTION(mCharacterMap, "failed to initialize character map"); } - return mCharacterMap.test(aCh); + return mCharacterMap->test(aCh); } nsresult gfxFontEntry::InitializeUVSMap() { // mUVSOffset will not be initialized // until cmap is initialized. - if (!mCmapInitialized) { + if (!mCharacterMap) { ReadCMAP(); + NS_ASSERTION(mCharacterMap, "failed to initialize character map"); } if (!mUVSOffset) { @@ -170,7 +182,8 @@ PRUint16 gfxFontEntry::GetUVSGlyph(PRUint32 aCh, PRUint32 aVS) nsresult gfxFontEntry::ReadCMAP() { - mCmapInitialized = true; + NS_ASSERTION(false, "using default no-op implementation of ReadCMAP"); + mCharacterMap = new gfxCharacterMap(); return NS_OK; } @@ -433,7 +446,12 @@ gfxFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, FontListSizes* aSizes) const { aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); - aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf); + + // cmaps are shared so only non-shared cmaps are included here + if (mCharacterMap && mCharacterMap->mBuildOnTheFly) { + aSizes->mCharMapsSize += + mCharacterMap->SizeOfIncludingThis(aMallocSizeOf); + } aSizes->mFontTableCacheSize += mFontTableCache.SizeOfExcludingThis( FontTableHashEntry::SizeOfEntryExcludingThis, @@ -770,7 +788,7 @@ CalcStyleMatch(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle) void gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData) { - if (mCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) { + if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) { // none of the faces in the family support the required char, // so bail out immediately return; @@ -1028,7 +1046,8 @@ gfxFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, { aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); - aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf); + aSizes->mCharMapsSize += + mFamilyCharacterMap.SizeOfExcludingThis(aMallocSizeOf); aSizes->mFontListSize += mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf); @@ -3647,7 +3666,9 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh, // check other faces of the family gfxFontFamily *family = font->GetFontEntry()->Family(); - if (family && family->TestCharacterMap(aCh)) { + if (family && !font->GetFontEntry()->mIsProxy && + family->TestCharacterMap(aCh)) + { GlobalFontMatch matchData(aCh, aRunScript, &mStyle); family->SearchAllFontsForChar(&matchData); gfxFontEntry *fe = matchData.mBestMatch; diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 460596e460bc..b2245a987de1 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -198,6 +198,56 @@ struct THEBES_API gfxFontStyle { static PRUint32 ParseFontLanguageOverride(const nsString& aLangTag); }; +class gfxCharacterMap : public gfxSparseBitSet { +public: + nsrefcnt AddRef() { + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this)); + return mRefCnt; + } + + nsrefcnt Release() { + NS_PRECONDITION(0 != mRefCnt, "dup release"); + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap"); + if (mRefCnt == 0) { + NotifyReleased(); + // |this| has been deleted. + return 0; + } + return mRefCnt; + } + + gfxCharacterMap() : + mHash(0), mBuildOnTheFly(false), mShared(false) + { } + + void CalcHash() { mHash = GetChecksum(); } + + size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const { + return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf); + } + + // hash of the cmap bitvector + PRUint32 mHash; + + // if cmap is built on the fly it's never shared + bool mBuildOnTheFly; + + // cmap is shared globally + bool mShared; + +protected: + void NotifyReleased(); + + nsAutoRefCnt mRefCnt; + +private: + gfxCharacterMap(const gfxCharacterMap&); + gfxCharacterMap& operator=(const gfxCharacterMap&); +}; + class gfxFontEntry { public: NS_INLINE_DECL_REFCOUNTING(gfxFontEntry) @@ -216,7 +266,6 @@ public: mCheckedForGraphiteTables(false), #endif mHasCmapTable(false), - mCmapInitialized(false), mUVSOffset(0), mUVSData(nsnull), mUserFontData(nsnull), mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), @@ -259,16 +308,17 @@ public: #endif inline bool HasCmapTable() { - if (!mCmapInitialized) { + if (!mCharacterMap) { ReadCMAP(); + NS_ASSERTION(mCharacterMap, "failed to initialize character map"); } return mHasCmapTable; } inline bool HasCharacter(PRUint32 ch) { - if (mCharacterMap.test(ch)) + if (mCharacterMap && mCharacterMap->test(ch)) { return true; - + } return TestCharacterMap(ch); } @@ -344,8 +394,7 @@ public: bool mCheckedForGraphiteTables; #endif bool mHasCmapTable; - bool mCmapInitialized; - gfxSparseBitSet mCharacterMap; + nsRefPtr mCharacterMap; PRUint32 mUVSOffset; nsAutoArrayPtr mUVSData; gfxUserFontData* mUserFontData; @@ -375,7 +424,6 @@ protected: mCheckedForGraphiteTables(false), #endif mHasCmapTable(false), - mCmapInitialized(false), mUVSOffset(0), mUVSData(nsnull), mUserFontData(nsnull), mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), @@ -529,7 +577,7 @@ public: mHasStyles(false), mIsSimpleFamily(false), mIsBadUnderlineFamily(false), - mCharacterMapInitialized(false) + mFamilyCharacterMapInitialized(false) { } virtual ~gfxFontFamily() { @@ -607,26 +655,27 @@ public: PRUint32 i, numFonts = mAvailableFonts.Length(); for (i = 0; i < numFonts; i++) { gfxFontEntry *fe = mAvailableFonts[i]; - if (!fe) { + // don't try to load cmaps for downloadable fonts not yet loaded + if (!fe || fe->mIsProxy) { continue; } fe->ReadCMAP(); - mCharacterMap.Union(fe->mCharacterMap); + mFamilyCharacterMap.Union(*(fe->mCharacterMap)); } - mCharacterMap.Compact(); - mCharacterMapInitialized = true; + mFamilyCharacterMap.Compact(); + mFamilyCharacterMapInitialized = true; } bool TestCharacterMap(PRUint32 aCh) { - if (!mCharacterMapInitialized) { + if (!mFamilyCharacterMapInitialized) { ReadAllCMAPs(); } - return mCharacterMap.test(aCh); + return mFamilyCharacterMap.test(aCh); } void ResetCharacterMap() { - mCharacterMap.reset(); - mCharacterMapInitialized = false; + mFamilyCharacterMap.reset(); + mFamilyCharacterMapInitialized = false; } // mark this family as being in the "bad" underline offset blacklist @@ -675,14 +724,14 @@ protected: nsString mName; nsTArray > mAvailableFonts; - gfxSparseBitSet mCharacterMap; - bool mOtherFamilyNamesInitialized; - bool mHasOtherFamilyNames; - bool mFaceNamesInitialized; - bool mHasStyles; - bool mIsSimpleFamily; - bool mIsBadUnderlineFamily; - bool mCharacterMapInitialized; + gfxSparseBitSet mFamilyCharacterMap; + bool mOtherFamilyNamesInitialized : 1; + bool mHasOtherFamilyNames : 1; + bool mFaceNamesInitialized : 1; + bool mHasStyles : 1; + bool mIsSimpleFamily : 1; + bool mIsBadUnderlineFamily : 1; + bool mFamilyCharacterMapInitialized : 1; enum { // for "simple" families, the faces are stored in mAvailableFonts diff --git a/gfx/thebes/gfxFontUtils.h b/gfx/thebes/gfxFontUtils.h index 3d6ba81f7d93..d1293ae2f17f 100644 --- a/gfx/thebes/gfxFontUtils.h +++ b/gfx/thebes/gfxFontUtils.h @@ -58,6 +58,8 @@ #include "nsAutoPtr.h" #include "nsIStreamBufferAccess.h" +#include "zlib.h" + /* Bug 341128 - w32api defines min/max which causes problems with */ #ifdef __MINGW32__ #undef min @@ -87,6 +89,28 @@ public: mBlocks[i] = new Block(*block); } } + + bool Equals(const gfxSparseBitSet *aOther) const { + if (mBlocks.Length() != aOther->mBlocks.Length()) { + return false; + } + size_t n = mBlocks.Length(); + for (size_t i = 0; i < n; ++i) { + const Block *b1 = mBlocks[i]; + const Block *b2 = aOther->mBlocks[i]; + if (!b1 != !b2) { + return false; + } + if (!b1) { + continue; + } + if (memcmp(&b1->mBits, &b2->mBits, BLOCK_SIZE) != 0) { + return false; + } + } + return true; + } + bool test(PRUint32 aIndex) const { NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad"); PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS; @@ -321,6 +345,18 @@ public: mBlocks.Compact(); } + PRUint32 GetChecksum() const { + PRUint32 check = adler32(0, Z_NULL, 0); + for (PRUint32 i = 0; i < mBlocks.Length(); i++) { + if (mBlocks[i]) { + const Block *block = mBlocks[i]; + check = adler32(check, (PRUint8*) (&i), 4); + check = adler32(check, (PRUint8*) block, sizeof(Block)); + } + } + return check; + } + private: nsTArray< nsAutoPtr > mBlocks; }; diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index c40304bf73f0..ba92cd42197f 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -201,7 +201,7 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName, : gfxFontEntry(aFaceName), mWindowsFamily(0), mWindowsPitch(0), mFontType(aFontType), - mForceGDI(false), mUnknownCMAP(false), + mForceGDI(false), mCharset(), mUnicodeRanges() { mUserFontData = aUserFontData; @@ -218,43 +218,62 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName, nsresult GDIFontEntry::ReadCMAP() { + // attempt this once, if errors occur leave a blank cmap + if (mCharacterMap) { + return NS_OK; + } + // skip non-SFNT fonts completely if (mFontType != GFX_FONT_TYPE_PS_OPENTYPE && mFontType != GFX_FONT_TYPE_TT_OPENTYPE && mFontType != GFX_FONT_TYPE_TRUETYPE) { + mCharacterMap = new gfxCharacterMap(); return NS_ERROR_FAILURE; } - // attempt this once, if errors occur leave a blank cmap - if (mCmapInitialized) - return NS_OK; - mCmapInitialized = true; + nsRefPtr charmap = new gfxCharacterMap(); - const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p'); - AutoFallibleTArray buffer; - if (GetFontTable(kCmapTag, buffer) != NS_OK) - return NS_ERROR_FAILURE; - PRUint8 *cmap = buffer.Elements(); + PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p'); + nsresult rv; - bool unicodeFont = false, symbolFont = false; - nsresult rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(), - mCharacterMap, mUVSOffset, - unicodeFont, symbolFont); + AutoFallibleTArray cmap; + rv = GetFontTable(kCMAP, cmap); + + bool unicodeFont = false, symbolFont = false; // currently ignored + + if (NS_SUCCEEDED(rv)) { + rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(), + *charmap, mUVSOffset, + unicodeFont, symbolFont); + } mSymbolFont = symbolFont; + mHasCmapTable = NS_SUCCEEDED(rv); + if (mHasCmapTable) { + gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); + mCharacterMap = pfl->FindCharMap(charmap); + } else { + // if error occurred, initialize to null cmap + mCharacterMap = new gfxCharacterMap(); + // For fonts where we failed to read the character map, + // we can take a slow path to look up glyphs character by character + mCharacterMap->mBuildOnTheFly = true; + } #ifdef PR_LOGGING - LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", + LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n", NS_ConvertUTF16toUTF8(mName).get(), - mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); + charmap->SizeOfIncludingThis(moz_malloc_size_of), + charmap->mHash, mCharacterMap == charmap ? " new" : "")); if (LOG_CMAPDATA_ENABLED()) { char prefix[256]; sprintf(prefix, "(cmapdata) name: %.220s", NS_ConvertUTF16toUTF8(mName).get()); - mCharacterMap.Dump(prefix, eGfxLog_cmapdata); + charmap->Dump(prefix, eGfxLog_cmapdata); } #endif + return rv; } @@ -346,13 +365,12 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont, bool GDIFontEntry::TestCharacterMap(PRUint32 aCh) { - if (ReadCMAP() != NS_OK) { - // For fonts where we failed to read the character map, - // we can take a slow path to look up glyphs character by character - mUnknownCMAP = true; + if (!mCharacterMap) { + nsresult rv = ReadCMAP(); + NS_ASSERTION(mCharacterMap, "failed to initialize a character map"); } - if (mUnknownCMAP) { + if (mCharacterMap->mBuildOnTheFly) { if (aCh > 0xFFFF) return false; @@ -404,12 +422,12 @@ GDIFontEntry::TestCharacterMap(PRUint32 aCh) ReleaseDC(NULL, dc); if (hasGlyph) { - mCharacterMap.set(aCh); + mCharacterMap->set(aCh); return true; } } else { // font had a cmap so simply check that - return mCharacterMap.test(aCh); + return mCharacterMap->test(aCh); } return false; diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h index 67315abeefcf..4f5648106adf 100644 --- a/gfx/thebes/gfxGDIFontList.h +++ b/gfx/thebes/gfxGDIFontList.h @@ -293,7 +293,6 @@ public: gfxWindowsFontType mFontType; bool mForceGDI : 1; - bool mUnknownCMAP : 1; gfxSparseBitSet mCharset; gfxSparseBitSet mUnicodeRanges; diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index 01a75ec7c0c5..c6119023d6bd 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -189,93 +189,98 @@ nsresult MacOSFontEntry::ReadCMAP() { // attempt this once, if errors occur leave a blank cmap - if (mCmapInitialized) { + if (mCharacterMap) { return NS_OK; } - mCmapInitialized = true; + + nsRefPtr charmap = new gfxCharacterMap(); PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p'); + nsresult rv; AutoFallibleTArray cmap; - if (GetFontTable(kCMAP, cmap) != NS_OK) { - return NS_ERROR_FAILURE; + rv = GetFontTable(kCMAP, cmap); + + bool unicodeFont = false, symbolFont = false; // currently ignored + + if (NS_SUCCEEDED(rv)) { + rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(), + *charmap, mUVSOffset, + unicodeFont, symbolFont); } - bool unicodeFont, symbolFont; // currently ignored - nsresult rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(), - mCharacterMap, mUVSOffset, - unicodeFont, symbolFont); - if (NS_FAILED(rv)) { - mCharacterMap.reset(); - return rv; - } - mHasCmapTable = true; + if (NS_SUCCEEDED(rv)) { + // for layout support, check for the presence of mort/morx and/or + // opentype layout tables + bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) || + HasFontTable(TRUETYPE_TAG('m','o','r','t')); + bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B')); + bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S')); - CGFontRef fontRef = GetFontRef(); - if (!fontRef) { - return NS_ERROR_FAILURE; - } + if (hasAATLayout && !(hasGSUB || hasGPOS)) { + mRequiresAAT = true; // prefer CoreText if font has no OTL tables + } - // for layout support, check for the presence of mort/morx and/or - // opentype layout tables - bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) || - HasFontTable(TRUETYPE_TAG('m','o','r','t')); - bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B')); - bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S')); + PRUint32 numScripts = + sizeof(gScriptsThatRequireShaping) / sizeof(ScriptRange); - if (hasAATLayout && !(hasGSUB || hasGPOS)) { - mRequiresAAT = true; // prefer CoreText if font has no OTL tables - } + for (PRUint32 s = 0; s < numScripts; s++) { + eComplexScript whichScript = gScriptsThatRequireShaping[s].script; - PRUint32 numScripts = - sizeof(gScriptsThatRequireShaping) / sizeof(ScriptRange); + // check to see if the cmap includes complex script codepoints + if (charmap->TestRange(gScriptsThatRequireShaping[s].rangeStart, + gScriptsThatRequireShaping[s].rangeEnd)) { + bool omitRange = true; - for (PRUint32 s = 0; s < numScripts; s++) { - eComplexScript whichScript = gScriptsThatRequireShaping[s].script; - - // check to see if the cmap includes complex script codepoints - if (mCharacterMap.TestRange(gScriptsThatRequireShaping[s].rangeStart, - gScriptsThatRequireShaping[s].rangeEnd)) { - bool omitRange = true; - - if (hasAATLayout) { - omitRange = false; - // prefer CoreText for Apple's complex-script fonts, - // even if they also have some OpenType tables - // (e.g. Geeza Pro Bold on 10.6; see bug 614903) - mRequiresAAT = true; - } else if (whichScript == eComplexScriptArabic) { - // special-case for Arabic: - // even if there's no morph table, CoreText can shape Arabic - // using OpenType layout; or if it's a downloaded font, - // assume the site knows what it's doing (as harfbuzz will - // be able to shape even though the font itself lacks tables - // stripped during sanitization). - // We check for GSUB here, as GPOS alone would not be ok - // for Arabic shaping. - if (hasGSUB || (mIsUserFont && !mIsLocalUserFont)) { - // TODO: to be really thorough, we could check that the - // GSUB table actually supports the 'arab' script tag. + if (hasAATLayout) { omitRange = false; + // prefer CoreText for Apple's complex-script fonts, + // even if they also have some OpenType tables + // (e.g. Geeza Pro Bold on 10.6; see bug 614903) + mRequiresAAT = true; + } else if (whichScript == eComplexScriptArabic) { + // special-case for Arabic: + // even if there's no morph table, CoreText can shape Arabic + // using OpenType layout; or if it's a downloaded font, + // assume the site knows what it's doing (as harfbuzz will + // be able to shape even though the font itself lacks tables + // stripped during sanitization). + // We check for GSUB here, as GPOS alone would not be ok + // for Arabic shaping. + if (hasGSUB || (mIsUserFont && !mIsLocalUserFont)) { + // TODO: to be really thorough, we could check that the + // GSUB table actually supports the 'arab' script tag. + omitRange = false; + } } - } - if (omitRange) { - mCharacterMap.ClearRange(gScriptsThatRequireShaping[s].rangeStart, - gScriptsThatRequireShaping[s].rangeEnd); + if (omitRange) { + charmap->ClearRange(gScriptsThatRequireShaping[s].rangeStart, + gScriptsThatRequireShaping[s].rangeEnd); + } } } } + mHasCmapTable = NS_SUCCEEDED(rv); + if (mHasCmapTable) { + gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); + mCharacterMap = pfl->FindCharMap(charmap); + } else { + // if error occurred, initialize to null cmap + mCharacterMap = new gfxCharacterMap(); + } + #ifdef PR_LOGGING - LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", + LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n", NS_ConvertUTF16toUTF8(mName).get(), - mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); + charmap->SizeOfIncludingThis(moz_malloc_size_of), + charmap->mHash, mCharacterMap == charmap ? " new" : "")); if (LOG_CMAPDATA_ENABLED()) { char prefix[256]; sprintf(prefix, "(cmapdata) name: %.220s", NS_ConvertUTF16toUTF8(mName).get()); - mCharacterMap.Dump(prefix, eGfxLog_cmapdata); + charmap->Dump(prefix, eGfxLog_cmapdata); } #endif diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index ef8e2bbd4ad9..fbf7cd65ed51 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -213,10 +213,13 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) gFontListPrefObserver = new gfxFontListPrefObserver(); NS_ADDREF(gFontListPrefObserver); Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs); + + mSharedCmaps.Init(16); } gfxPlatformFontList::~gfxPlatformFontList() { + mSharedCmaps.Clear(); NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer"); Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs); NS_RELEASE(gFontListPrefObserver); @@ -714,6 +717,41 @@ gfxPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString return !aFamilyName.IsEmpty(); } +gfxCharacterMap* +gfxPlatformFontList::FindCharMap(gfxCharacterMap *aCmap) +{ + aCmap->CalcHash(); + gfxCharacterMap *cmap = AddCmap(aCmap); + cmap->mShared = true; + return cmap; +} + +// add a cmap to the shared cmap set +gfxCharacterMap* +gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap) +{ + CharMapHashKey *found = + mSharedCmaps.PutEntry(const_cast(aCharMap)); + return found->GetKey(); +} + +// remove the cmap from the shared cmap set +void +gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap) +{ + // skip lookups during teardown + if (mSharedCmaps.Count() == 0) { + return; + } + + // cmap needs to match the entry *and* be the same ptr before removing + CharMapHashKey *found = + mSharedCmaps.GetEntry(const_cast(aCharMap)); + if (found && found->GetKey() == aCharMap) { + mSharedCmaps.RemoveEntry(const_cast(aCharMap)); + } +} + void gfxPlatformFontList::InitLoader() { @@ -830,6 +868,21 @@ SizeOfStringEntryExcludingThis(nsStringHashKey* aHashEntry, return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf); } +static size_t +SizeOfSharedCmapExcludingThis(CharMapHashKey* aHashEntry, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + FontListSizes *sizes = static_cast(aUserArg); + + PRUint32 size = aHashEntry->GetKey()->SizeOfIncludingThis(aMallocSizeOf); + sizes->mCharMapsSize += size; + + // we return zero here because the measurements have been added directly + // to the relevant fields of the FontListSizes record + return 0; +} + void gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, FontListSizes* aSizes) const @@ -865,6 +918,10 @@ gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, aSizes->mFontListSize += mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis, aMallocSizeOf); + + aSizes->mFontListSize += + mSharedCmaps.SizeOfExcludingThis(SizeOfSharedCmapExcludingThis, + aMallocSizeOf, aSizes); } void diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index b800d28c9d17..8ab03bc2e45e 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -50,6 +50,53 @@ #include "nsIMemoryReporter.h" #include "mozilla/FunctionTimer.h" +class CharMapHashKey : public PLDHashEntryHdr +{ +public: + typedef gfxCharacterMap* KeyType; + typedef const gfxCharacterMap* KeyTypePointer; + + CharMapHashKey(const gfxCharacterMap *aCharMap) : + mCharMap(const_cast(aCharMap)) + { + MOZ_COUNT_CTOR(CharMapHashKey); + } + CharMapHashKey(const CharMapHashKey& toCopy) : + mCharMap(toCopy.mCharMap) + { + MOZ_COUNT_CTOR(CharMapHashKey); + } + ~CharMapHashKey() + { + MOZ_COUNT_DTOR(CharMapHashKey); + } + + gfxCharacterMap* GetKey() const { return mCharMap; } + + bool KeyEquals(const gfxCharacterMap *aCharMap) const { + NS_ASSERTION(!aCharMap->mBuildOnTheFly && !mCharMap->mBuildOnTheFly, + "custom cmap used in shared cmap hashtable"); + // cmaps built on the fly never match + if (aCharMap->mHash != mCharMap->mHash) + { + return false; + } + return mCharMap->Equals(aCharMap); + } + + static const gfxCharacterMap* KeyToPointer(gfxCharacterMap *aCharMap) { + return aCharMap; + } + static PLDHashNumber HashKey(const gfxCharacterMap *aCharMap) { + return aCharMap->mHash; + } + + enum { ALLOW_MEMMOVE = true }; + +protected: + gfxCharacterMap *mCharMap; +}; + // gfxPlatformFontList is an abstract class for the global font list on the system; // concrete subclasses for each platform implement the actual interface to the system fonts. // This class exists because we cannot rely on the platform font-finding APIs to behave @@ -155,6 +202,16 @@ public: virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, FontListSizes* aSizes) const; + // search for existing cmap that matches the input + // return the input if no match is found + gfxCharacterMap* FindCharMap(gfxCharacterMap *aCmap); + + // add a cmap to the shared cmap set + gfxCharacterMap* AddCmap(const gfxCharacterMap *aCharMap); + + // remove the cmap from the shared cmap set + void RemoveCmap(const gfxCharacterMap *aCharMap); + protected: class MemoryReporter : public nsIMemoryMultiReporter @@ -264,6 +321,10 @@ protected: nsTHashtable mBadUnderlineFamilyNames; + // character map data shared across families + // contains weak ptrs to cmaps shared by font entry objects + nsTHashtable mSharedCmaps; + // data used as part of the font cmap loading process nsTArray > mFontFamiliesToLoad; PRUint32 mStartIndex; diff --git a/ipc/ipdl/Makefile.in b/ipc/ipdl/Makefile.in index 156ac1a151ae..327b1d6ac43b 100644 --- a/ipc/ipdl/Makefile.in +++ b/ipc/ipdl/Makefile.in @@ -115,12 +115,12 @@ include $(topsrcdir)/config/rules.mk # NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself, # which is why we don't have explicit .h/.cpp targets here export:: $(ALL_IPDLSRCS) - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ - $(srcdir)/ipdl.py \ - --outheaders-dir=_ipdlheaders \ - --outcpp-dir=. \ - $(IPDLDIRS:%=-I$(topsrcdir)/%) \ + $(PYTHON_PATH) \ + $(PLY_INCLUDE) \ + $(srcdir)/ipdl.py \ + --outheaders-dir=_ipdlheaders \ + --outcpp-dir=. \ + $(IPDLDIRS:%=-I$(topsrcdir)/%) \ $^ # We #include some things in the dom/plugins/ directory that rely on diff --git a/ipc/ipdl/test/ipdl/Makefile.in b/ipc/ipdl/test/ipdl/Makefile.in index 8d9d2bdc5705..8172f406bc89 100644 --- a/ipc/ipdl/test/ipdl/Makefile.in +++ b/ipc/ipdl/test/ipdl/Makefile.in @@ -49,7 +49,7 @@ check:: @$(PYTHON) $(srcdir)/runtests.py \ $(srcdir)/ok $(srcdir)/error \ $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ + $(PLY_INCLUDE) \ $(topsrcdir)/ipc/ipdl/ipdl.py \ OKTESTS $(OKTESTS) \ ERRORTESTS $(ERRORTESTS) diff --git a/ipc/ril/Ril.cpp b/ipc/ril/Ril.cpp index c6407c13d922..34e34fd9daa9 100644 --- a/ipc/ril/Ril.cpp +++ b/ipc/ril/Ril.cpp @@ -278,6 +278,15 @@ RilClient::OnFileCanReadWithoutBlocking(int fd) mIncoming = new RilRawData(); ssize_t ret = read(fd, mIncoming->mData, RilRawData::MAX_DATA_SIZE); if (ret <= 0) { + if (ret == -1) { + if (errno == EINTR) { + continue; // retry system call when interrupted + } + else if (errno == EAGAIN || errno == EWOULDBLOCK) { + return; // no data available: return and re-poll + } + // else fall through to error handling on other errno's + } LOG("Cannot read from network, error %d\n", ret); // At this point, assume that we can't actually access // the socket anymore, and start a reconnect loop. diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 4f6e1c620a63..e5da095a1452 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -409,9 +409,9 @@ GC(JSContext *cx, unsigned argc, jsval *vp) { - JS_GC(cx); -#ifdef JS_GCMETER JSRuntime *rt = JS_GetRuntime(cx); + JS_GC(rt); +#ifdef JS_GCMETER js_DumpGCStats(rt, stdout); #endif JS_SET_RVAL(cx, vp, JSVAL_VOID); @@ -1054,16 +1054,15 @@ XPCShellEnvironment::~XPCShellEnvironment() } mGlobalHolder.Release(); - JS_GC(mCx); + JSRuntime *rt = JS_GetRuntime(mCx); + JS_GC(rt); mCxStack = nsnull; if (mJSPrincipals) { - JS_DropPrincipals(JS_GetRuntime(mCx), mJSPrincipals); + JS_DropPrincipals(rt, mJSPrincipals); } - JSRuntime* rt = gOldContextCallback ? JS_GetRuntime(mCx) : NULL; - JS_EndRequest(mCx); JS_DestroyContext(mCx); diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index 4617eb47e231..9b57e891dca3 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -2817,8 +2817,8 @@ NS_IMETHODIMP jsdService::GC (void) { ASSERT_VALID_CONTEXT; - JSContext *cx = JSD_GetDefaultJSContext (mCx); - JS_GC(cx); + JSRuntime *rt = JSD_GetJSRuntime (mCx); + JS_GC(rt); return NS_OK; } diff --git a/js/jsd/jsdebug.c b/js/jsd/jsdebug.c index 939701358384..a3f400deafcb 100644 --- a/js/jsd/jsdebug.c +++ b/js/jsd/jsdebug.c @@ -98,6 +98,13 @@ JSD_GetDefaultJSContext(JSDContext* jsdc) return jsdc->dumbContext; } +JSD_PUBLIC_API(JSRuntime*) +JSD_GetJSRuntime(JSDContext* jsdc) +{ + JSD_ASSERT_VALID_CONTEXT(jsdc); + return jsdc->jsrt; +} + JSD_PUBLIC_API(void) JSD_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user) { diff --git a/js/jsd/jsdebug.h b/js/jsd/jsdebug.h index c7bb51e08dd2..d08bc94d0fcf 100644 --- a/js/jsd/jsdebug.h +++ b/js/jsd/jsdebug.h @@ -188,6 +188,12 @@ JSD_GetMinorVersion(void); extern JSD_PUBLIC_API(JSContext*) JSD_GetDefaultJSContext(JSDContext* jsdc); +/* +* Returns a JSRuntime this context is associated with +*/ +extern JSD_PUBLIC_API(JSRuntime*) +JSD_GetJSRuntime(JSDContext* jsdc); + /* * Set the private data for this context, returns previous value */ diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 3e864ed5404a..d9bd66b85f17 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -286,7 +286,7 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp) JSBool MapObject::size(JSContext *cx, unsigned argc, Value *vp) { - THIS_MAP(get, cx, argc, vp, args, map); + THIS_MAP(size, cx, argc, vp, args, map); JS_STATIC_ASSERT(sizeof map.count() <= sizeof(uint32_t)); args.rval().setNumber(map.count()); return true; @@ -455,7 +455,7 @@ SetObject::construct(JSContext *cx, unsigned argc, Value *vp) JSBool SetObject::size(JSContext *cx, unsigned argc, Value *vp) { - THIS_SET(has, cx, argc, vp, args, set); + THIS_SET(size, cx, argc, vp, args, set); JS_STATIC_ASSERT(sizeof set.count() <= sizeof(uint32_t)); args.rval().setNumber(set.count()); return true; diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index a0568a5fbdc5..dd040de45dd3 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -47,7 +47,7 @@ GC(JSContext *cx, unsigned argc, jsval *vp) PrepareForDebugGC(cx->runtime); else PrepareForFullGC(cx->runtime); - GCForReason(cx, gcreason::API); + GCForReason(cx->runtime, gcreason::API); char buf[256] = { '\0' }; #ifndef JS_MORE_DETERMINISTIC @@ -234,7 +234,7 @@ VerifyBarriers(JSContext *cx, unsigned argc, jsval *vp) ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Too many arguments"); return JS_FALSE; } - gc::VerifyBarriers(cx); + gc::VerifyBarriers(cx->runtime); *vp = JSVAL_VOID; return JS_TRUE; } @@ -257,7 +257,7 @@ GCSlice(JSContext *cx, unsigned argc, jsval *vp) limit = false; } - GCDebugSlice(cx, limit, budget); + GCDebugSlice(cx->runtime, limit, budget); *vp = JSVAL_VOID; return JS_TRUE; } @@ -469,7 +469,6 @@ MJitCodeStats(JSContext *cx, unsigned argc, jsval *vp) { #ifdef JS_METHODJIT JSRuntime *rt = cx->runtime; - AutoLockGC lock(rt); size_t n = 0; for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) { n += (*c)->sizeOfMjitCode(); @@ -499,7 +498,7 @@ MJitChunkLimit(JSContext *cx, unsigned argc, jsval *vp) // Clear out analysis information which might refer to code compiled with // the previous chunk limit. - JS_GC(cx); + JS_GC(cx->runtime); vp->setUndefined(); return true; diff --git a/js/src/config/config.mk b/js/src/config/config.mk index f9fd8b273d36..1e2bafe35697 100644 --- a/js/src/config/config.mk +++ b/js/src/config/config.mk @@ -837,3 +837,8 @@ EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) endif EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) + +# Include internal ply only if needed +ifndef MOZ_SYSTEM_PLY +PLY_INCLUDE = -I$(topsrcdir)/other-licenses/ply +endif diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index 5eae4ccc24c1..6358c1edbf86 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -1444,7 +1444,7 @@ xpidl-preqs = \ $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(xpidl-preqs) $(REPORT_BUILD) $(PYTHON_PATH) \ - -I$(topsrcdir)/other-licenses/ply \ + $(PLY_INCLUDE) \ -I$(topsrcdir)/xpcom/idl-parser \ $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ @if test -n "$(findstring $*.h, $(EXPORTS))"; \ @@ -1456,7 +1456,7 @@ ifndef NO_GEN_XPT $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs) $(REPORT_BUILD) $(PYTHON_PATH) \ - -I$(topsrcdir)/other-licenses/ply \ + $(PLY_INCLUDE) \ -I$(topsrcdir)/xpcom/idl-parser \ -I$(topsrcdir)/xpcom/typelib/xpt/tools \ $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ diff --git a/js/src/config/rules.mk.orig b/js/src/config/rules.mk.orig deleted file mode 100644 index e6353e18f9c6..000000000000 --- a/js/src/config/rules.mk.orig +++ /dev/null @@ -1,2035 +0,0 @@ -# -*- makefile -*- -# vim:set ts=8 sw=8 sts=8 noet: -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Chase Phillips -# Benjamin Smedberg -# Jeff Walden -# Joey Armstrong -# -# 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 topsrcdir -$(error topsrcdir was not set)) -endif - -ifndef MOZILLA_DIR -MOZILLA_DIR = $(topsrcdir) -endif - -ifndef INCLUDED_CONFIG_MK -include $(topsrcdir)/config/config.mk -endif - -ifndef INCLUDED_VERSION_MK -include $(topsrcdir)/config/version.mk -endif - -ifdef SDK_XPIDLSRCS -XPIDLSRCS += $(SDK_XPIDLSRCS) -endif -ifdef SDK_HEADERS -EXPORTS += $(SDK_HEADERS) -endif - -REPORT_BUILD = @echo $(notdir $<) - -ifeq ($(OS_ARCH),OS2) -EXEC = -else -EXEC = exec -endif - -# Don't copy xulrunner files at install time, when using system xulrunner -ifdef SYSTEM_LIBXUL - SKIP_COPY_XULRUNNER=1 -endif - -# ELOG prints out failed command when building silently (gmake -s). -ifneq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS)))) - ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh -else - ELOG := -endif - -_VPATH_SRCS = $(abspath $<) - -# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed -VPATH += $(DIST)/lib -ifdef LIBXUL_SDK -VPATH += $(LIBXUL_SDK)/lib -endif - -ifdef EXTRA_DSO_LIBS -EXTRA_DSO_LIBS := $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS)) -endif - -################################################################################ -# Testing frameworks support -################################################################################ - -testxpcobjdir = $(DEPTH)/_tests/xpcshell - -ifdef ENABLE_TESTS - -# Add test directories to the regular directories list. TEST_DIRS should -# arguably have the same status as TOOL_DIRS and other *_DIRS variables. It is -# coded this way until Makefiles stop using the "ifdef ENABLE_TESTS; DIRS +=" -# convention. -# -# The current developer workflow expects tests to be updated when processing -# the default target. If we ever change this implementation, the behavior -# should be preserved or the change should be widely communicated. A -# consequence of not processing test dir targets during the default target is -# that changes to tests may not be updated and code could assume to pass -# locally against non-current test code. -DIRS += $(TEST_DIRS) - -ifdef XPCSHELL_TESTS -ifndef relativesrcdir -$(error Must define relativesrcdir when defining XPCSHELL_TESTS.) -endif - -define _INSTALL_TESTS -$(DIR_INSTALL) $(wildcard $(srcdir)/$(dir)/*) $(testxpcobjdir)/$(relativesrcdir)/$(dir) - -endef # do not remove the blank line! - -SOLO_FILE ?= $(error Specify a test filename in SOLO_FILE when using check-interactive or check-one) - -libs:: - $(foreach dir,$(XPCSHELL_TESTS),$(_INSTALL_TESTS)) -ifndef NO_XPCSHELL_MANIFEST_CHECK - $(PYTHON) $(MOZILLA_DIR)/build/xpccheck.py \ - $(topsrcdir) \ - $(topsrcdir)/testing/xpcshell/xpcshell.ini \ - $(addprefix $(MOZILLA_DIR)/$(relativesrcdir)/,$(XPCSHELL_TESTS)) -endif - -testxpcsrcdir = $(topsrcdir)/testing/xpcshell - -# Execute all tests in the $(XPCSHELL_TESTS) directories. -# See also testsuite-targets.mk 'xpcshell-tests' target for global execution. -xpcshell-tests: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --tests-root-dir=$(testxpcobjdir) \ - --xunit-file=$(testxpcobjdir)/$(relativesrcdir)/results.xml \ - --xunit-suite-name=xpcshell \ - $(EXTRA_TEST_ARGS) \ - $(LIBXUL_DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -xpcshell-tests-remote: DM_TRANS?=adb -xpcshell-tests-remote: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - -I$(topsrcdir)/build/mobile \ - $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - $(EXTRA_TEST_ARGS) \ - --dm_trans=$(DM_TRANS) \ - --deviceIP=${TEST_DEVICE} \ - --objdir=$(DEPTH) \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -# Execute a single test, specified in $(SOLO_FILE), but don't automatically -# start the test. Instead, present the xpcshell prompt so the user can -# attach a debugger and then start the test. -check-interactive: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --interactive \ - $(LIBXUL_DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -# Execute a single test, specified in $(SOLO_FILE) -check-one: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --verbose \ - $(EXTRA_TEST_ARGS) \ - $(LIBXUL_DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) - -check-one-remote: DM_TRANS?=adb -check-one-remote: - $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - -I$(topsrcdir)/build/mobile \ - $(testxpcsrcdir)/remotexpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --build-info-json=$(DEPTH)/mozinfo.json \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --verbose \ - $(EXTRA_TEST_ARGS) \ - --dm_trans=$(DM_TRANS) \ - --deviceIP=${TEST_DEVICE} \ - --objdir=$(DEPTH) \ - --noSetup \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) -endif # XPCSHELL_TESTS - -ifdef CPP_UNIT_TESTS - -# Compile the tests to $(DIST)/bin. Make lots of niceties available by default -# through TestHarness.h, by modifying the list of includes and the libs against -# which stuff links. -CPPSRCS += $(CPP_UNIT_TESTS) -SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) -INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) - -# ...and run them the usual way -check:: - @$(EXIT_ON_ERROR) \ - for f in $(subst .cpp,$(BIN_SUFFIX),$(CPP_UNIT_TESTS)); do \ - XPCOM_DEBUG_BREAK=stack-and-abort $(RUN_TEST_PROGRAM) $(DIST)/bin/$$f; \ - done - -endif # CPP_UNIT_TESTS - -.PHONY: check xpcshell-tests check-interactive check-one - -endif # ENABLE_TESTS - - -# -# Library rules -# -# If FORCE_STATIC_LIB is set, build a static library. -# Otherwise, build a shared library. -# - -ifndef LIBRARY -ifdef STATIC_LIBRARY_NAME -REAL_LIBRARY := $(LIB_PREFIX)$(STATIC_LIBRARY_NAME).$(LIB_SUFFIX) -# Only build actual library if it is installed in DIST/lib or SDK -ifeq (,$(SDK_LIBRARY)$(DIST_INSTALL)$(NO_EXPAND_LIBS)) -LIBRARY := $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) -else -LIBRARY := $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX) -endif -endif # STATIC_LIBRARY_NAME -endif # LIBRARY - -ifndef HOST_LIBRARY -ifdef HOST_LIBRARY_NAME -HOST_LIBRARY := $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX) -endif -endif - -ifdef LIBRARY -ifdef FORCE_SHARED_LIB -ifdef MKSHLIB - -ifdef LIB_IS_C_ONLY -MKSHLIB = $(MKCSHLIB) -endif - -ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) -IMPORT_LIBRARY := $(LIB_PREFIX)$(SHARED_LIBRARY_NAME).$(IMPORT_LIB_SUFFIX) -endif - -ifeq (OS2,$(OS_ARCH)) -ifdef SHORT_LIBNAME -SHARED_LIBRARY_NAME := $(SHORT_LIBNAME) -endif -endif - -ifdef MAKE_FRAMEWORK -SHARED_LIBRARY := $(SHARED_LIBRARY_NAME) -else -SHARED_LIBRARY := $(DLL_PREFIX)$(SHARED_LIBRARY_NAME)$(DLL_SUFFIX) -endif - -ifeq ($(OS_ARCH),OS2) -DEF_FILE := $(SHARED_LIBRARY:.dll=.def) -endif - -EMBED_MANIFEST_AT=2 - -endif # MKSHLIB -endif # FORCE_SHARED_LIB -endif # LIBRARY - -ifdef FORCE_STATIC_LIB -ifndef FORCE_SHARED_LIB -SHARED_LIBRARY := $(NULL) -DEF_FILE := $(NULL) -IMPORT_LIBRARY := $(NULL) -endif -endif - -ifdef FORCE_SHARED_LIB -ifndef FORCE_STATIC_LIB -LIBRARY := $(NULL) -endif -endif - -ifdef JAVA_LIBRARY_NAME -JAVA_LIBRARY := $(JAVA_LIBRARY_NAME).jar -endif - -ifeq ($(OS_ARCH),WINNT) -ifndef GNU_CC - -# -# Unless we're building SIMPLE_PROGRAMS, all C++ files share a PDB file per -# directory. For parallel builds, this PDB file is shared and locked by -# MSPDBSRV.EXE, starting with MSVC8 SP1. If you're using MSVC 7.1 or MSVC8 -# without SP1, don't do parallel builds. -# -# The final PDB for libraries and programs is created by the linker and uses -# a different name from the single PDB file created by the compiler. See -# bug 462740. -# - -ifdef SIMPLE_PROGRAMS -COMPILE_PDBFILE = $(basename $(@F)).pdb -else -COMPILE_PDBFILE = generated.pdb -endif - -LINK_PDBFILE = $(basename $(@F)).pdb -ifdef MOZ_DEBUG -CODFILE=$(basename $(@F)).cod -endif - -ifdef MOZ_MAPINFO -ifdef SHARED_LIBRARY_NAME -MAPFILE=$(SHARED_LIBRARY_NAME).map -else -MAPFILE=$(basename $(@F)).map -endif # SHARED_LIBRARY_NAME -endif # MOZ_MAPINFO - -ifdef DEFFILE -OS_LDFLAGS += -DEF:$(call normalizepath,$(DEFFILE)) -EXTRA_DEPS += $(DEFFILE) -endif - -ifdef MAPFILE -OS_LDFLAGS += -MAP:$(MAPFILE) -endif - -else #!GNU_CC - -ifdef DEFFILE -OS_LDFLAGS += $(call normalizepath,$(DEFFILE)) -EXTRA_DEPS += $(DEFFILE) -endif - -endif # !GNU_CC - -endif # WINNT - -ifeq ($(SOLARIS_SUNPRO_CXX),1) -ifeq (86,$(findstring 86,$(OS_TEST))) -OS_LDFLAGS += -M $(topsrcdir)/config/solaris_ia32.map -endif # x86 -endif # Solaris Sun Studio C++ - -ifeq ($(HOST_OS_ARCH),WINNT) -HOST_PDBFILE=$(basename $(@F)).pdb -endif - -# Don't build SIMPLE_PROGRAMS during the MOZ_PROFILE_GENERATE pass -ifdef MOZ_PROFILE_GENERATE -SIMPLE_PROGRAMS := -endif - -ifndef TARGETS -TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(JAVA_LIBRARY) -endif - -ifndef OBJS -_OBJS = \ - $(JRI_STUB_CFILES) \ - $(addsuffix .$(OBJ_SUFFIX), $(JMC_GEN)) \ - $(CSRCS:.c=.$(OBJ_SUFFIX)) \ - $(SSRCS:.S=.$(OBJ_SUFFIX)) \ - $(patsubst %.cc,%.$(OBJ_SUFFIX),$(CPPSRCS:.cpp=.$(OBJ_SUFFIX))) \ - $(CMSRCS:.m=.$(OBJ_SUFFIX)) \ - $(CMMSRCS:.mm=.$(OBJ_SUFFIX)) \ - $(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX)) -OBJS = $(strip $(_OBJS)) -endif - -ifndef HOST_OBJS -_HOST_OBJS = \ - $(addprefix host_,$(HOST_CSRCS:.c=.$(OBJ_SUFFIX))) \ - $(addprefix host_,$(patsubst %.cc,%.$(OBJ_SUFFIX),$(HOST_CPPSRCS:.cpp=.$(OBJ_SUFFIX)))) \ - $(addprefix host_,$(HOST_CMSRCS:.m=.$(OBJ_SUFFIX))) \ - $(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX))) -HOST_OBJS = $(strip $(_HOST_OBJS)) -endif - -LIBOBJS := $(addprefix \", $(OBJS)) -LIBOBJS := $(addsuffix \", $(LIBOBJS)) - -ifndef MOZ_AUTO_DEPS -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) -MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp)) -ifndef NO_GEN_XPT -MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp)) -endif -endif -endif - -ALL_TRASH = \ - $(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \ - $(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \ - $(OBJS:.$(OBJ_SUFFIX)=.i) $(OBJS:.$(OBJ_SUFFIX)=.i_o) \ - $(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\ - $(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \ - $(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \ - $(SHARED_LIBRARY:$(DLL_SUFFIX)=.exp) $(wildcard *.ilk) \ - $(PROGRAM:$(BIN_SUFFIX)=.exp) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.exp) \ - $(PROGRAM:$(BIN_SUFFIX)=.lib) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.lib) \ - $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) \ - $(wildcard gts_tmp_*) $(LIBRARY:%.a=.%.timestamp) -ALL_TRASH_DIRS = \ - $(GARBAGE_DIRS) /no-such-file - -ifdef QTDIR -GARBAGE += $(MOCSRCS) -GARBAGE += $(RCCSRCS) -endif - -ifdef SIMPLE_PROGRAMS -GARBAGE += $(SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX)) -endif - -ifdef HOST_SIMPLE_PROGRAMS -GARBAGE += $(HOST_SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX)) -endif - -# -# the Solaris WorkShop template repository cache. it occasionally can get -# out of sync, so targets like clobber should kill it. -# -ifeq ($(SOLARIS_SUNPRO_CXX),1) -GARBAGE_DIRS += SunWS_cache -endif - -XPIDL_GEN_DIR = _xpidlgen - -ifdef MOZ_UPDATE_XTERM -# Its good not to have a newline at the end of the titlebar string because it -# makes the make -s output easier to read. Echo -n does not work on all -# platforms, but we can trick sed into doing it. -UPDATE_TITLE = sed -e "s!Y!$(1) in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2)!" $(MOZILLA_DIR)/config/xterm.str; -endif - -define SUBMAKE # $(call SUBMAKE,target,directory) -+@$(UPDATE_TITLE) -+$(MAKE) $(if $(2),-C $(2)) $(1) - -endef # The extra line is important here! don't delete it - -ifneq (,$(strip $(DIRS))) -LOOP_OVER_DIRS = \ - $(foreach dir,$(DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -# we only use this for the makefiles target and other stuff that doesn't matter -ifneq (,$(strip $(PARALLEL_DIRS))) -LOOP_OVER_PARALLEL_DIRS = \ - $(foreach dir,$(PARALLEL_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -ifneq (,$(strip $(STATIC_DIRS))) -LOOP_OVER_STATIC_DIRS = \ - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -ifneq (,$(strip $(TOOL_DIRS))) -LOOP_OVER_TOOL_DIRS = \ - $(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - -# -# Now we can differentiate between objects used to build a library, and -# objects used to build an executable in the same directory. -# -ifndef PROGOBJS -PROGOBJS = $(OBJS) -endif - -ifndef HOST_PROGOBJS -HOST_PROGOBJS = $(HOST_OBJS) -endif - -# MAKE_DIRS: List of directories to build while looping over directories. -# A Makefile that needs $(MDDEPDIR) created but doesn't set any of these -# variables we know to check can just set NEED_MDDEPDIR explicitly. -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)$(NEED_MDDEPDIR)) -MAKE_DIRS += $(CURDIR)/$(MDDEPDIR) -GARBAGE_DIRS += $(MDDEPDIR) -endif - -# -# Tags: emacs (etags), vi (ctags) -# TAG_PROGRAM := ctags -L - -# -TAG_PROGRAM = xargs etags -a - -# -# Turn on C++ linking if we have any .cpp or .mm files -# (moved this from config.mk so that config.mk can be included -# before the CPPSRCS are defined) -# -ifneq ($(CPPSRCS)$(CMMSRCS),) -CPP_PROG_LINK = 1 -endif -ifneq ($(HOST_CPPSRCS)$(HOST_CMMSRCS),) -HOST_CPP_PROG_LINK = 1 -endif - -# -# This will strip out symbols that the component should not be -# exporting from the .dynsym section. -# -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += $(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS) -endif # IS_COMPONENT - -# -# Enforce the requirement that MODULE_NAME must be set -# for components in static builds -# -ifdef IS_COMPONENT -ifdef EXPORT_LIBRARY -ifndef FORCE_SHARED_LIB -ifndef MODULE_NAME -$(error MODULE_NAME is required for components which may be used in static builds) -endif -endif -endif -endif - -# -# MacOS X specific stuff -# - -ifeq ($(OS_ARCH),Darwin) -ifdef SHARED_LIBRARY -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -bundle -else -EXTRA_DSO_LDOPTS += -dynamiclib -install_name @executable_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module -endif -endif -endif - -# -# On NetBSD a.out systems, use -Bsymbolic. This fixes what would otherwise be -# fatal symbol name clashes between components. -# -ifeq ($(OS_ARCH),NetBSD) -ifeq ($(DLL_SUFFIX),.so.1.0) -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -endif -endif -endif - -ifeq ($(OS_ARCH),FreeBSD) -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -endif -endif - -ifeq ($(OS_ARCH),NetBSD) -ifneq (,$(filter arc cobalt hpcmips mipsco newsmips pmax sgimips,$(OS_TEST))) -ifeq ($(MODULE),layout) -OS_CFLAGS += -Wa,-xgot -OS_CXXFLAGS += -Wa,-xgot -endif -endif -endif - -# -# HP-UXBeOS specific section: for COMPONENTS only, add -Bsymbolic flag -# which uses internal symbols first -# -ifeq ($(OS_ARCH),HP-UX) -ifdef IS_COMPONENT -ifeq ($(GNU_CC)$(GNU_CXX),) -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -ifneq ($(HAS_EXTRAEXPORTS),1) -MKSHLIB += -Wl,+eNSGetModule -Wl,+eerrno -MKCSHLIB += +eNSGetModule +eerrno -ifneq ($(OS_TEST),ia64) -MKSHLIB += -Wl,+e_shlInit -MKCSHLIB += +e_shlInit -endif # !ia64 -endif # !HAS_EXTRAEXPORTS -endif # non-gnu compilers -endif # IS_COMPONENT -endif # HP-UX - -ifeq ($(OS_ARCH),AIX) -ifdef IS_COMPONENT -ifneq ($(HAS_EXTRAEXPORTS),1) -MKSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall -MKCSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall -endif # HAS_EXTRAEXPORTS -endif # IS_COMPONENT -endif # AIX - -# -# OSF1: add -B symbolic flag for components -# -ifeq ($(OS_ARCH),OSF1) -ifdef IS_COMPONENT -ifeq ($(GNU_CC)$(GNU_CXX),) -EXTRA_DSO_LDOPTS += -B symbolic -endif -endif -endif - -# -# Linux: add -Bsymbolic flag for components -# -ifeq ($(OS_ARCH),Linux) -ifdef IS_COMPONENT -EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic -endif -endif - -# -# GNU doesn't have path length limitation -# - -ifeq ($(OS_ARCH),GNU) -OS_CPPFLAGS += -DPATH_MAX=1024 -DMAXPATHLEN=1024 -endif - -# -# MINGW32 -# -ifeq ($(OS_ARCH),WINNT) -ifdef GNU_CC -ifndef IS_COMPONENT -DSO_LDOPTS += -Wl,--out-implib -Wl,$(IMPORT_LIBRARY) -endif -endif -endif - -ifeq ($(USE_TVFS),1) -IFLAGS1 = -rb -IFLAGS2 = -rb -else -IFLAGS1 = -m 644 -IFLAGS2 = -m 755 -endif - -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) -OUTOPTION = -Fo# eol -else -OUTOPTION = -o # eol -endif # WINNT && !GNU_CC - -ifneq (,$(filter ml%,$(AS))) -ASOUTOPTION = -Fo# eol -else -ASOUTOPTION = -o # eol -endif - -ifeq (,$(CROSS_COMPILE)) -HOST_OUTOPTION = $(OUTOPTION) -else -HOST_OUTOPTION = -o # eol -endif -################################################################################ - -# SUBMAKEFILES: List of Makefiles for next level down. -# This is used to update or create the Makefiles before invoking them. -SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS)) - -# The root makefile doesn't want to do a plain export/libs, because -# of the tiers and because of libxul. Suppress the default rules in favor -# of something else. Makefiles which use this var *must* provide a sensible -# default rule before including rules.mk -ifndef SUPPRESS_DEFAULT_RULES -ifdef TIERS -default all alldep:: - $(foreach tier,$(TIERS),$(call SUBMAKE,tier_$(tier))) -else - -default all:: -ifneq (,$(strip $(STATIC_DIRS))) - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,,$(dir))) -endif - $(MAKE) export - $(MAKE) libs - $(MAKE) tools - -# Do depend as well -alldep:: - $(MAKE) export - $(MAKE) depend - $(MAKE) libs - $(MAKE) tools - -endif # TIERS -endif # SUPPRESS_DEFAULT_RULES - -ifeq ($(filter s,$(MAKEFLAGS)),) -ECHO := echo -QUIET := -else -ECHO := true -QUIET := -q -endif - -MAKE_TIER_SUBMAKEFILES = +$(if $(tier_$*_dirs),$(MAKE) $(addsuffix /Makefile,$(tier_$*_dirs))) - -$(foreach tier,$(TIERS),tier_$(tier)):: - @$(ECHO) "$@: $($@_staticdirs) $($@_dirs)" - $(foreach dir,$($@_staticdirs),$(call SUBMAKE,,$(dir))) - $(MAKE) export_$@ - $(MAKE) libs_$@ - $(MAKE) tools_$@ - -# Do everything from scratch -everything:: - $(MAKE) clean - $(MAKE) alldep - -# Add dummy depend target for tinderboxes -depend:: - -# Target to only regenerate makefiles -makefiles: $(SUBMAKEFILES) -ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS)) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) -endif - -include $(topsrcdir)/config/makefiles/target_export.mk -include $(topsrcdir)/config/makefiles/target_tools.mk - -# -# Rule to create list of libraries for final link -# -export:: -ifdef LIBRARY_NAME -ifdef EXPORT_LIBRARY -ifdef IS_COMPONENT -else # !IS_COMPONENT - $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME) -endif # IS_COMPONENT -endif # EXPORT_LIBRARY -endif # LIBRARY_NAME - -ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS))) -$(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only) -endif - -# Create dependencies on static (and shared EXTRA_DSO_LIBS) libraries -DO_EXPAND_LIBS = $(foreach f,$(1),$(if $(filter %.$(LIB_SUFFIX),$(f)),$(if $(wildcard $(f).$(LIBS_DESC_SUFFIX)),$(f).$(LIBS_DESC_SUFFIX),$(if $(wildcard $(f)),$(f))))) -LIBS_DEPS = $(call DO_EXPAND_LIBS,$(filter %.$(LIB_SUFFIX),$(LIBS) $(if $(PROGRAM)$(SIMPLE_PROGRAMS),$(MOZ_GLUE_PROGRAM_LDFLAGS)))) -SHARED_LIBRARY_LIBS_DEPS = $(call DO_EXPAND_LIBS,$(SHARED_LIBRARY_LIBS)) -HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS)) -DSO_LDOPTS_DEPS = $(call DO_EXPAND_LIBS,$(EXTRA_DSO_LIBS) $(filter %.$(LIB_SUFFIX), $(EXTRA_DSO_LDOPTS))) - -# Dependencies which, if modified, should cause everything to rebuild -GLOBAL_DEPS += Makefile Makefile.in $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk - -############################################## -include $(topsrcdir)/config/makefiles/target_libs.mk - -############################################## -ifndef NO_PROFILE_GUIDED_OPTIMIZE -ifdef MOZ_PROFILE_USE -ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_) -# When building with PGO, we have to make sure to re-link -# in the MOZ_PROFILE_USE phase if we linked in the -# MOZ_PROFILE_GENERATE phase. We'll touch this pgo.relink -# file in the link rule in the GENERATE phase to indicate -# that we need a relink. -ifdef SHARED_LIBRARY -$(SHARED_LIBRARY): pgo.relink -endif -ifdef PROGRAM -$(PROGRAM): pgo.relink -endif - -# In the second pass, we need to merge the pgc files into the pgd file. -# The compiler would do this for us automatically if they were in the right -# place, but they're in dist/bin. -ifneq (,$(SHARED_LIBRARY)$(PROGRAM)) -export:: -ifdef PROGRAM - $(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \ - $(PROGRAM:$(BIN_SUFFIX)=) $(DIST)/bin -endif -ifdef SHARED_LIBRARY - $(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \ - $(SHARED_LIBRARY_NAME) $(DIST)/bin -endif -endif # SHARED_LIBRARY || PROGRAM -endif # WINNT_ -endif # MOZ_PROFILE_USE -ifdef MOZ_PROFILE_GENERATE -# Clean up profiling data during PROFILE_GENERATE phase -export:: -ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_) - $(foreach pgd,$(wildcard *.pgd),pgomgr -clear $(pgd);) -else -ifdef GNU_CC - -$(RM) *.gcda -endif -endif -endif - -ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE)) -ifdef GNU_CC -# Force rebuilding libraries and programs in both passes because each -# pass uses different object files. -$(PROGRAM) $(SHARED_LIBRARY) $(LIBRARY): FORCE -endif -endif - -endif # NO_PROFILE_GUIDED_OPTIMIZE - -############################################## - -stdc++compat.$(OBJ_SUFFIX): CXXFLAGS+=-DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_TARGET_VERSION) -host_stdc++compat.$(OBJ_SUFFIX): CXXFLAGS+=-DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_HOST_VERSION) - -checkout: - $(MAKE) -C $(topsrcdir) -f client.mk checkout - -clean clobber realclean clobber_all:: $(SUBMAKEFILES) - -$(RM) $(ALL_TRASH) - -$(RM) -r $(ALL_TRASH_DIRS) - $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(STATIC_DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) - -distclean:: $(SUBMAKEFILES) - $(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(STATIC_DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir))) - -$(RM) -r $(ALL_TRASH_DIRS) - -$(RM) $(ALL_TRASH) \ - Makefile .HSancillary \ - $(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \ - $(wildcard *.$(LIB_SUFFIX)) $(wildcard *$(DLL_SUFFIX)) \ - $(wildcard *.$(IMPORT_LIB_SUFFIX)) -ifeq ($(OS_ARCH),OS2) - -$(RM) $(PROGRAM:.exe=.map) -endif - -alltags: - $(RM) TAGS - find $(topsrcdir) -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' -o -name '*.idl' \) -print | $(TAG_PROGRAM) - -# -# PROGRAM = Foo -# creates OBJS, links with LIBS to create Foo -# -$(PROGRAM): $(PROGOBJS) $(LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) $(GLOBAL_DEPS) - @$(RM) $@.manifest -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) - $(EXPAND_LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS) -ifdef MSMANIFEST_TOOL - @if test -f $@.manifest; then \ - if test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest and $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" $@.manifest -OUTPUTRESOURCE:$@\;1; \ - else \ - echo "Embedding manifest from $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ - fi; \ - elif test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" -OUTPUTRESOURCE:$@\;1; \ - fi -endif # MSVC with manifest tool -ifdef MOZ_PROFILE_GENERATE -# touch it a few seconds into the future to work around FAT's -# 2-second granularity - touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink -endif -else # !WINNT || GNU_CC -ifeq ($(CPP_PROG_LINK),1) - $(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) - @$(call CHECK_STDCXX,$@) -else # ! CPP_PROG_LINK - $(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) -endif # CPP_PROG_LINK -endif # WINNT && !GNU_CC - -ifdef ENABLE_STRIP - $(STRIP) $@ -endif -ifdef MOZ_POST_PROGRAM_COMMAND - $(MOZ_POST_PROGRAM_COMMAND) $@ -endif - -$(HOST_PROGRAM): $(HOST_PROGOBJS) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS) -ifeq (_WINNT,$(GNU_CC)_$(HOST_OS_ARCH)) - $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $(HOST_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -ifdef MSMANIFEST_TOOL - @if test -f $@.manifest; then \ - if test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest and $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" $@.manifest -OUTPUTRESOURCE:$@\;1; \ - else \ - echo "Embedding manifest from $@.manifest"; \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ - fi; \ - elif test -f "$(srcdir)/$@.manifest"; then \ - echo "Embedding manifest from $(srcdir)/$@.manifest"; \ - mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" -OUTPUTRESOURCE:$@\;1; \ - fi -endif # MSVC with manifest tool -else -ifeq ($(HOST_CPP_PROG_LINK),1) - $(HOST_CXX) -o $@ $(HOST_CXXFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -else - $(HOST_CC) -o $@ $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -endif # HOST_CPP_PROG_LINK -endif - -# -# This is an attempt to support generation of multiple binaries -# in one directory, it assumes everything to compile Foo is in -# Foo.o (from either Foo.c or Foo.cpp). -# -# SIMPLE_PROGRAMS = Foo Bar -# creates Foo.o Bar.o, links with LIBS to create Foo, Bar. -# -$(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS) -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) - $(EXPAND_LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS) -ifdef MSMANIFEST_TOOL - @if test -f $@.manifest; then \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ - rm -f $@.manifest; \ - fi -endif # MSVC with manifest tool -else -ifeq ($(CPP_PROG_LINK),1) - $(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) - @$(call CHECK_STDCXX,$@) -else - $(EXPAND_CC) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) -endif # CPP_PROG_LINK -endif # WINNT && !GNU_CC - -ifdef ENABLE_STRIP - $(STRIP) $@ -endif -ifdef MOZ_POST_PROGRAM_COMMAND - $(MOZ_POST_PROGRAM_COMMAND) $@ -endif - -$(HOST_SIMPLE_PROGRAMS): host_%$(HOST_BIN_SUFFIX): host_%.$(OBJ_SUFFIX) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS) -ifeq (WINNT_,$(HOST_OS_ARCH)_$(GNU_CC)) - $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) -else -ifneq (,$(HOST_CPPSRCS)$(USE_HOST_CXX)) - $(HOST_CXX) $(HOST_OUTOPTION)$@ $(HOST_CXXFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS) -else - $(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_CFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS) -endif -endif - -# -# Purify target. Solaris/sparc only to start. -# Purify does not recognize "egcs" or "c++" so we go with -# "gcc" and "g++" for now. -# -pure: $(PROGRAM) -ifeq ($(CPP_PROG_LINK),1) - $(PURIFY) $(CCC) -o $^.pure $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -else - $(PURIFY) $(CC) -o $^.pure $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -endif -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS2) $^.pure $(FINAL_TARGET) -endif - -quantify: $(PROGRAM) -ifeq ($(CPP_PROG_LINK),1) - $(QUANTIFY) $(CCC) -o $^.quantify $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -else - $(QUANTIFY) $(CC) -o $^.quantify $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) -endif -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS2) $^.quantify $(FINAL_TARGET) -endif - -ifdef DTRACE_PROBE_OBJ -EXTRA_DEPS += $(DTRACE_PROBE_OBJ) -OBJS += $(DTRACE_PROBE_OBJ) -endif - -$(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS) - $(RM) $(LIBRARY) - $(EXPAND_AR) $(AR_FLAGS) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS) - $(RANLIB) $@ - -$(filter-out %.$(LIB_SUFFIX),$(LIBRARY)): $(filter %.$(LIB_SUFFIX),$(LIBRARY)) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS) -# When we only build a library descriptor, blow out any existing library - $(if $(filter %.$(LIB_SUFFIX),$(LIBRARY)),,$(RM) $(REAL_LIBRARY) $(EXPORT_LIBRARY:%=%/$(REAL_LIBRARY))) - $(EXPAND_LIBS_GEN) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS) > $@ - -ifeq ($(OS_ARCH),WINNT) -$(IMPORT_LIBRARY): $(SHARED_LIBRARY) -endif - -ifeq ($(OS_ARCH),OS2) -$(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS) - $(RM) $@ - echo LIBRARY $(SHARED_LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@ - echo PROTMODE >> $@ - echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@ - echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@ - echo EXPORTS >> $@ - - $(ADD_TO_DEF_FILE) - -$(IMPORT_LIBRARY): $(SHARED_LIBRARY) - $(RM) $@ - $(IMPLIB) $@ $^ - $(RANLIB) $@ -endif # OS/2 - -$(HOST_LIBRARY): $(HOST_OBJS) Makefile - $(RM) $@ - $(HOST_AR) $(HOST_AR_FLAGS) $(HOST_OBJS) - $(HOST_RANLIB) $@ - -ifdef HAVE_DTRACE -ifndef XP_MACOSX -ifdef DTRACE_PROBE_OBJ -ifndef DTRACE_LIB_DEPENDENT -NON_DTRACE_OBJS := $(filter-out $(DTRACE_PROBE_OBJ),$(OBJS)) -$(DTRACE_PROBE_OBJ): $(NON_DTRACE_OBJS) - dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(NON_DTRACE_OBJS) -endif -endif -endif -endif - -# On Darwin (Mac OS X), dwarf2 debugging uses debug info left in .o files, -# so instead of deleting .o files after repacking them into a dylib, we make -# symlinks back to the originals. The symlinks are a no-op for stabs debugging, -# so no need to conditionalize on OS version or debugging format. - -$(SHARED_LIBRARY): $(OBJS) $(LOBJS) $(DEF_FILE) $(RESFILE) $(SHARED_LIBRARY_LIBS_DEPS) $(LIBRARY) $(EXTRA_DEPS) $(DSO_LDOPTS_DEPS) $(GLOBAL_DEPS) -ifndef INCREMENTAL_LINKER - $(RM) $@ -endif -ifdef DTRACE_LIB_DEPENDENT -ifndef XP_MACOSX - dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS)) -endif - $(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) - @$(RM) $(DTRACE_PROBE_OBJ) -else # ! DTRACE_LIB_DEPENDENT - $(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) -endif # DTRACE_LIB_DEPENDENT - @$(call CHECK_STDCXX,$@) - -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) -ifdef MSMANIFEST_TOOL -ifdef EMBED_MANIFEST_AT - @if test -f $@.manifest; then \ - mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \ - rm -f $@.manifest; \ - fi -endif # EMBED_MANIFEST_AT -endif # MSVC with manifest tool -ifdef MOZ_PROFILE_GENERATE - touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink -endif -endif # WINNT && !GCC - @$(RM) foodummyfilefoo $(DELETE_AFTER_LINK) - chmod +x $@ -ifdef ENABLE_STRIP - $(STRIP) $@ -endif -ifdef MOZ_POST_DSO_LIB_COMMAND - $(MOZ_POST_DSO_LIB_COMMAND) $@ -endif - -ifdef MOZ_AUTO_DEPS -ifdef COMPILER_DEPEND -ifeq ($(SOLARIS_SUNPRO_CC),1) -_MDDEPFILE = $(MDDEPDIR)/$(@F).pp - -define MAKE_DEPS_AUTO_CC -if test -d $(@D); then \ - echo "Building deps for $< using Sun Studio cc"; \ - $(CC) $(COMPILE_CFLAGS) -xM $< >$(_MDDEPFILE) ; \ -fi -endef -define MAKE_DEPS_AUTO_CXX -if test -d $(@D); then \ - echo "Building deps for $< using Sun Studio CC"; \ - $(CXX) $(COMPILE_CXXFLAGS) -xM $< >$(_MDDEPFILE) ; \ -fi -endef -endif # Sun Studio on Solaris -else # COMPILER_DEPEND -# -# Generate dependencies on the fly -# -_MDDEPFILE = $(MDDEPDIR)/$(@F).pp - -define MAKE_DEPS_AUTO -if test -d $(@D); then \ - echo "Building deps for $<"; \ - $(MKDEPEND) -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $(_MDDEPFILE) ; \ -fi -endef - -MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO) -MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO) - -endif # COMPILER_DEPEND - -endif # MOZ_AUTO_DEPS - -# Rules for building native targets must come first because of the host_ prefix -host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) - $(REPORT_BUILD) - $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS) - -%:: %.c $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CC) - $(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS) - -%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CC) - $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS) - -# DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs: -# 'moc' only knows about #defines it gets on the command line (-D...), not in -# included headers like mozilla-config.h -moc_%.cpp: %.h $(GLOBAL_DEPS) - $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@ - -moc_%.cc: %.cc $(GLOBAL_DEPS) - $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@ - -qrc_%.cpp: %.qrc $(GLOBAL_DEPS) - $(ELOG) $(RCC) -name $* $< $(OUTOPTION)$@ - -ifdef ASFILES -# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept -# a '-c' flag. -%.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) $(GLOBAL_DEPS) - $(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS) -endif - -%.$(OBJ_SUFFIX): %.S $(GLOBAL_DEPS) - $(AS) -o $@ $(ASFLAGS) -c $< - -%:: %.cpp $(GLOBAL_DEPS) - @$(MAKE_DEPS_AUTO_CXX) - $(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS) - -# -# Please keep the next two rules in sync. -# -%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CXX) - $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) - -%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CXX) -ifdef STRICT_CPLUSPLUS_SUFFIX - echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc - $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc - $(RM) t_$*.cc -else - $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) -endif #STRICT_CPLUSPLUS_SUFFIX - -$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CXX) - $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) - -$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS) - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO_CC) - $(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS) - -%.s: %.cpp - $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) - -%.s: %.cc - $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) - -%.s: %.c - $(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS) - -%.i: %.cpp - $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i - -%.i: %.cc - $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i - -%.i: %.c - $(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i - -%.i: %.mm - $(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i - -%.res: %.rc - @echo Creating Resource file: $@ -ifeq ($(OS_ARCH),OS2) - $(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@ -else -ifdef GNU_CC - $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS) -else - $(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $(_VPATH_SRCS) -endif -endif - -# need 3 separate lines for OS/2 -%:: %.pl - $(RM) $@ - cp $< $@ - chmod +x $@ - -%:: %.sh - $(RM) $@ - cp $< $@ - chmod +x $@ - -# Cancel these implicit rules -# -%: %,v - -%: RCS/%,v - -%: s.% - -%: SCCS/s.% - -############################################################################### -# Java rules -############################################################################### -ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) -SEP := ; -else -SEP := : -endif - -EMPTY := -SPACE := $(EMPTY) $(EMPTY) - -# MSYS has its own special path form, but javac expects the source and class -# paths to be in the DOS form (i.e. e:/builds/...). This function does the -# appropriate conversion on Windows, but is a noop on other systems. -ifeq ($(HOST_OS_ARCH),WINNT) -# We use 'pwd -W' to get DOS form of the path. However, since the given path -# could be a file or a non-existent path, we cannot call 'pwd -W' directly -# on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W' -# on it, then merge with the rest of the path. -root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|") -non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|") -normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1))) -else -normalizepath = $(1) -endif - -_srcdir = $(call normalizepath,$(srcdir)) -ifdef JAVA_SOURCEPATH -SP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_SOURCEPATH)))) -_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)$(SEP)$(SP)" -else -_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)" -endif - -ifdef JAVA_CLASSPATH -CP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_CLASSPATH)))) -_JAVA_CLASSPATH = ".$(SEP)$(CP)" -else -_JAVA_CLASSPATH = . -endif - -_JAVA_DIR = _java -$(_JAVA_DIR):: - $(NSINSTALL) -D $@ - -$(_JAVA_DIR)/%.class: %.java $(GLOBAL_DEPS) $(_JAVA_DIR) - $(JAVAC) $(JAVAC_FLAGS) -classpath $(_JAVA_CLASSPATH) \ - -sourcepath $(_JAVA_SOURCEPATH) -d $(_JAVA_DIR) $(_VPATH_SRCS) - -$(JAVA_LIBRARY): $(addprefix $(_JAVA_DIR)/,$(JAVA_SRCS:.java=.class)) $(GLOBAL_DEPS) - $(JAR) cf $@ -C $(_JAVA_DIR) . - -GARBAGE_DIRS += $(_JAVA_DIR) - -############################################################################### -# Update Makefiles -############################################################################### - -# Note: Passing depth to make-makefile is optional. -# It saves the script some work, though. -Makefile: Makefile.in - @$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) - -ifdef SUBMAKEFILES -# VPATH does not work on some machines in this case, so add $(srcdir) -$(SUBMAKEFILES): % : $(srcdir)/%.in - $(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) $@ -endif - -ifdef AUTOUPDATE_CONFIGURE -$(topsrcdir)/configure: $(topsrcdir)/configure.in - (cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck) -endif - -$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in - cd $(DEPTH) && CONFIG_HEADERS= CONFIG_FILES=config/autoconf.mk ./config.status - -############################################################################### -# Bunch of things that extend the 'export' rule (in order): -############################################################################### - -################################################################################ -# Copy each element of EXPORTS to $(DIST)/include - -ifneq ($(XPI_NAME),) -$(FINAL_TARGET): - $(NSINSTALL) -D $@ - -export:: $(FINAL_TARGET) -endif - -ifndef NO_DIST_INSTALL -ifneq (,$(EXPORTS)) -export:: $(EXPORTS) - $(INSTALL) $(IFLAGS1) $^ $(DIST)/include -endif -endif # NO_DIST_INSTALL - -define EXPORT_NAMESPACE_RULE -ifndef NO_DIST_INSTALL -export:: $(EXPORTS_$(namespace)) - $(INSTALL) $(IFLAGS1) $$^ $(DIST)/include/$(namespace) -endif # NO_DIST_INSTALL -endef - -$(foreach namespace,$(EXPORTS_NAMESPACES),$(eval $(EXPORT_NAMESPACE_RULE))) - -################################################################################ -# Copy each element of PREF_JS_EXPORTS - -ifdef GRE_MODULE -PREF_DIR = greprefs -else -ifneq (,$(XPI_NAME)$(LIBXUL_SDK)) -PREF_DIR = defaults/preferences -else -PREF_DIR = defaults/pref -endif -endif - -ifneq ($(PREF_JS_EXPORTS),) -# on win32, pref files need CRLF line endings... see bug 206029 -ifeq (WINNT,$(OS_ARCH)) -PREF_PPFLAGS = --line-endings=crlf -endif - -ifndef NO_DIST_INSTALL -$(FINAL_TARGET)/$(PREF_DIR): - $(NSINSTALL) -D $@ - -libs:: $(FINAL_TARGET)/$(PREF_DIR) -libs:: $(PREF_JS_EXPORTS) - $(EXIT_ON_ERROR) \ - for i in $^; do \ - dest=$(FINAL_TARGET)/$(PREF_DIR)/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done -endif -endif - -################################################################################ -# Copy each element of AUTOCFG_JS_EXPORTS to $(FINAL_TARGET)/defaults/autoconfig - -ifneq ($(AUTOCFG_JS_EXPORTS),) -$(FINAL_TARGET)/defaults/autoconfig:: - $(NSINSTALL) -D $@ - -ifndef NO_DIST_INSTALL -export:: $(AUTOCFG_JS_EXPORTS) $(FINAL_TARGET)/defaults/autoconfig - $(INSTALL) $(IFLAGS1) $^ -endif - -endif -################################################################################ -# Export the elements of $(XPIDLSRCS) -# generating .h and .xpt files and moving them to the appropriate places. - -ifneq ($(XPIDLSRCS),) - -export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) - -ifndef XPIDL_MODULE -XPIDL_MODULE = $(MODULE) -endif - -ifeq ($(XPIDL_MODULE),) # we need $(XPIDL_MODULE) to make $(XPIDL_MODULE).xpt -export:: FORCE - @echo - @echo "*** Error processing XPIDLSRCS:" - @echo "Please define MODULE or XPIDL_MODULE when defining XPIDLSRCS," - @echo "so we have a module name to use when creating MODULE.xpt." - @echo; sleep 2; false -endif - -# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include; -# warn against overriding existing .h file. -$(XPIDL_GEN_DIR)/.done: - $(MKDIR) -p $(XPIDL_GEN_DIR) - @$(TOUCH) $@ - -# don't depend on $(XPIDL_GEN_DIR), because the modification date changes -# with any addition to the directory, regenerating all .h files -> everything. - -XPIDL_DEPS = \ - $(topsrcdir)/xpcom/idl-parser/header.py \ - $(topsrcdir)/xpcom/idl-parser/typelib.py \ - $(topsrcdir)/xpcom/idl-parser/xpidl.py \ - $(NULL) - -$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done - $(REPORT_BUILD) - $(PYTHON_PATH) \ - -I$(topsrcdir)/other-licenses/ply \ - -I$(topsrcdir)/xpcom/idl-parser \ - $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ - @if test -n "$(findstring $*.h, $(EXPORTS))"; \ - then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi - -ifndef NO_GEN_XPT -# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link -# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components. -$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done - $(REPORT_BUILD) - $(PYTHON_PATH) \ - -I$(topsrcdir)/other-licenses/ply \ - -I$(topsrcdir)/xpcom/idl-parser \ - -I$(topsrcdir)/xpcom/typelib/xpt/tools \ - $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ - -# no need to link together if XPIDLSRCS contains only XPIDL_MODULE -ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS))) -$(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS) - $(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) -endif # XPIDL_MODULE.xpt != XPIDLSRCS - -libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components -ifndef NO_INTERFACES_MANIFEST - @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt" - @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest" -endif -endif - -endif # NO_GEN_XPT - -GARBAGE_DIRS += $(XPIDL_GEN_DIR) - -endif # XPIDLSRCS - -ifneq ($(XPIDLSRCS),) -# export .idl files to $(IDL_DIR) -ifndef NO_DIST_INSTALL -export:: $(XPIDLSRCS) $(IDL_DIR) - $(INSTALL) $(IFLAGS1) $^ - -export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) $(DIST)/include - $(INSTALL) $(IFLAGS1) $^ -endif # NO_DIST_INSTALL - -endif # XPIDLSRCS - - - -# General rules for exporting idl files. -$(IDL_DIR): - $(NSINSTALL) -D $@ - -export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS) - -ifneq ($(XPIDLSRCS),) -ifndef NO_DIST_INSTALL -export-idl:: $(XPIDLSRCS) $(IDL_DIR) - $(INSTALL) $(IFLAGS1) $^ -endif -endif - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -################################################################################ -# Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components -ifneq (,$(filter %.js,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))) -ifeq (,$(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))) -ifndef NO_JS_MANIFEST -$(error .js component without matching .manifest. See https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0) -endif -endif -endif - -ifdef EXTRA_COMPONENTS -libs:: $(EXTRA_COMPONENTS) -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/components -endif - -endif - -ifdef EXTRA_PP_COMPONENTS -libs:: $(EXTRA_PP_COMPONENTS) -ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(FINAL_TARGET)/components; \ - for i in $^; do \ - fname=`basename $$i`; \ - dest=$(FINAL_TARGET)/components/$${fname}; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done -endif -endif - -EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)) -ifneq (,$(EXTRA_MANIFESTS)) -libs:: - $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))) -endif - -################################################################################ -# Copy each element of EXTRA_JS_MODULES to $(FINAL_TARGET)/modules -ifdef EXTRA_JS_MODULES -libs:: $(EXTRA_JS_MODULES) -ifndef NO_DIST_INSTALL - $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/modules -endif - -endif - -ifdef EXTRA_PP_JS_MODULES -libs:: $(EXTRA_PP_JS_MODULES) -ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(FINAL_TARGET)/modules; \ - for i in $^; do \ - dest=$(FINAL_TARGET)/modules/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done -endif - -endif - -################################################################################ -# SDK - -ifneq (,$(SDK_LIBRARY)) -$(SDK_LIB_DIR):: - $(NSINSTALL) -D $@ - -ifndef NO_DIST_INSTALL -libs:: $(SDK_LIBRARY) $(SDK_LIB_DIR) - $(INSTALL) $(IFLAGS2) $^ -endif - -endif # SDK_LIBRARY - -ifneq (,$(strip $(SDK_BINARY))) -$(SDK_BIN_DIR):: - $(NSINSTALL) -D $@ - -ifndef NO_DIST_INSTALL -libs:: $(SDK_BINARY) $(SDK_BIN_DIR) - $(INSTALL) $(IFLAGS2) $^ -endif - -endif # SDK_BINARY - -################################################################################ -# CHROME PACKAGING - -JAR_MANIFEST := $(srcdir)/jar.mn - -chrome:: - $(MAKE) realchrome - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -$(FINAL_TARGET)/chrome: - $(NSINSTALL) -D $@ - -ifneq (,$(wildcard $(JAR_MANIFEST))) -ifndef NO_DIST_INSTALL -libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome - $(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \ - $(QUIET) -j $(FINAL_TARGET)/chrome \ - $(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \ - $(JAR_MANIFEST) -endif -endif - -ifneq ($(DIST_FILES),) -$(DIST)/bin: - $(NSINSTALL) -D $@ - -libs:: $(DIST)/bin -libs:: $(DIST_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done -endif - -ifneq ($(DIST_CHROME_FILES),) -libs:: $(DIST_CHROME_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/chrome/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done -endif - -ifneq ($(XPI_PKGNAME),) -libs realchrome:: -ifdef STRIP_XPI -ifndef MOZ_DEBUG - @echo "Stripping $(XPI_PKGNAME) package directory..." - @echo $(FINAL_TARGET) - @cd $(FINAL_TARGET) && find . ! -type d \ - ! -name "*.js" \ - ! -name "*.xpt" \ - ! -name "*.gif" \ - ! -name "*.jpg" \ - ! -name "*.png" \ - ! -name "*.xpm" \ - ! -name "*.txt" \ - ! -name "*.rdf" \ - ! -name "*.sh" \ - ! -name "*.properties" \ - ! -name "*.dtd" \ - ! -name "*.html" \ - ! -name "*.xul" \ - ! -name "*.css" \ - ! -name "*.xml" \ - ! -name "*.jar" \ - ! -name "*.dat" \ - ! -name "*.tbl" \ - ! -name "*.src" \ - ! -name "*.reg" \ - $(PLATFORM_EXCLUDE_LIST) \ - -exec $(STRIP) $(STRIP_FLAGS) {} >/dev/null 2>&1 \; -endif -endif - @echo "Packaging $(XPI_PKGNAME).xpi..." - cd $(FINAL_TARGET) && $(ZIP) -qr ../$(XPI_PKGNAME).xpi * -endif - -ifdef INSTALL_EXTENSION_ID -ifndef XPI_NAME -$(error XPI_NAME must be set for INSTALL_EXTENSION_ID) -endif - -libs:: - $(RM) -r "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)" - $(NSINSTALL) -D "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)" - cd $(FINAL_TARGET) && tar $(TAR_CREATE_FLAGS) - . | (cd "../../bin/extensions/$(INSTALL_EXTENSION_ID)" && tar -xf -) - -endif - -ifneq (,$(filter flat symlink,$(MOZ_CHROME_FILE_FORMAT))) -_JAR_REGCHROME_DISABLE_JAR=1 -else -_JAR_REGCHROME_DISABLE_JAR=0 -endif - -REGCHROME = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \ - $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \ - $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(FINAL_TARGET)/chrome/installed-chrome.txt \ - $(_JAR_REGCHROME_DISABLE_JAR) - -REGCHROME_INSTALL = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \ - $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \ - $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(DESTDIR)$(mozappdir)/chrome/installed-chrome.txt \ - $(_JAR_REGCHROME_DISABLE_JAR) - - -############################################################################# -# Dependency system -############################################################################# -ifdef COMPILER_DEPEND -depend:: - @echo "$(MAKE): No need to run depend target.\ - Using compiler-based depend." 1>&2 -ifeq ($(GNU_CC)$(GNU_CXX),) -# Non-GNU compilers - @echo "`echo '$(MAKE):'|sed 's/./ /g'`"\ - '(Compiler-based depend was turned on by "--enable-md".)' 1>&2 -else -# GNU compilers - @space="`echo '$(MAKE): '|sed 's/./ /g'`";\ - echo "$$space"'Since you are using a GNU compiler,\ - it is on by default.' 1>&2; \ - echo "$$space"'To turn it off, pass --disable-md to configure.' 1>&2 -endif - -else # ! COMPILER_DEPEND - -ifndef MOZ_AUTO_DEPS - -define MAKE_DEPS_NOAUTO - $(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@ -endef - -$(MDDEPDIR)/%.pp: %.c - $(REPORT_BUILD) - @$(MAKE_DEPS_NOAUTO) - -$(MDDEPDIR)/%.pp: %.cpp - $(REPORT_BUILD) - @$(MAKE_DEPS_NOAUTO) - -$(MDDEPDIR)/%.pp: %.s - $(REPORT_BUILD) - @$(MAKE_DEPS_NOAUTO) - -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) -depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES) -else -depend:: $(SUBMAKEFILES) -endif - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -dependclean:: $(SUBMAKEFILES) - $(RM) $(MDDEPFILES) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) - -endif # MOZ_AUTO_DEPS - -endif # COMPILER_DEPEND - - -############################################################################# -# MDDEPDIR is the subdirectory where all the dependency files are placed. -# This uses a make rule (instead of a macro) to support parallel -# builds (-jN). If this were done in the LOOP_OVER_DIRS macro, two -# processes could simultaneously try to create the same directory. -# -# We use $(CURDIR) in the rule's target to ensure that we don't find -# a dependency directory in the source tree via VPATH (perhaps from -# a previous build in the source tree) and thus neglect to create a -# dependency directory in the object directory, where we really need -# it. - -$(CURDIR)/$(MDDEPDIR): - $(MKDIR) -p $@ - -ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS))) -ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) -MDDEPEND_FILES := $(strip $(wildcard $(MDDEPDIR)/*.pp)) - -ifneq (,$(MDDEPEND_FILES)) -# The script mddepend.pl checks the dependencies and writes to stdout -# one rule to force out-of-date objects. For example, -# foo.o boo.o: FORCE -# The script has an advantage over including the *.pp files directly -# because it handles the case when header files are removed from the build. -# 'make' would complain that there is no way to build missing headers. -ALL_PP_RESULTS = $(shell $(PERL) $(BUILD_TOOLS)/mddepend.pl - $(MDDEPEND_FILES)) -$(eval $(ALL_PP_RESULTS)) -endif - -endif -endif -############################################################################# - --include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk --include $(MY_RULES) - -# -# Generate Emacs tags in a file named TAGS if ETAGS was set in $(MY_CONFIG) -# or in $(MY_RULES) -# -ifdef ETAGS -ifneq ($(CSRCS)$(CPPSRCS)$(HEADERS),) -all:: TAGS -TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS) - $(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS) -endif -endif - -################################################################################ -# Special gmake rules. -################################################################################ - - -# -# Disallow parallel builds with MSVC < 8 -# -ifneq (,$(filter 1200 1300 1310,$(_MSC_VER))) -.NOTPARALLEL: -endif - -# -# Re-define the list of default suffixes, so gmake won't have to churn through -# hundreds of built-in suffix rules for stuff we don't need. -# -.SUFFIXES: - -# -# Fake targets. Always run these rules, even if a file/directory with that -# name already exists. -# -.PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE - -# Used as a dependency to force targets to rebuild -FORCE: - -# Delete target if error occurs when building target -.DELETE_ON_ERROR: - -# Properly set LIBPATTERNS for the platform -.LIBPATTERNS = $(if $(IMPORT_LIB_SUFFIX),$(LIB_PREFIX)%.$(IMPORT_LIB_SUFFIX)) $(LIB_PREFIX)%.$(LIB_SUFFIX) $(DLL_PREFIX)%$(DLL_SUFFIX) - -tags: TAGS - -TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h) - -etags $(CSRCS) $(CPPSRCS) $(wildcard *.h) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - -echo-variable-%: - @echo "$($*)" - -echo-tiers: - @echo $(TIERS) - -echo-tier-dirs: - @$(foreach tier,$(TIERS),echo '$(tier):'; echo ' dirs: $(tier_$(tier)_dirs)'; echo ' staticdirs: $(tier_$(tier)_staticdirs)'; ) - -echo-dirs: - @echo $(DIRS) - -echo-module: - @echo $(MODULE) - -echo-depth-path: - @$(topsrcdir)/build/unix/print-depth-path.sh - -echo-module-name: - @$(topsrcdir)/build/package/rpm/print-module-name.sh - -echo-module-filelist: - @$(topsrcdir)/build/package/rpm/print-module-filelist.sh - -showtargs: -ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS))) - @echo -------------------------------------------------------------------------------- - @echo "PROGRAM = $(PROGRAM)" - @echo "SIMPLE_PROGRAMS = $(SIMPLE_PROGRAMS)" - @echo "LIBRARY = $(LIBRARY)" - @echo "SHARED_LIBRARY = $(SHARED_LIBRARY)" - @echo "SHARED_LIBRARY_LIBS = $(SHARED_LIBRARY_LIBS)" - @echo "LIBS = $(LIBS)" - @echo "DEF_FILE = $(DEF_FILE)" - @echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)" - @echo "STATIC_LIBS = $(STATIC_LIBS)" - @echo "SHARED_LIBS = $(SHARED_LIBS)" - @echo "EXTRA_DSO_LIBS = $(EXTRA_DSO_LIBS)" - @echo "EXTRA_DSO_LDOPTS = $(EXTRA_DSO_LDOPTS)" - @echo "DEPENDENT_LIBS = $(DEPENDENT_LIBS)" - @echo -------------------------------------------------------------------------------- -endif - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - -showbuild: - @echo "MOZ_BUILD_ROOT = $(MOZ_BUILD_ROOT)" - @echo "MOZ_WIDGET_TOOLKIT = $(MOZ_WIDGET_TOOLKIT)" - @echo "CC = $(CC)" - @echo "CXX = $(CXX)" - @echo "CCC = $(CCC)" - @echo "CPP = $(CPP)" - @echo "LD = $(LD)" - @echo "AR = $(AR)" - @echo "IMPLIB = $(IMPLIB)" - @echo "FILTER = $(FILTER)" - @echo "MKSHLIB = $(MKSHLIB)" - @echo "MKCSHLIB = $(MKCSHLIB)" - @echo "RC = $(RC)" - @echo "MC = $(MC)" - @echo "CFLAGS = $(CFLAGS)" - @echo "OS_CFLAGS = $(OS_CFLAGS)" - @echo "COMPILE_CFLAGS = $(COMPILE_CFLAGS)" - @echo "CXXFLAGS = $(CXXFLAGS)" - @echo "OS_CXXFLAGS = $(OS_CXXFLAGS)" - @echo "COMPILE_CXXFLAGS = $(COMPILE_CXXFLAGS)" - @echo "COMPILE_CMFLAGS = $(COMPILE_CMFLAGS)" - @echo "COMPILE_CMMFLAGS = $(COMPILE_CMMFLAGS)" - @echo "LDFLAGS = $(LDFLAGS)" - @echo "OS_LDFLAGS = $(OS_LDFLAGS)" - @echo "DSO_LDOPTS = $(DSO_LDOPTS)" - @echo "OS_INCLUDES = $(OS_INCLUDES)" - @echo "OS_LIBS = $(OS_LIBS)" - @echo "EXTRA_LIBS = $(EXTRA_LIBS)" - @echo "BIN_FLAGS = $(BIN_FLAGS)" - @echo "INCLUDES = $(INCLUDES)" - @echo "DEFINES = $(DEFINES)" - @echo "ACDEFINES = $(ACDEFINES)" - @echo "BIN_SUFFIX = $(BIN_SUFFIX)" - @echo "LIB_SUFFIX = $(LIB_SUFFIX)" - @echo "DLL_SUFFIX = $(DLL_SUFFIX)" - @echo "IMPORT_LIB_SUFFIX = $(IMPORT_LIB_SUFFIX)" - @echo "INSTALL = $(INSTALL)" - @echo "VPATH = $(VPATH)" - -showhost: - @echo "HOST_CC = $(HOST_CC)" - @echo "HOST_CXX = $(HOST_CXX)" - @echo "HOST_CFLAGS = $(HOST_CFLAGS)" - @echo "HOST_LDFLAGS = $(HOST_LDFLAGS)" - @echo "HOST_LIBS = $(HOST_LIBS)" - @echo "HOST_EXTRA_LIBS = $(HOST_EXTRA_LIBS)" - @echo "HOST_EXTRA_DEPS = $(HOST_EXTRA_DEPS)" - @echo "HOST_PROGRAM = $(HOST_PROGRAM)" - @echo "HOST_OBJS = $(HOST_OBJS)" - @echo "HOST_PROGOBJS = $(HOST_PROGOBJS)" - @echo "HOST_LIBRARY = $(HOST_LIBRARY)" - -showbuildmods:: - @echo "Module dirs = $(BUILD_MODULE_DIRS)" - -documentation: - @cd $(DEPTH) - $(DOXYGEN) $(DEPTH)/config/doxygen.cfg - -ifdef ENABLE_TESTS -check:: $(SUBMAKEFILES) $(MAKE_DIRS) - $(LOOP_OVER_PARALLEL_DIRS) - $(LOOP_OVER_DIRS) - $(LOOP_OVER_TOOL_DIRS) -endif - - -FREEZE_VARIABLES = \ - CSRCS \ - CPPSRCS \ - EXPORTS \ - XPIDLSRCS \ - DIRS \ - LIBRARY \ - MODULE \ - SHORT_LIBNAME \ - TIERS \ - EXTRA_COMPONENTS \ - EXTRA_PP_COMPONENTS \ - $(NULL) - -$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))')) - -CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \ - $(if $(subst $($(var)_FROZEN),,'$($(var))'),$(error Makefile variable '$(var)' changed value after including rules.mk. Was $($(var)_FROZEN), now $($(var)).))) - -libs export libs:: - $(CHECK_FROZEN_VARIABLES) - -default all:: - if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi diff --git a/js/src/jit-test/tests/collections/bug-743101.js b/js/src/jit-test/tests/collections/bug-743101.js new file mode 100644 index 000000000000..d30f3fc4e03c --- /dev/null +++ b/js/src/jit-test/tests/collections/bug-743101.js @@ -0,0 +1,5 @@ +load(libdir + "asserts.js"); + +var g = newGlobal('new-compartment'); +assertThrowsInstanceOf(function () { Map.prototype.size.apply(g, []); }, g.TypeError); +assertThrowsInstanceOf(function () { Set.prototype.size.apply(g, []); }, g.TypeError); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-01.js b/js/src/jit-test/tests/debug/Environment-getVariable-01.js new file mode 100644 index 000000000000..dd11d45a64ee --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-01.js @@ -0,0 +1,14 @@ +// Environment.prototype.getVariable does not see variables bound in enclosing scopes. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var hits = 0; +dbg.onDebuggerStatement = function (frame) { + assertEq(frame.environment.getVariable("x"), 13); + assertEq(frame.environment.getVariable("k"), undefined); + assertEq(frame.environment.find("k").getVariable("k"), 3); + hits++; +}; +g.eval("var k = 3; function f(x) { debugger; }"); +g.f(13); +assertEq(hits, 1); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-02.js b/js/src/jit-test/tests/debug/Environment-getVariable-02.js new file mode 100644 index 000000000000..640637d1f8e2 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-02.js @@ -0,0 +1,16 @@ +// getVariable works in function scopes. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var hits = 0; +dbg.onDebuggerStatement = function (frame) { + assertEq(frame.environment.getVariable("a"), 1); + assertEq(frame.environment.getVariable("b"), 2); + assertEq(frame.environment.getVariable("c"), 3); + assertEq(frame.environment.getVariable("d"), 4); + assertEq(frame.environment.getVariable("e"), 5); + hits++; +}; +g.eval("function f(a, [b, c]) { var d = c + 1; let e = d + 1; debugger; }"); +g.f(1, [2, 3]); +assertEq(hits, 1); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-03.js b/js/src/jit-test/tests/debug/Environment-getVariable-03.js new file mode 100644 index 000000000000..e18e8e0893c5 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-03.js @@ -0,0 +1,22 @@ +// getVariable sees bindings in let-block scopes. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var log = ''; +dbg.onDebuggerStatement = function (frame) { + log += frame.environment.getVariable("x"); +}; +g.eval("function f() {\n" + + " let x = 'a';\n" + + " debugger;\n" + + " for (let x = 0; x < 2; x++)\n" + + " if (x === 0)\n" + + " debugger;\n" + + " else {\n" + + " let x = 'b'; debugger;\n" + + " }\n" + + "}\n"); +g.f(); +g.eval("let (x = 'c') { debugger; }"); +g.eval("{ let x = 'd'; debugger; }"); +assertEq(log, 'a0bcd'); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-04.js b/js/src/jit-test/tests/debug/Environment-getVariable-04.js new file mode 100644 index 000000000000..1667433b5134 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-04.js @@ -0,0 +1,12 @@ +// getVariable sees variables in function scopes added by non-strict direct eval. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var v; +dbg.onDebuggerStatement = function (frame) { + v = frame.environment.getVariable("x"); +}; + +g.eval("function f(s) { eval(s); debugger; }"); +g.f("var x = 'Q';"); +assertEq(v, 'Q'); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-05.js b/js/src/jit-test/tests/debug/Environment-getVariable-05.js new file mode 100644 index 000000000000..ef681950adf8 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-05.js @@ -0,0 +1,10 @@ +// getVariable sees global variables. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var log = ''; +dbg.onDebuggerStatement = function (frame) { + log += frame.environment.getVariable("x") + frame.environment.getVariable("y"); +}; +g.eval("var x = 'a'; this.y = 'b'; debugger;"); +assertEq(log, 'ab'); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-06.js b/js/src/jit-test/tests/debug/Environment-getVariable-06.js new file mode 100644 index 000000000000..f291912ab24d --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-06.js @@ -0,0 +1,12 @@ +// getVariable sees properties inherited from the global object's prototype chain. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var log = ''; +dbg.onDebuggerStatement = function (frame) { + log += frame.environment.getVariable("x") + frame.environment.getVariable("y"); +}; +g.eval("Object.getPrototypeOf(this).x = 'a';\n" + + "Object.prototype.y = 'b';\n" + + "debugger;\n"); +assertEq(log, 'ab'); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-07.js b/js/src/jit-test/tests/debug/Environment-getVariable-07.js new file mode 100644 index 000000000000..5ce20050b2bc --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-07.js @@ -0,0 +1,10 @@ +// getVariable can get properties from with-block scopes. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var v; +dbg.onDebuggerStatement = function (frame) { + v = frame.environment.getVariable("x"); +}; +g.eval("var x = 1; { let x = 2; with ({x: 3}) { debugger; } }"); +assertEq(v, 3); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-08.js b/js/src/jit-test/tests/debug/Environment-getVariable-08.js new file mode 100644 index 000000000000..6a7b28b933bf --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-08.js @@ -0,0 +1,10 @@ +// getVariable sees properties inherited from a with-object's prototype chain. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var v; +dbg.onDebuggerStatement = function (frame) { + v = frame.environment.getVariable("x"); +}; +g.eval("var x = 1; { let x = 2; with (Object.create({x: 3})) { debugger; } }"); +assertEq(v, 3); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-09.js b/js/src/jit-test/tests/debug/Environment-getVariable-09.js new file mode 100644 index 000000000000..49b635c1cfda --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-09.js @@ -0,0 +1,13 @@ +// getVariable works on ancestors of frame.environment. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var log = ''; +dbg.onDebuggerStatement = function (frame) { + for (var env = frame.environment; env; env = env.parent) { + if (env.find("x") === env) + log += env.getVariable("x"); + } +}; +g.eval("var x = 1; { let x = 2; with (Object.create({x: 3})) { debugger; } }"); +assertEq(log, "321"); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-10.js b/js/src/jit-test/tests/debug/Environment-getVariable-10.js new file mode 100644 index 000000000000..8cfb4509a144 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-10.js @@ -0,0 +1,27 @@ +// getVariable works on a heavyweight environment after control leaves its scope. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var envs = []; +dbg.onDebuggerStatement = function (frame) { + envs.push(frame.environment); +}; +g.eval("var f;\n" + + "for (var x = 0; x < 3; x++) {\n" + + " (function (x) {\n" + + " for (var y = 0; y < 3; y++) {\n" + + " (function (z) {\n" + + " eval(z); // force heavyweight\n" + + " debugger;\n" + + " })(x + y);\n" + + " }\n" + + " })(x);\n" + + "}"); + +var i = 0; +for (var x = 0; x < 3; x++) { + for (var y = 0; y < 3; y++) { + var e = envs[i++]; + assertEq(e.getVariable("z"), x + y); + } +} diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-11.js b/js/src/jit-test/tests/debug/Environment-getVariable-11.js new file mode 100644 index 000000000000..0a0b73e420ed --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-11.js @@ -0,0 +1,15 @@ +// The value returned by getVariable can be a Debugger.Object. + +var g = newGlobal('new-compartment'); +var dbg = new Debugger; +var gw = dbg.addDebuggee(g); +var hits = 0; +dbg.onDebuggerStatement = function (frame) { + var a = frame.environment.getVariable('Math'); + assertEq(a instanceof Debugger.Object, true); + var b = gw.getOwnPropertyDescriptor('Math').value; + assertEq(a, b); + hits++; +}; +g.eval("debugger;"); +assertEq(hits, 1); diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-WouldRun.js b/js/src/jit-test/tests/debug/Environment-getVariable-WouldRun.js new file mode 100644 index 000000000000..9b7d7078e843 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-WouldRun.js @@ -0,0 +1,17 @@ +// getVariable that would trigger a getter does not crash or explode. +// It should throw WouldRunDebuggee, but that isn't implemented yet. + +load(libdir + "asserts.js"); + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var hits = 0; +dbg.onDebuggerStatement = function (frame) { + assertThrowsInstanceOf(function () { + frame.environment.getVariable("x"); + }, Error); + hits++; +}; +g.eval("Object.defineProperty(this, 'x', {get: function () { throw new Error('fail'); }});\n" + + "debugger;"); +assertEq(hits, 1); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-01.js b/js/src/jit-test/tests/debug/Environment-setVariable-01.js new file mode 100644 index 000000000000..adace4208175 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-01.js @@ -0,0 +1,9 @@ +// Environment.prototype.setVariable can set global variables. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +dbg.onDebuggerStatement = function (frame) { + frame.environment.setVariable("x", 2); +}; +g.eval("var x = 1; debugger;"); +assertEq(g.x, 2); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-02.js b/js/src/jit-test/tests/debug/Environment-setVariable-02.js new file mode 100644 index 000000000000..4b54d370a1d7 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-02.js @@ -0,0 +1,10 @@ +// The argument to setVariable can be a Debugger.Object. + +var g = newGlobal('new-compartment'); +var dbg = new Debugger; +var gw = dbg.addDebuggee(g); +dbg.onDebuggerStatement = function (frame) { + frame.environment.setVariable("x", gw); +}; +g.eval("var x = 1; debugger;"); +assertEq(g.x, g); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-03.js b/js/src/jit-test/tests/debug/Environment-setVariable-03.js new file mode 100644 index 000000000000..1e98727e707a --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-03.js @@ -0,0 +1,16 @@ +// setVariable cannot create new global variables. +// (Other kinds of environment are tested in Environment-variables.js.) + +load(libdir + "asserts.js"); + +var g = newGlobal('new-compartment'); +var dbg = new Debugger(g); +var hits = 0; +dbg.onDebuggerStatement = function (frame) { + assertThrowsInstanceOf(function () { frame.environment.setVariable("x", 7); }, TypeError); + hits++; +}; +g.eval("debugger"); +assertEq("x" in g, false); +assertEq(hits, 1); + diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-04.js b/js/src/jit-test/tests/debug/Environment-setVariable-04.js new file mode 100644 index 000000000000..77c34ae7cb20 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-04.js @@ -0,0 +1,10 @@ +// setVariable can set variables and arguments in functions. + +var g = newGlobal('new-compartment'); +var dbg = new Debugger(g); +dbg.onDebuggerStatement = function (frame) { + frame.environment.setVariable("a", 100); + frame.environment.setVariable("b", 200); +}; +g.eval("function f(a) { var b = a + 1; debugger; return a + b; }"); +assertEq(g.f(1), 300); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-05.js b/js/src/jit-test/tests/debug/Environment-setVariable-05.js new file mode 100644 index 000000000000..4fc9479296a1 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-05.js @@ -0,0 +1,14 @@ +// setVariable can change the types of variables and arguments in functions. + +var g = newGlobal('new-compartment'); +g.eval("function f(a) { var b = a + 1; debugger; return a + b; }"); +for (var i = 0; i < 20; i++) + assertEq(g.f(i), 2 * i + 1); + +var dbg = new Debugger(g); +dbg.onDebuggerStatement = function (frame) { + frame.environment.setVariable("a", "xyz"); + frame.environment.setVariable("b", "zy"); +}; +for (var i = 0; i < 10; i++) + assertEq(g.f(i), "xyzzy"); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-06.js b/js/src/jit-test/tests/debug/Environment-setVariable-06.js new file mode 100644 index 000000000000..0667a028e8ae --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-06.js @@ -0,0 +1,9 @@ +// setVariable on an argument works as expected with non-strict 'arguments'. + +var g = newGlobal('new-compartment'); +g.eval("function f(a) { debugger; return arguments[0]; }"); +var dbg = new Debugger(g); +dbg.onDebuggerStatement = function (frame) { + frame.environment.setVariable("a", 2); +}; +assertEq(g.f(1), 2); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-07.js b/js/src/jit-test/tests/debug/Environment-setVariable-07.js new file mode 100644 index 000000000000..f1b934528ad4 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-07.js @@ -0,0 +1,15 @@ +// setVariable works on let-bindings. + +var g = newGlobal('new-compartment'); +function test(code, val) { + g.eval("function f() { " + code + " }"); + var dbg = new Debugger(g); + dbg.onDebuggerStatement = function (frame) { + frame.environment.setVariable("a", val); + }; + assertEq(g.f(), val); +} + +test("let a = 1; debugger; return a;", "xyzzy"); +test("{ let a = 1; debugger; return a; }", "plugh"); +test("let (a = 1) { debugger; return a; }", "wcgr"); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-08.js b/js/src/jit-test/tests/debug/Environment-setVariable-08.js new file mode 100644 index 000000000000..c0a8402787e4 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-08.js @@ -0,0 +1,29 @@ +// setVariable throws if no binding exists. + +load(libdir + "asserts.js"); + +function test(code) { + var g = newGlobal('new-compartment'); + var dbg = new Debugger(g); + var hits = 0; + dbg.onDebuggerStatement = function (frame) { + var env = frame.older.environment; + assertThrowsInstanceOf(function () { env.setVariable("y", 2); }, Error); + hits++; + }; + g.eval("var y = 0; function d() { debugger; }"); + + assertEq(g.eval(code), 0); + + assertEq(g.y, 0); + assertEq(hits, 1); +} + +// local scope of non-heavyweight function +test("function f() { var x = 1; d(); return y; } f();"); + +// block scope +test("function h(x) { if (x) { let x = 1; d(); return y; } } h(3);"); + +// strict eval scope +test("'use strict'; eval('d(); y;');"); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-10.js b/js/src/jit-test/tests/debug/Environment-setVariable-10.js new file mode 100644 index 000000000000..3eaa8c2e17f9 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-10.js @@ -0,0 +1,32 @@ +// setVariable works on non-innermost environments. + +// (The debuggee code here is a bit convoluted to defeat optimizations that +// could make obj.b a null closure or obj.i a flat closure--that is, a function +// that gets a frozen copy of i instead of a reference to the runtime +// environment that contains it. setVariable does not currently detect this +// flat closure case.) + +var g = newGlobal('new-compartment'); +g.eval("function d() { debugger; }\n" + + "var i = 'FAIL';\n" + + "function a() {\n" + + " var obj = {b: function (i) { d(obj); return i; },\n" + + " i: function () { return i; }};\n" + + " var i = 'FAIL2';\n" + + " return obj;\n" + + "}\n"); + +var dbg = Debugger(g); +dbg.onDebuggerStatement = function (frame) { + var x = 0; + for (var env = frame.older.environment; env; env = env.parent) { + if (env.getVariable("i") !== undefined) + env.setVariable("i", x++); + } +}; + +var obj = g.a(); +var r = obj.b('FAIL3'); +assertEq(r, 0); +assertEq(obj.i(), 1); +assertEq(g.i, 2); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-11.js b/js/src/jit-test/tests/debug/Environment-setVariable-11.js new file mode 100644 index 000000000000..5010572159ef --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-11.js @@ -0,0 +1,16 @@ +// setVariable cannot modify the binding for a FunctionExpression's name. + +load(libdir + "asserts.js"); + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +var hits = 0; +dbg.onDebuggerStatement = function (frame) { + var env = frame.environment.find("f"); + assertEq(env.getVariable("f"), frame.callee); + assertThrowsInstanceOf(function () { env.setVariable("f", 0) }, TypeError); + assertThrowsInstanceOf(function () { env.setVariable("f", frame.callee) }, TypeError); + hits++; +}; +g.eval("(function f() { debugger; })();"); +assertEq(hits, 1); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-12.js b/js/src/jit-test/tests/debug/Environment-setVariable-12.js new file mode 100644 index 000000000000..c0e05551e5a9 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-12.js @@ -0,0 +1,21 @@ +// setVariable can create a new property on a with block's bindings object, if +// it is shadowing an existing property on the prototype chain. + +var g = newGlobal('new-compartment'); +var dbg = Debugger(g); +dbg.onDebuggerStatement = function (frame) { + var env = frame.environment.find("x"); + env.setVariable("x", 2); +}; +g.eval("var obj1 = {x: 1}, obj2 = Object.create(obj1), z; with (obj2) { debugger; z = x; }"); +assertEq(g.obj1.x, 1); +assertEq(g.obj2.x, 2); +assertEq(g.z, 2); + +// The property created by setVariable is like the one created by ordinary +// assignment in a with-block. +var desc = Object.getOwnPropertyDescriptor(g.obj2, "x"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, true); +assertEq(desc.writable, true); +assertEq(desc.value, 2); diff --git a/js/src/jit-test/tests/debug/Environment-setVariable-WouldRun.js b/js/src/jit-test/tests/debug/Environment-setVariable-WouldRun.js new file mode 100644 index 000000000000..3335fa2ca1dd --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-setVariable-WouldRun.js @@ -0,0 +1,22 @@ +// setVariable triggering a setter doesn't crash or explode. +// It should throw WouldRunDebuggee, but that isn't implemented yet. + +function test(code) { + var g = newGlobal('new-compartment'); + g.eval("function d() { debugger; }"); + var dbg = Debugger(g); + var hits = 0; + dbg.onDebuggerStatement = function (frame) { + var env = frame.environment.find("x"); + try { + env.setVariable("x", 0); + } catch (exc) { + } + hits++; + }; + g.eval(code); +} + +test("Object.defineProperty(this, 'x', {set: function (v) {}}); d();"); +test("Object.defineProperty(Object.prototype, 'x', {set: function (v) {}}); d();"); +test("with ({set x(v) {}}) eval(d());"); diff --git a/js/src/jit-test/tests/debug/Environment-variables.js b/js/src/jit-test/tests/debug/Environment-variables.js new file mode 100644 index 000000000000..9f6a2f160a91 --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-variables.js @@ -0,0 +1,92 @@ +// Comprehensive test of get/setVariable on many kinds of environments and +// bindings. + +load(libdir + "asserts.js"); + +var cases = [ + // global bindings and bindings on the global prototype chain + "x = VAL; @@", + "var x = VAL; @@", + "Object.prototype.x = VAL; @@", + + // let, catch, and comprehension bindings + "let x = VAL; @@", + "{ let x = VAL; @@ }", + "let (x = VAL) { @@ }", + "try { throw VAL; } catch (x) { @@ }", + "try { throw VAL; } catch (x) { @@ }", + "for (let x of [VAL]) { @@ }", + "for each (let x in [VAL]) { @@ }", + "switch (0) { default: let x = VAL; @@ }", + "[function () { @@ }() for (x of [VAL])];", + // "((function () { @@ })() for (x of [VAL])).next();", // bug 709367 + + // arguments + "function f(x) { @@ } f(VAL);", + "function f([w, x]) { @@ } f([0, VAL]);", + "function f({v: x}) { @@ } f({v: VAL});", + "function f([w, {v: x}]) { @@ } f([0, {v: VAL}]);", + + // bindings in functions + "function f() { var x = VAL; @@ } f();", + "function f() { let x = VAL; @@ } f();", + "function f([x]) { let x = VAL; @@ } f(['fail']);", + "function f(x) { { let x = VAL; @@ } } f('fail');", + "function f() { function x() {} x = VAL; @@ } f();", + + // dynamic bindings + "function f(s) { eval(s); @@ } f('var x = VAL');", + "function f(s) { let (x = 'fail') { eval(s); } x = VAL; @@ } f('var x;');", + "var x = VAL; function f(s) { eval('var x = 0;'); eval(s); @@ } f('delete x;');", + "function f(obj) { with (obj) { @@ } } f({x: VAL});", + "function f(obj) { with (obj) { @@ } } f(Object.create({x: VAL}));", + "function f(b) { if (b) { function x(){} } x = VAL; @@ } f(1);", +]; + +var nextval = 1000; + +function test(code, debugStmts, followupStmts) { + var val = nextval++; + var hits = 0; + + var g = newGlobal('new-compartment'); + g.eval("function debugMe() { var x = 'wrong-x'; debugger; }"); + g.capture = null; + + var dbg = Debugger(g); + dbg.onDebuggerStatement = function (frame) { + if (frame.callee !== null && frame.callee.name == 'debugMe') + frame = frame.older; + var env = frame.environment.find("x"); + assertEq(env.getVariable("x"), val) + assertEq(env.setVariable("x", 'ok'), undefined); + assertEq(env.getVariable("x"), 'ok'); + + // setVariable cannot create new variables. + assertThrowsInstanceOf(function () { env.setVariable("newVar", 0); }, TypeError); + hits++; + }; + + code = code.replace("@@", debugStmts); + if (followupStmts !== undefined) + code += " " + followupStmts; + code = code.replace(/VAL/g, uneval(val)); + g.eval(code); + assertEq(hits, 1); +} + +for (var s of cases) { + // Test triggering the debugger right in the scope in which x is bound. + test(s, "debugger; assertEq(x, 'ok');"); + + // Test calling a function that triggers the debugger. + test(s, "debugMe(); assertEq(x, 'ok');"); + + // Test triggering the debugger from a scope nested in x's scope. + test(s, "let (y = 'irrelevant') { (function (z) { let (zz = y) { debugger; }})(); } assertEq(x, 'ok');"), + + // Test closing over the variable and triggering the debugger later, after + // leaving the variable's scope. + test(s, "capture = {dbg: function () { debugger; }, get x() { return x; }};", + "assertEq(capture.x, VAL); capture.dbg(); assertEq(capture.x, 'ok');"); +} diff --git a/js/src/js.msg b/js/src/js.msg index cead265e494f..7f6782f08867 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -377,3 +377,5 @@ MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 290, 0, JSEXN_SYNTAXERR, "mistyped ; after MSG_DEF(JSMSG_NOT_ITERABLE, 291, 1, JSEXN_TYPEERR, "{0} is not iterable") MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 292, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property") MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 293, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties") +MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment") + diff --git a/js/src/jsapi-tests/testBug604087.cpp b/js/src/jsapi-tests/testBug604087.cpp index e968d3a767b1..5f49d94188a9 100644 --- a/js/src/jsapi-tests/testBug604087.cpp +++ b/js/src/jsapi-tests/testBug604087.cpp @@ -38,7 +38,7 @@ wrap(JSContext *cx, JSObject *toWrap, JSObject *target) static JSObject * PreWrap(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags) { - JS_GC(cx); + JS_GC(JS_GetRuntime(cx)); return obj; } diff --git a/js/src/jsapi-tests/testConservativeGC.cpp b/js/src/jsapi-tests/testConservativeGC.cpp index 726aae766afc..727067861c1a 100644 --- a/js/src/jsapi-tests/testConservativeGC.cpp +++ b/js/src/jsapi-tests/testConservativeGC.cpp @@ -29,14 +29,14 @@ BEGIN_TEST(testConservativeGC) tmp = JSVAL_NULL; - JS_GC(cx); + JS_GC(rt); EVAL("var a = [];\n" "for (var i = 0; i != 10000; ++i) {\n" "a.push(i + 0.1, [1, 2], String(Math.sqrt(i)), {a: i});\n" "}", &tmp); - JS_GC(cx); + JS_GC(rt); checkObjectFields((JSObject *)objCopy, JSVAL_TO_OBJECT(v2)); CHECK(!memcmp(&strCopy, JSVAL_TO_STRING(v3), sizeof(strCopy))); @@ -69,7 +69,7 @@ BEGIN_TEST(testDerivedValues) for (int i = 0; i < 3; i++) { for (int j = 0; j < 1000; j++) JS_NewStringCopyZ(cx, "as I pondered weak and weary"); - JS_GC(cx); + JS_GC(rt); } CHECK(!memcmp(ch, expected, sizeof(expected))); diff --git a/js/src/jsapi-tests/testExternalStrings.cpp b/js/src/jsapi-tests/testExternalStrings.cpp index 6510aa3c274a..f7e808bf53ad 100644 --- a/js/src/jsapi-tests/testExternalStrings.cpp +++ b/js/src/jsapi-tests/testExternalStrings.cpp @@ -39,7 +39,7 @@ BEGIN_TEST(testExternalStrings) // clear that newborn root JS_NewUCStringCopyN(cx, arr, arrlen); - JS_GC(cx); + JS_GC(rt); // a generous fudge factor to account for strings rooted by conservative gc const unsigned epsilon = 10; diff --git a/js/src/jsapi-tests/testGCOutOfMemory.cpp b/js/src/jsapi-tests/testGCOutOfMemory.cpp index cdac4cf4a691..8234d12bcbeb 100644 --- a/js/src/jsapi-tests/testGCOutOfMemory.cpp +++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp @@ -37,7 +37,7 @@ BEGIN_TEST(testGCOutOfMemory) CHECK(!ok); CHECK(!JS_IsExceptionPending(cx)); CHECK_EQUAL(errorCount, 1); - JS_GC(cx); + JS_GC(rt); EVAL("(function() {" " var array = [];" " for (var i = max >> 2; i != 0;) {" diff --git a/js/src/jsapi-tests/testIntern.cpp b/js/src/jsapi-tests/testIntern.cpp index 5bf32ccb4007..6ed718327d0a 100644 --- a/js/src/jsapi-tests/testIntern.cpp +++ b/js/src/jsapi-tests/testIntern.cpp @@ -36,7 +36,7 @@ BEGIN_TEST(testInternAcrossGC) sw.strOk = false; CHECK(sw.str); JS_SetFinalizeCallback(rt, FinalizeCallback); - JS_GC(cx); + JS_GC(rt); CHECK(sw.strOk); return true; } diff --git a/js/src/jsapi-tests/testScriptObject.cpp b/js/src/jsapi-tests/testScriptObject.cpp index 3aed403f6ffb..eebadaccbf05 100644 --- a/js/src/jsapi-tests/testScriptObject.cpp +++ b/js/src/jsapi-tests/testScriptObject.cpp @@ -19,7 +19,7 @@ struct ScriptObjectFixture : public JSAPITest { { CHECK(script); - JS_GC(cx); + JS_GC(rt); /* After a garbage collection, the script should still work. */ jsval result; diff --git a/js/src/jsapi-tests/testTrap.cpp b/js/src/jsapi-tests/testTrap.cpp index 24cd3bda35f4..91b4debd758a 100644 --- a/js/src/jsapi-tests/testTrap.cpp +++ b/js/src/jsapi-tests/testTrap.cpp @@ -11,7 +11,7 @@ static JSTrapStatus EmptyTrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsval closure) { - JS_GC(cx); + JS_GC(JS_GetRuntime(cx)); if (JSVAL_IS_STRING(closure)) ++emptyTrapCallCount; return JSTRAP_CONTINUE; @@ -59,7 +59,7 @@ BEGIN_TEST(testTrap_gc) JS_SetTrap(cx, script, line2, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure)); JS_SetTrap(cx, script, line6, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure)); - JS_GC(cx); + JS_GC(rt); CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText)); } @@ -68,7 +68,7 @@ BEGIN_TEST(testTrap_gc) CHECK(JS_ExecuteScript(cx, global, script, v2.addr())); CHECK_EQUAL(emptyTrapCallCount, 11); - JS_GC(cx); + JS_GC(rt); CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText)); diff --git a/js/src/jsapi-tests/testXDR.cpp b/js/src/jsapi-tests/testXDR.cpp index d78f41ffca92..b539ef5c452e 100644 --- a/js/src/jsapi-tests/testXDR.cpp +++ b/js/src/jsapi-tests/testXDR.cpp @@ -202,7 +202,7 @@ BEGIN_TEST(testXDR_bug506491) CHECK(JS_ExecuteScript(cx, global, script, v2.addr())); // try to break the Block object that is the parent of f - JS_GC(cx); + JS_GC(rt); // confirm EVAL("f() === 'ok';\n", v2.addr()); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 4b72d292673d..1b99221b403e 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1137,25 +1137,19 @@ JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback) JS_PUBLIC_API(JSContext *) JS_NewContext(JSRuntime *rt, size_t stackChunkSize) { - return js_NewContext(rt, stackChunkSize); + return NewContext(rt, stackChunkSize); } JS_PUBLIC_API(void) JS_DestroyContext(JSContext *cx) { - js_DestroyContext(cx, JSDCM_FORCE_GC); + DestroyContext(cx, DCM_FORCE_GC); } JS_PUBLIC_API(void) JS_DestroyContextNoGC(JSContext *cx) { - js_DestroyContext(cx, JSDCM_NO_GC); -} - -JS_PUBLIC_API(void) -JS_DestroyContextMaybeGC(JSContext *cx) -{ - js_DestroyContext(cx, JSDCM_MAYBE_GC); + DestroyContext(cx, DCM_NO_GC); } JS_PUBLIC_API(void *) @@ -2860,11 +2854,11 @@ JS_IsGCMarkingTracer(JSTracer *trc) } JS_PUBLIC_API(void) -JS_GC(JSContext *cx) +JS_GC(JSRuntime *rt) { - AssertNoGC(cx); - PrepareForFullGC(cx->runtime); - GC(cx, GC_NORMAL, gcreason::API); + AssertNoGC(rt); + PrepareForFullGC(rt); + GC(rt, GC_NORMAL, gcreason::API); } JS_PUBLIC_API(void) @@ -2961,11 +2955,6 @@ JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key) return 0; } -JS_PUBLIC_API(void) -JS_FlushCaches(JSContext *cx) -{ -} - JS_PUBLIC_API(JSString *) JS_NewExternalString(JSContext *cx, const jschar *chars, size_t length, const JSStringFinalizer *fin) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 0d7cc8a8940e..3c0725ad1569 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2568,9 +2568,6 @@ JS_DestroyContext(JSContext *cx); extern JS_PUBLIC_API(void) JS_DestroyContextNoGC(JSContext *cx); -extern JS_PUBLIC_API(void) -JS_DestroyContextMaybeGC(JSContext *cx); - extern JS_PUBLIC_API(void *) JS_GetContextPrivate(JSContext *cx); @@ -3158,12 +3155,6 @@ JS_DumpNamedRoots(JSRuntime *rt, * in the return value. To keep on mapping, return JS_MAP_GCROOT_NEXT. These * constants are flags; you can OR them together. * - * This function acquires and releases rt's GC lock around the mapping of the - * roots table, so the map function should run to completion in as few cycles - * as possible. Of course, map cannot call JS_GC, JS_MaybeGC, JS_BeginRequest, - * or any JS API entry point that acquires locks, without double-tripping or - * deadlocking on the GC lock. - * * The JSGCRootType parameter indicates whether rp is a pointer to a Value * (which is obtained by '(Value *)rp') or a pointer to a GC-thing pointer * (which is obtained by '(void **)rp'). @@ -3260,6 +3251,9 @@ struct JSTracer { const void *debugPrintArg; size_t debugPrintIndex; JSBool eagerlyTraceWeakMaps; +#ifdef DEBUG + void *realLocation; +#endif }; /* @@ -3300,6 +3294,22 @@ JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind); JS_END_MACRO #endif +/* + * Sets the real location for a marked reference, when passing the address + * directly is not feasable. + */ +#ifdef DEBUG +# define JS_SET_TRACING_LOCATION(trc, location) \ + JS_BEGIN_MACRO \ + (trc)->realLocation = (location); \ + JS_END_MACRO +#else +# define JS_SET_TRACING_LOCATION(trc, location) \ + JS_BEGIN_MACRO \ + JS_END_MACRO +#endif + + /* * Convenience macro to describe the argument of JS_CallTracer using C string * and index. @@ -3395,10 +3405,10 @@ JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind kind, * Garbage collector API. */ extern JS_PUBLIC_API(void) -JS_GC(JSContext *cx); +JS_GC(JSRuntime *rt); extern JS_PUBLIC_API(void) -JS_CompartmentGC(JSContext *cx, JSCompartment *comp); +JS_CompartmentGC(JSRuntime *rt, JSCompartment *comp); extern JS_PUBLIC_API(void) JS_MaybeGC(JSContext *cx); @@ -3473,15 +3483,6 @@ JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value); extern JS_PUBLIC_API(uint32_t) JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key); -/* - * Flush the code cache for the current thread. The operation might be - * delayed if the cache cannot be flushed currently because native - * code is currently executing. - */ - -extern JS_PUBLIC_API(void) -JS_FlushCaches(JSContext *cx); - /* * Create a new JSString whose chars member refers to external memory, i.e., * memory requiring application-specific finalization. diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 0eb0a974c74a..f716d7ae6183 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -502,8 +502,10 @@ js_DumpAtoms(JSContext *cx, FILE *fp) JS_STATIC_ASSERT(TEMP_SIZE_START >= sizeof(JSHashTable)); +namespace js { + void -js_InitAtomMap(JSContext *cx, AtomIndexMap *indices, JSAtom **atoms) +InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms) { if (indices->isMap()) { typedef AtomIndexMap::WordMap WordMap; @@ -512,7 +514,7 @@ js_InitAtomMap(JSContext *cx, AtomIndexMap *indices, JSAtom **atoms) JSAtom *atom = r.front().key; jsatomid index = r.front().value; JS_ASSERT(index < indices->count()); - atoms[index] = atom; + atoms[index].init(atom); } } else { for (const AtomIndexMap::InlineElem *it = indices->asInline(), *end = indices->inlineEnd(); @@ -521,13 +523,11 @@ js_InitAtomMap(JSContext *cx, AtomIndexMap *indices, JSAtom **atoms) if (!atom) continue; JS_ASSERT(it->value < indices->count()); - atoms[it->value] = atom; + atoms[it->value].init(atom); } } } -namespace js { - bool IndexToIdSlow(JSContext *cx, uint32_t index, jsid *idp) { diff --git a/js/src/jsatom.h b/js/src/jsatom.h index 9111dffb3663..361c03504c6a 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -470,15 +470,15 @@ inline bool js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval, jsid *idp, js::Value *vp); +namespace js { + /* * For all unmapped atoms recorded in al, add a mapping from the atom's index * to its address. map->length must already be set to the number of atoms in * the list and map->vector must point to pre-allocated memory. */ extern void -js_InitAtomMap(JSContext *cx, js::AtomIndexMap *indices, JSAtom **atoms); - -namespace js { +InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms); template bool diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 96151ca99588..ce1371f4faf7 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -169,7 +169,7 @@ js_GetCurrentScript(JSContext *cx) } JSContext * -js_NewContext(JSRuntime *rt, size_t stackChunkSize) +js::NewContext(JSRuntime *rt, size_t stackChunkSize) { JS_AbortIfWrongThread(rt); @@ -198,7 +198,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize) * keywords, numbers, and strings. If one of these steps should fail, the * runtime will be left in a partially initialized state, with zeroes and * nulls stored in the default-initialized remainder of the struct. We'll - * clean the runtime up under js_DestroyContext, because cx will be "last" + * clean the runtime up under DestroyContext, because cx will be "last" * as well as "first". */ if (first) { @@ -213,14 +213,14 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize) JS_EndRequest(cx); #endif if (!ok) { - js_DestroyContext(cx, JSDCM_NEW_FAILED); + DestroyContext(cx, DCM_NEW_FAILED); return NULL; } } JSContextCallback cxCallback = rt->cxCallback; if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) { - js_DestroyContext(cx, JSDCM_NEW_FAILED); + DestroyContext(cx, DCM_NEW_FAILED); return NULL; } @@ -228,7 +228,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize) } void -js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) +js::DestroyContext(JSContext *cx, DestroyContextMode mode) { JSRuntime *rt = cx->runtime; JS_AbortIfWrongThread(rt); @@ -239,14 +239,13 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) JS_ASSERT(cx->outstandingRequests == 0); #endif - if (mode != JSDCM_NEW_FAILED) { + if (mode != DCM_NEW_FAILED) { if (JSContextCallback cxCallback = rt->cxCallback) { /* * JSCONTEXT_DESTROY callback is not allowed to fail and must * return true. */ - DebugOnly callbackStatus = cxCallback(cx, JSCONTEXT_DESTROY); - JS_ASSERT(callbackStatus); + JS_ALWAYS_TRUE(cxCallback(cx, JSCONTEXT_DESTROY)); } } @@ -255,13 +254,6 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) if (last) { JS_ASSERT(!rt->gcRunning); -#ifdef JS_THREADSAFE - { - AutoLockGC lock(rt); - rt->gcHelperThread.waitBackgroundSweepEnd(); - } -#endif - /* * Dump remaining type inference results first. This printing * depends on atoms still existing. @@ -270,30 +262,20 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) c->types.print(cx, false); /* Unpin all common atoms before final GC. */ - FinishCommonAtoms(cx->runtime); + FinishCommonAtoms(rt); /* Clear debugging state to remove GC roots. */ for (CompartmentsIter c(rt); !c.done(); c.next()) - c->clearTraps(cx); + c->clearTraps(rt->defaultFreeOp()); JS_ClearAllWatchPoints(cx); PrepareForFullGC(rt); - GC(cx, GC_NORMAL, gcreason::LAST_CONTEXT); - } else if (mode == JSDCM_FORCE_GC) { + GC(rt, GC_NORMAL, gcreason::LAST_CONTEXT); + } else if (mode == DCM_FORCE_GC) { JS_ASSERT(!rt->gcRunning); PrepareForFullGC(rt); - GC(cx, GC_NORMAL, gcreason::DESTROY_CONTEXT); - } else if (mode == JSDCM_MAYBE_GC) { - JS_ASSERT(!rt->gcRunning); - JS_MaybeGC(cx); + GC(rt, GC_NORMAL, gcreason::DESTROY_CONTEXT); } - -#ifdef JS_THREADSAFE - { - AutoLockGC lock(rt); - rt->gcHelperThread.waitBackgroundSweepEnd(); - } -#endif Foreground::delete_(cx); } @@ -885,30 +867,14 @@ js_InvokeOperationCallback(JSContext *cx) JS_ATOMIC_SET(&rt->interrupt, 0); if (rt->gcIsNeeded) - GCSlice(cx, GC_NORMAL, rt->gcTriggerReason); - -#ifdef JS_THREADSAFE - /* - * We automatically yield the current context every time the operation - * callback is hit since we might be called as a result of an impending - * GC on another thread, which would deadlock if we do not yield. - * Operation callbacks are supposed to happen rarely (seconds, not - * milliseconds) so it is acceptable to yield at every callback. - * - * As the GC can be canceled before it does any request checks we yield - * even if rt->gcIsNeeded was true above. See bug 590533. - */ - JS_YieldRequest(cx); -#endif - - JSOperationCallback cb = cx->operationCallback; + GCSlice(rt, GC_NORMAL, rt->gcTriggerReason); /* * Important: Additional callbacks can occur inside the callback handler * if it re-enters the JS engine. The embedding must ensure that the * callback is disconnected before attempting such re-entry. */ - + JSOperationCallback cb = cx->operationCallback; return !cb || cb(cx); } @@ -990,9 +956,6 @@ JSContext::JSContext(JSRuntime *rt) functionCallback(NULL), #endif enumerators(NULL), -#ifdef JS_THREADSAFE - gcBackgroundFree(NULL), -#endif activeCompilations(0) #ifdef DEBUG , stackIterAssertionEnabled(true) diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index ab67d39ade84..edd52741a758 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -146,15 +146,8 @@ struct ConservativeGCData uintptr_t words[JS_HOWMANY(sizeof(jmp_buf), sizeof(uintptr_t))]; } registerSnapshot; - /* - * Cycle collector uses this to communicate that the native stack of the - * GC thread should be scanned only if the thread have more than the given - * threshold of requests. - */ - unsigned requestThreshold; - ConservativeGCData() - : nativeStackTop(NULL), requestThreshold(0) + : nativeStackTop(NULL) {} ~ConservativeGCData() { @@ -183,6 +176,13 @@ struct ConservativeGCData } }; +/* + * A FreeOp can do one thing: free memory. For convenience, it has delete_ + * convenience methods that also call destructors. + * + * FreeOp is passed to finalizers and other sweep-phase hooks so that we do not + * need to pass a JSContext to those hooks. + */ class FreeOp : public JSFreeOp { bool shouldFreeLater_; bool onBackgroundThread_; @@ -215,7 +215,7 @@ class FreeOp : public JSFreeOp { /* * Check that JSFreeOp is the first base class for FreeOp and we can * reinterpret a pointer to JSFreeOp as a pointer to FreeOp without - * any offset adjustments. JSClass::freeOp <-> Class::freeOp depends + * any offset adjustments. JSClass::finalize <-> Class::finalize depends * on this. */ JS_STATIC_ASSERT(offsetof(FreeOp, shouldFreeLater_) == sizeof(JSFreeOp)); @@ -1119,14 +1119,6 @@ struct JSContext : js::ContextFriendFields genStack.popBack(); } -#ifdef JS_THREADSAFE - /* - * When non-null JSContext::free_ delegates the job to the background - * thread. - */ - js::GCHelperThread *gcBackgroundFree; -#endif - inline void* malloc_(size_t bytes) { return runtime->malloc_(bytes, this); } @@ -1150,12 +1142,6 @@ struct JSContext : js::ContextFriendFields } inline void free_(void* p) { -#ifdef JS_THREADSAFE - if (gcBackgroundFree) { - gcBackgroundFree->freeLater(p); - return; - } -#endif runtime->free_(p); } @@ -1461,24 +1447,23 @@ public: } }; -} /* namespace js */ - /* * Create and destroy functions for JSContext, which is manually allocated * and exclusively owned. */ extern JSContext * -js_NewContext(JSRuntime *rt, size_t stackChunkSize); +NewContext(JSRuntime *rt, size_t stackChunkSize); -typedef enum JSDestroyContextMode { - JSDCM_NO_GC, - JSDCM_MAYBE_GC, - JSDCM_FORCE_GC, - JSDCM_NEW_FAILED -} JSDestroyContextMode; +enum DestroyContextMode { + DCM_NO_GC, + DCM_FORCE_GC, + DCM_NEW_FAILED +}; extern void -js_DestroyContext(JSContext *cx, JSDestroyContextMode mode); +DestroyContext(JSContext *cx, DestroyContextMode mode); + +} /* namespace js */ #ifdef va_start extern JSBool diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index bb64fd827524..631b2cba9c55 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -390,7 +390,7 @@ CallSetter(JSContext *cx, JSObject *obj, jsid id, StrictPropertyOp op, unsigned return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp); } -static inline JSAtom ** +static inline HeapPtrAtom * FrameAtomBase(JSContext *cx, js::StackFrame *fp) { return fp->script()->atoms; diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 817a226696f8..98fc02f4f5f2 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -746,22 +746,22 @@ JSCompartment::removeDebuggee(FreeOp *fop, } void -JSCompartment::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler) +JSCompartment::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, JSObject *handler) { for (gc::CellIter i(this, gc::FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); if (script->hasAnyBreakpointsOrStepMode()) - script->clearBreakpointsIn(cx, dbg, handler); + script->clearBreakpointsIn(fop, dbg, handler); } } void -JSCompartment::clearTraps(JSContext *cx) +JSCompartment::clearTraps(FreeOp *fop) { for (gc::CellIter i(this, gc::FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); if (script->hasAnyBreakpointsOrStepMode()) - script->clearTraps(cx->runtime->defaultFreeOp()); + script->clearTraps(fop); } } diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index c2c15f863517..1a72581cae61 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -455,8 +455,8 @@ struct JSCompartment js::GlobalObjectSet::Enum *debuggeesEnum = NULL); bool setDebugModeFromC(JSContext *cx, bool b); - void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler); - void clearTraps(JSContext *cx); + void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JSObject *handler); + void clearTraps(js::FreeOp *fop); private: void sweepBreakpoints(js::FreeOp *fop); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index f7c34c77121b..fa95e3a04f1a 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -231,7 +231,7 @@ JS_ClearScriptTraps(JSContext *cx, JSScript *script) JS_PUBLIC_API(void) JS_ClearAllTrapsForCompartment(JSContext *cx) { - cx->compartment->clearTraps(cx); + cx->compartment->clearTraps(cx->runtime->defaultFreeOp()); } JS_PUBLIC_API(JSBool) diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index e3141471e57e..71dde30ad28c 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -145,21 +145,21 @@ js::PrepareForFullGC(JSRuntime *rt) } JS_FRIEND_API(void) -js::GCForReason(JSContext *cx, gcreason::Reason reason) +js::GCForReason(JSRuntime *rt, gcreason::Reason reason) { - GC(cx, GC_NORMAL, reason); + GC(rt, GC_NORMAL, reason); } JS_FRIEND_API(void) -js::ShrinkingGC(JSContext *cx, gcreason::Reason reason) +js::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason) { - GC(cx, GC_SHRINK, reason); + GC(rt, GC_SHRINK, reason); } JS_FRIEND_API(void) -js::IncrementalGC(JSContext *cx, gcreason::Reason reason) +js::IncrementalGC(JSRuntime *rt, gcreason::Reason reason) { - GCSlice(cx, GC_NORMAL, reason); + GCSlice(rt, GC_NORMAL, reason); } JS_FRIEND_API(void) @@ -654,26 +654,6 @@ GetContextOutstandingRequests(const JSContext *cx) { return cx->outstandingRequests; } - -AutoSkipConservativeScan::AutoSkipConservativeScan(JSContext *cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) - : context(cx) -{ - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - - JSRuntime *rt = context->runtime; - JS_ASSERT(rt->requestDepth >= 1); - JS_ASSERT(!rt->conservativeGC.requestThreshold); - if (rt->requestDepth == 1) - rt->conservativeGC.requestThreshold = 1; -} - -AutoSkipConservativeScan::~AutoSkipConservativeScan() -{ - JSRuntime *rt = context->runtime; - if (rt->requestDepth == 1) - rt->conservativeGC.requestThreshold = 0; -} #endif JS_FRIEND_API(JSCompartment *) @@ -733,31 +713,17 @@ GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const return rt->gcStats.formatJSON(timestamp); } -JS_FRIEND_API(bool) -WantGCSlice(JSRuntime *rt) -{ - if (rt->gcZeal() == gc::ZealFrameVerifierValue || rt->gcZeal() == gc::ZealFrameGCValue) - return true; - - if (rt->gcIncrementalState != gc::NO_INCREMENTAL) - return true; - - return false; -} - JS_FRIEND_API(void) -NotifyDidPaint(JSContext *cx) +NotifyDidPaint(JSRuntime *rt) { - JSRuntime *rt = cx->runtime; - if (rt->gcZeal() == gc::ZealFrameVerifierValue) { - gc::VerifyBarriers(cx); + gc::VerifyBarriers(rt); return; } if (rt->gcZeal() == gc::ZealFrameGCValue) { PrepareForFullGC(rt); - GCSlice(cx, GC_NORMAL, gcreason::REFRESH_FRAME); + GCSlice(rt, GC_NORMAL, gcreason::REFRESH_FRAME); return; } @@ -766,7 +732,7 @@ NotifyDidPaint(JSContext *cx) if (c->needsBarrier()) PrepareCompartmentForGC(c); } - GCSlice(cx, GC_NORMAL, gcreason::REFRESH_FRAME); + GCSlice(rt, GC_NORMAL, gcreason::REFRESH_FRAME); } rt->gcInterFrameGC = false; diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index b532585b167a..4e5b4f708221 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -569,17 +569,6 @@ GetOwnerThread(const JSContext *cx); JS_FRIEND_API(unsigned) GetContextOutstandingRequests(const JSContext *cx); - -class JS_FRIEND_API(AutoSkipConservativeScan) -{ - public: - AutoSkipConservativeScan(JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM); - ~AutoSkipConservativeScan(); - - private: - JSContext *context; - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; #endif JS_FRIEND_API(JSCompartment *) @@ -680,13 +669,13 @@ PrepareForFullGC(JSRuntime *rt); */ extern JS_FRIEND_API(void) -GCForReason(JSContext *cx, gcreason::Reason reason); +GCForReason(JSRuntime *rt, gcreason::Reason reason); extern JS_FRIEND_API(void) -ShrinkingGC(JSContext *cx, gcreason::Reason reason); +ShrinkingGC(JSRuntime *rt, gcreason::Reason reason); extern JS_FRIEND_API(void) -IncrementalGC(JSContext *cx, gcreason::Reason reason); +IncrementalGC(JSRuntime *rt, gcreason::Reason reason); extern JS_FRIEND_API(void) SetGCSliceTimeBudget(JSContext *cx, int64_t millis); @@ -724,15 +713,12 @@ typedef void extern JS_FRIEND_API(GCSliceCallback) SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback); -extern JS_FRIEND_API(bool) -WantGCSlice(JSRuntime *rt); - /* * Signals a good place to do an incremental slice, because the browser is * drawing a frame. */ extern JS_FRIEND_API(void) -NotifyDidPaint(JSContext *cx); +NotifyDidPaint(JSRuntime *rt); extern JS_FRIEND_API(bool) IsIncrementalGCEnabled(JSRuntime *rt); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index b3f6536fd075..97e4cc754199 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -157,10 +157,10 @@ static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000; #ifdef JS_GC_ZEAL static void -StartVerifyBarriers(JSContext *cx); +StartVerifyBarriers(JSRuntime *rt); static void -EndVerifyBarriers(JSContext *cx); +EndVerifyBarriers(JSRuntime *rt); void FinishVerifier(JSRuntime *rt); @@ -1051,6 +1051,7 @@ MarkIfGCThingWord(JSTracer *trc, uintptr_t w) JS_snprintf(nameBuf, sizeof(nameBuf), pattern, thing); JS_SET_TRACING_NAME(trc, nameBuf); #endif + JS_SET_TRACING_LOCATION(trc, (void *)w); void *tmp = thing; MarkKind(trc, &tmp, traceKind); JS_ASSERT(tmp == thing); @@ -1112,7 +1113,7 @@ MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots) if (!cgcd->hasStackToScan()) { #ifdef JS_THREADSAFE JS_ASSERT(!rt->suspendCount); - JS_ASSERT(rt->requestDepth <= cgcd->requestThreshold); + JS_ASSERT(!rt->requestDepth); #endif return; } @@ -1180,8 +1181,7 @@ RecordNativeStackTopForGC(JSRuntime *rt) #ifdef JS_THREADSAFE /* Record the stack top here only if we are called from a request. */ - JS_ASSERT(rt->requestDepth >= cgcd->requestThreshold); - if (rt->requestDepth == cgcd->requestThreshold) + if (!rt->requestDepth) return; #endif cgcd->recordStackTop(); @@ -1648,7 +1648,7 @@ RunLastDitchGC(JSContext *cx, gcreason::Reason reason) /* The last ditch GC preserves all atoms. */ AutoKeepAtoms keep(rt); - GC(cx, GC_NORMAL, reason); + GC(rt, GC_NORMAL, reason); } /* static */ void * @@ -2008,6 +2008,7 @@ GCMarker::markBufferedGrayRoots() debugPrintArg = elem->debugPrintArg; debugPrintIndex = elem->debugPrintIndex; #endif + JS_SET_TRACING_LOCATION(this, (void *)&elem->thing); void *tmp = elem->thing; MarkKind(this, &tmp, elem->kind); JS_ASSERT(tmp == elem->thing); @@ -2074,6 +2075,7 @@ static void gc_lock_traversal(const GCLocks::Entry &entry, JSTracer *trc) { JS_ASSERT(entry.value >= 1); + JS_SET_TRACING_LOCATION(trc, (void *)&entry.key); void *tmp = entry.key; MarkGCThingRoot(trc, &tmp, "locked object"); JS_ASSERT(tmp == entry.key); @@ -2197,7 +2199,7 @@ AutoGCRooter::trace(JSTracer *trc) case SHAPEVECTOR: { AutoShapeVector::VectorImpl &vector = static_cast(this)->vector; - MarkShapeRootRange(trc, vector.length(), const_cast(vector.begin()), + MarkShapeRootRange(trc, vector.length(), const_cast(vector.begin()), "js::AutoShapeVector.vector"); return; } @@ -2392,28 +2394,28 @@ MaybeGC(JSContext *cx) if (rt->gcZeal() == ZealAllocValue || rt->gcZeal() == ZealPokeValue) { PrepareForFullGC(rt); - GC(cx, GC_NORMAL, gcreason::MAYBEGC); + GC(rt, GC_NORMAL, gcreason::MAYBEGC); + return; + } + + if (rt->gcIsNeeded) { + GCSlice(rt, GC_NORMAL, gcreason::MAYBEGC); return; } JSCompartment *comp = cx->compartment; - if (rt->gcIsNeeded) { - GCSlice(cx, GC_NORMAL, gcreason::MAYBEGC); - return; - } - if (comp->gcBytes > 8192 && comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4) && rt->gcIncrementalState == NO_INCREMENTAL) { PrepareCompartmentForGC(comp); - GCSlice(cx, GC_NORMAL, gcreason::MAYBEGC); + GCSlice(rt, GC_NORMAL, gcreason::MAYBEGC); return; } if (comp->gcMallocAndFreeBytes > comp->gcTriggerMallocAndFreeBytes) { PrepareCompartmentForGC(comp); - GCSlice(cx, GC_NORMAL, gcreason::MAYBEGC); + GCSlice(rt, GC_NORMAL, gcreason::MAYBEGC); return; } @@ -2428,7 +2430,7 @@ MaybeGC(JSContext *cx) rt->gcNumArenasFreeCommitted > FreeCommittedArenasThreshold) { PrepareForFullGC(rt); - GCSlice(cx, GC_SHRINK, gcreason::MAYBEGC); + GCSlice(rt, GC_SHRINK, gcreason::MAYBEGC); } else { rt->gcNextFullGCTime = now + GC_IDLE_FULL_SPAN; } @@ -2694,13 +2696,12 @@ GCHelperThread::prepareForBackgroundSweep() /* Must be called with the GC lock taken. */ void -GCHelperThread::startBackgroundSweep(JSContext *cx, bool shouldShrink) +GCHelperThread::startBackgroundSweep(bool shouldShrink) { /* The caller takes the GC lock. */ JS_ASSERT(state == IDLE); - JS_ASSERT(cx); - JS_ASSERT(!finalizationContext); - finalizationContext = cx; + JS_ASSERT(!sweepFlag); + sweepFlag = true; shrinkFlag = shouldShrink; state = SWEEPING; PR_NotifyCondVar(wakeup); @@ -2712,7 +2713,7 @@ GCHelperThread::startBackgroundShrink() { switch (state) { case IDLE: - JS_ASSERT(!finalizationContext); + JS_ASSERT(!sweepFlag); shrinkFlag = true; state = SWEEPING; PR_NotifyCondVar(wakeup); @@ -2783,8 +2784,8 @@ GCHelperThread::replenishAndFreeLater(void *ptr) void GCHelperThread::doSweep() { - if (finalizationContext) { - finalizationContext = NULL; + if (sweepFlag) { + sweepFlag = false; AutoUnlockGC unlock(rt); /* @@ -2897,6 +2898,18 @@ PurgeRuntime(JSTracer *trc) static void BeginMarkPhase(JSRuntime *rt) { + rt->gcMarker.start(rt); + JS_ASSERT(!rt->gcMarker.callback); + JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker)); + + /* For non-incremental GC the following sweep discards the jit code. */ + if (rt->gcIncrementalState != NO_INCREMENTAL) { + for (GCCompartmentsIter c(rt); !c.done(); c.next()) { + gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_CODE); + c->discardJitCode(rt->defaultFreeOp()); + } + } + GCMarker *gcmarker = &rt->gcMarker; rt->gcStartNumber = rt->gcNumber; @@ -2967,14 +2980,12 @@ MarkGrayAndWeak(JSRuntime *rt) #ifdef DEBUG static void -ValidateIncrementalMarking(JSContext *cx); +ValidateIncrementalMarking(JSRuntime *rt); #endif static void -EndMarkPhase(JSContext *cx) +EndMarkPhase(JSRuntime *rt) { - JSRuntime *rt = cx->runtime; - { gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_MARK); gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_MARK_OTHER); @@ -2985,7 +2996,7 @@ EndMarkPhase(JSContext *cx) #ifdef DEBUG if (rt->gcIncrementalState != NO_INCREMENTAL) - ValidateIncrementalMarking(cx); + ValidateIncrementalMarking(rt); #endif #ifdef DEBUG @@ -2995,18 +3006,21 @@ EndMarkPhase(JSContext *cx) c->arenas.checkArenaListAllUnmarked()); } #endif + + rt->gcMarker.stop(); + + /* We do not discard JIT here code as the following sweeping does that. */ } #ifdef DEBUG static void -ValidateIncrementalMarking(JSContext *cx) +ValidateIncrementalMarking(JSRuntime *rt) { typedef HashMap BitmapMap; BitmapMap map; if (!map.init()) return; - JSRuntime *rt = cx->runtime; GCMarker *gcmarker = &rt->gcMarker; /* Save existing mark bits. */ @@ -3092,10 +3106,8 @@ ValidateIncrementalMarking(JSContext *cx) #endif static void -SweepPhase(JSContext *cx, JSGCInvocationKind gckind) +SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep) { - JSRuntime *rt = cx->runtime; - /* * Sweep phase. * @@ -3113,19 +3125,16 @@ SweepPhase(JSContext *cx, JSGCInvocationKind gckind) gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP); #ifdef JS_THREADSAFE - if (rt->hasContexts() && rt->gcHelperThread.prepareForBackgroundSweep()) - cx->gcBackgroundFree = &rt->gcHelperThread; + *startBackgroundSweep = (rt->hasContexts() && rt->gcHelperThread.prepareForBackgroundSweep()); +#else + *startBackgroundSweep = false; #endif /* Purge the ArenaLists before sweeping. */ for (GCCompartmentsIter c(rt); !c.done(); c.next()) c->arenas.purge(); -#ifdef JS_THREADSAFE - FreeOp fop(rt, !!cx->gcBackgroundFree, false); -#else - FreeOp fop(rt, false, false); -#endif + FreeOp fop(rt, *startBackgroundSweep, false); { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_START); if (rt->gcFinalizeCallback) @@ -3222,27 +3231,17 @@ SweepPhase(JSContext *cx, JSGCInvocationKind gckind) c->setGCLastBytes(c->gcBytes, c->gcMallocAndFreeBytes, gckind); } -/* Perform mark-and-sweep GC. If comp is set, we perform a single-compartment GC. */ static void -MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind) +NonIncrementalMark(JSRuntime *rt, JSGCInvocationKind gckind) { - JSRuntime *rt = cx->runtime; - - AutoUnlockGC unlock(rt); - - rt->gcMarker.start(rt); - JS_ASSERT(!rt->gcMarker.callback); - + JS_ASSERT(rt->gcIncrementalState == NO_INCREMENTAL); BeginMarkPhase(rt); { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK); SliceBudget budget; rt->gcMarker.drainMarkStack(budget); } - EndMarkPhase(cx); - SweepPhase(cx, gckind); - - rt->gcMarker.stop(); + EndMarkPhase(rt); } /* @@ -3342,18 +3341,16 @@ ResetIncrementalGC(JSRuntime *rt, const char *reason) class AutoGCSlice { public: - AutoGCSlice(JSContext *cx); + AutoGCSlice(JSRuntime *rt); ~AutoGCSlice(); private: - JSContext *context; + JSRuntime *runtime; }; -AutoGCSlice::AutoGCSlice(JSContext *cx) - : context(cx) +AutoGCSlice::AutoGCSlice(JSRuntime *rt) + : runtime(rt) { - JSRuntime *rt = context->runtime; - /* * During incremental GC, the compartment's active flag determines whether * there are stack frames active for any of its scripts. Normally this flag @@ -3373,14 +3370,12 @@ AutoGCSlice::AutoGCSlice(JSContext *cx) AutoGCSlice::~AutoGCSlice() { - JSRuntime *rt = context->runtime; - - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - if (rt->gcIncrementalState == MARK) { + for (GCCompartmentsIter c(runtime); !c.done(); c.next()) { + if (runtime->gcIncrementalState == MARK) { c->needsBarrier_ = true; - c->arenas.prepareForIncrementalGC(rt); + c->arenas.prepareForIncrementalGC(runtime); } else { - JS_ASSERT(rt->gcIncrementalState == NO_INCREMENTAL); + JS_ASSERT(runtime->gcIncrementalState == NO_INCREMENTAL); c->needsBarrier_ = false; } } @@ -3403,12 +3398,9 @@ class AutoCopyFreeListToArenas { }; static void -IncrementalGCSlice(JSContext *cx, int64_t budget, JSGCInvocationKind gckind) +IncrementalMarkSlice(JSRuntime *rt, int64_t budget, JSGCInvocationKind gckind, bool *shouldSweep) { - JSRuntime *rt = cx->runtime; - - AutoUnlockGC unlock(rt); - AutoGCSlice slice(cx); + AutoGCSlice slice(rt); gc::State initialState = rt->gcIncrementalState; @@ -3418,19 +3410,11 @@ IncrementalGCSlice(JSContext *cx, int64_t budget, JSGCInvocationKind gckind) } if (rt->gcIncrementalState == MARK_ROOTS) { - rt->gcMarker.start(rt); - JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker)); - - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_CODE); - c->discardJitCode(rt->defaultFreeOp()); - } - BeginMarkPhase(rt); - rt->gcIncrementalState = MARK; } + *shouldSweep = false; if (rt->gcIncrementalState == MARK) { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK); SliceBudget sliceBudget(budget); @@ -3450,26 +3434,17 @@ IncrementalGCSlice(JSContext *cx, int64_t budget, JSGCInvocationKind gckind) #endif bool finished = rt->gcMarker.drainMarkStack(sliceBudget); - if (finished) { JS_ASSERT(rt->gcMarker.isDrained()); - if (initialState == MARK && !rt->gcLastMarkSlice && budget != SliceBudget::Unlimited) + if (initialState == MARK && !rt->gcLastMarkSlice && budget != SliceBudget::Unlimited) { rt->gcLastMarkSlice = true; - else - rt->gcIncrementalState = SWEEP; + } else { + EndMarkPhase(rt); + rt->gcIncrementalState = NO_INCREMENTAL; + *shouldSweep = true; + } } } - - if (rt->gcIncrementalState == SWEEP) { - EndMarkPhase(cx); - SweepPhase(cx, gckind); - - rt->gcMarker.stop(); - - /* JIT code was already discarded during sweeping. */ - - rt->gcIncrementalState = NO_INCREMENTAL; - } } class IncrementalSafety @@ -3558,10 +3533,8 @@ BudgetIncrementalGC(JSRuntime *rt, int64_t *budget) * the marking implementation. */ static JS_NEVER_INLINE void -GCCycle(JSContext *cx, bool incremental, int64_t budget, JSGCInvocationKind gckind) +GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gckind) { - JSRuntime *rt = cx->runtime; - #ifdef DEBUG for (CompartmentsIter c(rt); !c.done(); c.next()) JS_ASSERT_IF(rt->gcMode == JSGC_MODE_GLOBAL, c->isGCScheduled()); @@ -3571,12 +3544,13 @@ GCCycle(JSContext *cx, bool incremental, int64_t budget, JSGCInvocationKind gcki if (rt->gcRunning) return; - AutoGCSession gcsession(rt); - /* Don't GC if we are reporting an OOM. */ if (rt->inOOMReport) return; + AutoLockGC lock(rt); + AutoGCSession gcsession(rt); + #ifdef JS_THREADSAFE /* * As we about to purge caches and clear the mark bits we must wait for @@ -3586,41 +3560,45 @@ GCCycle(JSContext *cx, bool incremental, int64_t budget, JSGCInvocationKind gcki */ { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_WAIT_BACKGROUND_THREAD); - - JS_ASSERT(!cx->gcBackgroundFree); rt->gcHelperThread.waitBackgroundSweepOrAllocEnd(); } #endif - if (!incremental) { - /* If non-incremental GC was requested, reset incremental GC. */ - ResetIncrementalGC(rt, "requested"); - rt->gcStats.nonincremental("requested"); - } else { - BudgetIncrementalGC(rt, &budget); - } + bool startBackgroundSweep = false; + { + AutoUnlockGC unlock(rt); - AutoCopyFreeListToArenas copy(rt); + if (!incremental) { + /* If non-incremental GC was requested, reset incremental GC. */ + ResetIncrementalGC(rt, "requested"); + rt->gcStats.nonincremental("requested"); + } else { + BudgetIncrementalGC(rt, &budget); + } - if (budget == SliceBudget::Unlimited && rt->gcIncrementalState == NO_INCREMENTAL) - MarkAndSweep(cx, gckind); - else - IncrementalGCSlice(cx, budget, gckind); + AutoCopyFreeListToArenas copy(rt); + + bool shouldSweep; + if (budget == SliceBudget::Unlimited && rt->gcIncrementalState == NO_INCREMENTAL) { + NonIncrementalMark(rt, gckind); + shouldSweep = true; + } else { + IncrementalMarkSlice(rt, budget, gckind, &shouldSweep); + } #ifdef DEBUG - if (rt->gcIncrementalState == NO_INCREMENTAL) { - for (CompartmentsIter c(rt); !c.done(); c.next()) - JS_ASSERT(!c->needsBarrier_); - } -#endif -#ifdef JS_THREADSAFE - if (rt->gcIncrementalState == NO_INCREMENTAL) { - if (cx->gcBackgroundFree) { - JS_ASSERT(cx->gcBackgroundFree == &rt->gcHelperThread); - cx->gcBackgroundFree = NULL; - rt->gcHelperThread.startBackgroundSweep(cx, gckind == GC_SHRINK); + if (rt->gcIncrementalState == NO_INCREMENTAL) { + for (CompartmentsIter c(rt); !c.done(); c.next()) + JS_ASSERT(!c->needsBarrier_); } +#endif + if (shouldSweep) + SweepPhase(rt, gckind, &startBackgroundSweep); } + +#ifdef JS_THREADSAFE + if (startBackgroundSweep) + rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK); #endif } @@ -3639,10 +3617,9 @@ IsDeterministicGCReason(gcreason::Reason reason) #endif static void -Collect(JSContext *cx, bool incremental, int64_t budget, +Collect(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gckind, gcreason::Reason reason) { - JSRuntime *rt = cx->runtime; JS_AbortIfWrongThread(rt); #ifdef JS_GC_ZEAL @@ -3653,24 +3630,24 @@ Collect(JSContext *cx, bool incremental, int64_t budget, JS_ASSERT_IF(!incremental || budget != SliceBudget::Unlimited, JSGC_INCREMENTAL); #ifdef JS_GC_ZEAL - bool restartVerify = cx->runtime->gcVerifyData && - cx->runtime->gcZeal() == ZealVerifierValue && + bool restartVerify = rt->gcVerifyData && + rt->gcZeal() == ZealVerifierValue && reason != gcreason::CC_FORCED; struct AutoVerifyBarriers { - JSContext *cx; + JSRuntime *runtime; bool restart; - AutoVerifyBarriers(JSContext *cx, bool restart) - : cx(cx), restart(restart) + AutoVerifyBarriers(JSRuntime *rt, bool restart) + : runtime(rt), restart(restart) { - if (cx->runtime->gcVerifyData) - EndVerifyBarriers(cx); + if (rt->gcVerifyData) + EndVerifyBarriers(rt); } ~AutoVerifyBarriers() { if (restart) - StartVerifyBarriers(cx); + StartVerifyBarriers(runtime); } - } av(cx, restartVerify); + } av(rt, restartVerify); #endif RecordNativeStackTopForGC(rt); @@ -3704,10 +3681,8 @@ Collect(JSContext *cx, bool incremental, int64_t budget, } { - /* Lock out other GC allocator and collector invocations. */ - AutoLockGC lock(rt); rt->gcPoke = false; - GCCycle(cx, incremental, budget, gckind); + GCCycle(rt, incremental, budget, gckind); } if (rt->gcIncrementalState == NO_INCREMENTAL) { @@ -3726,23 +3701,23 @@ Collect(JSContext *cx, bool incremental, int64_t budget, namespace js { void -GC(JSContext *cx, JSGCInvocationKind gckind, gcreason::Reason reason) +GC(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason) { - Collect(cx, false, SliceBudget::Unlimited, gckind, reason); + Collect(rt, false, SliceBudget::Unlimited, gckind, reason); } void -GCSlice(JSContext *cx, JSGCInvocationKind gckind, gcreason::Reason reason) +GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason) { - Collect(cx, true, cx->runtime->gcSliceBudget, gckind, reason); + Collect(rt, true, rt->gcSliceBudget, gckind, reason); } void -GCDebugSlice(JSContext *cx, bool limit, int64_t objCount) +GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount) { int64_t budget = limit ? SliceBudget::WorkBudget(objCount) : SliceBudget::Unlimited; - PrepareForDebugGC(cx->runtime); - Collect(cx, true, budget, GC_NORMAL, gcreason::API); + PrepareForDebugGC(rt); + Collect(rt, true, budget, GC_NORMAL, gcreason::API); } /* Schedule a full GC unless a compartment will already be collected. */ @@ -4167,10 +4142,8 @@ NextNode(VerifyNode *node) } static void -StartVerifyBarriers(JSContext *cx) +StartVerifyBarriers(JSRuntime *rt) { - JSRuntime *rt = cx->runtime; - if (rt->gcVerifyData || rt->gcIncrementalState != NO_INCREMENTAL) return; @@ -4314,10 +4287,8 @@ CheckReachable(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) } static void -EndVerifyBarriers(JSContext *cx) +EndVerifyBarriers(JSRuntime *rt) { - JSRuntime *rt = cx->runtime; - AutoLockGC lock(rt); AutoHeapSession session(rt); @@ -4406,48 +4377,48 @@ FinishVerifier(JSRuntime *rt) } void -VerifyBarriers(JSContext *cx) +VerifyBarriers(JSRuntime *rt) { - JSRuntime *rt = cx->runtime; if (rt->gcVerifyData) - EndVerifyBarriers(cx); + EndVerifyBarriers(rt); else - StartVerifyBarriers(cx); + StartVerifyBarriers(rt); } void MaybeVerifyBarriers(JSContext *cx, bool always) { - if (cx->runtime->gcZeal() != ZealVerifierValue) { - if (cx->runtime->gcVerifyData) - EndVerifyBarriers(cx); + JSRuntime *rt = cx->runtime; + + if (rt->gcZeal() != ZealVerifierValue) { + if (rt->gcVerifyData) + EndVerifyBarriers(rt); return; } - uint32_t freq = cx->runtime->gcZealFrequency; + uint32_t freq = rt->gcZealFrequency; - JSRuntime *rt = cx->runtime; if (VerifyTracer *trc = (VerifyTracer *)rt->gcVerifyData) { if (++trc->count < freq && !always) return; - EndVerifyBarriers(cx); + EndVerifyBarriers(rt); } - StartVerifyBarriers(cx); + StartVerifyBarriers(rt); } #endif /* JS_GC_ZEAL */ } /* namespace gc */ -static void ReleaseAllJITCode(JSContext *cx) +static void ReleaseAllJITCode(FreeOp *fop) { #ifdef JS_METHODJIT - for (GCCompartmentsIter c(cx->runtime); !c.done(); c.next()) { + for (GCCompartmentsIter c(fop->runtime()); !c.done(); c.next()) { mjit::ClearAllFrames(c); for (CellIter i(c, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); - mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), script); + mjit::ReleaseScriptCode(fop, script); } } #endif @@ -4478,17 +4449,17 @@ static void ReleaseAllJITCode(JSContext *cx) */ static void -ReleaseScriptCounts(JSContext *cx) +ReleaseScriptCounts(FreeOp *fop) { - JSRuntime *rt = cx->runtime; + JSRuntime *rt = fop->runtime(); JS_ASSERT(rt->scriptAndCountsVector); ScriptAndCountsVector &vec = *rt->scriptAndCountsVector; for (size_t i = 0; i < vec.length(); i++) - vec[i].scriptCounts.destroy(cx); + vec[i].scriptCounts.destroy(fop); - cx->delete_(rt->scriptAndCountsVector); + fop->delete_(rt->scriptAndCountsVector); rt->scriptAndCountsVector = NULL; } @@ -4501,9 +4472,9 @@ StartPCCountProfiling(JSContext *cx) return; if (rt->scriptAndCountsVector) - ReleaseScriptCounts(cx); + ReleaseScriptCounts(rt->defaultFreeOp()); - ReleaseAllJITCode(cx); + ReleaseAllJITCode(rt->defaultFreeOp()); rt->profilingScripts = true; } @@ -4517,7 +4488,7 @@ StopPCCountProfiling(JSContext *cx) return; JS_ASSERT(!rt->scriptAndCountsVector); - ReleaseAllJITCode(cx); + ReleaseAllJITCode(rt->defaultFreeOp()); ScriptAndCountsVector *vec = cx->new_(SystemAllocPolicy()); if (!vec) @@ -4531,7 +4502,7 @@ StopPCCountProfiling(JSContext *cx) info.script = script; info.scriptCounts.steal(script->scriptCounts); if (!vec->append(info)) - info.scriptCounts.destroy(cx); + info.scriptCounts.destroy(rt->defaultFreeOp()); } } } @@ -4549,7 +4520,7 @@ PurgePCCounts(JSContext *cx) return; JS_ASSERT(!rt->profilingScripts); - ReleaseScriptCounts(cx); + ReleaseScriptCounts(rt->defaultFreeOp()); } } /* namespace js */ diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 9762dadd0876..09982d884041 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -84,7 +84,6 @@ enum State { NO_INCREMENTAL, MARK_ROOTS, MARK, - SWEEP, INVALID }; @@ -1398,13 +1397,13 @@ typedef enum JSGCInvocationKind { } JSGCInvocationKind; extern void -GC(JSContext *cx, JSGCInvocationKind gckind, js::gcreason::Reason reason); +GC(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason); extern void -GCSlice(JSContext *cx, JSGCInvocationKind gckind, js::gcreason::Reason reason); +GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason); extern void -GCDebugSlice(JSContext *cx, bool limit, int64_t objCount); +GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount); extern void PrepareForDebugGC(JSRuntime *rt); @@ -1446,7 +1445,7 @@ class GCHelperThread { PRCondVar *done; volatile State state; - JSContext *finalizationContext; + bool sweepFlag; bool shrinkFlag; Vector freeVector; @@ -1482,7 +1481,7 @@ class GCHelperThread { wakeup(NULL), done(NULL), state(IDLE), - finalizationContext(NULL), + sweepFlag(false), shrinkFlag(false), freeCursor(NULL), freeCursorEnd(NULL), @@ -1493,7 +1492,7 @@ class GCHelperThread { void finish(); /* Must be called with the GC lock taken. */ - void startBackgroundSweep(JSContext *cx, bool shouldShrink); + void startBackgroundSweep(bool shouldShrink); /* Must be called with the GC lock taken. */ void startBackgroundShrink(); @@ -1994,7 +1993,7 @@ const int ZealFrameVerifierValue = 5; /* Check that write barriers have been used correctly. See jsgc.cpp. */ void -VerifyBarriers(JSContext *cx); +VerifyBarriers(JSRuntime *rt); void MaybeVerifyBarriers(JSContext *cx, bool always = false); @@ -2002,7 +2001,7 @@ MaybeVerifyBarriers(JSContext *cx, bool always = false); #else static inline void -VerifyBarriers(JSContext *cx) +VerifyBarriers(JSRuntime *rt) { } diff --git a/js/src/jsgcmark.cpp b/js/src/jsgcmark.cpp index 15b426811451..0a26c06070a0 100644 --- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -110,6 +110,7 @@ MarkInternal(JSTracer *trc, T **thingp) PushMarkStack(static_cast(trc), thing); } else { trc->callback(trc, (void **)thingp, GetGCThingTraceKind(thing)); + JS_SET_TRACING_LOCATION(trc, NULL); } #ifdef DEBUG @@ -269,6 +270,7 @@ MarkGCThingRoot(JSTracer *trc, void **thingp, const char *name) static inline void MarkIdInternal(JSTracer *trc, jsid *id) { + JS_SET_TRACING_LOCATION(trc, (void *)id); if (JSID_IS_STRING(*id)) { JSString *str = JSID_TO_STRING(*id); MarkInternal(trc, &str); @@ -319,6 +321,7 @@ MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name) static inline void MarkValueInternal(JSTracer *trc, Value *v) { + JS_SET_TRACING_LOCATION(trc, (void *)v); if (v->isMarkable()) { JS_ASSERT(v->toGCThing()); void *thing = v->toGCThing(); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 2c10c4a7463e..d12e261c38e7 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1509,7 +1509,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) * access. For less frequent object loads we have to recover the segment * from atoms pointer first. */ - JSAtom **atoms = script->atoms; + HeapPtrAtom *atoms = script->atoms; #if JS_HAS_GENERATORS if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) { diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index df04f221c45a..b8faf6ba1f3c 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -5261,7 +5261,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, prop = NULL; } } else { - /* We should never add properties to lexical blocks. */ + /* We should never add properties to lexical blocks. */ JS_ASSERT(!obj->isBlock()); if (obj->isGlobal() && diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 7b2e76de4419..a9b6f5be6e86 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -802,7 +802,7 @@ struct Shape : public js::gc::Cell * care of making this work, but that suffices only because we require that * start points with the same shape have the same successor object in the * search path --- a cache hit means the starting shapes were equal, which - * means the seach path tail (everything but the first object in the path) + * means the search path tail (everything but the first object in the path) * was shared, which in turn means the effects of a purge will be seen by * all affected starting search points. * diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 33cfe33965e3..079d4b70e04a 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -674,8 +674,16 @@ js::XDRScript(XDRState *xdr, JSScript **scriptp, JSScript *parentScript) } for (i = 0; i != natoms; ++i) { - if (!XDRAtom(xdr, &script->atoms[i])) - return false; + if (mode == XDR_DECODE) { + JSAtom *tmp = NULL; + if (!XDRAtom(xdr, &tmp)) + return false; + script->atoms[i].init(tmp); + } else { + JSAtom *tmp = script->atoms[i]; + if (!XDRAtom(xdr, &tmp)) + return false; + } } /* @@ -1106,7 +1114,7 @@ JSScript::NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t if (natoms != 0) { script->natoms = natoms; - script->atoms = reinterpret_cast(cursor); + script->atoms = reinterpret_cast(cursor); cursor += natoms * sizeof(script->atoms[0]); } @@ -1205,7 +1213,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce) nfixed = bce->inFunction() ? bce->bindings.countVars() : 0; JS_ASSERT(nfixed < SLOTNO_LIMIT); script->nfixed = uint16_t(nfixed); - js_InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms); + InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms); filename = bce->parser->tokenStream.getFilename(); if (filename) { @@ -1788,7 +1796,7 @@ JSScript::destroyBreakpointSite(FreeOp *fop, jsbytecode *pc) } void -JSScript::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler) +JSScript::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, JSObject *handler) { if (!hasAnyBreakpointsOrStepMode()) return; @@ -1801,7 +1809,7 @@ JSScript::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) { nextbp = bp->nextInSite(); if ((!dbg || bp->debugger == dbg) && (!handler || bp->getHandler() == handler)) - bp->destroy(cx->runtime->defaultFreeOp()); + bp->destroy(fop); } } } @@ -1828,7 +1836,7 @@ JSScript::markChildren(JSTracer *trc) for (uint32_t i = 0; i < natoms; ++i) { if (atoms[i]) - MarkStringUnbarriered(trc, &atoms[i], "atom"); + MarkString(trc, &atoms[i], "atom"); } if (JSScript::isValidOffset(objectsOffset)) { diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 7483708534c9..ab04d4d82dc6 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -301,7 +301,7 @@ class ScriptCounts ScriptCounts() : pcCountsVector(NULL) { } - inline void destroy(JSContext *cx); + inline void destroy(FreeOp *fop); void steal(ScriptCounts &other) { *this = other; @@ -409,7 +409,7 @@ struct JSScript : public js::gc::Cell comment above NewScript() for details) */ const char *filename; /* source filename or null */ - JSAtom **atoms; /* maps immediate index to literal struct */ + js::HeapPtrAtom *atoms; /* maps immediate index to literal struct */ JSPrincipals *principals;/* principals for this script */ JSPrincipals *originPrincipals; /* see jsapi.h 'originPrincipals' comment */ @@ -755,7 +755,7 @@ struct JSScript : public js::gc::Cell return isValidOffset(closedVarsOffset) ? closedVars()->length : 0; } - JSAtom *getAtom(size_t index) { + js::HeapPtrAtom &getAtom(size_t index) const { JS_ASSERT(index < natoms); return atoms[index]; } @@ -831,7 +831,7 @@ struct JSScript : public js::gc::Cell void destroyBreakpointSite(js::FreeOp *fop, jsbytecode *pc); - void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler); + void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JSObject *handler); void clearTraps(js::FreeOp *fop); void markTrapClosures(JSTracer *trc); diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h index b88d06aac147..473d00c588f3 100644 --- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -139,9 +139,9 @@ CurrentScriptFileLineOrigin(JSContext *cx, const char **file, unsigned *linenop, } inline void -ScriptCounts::destroy(JSContext *cx) +ScriptCounts::destroy(FreeOp *fop) { - cx->free_(pcCountsVector); + fop->free_(pcCountsVector); } } // namespace js diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 2c324ba418ad..bc7654c53262 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -646,7 +646,7 @@ Debugger::slowPathOnLeaveFrame(JSContext *cx, bool frameOk) */ if (fp->isEvalFrame()) { JSScript *script = fp->script(); - script->clearBreakpointsIn(cx, NULL, NULL); + script->clearBreakpointsIn(cx->runtime->defaultFreeOp(), NULL, NULL); } /* Establish (status, value) as our resumption value. */ @@ -1787,7 +1787,7 @@ Debugger::clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp) { THIS_DEBUGGER(cx, argc, vp, "clearAllBreakpoints", args, dbg); for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) - r.front()->compartment()->clearBreakpointsIn(cx, dbg, NULL); + r.front()->compartment()->clearBreakpointsIn(cx->runtime->defaultFreeOp(), dbg, NULL); return true; } @@ -2900,7 +2900,7 @@ DebuggerScript_clearBreakpoint(JSContext *cx, unsigned argc, Value *vp) if (!handler) return false; - script->clearBreakpointsIn(cx, dbg, handler); + script->clearBreakpointsIn(cx->runtime->defaultFreeOp(), dbg, handler); args.rval().setUndefined(); return true; } @@ -2910,7 +2910,7 @@ DebuggerScript_clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp) { THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "clearAllBreakpoints", args, obj, script); Debugger *dbg = Debugger::fromChildJSObject(obj); - script->clearBreakpointsIn(cx, dbg, NULL); + script->clearBreakpointsIn(cx->runtime->defaultFreeOp(), dbg, NULL); args.rval().setUndefined(); return true; } @@ -4305,7 +4305,7 @@ DebuggerEnv_getObject(JSContext *cx, unsigned argc, Value *vp) static JSBool DebuggerEnv_names(JSContext *cx, unsigned argc, Value *vp) { - THIS_DEBUGENV_OWNER(cx, argc, vp, "get type", args, envobj, env, dbg); + THIS_DEBUGENV_OWNER(cx, argc, vp, "names", args, envobj, env, dbg); AutoIdVector keys(cx); { @@ -4338,7 +4338,7 @@ static JSBool DebuggerEnv_find(JSContext *cx, unsigned argc, Value *vp) { REQUIRE_ARGC("Debugger.Environment.find", 1); - THIS_DEBUGENV_OWNER(cx, argc, vp, "get type", args, envobj, env, dbg); + THIS_DEBUGENV_OWNER(cx, argc, vp, "find", args, envobj, env, dbg); jsid id; if (!ValueToIdentifier(cx, args[0], &id)) @@ -4364,6 +4364,74 @@ DebuggerEnv_find(JSContext *cx, unsigned argc, Value *vp) return dbg->wrapEnvironment(cx, env, &args.rval()); } +static JSBool +DebuggerEnv_getVariable(JSContext *cx, unsigned argc, Value *vp) +{ + REQUIRE_ARGC("Debugger.Environment.getVariable", 1); + THIS_DEBUGENV_OWNER(cx, argc, vp, "getVariable", args, envobj, env, dbg); + + jsid id; + if (!ValueToIdentifier(cx, args[0], &id)) + return false; + + Value v; + { + AutoCompartment ac(cx, env); + if (!ac.enter() || !cx->compartment->wrapId(cx, &id)) + return false; + + /* This can trigger getters. */ + ErrorCopier ec(ac, dbg->toJSObject()); + if (!env->getGeneric(cx, id, &v)) + return false; + } + + if (!dbg->wrapDebuggeeValue(cx, &v)) + return false; + args.rval() = v; + return true; +} + +static JSBool +DebuggerEnv_setVariable(JSContext *cx, unsigned argc, Value *vp) +{ + REQUIRE_ARGC("Debugger.Environment.setVariable", 2); + THIS_DEBUGENV_OWNER(cx, argc, vp, "setVariable", args, envobj, env, dbg); + + jsid id; + if (!ValueToIdentifier(cx, args[0], &id)) + return false; + + Value v = args[1]; + if (!dbg->unwrapDebuggeeValue(cx, &v)) + return false; + + { + AutoCompartment ac(cx, env); + if (!ac.enter() || !cx->compartment->wrapId(cx, &id) || !cx->compartment->wrap(cx, &v)) + return false; + + /* This can trigger setters. */ + ErrorCopier ec(ac, dbg->toJSObject()); + + /* Make sure the environment actually has the specified binding. */ + bool has; + if (!env->hasProperty(cx, id, &has)) + return false; + if (!has) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_VARIABLE_NOT_FOUND); + return false; + } + + /* Just set the property. */ + if (!env->setGeneric(cx, id, &v, true)) + return false; + } + + args.rval().setUndefined(); + return true; +} + static JSPropertySpec DebuggerEnv_properties[] = { JS_PSG("type", DebuggerEnv_getType, 0), JS_PSG("object", DebuggerEnv_getObject, 0), @@ -4374,6 +4442,8 @@ static JSPropertySpec DebuggerEnv_properties[] = { static JSFunctionSpec DebuggerEnv_methods[] = { JS_FN("names", DebuggerEnv_names, 0, 0), JS_FN("find", DebuggerEnv_find, 1, 0), + JS_FN("getVariable", DebuggerEnv_getVariable, 1, 0), + JS_FN("setVariable", DebuggerEnv_setVariable, 2, 0), JS_FS_END }; diff --git a/js/xpconnect/idl/xpccomponents.idl b/js/xpconnect/idl/xpccomponents.idl index 7602a44d3256..edf2e24aeb5c 100644 --- a/js/xpconnect/idl/xpccomponents.idl +++ b/js/xpconnect/idl/xpccomponents.idl @@ -261,7 +261,6 @@ interface nsIXPCComponents_Utils : nsISupports * * Force an immediate garbage collection cycle. */ - [implicit_jscontext] void forceGC(); /* @@ -269,21 +268,18 @@ interface nsIXPCComponents_Utils : nsISupports * * Force an immediate shrinking garbage collection cycle. */ - [implicit_jscontext] void forceShrinkingGC(); /* * Schedule a garbage collection cycle for a point in the future when no JS * is running. Call the provided function once this has occurred. */ - [implicit_jscontext] void schedulePreciseGC(in ScheduledGCCallback callback); /* * Schedule a shrinking garbage collection cycle for a point in the future * when no JS is running. Call the provided function once this has occured. */ - [implicit_jscontext] void schedulePreciseShrinkingGC(in ScheduledGCCallback callback); /** diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 4e03bd5a8756..6577d088ae01 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -552,9 +552,10 @@ DumpXPC(JSContext *cx, unsigned argc, jsval *vp) static JSBool GC(JSContext *cx, unsigned argc, jsval *vp) { - JS_GC(cx); + JSRuntime *rt = JS_GetRuntime(cx); + JS_GC(rt); #ifdef JS_GCMETER - js_DumpGCStats(JS_GetRuntime(cx), stdout); + js_DumpGCStats(rt, stdout); #endif JS_SET_RVAL(cx, vp, JSVAL_VOID); return true; @@ -2013,12 +2014,12 @@ main(int argc, char **argv, char **envp) #endif JS_DropPrincipals(rt, gJSPrincipals); JS_ClearScope(cx, glob); - JS_GC(cx); + JS_GC(rt); JSContext *oldcx; cxstack->Pop(&oldcx); NS_ASSERTION(oldcx == cx, "JS thread context push/pop mismatch"); cxstack = nsnull; - JS_GC(cx); + JS_GC(rt); } //this scopes the JSAutoCrossCompartmentCall JS_EndRequest(cx); JS_DestroyContext(cx); diff --git a/js/xpconnect/src/Makefile.in b/js/xpconnect/src/Makefile.in index 7814dda3cfb9..2f7c56665099 100644 --- a/js/xpconnect/src/Makefile.in +++ b/js/xpconnect/src/Makefile.in @@ -150,8 +150,8 @@ dom_quickstubs.cpp: $(srcdir)/dom_quickstubs.qsconf \ $(topsrcdir)/xpcom/idl-parser/header.py \ $(topsrcdir)/xpcom/idl-parser/xpidl.py \ $(DEPTH)/js/src/js-confdefs.h - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ + $(PYTHON_PATH) \ + $(PLY_INCLUDE) \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/qsgen.py \ --idlpath=$(DEPTH)/dist/idl \ @@ -171,8 +171,8 @@ dombindings_gen.h: $(srcdir)/dombindings.conf \ $(topsrcdir)/xpcom/idl-parser/header.py \ $(topsrcdir)/xpcom/idl-parser/xpidl.py \ $(DEPTH)/js/src/js-confdefs.h - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ + $(PYTHON_PATH) \ + $(PLY_INCLUDE) \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dombindingsgen.py \ --idlpath=$(DEPTH)/dist/idl \ @@ -188,8 +188,8 @@ dombindings_gen.cpp: $(srcdir)/dombindings.conf \ $(topsrcdir)/xpcom/idl-parser/header.py \ $(topsrcdir)/xpcom/idl-parser/xpidl.py \ $(DEPTH)/js/src/js-confdefs.h - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ + $(PYTHON_PATH) \ + $(PLY_INCLUDE) \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dombindingsgen.py \ --idlpath=$(DEPTH)/dist/idl \ @@ -207,8 +207,8 @@ DictionaryHelpers.h: $(srcdir)/dictionary_helper_gen.conf \ $(topsrcdir)/xpcom/idl-parser/header.py \ $(topsrcdir)/xpcom/idl-parser/xpidl.py \ $(DEPTH)/js/src/js-confdefs.h - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ + $(PYTHON_PATH) \ + $(PLY_INCLUDE) \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dictionary_helper_gen.py \ -I $(DEPTH)/dist/idl \ @@ -222,8 +222,8 @@ DictionaryHelpers.cpp: $(srcdir)/dictionary_helper_gen.conf \ $(topsrcdir)/xpcom/idl-parser/header.py \ $(topsrcdir)/xpcom/idl-parser/xpidl.py \ $(DEPTH)/js/src/js-confdefs.h - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ + $(PYTHON_PATH) \ + $(PLY_INCLUDE) \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dictionary_helper_gen.py \ -I $(DEPTH)/dist/idl \ diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 3c71a76608e0..06bac8782117 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3618,36 +3618,33 @@ nsXPCComponents_Utils::GetWeakReference(const JS::Value &object, JSContext *cx, /* void forceGC (); */ NS_IMETHODIMP -nsXPCComponents_Utils::ForceGC(JSContext *cx) +nsXPCComponents_Utils::ForceGC() { - js::PrepareForFullGC(JS_GetRuntime(cx)); - js::GCForReason(cx, js::gcreason::COMPONENT_UTILS); + JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime(); + js::PrepareForFullGC(rt); + js::GCForReason(rt, js::gcreason::COMPONENT_UTILS); return NS_OK; } /* void forceShrinkingGC (); */ NS_IMETHODIMP -nsXPCComponents_Utils::ForceShrinkingGC(JSContext *cx) +nsXPCComponents_Utils::ForceShrinkingGC() { - js::PrepareForFullGC(JS_GetRuntime(cx)); - js::ShrinkingGC(cx, js::gcreason::COMPONENT_UTILS); + JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime(); + js::PrepareForFullGC(rt); + js::ShrinkingGC(rt, js::gcreason::COMPONENT_UTILS); return NS_OK; } class PreciseGCRunnable : public nsRunnable { public: - PreciseGCRunnable(JSContext *aCx, ScheduledGCCallback* aCallback, bool aShrinking) - : mCallback(aCallback), mCx(aCx), mShrinking(aShrinking) {} + PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking) + : mCallback(aCallback), mShrinking(aShrinking) {} NS_IMETHOD Run() { - nsCOMPtr runtimeSvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); - NS_ENSURE_STATE(runtimeSvc); - - JSRuntime* rt = nsnull; - runtimeSvc->GetRuntime(&rt); - NS_ENSURE_STATE(rt); + JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime(); JSContext *cx; JSContext *iter = nsnull; @@ -3657,11 +3654,11 @@ class PreciseGCRunnable : public nsRunnable } } - js::PrepareForFullGC(JS_GetRuntime(mCx)); + js::PrepareForFullGC(rt); if (mShrinking) - js::ShrinkingGC(mCx, js::gcreason::COMPONENT_UTILS); + js::ShrinkingGC(rt, js::gcreason::COMPONENT_UTILS); else - js::GCForReason(mCx, js::gcreason::COMPONENT_UTILS); + js::GCForReason(rt, js::gcreason::COMPONENT_UTILS); mCallback->Callback(); return NS_OK; @@ -3669,23 +3666,22 @@ class PreciseGCRunnable : public nsRunnable private: nsRefPtr mCallback; - JSContext *mCx; bool mShrinking; }; -/* [inline_jscontext] void schedulePreciseGC(in ScheduledGCCallback callback); */ +/* void schedulePreciseGC(in ScheduledGCCallback callback); */ NS_IMETHODIMP -nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback, JSContext* aCx) +nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback) { - nsRefPtr event = new PreciseGCRunnable(aCx, aCallback, false); + nsRefPtr event = new PreciseGCRunnable(aCallback, false); return NS_DispatchToMainThread(event); } -/* [inline_jscontext] void schedulePreciseShrinkingGC(in ScheduledGCCallback callback); */ +/* void schedulePreciseShrinkingGC(in ScheduledGCCallback callback); */ NS_IMETHODIMP -nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback, JSContext* aCx) +nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback) { - nsRefPtr event = new PreciseGCRunnable(aCx, aCallback, true); + nsRefPtr event = new PreciseGCRunnable(aCallback, true); return NS_DispatchToMainThread(event); } diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 66c490e91160..0da92c524775 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -409,29 +409,18 @@ nsXPConnect::Collect(PRUint32 reason, PRUint32 kind) // To improve debugging, if DEBUG_CC is defined all JS objects are // traversed. - XPCCallContext ccx(NATIVE_CALLER); - if (!ccx.IsValid()) - return; - - JSContext *cx = ccx.GetJSContext(); - JSRuntime *rt = GetRuntime()->GetJSRuntime(); - - // We want to scan the current thread for GC roots only if it was in a - // request prior to the Collect call to avoid false positives during the - // cycle collection. So to compensate for JS_BeginRequest in - // XPCCallContext::Init we disable the conservative scanner if that call - // has started the request on this thread. - js::AutoSkipConservativeScan ascs(cx); MOZ_ASSERT(reason < js::gcreason::NUM_REASONS); js::gcreason::Reason gcreason = (js::gcreason::Reason)reason; + + JSRuntime *rt = GetRuntime()->GetJSRuntime(); js::PrepareForFullGC(rt); if (kind == nsGCShrinking) { - js::ShrinkingGC(cx, gcreason); + js::ShrinkingGC(rt, gcreason); } else if (kind == nsGCIncremental) { - js::IncrementalGC(cx, gcreason); + js::IncrementalGC(rt, gcreason); } else { MOZ_ASSERT(kind == nsGCNormal); - js::GCForReason(cx, gcreason); + js::GCForReason(rt, gcreason); } } @@ -2803,17 +2792,7 @@ nsXPConnect::GetTelemetryValue(JSContext *cx, jsval *rval) NS_IMETHODIMP nsXPConnect::NotifyDidPaint() { - JSRuntime *rt = mRuntime->GetJSRuntime(); - if (!js::WantGCSlice(rt)) - return NS_OK; - - XPCCallContext ccx(NATIVE_CALLER); - if (!ccx.IsValid()) - return UnexpectedFailure(NS_ERROR_FAILURE); - - JSContext *cx = ccx.GetJSContext(); - - js::NotifyDidPaint(cx); + js::NotifyDidPaint(GetRuntime()->GetJSRuntime()); return NS_OK; } diff --git a/layout/style/nsStyleCoord.h b/layout/style/nsStyleCoord.h index 7406f29d8da7..667ad368fe82 100644 --- a/layout/style/nsStyleCoord.h +++ b/layout/style/nsStyleCoord.h @@ -287,7 +287,7 @@ inline bool nsStyleCoord::operator!=(const nsStyleCoord& aOther) const return !((*this) == aOther); } -inline PRInt32 nsStyleCoord::GetCoordValue() const +inline nscoord nsStyleCoord::GetCoordValue() const { NS_ASSERTION((mUnit == eStyleUnit_Coord), "not a coord value"); if (mUnit == eStyleUnit_Coord) { diff --git a/mfbt/Scoped.h b/mfbt/Scoped.h new file mode 100644 index 000000000000..a39a077c46a2 --- /dev/null +++ b/mfbt/Scoped.h @@ -0,0 +1,224 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* A number of structures to simplify scope-based RAII management. */ + +#ifndef mozilla_Scoped_h_ +#define mozilla_Scoped_h_ + +/* + * Resource Acquisition Is Initialization is a programming idiom used + * to write robust code that is able to deallocate resources properly, + * even in presence of execution errors or exceptions that need to be + * propagated. The Scoped* classes defined in this header perform the + * deallocation of the resource they hold once program execution + * reaches the end of the scope for which they have been defined. + * + * This header provides the following RAII classes: + * + * - |ScopedFreePtr| - a container for a pointer, that automatically calls + * |free()| at the end of the scope; + * - |ScopedDeletePtr| - a container for a pointer, that automatically calls + * |delete| at the end of the scope; + * - |ScopedDeleteArray| - a container for a pointer to an array, that + * automatically calls |delete[]| at the end of the scope. + * + * The general scenario for each of the RAII classes is the following: + * + * ScopedClass foo(create_value()); + * // ... In this scope, |foo| is defined. Use |foo.get()| or |foo.rwget()| + * to access the value. + * // ... In case of |return| or |throw|, |foo| is deallocated automatically. + * // ... If |foo| needs to be returned or stored, use |foo.forget()| + * + * Note that the RAII classes defined in this header do _not_ perform any form + * of reference-counting or garbage-collection. These classes have exactly two + * behaviors: + * - if |forget()| has not been called, the resource is always deallocated at + * the end of the scope; + * - if |forget()| has been called, any control on the resource is unbound + * and the resource is not deallocated by the class. + * + * + * Extension: + * + * In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE| + * to simplify the definition of RAII classes for other scenarios. These macros + * have been used to automatically close file descriptors/file handles when + * reaching the end of the scope, graphics contexts, etc. + */ + +#include "mozilla/Attributes.h" +#include "mozilla/GuardObjects.h" + +/* + * Scoped is a helper to create RAII wrappers + * Type argument |Traits| is expected to have the following structure: + * + * struct Traits { + * // Define the type of the value stored in the wrapper + * typedef value_type type; + * // Returns the value corresponding to the uninitialized or freed state + * const static type empty(); + * // Release resources corresponding to the wrapped value + * // This function is responsible for not releasing an |empty| value + * const static void release(type); + * } + */ +template +class Scoped +{ +public: + typedef typename Traits::type Resource; + + explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) + : value(Traits::empty()) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + explicit Scoped(const Resource& value + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : value(value) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + ~Scoped() { + Traits::release(value); + } + + // Constant getter + operator const Resource&() const { return value; } + const Resource& operator->() const { return value; } + const Resource& get() const { return value; } + // Non-constant getter. + Resource& rwget() { return value; } + + /* + * Forget the resource. + * + * Once |forget| has been called, the |Scoped| is neutralized, i.e. it will + * have no effect at destruction (unless it is reset to another resource by + * |operator=|). + * + * @return The original resource. + */ + Resource forget() { + Resource tmp = value; + value = Traits::empty(); + return tmp; + } + + /* + * Perform immediate clean-up of this |Scoped|. + * + * If this |Scoped| is currently empty, this method has no effect. + */ + void dispose() { + Traits::release(value); + value = Traits::empty(); + } + + bool operator==(const Resource& other) const { + return value == other; + } + + /* + * Replace the resource with another resource. + * + * Calling |operator=| has the side-effect of triggering clean-up. If you do + * not want to trigger clean-up, you should first invoke |forget|. + * + * @return this + */ + Scoped& operator=(const Resource& other) { + return reset(other); + } + Scoped& reset(const Resource& other) { + Traits::release(value); + value = other; + return *this; + } + +private: + explicit Scoped(const Scoped& value) MOZ_DELETE; + Scoped& operator=(const Scoped& value) MOZ_DELETE; + +private: + Resource value; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +/* + * SCOPED_TEMPLATE defines a templated class derived from Scoped + * This allows to implement templates such as ScopedFreePtr. + * + * @param name The name of the class to define. + * @param Traits A struct implementing clean-up. See the implementations + * for more details. + */ +#define SCOPED_TEMPLATE(name, Traits) \ +template \ +struct name : public Scoped > \ +{ \ + typedef Scoped > Super; \ + typedef typename Super::Resource Resource; \ + name& operator=(Resource ptr) { \ + Super::operator=(ptr); \ + return *this; \ + } \ + explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \ + : Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \ + {} \ + explicit name(Resource ptr \ + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \ + : Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \ + {} \ +private: \ + explicit name(name& source) MOZ_DELETE; \ + name& operator=(name& source) MOZ_DELETE; \ +}; + +/* + * ScopedFreePtr is a RAII wrapper for pointers that need to be free()d. + * + * struct S { ... }; + * ScopedFreePtr foo = malloc(sizeof(S)); + * ScopedFreePtr bar = strdup(str); + */ +template +struct ScopedFreePtrTraits +{ + typedef T* type; + static T* empty() { return NULL; } + static void release(T* ptr) { free(ptr); } +}; +SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits) + +/* + * ScopedDeletePtr is a RAII wrapper for pointers that need to be deleted. + * + * struct S { ... }; + * ScopedDeletePtr foo = new S(); + */ +template +struct ScopedDeletePtrTraits : public ScopedFreePtrTraits { + static void release(T* ptr) { delete ptr; } +}; +SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits) + +/* + * ScopedDeleteArray is a RAII wrapper for pointers that need to be delete[]ed. + * + * struct S { ... }; + * ScopedDeleteArray foo = new S[42]; + */ +template +struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits +{ + static void release(T* ptr) { delete [] ptr; } +}; +SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits) + + +#endif // mozilla_Scoped_h_ diff --git a/mfbt/exported_headers.mk b/mfbt/exported_headers.mk index 12294fc024a4..9f557ac88249 100644 --- a/mfbt/exported_headers.mk +++ b/mfbt/exported_headers.mk @@ -52,6 +52,7 @@ EXPORTS_mozilla += \ MSStdInt.h \ RangedPtr.h \ RefPtr.h \ + Scoped.h \ StandardInteger.h \ Types.h \ Util.h \ diff --git a/mobile/android/base/FormAssistPopup.java b/mobile/android/base/FormAssistPopup.java index 815fc7b9762b..714a2dbaa52d 100644 --- a/mobile/android/base/FormAssistPopup.java +++ b/mobile/android/base/FormAssistPopup.java @@ -179,7 +179,6 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene mValidationMessageText = (TextView) mValidationMessage.findViewById(R.id.validation_message_text); } - validationMessage = "This is an incredibly long validation message to test the width of the popup."; mValidationMessageText.setText(validationMessage); // We need to set the text as selected for the marquee text to work. diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 1dfb96eff155..2518f992307d 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -991,7 +991,7 @@ abstract public class GeckoApp if (Tabs.getInstance().isSelectedTab(tab)) { mMainHandler.post(new Runnable() { public void run() { - mLayerController.setWaitForTouchListeners(true); + mLayerController.getView().getTouchEventHandler().setWaitForTouchListeners(true); } }); } @@ -2805,7 +2805,7 @@ abstract public class GeckoApp LayerController layerController = getLayerController(); layerController.setLayerClient(mLayerClient); - layerController.setOnTouchListener(new View.OnTouchListener() { + layerController.getView().getTouchEventHandler().setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View view, MotionEvent event) { if (event == null) return true; diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 702990729273..c8293fc2446e 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -1201,11 +1201,11 @@ public class GeckoAppShell }); } - public static void setPreventPanning(final boolean aPreventPanning) { + public static void notifyDefaultPrevented(final boolean defaultPrevented) { getMainHandler().post(new Runnable() { public void run() { - LayerController layerController = GeckoApp.mAppContext.getLayerController(); - layerController.preventPanning(aPreventPanning); + LayerView view = GeckoApp.mAppContext.getLayerController().getView(); + view.getTouchEventHandler().handleEventListenerAction(!defaultPrevented); } }); } diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 16e4a0338b4a..2314b4b5eb44 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -144,6 +144,7 @@ FENNEC_JAVA_FILES = \ gfx/TextureGenerator.java \ gfx/TextureReaper.java \ gfx/TileLayer.java \ + gfx/TouchEventHandler.java \ gfx/ViewTransform.java \ gfx/ViewportMetrics.java \ gfx/VirtualLayer.java \ diff --git a/mobile/android/base/gfx/LayerController.java b/mobile/android/base/gfx/LayerController.java index efb9f3eb350c..1173066da3b2 100644 --- a/mobile/android/base/gfx/LayerController.java +++ b/mobile/android/base/gfx/LayerController.java @@ -38,33 +38,20 @@ package org.mozilla.gecko.gfx; -import org.mozilla.gecko.gfx.IntSize; import org.mozilla.gecko.gfx.Layer; import org.mozilla.gecko.ui.PanZoomController; import org.mozilla.gecko.ui.SimpleScaleGestureDetector; import org.mozilla.gecko.GeckoApp; -import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.Tabs; -import org.mozilla.gecko.Tab; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Point; import android.graphics.PointF; -import android.graphics.Rect; import android.graphics.RectF; import android.util.Log; -import android.view.MotionEvent; import android.view.GestureDetector; -import android.view.ScaleGestureDetector; import android.view.View.OnTouchListener; -import android.view.ViewConfiguration; -import java.lang.Math; -import java.util.Timer; -import java.util.TimerTask; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -75,7 +62,7 @@ import java.util.regex.Pattern; * * Many methods require that the monitor be held, with a synchronized (controller) { ... } block. */ -public class LayerController implements Tabs.OnTabsChangedListener { +public class LayerController { private static final String LOGTAG = "GeckoLayerController"; private Layer mRootLayer; /* The root layer. */ @@ -95,15 +82,12 @@ public class LayerController implements Tabs.OnTabsChangedListener { * fields. */ private volatile ImmutableViewportMetrics mViewportMetrics; /* The current viewport metrics. */ - private boolean mWaitForTouchListeners; - - private PanZoomController mPanZoomController; /* * The panning and zooming controller, which interprets pan and zoom gestures for us and * updates our visible rect appropriately. */ + private PanZoomController mPanZoomController; - private OnTouchListener mOnTouchListener; /* The touch listener. */ private GeckoLayerClient mLayerClient; /* The layer client. */ /* The new color for the checkerboard. */ @@ -112,14 +96,6 @@ public class LayerController implements Tabs.OnTabsChangedListener { private boolean mForceRedraw; - /* The time limit for pages to respond with preventDefault on touchevents - * before we begin panning the page */ - private int mTimeout = 200; - - private boolean allowDefaultActions = true; - private Timer allowDefaultTimer = null; - private PointF initialTouchLocation = null; - private static Pattern sColorPattern; public LayerController(Context context) { @@ -130,14 +106,6 @@ public class LayerController implements Tabs.OnTabsChangedListener { mPanZoomController = new PanZoomController(this); mView = new LayerView(context, this); mCheckerboardShouldShowChecks = true; - - Tabs.registerOnTabsChangedListener(this); - - mTimeout = ViewConfiguration.getLongPressTimeout(); - } - - public void onDestroy() { - Tabs.unregisterOnTabsChangedListener(this); } public void setRoot(Layer layer) { mRootLayer = layer; } @@ -293,10 +261,6 @@ public class LayerController implements Tabs.OnTabsChangedListener { public boolean post(Runnable action) { return mView.post(action); } - public void setOnTouchListener(OnTouchListener onTouchListener) { - mOnTouchListener = onTouchListener; - } - /** * The view as well as the controller itself use this method to notify the layer client that * the geometry changed. @@ -366,81 +330,6 @@ public class LayerController implements Tabs.OnTabsChangedListener { return layerPoint; } - /* - * Gesture detection. This is handled only at a high level in this class; we dispatch to the - * pan/zoom controller to do the dirty work. - */ - public boolean onTouchEvent(MotionEvent event) { - int action = event.getAction(); - PointF point = new PointF(event.getX(), event.getY()); - - // this will only match the first touchstart in a series - if ((action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) { - initialTouchLocation = point; - allowDefaultActions = !mWaitForTouchListeners; - - // if we have a timer, this may be a double tap, - // cancel the current timer but don't clear the event queue - if (allowDefaultTimer != null) { - allowDefaultTimer.cancel(); - } else { - // if we don't have a timer, make sure we remove any old events - mView.clearEventQueue(); - } - allowDefaultTimer = new Timer(); - allowDefaultTimer.schedule(new TimerTask() { - public void run() { - post(new Runnable() { - public void run() { - preventPanning(false); - } - }); - } - }, mTimeout); - } - - // After the initial touch, ignore touch moves until they exceed a minimum distance. - if (initialTouchLocation != null && (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE) { - if (PointUtils.subtract(point, initialTouchLocation).length() > PanZoomController.PAN_THRESHOLD) { - initialTouchLocation = null; - } else { - return !allowDefaultActions; - } - } - - // send the event to content - if (mOnTouchListener != null) - mOnTouchListener.onTouch(mView, event); - - return !allowDefaultActions; - } - - public void preventPanning(boolean aValue) { - if (allowDefaultTimer != null) { - allowDefaultTimer.cancel(); - allowDefaultTimer = null; - } - if (aValue == allowDefaultActions) { - allowDefaultActions = !aValue; - - if (aValue) { - mView.clearEventQueue(); - mPanZoomController.cancelTouch(); - } else { - mView.processEventQueue(); - } - } - } - - public void onTabChanged(Tab tab, Tabs.TabEvents msg) { - if ((Tabs.getInstance().isSelectedTab(tab) && msg == Tabs.TabEvents.STOP) || msg == Tabs.TabEvents.SELECTED) { - mWaitForTouchListeners = tab.getHasTouchListeners(); - } - } - public void setWaitForTouchListeners(boolean aValue) { - mWaitForTouchListeners = aValue; - } - /** Retrieves whether we should show checkerboard checks or not. */ public boolean checkerboardShouldShowChecks() { return mCheckerboardShouldShowChecks; diff --git a/mobile/android/base/gfx/LayerView.java b/mobile/android/base/gfx/LayerView.java index b22ce9b2a87a..547e711ee091 100644 --- a/mobile/android/base/gfx/LayerView.java +++ b/mobile/android/base/gfx/LayerView.java @@ -43,20 +43,16 @@ import org.mozilla.gecko.GeckoInputConnection; import org.mozilla.gecko.gfx.FloatSize; import org.mozilla.gecko.gfx.InputConnectionHandler; import org.mozilla.gecko.gfx.LayerController; -import org.mozilla.gecko.ui.SimpleScaleGestureDetector; import android.content.Context; import android.opengl.GLSurfaceView; import android.view.View; -import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; -import android.view.ScaleGestureDetector; import android.widget.RelativeLayout; import android.util.Log; import java.nio.IntBuffer; -import java.util.LinkedList; import org.mozilla.gecko.GeckoApp; import android.content.Context; @@ -77,18 +73,16 @@ import javax.microedition.khronos.opengles.GL10; * Note that LayerView is accessed by Robocop via reflection. */ public class LayerView extends SurfaceView implements SurfaceHolder.Callback { + private static String LOGTAG = "GeckoLayerView"; + private Context mContext; private LayerController mController; + private TouchEventHandler mTouchEventHandler; private GLController mGLController; private InputConnectionHandler mInputConnectionHandler; private LayerRenderer mRenderer; - private GestureDetector mGestureDetector; - private SimpleScaleGestureDetector mScaleGestureDetector; private long mRenderTime; private boolean mRenderTimeReset; - private static String LOGTAG = "GeckoLayerView"; - /* List of events to be processed if the page does not prevent them. Should only be touched on the main thread */ - private LinkedList mEventQueue = new LinkedList(); /* Must be a PAINT_xxx constant */ private int mPaintState = PAINT_NONE; @@ -111,54 +105,21 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback { mGLController = new GLController(this); mContext = context; mController = controller; + mTouchEventHandler = new TouchEventHandler(context, this, mController); mRenderer = new LayerRenderer(this); - mGestureDetector = new GestureDetector(context, controller.getGestureListener()); - mScaleGestureDetector = - new SimpleScaleGestureDetector(controller.getScaleGestureListener()); - mGestureDetector.setOnDoubleTapListener(controller.getDoubleTapListener()); mInputConnectionHandler = null; setFocusable(true); setFocusableInTouchMode(true); } - private void addToEventQueue(MotionEvent event) { - MotionEvent copy = MotionEvent.obtain(event); - mEventQueue.add(copy); - } - - public void processEventQueue() { - MotionEvent event = mEventQueue.poll(); - while(event != null) { - processEvent(event); - event = mEventQueue.poll(); - } - } - - public void clearEventQueue() { - mEventQueue.clear(); - } - @Override public boolean onTouchEvent(MotionEvent event) { - if (mController.onTouchEvent(event)) { - addToEventQueue(event); - return true; - } - return processEvent(event); - } - - private boolean processEvent(MotionEvent event) { - if (mGestureDetector.onTouchEvent(event)) - return true; - mScaleGestureDetector.onTouchEvent(event); - if (mScaleGestureDetector.isInProgress()) - return true; - mController.getPanZoomController().onTouchEvent(event); - return true; + return mTouchEventHandler.handleEvent(event); } public LayerController getController() { return mController; } + public TouchEventHandler getTouchEventHandler() { return mTouchEventHandler; } /** The LayerRenderer calls this to indicate that the window has changed size. */ public void setViewportSize(IntSize size) { diff --git a/mobile/android/base/gfx/TouchEventHandler.java b/mobile/android/base/gfx/TouchEventHandler.java new file mode 100644 index 000000000000..707ea1b3b157 --- /dev/null +++ b/mobile/android/base/gfx/TouchEventHandler.java @@ -0,0 +1,294 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.gfx; + +import java.util.LinkedList; +import java.util.Queue; +import android.content.Context; +import android.graphics.PointF; +import android.os.SystemClock; +import android.util.Log; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ViewConfiguration; +import android.view.View.OnTouchListener; +import org.mozilla.gecko.ui.SimpleScaleGestureDetector; +import org.mozilla.gecko.Tab; +import org.mozilla.gecko.Tabs; + +/** + * This class handles incoming touch events from the user and sends them to + * listeners in Gecko and/or performs the "default action" (asynchronous pan/zoom + * behaviour. EVERYTHING IN THIS CLASS MUST RUN ON THE UI THREAD. + * + * In the following code/comments, a "block" of events refers to a contiguous + * sequence of events that starts with a DOWN or POINTER_DOWN and goes up to + * but not including the next DOWN or POINTER_DOWN event. + * + * "Dispatching" an event refers to performing the default actions for the event, + * which at our level of abstraction just means sending it off to the gesture + * detectors and the pan/zoom controller. + * + * If an event is "default-prevented" that means one or more listeners in Gecko + * has called preventDefault() on the event, which means that the default action + * for that event should not occur. Usually we care about a "block" of events being + * default-prevented, which means that the DOWN/POINTER_DOWN event that started + * the block, or the first MOVE event following that, were prevent-defaulted. + * + * A "default-prevented notification" is when we here in Java-land receive a notification + * from gecko as to whether or not a block of events was default-prevented. This happens + * at some point after the first or second event in the block is processed in Gecko. + * This code assumes we get EXACTLY ONE default-prevented notification for each block + * of events. + */ +public final class TouchEventHandler implements Tabs.OnTabsChangedListener { + private static final String LOGTAG = "GeckoTouchEventHandler"; + + // The time limit for listeners to respond with preventDefault on touchevents + // before we begin panning the page + private final int EVENT_LISTENER_TIMEOUT = ViewConfiguration.getLongPressTimeout(); + + private final LayerView mView; + private final LayerController mController; + private final GestureDetector mGestureDetector; + private final SimpleScaleGestureDetector mScaleGestureDetector; + + // the queue of events that we are holding on to while waiting for a preventDefault + // notification + private final Queue mEventQueue; + private final ListenerTimeoutProcessor mListenerTimeoutProcessor; + + // the listener we use to notify gecko of touch events + private OnTouchListener mOnTouchListener; + + // whether or not we should wait for touch listeners to respond (this state is + // per-tab and is updated when we switch tabs). + private boolean mWaitForTouchListeners; + + // true if we should hold incoming events in our queue. this is re-set for every + // block of events, this is cleared once we find out if the block has been + // default-prevented or not (or we time out waiting for that). + private boolean mHoldInQueue; + + // true if we should dispatch incoming events to the gesture detector and the pan/zoom + // controller. if this is false, then the current block of events has been + // default-prevented, and we should not dispatch these events (although we'll still send + // them to gecko listeners). + private boolean mDispatchEvents; + + // this next variable requires some explanation. strap yourself in. + // + // for each block of events, we do two things: (1) send the events to gecko and expect + // exactly one default-prevented notification in return, and (2) kick off a delayed + // ListenerTimeoutProcessor that triggers in case we don't hear from the listener in + // a timely fashion. + // since events are constantly coming in, we need to be able to handle more than one + // block of events in the queue. + // + // this means that there are ordering restrictions on these that we can take advantage of, + // and need to abide by. blocks of events in the queue will always be in the order that + // the user generated them. default-prevented notifications we get from gecko will be in + // the same order as the blocks of events in the queue. the ListenerTimeoutProcessors that + // have been posted will also fire in the same order as the blocks of events in the queue. + // HOWEVER, we may get multiple default-prevented notifications interleaved with multiple + // ListenerTimeoutProcessor firings, and that interleaving is not predictable. + // + // therefore, we need to make sure that for each block of events, we process the queued + // events exactly once, either when we get the default-prevented notification, or when the + // timeout expires (whichever happens first). there is no way to associate the + // default-prevented notification with a particular block of events other than via ordering, + // + // so what we do to accomplish this is to track a "processing balance", which is the number + // of default-prevented notifications that we have received, minus the number of ListenerTimeoutProcessors + // that have fired. (think "balance" as in teeter-totter balance). this value is: + // - zero when we are in a state where the next default-prevented notification we expect + // to receive and the next ListenerTimeoutProcessor we expect to fire both correspond to + // the next block of events in the queue. + // - positive when we are in a state where we have received more default-prevented notifications + // than ListenerTimeoutProcessors. This means that the next default-prevented notification + // does correspond to the block at the head of the queue, but the next n ListenerTimeoutProcessors + // need to be ignored as they are for blocks we have already processed. (n is the absolute value + // of the balance.) + // - negative when we are in a state where we have received more ListenerTimeoutProcessors than + // default-prevented notifications. This means that the next ListenerTimeoutProcessor that + // we receive does correspond to the block at the head of the queue, but the next n + // default-prevented notifications need to be ignored as they are for blocks we have already + // processed. (n is the absolute value of the balance.) + private int mProcessingBalance; + + TouchEventHandler(Context context, LayerView view, LayerController controller) { + mView = view; + mController = controller; + + mEventQueue = new LinkedList(); + mGestureDetector = new GestureDetector(context, controller.getGestureListener()); + mScaleGestureDetector = new SimpleScaleGestureDetector(controller.getScaleGestureListener()); + mListenerTimeoutProcessor = new ListenerTimeoutProcessor(); + mDispatchEvents = true; + + mGestureDetector.setOnDoubleTapListener(controller.getDoubleTapListener()); + Tabs.registerOnTabsChangedListener(this); + } + + /* This function MUST be called on the UI thread */ + public boolean handleEvent(MotionEvent event) { + // if we don't have gecko listeners, just dispatch the event + // and be done with it, no extra work needed. + if (mOnTouchListener == null) { + dispatchEvent(event); + return true; + } + + if (isDownEvent(event)) { + // this is the start of a new block of events! whee! + mHoldInQueue = mWaitForTouchListeners; + if (mHoldInQueue) { + // if we're holding the events in the queue, set the timeout so that + // we dispatch these events if we don't get a default-prevented notification + mView.postDelayed(mListenerTimeoutProcessor, EVENT_LISTENER_TIMEOUT); + } else { + // if we're not holding these events, then we still need to pretend like + // we did and had a ListenerTimeoutProcessor fire so that when we get + // the default-prevented notification for this block, it doesn't accidentally + // act upon some other block + mProcessingBalance++; + } + } + + // if we need to hold the events, add it to the queue. if we need to dispatch + // it directly, do that. it is possible that both mHoldInQueue and mDispatchEvents + // are false, in which case we are processing a block of events that we know + // has been default-prevented. in that case we don't keep the events as we don't + // need them (but we still pass them to the gecko listener). + if (mHoldInQueue) { + mEventQueue.add(MotionEvent.obtain(event)); + } else if (mDispatchEvents) { + dispatchEvent(event); + } + + // notify gecko of the event + mOnTouchListener.onTouch(mView, event); + + return true; + } + + /** + * This function is how gecko sends us a default-prevented notification. It is called + * once gecko knows definitively whether the block of events has had preventDefault + * called on it (either on the initial down event that starts the block, or on + * the first event following that down event). + * + * This function MUST be called on the UI thread. + */ + public void handleEventListenerAction(boolean allowDefaultAction) { + if (mProcessingBalance > 0) { + // this event listener that triggered this took too long, and the corresponding + // ListenerTimeoutProcessor runnable already ran for the event in question. the + // block of events this is for has already been processed, so we don't need to + // do anything here. + } else { + processEventBlock(allowDefaultAction); + } + mProcessingBalance--; + } + + /* This function MUST be called on the UI thread. */ + public void setWaitForTouchListeners(boolean aValue) { + mWaitForTouchListeners = aValue; + } + + /* This function MUST be called on the UI thread. */ + public void setOnTouchListener(OnTouchListener onTouchListener) { + mOnTouchListener = onTouchListener; + } + + private boolean isDownEvent(MotionEvent event) { + int action = (event.getAction() & MotionEvent.ACTION_MASK); + return (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN); + } + + /** + * Dispatch the event to the gesture detectors and the pan/zoom controller. + */ + private void dispatchEvent(MotionEvent event) { + if (mGestureDetector.onTouchEvent(event)) { + return; + } + mScaleGestureDetector.onTouchEvent(event); + if (mScaleGestureDetector.isInProgress()) { + return; + } + mController.getPanZoomController().onTouchEvent(event); + } + + /** + * Process the block of events at the head of the queue now that we know + * whether it has been default-prevented or not. + */ + private void processEventBlock(boolean allowDefaultAction) { + if (!allowDefaultAction) { + // if the block has been default-prevented, cancel whatever stuff we had in + // progress in the gesture detector and pan zoom controller + long now = SystemClock.uptimeMillis(); + dispatchEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0)); + } + + // the odd loop condition is because the first event in the queue will + // always be a DOWN or POINTER_DOWN event, and we want to process all + // the events in the queue starting at that one, up to but not including + // the next DOWN or POINTER_DOWN event. + + MotionEvent event = mEventQueue.poll(); + while (true) { + // for each event we process, only dispatch it if the block hasn't been + // default-prevented. + if (allowDefaultAction) { + dispatchEvent(event); + } + event = mEventQueue.peek(); + if (event == null) { + // we have processed the backlog of events, and are all caught up. + // now we can set clear the hold flag and set the dispatch flag so + // that the handleEvent() function can do the right thing for all + // remaining events in this block (which is still ongoing) without + // having to put them in the queue. + mHoldInQueue = false; + mDispatchEvents = allowDefaultAction; + break; + } + if (isDownEvent(event)) { + // we have finished processing the block we were interested in. + // now we wait for the next call to processEventBlock + break; + } + // pop the event we peeked above, as it is still part of the block and + // we want to keep processing + mEventQueue.remove(); + } + } + + private class ListenerTimeoutProcessor implements Runnable { + /* This MUST be run on the UI thread */ + public void run() { + if (mProcessingBalance < 0) { + // gecko already responded with default-prevented notification, and so + // the block of events this ListenerTimeoutProcessor corresponds to have + // already been removed from the queue. + } else { + processEventBlock(true); + } + mProcessingBalance++; + } + } + + // Tabs.OnTabsChangedListener implementation + + public void onTabChanged(Tab tab, Tabs.TabEvents msg) { + if ((Tabs.getInstance().isSelectedTab(tab) && msg == Tabs.TabEvents.STOP) || msg == Tabs.TabEvents.SELECTED) { + mWaitForTouchListeners = tab.getHasTouchListeners(); + } + } +} diff --git a/mobile/android/base/ui/PanZoomController.java b/mobile/android/base/ui/PanZoomController.java index bf39714c1be0..915fc46ee121 100644 --- a/mobile/android/base/ui/PanZoomController.java +++ b/mobile/android/base/ui/PanZoomController.java @@ -367,6 +367,7 @@ public class PanZoomController private boolean onTouchCancel(MotionEvent event) { mState = PanZoomState.NOTHING; + cancelTouch(); // ensure we snap back if we're overscrolled bounce(); return false; @@ -901,7 +902,7 @@ public class PanZoomController return true; } - public void cancelTouch() { + private void cancelTouch() { GeckoEvent e = GeckoEvent.createBroadcastEvent("Gesture:CancelTouch", ""); GeckoAppShell.sendEventToGecko(e); } diff --git a/mobile/android/base/ui/SimpleScaleGestureDetector.java b/mobile/android/base/ui/SimpleScaleGestureDetector.java index 69ebcb8012b2..1561b2416b4b 100644 --- a/mobile/android/base/ui/SimpleScaleGestureDetector.java +++ b/mobile/android/base/ui/SimpleScaleGestureDetector.java @@ -131,11 +131,12 @@ public class SimpleScaleGestureDetector { private void onTouchEnd(MotionEvent event) { mLastEventTime = event.getEventTime(); + boolean isCancel = (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_CANCEL; int id = event.getPointerId(getActionIndex(event)); ListIterator iterator = mPointerInfo.listIterator(); while (iterator.hasNext()) { PointerInfo pointerInfo = iterator.next(); - if (pointerInfo.getId() != id) { + if (!(isCancel || pointerInfo.getId() == id)) { continue; } diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index d3b65f6ed964..aa3704e18eca 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -3518,7 +3518,11 @@ var PopupBlockerObserver = { }, { label: strings.GetStringFromName("popupButtonAlwaysAllow2"), - callback: function() { PopupBlockerObserver.allowPopupsForSite(true); } + callback: function() { + // Set permission before opening popup windows + PopupBlockerObserver.allowPopupsForSite(true); + PopupBlockerObserver.showPopupsForSite(); + } }, { label: strings.GetStringFromName("popupButtonNeverWarn2"), diff --git a/mobile/xul/chrome/content/browser-scripts.js b/mobile/xul/chrome/content/browser-scripts.js index aa4ed082d362..561948f459f4 100644 --- a/mobile/xul/chrome/content/browser-scripts.js +++ b/mobile/xul/chrome/content/browser-scripts.js @@ -42,15 +42,17 @@ Cu.import("resource://gre/modules/Services.jsm"); /** * Delay load some JS modules */ -XPCOMUtils.defineLazyGetter(this, "PluralForm", function() { - Cu.import("resource://gre/modules/PluralForm.jsm"); - return PluralForm; -}); +XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", + "resource://gre/modules/PluralForm.jsm"); -XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() { - Cu.import("resource://gre/modules/PlacesUtils.jsm"); - return PlacesUtils; -}); +XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", + "resource://gre/modules/PlacesUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", + "resource://gre/modules/AddonManager.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", + "resource://gre/modules/NetUtil.jsm"); /* window.Rect is used by http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-Rect * so it is not possible to set a lazy getter for Geometry.jsm diff --git a/mobile/xul/chrome/content/browser-ui.js b/mobile/xul/chrome/content/browser-ui.js index f8c833845990..b4923126bea2 100644 --- a/mobile/xul/chrome/content/browser-ui.js +++ b/mobile/xul/chrome/content/browser-ui.js @@ -37,10 +37,6 @@ * * ***** END LICENSE BLOCK ***** */ -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/AddonManager.jsm"); - [ ["AllPagesList", "popup_autocomplete", "cmd_openLocation"], ["HistoryList", "history-items", "cmd_history"], diff --git a/mobile/xul/chrome/content/browser.xul b/mobile/xul/chrome/content/browser.xul index ad35df46ccbb..9bae8cfe9fdd 100644 --- a/mobile/xul/chrome/content/browser.xul +++ b/mobile/xul/chrome/content/browser.xul @@ -81,8 +81,8 @@ xmlns:html="http://www.w3.org/1999/xhtml">