mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge tm
This commit is contained in:
commit
f629983808
@ -835,6 +835,8 @@ endif
|
|||||||
|
|
||||||
OPTIMIZE_JARS_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/optimizejars.py)
|
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 = $(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_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
|
EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py
|
||||||
|
@ -45,6 +45,10 @@ def generate_precomplete():
|
|||||||
for the location to enumerate and to create the precomplete file.
|
for the location to enumerate and to create the precomplete file.
|
||||||
"""
|
"""
|
||||||
root_path = os.getcwd()
|
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)
|
rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
|
||||||
precomplete_file_path = os.path.join(root_path,"precomplete")
|
precomplete_file_path = os.path.join(root_path,"precomplete")
|
||||||
# open in binary mode to prevent OS specific line endings.
|
# open in binary mode to prevent OS specific line endings.
|
||||||
|
@ -29,13 +29,19 @@ function testCancelInPhase4() {
|
|||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.addEventListener("readystatechange", function(e) {
|
xhr.addEventListener("readystatechange", function(e) {
|
||||||
if (xhr.readyState >= 4) {
|
if (xhr.readyState >= 4) {
|
||||||
xhr.abort();
|
xhr.addEventListener("abort", function() {
|
||||||
SimpleTest.executeSoon(function() {
|
setTimeout(function() {
|
||||||
// This request was cancelled, so the responseText should be empty string
|
// This request was cancelled, so the responseText should be empty string
|
||||||
is(xhr.responseText, "", "Expected empty response to cancelled request");
|
is(xhr.responseText, "", "Expected empty response to cancelled request");
|
||||||
|
|
||||||
// Second request - should be found in cache
|
// Second request - should be found in cache
|
||||||
var xhr2 = new XMLHttpRequest();
|
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.open("GET", url, false); // note : synch-request
|
||||||
xhr2.setRequestHeader("X-Request", "1", false);
|
xhr2.setRequestHeader("X-Request", "1", false);
|
||||||
|
|
||||||
@ -43,11 +49,10 @@ function testCancelInPhase4() {
|
|||||||
catch(e) {
|
catch(e) {
|
||||||
is(xhr2.status, "200", "Exception!");
|
is(xhr2.status, "200", "Exception!");
|
||||||
}
|
}
|
||||||
|
}, 0);
|
||||||
|
}, false);
|
||||||
|
|
||||||
is(xhr2.responseText, "0", "Received fresh value for second request");
|
xhr.abort();
|
||||||
|
|
||||||
testCancelBeforePhase4();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
@ -69,13 +74,19 @@ function testCancelBeforePhase4() {
|
|||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.addEventListener("readystatechange", function(e) {
|
xhr.addEventListener("readystatechange", function(e) {
|
||||||
if (xhr.readyState == 3) {
|
if (xhr.readyState == 3) {
|
||||||
xhr.abort();
|
xhr.addEventListener("abort", function() {
|
||||||
SimpleTest.executeSoon(function() {
|
setTimeout(function() {
|
||||||
// This request was cancelled, so the responseText should be empty string
|
// This request was cancelled, so the responseText should be empty string
|
||||||
is(xhr.responseText, "", "Expected empty response to cancelled request");
|
is(xhr.responseText, "", "Expected empty response to cancelled request");
|
||||||
|
|
||||||
// Second request - should be found in cache
|
// Second request - should be found in cache
|
||||||
var xhr2 = new XMLHttpRequest();
|
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.open("GET", url, false); // note : synch-request
|
||||||
xhr2.setRequestHeader("X-Request", "1", false);
|
xhr2.setRequestHeader("X-Request", "1", false);
|
||||||
|
|
||||||
@ -83,11 +94,10 @@ function testCancelBeforePhase4() {
|
|||||||
catch(e) {
|
catch(e) {
|
||||||
is(xhr2.status, "200", "Exception!");
|
is(xhr2.status, "200", "Exception!");
|
||||||
}
|
}
|
||||||
|
}, 0);
|
||||||
|
}, false);
|
||||||
|
|
||||||
is(xhr2.responseText, "1", "Received cached value for second request");
|
xhr.abort();
|
||||||
|
|
||||||
SimpleTest.finish();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ DIRS += \
|
|||||||
base \
|
base \
|
||||||
src \
|
src \
|
||||||
locales \
|
locales \
|
||||||
plugins \
|
plugins/ipc \
|
||||||
indexedDB \
|
indexedDB \
|
||||||
system \
|
system \
|
||||||
ipc \
|
ipc \
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#
|
#
|
||||||
# ***** END LICENSE BLOCK *****
|
# ***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
DEPTH = ../..
|
DEPTH = ../../..
|
||||||
topsrcdir = @top_srcdir@
|
topsrcdir = @top_srcdir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
@ -157,7 +157,7 @@ public class GeckoInputConnection
|
|||||||
GeckoAppShell.sendEventToGecko(
|
GeckoAppShell.sendEventToGecko(
|
||||||
new GeckoEvent(GeckoEvent.IME_COMPOSITION_END, 0, 0));
|
new GeckoEvent(GeckoEvent.IME_COMPOSITION_END, 0, 0));
|
||||||
mComposing = false;
|
mComposing = false;
|
||||||
mComposingText = null;
|
mComposingText = "";
|
||||||
|
|
||||||
// Make sure caret stays at the same position
|
// Make sure caret stays at the same position
|
||||||
GeckoAppShell.sendEventToGecko(
|
GeckoAppShell.sendEventToGecko(
|
||||||
@ -532,7 +532,7 @@ public class GeckoInputConnection
|
|||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
mComposing = false;
|
mComposing = false;
|
||||||
mComposingText = null;
|
mComposingText = "";
|
||||||
mUpdateRequest = null;
|
mUpdateRequest = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +578,7 @@ public class GeckoInputConnection
|
|||||||
// Is a composition active?
|
// Is a composition active?
|
||||||
boolean mComposing;
|
boolean mComposing;
|
||||||
// Composition text when a composition is active
|
// Composition text when a composition is active
|
||||||
String mComposingText;
|
String mComposingText = "";
|
||||||
// Start index of the composition within the text body
|
// Start index of the composition within the text body
|
||||||
int mCompositionStart;
|
int mCompositionStart;
|
||||||
/* During a composition, we should not alter the real selection,
|
/* During a composition, we should not alter the real selection,
|
||||||
|
@ -55,7 +55,7 @@ EXPORT_LIBRARY = 1
|
|||||||
##
|
##
|
||||||
IPDLDIRS = \
|
IPDLDIRS = \
|
||||||
uriloader/exthandler \
|
uriloader/exthandler \
|
||||||
dom/plugins \
|
dom/plugins/ipc \
|
||||||
dom/ipc \
|
dom/ipc \
|
||||||
dom/src/storage \
|
dom/src/storage \
|
||||||
gfx/layers/ipc \
|
gfx/layers/ipc \
|
||||||
|
@ -670,7 +670,7 @@ ProcessFile(JSContext *cx,
|
|||||||
}
|
}
|
||||||
bufp += strlen(bufp);
|
bufp += strlen(bufp);
|
||||||
lineno++;
|
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. */
|
/* Clear any pending exception from previous failed compiles. */
|
||||||
JS_ClearPendingException(cx);
|
JS_ClearPendingException(cx);
|
||||||
|
227
js/landbranch.pl
227
js/landbranch.pl
@ -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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -125,6 +125,7 @@ DIST_INSTALL = 1
|
|||||||
VPATH = $(srcdir)
|
VPATH = $(srcdir)
|
||||||
|
|
||||||
CPPSRCS = \
|
CPPSRCS = \
|
||||||
|
jsalloc.cpp \
|
||||||
jsanalyze.cpp \
|
jsanalyze.cpp \
|
||||||
jsapi.cpp \
|
jsapi.cpp \
|
||||||
jsarena.cpp \
|
jsarena.cpp \
|
||||||
@ -173,6 +174,7 @@ CPPSRCS = \
|
|||||||
jsstr.cpp \
|
jsstr.cpp \
|
||||||
jstypedarray.cpp \
|
jstypedarray.cpp \
|
||||||
jsutil.cpp \
|
jsutil.cpp \
|
||||||
|
jsweakmap.cpp \
|
||||||
jswrapper.cpp \
|
jswrapper.cpp \
|
||||||
jsxdrapi.cpp \
|
jsxdrapi.cpp \
|
||||||
jsxml.cpp \
|
jsxml.cpp \
|
||||||
@ -185,6 +187,7 @@ INSTALLED_HEADERS = \
|
|||||||
jsautocfg.h \
|
jsautocfg.h \
|
||||||
$(CURDIR)/jsautokw.h \
|
$(CURDIR)/jsautokw.h \
|
||||||
js.msg \
|
js.msg \
|
||||||
|
jsalloc.h \
|
||||||
jsanalyze.h \
|
jsanalyze.h \
|
||||||
jsapi.h \
|
jsapi.h \
|
||||||
jsarray.h \
|
jsarray.h \
|
||||||
@ -252,6 +255,7 @@ INSTALLED_HEADERS = \
|
|||||||
jstl.h \
|
jstl.h \
|
||||||
jshashtable.h \
|
jshashtable.h \
|
||||||
jsversion.h \
|
jsversion.h \
|
||||||
|
jsweakmap.h \
|
||||||
jswrapper.h \
|
jswrapper.h \
|
||||||
jsxdrapi.h \
|
jsxdrapi.h \
|
||||||
jsxml.h \
|
jsxml.h \
|
||||||
@ -611,7 +615,7 @@ endif
|
|||||||
# (it can't be done with %-expansion, because the files we want to skip aren't
|
# (it can't be done with %-expansion, because the files we want to skip aren't
|
||||||
# in the vpath).
|
# in the vpath).
|
||||||
ALL_FILES=$(shell find $(srcdir) \( -name "*.cpp" -o -name "*.h" \) -not -path "*/dist/*")
|
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
|
# js_malloc and friends are only used by other memory managers, and should
|
||||||
# never be used elsewhere directly.
|
# 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
|
# We desire these numbers to go down, not up. See "User guide to memory
|
||||||
# management within SpiderMonkey" in jsutil.h.
|
# 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_}" $^
|
"in Makefile.in" "{cx,rt}->{new_,new_array,malloc_,calloc_,realloc_}" $^
|
||||||
# This should go to zero, if possible.
|
# 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}" $^
|
"in Makefile.in" "{cx,rt}->{free_,delete_,array_delete}" $^
|
||||||
|
|
||||||
ifneq ($(OS_ARCH),WINNT) # FIXME: this should be made work on Windows too.
|
ifneq ($(OS_ARCH),WINNT) # FIXME: this should be made work on Windows too.
|
||||||
|
@ -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
|
|
186
js/src/config.mk
186
js/src/config.mk
@ -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
|
|
||||||
|
|
@ -835,6 +835,8 @@ endif
|
|||||||
|
|
||||||
OPTIMIZE_JARS_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/optimizejars.py)
|
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 = $(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_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
|
EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py
|
||||||
|
56
js/src/jsalloc.cpp
Normal file
56
js/src/jsalloc.cpp
Normal 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
119
js/src/jsalloc.h
Normal 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_ */
|
@ -84,6 +84,7 @@
|
|||||||
#include "prmjtime.h"
|
#include "prmjtime.h"
|
||||||
#include "jsstaticcheck.h"
|
#include "jsstaticcheck.h"
|
||||||
#include "jsvector.h"
|
#include "jsvector.h"
|
||||||
|
#include "jsweakmap.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
#include "jstypedarray.h"
|
#include "jstypedarray.h"
|
||||||
|
|
||||||
@ -1174,7 +1175,7 @@ JS_ToggleOptions(JSContext *cx, uint32 options)
|
|||||||
JS_PUBLIC_API(const char *)
|
JS_PUBLIC_API(const char *)
|
||||||
JS_GetImplementationVersion(void)
|
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)
|
JS_PUBLIC_API(JSCompartmentCallback)
|
||||||
@ -1676,6 +1677,7 @@ static JSStdName standard_class_atoms[] = {
|
|||||||
#endif
|
#endif
|
||||||
{js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
|
{js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
|
||||||
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass},
|
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass},
|
||||||
|
{js_InitWeakMapClass, EAGER_CLASS_ATOM(WeakMap), &WeakMap::jsclass},
|
||||||
{NULL, 0, NULL, NULL}
|
{NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2057,7 +2059,10 @@ JS_PUBLIC_API(jsval)
|
|||||||
JS_ComputeThis(JSContext *cx, jsval *vp)
|
JS_ComputeThis(JSContext *cx, jsval *vp)
|
||||||
{
|
{
|
||||||
assertSameCompartment(cx, JSValueArray(vp, 2));
|
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 *)
|
JS_PUBLIC_API(void *)
|
||||||
@ -3987,7 +3992,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj)
|
|||||||
AutoIdVector props(cx);
|
AutoIdVector props(cx);
|
||||||
JSIdArray *ida;
|
JSIdArray *ida;
|
||||||
if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &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)
|
for (size_t n = 0; n < size_t(ida->length); ++n)
|
||||||
JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
|
JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
|
||||||
return ida;
|
return ida;
|
||||||
@ -4163,7 +4168,7 @@ JS_IsArrayObject(JSContext *cx, JSObject *obj)
|
|||||||
{
|
{
|
||||||
assertSameCompartment(cx, obj);
|
assertSameCompartment(cx, obj);
|
||||||
return obj->isArray() ||
|
return obj->isArray() ||
|
||||||
(obj->isWrapper() && JSWrapper::wrappedObject(obj)->isArray());
|
(obj->isWrapper() && obj->unwrap()->isArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
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_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;
|
jschar *chars;
|
||||||
JSBool result;
|
JSBool result;
|
||||||
@ -4622,6 +4627,9 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *bytes, size_
|
|||||||
|
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, obj);
|
assertSameCompartment(cx, obj);
|
||||||
|
if (bytes_are_utf8)
|
||||||
|
chars = js_InflateString(cx, bytes, &length, JS_TRUE);
|
||||||
|
else
|
||||||
chars = js_InflateString(cx, bytes, &length);
|
chars = js_InflateString(cx, bytes, &length);
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
@ -5003,7 +5011,7 @@ JS_ExecuteScript(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval)
|
|||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, obj, scriptObj);
|
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);
|
LAST_FRAME_CHECKS(cx, ok);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@ -5036,7 +5044,7 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JS_ASSERT(script->getVersion() == compileVersion);
|
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);
|
LAST_FRAME_CHECKS(cx, ok);
|
||||||
js_DestroyScript(cx, script);
|
js_DestroyScript(cx, script);
|
||||||
return ok;
|
return ok;
|
||||||
@ -5185,7 +5193,7 @@ JS_New(JSContext *cx, JSObject *ctor, uintN argc, jsval *argv)
|
|||||||
if (!cx->stack().pushInvokeArgs(cx, argc, &args))
|
if (!cx->stack().pushInvokeArgs(cx, argc, &args))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
args.callee().setObject(*ctor);
|
args.calleev().setObject(*ctor);
|
||||||
args.thisv().setNull();
|
args.thisv().setNull();
|
||||||
memcpy(args.argv(), argv, argc * sizeof(jsval));
|
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);
|
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_PUBLIC_API(char *)
|
||||||
JS_EncodeString(JSContext *cx, JSString *str)
|
JS_EncodeString(JSContext *cx, JSString *str)
|
||||||
{
|
{
|
||||||
@ -5600,28 +5615,6 @@ JS_TryJSON(JSContext *cx, jsval *vp)
|
|||||||
return js_TryJSON(cx, Valueify(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_PUBLIC_API(JSBool)
|
||||||
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32 len, jsval *vp)
|
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32 len, jsval *vp)
|
||||||
{
|
{
|
||||||
|
@ -1404,6 +1404,7 @@ class Anchor: AnchorPermitted<T> {
|
|||||||
explicit Anchor(T t) { hold = t; }
|
explicit Anchor(T t) { hold = t; }
|
||||||
inline ~Anchor();
|
inline ~Anchor();
|
||||||
T &get() { return hold; }
|
T &get() { return hold; }
|
||||||
|
const T &get() const { return hold; }
|
||||||
void set(const T &t) { hold = t; }
|
void set(const T &t) { hold = t; }
|
||||||
void clear() { hold = 0; }
|
void clear() { hold = 0; }
|
||||||
private:
|
private:
|
||||||
@ -1947,6 +1948,7 @@ struct JSClass {
|
|||||||
#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
|
#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
|
||||||
#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
|
#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
|
||||||
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */
|
#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
|
#define JSCLASS_NEW_RESOLVE_GETS_START (1<<5) /* JSNewResolveOp gets starting
|
||||||
object in prototype chain
|
object in prototype chain
|
||||||
passed in via *objp in/out
|
passed in via *objp in/out
|
||||||
@ -2660,8 +2662,8 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
|
|||||||
* the compiler.
|
* the compiler.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
|
JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8,
|
||||||
const char *bytes, size_t length);
|
JSObject *obj, const char *bytes, size_t length);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSObject *)
|
extern JS_PUBLIC_API(JSObject *)
|
||||||
JS_CompileScript(JSContext *cx, JSObject *obj,
|
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
|
* 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
|
* errors if the character sequence is malformed. If UTF-8 support is
|
||||||
* disabled, the functions deflate and inflate, respectively.
|
* disabled, the functions deflate and inflate, respectively.
|
||||||
|
*
|
||||||
|
* JS_DecodeUTF8() always behaves the same independently of JS_CStringsAreUTF8().
|
||||||
*/
|
*/
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
|
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,
|
JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
|
||||||
size_t *dstlenp);
|
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
|
* A variation on JS_EncodeCharacters where a null terminated string is
|
||||||
* returned that you are expected to call JS_free on when done.
|
* 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);
|
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_PUBLIC_API(JSBool)
|
||||||
JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
|
JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
|
||||||
@ -3298,17 +3306,8 @@ JS_PUBLIC_API(JSBool)
|
|||||||
JS_TryJSON(JSContext *cx, jsval *vp);
|
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_PUBLIC_API(JSBool)
|
||||||
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32 len, jsval *vp);
|
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32 len, jsval *vp);
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "jsalloc.h"
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
#include "jsstdint.h"
|
#include "jsstdint.h"
|
||||||
#include "jsbit.h"
|
#include "jsbit.h"
|
||||||
|
@ -1413,7 +1413,7 @@ array_toString(JSContext *cx, uintN argc, Value *vp)
|
|||||||
if (!cx->stack().pushInvokeArgs(cx, 0, &args))
|
if (!cx->stack().pushInvokeArgs(cx, 0, &args))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
args.callee() = join;
|
args.calleev() = join;
|
||||||
args.thisv().setObject(*obj);
|
args.thisv().setObject(*obj);
|
||||||
|
|
||||||
/* Do the call. */
|
/* Do the call. */
|
||||||
@ -2580,7 +2580,7 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
|||||||
if (v.isObject()) {
|
if (v.isObject()) {
|
||||||
aobj = &v.toObject();
|
aobj = &v.toObject();
|
||||||
if (aobj->isArray() ||
|
if (aobj->isArray() ||
|
||||||
(aobj->isWrapper() && JSWrapper::wrappedObject(aobj)->isArray())) {
|
(aobj->isWrapper() && aobj->unwrap()->isArray())) {
|
||||||
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
|
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
|
||||||
if (!aobj->getProperty(cx, id, tvr.addr()))
|
if (!aobj->getProperty(cx, id, tvr.addr()))
|
||||||
return false;
|
return false;
|
||||||
@ -3026,7 +3026,7 @@ array_isArray(JSContext *cx, uintN argc, Value *vp)
|
|||||||
vp->setBoolean(argc > 0 &&
|
vp->setBoolean(argc > 0 &&
|
||||||
vp[2].isObject() &&
|
vp[2].isObject() &&
|
||||||
((obj = &vp[2].toObject())->isArray() ||
|
((obj = &vp[2].toObject())->isArray() ||
|
||||||
(obj->isWrapper() && JSWrapper::wrappedObject(obj)->isArray())));
|
(obj->isWrapper() && obj->unwrap()->isArray())));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,9 @@ const char *const js_common_atom_names[] = {
|
|||||||
"has", /* hasAtom */
|
"has", /* hasAtom */
|
||||||
"hasOwn", /* hasOwnAtom */
|
"hasOwn", /* hasOwnAtom */
|
||||||
"keys", /* keysAtom */
|
"keys", /* keysAtom */
|
||||||
"iterate" /* iterateAtom */
|
"iterate", /* iterateAtom */
|
||||||
|
|
||||||
|
"WeakMap" /* WeakMapAtom */
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) ==
|
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) ==
|
||||||
|
@ -422,6 +422,8 @@ struct JSAtomState
|
|||||||
JSAtom *keysAtom;
|
JSAtom *keysAtom;
|
||||||
JSAtom *iterateAtom;
|
JSAtom *iterateAtom;
|
||||||
|
|
||||||
|
JSAtom *WeakMapAtom;
|
||||||
|
|
||||||
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
||||||
struct {
|
struct {
|
||||||
JSAtom *XMLListAtom;
|
JSAtom *XMLListAtom;
|
||||||
|
@ -468,7 +468,7 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
|
|||||||
JS_ASSERT(obj->isArray() || obj->isObject());
|
JS_ASSERT(obj->isArray() || obj->isObject());
|
||||||
|
|
||||||
/* Fail if obj is already on the stack. */
|
/* Fail if obj is already on the stack. */
|
||||||
HashSet<JSObject *>::AddPtr p = memory.lookupForAdd(obj);
|
MemorySet::AddPtr p = memory.lookupForAdd(obj);
|
||||||
if (p) {
|
if (p) {
|
||||||
JSContext *cx = context();
|
JSContext *cx = context();
|
||||||
if (callbacks && callbacks->reportError)
|
if (callbacks && callbacks->reportError)
|
||||||
|
@ -179,7 +179,8 @@ struct JSStructuredCloneWriter {
|
|||||||
|
|
||||||
// The "memory" list described in the HTML5 internal structured cloning algorithm.
|
// The "memory" list described in the HTML5 internal structured cloning algorithm.
|
||||||
// memory has the same elements as objs.
|
// 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.
|
// The user defined callbacks that will be used for cloning.
|
||||||
const JSStructuredCloneCallbacks *callbacks;
|
const JSStructuredCloneCallbacks *callbacks;
|
||||||
|
@ -108,29 +108,40 @@
|
|||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
JS_REQUIRES_STACK bool
|
JS_REQUIRES_STACK bool
|
||||||
StackSegment::contains(const JSStackFrame *fp) const
|
StackSegment::contains(const JSStackFrame *fp) const
|
||||||
{
|
{
|
||||||
JS_ASSERT(inContext());
|
JS_ASSERT(inContext());
|
||||||
|
|
||||||
|
if (fp < initialFrame)
|
||||||
|
return false;
|
||||||
|
|
||||||
JSStackFrame *start;
|
JSStackFrame *start;
|
||||||
JSStackFrame *stop;
|
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
JS_ASSERT(cx->hasfp());
|
JS_ASSERT(cx->hasfp() && this == cx->activeSegment());
|
||||||
start = cx->fp();
|
start = cx->fp();
|
||||||
stop = cx->activeSegment()->initialFrame->prev();
|
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(suspendedRegs && suspendedRegs->fp);
|
JS_ASSERT(suspendedRegs && suspendedRegs->fp);
|
||||||
start = suspendedRegs->fp;
|
start = suspendedRegs->fp;
|
||||||
stop = initialFrame->prev();
|
|
||||||
}
|
}
|
||||||
for (JSStackFrame *f = start; f != stop; f = f->prev()) {
|
|
||||||
if (f == fp)
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JS_ASSERT(found);
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JSStackFrame *
|
JSStackFrame *
|
||||||
StackSegment::computeNextFrame(JSStackFrame *fp) const
|
StackSegment::computeNextFrame(JSStackFrame *fp) const
|
||||||
@ -290,8 +301,7 @@ StackSpace::pushSegmentForInvoke(JSContext *cx, uintN argc, InvokeArgsGuard *ag)
|
|||||||
|
|
||||||
ag->cx = cx;
|
ag->cx = cx;
|
||||||
ag->seg = seg;
|
ag->seg = seg;
|
||||||
ag->argv_ = seg->valueRangeBegin() + 2;
|
ImplicitCast<CallArgs>(*ag) = CallArgsFromVp(argc, seg->valueRangeBegin());
|
||||||
ag->argc_ = argc;
|
|
||||||
|
|
||||||
/* Use invokeArgEnd to root [vp, vpend) until the frame is pushed. */
|
/* Use invokeArgEnd to root [vp, vpend) until the frame is pushed. */
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -1019,6 +1029,9 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||||||
JS_ASSERT(!rt->gcRunning);
|
JS_ASSERT(!rt->gcRunning);
|
||||||
|
|
||||||
JS_UNLOCK_GC(rt);
|
JS_UNLOCK_GC(rt);
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
@ -1087,6 +1100,9 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||||||
cx->dstOffsetCache.dumpStats();
|
cx->dstOffsetCache.dumpStats();
|
||||||
#endif
|
#endif
|
||||||
JS_UNLOCK_GC(rt);
|
JS_UNLOCK_GC(rt);
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
rt->gcHelperThread.waitBackgroundSweepEnd(rt);
|
||||||
|
#endif
|
||||||
Foreground::delete_(cx);
|
Foreground::delete_(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1697,7 +1713,7 @@ js_InvokeOperationCallback(JSContext *cx)
|
|||||||
*/
|
*/
|
||||||
bool delayedOutOfMemory;
|
bool delayedOutOfMemory;
|
||||||
JS_LOCK_GC(rt);
|
JS_LOCK_GC(rt);
|
||||||
delayedOutOfMemory = (rt->gcBytes > rt->gcMaxBytes);
|
delayedOutOfMemory = rt->gcBytes > rt->gcMaxBytes;
|
||||||
JS_UNLOCK_GC(rt);
|
JS_UNLOCK_GC(rt);
|
||||||
if (delayedOutOfMemory) {
|
if (delayedOutOfMemory) {
|
||||||
js_ReportOutOfMemory(cx);
|
js_ReportOutOfMemory(cx);
|
||||||
@ -2021,36 +2037,13 @@ JSContext::generatorFor(JSStackFrame *fp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
StackSegment *
|
StackSegment *
|
||||||
JSContext::containingSegment(const JSStackFrame *target)
|
StackSpace::containingSegment(const JSStackFrame *target)
|
||||||
{
|
{
|
||||||
/* The context may have nothing running. */
|
for (StackSegment *seg = currentSegment; seg; seg = seg->getPreviousInMemory()) {
|
||||||
StackSegment *seg = currentSegment;
|
if (seg->contains(target))
|
||||||
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;
|
return seg;
|
||||||
}
|
}
|
||||||
seg = seg->getPreviousInContext();
|
JS_NOT_REACHED("frame not in stack space");
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,27 +118,6 @@ namespace mjit {
|
|||||||
class JaegerCompartment;
|
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
|
* 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
|
* of stack frames and the slots associated with each frame. A segment and its
|
||||||
@ -380,9 +359,7 @@ class StackSegment
|
|||||||
return *initialVarObj;
|
return *initialVarObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
|
JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
|
||||||
#endif
|
|
||||||
|
|
||||||
JSStackFrame *computeNextFrame(JSStackFrame *fp) const;
|
JSStackFrame *computeNextFrame(JSStackFrame *fp) const;
|
||||||
};
|
};
|
||||||
@ -413,7 +390,7 @@ class InvokeArgsGuard : public CallArgs
|
|||||||
*/
|
*/
|
||||||
struct InvokeArgsAlreadyOnTheStack : 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. */
|
/* See StackSpace::pushInvokeFrame. */
|
||||||
@ -683,6 +660,9 @@ class StackSpace
|
|||||||
bool getExecuteFrame(JSContext *cx, JSScript *script, ExecuteFrameGuard *fg) const;
|
bool getExecuteFrame(JSContext *cx, JSScript *script, ExecuteFrameGuard *fg) const;
|
||||||
void pushExecuteFrame(JSContext *cx, JSObject *initialVarObj, ExecuteFrameGuard *fg);
|
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
|
* Since RAII cannot be used for inline frames, callers must manually
|
||||||
* call pushInlineFrame/popInlineFrame.
|
* call pushInlineFrame/popInlineFrame.
|
||||||
@ -1073,8 +1053,8 @@ struct JSRuntime {
|
|||||||
js::RootedValueMap gcRootsHash;
|
js::RootedValueMap gcRootsHash;
|
||||||
js::GCLocks gcLocksHash;
|
js::GCLocks gcLocksHash;
|
||||||
jsrefcount gcKeepAtoms;
|
jsrefcount gcKeepAtoms;
|
||||||
size_t gcBytes;
|
uint32 gcBytes;
|
||||||
size_t gcTriggerBytes;
|
uint32 gcTriggerBytes;
|
||||||
size_t gcLastBytes;
|
size_t gcLastBytes;
|
||||||
size_t gcMaxBytes;
|
size_t gcMaxBytes;
|
||||||
size_t gcMaxMallocBytes;
|
size_t gcMaxMallocBytes;
|
||||||
@ -1086,6 +1066,7 @@ struct JSRuntime {
|
|||||||
int64 gcJitReleaseTime;
|
int64 gcJitReleaseTime;
|
||||||
JSGCMode gcMode;
|
JSGCMode gcMode;
|
||||||
volatile bool gcIsNeeded;
|
volatile bool gcIsNeeded;
|
||||||
|
JSObject *gcWeakMapList;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compartment that triggered GC. If more than one Compatment need GC,
|
* Compartment that triggered GC. If more than one Compatment need GC,
|
||||||
@ -1284,9 +1265,6 @@ struct JSRuntime {
|
|||||||
jsrefcount nonInlineCalls;
|
jsrefcount nonInlineCalls;
|
||||||
jsrefcount constructs;
|
jsrefcount constructs;
|
||||||
|
|
||||||
jsrefcount liveObjectProps;
|
|
||||||
jsrefcount liveObjectPropsPreSweep;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: emptyShapes (in JSCompartment) is init'ed iff at least one
|
* NB: emptyShapes (in JSCompartment) is init'ed iff at least one
|
||||||
* of these envars is set:
|
* of these envars is set:
|
||||||
@ -1372,6 +1350,7 @@ struct JSRuntime {
|
|||||||
|
|
||||||
void setGCTriggerFactor(uint32 factor);
|
void setGCTriggerFactor(uint32 factor);
|
||||||
void setGCLastBytes(size_t lastBytes);
|
void setGCLastBytes(size_t lastBytes);
|
||||||
|
void reduceGCTriggerBytes(uint32 amount);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the system malloc while checking for GC memory pressure and
|
* Call the system malloc while checking for GC memory pressure and
|
||||||
@ -1448,7 +1427,6 @@ struct JSRuntime {
|
|||||||
onTooMuchMalloc();
|
onTooMuchMalloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
/*
|
/*
|
||||||
* The function must be called outside the GC lock.
|
* The function must be called outside the GC lock.
|
||||||
*/
|
*/
|
||||||
@ -1787,12 +1765,6 @@ struct JSContext
|
|||||||
/* Undoes calls to suspendActiveSegment. */
|
/* Undoes calls to suspendActiveSegment. */
|
||||||
void restoreSegment();
|
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. */
|
/* Search the call stack for the nearest frame with static level targetLevel. */
|
||||||
JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
|
JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
|
||||||
JSStackFrame *fp = regs->fp;
|
JSStackFrame *fp = regs->fp;
|
||||||
@ -3173,30 +3145,6 @@ js_RegenerateShapeForGC(JSRuntime *rt)
|
|||||||
|
|
||||||
namespace js {
|
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>
|
template<class T>
|
||||||
class AutoVectorRooter : protected AutoGCRooter
|
class AutoVectorRooter : protected AutoGCRooter
|
||||||
{
|
{
|
||||||
@ -3256,7 +3204,8 @@ class AutoVectorRooter : protected AutoGCRooter
|
|||||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<T, 8> vector;
|
typedef Vector<T, 8> VectorImpl;
|
||||||
|
VectorImpl vector;
|
||||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -246,8 +246,7 @@ StackSpace::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *ag)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ag->cx = cx;
|
ag->cx = cx;
|
||||||
ag->argv_ = vp + 2;
|
ImplicitCast<CallArgs>(*ag) = CallArgsFromVp(argc, vp);
|
||||||
ag->argc_ = argc;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ bool
|
|||||||
JSCompartment::arenaListsAreEmpty()
|
JSCompartment::arenaListsAreEmpty()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < FINALIZE_LIMIT; i++) {
|
for (unsigned i = 0; i < FINALIZE_LIMIT; i++) {
|
||||||
if (!arenas[i].isEmpty())
|
if (!arenas[i].isEmpty() || arenas[i].hasToBeFinalized)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -377,8 +377,8 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||||||
js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT];
|
js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT];
|
||||||
js::gc::FreeLists freeLists;
|
js::gc::FreeLists freeLists;
|
||||||
|
|
||||||
size_t gcBytes;
|
uint32 gcBytes;
|
||||||
size_t gcTriggerBytes;
|
uint32 gcTriggerBytes;
|
||||||
size_t gcLastBytes;
|
size_t gcLastBytes;
|
||||||
|
|
||||||
bool hold;
|
bool hold;
|
||||||
@ -479,12 +479,13 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||||||
void sweep(JSContext *cx, uint32 releaseInterval);
|
void sweep(JSContext *cx, uint32 releaseInterval);
|
||||||
void purge(JSContext *cx);
|
void purge(JSContext *cx);
|
||||||
void finishArenaLists();
|
void finishArenaLists();
|
||||||
void finalizeObjectArenaLists(JSContext *cx);
|
void finalizeObjectArenaLists(JSContext *cx, JSGCInvocationKind gckind);
|
||||||
void finalizeShapeArenaLists(JSContext *cx);
|
void finalizeStringArenaLists(JSContext *cx, JSGCInvocationKind gckind);
|
||||||
void finalizeStringArenaLists(JSContext *cx);
|
void finalizeShapeArenaLists(JSContext *cx, JSGCInvocationKind gckind);
|
||||||
bool arenaListsAreEmpty();
|
bool arenaListsAreEmpty();
|
||||||
|
|
||||||
void setGCLastBytes(size_t lastBytes);
|
void setGCLastBytes(size_t lastBytes);
|
||||||
|
void reduceGCTriggerBytes(uint32 amount);
|
||||||
|
|
||||||
js::DtoaCache dtoaCache;
|
js::DtoaCache dtoaCache;
|
||||||
|
|
||||||
|
@ -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:
|
|
@ -2109,7 +2109,7 @@ date_toJSON(JSContext *cx, uintN argc, Value *vp)
|
|||||||
if (!cx->stack().pushInvokeArgs(cx, 0, &args))
|
if (!cx->stack().pushInvokeArgs(cx, 0, &args))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
args.callee() = toISO;
|
args.calleev() = toISO;
|
||||||
args.thisv().setObject(*obj);
|
args.thisv().setObject(*obj);
|
||||||
|
|
||||||
if (!Invoke(cx, args, 0))
|
if (!Invoke(cx, args, 0))
|
||||||
|
@ -1382,49 +1382,11 @@ JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
|
|||||||
return js_GetScriptedCaller(cx, 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_PUBLIC_API(void *)
|
||||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
|
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
|
||||||
{
|
{
|
||||||
if (fp->annotation() && fp->isScriptFrame()) {
|
if (fp->annotation() && fp->isScriptFrame()) {
|
||||||
JSPrincipals *principals = js_StackFramePrincipals(cx, fp);
|
JSPrincipals *principals = fp->principals(cx);
|
||||||
|
|
||||||
if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
|
if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
|
||||||
/*
|
/*
|
||||||
@ -1449,7 +1411,7 @@ JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
|
|||||||
{
|
{
|
||||||
JSPrincipals *principals;
|
JSPrincipals *principals;
|
||||||
|
|
||||||
principals = js_StackFramePrincipals(cx, fp);
|
principals = fp->principals(cx);
|
||||||
if (!principals)
|
if (!principals)
|
||||||
return NULL;
|
return NULL;
|
||||||
return principals->getPrincipalArray(cx, principals);
|
return principals->getPrincipalArray(cx, principals);
|
||||||
@ -1513,7 +1475,7 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv)
|
|||||||
if (!ac.enter())
|
if (!ac.enter())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!fp->computeThis(cx))
|
if (!ComputeThis(cx, fp))
|
||||||
return false;
|
return false;
|
||||||
*thisv = Jsvalify(fp->thisValue());
|
*thisv = Jsvalify(fp->thisValue());
|
||||||
return true;
|
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
|
* we use a static level that will cause us not to attempt to optimize
|
||||||
* variable references made by this frame.
|
* 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,
|
TCF_COMPILE_N_GO, chars, length,
|
||||||
filename, lineno, cx->findVersion(),
|
filename, lineno, cx->findVersion(),
|
||||||
NULL, UpvarCookie::UPVAR_LEVEL_LIMIT);
|
NULL, UpvarCookie::UPVAR_LEVEL_LIMIT);
|
||||||
@ -1659,7 +1621,7 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
|
|||||||
if (!script)
|
if (!script)
|
||||||
return false;
|
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);
|
js_DestroyScript(cx, script);
|
||||||
return ok;
|
return ok;
|
||||||
|
@ -271,16 +271,6 @@ JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
|
|||||||
extern JS_PUBLIC_API(JSStackFrame *)
|
extern JS_PUBLIC_API(JSStackFrame *)
|
||||||
JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
|
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 *)
|
extern JS_PUBLIC_API(void *)
|
||||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
|
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
|
|||||||
stackDepth = 0;
|
stackDepth = 0;
|
||||||
valueCount = 0;
|
valueCount = 0;
|
||||||
for (fp = js_GetTopStackFrame(cx); fp; fp = fp->prev()) {
|
for (fp = js_GetTopStackFrame(cx); fp; fp = fp->prev()) {
|
||||||
if (fp->scopeChain().compartment() != cx->compartment)
|
if (fp->compartment() != cx->compartment)
|
||||||
break;
|
break;
|
||||||
if (fp->isNonEvalFunctionFrame()) {
|
if (fp->isNonEvalFunctionFrame()) {
|
||||||
Value v = NullValue();
|
Value v = NullValue();
|
||||||
@ -338,7 +338,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
|
|||||||
values = GetStackTraceValueBuffer(priv);
|
values = GetStackTraceValueBuffer(priv);
|
||||||
elem = priv->stackElems;
|
elem = priv->stackElems;
|
||||||
for (fp = js_GetTopStackFrame(cx); fp != fpstop; fp = fp->prev()) {
|
for (fp = js_GetTopStackFrame(cx); fp != fpstop; fp = fp->prev()) {
|
||||||
if (fp->scopeChain().compartment() != cx->compartment)
|
if (fp->compartment() != cx->compartment)
|
||||||
break;
|
break;
|
||||||
if (!fp->isFunctionFrame() || fp->isEvalFrame()) {
|
if (!fp->isFunctionFrame() || fp->isEvalFrame()) {
|
||||||
elem->funName = NULL;
|
elem->funName = NULL;
|
||||||
|
@ -1051,7 +1051,7 @@ CreateEvalCallObject(JSContext *cx, JSStackFrame *fp)
|
|||||||
{
|
{
|
||||||
JSObject *callobj = NewCallObject(cx, fp->script(), fp->scopeChain(), NULL);
|
JSObject *callobj = NewCallObject(cx, fp->script(), fp->scopeChain(), NULL);
|
||||||
if (!callobj)
|
if (!callobj)
|
||||||
return false;
|
return NULL;
|
||||||
|
|
||||||
callobj->setPrivate(fp);
|
callobj->setPrivate(fp);
|
||||||
fp->setScopeChainWithOwnCallObj(*callobj);
|
fp->setScopeChainWithOwnCallObj(*callobj);
|
||||||
@ -1454,7 +1454,7 @@ JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
|
|||||||
if (thisv.isObject()) {
|
if (thisv.isObject()) {
|
||||||
JS_ASSERT(funobj.getFunctionPrivate() == fun);
|
JS_ASSERT(funobj.getFunctionPrivate() == fun);
|
||||||
|
|
||||||
if (&fun->compiledFunObj() == &funobj && fun->methodAtom()) {
|
if (fun->compiledFunObj() == funobj && fun->methodAtom()) {
|
||||||
JSObject *thisp = &thisv.toObject();
|
JSObject *thisp = &thisv.toObject();
|
||||||
JSObject *first_barriered_thisp = NULL;
|
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
|
* In either case we must allow for the method property
|
||||||
* to have been replaced, or its value overwritten.
|
* 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))
|
if (!thisp->methodReadBarrier(cx, *shape, vp))
|
||||||
return false;
|
return false;
|
||||||
calleeValue().setObject(vp->toObject());
|
calleev().setObject(vp->toObject());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1496,7 +1496,7 @@ JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
|
|||||||
clone->hasMethodObj(*thisp)) {
|
clone->hasMethodObj(*thisp)) {
|
||||||
JS_ASSERT(clone != &funobj);
|
JS_ASSERT(clone != &funobj);
|
||||||
*vp = v;
|
*vp = v;
|
||||||
calleeValue().setObject(*clone);
|
calleev().setObject(*clone);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1525,7 +1525,7 @@ JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
|
|||||||
if (!newfunobj)
|
if (!newfunobj)
|
||||||
return false;
|
return false;
|
||||||
newfunobj->setMethodObj(*first_barriered_thisp);
|
newfunobj->setMethodObj(*first_barriered_thisp);
|
||||||
calleeValue().setObject(*newfunobj);
|
calleev().setObject(*newfunobj);
|
||||||
vp->setObject(*newfunobj);
|
vp->setObject(*newfunobj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2140,7 +2140,7 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
/* Push fval, thisv, and the args. */
|
/* Push fval, thisv, and the args. */
|
||||||
args.callee() = fval;
|
args.calleev() = fval;
|
||||||
args.thisv() = thisv;
|
args.thisv() = thisv;
|
||||||
memcpy(args.argv(), argv, argc * sizeof *argv);
|
memcpy(args.argv(), argv, argc * sizeof *argv);
|
||||||
|
|
||||||
@ -2191,7 +2191,7 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Push fval, obj, and aobj's elements as args. */
|
/* Push fval, obj, and aobj's elements as args. */
|
||||||
args.callee() = fval;
|
args.calleev() = fval;
|
||||||
args.thisv() = vp[2];
|
args.thisv() = vp[2];
|
||||||
|
|
||||||
/* Steps 7-8. */
|
/* Steps 7-8. */
|
||||||
@ -2308,7 +2308,7 @@ CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp)
|
|||||||
memcpy(args.argv() + argslen, vp + 2, argc * sizeof(Value));
|
memcpy(args.argv() + argslen, vp + 2, argc * sizeof(Value));
|
||||||
|
|
||||||
/* 15.3.4.5.1, 15.3.4.5.2 step 5. */
|
/* 15.3.4.5.1, 15.3.4.5.2 step 5. */
|
||||||
args.callee().setObject(*target);
|
args.calleev().setObject(*target);
|
||||||
|
|
||||||
if (!constructing)
|
if (!constructing)
|
||||||
args.thisv() = boundThis;
|
args.thisv() = boundThis;
|
||||||
@ -2431,12 +2431,13 @@ OnBadFormal(JSContext *cx, TokenKind tt)
|
|||||||
static JSBool
|
static JSBool
|
||||||
Function(JSContext *cx, uintN argc, Value *vp)
|
Function(JSContext *cx, uintN argc, Value *vp)
|
||||||
{
|
{
|
||||||
|
CallArgs call = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
JS::Anchor<JSObject *> obj(NewFunction(cx, NULL));
|
JS::Anchor<JSObject *> obj(NewFunction(cx, NULL));
|
||||||
if (!obj.get())
|
if (!obj.get())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSObject &callee = JS_CALLEE(cx, vp).toObject();
|
JSObject &calleeParent = *call.callee().getParent();
|
||||||
JSObject &calleeParent = *callee.getParent();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: (new Function) is not lexically closed by its caller, it's just an
|
* 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)
|
if (!fun)
|
||||||
return false;
|
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.
|
* CSP check: whether new Function() is allowed at all.
|
||||||
* Report errors via CSP is done in the script security manager.
|
* 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);
|
Bindings bindings(cx, emptyCallShape);
|
||||||
AutoBindingsRooter root(cx, bindings);
|
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;
|
uintN n = argc ? argc - 1 : 0;
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
/*
|
/*
|
||||||
@ -2637,10 +2615,12 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
|||||||
length = 0;
|
length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_SET_RVAL(cx, vp, ObjectValue(*obj.get()));
|
JSPrincipals *principals = PrincipalsForCompiledCode(call, cx);
|
||||||
return Compiler::compileFunctionBody(cx, fun, principals, &bindings,
|
bool ok = Compiler::compileFunctionBody(cx, fun, principals, &bindings,
|
||||||
chars, length, filename, lineno,
|
chars, length, filename, lineno,
|
||||||
cx->findVersion());
|
cx->findVersion());
|
||||||
|
call.rval().setObject(obj);
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
@ -2665,7 +2645,7 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj)
|
|||||||
const Shape *shape = funobj->nativeLookup(id);
|
const Shape *shape = funobj->nativeLookup(id);
|
||||||
if (!shape) {
|
if (!shape) {
|
||||||
if (!ResolveInterpretedFunctionPrototype(cx, funobj))
|
if (!ResolveInterpretedFunctionPrototype(cx, funobj))
|
||||||
return false;
|
return NULL;
|
||||||
shape = funobj->nativeLookup(id);
|
shape = funobj->nativeLookup(id);
|
||||||
}
|
}
|
||||||
JS_ASSERT(!shape->configurable());
|
JS_ASSERT(!shape->configurable());
|
||||||
|
584
js/src/jsgc.cpp
584
js/src/jsgc.cpp
@ -88,6 +88,7 @@
|
|||||||
#include "jsinterpinlines.h"
|
#include "jsinterpinlines.h"
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
#include "jshashtable.h"
|
#include "jshashtable.h"
|
||||||
|
#include "jsweakmap.h"
|
||||||
|
|
||||||
#include "jsstrinlines.h"
|
#include "jsstrinlines.h"
|
||||||
#include "jscompartment.h"
|
#include "jscompartment.h"
|
||||||
@ -232,16 +233,108 @@ Arena<T>::mark(T *thing, JSTracer *trc)
|
|||||||
return CGCT_VALID;
|
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
|
#ifdef DEBUG
|
||||||
bool
|
bool
|
||||||
checkArenaListsForThing(JSCompartment *comp, void *thing)
|
checkArenaListsForThing(JSCompartment *comp, void *thing)
|
||||||
{
|
{
|
||||||
if (comp->arenas[FINALIZE_OBJECT0].arenasContainThing<JSObject>(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].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].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].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].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].arenasContainThing<JSObject_Slots16>(thing) ||
|
||||||
|
comp->arenas[FINALIZE_OBJECT16_BACKGROUND].arenasContainThing<JSObject_Slots16>(thing) ||
|
||||||
comp->arenas[FINALIZE_FUNCTION].arenasContainThing<JSFunction>(thing) ||
|
comp->arenas[FINALIZE_FUNCTION].arenasContainThing<JSFunction>(thing) ||
|
||||||
comp->arenas[FINALIZE_SHAPE].arenasContainThing<Shape>(thing) ||
|
comp->arenas[FINALIZE_SHAPE].arenasContainThing<Shape>(thing) ||
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
@ -284,13 +377,18 @@ Chunk::clearMarkBitmap()
|
|||||||
PodZero(&bitmaps[0], ArenasPerChunk);
|
PodZero(&bitmaps[0], ArenasPerChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
Chunk::init(JSRuntime *rt)
|
Chunk::init(JSRuntime *rt)
|
||||||
{
|
{
|
||||||
info.runtime = rt;
|
info.runtime = rt;
|
||||||
info.age = 0;
|
info.age = 0;
|
||||||
info.emptyArenaLists.init();
|
info.emptyArenaLists.init();
|
||||||
info.emptyArenaLists.cellFreeList = &arenas[0];
|
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> *arena = &arenas[0];
|
||||||
Arena<FreeCell> *last = &arenas[JS_ARRAY_LENGTH(arenas) - 1];
|
Arena<FreeCell> *last = &arenas[JS_ARRAY_LENGTH(arenas) - 1];
|
||||||
while (arena < last) {
|
while (arena < last) {
|
||||||
@ -307,6 +405,7 @@ Chunk::init(JSRuntime *rt)
|
|||||||
last->header()->isUsed = false;
|
last->header()->isUsed = false;
|
||||||
#endif
|
#endif
|
||||||
info.numFree = ArenasPerChunk;
|
info.numFree = ArenasPerChunk;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -332,20 +431,25 @@ Chunk::withinArenasRange(Cell *cell)
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Arena<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());
|
JS_ASSERT(hasAvailableArenas());
|
||||||
Arena<T> *arena = info.emptyArenaLists.getNext<T>(comp, thingKind);
|
Arena<T> *arena = info.emptyArenaLists.getNext<T>(comp, thingKind);
|
||||||
JS_ASSERT(arena);
|
JS_ASSERT(arena);
|
||||||
JS_ASSERT(arena->header()->isUsed);
|
JS_ASSERT(arena->header()->isUsed);
|
||||||
--info.numFree;
|
--info.numFree;
|
||||||
|
|
||||||
JSRuntime *rt = info.runtime;
|
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)
|
if (comp->gcBytes >= comp->gcTriggerBytes)
|
||||||
TriggerCompartmentGC(comp);
|
TriggerCompartmentGC(comp);
|
||||||
METER(rt->gcStats.nallarenas++);
|
|
||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,15 +458,24 @@ void
|
|||||||
Chunk::releaseArena(Arena<T> *arena)
|
Chunk::releaseArena(Arena<T> *arena)
|
||||||
{
|
{
|
||||||
JSRuntime *rt = info.runtime;
|
JSRuntime *rt = info.runtime;
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
Conditionally<AutoLock> lockIf(rt->gcHelperThread.sweeping, info.chunkLock);
|
||||||
|
#endif
|
||||||
JSCompartment *comp = arena->header()->compartment;
|
JSCompartment *comp = arena->header()->compartment;
|
||||||
METER(rt->gcStats.afree++);
|
METER(rt->gcStats.afree++);
|
||||||
JS_ASSERT(rt->gcStats.nallarenas != 0);
|
JS_ASSERT(rt->gcStats.nallarenas != 0);
|
||||||
METER(rt->gcStats.nallarenas--);
|
METER(JS_ATOMIC_DECREMENT(&rt->gcStats.nallarenas));
|
||||||
JS_ASSERT(rt->gcBytes >= sizeof(Arena<T>));
|
|
||||||
JS_ASSERT(comp->gcBytes >= sizeof(Arena<T>));
|
|
||||||
|
|
||||||
rt->gcBytes -= sizeof(Arena<T>);
|
JS_ASSERT(size_t(rt->gcBytes) >= sizeof(Arena<T>));
|
||||||
comp->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);
|
info.emptyArenaLists.insert((Arena<Cell> *)arena);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
arena->header()->isUsed = false;
|
arena->header()->isUsed = false;
|
||||||
@ -399,6 +512,9 @@ ReleaseGCChunk(JSRuntime *rt, jsuword chunk)
|
|||||||
JS_ASSERT(p);
|
JS_ASSERT(p);
|
||||||
#ifdef MOZ_GCTIMER
|
#ifdef MOZ_GCTIMER
|
||||||
JS_ATOMIC_INCREMENT(&destroyChunkCount);
|
JS_ATOMIC_INCREMENT(&destroyChunkCount);
|
||||||
|
#endif
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
JS_DESTROY_LOCK(((Chunk *)chunk)->info.chunkLock);
|
||||||
#endif
|
#endif
|
||||||
JS_ASSERT(rt->gcStats.nchunks != 0);
|
JS_ASSERT(rt->gcStats.nchunks != 0);
|
||||||
METER(rt->gcStats.nchunks--);
|
METER(rt->gcStats.nchunks--);
|
||||||
@ -423,6 +539,9 @@ ReleaseGCChunk(JSRuntime *rt, Chunk *p)
|
|||||||
JS_ASSERT(p);
|
JS_ASSERT(p);
|
||||||
#ifdef MOZ_GCTIMER
|
#ifdef MOZ_GCTIMER
|
||||||
JS_ATOMIC_INCREMENT(&destroyChunkCount);
|
JS_ATOMIC_INCREMENT(&destroyChunkCount);
|
||||||
|
#endif
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
JS_DESTROY_LOCK(p->info.chunkLock);
|
||||||
#endif
|
#endif
|
||||||
JS_ASSERT(rt->gcStats.nchunks != 0);
|
JS_ASSERT(rt->gcStats.nchunks != 0);
|
||||||
METER(rt->gcStats.nchunks--);
|
METER(rt->gcStats.nchunks--);
|
||||||
@ -453,7 +572,10 @@ PickChunk(JSRuntime *rt)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk->init(rt);
|
if (!chunk->init(rt)) {
|
||||||
|
ReleaseGCChunk(rt, chunk);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
@ -496,7 +618,7 @@ AllocateArena(JSContext *cx, unsigned thingKind)
|
|||||||
}
|
}
|
||||||
cx->compartment->chunk = chunk;
|
cx->compartment->chunk = chunk;
|
||||||
}
|
}
|
||||||
return chunk->allocateArena<T>(cx->compartment, thingKind);
|
return chunk->allocateArena<T>(cx, thingKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
@ -652,21 +774,27 @@ MarkIfGCThingWord(JSTracer *trc, jsuword w, uint32 &thingKind)
|
|||||||
|
|
||||||
switch (thingKind) {
|
switch (thingKind) {
|
||||||
case FINALIZE_OBJECT0:
|
case FINALIZE_OBJECT0:
|
||||||
|
case FINALIZE_OBJECT0_BACKGROUND:
|
||||||
test = MarkCell<JSObject>(cell, trc);
|
test = MarkCell<JSObject>(cell, trc);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT2:
|
case FINALIZE_OBJECT2:
|
||||||
|
case FINALIZE_OBJECT2_BACKGROUND:
|
||||||
test = MarkCell<JSObject_Slots2>(cell, trc);
|
test = MarkCell<JSObject_Slots2>(cell, trc);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT4:
|
case FINALIZE_OBJECT4:
|
||||||
|
case FINALIZE_OBJECT4_BACKGROUND:
|
||||||
test = MarkCell<JSObject_Slots4>(cell, trc);
|
test = MarkCell<JSObject_Slots4>(cell, trc);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT8:
|
case FINALIZE_OBJECT8:
|
||||||
|
case FINALIZE_OBJECT8_BACKGROUND:
|
||||||
test = MarkCell<JSObject_Slots8>(cell, trc);
|
test = MarkCell<JSObject_Slots8>(cell, trc);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT12:
|
case FINALIZE_OBJECT12:
|
||||||
|
case FINALIZE_OBJECT12_BACKGROUND:
|
||||||
test = MarkCell<JSObject_Slots12>(cell, trc);
|
test = MarkCell<JSObject_Slots12>(cell, trc);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT16:
|
case FINALIZE_OBJECT16:
|
||||||
|
case FINALIZE_OBJECT16_BACKGROUND:
|
||||||
test = MarkCell<JSObject_Slots16>(cell, trc);
|
test = MarkCell<JSObject_Slots16>(cell, trc);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_STRING:
|
case FINALIZE_STRING:
|
||||||
@ -874,6 +1002,8 @@ js_FinishGC(JSRuntime *rt)
|
|||||||
rt->compartments.clear();
|
rt->compartments.clear();
|
||||||
rt->atomsCompartment = NULL;
|
rt->atomsCompartment = NULL;
|
||||||
|
|
||||||
|
rt->gcWeakMapList = NULL;
|
||||||
|
|
||||||
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
|
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
|
||||||
ReleaseGCChunk(rt, r.front());
|
ReleaseGCChunk(rt, r.front());
|
||||||
rt->gcChunkSet.clear();
|
rt->gcChunkSet.clear();
|
||||||
@ -1052,6 +1182,15 @@ JSRuntime::setGCLastBytes(size_t lastBytes)
|
|||||||
gcTriggerBytes = (float(gcMaxBytes) < maxtrigger) ? gcMaxBytes : size_t(maxtrigger);
|
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
|
void
|
||||||
JSCompartment::setGCLastBytes(size_t lastBytes)
|
JSCompartment::setGCLastBytes(size_t lastBytes)
|
||||||
{
|
{
|
||||||
@ -1065,6 +1204,15 @@ JSCompartment::setGCLastBytes(size_t lastBytes)
|
|||||||
gcTriggerBytes = (float(rt->gcMaxBytes) < maxtrigger) ? rt->gcMaxBytes : size_t(maxtrigger);
|
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
|
void
|
||||||
FreeLists::purge()
|
FreeLists::purge()
|
||||||
{
|
{
|
||||||
@ -1123,6 +1271,11 @@ RunLastDitchGC(JSContext *cx)
|
|||||||
AutoKeepAtoms keep(rt);
|
AutoKeepAtoms keep(rt);
|
||||||
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL);
|
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;
|
return rt->gcBytes < rt->gcMaxBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1139,6 +1292,10 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool canGC = !JS_ON_TRACE(cx) && !JS_THREAD_DATA(cx)->waiveGCQuota;
|
bool canGC = !JS_ON_TRACE(cx) && !JS_THREAD_DATA(cx)->waiveGCQuota;
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
bool waited = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (canGC && JS_UNLIKELY(NeedLastDitchGC(cx))) {
|
if (canGC && JS_UNLIKELY(NeedLastDitchGC(cx))) {
|
||||||
if (!RunLastDitchGC(cx))
|
if (!RunLastDitchGC(cx))
|
||||||
@ -1155,13 +1312,19 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArenaList *arenaList = GetFinalizableArenaList(compartment, thingKind);
|
ArenaList *arenaList = GetFinalizableArenaList(compartment, thingKind);
|
||||||
Arena<T> *a = reinterpret_cast<Arena<T> *>(arenaList->getNextWithFreeList());
|
#ifdef JS_THREADSAFE
|
||||||
|
try_again:
|
||||||
|
#endif
|
||||||
|
Arena<T> *a = NULL;
|
||||||
|
if (!arenaList->hasToBeFinalized) {
|
||||||
|
a = reinterpret_cast<Arena<T> *>(arenaList->getNextWithFreeList(cx));
|
||||||
if (a) {
|
if (a) {
|
||||||
JS_ASSERT(a->header()->freeList);
|
JS_ASSERT(a->header()->freeList);
|
||||||
JS_ASSERT(sizeof(T) == a->header()->thingSize);
|
JS_ASSERT(sizeof(T) == a->header()->thingSize);
|
||||||
compartment->freeLists.populate(a, thingKind);
|
compartment->freeLists.populate(a, thingKind);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the allocation fails rt->gcIsNeeded will be set and we will run
|
* If the allocation fails rt->gcIsNeeded will be set and we will run
|
||||||
@ -1174,6 +1337,14 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind)
|
|||||||
a->getMarkingDelay()->init();
|
a->getMarkingDelay()->init();
|
||||||
return true;
|
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);
|
} while (canGC);
|
||||||
|
|
||||||
METER(cx->runtime->gcStats.fail++);
|
METER(cx->runtime->gcStats.fail++);
|
||||||
@ -1186,16 +1357,22 @@ RefillFinalizableFreeList(JSContext *cx, unsigned thingKind)
|
|||||||
{
|
{
|
||||||
switch (thingKind) {
|
switch (thingKind) {
|
||||||
case FINALIZE_OBJECT0:
|
case FINALIZE_OBJECT0:
|
||||||
|
case FINALIZE_OBJECT0_BACKGROUND:
|
||||||
return RefillTypedFreeList<JSObject>(cx, thingKind);
|
return RefillTypedFreeList<JSObject>(cx, thingKind);
|
||||||
case FINALIZE_OBJECT2:
|
case FINALIZE_OBJECT2:
|
||||||
|
case FINALIZE_OBJECT2_BACKGROUND:
|
||||||
return RefillTypedFreeList<JSObject_Slots2>(cx, thingKind);
|
return RefillTypedFreeList<JSObject_Slots2>(cx, thingKind);
|
||||||
case FINALIZE_OBJECT4:
|
case FINALIZE_OBJECT4:
|
||||||
|
case FINALIZE_OBJECT4_BACKGROUND:
|
||||||
return RefillTypedFreeList<JSObject_Slots4>(cx, thingKind);
|
return RefillTypedFreeList<JSObject_Slots4>(cx, thingKind);
|
||||||
case FINALIZE_OBJECT8:
|
case FINALIZE_OBJECT8:
|
||||||
|
case FINALIZE_OBJECT8_BACKGROUND:
|
||||||
return RefillTypedFreeList<JSObject_Slots8>(cx, thingKind);
|
return RefillTypedFreeList<JSObject_Slots8>(cx, thingKind);
|
||||||
case FINALIZE_OBJECT12:
|
case FINALIZE_OBJECT12:
|
||||||
|
case FINALIZE_OBJECT12_BACKGROUND:
|
||||||
return RefillTypedFreeList<JSObject_Slots12>(cx, thingKind);
|
return RefillTypedFreeList<JSObject_Slots12>(cx, thingKind);
|
||||||
case FINALIZE_OBJECT16:
|
case FINALIZE_OBJECT16:
|
||||||
|
case FINALIZE_OBJECT16_BACKGROUND:
|
||||||
return RefillTypedFreeList<JSObject_Slots16>(cx, thingKind);
|
return RefillTypedFreeList<JSObject_Slots16>(cx, thingKind);
|
||||||
case FINALIZE_STRING:
|
case FINALIZE_STRING:
|
||||||
return RefillTypedFreeList<JSString>(cx, thingKind);
|
return RefillTypedFreeList<JSString>(cx, thingKind);
|
||||||
@ -1386,21 +1563,27 @@ GCMarker::markDelayedChildren()
|
|||||||
|
|
||||||
switch (a->header()->thingKind) {
|
switch (a->header()->thingKind) {
|
||||||
case FINALIZE_OBJECT0:
|
case FINALIZE_OBJECT0:
|
||||||
|
case FINALIZE_OBJECT0_BACKGROUND:
|
||||||
reinterpret_cast<Arena<JSObject> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSObject> *>(a)->markDelayedChildren(this);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT2:
|
case FINALIZE_OBJECT2:
|
||||||
|
case FINALIZE_OBJECT2_BACKGROUND:
|
||||||
reinterpret_cast<Arena<JSObject_Slots2> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSObject_Slots2> *>(a)->markDelayedChildren(this);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT4:
|
case FINALIZE_OBJECT4:
|
||||||
|
case FINALIZE_OBJECT4_BACKGROUND:
|
||||||
reinterpret_cast<Arena<JSObject_Slots4> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSObject_Slots4> *>(a)->markDelayedChildren(this);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT8:
|
case FINALIZE_OBJECT8:
|
||||||
|
case FINALIZE_OBJECT8_BACKGROUND:
|
||||||
reinterpret_cast<Arena<JSObject_Slots8> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSObject_Slots8> *>(a)->markDelayedChildren(this);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT12:
|
case FINALIZE_OBJECT12:
|
||||||
|
case FINALIZE_OBJECT12_BACKGROUND:
|
||||||
reinterpret_cast<Arena<JSObject_Slots12> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSObject_Slots12> *>(a)->markDelayedChildren(this);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_OBJECT16:
|
case FINALIZE_OBJECT16:
|
||||||
|
case FINALIZE_OBJECT16_BACKGROUND:
|
||||||
reinterpret_cast<Arena<JSObject_Slots16> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSObject_Slots16> *>(a)->markDelayedChildren(this);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_STRING:
|
case FINALIZE_STRING:
|
||||||
@ -1410,7 +1593,7 @@ GCMarker::markDelayedChildren()
|
|||||||
reinterpret_cast<Arena<JSExternalString> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSExternalString> *>(a)->markDelayedChildren(this);
|
||||||
break;
|
break;
|
||||||
case FINALIZE_SHORT_STRING:
|
case FINALIZE_SHORT_STRING:
|
||||||
JS_ASSERT(false);
|
JS_NOT_REACHED("no delayed marking");
|
||||||
break;
|
break;
|
||||||
case FINALIZE_FUNCTION:
|
case FINALIZE_FUNCTION:
|
||||||
reinterpret_cast<Arena<JSFunction> *>(a)->markDelayedChildren(this);
|
reinterpret_cast<Arena<JSFunction> *>(a)->markDelayedChildren(this);
|
||||||
@ -1504,7 +1687,7 @@ AutoIdArray::trace(JSTracer *trc)
|
|||||||
void
|
void
|
||||||
AutoEnumStateRooter::trace(JSTracer *trc)
|
AutoEnumStateRooter::trace(JSTracer *trc)
|
||||||
{
|
{
|
||||||
js::gc::MarkObject(trc, *obj, "js::AutoEnumStateRooter.obj");
|
gc::MarkObject(trc, *obj, "js::AutoEnumStateRooter.obj");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -1585,24 +1768,24 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case VALVECTOR: {
|
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");
|
MarkValueRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STRING:
|
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");
|
MarkString(trc, str, "js::AutoStringRooter.str");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case IDVECTOR: {
|
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");
|
MarkIdRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SHAPEVECTOR: {
|
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");
|
MarkShapeRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1787,7 +1970,7 @@ js_DestroyScriptsToGC(JSContext *cx, JSCompartment *comp)
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void
|
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));
|
JS_STATIC_ASSERT(!(sizeof(T) & Cell::CellMask));
|
||||||
ArenaList *arenaList = GetFinalizableArenaList(comp, thingKind);
|
ArenaList *arenaList = GetFinalizableArenaList(comp, thingKind);
|
||||||
@ -1801,94 +1984,14 @@ FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
|
|||||||
uint32 nlivearenas = 0, nkilledarenas = 0, nthings = 0;
|
uint32 nlivearenas = 0, nkilledarenas = 0, nthings = 0;
|
||||||
#endif
|
#endif
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ArenaHeader *header = a->header();
|
JS_ASSERT(a->header()->thingKind == thingKind);
|
||||||
JS_ASSERT_IF(header->hasFreeThings, header->freeList);
|
bool allClear = a->finalize(cx);
|
||||||
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
|
|
||||||
if (allClear) {
|
if (allClear) {
|
||||||
/*
|
*ap = a->header()->next;
|
||||||
* 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]);
|
|
||||||
a->chunk()->releaseArena(a);
|
a->chunk()->releaseArena(a);
|
||||||
METER(nkilledarenas++);
|
METER(nkilledarenas++);
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(nfree < a->ThingsPerArena);
|
ap = &a->header()->next;
|
||||||
*tailp = NULL;
|
|
||||||
header->freeList = freeList;
|
|
||||||
#ifdef DEBUG
|
|
||||||
header->hasFreeThings = (nfree == 0) ? false : true;
|
|
||||||
#endif
|
|
||||||
ap = &header->next;
|
|
||||||
METER(nlivearenas++);
|
METER(nlivearenas++);
|
||||||
}
|
}
|
||||||
if (!(a = (Arena<T> *) *ap))
|
if (!(a = (Arena<T> *) *ap))
|
||||||
@ -1898,33 +2001,173 @@ FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
|
|||||||
METER(UpdateCompartmentStats(comp, thingKind, nlivearenas, nkilledarenas, nthings));
|
METER(UpdateCompartmentStats(comp, thingKind, nlivearenas, nkilledarenas, nthings));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
template<typename T>
|
||||||
JSCompartment::finalizeObjectArenaLists(JSContext *cx)
|
static void
|
||||||
|
FinalizeArenaListLater(JSContext *cx, ArenaList *arenaList, Arena<FreeCell> *head)
|
||||||
{
|
{
|
||||||
FinalizeArenaList<JSObject>(this, cx, FINALIZE_OBJECT0);
|
JS_STATIC_ASSERT(!(sizeof(T) & Cell::CellMask));
|
||||||
FinalizeArenaList<JSObject_Slots2>(this, cx, FINALIZE_OBJECT2);
|
JS_ASSERT(arenaList->hasToBeFinalized);
|
||||||
FinalizeArenaList<JSObject_Slots4>(this, cx, FINALIZE_OBJECT4);
|
Arena<FreeCell> **ap = &head;
|
||||||
FinalizeArenaList<JSObject_Slots8>(this, cx, FINALIZE_OBJECT8);
|
Arena<T> *a = (Arena<T> *) *ap;
|
||||||
FinalizeArenaList<JSObject_Slots12>(this, cx, FINALIZE_OBJECT12);
|
JS_ASSERT(a);
|
||||||
FinalizeArenaList<JSObject_Slots16>(this, cx, FINALIZE_OBJECT16);
|
#ifdef DEBUG
|
||||||
FinalizeArenaList<JSFunction>(this, cx, FINALIZE_FUNCTION);
|
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
|
#if JS_HAS_XML_SUPPORT
|
||||||
FinalizeArenaList<JSXML>(this, cx, FINALIZE_XML);
|
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, gckind, FINALIZE_XML);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JSCompartment::finalizeStringArenaLists(JSContext *cx)
|
JSCompartment::finalizeStringArenaLists(JSContext *cx, JSGCInvocationKind gckind)
|
||||||
{
|
{
|
||||||
FinalizeArenaList<JSShortString>(this, cx, FINALIZE_SHORT_STRING);
|
#ifdef JS_THREADSAFE
|
||||||
FinalizeArenaList<JSString>(this, cx, FINALIZE_STRING);
|
if (cx->gcBackgroundFree && gckind != GC_LAST_CONTEXT && cx->runtime->state != JSRTS_LANDING) {
|
||||||
FinalizeArenaList<JSExternalString>(this, cx, FINALIZE_EXTERNAL_STRING);
|
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
|
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
|
#ifdef JS_THREADSAFE
|
||||||
@ -2032,9 +2275,44 @@ GCHelperThread::replenishAndFreeLater(void *ptr)
|
|||||||
Foreground::free_(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
|
void
|
||||||
GCHelperThread::doSweep()
|
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) {
|
if (freeCursor) {
|
||||||
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
|
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
|
||||||
freeElementsAndArray(array, freeCursor);
|
freeElementsAndArray(array, freeCursor);
|
||||||
@ -2189,7 +2467,21 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
|||||||
JS_ASSERT(gcmarker.getMarkColor() == BLACK);
|
JS_ASSERT(gcmarker.getMarkColor() == BLACK);
|
||||||
rt->gcMarkingTracer = &gcmarker;
|
rt->gcMarkingTracer = &gcmarker;
|
||||||
gcmarker.stackLimit = cx->stackLimit;
|
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())
|
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
|
||||||
r.front()->clearMarkBitmap();
|
r.front()->clearMarkBitmap();
|
||||||
|
|
||||||
@ -2212,8 +2504,10 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
|||||||
* Mark weak roots.
|
* Mark weak roots.
|
||||||
*/
|
*/
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!js_TraceWatchPoints(&gcmarker))
|
if (!js_TraceWatchPoints(&gcmarker) &&
|
||||||
|
!WeakMap::markIteratively(&gcmarker)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
gcmarker.markDelayedChildren();
|
gcmarker.markDelayedChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2222,17 +2516,6 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
|||||||
if (rt->gcCallback)
|
if (rt->gcCallback)
|
||||||
(void) rt->gcCallback(cx, JSGC_MARK_END);
|
(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
|
#ifdef DEBUG
|
||||||
/* Make sure that we didn't mark an object in another compartment */
|
/* Make sure that we didn't mark an object in another compartment */
|
||||||
if (comp) {
|
if (comp) {
|
||||||
@ -2256,16 +2539,15 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
|||||||
* the GC.
|
* the GC.
|
||||||
*/
|
*/
|
||||||
TIMESTAMP(startSweep);
|
TIMESTAMP(startSweep);
|
||||||
|
|
||||||
|
/* Finalize unreachable (key,value) pairs in all weak maps. */
|
||||||
|
WeakMap::sweep(cx);
|
||||||
|
|
||||||
js_SweepAtomState(cx);
|
js_SweepAtomState(cx);
|
||||||
|
|
||||||
/* Finalize watch points associated with unreachable objects. */
|
/* Finalize watch points associated with unreachable objects. */
|
||||||
js_SweepWatchPoints(cx);
|
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
|
* 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
|
* 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) {
|
if (comp) {
|
||||||
comp->sweep(cx, 0);
|
comp->sweep(cx, 0);
|
||||||
comp->finalizeObjectArenaLists(cx);
|
comp->finalizeObjectArenaLists(cx, gckind);
|
||||||
TIMESTAMP(sweepObjectEnd);
|
TIMESTAMP(sweepObjectEnd);
|
||||||
comp->finalizeStringArenaLists(cx);
|
comp->finalizeStringArenaLists(cx, gckind);
|
||||||
TIMESTAMP(sweepStringEnd);
|
TIMESTAMP(sweepStringEnd);
|
||||||
comp->finalizeShapeArenaLists(cx);
|
comp->finalizeShapeArenaLists(cx, gckind);
|
||||||
TIMESTAMP(sweepShapeEnd);
|
TIMESTAMP(sweepShapeEnd);
|
||||||
} else {
|
} else {
|
||||||
SweepCrossCompartmentWrappers(cx);
|
SweepCrossCompartmentWrappers(cx);
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
||||||
(*c)->finalizeObjectArenaLists(cx);
|
(*c)->finalizeObjectArenaLists(cx, gckind);
|
||||||
|
|
||||||
TIMESTAMP(sweepObjectEnd);
|
TIMESTAMP(sweepObjectEnd);
|
||||||
|
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
||||||
(*c)->finalizeStringArenaLists(cx);
|
(*c)->finalizeStringArenaLists(cx, gckind);
|
||||||
|
|
||||||
TIMESTAMP(sweepStringEnd);
|
TIMESTAMP(sweepStringEnd);
|
||||||
|
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
||||||
(*c)->finalizeShapeArenaLists(cx);
|
(*c)->finalizeShapeArenaLists(cx, gckind);
|
||||||
|
|
||||||
TIMESTAMP(sweepShapeEnd);
|
TIMESTAMP(sweepShapeEnd);
|
||||||
|
|
||||||
@ -2553,6 +2835,15 @@ GCUntilDone(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
|||||||
|
|
||||||
MarkAndSweep(cx, comp, gckind GCTIMER_ARG);
|
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:
|
// GC again if:
|
||||||
// - another thread, not in a request, called js_GC
|
// - another thread, not in a request, called js_GC
|
||||||
// - js_GC was called recursively
|
// - 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. */
|
/* Lock out other GC allocator and collector invocations. */
|
||||||
AutoLockGC lock(rt);
|
AutoLockGC lock(rt);
|
||||||
|
|
||||||
|
@ -79,12 +79,18 @@ namespace gc {
|
|||||||
/* The kind of GC thing with a finalizer. */
|
/* The kind of GC thing with a finalizer. */
|
||||||
enum FinalizeKind {
|
enum FinalizeKind {
|
||||||
FINALIZE_OBJECT0,
|
FINALIZE_OBJECT0,
|
||||||
|
FINALIZE_OBJECT0_BACKGROUND,
|
||||||
FINALIZE_OBJECT2,
|
FINALIZE_OBJECT2,
|
||||||
|
FINALIZE_OBJECT2_BACKGROUND,
|
||||||
FINALIZE_OBJECT4,
|
FINALIZE_OBJECT4,
|
||||||
|
FINALIZE_OBJECT4_BACKGROUND,
|
||||||
FINALIZE_OBJECT8,
|
FINALIZE_OBJECT8,
|
||||||
|
FINALIZE_OBJECT8_BACKGROUND,
|
||||||
FINALIZE_OBJECT12,
|
FINALIZE_OBJECT12,
|
||||||
|
FINALIZE_OBJECT12_BACKGROUND,
|
||||||
FINALIZE_OBJECT16,
|
FINALIZE_OBJECT16,
|
||||||
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16,
|
FINALIZE_OBJECT16_BACKGROUND,
|
||||||
|
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND,
|
||||||
FINALIZE_FUNCTION,
|
FINALIZE_FUNCTION,
|
||||||
FINALIZE_SHAPE,
|
FINALIZE_SHAPE,
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
@ -96,7 +102,7 @@ enum FinalizeKind {
|
|||||||
FINALIZE_LIMIT
|
FINALIZE_LIMIT
|
||||||
};
|
};
|
||||||
|
|
||||||
const uintN JS_FINALIZE_OBJECT_LIMIT = 6;
|
const uintN JS_FINALIZE_OBJECT_LIMIT = 12;
|
||||||
|
|
||||||
/* Every arena has a header. */
|
/* Every arena has a header. */
|
||||||
struct ArenaHeader {
|
struct ArenaHeader {
|
||||||
@ -190,8 +196,11 @@ struct Arena {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void init(JSCompartment *compartment, unsigned thingKind);
|
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
|
* Live objects are marked black. How many other additional colors are available
|
||||||
* depends on the size of the GCThing.
|
* depends on the size of the GCThing.
|
||||||
@ -350,6 +359,9 @@ struct ChunkInfo {
|
|||||||
EmptyArenaLists emptyArenaLists;
|
EmptyArenaLists emptyArenaLists;
|
||||||
size_t age;
|
size_t age;
|
||||||
size_t numFree;
|
size_t numFree;
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
PRLock *chunkLock;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Chunks contain arenas and associated data structures (mark bitmap, delayed marking state). */
|
/* Chunks contain arenas and associated data structures (mark bitmap, delayed marking state). */
|
||||||
@ -367,14 +379,14 @@ struct Chunk {
|
|||||||
ChunkInfo info;
|
ChunkInfo info;
|
||||||
|
|
||||||
void clearMarkBitmap();
|
void clearMarkBitmap();
|
||||||
void init(JSRuntime *rt);
|
bool init(JSRuntime *rt);
|
||||||
|
|
||||||
bool unused();
|
bool unused();
|
||||||
bool hasAvailableArenas();
|
bool hasAvailableArenas();
|
||||||
bool withinArenasRange(Cell *cell);
|
bool withinArenasRange(Cell *cell);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Arena<T> *allocateArena(JSCompartment *comp, unsigned thingKind);
|
Arena<T> *allocateArena(JSContext *cx, unsigned thingKind);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void releaseArena(Arena<T> *a);
|
void releaseArena(Arena<T> *a);
|
||||||
@ -534,11 +546,17 @@ GetFinalizableTraceKind(size_t thingKind)
|
|||||||
|
|
||||||
static const uint8 map[FINALIZE_LIMIT] = {
|
static const uint8 map[FINALIZE_LIMIT] = {
|
||||||
JSTRACE_OBJECT, /* FINALIZE_OBJECT0 */
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT0 */
|
||||||
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT0_BACKGROUND */
|
||||||
JSTRACE_OBJECT, /* FINALIZE_OBJECT2 */
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT2 */
|
||||||
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT2_BACKGROUND */
|
||||||
JSTRACE_OBJECT, /* FINALIZE_OBJECT4 */
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT4 */
|
||||||
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT4_BACKGROUND */
|
||||||
JSTRACE_OBJECT, /* FINALIZE_OBJECT8 */
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT8 */
|
||||||
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT8_BACKGROUND */
|
||||||
JSTRACE_OBJECT, /* FINALIZE_OBJECT12 */
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT12 */
|
||||||
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT12_BACKGROUND */
|
||||||
JSTRACE_OBJECT, /* FINALIZE_OBJECT16 */
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT16 */
|
||||||
|
JSTRACE_OBJECT, /* FINALIZE_OBJECT16_BACKGROUND */
|
||||||
JSTRACE_OBJECT, /* FINALIZE_FUNCTION */
|
JSTRACE_OBJECT, /* FINALIZE_FUNCTION */
|
||||||
JSTRACE_SHAPE, /* FINALIZE_SHAPE */
|
JSTRACE_SHAPE, /* FINALIZE_SHAPE */
|
||||||
#if JS_HAS_XML_SUPPORT /* FINALIZE_XML */
|
#if JS_HAS_XML_SUPPORT /* FINALIZE_XML */
|
||||||
@ -571,13 +589,16 @@ checkArenaListsForThing(JSCompartment *comp, jsuword thing);
|
|||||||
struct ArenaList {
|
struct ArenaList {
|
||||||
Arena<FreeCell> *head; /* list start */
|
Arena<FreeCell> *head; /* list start */
|
||||||
Arena<FreeCell> *cursor; /* arena with free things */
|
Arena<FreeCell> *cursor; /* arena with free things */
|
||||||
|
volatile bool hasToBeFinalized;
|
||||||
|
|
||||||
inline void init() {
|
inline void init() {
|
||||||
head = NULL;
|
head = NULL;
|
||||||
cursor = NULL;
|
cursor = NULL;
|
||||||
|
hasToBeFinalized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Arena<FreeCell> *getNextWithFreeList() {
|
inline Arena<FreeCell> *getNextWithFreeList(JSContext *cx) {
|
||||||
|
JS_ASSERT(!hasToBeFinalized);
|
||||||
Arena<FreeCell> *a;
|
Arena<FreeCell> *a;
|
||||||
while (cursor != NULL) {
|
while (cursor != NULL) {
|
||||||
ArenaHeader *aheader = cursor->header();
|
ArenaHeader *aheader = cursor->header();
|
||||||
@ -863,6 +884,9 @@ js_WaitForGC(JSRuntime *rt);
|
|||||||
extern void
|
extern void
|
||||||
js_DestroyScriptsToGC(JSContext *cx, JSCompartment *comp);
|
js_DestroyScriptsToGC(JSContext *cx, JSCompartment *comp);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
FinalizeArenaList(JSContext *cx, js::gc::ArenaList *arenaList, js::gc::Arena<js::gc::FreeCell> *head);
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#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_SIZE = size_t(1) << 16;
|
||||||
static const size_t FREE_ARRAY_LENGTH = FREE_ARRAY_SIZE / sizeof(void *);
|
static const size_t FREE_ARRAY_LENGTH = FREE_ARRAY_SIZE / sizeof(void *);
|
||||||
|
|
||||||
|
JSContext *cx;
|
||||||
PRThread* thread;
|
PRThread* thread;
|
||||||
PRCondVar* wakeup;
|
PRCondVar* wakeup;
|
||||||
PRCondVar* sweepingDone;
|
PRCondVar* sweepingDone;
|
||||||
bool shutdown;
|
bool shutdown;
|
||||||
bool sweeping;
|
|
||||||
|
|
||||||
Vector<void **, 16, js::SystemAllocPolicy> freeVector;
|
Vector<void **, 16, js::SystemAllocPolicy> freeVector;
|
||||||
void **freeCursor;
|
void **freeCursor;
|
||||||
void **freeCursorEnd;
|
void **freeCursorEnd;
|
||||||
|
Vector<void **, 16, js::SystemAllocPolicy> finalizeVector;
|
||||||
|
void **finalizeCursor;
|
||||||
|
void **finalizeCursorEnd;
|
||||||
|
|
||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(void)
|
||||||
replenishAndFreeLater(void *ptr);
|
replenishAndFreeLater(void *ptr);
|
||||||
|
|
||||||
|
void replenishAndFinalizeLater(js::gc::ArenaList *list);
|
||||||
|
|
||||||
static void freeElementsAndArray(void **array, void **end) {
|
static void freeElementsAndArray(void **array, void **end) {
|
||||||
JS_ASSERT(array <= end);
|
JS_ASSERT(array <= end);
|
||||||
for (void **p = array; p != end; ++p)
|
for (void **p = array; p != end; ++p)
|
||||||
@ -901,6 +930,17 @@ class GCHelperThread {
|
|||||||
js::Foreground::free_(array);
|
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);
|
static void threadMain(void* arg);
|
||||||
|
|
||||||
void threadLoop(JSRuntime *rt);
|
void threadLoop(JSRuntime *rt);
|
||||||
@ -912,10 +952,13 @@ class GCHelperThread {
|
|||||||
wakeup(NULL),
|
wakeup(NULL),
|
||||||
sweepingDone(NULL),
|
sweepingDone(NULL),
|
||||||
shutdown(false),
|
shutdown(false),
|
||||||
sweeping(false),
|
|
||||||
freeCursor(NULL),
|
freeCursor(NULL),
|
||||||
freeCursorEnd(NULL) { }
|
freeCursorEnd(NULL),
|
||||||
|
finalizeCursor(NULL),
|
||||||
|
finalizeCursorEnd(NULL),
|
||||||
|
sweeping(false) { }
|
||||||
|
|
||||||
|
volatile bool sweeping;
|
||||||
bool init(JSRuntime *rt);
|
bool init(JSRuntime *rt);
|
||||||
void finish(JSRuntime *rt);
|
void finish(JSRuntime *rt);
|
||||||
|
|
||||||
@ -932,6 +975,23 @@ class GCHelperThread {
|
|||||||
else
|
else
|
||||||
replenishAndFreeLater(ptr);
|
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 */
|
#endif /* JS_THREADSAFE */
|
||||||
|
@ -138,16 +138,22 @@ GetGCKindSlots(FinalizeKind thingKind)
|
|||||||
/* Using a switch in hopes that thingKind will usually be a compile-time constant. */
|
/* Using a switch in hopes that thingKind will usually be a compile-time constant. */
|
||||||
switch (thingKind) {
|
switch (thingKind) {
|
||||||
case FINALIZE_OBJECT0:
|
case FINALIZE_OBJECT0:
|
||||||
|
case FINALIZE_OBJECT0_BACKGROUND:
|
||||||
return 0;
|
return 0;
|
||||||
case FINALIZE_OBJECT2:
|
case FINALIZE_OBJECT2:
|
||||||
|
case FINALIZE_OBJECT2_BACKGROUND:
|
||||||
return 2;
|
return 2;
|
||||||
case FINALIZE_OBJECT4:
|
case FINALIZE_OBJECT4:
|
||||||
|
case FINALIZE_OBJECT4_BACKGROUND:
|
||||||
return 4;
|
return 4;
|
||||||
case FINALIZE_OBJECT8:
|
case FINALIZE_OBJECT8:
|
||||||
|
case FINALIZE_OBJECT8_BACKGROUND:
|
||||||
return 8;
|
return 8;
|
||||||
case FINALIZE_OBJECT12:
|
case FINALIZE_OBJECT12:
|
||||||
|
case FINALIZE_OBJECT12_BACKGROUND:
|
||||||
return 12;
|
return 12;
|
||||||
case FINALIZE_OBJECT16:
|
case FINALIZE_OBJECT16:
|
||||||
|
case FINALIZE_OBJECT16_BACKGROUND:
|
||||||
return 16;
|
return 16;
|
||||||
default:
|
default:
|
||||||
JS_NOT_REACHED("Bad object finalize kind");
|
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));
|
JS_ASSERT_IF(trc->context->runtime->gcCurrentCompartment, IS_GC_MARKING_TRACER(trc));
|
||||||
|
|
||||||
JSRuntime *rt = trc->context->runtime;
|
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 */
|
/* Don't mark things outside a compartment if we are in a per-compartment GC */
|
||||||
if (rt->gcCurrentCompartment && thing->compartment() != rt->gcCurrentCompartment)
|
if (rt->gcCurrentCompartment && thing->compartment() != rt->gcCurrentCompartment)
|
||||||
goto out;
|
goto out;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user