зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-i to m-c
This commit is contained in:
Коммит
f156befe0b
|
@ -798,3 +798,7 @@ bin/libfreebl_32int64_3.so
|
|||
@BINPATH@/metro/defaults
|
||||
@BINPATH@/metro/modules
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_ASAN
|
||||
@BINPATH@/llvm-symbolizer
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,7 @@ dnl If this is a mozilla-central, we'll find the virtualenv in the top
|
|||
dnl source directory. If this is a SpiderMonkey build, we assume we're at
|
||||
dnl js/src and try to find the virtualenv from the mozilla-central root.
|
||||
for base in $MOZILLA_CENTRAL_PATH $_topsrcdir $_topsrcdir/../..; do
|
||||
possible=$base/build/virtualenv/populate_virtualenv.py
|
||||
possible=$base/python/mozbuild/mozbuild/virtualenv.py
|
||||
|
||||
if test -e $possible; then
|
||||
_virtualenv_topsrcdir=$base
|
||||
|
@ -53,7 +53,8 @@ if test -z $DONT_POPULATE_VIRTUALENV; then
|
|||
dnl virtualenv is present and up to date. It sanitizes the environment
|
||||
dnl for us, so we don't need to clean anything out.
|
||||
$PYTHON $_virtualenv_populate_path \
|
||||
$_virtualenv_topsrcdir $MOZ_BUILD_ROOT $MOZ_BUILD_ROOT/_virtualenv || exit 1
|
||||
$_virtualenv_topsrcdir $MOZ_BUILD_ROOT $MOZ_BUILD_ROOT/_virtualenv \
|
||||
$_virtualenv_topsrcdir/build/virtualenv_packages.txt || exit 1
|
||||
|
||||
case "$host_os" in
|
||||
mingw*)
|
||||
|
|
|
@ -512,6 +512,12 @@ class Automation(object):
|
|||
|
||||
# ASan specific environment stuff
|
||||
if self.IS_ASAN and (self.IS_LINUX or self.IS_MAC):
|
||||
# Symbolizer support
|
||||
llvmsym = os.path.join(xrePath, "llvm-symbolizer")
|
||||
if os.path.isfile(llvmsym):
|
||||
env["ASAN_SYMBOLIZER_PATH"] = llvmsym
|
||||
self.log.info("INFO | automation.py | ASan using symbolizer at %s", llvmsym)
|
||||
|
||||
try:
|
||||
totalMemory = int(os.popen("free").readlines()[1].split()[1])
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
mozilla_dir = os.path.normpath(os.path.join(here, '..', '..'))
|
||||
|
||||
import mdn_theme
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
]
|
||||
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = u'Mozilla Build System'
|
||||
year = datetime.now().year
|
||||
copyright = u'%s, Mozilla Foundation, CC BY-SA 3.0' % year
|
||||
|
||||
# Grab the version from the source tree's milestone.
|
||||
with open(os.path.join(mozilla_dir, 'config', 'milestone.txt'), 'rt') as fh:
|
||||
for line in fh:
|
||||
line = line.strip()
|
||||
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
|
||||
release = line
|
||||
break
|
||||
|
||||
version = re.sub(r'[ab]\d+$', '', release)
|
||||
|
||||
exclude_patterns = ['_build']
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
html_theme_path = [mdn_theme.get_theme_dir()]
|
||||
html_theme = 'mdn'
|
||||
|
||||
html_static_path = ['_static']
|
||||
htmlhelp_basename = 'MozillaBuildSystemdoc'
|
|
@ -0,0 +1,28 @@
|
|||
========
|
||||
Glossary
|
||||
========
|
||||
|
||||
.. glossary::
|
||||
:sorted:
|
||||
|
||||
object directory
|
||||
A directory holding the output of the build system. The build
|
||||
system attempts to isolate all file modifications to this
|
||||
directory. By convention, object directories are commonly
|
||||
directories under the source directory prefixed with **obj-**.
|
||||
e.g. **obj-firefox**.
|
||||
|
||||
mozconfig
|
||||
A shell script used to configure the build system.
|
||||
|
||||
configure
|
||||
A generated shell script which detects the current system
|
||||
environment, applies a requested set of build configuration
|
||||
options, and writes out metadata to be consumed by the build
|
||||
system.
|
||||
|
||||
config.status
|
||||
An executable file produced by **configure** that takes the
|
||||
generated build config and writes out files used to build the
|
||||
tree. Traditionally, config.status writes out a bunch of
|
||||
Makefiles.
|
|
@ -0,0 +1,41 @@
|
|||
==================================
|
||||
Mozilla Build System Documentation
|
||||
==================================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
glossary
|
||||
|
||||
Important Concepts
|
||||
==================
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
Mozconfig Files <mozconfigs>
|
||||
Profile Guided Optimization <pgo>
|
||||
|
||||
mozbuild
|
||||
========
|
||||
|
||||
mozbuild is a Python package containing a lot of the code for the
|
||||
Mozilla build system.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
mozbuild/index
|
||||
mozbuild/frontend
|
||||
mozbuild/dumbmake
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
===============
|
||||
mozconfig Files
|
||||
===============
|
||||
|
||||
mozconfig files are used to configure how a build works.
|
||||
|
||||
mozconfig files are actually shell scripts. They are executed in a
|
||||
special context with specific variables and functions exposed to them.
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
The following special functions are available to a mozconfig script.
|
||||
|
||||
ac_add_options
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
This function is used to declare extra options/arguments to pass into
|
||||
configure.
|
||||
|
||||
e.g.::
|
||||
|
||||
ac_add_options --disable-tests
|
||||
ac_add_options --enable-optimize
|
||||
|
||||
mk_add_options
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
This function is used to inject statements into client.mk for execution.
|
||||
It is typically used to define variables, notably the object directory.
|
||||
|
||||
e.g.::
|
||||
|
||||
mk_add_options AUTOCLOBBER=1
|
||||
|
||||
ac_add_options
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
This is a variant of ac_add_options() which only adds configure options
|
||||
for a specified application. This is only used when building multiple
|
||||
applications through client.mk. This function is typically not needed.
|
||||
|
||||
Special mk_add_options Variables
|
||||
--------------------------------
|
||||
|
||||
For historical reasons, the method for communicating certain
|
||||
well-defined variables is via mk_add_options(). In this section, we
|
||||
document what those special variables are.
|
||||
|
||||
MOZ_OBJDIR
|
||||
^^^^^^^^^^
|
||||
|
||||
This variable is used to define the :term:`object directory` for the current
|
||||
build.
|
||||
|
||||
Finding the active mozconfig
|
||||
============================
|
||||
|
||||
Multiple mozconfig files can exist to provide different configuration
|
||||
options for different tasks. The rules for finding the active mozconfig
|
||||
are defined in the
|
||||
:py:func:`mozbuild.mozconfig.MozconfigLoader.find_mozconfig` method:
|
||||
|
||||
.. autoclass:: mozbuild.mozconfig.MozconfigLoader
|
||||
:members: find_mozconfig
|
|
@ -0,0 +1,40 @@
|
|||
.. _pgo:
|
||||
|
||||
===========================
|
||||
Profile Guided Optimization
|
||||
===========================
|
||||
|
||||
:abbr:`PGO (Profile Guided Optimization)` is the process of adding
|
||||
probes to a compiled binary, running said binary, then using the
|
||||
run-time information to *recompile* the binary to (hopefully) make it
|
||||
faster.
|
||||
|
||||
How PGO Builds Work
|
||||
===================
|
||||
|
||||
The supported interface for invoking a PGO build is to evaluate the
|
||||
*build* target of client.mk with *MOZ_PGO* defined. e.g.::
|
||||
|
||||
$ make -f client.mk MOZ_PGO=1
|
||||
|
||||
This is equivalent to::
|
||||
|
||||
$ make -f client.mk profiledbuild
|
||||
|
||||
Which is roughly equivalent to:
|
||||
|
||||
#. Perform a build with *MOZ_PROFILE_GENERATE=1* and *MOZ_PGO_INSTRUMENTED=1*
|
||||
#. Package with *MOZ_PGO_INSTRUMENTED=1*
|
||||
#. Performing a run of the instrumented binaries
|
||||
#. $ make maybe_clobber_profiledbuild
|
||||
#. Perform a build with *MOZ_PROFILE_USE=1*
|
||||
|
||||
Differences between toolchains
|
||||
==============================
|
||||
|
||||
There are some implementation differences depending on the compiler
|
||||
toolchain being used.
|
||||
|
||||
The *maybe_clobber_profiledbuild* step gets its name because of a
|
||||
difference. On Windows, this step merely moves some *.pgc* files around.
|
||||
Using GCC or Clang, it is equivalent to a *make clean*.
|
|
@ -6,6 +6,14 @@
|
|||
|
||||
SDK_BINARY = run-mozilla.sh
|
||||
|
||||
ifneq ($(LLVM_SYMBOLIZER),)
|
||||
# Install a copy of the llvm-symbolizer binary to dist/bin, so it can
|
||||
# be used for symbolizing traces for e.g. AddressSanitizer
|
||||
LLVMSYM_EXECUTABLES=$(LLVM_SYMBOLIZER)
|
||||
LLVMSYM_DEST=$(FINAL_TARGET)
|
||||
INSTALL_TARGETS += LLVMSYM
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs:: $(srcdir)/run-mozilla.sh
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# Use Clang as specified in manifest
|
||||
export CC="$topsrcdir/clang/bin/clang -fgnu89-inline"
|
||||
export CXX="$topsrcdir/clang/bin/clang++"
|
||||
export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
|
||||
|
||||
# Mandatory flags for ASan
|
||||
export ASANFLAGS="-fsanitize=address -Dxmalloc=myxmalloc -fPIC"
|
||||
|
|
|
@ -325,8 +325,8 @@ CONFIG_STATUS_DEPS := \
|
|||
$(TOPSRCDIR)/config/milestone.txt \
|
||||
$(TOPSRCDIR)/js/src/config/milestone.txt \
|
||||
$(TOPSRCDIR)/browser/config/version.txt \
|
||||
$(TOPSRCDIR)/build/virtualenv/packages.txt \
|
||||
$(TOPSRCDIR)/build/virtualenv/populate_virtualenv.py \
|
||||
$(TOPSRCDIR)/build/virtualenv_packages.txt \
|
||||
$(TOPSRCDIR)/python/mozbuild/mozbuild/virtualenv.py \
|
||||
$(TOPSRCDIR)/testing/mozbase/packages.txt \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -1212,8 +1212,10 @@ MOZ_ARG_ENABLE_BOOL(address-sanitizer,
|
|||
if test -n "$MOZ_ASAN"; then
|
||||
MOZ_LLVM_HACKS=1
|
||||
AC_DEFINE(MOZ_ASAN)
|
||||
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
||||
fi
|
||||
AC_SUBST(MOZ_ASAN)
|
||||
AC_SUBST(LLVM_SYMBOLIZER)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable hacks required for LLVM instrumentations
|
||||
|
@ -1235,7 +1237,12 @@ dnl ========================================================
|
|||
if test "$GNU_CC"; then
|
||||
# Per bug 719659 comment 2, some of the headers on ancient build machines
|
||||
# may require gnu89 inline semantics. But otherwise, we use C99.
|
||||
CFLAGS="$CFLAGS -std=gnu99 -fgnu89-inline"
|
||||
# But on OS X we just use C99 plus GNU extensions, in order to fix
|
||||
# bug 917526.
|
||||
CFLAGS="$CFLAGS -std=gnu99"
|
||||
if test "${OS_ARCH}" != Darwin; then
|
||||
CFLAGS="$CFLAGS -fgnu89-inline"
|
||||
fi
|
||||
# FIXME: Let us build with strict aliasing. bug 414641.
|
||||
CFLAGS="$CFLAGS -fno-strict-aliasing"
|
||||
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsIFile.h"
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -298,11 +298,18 @@ JITTEST_VALGRIND_FLAG = --valgrind
|
|||
endif
|
||||
endif
|
||||
|
||||
ifdef MOZ_ASAN
|
||||
ifneq ($(LLVM_SYMBOLIZER),)
|
||||
# Use the LLVM symbolizer when running jit-tests under ASan, if available
|
||||
JITTEST_ASAN_ENV=ASAN_SYMBOLIZER_PATH='$(LLVM_SYMBOLIZER)'
|
||||
endif
|
||||
endif
|
||||
|
||||
check-style::
|
||||
(cd $(srcdir) && $(PYTHON) config/check_spidermonkey_style.py);
|
||||
|
||||
check-jit-test::
|
||||
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \
|
||||
$(JITTEST_ASAN_ENV) $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \
|
||||
--no-slow --no-progress --tinderbox --tbpl $(JITTEST_VALGRIND_FLAG) \
|
||||
$(DIST)/bin/$(JS_SHELL_NAME)$(BIN_SUFFIX)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ dnl If this is a mozilla-central, we'll find the virtualenv in the top
|
|||
dnl source directory. If this is a SpiderMonkey build, we assume we're at
|
||||
dnl js/src and try to find the virtualenv from the mozilla-central root.
|
||||
for base in $MOZILLA_CENTRAL_PATH $_topsrcdir $_topsrcdir/../..; do
|
||||
possible=$base/build/virtualenv/populate_virtualenv.py
|
||||
possible=$base/python/mozbuild/mozbuild/virtualenv.py
|
||||
|
||||
if test -e $possible; then
|
||||
_virtualenv_topsrcdir=$base
|
||||
|
@ -53,7 +53,8 @@ if test -z $DONT_POPULATE_VIRTUALENV; then
|
|||
dnl virtualenv is present and up to date. It sanitizes the environment
|
||||
dnl for us, so we don't need to clean anything out.
|
||||
$PYTHON $_virtualenv_populate_path \
|
||||
$_virtualenv_topsrcdir $MOZ_BUILD_ROOT $MOZ_BUILD_ROOT/_virtualenv || exit 1
|
||||
$_virtualenv_topsrcdir $MOZ_BUILD_ROOT $MOZ_BUILD_ROOT/_virtualenv \
|
||||
$_virtualenv_topsrcdir/build/virtualenv_packages.txt || exit 1
|
||||
|
||||
case "$host_os" in
|
||||
mingw*)
|
||||
|
|
|
@ -260,7 +260,7 @@ StructTypeRepresentation::init(JSContext *cx,
|
|||
|
||||
JSObject *
|
||||
TypeRepresentation::addToTableOrFree(JSContext *cx,
|
||||
TypeRepresentationSet::AddPtr &p)
|
||||
TypeRepresentationHash::AddPtr &p)
|
||||
{
|
||||
JS_ASSERT(!ownerObject_);
|
||||
|
||||
|
@ -298,7 +298,7 @@ ScalarTypeRepresentation::Create(JSContext *cx,
|
|||
JSCompartment *comp = cx->compartment();
|
||||
|
||||
ScalarTypeRepresentation sample(type);
|
||||
TypeRepresentationSet::AddPtr p = comp->typeReprs.lookupForAdd(&sample);
|
||||
TypeRepresentationHash::AddPtr p = comp->typeReprs.lookupForAdd(&sample);
|
||||
if (p)
|
||||
return (*p)->ownerObject();
|
||||
|
||||
|
@ -332,7 +332,7 @@ ArrayTypeRepresentation::Create(JSContext *cx,
|
|||
}
|
||||
|
||||
ArrayTypeRepresentation sample(element, length);
|
||||
TypeRepresentationSet::AddPtr p = comp->typeReprs.lookupForAdd(&sample);
|
||||
TypeRepresentationHash::AddPtr p = comp->typeReprs.lookupForAdd(&sample);
|
||||
if (p)
|
||||
return (*p)->ownerObject();
|
||||
|
||||
|
@ -364,7 +364,7 @@ StructTypeRepresentation::Create(JSContext *cx,
|
|||
if (!ptr->init(cx, ids, typeReprOwners))
|
||||
return NULL;
|
||||
|
||||
TypeRepresentationSet::AddPtr p = comp->typeReprs.lookupForAdd(ptr);
|
||||
TypeRepresentationHash::AddPtr p = comp->typeReprs.lookupForAdd(ptr);
|
||||
if (p) {
|
||||
js_free(ptr); // do not finalize, not present in the table
|
||||
return (*p)->ownerObject();
|
||||
|
@ -540,10 +540,10 @@ StructTypeRepresentation::appendStringStruct(JSContext *cx, StringBuffer &conten
|
|||
// Misc
|
||||
|
||||
const StructField *
|
||||
StructTypeRepresentation::fieldNamed(HandleId id) const
|
||||
StructTypeRepresentation::fieldNamed(jsid id) const
|
||||
{
|
||||
for (size_t i = 0; i < fieldCount(); i++) {
|
||||
if (field(i).id.get() == id.get())
|
||||
if (field(i).id.get() == id)
|
||||
return &field(i);
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -85,7 +85,7 @@ struct TypeRepresentationHasher
|
|||
|
||||
typedef js::HashSet<TypeRepresentation *,
|
||||
TypeRepresentationHasher,
|
||||
RuntimeAllocPolicy> TypeRepresentationSet;
|
||||
RuntimeAllocPolicy> TypeRepresentationHash;
|
||||
|
||||
class TypeRepresentation {
|
||||
public:
|
||||
|
@ -102,7 +102,7 @@ class TypeRepresentation {
|
|||
size_t alignment_;
|
||||
Kind kind_;
|
||||
|
||||
JSObject *addToTableOrFree(JSContext *cx, TypeRepresentationSet::AddPtr &p);
|
||||
JSObject *addToTableOrFree(JSContext *cx, TypeRepresentationHash::AddPtr &p);
|
||||
|
||||
private:
|
||||
static const Class class_;
|
||||
|
@ -290,7 +290,7 @@ class StructTypeRepresentation : public TypeRepresentation {
|
|||
return fields()[i];
|
||||
}
|
||||
|
||||
const StructField *fieldNamed(HandleId id) const;
|
||||
const StructField *fieldNamed(jsid id) const;
|
||||
|
||||
static JSObject *Create(JSContext *cx,
|
||||
AutoIdVector &ids,
|
||||
|
|
|
@ -2366,3 +2366,10 @@ BinaryBlock::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
BinaryBlock::dataOffset()
|
||||
{
|
||||
return JSObject::getPrivateDataOffset(BLOCK_RESERVED_SLOTS + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -197,6 +197,10 @@ class BinaryBlock
|
|||
public:
|
||||
static const Class class_;
|
||||
|
||||
// Returns the offset in bytes within the object where the `void*`
|
||||
// pointer can be found.
|
||||
static size_t dataOffset();
|
||||
|
||||
static bool isBlock(HandleObject val);
|
||||
static uint8_t *mem(HandleObject val);
|
||||
|
||||
|
|
|
@ -1061,7 +1061,12 @@ dnl ========================================================
|
|||
if test "$GNU_CC"; then
|
||||
# Per bug 719659 comment 2, some of the headers on ancient build machines
|
||||
# may require gnu89 inline semantics. But otherwise, we use C99.
|
||||
CFLAGS="$CFLAGS -std=gnu99 -fgnu89-inline"
|
||||
# But on OS X we just use C99 plus GNU extensions, in order to fix
|
||||
# bug 917526.
|
||||
CFLAGS="$CFLAGS -std=gnu99"
|
||||
if test "${OS_ARCH}" != Darwin; then
|
||||
CFLAGS="$CFLAGS -fgnu89-inline"
|
||||
fi
|
||||
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
|
||||
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
|
||||
DSO_LDOPTS='-shared'
|
||||
|
|
|
@ -134,16 +134,10 @@ class gcstats::StatisticsSerializer
|
|||
return NULL;
|
||||
}
|
||||
|
||||
size_t outlen = nchars;
|
||||
bool ok = InflateStringToBuffer(NULL, buf, nchars, out, &outlen);
|
||||
InflateStringToBuffer(buf, nchars, out);
|
||||
js_free(buf);
|
||||
if (!ok) {
|
||||
oom_ = true;
|
||||
js_free(out);
|
||||
return NULL;
|
||||
}
|
||||
out[nchars] = 0;
|
||||
|
||||
out[nchars] = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Test that we can optimize stuff like line.target.x without
|
||||
// creating an intermediate object.
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
quit();
|
||||
|
||||
var PointType = new StructType({x: float64,
|
||||
y: float64});
|
||||
var LineType = new StructType({source: PointType,
|
||||
target: PointType});
|
||||
|
||||
function manhattenDistance(line) {
|
||||
return (Math.abs(line.target.x - line.source.x) +
|
||||
Math.abs(line.target.y - line.source.y));
|
||||
}
|
||||
|
||||
function foo() {
|
||||
var N = 30000;
|
||||
var points = [];
|
||||
var obj;
|
||||
var s;
|
||||
|
||||
var fromAToB = new LineType({source: {x: 22, y: 44},
|
||||
target: {x: 66, y: 88}});
|
||||
|
||||
for (var i = 0; i < N; i++)
|
||||
assertEq(manhattenDistance(fromAToB), 88);
|
||||
}
|
||||
|
||||
foo();
|
|
@ -12,16 +12,25 @@ function xPlusY(p) {
|
|||
return p.x + p.y;
|
||||
}
|
||||
|
||||
function xPlusYTweak(p) {
|
||||
p.x = 22;
|
||||
return xPlusY(p);
|
||||
}
|
||||
|
||||
function foo() {
|
||||
var N = 30000;
|
||||
var points = [];
|
||||
var obj;
|
||||
var s;
|
||||
|
||||
for (var i = 0; i < N; i++) {
|
||||
var s;
|
||||
if ((i % 2) == 0 || true)
|
||||
s = xPlusY(new PointType2({x: i, y: i+1}));
|
||||
obj = new PointType2({x: i, y: i+1});
|
||||
else
|
||||
s = xPlusY(new PointType3({x: i, y: i+1, z: i+2}));
|
||||
assertEq(s, i + i + 1);
|
||||
obj = new PointType3({x: i, y: i+1, z: i+2});
|
||||
|
||||
assertEq(xPlusY(obj), i + i + 1);
|
||||
assertEq(xPlusYTweak(obj), 22 + i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "jsnum.h"
|
||||
|
||||
#include "builtin/Eval.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "gc/Nursery.h"
|
||||
#include "jit/ExecutionModeInlines.h"
|
||||
#include "jit/IonLinker.h"
|
||||
|
@ -2861,6 +2862,25 @@ CodeGenerator::visitNewArrayCallVM(LNewArray *lir)
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*NewDerivedTypedObjectFn)(JSContext *,
|
||||
HandleObject type,
|
||||
HandleObject owner,
|
||||
int32_t offset);
|
||||
static const VMFunction CreateDerivedTypedObjInfo =
|
||||
FunctionInfo<NewDerivedTypedObjectFn>(CreateDerivedTypedObj);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewDerivedTypedObject(LNewDerivedTypedObject *lir)
|
||||
{
|
||||
// Not yet made safe for par exec:
|
||||
JS_ASSERT(gen->info().executionMode() == SequentialExecution);
|
||||
|
||||
pushArg(ToRegister(lir->offset()));
|
||||
pushArg(ToRegister(lir->owner()));
|
||||
pushArg(ToRegister(lir->type()));
|
||||
return callVM(CreateDerivedTypedObjInfo, lir);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewSlots(LNewSlots *lir)
|
||||
{
|
||||
|
@ -3577,6 +3597,15 @@ CodeGenerator::visitTypedArrayElements(LTypedArrayElements *lir)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitTypedObjectElements(LTypedObjectElements *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register out = ToRegister(lir->output());
|
||||
masm.loadPtr(Address(obj, BinaryBlock::dataOffset()), out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitStringLength(LStringLength *lir)
|
||||
{
|
||||
|
|
|
@ -132,6 +132,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitNewStringObject(LNewStringObject *lir);
|
||||
bool visitNewPar(LNewPar *lir);
|
||||
bool visitNewDenseArrayPar(LNewDenseArrayPar *lir);
|
||||
bool visitNewDerivedTypedObject(LNewDerivedTypedObject *lir);
|
||||
bool visitAbortPar(LAbortPar *lir);
|
||||
bool visitInitElem(LInitElem *lir);
|
||||
bool visitInitElemGetterSetter(LInitElemGetterSetter *lir);
|
||||
|
@ -148,6 +149,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitArrayLength(LArrayLength *lir);
|
||||
bool visitTypedArrayLength(LTypedArrayLength *lir);
|
||||
bool visitTypedArrayElements(LTypedArrayElements *lir);
|
||||
bool visitTypedObjectElements(LTypedObjectElements *lir);
|
||||
bool visitStringLength(LStringLength *lir);
|
||||
bool visitInitializedLength(LInitializedLength *lir);
|
||||
bool visitSetInitializedLength(LSetInitializedLength *lir);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "jsautooplen.h"
|
||||
|
||||
#include "builtin/Eval.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/TypeRepresentation.h"
|
||||
#include "frontend/SourceNotes.h"
|
||||
#include "jit/BaselineFrame.h"
|
||||
|
@ -1186,7 +1187,15 @@ IonBuilder::traverseBytecode()
|
|||
// FALL THROUGH
|
||||
|
||||
default:
|
||||
JS_ASSERT(popped[i]->isFolded() || popped[i]->defUseCount() > poppedUses[i]);
|
||||
JS_ASSERT(popped[i]->isFolded() ||
|
||||
|
||||
// MNewDerivedTypedObject instances are
|
||||
// often dead unless they escape from the
|
||||
// fn. See IonBuilder::loadTypedObjectData()
|
||||
// for more details.
|
||||
popped[i]->isNewDerivedTypedObject() ||
|
||||
|
||||
popped[i]->defUseCount() > poppedUses[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -7001,6 +7010,28 @@ IonBuilder::convertShiftToMaskForStaticTypedArray(MDefinition *id,
|
|||
return ptr;
|
||||
}
|
||||
|
||||
static MIRType
|
||||
MIRTypeForTypedArrayRead(ScalarTypeRepresentation::Type arrayType,
|
||||
bool observedDouble)
|
||||
{
|
||||
switch (arrayType) {
|
||||
case ScalarTypeRepresentation::TYPE_INT8:
|
||||
case ScalarTypeRepresentation::TYPE_UINT8:
|
||||
case ScalarTypeRepresentation::TYPE_UINT8_CLAMPED:
|
||||
case ScalarTypeRepresentation::TYPE_INT16:
|
||||
case ScalarTypeRepresentation::TYPE_UINT16:
|
||||
case ScalarTypeRepresentation::TYPE_INT32:
|
||||
return MIRType_Int32;
|
||||
case ScalarTypeRepresentation::TYPE_UINT32:
|
||||
return observedDouble ? MIRType_Double : MIRType_Int32;
|
||||
case ScalarTypeRepresentation::TYPE_FLOAT32:
|
||||
return (LIRGenerator::allowFloat32Optimizations()) ? MIRType_Float32 : MIRType_Double;
|
||||
case ScalarTypeRepresentation::TYPE_FLOAT64:
|
||||
return MIRType_Double;
|
||||
}
|
||||
MOZ_ASSUME_UNREACHABLE("Unknown typed array type");
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_getelem_typed(MDefinition *obj, MDefinition *index,
|
||||
ScalarTypeRepresentation::Type arrayType)
|
||||
|
@ -7027,28 +7058,7 @@ IonBuilder::jsop_getelem_typed(MDefinition *obj, MDefinition *index,
|
|||
// the array type to determine the result type, even if the opcode has
|
||||
// never executed. The known pushed type is only used to distinguish
|
||||
// uint32 reads that may produce either doubles or integers.
|
||||
MIRType knownType;
|
||||
switch (arrayType) {
|
||||
case ScalarTypeRepresentation::TYPE_INT8:
|
||||
case ScalarTypeRepresentation::TYPE_UINT8:
|
||||
case ScalarTypeRepresentation::TYPE_UINT8_CLAMPED:
|
||||
case ScalarTypeRepresentation::TYPE_INT16:
|
||||
case ScalarTypeRepresentation::TYPE_UINT16:
|
||||
case ScalarTypeRepresentation::TYPE_INT32:
|
||||
knownType = MIRType_Int32;
|
||||
break;
|
||||
case ScalarTypeRepresentation::TYPE_UINT32:
|
||||
knownType = allowDouble ? MIRType_Double : MIRType_Int32;
|
||||
break;
|
||||
case ScalarTypeRepresentation::TYPE_FLOAT32:
|
||||
knownType = (LIRGenerator::allowFloat32Optimizations()) ? MIRType_Float32 : MIRType_Double;
|
||||
break;
|
||||
case ScalarTypeRepresentation::TYPE_FLOAT64:
|
||||
knownType = MIRType_Double;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unknown typed array type");
|
||||
}
|
||||
MIRType knownType = MIRTypeForTypedArrayRead(arrayType, allowDouble);
|
||||
|
||||
// Get the length.
|
||||
MInstruction *length = getTypedArrayLength(obj);
|
||||
|
@ -8150,6 +8160,10 @@ IonBuilder::jsop_getprop(PropertyName *name)
|
|||
return resumeAfter(call);
|
||||
}
|
||||
|
||||
// Try to emit loads from known binary data blocks
|
||||
if (!getPropTryTypedObject(&emitted, id, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit loads from definite slots.
|
||||
if (!getPropTryDefiniteSlot(&emitted, name, barrier, types) || emitted)
|
||||
return emitted;
|
||||
|
@ -8231,6 +8245,121 @@ IonBuilder::getPropTryConstant(bool *emitted, jsid id, types::TemporaryTypeSet *
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryTypedObject(bool *emitted,
|
||||
jsid id,
|
||||
types::TemporaryTypeSet *resultTypes)
|
||||
{
|
||||
TypeRepresentationSet fieldTypeReprs;
|
||||
int32_t fieldOffset;
|
||||
size_t fieldIndex;
|
||||
if (!lookupTypedObjectField(current->peek(-1), id, &fieldOffset,
|
||||
&fieldTypeReprs, &fieldIndex))
|
||||
return false;
|
||||
if (fieldTypeReprs.empty())
|
||||
return true;
|
||||
|
||||
switch (fieldTypeReprs.kind()) {
|
||||
case TypeRepresentation::Struct:
|
||||
case TypeRepresentation::Array:
|
||||
return getPropTryComplexPropOfTypedObject(emitted,
|
||||
fieldOffset,
|
||||
fieldTypeReprs,
|
||||
fieldIndex,
|
||||
resultTypes);
|
||||
|
||||
case TypeRepresentation::Scalar:
|
||||
return getPropTryScalarPropOfTypedObject(emitted,
|
||||
fieldOffset,
|
||||
fieldTypeReprs,
|
||||
resultTypes);
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("Bad kind");
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryScalarPropOfTypedObject(bool *emitted,
|
||||
int32_t fieldOffset,
|
||||
TypeRepresentationSet fieldTypeReprs,
|
||||
types::TemporaryTypeSet *resultTypes)
|
||||
{
|
||||
// Must always be loading the same scalar type
|
||||
if (fieldTypeReprs.length() != 1)
|
||||
return true;
|
||||
ScalarTypeRepresentation *fieldTypeRepr = fieldTypeReprs.get(0)->asScalar();
|
||||
|
||||
// OK!
|
||||
*emitted = true;
|
||||
|
||||
MDefinition *typedObj = current->pop();
|
||||
|
||||
// Find location within the owner object.
|
||||
MDefinition *owner, *ownerOffset;
|
||||
loadTypedObjectData(typedObj, fieldOffset, &owner, &ownerOffset);
|
||||
|
||||
// Load the element data.
|
||||
MTypedObjectElements *elements = MTypedObjectElements::New(owner);
|
||||
current->add(elements);
|
||||
|
||||
// Reading from an Uint32Array will result in a double for values
|
||||
// that don't fit in an int32. We have to bailout if this happens
|
||||
// and the instruction is not known to return a double.
|
||||
bool allowDouble = resultTypes->hasType(types::Type::DoubleType());
|
||||
MIRType knownType = MIRTypeForTypedArrayRead(fieldTypeRepr->type(), allowDouble);
|
||||
|
||||
// Typed array offsets are expressed in units of the alignment,
|
||||
// and the binary data API guarantees all offsets are properly
|
||||
// aligned. So just do the divide.
|
||||
MConstant *alignment = MConstant::New(Int32Value(fieldTypeRepr->alignment()));
|
||||
current->add(alignment);
|
||||
MDiv *scaledOffset = MDiv::NewAsmJS(ownerOffset, alignment, MIRType_Int32);
|
||||
current->add(scaledOffset);
|
||||
|
||||
MLoadTypedArrayElement *load =
|
||||
MLoadTypedArrayElement::New(elements, scaledOffset,
|
||||
fieldTypeRepr->type());
|
||||
load->setResultType(knownType);
|
||||
load->setResultTypeSet(resultTypes);
|
||||
current->add(load);
|
||||
current->push(load);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryComplexPropOfTypedObject(bool *emitted,
|
||||
int32_t fieldOffset,
|
||||
TypeRepresentationSet fieldTypeReprs,
|
||||
size_t fieldIndex,
|
||||
types::TemporaryTypeSet *resultTypes)
|
||||
{
|
||||
// Must know the field index so that we can load the new type
|
||||
// object for the derived value
|
||||
if (fieldIndex == SIZE_MAX)
|
||||
return true;
|
||||
|
||||
*emitted = true;
|
||||
MDefinition *typedObj = current->pop();
|
||||
|
||||
// Identify the type object for the field.
|
||||
MDefinition *type = loadTypedObjectType(typedObj);
|
||||
MDefinition *fieldType = typeObjectForFieldFromStructType(type, fieldIndex);
|
||||
|
||||
// Find location within the owner object.
|
||||
MDefinition *owner, *ownerOffset;
|
||||
loadTypedObjectData(typedObj, fieldOffset, &owner, &ownerOffset);
|
||||
|
||||
// Create the derived type object.
|
||||
MInstruction *derived = new MNewDerivedTypedObject(fieldTypeReprs,
|
||||
fieldType,
|
||||
owner,
|
||||
ownerOffset);
|
||||
derived->setResultTypeSet(resultTypes);
|
||||
current->add(derived);
|
||||
current->push(derived);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
|
||||
bool barrier, types::TemporaryTypeSet *types)
|
||||
|
@ -8521,6 +8650,10 @@ IonBuilder::jsop_setprop(PropertyName *name)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Try to emit stores to known binary data blocks
|
||||
if (!setPropTryTypedObject(&emitted, obj, id, value) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit store from definite slots.
|
||||
if (!setPropTryDefiniteSlot(&emitted, obj, name, value, barrier, objTypes) || emitted)
|
||||
return emitted;
|
||||
|
@ -8653,6 +8786,66 @@ IonBuilder::setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::setPropTryTypedObject(bool *emitted, MDefinition *obj,
|
||||
jsid id, MDefinition *value)
|
||||
{
|
||||
TypeRepresentationSet fieldTypeReprs;
|
||||
int32_t fieldOffset;
|
||||
size_t fieldIndex;
|
||||
if (!lookupTypedObjectField(obj, id, &fieldOffset, &fieldTypeReprs,
|
||||
&fieldIndex))
|
||||
return false;
|
||||
if (fieldTypeReprs.empty())
|
||||
return true;
|
||||
|
||||
switch (fieldTypeReprs.kind()) {
|
||||
case TypeRepresentation::Struct:
|
||||
case TypeRepresentation::Array:
|
||||
// For now, only optimize storing scalars.
|
||||
return true;
|
||||
|
||||
case TypeRepresentation::Scalar:
|
||||
break;
|
||||
}
|
||||
|
||||
// Must always be storing the same scalar type
|
||||
if (fieldTypeReprs.length() != 1)
|
||||
return true;
|
||||
ScalarTypeRepresentation *fieldTypeRepr = fieldTypeReprs.get(0)->asScalar();
|
||||
|
||||
// OK!
|
||||
*emitted = true;
|
||||
|
||||
MTypedObjectElements *elements = MTypedObjectElements::New(obj);
|
||||
current->add(elements);
|
||||
|
||||
// Typed array offsets are expressed in units of the alignment,
|
||||
// and the binary data API guarantees all offsets are properly
|
||||
// aligned.
|
||||
JS_ASSERT(fieldOffset % fieldTypeRepr->alignment() == 0);
|
||||
int32_t scaledFieldOffset = fieldOffset / fieldTypeRepr->alignment();
|
||||
|
||||
MConstant *offset = MConstant::New(Int32Value(scaledFieldOffset));
|
||||
current->add(offset);
|
||||
|
||||
// Clamp value to [0, 255] for Uint8ClampedArray.
|
||||
MDefinition *toWrite = value;
|
||||
if (fieldTypeRepr->type() == ScalarTypeRepresentation::TYPE_UINT8_CLAMPED) {
|
||||
toWrite = MClampToUint8::New(value);
|
||||
current->add(toWrite->toInstruction());
|
||||
}
|
||||
|
||||
MStoreTypedArrayElement *store =
|
||||
MStoreTypedArrayElement::New(elements, offset, toWrite,
|
||||
fieldTypeRepr->type());
|
||||
current->add(store);
|
||||
|
||||
current->push(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::setPropTryDefiniteSlot(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
|
@ -9325,3 +9518,172 @@ IonBuilder::cloneTypeSet(types::StackTypeSet *types)
|
|||
// after bug 804676 this code can be removed.
|
||||
return types->clone(GetIonContext()->temp->lifoAlloc());
|
||||
}
|
||||
|
||||
TypeRepresentationSetHash *
|
||||
IonBuilder::getOrCreateReprSetHash()
|
||||
{
|
||||
if (!reprSetHash_) {
|
||||
TypeRepresentationSetHash* hash =
|
||||
cx->new_<TypeRepresentationSetHash>();
|
||||
if (!hash || !hash->init()) {
|
||||
js_delete(hash);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reprSetHash_ = hash;
|
||||
}
|
||||
return reprSetHash_.get();
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::lookupTypeRepresentationSet(MDefinition *typedObj,
|
||||
TypeRepresentationSet *out)
|
||||
{
|
||||
*out = TypeRepresentationSet(); // default to unknown
|
||||
|
||||
// Extract TypeRepresentationSet directly if we can
|
||||
if (typedObj->isNewDerivedTypedObject()) {
|
||||
*out = typedObj->toNewDerivedTypedObject()->set();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Extract TypeRepresentationSet directly if we can
|
||||
types::TemporaryTypeSet *types = typedObj->resultTypeSet();
|
||||
if (!types || types->getKnownTypeTag() != JSVAL_TYPE_OBJECT)
|
||||
return true;
|
||||
|
||||
// And only known objects.
|
||||
if (types->unknownObject())
|
||||
return true;
|
||||
|
||||
TypeRepresentationSetBuilder set;
|
||||
for (uint32_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObject *type = types->getTypeObject(0);
|
||||
if (!type || type->unknownProperties())
|
||||
return true;
|
||||
|
||||
if (!type->hasTypedObject())
|
||||
return true;
|
||||
|
||||
TypeRepresentation *typeRepr = type->typedObject()->typeRepr;
|
||||
if (!set.insert(typeRepr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return set.build(*this, out);
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
IonBuilder::loadTypedObjectType(MDefinition *typedObj)
|
||||
{
|
||||
// Shortcircuit derived type objects, meaning the intermediate
|
||||
// objects created to represent `a.b` in an expression like
|
||||
// `a.b.c`. In that case, the type object can be simply pulled
|
||||
// from the operands of that instruction.
|
||||
if (typedObj->isNewDerivedTypedObject())
|
||||
return typedObj->toNewDerivedTypedObject()->type();
|
||||
|
||||
MInstruction *load = MLoadFixedSlot::New(typedObj, js::SLOT_DATATYPE);
|
||||
current->add(load);
|
||||
return load;
|
||||
}
|
||||
|
||||
// Given a typed object `typedObj` and an offset `offset` into that
|
||||
// object's data, returns another typed object and adusted offset
|
||||
// where the data can be found. Often, these returned values are the
|
||||
// same as the inputs, but in cases where intermediate derived type
|
||||
// objects have been created, the return values will remove
|
||||
// intermediate layers (often rendering those derived type objects
|
||||
// into dead code).
|
||||
void
|
||||
IonBuilder::loadTypedObjectData(MDefinition *typedObj,
|
||||
int32_t offset,
|
||||
MDefinition **owner,
|
||||
MDefinition **ownerOffset)
|
||||
{
|
||||
MConstant *offsetDef = MConstant::New(Int32Value(offset));
|
||||
current->add(offsetDef);
|
||||
|
||||
// Shortcircuit derived type objects, meaning the intermediate
|
||||
// objects created to represent `a.b` in an expression like
|
||||
// `a.b.c`. In that case, the owned and a base offset can be
|
||||
// pulled from the operands of the instruction and combined with
|
||||
// `offset`.
|
||||
if (typedObj->isNewDerivedTypedObject()) {
|
||||
// If we see that the
|
||||
MNewDerivedTypedObject *ins = typedObj->toNewDerivedTypedObject();
|
||||
|
||||
MAdd *offsetAdd = MAdd::NewAsmJS(ins->offset(), offsetDef,
|
||||
MIRType_Int32);
|
||||
current->add(offsetAdd);
|
||||
|
||||
*owner = ins->owner();
|
||||
*ownerOffset = offsetAdd;
|
||||
return;
|
||||
}
|
||||
|
||||
*owner = typedObj;
|
||||
*ownerOffset = offsetDef;
|
||||
}
|
||||
|
||||
// Looks up the offset/type-repr-set of the field `id`, given the type
|
||||
// set `objTypes` of the field owner. Note that even when true is
|
||||
// returned, `*fieldTypeReprs` might be empty if no useful type/offset
|
||||
// pair could be determined.
|
||||
bool
|
||||
IonBuilder::lookupTypedObjectField(MDefinition *typedObj,
|
||||
jsid id,
|
||||
int32_t *fieldOffset,
|
||||
TypeRepresentationSet *fieldTypeReprs,
|
||||
size_t *fieldIndex)
|
||||
{
|
||||
TypeRepresentationSet objTypeReprs;
|
||||
if (!lookupTypeRepresentationSet(typedObj, &objTypeReprs))
|
||||
return false;
|
||||
|
||||
// Must be accessing a struct.
|
||||
if (!objTypeReprs.allOfKind(TypeRepresentation::Struct))
|
||||
return true;
|
||||
|
||||
// Determine the type/offset of the field `id`, if any.
|
||||
size_t offset;
|
||||
if (!objTypeReprs.fieldNamed(*this, id, &offset,
|
||||
fieldTypeReprs, fieldIndex))
|
||||
return false;
|
||||
if (fieldTypeReprs->empty())
|
||||
return false;
|
||||
|
||||
// Field offset must be representable as signed integer.
|
||||
if (offset >= size_t(INT_MAX)) {
|
||||
*fieldTypeReprs = TypeRepresentationSet();
|
||||
return true;
|
||||
}
|
||||
|
||||
*fieldOffset = int32_t(offset);
|
||||
JS_ASSERT(*fieldOffset >= 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
IonBuilder::typeObjectForFieldFromStructType(MDefinition *typeObj,
|
||||
size_t fieldIndex)
|
||||
{
|
||||
// Load list of field type objects.
|
||||
|
||||
MInstruction *fieldTypes = MLoadFixedSlot::New(typeObj, SLOT_STRUCT_FIELD_TYPES);
|
||||
current->add(fieldTypes);
|
||||
|
||||
// Index into list with index of field.
|
||||
|
||||
MInstruction *fieldTypesElements = MElements::New(fieldTypes);
|
||||
current->add(fieldTypesElements);
|
||||
|
||||
MConstant *fieldIndexDef = MConstant::New(Int32Value(fieldIndex));
|
||||
current->add(fieldIndexDef);
|
||||
|
||||
MInstruction *fieldType = MLoadElement::New(fieldTypesElements, fieldIndexDef, false, false);
|
||||
current->add(fieldType);
|
||||
|
||||
return fieldType;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "jit/BytecodeAnalysis.h"
|
||||
#include "jit/MIR.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "jit/TypeRepresentationSet.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
@ -363,6 +364,17 @@ class IonBuilder : public MIRGenerator
|
|||
bool barrier, types::TemporaryTypeSet *types);
|
||||
bool getPropTryInlineAccess(bool *emitted, PropertyName *name, jsid id,
|
||||
bool barrier, types::TemporaryTypeSet *types);
|
||||
bool getPropTryTypedObject(bool *emitted, jsid id,
|
||||
types::TemporaryTypeSet *resultTypes);
|
||||
bool getPropTryScalarPropOfTypedObject(bool *emitted,
|
||||
int32_t fieldOffset,
|
||||
TypeRepresentationSet fieldTypeReprs,
|
||||
types::TemporaryTypeSet *resultTypes);
|
||||
bool getPropTryComplexPropOfTypedObject(bool *emitted,
|
||||
int32_t fieldOffset,
|
||||
TypeRepresentationSet fieldTypeReprs,
|
||||
size_t fieldIndex,
|
||||
types::TemporaryTypeSet *resultTypes);
|
||||
bool getPropTryCache(bool *emitted, PropertyName *name, jsid id,
|
||||
bool barrier, types::TemporaryTypeSet *types);
|
||||
bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types);
|
||||
|
@ -381,10 +393,28 @@ class IonBuilder : public MIRGenerator
|
|||
PropertyName *name, jsid id,
|
||||
MDefinition *value, bool barrier,
|
||||
types::TemporaryTypeSet *objTypes);
|
||||
bool setPropTryTypedObject(bool *emitted, MDefinition *obj,
|
||||
jsid id, MDefinition *value);
|
||||
bool setPropTryCache(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
|
||||
// binary data lookup helpers.
|
||||
bool lookupTypeRepresentationSet(MDefinition *typedObj,
|
||||
TypeRepresentationSet *out);
|
||||
bool lookupTypedObjectField(MDefinition *typedObj,
|
||||
jsid id,
|
||||
int32_t *fieldOffset,
|
||||
TypeRepresentationSet *fieldTypeReprs,
|
||||
size_t *fieldIndex);
|
||||
MDefinition *loadTypedObjectType(MDefinition *value);
|
||||
void loadTypedObjectData(MDefinition *inOwner,
|
||||
int32_t inOffset,
|
||||
MDefinition **outOwner,
|
||||
MDefinition **outOffset);
|
||||
MDefinition *typeObjectForFieldFromStructType(MDefinition *type,
|
||||
size_t fieldIndex);
|
||||
|
||||
// jsop_setelem() helpers.
|
||||
bool setElemTryTyped(bool *emitted, MDefinition *object,
|
||||
MDefinition *index, MDefinition *value);
|
||||
|
@ -641,12 +671,15 @@ class IonBuilder : public MIRGenerator
|
|||
|
||||
AbortReason abortReason() { return abortReason_; }
|
||||
|
||||
TypeRepresentationSetHash *getOrCreateReprSetHash(); // fallible
|
||||
|
||||
private:
|
||||
bool init();
|
||||
|
||||
JSContext *cx;
|
||||
BaselineFrame *baselineFrame_;
|
||||
AbortReason abortReason_;
|
||||
ScopedJSDeletePtr<TypeRepresentationSetHash> reprSetHash_;
|
||||
|
||||
// Basic analysis information about the script.
|
||||
BytecodeAnalysis analysis_;
|
||||
|
|
|
@ -501,6 +501,32 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class LNewDerivedTypedObject : public LCallInstructionHelper<1, 3, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewDerivedTypedObject);
|
||||
|
||||
LNewDerivedTypedObject(const LAllocation &type,
|
||||
const LAllocation &owner,
|
||||
const LAllocation &offset) {
|
||||
setOperand(0, type);
|
||||
setOperand(1, owner);
|
||||
setOperand(2, offset);
|
||||
}
|
||||
|
||||
const LAllocation *type() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
const LAllocation *owner() {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
const LAllocation *offset() {
|
||||
return getOperand(2);
|
||||
}
|
||||
};
|
||||
|
||||
class LNewStringObject : public LInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
|
@ -3042,6 +3068,20 @@ class LTypedArrayElements : public LInstructionHelper<1, 1, 0>
|
|||
}
|
||||
};
|
||||
|
||||
// Load a typed array's elements vector.
|
||||
class LTypedObjectElements : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(TypedObjectElements)
|
||||
|
||||
LTypedObjectElements(const LAllocation &object) {
|
||||
setOperand(0, object);
|
||||
}
|
||||
const LAllocation *object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Bailout if index >= length.
|
||||
class LBoundsCheck : public LInstructionHelper<0, 2, 0>
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
_(NewPar) \
|
||||
_(NewDenseArrayPar) \
|
||||
_(NewCallObjectPar) \
|
||||
_(NewDerivedTypedObject) \
|
||||
_(AbortPar) \
|
||||
_(InitElem) \
|
||||
_(InitElemGetterSetter) \
|
||||
|
@ -221,6 +222,7 @@
|
|||
_(ArrayLength) \
|
||||
_(TypedArrayLength) \
|
||||
_(TypedArrayElements) \
|
||||
_(TypedObjectElements) \
|
||||
_(StringLength) \
|
||||
_(ArgumentsLength) \
|
||||
_(GetArgument) \
|
||||
|
|
|
@ -207,6 +207,16 @@ LIRGenerator::visitNewCallObject(MNewCallObject *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitNewDerivedTypedObject(MNewDerivedTypedObject *ins)
|
||||
{
|
||||
LNewDerivedTypedObject *lir =
|
||||
new LNewDerivedTypedObject(useRegisterAtStart(ins->type()),
|
||||
useRegisterAtStart(ins->owner()),
|
||||
useRegisterAtStart(ins->offset()));
|
||||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitNewCallObjectPar(MNewCallObjectPar *ins)
|
||||
{
|
||||
|
@ -2068,6 +2078,13 @@ LIRGenerator::visitTypedArrayElements(MTypedArrayElements *ins)
|
|||
return define(new LTypedArrayElements(useRegisterAtStart(ins->object())), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitTypedObjectElements(MTypedObjectElements *ins)
|
||||
{
|
||||
JS_ASSERT(ins->type() == MIRType_Elements);
|
||||
return define(new LTypedObjectElements(useRegisterAtStart(ins->object())), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitInitializedLength(MInitializedLength *ins)
|
||||
{
|
||||
|
|
|
@ -89,6 +89,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitNewDeclEnvObject(MNewDeclEnvObject *ins);
|
||||
bool visitNewCallObject(MNewCallObject *ins);
|
||||
bool visitNewStringObject(MNewStringObject *ins);
|
||||
bool visitNewDerivedTypedObject(MNewDerivedTypedObject *ins);
|
||||
bool visitNewPar(MNewPar *ins);
|
||||
bool visitNewCallObjectPar(MNewCallObjectPar *ins);
|
||||
bool visitNewDenseArrayPar(MNewDenseArrayPar *ins);
|
||||
|
@ -182,6 +183,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitArrayLength(MArrayLength *ins);
|
||||
bool visitTypedArrayLength(MTypedArrayLength *ins);
|
||||
bool visitTypedArrayElements(MTypedArrayElements *ins);
|
||||
bool visitTypedObjectElements(MTypedObjectElements *ins);
|
||||
bool visitInitializedLength(MInitializedLength *ins);
|
||||
bool visitSetInitializedLength(MSetInitializedLength *ins);
|
||||
bool visitNot(MNot *ins);
|
||||
|
|
|
@ -539,6 +539,13 @@ MConstantElements::printOpcode(FILE *fp) const
|
|||
fprintf(fp, " %p", value());
|
||||
}
|
||||
|
||||
void
|
||||
MLoadTypedArrayElement::printOpcode(FILE *fp) const
|
||||
{
|
||||
MDefinition::printOpcode(fp);
|
||||
fprintf(fp, " %s", ScalarTypeRepresentation::typeName(arrayType()));
|
||||
}
|
||||
|
||||
MParameter *
|
||||
MParameter::New(int32_t index, types::TemporaryTypeSet *types)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "jit/IonMacroAssembler.h"
|
||||
#include "jit/MOpcodes.h"
|
||||
#include "jit/TypePolicy.h"
|
||||
#include "jit/TypeRepresentationSet.h"
|
||||
#include "vm/ScopeObject.h"
|
||||
|
||||
namespace js {
|
||||
|
@ -1487,6 +1488,66 @@ class MNewPar : public MUnaryInstruction
|
|||
}
|
||||
};
|
||||
|
||||
// Creates a new derived type object. At runtime, this is just a call
|
||||
// to `BinaryBlock::createDerived()`. That is, the MIR itself does not
|
||||
// compile to particularly optimized code. However, using a distinct
|
||||
// MIR for creating derived type objects allows the compiler to
|
||||
// optimize ephemeral typed objects as would be created for a
|
||||
// reference like `a.b.c` -- here, the `a.b` will create an ephemeral
|
||||
// derived type object that aliases the memory of `a` itself. The
|
||||
// specific nature of `a.b` is revealed by using
|
||||
// `MNewDerivedTypedObject` rather than `MGetProperty` or what have
|
||||
// you. Moreover, the compiler knows that there are no side-effects,
|
||||
// so `MNewDerivedTypedObject` instructions can be reordered or pruned
|
||||
// as dead code.
|
||||
class MNewDerivedTypedObject
|
||||
: public MTernaryInstruction,
|
||||
public Mix3Policy<ObjectPolicy<0>,
|
||||
ObjectPolicy<1>,
|
||||
IntPolicy<2> >
|
||||
{
|
||||
private:
|
||||
TypeRepresentationSet set_;
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewDerivedTypedObject);
|
||||
|
||||
MNewDerivedTypedObject(TypeRepresentationSet set,
|
||||
MDefinition *type,
|
||||
MDefinition *owner,
|
||||
MDefinition *offset)
|
||||
: MTernaryInstruction(type, owner, offset),
|
||||
set_(set)
|
||||
{
|
||||
setMovable();
|
||||
setResultType(MIRType_Object);
|
||||
}
|
||||
|
||||
TypeRepresentationSet set() const {
|
||||
return set_;
|
||||
}
|
||||
|
||||
MDefinition *type() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MDefinition *owner() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
MDefinition *offset() const {
|
||||
return getOperand(2);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
// Abort parallel execution.
|
||||
class MAbortPar : public MAryControlInstruction<0, 0>
|
||||
{
|
||||
|
@ -4882,6 +4943,42 @@ class MTypedArrayElements
|
|||
}
|
||||
};
|
||||
|
||||
// Load a binary data object's "elements", which is just its opaque
|
||||
// binary data space. Eventually this should probably be
|
||||
// unified with `MTypedArrayElements`.
|
||||
class MTypedObjectElements
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy
|
||||
{
|
||||
private:
|
||||
MTypedObjectElements(MDefinition *object)
|
||||
: MUnaryInstruction(object)
|
||||
{
|
||||
setResultType(MIRType_Elements);
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(TypedObjectElements)
|
||||
|
||||
static MTypedObjectElements *New(MDefinition *object) {
|
||||
return new MTypedObjectElements(object);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
MDefinition *object() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
bool congruentTo(MDefinition *ins) const {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
};
|
||||
|
||||
// Perform !-operation
|
||||
class MNot
|
||||
: public MUnaryInstruction,
|
||||
|
@ -5423,6 +5520,8 @@ class MLoadTypedArrayElement
|
|||
return AliasSet::Load(AliasSet::TypedArrayElement);
|
||||
}
|
||||
|
||||
void printOpcode(FILE *fp) const;
|
||||
|
||||
void computeRange();
|
||||
|
||||
bool canProduceFloat32() const { return arrayType_ == ScalarTypeRepresentation::TYPE_FLOAT32; }
|
||||
|
|
|
@ -123,6 +123,7 @@ namespace jit {
|
|||
_(ArrayLength) \
|
||||
_(TypedArrayLength) \
|
||||
_(TypedArrayElements) \
|
||||
_(TypedObjectElements) \
|
||||
_(InitializedLength) \
|
||||
_(SetInitializedLength) \
|
||||
_(Not) \
|
||||
|
@ -197,6 +198,7 @@ namespace jit {
|
|||
_(NewCallObjectPar) \
|
||||
_(NewPar) \
|
||||
_(NewDenseArrayPar) \
|
||||
_(NewDerivedTypedObject) \
|
||||
_(AbortPar) \
|
||||
_(LambdaPar) \
|
||||
_(RestPar) \
|
||||
|
|
|
@ -175,6 +175,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
|||
CUSTOM_OP(NewObject)
|
||||
CUSTOM_OP(NewCallObject)
|
||||
CUSTOM_OP(NewParallelArray)
|
||||
UNSAFE_OP(NewDerivedTypedObject)
|
||||
UNSAFE_OP(InitElem)
|
||||
UNSAFE_OP(InitElemGetterSetter)
|
||||
UNSAFE_OP(InitProp)
|
||||
|
@ -207,6 +208,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
|||
SAFE_OP(ArrayLength)
|
||||
SAFE_OP(TypedArrayLength)
|
||||
SAFE_OP(TypedArrayElements)
|
||||
SAFE_OP(TypedObjectElements)
|
||||
SAFE_OP(InitializedLength)
|
||||
WRITE_GUARDED_OP(SetInitializedLength, elements)
|
||||
SAFE_OP(Not)
|
||||
|
|
|
@ -416,6 +416,7 @@ IntPolicy<Op>::staticAdjustInputs(MInstruction *def)
|
|||
|
||||
template bool IntPolicy<0>::staticAdjustInputs(MInstruction *def);
|
||||
template bool IntPolicy<1>::staticAdjustInputs(MInstruction *def);
|
||||
template bool IntPolicy<2>::staticAdjustInputs(MInstruction *def);
|
||||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jit/TypeRepresentationSet.h"
|
||||
|
||||
#include "mozilla/HashFunctions.h"
|
||||
|
||||
#include "jit/IonBuilder.h"
|
||||
|
||||
#include "jsinferinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace jit;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeRepresentationSet hasher
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationSetHasher::hash(TypeRepresentationSet key)
|
||||
{
|
||||
HashNumber hn = mozilla::HashGeneric(key.length());
|
||||
for (size_t i = 0; i < key.length(); i++)
|
||||
hn = mozilla::AddToHash(hn, uintptr_t(key.get(i)));
|
||||
return hn;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationSetHasher::match(TypeRepresentationSet key1,
|
||||
TypeRepresentationSet key2)
|
||||
{
|
||||
if (key1.length() != key2.length())
|
||||
return false;
|
||||
|
||||
// Note: entries are always sorted
|
||||
for (size_t i = 0; i < key1.length(); i++) {
|
||||
if (key1.get(i) != key2.get(i))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeRepresentationSetBuilder
|
||||
|
||||
TypeRepresentationSetBuilder::TypeRepresentationSetBuilder()
|
||||
: invalid_(false)
|
||||
{}
|
||||
|
||||
bool
|
||||
TypeRepresentationSetBuilder::insert(TypeRepresentation *typeRepr)
|
||||
{
|
||||
if (invalid_)
|
||||
return true;
|
||||
|
||||
if (entries_.length() == 0)
|
||||
return entries_.append(typeRepr);
|
||||
|
||||
// Check that this new type repr is of the same basic kind as the
|
||||
// ones we have seen thus far. If not, for example if we have an
|
||||
// `int` and a `struct`, then convert this set to the invalid set.
|
||||
TypeRepresentation *entry0 = entries_[0];
|
||||
if (typeRepr->kind() != entry0->kind()) {
|
||||
invalid_ = true;
|
||||
entries_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, use binary search to find the right place to insert
|
||||
// the type descriptor. We keep list sorted by the *address* of
|
||||
// the type representations within.
|
||||
uintptr_t typeReprAddr = (uintptr_t) typeRepr;
|
||||
size_t min = 0;
|
||||
size_t max = entries_.length();
|
||||
while (min != max) {
|
||||
size_t i = min + ((max - min) >> 1); // average w/o fear of overflow
|
||||
|
||||
uintptr_t entryiaddr = (uintptr_t) entries_[i];
|
||||
if (entryiaddr == typeReprAddr)
|
||||
return true; // typeRepr already present in the set
|
||||
|
||||
if (entryiaddr < typeReprAddr) {
|
||||
// typeRepr lies to the right of entry i
|
||||
min = i;
|
||||
} else {
|
||||
// typeRepr lies to the left of entry i
|
||||
max = i;
|
||||
}
|
||||
}
|
||||
|
||||
// As a sanity check, give up if the TypeRepresentationSet grows too large.
|
||||
if (entries_.length() >= 512) {
|
||||
invalid_ = true;
|
||||
entries_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not present. Insert at position `min`.
|
||||
if (min == entries_.length())
|
||||
return entries_.append(typeRepr);
|
||||
TypeRepresentation **insertLoc = &entries_[min];
|
||||
return entries_.insert(insertLoc, typeRepr) != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationSetBuilder::build(IonBuilder &builder,
|
||||
TypeRepresentationSet *out)
|
||||
{
|
||||
if (invalid_) {
|
||||
*out = TypeRepresentationSet();
|
||||
return true;
|
||||
}
|
||||
|
||||
TypeRepresentationSetHash *table = builder.getOrCreateReprSetHash();
|
||||
if (!table)
|
||||
return false;
|
||||
|
||||
// Check if there is already a copy in the hashtable.
|
||||
size_t length = entries_.length();
|
||||
TypeRepresentationSet tempSet(length, entries_.begin());
|
||||
TypeRepresentationSetHash::AddPtr p = table->lookupForAdd(tempSet);
|
||||
if (p) {
|
||||
*out = *p;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If not, allocate a permanent copy in Ion temp memory and add it.
|
||||
size_t space = sizeof(TypeRepresentation*) * length;
|
||||
TypeRepresentation **array = (TypeRepresentation**)
|
||||
GetIonContext()->temp->allocate(space);
|
||||
if (!array)
|
||||
return false;
|
||||
memcpy(array, entries_.begin(), space);
|
||||
TypeRepresentationSet permSet(length, array);
|
||||
if (!table->add(p, permSet))
|
||||
return false;
|
||||
|
||||
*out = permSet;
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeRepresentationSet
|
||||
|
||||
TypeRepresentationSet::TypeRepresentationSet(const TypeRepresentationSet &c)
|
||||
: length_(c.length_),
|
||||
entries_(c.entries_)
|
||||
{}
|
||||
|
||||
TypeRepresentationSet::TypeRepresentationSet(size_t length,
|
||||
TypeRepresentation **entries)
|
||||
: length_(length),
|
||||
entries_(entries)
|
||||
{}
|
||||
|
||||
TypeRepresentationSet::TypeRepresentationSet()
|
||||
: length_(0),
|
||||
entries_(NULL)
|
||||
{}
|
||||
|
||||
bool
|
||||
TypeRepresentationSet::empty()
|
||||
{
|
||||
return length() == 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
TypeRepresentationSet::length()
|
||||
{
|
||||
return length_;
|
||||
}
|
||||
|
||||
TypeRepresentation *
|
||||
TypeRepresentationSet::get(size_t i)
|
||||
{
|
||||
JS_ASSERT(i < length());
|
||||
return entries_[i];
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationSet::allOfKind(TypeRepresentation::Kind aKind)
|
||||
{
|
||||
if (empty())
|
||||
return false;
|
||||
|
||||
return kind() == aKind;
|
||||
}
|
||||
|
||||
TypeRepresentation::Kind
|
||||
TypeRepresentationSet::kind()
|
||||
{
|
||||
JS_ASSERT(!empty());
|
||||
return get(0)->kind();
|
||||
}
|
||||
|
||||
size_t
|
||||
TypeRepresentationSet::arrayLength()
|
||||
{
|
||||
JS_ASSERT(kind() == TypeRepresentation::Array);
|
||||
const size_t result = get(0)->asArray()->length();
|
||||
for (size_t i = 1; i < length(); i++) {
|
||||
if (get(i)->asArray()->length() != result)
|
||||
return SIZE_MAX;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationSet::arrayElementType(IonBuilder &builder,
|
||||
TypeRepresentationSet *out)
|
||||
{
|
||||
JS_ASSERT(kind() == TypeRepresentation::Array);
|
||||
|
||||
TypeRepresentationSetBuilder elementTypes;
|
||||
for (size_t i = 0; i < length(); i++) {
|
||||
if (!elementTypes.insert(get(i)->asArray()->element()))
|
||||
return false;
|
||||
}
|
||||
return elementTypes.build(builder, out);
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationSet::fieldNamed(IonBuilder &builder,
|
||||
jsid id,
|
||||
size_t *offset,
|
||||
TypeRepresentationSet *out,
|
||||
size_t *index)
|
||||
{
|
||||
JS_ASSERT(kind() == TypeRepresentation::Struct);
|
||||
|
||||
// Initialize `*offset` and `*out` for the case where incompatible
|
||||
// or absent fields are found.
|
||||
*offset = SIZE_MAX;
|
||||
*index = SIZE_MAX;
|
||||
*out = TypeRepresentationSet();
|
||||
|
||||
// Remember offset of the first field.
|
||||
size_t offset0;
|
||||
size_t index0;
|
||||
TypeRepresentationSetBuilder fieldTypes;
|
||||
{
|
||||
const StructField *field = get(0)->asStruct()->fieldNamed(id);
|
||||
if (!field)
|
||||
return true;
|
||||
|
||||
offset0 = field->offset;
|
||||
index0 = field->index;
|
||||
if (!fieldTypes.insert(field->typeRepr))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that all subsequent fields are at the same offset
|
||||
// and compute the union of their types.
|
||||
for (size_t i = 1; i < length(); i++) {
|
||||
const StructField *field = get(i)->asStruct()->fieldNamed(id);
|
||||
if (!field)
|
||||
return true;
|
||||
|
||||
if (field->offset != offset0)
|
||||
return true;
|
||||
|
||||
if (field->index != index0)
|
||||
index0 = SIZE_MAX;
|
||||
|
||||
if (!fieldTypes.insert(field->typeRepr))
|
||||
return false;
|
||||
}
|
||||
|
||||
// All struct types had a field named `id` at the same offset
|
||||
// (though it's still possible that the types are incompatible and
|
||||
// that the indices disagree).
|
||||
*offset = offset0;
|
||||
*index = index0;
|
||||
return fieldTypes.build(builder, out);
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef jit_TypeRepresentationSet_h
|
||||
#define jit_TypeRepresentationSet_h
|
||||
|
||||
#include "builtin/TypeRepresentation.h"
|
||||
#include "jit/IonAllocPolicy.h"
|
||||
#include "js/HashTable.h"
|
||||
|
||||
// TypeRepresentationSet stores a set of TypeRepresentation* objects,
|
||||
// representing the possible types of the binary data associated with
|
||||
// a typed object value. Often TypeRepresentationSets will be
|
||||
// singleton sets, but it is also possible to have cases where many
|
||||
// type representations flow into a single point. In such cases, the
|
||||
// various type representations may differ in their details but often
|
||||
// have a common prefix. We try to optimize this case as well.
|
||||
//
|
||||
// So, for example, consider some code like:
|
||||
//
|
||||
// var Point2Type = new StructType({x: uint8, y: uint8});
|
||||
// var Point3Type = new StructType({x: uint8, y: uint8, z: uint8});
|
||||
//
|
||||
// function distance2d(pnt) {
|
||||
// return Math.sqrt(pnt.x * pnt.x + pnt.y * pnt.y);
|
||||
// }
|
||||
//
|
||||
// Even if the function `distance2d()` were used with instances of
|
||||
// both Point2Type and Point3Type, we can still generate optimal code,
|
||||
// because both of those types contain fields named `x` and `y` with
|
||||
// the same types at the same offset.
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class IonBuilder;
|
||||
class TypeRepresentationSet;
|
||||
|
||||
class TypeRepresentationSetBuilder {
|
||||
private:
|
||||
Vector<TypeRepresentation *, 4, SystemAllocPolicy> entries_;
|
||||
bool invalid_;
|
||||
|
||||
bool overlaps(TypeRepresentation *a, TypeRepresentation *b);
|
||||
|
||||
public:
|
||||
TypeRepresentationSetBuilder();
|
||||
|
||||
bool insert(TypeRepresentation *typeRepr);
|
||||
bool build(IonBuilder &builder, TypeRepresentationSet *out);
|
||||
};
|
||||
|
||||
class TypeRepresentationSet {
|
||||
private:
|
||||
friend class TypeRepresentationSetBuilder;
|
||||
|
||||
size_t length_;
|
||||
TypeRepresentation **entries_; // Allocated using temp policy
|
||||
|
||||
TypeRepresentationSet(size_t length, TypeRepresentation **entries);
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Constructors
|
||||
//
|
||||
// For more flexible constructors, see
|
||||
// TypeRepresentationSetBuilder above.
|
||||
|
||||
TypeRepresentationSet(const TypeRepresentationSet &c);
|
||||
TypeRepresentationSet(); // empty set
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Query the set
|
||||
|
||||
bool empty();
|
||||
size_t length();
|
||||
TypeRepresentation *get(size_t i);
|
||||
bool allOfKind(TypeRepresentation::Kind kind);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// The following operations are only valid on a non-empty set:
|
||||
|
||||
TypeRepresentation::Kind kind();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Array operations
|
||||
//
|
||||
// Only valid when `kind() == TypeRepresentation::Array`
|
||||
|
||||
// Returns the length of the arrays in this set, or SIZE_MAX
|
||||
// if they are not all the same.
|
||||
size_t arrayLength();
|
||||
|
||||
// Returns a `TypeRepresentationSet` representing the element
|
||||
// types of the various array types in this set. The returned set
|
||||
// may be the empty set.
|
||||
bool arrayElementType(IonBuilder &builder, TypeRepresentationSet *out);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Struct operations
|
||||
//
|
||||
// Only valid when `kind() == TypeRepresentation::Struct`
|
||||
|
||||
// Searches the type in the set for a field named `id`. All
|
||||
// possible types must agree on the offset of the field within the
|
||||
// structure and the possible types of the field must be
|
||||
// compatible. If any pair of types disagree on the offset or have
|
||||
// incompatible types for the field, then `*out` will be set to
|
||||
// the empty set.
|
||||
//
|
||||
// Upon success, `out` will be set to the set of possible types of
|
||||
// the field and `offset` will be set to the field's offset within
|
||||
// the struct (measured in bytes).
|
||||
//
|
||||
// The parameter `*index` is special. If all types agree on the
|
||||
// index of the field, then `*index` is set to the field index.
|
||||
// Otherwise, it is set to SIZE_MAX. Note that two types may agree
|
||||
// on the type and offset of a field but disagree about its index,
|
||||
// e.g. the field `c` in `new StructType({a: uint8, b: uint8, c:
|
||||
// uint16})` and `new StructType({a: uint16, c: uint16})`.
|
||||
bool fieldNamed(IonBuilder &builder,
|
||||
jsid id,
|
||||
size_t *offset,
|
||||
TypeRepresentationSet *out,
|
||||
size_t *index);
|
||||
};
|
||||
|
||||
struct TypeRepresentationSetHasher
|
||||
{
|
||||
typedef TypeRepresentationSet Lookup;
|
||||
static HashNumber hash(TypeRepresentationSet key);
|
||||
static bool match(TypeRepresentationSet key1,
|
||||
TypeRepresentationSet key2);
|
||||
};
|
||||
|
||||
typedef js::HashSet<TypeRepresentationSet,
|
||||
TypeRepresentationSetHasher,
|
||||
IonAllocPolicy> TypeRepresentationSetHash;
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif
|
|
@ -7,6 +7,7 @@
|
|||
#include "jit/VMFunctions.h"
|
||||
|
||||
#include "builtin/ParallelArray.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/Ion.h"
|
||||
|
@ -872,5 +873,12 @@ InitBaselineFrameForOsr(BaselineFrame *frame, StackFrame *interpFrame, uint32_t
|
|||
return frame->initForOsr(interpFrame, numStackValues);
|
||||
}
|
||||
|
||||
JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject type,
|
||||
HandleObject owner, int32_t offset)
|
||||
{
|
||||
return BinaryBlock::createDerived(cx, type, owner, offset);
|
||||
}
|
||||
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
|
|
@ -665,6 +665,9 @@ bool LeaveBlock(JSContext *cx, BaselineFrame *frame);
|
|||
bool InitBaselineFrameForOsr(BaselineFrame *frame, StackFrame *interpFrame,
|
||||
uint32_t numStackValues);
|
||||
|
||||
JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject type,
|
||||
HandleObject owner, int32_t offset);
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -5463,7 +5463,25 @@ JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_
|
|||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
|
||||
|
||||
if (!dst) {
|
||||
*dstlenp = srclen;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t dstlen = *dstlenp;
|
||||
|
||||
if (srclen > dstlen) {
|
||||
InflateStringToBuffer(src, dstlen, dst);
|
||||
|
||||
AutoSuppressGC suppress(cx);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BUFFER_TOO_SMALL);
|
||||
return false;
|
||||
}
|
||||
|
||||
InflateStringToBuffer(src, srclen, dst);
|
||||
*dstlenp = srclen;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(char *)
|
||||
|
|
|
@ -388,13 +388,8 @@ js::AtomizeMaybeGC(ExclusiveContext *cx, const char *bytes, size_t length, Inter
|
|||
* js::AtomizeString rarely has to copy the temp string we make.
|
||||
*/
|
||||
jschar inflated[ATOMIZE_BUF_MAX];
|
||||
size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
|
||||
if (!InflateStringToBuffer(cx->maybeJSContext(),
|
||||
bytes, length, inflated, &inflatedLength))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return AtomizeAndCopyChars<allowGC>(cx, inflated, inflatedLength, ib);
|
||||
InflateStringToBuffer(bytes, length, inflated);
|
||||
return AtomizeAndCopyChars<allowGC>(cx, inflated, length, ib);
|
||||
}
|
||||
|
||||
jschar *tbcharsZ = InflateString(cx, bytes, &length);
|
||||
|
|
|
@ -204,7 +204,7 @@ struct JSCompartment
|
|||
js::RegExpCompartment regExps;
|
||||
|
||||
/* Set of all currently living type representations. */
|
||||
js::TypeRepresentationSet typeReprs;
|
||||
js::TypeRepresentationHash typeReprs;
|
||||
|
||||
private:
|
||||
void sizeOfTypeInferenceData(JS::TypeInferenceSizes *stats, mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
|
|
@ -46,7 +46,7 @@ PerThreadDataFriendFields::PerThreadDataFriendFields()
|
|||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook)
|
||||
js::SetSourceHook(JSRuntime *rt, SourceHook *hook)
|
||||
{
|
||||
rt->sourceHook = hook;
|
||||
}
|
||||
|
|
|
@ -203,14 +203,34 @@ struct JSFunctionSpecWithHelp {
|
|||
extern JS_FRIEND_API(bool)
|
||||
JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs);
|
||||
|
||||
typedef bool (* JS_SourceHook)(JSContext *cx, const char *filename,
|
||||
jschar **src, uint32_t *length);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook);
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* A class of objects that return source code on demand.
|
||||
*
|
||||
* When code is compiled with CompileOptions::LAZY_SOURCE, SpiderMonkey
|
||||
* doesn't retain the source code (and doesn't do lazy bytecode
|
||||
* generation). If we ever need the source code, say, in response to a call
|
||||
* to Function.prototype.toSource or Debugger.Source.prototype.text, then
|
||||
* we call the 'load' member function of the instance of this class that
|
||||
* has hopefully been registered with the runtime, passing the code's URL,
|
||||
* and hope that it will be able to find the source.
|
||||
*/
|
||||
class SourceHook {
|
||||
public:
|
||||
virtual ~SourceHook() { }
|
||||
|
||||
/* Set |*src| and |*length| to refer to the source code for |filename|. */
|
||||
virtual bool load(JSContext *cx, const char *filename, jschar **src, size_t *length) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
* Have |rt| use |hook| to retrieve LAZY_SOURCE source code.
|
||||
* See the comments for SourceHook.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
SetSourceHook(JSRuntime *rt, SourceHook *hook);
|
||||
|
||||
inline JSRuntime *
|
||||
GetRuntime(const JSContext *cx)
|
||||
{
|
||||
|
|
|
@ -650,11 +650,12 @@ js::Int32ToAtom<NoGC>(ExclusiveContext *cx, int32_t si);
|
|||
|
||||
/* Returns a non-NULL pointer to inside cbuf. */
|
||||
static char *
|
||||
IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
|
||||
IntToCString(ToCStringBuf *cbuf, int i, size_t *len, int base = 10)
|
||||
{
|
||||
unsigned u = (i < 0) ? -i : i;
|
||||
|
||||
RangedPtr<char> cp(cbuf->sbuf + cbuf->sbufSize - 1, cbuf->sbuf, cbuf->sbufSize);
|
||||
RangedPtr<char> cp(cbuf->sbuf + ToCStringBuf::sbufSize - 1, cbuf->sbuf, ToCStringBuf::sbufSize);
|
||||
char *end = cp.get();
|
||||
*cp = '\0';
|
||||
|
||||
/* Build the string from behind. */
|
||||
|
@ -681,6 +682,7 @@ IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
|
|||
if (i < 0)
|
||||
*--cp = '-';
|
||||
|
||||
*len = end - cp.get();
|
||||
return cp.get();
|
||||
}
|
||||
|
||||
|
@ -1309,8 +1311,9 @@ char *
|
|||
js::NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base/* = 10*/)
|
||||
{
|
||||
int32_t i;
|
||||
size_t len;
|
||||
return mozilla::DoubleIsInt32(d, &i)
|
||||
? IntToCString(cbuf, i, base)
|
||||
? IntToCString(cbuf, i, &len, base)
|
||||
: FracNumberToCString(cx, cbuf, d, base);
|
||||
}
|
||||
|
||||
|
@ -1350,7 +1353,8 @@ js_NumberToStringWithBase(ThreadSafeContext *cx, double d, int base)
|
|||
return str;
|
||||
}
|
||||
|
||||
numStr = IntToCString(&cbuf, i, base);
|
||||
size_t len;
|
||||
numStr = IntToCString(&cbuf, i, &len, base);
|
||||
JS_ASSERT(!cbuf.dbuf && numStr >= cbuf.sbuf && numStr < cbuf.sbuf + cbuf.sbufSize);
|
||||
} else {
|
||||
if (comp) {
|
||||
|
@ -1466,21 +1470,23 @@ js::NumberValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb)
|
|||
/* Convert to C-string. */
|
||||
ToCStringBuf cbuf;
|
||||
const char *cstr;
|
||||
size_t cstrlen;
|
||||
if (v.isInt32()) {
|
||||
cstr = IntToCString(&cbuf, v.toInt32());
|
||||
cstr = IntToCString(&cbuf, v.toInt32(), &cstrlen);
|
||||
JS_ASSERT(cstrlen == strlen(cstr));
|
||||
} else {
|
||||
cstr = NumberToCString(cx, &cbuf, v.toDouble());
|
||||
if (!cstr) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
cstrlen = strlen(cstr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inflate to jschar string. The input C-string characters are < 127, so
|
||||
* even if jschars are UTF-8, all chars should map to one jschar.
|
||||
*/
|
||||
size_t cstrlen = strlen(cstr);
|
||||
JS_ASSERT(!cbuf.dbuf && cstrlen < cbuf.sbufSize);
|
||||
return sb.appendInflated(cstr, cstrlen);
|
||||
}
|
||||
|
|
|
@ -998,8 +998,8 @@ JSScript::loadSource(JSContext *cx, ScriptSource *ss, bool *worked)
|
|||
if (!cx->runtime()->sourceHook || !ss->sourceRetrievable())
|
||||
return true;
|
||||
jschar *src = NULL;
|
||||
uint32_t length;
|
||||
if (!cx->runtime()->sourceHook(cx, ss->filename(), &src, &length))
|
||||
size_t length;
|
||||
if (!cx->runtime()->sourceHook->load(cx, ss->filename(), &src, &length))
|
||||
return false;
|
||||
if (!src)
|
||||
return true;
|
||||
|
@ -1124,7 +1124,7 @@ ScriptSource::setSourceCopy(ExclusiveContext *cx, const jschar *src, uint32_t le
|
|||
}
|
||||
|
||||
void
|
||||
ScriptSource::setSource(const jschar *src, uint32_t length)
|
||||
ScriptSource::setSource(const jschar *src, size_t length)
|
||||
{
|
||||
JS_ASSERT(!hasSourceData());
|
||||
length_ = length;
|
||||
|
|
|
@ -341,7 +341,7 @@ class ScriptSource
|
|||
uint32_t length,
|
||||
bool argumentsNotIncluded,
|
||||
SourceCompressionTask *tok);
|
||||
void setSource(const jschar *src, uint32_t length);
|
||||
void setSource(const jschar *src, size_t length);
|
||||
bool ready() const { return ready_; }
|
||||
void setSourceRetrievable() { sourceRetrievable_ = true; }
|
||||
bool sourceRetrievable() const { return sourceRetrievable_; }
|
||||
|
|
|
@ -4164,29 +4164,6 @@ js::DeflateStringToBuffer(JSContext *maybecx, const jschar *src, size_t srclen,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::InflateStringToBuffer(JSContext *maybecx, const char *src, size_t srclen,
|
||||
jschar *dst, size_t *dstlenp)
|
||||
{
|
||||
if (dst) {
|
||||
size_t dstlen = *dstlenp;
|
||||
if (srclen > dstlen) {
|
||||
for (size_t i = 0; i < dstlen; i++)
|
||||
dst[i] = (unsigned char) src[i];
|
||||
if (maybecx) {
|
||||
AutoSuppressGC suppress(maybecx);
|
||||
JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BUFFER_TOO_SMALL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < srclen; i++)
|
||||
dst[i] = (unsigned char) src[i];
|
||||
}
|
||||
*dstlenp = srclen;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ____ false
|
||||
|
||||
/*
|
||||
|
|
|
@ -249,15 +249,15 @@ extern jschar *
|
|||
InflateString(ThreadSafeContext *cx, const char *bytes, size_t *length);
|
||||
|
||||
/*
|
||||
* Inflate bytes to JS chars in an existing buffer. 'chars' must be large
|
||||
* enough for 'length' jschars. The buffer is NOT null-terminated.
|
||||
*
|
||||
* charsLength must be be initialized with the destination buffer size and, on
|
||||
* return, will contain on return the number of copied chars.
|
||||
* Inflate bytes to JS chars in an existing buffer. 'dst' must be large
|
||||
* enough for 'srclen' jschars. The buffer is NOT null-terminated.
|
||||
*/
|
||||
extern bool
|
||||
InflateStringToBuffer(JSContext *maybecx, const char *bytes, size_t length,
|
||||
jschar *chars, size_t *charsLength);
|
||||
inline void
|
||||
InflateStringToBuffer(const char *src, size_t srclen, jschar *dst)
|
||||
{
|
||||
for (size_t i = 0; i < srclen; i++)
|
||||
dst[i] = (unsigned char) src[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
|
||||
|
|
|
@ -248,6 +248,7 @@ if CONFIG['ENABLE_ION']:
|
|||
'Snapshots.cpp',
|
||||
'StupidAllocator.cpp',
|
||||
'TypePolicy.cpp',
|
||||
'TypeRepresentationSet.cpp',
|
||||
'UnreachableCodeElimination.cpp',
|
||||
'VMFunctions.cpp',
|
||||
'ValueNumbering.cpp',
|
||||
|
|
|
@ -234,7 +234,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
|||
negativeInfinityValue(DoubleValue(NegativeInfinity())),
|
||||
positiveInfinityValue(DoubleValue(PositiveInfinity())),
|
||||
emptyString(NULL),
|
||||
sourceHook(NULL),
|
||||
debugMode(false),
|
||||
spsProfiler(thisFromCtor()),
|
||||
profilingScripts(false),
|
||||
|
@ -399,6 +398,9 @@ JSRuntime::~JSRuntime()
|
|||
{
|
||||
JS_ASSERT(!isHeapBusy());
|
||||
|
||||
/* Free source hook early, as its destructor may want to delete roots. */
|
||||
sourceHook = NULL;
|
||||
|
||||
/* Off thread compilation and parsing depend on atoms still existing. */
|
||||
for (CompartmentsIter comp(this); !comp.done(); comp.next())
|
||||
CancelOffThreadIonCompile(comp, NULL);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
#include "mozilla/ThreadLocal.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
@ -1275,7 +1276,7 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||
return !contextList.isEmpty();
|
||||
}
|
||||
|
||||
JS_SourceHook sourceHook;
|
||||
mozilla::ScopedDeletePtr<js::SourceHook> sourceHook;
|
||||
|
||||
/* Per runtime debug hooks -- see js/OldDebugAPI.h. */
|
||||
JSDebugHooks debugHooks;
|
||||
|
|
|
@ -122,10 +122,7 @@ StringBuffer::appendInflated(const char *cstr, size_t cstrlen)
|
|||
size_t lengthBefore = length();
|
||||
if (!cb.growByUninitialized(cstrlen))
|
||||
return false;
|
||||
mozilla::DebugOnly<size_t> oldcstrlen = cstrlen;
|
||||
mozilla::DebugOnly<bool> ok = InflateStringToBuffer(NULL, cstr, cstrlen,
|
||||
begin() + lengthBefore, &cstrlen);
|
||||
JS_ASSERT(ok && oldcstrlen == cstrlen);
|
||||
InflateStringToBuffer(cstr, cstrlen, begin() + lengthBefore);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2774,100 +2774,103 @@ PreserveWrapper(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
static nsresult
|
||||
ReadSourceFromFilename(JSContext *cx, const char *filename, jschar **src, uint32_t *len)
|
||||
ReadSourceFromFilename(JSContext *cx, const char *filename, jschar **src, size_t *len)
|
||||
{
|
||||
nsresult rv;
|
||||
nsresult rv;
|
||||
|
||||
// mozJSSubScriptLoader prefixes the filenames of the scripts it loads with
|
||||
// the filename of its caller. Axe that if present.
|
||||
const char *arrow;
|
||||
while ((arrow = strstr(filename, " -> ")))
|
||||
filename = arrow + strlen(" -> ");
|
||||
// mozJSSubScriptLoader prefixes the filenames of the scripts it loads with
|
||||
// the filename of its caller. Axe that if present.
|
||||
const char *arrow;
|
||||
while ((arrow = strstr(filename, " -> ")))
|
||||
filename = arrow + strlen(" -> ");
|
||||
|
||||
// Get the URI.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), filename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Get the URI.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), filename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> scriptChannel;
|
||||
rv = NS_NewChannel(getter_AddRefs(scriptChannel), uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIChannel> scriptChannel;
|
||||
rv = NS_NewChannel(getter_AddRefs(scriptChannel), uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Only allow local reading.
|
||||
nsCOMPtr<nsIURI> actualUri;
|
||||
rv = scriptChannel->GetURI(getter_AddRefs(actualUri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCString scheme;
|
||||
rv = actualUri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!scheme.EqualsLiteral("file") && !scheme.EqualsLiteral("jar"))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIInputStream> scriptStream;
|
||||
rv = scriptChannel->Open(getter_AddRefs(scriptStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint64_t rawLen;
|
||||
rv = scriptStream->Available(&rawLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!rawLen)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Technically, this should be SIZE_MAX, but we don't run on machines
|
||||
// where that would be less than UINT32_MAX, and the latter is already
|
||||
// well beyond a reasonable limit.
|
||||
if (rawLen > UINT32_MAX)
|
||||
return NS_ERROR_FILE_TOO_BIG;
|
||||
|
||||
// Allocate an internal buf the size of the file.
|
||||
nsAutoArrayPtr<unsigned char> buf(new unsigned char[rawLen]);
|
||||
if (!buf)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
unsigned char *ptr = buf, *end = ptr + rawLen;
|
||||
while (ptr < end) {
|
||||
uint32_t bytesRead;
|
||||
rv = scriptStream->Read(reinterpret_cast<char *>(ptr), end - ptr, &bytesRead);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
MOZ_ASSERT(bytesRead > 0, "stream promised more bytes before EOF");
|
||||
ptr += bytesRead;
|
||||
}
|
||||
|
||||
nsString decoded;
|
||||
rv = nsScriptLoader::ConvertToUTF16(scriptChannel, buf, rawLen, EmptyString(), NULL, decoded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Copy to JS engine.
|
||||
*len = decoded.Length();
|
||||
*src = static_cast<jschar *>(JS_malloc(cx, decoded.Length()*sizeof(jschar)));
|
||||
if (!*src)
|
||||
return NS_ERROR_FAILURE;
|
||||
memcpy(*src, decoded.get(), decoded.Length()*sizeof(jschar));
|
||||
|
||||
// Only allow local reading.
|
||||
nsCOMPtr<nsIURI> actualUri;
|
||||
rv = scriptChannel->GetURI(getter_AddRefs(actualUri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCString scheme;
|
||||
rv = actualUri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!scheme.EqualsLiteral("file") && !scheme.EqualsLiteral("jar"))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIInputStream> scriptStream;
|
||||
rv = scriptChannel->Open(getter_AddRefs(scriptStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint64_t rawLen;
|
||||
rv = scriptStream->Available(&rawLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!rawLen)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (rawLen > UINT32_MAX)
|
||||
return NS_ERROR_FILE_TOO_BIG;
|
||||
|
||||
// Allocate an internal buf the size of the file.
|
||||
nsAutoArrayPtr<unsigned char> buf(new unsigned char[rawLen]);
|
||||
if (!buf)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
unsigned char *ptr = buf, *end = ptr + rawLen;
|
||||
while (ptr < end) {
|
||||
uint32_t bytesRead;
|
||||
rv = scriptStream->Read(reinterpret_cast<char *>(ptr), end - ptr, &bytesRead);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
MOZ_ASSERT(bytesRead > 0, "stream promised more bytes before EOF");
|
||||
ptr += bytesRead;
|
||||
}
|
||||
|
||||
nsString decoded;
|
||||
rv = nsScriptLoader::ConvertToUTF16(scriptChannel, buf, rawLen, EmptyString(), NULL, decoded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Copy to JS engine.
|
||||
*len = decoded.Length();
|
||||
*src = static_cast<jschar *>(JS_malloc(cx, decoded.Length()*sizeof(jschar)));
|
||||
if (!*src)
|
||||
return NS_ERROR_FAILURE;
|
||||
memcpy(*src, decoded.get(), decoded.Length()*sizeof(jschar));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
The JS engine calls this function when it needs the source for a chrome JS
|
||||
function. See the comment in the XPCJSRuntime constructor.
|
||||
*/
|
||||
static bool
|
||||
SourceHook(JSContext *cx, const char *filename, jschar **src, uint32_t *length)
|
||||
{
|
||||
*src = NULL;
|
||||
*length = 0;
|
||||
// The JS engine calls this object's 'load' member function when it needs
|
||||
// the source for a chrome JS function. See the comment in the XPCJSRuntime
|
||||
// constructor.
|
||||
class XPCJSSourceHook: public js::SourceHook {
|
||||
bool load(JSContext *cx, const char *filename, jschar **src, size_t *length) {
|
||||
*src = NULL;
|
||||
*length = 0;
|
||||
|
||||
if (!nsContentUtils::IsCallerChrome())
|
||||
return true;
|
||||
if (!nsContentUtils::IsCallerChrome())
|
||||
return true;
|
||||
|
||||
if (!filename)
|
||||
return true;
|
||||
if (!filename)
|
||||
return true;
|
||||
|
||||
nsresult rv = ReadSourceFromFilename(cx, filename, src, length);
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc::Throw(cx, rv);
|
||||
return false;
|
||||
}
|
||||
nsresult rv = ReadSourceFromFilename(cx, filename, src, length);
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc::Throw(cx, rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||
: CycleCollectedJSRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS),
|
||||
|
@ -3036,7 +3039,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
|||
// compileAndGo mode and compiled function bodies (from
|
||||
// JS_CompileFunction*). In practice, this means content scripts and event
|
||||
// handlers.
|
||||
JS_SetSourceHook(runtime, SourceHook);
|
||||
js::SetSourceHook(runtime, new XPCJSSourceHook);
|
||||
|
||||
// Set up locale information and callbacks for the newly-created runtime so
|
||||
// that the various toLocaleString() methods, localeCompare(), and other
|
||||
|
|
|
@ -5494,7 +5494,24 @@ nsLayoutUtils::UpdateImageVisibilityForFrame(nsIFrame* aImageFrame)
|
|||
visible = false;
|
||||
break;
|
||||
}
|
||||
rect = sf->GetScrollPortRect();
|
||||
// Move transformedRect to be contained in the scrollport as best we can
|
||||
// (it might not fit) to pretend that it was scrolled into view.
|
||||
nsRect scrollPort = sf->GetScrollPortRect();
|
||||
if (transformedRect.XMost() > scrollPort.XMost()) {
|
||||
transformedRect.x -= transformedRect.XMost() - scrollPort.XMost();
|
||||
}
|
||||
if (transformedRect.x < scrollPort.x) {
|
||||
transformedRect.x = scrollPort.x;
|
||||
}
|
||||
if (transformedRect.YMost() > scrollPort.YMost()) {
|
||||
transformedRect.y -= transformedRect.YMost() - scrollPort.YMost();
|
||||
}
|
||||
if (transformedRect.y < scrollPort.y) {
|
||||
transformedRect.y = scrollPort.y;
|
||||
}
|
||||
transformedRect.width = std::min(transformedRect.width, scrollPort.width);
|
||||
transformedRect.height = std::min(transformedRect.height, scrollPort.height);
|
||||
rect = transformedRect;
|
||||
rectFrame = f;
|
||||
}
|
||||
nsIFrame* parent = f->GetParent();
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#define ArrayBufferInputStream_h
|
||||
|
||||
#include "nsIArrayBufferInputStream.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "js/Value.h"
|
||||
|
||||
#define NS_ARRAYBUFFERINPUTSTREAM_CONTRACTID "@mozilla.org/io/arraybuffer-input-stream;1"
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "pk11pub.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
#include "secoidt.h"
|
||||
|
@ -13,7 +12,6 @@
|
|||
#include "nsIPipe.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
|
||||
#include "BackgroundFileSaver.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
#include "mozilla/net/HttpInfo.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsHttp.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsISocketTransport.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsSocketTransport2.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using mozilla::AutoSafeJSContext;
|
||||
|
|
|
@ -6,9 +6,13 @@
|
|||
|
||||
#include "EventTokenBucket.h"
|
||||
|
||||
#include "nsICancelable.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "MainThreadUtils.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class nsICancelable;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "nsIDNSListener.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
@ -17,6 +16,8 @@
|
|||
#include "prnetdb.h"
|
||||
#include "nsITimer.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -326,6 +327,14 @@ bool PACResolve(const nsCString &aHostName, NetAddr *aNetAddr,
|
|||
return sRunning->ResolveAddress(aHostName, aNetAddr, aTimeout);
|
||||
}
|
||||
|
||||
ProxyAutoConfig::ProxyAutoConfig()
|
||||
: mJSRuntime(nullptr)
|
||||
, mJSNeedsSetup(false)
|
||||
, mShutdown(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProxyAutoConfig);
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyAutoConfig::ResolveAddress(const nsCString &aHostName,
|
||||
NetAddr *aNetAddr,
|
||||
|
|
|
@ -8,15 +8,17 @@
|
|||
#define ProxyAutoConfig_h__
|
||||
|
||||
#include "nsString.h"
|
||||
#include "prio.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsITimer;
|
||||
namespace JS {
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class JSRuntimeWrapper;
|
||||
union NetAddr;
|
||||
|
||||
// The ProxyAutoConfig class is meant to be created and run on a
|
||||
// non main thread. It synchronously resolves PAC files by blocking that
|
||||
|
@ -24,13 +26,7 @@ class JSRuntimeWrapper;
|
|||
|
||||
class ProxyAutoConfig {
|
||||
public:
|
||||
ProxyAutoConfig()
|
||||
: mJSRuntime(nullptr)
|
||||
, mJSNeedsSetup(false)
|
||||
, mShutdown(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProxyAutoConfig);
|
||||
}
|
||||
ProxyAutoConfig();
|
||||
~ProxyAutoConfig();
|
||||
|
||||
nsresult Init(const nsCString &aPACURI,
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Tickler.h"
|
||||
|
||||
#ifdef MOZ_USE_WIFI_TICKLER
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "prnetdb.h"
|
||||
#include "Tickler.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef MOZ_USE_WIFI_TICKLER
|
||||
#include "prnetdb.h"
|
||||
|
||||
#include "AndroidBridge.h"
|
||||
|
||||
|
|
|
@ -27,6 +27,15 @@
|
|||
// The tickler only applies to wifi on mobile right now. Hopefully it
|
||||
// can also be restricted to particular handset models in the future.
|
||||
|
||||
#if defined(ANDROID) && !defined(MOZ_B2G)
|
||||
#define MOZ_USE_WIFI_TICKLER
|
||||
#endif
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsISupports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef MOZ_USE_WIFI_TICKLER
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -34,16 +43,14 @@
|
|||
#include "nsIThread.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "prio.h"
|
||||
|
||||
class nsIPrefBranch;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
#if defined(ANDROID) && !defined(MOZ_B2G)
|
||||
#define MOZ_USE_WIFI_TICKLER
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_USE_WIFI_TICKLER
|
||||
|
||||
class Tickler MOZ_FINAL : public nsSupportsWeakReference
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIOService.h"
|
||||
#include "nsAsyncStreamCopier.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsNetSegmentUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "prlog.h"
|
||||
|
||||
|
|
|
@ -6,13 +6,12 @@
|
|||
#define nsAsyncStreamCopier_h__
|
||||
|
||||
#include "nsIAsyncStreamCopier.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIRequestObserver;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsAsyncStreamCopier : public nsIAsyncStreamCopier
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsBaseChannel.h"
|
||||
#include "nsChannelProperties.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsIHttpEventSink.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "nsInputStreamPump.h"
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
@ -25,6 +24,8 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsBaseChannel is designed to be subclassed. The subclass is responsible for
|
||||
// implementing the OpenContentStream method, which will be called by the
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsBufferedStreams.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#define nsChannelClassifier_h__
|
||||
|
||||
#include "nsIURIClassifier.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
|
|
|
@ -7,12 +7,10 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
static nsIDNSService *sDNSService = nullptr;
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#ifndef nsDNSPrefetch_h___
|
||||
#define nsDNSPrefetch_h___
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
|
|
@ -16,23 +16,20 @@
|
|||
|
||||
#include "nsEscape.h"
|
||||
#include "nsDirectoryIndexStream.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "prio.h"
|
||||
#include "prlog.h"
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gLog;
|
||||
#endif
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#ifdef THREADSAFE_I18N
|
||||
#include "nsCollationCID.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsILocale.h"
|
||||
#include "nsILocaleService.h"
|
||||
#include "nsCollationCID.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#endif
|
||||
#include "nsIFile.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
|
||||
// NOTE: This runs on the _file transport_ thread.
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "nsIFile.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsITextToSubURI.h"
|
||||
|
||||
class nsIFile;
|
||||
|
||||
class nsDirectoryIndexStream MOZ_FINAL : public nsIInputStream
|
||||
{
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
#define nsDownloader_h__
|
||||
|
||||
#include "nsIDownloader.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIFile;
|
||||
class nsIOutputStream;
|
||||
|
||||
class nsDownloader : public nsIDownloader
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -19,16 +19,11 @@
|
|||
#include "private/pprio.h"
|
||||
|
||||
#include "nsFileStreams.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "prerror.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsDirectoryIndexStream.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsReadLine.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
|
||||
#define NS_NO_INPUT_BUFFERING 1 // see http://bugzilla.mozilla.org/show_bug.cgi?id=41067
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#ifndef nsFileStreams_h__
|
||||
#define nsFileStreams_h__
|
||||
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsIFile.h"
|
||||
|
@ -16,8 +15,6 @@
|
|||
#include "nsISeekableStream.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "prlog.h"
|
||||
#include "prio.h"
|
||||
#include "nsIIPCSerializableInputStream.h"
|
||||
#include "nsReadLine.h"
|
||||
#include <algorithm>
|
||||
|
|
|
@ -10,40 +10,33 @@
|
|||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIFileProtocolHandler.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "prprf.h"
|
||||
#include "prlog.h"
|
||||
#include "nsLoadGroup.h"
|
||||
#include "nsInputStreamChannel.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIErrorService.h"
|
||||
#include "nsIErrorService.h"
|
||||
#include "netCore.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIProxiedProtocolHandler.h"
|
||||
#include "nsIProxyInfo.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsISocketTransport.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsSimpleNestedURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsIProxiedChannel.h"
|
||||
#include "nsIProtocolProxyCallback.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
#include "nsPISocketTransportService.h"
|
||||
#include "nsAsyncRedirectVerifyHelper.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsPIDNSService.h"
|
||||
#include "nsIProtocolProxyService2.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "nsNativeConnectionHelper.h"
|
||||
|
|
|
@ -6,26 +6,16 @@
|
|||
#ifndef nsIOService_h__
|
||||
#define nsIOService_h__
|
||||
|
||||
#include "necko-config.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "nsIIOService2.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsPISocketTransportService.h"
|
||||
#include "nsPIDNSService.h"
|
||||
#include "nsIProtocolProxyService2.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIURLParser.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsINetUtil.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIContentSniffer.h"
|
||||
#include "nsCategoryCache.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
#include "nsAsyncRedirectVerifyHelper.h"
|
||||
#include "nsISpeculativeConnect.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
|
@ -39,7 +29,13 @@
|
|||
static const char gScheme[][sizeof("resource")] =
|
||||
{"chrome", "file", "http", "jar", "resource"};
|
||||
|
||||
class nsAsyncRedirectVerifyHelper;
|
||||
class nsINetworkLinkService;
|
||||
class nsIPrefBranch;
|
||||
class nsIProtocolProxyService2;
|
||||
class nsIProxyInfo;
|
||||
class nsPIDNSService;
|
||||
class nsPISocketTransportService;
|
||||
|
||||
class nsIOService MOZ_FINAL : public nsIIOService2
|
||||
, public nsIObserver
|
||||
|
|
|
@ -14,14 +14,11 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsChannelProperties.h"
|
||||
#include "prio.h"
|
||||
#include "prprf.h"
|
||||
#include <algorithm>
|
||||
|
|
|
@ -4,22 +4,19 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsInputStreamPump.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStreamTransportService.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "prlog.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsNetCID.h"
|
||||
#include <algorithm>
|
||||
|
||||
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
|
||||
|
|
|
@ -7,18 +7,15 @@
|
|||
#define nsInputStreamPump_h__
|
||||
|
||||
#include "nsIInputStreamPump.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsIInputStream;
|
||||
class nsILoadGroup;
|
||||
class nsIStreamListener;
|
||||
|
||||
class nsInputStreamPump MOZ_FINAL : public nsIInputStreamPump
|
||||
, public nsIInputStreamCallback
|
||||
, public nsIThreadRetargetableRequest
|
||||
|
|
|
@ -10,22 +10,17 @@
|
|||
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIURI.h"
|
||||
#include "prlog.h"
|
||||
#include "nsCRT.h"
|
||||
#include "netCore.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/net/PSpdyPush3.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -9,20 +9,16 @@
|
|||
#include "nsILoadGroup.h"
|
||||
#include "nsILoadGroupChild.h"
|
||||
#include "nsPILoadGroupInternal.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsAgg.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "pldhash.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class nsILoadGroupConnectionInfo;
|
||||
class nsILoadGroupConnectionInfo;
|
||||
class nsITimedChannel;
|
||||
|
||||
class nsLoadGroup : public nsILoadGroup,
|
||||
public nsILoadGroupChild,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsIURI.h"
|
||||
#include <utility>
|
||||
|
||||
#include "nsMediaFragmentURIParser.h"
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
#define nsMediaFragmentURIParser_h__
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsString.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
class nsIURI;
|
||||
|
||||
// Class to handle parsing of a W3C media fragment URI as per
|
||||
// spec at: http://www.w3.org/TR/media-frags/
|
||||
// Only the temporaral URI portion of the spec is implemented.
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "nsNetAddr.h"
|
||||
#include "nsString.h"
|
||||
#include "prnetdb.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
|
||||
using namespace mozilla::net;
|
||||
|
|
|
@ -12,10 +12,8 @@
|
|||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prmon.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsISystemProxySettings.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
using namespace mozilla;
|
||||
|
|
|
@ -11,19 +11,18 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "ProxyAutoConfig.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISystemProxySettings.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class nsPACMan;
|
||||
class nsISystemProxySettings;
|
||||
class nsIThread;
|
||||
|
||||
/**
|
||||
* This class defines a callback interface used by AsyncGetProxyForURI.
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "nsIRunnable.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#include "nsProtocolProxyService.h"
|
||||
#include "nsProxyInfo.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
|
@ -21,17 +19,16 @@
|
|||
#include "nsPIDNSService.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nsPACMan.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/CondVar.h"
|
||||
#include "nsISystemProxySettings.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -10,16 +10,12 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIProtocolProxyService2.h"
|
||||
#include "nsIProtocolProxyFilter.h"
|
||||
#include "nsISystemProxySettings.h"
|
||||
#include "nsIProxyInfo.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsPACMan.h"
|
||||
#include "prtime.h"
|
||||
#include "prio.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
|
@ -27,6 +23,9 @@ typedef nsDataHashtable<nsCStringHashKey, uint32_t> nsFailedProxyTable;
|
|||
|
||||
class nsProxyInfo;
|
||||
struct nsProtocolInfo;
|
||||
class nsIPrefBranch;
|
||||
class nsISystemProxySettings;
|
||||
class nsPACMan;
|
||||
|
||||
class nsProtocolProxyService MOZ_FINAL : public nsIProtocolProxyService2
|
||||
, public nsIObserver
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
#include "nscore.h"
|
||||
#include "nsRequestObserverProxy.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "prlog.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsISerializable;
|
||||
class nsISupports;
|
||||
|
||||
/**
|
||||
* Serialize an object to an ASCII string.
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsSocketTransport2.h"
|
||||
#include "nsServerSocket.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче