This commit is contained in:
Jim Blandy 2011-04-18 09:18:20 -07:00
commit f629983808
233 changed files with 2824 additions and 5567 deletions

View File

@ -835,6 +835,8 @@ endif
OPTIMIZE_JARS_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/optimizejars.py)
CREATE_PRECOMPLETE_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/createprecomplete.py)
EXPAND_LIBS = $(PYTHON) -I$(DEPTH)/config $(topsrcdir)/config/expandlibs.py
EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py
EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py

View File

@ -45,6 +45,10 @@ def generate_precomplete():
for the location to enumerate and to create the precomplete file.
"""
root_path = os.getcwd()
# If inside a Mac bundle use the root of the bundle for the path.
if os.path.basename(root_path) == "MacOS":
root_path = os.path.abspath(os.path.join(root_path, '../../'))
rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
precomplete_file_path = os.path.join(root_path,"precomplete")
# open in binary mode to prevent OS specific line endings.

View File

@ -29,25 +29,30 @@ function testCancelInPhase4() {
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function(e) {
if (xhr.readyState >= 4) {
xhr.addEventListener("abort", function() {
setTimeout(function() {
// This request was cancelled, so the responseText should be empty string
is(xhr.responseText, "", "Expected empty response to cancelled request");
// Second request - should be found in cache
var xhr2 = new XMLHttpRequest();
xhr2.addEventListener("load", function() {
is(xhr2.responseText, "0", "Received fresh value for second request");
testCancelBeforePhase4();
}, false);
xhr2.open("GET", url, false); // note : synch-request
xhr2.setRequestHeader("X-Request", "1", false);
try { xhr2.send(); }
catch(e) {
is(xhr2.status, "200", "Exception!");
}
}, 0);
}, false);
xhr.abort();
SimpleTest.executeSoon(function() {
// This request was cancelled, so the responseText should be empty string
is(xhr.responseText, "", "Expected empty response to cancelled request");
// Second request - should be found in cache
var xhr2 = new XMLHttpRequest();
xhr2.open("GET", url, false); // note : synch-request
xhr2.setRequestHeader("X-Request", "1", false);
try { xhr2.send(); }
catch(e) {
is(xhr2.status, "200", "Exception!");
}
is(xhr2.responseText, "0", "Received fresh value for second request");
testCancelBeforePhase4();
});
}
}, false);
@ -69,25 +74,30 @@ function testCancelBeforePhase4() {
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function(e) {
if (xhr.readyState == 3) {
xhr.addEventListener("abort", function() {
setTimeout(function() {
// This request was cancelled, so the responseText should be empty string
is(xhr.responseText, "", "Expected empty response to cancelled request");
// Second request - should be found in cache
var xhr2 = new XMLHttpRequest();
xhr2.addEventListener("load", function() {
is(xhr2.responseText, "1", "Received cached value for second request");
SimpleTest.finish();
}, false);
xhr2.open("GET", url, false); // note : synch-request
xhr2.setRequestHeader("X-Request", "1", false);
try { xhr2.send(); }
catch(e) {
is(xhr2.status, "200", "Exception!");
}
}, 0);
}, false);
xhr.abort();
SimpleTest.executeSoon(function() {
// This request was cancelled, so the responseText should be empty string
is(xhr.responseText, "", "Expected empty response to cancelled request");
// Second request - should be found in cache
var xhr2 = new XMLHttpRequest();
xhr2.open("GET", url, false); // note : synch-request
xhr2.setRequestHeader("X-Request", "1", false);
try { xhr2.send(); }
catch(e) {
is(xhr2.status, "200", "Exception!");
}
is(xhr2.responseText, "1", "Received cached value for second request");
SimpleTest.finish();
});
}
}, false);

View File

@ -80,7 +80,7 @@ DIRS += \
base \
src \
locales \
plugins \
plugins/ipc \
indexedDB \
system \
ipc \

View File

@ -35,7 +35,7 @@
#
# ***** END LICENSE BLOCK *****
DEPTH = ../..
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@

View File

@ -157,7 +157,7 @@ public class GeckoInputConnection
GeckoAppShell.sendEventToGecko(
new GeckoEvent(GeckoEvent.IME_COMPOSITION_END, 0, 0));
mComposing = false;
mComposingText = null;
mComposingText = "";
// Make sure caret stays at the same position
GeckoAppShell.sendEventToGecko(
@ -532,7 +532,7 @@ public class GeckoInputConnection
public void reset() {
mComposing = false;
mComposingText = null;
mComposingText = "";
mUpdateRequest = null;
}
@ -578,7 +578,7 @@ public class GeckoInputConnection
// Is a composition active?
boolean mComposing;
// Composition text when a composition is active
String mComposingText;
String mComposingText = "";
// Start index of the composition within the text body
int mCompositionStart;
/* During a composition, we should not alter the real selection,

View File

@ -55,7 +55,7 @@ EXPORT_LIBRARY = 1
##
IPDLDIRS = \
uriloader/exthandler \
dom/plugins \
dom/plugins/ipc \
dom/ipc \
dom/src/storage \
gfx/layers/ipc \

View File

@ -670,7 +670,7 @@ ProcessFile(JSContext *cx,
}
bufp += strlen(bufp);
lineno++;
} while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
} while (!JS_BufferIsCompilableUnit(cx, JS_FALSE, obj, buffer, strlen(buffer)));
/* Clear any pending exception from previous failed compiles. */
JS_ClearPendingException(cx);

View File

@ -1,227 +0,0 @@
#! /usr/local/bin/perl5
use File::Path;
# The development branch is where primary development and checkins
# are done on a day-to-day basis.
$development_branch_prefix = "SpiderMonkey140";
# Space-separated list of CVS-controlled directories to tag/merge
$merge_dirs =
"mozilla/js/src " ;
# When line below uncommented, don't recurse into subdirs
#$recurse_flag = '-l';
#----------------------------------------------------------------------------
# The merge branch is itself a branch off of the development branch
# at a point where the development branch is thought to be stable.
# (A branch is used rather than a static tag because, inevitably,
# the development branch is not quite as stable/buildable as was
# thought.) The contents of the merge branch will be copied to
# the trunk when merging takes place.
# The following tags are created automatically by this script:
#
# JS_STABLE_DROP
#
# A static tag on the development branch (or a branch off the
# development branch) that indicates the code that should be merged
# into the trunk. This is a "variable" tag in the sense that it is
# redefined after each merge.
#
# JS_LAST_STABLE_DROP
#
# A static tag that is a copy of what the JS_STABLE_DROP tag was in
# the previous merge cycle. This is a "variable" tag that is
# redefined after each merge. Changes in the branch can be merged
# to the trunk by using:
#
# cvs up -jJS_LAST_STABLE_DROP -jJS_STABLE_DROP
#
# JS_LANDING
#
# A static tag that identifies the code on the trunk after the merge
# from the branch to the trunk takes place. This is a "variable"
# tag that is redefined after each merge. Changes on the trunk
# since the last branch landing can be seen by using:
#
# cvs diff -rJS_LANDING -rHEAD
#
# JS_LANDING_mmddyyyy
#
# This is a tag on the trunk which may be used for archaeological
# purposes. This tag is made from the JS_LANDING tag.
$development_branch = $development_branch_prefix . "_BRANCH";
$development_base = $development_branch_prefix . "_BASE";
sub help {
print <<"END";
$0: A tool for merging stable snapshots of JavaScript from a CVS
development branch onto the trunk
Landing a snapshot of the development branch consists of
the following steps:
1) Tag all/some files on the branch to identify files to be merged.
2) Merge files from the branch into the trunk using a temporary
working directory.
3) Resolve any conflicts that arise as a result of the merge.
4) Commit merged changes to the trunk.
5) Make changes to resolve (build) difficulties and re-commit.
Repeat as necessary.
6) Backpropagate changes on the trunk to the development branch.
This script will assist with steps #2, #4 and #6:
$0 -merge JS_STABLE_10131998
$0 -commit
$0 -backpatch
END
}
sub log {
local($msg) = @_;
print LOGFILE $msg if $logfile;
}
# Similar to die built-in
sub die {
local($msg) = @_;
&log($msg);
chomp($msg);
if ($logfile) {
$msg .= "\nSee $logfile for details.";
}
die "$msg\n";
}
# Similar to system() built-in
sub system {
local(@args) = @_;
local($cmd) = join(" ", @args);
&log("Executing: $cmd\n");
if ($logfile) {
$cmd .= " >> $logfile 2>&1";
close(LOGFILE);
}
local($result) = 0xffff & system($cmd);
if ($logfile) {
open(LOGFILE, ">>$logfile");
}
return unless ($result);
$msg = "Died while executing $cmd";
if ($result == 0xff00) {
&die("$msg\nWhile executExecution failed due to perl error: $!. ");
} else {
$result >>= 8;
&die("$msg\nExecution failed; exit status: $result. ");
}
}
chomp($root_dir = `pwd`);
# Default log file
$logfile = $root_dir . "/log";
while ($#ARGV >=0) {
$_ = shift;
if (/-merge/) {
$do_tag = 1;
$do_checkout = 1;
$do_merge = 1;
$tag = shift;
} elsif (/-commit/ || /-ci/) {
$do_commit = 1;
} elsif (/-backpatch/) {
$do_backpatch = 1;
} elsif (/-log/) {
$logfile = shift;
} elsif (/-tag/) { # Debugging option
$do_tag = 1;
$tag = shift;
} elsif (/-co/) { # Debugging option
$do_checkout = 1;
} else {
print STDERR "Illegal option: $_\n" unless (/-h/);
&help();
exit(1);
}
}
die "You must set your CVSROOT environment variable" if !$ENV{"CVSROOT"};
if ($logfile) {
open(LOGFILE, ">$logfile") || die "Couldn't open log file \"$logfile\"";
print("Logging to file \"$logfile\".\n");
}
$trunk_dir = $root_dir . "/trunk";
if ($do_tag) {
if (!$tag) {
&die("Must specify tag on command-line\n");
}
print("Tagging tree with tag JS_STABLE_DROP.\n");
&system("cvs rtag $recurse_flag -F -r $tag JS_STABLE_DROP $merge_dirs");
}
if ($do_checkout) {
# Delete trunk subdir if it already exists
if (-d $trunk_dir) {
&log("Deleting directory $trunk_dir\n");
rmtree ($trunk_dir, 0, 1);
}
&log("Creating directory $trunk_dir\n");
mkdir($trunk_dir, 0777) || die "Couldn't create directory $trunk_dir";
# Check out on trunk
print("Checking out $merge_dirs.\n");
chdir $trunk_dir;
&system("cvs co $recurse_flag -A $merge_dirs");
}
if ($do_merge) {
chdir $trunk_dir;
print("Merging from JS_STABLE_DROP into trunk\n");
&system("cvs up -jJS_LAST_STABLE_DROP -jJS_STABLE_DROP");
}
if ($do_commit) {
&die("No merged tree found. Wrong directory ?") if (!chdir $trunk_dir);
($_,$_,$_,$day,$mon,$year,$_,$_) = localtime(time());
if ($year < 30) {
$year = "20" . $year;
} else {
$year = "19" . $year;
}
$mmddyyyy = sprintf("%02d%02d%s", $mon, $day, $year);
print("Checking in code on trunk");
&system("cvs ci -m 'Stable drop of JavaScript interpreter code from " .
"$development_branch'");
# Tag merged result
&system("cvs tag -F JS_LANDING");
&system("cvs tag -F JS_LANDING_$mmddyyyy");
# Move JS_LAST_STABLE_DROP tag forward
&system("cvs tag -F -rJS_STABLE_DROP JS_LAST_STABLE_DROP");
}

View File

@ -125,6 +125,7 @@ DIST_INSTALL = 1
VPATH = $(srcdir)
CPPSRCS = \
jsalloc.cpp \
jsanalyze.cpp \
jsapi.cpp \
jsarena.cpp \
@ -173,6 +174,7 @@ CPPSRCS = \
jsstr.cpp \
jstypedarray.cpp \
jsutil.cpp \
jsweakmap.cpp \
jswrapper.cpp \
jsxdrapi.cpp \
jsxml.cpp \
@ -185,6 +187,7 @@ INSTALLED_HEADERS = \
jsautocfg.h \
$(CURDIR)/jsautokw.h \
js.msg \
jsalloc.h \
jsanalyze.h \
jsapi.h \
jsarray.h \
@ -252,6 +255,7 @@ INSTALLED_HEADERS = \
jstl.h \
jshashtable.h \
jsversion.h \
jsweakmap.h \
jswrapper.h \
jsxdrapi.h \
jsxml.h \
@ -611,7 +615,7 @@ endif
# (it can't be done with %-expansion, because the files we want to skip aren't
# in the vpath).
ALL_FILES=$(shell find $(srcdir) \( -name "*.cpp" -o -name "*.h" \) -not -path "*/dist/*")
check-malloc-function-usage: $(filter-out %jsutil.h %jscntxt.h, $(ALL_FILES))
check-malloc-function-usage: $(filter-out %jsalloc.h %jscntxt.h %jsutil.h, $(ALL_FILES))
# js_malloc and friends are only used by other memory managers, and should
# never be used elsewhere directly.
@ -626,10 +630,10 @@ check-malloc-function-usage: $(filter-out %jsutil.h %jscntxt.h, $(ALL_FILES))
# We desire these numbers to go down, not up. See "User guide to memory
# management within SpiderMonkey" in jsutil.h.
$(srcdir)/config/check_source_count.py OffTheBooks:: 54 \
$(srcdir)/config/check_source_count.py OffTheBooks:: 53 \
"in Makefile.in" "{cx,rt}->{new_,new_array,malloc_,calloc_,realloc_}" $^
# This should go to zero, if possible.
$(srcdir)/config/check_source_count.py UnwantedForeground:: 35 \
$(srcdir)/config/check_source_count.py UnwantedForeground:: 34 \
"in Makefile.in" "{cx,rt}->{free_,delete_,array_delete}" $^
ifneq ($(OS_ARCH),WINNT) # FIXME: this should be made work on Windows too.

View File

@ -1,468 +0,0 @@
# -*- Mode: makefile -*-
# vim: ft=make
#
# ***** 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 Communicator client code, released
# March 31, 1998.
#
# 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):
# Michael Ang <mang@subcarrier.org>
# Kevin Buhr <buhr@stat.wisc.edu>
#
# 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 *****
#
# JSRef GNUmake makefile.
#
# Note: dependency rules are missing for some files (some
# .h, all .msg, etc.) Re-make clean if in doubt.
#
DEPTH = .
include config.mk
#NS_USE_NATIVE = 1
ifndef NANOJIT_ARCH
$(warning NANOJIT_ARCH not defined in config/$(OS_CONFIG).mk, JIT disabled)
else
ifdef DISABLE_JIT
$(warning disabling JIT per build specification)
else
ENABLE_JIT=1
endif
endif
ifdef ENABLE_JIT
DEFINES += -DJS_TRACER
DEFINES += -DFEATURE_NANOJIT
INCLUDES += -Inanojit
endif
#ifndef BUILD_OPT
#DEFINES += -Ivprof
#endif
# Look in OBJDIR to find jsautocfg.h, jsautokw.h, and js-config.h
INCLUDES += -I. -I$(OBJDIR)
ifdef JS_THREADSAFE
DEFINES += -DJS_THREADSAFE
INCLUDES += -I$(DIST)/include/nspr
ifdef USE_MSVC
OTHER_LIBS += $(DIST)/lib/libnspr$(NSPR_LIBSUFFIX).lib
else
OTHER_LIBS += -L$(DIST)/lib -lnspr$(NSPR_LIBSUFFIX)
endif
endif
ifdef JS_HAS_CTYPES
DEFINES += -DJS_HAS_CTYPES
INCLUDES += -I$(DIST)/include/nspr
ifdef USE_MSVC
OTHER_LIBS += $(DIST)/lib/libnspr$(NSPR_LIBSUFFIX).lib
else
OTHER_LIBS += -L$(DIST)/lib -lnspr$(NSPR_LIBSUFFIX)
endif
endif
ifdef JS_NO_THIN_LOCKS
DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
endif
ifdef JS_GC_ZEAL
DEFINES += -DJS_GC_ZEAL
endif
#
# XCFLAGS may be set in the environment or on the gmake command line
#
#CFLAGS += -DDEBUG -DDEBUG_brendan -DJS_ARENAMETER -DJS_HASHMETER -DJS_DUMP_PROPTREE_STATS -DJS_DUMP_SCOPE_METERS -DJS_SCOPE_DEPTH_METER -DJS_BASIC_STATS
CFLAGS += $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS)
LDFLAGS = $(XLDFLAGS)
LDFLAGS += $(OS_LDFLAGS)
ifdef MOZ_SHARK
DEFINES += -DMOZ_SHARK
CFLAGS += -F/System/Library/PrivateFrameworks
LDFLAGS += -F/System/Library/PrivateFrameworks -framework CHUD
endif
ifdef MOZ_CALLGRIND
DEFINES += -DMOZ_CALLGRIND
endif
ifdef MOZ_VTUNE
DEFINES += -DMOZ_VTUNE
CXXFLAGS += -IC:/Program\ Files/Intel/VTune/Analyzer/Include
OTHER_LIBS += C:/Program\ Files/Intel/VTune/Analyzer/Lib/VtuneApi.lib
endif
ifndef NO_LIBM
LDFLAGS += -lm
endif
# Prevent floating point errors caused by VC++ optimizations
ifeq ($(OS_ARCH),WINNT)
_MSC_VER = $(shell $(CXX) 2>&1 | sed -n 's/.*Compiler Version \([0-9]*\)\.\([0-9]*\).*/\1\2/p')
ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
CFLAGS += -Op
else
CFLAGS += -fp:precise
endif
endif # WINNT
#
# Server-related changes :
#
ifdef NES40
DEFINES += -DNES40
endif
#
# Line editing support.
# Define JS_READLINE or JS_EDITLINE to enable line editing in the
# js command-line interpreter.
#
ifdef JS_READLINE
# For those platforms with the readline library installed.
DEFINES += -DEDITLINE
PROG_LIBS += -lreadline -ltermcap
else
ifdef JS_EDITLINE
# Use the editline library, built locally.
PREDIRS += editline
DEFINES += -DEDITLINE
PROG_LIBS += $(OBJDIR)/editline/libedit.a
endif
endif
# For purify
PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \
$(INCLUDES) $(XCFLAGS)
#
# JS file lists
#
JS_HFILES = \
jsarray.h \
jsatom.h \
jsbool.h \
jscntxt.h \
jsdate.h \
jsemit.h \
jsexn.h \
jsfun.h \
jsgc.h \
jsinterp.h \
jsiter.h \
jslibmath.h \
jslock.h \
jsmath.h \
jsnum.h \
jsobj.h \
json.h \
jsopcode.h \
jsparse.h \
jsarena.h \
jsclist.h \
jsdhash.h \
jsdtoa.h \
jshash.h \
jslong.h \
jstypes.h \
jsprvtd.h \
jspubtd.h \
jsregexp.h \
jsscan.h \
jsscope.h \
jsscript.h \
jsstr.h \
jsversion.h \
jsxdrapi.h \
jsxml.h \
$(NULL)
ifdef ENABLE_JIT
JS_HFILES += \
jstracer.h \
nanojit/Assembler.h \
nanojit/LIR.h \
nanojit/Native$(NANOJIT_ARCH).h \
nanojit/avmplus.h \
nanojit/vm_fops.h \
nanojit/Fragmento.h \
nanojit/Native.h \
nanojit/RegAlloc.h \
nanojit/nanojit.h \
$(NULL)
endif
ifndef BUILD_OPT
#JS_HFILES += \
# vprof/vprof.h \
# $(NULL)
endif
API_HFILES = \
jsapi.h \
jsdbgapi.h \
$(NULL)
OTHER_HFILES = \
jsbit.h \
jscompat.h \
jscpucfg.h \
jsotypes.h \
prmjtime.h \
resource.h \
jsopcode.tbl \
jsproto.tbl \
js.msg \
jsshell.msg \
jskeyword.tbl \
$(NULL)
ifndef PREBUILT_CPUCFG
OTHER_HFILES += $(OBJDIR)/jsautocfg.h
endif
OTHER_HFILES += $(OBJDIR)/jsautokw.h $(OBJDIR)/js-config.h
HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES)
JS_CPPFILES = \
jsapi.cpp \
jsarena.cpp \
jsarray.cpp \
jsatom.cpp \
jsbool.cpp \
jscntxt.cpp \
jsdate.cpp \
jsdbgapi.cpp \
jsdhash.cpp \
jsdtoa.cpp \
jsemit.cpp \
jsexn.cpp \
jsfun.cpp \
jsgc.cpp \
jshash.cpp \
jsinterp.cpp \
jsinvoke.cpp \
jsiter.cpp \
jslock.cpp \
jslog2.cpp \
jslong.cpp \
jsmath.cpp \
jsnum.cpp \
jsobj.cpp \
json.cpp \
jsopcode.cpp \
jsparse.cpp \
jsprf.cpp \
jsregexp.cpp \
jsscan.cpp \
jsscope.cpp \
jsscript.cpp \
jsstr.cpp \
jsutil.cpp \
jsxdrapi.cpp \
jsxml.cpp \
prmjtime.cpp \
$(NULL)
ifdef ENABLE_JIT
JS_CPPFILES += \
jsbuiltins.cpp \
jstracer.cpp \
nanojit/Assembler.cpp \
nanojit/Fragmento.cpp \
nanojit/LIR.cpp \
nanojit/Native$(NANOJIT_ARCH).cpp \
nanojit/RegAlloc.cpp \
nanojit/avmplus.cpp \
$(NULL)
endif
ifndef BUILD_OPT
#JS_CPPFILES += \
# vprof/vprof.cpp \
# $(NULL)
endif
LIB_CPPFILES = $(JS_CPPFILES)
LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
PROG_CPPFILES = js.cpp
ifdef USE_MSVC
LIBRARY = $(OBJDIR)/js32.lib
SHARED_LIBRARY = $(OBJDIR)/js32.dll
PROGRAM = $(OBJDIR)/js.exe
else
LIBRARY = $(OBJDIR)/libjs.a
SHARED_LIBRARY = $(OBJDIR)/libjs.$(SO_SUFFIX)
PROGRAM = $(OBJDIR)/js
endif
include rules.mk
MOZ_DEPTH = ../..
include jsconfig.mk
nsinstall-target:
cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR)
#
# Automatic header generation
#
AUTO_HEADERS = \
$(OBJDIR)/jsautokw.h \
$(OBJDIR)/jsautooplen.h \
$(NULL)
$(OBJDIR)/jsautokw.h: jskeyword.tbl
$(OBJDIR)/jsautooplen.h: jsopcode.tbl
GARBAGE += $(AUTO_HEADERS)
GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX))
ifdef USE_MSVC
GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj)
$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
@$(MAKE_OBJDIR)
$(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(OPTIMIZER) $<
link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj
$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
else
GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.d)
$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
@$(MAKE_OBJDIR)
$(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(OPTIMIZER) $(LDFLAGS) $<
$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
endif
# force creation of autoheaders before compiling any source that may use them
$(LIB_OBJS) : $(AUTO_HEADERS)
#
# An installed header file describing configuration options that affect
# the API.
#
# Avoid rebuilding unless js-config.h's contents actually change. The
# timestamp on js-config.h.stamp corresponds to the last time we
# checked that js-config.h was up to date. If the stamp changes but
# js-config.h does not, then make concludes that targets depending on
# js-config.h don't need to be rebuilt. The dummy '@true' rule here
# keeps make from concluding that js-config.h never changes.
$(OBJDIR)/js-config.h: $(OBJDIR)/js-config.h.stamp
@true
js-config-switch=$(if $(value $($1)),-e 's/\#undef $1/\#define $1/')
$(OBJDIR)/js-config.h.stamp: js-config.h.in Makefile.ref
sed < $< > $(@:.stamp=.tmp) \
$(call js-config-switch,JS_THREADSAFE) \
$(call js-config-switch,JS_HAS_CTYPES) \
$(call js-config-switch,JS_GC_ZEAL) \
-e :dummy
if ! [ -f $(@:.stamp=) ] || ! cmp $(@:.stamp=.tmp) $(@:.stamp=); then \
mv $(@:.stamp=.tmp) $(@:.stamp=); \
fi
touch $@
GARBAGE += $(OBJDIR)/js-config.h $(OBJDIR)/js-config.h.stamp
# Force creation of js-config.h before compiling any source that may use it.
$(LIB_OBJS) : $(OBJDIR)/js-config.h
#
# JS shell executable
#
ifdef USE_MSVC
$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
else
$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
$(CXX) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS) \
$(PROG_LIBS)
endif
$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY)
purify $(PUREFLAGS) \
$(CXX) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) \
$(OTHER_LIBS) $(PROG_LIBS)
ifndef PREBUILT_CPUCFG
$(filter-out jscpucfg.h $(OBJDIR)/jsautocfg.h, $(HFILES)) $(CPPFILES): $(OBJDIR)/jsautocfg.h
$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
rm -f $@
$(OBJDIR)/jscpucfg > $@
$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
$(CXX) $(OS_LDFLAGS) -o $@ $(OBJDIR)/jscpucfg.o
GARBAGE += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \
$(OBJDIR)/jscpucfg.o $(OBJDIR)/jscpucfg.d
endif
# Automatic make dependencies files
DEPENDENCIES = $(CPPFILES:%.cpp=$(OBJDIR)/%.d)
#
# Hardwire dependencies for some files
#
ifdef USE_MSVC
OBJ=obj
else
OBJ=o
endif
$(OBJDIR)/jsinvoke.$(OBJ): jsinterp.h jsinterp.cpp
$(OBJDIR)/jsinvoke.obj : jsinterp.h jsinterp.cpp
-include $(DEPENDENCIES)
TARNAME = jsref.tar
TARFILES = files `cat files`
SUFFIXES: .i
%.i: %.cpp
$(CXX) -C -E $(CFLAGS) $< > $*.i

View File

@ -1,186 +0,0 @@
# -*- Mode: makefile -*-
#
# ***** 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 Communicator client code, released
# March 31, 1998.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-1999
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# 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 *****
ifdef JS_DIST
DIST = $(JS_DIST)
else
DIST = $(DEPTH)/../../dist
endif
# Set os+release dependent make variables
OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/))
# Attempt to differentiate between SunOS 5.4 and x86 5.4
OS_CPUARCH := $(shell uname -m)
ifeq ($(OS_CPUARCH),i86pc)
OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH)
else
ifeq ($(OS_ARCH),AIX)
OS_RELEASE := $(shell uname -v).$(shell uname -r)
else
OS_RELEASE := $(shell uname -r)
endif
endif
ifeq ($(OS_ARCH),IRIX64)
OS_ARCH := IRIX
endif
# Handle output from win32 unames other than Netscape's version
ifeq (,$(filter-out Windows_95 Windows_98, $(OS_ARCH)))
OS_ARCH := WIN95
endif
ifeq ($(OS_ARCH),WIN95)
OS_ARCH := WINNT
OS_RELEASE := 4.0
endif
ifeq ($(OS_ARCH), Windows_NT)
OS_ARCH := WINNT
OS_MINOR_RELEASE := $(shell uname -v)
ifeq ($(OS_MINOR_RELEASE),00)
OS_MINOR_RELEASE = 0
endif
OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE)
endif
ifeq (MINGW32_NT,$(findstring MINGW32_NT,$(OS_ARCH)))
OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH))
OS_ARCH := WINNT
endif
# Virtually all Linux versions are identical.
# Any distinctions are handled in linux.h
ifeq ($(OS_ARCH),Linux)
OS_CONFIG := Linux_All
else
ifeq ($(OS_ARCH),dgux)
OS_CONFIG := dgux
else
ifeq ($(OS_ARCH),Darwin)
OS_CONFIG := Darwin
else
ifeq ($(OS_ARCH),Darwin64)
OS_CONFIG := Darwin64
else
OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE)
endif
endif
endif
endif
ASFLAGS =
DEFINES =
ifeq ($(OS_ARCH), WINNT)
INSTALL = nsinstall
CP = cp
else
INSTALL = $(DIST)/bin/nsinstall
CP = cp
endif
ifdef BUILD_OPT
ifdef USE_MSVC
OPTIMIZER = -O2 -GL
INTERP_OPTIMIZER = -O2 -GL
BUILTINS_OPTIMIZER = -O2 -GL
LDFLAGS += -LTCG
else
OPTIMIZER = -Os -fno-exceptions -fno-rtti -fstrict-aliasing -Wstrict-aliasing=3
BUILTINS_OPTIMIZER = -O9 -fno-exceptions -fno-rtti -fstrict-aliasing
INTERP_OPTIMIZER = -O3 -fno-exceptions -fno-rtti -fstrict-aliasing
endif
DEFINES += -UDEBUG -DNDEBUG -UDEBUG_$(USER)
OBJDIR_TAG = _OPT
else
ifdef USE_MSVC
OPTIMIZER = -Zi
INTERP_OPTIMIZER = -Zi
BUILTINS_OPTIMIZER = $(INTERP_OPTIMIZER)
else
OPTIMIZER = -g3 -fstrict-aliasing -fno-exceptions -fno-rtti -Wstrict-aliasing=3
INTERP_OPTIMIZER = -g3 -fstrict-aliasing -fno-exceptions -fno-rtti
BUILTINS_OPTIMIZER = $(INTERP_OPTIMIZER)
endif
DEFINES += -DDEBUG -DDEBUG_$(USER)
OBJDIR_TAG = _DBG
endif
SO_SUFFIX = so
NS_USE_NATIVE = 1
include $(DEPTH)/ref-config/$(OS_CONFIG).mk
ifndef OBJ_SUFFIX
ifdef USE_MSVC
OBJ_SUFFIX = obj
else
OBJ_SUFFIX = o
endif
endif
ifndef HOST_BIN_SUFFIX
ifeq ($(OS_ARCH),WINNT)
HOST_BIN_SUFFIX = .exe
else
HOST_BIN_SUFFIX =
endif
endif
# Name of the binary code directories
ifdef OBJROOT
# prepend $(DEPTH) to the root unless it is an absolute path
OBJDIR = $(if $(filter /%,$(OBJROOT)),$(OBJROOT),$(DEPTH)/$(OBJROOT))
else
ifeq ($(DEPTH),.)
OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).$(if $(BUILD_IDG),OBJD,OBJ)
else
OBJDIR = $(DEPTH)/$(OS_CONFIG)$(OBJDIR_TAG).$(if $(BUILD_IDG),OBJD,OBJ)
endif
endif
VPATH = $(OBJDIR)
LCJAR = js15lc30.jar
# Library name
LIBDIR := lib
ifeq ($(CPU_ARCH), x86_64)
LIBDIR := lib64
endif

View File

@ -835,6 +835,8 @@ endif
OPTIMIZE_JARS_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/optimizejars.py)
CREATE_PRECOMPLETE_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/createprecomplete.py)
EXPAND_LIBS = $(PYTHON) -I$(DEPTH)/config $(topsrcdir)/config/expandlibs.py
EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py
EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py

56
js/src/jsalloc.cpp Normal file
View File

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* July 16, 2009.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "jsalloc.h"
#include "jscntxt.h"
namespace js {
void *
ContextAllocPolicy::onOutOfMemory(void *p, size_t nbytes)
{
return cx->runtime->onOutOfMemory(p, nbytes, cx);
}
void
ContextAllocPolicy::reportAllocOverflow() const
{
js_ReportAllocationOverflow(cx);
}
} /* namespace js */

119
js/src/jsalloc.h Normal file
View File

@ -0,0 +1,119 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* July 16, 2009.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
*
* 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 jsalloc_h_
#define jsalloc_h_
#include "jspubtd.h"
#include "jsutil.h"
#include "jsstaticcheck.h"
namespace js {
/*
* Allocation policies. These model the concept:
* - public copy constructor, assignment, destructor
* - void *malloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void *realloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void free_(void *)
* - reportAllocOverflow()
* Called on overflow before the container returns NULL.
*/
/* Policy for using system memory functions and doing no error reporting. */
class SystemAllocPolicy
{
public:
void *malloc_(size_t bytes) { return js_malloc(bytes); }
void *realloc_(void *p, size_t bytes) { return js_realloc(p, bytes); }
void free_(void *p) { js_free(p); }
void reportAllocOverflow() const {}
};
/*
* Allocation policy that calls the system memory functions and reports errors
* to the context. Since the JSContext given on construction is stored for
* the lifetime of the container, this policy may only be used for containers
* whose lifetime is a shorter than the given JSContext.
*
* FIXME bug 647103 - rewrite this in terms of temporary allocation functions,
* not the system ones.
*/
class ContextAllocPolicy
{
JSContext *const cx;
/*
* Non-inline helper to call JSRuntime::onOutOfMemory with minimal
* code bloat.
*/
JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes);
public:
ContextAllocPolicy(JSContext *cx) : cx(cx) {}
JSContext *context() const {
return cx;
}
void *malloc_(size_t bytes) {
void *p = js_malloc(bytes);
if (JS_UNLIKELY(!p))
p = onOutOfMemory(NULL, bytes);
return p;
}
void *realloc_(void *p, size_t bytes) {
void *p2 = js_realloc(p, bytes);
if (JS_UNLIKELY(!p2))
p2 = onOutOfMemory(p2, bytes);
return p2;
}
void free_(void *p) {
js_free(p);
}
JS_FRIEND_API(void) reportAllocOverflow() const;
};
} /* namespace js */
#endif /* jsalloc_h_ */

View File

@ -84,6 +84,7 @@
#include "prmjtime.h"
#include "jsstaticcheck.h"
#include "jsvector.h"
#include "jsweakmap.h"
#include "jswrapper.h"
#include "jstypedarray.h"
@ -1174,7 +1175,7 @@ JS_ToggleOptions(JSContext *cx, uint32 options)
JS_PUBLIC_API(const char *)
JS_GetImplementationVersion(void)
{
return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
return "JavaScript-C 1.8.5+ 2011-04-16";
}
JS_PUBLIC_API(JSCompartmentCallback)
@ -1676,6 +1677,7 @@ static JSStdName standard_class_atoms[] = {
#endif
{js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass},
{js_InitWeakMapClass, EAGER_CLASS_ATOM(WeakMap), &WeakMap::jsclass},
{NULL, 0, NULL, NULL}
};
@ -2057,7 +2059,10 @@ JS_PUBLIC_API(jsval)
JS_ComputeThis(JSContext *cx, jsval *vp)
{
assertSameCompartment(cx, JSValueArray(vp, 2));
return BoxThisForVp(cx, Valueify(vp)) ? vp[1] : JSVAL_NULL;
CallReceiver call = CallReceiverFromVp(Valueify(vp));
if (!BoxNonStrictThis(cx, call))
return JSVAL_NULL;
return Jsvalify(call.thisv());
}
JS_PUBLIC_API(void *)
@ -3987,7 +3992,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj)
AutoIdVector props(cx);
JSIdArray *ida;
if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
return false;
return NULL;
for (size_t n = 0; n < size_t(ida->length); ++n)
JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
return ida;
@ -4163,7 +4168,7 @@ JS_IsArrayObject(JSContext *cx, JSObject *obj)
{
assertSameCompartment(cx, obj);
return obj->isArray() ||
(obj->isWrapper() && JSWrapper::wrappedObject(obj)->isArray());
(obj->isWrapper() && obj->unwrap()->isArray());
}
JS_PUBLIC_API(JSBool)
@ -4613,7 +4618,7 @@ JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length,
}
JS_PUBLIC_API(JSBool)
JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *bytes, size_t length)
JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *obj, const char *bytes, size_t length)
{
jschar *chars;
JSBool result;
@ -4622,7 +4627,10 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *bytes, size_
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
chars = js_InflateString(cx, bytes, &length);
if (bytes_are_utf8)
chars = js_InflateString(cx, bytes, &length, JS_TRUE);
else
chars = js_InflateString(cx, bytes, &length);
if (!chars)
return JS_TRUE;
@ -5003,7 +5011,7 @@ JS_ExecuteScript(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval)
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, scriptObj);
JSBool ok = Execute(cx, obj, scriptObj->getScript(), NULL, 0, Valueify(rval));
JSBool ok = Execute(cx, *obj, scriptObj->getScript(), NULL, 0, Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
return ok;
}
@ -5036,7 +5044,7 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
return false;
}
JS_ASSERT(script->getVersion() == compileVersion);
bool ok = Execute(cx, obj, script, NULL, 0, Valueify(rval));
bool ok = Execute(cx, *obj, script, NULL, 0, Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
js_DestroyScript(cx, script);
return ok;
@ -5185,7 +5193,7 @@ JS_New(JSContext *cx, JSObject *ctor, uintN argc, jsval *argv)
if (!cx->stack().pushInvokeArgs(cx, argc, &args))
return NULL;
args.callee().setObject(*ctor);
args.calleev().setObject(*ctor);
args.thisv().setNull();
memcpy(args.argv(), argv, argc * sizeof(jsval));
@ -5534,6 +5542,13 @@ JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_
return js_InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
}
JS_PUBLIC_API(JSBool)
JS_DecodeUTF8(JSContext *cx, const char *src, size_t srclen, jschar *dst,
size_t *dstlenp)
{
return js_InflateUTF8StringToBuffer(cx, src, srclen, dst, dstlenp);
}
JS_PUBLIC_API(char *)
JS_EncodeString(JSContext *cx, JSString *str)
{
@ -5600,28 +5615,6 @@ JS_TryJSON(JSContext *cx, jsval *vp)
return js_TryJSON(cx, Valueify(vp));
}
JS_PUBLIC_API(JSONParser *)
JS_BeginJSONParse(JSContext *cx, jsval *vp)
{
CHECK_REQUEST(cx);
return js_BeginJSONParse(cx, Valueify(vp));
}
JS_PUBLIC_API(JSBool)
JS_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len)
{
CHECK_REQUEST(cx);
return js_ConsumeJSONText(cx, jp, data, len);
}
JS_PUBLIC_API(JSBool)
JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver)
{
CHECK_REQUEST(cx);
assertSameCompartment(cx, reviver);
return js_FinishJSONParse(cx, jp, Valueify(reviver));
}
JS_PUBLIC_API(JSBool)
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32 len, jsval *vp)
{

View File

@ -1404,6 +1404,7 @@ class Anchor: AnchorPermitted<T> {
explicit Anchor(T t) { hold = t; }
inline ~Anchor();
T &get() { return hold; }
const T &get() const { return hold; }
void set(const T &t) { hold = t; }
void clear() { hold = 0; }
private:
@ -1947,6 +1948,7 @@ struct JSClass {
#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */
#define JSCLASS_CONCURRENT_FINALIZER (1<<4) /* finalize is called on background thread */
#define JSCLASS_NEW_RESOLVE_GETS_START (1<<5) /* JSNewResolveOp gets starting
object in prototype chain
passed in via *objp in/out
@ -2660,8 +2662,8 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
* the compiler.
*/
extern JS_PUBLIC_API(JSBool)
JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
const char *bytes, size_t length);
JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8,
JSObject *obj, const char *bytes, size_t length);
extern JS_PUBLIC_API(JSObject *)
JS_CompileScript(JSContext *cx, JSObject *obj,
@ -3182,6 +3184,8 @@ JS_SetCStringsAreUTF8(void);
* UTF-8, and JS_DecodeBytes decodes from UTF-8, which may create additional
* errors if the character sequence is malformed. If UTF-8 support is
* disabled, the functions deflate and inflate, respectively.
*
* JS_DecodeUTF8() always behaves the same independently of JS_CStringsAreUTF8().
*/
JS_PUBLIC_API(JSBool)
JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
@ -3191,6 +3195,10 @@ JS_PUBLIC_API(JSBool)
JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
size_t *dstlenp);
JS_PUBLIC_API(JSBool)
JS_DecodeUTF8(JSContext *cx, const char *src, size_t srclen, jschar *dst,
size_t *dstlenp);
/*
* A variation on JS_EncodeCharacters where a null terminated string is
* returned that you are expected to call JS_free on when done.
@ -3285,7 +3293,7 @@ class JSAutoByteString {
typedef JSBool (* JSONWriteCallback)(const jschar *buf, uint32 len, void *data);
/*
* JSON.stringify as specified by ES3.1 (draft)
* JSON.stringify as specified by ES5.
*/
JS_PUBLIC_API(JSBool)
JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
@ -3298,17 +3306,8 @@ JS_PUBLIC_API(JSBool)
JS_TryJSON(JSContext *cx, jsval *vp);
/*
* JSON.parse as specified by ES3.1 (draft)
* JSON.parse as specified by ES5.
*/
JS_PUBLIC_API(JSONParser *)
JS_BeginJSONParse(JSContext *cx, jsval *vp);
JS_PUBLIC_API(JSBool)
JS_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len);
JS_PUBLIC_API(JSBool)
JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver);
JS_PUBLIC_API(JSBool)
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32 len, jsval *vp);

View File

@ -44,6 +44,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include "jsalloc.h"
#include "jstypes.h"
#include "jsstdint.h"
#include "jsbit.h"

View File

@ -1413,7 +1413,7 @@ array_toString(JSContext *cx, uintN argc, Value *vp)
if (!cx->stack().pushInvokeArgs(cx, 0, &args))
return false;
args.callee() = join;
args.calleev() = join;
args.thisv().setObject(*obj);
/* Do the call. */
@ -2580,7 +2580,7 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
if (v.isObject()) {
aobj = &v.toObject();
if (aobj->isArray() ||
(aobj->isWrapper() && JSWrapper::wrappedObject(aobj)->isArray())) {
(aobj->isWrapper() && aobj->unwrap()->isArray())) {
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
if (!aobj->getProperty(cx, id, tvr.addr()))
return false;
@ -3026,7 +3026,7 @@ array_isArray(JSContext *cx, uintN argc, Value *vp)
vp->setBoolean(argc > 0 &&
vp[2].isObject() &&
((obj = &vp[2].toObject())->isArray() ||
(obj->isWrapper() && JSWrapper::wrappedObject(obj)->isArray())));
(obj->isWrapper() && obj->unwrap()->isArray())));
return true;
}

View File

@ -211,7 +211,9 @@ const char *const js_common_atom_names[] = {
"has", /* hasAtom */
"hasOwn", /* hasOwnAtom */
"keys", /* keysAtom */
"iterate" /* iterateAtom */
"iterate", /* iterateAtom */
"WeakMap" /* WeakMapAtom */
};
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) ==

View File

@ -422,6 +422,8 @@ struct JSAtomState
JSAtom *keysAtom;
JSAtom *iterateAtom;
JSAtom *WeakMapAtom;
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
struct {
JSAtom *XMLListAtom;

View File

@ -468,7 +468,7 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
JS_ASSERT(obj->isArray() || obj->isObject());
/* Fail if obj is already on the stack. */
HashSet<JSObject *>::AddPtr p = memory.lookupForAdd(obj);
MemorySet::AddPtr p = memory.lookupForAdd(obj);
if (p) {
JSContext *cx = context();
if (callbacks && callbacks->reportError)

View File

@ -179,7 +179,8 @@ struct JSStructuredCloneWriter {
// The "memory" list described in the HTML5 internal structured cloning algorithm.
// memory has the same elements as objs.
js::HashSet<JSObject *> memory;
typedef js::HashSet<JSObject *> MemorySet;
MemorySet memory;
// The user defined callbacks that will be used for cloning.
const JSStructuredCloneCallbacks *callbacks;

View File

@ -108,30 +108,41 @@
using namespace js;
using namespace js::gc;
#ifdef DEBUG
JS_REQUIRES_STACK bool
StackSegment::contains(const JSStackFrame *fp) const
{
JS_ASSERT(inContext());
if (fp < initialFrame)
return false;
JSStackFrame *start;
JSStackFrame *stop;
if (isActive()) {
JS_ASSERT(cx->hasfp());
JS_ASSERT(cx->hasfp() && this == cx->activeSegment());
start = cx->fp();
stop = cx->activeSegment()->initialFrame->prev();
} else {
JS_ASSERT(suspendedRegs && suspendedRegs->fp);
start = suspendedRegs->fp;
stop = initialFrame->prev();
}
for (JSStackFrame *f = start; f != stop; f = f->prev()) {
if (f == fp)
return true;
if (fp > start)
return false;
#ifdef DEBUG
bool found = false;
JSStackFrame *stop = initialFrame->prev();
for (JSStackFrame *f = start; !found && f != stop; f = f->prev()) {
if (f == fp) {
found = true;
break;
}
}
return false;
}
JS_ASSERT(found);
#endif
return true;
}
JSStackFrame *
StackSegment::computeNextFrame(JSStackFrame *fp) const
{
@ -290,8 +301,7 @@ StackSpace::pushSegmentForInvoke(JSContext *cx, uintN argc, InvokeArgsGuard *ag)
ag->cx = cx;
ag->seg = seg;
ag->argv_ = seg->valueRangeBegin() + 2;
ag->argc_ = argc;
ImplicitCast<CallArgs>(*ag) = CallArgsFromVp(argc, seg->valueRangeBegin());
/* Use invokeArgEnd to root [vp, vpend) until the frame is pushed. */
#ifdef DEBUG
@ -1019,6 +1029,9 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
JS_ASSERT(!rt->gcRunning);
JS_UNLOCK_GC(rt);
#ifdef JS_THREADSAFE
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
#endif
if (last) {
#ifdef JS_THREADSAFE
@ -1087,6 +1100,9 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
cx->dstOffsetCache.dumpStats();
#endif
JS_UNLOCK_GC(rt);
#ifdef JS_THREADSAFE
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
#endif
Foreground::delete_(cx);
}
@ -1697,7 +1713,7 @@ js_InvokeOperationCallback(JSContext *cx)
*/
bool delayedOutOfMemory;
JS_LOCK_GC(rt);
delayedOutOfMemory = (rt->gcBytes > rt->gcMaxBytes);
delayedOutOfMemory = rt->gcBytes > rt->gcMaxBytes;
JS_UNLOCK_GC(rt);
if (delayedOutOfMemory) {
js_ReportOutOfMemory(cx);
@ -2021,36 +2037,13 @@ JSContext::generatorFor(JSStackFrame *fp) const
}
StackSegment *
JSContext::containingSegment(const JSStackFrame *target)
StackSpace::containingSegment(const JSStackFrame *target)
{
/* The context may have nothing running. */
StackSegment *seg = currentSegment;
if (!seg)
return NULL;
/* The active segments's top frame is cx->regs->fp. */
if (regs) {
JS_ASSERT(regs->fp);
JS_ASSERT(activeSegment() == seg);
JSStackFrame *f = regs->fp;
JSStackFrame *stop = seg->getInitialFrame()->prev();
for (; f != stop; f = f->prev()) {
if (f == target)
return seg;
}
seg = seg->getPreviousInContext();
for (StackSegment *seg = currentSegment; seg; seg = seg->getPreviousInMemory()) {
if (seg->contains(target))
return seg;
}
/* A suspended segment's top frame is its suspended frame. */
for (; seg; seg = seg->getPreviousInContext()) {
JSStackFrame *f = seg->getSuspendedFrame();
JSStackFrame *stop = seg->getInitialFrame()->prev();
for (; f != stop; f = f->prev()) {
if (f == target)
return seg;
}
}
JS_NOT_REACHED("frame not in stack space");
return NULL;
}

View File

@ -118,27 +118,6 @@ namespace mjit {
class JaegerCompartment;
}
/*
* Allocation policy that calls JSContext memory functions and reports errors
* to the context. Since the JSContext given on construction is stored for
* the lifetime of the container, this policy may only be used for containers
* whose lifetime is a shorter than the given JSContext.
*/
class ContextAllocPolicy
{
JSContext *cx;
public:
ContextAllocPolicy(JSContext *cx) : cx(cx) {}
JSContext *context() const { return cx; }
/* Inline definitions below. */
void *malloc_(size_t bytes);
void free_(void *p);
void *realloc_(void *p, size_t bytes);
void reportAllocOverflow() const;
};
/*
* A StackSegment (referred to as just a 'segment') contains a prev-linked set
* of stack frames and the slots associated with each frame. A segment and its
@ -380,9 +359,7 @@ class StackSegment
return *initialVarObj;
}
#ifdef DEBUG
JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
#endif
JSStackFrame *computeNextFrame(JSStackFrame *fp) const;
};
@ -413,7 +390,7 @@ class InvokeArgsGuard : public CallArgs
*/
struct InvokeArgsAlreadyOnTheStack : CallArgs
{
InvokeArgsAlreadyOnTheStack(Value *vp, uintN argc) : CallArgs(vp + 2, argc) {}
InvokeArgsAlreadyOnTheStack(Value *vp, uintN argc) : CallArgs(argc, vp + 2) {}
};
/* See StackSpace::pushInvokeFrame. */
@ -683,6 +660,9 @@ class StackSpace
bool getExecuteFrame(JSContext *cx, JSScript *script, ExecuteFrameGuard *fg) const;
void pushExecuteFrame(JSContext *cx, JSObject *initialVarObj, ExecuteFrameGuard *fg);
/* Get the segment which contains the target frame. */
js::StackSegment *containingSegment(const JSStackFrame *target);
/*
* Since RAII cannot be used for inline frames, callers must manually
* call pushInlineFrame/popInlineFrame.
@ -1073,8 +1053,8 @@ struct JSRuntime {
js::RootedValueMap gcRootsHash;
js::GCLocks gcLocksHash;
jsrefcount gcKeepAtoms;
size_t gcBytes;
size_t gcTriggerBytes;
uint32 gcBytes;
uint32 gcTriggerBytes;
size_t gcLastBytes;
size_t gcMaxBytes;
size_t gcMaxMallocBytes;
@ -1086,6 +1066,7 @@ struct JSRuntime {
int64 gcJitReleaseTime;
JSGCMode gcMode;
volatile bool gcIsNeeded;
JSObject *gcWeakMapList;
/*
* Compartment that triggered GC. If more than one Compatment need GC,
@ -1284,9 +1265,6 @@ struct JSRuntime {
jsrefcount nonInlineCalls;
jsrefcount constructs;
jsrefcount liveObjectProps;
jsrefcount liveObjectPropsPreSweep;
/*
* NB: emptyShapes (in JSCompartment) is init'ed iff at least one
* of these envars is set:
@ -1372,6 +1350,7 @@ struct JSRuntime {
void setGCTriggerFactor(uint32 factor);
void setGCLastBytes(size_t lastBytes);
void reduceGCTriggerBytes(uint32 amount);
/*
* Call the system malloc while checking for GC memory pressure and
@ -1448,7 +1427,6 @@ struct JSRuntime {
onTooMuchMalloc();
}
private:
/*
* The function must be called outside the GC lock.
*/
@ -1787,12 +1765,6 @@ struct JSContext
/* Undoes calls to suspendActiveSegment. */
void restoreSegment();
/*
* Perform a linear search of all frames in all segments in the given context
* for the given frame, returning the segment, if found, and null otherwise.
*/
js::StackSegment *containingSegment(const JSStackFrame *target);
/* Search the call stack for the nearest frame with static level targetLevel. */
JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
JSStackFrame *fp = regs->fp;
@ -3173,30 +3145,6 @@ js_RegenerateShapeForGC(JSRuntime *rt)
namespace js {
inline void *
ContextAllocPolicy::malloc_(size_t bytes)
{
return cx->malloc_(bytes);
}
inline void
ContextAllocPolicy::free_(void *p)
{
cx->free_(p);
}
inline void *
ContextAllocPolicy::realloc_(void *p, size_t bytes)
{
return cx->realloc_(p, bytes);
}
inline void
ContextAllocPolicy::reportAllocOverflow() const
{
js_ReportAllocationOverflow(cx);
}
template<class T>
class AutoVectorRooter : protected AutoGCRooter
{
@ -3256,7 +3204,8 @@ class AutoVectorRooter : protected AutoGCRooter
friend void AutoGCRooter::trace(JSTracer *trc);
private:
Vector<T, 8> vector;
typedef Vector<T, 8> VectorImpl;
VectorImpl vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};

View File

@ -246,8 +246,7 @@ StackSpace::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *ag)
#endif
ag->cx = cx;
ag->argv_ = vp + 2;
ag->argc_ = argc;
ImplicitCast<CallArgs>(*ag) = CallArgsFromVp(argc, vp);
return true;
}

View File

@ -168,7 +168,7 @@ bool
JSCompartment::arenaListsAreEmpty()
{
for (unsigned i = 0; i < FINALIZE_LIMIT; i++) {
if (!arenas[i].isEmpty())
if (!arenas[i].isEmpty() || arenas[i].hasToBeFinalized)
return false;
}
return true;

View File

@ -377,8 +377,8 @@ struct JS_FRIEND_API(JSCompartment) {
js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT];
js::gc::FreeLists freeLists;
size_t gcBytes;
size_t gcTriggerBytes;
uint32 gcBytes;
uint32 gcTriggerBytes;
size_t gcLastBytes;
bool hold;
@ -479,12 +479,13 @@ struct JS_FRIEND_API(JSCompartment) {
void sweep(JSContext *cx, uint32 releaseInterval);
void purge(JSContext *cx);
void finishArenaLists();
void finalizeObjectArenaLists(JSContext *cx);
void finalizeShapeArenaLists(JSContext *cx);
void finalizeStringArenaLists(JSContext *cx);
void finalizeObjectArenaLists(JSContext *cx, JSGCInvocationKind gckind);
void finalizeStringArenaLists(JSContext *cx, JSGCInvocationKind gckind);
void finalizeShapeArenaLists(JSContext *cx, JSGCInvocationKind gckind);
bool arenaListsAreEmpty();
void setGCLastBytes(size_t lastBytes);
void reduceGCTriggerBytes(uint32 amount);
js::DtoaCache dtoaCache;

View File

@ -1,169 +0,0 @@
# -*- Mode: makefile -*-
#
# ***** 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 Communicator client code, released
# March 31, 1998.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-1999
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# 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 OBJDIR
ifdef OBJDIR_NAME
OBJDIR = $(OBJDIR_NAME)
endif
endif
NSPR_VERSION = v4.0
NSPR_LIBSUFFIX = 4
NSPR_LOCAL = $(MOZ_DEPTH)/dist/$(OBJDIR)/nspr
NSPR_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
NSPR_OBJDIR = $(OBJDIR)
ifeq ($(OS_ARCH), SunOS)
NSPR_OBJDIR := $(subst _sparc,,$(NSPR_OBJDIR))
endif
ifeq ($(OS_ARCH), Linux)
LINUX_REL := $(shell uname -r)
ifneq (,$(findstring 2.0,$(LINUX_REL)))
NSPR_OBJDIR := $(subst _All,2.0_x86_glibc_PTH,$(NSPR_OBJDIR))
else
NSPR_OBJDIR := $(subst _All,2.2_x86_glibc_PTH,$(NSPR_OBJDIR))
endif
endif
ifeq ($(OS_ARCH), AIX)
NSPR_OBJDIR := $(subst 4.1,4.2,$(NSPR_OBJDIR))
endif
ifeq ($(OS_CONFIG), IRIX6.2)
NSPR_OBJDIR := $(subst 6.2,6.2_n32_PTH,$(NSPR_OBJDIR))
endif
ifeq ($(OS_CONFIG), IRIX6.5)
NSPR_OBJDIR := $(subst 6.5,6.5_n32_PTH,$(NSPR_OBJDIR))
endif
ifeq ($(OS_ARCH), WINNT)
ifeq ($(OBJDIR), WIN32_D.OBJ)
NSPR_OBJDIR = WINNT4.0_DBG.OBJ
endif
ifeq ($(OBJDIR), WIN32_O.OBJ)
NSPR_OBJDIR = WINNT4.0_OPT.OBJ
endif
endif
NSPR_SHARED = /share/builds/components/nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
ifeq ($(OS_ARCH), WINNT)
NSPR_SHARED = nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
endif
NSPR_VERSIONFILE = $(NSPR_LOCAL)/Version
NSPR_CURVERSION := $(shell cat $(NSPR_VERSIONFILE) 2>/dev/null)
get_nspr:
@echo "Grabbing NSPR component..."
ifeq ($(NSPR_VERSION), $(NSPR_CURVERSION))
@echo "No need, NSPR is up to date in this tree (ver=$(NSPR_VERSION))."
else
mkdir -p $(NSPR_LOCAL)
mkdir -p $(NSPR_DIST)
ifneq ($(OS_ARCH), WINNT)
cp $(NSPR_SHARED)/*.jar $(NSPR_LOCAL)
else
sh $(MOZ_DEPTH)/../reltools/compftp.sh $(NSPR_SHARED) $(NSPR_LOCAL) *.jar
endif
unzip -o $(NSPR_LOCAL)/mdbinary.jar -d $(NSPR_DIST)
mkdir -p $(NSPR_DIST)/include
unzip -o $(NSPR_LOCAL)/mdheader.jar -d $(NSPR_DIST)/include
rm -rf $(NSPR_DIST)/META-INF
rm -rf $(NSPR_DIST)/include/META-INF
echo $(NSPR_VERSION) > $(NSPR_VERSIONFILE)
endif
SHIP_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
SHIP_DIR = $(SHIP_DIST)/SHIP
SHIP_LIBS = libjs.$(SO_SUFFIX) libjs.a
ifeq ($(OS_ARCH), WINNT)
SHIP_LIBS = js32.dll js32.lib
endif
SHIP_LIBS += $(LCJAR)
SHIP_LIBS := $(addprefix $(SHIP_DIST)/lib/, $(SHIP_LIBS))
SHIP_INCS = js*.h prmjtime.h resource.h *.msg *.tbl
SHIP_INCS := $(addprefix $(SHIP_DIST)/include/, $(SHIP_INCS))
SHIP_BINS = js
ifeq ($(OS_ARCH), WINNT)
SHIP_BINS := $(addsuffix .exe, $(SHIP_BINS))
endif
SHIP_BINS := $(addprefix $(SHIP_DIST)/bin/, $(SHIP_BINS))
ifdef BUILD_OPT
JSREFJAR = jsref_opt.jar
else
ifdef BUILD_IDG
JSREFJAR = jsref_idg.jar
else
JSREFJAR = jsref_dbg.jar
endif
endif
ship:
mkdir -p $(SHIP_DIR)/$(LIBDIR)
mkdir -p $(SHIP_DIR)/include
mkdir -p $(SHIP_DIR)/bin
cp $(SHIP_LIBS) $(SHIP_DIR)/$(LIBDIR)
cp $(SHIP_INCS) $(SHIP_DIR)/include
cp $(SHIP_BINS) $(SHIP_DIR)/bin
cd $(SHIP_DIR); \
zip -r $(JSREFJAR) bin lib include
ifdef BUILD_SHIP
cp $(SHIP_DIR)/$(JSREFJAR) $(BUILD_SHIP)
endif
CWD = $(shell pwd)
shipSource: $(SHIP_DIR)/jsref_src.lst .FORCE
mkdir -p $(SHIP_DIR)
cd $(MOZ_DEPTH)/.. ; \
zip $(CWD)/$(SHIP_DIR)/jsref_src.jar -@ < $(CWD)/$(SHIP_DIR)/jsref_src.lst
ifdef BUILD_SHIP
cp $(SHIP_DIR)/jsref_src.jar $(BUILD_SHIP)
endif
JSREFSRCDIRS := $(shell cat $(DEPTH)/SpiderMonkey.rsp)
$(SHIP_DIR)/jsref_src.lst: .FORCE
mkdir -p $(SHIP_DIR)
rm -f $@
touch $@
for d in $(JSREFSRCDIRS); do \
cd $(MOZ_DEPTH)/..; \
ls -1 -d $$d | grep -v CVS | grep -v \.OBJ >> $(CWD)/$@; \
cd $(CWD); \
done
.FORCE:

View File

@ -2109,7 +2109,7 @@ date_toJSON(JSContext *cx, uintN argc, Value *vp)
if (!cx->stack().pushInvokeArgs(cx, 0, &args))
return false;
args.callee() = toISO;
args.calleev() = toISO;
args.thisv().setObject(*obj);
if (!Invoke(cx, args, 0))

View File

@ -1382,49 +1382,11 @@ JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
return js_GetScriptedCaller(cx, fp);
}
JSPrincipals *
js_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
{
JSSecurityCallbacks *callbacks;
if (fp->isFunctionFrame()) {
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks && callbacks->findObjectPrincipals) {
if (&fp->fun()->compiledFunObj() != &fp->callee())
return callbacks->findObjectPrincipals(cx, &fp->callee());
/* FALL THROUGH */
}
}
if (fp->isScriptFrame())
return fp->script()->principals;
return NULL;
}
JSPrincipals *
js_EvalFramePrincipals(JSContext *cx, JSObject *callee, JSStackFrame *caller)
{
JSPrincipals *principals, *callerPrincipals;
JSSecurityCallbacks *callbacks;
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks && callbacks->findObjectPrincipals)
principals = callbacks->findObjectPrincipals(cx, callee);
else
principals = NULL;
if (!caller)
return principals;
callerPrincipals = js_StackFramePrincipals(cx, caller);
return (callerPrincipals && principals &&
callerPrincipals->subsume(callerPrincipals, principals))
? principals
: callerPrincipals;
}
JS_PUBLIC_API(void *)
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
{
if (fp->annotation() && fp->isScriptFrame()) {
JSPrincipals *principals = js_StackFramePrincipals(cx, fp);
JSPrincipals *principals = fp->principals(cx);
if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
/*
@ -1449,7 +1411,7 @@ JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
{
JSPrincipals *principals;
principals = js_StackFramePrincipals(cx, fp);
principals = fp->principals(cx);
if (!principals)
return NULL;
return principals->getPrincipalArray(cx, principals);
@ -1513,7 +1475,7 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv)
if (!ac.enter())
return false;
if (!fp->computeThis(cx))
if (!ComputeThis(cx, fp))
return false;
*thisv = Jsvalify(fp->thisValue());
return true;
@ -1651,7 +1613,7 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
* we use a static level that will cause us not to attempt to optimize
* variable references made by this frame.
*/
JSScript *script = Compiler::compileScript(cx, scobj, fp, js_StackFramePrincipals(cx, fp),
JSScript *script = Compiler::compileScript(cx, scobj, fp, fp->principals(cx),
TCF_COMPILE_N_GO, chars, length,
filename, lineno, cx->findVersion(),
NULL, UpvarCookie::UPVAR_LEVEL_LIMIT);
@ -1659,7 +1621,7 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
if (!script)
return false;
bool ok = Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL, Valueify(rval));
bool ok = Execute(cx, *scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL, Valueify(rval));
js_DestroyScript(cx, script);
return ok;

View File

@ -271,16 +271,6 @@ JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSStackFrame *)
JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
/*
* Return a weak reference to fp's principals. A null return does not denote
* an error, it means there are no principals.
*/
extern JSPrincipals *
js_StackFramePrincipals(JSContext *cx, JSStackFrame *fp);
JSPrincipals *
js_EvalFramePrincipals(JSContext *cx, JSObject *callee, JSStackFrame *caller);
extern JS_PUBLIC_API(void *)
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);

View File

@ -295,7 +295,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
stackDepth = 0;
valueCount = 0;
for (fp = js_GetTopStackFrame(cx); fp; fp = fp->prev()) {
if (fp->scopeChain().compartment() != cx->compartment)
if (fp->compartment() != cx->compartment)
break;
if (fp->isNonEvalFunctionFrame()) {
Value v = NullValue();
@ -338,7 +338,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
values = GetStackTraceValueBuffer(priv);
elem = priv->stackElems;
for (fp = js_GetTopStackFrame(cx); fp != fpstop; fp = fp->prev()) {
if (fp->scopeChain().compartment() != cx->compartment)
if (fp->compartment() != cx->compartment)
break;
if (!fp->isFunctionFrame() || fp->isEvalFrame()) {
elem->funName = NULL;

View File

@ -1051,7 +1051,7 @@ CreateEvalCallObject(JSContext *cx, JSStackFrame *fp)
{
JSObject *callobj = NewCallObject(cx, fp->script(), fp->scopeChain(), NULL);
if (!callobj)
return false;
return NULL;
callobj->setPrivate(fp);
fp->setScopeChainWithOwnCallObj(*callobj);
@ -1454,7 +1454,7 @@ JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
if (thisv.isObject()) {
JS_ASSERT(funobj.getFunctionPrivate() == fun);
if (&fun->compiledFunObj() == &funobj && fun->methodAtom()) {
if (fun->compiledFunObj() == funobj && fun->methodAtom()) {
JSObject *thisp = &thisv.toObject();
JSObject *first_barriered_thisp = NULL;
@ -1480,10 +1480,10 @@ JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
* In either case we must allow for the method property
* to have been replaced, or its value overwritten.
*/
if (shape->isMethod() && &shape->methodObject() == &funobj) {
if (shape->isMethod() && shape->methodObject() == funobj) {
if (!thisp->methodReadBarrier(cx, *shape, vp))
return false;
calleeValue().setObject(vp->toObject());
calleev().setObject(vp->toObject());
return true;
}
@ -1496,7 +1496,7 @@ JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
clone->hasMethodObj(*thisp)) {
JS_ASSERT(clone != &funobj);
*vp = v;
calleeValue().setObject(*clone);
calleev().setObject(*clone);
return true;
}
}
@ -1525,7 +1525,7 @@ JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
if (!newfunobj)
return false;
newfunobj->setMethodObj(*first_barriered_thisp);
calleeValue().setObject(*newfunobj);
calleev().setObject(*newfunobj);
vp->setObject(*newfunobj);
return true;
}
@ -2140,7 +2140,7 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
return JS_FALSE;
/* Push fval, thisv, and the args. */
args.callee() = fval;
args.calleev() = fval;
args.thisv() = thisv;
memcpy(args.argv(), argv, argc * sizeof *argv);
@ -2191,7 +2191,7 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp)
return false;
/* Push fval, obj, and aobj's elements as args. */
args.callee() = fval;
args.calleev() = fval;
args.thisv() = vp[2];
/* Steps 7-8. */
@ -2308,7 +2308,7 @@ CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp)
memcpy(args.argv() + argslen, vp + 2, argc * sizeof(Value));
/* 15.3.4.5.1, 15.3.4.5.2 step 5. */
args.callee().setObject(*target);
args.calleev().setObject(*target);
if (!constructing)
args.thisv() = boundThis;
@ -2431,12 +2431,13 @@ OnBadFormal(JSContext *cx, TokenKind tt)
static JSBool
Function(JSContext *cx, uintN argc, Value *vp)
{
CallArgs call = CallArgsFromVp(argc, vp);
JS::Anchor<JSObject *> obj(NewFunction(cx, NULL));
if (!obj.get())
return false;
JSObject &callee = JS_CALLEE(cx, vp).toObject();
JSObject &calleeParent = *callee.getParent();
JSObject &calleeParent = *call.callee().getParent();
/*
* NB: (new Function) is not lexically closed by its caller, it's just an
@ -2453,32 +2454,6 @@ Function(JSContext *cx, uintN argc, Value *vp)
if (!fun)
return false;
/*
* Function is static and not called directly by other functions in this
* file, therefore it is callable only as a native function by js_Invoke.
* Find the scripted caller, possibly skipping other native frames such as
* are built for Function.prototype.call or .apply activations that invoke
* Function indirectly from a script.
*/
JSStackFrame *caller = js_GetScriptedCaller(cx, NULL);
uintN lineno;
const char *filename;
JSPrincipals *principals;
if (caller) {
principals = js_EvalFramePrincipals(cx, &callee, caller);
filename = js_ComputeFilename(cx, caller, principals, &lineno);
} else {
filename = NULL;
lineno = 0;
principals = NULL;
}
/* Belt-and-braces: check that the caller has access to parent. */
if (!js_CheckPrincipalsAccess(cx, &calleeParent, principals,
CLASS_ATOM(cx, Function))) {
return false;
}
/*
* CSP check: whether new Function() is allowed at all.
* Report errors via CSP is done in the script security manager.
@ -2497,7 +2472,10 @@ Function(JSContext *cx, uintN argc, Value *vp)
Bindings bindings(cx, emptyCallShape);
AutoBindingsRooter root(cx, bindings);
Value *argv = JS_ARGV(cx, vp);
uintN lineno;
const char *filename = CurrentScriptFileAndLine(cx, &lineno);
Value *argv = call.argv();
uintN n = argc ? argc - 1 : 0;
if (n > 0) {
/*
@ -2637,10 +2615,12 @@ Function(JSContext *cx, uintN argc, Value *vp)
length = 0;
}
JS_SET_RVAL(cx, vp, ObjectValue(*obj.get()));
return Compiler::compileFunctionBody(cx, fun, principals, &bindings,
chars, length, filename, lineno,
cx->findVersion());
JSPrincipals *principals = PrincipalsForCompiledCode(call, cx);
bool ok = Compiler::compileFunctionBody(cx, fun, principals, &bindings,
chars, length, filename, lineno,
cx->findVersion());
call.rval().setObject(obj);
return ok;
}
namespace js {
@ -2665,7 +2645,7 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj)
const Shape *shape = funobj->nativeLookup(id);
if (!shape) {
if (!ResolveInterpretedFunctionPrototype(cx, funobj))
return false;
return NULL;
shape = funobj->nativeLookup(id);
}
JS_ASSERT(!shape->configurable());

View File

@ -88,6 +88,7 @@
#include "jsinterpinlines.h"
#include "jsobjinlines.h"
#include "jshashtable.h"
#include "jsweakmap.h"
#include "jsstrinlines.h"
#include "jscompartment.h"
@ -232,16 +233,108 @@ Arena<T>::mark(T *thing, JSTracer *trc)
return CGCT_VALID;
}
template<typename T>
inline bool
Arena<T>::finalize(JSContext *cx)
{
JS_ASSERT_IF(header()->hasFreeThings, header()->freeList);
JS_ASSERT(!getMarkingDelay()->link);
JS_ASSERT(getMarkingDelay()->unmarkedChildren == 0);
JS_ASSERT(header()->isUsed);
FreeCell *nextFree = header()->freeList;
FreeCell *freeList = NULL;
FreeCell **tailp = &freeList;
bool allClear = true;
T *thingsEnd = &t.things[ThingsPerArena-1];
T *thing = &t.things[0];
thingsEnd++;
if (!nextFree) {
nextFree = thingsEnd->asFreeCell();
} else {
JS_ASSERT(thing->asFreeCell() <= nextFree);
JS_ASSERT(nextFree < thingsEnd->asFreeCell());
}
for (;; thing++) {
if (thing->asFreeCell() == nextFree) {
if (thing == thingsEnd)
break;
nextFree = nextFree->link;
if (!nextFree) {
nextFree = thingsEnd->asFreeCell();
} else {
JS_ASSERT(thing->asFreeCell() < nextFree);
JS_ASSERT(nextFree < thingsEnd->asFreeCell());
}
} else if (thing->asFreeCell()->isMarked()) {
allClear = false;
continue;
} else {
thing->finalize(cx);
#ifdef DEBUG
memset(thing, JS_FREE_PATTERN, sizeof(T));
#endif
}
FreeCell *t = thing->asFreeCell();
*tailp = t;
tailp = &t->link;
}
#ifdef DEBUG
/* Check that the free list is consistent. */
unsigned nfree = 0;
if (freeList) {
JS_ASSERT(tailp != &freeList);
FreeCell *t = freeList;
for (;;) {
++nfree;
if (&t->link == tailp)
break;
JS_ASSERT(t < t->link);
t = t->link;
}
}
#endif
if (allClear) {
JS_ASSERT(nfree == ThingsPerArena);
JS_ASSERT((T *)tailp == &t.things[ThingsPerArena-1]);
*tailp = NULL;
header()->freeList = freeList;
#ifdef DEBUG
header()->hasFreeThings = true;
#endif
JS_ASSERT((T *)header()->freeList == &t.things[0]);
} else {
JS_ASSERT(nfree < ThingsPerArena);
*tailp = NULL;
header()->freeList = freeList;
#ifdef DEBUG
header()->hasFreeThings = (nfree == 0) ? false : true;
#endif
}
return allClear;
}
#ifdef DEBUG
bool
checkArenaListsForThing(JSCompartment *comp, void *thing)
{
if (comp->arenas[FINALIZE_OBJECT0].arenasContainThing<JSObject>(thing) ||
comp->arenas[FINALIZE_OBJECT0_BACKGROUND].arenasContainThing<JSObject>(thing) ||
comp->arenas[FINALIZE_OBJECT2].arenasContainThing<JSObject_Slots2>(thing) ||
comp->arenas[FINALIZE_OBJECT2_BACKGROUND].arenasContainThing<JSObject_Slots2>(thing) ||
comp->arenas[FINALIZE_OBJECT4].arenasContainThing<JSObject_Slots4>(thing) ||
comp->arenas[FINALIZE_OBJECT4_BACKGROUND].arenasContainThing<JSObject_Slots4>(thing) ||
comp->arenas[FINALIZE_OBJECT8].arenasContainThing<JSObject_Slots8>(thing) ||
comp->arenas[FINALIZE_OBJECT8_BACKGROUND].arenasContainThing<JSObject_Slots8>(thing) ||
comp->arenas[FINALIZE_OBJECT12].arenasContainThing<JSObject_Slots12>(thing) ||
comp->arenas[FINALIZE_OBJECT12_BACKGROUND].arenasContainThing<JSObject_Slots12>(thing) ||
comp->arenas[FINALIZE_OBJECT16].arenasContainThing<JSObject_Slots16>(thing) ||
comp->arenas[FINALIZE_OBJECT16_BACKGROUND].arenasContainThing<JSObject_Slots16>(thing) ||
comp->arenas[FINALIZE_FUNCTION].arenasContainThing<JSFunction>(thing) ||
comp->arenas[FINALIZE_SHAPE].arenasContainThing<Shape>(thing) ||
#if JS_HAS_XML_SUPPORT
@ -284,13 +377,18 @@ Chunk::clearMarkBitmap()
PodZero(&bitmaps[0], ArenasPerChunk);
}
void
bool
Chunk::init(JSRuntime *rt)
{
info.runtime = rt;
info.age = 0;
info.emptyArenaLists.init();
info.emptyArenaLists.cellFreeList = &arenas[0];
#ifdef JS_THREADSAFE
info.chunkLock = JS_NEW_LOCK();
if (!info.chunkLock)
return false;
#endif
Arena<FreeCell> *arena = &arenas[0];
Arena<FreeCell> *last = &arenas[JS_ARRAY_LENGTH(arenas) - 1];
while (arena < last) {
@ -307,6 +405,7 @@ Chunk::init(JSRuntime *rt)
last->header()->isUsed = false;
#endif
info.numFree = ArenasPerChunk;
return true;
}
bool
@ -332,20 +431,25 @@ Chunk::withinArenasRange(Cell *cell)
template <typename T>
Arena<T> *
Chunk::allocateArena(JSCompartment *comp, unsigned thingKind)
Chunk::allocateArena(JSContext *cx, unsigned thingKind)
{
#ifdef JS_THREADSAFE
Conditionally<AutoLock> lockIf(cx->runtime->gcHelperThread.sweeping, info.chunkLock);
#endif
JSCompartment *comp = cx->compartment;
JS_ASSERT(hasAvailableArenas());
Arena<T> *arena = info.emptyArenaLists.getNext<T>(comp, thingKind);
JS_ASSERT(arena);
JS_ASSERT(arena->header()->isUsed);
--info.numFree;
JSRuntime *rt = info.runtime;
rt->gcBytes += sizeof(Arena<T>);
comp->gcBytes += sizeof(Arena<T>);
JS_ATOMIC_ADD(&rt->gcBytes, sizeof(Arena<T>));
JS_ATOMIC_ADD(&comp->gcBytes, sizeof(Arena<T>));
METER(JS_ATOMIC_INCREMENT(&rt->gcStats.nallarenas));
if (comp->gcBytes >= comp->gcTriggerBytes)
TriggerCompartmentGC(comp);
METER(rt->gcStats.nallarenas++);
return arena;
}
@ -354,15 +458,24 @@ void
Chunk::releaseArena(Arena<T> *arena)
{
JSRuntime *rt = info.runtime;
#ifdef JS_THREADSAFE
Conditionally<AutoLock> lockIf(rt->gcHelperThread.sweeping, info.chunkLock);
#endif
JSCompartment *comp = arena->header()->compartment;
METER(rt->gcStats.afree++);
JS_ASSERT(rt->gcStats.nallarenas != 0);
METER(rt->gcStats.nallarenas--);
JS_ASSERT(rt->gcBytes >= sizeof(Arena<T>));
JS_ASSERT(comp->gcBytes >= sizeof(Arena<T>));
METER(JS_ATOMIC_DECREMENT(&rt->gcStats.nallarenas));
rt->gcBytes -= sizeof(Arena<T>);
comp->gcBytes -= sizeof(Arena<T>);
JS_ASSERT(size_t(rt->gcBytes) >= sizeof(Arena<T>));
JS_ASSERT(size_t(comp->gcBytes) >= sizeof(Arena<T>));
#ifdef JS_THREADSAFE
if (rt->gcHelperThread.sweeping) {
rt->reduceGCTriggerBytes(3 * sizeof(Arena<T>));
comp->reduceGCTriggerBytes(3 * sizeof(Arena<T>));
}
#endif
JS_ATOMIC_ADD(&rt->gcBytes, -sizeof(Arena<T>));
JS_ATOMIC_ADD(&comp->gcBytes, -sizeof(Arena<T>));
info.emptyArenaLists.insert((Arena<Cell> *)arena);
#ifdef DEBUG
arena->header()->isUsed = false;
@ -399,6 +512,9 @@ ReleaseGCChunk(JSRuntime *rt, jsuword chunk)
JS_ASSERT(p);
#ifdef MOZ_GCTIMER
JS_ATOMIC_INCREMENT(&destroyChunkCount);
#endif
#ifdef JS_THREADSAFE
JS_DESTROY_LOCK(((Chunk *)chunk)->info.chunkLock);
#endif
JS_ASSERT(rt->gcStats.nchunks != 0);
METER(rt->gcStats.nchunks--);
@ -423,6 +539,9 @@ ReleaseGCChunk(JSRuntime *rt, Chunk *p)
JS_ASSERT(p);
#ifdef MOZ_GCTIMER
JS_ATOMIC_INCREMENT(&destroyChunkCount);
#endif
#ifdef JS_THREADSAFE
JS_DESTROY_LOCK(p->info.chunkLock);
#endif
JS_ASSERT(rt->gcStats.nchunks != 0);
METER(rt->gcStats.nchunks--);
@ -453,7 +572,10 @@ PickChunk(JSRuntime *rt)
return NULL;
}
chunk->init(rt);
if (!chunk->init(rt)) {
ReleaseGCChunk(rt, chunk);
return NULL;
}
return chunk;
}
@ -496,7 +618,7 @@ AllocateArena(JSContext *cx, unsigned thingKind)
}
cx->compartment->chunk = chunk;
}
return chunk->allocateArena<T>(cx->compartment, thingKind);
return chunk->allocateArena<T>(cx, thingKind);
}
JS_FRIEND_API(bool)
@ -652,21 +774,27 @@ MarkIfGCThingWord(JSTracer *trc, jsuword w, uint32 &thingKind)
switch (thingKind) {
case FINALIZE_OBJECT0:
case FINALIZE_OBJECT0_BACKGROUND:
test = MarkCell<JSObject>(cell, trc);
break;
case FINALIZE_OBJECT2:
case FINALIZE_OBJECT2_BACKGROUND:
test = MarkCell<JSObject_Slots2>(cell, trc);
break;
case FINALIZE_OBJECT4:
case FINALIZE_OBJECT4_BACKGROUND:
test = MarkCell<JSObject_Slots4>(cell, trc);
break;
case FINALIZE_OBJECT8:
case FINALIZE_OBJECT8_BACKGROUND:
test = MarkCell<JSObject_Slots8>(cell, trc);
break;
case FINALIZE_OBJECT12:
case FINALIZE_OBJECT12_BACKGROUND:
test = MarkCell<JSObject_Slots12>(cell, trc);
break;
case FINALIZE_OBJECT16:
case FINALIZE_OBJECT16_BACKGROUND:
test = MarkCell<JSObject_Slots16>(cell, trc);
break;
case FINALIZE_STRING:
@ -874,6 +1002,8 @@ js_FinishGC(JSRuntime *rt)
rt->compartments.clear();
rt->atomsCompartment = NULL;
rt->gcWeakMapList = NULL;
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
ReleaseGCChunk(rt, r.front());
rt->gcChunkSet.clear();
@ -1052,6 +1182,15 @@ JSRuntime::setGCLastBytes(size_t lastBytes)
gcTriggerBytes = (float(gcMaxBytes) < maxtrigger) ? gcMaxBytes : size_t(maxtrigger);
}
void
JSRuntime::reduceGCTriggerBytes(uint32 amount) {
JS_ASSERT(amount > 0);
JS_ASSERT((gcTriggerBytes - amount) > 0);
if (gcTriggerBytes - amount < GC_ARENA_ALLOCATION_TRIGGER * GC_HEAP_GROWTH_FACTOR)
return;
gcTriggerBytes -= amount;
}
void
JSCompartment::setGCLastBytes(size_t lastBytes)
{
@ -1065,6 +1204,15 @@ JSCompartment::setGCLastBytes(size_t lastBytes)
gcTriggerBytes = (float(rt->gcMaxBytes) < maxtrigger) ? rt->gcMaxBytes : size_t(maxtrigger);
}
void
JSCompartment::reduceGCTriggerBytes(uint32 amount) {
JS_ASSERT(amount > 0);
JS_ASSERT((gcTriggerBytes - amount) > 0);
if (gcTriggerBytes - amount < GC_ARENA_ALLOCATION_TRIGGER * GC_HEAP_GROWTH_FACTOR)
return;
gcTriggerBytes -= amount;
}
void
FreeLists::purge()
{
@ -1123,6 +1271,11 @@ RunLastDitchGC(JSContext *cx)
AutoKeepAtoms keep(rt);
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL);
#ifdef JS_THREADSAFE
if (rt->gcBytes >= rt->gcMaxBytes)
cx->runtime->gcHelperThread.waitBackgroundSweepEnd(cx->runtime);
#endif
return rt->gcBytes < rt->gcMaxBytes;
}
@ -1139,6 +1292,10 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind)
return false;
bool canGC = !JS_ON_TRACE(cx) && !JS_THREAD_DATA(cx)->waiveGCQuota;
#ifdef JS_THREADSAFE
bool waited = false;
#endif
do {
if (canGC && JS_UNLIKELY(NeedLastDitchGC(cx))) {
if (!RunLastDitchGC(cx))
@ -1155,12 +1312,18 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind)
}
ArenaList *arenaList = GetFinalizableArenaList(compartment, thingKind);
Arena<T> *a = reinterpret_cast<Arena<T> *>(arenaList->getNextWithFreeList());
if (a) {
JS_ASSERT(a->header()->freeList);
JS_ASSERT(sizeof(T) == a->header()->thingSize);
compartment->freeLists.populate(a, thingKind);
return true;
#ifdef JS_THREADSAFE
try_again:
#endif
Arena<T> *a = NULL;
if (!arenaList->hasToBeFinalized) {
a = reinterpret_cast<Arena<T> *>(arenaList->getNextWithFreeList(cx));
if (a) {
JS_ASSERT(a->header()->freeList);
JS_ASSERT(sizeof(T) == a->header()->thingSize);
compartment->freeLists.populate(a, thingKind);
return true;
}
}
/*
@ -1174,6 +1337,14 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind)
a->getMarkingDelay()->init();
return true;
}
#ifdef JS_THREADSAFE
if (!waited) {
/* The background thread can still free arenas during the finalization phase. */
cx->runtime->gcHelperThread.waitBackgroundSweepEnd(cx->runtime);
waited = true;
goto try_again;
}
#endif
} while (canGC);
METER(cx->runtime->gcStats.fail++);
@ -1186,16 +1357,22 @@ RefillFinalizableFreeList(JSContext *cx, unsigned thingKind)
{
switch (thingKind) {
case FINALIZE_OBJECT0:
case FINALIZE_OBJECT0_BACKGROUND:
return RefillTypedFreeList<JSObject>(cx, thingKind);
case FINALIZE_OBJECT2:
case FINALIZE_OBJECT2_BACKGROUND:
return RefillTypedFreeList<JSObject_Slots2>(cx, thingKind);
case FINALIZE_OBJECT4:
case FINALIZE_OBJECT4_BACKGROUND:
return RefillTypedFreeList<JSObject_Slots4>(cx, thingKind);
case FINALIZE_OBJECT8:
case FINALIZE_OBJECT8_BACKGROUND:
return RefillTypedFreeList<JSObject_Slots8>(cx, thingKind);
case FINALIZE_OBJECT12:
case FINALIZE_OBJECT12_BACKGROUND:
return RefillTypedFreeList<JSObject_Slots12>(cx, thingKind);
case FINALIZE_OBJECT16:
case FINALIZE_OBJECT16_BACKGROUND:
return RefillTypedFreeList<JSObject_Slots16>(cx, thingKind);
case FINALIZE_STRING:
return RefillTypedFreeList<JSString>(cx, thingKind);
@ -1386,21 +1563,27 @@ GCMarker::markDelayedChildren()
switch (a->header()->thingKind) {
case FINALIZE_OBJECT0:
case FINALIZE_OBJECT0_BACKGROUND:
reinterpret_cast<Arena<JSObject> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_OBJECT2:
case FINALIZE_OBJECT2_BACKGROUND:
reinterpret_cast<Arena<JSObject_Slots2> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_OBJECT4:
case FINALIZE_OBJECT4_BACKGROUND:
reinterpret_cast<Arena<JSObject_Slots4> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_OBJECT8:
case FINALIZE_OBJECT8_BACKGROUND:
reinterpret_cast<Arena<JSObject_Slots8> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_OBJECT12:
case FINALIZE_OBJECT12_BACKGROUND:
reinterpret_cast<Arena<JSObject_Slots12> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_OBJECT16:
case FINALIZE_OBJECT16_BACKGROUND:
reinterpret_cast<Arena<JSObject_Slots16> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_STRING:
@ -1410,7 +1593,7 @@ GCMarker::markDelayedChildren()
reinterpret_cast<Arena<JSExternalString> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_SHORT_STRING:
JS_ASSERT(false);
JS_NOT_REACHED("no delayed marking");
break;
case FINALIZE_FUNCTION:
reinterpret_cast<Arena<JSFunction> *>(a)->markDelayedChildren(this);
@ -1504,7 +1687,7 @@ AutoIdArray::trace(JSTracer *trc)
void
AutoEnumStateRooter::trace(JSTracer *trc)
{
js::gc::MarkObject(trc, *obj, "js::AutoEnumStateRooter.obj");
gc::MarkObject(trc, *obj, "js::AutoEnumStateRooter.obj");
}
inline void
@ -1585,24 +1768,24 @@ AutoGCRooter::trace(JSTracer *trc)
return;
case VALVECTOR: {
Vector<Value, 8> &vector = static_cast<js::AutoValueVector *>(this)->vector;
AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
MarkValueRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
return;
}
case STRING:
if (JSString *str = static_cast<js::AutoStringRooter *>(this)->str)
if (JSString *str = static_cast<AutoStringRooter *>(this)->str)
MarkString(trc, str, "js::AutoStringRooter.str");
return;
case IDVECTOR: {
Vector<jsid, 8> &vector = static_cast<js::AutoIdVector *>(this)->vector;
AutoIdVector::VectorImpl &vector = static_cast<AutoIdVector *>(this)->vector;
MarkIdRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
return;
}
case SHAPEVECTOR: {
Vector<const Shape *, 8> &vector = static_cast<js::AutoShapeVector *>(this)->vector;
AutoShapeVector::VectorImpl &vector = static_cast<js::AutoShapeVector *>(this)->vector;
MarkShapeRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector");
return;
}
@ -1787,7 +1970,7 @@ js_DestroyScriptsToGC(JSContext *cx, JSCompartment *comp)
template<typename T>
static void
FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
FinalizeArenaList(JSCompartment *comp, JSContext *cx, JSGCInvocationKind gckind, unsigned thingKind)
{
JS_STATIC_ASSERT(!(sizeof(T) & Cell::CellMask));
ArenaList *arenaList = GetFinalizableArenaList(comp, thingKind);
@ -1801,94 +1984,14 @@ FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
uint32 nlivearenas = 0, nkilledarenas = 0, nthings = 0;
#endif
for (;;) {
ArenaHeader *header = a->header();
JS_ASSERT_IF(header->hasFreeThings, header->freeList);
JS_ASSERT(header->thingKind == thingKind);
JS_ASSERT(!a->getMarkingDelay()->link);
JS_ASSERT(a->getMarkingDelay()->unmarkedChildren == 0);
JS_ASSERT(a->header()->isUsed);
FreeCell *nextFree = header->freeList;
FreeCell *freeList = NULL;
FreeCell **tailp = &freeList;
bool allClear = true;
T *thingsEnd = &a->t.things[a->ThingsPerArena-1];
T *thing = &a->t.things[0];
thingsEnd++;
if (!nextFree) {
nextFree = thingsEnd->asFreeCell();
} else {
JS_ASSERT(thing->asFreeCell() <= nextFree);
JS_ASSERT(nextFree < thingsEnd->asFreeCell());
}
for (;; thing++) {
if (thing->asFreeCell() == nextFree) {
if (thing == thingsEnd)
break;
nextFree = nextFree->link;
if (!nextFree) {
nextFree = thingsEnd->asFreeCell();
} else {
JS_ASSERT(thing->asFreeCell() < nextFree);
JS_ASSERT(nextFree < thingsEnd->asFreeCell());
}
} else if (thing->isMarked()) {
allClear = false;
METER(nthings++);
continue;
} else {
thing->finalize(cx);
#ifdef DEBUG
memset(thing, JS_FREE_PATTERN, sizeof(T));
#endif
}
FreeCell *t = thing->asFreeCell();
*tailp = t;
tailp = &t->link;
}
#ifdef DEBUG
/* Check that the free list is consistent. */
unsigned nfree = 0;
if (freeList) {
JS_ASSERT(tailp != &freeList);
FreeCell *t = freeList;
for (;;) {
++nfree;
if (&t->link == tailp)
break;
JS_ASSERT(t < t->link);
t = t->link;
}
}
#endif
JS_ASSERT(a->header()->thingKind == thingKind);
bool allClear = a->finalize(cx);
if (allClear) {
/*
* Forget just assembled free list head for the arena and
* add the arena itself to the destroy list.
*/
JS_ASSERT(nfree == a->ThingsPerArena);
JS_ASSERT((T *)tailp == &a->t.things[a->ThingsPerArena-1]);
*tailp = NULL;
header->freeList = freeList;
#ifdef DEBUG
header->hasFreeThings = true;
#endif
*ap = (header->next);
JS_ASSERT((T *)header->freeList == &a->t.things[0]);
*ap = a->header()->next;
a->chunk()->releaseArena(a);
METER(nkilledarenas++);
} else {
JS_ASSERT(nfree < a->ThingsPerArena);
*tailp = NULL;
header->freeList = freeList;
#ifdef DEBUG
header->hasFreeThings = (nfree == 0) ? false : true;
#endif
ap = &header->next;
ap = &a->header()->next;
METER(nlivearenas++);
}
if (!(a = (Arena<T> *) *ap))
@ -1898,33 +2001,173 @@ FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
METER(UpdateCompartmentStats(comp, thingKind, nlivearenas, nkilledarenas, nthings));
}
void
JSCompartment::finalizeObjectArenaLists(JSContext *cx)
template<typename T>
static void
FinalizeArenaListLater(JSContext *cx, ArenaList *arenaList, Arena<FreeCell> *head)
{
FinalizeArenaList<JSObject>(this, cx, FINALIZE_OBJECT0);
FinalizeArenaList<JSObject_Slots2>(this, cx, FINALIZE_OBJECT2);
FinalizeArenaList<JSObject_Slots4>(this, cx, FINALIZE_OBJECT4);
FinalizeArenaList<JSObject_Slots8>(this, cx, FINALIZE_OBJECT8);
FinalizeArenaList<JSObject_Slots12>(this, cx, FINALIZE_OBJECT12);
FinalizeArenaList<JSObject_Slots16>(this, cx, FINALIZE_OBJECT16);
FinalizeArenaList<JSFunction>(this, cx, FINALIZE_FUNCTION);
JS_STATIC_ASSERT(!(sizeof(T) & Cell::CellMask));
JS_ASSERT(arenaList->hasToBeFinalized);
Arena<FreeCell> **ap = &head;
Arena<T> *a = (Arena<T> *) *ap;
JS_ASSERT(a);
#ifdef DEBUG
int thingKind = head->header()->thingKind;
JSCompartment *comp = head->header()->compartment;
#endif
JS_ASSERT(sizeof(T) == head->header()->thingSize);
#ifdef JS_GCMETER
uint32 nlivearenas = 0, nkilledarenas = 0, nthings = 0;
#endif
for (;;) {
bool allClear = a->finalize(cx);
/* We don't delete the head because the next allcoated arena has to link to it. */
if (allClear && (a != (Arena<T> *)head)) {
*ap = a->header()->next;
a->chunk()->releaseArena(a);
METER(nkilledarenas++);
} else {
ap = &a->header()->next;
METER(nlivearenas++);
}
if (!(a = (Arena<T> *) *ap))
break;
}
arenaList->cursor = (Arena<FreeCell> *)head;
arenaList->hasToBeFinalized = false;
METER(UpdateCompartmentStats(comp, thingKind, nlivearenas, nkilledarenas, nthings));
}
void
FinalizeArenaList(JSContext *cx, ArenaList *list, Arena<FreeCell> *head)
{
JS_ASSERT(list->head);
JS_ASSERT(head);
js::gc::FinalizeKind kind = js::gc::FinalizeKind(head->header()->thingKind);
switch (kind) {
case FINALIZE_OBJECT0:
case FINALIZE_OBJECT2:
case FINALIZE_OBJECT4:
case FINALIZE_OBJECT8:
case FINALIZE_OBJECT12:
case FINALIZE_OBJECT16:
case FINALIZE_FUNCTION:
case FINALIZE_SHAPE:
case FINALIZE_EXTERNAL_STRING:
JS_NOT_REACHED("no background finalization");
break;
case FINALIZE_OBJECT0_BACKGROUND:
FinalizeArenaListLater<JSObject>(cx, list, (Arena<FreeCell> *)head);
break;
case FINALIZE_OBJECT2_BACKGROUND:
FinalizeArenaListLater<JSObject_Slots2>(cx, list, (Arena<FreeCell> *)head);
break;
case FINALIZE_OBJECT4_BACKGROUND:
FinalizeArenaListLater<JSObject_Slots4>(cx, list, (Arena<FreeCell> *)head);
break;
case FINALIZE_OBJECT8_BACKGROUND:
FinalizeArenaListLater<JSObject_Slots8>(cx, list, (Arena<FreeCell> *)head);
break;
case FINALIZE_OBJECT12_BACKGROUND:
FinalizeArenaListLater<JSObject_Slots12>(cx, list, (Arena<FreeCell> *)head);
break;
case FINALIZE_OBJECT16_BACKGROUND:
FinalizeArenaListLater<JSObject_Slots16>(cx, list, (Arena<FreeCell> *)head);
break;
case FINALIZE_STRING:
FinalizeArenaListLater<JSString>(cx, list, (Arena<FreeCell> *)head);
break;
case FINALIZE_SHORT_STRING:
FinalizeArenaListLater<JSShortString>(cx, list, (Arena<FreeCell> *)head);
break;
#if JS_HAS_XML_SUPPORT
case FINALIZE_XML:
JS_NOT_REACHED("no background finalization");
break;
#endif
default:
JS_NOT_REACHED("wrong kind");
}
}
#ifdef JS_THREADSAFE
template<typename T>
void BackgroundFinalize(JSCompartment *comp, JSContext *cx, JSGCInvocationKind gckind, unsigned thingKind)
{
ArenaList *list = GetFinalizableArenaList(comp, thingKind);
if (list->head && list->head->header()->next) {
cx->gcBackgroundFree->finalizeLater(list);
} else {
FinalizeArenaList<T>(comp, cx, gckind, thingKind);
}
}
#endif
void
JSCompartment::finalizeObjectArenaLists(JSContext *cx, JSGCInvocationKind gckind)
{
FinalizeArenaList<JSObject>(this, cx, gckind, FINALIZE_OBJECT0);
FinalizeArenaList<JSObject_Slots2>(this, cx, gckind, FINALIZE_OBJECT2);
FinalizeArenaList<JSObject_Slots4>(this, cx, gckind, FINALIZE_OBJECT4);
FinalizeArenaList<JSObject_Slots8>(this, cx, gckind, FINALIZE_OBJECT8);
FinalizeArenaList<JSObject_Slots12>(this, cx, gckind, FINALIZE_OBJECT12);
FinalizeArenaList<JSObject_Slots16>(this, cx, gckind, FINALIZE_OBJECT16);
FinalizeArenaList<JSFunction>(this, cx, gckind, FINALIZE_FUNCTION);
#ifdef JS_THREADSAFE
if (cx->gcBackgroundFree && gckind != GC_LAST_CONTEXT && cx->runtime->state != JSRTS_LANDING) {
BackgroundFinalize<JSObject>(this, cx, gckind, FINALIZE_OBJECT0_BACKGROUND);
BackgroundFinalize<JSObject_Slots2>(this, cx, gckind, FINALIZE_OBJECT2_BACKGROUND);
BackgroundFinalize<JSObject_Slots4>(this, cx, gckind, FINALIZE_OBJECT4_BACKGROUND);
BackgroundFinalize<JSObject_Slots8>(this, cx, gckind, FINALIZE_OBJECT8_BACKGROUND);
BackgroundFinalize<JSObject_Slots12>(this, cx, gckind, FINALIZE_OBJECT12_BACKGROUND);
BackgroundFinalize<JSObject_Slots16>(this, cx, gckind, FINALIZE_OBJECT16_BACKGROUND);
} else {
FinalizeArenaList<JSObject>(this, cx, gckind, FINALIZE_OBJECT0_BACKGROUND);
FinalizeArenaList<JSObject_Slots2>(this, cx, gckind, FINALIZE_OBJECT2_BACKGROUND);
FinalizeArenaList<JSObject_Slots4>(this, cx, gckind, FINALIZE_OBJECT4_BACKGROUND);
FinalizeArenaList<JSObject_Slots8>(this, cx, gckind, FINALIZE_OBJECT8_BACKGROUND);
FinalizeArenaList<JSObject_Slots12>(this, cx, gckind, FINALIZE_OBJECT12_BACKGROUND);
FinalizeArenaList<JSObject_Slots16>(this, cx, gckind, FINALIZE_OBJECT16_BACKGROUND);
}
#else
FinalizeArenaList<JSObject>(this, cx, gckind, FINALIZE_OBJECT0_BACKGROUND);
FinalizeArenaList<JSObject_Slots2>(this, cx, gckind, FINALIZE_OBJECT2_BACKGROUND);
FinalizeArenaList<JSObject_Slots4>(this, cx, gckind, FINALIZE_OBJECT4_BACKGROUND);
FinalizeArenaList<JSObject_Slots8>(this, cx, gckind, FINALIZE_OBJECT8_BACKGROUND);
FinalizeArenaList<JSObject_Slots12>(this, cx, gckind, FINALIZE_OBJECT12_BACKGROUND);
FinalizeArenaList<JSObject_Slots16>(this, cx, gckind, FINALIZE_OBJECT16_BACKGROUND);
#endif
#if JS_HAS_XML_SUPPORT
FinalizeArenaList<JSXML>(this, cx, FINALIZE_XML);
FinalizeArenaList<JSXML>(this, cx, gckind, FINALIZE_XML);
#endif
}
void
JSCompartment::finalizeStringArenaLists(JSContext *cx)
JSCompartment::finalizeStringArenaLists(JSContext *cx, JSGCInvocationKind gckind)
{
FinalizeArenaList<JSShortString>(this, cx, FINALIZE_SHORT_STRING);
FinalizeArenaList<JSString>(this, cx, FINALIZE_STRING);
FinalizeArenaList<JSExternalString>(this, cx, FINALIZE_EXTERNAL_STRING);
#ifdef JS_THREADSAFE
if (cx->gcBackgroundFree && gckind != GC_LAST_CONTEXT && cx->runtime->state != JSRTS_LANDING) {
BackgroundFinalize<JSShortString>(this, cx, gckind, FINALIZE_SHORT_STRING);
BackgroundFinalize<JSString>(this, cx, gckind, FINALIZE_STRING);
} else {
FinalizeArenaList<JSShortString>(this, cx, gckind, FINALIZE_SHORT_STRING);
FinalizeArenaList<JSString>(this, cx, gckind, FINALIZE_STRING);
}
FinalizeArenaList<JSExternalString>(this, cx, gckind, FINALIZE_EXTERNAL_STRING);
#else
FinalizeArenaList<JSShortString>(this, cx, gckind, FINALIZE_SHORT_STRING);
FinalizeArenaList<JSString>(this, cx, gckind, FINALIZE_STRING);
FinalizeArenaList<JSExternalString>(this, cx, gckind, FINALIZE_EXTERNAL_STRING);
#endif
}
void
JSCompartment::finalizeShapeArenaLists(JSContext *cx)
JSCompartment::finalizeShapeArenaLists(JSContext *cx, JSGCInvocationKind gckind)
{
FinalizeArenaList<Shape>(this, cx, FINALIZE_SHAPE);
FinalizeArenaList<Shape>(this, cx, gckind, FINALIZE_SHAPE);
}
#ifdef JS_THREADSAFE
@ -2032,9 +2275,44 @@ GCHelperThread::replenishAndFreeLater(void *ptr)
Foreground::free_(ptr);
}
void
GCHelperThread::replenishAndFinalizeLater(ArenaList *list)
{
JS_ASSERT(cx);
JS_ASSERT(finalizeCursor == finalizeCursorEnd);
do {
if (finalizeCursor && !finalizeVector.append(finalizeCursorEnd - FREE_ARRAY_LENGTH))
break;
finalizeCursor = (void **) OffTheBooks::malloc_(FREE_ARRAY_SIZE);
if (!finalizeCursor) {
finalizeCursorEnd = NULL;
break;
}
finalizeCursorEnd = finalizeCursor + FREE_ARRAY_LENGTH;
*finalizeCursor++ = list;
*finalizeCursor++ = list->head;
return;
} while (false);
FinalizeArenaList(cx, list, list->head);
}
void
GCHelperThread::doSweep()
{
JS_ASSERT(cx);
if (finalizeCursor) {
void **array = finalizeCursorEnd - FREE_ARRAY_LENGTH;
finalizeElementsAndArray(array, finalizeCursor);
finalizeCursor = finalizeCursorEnd = NULL;
} else {
JS_ASSERT(!finalizeCursorEnd);
}
for (void ***iter = finalizeVector.begin(); iter != finalizeVector.end(); ++iter) {
void **array = *iter;
finalizeElementsAndArray(array, array + FREE_ARRAY_LENGTH);
}
finalizeVector.resize(0);
cx = NULL;
if (freeCursor) {
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
freeElementsAndArray(array, freeCursor);
@ -2189,7 +2467,21 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
JS_ASSERT(gcmarker.getMarkColor() == BLACK);
rt->gcMarkingTracer = &gcmarker;
gcmarker.stackLimit = cx->stackLimit;
#ifdef JS_THREADSAFE
/*
* cx->gcBackgroundFree is set if we need several mark-and-sweep loops to
* finish the GC.
*/
if (!cx->gcBackgroundFree) {
/* Wait until the sweeping from the previois GC finishes. */
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
cx->gcBackgroundFree = &rt->gcHelperThread;
} else {
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
}
JS_ASSERT(!rt->gcHelperThread.sweeping);
cx->gcBackgroundFree->setContext(cx);
#endif
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
r.front()->clearMarkBitmap();
@ -2212,8 +2504,10 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
* Mark weak roots.
*/
while (true) {
if (!js_TraceWatchPoints(&gcmarker))
if (!js_TraceWatchPoints(&gcmarker) &&
!WeakMap::markIteratively(&gcmarker)) {
break;
}
gcmarker.markDelayedChildren();
}
@ -2222,17 +2516,6 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
if (rt->gcCallback)
(void) rt->gcCallback(cx, JSGC_MARK_END);
#ifdef JS_THREADSAFE
/*
* cx->gcBackgroundFree is set if we need several mark-and-sweep loops to
* finish the GC.
*/
if (!cx->gcBackgroundFree) {
/* Wait until the sweeping from the previois GC finishes. */
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
cx->gcBackgroundFree = &rt->gcHelperThread;
}
#endif
#ifdef DEBUG
/* Make sure that we didn't mark an object in another compartment */
if (comp) {
@ -2256,16 +2539,15 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
* the GC.
*/
TIMESTAMP(startSweep);
/* Finalize unreachable (key,value) pairs in all weak maps. */
WeakMap::sweep(cx);
js_SweepAtomState(cx);
/* Finalize watch points associated with unreachable objects. */
js_SweepWatchPoints(cx);
#ifdef DEBUG
/* Save the pre-sweep count of scope-mapped properties. */
rt->liveObjectPropsPreSweep = rt->liveObjectProps;
#endif
/*
* We finalize objects before other GC things to ensure that object's finalizer
* can access them even if they will be freed. Sweep the runtime's property trees
@ -2275,26 +2557,26 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
*/
if (comp) {
comp->sweep(cx, 0);
comp->finalizeObjectArenaLists(cx);
comp->finalizeObjectArenaLists(cx, gckind);
TIMESTAMP(sweepObjectEnd);
comp->finalizeStringArenaLists(cx);
comp->finalizeStringArenaLists(cx, gckind);
TIMESTAMP(sweepStringEnd);
comp->finalizeShapeArenaLists(cx);
comp->finalizeShapeArenaLists(cx, gckind);
TIMESTAMP(sweepShapeEnd);
} else {
SweepCrossCompartmentWrappers(cx);
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
(*c)->finalizeObjectArenaLists(cx);
(*c)->finalizeObjectArenaLists(cx, gckind);
TIMESTAMP(sweepObjectEnd);
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
(*c)->finalizeStringArenaLists(cx);
(*c)->finalizeStringArenaLists(cx, gckind);
TIMESTAMP(sweepStringEnd);
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
(*c)->finalizeShapeArenaLists(cx);
(*c)->finalizeShapeArenaLists(cx, gckind);
TIMESTAMP(sweepShapeEnd);
@ -2553,6 +2835,15 @@ GCUntilDone(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
MarkAndSweep(cx, comp, gckind GCTIMER_ARG);
#ifdef JS_THREADSAFE
JS_ASSERT(cx->gcBackgroundFree == &rt->gcHelperThread);
if (rt->gcPoke) {
AutoLockGC lock(rt);
cx->gcBackgroundFree = NULL;
rt->gcHelperThread.startBackgroundSweep(rt);
}
#endif
// GC again if:
// - another thread, not in a request, called js_GC
// - js_GC was called recursively
@ -2617,6 +2908,9 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
}
{
#ifdef JS_THREADSAFE
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
#endif
/* Lock out other GC allocator and collector invocations. */
AutoLockGC lock(rt);

View File

@ -79,12 +79,18 @@ namespace gc {
/* The kind of GC thing with a finalizer. */
enum FinalizeKind {
FINALIZE_OBJECT0,
FINALIZE_OBJECT0_BACKGROUND,
FINALIZE_OBJECT2,
FINALIZE_OBJECT2_BACKGROUND,
FINALIZE_OBJECT4,
FINALIZE_OBJECT4_BACKGROUND,
FINALIZE_OBJECT8,
FINALIZE_OBJECT8_BACKGROUND,
FINALIZE_OBJECT12,
FINALIZE_OBJECT12_BACKGROUND,
FINALIZE_OBJECT16,
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16,
FINALIZE_OBJECT16_BACKGROUND,
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND,
FINALIZE_FUNCTION,
FINALIZE_SHAPE,
#if JS_HAS_XML_SUPPORT
@ -96,7 +102,7 @@ enum FinalizeKind {
FINALIZE_LIMIT
};
const uintN JS_FINALIZE_OBJECT_LIMIT = 6;
const uintN JS_FINALIZE_OBJECT_LIMIT = 12;
/* Every arena has a header. */
struct ArenaHeader {
@ -190,8 +196,11 @@ struct Arena {
#endif
void init(JSCompartment *compartment, unsigned thingKind);
bool finalize(JSContext *cx);
};
void FinalizeArena(Arena<FreeCell> *a);
/*
* Live objects are marked black. How many other additional colors are available
* depends on the size of the GCThing.
@ -350,6 +359,9 @@ struct ChunkInfo {
EmptyArenaLists emptyArenaLists;
size_t age;
size_t numFree;
#ifdef JS_THREADSAFE
PRLock *chunkLock;
#endif
};
/* Chunks contain arenas and associated data structures (mark bitmap, delayed marking state). */
@ -367,14 +379,14 @@ struct Chunk {
ChunkInfo info;
void clearMarkBitmap();
void init(JSRuntime *rt);
bool init(JSRuntime *rt);
bool unused();
bool hasAvailableArenas();
bool withinArenasRange(Cell *cell);
template <typename T>
Arena<T> *allocateArena(JSCompartment *comp, unsigned thingKind);
Arena<T> *allocateArena(JSContext *cx, unsigned thingKind);
template <typename T>
void releaseArena(Arena<T> *a);
@ -534,11 +546,17 @@ GetFinalizableTraceKind(size_t thingKind)
static const uint8 map[FINALIZE_LIMIT] = {
JSTRACE_OBJECT, /* FINALIZE_OBJECT0 */
JSTRACE_OBJECT, /* FINALIZE_OBJECT0_BACKGROUND */
JSTRACE_OBJECT, /* FINALIZE_OBJECT2 */
JSTRACE_OBJECT, /* FINALIZE_OBJECT2_BACKGROUND */
JSTRACE_OBJECT, /* FINALIZE_OBJECT4 */
JSTRACE_OBJECT, /* FINALIZE_OBJECT4_BACKGROUND */
JSTRACE_OBJECT, /* FINALIZE_OBJECT8 */
JSTRACE_OBJECT, /* FINALIZE_OBJECT8_BACKGROUND */
JSTRACE_OBJECT, /* FINALIZE_OBJECT12 */
JSTRACE_OBJECT, /* FINALIZE_OBJECT12_BACKGROUND */
JSTRACE_OBJECT, /* FINALIZE_OBJECT16 */
JSTRACE_OBJECT, /* FINALIZE_OBJECT16_BACKGROUND */
JSTRACE_OBJECT, /* FINALIZE_FUNCTION */
JSTRACE_SHAPE, /* FINALIZE_SHAPE */
#if JS_HAS_XML_SUPPORT /* FINALIZE_XML */
@ -571,13 +589,16 @@ checkArenaListsForThing(JSCompartment *comp, jsuword thing);
struct ArenaList {
Arena<FreeCell> *head; /* list start */
Arena<FreeCell> *cursor; /* arena with free things */
volatile bool hasToBeFinalized;
inline void init() {
head = NULL;
cursor = NULL;
hasToBeFinalized = false;
}
inline Arena<FreeCell> *getNextWithFreeList() {
inline Arena<FreeCell> *getNextWithFreeList(JSContext *cx) {
JS_ASSERT(!hasToBeFinalized);
Arena<FreeCell> *a;
while (cursor != NULL) {
ArenaHeader *aheader = cursor->header();
@ -863,6 +884,9 @@ js_WaitForGC(JSRuntime *rt);
extern void
js_DestroyScriptsToGC(JSContext *cx, JSCompartment *comp);
extern void
FinalizeArenaList(JSContext *cx, js::gc::ArenaList *arenaList, js::gc::Arena<js::gc::FreeCell> *head);
namespace js {
#ifdef JS_THREADSAFE
@ -881,19 +905,24 @@ class GCHelperThread {
static const size_t FREE_ARRAY_SIZE = size_t(1) << 16;
static const size_t FREE_ARRAY_LENGTH = FREE_ARRAY_SIZE / sizeof(void *);
JSContext *cx;
PRThread* thread;
PRCondVar* wakeup;
PRCondVar* sweepingDone;
bool shutdown;
bool sweeping;
Vector<void **, 16, js::SystemAllocPolicy> freeVector;
void **freeCursor;
void **freeCursorEnd;
Vector<void **, 16, js::SystemAllocPolicy> finalizeVector;
void **finalizeCursor;
void **finalizeCursorEnd;
JS_FRIEND_API(void)
replenishAndFreeLater(void *ptr);
void replenishAndFinalizeLater(js::gc::ArenaList *list);
static void freeElementsAndArray(void **array, void **end) {
JS_ASSERT(array <= end);
for (void **p = array; p != end; ++p)
@ -901,6 +930,17 @@ class GCHelperThread {
js::Foreground::free_(array);
}
void finalizeElementsAndArray(void **array, void **end) {
JS_ASSERT(array <= end);
for (void **p = array; p != end; p += 2) {
js::gc::ArenaList *list = (js::gc::ArenaList *)*p;
js::gc::Arena<js::gc::FreeCell> *head = (js::gc::Arena<js::gc::FreeCell> *)*(p+1);
FinalizeArenaList(cx, list, head);
}
js::Foreground::free_(array);
}
static void threadMain(void* arg);
void threadLoop(JSRuntime *rt);
@ -912,10 +952,13 @@ class GCHelperThread {
wakeup(NULL),
sweepingDone(NULL),
shutdown(false),
sweeping(false),
freeCursor(NULL),
freeCursorEnd(NULL) { }
freeCursorEnd(NULL),
finalizeCursor(NULL),
finalizeCursorEnd(NULL),
sweeping(false) { }
volatile bool sweeping;
bool init(JSRuntime *rt);
void finish(JSRuntime *rt);
@ -932,6 +975,23 @@ class GCHelperThread {
else
replenishAndFreeLater(ptr);
}
void finalizeLater(js::gc::ArenaList *list) {
JS_ASSERT(!list->hasToBeFinalized);
if (!list->head)
return;
list->hasToBeFinalized = true;
JS_ASSERT(!sweeping);
if (finalizeCursor + 1 < finalizeCursorEnd) {
*finalizeCursor++ = list;
*finalizeCursor++ = list->head;
} else {
replenishAndFinalizeLater(list);
}
}
void setContext(JSContext *context) { cx = context; }
};
#endif /* JS_THREADSAFE */

View File

@ -138,16 +138,22 @@ GetGCKindSlots(FinalizeKind thingKind)
/* Using a switch in hopes that thingKind will usually be a compile-time constant. */
switch (thingKind) {
case FINALIZE_OBJECT0:
case FINALIZE_OBJECT0_BACKGROUND:
return 0;
case FINALIZE_OBJECT2:
case FINALIZE_OBJECT2_BACKGROUND:
return 2;
case FINALIZE_OBJECT4:
case FINALIZE_OBJECT4_BACKGROUND:
return 4;
case FINALIZE_OBJECT8:
case FINALIZE_OBJECT8_BACKGROUND:
return 8;
case FINALIZE_OBJECT12:
case FINALIZE_OBJECT12_BACKGROUND:
return 12;
case FINALIZE_OBJECT16:
case FINALIZE_OBJECT16_BACKGROUND:
return 16;
default:
JS_NOT_REACHED("Bad object finalize kind");
@ -281,7 +287,8 @@ Mark(JSTracer *trc, T *thing)
JS_ASSERT_IF(trc->context->runtime->gcCurrentCompartment, IS_GC_MARKING_TRACER(trc));
JSRuntime *rt = trc->context->runtime;
JS_ASSERT(thing->arena()->header()->compartment);
JS_ASSERT(thing->arena()->header()->compartment->rt == rt);
/* Don't mark things outside a compartment if we are in a per-compartment GC */
if (rt->gcCurrentCompartment && thing->compartment() != rt->gcCurrentCompartment)
goto out;

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