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