diff --git a/.taskcluster.yml b/.taskcluster.yml
index f8bbc9939f78..f5ce9752aba1 100644
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -48,12 +48,18 @@ tasks:
tags:
$if: 'tasks_for == "hg-push"'
- then: {createdForUser: "${ownerEmail}"}
+ then:
+ createdForUser: "${ownerEmail}"
+ kind: decision-task
else:
$if: 'tasks_for == "action"'
then:
createdForUser: '${ownerEmail}'
kind: 'action-callback'
+ else:
+ $if: 'tasks_for == "cron"'
+ then:
+ kind: cron-task
routes:
$flatten:
diff --git a/Cargo.lock b/Cargo.lock
index cec05e5f2680..ce37071015e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -69,7 +69,7 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -79,7 +79,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -88,19 +88,19 @@ name = "audioipc"
version = "0.2.4"
dependencies = [
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"cubeb 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)",
- "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -111,11 +111,11 @@ dependencies = [
"audioipc 0.2.4",
"cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -124,15 +124,15 @@ name = "audioipc-server"
version = "0.2.3"
dependencies = [
"audioipc 0.2.4",
- "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"cubeb-core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -221,11 +221,6 @@ name = "bit-vec"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "bitflags"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "bitflags"
version = "1.0.1"
@@ -253,11 +248,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bytes"
-version = "0.4.5"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -266,7 +261,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -275,7 +270,7 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -311,7 +306,7 @@ version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -340,7 +335,7 @@ dependencies = [
[[package]]
name = "cookie"
-version = "0.10.1"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -352,7 +347,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -368,7 +363,7 @@ dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -379,7 +374,7 @@ dependencies = [
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -415,6 +410,15 @@ dependencies = [
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "crossbeam-deque"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-epoch 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "crossbeam-epoch"
version = "0.3.1"
@@ -429,6 +433,19 @@ dependencies = [
"scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "crossbeam-epoch"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "crossbeam-utils"
version = "0.2.2"
@@ -437,6 +454,14 @@ dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "crossbeam-utils"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "cssparser"
version = "0.24.0"
@@ -564,7 +589,7 @@ name = "devd-rs"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -613,7 +638,7 @@ dependencies = [
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -718,7 +743,7 @@ name = "flate2"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -737,7 +762,7 @@ name = "freetype"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -746,29 +771,27 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
-version = "0.2.1"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
-version = "0.2.0"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
[[package]]
name = "futures"
-version = "0.1.18"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -776,7 +799,7 @@ name = "futures-cpupool"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -809,7 +832,7 @@ dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mozprofile 0.3.0",
@@ -831,7 +854,7 @@ dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1",
"nsstring 0.1.0",
@@ -914,11 +937,38 @@ name = "glob"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "h2"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "hashglobe"
version = "0.1.0"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "http"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -936,20 +986,27 @@ dependencies = [
[[package]]
name = "hyper"
-version = "0.10.13"
+version = "0.12.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -967,12 +1024,17 @@ dependencies = [
"unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "indexmap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "iovec"
-version = "0.1.0"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -998,7 +1060,7 @@ dependencies = [
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mozjs_sys 0.0.0",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1073,11 +1135,6 @@ name = "lalrpop-util"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "language-tags"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "lazy_static"
version = "1.0.1"
@@ -1088,9 +1145,14 @@ name = "lazycell"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "lazycell"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "libc"
-version = "0.2.39"
+version = "0.2.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -1107,7 +1169,7 @@ name = "libudev"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libudev-sys 0.1.3",
]
@@ -1116,7 +1178,7 @@ name = "libudev-sys"
version = "0.1.3"
dependencies = [
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1125,7 +1187,7 @@ version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1141,7 +1203,7 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"lmdb-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1151,7 +1213,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1215,7 +1277,7 @@ name = "memchr"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1223,7 +1285,7 @@ name = "memchr"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1233,7 +1295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1242,21 +1304,13 @@ name = "memoffset"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "mime"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "miniz_oxide"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1266,23 +1320,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio"
-version = "0.6.9"
+version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1291,8 +1347,8 @@ name = "mio-uds"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1301,7 +1357,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1315,7 +1371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "mozjs_sys"
version = "0.0.0"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1397,14 +1453,12 @@ dependencies = [
[[package]]
name = "net2"
-version = "0.2.31"
+version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1528,7 +1582,7 @@ name = "num_cpus"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1559,8 +1613,8 @@ version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1607,7 +1661,7 @@ version = "0.7.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1681,7 +1735,7 @@ dependencies = [
name = "pulse-ffi"
version = "0.1.0"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1712,11 +1766,22 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.3.18"
+version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1735,9 +1800,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1819,7 +1884,7 @@ dependencies = [
name = "rsdparsa_capi"
version = "0.1.0"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"nserror 0.1.0",
"rsdparsa 0.1.0",
@@ -1969,6 +2034,11 @@ name = "slab"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "slab"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "smallbitvec"
version = "2.1.1"
@@ -1987,6 +2057,11 @@ name = "stable_deref_trait"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "string"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "string_cache"
version = "0.7.3"
@@ -2111,7 +2186,7 @@ dependencies = [
"cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"geckoservo 0.0.1",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1",
"num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2170,7 +2245,7 @@ name = "tempdir"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2188,7 +2263,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2233,34 +2308,144 @@ name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "tokio-core"
+name = "tokio"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-udp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-codec"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-core"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-executor"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-fs"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-io"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-reactor"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-tcp"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-threadpool"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-timer"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-udp"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2268,15 +2453,15 @@ name = "tokio-uds"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2288,13 +2473,8 @@ dependencies = [
]
[[package]]
-name = "traitobject"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "typeable"
-version = "0.1.2"
+name = "try-lock"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -2306,10 +2486,10 @@ dependencies = [
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"devd-rs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2327,14 +2507,6 @@ dependencies = [
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "unicase"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "unicode-bidi"
version = "0.3.4"
@@ -2391,7 +2563,7 @@ name = "uuid"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2404,11 +2576,6 @@ name = "vec_map"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "version_check"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "void"
version = "1.0.2"
@@ -2423,13 +2590,25 @@ dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "want"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "webdriver"
version = "0.36.0"
dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2437,6 +2616,7 @@ dependencies = [
"serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2524,7 +2704,7 @@ name = "which"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2593,7 +2773,7 @@ dependencies = [
name = "xpcom"
version = "0.1.0"
dependencies = [
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"nserror 0.1.0",
"nsstring 0.1.0",
"xpcom_macros 0.1.0",
@@ -2656,13 +2836,12 @@ dependencies = [
"checksum binjs_meta 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fd7ca5635f1c6f94aaef7de76cb834c5920578355ce41dbcaf731b7ebe348518"
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
-"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
"checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
"checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
-"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
+"checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
@@ -2672,7 +2851,7 @@ dependencies = [
"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
-"checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb"
+"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
"checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
"checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
"checksum core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92801c908ea6301ae619ed842a72e01098085fc321b9c2f3f833dad555bba055"
@@ -2681,8 +2860,11 @@ dependencies = [
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
+"checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
+"checksum crossbeam-epoch 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2af0e75710d6181e234c8ecc79f14a97907850a541b13b0be1dd10992f2e4620"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
+"checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b"
"checksum cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)" = "495beddc39b1987b8e9f029354eccbd5ef88eb5f1cd24badb764dce338acf2e0"
"checksum cssparser-macros 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f3a5383ae18dbfdeb569ed62019f5bddb2a95cd2d3833313c475a0d014777805"
"checksum cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b6557bdb1dc9647eae1cf7f5601b14cd45fc3c7ccf2df618387416fe542da6ea"
@@ -2715,9 +2897,9 @@ dependencies = [
"checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0"
"checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
-"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
-"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
-"checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7"
+"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+"checksum futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "884dbe32a6ae4cd7da5c6db9b78114449df9953b8d490c9d7e1b51720b922c62"
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
@@ -2725,12 +2907,15 @@ dependencies = [
"checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a"
"checksum gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d41e7ac812597988fdae31c9baec3c6d35cadb8ad9ab88a9bf9c0f119ed66c2"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
+"checksum h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a27e7ed946e8335bdf9a191bc1b9b14a03ba822d013d2f58437f4fabcbd7fc2c"
+"checksum http 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "dca621d0fa606a5ff2850b6e337b57ad6137ee4d67e940449643ff45af6874c6"
"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
-"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2"
+"checksum hyper 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c087746de95e20e4dabe86606c3a019964a8fde2d5f386152939063c116c5971"
"checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
-"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
+"checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220"
+"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394"
"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
@@ -2739,10 +2924,10 @@ dependencies = [
"checksum lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4fd87be4a815fd373e02773983940f0d75fb26fde8c098e9e45f7af03154c0"
"checksum lalrpop-snap 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f244285324e4e33d486910b66fd3b7cb37e2072c5bf63319f506fe99ed72650"
"checksum lalrpop-util 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "de408fd50dea8ad7a77107144983a25c7fdabf5f8faf707a6e020d68874ed06c"
-"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
-"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
+"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
+"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
"checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
@@ -2757,16 +2942,15 @@ dependencies = [
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
"checksum miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa2d3ad070f428fffbd7d3ca2ea20bb0d8cffe9024405c44e1840bc1418b398"
"checksum miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92d98fdbd6145645828069b37ea92ca3de225e000d80702da25c20d3584b38a5"
-"checksum mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9e965267d4d58496fc4f740e9861118367f13570cadf66316ed2c3f2f14d87c7"
+"checksum mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4fcfcb32d63961fb6f367bfd5d21e4600b92cd310f71f9dca25acae196eb1560"
"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c82a57087fd5990d7122dbff1607c3b20c3d2958e9d9ad9765aab415e2c91c"
"checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
"checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958"
-"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
+"checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0"
"checksum new-ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ccbebba6fb53a6d2bdcfaf79cb339bc136dee3bfff54dc337a334bafe36476a"
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
@@ -2801,7 +2985,8 @@ dependencies = [
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
-"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
+"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
+"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d"
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
@@ -2829,9 +3014,11 @@ dependencies = [
"checksum simd 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3686dd9418ebcc3a26a0c0ae56deab0681e53fe899af91f5bbcee667ebffb1"
"checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
+"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
"checksum smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c63726029f0069f88467873e47f392575f28f9f16b72ac65465263db4b3a13c"
"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
+"checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970"
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
"checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
@@ -2850,15 +3037,22 @@ dependencies = [
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
"checksum thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf947d192a9be60ef5131cc7a4648886ba89d712f16700ebbf80c8a69d05d48f"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
-"checksum tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "febd81b3e2ef615c6c8077347b33f3f3deec3d708ecd08194c9707b7a1eccfc9"
-"checksum tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ab83e7adb5677e42e405fa4ceff75659d93c4d7d7dd22f52fcec59ee9f02af"
+"checksum tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee337e5f4e501fc32966fec6fe0ca0cc1c237b0b1b14a335f8bfe3c5f06e286"
+"checksum tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "881e9645b81c2ce95fcb799ded2c29ffb9f25ef5bef909089a420e5961dd8ccb"
+"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71"
+"checksum tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "424f0c87ecd66b863045d84e384cb7ce0ae384d8b065b9f0363d29c0d1b30b2f"
+"checksum tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5cbe4ca6e71cb0b62a66e4e6f53a8c06a6eefe46cc5f665ad6f274c9906f135"
+"checksum tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a5c9635ee806f26d302b8baa1e145689a280d8f5aa8d0552e7344808da54cc21"
+"checksum tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8703a5762ff6913510dc64272c714c4389ffd8c4b3cf602879b8bd14ff06b604"
+"checksum tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4c329b47f071eb8a746040465fa751bd95e4716e98daef6a9b4e434c17d565"
+"checksum tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "24ab84f574027b0e875378f31575cf175360891919e93a3490f07e76e00e4efb"
+"checksum tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1c76b4e97a4f61030edff8bd272364e4f731b9f54c7307eb4eb733c3926eb96a"
+"checksum tokio-udp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43eb534af6e8f37d43ab1b612660df14755c42bd003c5f8d2475ee78cc4600c0"
"checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9"
"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
-"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
-"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
+"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
"checksum uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "519130f0ea964ba540a9d8af1373738c2226f1d465eda07e61db29feb5479db9"
-"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
@@ -2870,9 +3064,9 @@ dependencies = [
"checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22"
"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
-"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
+"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
"checksum webidl 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc14e4b71f94b5bb4c6d696e3b3be4d2e9ee6750a60870ecae09ff7138a131a7"
"checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini
index c2dff3ba6892..dc86d67d070a 100644
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -416,7 +416,7 @@ skip-if = verify
[browser_tab_drag_drop_perwindow.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_tab_dragdrop.js]
-skip-if = debug || (os == 'linux') || (os == 'mac') # Bug 1312436, Bug 1388973
+skip-if = debug || (os == 'linux') || (os == 'mac') || (os == 'win' && asan) # Bug 1312436, Bug 1388973
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_tab_dragdrop2.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml
index d5042016c1b9..0ba6166d107c 100644
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -589,11 +589,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
// invoked regardless, thus this should be enough.
if (this._formattingInstance != instance)
return;
- let isDomainRTL = window.windowUtils.getDirectionFromText(domain);
+ let directionality = window.windowUtils.getDirectionFromText(domain);
// In the future, for example in bug 525831, we may add a forceRTL
// char just after the domain, and in such a case we should not
// scroll to the left.
- if (isDomainRTL && value[preDomain.length + domain.length] != "\u200E") {
+ if (directionality == window.windowUtils.DIRECTION_RTL &&
+ value[preDomain.length + domain.length] != "\u200E") {
this.inputField.scrollLeft = this.inputField.scrollLeftMax;
}
});
diff --git a/browser/themes/shared/identity-block/identity-block.inc.css b/browser/themes/shared/identity-block/identity-block.inc.css
index f6d9c3157dc5..5ec935ab1f03 100644
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -239,7 +239,6 @@
}
50% {
transform: translateX(-1232px);
- fill: var(--tracking-protection-shield-color);
}
65% {
fill: var(--tracking-protection-shield-color);
@@ -266,7 +265,6 @@
}
50% {
transform: scaleX(-1) translateX(-1232px);
- fill: var(--tracking-protection-shield-color);
}
65% {
fill: var(--tracking-protection-shield-color);
diff --git a/devtools/client/debugger/new/README.mozilla b/devtools/client/debugger/new/README.mozilla
index 1878c04672af..f5b8ad4fdfee 100644
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,9 +1,9 @@
This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html
-Version 84
+Version 85
-Comparison: https://github.com/devtools-html/debugger.html/compare/release-83...release-84
+Comparison: https://github.com/devtools-html/debugger.html/compare/release-84...release-85
Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
diff --git a/devtools/client/debugger/new/dist/vendors.js b/devtools/client/debugger/new/dist/vendors.js
index 5cf1a1da7a31..ba5082ee5185 100644
--- a/devtools/client/debugger/new/dist/vendors.js
+++ b/devtools/client/debugger/new/dist/vendors.js
@@ -1,13 +1,13 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
- module.exports = factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories"));
+ module.exports = factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories"));
else if(typeof define === 'function' && define.amd)
- define(["devtools/client/shared/vendor/react", "devtools/client/shared/vendor/react-dom", "Services", "devtools/shared/flags", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react-dom-factories"], factory);
+ define(["devtools/client/shared/vendor/react", "devtools/client/shared/vendor/lodash", "devtools/client/shared/vendor/react-dom", "Services", "devtools/shared/flags", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react-dom-factories"], factory);
else {
- var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")) : factory(root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/react-dom"], root["Services"], root["devtools/shared/flags"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react-dom-factories"]);
+ var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")) : factory(root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/lodash"], root["devtools/client/shared/vendor/react-dom"], root["Services"], root["devtools/shared/flags"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react-dom-factories"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
-})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_22__, __WEBPACK_EXTERNAL_MODULE_52__, __WEBPACK_EXTERNAL_MODULE_3642__, __WEBPACK_EXTERNAL_MODULE_3643__) {
+})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_22__, __WEBPACK_EXTERNAL_MODULE_52__, __WEBPACK_EXTERNAL_MODULE_3642__, __WEBPACK_EXTERNAL_MODULE_3643__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
@@ -80,92 +80,6 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
-/***/ }),
-
-/***/ 10:
-/***/ (function(module, exports, __webpack_require__) {
-
-var Symbol = __webpack_require__(7);
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Used to resolve the
- * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
- * of values.
- */
-var nativeObjectToString = objectProto.toString;
-
-/** Built-in value references. */
-var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
-
-/**
- * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
- *
- * @private
- * @param {*} value The value to query.
- * @returns {string} Returns the raw `toStringTag`.
- */
-function getRawTag(value) {
- var isOwn = hasOwnProperty.call(value, symToStringTag),
- tag = value[symToStringTag];
-
- try {
- value[symToStringTag] = undefined;
- var unmasked = true;
- } catch (e) {}
-
- var result = nativeObjectToString.call(value);
- if (unmasked) {
- if (isOwn) {
- value[symToStringTag] = tag;
- } else {
- delete value[symToStringTag];
- }
- }
- return result;
-}
-
-module.exports = getRawTag;
-
-
-/***/ }),
-
-/***/ 100:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/**
- * Sets the list cache `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf ListCache
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the list cache instance.
- */
-function listCacheSet(key, value) {
- var data = this.__data__,
- index = assocIndexOf(data, key);
-
- if (index < 0) {
- ++this.size;
- data.push([key, value]);
- } else {
- data[index][1] = value;
- }
- return this;
-}
-
-module.exports = listCacheSet;
-
-
/***/ }),
/***/ 1000:
@@ -201,92 +115,6 @@ module.exports = ""
-/***/ }),
-
-/***/ 101:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getNative = __webpack_require__(81),
- root = __webpack_require__(8);
-
-/* Built-in method references that are verified to be native. */
-var Map = getNative(root, 'Map');
-
-module.exports = Map;
-
-
-/***/ }),
-
-/***/ 102:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Removes `key` and its value from the map.
- *
- * @private
- * @name delete
- * @memberOf MapCache
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function mapCacheDelete(key) {
- var result = getMapData(this, key)['delete'](key);
- this.size -= result ? 1 : 0;
- return result;
-}
-
-module.exports = mapCacheDelete;
-
-
-/***/ }),
-
-/***/ 103:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isKeyable = __webpack_require__(104);
-
-/**
- * Gets the data for `map`.
- *
- * @private
- * @param {Object} map The map to query.
- * @param {string} key The reference key.
- * @returns {*} Returns the map data.
- */
-function getMapData(map, key) {
- var data = map.__data__;
- return isKeyable(key)
- ? data[typeof key == 'string' ? 'string' : 'hash']
- : data.map;
-}
-
-module.exports = getMapData;
-
-
-/***/ }),
-
-/***/ 104:
-/***/ (function(module, exports) {
-
-/**
- * Checks if `value` is suitable for use as unique object key.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
- */
-function isKeyable(value) {
- var type = typeof value;
- return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
- ? (value !== '__proto__')
- : (value === null);
-}
-
-module.exports = isKeyable;
-
-
/***/ }),
/***/ 1043:
@@ -308,245 +136,6 @@ module.exports = ""
-/***/ }),
-
-/***/ 105:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Gets the map value for `key`.
- *
- * @private
- * @name get
- * @memberOf MapCache
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function mapCacheGet(key) {
- return getMapData(this, key).get(key);
-}
-
-module.exports = mapCacheGet;
-
-
-/***/ }),
-
-/***/ 106:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Checks if a map value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf MapCache
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function mapCacheHas(key) {
- return getMapData(this, key).has(key);
-}
-
-module.exports = mapCacheHas;
-
-
-/***/ }),
-
-/***/ 107:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Sets the map `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf MapCache
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the map cache instance.
- */
-function mapCacheSet(key, value) {
- var data = getMapData(this, key),
- size = data.size;
-
- data.set(key, value);
- this.size += data.size == size ? 0 : 1;
- return this;
-}
-
-module.exports = mapCacheSet;
-
-
-/***/ }),
-
-/***/ 108:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseToString = __webpack_require__(109);
-
-/**
- * Converts `value` to a string. An empty string is returned for `null`
- * and `undefined` values. The sign of `-0` is preserved.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to convert.
- * @returns {string} Returns the converted string.
- * @example
- *
- * _.toString(null);
- * // => ''
- *
- * _.toString(-0);
- * // => '-0'
- *
- * _.toString([1, 2, 3]);
- * // => '1,2,3'
- */
-function toString(value) {
- return value == null ? '' : baseToString(value);
-}
-
-module.exports = toString;
-
-
-/***/ }),
-
-/***/ 109:
-/***/ (function(module, exports, __webpack_require__) {
-
-var Symbol = __webpack_require__(7),
- arrayMap = __webpack_require__(110),
- isArray = __webpack_require__(70),
- isSymbol = __webpack_require__(72);
-
-/** Used as references for various `Number` constants. */
-var INFINITY = 1 / 0;
-
-/** Used to convert symbols to primitives and strings. */
-var symbolProto = Symbol ? Symbol.prototype : undefined,
- symbolToString = symbolProto ? symbolProto.toString : undefined;
-
-/**
- * The base implementation of `_.toString` which doesn't convert nullish
- * values to empty strings.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
-function baseToString(value) {
- // Exit early for strings to avoid a performance hit in some environments.
- if (typeof value == 'string') {
- return value;
- }
- if (isArray(value)) {
- // Recursively convert values (susceptible to call stack limits).
- return arrayMap(value, baseToString) + '';
- }
- if (isSymbol(value)) {
- return symbolToString ? symbolToString.call(value) : '';
- }
- var result = (value + '');
- return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
-}
-
-module.exports = baseToString;
-
-
-/***/ }),
-
-/***/ 11:
-/***/ (function(module, exports) {
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/**
- * Used to resolve the
- * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
- * of values.
- */
-var nativeObjectToString = objectProto.toString;
-
-/**
- * Converts `value` to a string using `Object.prototype.toString`.
- *
- * @private
- * @param {*} value The value to convert.
- * @returns {string} Returns the converted string.
- */
-function objectToString(value) {
- return nativeObjectToString.call(value);
-}
-
-module.exports = objectToString;
-
-
-/***/ }),
-
-/***/ 110:
-/***/ (function(module, exports) {
-
-/**
- * A specialized version of `_.map` for arrays without support for iteratee
- * shorthands.
- *
- * @private
- * @param {Array} [array] The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
- */
-function arrayMap(array, iteratee) {
- var index = -1,
- length = array == null ? 0 : array.length,
- result = Array(length);
-
- while (++index < length) {
- result[index] = iteratee(array[index], index, array);
- }
- return result;
-}
-
-module.exports = arrayMap;
-
-
-/***/ }),
-
-/***/ 111:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isSymbol = __webpack_require__(72);
-
-/** Used as references for various `Number` constants. */
-var INFINITY = 1 / 0;
-
-/**
- * Converts `value` to a string key if it's not a string or symbol.
- *
- * @private
- * @param {*} value The value to inspect.
- * @returns {string|symbol} Returns the key.
- */
-function toKey(value) {
- if (typeof value == 'string' || isSymbol(value)) {
- return value;
- }
- var result = (value + '');
- return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
-}
-
-module.exports = toKey;
-
-
/***/ }),
/***/ 1117:
@@ -568,219 +157,6 @@ module.exports = ""
-/***/ }),
-
-/***/ 112:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseSet = __webpack_require__(113);
-
-/**
- * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
- * it's created. Arrays are created for missing index properties while objects
- * are created for all other missing properties. Use `_.setWith` to customize
- * `path` creation.
- *
- * **Note:** This method mutates `object`.
- *
- * @static
- * @memberOf _
- * @since 3.7.0
- * @category Object
- * @param {Object} object The object to modify.
- * @param {Array|string} path The path of the property to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns `object`.
- * @example
- *
- * var object = { 'a': [{ 'b': { 'c': 3 } }] };
- *
- * _.set(object, 'a[0].b.c', 4);
- * console.log(object.a[0].b.c);
- * // => 4
- *
- * _.set(object, ['x', '0', 'y', 'z'], 5);
- * console.log(object.x[0].y.z);
- * // => 5
- */
-function set(object, path, value) {
- return object == null ? object : baseSet(object, path, value);
-}
-
-module.exports = set;
-
-
-/***/ }),
-
-/***/ 113:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assignValue = __webpack_require__(114),
- castPath = __webpack_require__(69),
- isIndex = __webpack_require__(117),
- isObject = __webpack_require__(84),
- toKey = __webpack_require__(111);
-
-/**
- * The base implementation of `_.set`.
- *
- * @private
- * @param {Object} object The object to modify.
- * @param {Array|string} path The path of the property to set.
- * @param {*} value The value to set.
- * @param {Function} [customizer] The function to customize path creation.
- * @returns {Object} Returns `object`.
- */
-function baseSet(object, path, value, customizer) {
- if (!isObject(object)) {
- return object;
- }
- path = castPath(path, object);
-
- var index = -1,
- length = path.length,
- lastIndex = length - 1,
- nested = object;
-
- while (nested != null && ++index < length) {
- var key = toKey(path[index]),
- newValue = value;
-
- if (index != lastIndex) {
- var objValue = nested[key];
- newValue = customizer ? customizer(objValue, key, nested) : undefined;
- if (newValue === undefined) {
- newValue = isObject(objValue)
- ? objValue
- : (isIndex(path[index + 1]) ? [] : {});
- }
- }
- assignValue(nested, key, newValue);
- nested = nested[key];
- }
- return object;
-}
-
-module.exports = baseSet;
-
-
-/***/ }),
-
-/***/ 114:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseAssignValue = __webpack_require__(115),
- eq = __webpack_require__(97);
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Assigns `value` to `key` of `object` if the existing value is not equivalent
- * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
- * for equality comparisons.
- *
- * @private
- * @param {Object} object The object to modify.
- * @param {string} key The key of the property to assign.
- * @param {*} value The value to assign.
- */
-function assignValue(object, key, value) {
- var objValue = object[key];
- if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
- (value === undefined && !(key in object))) {
- baseAssignValue(object, key, value);
- }
-}
-
-module.exports = assignValue;
-
-
-/***/ }),
-
-/***/ 115:
-/***/ (function(module, exports, __webpack_require__) {
-
-var defineProperty = __webpack_require__(116);
-
-/**
- * The base implementation of `assignValue` and `assignMergeValue` without
- * value checks.
- *
- * @private
- * @param {Object} object The object to modify.
- * @param {string} key The key of the property to assign.
- * @param {*} value The value to assign.
- */
-function baseAssignValue(object, key, value) {
- if (key == '__proto__' && defineProperty) {
- defineProperty(object, key, {
- 'configurable': true,
- 'enumerable': true,
- 'value': value,
- 'writable': true
- });
- } else {
- object[key] = value;
- }
-}
-
-module.exports = baseAssignValue;
-
-
-/***/ }),
-
-/***/ 116:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getNative = __webpack_require__(81);
-
-var defineProperty = (function() {
- try {
- var func = getNative(Object, 'defineProperty');
- func({}, '', {});
- return func;
- } catch (e) {}
-}());
-
-module.exports = defineProperty;
-
-
-/***/ }),
-
-/***/ 117:
-/***/ (function(module, exports) {
-
-/** Used as references for various `Number` constants. */
-var MAX_SAFE_INTEGER = 9007199254740991;
-
-/** Used to detect unsigned integer values. */
-var reIsUint = /^(?:0|[1-9]\d*)$/;
-
-/**
- * Checks if `value` is a valid array-like index.
- *
- * @private
- * @param {*} value The value to check.
- * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
- * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
- */
-function isIndex(value, length) {
- var type = typeof value;
- length = length == null ? MAX_SAFE_INTEGER : length;
-
- return !!length &&
- (type == 'number' ||
- (type != 'symbol' && reIsUint.test(value))) &&
- (value > -1 && value % 1 == 0 && value < length);
-}
-
-module.exports = isIndex;
-
-
/***/ }),
/***/ 1174:
@@ -1275,6 +651,10 @@ module.exports = ""
-/***/ }),
-
-/***/ 81:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseIsNative = __webpack_require__(82),
- getValue = __webpack_require__(88);
-
-/**
- * Gets the native function at `key` of `object`.
- *
- * @private
- * @param {Object} object The object to query.
- * @param {string} key The key of the method to get.
- * @returns {*} Returns the function if it's native, else `undefined`.
- */
-function getNative(object, key) {
- var value = getValue(object, key);
- return baseIsNative(value) ? value : undefined;
-}
-
-module.exports = getNative;
-
-
-/***/ }),
-
-/***/ 82:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isFunction = __webpack_require__(83),
- isMasked = __webpack_require__(85),
- isObject = __webpack_require__(84),
- toSource = __webpack_require__(87);
-
-/**
- * Used to match `RegExp`
- * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
- */
-var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
-
-/** Used to detect host constructors (Safari). */
-var reIsHostCtor = /^\[object .+?Constructor\]$/;
-
-/** Used for built-in method references. */
-var funcProto = Function.prototype,
- objectProto = Object.prototype;
-
-/** Used to resolve the decompiled source of functions. */
-var funcToString = funcProto.toString;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/** Used to detect if a method is native. */
-var reIsNative = RegExp('^' +
- funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
- .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
-);
-
-/**
- * The base implementation of `_.isNative` without bad shim checks.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a native function,
- * else `false`.
- */
-function baseIsNative(value) {
- if (!isObject(value) || isMasked(value)) {
- return false;
- }
- var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
- return pattern.test(toSource(value));
-}
-
-module.exports = baseIsNative;
-
-
-/***/ }),
-
-/***/ 83:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseGetTag = __webpack_require__(6),
- isObject = __webpack_require__(84);
-
-/** `Object#toString` result references. */
-var asyncTag = '[object AsyncFunction]',
- funcTag = '[object Function]',
- genTag = '[object GeneratorFunction]',
- proxyTag = '[object Proxy]';
-
-/**
- * Checks if `value` is classified as a `Function` object.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a function, else `false`.
- * @example
- *
- * _.isFunction(_);
- * // => true
- *
- * _.isFunction(/abc/);
- * // => false
- */
-function isFunction(value) {
- if (!isObject(value)) {
- return false;
- }
- // The use of `Object#toString` avoids issues with the `typeof` operator
- // in Safari 9 which returns 'object' for typed arrays and other constructors.
- var tag = baseGetTag(value);
- return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
-}
-
-module.exports = isFunction;
-
-
-/***/ }),
-
-/***/ 84:
-/***/ (function(module, exports) {
-
-/**
- * Checks if `value` is the
- * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
- * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an object, else `false`.
- * @example
- *
- * _.isObject({});
- * // => true
- *
- * _.isObject([1, 2, 3]);
- * // => true
- *
- * _.isObject(_.noop);
- * // => true
- *
- * _.isObject(null);
- * // => false
- */
-function isObject(value) {
- var type = typeof value;
- return value != null && (type == 'object' || type == 'function');
-}
-
-module.exports = isObject;
-
-
-/***/ }),
-
-/***/ 85:
-/***/ (function(module, exports, __webpack_require__) {
-
-var coreJsData = __webpack_require__(86);
-
-/** Used to detect methods masquerading as native. */
-var maskSrcKey = (function() {
- var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
- return uid ? ('Symbol(src)_1.' + uid) : '';
-}());
-
-/**
- * Checks if `func` has its source masked.
- *
- * @private
- * @param {Function} func The function to check.
- * @returns {boolean} Returns `true` if `func` is masked, else `false`.
- */
-function isMasked(func) {
- return !!maskSrcKey && (maskSrcKey in func);
-}
-
-module.exports = isMasked;
-
-
-/***/ }),
-
-/***/ 86:
-/***/ (function(module, exports, __webpack_require__) {
-
-var root = __webpack_require__(8);
-
-/** Used to detect overreaching core-js shims. */
-var coreJsData = root['__core-js_shared__'];
-
-module.exports = coreJsData;
-
-
-/***/ }),
-
-/***/ 87:
-/***/ (function(module, exports) {
-
-/** Used for built-in method references. */
-var funcProto = Function.prototype;
-
-/** Used to resolve the decompiled source of functions. */
-var funcToString = funcProto.toString;
-
-/**
- * Converts `func` to its source code.
- *
- * @private
- * @param {Function} func The function to convert.
- * @returns {string} Returns the source code.
- */
-function toSource(func) {
- if (func != null) {
- try {
- return funcToString.call(func);
- } catch (e) {}
- try {
- return (func + '');
- } catch (e) {}
- }
- return '';
-}
-
-module.exports = toSource;
-
-
-/***/ }),
-
-/***/ 88:
-/***/ (function(module, exports) {
-
-/**
- * Gets the value at `key` of `object`.
- *
- * @private
- * @param {Object} [object] The object to query.
- * @param {string} key The key of the property to get.
- * @returns {*} Returns the property value.
- */
-function getValue(object, key) {
- return object == null ? undefined : object[key];
-}
-
-module.exports = getValue;
-
-
-/***/ }),
-
-/***/ 89:
-/***/ (function(module, exports) {
-
-/**
- * Removes `key` and its value from the hash.
- *
- * @private
- * @name delete
- * @memberOf Hash
- * @param {Object} hash The hash to modify.
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function hashDelete(key) {
- var result = this.has(key) && delete this.__data__[key];
- this.size -= result ? 1 : 0;
- return result;
-}
-
-module.exports = hashDelete;
-
-
-/***/ }),
-
-/***/ 9:
-/***/ (function(module, exports, __webpack_require__) {
-
-/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
-var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
-
-module.exports = freeGlobal;
-
-/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(792)))
-
-/***/ }),
-
-/***/ 90:
-/***/ (function(module, exports, __webpack_require__) {
-
-var nativeCreate = __webpack_require__(80);
-
-/** Used to stand-in for `undefined` hash values. */
-var HASH_UNDEFINED = '__lodash_hash_undefined__';
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Gets the hash value for `key`.
- *
- * @private
- * @name get
- * @memberOf Hash
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function hashGet(key) {
- var data = this.__data__;
- if (nativeCreate) {
- var result = data[key];
- return result === HASH_UNDEFINED ? undefined : result;
- }
- return hasOwnProperty.call(data, key) ? data[key] : undefined;
-}
-
-module.exports = hashGet;
-
-
-/***/ }),
-
-/***/ 91:
-/***/ (function(module, exports, __webpack_require__) {
-
-var nativeCreate = __webpack_require__(80);
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Checks if a hash value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf Hash
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function hashHas(key) {
- var data = this.__data__;
- return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
-}
-
-module.exports = hashHas;
-
-
/***/ }),
/***/ 916:
@@ -9526,36 +7918,6 @@ module.exports = hashHas;
module.exports = ""
-/***/ }),
-
-/***/ 92:
-/***/ (function(module, exports, __webpack_require__) {
-
-var nativeCreate = __webpack_require__(80);
-
-/** Used to stand-in for `undefined` hash values. */
-var HASH_UNDEFINED = '__lodash_hash_undefined__';
-
-/**
- * Sets the hash `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf Hash
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the hash instance.
- */
-function hashSet(key, value) {
- var data = this.__data__;
- this.size += this.has(key) ? 0 : 1;
- data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
- return this;
-}
-
-module.exports = hashSet;
-
-
/***/ }),
/***/ 920:
@@ -9563,228 +7925,6 @@ module.exports = hashSet;
module.exports = ""
-/***/ }),
-
-/***/ 93:
-/***/ (function(module, exports, __webpack_require__) {
-
-var listCacheClear = __webpack_require__(94),
- listCacheDelete = __webpack_require__(95),
- listCacheGet = __webpack_require__(98),
- listCacheHas = __webpack_require__(99),
- listCacheSet = __webpack_require__(100);
-
-/**
- * Creates an list cache object.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function ListCache(entries) {
- var index = -1,
- length = entries == null ? 0 : entries.length;
-
- this.clear();
- while (++index < length) {
- var entry = entries[index];
- this.set(entry[0], entry[1]);
- }
-}
-
-// Add methods to `ListCache`.
-ListCache.prototype.clear = listCacheClear;
-ListCache.prototype['delete'] = listCacheDelete;
-ListCache.prototype.get = listCacheGet;
-ListCache.prototype.has = listCacheHas;
-ListCache.prototype.set = listCacheSet;
-
-module.exports = ListCache;
-
-
-/***/ }),
-
-/***/ 94:
-/***/ (function(module, exports) {
-
-/**
- * Removes all key-value entries from the list cache.
- *
- * @private
- * @name clear
- * @memberOf ListCache
- */
-function listCacheClear() {
- this.__data__ = [];
- this.size = 0;
-}
-
-module.exports = listCacheClear;
-
-
-/***/ }),
-
-/***/ 95:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/** Used for built-in method references. */
-var arrayProto = Array.prototype;
-
-/** Built-in value references. */
-var splice = arrayProto.splice;
-
-/**
- * Removes `key` and its value from the list cache.
- *
- * @private
- * @name delete
- * @memberOf ListCache
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function listCacheDelete(key) {
- var data = this.__data__,
- index = assocIndexOf(data, key);
-
- if (index < 0) {
- return false;
- }
- var lastIndex = data.length - 1;
- if (index == lastIndex) {
- data.pop();
- } else {
- splice.call(data, index, 1);
- }
- --this.size;
- return true;
-}
-
-module.exports = listCacheDelete;
-
-
-/***/ }),
-
-/***/ 96:
-/***/ (function(module, exports, __webpack_require__) {
-
-var eq = __webpack_require__(97);
-
-/**
- * Gets the index at which the `key` is found in `array` of key-value pairs.
- *
- * @private
- * @param {Array} array The array to inspect.
- * @param {*} key The key to search for.
- * @returns {number} Returns the index of the matched value, else `-1`.
- */
-function assocIndexOf(array, key) {
- var length = array.length;
- while (length--) {
- if (eq(array[length][0], key)) {
- return length;
- }
- }
- return -1;
-}
-
-module.exports = assocIndexOf;
-
-
-/***/ }),
-
-/***/ 97:
-/***/ (function(module, exports) {
-
-/**
- * Performs a
- * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
- * comparison between two values to determine if they are equivalent.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * var object = { 'a': 1 };
- * var other = { 'a': 1 };
- *
- * _.eq(object, object);
- * // => true
- *
- * _.eq(object, other);
- * // => false
- *
- * _.eq('a', 'a');
- * // => true
- *
- * _.eq('a', Object('a'));
- * // => false
- *
- * _.eq(NaN, NaN);
- * // => true
- */
-function eq(value, other) {
- return value === other || (value !== value && other !== other);
-}
-
-module.exports = eq;
-
-
-/***/ }),
-
-/***/ 98:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/**
- * Gets the list cache value for `key`.
- *
- * @private
- * @name get
- * @memberOf ListCache
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function listCacheGet(key) {
- var data = this.__data__,
- index = assocIndexOf(data, key);
-
- return index < 0 ? undefined : data[index][1];
-}
-
-module.exports = listCacheGet;
-
-
-/***/ }),
-
-/***/ 99:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/**
- * Checks if a list cache value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf ListCache
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function listCacheHas(key) {
- return assocIndexOf(this.__data__, key) > -1;
-}
-
-module.exports = listCacheHas;
-
-
/***/ }),
/***/ 993:
diff --git a/devtools/client/debugger/new/src/actions/sources/select.js b/devtools/client/debugger/new/src/actions/sources/select.js
index b4947dae3995..56eed6e5ab31 100644
--- a/devtools/client/debugger/new/src/actions/sources/select.js
+++ b/devtools/client/debugger/new/src/actions/sources/select.js
@@ -8,7 +8,6 @@ exports.selectSourceURL = selectSourceURL;
exports.selectSource = selectSource;
exports.selectLocation = selectLocation;
exports.selectSpecificLocation = selectSpecificLocation;
-exports.selectSpecificSource = selectSpecificSource;
exports.jumpToMappedLocation = jumpToMappedLocation;
exports.jumpToMappedSelectedLocation = jumpToMappedSelectedLocation;
@@ -106,7 +105,7 @@ function selectSource(sourceId) {
const location = (0, _location.createLocation)({
sourceId
});
- return await dispatch(selectLocation(location));
+ return await dispatch(selectSpecificLocation(location));
};
}
/**
@@ -196,22 +195,6 @@ function selectSpecificLocation(location) {
*/
-function selectSpecificSource(sourceId) {
- return async ({
- dispatch
- }) => {
- const location = (0, _location.createLocation)({
- sourceId
- });
- return await dispatch(selectSpecificLocation(location));
- };
-}
-/**
- * @memberof actions/sources
- * @static
- */
-
-
function jumpToMappedLocation(location) {
return async function ({
dispatch,
diff --git a/devtools/client/debugger/new/src/client/firefox/commands.js b/devtools/client/debugger/new/src/client/firefox/commands.js
index 54445a9945cf..4837edb3950c 100644
--- a/devtools/client/debugger/new/src/client/firefox/commands.js
+++ b/devtools/client/debugger/new/src/client/firefox/commands.js
@@ -366,7 +366,7 @@ async function checkServerSupportsListWorkers() {
return false;
}
- const deviceFront = await (0, _frontsDevice.getDeviceFront)(debuggerClient, root);
+ const deviceFront = await debuggerClient.mainRoot.getFront("device");
const description = await deviceFront.getDescription();
const isFennec = description.apptype === "mobile/android";
@@ -438,4 +438,4 @@ const clientCommands = {
setSkipPausing
};
exports.setupCommands = setupCommands;
-exports.clientCommands = clientCommands;
\ No newline at end of file
+exports.clientCommands = clientCommands;
diff --git a/devtools/client/debugger/new/src/components/Editor/Tab.js b/devtools/client/debugger/new/src/components/Editor/Tab.js
index f90f2c1db37a..7547d47c079d 100644
--- a/devtools/client/debugger/new/src/components/Editor/Tab.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tab.js
@@ -132,7 +132,7 @@ class Tab extends _react.PureComponent {
render() {
const {
selectedSource,
- selectSpecificSource,
+ selectSource,
closeTab,
source,
tabSources
@@ -149,7 +149,7 @@ class Tab extends _react.PureComponent {
function handleTabClick(e) {
e.preventDefault();
e.stopPropagation();
- return selectSpecificSource(sourceId);
+ return selectSource(sourceId);
}
const className = (0, _classnames2.default)("source-tab", {
@@ -190,7 +190,7 @@ const mapStateToProps = (state, {
};
exports.default = (0, _reactRedux.connect)(mapStateToProps, {
- selectSpecificSource: _actions2.default.selectSpecificSource,
+ selectSource: _actions2.default.selectSource,
closeTab: _actions2.default.closeTab,
closeTabs: _actions2.default.closeTabs,
togglePrettyPrint: _actions2.default.togglePrettyPrint,
diff --git a/devtools/client/debugger/new/src/components/Editor/Tabs.js b/devtools/client/debugger/new/src/components/Editor/Tabs.js
index 5881ed5b6acc..fa125acc66f5 100644
--- a/devtools/client/debugger/new/src/components/Editor/Tabs.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tabs.js
@@ -67,11 +67,11 @@ class Tabs extends _react.PureComponent {
this.renderDropdownSource = source => {
const {
- selectSpecificSource
+ selectSource
} = this.props;
const filename = (0, _source.getFilename)(source);
- const onClick = () => selectSpecificSource(source.id);
+ const onClick = () => selectSource(source.id);
return _react2.default.createElement("li", {
key: source.id,
@@ -206,7 +206,7 @@ const mapStateToProps = state => ({
});
exports.default = (0, _reactRedux.connect)(mapStateToProps, {
- selectSpecificSource: _actions2.default.selectSpecificSource,
+ selectSource: _actions2.default.selectSource,
moveTab: _actions2.default.moveTab,
closeTab: _actions2.default.closeTab,
togglePaneCollapse: _actions2.default.togglePaneCollapse,
diff --git a/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
index 03e8e32cc4d2..8c6d18860c74 100644
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
@@ -247,17 +247,14 @@ var _initialiseProps = function () {
this.getPath = item => {
const path = `${item.path}/${item.name}`;
+ const source = this.getSource(item);
- if ((0, _sourcesTree.isDirectory)(item)) {
+ if (!source || (0, _sourcesTree.isDirectory)(item)) {
return path;
}
- const source = this.getSource(item);
- const blackBoxedPart = source && source.isBlackBoxed ? ":blackboxed" : ""; // Original and generated sources can point to the same path
- // therefore necessary to distinguish as path is used as keys.
-
- const generatedPart = source && source.sourceMapURL ? ":generated" : "";
- return `${path}${blackBoxedPart}${generatedPart}`;
+ const blackBoxedPart = source.isBlackBoxed ? ":blackboxed" : "";
+ return `${path}/${source.id}/${blackBoxedPart}`;
};
this.onExpand = (item, expandedState) => {
diff --git a/devtools/client/debugger/new/src/utils/dbg.js b/devtools/client/debugger/new/src/utils/dbg.js
index 13dab870abfc..0db09838edfc 100644
--- a/devtools/client/debugger/new/src/utils/dbg.js
+++ b/devtools/client/debugger/new/src/utils/dbg.js
@@ -21,14 +21,13 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at . */
function findSource(dbg, url) {
- const sources = dbg.selectors.getSources();
- const source = sources.find(s => (s.url || "").includes(url));
+ const sources = dbg.selectors.getSourceList();
+ return sources.find(s => (s.url || "").includes(url));
+}
- if (!source) {
- return;
- }
-
- return source;
+function findSources(dbg, url) {
+ const sources = dbg.selectors.getSourceList();
+ return sources.filter(s => (s.url || "").includes(url));
}
function sendPacket(dbg, packet, callback) {
@@ -76,6 +75,7 @@ function setupHelper(obj) {
getCM,
helpers: {
findSource: url => findSource(dbg, url),
+ findSources: url => findSources(dbg, url),
evaluate: (expression, cbk) => evaluate(dbg, expression, cbk),
sendPacketToThread: (packet, cbk) => sendPacketToThread(dbg, packet, cbk),
sendPacket: (packet, cbk) => sendPacket(dbg, packet, cbk)
diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js
index bf7e7eaf045b..caae3ab10e21 100644
--- a/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js
+++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js
@@ -31,8 +31,13 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) {
return null;
}
- const generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this);
const originalRanges = await (0, _rangeMetadata.loadRangeMetadata)(source, frame, originalAstScopes, sourceMaps);
+
+ if (hasLineMappings(originalRanges)) {
+ return null;
+ }
+
+ const generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this);
const {
mappedOriginalScopes,
expressionLookup
@@ -104,6 +109,10 @@ function isReliableScope(scope) {
return totalBindings === 0 || unknownBindings / totalBindings < 0.25;
}
+function hasLineMappings(ranges) {
+ return ranges.every(range => range.columnStart === 0 && range.columnEnd === Infinity);
+}
+
function batchScopeMappings(originalAstScopes, source, sourceMaps) {
const precalculatedRanges = new Map();
const precalculatedLocations = new Map(); // Explicitly dispatch all of the sourcemap requests synchronously up front so
diff --git a/devtools/client/debugger/new/src/utils/prefs.js b/devtools/client/debugger/new/src/utils/prefs.js
index 5ebc7076ed9c..9f41954d694d 100644
--- a/devtools/client/debugger/new/src/utils/prefs.js
+++ b/devtools/client/debugger/new/src/utils/prefs.js
@@ -20,7 +20,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
/* 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 . */
-const prefsSchemaVersion = "1.0.3";
+const prefsSchemaVersion = "1.0.4";
const pref = _devtoolsServices2.default.pref;
if ((0, _devtoolsEnvironment.isDevelopment)()) {
@@ -128,5 +128,6 @@ const asyncStore = exports.asyncStore = (0, _asyncStoreHelper.asyncStoreHelper)(
if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) {
// clear pending Breakpoints
prefs.pendingBreakpoints = {};
+ prefs.tabs = [];
prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion;
}
\ No newline at end of file
diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js
index 8f6aed1fc07c..b6b37c1331fc 100644
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js
@@ -60,7 +60,7 @@ add_task(async function() {
]);
info(`Test that you can not preview in another original file`);
- await selectSpecificSource(dbg, "output");
+ await selectSource(dbg, "output");
await hoverAtPos(dbg, { line: 2, ch: 16 });
await assertNoTooltip(dbg);
});
diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js
index 4d5e6fc31d77..f8296c0363e2 100644
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js
@@ -49,7 +49,7 @@ add_task(async function() {
ok(true, "Original sources exist");
const bundleSrc = findSource(dbg, "bundle.js");
- await selectSpecificSource(dbg, bundleSrc);
+ await selectSource(dbg, bundleSrc);
await clickGutter(dbg, 13);
await waitForDispatch(dbg, "ADD_BREAKPOINT");
@@ -61,7 +61,7 @@ add_task(async function() {
const entrySrc = findSource(dbg, "entry.js");
- await selectSpecificSource(dbg, entrySrc);
+ await selectSource(dbg, entrySrc);
ok(
getCM(dbg)
.getValue()
diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-wasm-sourcemaps.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-wasm-sourcemaps.js
index 293bcea56ad7..2af1ecc4c07e 100644
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-wasm-sourcemaps.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-wasm-sourcemaps.js
@@ -24,7 +24,7 @@ add_task(async function() {
ok(true, "Original sources exist");
const mainSrc = findSource(dbg, "fib.c");
- await selectSpecificSource(dbg, mainSrc);
+ await selectSource(dbg, mainSrc);
await addBreakpoint(dbg, "fib.c", 10);
resume(dbg);
diff --git a/devtools/client/debugger/new/test/mochitest/helpers.js b/devtools/client/debugger/new/test/mochitest/helpers.js
index 1fbcb48cf104..abfbda51ae30 100644
--- a/devtools/client/debugger/new/test/mochitest/helpers.js
+++ b/devtools/client/debugger/new/test/mochitest/helpers.js
@@ -598,12 +598,6 @@ function waitForLoadedSources(dbg) {
* @static
*/
async function selectSource(dbg, url, line) {
- const source = findSource(dbg, url);
- await dbg.actions.selectLocation({ sourceId: source.id, line });
- return waitForSelectedSource(dbg, url);
-}
-
-async function selectSpecificSource(dbg, url, line) {
const source = findSource(dbg, url);
await dbg.actions.selectLocation({ sourceId: source.id, line }, {keepContext: false});
return waitForSelectedSource(dbg, url);
diff --git a/devtools/client/framework/source-map-url-service.js b/devtools/client/framework/source-map-url-service.js
index 44323a66937c..5eba1e1225ec 100644
--- a/devtools/client/framework/source-map-url-service.js
+++ b/devtools/client/framework/source-map-url-service.js
@@ -53,30 +53,33 @@ function SourceMapURLService(toolbox, sourceMapService) {
*/
SourceMapURLService.prototype._getLoadingPromise = function() {
if (!this._loadingPromise) {
- let styleSheetsLoadingPromise = null;
- this._stylesheetsFront = this._toolbox.initStyleSheetsFront();
- if (this._stylesheetsFront) {
+ this._loadingPromise = (async () => {
+ if (this._target.isWorkerTarget) {
+ return;
+ }
+ this._stylesheetsFront = await this._target.getFront("stylesheets");
this._stylesheetsFront.on("stylesheet-added", this._onNewStyleSheet);
- styleSheetsLoadingPromise =
+ const styleSheetsLoadingPromise =
this._stylesheetsFront.getStyleSheets().then(sheets => {
sheets.forEach(this._onNewStyleSheet);
}, () => {
// Ignore any protocol-based errors.
});
- }
- // Start fetching the sources now.
- const loadingPromise = this._toolbox.threadClient.getSources().then(({sources}) => {
- // Ignore errors. Register the sources we got; we can't rely on
- // an event to arrive if the source actor already existed.
- for (const source of sources) {
- this._onSourceUpdated({source});
- }
- }, e => {
- // Also ignore any protocol-based errors.
- });
+ // Start fetching the sources now.
+ const loadingPromise = this._toolbox.threadClient.getSources().then(({sources}) => {
+ // Ignore errors. Register the sources we got; we can't rely on
+ // an event to arrive if the source actor already existed.
+ for (const source of sources) {
+ this._onSourceUpdated({source});
+ }
+ }, e => {
+ // Also ignore any protocol-based errors.
+ });
- this._loadingPromise = Promise.all([styleSheetsLoadingPromise, loadingPromise]);
+ await styleSheetsLoadingPromise;
+ await loadingPromise;
+ })();
}
return this._loadingPromise;
};
diff --git a/devtools/client/framework/target.js b/devtools/client/framework/target.js
index adae057d0e0a..32dc05367f7f 100644
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -13,6 +13,7 @@ loader.lazyRequireGetter(this, "DebuggerClient",
"devtools/shared/client/debugger-client", true);
loader.lazyRequireGetter(this, "gDevTools",
"devtools/client/framework/devtools", true);
+loader.lazyRequireGetter(this, "getFront", "devtools/shared/protocol", true);
const targets = new WeakMap();
const promiseTargets = new WeakMap();
@@ -138,6 +139,9 @@ function TabTarget(tab) {
} else {
this._isBrowsingContext = true;
}
+ // Cache of already created targed-scoped fronts
+ // [typeName:string => Front instance]
+ this.fronts = new Map();
}
exports.TabTarget = TabTarget;
@@ -271,26 +275,21 @@ TabTarget.prototype = {
return this._form;
},
- // Get a promise of the root form returned by a getRoot request. This promise
- // is cached.
+ // Get a promise of the RootActor's form
get root() {
- if (!this._root) {
- this._root = this._getRoot();
- }
- return this._root;
+ return this.client.mainRoot.rootForm;
},
- _getRoot: function() {
- return new Promise((resolve, reject) => {
- this.client.mainRoot.getRoot(response => {
- if (response.error) {
- reject(new Error(response.error + ": " + response.message));
- return;
- }
-
- resolve(response);
- });
- });
+ // Get a Front for a target-scoped actor.
+ // i.e. an actor served by RootActor.listTabs or RootActorActor.getTab requests
+ getFront(typeName) {
+ let front = this.fronts.get(typeName);
+ if (front) {
+ return front;
+ }
+ front = getFront(this.client, typeName, this.form);
+ this.fronts.set(typeName, front);
+ return front;
},
get client() {
@@ -506,7 +505,6 @@ TabTarget.prototype = {
*/
_setupListeners: function() {
this.tab.addEventListener("TabClose", this);
- this.tab.parentNode.addEventListener("TabSelect", this);
this.tab.ownerDocument.defaultView.addEventListener("unload", this);
this.tab.addEventListener("TabRemotenessChange", this);
},
@@ -517,7 +515,6 @@ TabTarget.prototype = {
_teardownListeners: function() {
this._tab.ownerDocument.defaultView.removeEventListener("unload", this);
this._tab.removeEventListener("TabClose", this);
- this._tab.parentNode.removeEventListener("TabSelect", this);
this._tab.removeEventListener("TabRemotenessChange", this);
},
@@ -599,13 +596,6 @@ TabTarget.prototype = {
case "unload":
this.destroy();
break;
- case "TabSelect":
- if (this.tab.selected) {
- this.emit("visible", event);
- } else {
- this.emit("hidden", event);
- }
- break;
case "TabRemotenessChange":
this.onRemotenessChange();
break;
@@ -650,10 +640,14 @@ TabTarget.prototype = {
return this._destroyer;
}
- this._destroyer = new Promise(resolve => {
+ this._destroyer = new Promise(async (resolve) => {
// Before taking any action, notify listeners that destruction is imminent.
this.emit("close");
+ for (const [, front] of this.fronts) {
+ await front.destroy();
+ }
+
if (this._tab) {
this._teardownListeners();
}
diff --git a/devtools/client/framework/test/browser_target_events.js b/devtools/client/framework/test/browser_target_events.js
index a16bcdafa0b7..45c8c766eb3c 100644
--- a/devtools/client/framework/test/browser_target_events.js
+++ b/devtools/client/framework/test/browser_target_events.js
@@ -9,16 +9,6 @@ add_task(async function() {
await target.makeRemote();
is(target.tab, gBrowser.selectedTab, "Target linked to the right tab.");
- const hidden = once(target, "hidden");
- gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
- await hidden;
- ok(true, "Hidden event received");
-
- const visible = once(target, "visible");
- gBrowser.removeCurrentTab();
- await visible;
- ok(true, "Visible event received");
-
const willNavigate = once(target, "will-navigate");
const navigate = once(target, "navigate");
ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
diff --git a/devtools/client/framework/test/browser_toolbox_tool_remote_reopen.js b/devtools/client/framework/test/browser_toolbox_tool_remote_reopen.js
index ddcc5f8c5be8..66c26d8aed96 100644
--- a/devtools/client/framework/test/browser_toolbox_tool_remote_reopen.js
+++ b/devtools/client/framework/test/browser_toolbox_tool_remote_reopen.js
@@ -92,12 +92,21 @@ function test() {
const target = await getTarget(client);
await runTools(target);
+ const rootFronts = [...client.mainRoot.fronts.values()];
+
// Actor fronts should be destroyed now that the toolbox has closed, but
// look for any that remain.
for (const pool of client.__pools) {
if (!pool.__poolMap) {
continue;
}
+
+ // Ignore the root fronts, which are top-level pools and aren't released
+ // on toolbox destroy, but on client close.
+ if (rootFronts.includes(pool)) {
+ continue;
+ }
+
for (const actor of pool.__poolMap.keys()) {
// Bug 1056342: Profiler fails today because of framerate actor, but
// this appears more complex to rework, so leave it for that bug to
diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js
index fe5a5da6ca13..472d133c9884 100644
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -45,10 +45,6 @@ loader.lazyRequireGetter(this, "InspectorFront",
"devtools/shared/fronts/inspector", true);
loader.lazyRequireGetter(this, "flags",
"devtools/shared/flags");
-loader.lazyRequireGetter(this, "createPerformanceFront",
- "devtools/shared/fronts/performance", true);
-loader.lazyRequireGetter(this, "getPreferenceFront",
- "devtools/shared/fronts/preference", true);
loader.lazyRequireGetter(this, "KeyShortcuts",
"devtools/client/shared/key-shortcuts");
loader.lazyRequireGetter(this, "ZoomKeys",
@@ -63,12 +59,8 @@ loader.lazyRequireGetter(this, "HUDService",
"devtools/client/webconsole/hudservice", true);
loader.lazyRequireGetter(this, "viewSource",
"devtools/client/shared/view-source");
-loader.lazyRequireGetter(this, "StyleSheetsFront",
- "devtools/shared/fronts/stylesheets", true);
loader.lazyRequireGetter(this, "buildHarLog",
"devtools/client/netmonitor/src/har/har-builder-utils", true);
-loader.lazyRequireGetter(this, "getKnownDeviceFront",
- "devtools/shared/fronts/device", true);
loader.lazyRequireGetter(this, "NetMonitorAPI",
"devtools/client/netmonitor/src/api", true);
loader.lazyRequireGetter(this, "sortPanelDefinitions",
@@ -125,7 +117,6 @@ function Toolbox(target, selectedTool, hostType, contentWindow, frameId,
this._initInspector = null;
this._inspector = null;
- this._styleSheets = null;
this._netMonitorAPI = null;
// Map of frames (id => frame-info) and currently selected frame id.
@@ -2220,16 +2211,7 @@ Toolbox.prototype = {
* client. See the definition of the preference actor for more information.
*/
get preferenceFront() {
- if (this._preferenceFront) {
- return Promise.resolve(this._preferenceFront);
- }
- return this.isOpen.then(() => {
- return this.target.root.then(rootForm => {
- const front = getPreferenceFront(this.target.client, rootForm);
- this._preferenceFront = front;
- return front;
- });
- });
+ return this.target.client.mainRoot.getFront("preference");
},
// Is the disable auto-hide of pop-ups feature available in this context?
@@ -2935,22 +2917,8 @@ Toolbox.prototype = {
// Destroy the profiler connection
outstanding.push(this.destroyPerformance());
- // Destroy the preference front
- outstanding.push(this.destroyPreference());
-
- // Destroy the style sheet front.
- if (this._styleSheets) {
- this._styleSheets.destroy();
- this._styleSheets = null;
- }
-
- // Destroy the device front for the current client if any.
- // A given DeviceFront instance can cached and shared between different panels, so
- // destroying it is the responsibility of the toolbox.
- const deviceFront = getKnownDeviceFront(this.target.client);
- if (deviceFront) {
- deviceFront.destroy();
- }
+ // Reset preferences set by the toolbox
+ outstanding.push(this.resetPreference());
// Detach the thread
detachThread(this._threadClient);
@@ -3104,7 +3072,7 @@ Toolbox.prototype = {
resolvePerformance = resolve;
});
- this._performance = createPerformanceFront(this._target);
+ this._performance = this.target.getFront("performance");
await this.performance.connect();
// Emit an event when connected, but don't wait on startup for this.
@@ -3135,20 +3103,9 @@ Toolbox.prototype = {
},
/**
- * Return the style sheets front, creating it if necessary. If the
- * style sheets front is not supported by the target, returns null.
+ * Reset preferences set by the toolbox.
*/
- initStyleSheetsFront: function() {
- if (!this._styleSheets && this.target.hasActor("styleSheets")) {
- this._styleSheets = StyleSheetsFront(this.target.client, this.target.form);
- }
- return this._styleSheets;
- },
-
- /**
- * Destroy the preferences actor when the toolbox is unloaded.
- */
- async destroyPreference() {
+ async resetPreference() {
if (!this._preferenceFront) {
return;
}
@@ -3159,7 +3116,6 @@ Toolbox.prototype = {
await this._preferenceFront.clearUserPref(DISABLE_AUTOHIDE_PREF);
}
- this._preferenceFront.destroy();
this._preferenceFront = null;
},
diff --git a/devtools/client/performance-new/panel.js b/devtools/client/performance-new/panel.js
index bc03c5d80f3c..5e1dfc3cf803 100644
--- a/devtools/client/performance-new/panel.js
+++ b/devtools/client/performance-new/panel.js
@@ -4,7 +4,6 @@
"use strict";
const { PerfFront } = require("devtools/shared/fronts/perf");
-const { getPreferenceFront } = require("devtools/shared/fronts/preference");
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
class PerformancePanel {
@@ -32,7 +31,7 @@ class PerformancePanel {
const rootForm = await this.target.root;
const perfFront = new PerfFront(this.target.client, rootForm);
- const preferenceFront = getPreferenceFront(this.target.client, rootForm);
+ const preferenceFront = this.target.client.mainRoot.getFront("preference");
this.isReady = true;
this.emit("ready");
diff --git a/devtools/client/preferences/devtools-client.js b/devtools/client/preferences/devtools-client.js
index 44220d721e94..d879802bcd38 100644
--- a/devtools/client/preferences/devtools-client.js
+++ b/devtools/client/preferences/devtools-client.js
@@ -335,8 +335,8 @@ pref("devtools.aboutdebugging.network-locations", "[]");
#endif
// Map top-level await expressions in the console
-#if defined(RELEASE_OR_BETA)
-pref("devtools.debugger.features.map-await-expression", false);
-#else
+#if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION)
pref("devtools.debugger.features.map-await-expression", true);
+#else
+pref("devtools.debugger.features.map-await-expression", false);
#endif
diff --git a/devtools/client/styleeditor/panel.js b/devtools/client/styleeditor/panel.js
index 9a9cccedf786..d94be9843408 100644
--- a/devtools/client/styleeditor/panel.js
+++ b/devtools/client/styleeditor/panel.js
@@ -47,7 +47,7 @@ StyleEditorPanel.prototype = {
this.target.on("close", this.destroy);
- this._debuggee = this._toolbox.initStyleSheetsFront();
+ this._debuggee = await this._target.getFront("stylesheets");
// Initialize the CSS properties database.
const {cssProperties} = await initCssProperties(this._toolbox);
diff --git a/devtools/client/webide/modules/app-manager.js b/devtools/client/webide/modules/app-manager.js
index a68cf22faca6..be5e62f97fbe 100644
--- a/devtools/client/webide/modules/app-manager.js
+++ b/devtools/client/webide/modules/app-manager.js
@@ -11,8 +11,6 @@ const {AppProjects} = require("devtools/client/webide/modules/app-projects");
const TabStore = require("devtools/client/webide/modules/tab-store");
const {AppValidator} = require("devtools/client/webide/modules/app-validator");
const {ConnectionManager, Connection} = require("devtools/shared/client/connection-manager");
-const {getDeviceFront} = require("devtools/shared/fronts/device");
-const {getPreferenceFront} = require("devtools/shared/fronts/preference");
const {RuntimeScanners} = require("devtools/client/webide/modules/runtimes");
const {RuntimeTypes} = require("devtools/client/webide/modules/runtime-types");
const {NetUtil} = require("resource://gre/modules/NetUtil.jsm");
@@ -141,7 +139,7 @@ var AppManager = exports.AppManager = {
}
},
- onConnectionChanged: function() {
+ onConnectionChanged: async function() {
console.log("Connection status changed: " + this.connection.status);
if (this.connection.status == Connection.Status.DISCONNECTED) {
@@ -150,12 +148,21 @@ var AppManager = exports.AppManager = {
if (!this.connected) {
this._listTabsResponse = null;
+ this.deviceFront = null;
+ this.preferenceFront = null;
} else {
- this.connection.client.listTabs().then((response) => {
- this._listTabsResponse = response;
- this._recordRuntimeInfo();
- this.update("runtime-global-actors");
+ const response = await this.connection.client.listTabs();
+ // RootClient.getRoot request was introduced in FF59, but RootClient.getFront
+ // expects it to work. Override its root form with the listTabs results (which is
+ // an equivalent) in orfer to fix RootClient.getFront.
+ Object.defineProperty(this.connection.client.mainRoot, "rootForm", {
+ value: response
});
+ this._listTabsResponse = response;
+ this.deviceFront = await this.connection.client.mainRoot.getFront("device");
+ this.preferenceFront = await this.connection.client.mainRoot.getFront("preference");
+ this._recordRuntimeInfo();
+ this.update("runtime-global-actors");
}
this.update("connection");
@@ -509,20 +516,6 @@ var AppManager = exports.AppManager = {
return this._listTabsResponse;
},
- get deviceFront() {
- if (!this._listTabsResponse) {
- return null;
- }
- return getDeviceFront(this.connection.client, this._listTabsResponse);
- },
-
- get preferenceFront() {
- if (!this._listTabsResponse) {
- return null;
- }
- return getPreferenceFront(this.connection.client, this._listTabsResponse);
- },
-
disconnectRuntime: function() {
if (!this.connected) {
return Promise.resolve();
diff --git a/devtools/client/webide/test/test_fullscreenToolbox.html b/devtools/client/webide/test/test_fullscreenToolbox.html
index 6a5c1a4c519d..1a51432be892 100644
--- a/devtools/client/webide/test/test_fullscreenToolbox.html
+++ b/devtools/client/webide/test/test_fullscreenToolbox.html
@@ -33,10 +33,13 @@
const docRuntime = getRuntimeDocument(win);
win.AppManager.update("runtime-list");
+ const onGlobalActors = waitForUpdate(win, "runtime-global-actors");
+ const onRuntimeTargets = waitForUpdate(win, "runtime-targets");
connectToLocal(win, docRuntime);
+ await onGlobalActors;
+ await onRuntimeTargets;
// Select main process
- await waitForUpdate(win, "runtime-targets");
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
diff --git a/devtools/client/webide/test/test_runtime.html b/devtools/client/webide/test/test_runtime.html
index 7f95879da84e..cf4d07d73353 100644
--- a/devtools/client/webide/test/test_runtime.html
+++ b/devtools/client/webide/test/test_runtime.html
@@ -136,11 +136,13 @@
ok(!isStopActive(), "stop button is disabled");
connectionsChanged = waitForConnectionChange("opened", 2);
+ const onGlobalActors = waitForUpdate(win, "runtime-global-actors");
+ const onRuntimeTargets = waitForUpdate(win, "runtime-targets");
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
-
- await waitForUpdate(win, "runtime-targets");
-
await connectionsChanged;
+ await onGlobalActors;
+ await onRuntimeTargets;
+
is(Object.keys(DebuggerServer._connections).length, 2, "Locally connected");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
diff --git a/devtools/server/tests/mochitest/test_device.html b/devtools/server/tests/mochitest/test_device.html
index 3ada49f0c628..0c2b44c907d5 100644
--- a/devtools/server/tests/mochitest/test_device.html
+++ b/devtools/server/tests/mochitest/test_device.html
@@ -22,16 +22,14 @@ window.onload = function() {
SimpleTest.waitForExplicitFinish();
- const {getDeviceFront} = require("devtools/shared/fronts/device");
-
DebuggerServer.init();
DebuggerServer.registerAllActors();
const client = new DebuggerClient(DebuggerServer.connectPipe());
client.connect().then(function onConnect() {
client.listTabs().then(function onListTabs(response) {
- const d = getDeviceFront(client, response);
-
+ return client.mainRoot.getFront("device");
+ }).then(function(d) {
let desc;
const appInfo = Services.appinfo;
const utils = window.windowUtils;
diff --git a/devtools/server/tests/mochitest/test_preference.html b/devtools/server/tests/mochitest/test_preference.html
index 1ae9ef0a3770..aec7ff0d52ff 100644
--- a/devtools/server/tests/mochitest/test_preference.html
+++ b/devtools/server/tests/mochitest/test_preference.html
@@ -22,16 +22,14 @@ function runTests() {
SimpleTest.waitForExplicitFinish();
- const {getPreferenceFront} = require("devtools/shared/fronts/preference");
-
DebuggerServer.init();
DebuggerServer.registerAllActors();
const client = new DebuggerClient(DebuggerServer.connectPipe());
client.connect().then(function onConnect() {
client.listTabs().then(function onListTabs(response) {
- const p = getPreferenceFront(client, response);
-
+ return client.mainRoot.getFront("preference");
+ }).then(function(p) {
const prefs = {};
const localPref = {
diff --git a/devtools/server/tests/unit/test_xpcshell_debugging.js b/devtools/server/tests/unit/test_xpcshell_debugging.js
index 47121ed02591..c48b24e2dec6 100644
--- a/devtools/server/tests/unit/test_xpcshell_debugging.js
+++ b/devtools/server/tests/unit/test_xpcshell_debugging.js
@@ -7,8 +7,6 @@
// Test the xpcshell-test debug support. Ideally we should have this test
// next to the xpcshell support code, but that's tricky...
-const {getDeviceFront} = require("devtools/shared/fronts/device");
-
add_task(async function() {
const testFile = do_get_file("xpcshell_debugging_script.js");
@@ -23,8 +21,7 @@ add_task(async function() {
await client.connect();
// Ensure that global actors are available. Just test the device actor.
- const rootForm = await client.mainRoot.getRoot();
- const deviceFront = await getDeviceFront(client, rootForm);
+ const deviceFront = await client.mainRoot.getFront("device");
const desc = await deviceFront.getDescription();
equal(desc.geckobuildid, Services.appinfo.platformBuildID, "device actor works");
diff --git a/devtools/shared/client/debugger-client.js b/devtools/shared/client/debugger-client.js
index 216a208c8d22..ef69ecf79d34 100644
--- a/devtools/shared/client/debugger-client.js
+++ b/devtools/shared/client/debugger-client.js
@@ -19,7 +19,6 @@ const {
loader.lazyRequireGetter(this, "Authentication", "devtools/shared/security/auth");
loader.lazyRequireGetter(this, "DebuggerSocket", "devtools/shared/security/socket", true);
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
-loader.lazyRequireGetter(this, "getDeviceFront", "devtools/shared/fronts/device", true);
loader.lazyRequireGetter(this, "WebConsoleClient", "devtools/shared/webconsole/client", true);
loader.lazyRequireGetter(this, "AddonClient", "devtools/shared/client/addon-client");
@@ -204,9 +203,7 @@ DebuggerClient.prototype = {
async checkRuntimeVersion(listTabsForm) {
let incompatible = null;
- // Instead of requiring to pass `listTabsForm` here,
- // we can call getRoot() instead, but only once Firefox ESR59 is released
- const deviceFront = await getDeviceFront(this, listTabsForm);
+ const deviceFront = await this.mainRoot.getFront("device");
const desc = await deviceFront.getDescription();
// 1) Check for Firefox too recent on device.
diff --git a/devtools/shared/client/root-client.js b/devtools/shared/client/root-client.js
index 691c7b90bb3e..e3cd26e6b9f5 100644
--- a/devtools/shared/client/root-client.js
+++ b/devtools/shared/client/root-client.js
@@ -6,6 +6,7 @@
const { Ci } = require("chrome");
const { arg, DebuggerClient } = require("devtools/shared/client/debugger-client");
+loader.lazyRequireGetter(this, "getFront", "devtools/shared/protocol", true);
/**
* A RootClient object represents a root actor on the server. Each
@@ -32,6 +33,23 @@ function RootClient(client, greeting) {
this.actor = greeting.from;
this.applicationType = greeting.applicationType;
this.traits = greeting.traits;
+
+ // Cache root form as this will always be the same value.
+ //
+ // Note that rootForm is overloaded by DebuggerClient.checkRuntimeVersion
+ // in order to support Front instance]
+ this.fronts = new Map();
}
exports.RootClient = RootClient;
@@ -43,7 +61,7 @@ RootClient.prototype = {
* browser. This can replace usages of `listTabs` that only wanted the global actors
* and didn't actually care about tabs.
*/
- getRoot: DebuggerClient.requester({ type: "getRoot" }),
+ _getRoot: DebuggerClient.requester({ type: "getRoot" }),
/**
* List the open tabs.
@@ -259,6 +277,24 @@ RootClient.prototype = {
return this.request(packet);
},
+ /*
+ * This function returns a protocol.js Front for any root actor.
+ * i.e. the one directly served from RootActor.listTabs or getRoot.
+ *
+ * @param String typeName
+ * The type name used in protocol.js's spec for this actor.
+ */
+ async getFront(typeName) {
+ let front = this.fronts.get(typeName);
+ if (front) {
+ return front;
+ }
+ const rootForm = await this.rootForm;
+ front = getFront(this._client, typeName, rootForm);
+ this.fronts.set(typeName, front);
+ return front;
+ },
+
/**
* Description of protocol's actors and methods.
*
diff --git a/devtools/shared/fronts/device.js b/devtools/shared/fronts/device.js
index ed40e59f20a2..b6b85d400a55 100644
--- a/devtools/shared/fronts/device.js
+++ b/devtools/shared/fronts/device.js
@@ -36,29 +36,4 @@ const DeviceFront = protocol.FrontClassWithSpec(deviceSpec, {
},
});
-const _knownDeviceFronts = new WeakMap();
-
-/**
- * Retrieve the device front already created for the provided client, if available.
- */
-exports.getKnownDeviceFront = function(client) {
- return _knownDeviceFronts.get(client);
-};
-
-/**
- * Only one DeviceFront is created for a given client, afterwards the instance is cached
- * and returned immediately.
- */
-exports.getDeviceFront = function(client, form) {
- if (!form.deviceActor) {
- return null;
- }
-
- if (_knownDeviceFronts.has(client)) {
- return _knownDeviceFronts.get(client);
- }
-
- const front = new DeviceFront(client, form);
- _knownDeviceFronts.set(client, front);
- return front;
-};
+exports.DeviceFront = DeviceFront;
diff --git a/devtools/shared/fronts/performance.js b/devtools/shared/fronts/performance.js
index 9ef9f444320b..f215edd14060 100644
--- a/devtools/shared/fronts/performance.js
+++ b/devtools/shared/fronts/performance.js
@@ -131,7 +131,3 @@ const PerformanceFront = FrontClassWithSpec(performanceSpec, {
});
exports.PerformanceFront = PerformanceFront;
-
-exports.createPerformanceFront = function createPerformanceFront(target) {
- return new PerformanceFront(target.client, target.form);
-};
diff --git a/devtools/shared/fronts/preference.js b/devtools/shared/fronts/preference.js
index 6fbed6513c73..dcf8f280e1c4 100644
--- a/devtools/shared/fronts/preference.js
+++ b/devtools/shared/fronts/preference.js
@@ -14,18 +14,4 @@ const PreferenceFront = protocol.FrontClassWithSpec(preferenceSpec, {
},
});
-const _knownPreferenceFronts = new WeakMap();
-
-exports.getPreferenceFront = function(client, form) {
- if (!form.preferenceActor) {
- return null;
- }
-
- if (_knownPreferenceFronts.has(client)) {
- return _knownPreferenceFronts.get(client);
- }
-
- const front = new PreferenceFront(client, form);
- _knownPreferenceFronts.set(client, front);
- return front;
-};
+exports.PreferenceFront = PreferenceFront;
diff --git a/devtools/shared/protocol.js b/devtools/shared/protocol.js
index 64a66950cf71..3eedc497c8b7 100644
--- a/devtools/shared/protocol.js
+++ b/devtools/shared/protocol.js
@@ -1642,3 +1642,15 @@ exports.dumpProtocolSpec = function() {
return ret;
};
+
+function getFront(client, typeName, form) {
+ const type = types.getType(typeName);
+ if (!type) {
+ throw new Error(`No spec for front type '${typeName}'.`);
+ }
+ if (!type.frontClass) {
+ lazyLoadFront(typeName);
+ }
+ return type.frontClass(client, form);
+}
+exports.getFront = getFront;
diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
index f2ad610166d4..1149b4dbb6a5 100644
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -906,12 +906,10 @@ CopyingStructuredCloneReadCallback(JSContext* aCx,
if (aTag == SCTAG_DOM_BLOB) {
MOZ_ASSERT(file.mType == StructuredCloneFile::eBlob);
-
- RefPtr blob = file.mBlob;
- MOZ_ASSERT(!blob->IsFile());
+ MOZ_ASSERT(!file.mBlob->IsFile());
JS::Rooted wrappedBlob(aCx);
- if (NS_WARN_IF(!ToJSValue(aCx, blob, &wrappedBlob))) {
+ if (NS_WARN_IF(!ToJSValue(aCx, file.mBlob, &wrappedBlob))) {
return nullptr;
}
@@ -923,19 +921,23 @@ CopyingStructuredCloneReadCallback(JSContext* aCx,
if (aTag == SCTAG_DOM_FILE) {
MOZ_ASSERT(file.mType == StructuredCloneFile::eBlob);
- RefPtr blob = file.mBlob;
- MOZ_ASSERT(blob->IsFile());
+ {
+ // Create a scope so ~RefPtr fires before returning an unwrapped
+ // JS::Value.
+ RefPtr blob = file.mBlob;
+ MOZ_ASSERT(blob->IsFile());
- RefPtr file = blob->ToFile();
- MOZ_ASSERT(file);
+ RefPtr file = blob->ToFile();
+ MOZ_ASSERT(file);
- JS::Rooted wrappedFile(aCx);
- if (NS_WARN_IF(!ToJSValue(aCx, file, &wrappedFile))) {
- return nullptr;
+ JS::Rooted wrappedFile(aCx);
+ if (NS_WARN_IF(!ToJSValue(aCx, file, &wrappedFile))) {
+ return nullptr;
+ }
+
+ result.set(&wrappedFile.toObject());
}
- result.set(&wrappedFile.toObject());
-
return result;
}
diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp
index fc1d2e9c1d29..511ebf884c21 100644
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -109,6 +109,8 @@
#include "CubebUtils.h"
#elif defined(XP_MACOSX)
#include "mozilla/Sandbox.h"
+#elif defined(__OpenBSD__)
+#include
#endif
#endif
@@ -1783,6 +1785,8 @@ ContentChild::RecvSetProcessSandbox(const MaybeFileDesc& aBroker)
mozilla::SandboxTarget::Instance()->StartSandbox();
#elif defined(XP_MACOSX)
sandboxEnabled = StartMacOSContentSandbox();
+#elif defined(__OpenBSD__)
+ sandboxEnabled = StartOpenBSDSandbox(GeckoProcessType_Content);
#endif
CrashReporter::AnnotateCrashReport(
@@ -3921,6 +3925,55 @@ ContentChild::OnMessageReceived(const Message& aMsg, Message*& aReply)
} // namespace dom
+#if defined(__OpenBSD__) && defined(MOZ_CONTENT_SANDBOX)
+#include
+
+static LazyLogModule sPledgeLog("SandboxPledge");
+
+bool
+StartOpenBSDSandbox(GeckoProcessType type)
+{
+ nsAutoCString promisesString;
+ nsAutoCString processTypeString;
+
+ switch (type) {
+ case GeckoProcessType_Default:
+ processTypeString = "main";
+ Preferences::GetCString("security.sandbox.pledge.main",
+ promisesString);
+ break;
+
+ case GeckoProcessType_Content:
+ processTypeString = "content";
+ Preferences::GetCString("security.sandbox.pledge.content",
+ promisesString);
+ break;
+
+ default:
+ MOZ_ASSERT(false, "unknown process type");
+ return false;
+ };
+
+ if (pledge(promisesString.get(), NULL) == -1) {
+ if (errno == EINVAL) {
+ MOZ_LOG(sPledgeLog, LogLevel::Error,
+ ("pledge promises for %s process is a malformed string: '%s'\n",
+ processTypeString.get(), promisesString.get()));
+ } else if (errno == EPERM) {
+ MOZ_LOG(sPledgeLog, LogLevel::Error,
+ ("pledge promises for %s process can't elevate privileges: '%s'\n",
+ processTypeString.get(), promisesString.get()));
+ }
+ return false;
+ } else {
+ MOZ_LOG(sPledgeLog, LogLevel::Debug,
+ ("pledged %s process with promises: '%s'\n",
+ processTypeString.get(), promisesString.get()));
+ }
+ return true;
+}
+#endif
+
#if !defined(XP_WIN)
bool IsDevelopmentBuild()
{
diff --git a/dom/tests/mochitest/general/test_datatransfer_disallowed.html b/dom/tests/mochitest/general/test_datatransfer_disallowed.html
index 726db26a870c..bcf6915fa1b6 100644
--- a/dom/tests/mochitest/general/test_datatransfer_disallowed.html
+++ b/dom/tests/mochitest/general/test_datatransfer_disallowed.html
@@ -11,7 +11,7 @@
function run_test()
{
SpecialPowers.pushPrefEnv({"set": [
- ["dom.datatransfer.moz", false],
+ ["dom.datatransfer.mozAtAPIs", false],
]}, function() {
let hiddenMethods = ["mozTypesAt", "mozClearDataAt", "mozGetDataAt", "mozSetDataAt", "mozItemCount"];
let exposedMethods = Object.getOwnPropertyNames(DataTransfer.prototype);
diff --git a/editor/txmgr/TransactionManagerFactory.cpp b/editor/txmgr/TransactionManagerFactory.cpp
deleted file mode 100644
index 94876e8462cc..000000000000
--- a/editor/txmgr/TransactionManagerFactory.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* 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
-
-#include "mozilla/Module.h"
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/TransactionManager.h"
-#include "nsID.h"
-#include "nsITransactionManager.h"
-
-using mozilla::TransactionManager;
-
-////////////////////////////////////////////////////////////////////////
-// Define the contructor function for the objects
-//
-// NOTE: This creates an instance of objects by using the default constructor
-//
-NS_GENERIC_FACTORY_CONSTRUCTOR(TransactionManager)
-NS_DEFINE_NAMED_CID(NS_TRANSACTIONMANAGER_CID);
-
-static const mozilla::Module::CIDEntry kTxMgrCIDs[] = {
- { &kNS_TRANSACTIONMANAGER_CID, false, nullptr,
- TransactionManagerConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kTxMgrContracts[] = {
- { NS_TRANSACTIONMANAGER_CONTRACTID, &kNS_TRANSACTIONMANAGER_CID },
- { nullptr }
-};
-
-static const mozilla::Module kTxMgrModule = {
- mozilla::Module::kVersion,
- kTxMgrCIDs,
- kTxMgrContracts
-};
-
-NSMODULE_DEFN(nsTransactionManagerModule) = &kTxMgrModule;
diff --git a/editor/txmgr/moz.build b/editor/txmgr/moz.build
index 98957516202a..fe2ff825e383 100644
--- a/editor/txmgr/moz.build
+++ b/editor/txmgr/moz.build
@@ -26,7 +26,6 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [
'TransactionItem.cpp',
'TransactionManager.cpp',
- 'TransactionManagerFactory.cpp',
'TransactionStack.cpp',
]
diff --git a/editor/txmgr/nsITransactionManager.idl b/editor/txmgr/nsITransactionManager.idl
index 1443eb8357b9..0baaf0423da6 100644
--- a/editor/txmgr/nsITransactionManager.idl
+++ b/editor/txmgr/nsITransactionManager.idl
@@ -160,14 +160,3 @@ interface nsITransactionManager : nsISupports
inline mozilla::TransactionManager* AsTransactionManager();
%}
};
-
-%{ C++
-
-#define NS_TRANSACTIONMANAGER_CONTRACTID "@mozilla.org/transactionmanager;1"
-
-// 9C8F9601-801A-11d2-98BA-00805F297D89
-#define NS_TRANSACTIONMANAGER_CID \
-{ 0x9c8f9601, 0x801a, 0x11d2, \
- { 0x98, 0xba, 0x0, 0x80, 0x5f, 0x29, 0x7d, 0x89 } }
-
-%} C++
diff --git a/editor/txmgr/tests/TestTXMgr.cpp b/editor/txmgr/tests/TestTXMgr.cpp
index ccaca6c67b9a..361c9913d303 100644
--- a/editor/txmgr/tests/TestTXMgr.cpp
+++ b/editor/txmgr/tests/TestTXMgr.cpp
@@ -8,6 +8,9 @@
#include "nsITransactionManager.h"
#include "nsComponentManagerUtils.h"
#include "mozilla/Likely.h"
+#include "mozilla/TransactionManager.h"
+
+using mozilla::TransactionManager;
static int32_t sConstructorCount = 0;
static int32_t sDoCount = 0;
@@ -533,10 +536,7 @@ quick_test(TestTransactionFactory *factory)
*
*******************************************************************/
- nsresult rv;
- nsCOMPtr mgr =
- do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &rv);
- ASSERT_TRUE(NS_SUCCEEDED(rv));
+ nsCOMPtr mgr = new TransactionManager();
/*******************************************************************
*
@@ -544,7 +544,7 @@ quick_test(TestTransactionFactory *factory)
*
*******************************************************************/
- rv = mgr->DoTransaction(0);
+ nsresult rv = mgr->DoTransaction(0);
EXPECT_EQ(rv, NS_ERROR_NULL_POINTER);
/*******************************************************************
@@ -1285,11 +1285,7 @@ quick_batch_test(TestTransactionFactory *factory)
*
*******************************************************************/
- nsresult rv;
- nsCOMPtr mgr =
- do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &rv);
- ASSERT_TRUE(mgr);
- ASSERT_TRUE(NS_SUCCEEDED(rv));
+ nsCOMPtr mgr = new TransactionManager();
int32_t numitems;
@@ -1300,7 +1296,7 @@ quick_batch_test(TestTransactionFactory *factory)
*
*******************************************************************/
- rv = mgr->GetNumberOfUndoItems(&numitems);
+ nsresult rv = mgr->GetNumberOfUndoItems(&numitems);
EXPECT_TRUE(NS_SUCCEEDED(rv));
EXPECT_EQ(numitems, 0);
@@ -1920,12 +1916,9 @@ stress_test(TestTransactionFactory *factory, int32_t iterations)
*
*******************************************************************/
- nsresult rv;
- nsCOMPtr mgr =
- do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &rv);
- ASSERT_TRUE(NS_SUCCEEDED(rv));
- ASSERT_TRUE(mgr);
+ nsCOMPtr mgr = new TransactionManager();
+ nsresult rv;
int32_t i, j;
for (i = 1; i <= iterations; i++) {
diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp
index 1cb6cbfd6014..23e0d6e4c9b8 100644
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -1543,7 +1543,7 @@ gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet,
continue;
}
-#ifdef MOZ_CONTENT_SANDBOX
+#if defined(MOZ_CONTENT_SANDBOX) && defined (XP_LINUX)
// Skip any fonts that will be blocked by the content-process sandbox
// policy.
if (aPolicy && !(aPolicy->Lookup(reinterpret_cast(path)) &
@@ -1705,7 +1705,7 @@ gfxFcPlatformFontList::InitFontListForPlatform()
UniquePtr policy;
-#ifdef MOZ_CONTENT_SANDBOX
+#if defined(MOZ_CONTENT_SANDBOX) && defined (XP_LINUX)
// If read sandboxing is enabled, create a temporary SandboxPolicy to
// check font paths; use a fake PID to avoid picking up any PID-specific
// rules by accident.
diff --git a/gfx/thebes/gfxFcPlatformFontList.h b/gfx/thebes/gfxFcPlatformFontList.h
index 510a4a21b86a..886223134f17 100644
--- a/gfx/thebes/gfxFcPlatformFontList.h
+++ b/gfx/thebes/gfxFcPlatformFontList.h
@@ -340,7 +340,7 @@ public:
protected:
virtual ~gfxFcPlatformFontList();
-#ifdef MOZ_CONTENT_SANDBOX
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
typedef mozilla::SandboxBroker::Policy SandboxPolicy;
#else
// Dummy type just so we can still have a SandboxPolicy* parameter.
diff --git a/ipc/chromium/src/build/build_config.h b/ipc/chromium/src/build/build_config.h
index dbbf0f3c7963..3965492aa467 100644
--- a/ipc/chromium/src/build/build_config.h
+++ b/ipc/chromium/src/build/build_config.h
@@ -117,7 +117,7 @@
#elif defined(__alpha__)
#define ARCH_CPU_ALPHA 1
#define ARCH_CPU_64_BITS 1
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || defined(_M_ARM64)
#define ARCH_CPU_ARM_FAMILY 1
#define ARCH_CPU_ARM64 1
#define ARCH_CPU_64_BITS 1
diff --git a/js/public/AllocPolicy.h b/js/public/AllocPolicy.h
index 7df6d24c426b..0ab9417989bb 100644
--- a/js/public/AllocPolicy.h
+++ b/js/public/AllocPolicy.h
@@ -128,40 +128,6 @@ class TempAllocPolicy : public AllocPolicyBase
}
};
-/*
- * Allocation policy that uses Zone::pod_malloc and friends, so that memory
- * pressure is accounted for on the zone. This is suitable for memory associated
- * with GC things allocated in the zone.
- *
- * Since it doesn't hold a JSContext (those may not live long enough), it can't
- * report out-of-memory conditions itself; the caller must check for OOM and
- * take the appropriate action.
- *
- * FIXME bug 647103 - replace these *AllocPolicy names.
- */
-class ZoneAllocPolicy
-{
- JS::Zone* const zone;
-
- public:
- MOZ_IMPLICIT ZoneAllocPolicy(JS::Zone* z) : zone(z) {}
-
- // These methods are defined in gc/Zone.h.
- template inline T* maybe_pod_malloc(size_t numElems);
- template inline T* maybe_pod_calloc(size_t numElems);
- template inline T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize);
- template inline T* pod_malloc(size_t numElems);
- template inline T* pod_calloc(size_t numElems);
- template inline T* pod_realloc(T* p, size_t oldSize, size_t newSize);
-
- template void free_(T* p, size_t numElems = 0) { js_free(p); }
- void reportAllocOverflow() const {}
-
- MOZ_MUST_USE bool checkSimulatedOOM() const {
- return !js::oom::ShouldFailWithOOM();
- }
-};
-
} /* namespace js */
#endif /* js_AllocPolicy_h */
diff --git a/js/public/GCAnnotations.h b/js/public/GCAnnotations.h
index 8b47b24041e8..7b8f9becd43f 100644
--- a/js/public/GCAnnotations.h
+++ b/js/public/GCAnnotations.h
@@ -26,6 +26,12 @@
// is not itself a GC pointer.
# define JS_HAZ_GC_INVALIDATED __attribute__((tag("Invalidated by GC")))
+// Mark a class as a base class of rooted types, eg CustomAutoRooter. All
+// descendants of this class will be considered rooted, though classes that
+// merely contain these as a field member will not be. "Inherited" by
+// templatized types with MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS
+# define JS_HAZ_ROOTED_BASE __attribute__((tag("Rooted Base")))
+
// Mark a type that would otherwise be considered a GC Pointer (eg because it
// contains a JS::Value field) as a non-GC pointer. It is handled almost the
// same in the analysis as a rooted pointer, except it will not be reported as
@@ -52,6 +58,7 @@
# define JS_HAZ_GC_POINTER
# define JS_HAZ_ROOTED
# define JS_HAZ_GC_INVALIDATED
+# define JS_HAZ_ROOTED_BASE
# define JS_HAZ_NON_GC_POINTER
# define JS_HAZ_GC_CALL
# define JS_HAZ_GC_SUPPRESSED
diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h
index c39c757b9508..b3acc89287d3 100644
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -945,7 +945,7 @@ class JS_PUBLIC_API(AutoGCRooter)
/* No copy or assignment semantics. */
AutoGCRooter(AutoGCRooter& ida) = delete;
void operator=(AutoGCRooter& ida) = delete;
-};
+} JS_HAZ_ROOTED_BASE;
namespace detail {
diff --git a/js/src/builtin/AtomicsObject.cpp b/js/src/builtin/AtomicsObject.cpp
index a421cbcf1572..3de47aa6fc75 100644
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -689,10 +689,10 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
}
int64_t
-js::atomics_wake_impl(SharedArrayRawBuffer* sarb, uint32_t byteOffset, int64_t count)
+js::atomics_notify_impl(SharedArrayRawBuffer* sarb, uint32_t byteOffset, int64_t count)
{
// Validation should ensure this does not happen.
- MOZ_ASSERT(sarb, "wake is only applicable to shared memory");
+ MOZ_ASSERT(sarb, "notify is only applicable to shared memory");
AutoLockFutexAPI lock;
@@ -706,7 +706,7 @@ js::atomics_wake_impl(SharedArrayRawBuffer* sarb, uint32_t byteOffset, int64_t c
iter = iter->lower_pri;
if (c->offset != byteOffset || !c->cx->fx.isWaiting())
continue;
- c->cx->fx.wake(FutexThread::WakeExplicit);
+ c->cx->fx.notify(FutexThread::NotifyExplicit);
// Overflow will be a problem only in two cases:
// (1) 128-bit systems with substantially more than 2^64 bytes of
// memory per process, and a very lightweight
@@ -723,7 +723,7 @@ js::atomics_wake_impl(SharedArrayRawBuffer* sarb, uint32_t byteOffset, int64_t c
}
bool
-js::atomics_wake(JSContext* cx, unsigned argc, Value* vp)
+js::atomics_notify(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
HandleValue objv = args.get(0);
@@ -758,7 +758,7 @@ js::atomics_wake(JSContext* cx, unsigned argc, Value* vp)
(view->viewDataShared().cast().unwrap(/* arithmetic */) -
sab->dataPointerShared().unwrap(/* arithmetic */));
- r.setNumber(double(atomics_wake_impl(sab->rawBufferObject(), byteOffset, count)));
+ r.setNumber(double(atomics_notify_impl(sab->rawBufferObject(), byteOffset, count)));
return true;
}
@@ -830,7 +830,7 @@ js::FutexThread::isWaiting()
// When a worker is awoken for an interrupt it goes into state
// WaitingNotifiedForInterrupt for a short time before it actually
// wakes up and goes into WaitingInterrupted. In those states the
- // worker is still waiting, and if an explicit wake arrives the
+ // worker is still waiting, and if an explicit notify arrives the
// worker transitions to Woken. See further comments in
// FutexThread::wait().
return state_ == Waiting || state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt;
@@ -909,14 +909,14 @@ js::FutexThread::wait(JSContext* cx, js::UniqueLock& locked,
// should be woken when the interrupt handler returns.
// To that end, we flag the thread as interrupted around
// the interrupt and check state_ when the interrupt
- // handler returns. A wake() call that reaches the
+ // handler returns. A notify() call that reaches the
// runtime during the interrupt sets state_ to Woken.
//
// - It is in principle possible for wait() to be
// reentered on the same thread/runtime and waiting on the
// same location and to yet again be interrupted and enter
// the interrupt handler. In this case, it is important
- // that when another agent wakes waiters, all waiters using
+ // that when another agent notifies waiters, all waiters using
// the same runtime on the same location are woken in LIFO
// order; FIFO may be the required order, but FIFO would
// fail to wake up the innermost call. Interrupts are
@@ -947,25 +947,25 @@ js::FutexThread::wait(JSContext* cx, js::UniqueLock& locked,
}
void
-js::FutexThread::wake(WakeReason reason)
+js::FutexThread::notify(NotifyReason reason)
{
MOZ_ASSERT(isWaiting());
- if ((state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt) && reason == WakeExplicit) {
+ if ((state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt) && reason == NotifyExplicit) {
state_ = Woken;
return;
}
switch (reason) {
- case WakeExplicit:
+ case NotifyExplicit:
state_ = Woken;
break;
- case WakeForJSInterrupt:
+ case NotifyForJSInterrupt:
if (state_ == WaitingNotifiedForInterrupt)
return;
state_ = WaitingNotifiedForInterrupt;
break;
default:
- MOZ_CRASH("bad WakeReason in FutexThread::wake()");
+ MOZ_CRASH("bad NotifyReason in FutexThread::notify()");
}
cond_->notify_all();
}
@@ -982,7 +982,8 @@ const JSFunctionSpec AtomicsMethods[] = {
JS_INLINABLE_FN("xor", atomics_xor, 3,0, AtomicsXor),
JS_INLINABLE_FN("isLockFree", atomics_isLockFree, 1,0, AtomicsIsLockFree),
JS_FN("wait", atomics_wait, 4,0),
- JS_FN("wake", atomics_wake, 3,0),
+ JS_FN("notify", atomics_notify, 3,0),
+ JS_FN("wake", atomics_notify, 3,0), // Legacy name
JS_FS_END
};
diff --git a/js/src/builtin/AtomicsObject.h b/js/src/builtin/AtomicsObject.h
index 42ed57cc819d..e1078a158e0c 100644
--- a/js/src/builtin/AtomicsObject.h
+++ b/js/src/builtin/AtomicsObject.h
@@ -39,7 +39,7 @@ MOZ_MUST_USE bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
MOZ_MUST_USE bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
MOZ_MUST_USE bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
MOZ_MUST_USE bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
-MOZ_MUST_USE bool atomics_wake(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_notify(JSContext* cx, unsigned argc, Value* vp);
class FutexThread
{
@@ -56,10 +56,10 @@ public:
MOZ_MUST_USE bool initInstance();
void destroyInstance();
- // Parameters to wake().
- enum WakeReason {
- WakeExplicit, // Being asked to wake up by another thread
- WakeForJSInterrupt // Interrupt requested
+ // Parameters to notify().
+ enum NotifyReason {
+ NotifyExplicit, // Being asked to wake up by another thread
+ NotifyForJSInterrupt // Interrupt requested
};
// Result codes from wait() and atomics_wait_impl().
@@ -78,29 +78,27 @@ public:
// times allowed; specify mozilla::Nothing() for an indefinite
// wait.
//
- // wait() will not wake up spuriously. It will return true and
- // set *result to a return code appropriate for
- // Atomics.wait() on success, and return false on error.
+ // wait() will not wake up spuriously.
MOZ_MUST_USE WaitResult wait(JSContext* cx, js::UniqueLock& locked,
const mozilla::Maybe& timeout);
- // Wake the thread this is associated with.
+ // Notify the thread this is associated with.
//
// The futex lock must be held around this call. (The sleeping
- // thread will not wake up until the caller of Atomics.wake()
+ // thread will not wake up until the caller of Atomics.notify()
// releases the lock.)
//
// If the thread is not waiting then this method does nothing.
//
// If the thread is waiting in a call to wait() and the
- // reason is WakeExplicit then the wait() call will return
+ // reason is NotifyExplicit then the wait() call will return
// with Woken.
//
// If the thread is waiting in a call to wait() and the
- // reason is WakeForJSInterrupt then the wait() will return
+ // reason is NotifyForJSInterrupt then the wait() will return
// with WaitingNotifiedForInterrupt; in the latter case the caller
// of wait() must handle the interrupt.
- void wake(WakeReason reason);
+ void notify(NotifyReason reason);
bool isWaiting();
@@ -123,7 +121,7 @@ public:
// interrupt handler
WaitingInterrupted, // We are waiting, but have been interrupted
// and are running the interrupt handler
- Woken // Woken by a script call to Atomics.wake
+ Woken // Woken by a script call to Atomics.notify
};
// Condition variable that this runtime will wait on.
@@ -157,12 +155,12 @@ MOZ_MUST_USE FutexThread::WaitResult
atomics_wait_impl(JSContext* cx, SharedArrayRawBuffer* sarb, uint32_t byteOffset, int64_t value,
const mozilla::Maybe& timeout);
-// Wake some waiters on the given address. If `count` is negative then wake
+// Notify some waiters on the given address. If `count` is negative then notify
// all. The return value is nonnegative and is the number of waiters woken. If
// the number of waiters woken exceeds INT64_MAX then this never returns. If
// `count` is nonnegative then the return value is never greater than `count`.
MOZ_MUST_USE int64_t
-atomics_wake_impl(SharedArrayRawBuffer* sarb, uint32_t byteOffset, int64_t count);
+atomics_notify_impl(SharedArrayRawBuffer* sarb, uint32_t byteOffset, int64_t count);
} /* namespace js */
diff --git a/js/src/builtin/DataViewObject.cpp b/js/src/builtin/DataViewObject.cpp
index e4797163954e..d9f6174523a6 100644
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -171,7 +171,7 @@ bool
DataViewObject::constructSameCompartment(JSContext* cx, HandleObject bufobj, const CallArgs& args)
{
MOZ_ASSERT(args.isConstructing());
- assertSameCompartment(cx, bufobj);
+ cx->check(bufobj);
uint32_t byteOffset, byteLength;
if (!getAndCheckConstructorArgs(cx, bufobj, args, &byteOffset, &byteLength))
diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp
index db96a837bf12..f78aac37b23e 100644
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -440,7 +440,7 @@ static bool
ExecuteInExtensibleLexicalEnvironment(JSContext* cx, HandleScript scriptArg, HandleObject env)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, env);
+ cx->check(env);
MOZ_ASSERT(IsExtensibleLexicalEnvironment(env));
MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope());
@@ -518,7 +518,7 @@ JS_FRIEND_API(bool)
js::ExecuteInJSMEnvironment(JSContext* cx, HandleScript scriptArg, HandleObject varEnv,
AutoObjectVector& targetObj)
{
- assertSameCompartment(cx, varEnv);
+ cx->check(varEnv);
MOZ_ASSERT(ObjectRealm::get(varEnv).getNonSyntacticLexicalEnvironment(varEnv));
MOZ_DIAGNOSTIC_ASSERT(scriptArg->noScriptRval());
diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp
index 5b1e4c4571ba..ef4845fcc382 100644
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1711,7 +1711,7 @@ RetT
CallObjFunc(RetT(*ObjFunc)(JSContext*, HandleObject), JSContext* cx, HandleObject obj)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, obj);
+ cx->check(obj);
// Always unwrap, in case this is an xray or cross-compartment wrapper.
RootedObject unwrappedObj(cx);
@@ -1729,7 +1729,7 @@ CallObjFunc(bool(*ObjFunc)(JSContext *cx, HandleObject obj, HandleValue key, boo
JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, obj, key);
+ cx->check(obj, key);
// Always unwrap, in case this is an xray or cross-compartment wrapper.
RootedObject unwrappedObj(cx);
@@ -1754,7 +1754,7 @@ CallObjFunc(bool(*ObjFunc)(JSContext* cx, Iter kind,
JSContext *cx, Iter iterType, HandleObject obj, MutableHandleValue rval)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, obj);
+ cx->check(obj);
// Always unwrap, in case this is an xray or cross-compartment wrapper.
RootedObject unwrappedObj(cx);
@@ -1794,7 +1794,7 @@ JS_PUBLIC_API(bool)
JS::MapGet(JSContext* cx, HandleObject obj, HandleValue key, MutableHandleValue rval)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, obj, key, rval);
+ cx->check(obj, key, rval);
// Unwrap the object, and enter its realm. If object isn't wrapped,
// this is essentially a noop.
@@ -1825,7 +1825,7 @@ JS_PUBLIC_API(bool)
JS::MapSet(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, obj, key, val);
+ cx->check(obj, key, val);
// Unwrap the object, and enter its compartment. If object isn't wrapped,
// this is essentially a noop.
@@ -1906,7 +1906,7 @@ JS_PUBLIC_API(bool)
JS::SetAdd(JSContext *cx, HandleObject obj, HandleValue key)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, obj, key);
+ cx->check(obj, key);
// Unwrap the object, and enter its compartment. If object isn't wrapped,
// this is essentially a noop.
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 1c39b38bb2da..cadfe92c7410 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -1192,8 +1192,6 @@ GlobalObject::initModuleProto(JSContext* cx, Handle global)
static const JSFunctionSpec protoFunctions[] = {
JS_SELF_HOSTED_FN("getExportedNames", "ModuleGetExportedNames", 1, 0),
JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 2, 0),
- JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleInstantiate", 0, 0),
- JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluate", 0, 0),
JS_FS_END
};
diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
index 68b9607ff08c..b3e7090c45c9 100644
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -12,6 +12,7 @@
#include "jsapi.h"
#include "builtin/SelfHostingDefines.h"
+#include "gc/Zone.h"
#include "js/GCVector.h"
#include "js/Id.h"
#include "js/UniquePtr.h"
diff --git a/js/src/builtin/Profilers.cpp b/js/src/builtin/Profilers.cpp
index 7507c4925d2e..843d7849320e 100644
--- a/js/src/builtin/Profilers.cpp
+++ b/js/src/builtin/Profilers.cpp
@@ -400,7 +400,7 @@ static const JSFunctionSpec profiling_functions[] = {
JS_PUBLIC_API(bool)
JS_DefineProfilingFunctions(JSContext* cx, HandleObject obj)
{
- assertSameCompartment(cx, obj);
+ cx->check(obj);
#ifdef MOZ_PROFILING
return JS_DefineFunctions(cx, obj, profiling_functions);
#else
diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp
index 407dd01a7581..f52a99082339 100644
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -232,9 +232,9 @@ NewPromiseAllDataHolder(JSContext* cx, HandleObject resultPromise, HandleValue v
if (!dataHolder)
return nullptr;
- assertSameCompartment(cx, resultPromise);
- assertSameCompartment(cx, valuesArray);
- assertSameCompartment(cx, resolve);
+ cx->check(resultPromise);
+ cx->check(valuesArray);
+ cx->check(resolve);
dataHolder->setFixedSlot(PromiseAllDataHolderSlot_Promise, ObjectValue(*resultPromise));
dataHolder->setFixedSlot(PromiseAllDataHolderSlot_RemainingElements, Int32Value(1));
@@ -772,7 +772,7 @@ static bool Promise_then_impl(JSContext* cx, HandleValue promiseVal, HandleValue
static MOZ_MUST_USE bool
ResolvePromiseInternal(JSContext* cx, HandleObject promise, HandleValue resolutionVal)
{
- assertSameCompartment(cx, promise, resolutionVal);
+ cx->check(promise, resolutionVal);
MOZ_ASSERT(!IsSettledMaybeWrappedPromise(promise));
// Step 7 (reordered).
@@ -935,7 +935,7 @@ EnqueuePromiseReactionJob(JSContext* cx, HandleObject reactionObj,
// Must not enqueue a reaction job more than once.
MOZ_ASSERT(reaction->targetState() == JS::PromiseState::Pending);
- assertSameCompartment(cx, handlerArg);
+ cx->check(handlerArg);
reaction->setTargetStateAndHandlerArg(targetState, handlerArg);
RootedValue reactionVal(cx, ObjectValue(*reaction));
@@ -1637,7 +1637,7 @@ PromiseResolveBuiltinThenableJob(JSContext* cx, unsigned argc, Value* vp)
RootedObject promise(cx, &job->getExtendedSlot(BuiltinThenableJobSlot_Promise).toObject());
RootedObject thenable(cx, &job->getExtendedSlot(BuiltinThenableJobSlot_Thenable).toObject());
- assertSameCompartment(cx, promise, thenable);
+ cx->check(promise, thenable);
MOZ_ASSERT(promise->is());
MOZ_ASSERT(thenable->is());
@@ -1740,7 +1740,7 @@ static MOZ_MUST_USE bool
EnqueuePromiseResolveThenableBuiltinJob(JSContext* cx, HandleObject promiseToResolve,
HandleObject thenable)
{
- assertSameCompartment(cx, promiseToResolve, thenable);
+ cx->check(promiseToResolve, thenable);
MOZ_ASSERT(promiseToResolve->is());
MOZ_ASSERT(thenable->is());
@@ -2156,7 +2156,7 @@ js::GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises)
#ifdef DEBUG
for (size_t i = 0, len = promises.length(); i < len; i++) {
JSObject* obj = promises[i];
- assertSameCompartment(cx, obj);
+ cx->check(obj);
MOZ_ASSERT(UncheckedUnwrap(obj)->is());
}
#endif
@@ -2285,9 +2285,9 @@ RunResolutionFunction(JSContext *cx, HandleObject resolutionFun, HandleValue res
// subclass constructor passes null/undefined to `super()`.)
// There are also reactions where the Promise itself is missing. For
// those, there's nothing left to do here.
- assertSameCompartment(cx, resolutionFun);
- assertSameCompartment(cx, result);
- assertSameCompartment(cx, promiseObj);
+ cx->check(resolutionFun);
+ cx->check(result);
+ cx->check(promiseObj);
if (resolutionFun) {
RootedValue calleeOrRval(cx, ObjectValue(*resolutionFun));
return Call(cx, calleeOrRval, UndefinedHandleValue, result, &calleeOrRval);
@@ -3080,12 +3080,12 @@ NewReactionRecord(JSContext* cx, Handle resultCapability,
if (!reaction)
return nullptr;
- assertSameCompartment(cx, resultCapability.promise());
- assertSameCompartment(cx, onFulfilled);
- assertSameCompartment(cx, onRejected);
- assertSameCompartment(cx, resultCapability.resolve());
- assertSameCompartment(cx, resultCapability.reject());
- assertSameCompartment(cx, incumbentGlobalObject);
+ cx->check(resultCapability.promise());
+ cx->check(onFulfilled);
+ cx->check(onRejected);
+ cx->check(resultCapability.resolve());
+ cx->check(resultCapability.reject());
+ cx->check(incumbentGlobalObject);
reaction->setFixedSlot(ReactionRecordSlot_Promise,
ObjectOrNullValue(resultCapability.promise()));
@@ -3160,7 +3160,7 @@ static MOZ_MUST_USE bool
OriginalPromiseThenWithoutSettleHandlers(JSContext* cx, Handle promise,
Handle promiseToResolve)
{
- assertSameCompartment(cx, promise);
+ cx->check(promise);
// Steps 3-4.
Rooted resultCapability(cx);
@@ -3187,7 +3187,7 @@ static bool
OriginalPromiseThenBuiltin(JSContext* cx, HandleValue promiseVal, HandleValue onFulfilled,
HandleValue onRejected, MutableHandleValue rval, bool rvalUsed)
{
- assertSameCompartment(cx, promiseVal, onFulfilled, onRejected);
+ cx->check(promiseVal, onFulfilled, onRejected);
MOZ_ASSERT(CanCallOriginalPromiseThenBuiltin(cx, promiseVal));
Rooted promise(cx, &promiseVal.toObject().as());
diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp
index e6a44c4af1f4..79696d3d21e4 100644
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -186,7 +186,7 @@ CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
// If we already have a RegExpShared for this pattern/flags, we can
// avoid the much slower CheckPatternSyntaxSlow call.
- if (RegExpShared* shared = cx->zone()->regExps.maybeGet(pattern, flags)) {
+ if (RegExpShared* shared = cx->zone()->regExps().maybeGet(pattern, flags)) {
#ifdef DEBUG
// Assert the pattern is valid.
if (!CheckPatternSyntaxSlow(cx, pattern, flags)) {
@@ -202,7 +202,7 @@ CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
// Allocate and return a new RegExpShared so we will hit the fast path
// next time.
- return cx->zone()->regExps.get(cx, pattern, flags);
+ return cx->zone()->regExps().get(cx, pattern, flags);
}
/*
diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
index f9ba87cffbd4..1db760b8c4fc 100644
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -205,6 +205,22 @@ GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp)
if (!JS_SetProperty(cx, info, "arm64-simulator", value))
return false;
+#ifdef JS_SIMULATOR_MIPS32
+ value = BooleanValue(true);
+#else
+ value = BooleanValue(false);
+#endif
+ if (!JS_SetProperty(cx, info, "mips32-simulator", value))
+ return false;
+
+#ifdef JS_SIMULATOR_MIPS64
+ value = BooleanValue(true);
+#else
+ value = BooleanValue(false);
+#endif
+ if (!JS_SetProperty(cx, info, "mips64-simulator", value))
+ return false;
+
#ifdef MOZ_ASAN
value = BooleanValue(true);
#else
@@ -4397,96 +4413,6 @@ SetRNGState(JSContext* cx, unsigned argc, Value* vp)
}
#endif
-static ModuleEnvironmentObject*
-GetModuleEnvironment(JSContext* cx, HandleModuleObject module)
-{
- // Use the initial environment so that tests can check bindings exists
- // before they have been instantiated.
- RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
- MOZ_ASSERT(env);
- return env;
-}
-
-static bool
-GetModuleEnvironmentNames(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
- if (args.length() != 1) {
- JS_ReportErrorASCII(cx, "Wrong number of arguments");
- return false;
- }
-
- if (!args[0].isObject() || !args[0].toObject().is()) {
- JS_ReportErrorASCII(cx, "First argument should be a ModuleObject");
- return false;
- }
-
- RootedModuleObject module(cx, &args[0].toObject().as());
- if (module->hadEvaluationError()) {
- JS_ReportErrorASCII(cx, "Module environment unavailable");
- return false;
- }
-
- RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, module));
- Rooted ids(cx, IdVector(cx));
- if (!JS_Enumerate(cx, env, &ids))
- return false;
-
- uint32_t length = ids.length();
- RootedArrayObject array(cx, NewDenseFullyAllocatedArray(cx, length));
- if (!array)
- return false;
-
- array->setDenseInitializedLength(length);
- for (uint32_t i = 0; i < length; i++)
- array->initDenseElement(i, StringValue(JSID_TO_STRING(ids[i])));
-
- args.rval().setObject(*array);
- return true;
-}
-
-static bool
-GetModuleEnvironmentValue(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
- if (args.length() != 2) {
- JS_ReportErrorASCII(cx, "Wrong number of arguments");
- return false;
- }
-
- if (!args[0].isObject() || !args[0].toObject().is()) {
- JS_ReportErrorASCII(cx, "First argument should be a ModuleObject");
- return false;
- }
-
- if (!args[1].isString()) {
- JS_ReportErrorASCII(cx, "Second argument should be a string");
- return false;
- }
-
- RootedModuleObject module(cx, &args[0].toObject().as());
- if (module->hadEvaluationError()) {
- JS_ReportErrorASCII(cx, "Module environment unavailable");
- return false;
- }
-
- RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, module));
- RootedString name(cx, args[1].toString());
- RootedId id(cx);
- if (!JS_StringToId(cx, name, &id))
- return false;
-
- if (!GetProperty(cx, env, env, id, args.rval()))
- return false;
-
- if (args.rval().isMagic(JS_UNINITIALIZED_LEXICAL)) {
- ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, id);
- return false;
- }
-
- return true;
-}
-
#ifdef DEBUG
static const char*
AssertionTypeToString(irregexp::RegExpAssertion::AssertionType type)
@@ -6002,14 +5928,6 @@ gc::ZealModeHelpText),
" Set this compartment's RNG state.\n"),
#endif
- JS_FN_HELP("getModuleEnvironmentNames", GetModuleEnvironmentNames, 1, 0,
-"getModuleEnvironmentNames(module)",
-" Get the list of a module environment's bound names for a specified module.\n"),
-
- JS_FN_HELP("getModuleEnvironmentValue", GetModuleEnvironmentValue, 2, 0,
-"getModuleEnvironmentValue(module, name)",
-" Get the value of a bound name in a module environment.\n"),
-
#if defined(FUZZING) && defined(__AFL_COMPILER)
JS_FN_HELP("aflloop", AflLoop, 1, 0,
"aflloop(max_cnt)",
diff --git a/js/src/builtin/WeakMapObject.cpp b/js/src/builtin/WeakMapObject.cpp
index b1d74bb50dd2..490484df85c4 100644
--- a/js/src/builtin/WeakMapObject.cpp
+++ b/js/src/builtin/WeakMapObject.cpp
@@ -204,7 +204,7 @@ JS::GetWeakMapEntry(JSContext* cx, HandleObject mapObj, HandleObject key,
MutableHandleValue rval)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, key);
+ cx->check(key);
rval.setUndefined();
ObjectValueMap* map = mapObj->as().getMap();
if (!map)
@@ -223,7 +223,7 @@ JS::SetWeakMapEntry(JSContext* cx, HandleObject mapObj, HandleObject key,
HandleValue val)
{
CHECK_REQUEST(cx);
- assertSameCompartment(cx, key, val);
+ cx->check(key, val);
Handle rootedMap = mapObj.as();
return WeakCollectionPutEntryInternal(cx, rootedMap, key, val);
}
diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js
index 7797febb3051..b46fed1e0595 100644
--- a/js/src/devtools/rootAnalysis/analyzeRoots.js
+++ b/js/src/devtools/rootAnalysis/analyzeRoots.js
@@ -222,6 +222,9 @@ function edgeUsesVariable(edge, variable, body)
case "Loop":
return 0;
+ case "Assembly":
+ return 0;
+
default:
assert(false);
}
diff --git a/js/src/devtools/rootAnalysis/computeCallgraph.js b/js/src/devtools/rootAnalysis/computeCallgraph.js
index 8d27601de45d..0e0ae47b16d3 100644
--- a/js/src/devtools/rootAnalysis/computeCallgraph.js
+++ b/js/src/devtools/rootAnalysis/computeCallgraph.js
@@ -176,20 +176,9 @@ function process(functionName, functionBodies)
if (markerPos > 0) {
var inChargeXTor = functionName.replace(internalMarker, "");
print("D " + memo(inChargeXTor) + " " + memo(functionName));
-
- // Bug 1056410: Oh joy. GCC does something even funkier internally,
- // where it generates calls to ~Foo() but a body for ~Foo(int32) even
- // though it uses the same mangled name for both. So we need to add a
- // synthetic edge from ~Foo() -> ~Foo(int32).
- //
- // inChargeXTor will have the (int32).
- if (functionName.indexOf("::~") > 0) {
- var calledDestructor = inChargeXTor.replace("(int32)", "()");
- print("D " + memo(calledDestructor) + " " + memo(inChargeXTor));
- }
}
- // Further note: from http://mentorembedded.github.io/cxx-abi/abi.html the
+ // Further note: from https://itanium-cxx-abi.github.io/cxx-abi/abi.html the
// different kinds of constructors/destructors are:
// C1 # complete object constructor
// C2 # base object constructor
@@ -210,18 +199,35 @@ function process(functionName, functionBodies)
// inject an edge to it from C1, C2, and C3 (or D1, D2, and D3). (Note that
// C3 isn't even used in current GCC, but add the edge anyway just in
// case.)
- if (functionName.indexOf("C4E") != -1 || functionName.indexOf("D4Ev") != -1) {
+ //
+ // from gcc/cp/mangle.c:
+ //
+ // ::= D0 # deleting (in-charge) destructor
+ // ::= D1 # complete object (in-charge) destructor
+ // ::= D2 # base object (not-in-charge) destructor
+ // ::= C1 # complete object constructor
+ // ::= C2 # base object constructor
+ // ::= C3 # complete object allocating constructor
+ //
+ // Currently, allocating constructors are never used.
+ //
+ if (functionName.indexOf("C4") != -1) {
var [ mangled, unmangled ] = splitFunction(functionName);
// E terminates the method name (and precedes the method parameters).
// If eg "C4E" shows up in the mangled name for another reason, this
- // will create bogus edges in the callgraph. But will affect little and
- // is somewhat difficult to avoid, so we will live with it.
- for (let [synthetic, variant] of [['C4E', 'C1E'],
- ['C4E', 'C2E'],
- ['C4E', 'C3E'],
- ['D4Ev', 'D1Ev'],
- ['D4Ev', 'D2Ev'],
- ['D4Ev', 'D3Ev']])
+ // will create bogus edges in the callgraph. But it will affect little
+ // and is somewhat difficult to avoid, so we will live with it.
+ //
+ // Another possibility! A templatized constructor will contain C4I...E
+ // for template arguments.
+ //
+ for (let [synthetic, variant] of [
+ ['C4E', 'C1E'],
+ ['C4E', 'C2E'],
+ ['C4E', 'C3E'],
+ ['C4I', 'C1I'],
+ ['C4I', 'C2I'],
+ ['C4I', 'C3I']])
{
if (mangled.indexOf(synthetic) == -1)
continue;
@@ -231,6 +237,30 @@ function process(functionName, functionBodies)
print("D " + memo(variant_full) + " " + memo(functionName));
}
}
+
+ // For destructors:
+ //
+ // I've never seen D4Ev() + D4Ev(int32), only one or the other. So
+ // for a D4Ev of any sort, create:
+ //
+ // D0() -> D1() # deleting destructor calls complete destructor, then deletes
+ // D1() -> D2() # complete destructor calls base destructor, then destroys virtual bases
+ // D2() -> D4(?) # base destructor might be aliased to unified destructor
+ // # use whichever one is defined, in-charge or not.
+ // # ('?') means either () or (int32).
+ //
+ // Note that this doesn't actually make sense -- D0 and D1 should be
+ // in-charge, but gcc doesn't seem to give them the in-charge parameter?!
+ //
+ if (functionName.indexOf("D4Ev") != -1 && functionName.indexOf("::~") != -1) {
+ const not_in_charge_dtor = functionName.replace("(int32)", "()");
+ const D0 = not_in_charge_dtor.replace("D4Ev", "D0Ev");
+ const D1 = not_in_charge_dtor.replace("D4Ev", "D1Ev");
+ const D2 = not_in_charge_dtor.replace("D4Ev", "D2Ev");
+ print("D " + memo(D0) + " " + memo(D1));
+ print("D " + memo(D1) + " " + memo(D2));
+ print("D " + memo(D2) + " " + memo(functionName));
+ }
}
for (var nameIndex = minStream; nameIndex <= maxStream; nameIndex++) {
diff --git a/js/src/devtools/rootAnalysis/computeGCTypes.js b/js/src/devtools/rootAnalysis/computeGCTypes.js
index 337adfabfed9..db4419a941fa 100644
--- a/js/src/devtools/rootAnalysis/computeGCTypes.js
+++ b/js/src/devtools/rootAnalysis/computeGCTypes.js
@@ -15,6 +15,7 @@ var typeInfo = {
'NonGCPointers': {},
'RootedGCThings': {},
'RootedPointers': {},
+ 'RootedBases': {'JS::AutoGCRooter': true},
// RAII types within which we should assume GC is suppressed, eg
// AutoSuppressGC.
@@ -36,6 +37,26 @@ var rootedPointers = {};
function processCSU(csu, body)
{
+ for (let { 'Name': [ annType, tag ] } of (body.Annotation || [])) {
+ if (annType != 'Tag')
+ continue;
+
+ if (tag == 'GC Pointer')
+ typeInfo.GCPointers.push(csu);
+ else if (tag == 'Invalidated by GC')
+ typeInfo.GCPointers.push(csu);
+ else if (tag == 'GC Thing')
+ typeInfo.GCThings.push(csu);
+ else if (tag == 'Suppressed GC Pointer')
+ typeInfo.NonGCPointers[csu] = true;
+ else if (tag == 'Rooted Pointer')
+ typeInfo.RootedPointers[csu] = true;
+ else if (tag == 'Rooted Base')
+ typeInfo.RootedBases[csu] = true;
+ else if (tag == 'Suppress GC')
+ typeInfo.GCSuppressors[csu] = true;
+ }
+
for (let { 'Base': base } of (body.CSUBaseClass || []))
addBaseClass(csu, base);
@@ -52,31 +73,8 @@ function processCSU(csu, body)
if (target.Kind == "CSU")
addNestedStructure(csu, target.Name, fieldName);
}
- if (type.Kind == "CSU") {
- // Ignore nesting in classes which are AutoGCRooters. We only consider
- // types with fields that may not be properly rooted.
- if (type.Name == "JS::AutoGCRooter" || type.Name == "JS::CustomAutoRooter")
- return;
+ if (type.Kind == "CSU")
addNestedStructure(csu, type.Name, fieldName);
- }
- }
-
- for (let { 'Name': [ annType, tag ] } of (body.Annotation || [])) {
- if (annType != 'Tag')
- continue;
-
- if (tag == 'GC Pointer')
- typeInfo.GCPointers.push(csu);
- else if (tag == 'Invalidated by GC')
- typeInfo.GCPointers.push(csu);
- else if (tag == 'GC Thing')
- typeInfo.GCThings.push(csu);
- else if (tag == 'Suppressed GC Pointer')
- typeInfo.NonGCPointers[csu] = true;
- else if (tag == 'Rooted Pointer')
- typeInfo.RootedPointers[csu] = true;
- else if (tag == 'Suppress GC')
- typeInfo.GCSuppressors[csu] = true;
}
}
@@ -86,6 +84,8 @@ function addNestedStructure(csu, inner, field)
if (!(inner in structureParents))
structureParents[inner] = [];
+ // Skip fields that are really base classes, to avoid duplicating the base
+ // fields; addBaseClass already added a "base-N" name.
if (field.match(/^field:\d+$/) && (csu in baseClasses) && (baseClasses[csu].indexOf(inner) != -1))
return;
@@ -140,6 +140,16 @@ for (const csu of typeInfo.GCThings)
for (const csu of typeInfo.GCPointers)
addGCPointer(csu);
+// Everything that inherits from a "Rooted Base" is considered to be rooted.
+// This is for things like CustomAutoRooter and its subclasses.
+var basework = Object.keys(typeInfo.RootedBases);
+while (basework.length) {
+ const base = basework.pop();
+ typeInfo.RootedPointers[base] = true;
+ if (base in subClasses)
+ basework.push(...subClasses[base]);
+}
+
// "typeName is a (pointer to a)^'typePtrLevel' GC type because it contains a field
// named 'child' of type 'why' (or pointer to 'why' if fieldPtrLevel == 1), which is
// itself a GCThing or GCPointer."
@@ -230,7 +240,7 @@ function addGCPointer(typeName)
// Call a function for a type and every type that contains the type in a field
// or as a base class (which internally is pretty much the same thing --
-// sublcasses are structs beginning with the base class and adding on their
+// subclasses are structs beginning with the base class and adding on their
// local fields.)
function foreachContainingStruct(typeName, func, seen = new Set())
{
diff --git a/js/src/ds/LifoAlloc.cpp b/js/src/ds/LifoAlloc.cpp
index 9a4780fe88b8..a6edc9a5e9d2 100644
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -41,15 +41,6 @@ BumpChunk::newWithCapacity(size_t size, bool protect)
return result;
}
-bool
-BumpChunk::canAlloc(size_t n)
-{
- uint8_t* aligned = AlignPtr(bump_);
- uint8_t* newBump = aligned + n;
- // bump_ <= newBump, is necessary to catch overflow.
- return bump_ <= newBump && newBump <= capacity_;
-}
-
#ifdef LIFO_CHUNK_PROTECT
static const uint8_t*
@@ -186,25 +177,25 @@ LifoAlloc::newChunkWithCapacity(size_t n)
MOZ_ASSERT(fallibleScope_, "[OOM] Cannot allocate a new chunk in an infallible scope.");
// Compute the size which should be requested in order to be able to fit |n|
- // bytes in the newly allocated chunk, or default the |defaultChunkSize_|.
- size_t defaultChunkFreeSpace = defaultChunkSize_ - detail::BumpChunkReservedSpace;
- size_t chunkSize;
- if (n > defaultChunkFreeSpace) {
- MOZ_ASSERT(defaultChunkFreeSpace < defaultChunkSize_);
- size_t allocSizeWithCanaries = n + (defaultChunkSize_ - defaultChunkFreeSpace);
+ // bytes in a newly allocated chunk, or default to |defaultChunkSize_|.
+ uint8_t* u8begin = nullptr;
+ uint8_t* u8end = u8begin + detail::BumpChunkReservedSpace;
+ u8end = detail::BumpChunk::nextAllocEnd(detail::BumpChunk::nextAllocBase(u8end), n);
+ size_t allocSizeWithCanaries = u8end - u8begin;
- // Guard for overflow.
- if (allocSizeWithCanaries < n ||
- (allocSizeWithCanaries & (size_t(1) << (BitSize::value - 1))))
- {
- return nullptr;
- }
-
- chunkSize = RoundUpPow2(allocSizeWithCanaries);
- } else {
- chunkSize = defaultChunkSize_;
+ // Guard for overflow.
+ if (allocSizeWithCanaries < n ||
+ (allocSizeWithCanaries & (size_t(1) << (BitSize::value - 1))))
+ {
+ return nullptr;
}
+ size_t chunkSize;
+ if (allocSizeWithCanaries > defaultChunkSize_)
+ chunkSize = RoundUpPow2(allocSizeWithCanaries);
+ else
+ chunkSize = defaultChunkSize_;
+
bool protect = false;
#ifdef LIFO_CHUNK_PROTECT
protect = protect_;
diff --git a/js/src/ds/LifoAlloc.h b/js/src/ds/LifoAlloc.h
index 739e646563e0..6a9fc416c025 100644
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -224,7 +224,7 @@ class BumpChunk : public SingleLinkedListElement
static constexpr uintptr_t magicNumber = uintptr_t(0x4c6966);
#endif
-#if defined(DEBUG) || defined(MOZ_ASAN)
+#if defined(DEBUG)
# define LIFO_CHUNK_PROTECT 1
#endif
@@ -250,6 +250,7 @@ class BumpChunk : public SingleLinkedListElement
do { \
uint8_t* base = (addr); \
size_t sz = (size); \
+ MOZ_MAKE_MEM_UNDEFINED(base, sz); \
memset(base, undefinedChunkMemory, sz); \
MOZ_MAKE_MEM_NOACCESS(base, sz); \
} while (0)
@@ -269,6 +270,13 @@ class BumpChunk : public SingleLinkedListElement
# define LIFO_MAKE_MEM_UNDEFINED(addr, size) MOZ_MAKE_MEM_UNDEFINED((addr), (size))
#endif
+#ifdef LIFO_HAVE_MEM_CHECKS
+ // Red zone reserved after each allocation.
+ static constexpr size_t RedZoneSize = 16;
+#else
+ static constexpr size_t RedZoneSize = 0;
+#endif
+
void assertInvariants() {
MOZ_DIAGNOSTIC_ASSERT(magic_ == magicNumber);
MOZ_ASSERT(begin() <= end());
@@ -319,10 +327,15 @@ class BumpChunk : public SingleLinkedListElement
MOZ_ASSERT(newBump <= capacity_);
#if defined(LIFO_HAVE_MEM_CHECKS)
// Poison/Unpoison memory that we just free'd/allocated.
- if (bump_ > newBump)
+ if (bump_ > newBump) {
LIFO_MAKE_MEM_NOACCESS(newBump, bump_ - newBump);
- else if (newBump > bump_)
- LIFO_MAKE_MEM_UNDEFINED(bump_, newBump - bump_);
+ } else if (newBump > bump_) {
+ MOZ_ASSERT(newBump - RedZoneSize >= bump_);
+ LIFO_MAKE_MEM_UNDEFINED(bump_, newBump - RedZoneSize - bump_);
+ // The area [newBump - RedZoneSize .. newBump[ is already flagged as
+ // no-access either with the previous if-branch or with the
+ // BumpChunk constructor. No need to mark it twice.
+ }
#endif
bump_ = newBump;
}
@@ -417,13 +430,27 @@ class BumpChunk : public SingleLinkedListElement
setBump(m.bump_);
}
+ // Given a bump chunk pointer, find the next base/end pointers. This is
+ // useful for having consistent allocations, and iterating over known size
+ // allocations.
+ static uint8_t* nextAllocBase(uint8_t* e) {
+ return detail::AlignPtr(e);
+ }
+ static uint8_t* nextAllocEnd(uint8_t* b, size_t n) {
+ return b + n + RedZoneSize;
+ }
+
// Returns true, if the unused space is large enough for an allocation of
// |n| bytes.
- bool canAlloc(size_t n);
+ bool canAlloc(size_t n) const {
+ uint8_t* newBump = nextAllocEnd(nextAllocBase(end()), n);
+ // bump_ <= newBump, is necessary to catch overflow.
+ return bump_ <= newBump && newBump <= capacity_;
+ }
// Space remaining in the current chunk.
size_t unused() const {
- uint8_t* aligned = AlignPtr(end());
+ uint8_t* aligned = nextAllocBase(end());
if (aligned < capacity_)
return capacity_ - aligned;
return 0;
@@ -432,8 +459,8 @@ class BumpChunk : public SingleLinkedListElement
// Try to perform an allocation of size |n|, returns nullptr if not possible.
MOZ_ALWAYS_INLINE
void* tryAlloc(size_t n) {
- uint8_t* aligned = AlignPtr(end());
- uint8_t* newBump = aligned + n;
+ uint8_t* aligned = nextAllocBase(end());
+ uint8_t* newBump = nextAllocEnd(aligned, n);
if (newBump > capacity_)
return nullptr;
@@ -903,15 +930,15 @@ class LifoAlloc
uint8_t* seekBaseAndAdvanceBy(size_t size) {
MOZ_ASSERT(!empty());
- uint8_t* aligned = detail::AlignPtr(head_);
- if (aligned + size > chunkIt_->end()) {
+ uint8_t* aligned = detail::BumpChunk::nextAllocBase(head_);
+ if (detail::BumpChunk::nextAllocEnd(aligned, size) > chunkIt_->end()) {
++chunkIt_;
aligned = chunkIt_->begin();
// The current code assumes that if we have a chunk, then we
// have allocated something it in.
MOZ_ASSERT(!chunkIt_->empty());
}
- head_ = aligned + size;
+ head_ = detail::BumpChunk::nextAllocEnd(aligned, size);
MOZ_ASSERT(head_ <= chunkIt_->end());
return aligned;
}
diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
index 83dc5799a744..0bf06defc8a7 100644
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -26,7 +26,6 @@
#endif
#include "vm/Debugger.h"
#include "vm/EnvironmentObject.h"
-#include "vm/RegExpObject.h"
#include "vm/RegExpShared.h"
#include "vm/Scope.h"
#include "vm/Shape.h"
diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp
index 934eb15651d3..8334df462662 100644
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -116,6 +116,10 @@ JS_FOR_EACH_TRACEKIND(TRACE_ROOTS)
#undef TRACE_ROOTS
TracePersistentRootedList(trc, heapRoots.ref()[JS::RootKind::Id], "persistent-id");
TracePersistentRootedList(trc, heapRoots.ref()[JS::RootKind::Value], "persistent-value");
+
+ // ConcreteTraceable calls through a function pointer.
+ JS::AutoSuppressGCAnalysis nogc;
+
TracePersistentRootedList(
trc, heapRoots.ref()[JS::RootKind::Traceable], "persistent-traceable");
}
@@ -391,6 +395,9 @@ js::gc::GCRuntime::traceRuntimeCommon(JSTracer* trc, TraceOrMarkRuntime traceOrM
if (!JS::RuntimeHeapIsMinorCollecting()) {
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK_EMBEDDING);
+ // The analysis doesn't like the function pointers below.
+ JS::AutoSuppressGCAnalysis nogc;
+
/*
* The embedding can register additional roots here.
*
diff --git a/js/src/gc/WeakMap.h b/js/src/gc/WeakMap.h
index 176482fb0e88..f253985799a5 100644
--- a/js/src/gc/WeakMap.h
+++ b/js/src/gc/WeakMap.h
@@ -11,6 +11,7 @@
#include "gc/Barrier.h"
#include "gc/DeletePolicy.h"
+#include "gc/Zone.h"
#include "js/HashTable.h"
namespace JS {
diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
index 6f30f049c639..725f73f0d09d 100644
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -43,7 +43,6 @@ JS::Zone::Zone(JSRuntime* rt)
weakCaches_(this),
gcWeakKeys_(this, SystemAllocPolicy(), rt->randomHashCodeScrambler()),
typeDescrObjects_(this, this),
- regExps(this),
markedAtoms_(this),
atomCache_(this),
externalStringCache_(this),
@@ -97,7 +96,7 @@ Zone::~Zone()
// if the embedding leaked GC things.
if (!rt->gc.shutdownCollectedEverything()) {
gcWeakMapList().clear();
- regExps.clear();
+ regExps().clear();
}
#endif
}
@@ -106,7 +105,8 @@ bool
Zone::init(bool isSystemArg)
{
isSystem = isSystemArg;
- return gcWeakKeys().init();
+ regExps_.ref() = make_unique(this);
+ return regExps_.ref() && gcWeakKeys().init();
}
void
@@ -357,7 +357,7 @@ Zone::nextZone() const
void
Zone::clearTables()
{
- MOZ_ASSERT(regExps.empty());
+ MOZ_ASSERT(regExps().empty());
baseShapes().clear();
initialShapes().clear();
diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
index c6afaf7f4d5e..61f03330934b 100644
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -14,12 +14,12 @@
#include "gc/GCRuntime.h"
#include "js/GCHashTable.h"
#include "vm/MallocProvider.h"
-#include "vm/RegExpShared.h"
#include "vm/Runtime.h"
namespace js {
class Debugger;
+class RegExpZone;
namespace jit {
class JitZone;
@@ -459,8 +459,10 @@ class Zone : public JS::shadow::Zone,
counter.recordTrigger(trigger);
}
+ js::MainThreadData> regExps_;
+
public:
- js::RegExpZone regExps;
+ js::RegExpZone& regExps() { return *regExps_.ref(); }
JS::WeakCache& typeDescrObjects() { return typeDescrObjects_.ref(); }
@@ -755,47 +757,50 @@ class Zone : public JS::shadow::Zone,
namespace js {
-template
-inline T*
-ZoneAllocPolicy::maybe_pod_malloc(size_t numElems)
+/*
+ * Allocation policy that uses Zone::pod_malloc and friends, so that memory
+ * pressure is accounted for on the zone. This is suitable for memory associated
+ * with GC things allocated in the zone.
+ *
+ * Since it doesn't hold a JSContext (those may not live long enough), it can't
+ * report out-of-memory conditions itself; the caller must check for OOM and
+ * take the appropriate action.
+ *
+ * FIXME bug 647103 - replace these *AllocPolicy names.
+ */
+class ZoneAllocPolicy
{
- return zone->maybe_pod_malloc(numElems);
-}
+ JS::Zone* const zone;
-template
-inline T*
-ZoneAllocPolicy::maybe_pod_calloc(size_t numElems)
-{
- return zone->maybe_pod_calloc(numElems);
-}
+ public:
+ MOZ_IMPLICIT ZoneAllocPolicy(JS::Zone* z) : zone(z) {}
-template
-inline T*
-ZoneAllocPolicy::maybe_pod_realloc(T* p, size_t oldSize, size_t newSize)
-{
- return zone->maybe_pod_realloc(p, oldSize, newSize);
-}
+ template T* maybe_pod_malloc(size_t numElems) {
+ return zone->maybe_pod_malloc(numElems);
+ }
+ template T* maybe_pod_calloc(size_t numElems) {
+ return zone->maybe_pod_calloc(numElems);
+ }
+ template T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) {
+ return zone->maybe_pod_realloc(p, oldSize, newSize);
+ }
+ template T* pod_malloc(size_t numElems) {
+ return zone->pod_malloc(numElems);
+ }
+ template T* pod_calloc(size_t numElems) {
+ return zone->pod_calloc(numElems);
+ }
+ template T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
+ return zone->pod_realloc(p, oldSize, newSize);
+ }
-template
-inline T*
-ZoneAllocPolicy::pod_malloc(size_t numElems)
-{
- return zone->pod_malloc(numElems);
-}
+ template void free_(T* p, size_t numElems = 0) { js_free(p); }
+ void reportAllocOverflow() const {}
-template
-inline T*
-ZoneAllocPolicy::pod_calloc(size_t numElems)
-{
- return zone->pod_calloc(numElems);
-}
-
-template
-inline T*
-ZoneAllocPolicy::pod_realloc(T* p, size_t oldSize, size_t newSize)
-{
- return zone->pod_realloc(p, oldSize, newSize);
-}
+ MOZ_MUST_USE bool checkSimulatedOOM() const {
+ return !js::oom::ShouldFailWithOOM();
+ }
+};
} // namespace js
diff --git a/js/src/jit-test/tests/basic/bug1470732.js b/js/src/jit-test/tests/basic/bug1470732.js
index 05fdbd1e87c8..378cac012942 100644
--- a/js/src/jit-test/tests/basic/bug1470732.js
+++ b/js/src/jit-test/tests/basic/bug1470732.js
@@ -7,6 +7,6 @@ while(i++ < 500) {
assertFloat32(0x23456789 | 0, false);
`);
let m = parseModule("");
- m.declarationInstantiation();
+ instantiateModule(m);
}
diff --git a/js/src/jit-test/tests/basic/write-frozen-dense-strict-inlinecache.js b/js/src/jit-test/tests/basic/write-frozen-dense-strict-inlinecache.js
index bdd8d055fd25..abb620c6eb9f 100644
--- a/js/src/jit-test/tests/basic/write-frozen-dense-strict-inlinecache.js
+++ b/js/src/jit-test/tests/basic/write-frozen-dense-strict-inlinecache.js
@@ -1,4 +1,4 @@
-// |jit-test| --no-threads; --ion-eager; --ion-shared-stubs=off
+// |jit-test| --no-threads; --ion-eager;
setJitCompilerOption('ion.forceinlineCaches', 1);
function foo(t) {
"use strict";
diff --git a/js/src/jit-test/tests/debug/RematerializedFrame-retval.js b/js/src/jit-test/tests/debug/RematerializedFrame-retval.js
index ce16404d1f6c..764f91b12bdf 100644
--- a/js/src/jit-test/tests/debug/RematerializedFrame-retval.js
+++ b/js/src/jit-test/tests/debug/RematerializedFrame-retval.js
@@ -32,8 +32,8 @@ loadFile(lfLogBuffer);
function loadFile(lfVarx) {
try {
let m = parseModule(lfVarx);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
} catch (lfVare) {}
}
diff --git a/js/src/jit-test/tests/debug/bug1304553.js b/js/src/jit-test/tests/debug/bug1304553.js
index 08a97d909705..42c445e12b4b 100644
--- a/js/src/jit-test/tests/debug/bug1304553.js
+++ b/js/src/jit-test/tests/debug/bug1304553.js
@@ -17,5 +17,5 @@ let m = parseModule(`
f(i);
actual;
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/debug/bug1363233.js b/js/src/jit-test/tests/debug/bug1363233.js
new file mode 100644
index 000000000000..5db1ef6931e0
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug1363233.js
@@ -0,0 +1,14 @@
+// |jit-test| error: SyntaxError;
+g = newGlobal();
+dbg = new Debugger;
+setInterruptCallback(function () {
+ dbg.addDebuggee(g);
+ dbg.getNewestFrame();
+ return true;
+});
+g.eval("" + function f() {
+ for (var i = 0; i < 1; evaluate("class h { constructor() {} }")) {
+ interruptIf(1);
+ }
+});
+g.f();
diff --git a/js/src/jit-test/tests/for-of/bug-1341339.js b/js/src/jit-test/tests/for-of/bug-1341339.js
index 1f88acdafaa5..2a0cf1f49840 100644
--- a/js/src/jit-test/tests/for-of/bug-1341339.js
+++ b/js/src/jit-test/tests/for-of/bug-1341339.js
@@ -5,5 +5,5 @@ for (var i=0; i < 10000; ++i) {
for (var x of iterator) {}
}
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/gc/bug-1282986.js b/js/src/jit-test/tests/gc/bug-1282986.js
index 5c2c3ab67ce7..879731ece47b 100644
--- a/js/src/jit-test/tests/gc/bug-1282986.js
+++ b/js/src/jit-test/tests/gc/bug-1282986.js
@@ -11,7 +11,7 @@ loadFile(lfLogBuffer);
function loadFile(lfVarx) {
oomTest(function() {
let m = parseModule(lfVarx);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
});
}
diff --git a/js/src/jit-test/tests/ion/bug1269756.js b/js/src/jit-test/tests/ion/bug1269756.js
index 5555e5f14d68..d93ce58f4d13 100644
--- a/js/src/jit-test/tests/ion/bug1269756.js
+++ b/js/src/jit-test/tests/ion/bug1269756.js
@@ -3,6 +3,6 @@ if (!('oomTest' in this))
oomTest(function() {
m = parseModule(`while (x && NaN) prototype; let x`);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
})
diff --git a/js/src/jit-test/tests/modules/ambiguous-star-export.js b/js/src/jit-test/tests/modules/ambiguous-star-export.js
index 94aa7ac4af2c..cc6b796cd6e1 100644
--- a/js/src/jit-test/tests/modules/ambiguous-star-export.js
+++ b/js/src/jit-test/tests/modules/ambiguous-star-export.js
@@ -7,21 +7,21 @@ load(libdir + "dummyModuleResolveHook.js");
function checkModuleEval(source) {
let m = parseModule(source);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
return m;
}
function checkModuleSyntaxError(source) {
let m = parseModule(source);
- assertThrowsInstanceOf(() => m.declarationInstantiation(), SyntaxError);
+ assertThrowsInstanceOf(() => instantiateModule(m), SyntaxError);
}
let a = moduleRepo['a'] = parseModule("export var a = 1; export var b = 2;");
let b = moduleRepo['b'] = parseModule("export var b = 3; export var c = 4;");
let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
-c.declarationInstantiation();
-c.evaluation();
+instantiateModule(c);
+evaluateModule(c);
// Check importing/exporting non-ambiguous name works.
let d = checkModuleEval("import { a } from 'c';");
@@ -34,9 +34,9 @@ checkModuleSyntaxError("export { b } from 'c';");
// Check that namespace objects include only non-ambiguous names.
let m = parseModule("import * as ns from 'c';");
-m.declarationInstantiation();
-m.evaluation();
-let ns = c.namespace;
+instantiateModule(m);
+evaluateModule(m);
+let ns = getModuleObject(c).namespace;
let names = Object.keys(ns);
assertEq(names.length, 2);
assertEq('a' in ns, true);
diff --git a/js/src/jit-test/tests/modules/bad-namespace-created.js b/js/src/jit-test/tests/modules/bad-namespace-created.js
index 7d17546a4079..6a323a7ff3a1 100644
--- a/js/src/jit-test/tests/modules/bad-namespace-created.js
+++ b/js/src/jit-test/tests/modules/bad-namespace-created.js
@@ -14,4 +14,4 @@ moduleRepo['D'] = parseModule('export let x');
moduleRepo['E'] = parseModule('export let x');
let m = moduleRepo['A'];
-assertThrowsInstanceOf(() => m.declarationInstantiation(), SyntaxError);
+assertThrowsInstanceOf(() => instantiateModule(m), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/bug-1233915.js b/js/src/jit-test/tests/modules/bug-1233915.js
index cef016f5da4f..2280aa66c0f3 100644
--- a/js/src/jit-test/tests/modules/bug-1233915.js
+++ b/js/src/jit-test/tests/modules/bug-1233915.js
@@ -7,5 +7,5 @@ g.eval("(" + function() {
};
} + ")()");
m = parseModule(` s1 `);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug-1236875.js b/js/src/jit-test/tests/modules/bug-1236875.js
index 41751f947623..c11fb1e5e939 100644
--- a/js/src/jit-test/tests/modules/bug-1236875.js
+++ b/js/src/jit-test/tests/modules/bug-1236875.js
@@ -1,2 +1,2 @@
let m = parseModule(`{ function x() {} }`);
-m.declarationInstantiation();
+instantiateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug-1245518.js b/js/src/jit-test/tests/modules/bug-1245518.js
index 0621d68c2162..d9324c9909ba 100644
--- a/js/src/jit-test/tests/modules/bug-1245518.js
+++ b/js/src/jit-test/tests/modules/bug-1245518.js
@@ -11,5 +11,5 @@ m = parseModule(`
function g() { return this.hours = 0; }
evalInFrame.call(0, 0, "g()")
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug-1247934.js b/js/src/jit-test/tests/modules/bug-1247934.js
index a58d78fe3cc0..4ecc5bcc5a05 100644
--- a/js/src/jit-test/tests/modules/bug-1247934.js
+++ b/js/src/jit-test/tests/modules/bug-1247934.js
@@ -6,4 +6,4 @@ setJitCompilerOption("ion.warmup.trigger", 50);
s = "";
for (i = 0; i < 1024; i++) s += "export let e" + i + "\n";
moduleRepo['a'] = parseModule(s);
-parseModule("import * as ns from 'a'").declarationInstantiation();
+instantiateModule(parseModule("import * as ns from 'a'"));
diff --git a/js/src/jit-test/tests/modules/bug-1283448.js b/js/src/jit-test/tests/modules/bug-1283448.js
index 9ee6217abf79..175711478ee4 100644
--- a/js/src/jit-test/tests/modules/bug-1283448.js
+++ b/js/src/jit-test/tests/modules/bug-1283448.js
@@ -6,5 +6,5 @@ setModuleResolveHook(function(module, specifier) {
});
let a = moduleRepo['a'] = parseModule("var x = 1; export { x };");
let b = moduleRepo['b'] = parseModule("import { x as y } from 'a';");
-a.__proto__ = {15: 1337};
-b.declarationInstantiation();
+getModuleObject(a).__proto__ = {15: 1337};
+instantiateModule(b);
diff --git a/js/src/jit-test/tests/modules/bug-1284486-2.js b/js/src/jit-test/tests/modules/bug-1284486-2.js
index 62d765fd08e1..e9eb252fad28 100644
--- a/js/src/jit-test/tests/modules/bug-1284486-2.js
+++ b/js/src/jit-test/tests/modules/bug-1284486-2.js
@@ -15,7 +15,7 @@ let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
let e1;
let threw = false;
try {
- c.declarationInstantiation();
+ instantiateModule(c);
} catch (exc) {
threw = true;
e1 = exc;
@@ -26,7 +26,7 @@ assertEq(typeof e1 === "undefined", false);
threw = false;
let e2;
try {
- c.declarationInstantiation();
+ instantiateModule(c);
} catch (exc) {
threw = true;
e2 = exc;
diff --git a/js/src/jit-test/tests/modules/bug-1284486.js b/js/src/jit-test/tests/modules/bug-1284486.js
index 61c7cafaa2fe..3a520bbcbbf6 100644
--- a/js/src/jit-test/tests/modules/bug-1284486.js
+++ b/js/src/jit-test/tests/modules/bug-1284486.js
@@ -15,7 +15,7 @@ let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
let e1;
let threw = false;
try {
- c.declarationInstantiation();
+ instantiateModule(c);
} catch (exc) {
threw = true;
e1 = exc;
@@ -28,7 +28,7 @@ let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
threw = false;
try {
- d.declarationInstantiation();
+ instantiateModule(d);
} catch (exc) {
threw = true;
}
diff --git a/js/src/jit-test/tests/modules/bug-1287410.js b/js/src/jit-test/tests/modules/bug-1287410.js
index 0d36fe444ade..4460b5054100 100644
--- a/js/src/jit-test/tests/modules/bug-1287410.js
+++ b/js/src/jit-test/tests/modules/bug-1287410.js
@@ -9,7 +9,7 @@ setModuleResolveHook(function(module, specifier) {
let a = moduleRepo['a'] = parseModule("export var a = 1; export var b = 2;");
let b = moduleRepo['b'] = parseModule("export var b = 3; export var c = 4;");
let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
-c.declarationInstantiation();
+instantiateModule(c);
// Module 'a' is replaced with another module that has not been instantiated.
// This should not happen and would be a bug in the module loader.
@@ -19,5 +19,5 @@ let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
// Attempting to instantiate 'd' throws an error because depdency 'a' of
// instantiated module 'c' is not instantiated.
-d.declarationInstantiation();
-d.evaluation();
+instantiateModule(d);
+evaluateModule(d);
diff --git a/js/src/jit-test/tests/modules/bug-1372258.js b/js/src/jit-test/tests/modules/bug-1372258.js
index ba7dcf2dec0f..16750340a82d 100644
--- a/js/src/jit-test/tests/modules/bug-1372258.js
+++ b/js/src/jit-test/tests/modules/bug-1372258.js
@@ -24,5 +24,5 @@ for (let i = 0; i < count; i++) {
}
let b = moduleRepo['b'] = parseModule(s);
-b.declarationInstantiation();
-b.evaluation();
+instantiateModule(b);
+evaluateModule(b);
diff --git a/js/src/jit-test/tests/modules/bug-1402535.js b/js/src/jit-test/tests/modules/bug-1402535.js
index 5ac2b24031bb..4332f9cf48d3 100644
--- a/js/src/jit-test/tests/modules/bug-1402535.js
+++ b/js/src/jit-test/tests/modules/bug-1402535.js
@@ -3,5 +3,5 @@ if (!('stackTest' in this))
stackTest(function() {
let m = parseModule(``);
- m.declarationInstantiation();
+ instantiateModule(m);
});
diff --git a/js/src/jit-test/tests/modules/bug-1402649.js b/js/src/jit-test/tests/modules/bug-1402649.js
index 2e5487210b51..fec05c1bd107 100644
--- a/js/src/jit-test/tests/modules/bug-1402649.js
+++ b/js/src/jit-test/tests/modules/bug-1402649.js
@@ -4,7 +4,7 @@ if (!('oomTest' in this))
loadFile(`
function parseAndEvaluate(source) {
let m = parseModule(source);
- m.declarationInstantiation();
+ instantiateModule(m);
}
parseAndEvaluate("async function a() { await 2 + 3; }")
`);
diff --git a/js/src/jit-test/tests/modules/bug-1406452.js b/js/src/jit-test/tests/modules/bug-1406452.js
index 7b8325aad723..9be4b7accf4a 100644
--- a/js/src/jit-test/tests/modules/bug-1406452.js
+++ b/js/src/jit-test/tests/modules/bug-1406452.js
@@ -1,5 +1,5 @@
// |jit-test| error: Error
let m = parseModule(`for (var x of iterator) {}`);
-m.declarationInstantiation();
-try { m.evaluation(); } catch (e) {}
+instantiateModule(m);
+try { evaluateModule(m); } catch (e) {}
getModuleEnvironmentValue(m, "r");
diff --git a/js/src/jit-test/tests/modules/bug-1420420-2.js b/js/src/jit-test/tests/modules/bug-1420420-2.js
index e7de4eff4c5b..1f27aef34486 100644
--- a/js/src/jit-test/tests/modules/bug-1420420-2.js
+++ b/js/src/jit-test/tests/modules/bug-1420420-2.js
@@ -14,5 +14,5 @@ moduleRepo["a"] = parseModule(`import* as ns from "good"; import {y} from "bad";
let b = moduleRepo["b"] = parseModule(`import "a";`);
let c = moduleRepo["c"] = parseModule(`import "a";`);
-assertThrowsInstanceOf(() => b.declarationInstantiation(), SyntaxError);
-assertThrowsInstanceOf(() => c.declarationInstantiation(), SyntaxError);
+assertThrowsInstanceOf(() => instantiateModule(b), SyntaxError);
+assertThrowsInstanceOf(() => instantiateModule(c), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/bug-1420420-3.js b/js/src/jit-test/tests/modules/bug-1420420-3.js
index 5fec62d0caf5..af72a5ff7d7c 100644
--- a/js/src/jit-test/tests/modules/bug-1420420-3.js
+++ b/js/src/jit-test/tests/modules/bug-1420420-3.js
@@ -2,7 +2,7 @@ if (!('stackTest' in this))
quit();
let a = parseModule(`throw new Error`);
-a.declarationInstantiation();
+instantiateModule(a);
stackTest(function() {
- a.evaluation();
+ evaluateModule(a);
});
diff --git a/js/src/jit-test/tests/modules/bug-1420420-4.js b/js/src/jit-test/tests/modules/bug-1420420-4.js
index f6ae8f2f6922..57cfd9ac4905 100644
--- a/js/src/jit-test/tests/modules/bug-1420420-4.js
+++ b/js/src/jit-test/tests/modules/bug-1420420-4.js
@@ -6,10 +6,10 @@ moduleRepo["a"] = parseModule(`throw undefined`);
let b = moduleRepo["b"] = parseModule(`import "a";`);
let c = moduleRepo["c"] = parseModule(`import "a";`);
-b.declarationInstantiation();
-c.declarationInstantiation();
+instantiateModule(b);
+instantiateModule(c);
let count = 0;
-try { b.evaluation() } catch (e) { count++; }
-try { c.evaluation() } catch (e) { count++; }
+try { evaluateModule(b) } catch (e) { count++; }
+try { evaluateModule(c) } catch (e) { count++; }
assertEq(count, 2);
diff --git a/js/src/jit-test/tests/modules/bug-1420420.js b/js/src/jit-test/tests/modules/bug-1420420.js
index b1eda3aead1f..1d513b34f931 100644
--- a/js/src/jit-test/tests/modules/bug-1420420.js
+++ b/js/src/jit-test/tests/modules/bug-1420420.js
@@ -14,5 +14,5 @@ moduleRepo["a"] = parseModule(`import {x} from "good"; import {y} from "bad";`);
let b = moduleRepo["b"] = parseModule(`import "a";`);
let c = moduleRepo["c"] = parseModule(`import "a";`);
-assertThrowsInstanceOf(() => b.declarationInstantiation(), SyntaxError);
-assertThrowsInstanceOf(() => c.declarationInstantiation(), SyntaxError);
+assertThrowsInstanceOf(() => instantiateModule(b), SyntaxError);
+assertThrowsInstanceOf(() => instantiateModule(c), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/bug-1435327.js b/js/src/jit-test/tests/modules/bug-1435327.js
index 577e9e4ca526..fe59fc19c0fa 100644
--- a/js/src/jit-test/tests/modules/bug-1435327.js
+++ b/js/src/jit-test/tests/modules/bug-1435327.js
@@ -8,7 +8,7 @@ lfLogBuffer = `
});
let c = moduleRepo['c'] = parseModule("");
let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
- d.declarationInstantiation();
+ instantiateModule(d);
`;
lfLogBuffer = lfLogBuffer.split('\n');
var lfCodeBuffer = "";
@@ -25,8 +25,8 @@ function loadFile(lfVarx) {
try {
oomTest(function() {
let m = parseModule(lfVarx);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
});
} catch (lfVare) {}
}
diff --git a/js/src/jit-test/tests/modules/bug-1443555.js b/js/src/jit-test/tests/modules/bug-1443555.js
index c9ee40668504..9de864179a49 100644
--- a/js/src/jit-test/tests/modules/bug-1443555.js
+++ b/js/src/jit-test/tests/modules/bug-1443555.js
@@ -32,5 +32,5 @@ export default 1;
moduleRepo['A'] = parseModule(ASrc);
let m = parseModule(mainSrc);
-m.declarationInstantiation()
-m.evaluation();
+instantiateModule(m)
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug-1462286.js b/js/src/jit-test/tests/modules/bug-1462286.js
index b1da5727c2c2..d42bdc50d193 100644
--- a/js/src/jit-test/tests/modules/bug-1462286.js
+++ b/js/src/jit-test/tests/modules/bug-1462286.js
@@ -5,6 +5,6 @@ let a = moduleRepo['a'] = parseModule(`
`);
let m = parseModule("import { get } from 'a'; export { get };");
-m.declarationInstantiation();
-m.evaluation()
+instantiateModule(m);
+evaluateModule(m)
assertEq(getModuleEnvironmentValue(m, "get").x, "foo");
diff --git a/js/src/jit-test/tests/modules/bug-1462326.js b/js/src/jit-test/tests/modules/bug-1462326.js
index 1c43f160be36..19b011b05631 100644
--- a/js/src/jit-test/tests/modules/bug-1462326.js
+++ b/js/src/jit-test/tests/modules/bug-1462326.js
@@ -3,4 +3,4 @@
let m = parseModule(`
import A from "A";
`);
-m.declarationInstantiation();
+instantiateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug-1463371.js b/js/src/jit-test/tests/modules/bug-1463371.js
index f0e8782e8ec4..1e509072f8c1 100644
--- a/js/src/jit-test/tests/modules/bug-1463371.js
+++ b/js/src/jit-test/tests/modules/bug-1463371.js
@@ -7,4 +7,4 @@ g.eval(`
let m = parseModule(`
import {} from './foo.js';
`);
-m.declarationInstantiation();
+instantiateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug-1463373.js b/js/src/jit-test/tests/modules/bug-1463373.js
index 2319091660b5..255c14a7bbb3 100644
--- a/js/src/jit-test/tests/modules/bug-1463373.js
+++ b/js/src/jit-test/tests/modules/bug-1463373.js
@@ -4,8 +4,8 @@ let m = parseModule(`
let c = parseModule(\`
import "a";
\`);
- c.declarationInstantiation();
+ instantiateModule(c);
`);
setModuleResolveHook(function(module, specifier) { return m; });
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug-1466487.js b/js/src/jit-test/tests/modules/bug-1466487.js
index 1d5ce7bcf3d0..2ba9762ddbb6 100644
--- a/js/src/jit-test/tests/modules/bug-1466487.js
+++ b/js/src/jit-test/tests/modules/bug-1466487.js
@@ -2,6 +2,6 @@ if (helperThreadCount() === 0)
quit();
evalInWorker(`
let m = parseModule("import.meta;");
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
`);
diff --git a/js/src/jit-test/tests/modules/bug1210391.js b/js/src/jit-test/tests/modules/bug1210391.js
index 78874a3c1f60..326eb48c28b3 100644
--- a/js/src/jit-test/tests/modules/bug1210391.js
+++ b/js/src/jit-test/tests/modules/bug1210391.js
@@ -3,6 +3,6 @@ let a = moduleRepo['a'] = parseModule("export var a = 1; export var b = 2;");
let b = moduleRepo['b'] = parseModule("export var b = 3; export var c = 4;");
let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
-d.declarationInstantiation();
-d.evaluation();
+instantiateModule(d);
+evaluateModule(d);
diff --git a/js/src/jit-test/tests/modules/bug1394492.js b/js/src/jit-test/tests/modules/bug1394492.js
index a0e5d2ac39d4..b05146d0eb2b 100644
--- a/js/src/jit-test/tests/modules/bug1394492.js
+++ b/js/src/jit-test/tests/modules/bug1394492.js
@@ -1,6 +1,6 @@
-// |jit-test| error: NaN
+// |jit-test| error: TypeError
let m = parseModule(`
throw i => { return 5; }, m-1;
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/modules/bug1429031.js b/js/src/jit-test/tests/modules/bug1429031.js
index 20079428ef15..1b9bb3b42583 100644
--- a/js/src/jit-test/tests/modules/bug1429031.js
+++ b/js/src/jit-test/tests/modules/bug1429031.js
@@ -13,7 +13,7 @@ let b = moduleRepo['b'] = parseModule(
\`import * as ns from 'a';
export var x = ns.a + ns.b;\`
);
-b.declarationInstantiation();
+instantiateModule(b);
let ns = getModuleEnvironmentValue(b, "ns");
assertEq(ns.a, 1);
while ( t.ArrayType() ) 1;
diff --git a/js/src/jit-test/tests/modules/bug1449153.js b/js/src/jit-test/tests/modules/bug1449153.js
index bf8a2251799a..50009c856c54 100644
--- a/js/src/jit-test/tests/modules/bug1449153.js
+++ b/js/src/jit-test/tests/modules/bug1449153.js
@@ -26,10 +26,10 @@ moduleRepo["a"] = parseModule(`
let c = moduleRepo["c"] = parseModule(`
import "a";
`);
-c.declarationInstantiation();
-assertThrowsMyError(() => c.evaluation());
+instantiateModule(c);
+assertThrowsMyError(() => evaluateModule(c));
let b = moduleRepo['b'] = parseModule(`
import * as ns0 from 'a'
`);
-assertThrowsMyError(() => b.declarationInstantiation());
+assertThrowsMyError(() => instantiateModule(b));
diff --git a/js/src/jit-test/tests/modules/debugger-frames.js b/js/src/jit-test/tests/modules/debugger-frames.js
index ba7a1471c4df..61d01d39526e 100644
--- a/js/src/jit-test/tests/modules/debugger-frames.js
+++ b/js/src/jit-test/tests/modules/debugger-frames.js
@@ -72,8 +72,8 @@ f = g2.eval(
export const c = 3;
export function f(x) { return x + 1; }
\`);
- a.declarationInstantiation();
- a.evaluation();
+ instantiateModule(a);
+ evaluateModule(a);
let m = parseModule(
\`
@@ -84,6 +84,6 @@ f = g2.eval(
debugger;
\`);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
`);
diff --git a/js/src/jit-test/tests/modules/debugger-vars-function.js b/js/src/jit-test/tests/modules/debugger-vars-function.js
index 75dc023749a1..11feaabb56fc 100644
--- a/js/src/jit-test/tests/modules/debugger-vars-function.js
+++ b/js/src/jit-test/tests/modules/debugger-vars-function.js
@@ -31,7 +31,7 @@ g.eval(
let e = 5;
function f() { debugger; return e; }
\`);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
`);
diff --git a/js/src/jit-test/tests/modules/debugger-vars-toplevel.js b/js/src/jit-test/tests/modules/debugger-vars-toplevel.js
index 8be8f4079a04..46b7db1642f5 100644
--- a/js/src/jit-test/tests/modules/debugger-vars-toplevel.js
+++ b/js/src/jit-test/tests/modules/debugger-vars-toplevel.js
@@ -32,7 +32,7 @@ g.eval(
function f() { return e; }
debugger;
\`);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
`);
diff --git a/js/src/jit-test/tests/modules/eval-module-oom.js b/js/src/jit-test/tests/modules/eval-module-oom.js
index a1bd9db2a9ec..b2e318ded77e 100644
--- a/js/src/jit-test/tests/modules/eval-module-oom.js
+++ b/js/src/jit-test/tests/modules/eval-module-oom.js
@@ -21,6 +21,6 @@ const sb =
oomTest(() => {
let a = moduleRepo['a'] = parseModule(sa);
let b = moduleRepo['b'] = parseModule(sb);
- b.declarationInstantiation();
- assertEq(b.evaluation(), 42);
+ instantiateModule(b);
+ assertEq(evaluateModule(b), 42);
});
diff --git a/js/src/jit-test/tests/modules/export-destructuring.js b/js/src/jit-test/tests/modules/export-destructuring.js
index 5e26b9c640f0..fa4c21719306 100644
--- a/js/src/jit-test/tests/modules/export-destructuring.js
+++ b/js/src/jit-test/tests/modules/export-destructuring.js
@@ -40,8 +40,8 @@ m = parseModule(`
assertArrayEq(a.n, [22]);
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
moduleRepo['o'] = parseModule(`
export const {} = {};
@@ -66,8 +66,8 @@ m = parseModule(`
assertEq(o.h, 6);
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
moduleRepo['ao'] = parseModule(`
export const [{x: a}, {x: b}] = [{x: 1}, {x: 2}];
@@ -102,5 +102,5 @@ m = parseModule(`
assertEq(ao.p, 21);
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/modules/export-entries.js b/js/src/jit-test/tests/modules/export-entries.js
index b383d9e1e988..feb5c0632244 100644
--- a/js/src/jit-test/tests/modules/export-entries.js
+++ b/js/src/jit-test/tests/modules/export-entries.js
@@ -10,7 +10,7 @@ function testArrayContents(actual, expected) {
}
function testLocalExportEntries(source, expected) {
- var module = parseModule(source);
+ var module = getModuleObject(parseModule(source));
testArrayContents(module.localExportEntries, expected);
}
@@ -69,7 +69,7 @@ testLocalExportEntries(
// Test indirectExportEntries property
function testIndirectExportEntries(source, expected) {
- var module = parseModule(source);
+ var module = getModuleObject(parseModule(source));
testArrayContents(module.indirectExportEntries, expected);
}
@@ -100,7 +100,7 @@ testIndirectExportEntries(
// Test starExportEntries property
function testStarExportEntries(source, expected) {
- var module = parseModule(source);
+ var module = getModuleObject(parseModule(source));
testArrayContents(module.starExportEntries, expected);
}
diff --git a/js/src/jit-test/tests/modules/global-scope.js b/js/src/jit-test/tests/modules/global-scope.js
index b99019fa86b9..4f38a5e49902 100644
--- a/js/src/jit-test/tests/modules/global-scope.js
+++ b/js/src/jit-test/tests/modules/global-scope.js
@@ -2,8 +2,8 @@
function evalModuleAndCheck(source, expected) {
let m = parseModule(source);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
assertEq(getModuleEnvironmentValue(m, "r"), expected);
}
@@ -22,8 +22,8 @@ function offThreadEvalModuleAndCheck(source, expected) {
offThreadCompileModule(source);
let m = finishOffThreadModule();
print("compiled");
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
assertEq(getModuleEnvironmentValue(m, "r"), expected);
}
diff --git a/js/src/jit-test/tests/modules/import-entries.js b/js/src/jit-test/tests/modules/import-entries.js
index e5f7066f10e6..6ff37d6da591 100644
--- a/js/src/jit-test/tests/modules/import-entries.js
+++ b/js/src/jit-test/tests/modules/import-entries.js
@@ -17,7 +17,7 @@ function findImportEntry(array, target)
}
function testImportEntries(source, expected) {
- var module = parseModule(source);
+ var module = getModuleObject(parseModule(source));
var actual = module.importEntries.slice(0);
assertEq(actual.length, expected.length);
for (var i = 0; i < expected.length; i++) {
diff --git a/js/src/jit-test/tests/modules/import-namespace.js b/js/src/jit-test/tests/modules/import-namespace.js
index 0287f7a60e4a..6e18c7e9ec5a 100644
--- a/js/src/jit-test/tests/modules/import-namespace.js
+++ b/js/src/jit-test/tests/modules/import-namespace.js
@@ -8,8 +8,8 @@ load(libdir + "dummyModuleResolveHook.js");
function parseAndEvaluate(source) {
let m = parseModule(source);
- m.declarationInstantiation();
- return m.evaluation();
+ instantiateModule(m);
+ return evaluateModule(m);
}
function testHasNames(names, expected) {
@@ -40,8 +40,8 @@ let b = moduleRepo['b'] = parseModule(
export var x = ns.a + ns.b;`
);
-b.declarationInstantiation();
-b.evaluation();
+instantiateModule(b);
+evaluateModule(b);
testHasNames(getModuleEnvironmentNames(b), ["ns", "x"]);
let ns = getModuleEnvironmentValue(b, "ns");
testHasNames(Object.keys(ns), ["a", "b"]);
@@ -89,18 +89,18 @@ let c = moduleRepo['c'] =
parseModule("export let c = 1; import * as ns from 'd'; let d = ns.d;");
let d = moduleRepo['d'] =
parseModule("export let d = 2; import * as ns from 'c'; let c = ns.c;");
-c.declarationInstantiation();
-d.declarationInstantiation();
-assertThrowsInstanceOf(() => c.evaluation(), ReferenceError);
+instantiateModule(c);
+instantiateModule(d);
+assertThrowsInstanceOf(() => evaluateModule(c), ReferenceError);
// Test cyclic namespace import.
let e = moduleRepo['e'] =
parseModule("export let e = 1; import * as ns from 'f'; export function f() { return ns.f }");
let f = moduleRepo['f'] =
parseModule("export let f = 2; import * as ns from 'e'; export function e() { return ns.e }");
-e.declarationInstantiation();
-f.declarationInstantiation();
-e.evaluation();
-f.evaluation();
-assertEq(e.namespace.f(), 2);
-assertEq(f.namespace.e(), 1);
+instantiateModule(e);
+instantiateModule(f);
+evaluateModule(e);
+evaluateModule(f);
+assertEq(getModuleObject(e).namespace.f(), 2);
+assertEq(getModuleObject(f).namespace.e(), 1);
diff --git a/js/src/jit-test/tests/modules/many-exports.js b/js/src/jit-test/tests/modules/many-exports.js
index 8e32d34fc177..7928242c0c6e 100644
--- a/js/src/jit-test/tests/modules/many-exports.js
+++ b/js/src/jit-test/tests/modules/many-exports.js
@@ -11,9 +11,9 @@ let a = moduleRepo['a'] = parseModule(s);
let b = moduleRepo['b'] = parseModule("import * as ns from 'a'");
-b.declarationInstantiation();
-b.evaluation();
+instantiateModule(b);
+evaluateModule(b);
-let ns = a.namespace;
+let ns = getModuleObject(a).namespace;
for (let i = 0; i < count; i++)
assertEq(ns["e" + i], i * i);
diff --git a/js/src/jit-test/tests/modules/many-imports.js b/js/src/jit-test/tests/modules/many-imports.js
index 14ed6b810742..acfb292b1cdd 100644
--- a/js/src/jit-test/tests/modules/many-imports.js
+++ b/js/src/jit-test/tests/modules/many-imports.js
@@ -13,5 +13,5 @@ for (let i = 0; i < count; i++) {
}
let b = moduleRepo['b'] = parseModule(s);
-b.declarationInstantiation();
-b.evaluation();
+instantiateModule(b);
+evaluateModule(b);
diff --git a/js/src/jit-test/tests/modules/many-namespace-imports.js b/js/src/jit-test/tests/modules/many-namespace-imports.js
index bfcac8eef47b..3d21b99d492e 100644
--- a/js/src/jit-test/tests/modules/many-namespace-imports.js
+++ b/js/src/jit-test/tests/modules/many-namespace-imports.js
@@ -13,5 +13,5 @@ for (let i = 0; i < count; i++) {
}
let b = moduleRepo['b'] = parseModule(s);
-b.declarationInstantiation();
-b.evaluation();
+instantiateModule(b);
+evaluateModule(b);
diff --git a/js/src/jit-test/tests/modules/module-declaration-instantiation.js b/js/src/jit-test/tests/modules/module-declaration-instantiation.js
index de820ae5b70d..f1484c677090 100644
--- a/js/src/jit-test/tests/modules/module-declaration-instantiation.js
+++ b/js/src/jit-test/tests/modules/module-declaration-instantiation.js
@@ -12,14 +12,14 @@ function testModuleEnvironment(module, expected) {
// Check the environment of an empty module.
let m = parseModule("");
-m.declarationInstantiation();
+instantiateModule(m);
testModuleEnvironment(m, []);
let a = moduleRepo['a'] = parseModule("var x = 1; export { x };");
let b = moduleRepo['b'] = parseModule("import { x as y } from 'a';");
-a.declarationInstantiation();
-b.declarationInstantiation();
+instantiateModule(a);
+instantiateModule(b);
testModuleEnvironment(a, ['x']);
testModuleEnvironment(b, ['y']);
@@ -32,7 +32,7 @@ let c = parseModule(`function a(x) { return x; }
const names = ['a', 'b', 'c', 'd'];
testModuleEnvironment(c, names);
names.forEach((n) => assertEq(typeof getModuleEnvironmentValue(c, n), "undefined"));
-c.declarationInstantiation();
+instantiateModule(c);
for (let i = 0; i < names.length; i++) {
let f = getModuleEnvironmentValue(c, names[i]);
assertEq(f(21), 21 + i);
diff --git a/js/src/jit-test/tests/modules/module-evaluation.js b/js/src/jit-test/tests/modules/module-evaluation.js
index 1b2f2c9990f9..0b008f95b380 100644
--- a/js/src/jit-test/tests/modules/module-evaluation.js
+++ b/js/src/jit-test/tests/modules/module-evaluation.js
@@ -5,8 +5,8 @@ load(libdir + "dummyModuleResolveHook.js");
function parseAndEvaluate(source) {
let m = parseModule(source);
- m.declarationInstantiation();
- m.evaluation();
+ instantiateModule(m);
+ evaluateModule(m);
return m;
}
@@ -15,20 +15,20 @@ parseAndEvaluate("");
// Check evaluation returns evaluation result the first time, then undefined.
let m = parseModule("1");
-m.declarationInstantiation();
-assertEq(m.evaluation(), undefined);
-assertEq(typeof m.evaluation(), "undefined");
+instantiateModule(m);
+assertEq(evaluateModule(m), undefined);
+assertEq(typeof evaluateModule(m), "undefined");
// Check top level variables are initialized by evaluation.
m = parseModule("export var x = 2 + 2;");
assertEq(typeof getModuleEnvironmentValue(m, "x"), "undefined");
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
assertEq(getModuleEnvironmentValue(m, "x"), 4);
m = parseModule("export let x = 2 * 3;");
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
assertEq(getModuleEnvironmentValue(m, "x"), 6);
// Set up a module to import from.
@@ -62,20 +62,20 @@ parseAndEvaluate("export default class foo { constructor() {} };");
// Test default import
m = parseModule("import a from 'a'; export { a };")
-m.declarationInstantiation();
-m.evaluation()
+instantiateModule(m);
+evaluateModule(m)
assertEq(getModuleEnvironmentValue(m, "a"), 2);
// Test named import
m = parseModule("import { x as y } from 'a'; export { y };")
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
assertEq(getModuleEnvironmentValue(m, "y"), 1);
// Call exported function
m = parseModule("import { f } from 'a'; export let x = f(3);")
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
assertEq(getModuleEnvironmentValue(m, "x"), 4);
// Test importing an indirect export
@@ -93,7 +93,7 @@ assertDeepEq(getModuleEnvironmentValue(m, "z"), [1, 2, 1, 2]);
// Import access in functions
m = parseModule("import { x } from 'a'; function f() { return x; }")
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
let f = getModuleEnvironmentValue(m, "f");
assertEq(f(), 1);
diff --git a/js/src/jit-test/tests/modules/module-this.js b/js/src/jit-test/tests/modules/module-this.js
index 10a3241aa756..c11f92657ee5 100644
--- a/js/src/jit-test/tests/modules/module-this.js
+++ b/js/src/jit-test/tests/modules/module-this.js
@@ -2,14 +2,14 @@
function parseAndEvaluate(source) {
let m = parseModule(source);
- m.declarationInstantiation();
- return m.evaluation();
+ instantiateModule(m);
+ return evaluateModule(m);
}
assertEq(typeof(parseAndEvaluate("this")), "undefined");
let m = parseModule("export function getThis() { return this; }");
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
let f = getModuleEnvironmentValue(m, "getThis");
assertEq(typeof(f()), "undefined");
diff --git a/js/src/jit-test/tests/modules/off-thread-compile.js b/js/src/jit-test/tests/modules/off-thread-compile.js
index 8d17d4a749fe..fe260abd1d1b 100644
--- a/js/src/jit-test/tests/modules/off-thread-compile.js
+++ b/js/src/jit-test/tests/modules/off-thread-compile.js
@@ -9,8 +9,8 @@ load(libdir + "dummyModuleResolveHook.js");
function offThreadParseAndEvaluate(source) {
offThreadCompileModule(source);
let m = finishOffThreadModule();
- m.declarationInstantiation();
- return m.evaluation();
+ instantiateModule(m);
+ return evaluateModule(m);
}
offThreadParseAndEvaluate("export let x = 2 * 3;");
diff --git a/js/src/jit-test/tests/modules/requested-modules.js b/js/src/jit-test/tests/modules/requested-modules.js
index acf58e5a6ee3..ff74f001d143 100644
--- a/js/src/jit-test/tests/modules/requested-modules.js
+++ b/js/src/jit-test/tests/modules/requested-modules.js
@@ -1,7 +1,7 @@
// Test requestedModules property
function testRequestedModules(source, expected) {
- var module = parseModule(source);
+ var module = getModuleObject(parseModule(source));
var actual = module.requestedModules;
assertEq(actual.length, expected.length);
for (var i = 0; i < actual.length; i++) {
diff --git a/js/src/jit-test/tests/parser/bug-1263355-16.js b/js/src/jit-test/tests/parser/bug-1263355-16.js
index df66d9593b94..89a76f5160f4 100644
--- a/js/src/jit-test/tests/parser/bug-1263355-16.js
+++ b/js/src/jit-test/tests/parser/bug-1263355-16.js
@@ -7,5 +7,5 @@ function addThis() {
return statusmessages[i] = Number;
}
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-23.js b/js/src/jit-test/tests/parser/bug-1263355-23.js
index 690a6c728f67..5eaa1f40d5a7 100644
--- a/js/src/jit-test/tests/parser/bug-1263355-23.js
+++ b/js/src/jit-test/tests/parser/bug-1263355-23.js
@@ -3,5 +3,5 @@ let m = parseModule(`
minorgc();
root.eval();
`);
-m.declarationInstantiation();
-m.evaluation();
+instantiateModule(m);
+evaluateModule(m);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-48.js b/js/src/jit-test/tests/parser/bug-1263355-48.js
index 2345b422edf1..88384a34fb65 100644
--- a/js/src/jit-test/tests/parser/bug-1263355-48.js
+++ b/js/src/jit-test/tests/parser/bug-1263355-48.js
@@ -4,8 +4,8 @@ if (helperThreadCount() == 0)
function eval(source) {
offThreadCompileModule(source);
let m = finishOffThreadModule();
- m.declarationInstantiation();
- return m.evaluation();
+ instantiateModule(m);
+ return evaluateModule(m);
}
function runTestCase(testcase) {
if (testcase() !== true) {}
diff --git a/js/src/jit-test/tests/wasm/atomicity.js b/js/src/jit-test/tests/wasm/atomicity.js
new file mode 100644
index 000000000000..8e6a6f85ad11
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/atomicity.js
@@ -0,0 +1,373 @@
+// |jit-test| slow;
+//
+// Temporarily marked as slow - they time out on the build systems even with
+// reduced iteration count.
+//
+// Test that wasm atomic operations implement correct mutual exclusion.
+//
+// We have several agents that attempt to hammer on a shared location with rmw
+// operations in such a way that failed atomicity will lead to an incorrect
+// result. Each agent attempts to clear or set specific bits in a shared datum.
+
+// 1 for a little bit, 2 for a lot, 3 to quit before running tests
+const DEBUG = 0;
+
+// The longer we run, the better, really, but we don't want to time out.
+const ITERATIONS = 100000;
+
+// If you change NUMWORKERS you must also change the tables for INIT, VAL, and
+// RESULT for all the operations, below, by adding or removing bits.
+const NUMWORKERS = 2;
+const NUMAGENTS = NUMWORKERS + 1;
+
+if (!wasmThreadsSupported() || helperThreadCount() < NUMWORKERS) {
+ if (DEBUG > 0)
+ print("Threads not supported");
+ quit(0);
+}
+
+// Most of the simulators have poor support for mutual exclusion and are anyway
+// too slow; avoid intermittent failures and timeouts.
+
+let conf = getBuildConfiguration();
+if (conf["arm-simulator"] || conf["arm64-simulator"] ||
+ conf["mips-simulator"] || conf["mips64-simulator"])
+{
+ if (DEBUG > 0)
+ print("Atomicity test disabled on simulator");
+ quit(0);
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+// Coordination code for bootstrapping workers - use spawn() to create a worker,
+// send() to send an item to a worker. send() will send to anyone, so only one
+// worker should be receiving at a time. spawn() will block until the worker is
+// running; send() will block until the message has been received.
+
+var COORD_BUSY = 0;
+var COORD_NUMLOC = 1;
+
+var coord = new Int32Array(new SharedArrayBuffer(COORD_NUMLOC*4));
+
+function spawn(text) {
+ text = `
+var _coord = new Int32Array(getSharedObject());
+Atomics.store(_coord, ${COORD_BUSY}, 0);
+function receive() {
+ while (!Atomics.load(_coord, ${COORD_BUSY}))
+ ;
+ let x = getSharedObject();
+ Atomics.store(_coord, ${COORD_BUSY}, 0);
+ return x;
+}
+` + text;
+ setSharedObject(coord.buffer);
+ Atomics.store(coord, COORD_BUSY, 1);
+ evalInWorker(text);
+ while (Atomics.load(coord, COORD_BUSY))
+ ;
+}
+
+function send(x) {
+ while(Atomics.load(coord, COORD_BUSY))
+ ;
+ setSharedObject(x);
+ Atomics.store(coord, COORD_BUSY, 1);
+ while(Atomics.load(coord, COORD_BUSY))
+ ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// The "agents" comprise one master and one or more additional workers. We make
+// a separate module for each agent so that test values can be inlined as
+// constants.
+//
+// The master initially sets a shared location LOC to a value START.
+//
+// Each agent then operates atomically on LOC with an operation OP and a value
+// VAL. The operation OP is the same for all agents but each agent `i` has a
+// different VAL_i.
+//
+// To make this more interesting, the value START is distributed as many times
+// through the value at LOC as there is space for, and we perform several
+// operations back-to-back, with the VAL_i appropriately shifted.
+//
+// Each agent then spin-waits for LOC to contain a particular RESULT, which is
+// always (START OP VAL_0 OP VAL_1 ... VAL_k), again repeated throughout the
+// RESULT as appropriate.
+//
+// The process then starts over, and we repeat the process many times. If we
+// fail to have atomicity at any point the program will hang (LOC will never
+// attain the desired value) and the test should therefore time out.
+//
+// (Barriers are needed to make this all work out.)
+//
+// The general principle for the values is that each VAL should add (or clear) a
+// bit of the stored value.
+//
+// OP START VAL0 VAL1 VAL2 RESULT
+//
+// ADD[*] 0 1 2 4 7
+// SUB 7 1 2 4 0
+// AND 7 3 6 5 0
+// OR 0 1 2 4 7
+// XOR 0 1 2 4 7 // or start with 7 and end with 0
+// CMPXCHG 0 1 2 4 7 // use nonatomic "or" to add the bit
+//
+// [*] Running the tests actually assumes that ADD works reasonably well.
+//
+// TODO - more variants we could test:
+//
+// - tests that do not drop the values of the atomic ops but accumulate them:
+// uses different code generation on x86/x64
+//
+// - Xchg needs a different method, since here the atomic thing is that we read
+// the "previous value" and set the next value atomically. How can we observe
+// that that fails? If we run three agents, which all set the value to X,
+// X+1, ..., X+n, with the initial value being (say) X-1, each can record the
+// value it observed in a table, and we should be able to predict the counts
+// in that table once postprocessed. eg, the counts should all be the same.
+// If atomicity fails then a value is read twice when it shouldn't be, and
+// some other value is not read at all, and the counts will be off.
+//
+// - the different rmw operations can usually be combined so that we can test
+// the atomicity of operations that may be implemented differently.
+//
+// - the same tests, with test values as variables instead of constants.
+
+function makeModule(id) {
+ let isMaster = id == 0;
+ let VALSHIFT = NUMAGENTS; // 1 bit per agent
+
+ function makeLoop(bits, name, op, loc, initial, val, expected) {
+ // Exclude high bit to avoid messing with the sign.
+ let NUMVALS32 = Math.floor(31/VALSHIFT);
+ let NUMVALS = bits == 64 ? 2 * NUMVALS32 : Math.floor(Math.min(bits,31)/VALSHIFT);
+ let BARRIER = "(i32.const 0)";
+ let barrier = `
+ ;; Barrier
+ (set_local $barrierValue (i32.add (get_local $barrierValue) (i32.const ${NUMAGENTS})))
+ (drop (i32.atomic.rmw.add ${BARRIER} (i32.const 1)))
+ (loop $c1
+ (if (i32.lt_s (i32.atomic.load ${BARRIER}) (get_local $barrierValue))
+ (br $c1)))
+ ;; End barrier
+`;
+
+ // Distribute a value `v` across a word NUMVALs times
+
+ function distribute(v) {
+ if (bits <= 32)
+ return '0x' + dist32(v);
+ return '0x' + dist32(v) + dist32(v);
+ }
+
+ function dist32(v) {
+ let n = 0;
+ for (let i=0; i < Math.min(NUMVALS, NUMVALS32); i++)
+ n = n | (v << (i*VALSHIFT));
+ assertEq(n >= 0, true);
+ return (n + 0x100000000).toString(16).substring(1);
+ }
+
+ // Position a value `v` at position `pos` in a word
+
+ function format(val, pos) {
+ if (bits <= 32)
+ return '0x' + format32(val, pos);
+ if (pos < NUMVALS32)
+ return '0x' + '00000000' + format32(val, pos);
+ return '0x' + format32(val, pos - NUMVALS32) + '00000000';
+ }
+
+ function format32(val, pos) {
+ return ((val << (pos * VALSHIFT)) + 0x100000000).toString(16).substring(1);
+ }
+
+ let tag = bits < 32 ? bits + '_u' : '';
+ let prefix = bits == 64 ? 'i64' : 'i32';
+ return `
+ (func ${name} (param $barrierValue i32) (result i32)
+ (local $n i32)
+ (local $tmp ${prefix})
+ (set_local $n (i32.const ${ITERATIONS}))
+ (loop $outer
+ (if (get_local $n)
+ (block
+ ${isMaster ? `;; Init
+(${prefix}.atomic.store${tag} ${loc} (${prefix}.const ${distribute(initial)}))` : ``}
+ ${barrier}
+
+${(() => {
+ let s = `;; Do\n`;
+ for (let i=0; i < NUMVALS; i++) {
+ let bitval = `(${prefix}.const ${format(val, i)})`
+ // The load must be atomic though it would be better if it were relaxed,
+ // we would avoid fences in that case.
+ if (op.match(/cmpxchg/)) {
+ s += `(loop $doit
+ (set_local $tmp (${prefix}.atomic.load${tag} ${loc}))
+ (br_if $doit (i32.eqz
+ (${prefix}.eq
+ (get_local $tmp)
+ (${op} ${loc} (get_local $tmp) (${prefix}.or (get_local $tmp) ${bitval}))))))
+ `;
+ } else {
+ s += `(drop (${op} ${loc} ${bitval}))
+ `;
+ }
+ }
+ return s
+})()}
+ (loop $wait_done
+ (br_if $wait_done (${prefix}.ne (${prefix}.atomic.load${tag} ${loc}) (${prefix}.const ${distribute(expected)}))))
+ ${barrier}
+ (set_local $n (i32.sub (get_local $n) (i32.const 1)))
+ (br $outer))))
+ (get_local $barrierValue))`;
+ }
+
+ const ADDLOC = "(i32.const 256)";
+ const ADDINIT = 0;
+ const ADDVAL = [1, 2, 4];
+ const ADDRESULT = 7;
+
+ const SUBLOC = "(i32.const 512)";
+ const SUBINIT = 7;
+ const SUBVAL = [1, 2, 4];
+ const SUBRESULT = 0;
+
+ const ANDLOC = "(i32.const 768)";
+ const ANDINIT = 7;
+ const ANDVAL = [3, 6, 5];
+ const ANDRESULT = 0;
+
+ const ORLOC = "(i32.const 1024)";
+ const ORINIT = 0;
+ const ORVAL = [1, 2, 4];
+ const ORRESULT = 7;
+
+ const XORLOC = "(i32.const 1280)";
+ const XORINIT = 0;
+ const XORVAL = [1, 2, 4];
+ const XORRESULT = 7;
+
+ const CMPXCHGLOC = "(i32.const 1536)";
+ const CMPXCHGINIT = 0;
+ const CMPXCHGVAL = [1, 2, 4];
+ const CMPXCHGRESULT = 7;
+
+ return `
+(module
+ (import "" "memory" (memory 1 1 shared))
+ (import $print "" "print" (param i32))
+
+ ${makeLoop(8, "$test_add8", "i32.atomic.rmw8_u.add", ADDLOC, ADDINIT, ADDVAL[id], ADDRESULT)}
+ ${makeLoop(8, "$test_sub8", "i32.atomic.rmw8_u.sub", SUBLOC, SUBINIT, SUBVAL[id], SUBRESULT)}
+ ${makeLoop(8, "$test_and8", "i32.atomic.rmw8_u.and", ANDLOC, ANDINIT, ANDVAL[id], ANDRESULT)}
+ ${makeLoop(8, "$test_or8", "i32.atomic.rmw8_u.or", ORLOC, ORINIT, ORVAL[id], ORRESULT)}
+ ${makeLoop(8, "$test_xor8", "i32.atomic.rmw8_u.xor", XORLOC, XORINIT, XORVAL[id], XORRESULT)}
+ ${makeLoop(8, "$test_cmpxchg8", "i32.atomic.rmw8_u.cmpxchg", CMPXCHGLOC, CMPXCHGINIT, CMPXCHGVAL[id], CMPXCHGRESULT)}
+
+ ${makeLoop(16, "$test_add16", "i32.atomic.rmw16_u.add", ADDLOC, ADDINIT, ADDVAL[id], ADDRESULT)}
+ ${makeLoop(16, "$test_sub16", "i32.atomic.rmw16_u.sub", SUBLOC, SUBINIT, SUBVAL[id], SUBRESULT)}
+ ${makeLoop(16, "$test_and16", "i32.atomic.rmw16_u.and", ANDLOC, ANDINIT, ANDVAL[id], ANDRESULT)}
+ ${makeLoop(16, "$test_or16", "i32.atomic.rmw16_u.or", ORLOC, ORINIT, ORVAL[id], ORRESULT)}
+ ${makeLoop(16, "$test_xor16", "i32.atomic.rmw16_u.xor", XORLOC, XORINIT, XORVAL[id], XORRESULT)}
+ ${makeLoop(16, "$test_cmpxchg16", "i32.atomic.rmw16_u.cmpxchg", CMPXCHGLOC, CMPXCHGINIT, CMPXCHGVAL[id], CMPXCHGRESULT)}
+
+ ${makeLoop(32, "$test_add", "i32.atomic.rmw.add", ADDLOC, ADDINIT, ADDVAL[id], ADDRESULT)}
+ ${makeLoop(32, "$test_sub", "i32.atomic.rmw.sub", SUBLOC, SUBINIT, SUBVAL[id], SUBRESULT)}
+ ${makeLoop(32, "$test_and", "i32.atomic.rmw.and", ANDLOC, ANDINIT, ANDVAL[id], ANDRESULT)}
+ ${makeLoop(32, "$test_or", "i32.atomic.rmw.or", ORLOC, ORINIT, ORVAL[id], ORRESULT)}
+ ${makeLoop(32, "$test_xor", "i32.atomic.rmw.xor", XORLOC, XORINIT, XORVAL[id], XORRESULT)}
+ ${makeLoop(32, "$test_cmpxchg", "i32.atomic.rmw.cmpxchg", CMPXCHGLOC, CMPXCHGINIT, CMPXCHGVAL[id], CMPXCHGRESULT)}
+
+ ${makeLoop(64, "$test_add64", "i64.atomic.rmw.add", ADDLOC, ADDINIT, ADDVAL[id], ADDRESULT)}
+ ${makeLoop(64, "$test_sub64", "i64.atomic.rmw.sub", SUBLOC, SUBINIT, SUBVAL[id], SUBRESULT)}
+ ${makeLoop(64, "$test_and64", "i64.atomic.rmw.and", ANDLOC, ANDINIT, ANDVAL[id], ANDRESULT)}
+ ${makeLoop(64, "$test_or64", "i64.atomic.rmw.or", ORLOC, ORINIT, ORVAL[id], ORRESULT)}
+ ${makeLoop(64, "$test_xor64", "i64.atomic.rmw.xor", XORLOC, XORINIT, XORVAL[id], XORRESULT)}
+ ${makeLoop(64, "$test_cmpxchg64", "i64.atomic.rmw.cmpxchg", CMPXCHGLOC, CMPXCHGINIT, CMPXCHGVAL[id], CMPXCHGRESULT)}
+
+ (func (export "test")
+ (local $barrierValue i32)
+ (call $print (i32.const ${10 + id}))
+ (set_local $barrierValue (call $test_add8 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_sub8 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_and8 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_or8 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_xor8 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_cmpxchg8 (get_local $barrierValue)))
+ (call $print (i32.const ${20 + id}))
+ (set_local $barrierValue (call $test_add16 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_sub16 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_and16 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_or16 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_xor16 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_cmpxchg16 (get_local $barrierValue)))
+ (call $print (i32.const ${30 + id}))
+ (set_local $barrierValue (call $test_add (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_sub (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_and (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_or (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_xor (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_cmpxchg (get_local $barrierValue)))
+ (call $print (i32.const ${40 + id}))
+ (set_local $barrierValue (call $test_add64 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_sub64 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_and64 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_or64 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_xor64 (get_local $barrierValue)))
+ (set_local $barrierValue (call $test_cmpxchg64 (get_local $barrierValue)))
+ ))
+`;
+}
+
+function makeModule2(id) {
+ let text = makeModule(id);
+ if (DEBUG > 1)
+ print(text);
+ return new WebAssembly.Module(wasmTextToBinary(text));
+}
+
+var mods = [];
+mods.push(makeModule2(0));
+for ( let i=0; i < NUMWORKERS; i++ )
+ mods.push(makeModule2(i+1));
+if (DEBUG > 2)
+ quit(0);
+var mem = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
+
+////////////////////////////////////////////////////////////////////////
+//
+// Worker code
+
+function startWorkers() {
+ for ( let i=0; i < NUMWORKERS; i++ ) {
+ spawn(`
+var mem = receive();
+var mod = receive();
+function pr(n) { if (${DEBUG}) print(n); }
+var ins = new WebAssembly.Instance(mod, {"":{memory: mem, print:pr}});
+if (${DEBUG} > 0)
+ print("Running ${i}");
+ins.exports.test();
+ `);
+ send(mem);
+ send(mods[i+1]);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+// Main thread code
+
+startWorkers();
+function pr(n) { if (DEBUG) print(n); }
+var ins = new WebAssembly.Instance(mods[0], {"":{memory: mem, print:pr}});
+if (DEBUG > 0)
+ print("Running master");
+ins.exports.test();
diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp
index 84a638894ded..29e3eecf266f 100644
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1065,7 +1065,7 @@ InitFromBailout(JSContext* cx, size_t frameNo,
// Not every monitored op has a monitored fallback stub, e.g.
// JSOP_NEWOBJECT, which always returns the same type for a
// particular script/pc location.
- BaselineICEntry& icEntry = baselineScript->icEntryFromPCOffset(pcOff);
+ ICEntry& icEntry = baselineScript->icEntryFromPCOffset(pcOff);
ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
if (fallbackStub->isMonitoredFallback())
enterMonitorChain = true;
@@ -1080,7 +1080,7 @@ InitFromBailout(JSContext* cx, size_t frameNo,
builder.setResumeFramePtr(prevFramePtr);
if (enterMonitorChain) {
- BaselineICEntry& icEntry = baselineScript->icEntryFromPCOffset(pcOff);
+ ICEntry& icEntry = baselineScript->icEntryFromPCOffset(pcOff);
ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
MOZ_ASSERT(fallbackStub->isMonitoredFallback());
JitSpew(JitSpew_BaselineBailouts, " [TYPE-MONITOR CHAIN]");
@@ -1247,7 +1247,7 @@ InitFromBailout(JSContext* cx, size_t frameNo,
// Calculate and write out return address.
// The icEntry in question MUST have an inlinable fallback stub.
- BaselineICEntry& icEntry = baselineScript->icEntryFromPCOffset(pcOff);
+ ICEntry& icEntry = baselineScript->icEntryFromPCOffset(pcOff);
MOZ_ASSERT(IsInlinableFallback(icEntry.firstStub()->getChainFallback()));
if (!builder.writePtr(baselineScript->returnAddressForIC(icEntry), "ReturnAddr"))
return false;
diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp
index 23e971dff479..cb6beab5886a 100644
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -35,13 +35,6 @@ CacheRegisterAllocator::addressOf(MacroAssembler& masm, BaselineFrameSlot slot)
// BaselineCacheIRCompiler compiles CacheIR to BaselineIC native code.
class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler
{
-#ifdef DEBUG
- // Some Baseline IC stubs can be used in IonMonkey through SharedStubs.
- // Those stubs have different machine code, so we need to track whether
- // we're compiling for Baseline or Ion.
- ICStubEngine engine_;
-#endif
-
bool inStubFrame_;
bool makesGCCalls_;
@@ -58,12 +51,9 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler
public:
friend class AutoStubFrame;
- BaselineCacheIRCompiler(JSContext* cx, const CacheIRWriter& writer, ICStubEngine engine,
+ BaselineCacheIRCompiler(JSContext* cx, const CacheIRWriter& writer,
uint32_t stubDataOffset)
: CacheIRCompiler(cx, writer, stubDataOffset, Mode::Baseline, StubFieldPolicy::Address),
-#ifdef DEBUG
- engine_(engine),
-#endif
inStubFrame_(false),
makesGCCalls_(false)
{}
@@ -113,7 +103,6 @@ class MOZ_RAII AutoStubFrame
void enter(MacroAssembler& masm, Register scratch, CallCanGC canGC = CallCanGC::CanGC) {
MOZ_ASSERT(compiler.allocator.stackPushed() == 0);
- MOZ_ASSERT(compiler.engine_ == ICStubEngine::Baseline);
EmitBaselineEnterStubFrame(masm, scratch);
@@ -153,7 +142,6 @@ BaselineCacheIRCompiler::callVM(MacroAssembler& masm, const VMFunction& fun)
TrampolinePtr code = cx_->runtime()->jitRuntime()->getVMWrapper(fun);
MOZ_ASSERT(fun.expectTailCall == NonTailCall);
- MOZ_ASSERT(engine_ == ICStubEngine::Baseline);
EmitBaselineCallVM(code, masm);
return true;
@@ -166,7 +154,6 @@ BaselineCacheIRCompiler::tailCallVM(MacroAssembler& masm, const VMFunction& fun)
TrampolinePtr code = cx_->runtime()->jitRuntime()->getVMWrapper(fun);
MOZ_ASSERT(fun.expectTailCall == TailCall);
- MOZ_ASSERT(engine_ == ICStubEngine::Baseline);
size_t argSize = fun.explicitStackSlots() * sizeof(void*);
EmitBaselineTailCallVM(code, masm, argSize);
@@ -557,8 +544,6 @@ BaselineCacheIRCompiler::emitGuardHasGetterSetter()
bool
BaselineCacheIRCompiler::emitCallScriptedGetterResult()
{
- MOZ_ASSERT(engine_ == ICStubEngine::Baseline);
-
Register obj = allocator.useRegister(masm, reader.objOperandId());
Address getterAddr(stubAddress(reader.stubOffset()));
bool isCrossRealm = reader.readBool();
@@ -2121,8 +2106,8 @@ static const size_t MaxOptimizedCacheIRStubs = 16;
ICStub*
js::jit::AttachBaselineCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
CacheKind kind, BaselineCacheIRStubKind stubKind,
- ICStubEngine engine, JSScript* outerScript,
- ICFallbackStub* stub, bool* attached)
+ JSScript* outerScript, ICFallbackStub* stub,
+ bool* attached)
{
// We shouldn't GC or report OOM (or any other exception) here.
AutoAssertNoPendingException aanpe(cx);
@@ -2154,12 +2139,13 @@ js::jit::AttachBaselineCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
// Check if we already have JitCode for this stub.
CacheIRStubInfo* stubInfo;
- CacheIRStubKey::Lookup lookup(kind, engine, writer.codeStart(), writer.codeLength());
+ CacheIRStubKey::Lookup lookup(kind, ICStubEngine::Baseline, writer.codeStart(),
+ writer.codeLength());
JitCode* code = jitZone->getBaselineCacheIRStubCode(lookup, &stubInfo);
if (!code) {
// We have to generate stub code.
JitContext jctx(cx, nullptr);
- BaselineCacheIRCompiler comp(cx, writer, engine, stubDataOffset);
+ BaselineCacheIRCompiler comp(cx, writer, stubDataOffset);
if (!comp.init(kind))
return nullptr;
@@ -2172,7 +2158,8 @@ js::jit::AttachBaselineCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
// to the stub code HashMap, so we don't have to worry about freeing
// it below.
MOZ_ASSERT(!stubInfo);
- stubInfo = CacheIRStubInfo::New(kind, engine, comp.makesGCCalls(), stubDataOffset, writer);
+ stubInfo = CacheIRStubInfo::New(kind, ICStubEngine::Baseline, comp.makesGCCalls(),
+ stubDataOffset, writer);
if (!stubInfo)
return nullptr;
@@ -2236,7 +2223,7 @@ js::jit::AttachBaselineCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
size_t bytesNeeded = stubInfo->stubDataOffset() + stubInfo->stubDataSize();
ICStubSpace* stubSpace = ICStubCompiler::StubSpaceForStub(stubInfo->makesGCCalls(),
- outerScript, engine);
+ outerScript);
void* newStubMem = stubSpace->alloc(bytesNeeded);
if (!newStubMem)
return nullptr;
diff --git a/js/src/jit/BaselineCacheIRCompiler.h b/js/src/jit/BaselineCacheIRCompiler.h
index fdef63187505..aa61c66825ae 100644
--- a/js/src/jit/BaselineCacheIRCompiler.h
+++ b/js/src/jit/BaselineCacheIRCompiler.h
@@ -21,8 +21,8 @@ enum class BaselineCacheIRStubKind { Regular, Monitored, Updated };
ICStub* AttachBaselineCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
CacheKind kind, BaselineCacheIRStubKind stubKind,
- ICStubEngine engine, JSScript* outerScript,
- ICFallbackStub* stub, bool* attached);
+ JSScript* outerScript, ICFallbackStub* stub,
+ bool* attached);
} // namespace jit
} // namespace js
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 0f5414099732..2a621afd9506 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -247,7 +247,7 @@ BaselineCompiler::compile()
for (size_t i = 0; i < icLoadLabels_.length(); i++) {
CodeOffset label = icLoadLabels_[i].label;
size_t icEntry = icLoadLabels_[i].icEntry;
- BaselineICEntry* entryAddr = &(baselineScript->icEntry(icEntry));
+ ICEntry* entryAddr = &(baselineScript->icEntry(icEntry));
Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, label),
ImmPtr(entryAddr),
ImmPtr((void*)-1));
@@ -512,7 +512,7 @@ BaselineCompiler::emitOutOfLinePostBarrierSlot()
bool
BaselineCompiler::emitIC(ICStub* stub, ICEntry::Kind kind)
{
- BaselineICEntry* entry = allocateICEntry(stub, kind);
+ ICEntry* entry = allocateICEntry(stub, kind);
if (!entry)
return false;
@@ -1926,7 +1926,7 @@ BaselineCompiler::emitBinaryArith()
frame.popRegsAndSync(2);
// Call IC
- ICBinaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
+ ICBinaryArith_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@@ -2008,7 +2008,7 @@ BaselineCompiler::emitCompare()
frame.popRegsAndSync(2);
// Call IC.
- ICCompare_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
+ ICCompare_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@@ -2043,7 +2043,7 @@ BaselineCompiler::emit_JSOP_CASE()
frame.syncStack(0);
// Call IC.
- ICCompare_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
+ ICCompare_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@@ -2091,7 +2091,7 @@ BaselineCompiler::emit_JSOP_NEWARRAY()
if (!group)
return false;
- ICNewArray_Fallback::Compiler stubCompiler(cx, group, ICStubCompiler::Engine::Baseline);
+ ICNewArray_Fallback::Compiler stubCompiler(cx, group);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@@ -2155,7 +2155,7 @@ BaselineCompiler::emit_JSOP_NEWOBJECT()
{
frame.syncStack(0);
- ICNewObject_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
+ ICNewObject_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@@ -2168,7 +2168,7 @@ BaselineCompiler::emit_JSOP_NEWINIT()
{
frame.syncStack(0);
- ICNewObject_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
+ ICNewObject_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@@ -2616,7 +2616,7 @@ BaselineCompiler::emit_JSOP_GETPROP()
frame.popRegsAndSync(1);
// Call IC.
- ICGetProp_Fallback::Compiler compiler(cx, ICStubCompiler::Engine::Baseline);
+ ICGetProp_Fallback::Compiler compiler(cx);
if (!emitOpIC(compiler.getStub(&stubSpace_)))
return false;
@@ -2651,8 +2651,7 @@ BaselineCompiler::emit_JSOP_GETPROP_SUPER()
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
frame.pop();
- ICGetProp_Fallback::Compiler compiler(cx, ICStubCompiler::Engine::Baseline,
- /* hasReceiver = */ true);
+ ICGetProp_Fallback::Compiler compiler(cx, /* hasReceiver = */ true);
if (!emitOpIC(compiler.getStub(&stubSpace_)))
return false;
diff --git a/js/src/jit/BaselineDebugModeOSR.cpp b/js/src/jit/BaselineDebugModeOSR.cpp
index 674ee3237c28..da4a2cf607c1 100644
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -218,7 +218,7 @@ CollectJitStackScripts(JSContext* cx, const Debugger::ExecutionObservableSet& ob
} else {
// The frame must be settled on a pc with an ICEntry.
uint8_t* retAddr = frame.returnAddressToFp();
- BaselineICEntry& icEntry = script->baselineScript()->icEntryFromReturnAddress(retAddr);
+ ICEntry& icEntry = script->baselineScript()->icEntryFromReturnAddress(retAddr);
if (!entries.append(DebugModeOSREntry(script, icEntry)))
return false;
}
@@ -498,7 +498,7 @@ PatchBaselineFramesForDebugMode(JSContext* cx,
// callVMs which can trigger debug mode OSR are the *only*
// callVMs generated for their respective pc locations in the
// baseline JIT code.
- BaselineICEntry& callVMEntry = bl->callVMEntryFromPCOffset(pcOffset);
+ ICEntry& callVMEntry = bl->callVMEntryFromPCOffset(pcOffset);
recompInfo->resumeAddr = bl->returnAddressForIC(callVMEntry);
popFrameReg = false;
break;
@@ -510,7 +510,7 @@ PatchBaselineFramesForDebugMode(JSContext* cx,
// Patching mechanism is identical to a CallVM. This is
// handled especially only because the warmup counter VM call is
// part of the prologue, and not tied an opcode.
- BaselineICEntry& warmupCountEntry = bl->warmupCountICEntry();
+ ICEntry& warmupCountEntry = bl->warmupCountICEntry();
recompInfo->resumeAddr = bl->returnAddressForIC(warmupCountEntry);
popFrameReg = false;
break;
@@ -524,7 +524,7 @@ PatchBaselineFramesForDebugMode(JSContext* cx,
// handled especially only because the stack check VM call is
// part of the prologue, and not tied an opcode.
bool earlyCheck = kind == ICEntry::Kind_EarlyStackCheck;
- BaselineICEntry& stackCheckEntry = bl->stackCheckICEntry(earlyCheck);
+ ICEntry& stackCheckEntry = bl->stackCheckICEntry(earlyCheck);
recompInfo->resumeAddr = bl->returnAddressForIC(stackCheckEntry);
popFrameReg = false;
break;
@@ -782,8 +782,8 @@ CloneOldBaselineStub(JSContext* cx, DebugModeOSREntryVector& entries, size_t ent
}
}
- ICStubSpace* stubSpace = ICStubCompiler::StubSpaceForStub(oldStub->makesGCCalls(), entry.script,
- ICStubCompiler::Engine::Baseline);
+ ICStubSpace* stubSpace = ICStubCompiler::StubSpaceForStub(oldStub->makesGCCalls(),
+ entry.script);
// Clone the existing stub into the recompiled IC.
//
diff --git a/js/src/jit/BaselineDebugModeOSR.h b/js/src/jit/BaselineDebugModeOSR.h
index 0854dbe9b3db..0feb2df5d96e 100644
--- a/js/src/jit/BaselineDebugModeOSR.h
+++ b/js/src/jit/BaselineDebugModeOSR.h
@@ -41,30 +41,18 @@ namespace jit {
template
class DebugModeOSRVolatileStub
{
- ICStubCompiler::Engine engine_;
T stub_;
BaselineFrame* frame_;
uint32_t pcOffset_;
public:
- DebugModeOSRVolatileStub(ICStubCompiler::Engine engine, BaselineFrame* frame,
- ICFallbackStub* stub)
- : engine_(engine),
- stub_(static_cast(stub)),
- frame_(frame),
- pcOffset_(stub->icEntry()->pcOffset())
- { }
-
DebugModeOSRVolatileStub(BaselineFrame* frame, ICFallbackStub* stub)
- : engine_(ICStubCompiler::Engine::Baseline),
- stub_(static_cast(stub)),
+ : stub_(static_cast(stub)),
frame_(frame),
pcOffset_(stub->icEntry()->pcOffset())
{ }
bool invalid() const {
- if (engine_ == ICStubCompiler::Engine::IonSharedIC)
- return stub_->invalid();
MOZ_ASSERT(!frame_->isHandlingException());
ICEntry& entry = frame_->script()->baselineScript()->icEntryFromPCOffset(pcOffset_);
return stub_ != entry.fallbackStub();
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 701d72c4ef65..4e301cea8294 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -6,7 +6,10 @@
#include "jit/BaselineIC.h"
+#include "mozilla/Casting.h"
#include "mozilla/DebugOnly.h"
+#include "mozilla/IntegerPrintfMacros.h"
+#include "mozilla/Sprintf.h"
#include "mozilla/TemplateLib.h"
#include "jsfriendapi.h"
@@ -51,6 +54,285 @@ using mozilla::DebugOnly;
namespace js {
namespace jit {
+
+#ifdef JS_JITSPEW
+void
+FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...)
+{
+ if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
+ RootedScript script(cx, GetTopJitJSScript(cx));
+ jsbytecode* pc = stub->icEntry()->pc(script);
+
+ char fmtbuf[100];
+ va_list args;
+ va_start(args, fmt);
+ (void) VsprintfLiteral(fmtbuf, fmt, args);
+ va_end(args);
+
+ JitSpew(JitSpew_BaselineICFallback,
+ "Fallback hit for (%s:%u) (pc=%zu,line=%d,uses=%d,stubs=%zu): %s",
+ script->filename(),
+ script->lineno(),
+ script->pcToOffset(pc),
+ PCToLineNumber(script, pc),
+ script->getWarmUpCount(),
+ stub->numOptimizedStubs(),
+ fmtbuf);
+ }
+}
+
+void
+TypeFallbackICSpew(JSContext* cx, ICTypeMonitor_Fallback* stub, const char* fmt, ...)
+{
+ if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
+ RootedScript script(cx, GetTopJitJSScript(cx));
+ jsbytecode* pc = stub->icEntry()->pc(script);
+
+ char fmtbuf[100];
+ va_list args;
+ va_start(args, fmt);
+ (void) VsprintfLiteral(fmtbuf, fmt, args);
+ va_end(args);
+
+ JitSpew(JitSpew_BaselineICFallback,
+ "Type monitor fallback hit for (%s:%u) (pc=%zu,line=%d,uses=%d,stubs=%d): %s",
+ script->filename(),
+ script->lineno(),
+ script->pcToOffset(pc),
+ PCToLineNumber(script, pc),
+ script->getWarmUpCount(),
+ (int) stub->numOptimizedMonitorStubs(),
+ fmtbuf);
+ }
+}
+#endif // JS_JITSPEW
+
+ICFallbackStub*
+ICEntry::fallbackStub() const
+{
+ return firstStub()->getChainFallback();
+}
+
+void
+ICEntry::trace(JSTracer* trc)
+{
+ if (!hasStub())
+ return;
+ for (ICStub* stub = firstStub(); stub; stub = stub->next())
+ stub->trace(trc);
+}
+
+ICStubConstIterator&
+ICStubConstIterator::operator++()
+{
+ MOZ_ASSERT(currentStub_ != nullptr);
+ currentStub_ = currentStub_->next();
+ return *this;
+}
+
+
+ICStubIterator::ICStubIterator(ICFallbackStub* fallbackStub, bool end)
+ : icEntry_(fallbackStub->icEntry()),
+ fallbackStub_(fallbackStub),
+ previousStub_(nullptr),
+ currentStub_(end ? fallbackStub : icEntry_->firstStub()),
+ unlinked_(false)
+{ }
+
+ICStubIterator&
+ICStubIterator::operator++()
+{
+ MOZ_ASSERT(currentStub_->next() != nullptr);
+ if (!unlinked_)
+ previousStub_ = currentStub_;
+ currentStub_ = currentStub_->next();
+ unlinked_ = false;
+ return *this;
+}
+
+void
+ICStubIterator::unlink(JSContext* cx)
+{
+ MOZ_ASSERT(currentStub_->next() != nullptr);
+ MOZ_ASSERT(currentStub_ != fallbackStub_);
+ MOZ_ASSERT(!unlinked_);
+
+ fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
+
+ // Mark the current iterator position as unlinked, so operator++ works properly.
+ unlinked_ = true;
+}
+
+/* static */ bool
+ICStub::NonCacheIRStubMakesGCCalls(Kind kind)
+{
+ MOZ_ASSERT(IsValidKind(kind));
+ MOZ_ASSERT(!IsCacheIRKind(kind));
+
+ switch (kind) {
+ case Call_Fallback:
+ case Call_Scripted:
+ case Call_AnyScripted:
+ case Call_Native:
+ case Call_ClassHook:
+ case Call_ScriptedApplyArray:
+ case Call_ScriptedApplyArguments:
+ case Call_ScriptedFunCall:
+ case Call_ConstStringSplit:
+ case WarmUpCounter_Fallback:
+ case RetSub_Fallback:
+ // These two fallback stubs don't actually make non-tail calls,
+ // but the fallback code for the bailout path needs to pop the stub frame
+ // pushed during the bailout.
+ case GetProp_Fallback:
+ case SetProp_Fallback:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+ICStub::makesGCCalls() const
+{
+ switch (kind()) {
+ case CacheIR_Regular:
+ return toCacheIR_Regular()->stubInfo()->makesGCCalls();
+ case CacheIR_Monitored:
+ return toCacheIR_Monitored()->stubInfo()->makesGCCalls();
+ case CacheIR_Updated:
+ return toCacheIR_Updated()->stubInfo()->makesGCCalls();
+ default:
+ return NonCacheIRStubMakesGCCalls(kind());
+ }
+}
+
+void
+ICStub::traceCode(JSTracer* trc, const char* name)
+{
+ JitCode* stubJitCode = jitCode();
+ TraceManuallyBarrieredEdge(trc, &stubJitCode, name);
+}
+
+void
+ICStub::updateCode(JitCode* code)
+{
+ // Write barrier on the old code.
+ JitCode::writeBarrierPre(jitCode());
+ stubCode_ = code->raw();
+}
+
+/* static */ void
+ICStub::trace(JSTracer* trc)
+{
+ traceCode(trc, "shared-stub-jitcode");
+
+ // If the stub is a monitored fallback stub, then trace the monitor ICs hanging
+ // off of that stub. We don't need to worry about the regular monitored stubs,
+ // because the regular monitored stubs will always have a monitored fallback stub
+ // that references the same stub chain.
+ if (isMonitoredFallback()) {
+ ICTypeMonitor_Fallback* lastMonStub =
+ toMonitoredFallbackStub()->maybeFallbackMonitorStub();
+ if (lastMonStub) {
+ for (ICStubConstIterator iter(lastMonStub->firstMonitorStub());
+ !iter.atEnd();
+ iter++)
+ {
+ MOZ_ASSERT_IF(iter->next() == nullptr, *iter == lastMonStub);
+ iter->trace(trc);
+ }
+ }
+ }
+
+ if (isUpdated()) {
+ for (ICStubConstIterator iter(toUpdatedStub()->firstUpdateStub()); !iter.atEnd(); iter++) {
+ MOZ_ASSERT_IF(iter->next() == nullptr, iter->isTypeUpdate_Fallback());
+ iter->trace(trc);
+ }
+ }
+
+ switch (kind()) {
+ case ICStub::Call_Scripted: {
+ ICCall_Scripted* callStub = toCall_Scripted();
+ TraceEdge(trc, &callStub->callee(), "baseline-callscripted-callee");
+ TraceNullableEdge(trc, &callStub->templateObject(), "baseline-callscripted-template");
+ break;
+ }
+ case ICStub::Call_Native: {
+ ICCall_Native* callStub = toCall_Native();
+ TraceEdge(trc, &callStub->callee(), "baseline-callnative-callee");
+ TraceNullableEdge(trc, &callStub->templateObject(), "baseline-callnative-template");
+ break;
+ }
+ case ICStub::Call_ClassHook: {
+ ICCall_ClassHook* callStub = toCall_ClassHook();
+ TraceNullableEdge(trc, &callStub->templateObject(), "baseline-callclasshook-template");
+ break;
+ }
+ case ICStub::Call_ConstStringSplit: {
+ ICCall_ConstStringSplit* callStub = toCall_ConstStringSplit();
+ TraceEdge(trc, &callStub->templateObject(), "baseline-callstringsplit-template");
+ TraceEdge(trc, &callStub->expectedSep(), "baseline-callstringsplit-sep");
+ TraceEdge(trc, &callStub->expectedStr(), "baseline-callstringsplit-str");
+ break;
+ }
+ case ICStub::TypeMonitor_SingleObject: {
+ ICTypeMonitor_SingleObject* monitorStub = toTypeMonitor_SingleObject();
+ TraceEdge(trc, &monitorStub->object(), "baseline-monitor-singleton");
+ break;
+ }
+ case ICStub::TypeMonitor_ObjectGroup: {
+ ICTypeMonitor_ObjectGroup* monitorStub = toTypeMonitor_ObjectGroup();
+ TraceEdge(trc, &monitorStub->group(), "baseline-monitor-group");
+ break;
+ }
+ case ICStub::TypeUpdate_SingleObject: {
+ ICTypeUpdate_SingleObject* updateStub = toTypeUpdate_SingleObject();
+ TraceEdge(trc, &updateStub->object(), "baseline-update-singleton");
+ break;
+ }
+ case ICStub::TypeUpdate_ObjectGroup: {
+ ICTypeUpdate_ObjectGroup* updateStub = toTypeUpdate_ObjectGroup();
+ TraceEdge(trc, &updateStub->group(), "baseline-update-group");
+ break;
+ }
+ case ICStub::NewArray_Fallback: {
+ ICNewArray_Fallback* stub = toNewArray_Fallback();
+ TraceNullableEdge(trc, &stub->templateObject(), "baseline-newarray-template");
+ TraceEdge(trc, &stub->templateGroup(), "baseline-newarray-template-group");
+ break;
+ }
+ case ICStub::NewObject_Fallback: {
+ ICNewObject_Fallback* stub = toNewObject_Fallback();
+ TraceNullableEdge(trc, &stub->templateObject(), "baseline-newobject-template");
+ break;
+ }
+ case ICStub::Rest_Fallback: {
+ ICRest_Fallback* stub = toRest_Fallback();
+ TraceEdge(trc, &stub->templateObject(), "baseline-rest-template");
+ break;
+ }
+ case ICStub::CacheIR_Regular:
+ TraceCacheIRStub(trc, this, toCacheIR_Regular()->stubInfo());
+ break;
+ case ICStub::CacheIR_Monitored:
+ TraceCacheIRStub(trc, this, toCacheIR_Monitored()->stubInfo());
+ break;
+ case ICStub::CacheIR_Updated: {
+ ICCacheIR_Updated* stub = toCacheIR_Updated();
+ TraceNullableEdge(trc, &stub->updateStubGroup(), "baseline-update-stub-group");
+ TraceEdge(trc, &stub->updateStubId(), "baseline-update-stub-id");
+ TraceCacheIRStub(trc, this, stub->stubInfo());
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+
//
// WarmUpCounter_Fallback
//
@@ -178,8 +460,6 @@ static const VMFunction DoWarmUpCounterFallbackOSRInfo =
bool
ICWarmUpCounter_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
// Push a stub frame so that we can perform a non-tail call.
enterStubFrame(masm, R1.scratchReg());
@@ -264,6 +544,804 @@ ICWarmUpCounter_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
return true;
}
+
+void
+ICFallbackStub::unlinkStub(Zone* zone, ICStub* prev, ICStub* stub)
+{
+ MOZ_ASSERT(stub->next());
+
+ // If stub is the last optimized stub, update lastStubPtrAddr.
+ if (stub->next() == this) {
+ MOZ_ASSERT(lastStubPtrAddr_ == stub->addressOfNext());
+ if (prev)
+ lastStubPtrAddr_ = prev->addressOfNext();
+ else
+ lastStubPtrAddr_ = icEntry()->addressOfFirstStub();
+ *lastStubPtrAddr_ = this;
+ } else {
+ if (prev) {
+ MOZ_ASSERT(prev->next() == stub);
+ prev->setNext(stub->next());
+ } else {
+ MOZ_ASSERT(icEntry()->firstStub() == stub);
+ icEntry()->setFirstStub(stub->next());
+ }
+ }
+
+ state_.trackUnlinkedStub();
+
+ if (zone->needsIncrementalBarrier()) {
+ // We are removing edges from ICStub to gcthings. Perform one final trace
+ // of the stub for incremental GC, as it must know about those edges.
+ stub->trace(zone->barrierTracer());
+ }
+
+ if (stub->makesGCCalls() && stub->isMonitored()) {
+ // This stub can make calls so we can return to it if it's on the stack.
+ // We just have to reset its firstMonitorStub_ field to avoid a stale
+ // pointer when purgeOptimizedStubs destroys all optimized monitor
+ // stubs (unlinked stubs won't be updated).
+ ICTypeMonitor_Fallback* monitorFallback =
+ toMonitoredFallbackStub()->maybeFallbackMonitorStub();
+ MOZ_ASSERT(monitorFallback);
+ stub->toMonitoredStub()->resetFirstMonitorStub(monitorFallback);
+ }
+
+#ifdef DEBUG
+ // Poison stub code to ensure we don't call this stub again. However, if
+ // this stub can make calls, a pointer to it may be stored in a stub frame
+ // on the stack, so we can't touch the stubCode_ or GC will crash when
+ // tracing this pointer.
+ if (!stub->makesGCCalls())
+ stub->stubCode_ = (uint8_t*)0xbad;
+#endif
+}
+
+void
+ICFallbackStub::unlinkStubsWithKind(JSContext* cx, ICStub::Kind kind)
+{
+ for (ICStubIterator iter = beginChain(); !iter.atEnd(); iter++) {
+ if (iter->kind() == kind)
+ iter.unlink(cx);
+ }
+}
+
+void
+ICFallbackStub::discardStubs(JSContext* cx)
+{
+ for (ICStubIterator iter = beginChain(); !iter.atEnd(); iter++)
+ iter.unlink(cx);
+}
+
+void
+ICTypeMonitor_Fallback::resetMonitorStubChain(Zone* zone)
+{
+ if (zone->needsIncrementalBarrier()) {
+ // We are removing edges from monitored stubs to gcthings (JitCode).
+ // Perform one final trace of all monitor stubs for incremental GC,
+ // as it must know about those edges.
+ for (ICStub* s = firstMonitorStub_; !s->isTypeMonitor_Fallback(); s = s->next())
+ s->trace(zone->barrierTracer());
+ }
+
+ firstMonitorStub_ = this;
+ numOptimizedMonitorStubs_ = 0;
+
+ if (hasFallbackStub_) {
+ lastMonitorStubPtrAddr_ = nullptr;
+
+ // Reset firstMonitorStub_ field of all monitored stubs.
+ for (ICStubConstIterator iter = mainFallbackStub_->beginChainConst();
+ !iter.atEnd(); iter++)
+ {
+ if (!iter->isMonitored())
+ continue;
+ iter->toMonitoredStub()->resetFirstMonitorStub(this);
+ }
+ } else {
+ icEntry_->setFirstStub(this);
+ lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
+ }
+}
+
+void
+ICUpdatedStub::resetUpdateStubChain(Zone* zone)
+{
+ while (!firstUpdateStub_->isTypeUpdate_Fallback()) {
+ if (zone->needsIncrementalBarrier()) {
+ // We are removing edges from update stubs to gcthings (JitCode).
+ // Perform one final trace of all update stubs for incremental GC,
+ // as it must know about those edges.
+ firstUpdateStub_->trace(zone->barrierTracer());
+ }
+ firstUpdateStub_ = firstUpdateStub_->next();
+ }
+
+ numOptimizedStubs_ = 0;
+}
+
+ICMonitoredStub::ICMonitoredStub(Kind kind, JitCode* stubCode, ICStub* firstMonitorStub)
+ : ICStub(kind, ICStub::Monitored, stubCode),
+ firstMonitorStub_(firstMonitorStub)
+{
+ // In order to silence Coverity - null pointer dereference checker
+ MOZ_ASSERT(firstMonitorStub_);
+ // If the first monitored stub is a ICTypeMonitor_Fallback stub, then
+ // double check that _its_ firstMonitorStub is the same as this one.
+ MOZ_ASSERT_IF(firstMonitorStub_->isTypeMonitor_Fallback(),
+ firstMonitorStub_->toTypeMonitor_Fallback()->firstMonitorStub() ==
+ firstMonitorStub_);
+}
+
+bool
+ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx, JSScript* script)
+{
+ MOZ_ASSERT(fallbackMonitorStub_ == nullptr);
+
+ ICTypeMonitor_Fallback::Compiler compiler(cx, this);
+ ICStubSpace* space = script->baselineScript()->fallbackStubSpace();
+ ICTypeMonitor_Fallback* stub = compiler.getStub(space);
+ if (!stub)
+ return false;
+ fallbackMonitorStub_ = stub;
+ return true;
+}
+
+bool
+ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
+ StackTypeSet* types, HandleValue val)
+{
+ ICTypeMonitor_Fallback* typeMonitorFallback = getFallbackMonitorStub(cx, frame->script());
+ if (!typeMonitorFallback)
+ return false;
+ return typeMonitorFallback->addMonitorStubForValue(cx, frame, types, val);
+}
+
+bool
+ICUpdatedStub::initUpdatingChain(JSContext* cx, ICStubSpace* space)
+{
+ MOZ_ASSERT(firstUpdateStub_ == nullptr);
+
+ ICTypeUpdate_Fallback::Compiler compiler(cx);
+ ICTypeUpdate_Fallback* stub = compiler.getStub(space);
+ if (!stub)
+ return false;
+
+ firstUpdateStub_ = stub;
+ return true;
+}
+
+JitCode*
+ICStubCompiler::getStubCode()
+{
+ JitRealm* realm = cx->realm()->jitRealm();
+
+ // Check for existing cached stubcode.
+ uint32_t stubKey = getKey();
+ JitCode* stubCode = realm->getStubCode(stubKey);
+ if (stubCode)
+ return stubCode;
+
+ // Compile new stubcode.
+ JitContext jctx(cx, nullptr);
+ StackMacroAssembler masm;
+#ifndef JS_USE_LINK_REGISTER
+ // The first value contains the return addres,
+ // which we pull into ICTailCallReg for tail calls.
+ masm.adjustFrame(sizeof(intptr_t));
+#endif
+#ifdef JS_CODEGEN_ARM
+ masm.setSecondScratchReg(BaselineSecondScratchReg);
+#endif
+
+ if (!generateStubCode(masm))
+ return nullptr;
+ Linker linker(masm);
+ AutoFlushICache afc("getStubCode");
+ Rooted newStubCode(cx, linker.newCode(cx, CodeKind::Baseline));
+ if (!newStubCode)
+ return nullptr;
+
+ // Cache newly compiled stubcode.
+ if (!realm->putStubCode(cx, stubKey, newStubCode))
+ return nullptr;
+
+ // After generating code, run postGenerateStubCode(). We must not fail
+ // after this point.
+ postGenerateStubCode(masm, newStubCode);
+
+ MOZ_ASSERT(entersStubFrame_ == ICStub::NonCacheIRStubMakesGCCalls(kind));
+ MOZ_ASSERT(!inStubFrame_);
+
+#ifdef JS_ION_PERF
+ writePerfSpewerJitCodeProfile(newStubCode, "BaselineIC");
+#endif
+
+ return newStubCode;
+}
+
+bool
+ICStubCompiler::tailCallVM(const VMFunction& fun, MacroAssembler& masm)
+{
+ TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
+ MOZ_ASSERT(fun.expectTailCall == TailCall);
+ uint32_t argSize = fun.explicitStackSlots() * sizeof(void*);
+ EmitBaselineTailCallVM(code, masm, argSize);
+ return true;
+}
+
+bool
+ICStubCompiler::callVM(const VMFunction& fun, MacroAssembler& masm)
+{
+ MOZ_ASSERT(inStubFrame_);
+
+ TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
+ MOZ_ASSERT(fun.expectTailCall == NonTailCall);
+
+ EmitBaselineCallVM(code, masm);
+ return true;
+}
+
+void
+ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch)
+{
+ EmitBaselineEnterStubFrame(masm, scratch);
+#ifdef DEBUG
+ framePushedAtEnterStubFrame_ = masm.framePushed();
+#endif
+
+ MOZ_ASSERT(!inStubFrame_);
+ inStubFrame_ = true;
+
+#ifdef DEBUG
+ entersStubFrame_ = true;
+#endif
+}
+
+void
+ICStubCompiler::assumeStubFrame()
+{
+ MOZ_ASSERT(!inStubFrame_);
+ inStubFrame_ = true;
+
+#ifdef DEBUG
+ entersStubFrame_ = true;
+
+ // |framePushed| isn't tracked precisely in ICStubs, so simply assume it to
+ // be STUB_FRAME_SIZE so that assertions don't fail in leaveStubFrame.
+ framePushedAtEnterStubFrame_ = STUB_FRAME_SIZE;
+#endif
+}
+
+void
+ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon)
+{
+ MOZ_ASSERT(entersStubFrame_ && inStubFrame_);
+ inStubFrame_ = false;
+
+#ifdef DEBUG
+ masm.setFramePushed(framePushedAtEnterStubFrame_);
+ if (calledIntoIon)
+ masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
+#endif
+ EmitBaselineLeaveStubFrame(masm, calledIntoIon);
+}
+
+void
+ICStubCompiler::pushStubPayload(MacroAssembler& masm, Register scratch)
+{
+ if (inStubFrame_) {
+ masm.loadPtr(Address(BaselineFrameReg, 0), scratch);
+ masm.pushBaselineFramePtr(scratch, scratch);
+ } else {
+ masm.pushBaselineFramePtr(BaselineFrameReg, scratch);
+ }
+}
+
+void
+ICStubCompiler::PushStubPayload(MacroAssembler& masm, Register scratch)
+{
+ pushStubPayload(masm, scratch);
+ masm.adjustFrame(sizeof(intptr_t));
+}
+
+//
+void
+BaselineScript::noteAccessedGetter(uint32_t pcOffset)
+{
+ ICEntry& entry = icEntryFromPCOffset(pcOffset);
+ ICFallbackStub* stub = entry.fallbackStub();
+
+ if (stub->isGetProp_Fallback())
+ stub->toGetProp_Fallback()->noteAccessedGetter();
+}
+
+// TypeMonitor_Fallback
+//
+
+bool
+ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
+ StackTypeSet* types, HandleValue val)
+{
+ MOZ_ASSERT(types);
+
+ // Don't attach too many SingleObject/ObjectGroup stubs. If the value is a
+ // primitive or if we will attach an any-object stub, we can handle this
+ // with a single PrimitiveSet or AnyValue stub so we always optimize.
+ if (numOptimizedMonitorStubs_ >= MAX_OPTIMIZED_STUBS &&
+ val.isObject() &&
+ !types->unknownObject())
+ {
+ return true;
+ }
+
+ bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr;
+ MOZ_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0);
+
+ if (types->unknown()) {
+ // The TypeSet got marked as unknown so attach a stub that always
+ // succeeds.
+
+ // Check for existing TypeMonitor_AnyValue stubs.
+ for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
+ if (iter->isTypeMonitor_AnyValue())
+ return true;
+ }
+
+ // Discard existing stubs.
+ resetMonitorStubChain(cx->zone());
+ wasDetachedMonitorChain = (lastMonitorStubPtrAddr_ == nullptr);
+
+ ICTypeMonitor_AnyValue::Compiler compiler(cx);
+ ICStub* stub = compiler.getStub(compiler.getStubSpace(frame->script()));
+ if (!stub) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+
+ JitSpew(JitSpew_BaselineIC, " Added TypeMonitor stub %p for any value", stub);
+ addOptimizedMonitorStub(stub);
+
+ } else if (val.isPrimitive() || types->unknownObject()) {
+ if (val.isMagic(JS_UNINITIALIZED_LEXICAL))
+ return true;
+ MOZ_ASSERT(!val.isMagic());
+ JSValueType type = val.isDouble() ? JSVAL_TYPE_DOUBLE : val.extractNonDoubleType();
+
+ // Check for existing TypeMonitor stub.
+ ICTypeMonitor_PrimitiveSet* existingStub = nullptr;
+ for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
+ if (iter->isTypeMonitor_PrimitiveSet()) {
+ existingStub = iter->toTypeMonitor_PrimitiveSet();
+ if (existingStub->containsType(type))
+ return true;
+ }
+ }
+
+ if (val.isObject()) {
+ // Check for existing SingleObject/ObjectGroup stubs and discard
+ // stubs if we find one. Ideally we would discard just these stubs,
+ // but unlinking individual type monitor stubs is somewhat
+ // complicated.
+ MOZ_ASSERT(types->unknownObject());
+ bool hasObjectStubs = false;
+ for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
+ if (iter->isTypeMonitor_SingleObject() || iter->isTypeMonitor_ObjectGroup()) {
+ hasObjectStubs = true;
+ break;
+ }
+ }
+ if (hasObjectStubs) {
+ resetMonitorStubChain(cx->zone());
+ wasDetachedMonitorChain = (lastMonitorStubPtrAddr_ == nullptr);
+ existingStub = nullptr;
+ }
+ }
+
+ ICTypeMonitor_PrimitiveSet::Compiler compiler(cx, existingStub, type);
+ ICStub* stub = existingStub
+ ? compiler.updateStub()
+ : compiler.getStub(compiler.getStubSpace(frame->script()));
+ if (!stub) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+
+ JitSpew(JitSpew_BaselineIC, " %s TypeMonitor stub %p for primitive type %d",
+ existingStub ? "Modified existing" : "Created new", stub, type);
+
+ if (!existingStub) {
+ MOZ_ASSERT(!hasStub(TypeMonitor_PrimitiveSet));
+ addOptimizedMonitorStub(stub);
+ }
+
+ } else if (val.toObject().isSingleton()) {
+ RootedObject obj(cx, &val.toObject());
+
+ // Check for existing TypeMonitor stub.
+ for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
+ if (iter->isTypeMonitor_SingleObject() &&
+ iter->toTypeMonitor_SingleObject()->object() == obj)
+ {
+ return true;
+ }
+ }
+
+ ICTypeMonitor_SingleObject::Compiler compiler(cx, obj);
+ ICStub* stub = compiler.getStub(compiler.getStubSpace(frame->script()));
+ if (!stub) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+
+ JitSpew(JitSpew_BaselineIC, " Added TypeMonitor stub %p for singleton %p",
+ stub, obj.get());
+
+ addOptimizedMonitorStub(stub);
+
+ } else {
+ RootedObjectGroup group(cx, val.toObject().group());
+
+ // Check for existing TypeMonitor stub.
+ for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
+ if (iter->isTypeMonitor_ObjectGroup() &&
+ iter->toTypeMonitor_ObjectGroup()->group() == group)
+ {
+ return true;
+ }
+ }
+
+ ICTypeMonitor_ObjectGroup::Compiler compiler(cx, group);
+ ICStub* stub = compiler.getStub(compiler.getStubSpace(frame->script()));
+ if (!stub) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+
+ JitSpew(JitSpew_BaselineIC, " Added TypeMonitor stub %p for ObjectGroup %p",
+ stub, group.get());
+
+ addOptimizedMonitorStub(stub);
+ }
+
+ bool firstMonitorStubAdded = wasDetachedMonitorChain && (numOptimizedMonitorStubs_ > 0);
+
+ if (firstMonitorStubAdded) {
+ // Was an empty monitor chain before, but a new stub was added. This is the
+ // only time that any main stubs' firstMonitorStub fields need to be updated to
+ // refer to the newly added monitor stub.
+ ICStub* firstStub = mainFallbackStub_->icEntry()->firstStub();
+ for (ICStubConstIterator iter(firstStub); !iter.atEnd(); iter++) {
+ // Non-monitored stubs are used if the result has always the same type,
+ // e.g. a StringLength stub will always return int32.
+ if (!iter->isMonitored())
+ continue;
+
+ // Since we just added the first optimized monitoring stub, any
+ // existing main stub's |firstMonitorStub| MUST be pointing to the fallback
+ // monitor stub (i.e. this stub).
+ MOZ_ASSERT(iter->toMonitoredStub()->firstMonitorStub() == this);
+ iter->toMonitoredStub()->updateFirstMonitorStub(firstMonitorStub_);
+ }
+ }
+
+ return true;
+}
+
+static bool
+DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallback* stub,
+ HandleValue value, MutableHandleValue res)
+{
+ JSScript* script = frame->script();
+ jsbytecode* pc = stub->icEntry()->pc(script);
+ TypeFallbackICSpew(cx, stub, "TypeMonitor");
+
+ // Copy input value to res.
+ res.set(value);
+
+ if (MOZ_UNLIKELY(value.isMagic())) {
+ // It's possible that we arrived here from bailing out of Ion, and that
+ // Ion proved that the value is dead and optimized out. In such cases,
+ // do nothing. However, it's also possible that we have an uninitialized
+ // this, in which case we should not look for other magic values.
+
+ if (value.whyMagic() == JS_OPTIMIZED_OUT) {
+ MOZ_ASSERT(!stub->monitorsThis());
+ return true;
+ }
+
+ // In derived class constructors (including nested arrows/eval), the
+ // |this| argument or GETALIASEDVAR can return the magic TDZ value.
+ MOZ_ASSERT(value.isMagic(JS_UNINITIALIZED_LEXICAL));
+ MOZ_ASSERT(frame->isFunctionFrame() || frame->isEvalFrame());
+ MOZ_ASSERT(stub->monitorsThis() ||
+ *GetNextPc(pc) == JSOP_CHECKTHIS ||
+ *GetNextPc(pc) == JSOP_CHECKTHISREINIT ||
+ *GetNextPc(pc) == JSOP_CHECKRETURN);
+ if (stub->monitorsThis())
+ TypeScript::SetThis(cx, script, TypeSet::UnknownType());
+ else
+ TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType());
+ return true;
+ }
+
+ StackTypeSet* types;
+ uint32_t argument;
+ if (stub->monitorsArgument(&argument)) {
+ MOZ_ASSERT(pc == script->code());
+ types = TypeScript::ArgTypes(script, argument);
+ TypeScript::SetArgument(cx, script, argument, value);
+ } else if (stub->monitorsThis()) {
+ MOZ_ASSERT(pc == script->code());
+ types = TypeScript::ThisTypes(script);
+ TypeScript::SetThis(cx, script, value);
+ } else {
+ types = TypeScript::BytecodeTypes(script, pc);
+ TypeScript::Monitor(cx, script, pc, types, value);
+ }
+
+ if (MOZ_UNLIKELY(stub->invalid()))
+ return true;
+
+ return stub->addMonitorStubForValue(cx, frame, types, value);
+}
+
+typedef bool (*DoTypeMonitorFallbackFn)(JSContext*, BaselineFrame*, ICTypeMonitor_Fallback*,
+ HandleValue, MutableHandleValue);
+static const VMFunction DoTypeMonitorFallbackInfo =
+ FunctionInfo(DoTypeMonitorFallback, "DoTypeMonitorFallback",
+ TailCall);
+
+bool
+ICTypeMonitor_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
+{
+ MOZ_ASSERT(R0 == JSReturnOperand);
+
+ // Restore the tail call register.
+ EmitRestoreTailCallReg(masm);
+
+ masm.pushValue(R0);
+ masm.push(ICStubReg);
+ masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
+
+ return tailCallVM(DoTypeMonitorFallbackInfo, masm);
+}
+
+bool
+ICTypeMonitor_PrimitiveSet::Compiler::generateStubCode(MacroAssembler& masm)
+{
+ Label success;
+ if ((flags_ & TypeToFlag(JSVAL_TYPE_INT32)) && !(flags_ & TypeToFlag(JSVAL_TYPE_DOUBLE)))
+ masm.branchTestInt32(Assembler::Equal, R0, &success);
+
+ if (flags_ & TypeToFlag(JSVAL_TYPE_DOUBLE))
+ masm.branchTestNumber(Assembler::Equal, R0, &success);
+
+ if (flags_ & TypeToFlag(JSVAL_TYPE_UNDEFINED))
+ masm.branchTestUndefined(Assembler::Equal, R0, &success);
+
+ if (flags_ & TypeToFlag(JSVAL_TYPE_BOOLEAN))
+ masm.branchTestBoolean(Assembler::Equal, R0, &success);
+
+ if (flags_ & TypeToFlag(JSVAL_TYPE_STRING))
+ masm.branchTestString(Assembler::Equal, R0, &success);
+
+ if (flags_ & TypeToFlag(JSVAL_TYPE_SYMBOL))
+ masm.branchTestSymbol(Assembler::Equal, R0, &success);
+
+ if (flags_ & TypeToFlag(JSVAL_TYPE_OBJECT))
+ masm.branchTestObject(Assembler::Equal, R0, &success);
+
+ if (flags_ & TypeToFlag(JSVAL_TYPE_NULL))
+ masm.branchTestNull(Assembler::Equal, R0, &success);
+
+ EmitStubGuardFailure(masm);
+
+ masm.bind(&success);
+ EmitReturnFromIC(masm);
+ return true;
+}
+
+static void
+MaybeWorkAroundAmdBug(MacroAssembler& masm)
+{
+ // Attempt to work around an AMD bug (see bug 1034706 and bug 1281759), by
+ // inserting 32-bytes of NOPs.
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+ if (CPUInfo::NeedAmdBugWorkaround()) {
+ masm.nop(9);
+ masm.nop(9);
+ masm.nop(9);
+ masm.nop(5);
+ }
+#endif
+}
+
+bool
+ICTypeMonitor_SingleObject::Compiler::generateStubCode(MacroAssembler& masm)
+{
+ Label failure;
+ masm.branchTestObject(Assembler::NotEqual, R0, &failure);
+ MaybeWorkAroundAmdBug(masm);
+
+ // Guard on the object's identity.
+ Register obj = masm.extractObject(R0, ExtractTemp0);
+ Address expectedObject(ICStubReg, ICTypeMonitor_SingleObject::offsetOfObject());
+ masm.branchPtr(Assembler::NotEqual, expectedObject, obj, &failure);
+ MaybeWorkAroundAmdBug(masm);
+
+ EmitReturnFromIC(masm);
+ MaybeWorkAroundAmdBug(masm);
+
+ masm.bind(&failure);
+ EmitStubGuardFailure(masm);
+ return true;
+}
+
+bool
+ICTypeMonitor_ObjectGroup::Compiler::generateStubCode(MacroAssembler& masm)
+{
+ Label failure;
+ masm.branchTestObject(Assembler::NotEqual, R0, &failure);
+ MaybeWorkAroundAmdBug(masm);
+
+ // Guard on the object's ObjectGroup. No Spectre mitigations are needed
+ // here: we're just recording type information for Ion compilation and
+ // it's safe to speculatively return.
+ Register obj = masm.extractObject(R0, ExtractTemp0);
+ Address expectedGroup(ICStubReg, ICTypeMonitor_ObjectGroup::offsetOfGroup());
+ masm.branchTestObjGroupNoSpectreMitigations(Assembler::NotEqual, obj, expectedGroup,
+ R1.scratchReg(), &failure);
+ MaybeWorkAroundAmdBug(masm);
+
+ EmitReturnFromIC(masm);
+ MaybeWorkAroundAmdBug(masm);
+
+ masm.bind(&failure);
+ EmitStubGuardFailure(masm);
+ return true;
+}
+
+bool
+ICTypeMonitor_AnyValue::Compiler::generateStubCode(MacroAssembler& masm)
+{
+ EmitReturnFromIC(masm);
+ return true;
+}
+
+bool
+ICUpdatedStub::addUpdateStubForValue(JSContext* cx, HandleScript outerScript, HandleObject obj,
+ HandleObjectGroup group, HandleId id, HandleValue val)
+{
+ EnsureTrackPropertyTypes(cx, obj, id);
+
+ // Make sure that undefined values are explicitly included in the property
+ // types for an object if generating a stub to write an undefined value.
+ if (val.isUndefined() && CanHaveEmptyPropertyTypesForOwnProperty(obj)) {
+ MOZ_ASSERT(obj->group() == group);
+ AddTypePropertyId(cx, obj, id, val);
+ }
+
+ bool unknown = false, unknownObject = false;
+ AutoSweepObjectGroup sweep(group);
+ if (group->unknownProperties(sweep)) {
+ unknown = unknownObject = true;
+ } else {
+ if (HeapTypeSet* types = group->maybeGetProperty(sweep, id)) {
+ unknown = types->unknown();
+ unknownObject = types->unknownObject();
+ } else {
+ // We don't record null/undefined types for certain TypedObject
+ // properties. In these cases |types| is allowed to be nullptr
+ // without implying unknown types. See DoTypeUpdateFallback.
+ MOZ_ASSERT(obj->is());
+ MOZ_ASSERT(val.isNullOrUndefined());
+ }
+ }
+ MOZ_ASSERT_IF(unknown, unknownObject);
+
+ // Don't attach too many SingleObject/ObjectGroup stubs unless we can
+ // replace them with a single PrimitiveSet or AnyValue stub.
+ if (numOptimizedStubs_ >= MAX_OPTIMIZED_STUBS &&
+ val.isObject() &&
+ !unknownObject)
+ {
+ return true;
+ }
+
+ if (unknown) {
+ // Attach a stub that always succeeds. We should not have a
+ // TypeUpdate_AnyValue stub yet.
+ MOZ_ASSERT(!hasTypeUpdateStub(TypeUpdate_AnyValue));
+
+ // Discard existing stubs.
+ resetUpdateStubChain(cx->zone());
+
+ ICTypeUpdate_AnyValue::Compiler compiler(cx);
+ ICStub* stub = compiler.getStub(compiler.getStubSpace(outerScript));
+ if (!stub)
+ return false;
+
+ JitSpew(JitSpew_BaselineIC, " Added TypeUpdate stub %p for any value", stub);
+ addOptimizedUpdateStub(stub);
+
+ } else if (val.isPrimitive() || unknownObject) {
+ JSValueType type = val.isDouble() ? JSVAL_TYPE_DOUBLE : val.extractNonDoubleType();
+
+ // Check for existing TypeUpdate stub.
+ ICTypeUpdate_PrimitiveSet* existingStub = nullptr;
+ for (ICStubConstIterator iter(firstUpdateStub_); !iter.atEnd(); iter++) {
+ if (iter->isTypeUpdate_PrimitiveSet()) {
+ existingStub = iter->toTypeUpdate_PrimitiveSet();
+ MOZ_ASSERT(!existingStub->containsType(type));
+ }
+ }
+
+ if (val.isObject()) {
+ // Discard existing ObjectGroup/SingleObject stubs.
+ resetUpdateStubChain(cx->zone());
+ if (existingStub)
+ addOptimizedUpdateStub(existingStub);
+ }
+
+ ICTypeUpdate_PrimitiveSet::Compiler compiler(cx, existingStub, type);
+ ICStub* stub = existingStub ? compiler.updateStub()
+ : compiler.getStub(compiler.getStubSpace(outerScript));
+ if (!stub)
+ return false;
+ if (!existingStub) {
+ MOZ_ASSERT(!hasTypeUpdateStub(TypeUpdate_PrimitiveSet));
+ addOptimizedUpdateStub(stub);
+ }
+
+ JitSpew(JitSpew_BaselineIC, " %s TypeUpdate stub %p for primitive type %d",
+ existingStub ? "Modified existing" : "Created new", stub, type);
+
+ } else if (val.toObject().isSingleton()) {
+ RootedObject obj(cx, &val.toObject());
+
+#ifdef DEBUG
+ // We should not have a stub for this object.
+ for (ICStubConstIterator iter(firstUpdateStub_); !iter.atEnd(); iter++) {
+ MOZ_ASSERT_IF(iter->isTypeUpdate_SingleObject(),
+ iter->toTypeUpdate_SingleObject()->object() != obj);
+ }
+#endif
+
+ ICTypeUpdate_SingleObject::Compiler compiler(cx, obj);
+ ICStub* stub = compiler.getStub(compiler.getStubSpace(outerScript));
+ if (!stub)
+ return false;
+
+ JitSpew(JitSpew_BaselineIC, " Added TypeUpdate stub %p for singleton %p", stub, obj.get());
+
+ addOptimizedUpdateStub(stub);
+
+ } else {
+ RootedObjectGroup group(cx, val.toObject().group());
+
+#ifdef DEBUG
+ // We should not have a stub for this group.
+ for (ICStubConstIterator iter(firstUpdateStub_); !iter.atEnd(); iter++) {
+ MOZ_ASSERT_IF(iter->isTypeUpdate_ObjectGroup(),
+ iter->toTypeUpdate_ObjectGroup()->group() != group);
+ }
+#endif
+
+ ICTypeUpdate_ObjectGroup::Compiler compiler(cx, group);
+ ICStub* stub = compiler.getStub(compiler.getStubSpace(outerScript));
+ if (!stub)
+ return false;
+
+ JitSpew(JitSpew_BaselineIC, " Added TypeUpdate stub %p for ObjectGroup %p",
+ stub, group.get());
+
+ addOptimizedUpdateStub(stub);
+ }
+
+ return true;
+}
+
//
// TypeUpdate_Fallback
//
@@ -346,8 +1424,6 @@ const VMFunction DoTypeUpdateFallbackInfo =
bool
ICTypeUpdate_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
// Just store false into R1.scratchReg() and return.
masm.move32(Imm32(0), R1.scratchReg());
EmitReturnFromIC(masm);
@@ -357,8 +1433,6 @@ ICTypeUpdate_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICTypeUpdate_PrimitiveSet::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label success;
if ((flags_ & TypeToFlag(JSVAL_TYPE_INT32)) && !(flags_ & TypeToFlag(JSVAL_TYPE_DOUBLE)))
masm.branchTestInt32(Assembler::Equal, R0, &success);
@@ -397,8 +1471,6 @@ ICTypeUpdate_PrimitiveSet::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICTypeUpdate_SingleObject::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
@@ -419,8 +1491,6 @@ ICTypeUpdate_SingleObject::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICTypeUpdate_ObjectGroup::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
@@ -469,14 +1539,13 @@ DoToBoolFallback(JSContext* cx, BaselineFrame* frame, ICToBool_Fallback* stub, H
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
- ICStubEngine engine = ICStubEngine::Baseline;
ToBoolIRGenerator gen(cx, script, pc, stub->state().mode(),
arg);
bool attached = false;
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached ToBool CacheIR stub, attached is now %d", attached);
}
@@ -497,7 +1566,6 @@ static const VMFunction fun = FunctionInfo(DoToBoolFallback, "DoToBoolFallba
bool
ICToBool_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@@ -532,7 +1600,6 @@ static const VMFunction DoToNumberFallbackInfo =
bool
ICToNumber_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@@ -548,6 +1615,28 @@ ICToNumber_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
return tailCallVM(DoToNumberFallbackInfo, masm);
}
+static void
+StripPreliminaryObjectStubs(JSContext* cx, ICFallbackStub* stub)
+{
+ // Before the new script properties analysis has been performed on a type,
+ // all instances of that type have the maximum number of fixed slots.
+ // Afterwards, the objects (even the preliminary ones) might be changed
+ // to reduce the number of fixed slots they have. If we generate stubs for
+ // both the old and new number of fixed slots, the stub will look
+ // polymorphic to IonBuilder when it is actually monomorphic. To avoid
+ // this, strip out any stubs for preliminary objects before attaching a new
+ // stub which isn't on a preliminary object.
+
+ for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
+ if (iter->isCacheIR_Regular() && iter->toCacheIR_Regular()->hasPreliminaryObject())
+ iter.unlink(cx);
+ else if (iter->isCacheIR_Monitored() && iter->toCacheIR_Monitored()->hasPreliminaryObject())
+ iter.unlink(cx);
+ else if (iter->isCacheIR_Updated() && iter->toCacheIR_Updated()->hasPreliminaryObject())
+ iter.unlink(cx);
+ }
+}
+
//
// GetElem_Fallback
//
@@ -587,7 +1676,6 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
stub->discardStubs(cx);
if (stub->state().canAttachStub()) {
- ICStubEngine engine = ICStubEngine::Baseline;
GetPropIRGenerator gen(cx, script, pc,
CacheKind::GetElem, stub->state().mode(),
&isTemporarilyUnoptimizable, lhs, rhs, lhs,
@@ -595,7 +1683,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached GetElem CacheIR stub");
if (gen.shouldNotePreliminaryObjectStub())
@@ -661,14 +1749,13 @@ DoGetElemSuperFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback*
stub->discardStubs(cx);
if (stub->state().canAttachStub()) {
- ICStubEngine engine = ICStubEngine::Baseline;
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetElemSuper, stub->state().mode(),
&isTemporarilyUnoptimizable, lhs, rhs, receiver,
GetPropertyResultFlags::All);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached GetElemSuper CacheIR stub");
if (gen.shouldNotePreliminaryObjectStub())
@@ -726,7 +1813,6 @@ static const VMFunction DoGetElemSuperFallbackInfo =
bool
ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@@ -765,22 +1851,6 @@ ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
return tailCallVM(DoGetElemFallbackInfo, masm);
}
-void
-LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result)
-{
- switch (layout) {
- case Layout_TypedArray:
- masm.unboxInt32(Address(obj, TypedArrayObject::lengthOffset()), result);
- break;
- case Layout_OutlineTypedObject:
- case Layout_InlineTypedObject:
- masm.loadTypedObjectLength(obj, result);
- break;
- default:
- MOZ_CRASH();
- }
-}
-
static void
SetUpdateStubData(ICCacheIR_Updated* stub, const PropertyTypeCheckInfo* info)
{
@@ -837,8 +1907,7 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Updated,
- ICStubEngine::Baseline, frame->script(),
- stub, &attached);
+ frame->script(), stub, &attached);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached SetElem CacheIR stub");
@@ -901,8 +1970,7 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
if (gen.tryAttachAddSlotStub(oldGroup, oldShape)) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Updated,
- ICStubEngine::Baseline, frame->script(),
- stub, &attached);
+ frame->script(), stub, &attached);
if (newStub) {
if (gen.shouldNotePreliminaryObjectStub())
newStub->toCacheIR_Updated()->notePreliminaryObject();
@@ -932,7 +2000,6 @@ static const VMFunction DoSetElemFallbackInfo =
bool
ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@@ -1093,13 +2160,12 @@ DoInFallback(JSContext* cx, BaselineFrame* frame, ICIn_Fallback* stub_,
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
- ICStubEngine engine = ICStubEngine::Baseline;
HasPropIRGenerator gen(cx, script, pc, CacheKind::In, stub->state().mode(), key, objValue);
bool attached = false;
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached In CacheIR stub");
}
@@ -1124,8 +2190,6 @@ static const VMFunction DoInFallbackInfo =
bool
ICIn_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
// Sync for the decompiler.
@@ -1161,14 +2225,13 @@ DoHasOwnFallback(JSContext* cx, BaselineFrame* frame, ICHasOwn_Fallback* stub_,
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
- ICStubEngine engine = ICStubEngine::Baseline;
HasPropIRGenerator gen(cx, script, pc, CacheKind::HasOwn,
stub->state().mode(), keyValue, objValue);
bool attached = false;
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached HasOwn CacheIR stub");
}
@@ -1192,8 +2255,6 @@ static const VMFunction DoHasOwnFallbackInfo =
bool
ICHasOwn_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
// Sync for the decompiler.
@@ -1235,12 +2296,11 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
stub->discardStubs(cx);
if (stub->state().canAttachStub()) {
- ICStubEngine engine = ICStubEngine::Baseline;
GetNameIRGenerator gen(cx, script, pc, stub->state().mode(), envChain, name);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached GetName CacheIR stub");
}
@@ -1282,7 +2342,6 @@ static const VMFunction DoGetNameFallbackInfo =
bool
ICGetName_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@@ -1320,8 +2379,7 @@ DoBindNameFallback(JSContext* cx, BaselineFrame* frame, ICBindName_Fallback* stu
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- ICStubEngine::Baseline, script, stub,
- &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached BindName CacheIR stub");
}
@@ -1345,7 +2403,6 @@ static const VMFunction DoBindNameFallbackInfo =
bool
ICBindName_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@@ -1398,8 +2455,7 @@ DoGetIntrinsicFallback(JSContext* cx, BaselineFrame* frame, ICGetIntrinsic_Fallb
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- ICStubEngine::Baseline, script, stub,
- &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached GetIntrinsic CacheIR stub");
}
@@ -1419,8 +2475,6 @@ static const VMFunction DoGetIntrinsicFallbackInfo =
bool
ICGetIntrinsic_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
masm.push(ICStubReg);
@@ -1433,28 +2487,6 @@ ICGetIntrinsic_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
// GetProp_Fallback
//
-void
-StripPreliminaryObjectStubs(JSContext* cx, ICFallbackStub* stub)
-{
- // Before the new script properties analysis has been performed on a type,
- // all instances of that type have the maximum number of fixed slots.
- // Afterwards, the objects (even the preliminary ones) might be changed
- // to reduce the number of fixed slots they have. If we generate stubs for
- // both the old and new number of fixed slots, the stub will look
- // polymorphic to IonBuilder when it is actually monomorphic. To avoid
- // this, strip out any stubs for preliminary objects before attaching a new
- // stub which isn't on a preliminary object.
-
- for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
- if (iter->isCacheIR_Regular() && iter->toCacheIR_Regular()->hasPreliminaryObject())
- iter.unlink(cx);
- else if (iter->isCacheIR_Monitored() && iter->toCacheIR_Monitored()->hasPreliminaryObject())
- iter.unlink(cx);
- else if (iter->isCacheIR_Updated() && iter->toCacheIR_Updated()->hasPreliminaryObject())
- iter.unlink(cx);
- }
-}
-
static bool
ComputeGetPropResult(JSContext* cx, BaselineFrame* frame, JSOp op, HandlePropertyName name,
MutableHandleValue val, MutableHandleValue res)
@@ -1522,8 +2554,7 @@ DoGetPropFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback* stub_
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,
- ICStubEngine::Baseline, script,
- stub, &attached);
+ script, stub, &attached);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");
if (gen.shouldNotePreliminaryObjectStub())
@@ -1593,8 +2624,7 @@ DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback*
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Monitored,
- ICStubEngine::Baseline, script,
- stub, &attached);
+ script, stub, &attached);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");
if (gen.shouldNotePreliminaryObjectStub())
@@ -1697,12 +2727,10 @@ ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
void
ICGetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm, Handle code)
{
- if (engine_ == Engine::Baseline) {
- BailoutReturnStub kind = hasReceiver_ ? BailoutReturnStub::GetPropSuper
- : BailoutReturnStub::GetProp;
- void* address = code->raw() + bailoutReturnOffset_.offset();
- cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
- }
+ BailoutReturnStub kind = hasReceiver_ ? BailoutReturnStub::GetPropSuper
+ : BailoutReturnStub::GetProp;
+ void* address = code->raw() + bailoutReturnOffset_.offset();
+ cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
}
//
@@ -1772,8 +2800,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Updated,
- ICStubEngine::Baseline, frame->script(),
- stub, &attached);
+ frame->script(), stub, &attached);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached SetProp CacheIR stub");
@@ -1844,8 +2871,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
if (gen.tryAttachAddSlotStub(oldGroup, oldShape)) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Updated,
- ICStubEngine::Baseline, frame->script(),
- stub, &attached);
+ frame->script(), stub, &attached);
if (newStub) {
if (gen.shouldNotePreliminaryObjectStub())
newStub->toCacheIR_Updated()->notePreliminaryObject();
@@ -1877,7 +2903,6 @@ static const VMFunction DoSetPropFallbackInfo =
bool
ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@@ -2533,9 +3558,8 @@ DoCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_, uint
HandleValueArray::fromMarkedLocation(argc, vp+2));
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
- gen.cacheIRStubKind(),
- ICStubEngine::Baseline,
- script, stub, &handled);
+ gen.cacheIRStubKind(), script,
+ stub, &handled);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached Call CacheIR stub");
@@ -2973,8 +3997,6 @@ static const VMFunction DoSpreadCallFallbackInfo =
bool
ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
MOZ_ASSERT(R0 == JSReturnOperand);
// Values are on the stack left-to-right. Calling convention wants them
@@ -3101,8 +4123,6 @@ static const VMFunction CreateThisInfoBaseline =
bool
ICCallScriptedCompiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
bool canUseTailCallReg = regs.has(ICTailCallReg);
@@ -3369,8 +4389,6 @@ static const VMFunction CopyStringSplitArrayInfo =
bool
ICCall_ConstStringSplit::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
// Stack Layout: [ ..., CalleeVal, ThisVal, strVal, sepVal, +ICStackValueOffset+ ]
static const size_t SEP_DEPTH = 0;
static const size_t STR_DEPTH = sizeof(Value);
@@ -3469,8 +4487,6 @@ ICCall_ConstStringSplit::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICCall_IsSuspendedGenerator::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
// The IsSuspendedGenerator intrinsic is only called in self-hosted code,
// so it's safe to assume we have a single argument and the callee is our
// intrinsic.
@@ -3514,8 +4530,6 @@ ICCall_IsSuspendedGenerator::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICCall_Native::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
@@ -3627,8 +4641,6 @@ ICCall_Native::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
@@ -3718,8 +4730,6 @@ ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICCall_ScriptedApplyArray::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
@@ -3816,8 +4826,6 @@ ICCall_ScriptedApplyArray::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICCall_ScriptedApplyArguments::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
@@ -3908,8 +4916,6 @@ ICCall_ScriptedApplyArguments::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICCall_ScriptedFunCall::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
bool canUseTailCallReg = regs.has(ICTailCallReg);
@@ -4042,8 +5048,6 @@ DoubleValueToInt32ForSwitch(Value* v)
bool
ICTableSwitch::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label isInt32, notInt32, outOfRange;
Register scratch = R1.scratchReg();
@@ -4160,13 +5164,12 @@ DoGetIteratorFallback(JSContext* cx, BaselineFrame* frame, ICGetIterator_Fallbac
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
- ICStubEngine engine = ICStubEngine::Baseline;
GetIteratorIRGenerator gen(cx, script, pc, stub->state().mode(), value);
bool attached = false;
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached GetIterator CacheIR stub");
}
@@ -4191,8 +5194,6 @@ static const VMFunction DoGetIteratorFallbackInfo =
bool
ICGetIterator_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
// Sync stack for the decompiler.
@@ -4250,8 +5251,6 @@ static const VMFunction DoIteratorMoreFallbackInfo =
bool
ICIteratorMore_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
masm.unboxObject(R0, R0.scratchReg());
@@ -4269,8 +5268,6 @@ ICIteratorMore_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICIteratorMore_Native::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
Label failure;
Register obj = masm.extractObject(R0, ExtractTemp0);
@@ -4330,8 +5327,6 @@ static const VMFunction DoIteratorCloseFallbackInfo =
bool
ICIteratorClose_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
masm.pushValue(R0);
@@ -4358,7 +5353,6 @@ TryAttachInstanceOfStub(JSContext* cx, BaselineFrame* frame, ICInstanceOf_Fallba
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
- ICStubEngine engine = ICStubEngine::Baseline;
InstanceOfIRGenerator gen(cx, script, pc, stub->state().mode(),
lhs,
rhs);
@@ -4366,7 +5360,7 @@ TryAttachInstanceOfStub(JSContext* cx, BaselineFrame* frame, ICInstanceOf_Fallba
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- engine, script, stub, attached);
+ script, stub, attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached InstanceOf CacheIR stub, attached is now %d", *attached);
}
@@ -4382,7 +5376,7 @@ DoInstanceOfFallback(JSContext* cx, BaselineFrame* frame, ICInstanceOf_Fallback*
HandleValue lhs, HandleValue rhs, MutableHandleValue res)
{
// This fallback stub may trigger debug mode toggling.
- DebugModeOSRVolatileStub stub(ICStubEngine::Baseline, frame, stub_);
+ DebugModeOSRVolatileStub stub(frame, stub_);
FallbackICSpew(cx, stub, "InstanceOf");
@@ -4428,8 +5422,6 @@ static const VMFunction DoInstanceOfFallbackInfo =
bool
ICInstanceOf_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
// Sync stack for the decompiler.
@@ -4461,13 +5453,12 @@ DoTypeOfFallback(JSContext* cx, BaselineFrame* frame, ICTypeOf_Fallback* stub, H
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
- ICStubEngine engine = ICStubEngine::Baseline;
TypeOfIRGenerator gen(cx, script, pc, stub->state().mode(), val);
bool attached = false;
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- engine, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached TypeOf CacheIR stub");
}
@@ -4489,8 +5480,6 @@ static const VMFunction DoTypeOfFallbackInfo =
bool
ICTypeOf_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
masm.pushValue(R0);
@@ -4542,8 +5531,6 @@ static const VMFunction ThrowInfoBaseline =
bool
ICRetSub_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
// If R0 is BooleanValue(true), rethrow R1.
Label rethrow;
masm.branchTestBooleanTruthy(true, R0, &rethrow);
@@ -4578,8 +5565,6 @@ ICRetSub_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICRetSub_Resume::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
// If R0 is BooleanValue(true), rethrow R1.
Label fail, rethrow;
masm.branchTestBooleanTruthy(true, R0, &rethrow);
@@ -4761,8 +5746,6 @@ static const VMFunction DoRestFallbackInfo =
bool
ICRest_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
EmitRestoreTailCallReg(masm);
masm.push(ICStubReg);
@@ -4780,7 +5763,7 @@ DoUnaryArithFallback(JSContext* cx, BaselineFrame* frame, ICUnaryArith_Fallback*
HandleValue val, MutableHandleValue res)
{
// This fallback stub may trigger debug mode toggling.
- DebugModeOSRVolatileStub debug_stub(ICStubEngine::Baseline, frame, stub);
+ DebugModeOSRVolatileStub debug_stub(frame, stub);
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
@@ -4823,7 +5806,7 @@ DoUnaryArithFallback(JSContext* cx, BaselineFrame* frame, ICUnaryArith_Fallback*
bool attached = false;
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- ICStubEngine::Baseline, script, stub, &attached);
+ script, stub, &attached);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached UnaryArith CacheIR stub for %s", CodeName[op]);
}
@@ -4867,7 +5850,7 @@ DoBinaryArithFallback(JSContext* cx, BaselineFrame* frame, ICBinaryArith_Fallbac
HandleValue lhs, HandleValue rhs, MutableHandleValue ret)
{
// This fallback stub may trigger debug mode toggling.
- DebugModeOSRVolatileStub stub(ICStubEngine::Baseline, frame, stub_);
+ DebugModeOSRVolatileStub stub(frame, stub_);
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
@@ -4976,7 +5959,7 @@ DoBinaryArithFallback(JSContext* cx, BaselineFrame* frame, ICBinaryArith_Fallbac
bool attached = false;
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- ICStubEngine::Baseline, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached BinaryArith CacheIR stub for %s", CodeName[op]);
@@ -5022,7 +6005,7 @@ DoCompareFallback(JSContext* cx, BaselineFrame* frame, ICCompare_Fallback* stub_
HandleValue rhs, MutableHandleValue ret)
{
// This fallback stub may trigger debug mode toggling.
- DebugModeOSRVolatileStub stub(ICStubEngine::Baseline, frame, stub_);
+ DebugModeOSRVolatileStub stub(frame, stub_);
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
@@ -5098,7 +6081,7 @@ DoCompareFallback(JSContext* cx, BaselineFrame* frame, ICCompare_Fallback* stub_
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- ICStubEngine::Baseline, script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");
return true;
@@ -5192,10 +6175,8 @@ ICNewArray_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
// NewObject_Fallback
//
static bool
-DoNewObject(JSContext* cx, void* payload, ICNewObject_Fallback* stub, MutableHandleValue res)
+DoNewObject(JSContext* cx, BaselineFrame* frame, ICNewObject_Fallback* stub, MutableHandleValue res)
{
- SharedStubInfo info(cx, payload, stub->icEntry());
-
FallbackICSpew(cx, stub, "NewObject");
RootedObject obj(cx);
@@ -5205,8 +6186,8 @@ DoNewObject(JSContext* cx, void* payload, ICNewObject_Fallback* stub, MutableHan
MOZ_ASSERT(!templateObject->group()->maybePreliminaryObjectsDontCheckGeneration());
obj = NewObjectOperationWithTemplate(cx, templateObject);
} else {
- HandleScript script = info.script();
- jsbytecode* pc = info.pc();
+ RootedScript script(cx, frame->script());
+ jsbytecode* pc = stub->icEntry()->pc(script);
obj = NewObjectOperation(cx, script, pc);
if (obj && !obj->isSingleton() &&
@@ -5218,12 +6199,11 @@ DoNewObject(JSContext* cx, void* payload, ICNewObject_Fallback* stub, MutableHan
if (!JitOptions.disableCacheIR) {
bool attached = false;
- RootedScript script(cx, info.outerScript(cx));
NewObjectIRGenerator gen(cx, script, pc, stub->state().mode(), JSOp(*pc), templateObject);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
BaselineCacheIRStubKind::Regular,
- ICStubEngine::Baseline , script, stub, &attached);
+ script, stub, &attached);
if (newStub)
JitSpew(JitSpew_BaselineIC, " NewObject Attached CacheIR stub");
}
@@ -5239,7 +6219,7 @@ DoNewObject(JSContext* cx, void* payload, ICNewObject_Fallback* stub, MutableHan
return true;
}
-typedef bool(*DoNewObjectFn)(JSContext*, void*, ICNewObject_Fallback*, MutableHandleValue);
+typedef bool(*DoNewObjectFn)(JSContext*, BaselineFrame*, ICNewObject_Fallback*, MutableHandleValue);
static const VMFunction DoNewObjectInfo =
FunctionInfo(DoNewObject, "DoNewObject", TailCall);
diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h
index 8eac9cf79ff9..53139bc393ca 100644
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -11,9 +11,10 @@
#include "builtin/TypedObject.h"
#include "gc/Barrier.h"
+#include "gc/GC.h"
#include "jit/BaselineICList.h"
#include "jit/BaselineJIT.h"
-#include "jit/SharedIC.h"
+#include "jit/ICState.h"
#include "jit/SharedICRegisters.h"
#include "js/GCVector.h"
#include "vm/ArrayObject.h"
@@ -25,6 +26,1092 @@
namespace js {
namespace jit {
+// [SMDOC] JIT Inline Caches (ICs)
+//
+// Baseline Inline Caches are polymorphic caches that aggressively
+// share their stub code.
+//
+// Every polymorphic site contains a linked list of stubs which are
+// specific to that site. These stubs are composed of a |StubData|
+// structure that stores parametrization information (e.g.
+// the shape pointer for a shape-check-and-property-get stub), any
+// dynamic information (e.g. warm-up counters), a pointer to the stub code,
+// and a pointer to the next stub state in the linked list.
+//
+// Every BaselineScript keeps an table of |CacheDescriptor| data
+// structures, which store the following:
+// A pointer to the first StubData in the cache.
+// The bytecode PC of the relevant IC.
+// The machine-code PC where the call to the stubcode returns.
+//
+// A diagram:
+//
+// Control flow Pointers
+// =======# ----. .---->
+// # | |
+// #======> \-----/
+//
+//
+// .---------------------------------------.
+// | .-------------------------. |
+// | | .----. | |
+// Baseline | | | | | |
+// JIT Code 0 ^ 1 ^ 2 ^ | | |
+// +--------------+ .-->+-----+ +-----+ +-----+ | | |
+// | | #=|==>| |==>| |==>| FB | | | |
+// | | # | +-----+ +-----+ +-----+ | | |
+// | | # | # # # | | |
+// |==============|==# | # # # | | |
+// |=== IC =======| | # # # | | |
+// .->|==============|<===|======#=========#=========# | | |
+// | | | | | | |
+// | | | | | | |
+// | | | | | | |
+// | | | | v | |
+// | | | | +---------+ | |
+// | | | | | Fallback| | |
+// | | | | | Stub | | |
+// | | | | | Code | | |
+// | | | | +---------+ | |
+// | +--------------+ | | |
+// | |_______ | +---------+ | |
+// | | | | Stub |<---/ |
+// | IC | \--. | Code | |
+// | Descriptor | | +---------+ |
+// | Table v | |
+// | +-----------------+ | +---------+ |
+// \--| Ins | PC | Stub |----/ | Stub |<-------/
+// +-----------------+ | Code |
+// | ... | +---------+
+// +-----------------+
+// Shared
+// Stub Code
+//
+//
+// Type ICs
+// ========
+//
+// Type ICs are otherwise regular ICs that are actually nested within
+// other IC chains. They serve to optimize locations in the code where the
+// baseline compiler would have otherwise had to perform a type Monitor operation
+// (e.g. the result of GetProp, GetElem, etc.), or locations where the baseline
+// compiler would have had to modify a heap typeset using the type of an input
+// value (e.g. SetProp, SetElem, etc.)
+//
+// There are two kinds of Type ICs: Monitor and Update.
+//
+// Note that type stub bodies are no-ops. The stubs only exist for their
+// guards, and their existence simply signifies that the typeset (implicit)
+// that is being checked already contains that type.
+//
+// TypeMonitor ICs
+// ---------------
+// Monitor ICs are shared between stubs in the general IC, and monitor the resulting
+// types of getter operations (call returns, getprop outputs, etc.)
+//
+// +-----------+ +-----------+ +-----------+ +-----------+
+// ---->| Stub 1 |---->| Stub 2 |---->| Stub 3 |---->| FB Stub |
+// +-----------+ +-----------+ +-----------+ +-----------+
+// | | | |
+// |------------------/-----------------/ |
+// v |
+// +-----------+ +-----------+ +-----------+ |
+// | Type 1 |---->| Type 2 |---->| Type FB | |
+// +-----------+ +-----------+ +-----------+ |
+// | | | |
+// <----------/-----------------/------------------/------------------/
+// r e t u r n p a t h
+//
+// After an optimized IC stub successfully executes, it passes control to the type stub
+// chain to check the resulting type. If no type stub succeeds, and the monitor fallback
+// stub is reached, the monitor fallback stub performs a manual monitor, and also adds the
+// appropriate type stub to the chain.
+//
+// The IC's main fallback, in addition to generating new mainline stubs, also generates
+// type stubs as reflected by its returned value.
+//
+// NOTE: The type IC chain returns directly to the mainline code, not back to the
+// stub it was entered from. Thus, entering a type IC is a matter of a |jump|, not
+// a |call|. This allows us to safely call a VM Monitor function from within the monitor IC's
+// fallback chain, since the return address (needed for stack inspection) is preserved.
+//
+//
+// TypeUpdate ICs
+// --------------
+// Update ICs update heap typesets and monitor the input types of setter operations
+// (setelem, setprop inputs, etc.). Unlike monitor ICs, they are not shared
+// between stubs on an IC, but instead are kept track of on a per-stub basis.
+//
+// This is because the main stubs for the operation will each identify a potentially
+// different ObjectGroup to update. New input types must be tracked on a group-to-
+// group basis.
+//
+// Type-update ICs cannot be called in tail position (they must return to the
+// the stub that called them so that the stub may continue to perform its original
+// purpose). This means that any VMCall to perform a manual type update from C++ must be
+// done from within the main IC stub. This necessitates that the stub enter a
+// "BaselineStub" frame before making the call.
+//
+// If the type-update IC chain could itself make the VMCall, then the BaselineStub frame
+// must be entered before calling the type-update chain, and exited afterward. This
+// is very expensive for a common case where we expect the type-update fallback to not
+// be called. To avoid the cost of entering and exiting a BaselineStub frame when
+// using the type-update IC chain, we design the chain to not perform any VM-calls
+// in its fallback.
+//
+// Instead, the type-update IC chain is responsible for returning 1 or 0, depending
+// on if a type is represented in the chain or not. The fallback stub simply returns
+// 0, and all other optimized stubs return 1.
+// If the chain returns 1, then the IC stub goes ahead and performs its operation.
+// If the chain returns 0, then the IC stub performs a call to the fallback function
+// inline (doing the requisite BaselineStub frame enter/exit).
+// This allows us to avoid the expensive subfram enter/exit in the common case.
+//
+// r e t u r n p a t h
+// <--------------.-----------------.-----------------.-----------------.
+// | | | |
+// +-----------+ +-----------+ +-----------+ +-----------+
+// ---->| Stub 1 |---->| Stub 2 |---->| Stub 3 |---->| FB Stub |
+// +-----------+ +-----------+ +-----------+ +-----------+
+// | ^ | ^ | ^
+// | | | | | |
+// | | | | | |----------------.
+// | | | | v |1 |0
+// | | | | +-----------+ +-----------+
+// | | | | | Type 3.1 |--->| FB 3 |
+// | | | | +-----------+ +-----------+
+// | | | |
+// | | | \-------------.-----------------.
+// | | | | | |
+// | | v |1 |1 |0
+// | | +-----------+ +-----------+ +-----------+
+// | | | Type 2.1 |---->| Type 2.2 |---->| FB 2 |
+// | | +-----------+ +-----------+ +-----------+
+// | |
+// | \-------------.-----------------.
+// | | | |
+// v |1 |1 |0
+// +-----------+ +-----------+ +-----------+
+// | Type 1.1 |---->| Type 1.2 |---->| FB 1 |
+// +-----------+ +-----------+ +-----------+
+//
+
+class ICStub;
+class ICFallbackStub;
+
+
+#define FORWARD_DECLARE_STUBS(kindName) class IC##kindName;
+ IC_BASELINE_STUB_KIND_LIST(FORWARD_DECLARE_STUBS)
+#undef FORWARD_DECLARE_STUBS
+
+#ifdef JS_JITSPEW
+void FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...)
+ MOZ_FORMAT_PRINTF(3, 4);
+void TypeFallbackICSpew(JSContext* cx, ICTypeMonitor_Fallback* stub, const char* fmt, ...)
+ MOZ_FORMAT_PRINTF(3, 4);
+#else
+#define FallbackICSpew(...)
+#define TypeFallbackICSpew(...)
+#endif
+
+//
+// An entry in the JIT IC descriptor table.
+//
+class ICEntry
+{
+ private:
+ // A pointer to the shared IC stub for this instruction.
+ ICStub* firstStub_;
+
+ // Offset from the start of the JIT code where the IC
+ // load and call instructions are.
+ uint32_t returnOffset_;
+
+ // The PC of this IC's bytecode op within the JSScript.
+ uint32_t pcOffset_ : 28;
+
+ public:
+ enum Kind {
+ // A for-op IC entry.
+ Kind_Op = 0,
+
+ // A non-op IC entry.
+ Kind_NonOp,
+
+ // A fake IC entry for returning from a callVM for an op.
+ Kind_CallVM,
+
+ // A fake IC entry for returning from a callVM not for an op (e.g., in
+ // the prologue).
+ Kind_NonOpCallVM,
+
+ // A fake IC entry for returning from a callVM to after the
+ // warmup counter.
+ Kind_WarmupCounter,
+
+ // A fake IC entry for returning from a callVM to the interrupt
+ // handler via the over-recursion check on function entry.
+ Kind_StackCheck,
+
+ // As above, but for the early check. See emitStackCheck.
+ Kind_EarlyStackCheck,
+
+ // A fake IC entry for returning from DebugTrapHandler.
+ Kind_DebugTrap,
+
+ // A fake IC entry for returning from a callVM to
+ // Debug{Prologue,AfterYield,Epilogue}.
+ Kind_DebugPrologue,
+ Kind_DebugAfterYield,
+ Kind_DebugEpilogue,
+
+ Kind_Invalid
+ };
+
+ private:
+ // What this IC is for.
+ Kind kind_ : 4;
+
+ // Set the kind and asserts that it's sane.
+ void setKind(Kind kind) {
+ MOZ_ASSERT(kind < Kind_Invalid);
+ kind_ = kind;
+ MOZ_ASSERT(this->kind() == kind);
+ }
+
+ public:
+ ICEntry(uint32_t pcOffset, Kind kind)
+ : firstStub_(nullptr), returnOffset_(), pcOffset_(pcOffset)
+ {
+ // The offset must fit in at least 28 bits, since we shave off 4 for
+ // the Kind enum.
+ MOZ_ASSERT(pcOffset_ == pcOffset);
+ JS_STATIC_ASSERT(BaselineScript::MAX_JSSCRIPT_LENGTH <= (1u << 28) - 1);
+ MOZ_ASSERT(pcOffset <= BaselineScript::MAX_JSSCRIPT_LENGTH);
+ setKind(kind);
+ }
+
+ CodeOffset returnOffset() const {
+ return CodeOffset(returnOffset_);
+ }
+
+ void setReturnOffset(CodeOffset offset) {
+ MOZ_ASSERT(offset.offset() <= (size_t) UINT32_MAX);
+ returnOffset_ = (uint32_t) offset.offset();
+ }
+
+ uint32_t pcOffset() const {
+ return pcOffset_;
+ }
+
+ jsbytecode* pc(JSScript* script) const {
+ return script->offsetToPC(pcOffset_);
+ }
+
+ Kind kind() const {
+ // MSVC compiles enums as signed.
+ return Kind(kind_ & 0xf);
+ }
+ bool isForOp() const {
+ return kind() == Kind_Op;
+ }
+
+ void setFakeKind(Kind kind) {
+ MOZ_ASSERT(kind != Kind_Op && kind != Kind_NonOp);
+ setKind(kind);
+ }
+
+ bool hasStub() const {
+ return firstStub_ != nullptr;
+ }
+ ICStub* firstStub() const {
+ MOZ_ASSERT(hasStub());
+ return firstStub_;
+ }
+
+ ICFallbackStub* fallbackStub() const;
+
+ void setFirstStub(ICStub* stub) {
+ firstStub_ = stub;
+ }
+
+ static inline size_t offsetOfFirstStub() {
+ return offsetof(ICEntry, firstStub_);
+ }
+
+ inline ICStub** addressOfFirstStub() {
+ return &firstStub_;
+ }
+
+ void trace(JSTracer* trc);
+};
+
+class ICMonitoredStub;
+class ICMonitoredFallbackStub;
+class ICUpdatedStub;
+
+// Constant iterator that traverses arbitrary chains of ICStubs.
+// No requirements are made of the ICStub used to construct this
+// iterator, aside from that the stub be part of a nullptr-terminated
+// chain.
+// The iterator is considered to be at its end once it has been
+// incremented _past_ the last stub. Thus, if 'atEnd()' returns
+// true, the '*' and '->' operations are not valid.
+class ICStubConstIterator
+{
+ friend class ICStub;
+ friend class ICFallbackStub;
+
+ private:
+ ICStub* currentStub_;
+
+ public:
+ explicit ICStubConstIterator(ICStub* currentStub) : currentStub_(currentStub) {}
+
+ static ICStubConstIterator StartingAt(ICStub* stub) {
+ return ICStubConstIterator(stub);
+ }
+ static ICStubConstIterator End(ICStub* stub) {
+ return ICStubConstIterator(nullptr);
+ }
+
+ bool operator ==(const ICStubConstIterator& other) const {
+ return currentStub_ == other.currentStub_;
+ }
+ bool operator !=(const ICStubConstIterator& other) const {
+ return !(*this == other);
+ }
+
+ ICStubConstIterator& operator++();
+
+ ICStubConstIterator operator++(int) {
+ ICStubConstIterator oldThis(*this);
+ ++(*this);
+ return oldThis;
+ }
+
+ ICStub* operator*() const {
+ MOZ_ASSERT(currentStub_);
+ return currentStub_;
+ }
+
+ ICStub* operator ->() const {
+ MOZ_ASSERT(currentStub_);
+ return currentStub_;
+ }
+
+ bool atEnd() const {
+ return currentStub_ == nullptr;
+ }
+};
+
+// Iterator that traverses "regular" IC chains that start at an ICEntry
+// and are terminated with an ICFallbackStub.
+//
+// The iterator is considered to be at its end once it is _at_ the
+// fallback stub. Thus, unlike the ICStubConstIterator, operators
+// '*' and '->' are valid even if 'atEnd()' returns true - they
+// will act on the fallback stub.
+//
+// This iterator also allows unlinking of stubs being traversed.
+// Note that 'unlink' does not implicitly advance the iterator -
+// it must be advanced explicitly using '++'.
+class ICStubIterator
+{
+ friend class ICFallbackStub;
+
+ private:
+ ICEntry* icEntry_;
+ ICFallbackStub* fallbackStub_;
+ ICStub* previousStub_;
+ ICStub* currentStub_;
+ bool unlinked_;
+
+ explicit ICStubIterator(ICFallbackStub* fallbackStub, bool end=false);
+ public:
+
+ bool operator ==(const ICStubIterator& other) const {
+ // == should only ever be called on stubs from the same chain.
+ MOZ_ASSERT(icEntry_ == other.icEntry_);
+ MOZ_ASSERT(fallbackStub_ == other.fallbackStub_);
+ return currentStub_ == other.currentStub_;
+ }
+ bool operator !=(const ICStubIterator& other) const {
+ return !(*this == other);
+ }
+
+ ICStubIterator& operator++();
+
+ ICStubIterator operator++(int) {
+ ICStubIterator oldThis(*this);
+ ++(*this);
+ return oldThis;
+ }
+
+ ICStub* operator*() const {
+ return currentStub_;
+ }
+
+ ICStub* operator ->() const {
+ return currentStub_;
+ }
+
+ bool atEnd() const {
+ return currentStub_ == (ICStub*) fallbackStub_;
+ }
+
+ void unlink(JSContext* cx);
+};
+
+//
+// Base class for all IC stubs.
+//
+class ICStub
+{
+ friend class ICFallbackStub;
+
+ public:
+ enum Kind {
+ INVALID = 0,
+#define DEF_ENUM_KIND(kindName) kindName,
+ IC_BASELINE_STUB_KIND_LIST(DEF_ENUM_KIND)
+#undef DEF_ENUM_KIND
+ LIMIT
+ };
+
+ static bool IsValidKind(Kind k) {
+ return (k > INVALID) && (k < LIMIT);
+ }
+ static bool IsCacheIRKind(Kind k) {
+ return k == CacheIR_Regular || k == CacheIR_Monitored || k == CacheIR_Updated;
+ }
+
+ static const char* KindString(Kind k) {
+ switch(k) {
+#define DEF_KIND_STR(kindName) case kindName: return #kindName;
+ IC_BASELINE_STUB_KIND_LIST(DEF_KIND_STR)
+#undef DEF_KIND_STR
+ default:
+ MOZ_CRASH("Invalid kind.");
+ }
+ }
+
+ enum Trait {
+ Regular = 0x0,
+ Fallback = 0x1,
+ Monitored = 0x2,
+ MonitoredFallback = 0x3,
+ Updated = 0x4
+ };
+
+ void traceCode(JSTracer* trc, const char* name);
+ void updateCode(JitCode* stubCode);
+ void trace(JSTracer* trc);
+
+ template
+ static T* New(JSContext* cx, ICStubSpace* space, JitCode* code, Args&&... args) {
+ if (!code)
+ return nullptr;
+ T* result = space->allocate(code, std::forward(args)...);
+ if (!result)
+ ReportOutOfMemory(cx);
+ return result;
+ }
+
+ protected:
+ // The raw jitcode to call for this stub.
+ uint8_t* stubCode_;
+
+ // Pointer to next IC stub. This is null for the last IC stub, which should
+ // either be a fallback or inert IC stub.
+ ICStub* next_;
+
+ // A 16-bit field usable by subtypes of ICStub for subtype-specific small-info
+ uint16_t extra_;
+
+ // The kind of the stub.
+ // High bit is 'isFallback' flag.
+ // Second high bit is 'isMonitored' flag.
+ Trait trait_ : 3;
+ Kind kind_ : 13;
+
+ inline ICStub(Kind kind, JitCode* stubCode)
+ : stubCode_(stubCode->raw()),
+ next_(nullptr),
+ extra_(0),
+ trait_(Regular),
+ kind_(kind)
+ {
+ MOZ_ASSERT(stubCode != nullptr);
+ }
+
+ inline ICStub(Kind kind, Trait trait, JitCode* stubCode)
+ : stubCode_(stubCode->raw()),
+ next_(nullptr),
+ extra_(0),
+ trait_(trait),
+ kind_(kind)
+ {
+ MOZ_ASSERT(stubCode != nullptr);
+ }
+
+ inline Trait trait() const {
+ // Workaround for MSVC reading trait_ as signed value.
+ return (Trait)(trait_ & 0x7);
+ }
+
+ public:
+
+ inline Kind kind() const {
+ return static_cast(kind_);
+ }
+
+ inline bool isFallback() const {
+ return trait() == Fallback || trait() == MonitoredFallback;
+ }
+
+ inline bool isMonitored() const {
+ return trait() == Monitored;
+ }
+
+ inline bool isUpdated() const {
+ return trait() == Updated;
+ }
+
+ inline bool isMonitoredFallback() const {
+ return trait() == MonitoredFallback;
+ }
+
+ inline const ICFallbackStub* toFallbackStub() const {
+ MOZ_ASSERT(isFallback());
+ return reinterpret_cast(this);
+ }
+
+ inline ICFallbackStub* toFallbackStub() {
+ MOZ_ASSERT(isFallback());
+ return reinterpret_cast(this);
+ }
+
+ inline const ICMonitoredStub* toMonitoredStub() const {
+ MOZ_ASSERT(isMonitored());
+ return reinterpret_cast(this);
+ }
+
+ inline ICMonitoredStub* toMonitoredStub() {
+ MOZ_ASSERT(isMonitored());
+ return reinterpret_cast(this);
+ }
+
+ inline const ICMonitoredFallbackStub* toMonitoredFallbackStub() const {
+ MOZ_ASSERT(isMonitoredFallback());
+ return reinterpret_cast(this);
+ }
+
+ inline ICMonitoredFallbackStub* toMonitoredFallbackStub() {
+ MOZ_ASSERT(isMonitoredFallback());
+ return reinterpret_cast(this);
+ }
+
+ inline const ICUpdatedStub* toUpdatedStub() const {
+ MOZ_ASSERT(isUpdated());
+ return reinterpret_cast(this);
+ }
+
+ inline ICUpdatedStub* toUpdatedStub() {
+ MOZ_ASSERT(isUpdated());
+ return reinterpret_cast(this);
+ }
+
+#define KIND_METHODS(kindName) \
+ inline bool is##kindName() const { return kind() == kindName; } \
+ inline const IC##kindName* to##kindName() const { \
+ MOZ_ASSERT(is##kindName()); \
+ return reinterpret_cast(this); \
+ } \
+ inline IC##kindName* to##kindName() { \
+ MOZ_ASSERT(is##kindName()); \
+ return reinterpret_cast(this); \
+ }
+ IC_BASELINE_STUB_KIND_LIST(KIND_METHODS)
+#undef KIND_METHODS
+
+ inline ICStub* next() const {
+ return next_;
+ }
+
+ inline bool hasNext() const {
+ return next_ != nullptr;
+ }
+
+ inline void setNext(ICStub* stub) {
+ // Note: next_ only needs to be changed under the compilation lock for
+ // non-type-monitor/update ICs.
+ next_ = stub;
+ }
+
+ inline ICStub** addressOfNext() {
+ return &next_;
+ }
+
+ inline JitCode* jitCode() {
+ return JitCode::FromExecutable(stubCode_);
+ }
+
+ inline uint8_t* rawStubCode() const {
+ return stubCode_;
+ }
+
+ // This method is not valid on TypeUpdate stub chains!
+ inline ICFallbackStub* getChainFallback() {
+ ICStub* lastStub = this;
+ while (lastStub->next_)
+ lastStub = lastStub->next_;
+ MOZ_ASSERT(lastStub->isFallback());
+ return lastStub->toFallbackStub();
+ }
+
+ inline ICStubConstIterator beginHere() {
+ return ICStubConstIterator::StartingAt(this);
+ }
+
+ static inline size_t offsetOfNext() {
+ return offsetof(ICStub, next_);
+ }
+
+ static inline size_t offsetOfStubCode() {
+ return offsetof(ICStub, stubCode_);
+ }
+
+ static inline size_t offsetOfExtra() {
+ return offsetof(ICStub, extra_);
+ }
+
+ static bool NonCacheIRStubMakesGCCalls(Kind kind);
+ bool makesGCCalls() const;
+
+ // Optimized stubs get purged on GC. But some stubs can be active on the
+ // stack during GC - specifically the ones that can make calls. To ensure
+ // that these do not get purged, all stubs that can make calls are allocated
+ // in the fallback stub space.
+ bool allocatedInFallbackSpace() const {
+ MOZ_ASSERT(next());
+ return makesGCCalls();
+ }
+};
+
+class ICFallbackStub : public ICStub
+{
+ friend class ICStubConstIterator;
+ protected:
+ // Fallback stubs need these fields to easily add new stubs to
+ // the linked list of stubs for an IC.
+
+ // The IC entry for this linked list of stubs.
+ ICEntry* icEntry_;
+
+ // The number of stubs kept in the IC entry.
+ ICState state_;
+
+ // A pointer to the location stub pointer that needs to be
+ // changed to add a new "last" stub immediately before the fallback
+ // stub. This'll start out pointing to the icEntry's "firstStub_"
+ // field, and as new stubs are added, it'll point to the current
+ // last stub's "next_" field.
+ ICStub** lastStubPtrAddr_;
+
+ ICFallbackStub(Kind kind, JitCode* stubCode)
+ : ICStub(kind, ICStub::Fallback, stubCode),
+ icEntry_(nullptr),
+ state_(),
+ lastStubPtrAddr_(nullptr) {}
+
+ ICFallbackStub(Kind kind, Trait trait, JitCode* stubCode)
+ : ICStub(kind, trait, stubCode),
+ icEntry_(nullptr),
+ state_(),
+ lastStubPtrAddr_(nullptr)
+ {
+ MOZ_ASSERT(trait == ICStub::Fallback ||
+ trait == ICStub::MonitoredFallback);
+ }
+
+ public:
+ inline ICEntry* icEntry() const {
+ return icEntry_;
+ }
+
+ inline size_t numOptimizedStubs() const {
+ return state_.numOptimizedStubs();
+ }
+
+ void setInvalid() {
+ state_.setInvalid();
+ }
+
+ bool invalid() const {
+ return state_.invalid();
+ }
+
+ ICState& state() {
+ return state_;
+ }
+
+ // The icEntry and lastStubPtrAddr_ fields can't be initialized when the stub is
+ // created since the stub is created at compile time, and we won't know the IC entry
+ // address until after compile when the JitScript is created. This method
+ // allows these fields to be fixed up at that point.
+ void fixupICEntry(ICEntry* icEntry) {
+ MOZ_ASSERT(icEntry_ == nullptr);
+ MOZ_ASSERT(lastStubPtrAddr_ == nullptr);
+ icEntry_ = icEntry;
+ lastStubPtrAddr_ = icEntry_->addressOfFirstStub();
+ }
+
+ // Add a new stub to the IC chain terminated by this fallback stub.
+ void addNewStub(ICStub* stub) {
+ MOZ_ASSERT(!invalid());
+ MOZ_ASSERT(*lastStubPtrAddr_ == this);
+ MOZ_ASSERT(stub->next() == nullptr);
+ stub->setNext(this);
+ *lastStubPtrAddr_ = stub;
+ lastStubPtrAddr_ = stub->addressOfNext();
+ state_.trackAttached();
+ }
+
+ ICStubConstIterator beginChainConst() const {
+ return ICStubConstIterator(icEntry_->firstStub());
+ }
+
+ ICStubIterator beginChain() {
+ return ICStubIterator(this);
+ }
+
+ bool hasStub(ICStub::Kind kind) const {
+ for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
+ if (iter->kind() == kind)
+ return true;
+ }
+ return false;
+ }
+
+ unsigned numStubsWithKind(ICStub::Kind kind) const {
+ unsigned count = 0;
+ for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
+ if (iter->kind() == kind)
+ count++;
+ }
+ return count;
+ }
+
+ void discardStubs(JSContext* cx);
+
+ void unlinkStub(Zone* zone, ICStub* prev, ICStub* stub);
+ void unlinkStubsWithKind(JSContext* cx, ICStub::Kind kind);
+};
+
+// Base class for Trait::Regular CacheIR stubs
+class ICCacheIR_Regular : public ICStub
+{
+ const CacheIRStubInfo* stubInfo_;
+
+ public:
+ ICCacheIR_Regular(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
+ : ICStub(ICStub::CacheIR_Regular, stubCode),
+ stubInfo_(stubInfo)
+ {}
+
+ static ICCacheIR_Regular* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
+ ICCacheIR_Regular& other);
+
+ void notePreliminaryObject() {
+ extra_ = 1;
+ }
+ bool hasPreliminaryObject() const {
+ return extra_;
+ }
+
+ const CacheIRStubInfo* stubInfo() const {
+ return stubInfo_;
+ }
+
+ uint8_t* stubDataStart();
+};
+
+// Monitored stubs are IC stubs that feed a single resulting value out to a
+// type monitor operation.
+class ICMonitoredStub : public ICStub
+{
+ protected:
+ // Pointer to the start of the type monitoring stub chain.
+ ICStub* firstMonitorStub_;
+
+ ICMonitoredStub(Kind kind, JitCode* stubCode, ICStub* firstMonitorStub);
+
+ public:
+ inline void updateFirstMonitorStub(ICStub* monitorStub) {
+ // This should only be called once: when the first optimized monitor stub
+ // is added to the type monitor IC chain.
+ MOZ_ASSERT(firstMonitorStub_ && firstMonitorStub_->isTypeMonitor_Fallback());
+ firstMonitorStub_ = monitorStub;
+ }
+ inline void resetFirstMonitorStub(ICStub* monitorFallback) {
+ MOZ_ASSERT(monitorFallback->isTypeMonitor_Fallback());
+ firstMonitorStub_ = monitorFallback;
+ }
+ inline ICStub* firstMonitorStub() const {
+ return firstMonitorStub_;
+ }
+
+ static inline size_t offsetOfFirstMonitorStub() {
+ return offsetof(ICMonitoredStub, firstMonitorStub_);
+ }
+};
+
+class ICCacheIR_Monitored : public ICMonitoredStub
+{
+ const CacheIRStubInfo* stubInfo_;
+
+ public:
+ ICCacheIR_Monitored(JitCode* stubCode, ICStub* firstMonitorStub,
+ const CacheIRStubInfo* stubInfo)
+ : ICMonitoredStub(ICStub::CacheIR_Monitored, stubCode, firstMonitorStub),
+ stubInfo_(stubInfo)
+ {}
+
+ static ICCacheIR_Monitored* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
+ ICCacheIR_Monitored& other);
+
+ void notePreliminaryObject() {
+ extra_ = 1;
+ }
+ bool hasPreliminaryObject() const {
+ return extra_;
+ }
+
+ const CacheIRStubInfo* stubInfo() const {
+ return stubInfo_;
+ }
+
+ uint8_t* stubDataStart();
+};
+
+// Updated stubs are IC stubs that use a TypeUpdate IC to track
+// the status of heap typesets that need to be updated.
+class ICUpdatedStub : public ICStub
+{
+ protected:
+ // Pointer to the start of the type updating stub chain.
+ ICStub* firstUpdateStub_;
+
+ static const uint32_t MAX_OPTIMIZED_STUBS = 8;
+ uint32_t numOptimizedStubs_;
+
+ ICUpdatedStub(Kind kind, JitCode* stubCode)
+ : ICStub(kind, ICStub::Updated, stubCode),
+ firstUpdateStub_(nullptr),
+ numOptimizedStubs_(0)
+ {}
+
+ public:
+ MOZ_MUST_USE bool initUpdatingChain(JSContext* cx, ICStubSpace* space);
+
+ MOZ_MUST_USE bool addUpdateStubForValue(JSContext* cx, HandleScript script, HandleObject obj,
+ HandleObjectGroup group, HandleId id, HandleValue val);
+
+ void addOptimizedUpdateStub(ICStub* stub) {
+ if (firstUpdateStub_->isTypeUpdate_Fallback()) {
+ stub->setNext(firstUpdateStub_);
+ firstUpdateStub_ = stub;
+ } else {
+ ICStub* iter = firstUpdateStub_;
+ MOZ_ASSERT(iter->next() != nullptr);
+ while (!iter->next()->isTypeUpdate_Fallback())
+ iter = iter->next();
+ MOZ_ASSERT(iter->next()->next() == nullptr);
+ stub->setNext(iter->next());
+ iter->setNext(stub);
+ }
+
+ numOptimizedStubs_++;
+ }
+
+ inline ICStub* firstUpdateStub() const {
+ return firstUpdateStub_;
+ }
+
+ void resetUpdateStubChain(Zone* zone);
+
+ bool hasTypeUpdateStub(ICStub::Kind kind) {
+ ICStub* stub = firstUpdateStub_;
+ do {
+ if (stub->kind() == kind)
+ return true;
+
+ stub = stub->next();
+ } while (stub);
+
+ return false;
+ }
+
+ inline uint32_t numOptimizedStubs() const {
+ return numOptimizedStubs_;
+ }
+
+ static inline size_t offsetOfFirstUpdateStub() {
+ return offsetof(ICUpdatedStub, firstUpdateStub_);
+ }
+};
+
+class ICCacheIR_Updated : public ICUpdatedStub
+{
+ const CacheIRStubInfo* stubInfo_;
+ GCPtrObjectGroup updateStubGroup_;
+ GCPtrId updateStubId_;
+
+ public:
+ ICCacheIR_Updated(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
+ : ICUpdatedStub(ICStub::CacheIR_Updated, stubCode),
+ stubInfo_(stubInfo),
+ updateStubGroup_(nullptr),
+ updateStubId_(JSID_EMPTY)
+ {}
+
+ static ICCacheIR_Updated* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
+ ICCacheIR_Updated& other);
+
+ GCPtrObjectGroup& updateStubGroup() {
+ return updateStubGroup_;
+ }
+ GCPtrId& updateStubId() {
+ return updateStubId_;
+ }
+
+ void notePreliminaryObject() {
+ extra_ = 1;
+ }
+ bool hasPreliminaryObject() const {
+ return extra_;
+ }
+
+ const CacheIRStubInfo* stubInfo() const {
+ return stubInfo_;
+ }
+
+ uint8_t* stubDataStart();
+};
+
+// Base class for stubcode compilers.
+class ICStubCompiler
+{
+ // Prevent GC in the middle of stub compilation.
+ js::gc::AutoSuppressGC suppressGC;
+
+ protected:
+ JSContext* cx;
+ ICStub::Kind kind;
+ bool inStubFrame_;
+
+#ifdef DEBUG
+ bool entersStubFrame_;
+ uint32_t framePushedAtEnterStubFrame_;
+#endif
+
+ // By default the stubcode key is just the kind.
+ virtual int32_t getKey() const {
+ return static_cast(kind);
+ }
+
+ virtual MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) = 0;
+ virtual void postGenerateStubCode(MacroAssembler& masm, Handle genCode) {}
+
+ JitCode* getStubCode();
+
+ ICStubCompiler(JSContext* cx, ICStub::Kind kind)
+ : suppressGC(cx), cx(cx), kind(kind), inStubFrame_(false)
+#ifdef DEBUG
+ , entersStubFrame_(false), framePushedAtEnterStubFrame_(0)
+#endif
+ {}
+
+ // Push a payload specialized per compiler needed to execute stubs.
+ void PushStubPayload(MacroAssembler& masm, Register scratch);
+ void pushStubPayload(MacroAssembler& masm, Register scratch);
+
+ // Emits a tail call to a VMFunction wrapper.
+ MOZ_MUST_USE bool tailCallVM(const VMFunction& fun, MacroAssembler& masm);
+
+ // Emits a normal (non-tail) call to a VMFunction wrapper.
+ MOZ_MUST_USE bool callVM(const VMFunction& fun, MacroAssembler& masm);
+
+ // A stub frame is used when a stub wants to call into the VM without
+ // performing a tail call. This is required for the return address
+ // to pc mapping to work.
+ void enterStubFrame(MacroAssembler& masm, Register scratch);
+ void assumeStubFrame();
+ void leaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false);
+
+ public:
+ static inline AllocatableGeneralRegisterSet availableGeneralRegs(size_t numInputs) {
+ AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+#if defined(JS_CODEGEN_ARM)
+ MOZ_ASSERT(!regs.has(BaselineStackReg));
+ MOZ_ASSERT(!regs.has(ICTailCallReg));
+ regs.take(BaselineSecondScratchReg);
+#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
+ MOZ_ASSERT(!regs.has(BaselineStackReg));
+ MOZ_ASSERT(!regs.has(ICTailCallReg));
+ MOZ_ASSERT(!regs.has(BaselineSecondScratchReg));
+#elif defined(JS_CODEGEN_ARM64)
+ MOZ_ASSERT(!regs.has(PseudoStackPointer));
+ MOZ_ASSERT(!regs.has(RealStackPointer));
+ MOZ_ASSERT(!regs.has(ICTailCallReg));
+#else
+ MOZ_ASSERT(!regs.has(BaselineStackReg));
+#endif
+ regs.take(BaselineFrameReg);
+ regs.take(ICStubReg);
+#ifdef JS_CODEGEN_X64
+ regs.take(ExtractTemp0);
+ regs.take(ExtractTemp1);
+#endif
+
+ switch (numInputs) {
+ case 0:
+ break;
+ case 1:
+ regs.take(R0);
+ break;
+ case 2:
+ regs.take(R0);
+ regs.take(R1);
+ break;
+ default:
+ MOZ_CRASH("Invalid numInputs");
+ }
+
+ return regs;
+ }
+
+ protected:
+ template
+ T* newStub(Args&&... args) {
+ return ICStub::New(cx, std::forward(args)...);
+ }
+
+ public:
+ virtual ICStub* getStub(ICStubSpace* space) = 0;
+
+ static ICStubSpace* StubSpaceForStub(bool makesGCCalls, JSScript* outerScript) {
+ if (makesGCCalls) {
+ return outerScript->baselineScript()->fallbackStubSpace();
+ }
+ return outerScript->zone()->jitZone()->optimizedStubSpace();
+ }
+ ICStubSpace* getStubSpace(JSScript* outerScript) {
+ return StubSpaceForStub(ICStub::NonCacheIRStubMakesGCCalls(kind), outerScript);
+ }
+};
+
// WarmUpCounter_Fallback
// A WarmUpCounter IC chain has only the fallback stub.
@@ -44,7 +1131,7 @@ class ICWarmUpCounter_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::WarmUpCounter_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::WarmUpCounter_Fallback)
{ }
ICWarmUpCounter_Fallback* getStub(ICStubSpace* space) override {
@@ -54,6 +1141,426 @@ class ICWarmUpCounter_Fallback : public ICFallbackStub
};
+// Monitored fallback stubs - as the name implies.
+class ICMonitoredFallbackStub : public ICFallbackStub
+{
+ protected:
+ // Pointer to the fallback monitor stub. Created lazily by
+ // getFallbackMonitorStub if needed.
+ ICTypeMonitor_Fallback* fallbackMonitorStub_;
+
+ ICMonitoredFallbackStub(Kind kind, JitCode* stubCode)
+ : ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
+ fallbackMonitorStub_(nullptr) {}
+
+ public:
+ MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, JSScript* script);
+ MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
+ StackTypeSet* types, HandleValue val);
+
+ ICTypeMonitor_Fallback* maybeFallbackMonitorStub() const {
+ return fallbackMonitorStub_;
+ }
+ ICTypeMonitor_Fallback* getFallbackMonitorStub(JSContext* cx, JSScript* script) {
+ if (!fallbackMonitorStub_ && !initMonitoringChain(cx, script))
+ return nullptr;
+ MOZ_ASSERT(fallbackMonitorStub_);
+ return fallbackMonitorStub_;
+ }
+
+ static inline size_t offsetOfFallbackMonitorStub() {
+ return offsetof(ICMonitoredFallbackStub, fallbackMonitorStub_);
+ }
+};
+
+// TypeCheckPrimitiveSetStub
+// Base class for IC stubs (TypeUpdate or TypeMonitor) that check that a given
+// value's type falls within a set of primitive types.
+
+class TypeCheckPrimitiveSetStub : public ICStub
+{
+ friend class ICStubSpace;
+ protected:
+ inline static uint16_t TypeToFlag(JSValueType type) {
+ return 1u << static_cast(type);
+ }
+
+ inline static uint16_t ValidFlags() {
+ return ((TypeToFlag(JSVAL_TYPE_OBJECT) << 1) - 1) & ~TypeToFlag(JSVAL_TYPE_MAGIC);
+ }
+
+ TypeCheckPrimitiveSetStub(Kind kind, JitCode* stubCode, uint16_t flags)
+ : ICStub(kind, stubCode)
+ {
+ MOZ_ASSERT(kind == TypeMonitor_PrimitiveSet || kind == TypeUpdate_PrimitiveSet);
+ MOZ_ASSERT(flags && !(flags & ~ValidFlags()));
+ extra_ = flags;
+ }
+
+ TypeCheckPrimitiveSetStub* updateTypesAndCode(uint16_t flags, JitCode* code) {
+ MOZ_ASSERT(flags && !(flags & ~ValidFlags()));
+ if (!code)
+ return nullptr;
+ extra_ = flags;
+ updateCode(code);
+ return this;
+ }
+
+ public:
+ uint16_t typeFlags() const {
+ return extra_;
+ }
+
+ bool containsType(JSValueType type) const {
+ MOZ_ASSERT(type <= JSVAL_TYPE_OBJECT);
+ MOZ_ASSERT(type != JSVAL_TYPE_MAGIC);
+ return extra_ & TypeToFlag(type);
+ }
+
+ ICTypeMonitor_PrimitiveSet* toMonitorStub() {
+ return toTypeMonitor_PrimitiveSet();
+ }
+
+ ICTypeUpdate_PrimitiveSet* toUpdateStub() {
+ return toTypeUpdate_PrimitiveSet();
+ }
+
+ class Compiler : public ICStubCompiler {
+ protected:
+ TypeCheckPrimitiveSetStub* existingStub_;
+ uint16_t flags_;
+
+ virtual int32_t getKey() const override {
+ return static_cast(kind) |
+ (static_cast(flags_) << 16);
+ }
+
+ public:
+ Compiler(JSContext* cx, Kind kind, TypeCheckPrimitiveSetStub* existingStub,
+ JSValueType type)
+ : ICStubCompiler(cx, kind),
+ existingStub_(existingStub),
+ flags_((existingStub ? existingStub->typeFlags() : 0) | TypeToFlag(type))
+ {
+ MOZ_ASSERT_IF(existingStub_, flags_ != existingStub_->typeFlags());
+ }
+
+ TypeCheckPrimitiveSetStub* updateStub() {
+ MOZ_ASSERT(existingStub_);
+ return existingStub_->updateTypesAndCode(flags_, getStubCode());
+ }
+ };
+};
+
+// TypeMonitor
+
+// The TypeMonitor fallback stub is not always a regular fallback stub. When
+// used for monitoring the values pushed by a bytecode it doesn't hold a
+// pointer to the IC entry, but rather back to the main fallback stub for the
+// IC (from which a pointer to the IC entry can be retrieved). When monitoring
+// the types of 'this', arguments or other values with no associated IC, there
+// is no main fallback stub, and the IC entry is referenced directly.
+class ICTypeMonitor_Fallback : public ICStub
+{
+ friend class ICStubSpace;
+
+ static const uint32_t MAX_OPTIMIZED_STUBS = 8;
+
+ // Pointer to the main fallback stub for the IC or to the main IC entry,
+ // depending on hasFallbackStub.
+ union {
+ ICMonitoredFallbackStub* mainFallbackStub_;
+ ICEntry* icEntry_;
+ };
+
+ // Pointer to the first monitor stub.
+ ICStub* firstMonitorStub_;
+
+ // Address of the last monitor stub's field pointing to this
+ // fallback monitor stub. This will get updated when new
+ // monitor stubs are created and added.
+ ICStub** lastMonitorStubPtrAddr_;
+
+ // Count of optimized type monitor stubs in this chain.
+ uint32_t numOptimizedMonitorStubs_ : 7;
+
+ uint32_t invalid_ : 1;
+
+ // Whether this has a fallback stub referring to the IC entry.
+ bool hasFallbackStub_ : 1;
+
+ // Index of 'this' or argument which is being monitored, or BYTECODE_INDEX
+ // if this is monitoring the types of values pushed at some bytecode.
+ uint32_t argumentIndex_ : 23;
+
+ static const uint32_t BYTECODE_INDEX = (1 << 23) - 1;
+
+ ICTypeMonitor_Fallback(JitCode* stubCode, ICMonitoredFallbackStub* mainFallbackStub,
+ uint32_t argumentIndex)
+ : ICStub(ICStub::TypeMonitor_Fallback, stubCode),
+ mainFallbackStub_(mainFallbackStub),
+ firstMonitorStub_(thisFromCtor()),
+ lastMonitorStubPtrAddr_(nullptr),
+ numOptimizedMonitorStubs_(0),
+ invalid_(false),
+ hasFallbackStub_(mainFallbackStub != nullptr),
+ argumentIndex_(argumentIndex)
+ { }
+
+ ICTypeMonitor_Fallback* thisFromCtor() {
+ return this;
+ }
+
+ void addOptimizedMonitorStub(ICStub* stub) {
+ MOZ_ASSERT(!invalid());
+ stub->setNext(this);
+
+ MOZ_ASSERT((lastMonitorStubPtrAddr_ != nullptr) ==
+ (numOptimizedMonitorStubs_ || !hasFallbackStub_));
+
+ if (lastMonitorStubPtrAddr_)
+ *lastMonitorStubPtrAddr_ = stub;
+
+ if (numOptimizedMonitorStubs_ == 0) {
+ MOZ_ASSERT(firstMonitorStub_ == this);
+ firstMonitorStub_ = stub;
+ } else {
+ MOZ_ASSERT(firstMonitorStub_ != nullptr);
+ }
+
+ lastMonitorStubPtrAddr_ = stub->addressOfNext();
+ numOptimizedMonitorStubs_++;
+ }
+
+ public:
+ bool hasStub(ICStub::Kind kind) {
+ ICStub* stub = firstMonitorStub_;
+ do {
+ if (stub->kind() == kind)
+ return true;
+
+ stub = stub->next();
+ } while (stub);
+
+ return false;
+ }
+
+ inline ICFallbackStub* mainFallbackStub() const {
+ MOZ_ASSERT(hasFallbackStub_);
+ return mainFallbackStub_;
+ }
+
+ inline ICEntry* icEntry() const {
+ return hasFallbackStub_ ? mainFallbackStub()->icEntry() : icEntry_;
+ }
+
+ inline ICStub* firstMonitorStub() const {
+ return firstMonitorStub_;
+ }
+
+ static inline size_t offsetOfFirstMonitorStub() {
+ return offsetof(ICTypeMonitor_Fallback, firstMonitorStub_);
+ }
+
+ inline uint32_t numOptimizedMonitorStubs() const {
+ return numOptimizedMonitorStubs_;
+ }
+
+ void setInvalid() {
+ invalid_ = 1;
+ }
+
+ bool invalid() const {
+ return invalid_;
+ }
+
+ inline bool monitorsThis() const {
+ return argumentIndex_ == 0;
+ }
+
+ inline bool monitorsArgument(uint32_t* pargument) const {
+ if (argumentIndex_ > 0 && argumentIndex_ < BYTECODE_INDEX) {
+ *pargument = argumentIndex_ - 1;
+ return true;
+ }
+ return false;
+ }
+
+ inline bool monitorsBytecode() const {
+ return argumentIndex_ == BYTECODE_INDEX;
+ }
+
+ // Fixup the IC entry as for a normal fallback stub, for this/arguments.
+ void fixupICEntry(ICEntry* icEntry) {
+ MOZ_ASSERT(!hasFallbackStub_);
+ MOZ_ASSERT(icEntry_ == nullptr);
+ MOZ_ASSERT(lastMonitorStubPtrAddr_ == nullptr);
+ icEntry_ = icEntry;
+ lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
+ }
+
+ // Create a new monitor stub for the type of the given value, and
+ // add it to this chain.
+ MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
+ StackTypeSet* types, HandleValue val);
+
+ void resetMonitorStubChain(Zone* zone);
+
+ // Compiler for this stub kind.
+ class Compiler : public ICStubCompiler {
+ ICMonitoredFallbackStub* mainFallbackStub_;
+ uint32_t argumentIndex_;
+
+ protected:
+ MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
+
+ public:
+ Compiler(JSContext* cx, ICMonitoredFallbackStub* mainFallbackStub)
+ : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
+ mainFallbackStub_(mainFallbackStub),
+ argumentIndex_(BYTECODE_INDEX)
+ { }
+
+ Compiler(JSContext* cx, uint32_t argumentIndex)
+ : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
+ mainFallbackStub_(nullptr),
+ argumentIndex_(argumentIndex)
+ { }
+
+ ICTypeMonitor_Fallback* getStub(ICStubSpace* space) override {
+ return newStub(space, getStubCode(), mainFallbackStub_,
+ argumentIndex_);
+ }
+ };
+};
+
+class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub
+{
+ friend class ICStubSpace;
+
+ ICTypeMonitor_PrimitiveSet(JitCode* stubCode, uint16_t flags)
+ : TypeCheckPrimitiveSetStub(TypeMonitor_PrimitiveSet, stubCode, flags)
+ {}
+
+ public:
+ class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
+ protected:
+ MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
+
+ public:
+ Compiler(JSContext* cx, ICTypeMonitor_PrimitiveSet* existingStub,
+ JSValueType type)
+ : TypeCheckPrimitiveSetStub::Compiler(cx, TypeMonitor_PrimitiveSet, existingStub,
+ type)
+ {}
+
+ ICTypeMonitor_PrimitiveSet* updateStub() {
+ TypeCheckPrimitiveSetStub* stub =
+ this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
+ if (!stub)
+ return nullptr;
+ return stub->toMonitorStub();
+ }
+
+ ICTypeMonitor_PrimitiveSet* getStub(ICStubSpace* space) override {
+ MOZ_ASSERT(!existingStub_);
+ return newStub(space, getStubCode(), flags_);
+ }
+ };
+};
+
+class ICTypeMonitor_SingleObject : public ICStub
+{
+ friend class ICStubSpace;
+
+ GCPtrObject obj_;
+
+ ICTypeMonitor_SingleObject(JitCode* stubCode, JSObject* obj);
+
+ public:
+ GCPtrObject& object() {
+ return obj_;
+ }
+
+ static size_t offsetOfObject() {
+ return offsetof(ICTypeMonitor_SingleObject, obj_);
+ }
+
+ class Compiler : public ICStubCompiler {
+ protected:
+ HandleObject obj_;
+ MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
+
+ public:
+ Compiler(JSContext* cx, HandleObject obj)
+ : ICStubCompiler(cx, TypeMonitor_SingleObject),
+ obj_(obj)
+ { }
+
+ ICTypeMonitor_SingleObject* getStub(ICStubSpace* space) override {
+ return newStub(space, getStubCode(), obj_);
+ }
+ };
+};
+
+class ICTypeMonitor_ObjectGroup : public ICStub
+{
+ friend class ICStubSpace;
+
+ GCPtrObjectGroup group_;
+
+ ICTypeMonitor_ObjectGroup(JitCode* stubCode, ObjectGroup* group);
+
+ public:
+ GCPtrObjectGroup& group() {
+ return group_;
+ }
+
+ static size_t offsetOfGroup() {
+ return offsetof(ICTypeMonitor_ObjectGroup, group_);
+ }
+
+ class Compiler : public ICStubCompiler {
+ protected:
+ HandleObjectGroup group_;
+ MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
+
+ public:
+ Compiler(JSContext* cx, HandleObjectGroup group)
+ : ICStubCompiler(cx, TypeMonitor_ObjectGroup),
+ group_(group)
+ { }
+
+ ICTypeMonitor_ObjectGroup* getStub(ICStubSpace* space) override {
+ return newStub(space, getStubCode(), group_);
+ }
+ };
+};
+
+class ICTypeMonitor_AnyValue : public ICStub
+{
+ friend class ICStubSpace;
+
+ explicit ICTypeMonitor_AnyValue(JitCode* stubCode)
+ : ICStub(TypeMonitor_AnyValue, stubCode)
+ {}
+
+ public:
+ class Compiler : public ICStubCompiler {
+ protected:
+ MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
+
+ public:
+ explicit Compiler(JSContext* cx)
+ : ICStubCompiler(cx, TypeMonitor_AnyValue)
+ { }
+
+ ICTypeMonitor_AnyValue* getStub(ICStubSpace* space) override {
+ return newStub(space, getStubCode());
+ }
+ };
+};
+
// TypeUpdate
extern const VMFunction DoTypeUpdateFallbackInfo;
@@ -76,7 +1583,7 @@ class ICTypeUpdate_Fallback : public ICStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::TypeUpdate_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::TypeUpdate_Fallback)
{ }
ICTypeUpdate_Fallback* getStub(ICStubSpace* space) override {
@@ -144,7 +1651,7 @@ class ICTypeUpdate_SingleObject : public ICStub
public:
Compiler(JSContext* cx, HandleObject obj)
- : ICStubCompiler(cx, TypeUpdate_SingleObject, Engine::Baseline),
+ : ICStubCompiler(cx, TypeUpdate_SingleObject),
obj_(obj)
{ }
@@ -179,7 +1686,7 @@ class ICTypeUpdate_ObjectGroup : public ICStub
public:
Compiler(JSContext* cx, HandleObjectGroup group)
- : ICStubCompiler(cx, TypeUpdate_ObjectGroup, Engine::Baseline),
+ : ICStubCompiler(cx, TypeUpdate_ObjectGroup),
group_(group)
{ }
@@ -204,7 +1711,7 @@ class ICTypeUpdate_AnyValue : public ICStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, TypeUpdate_AnyValue, Engine::Baseline)
+ : ICStubCompiler(cx, TypeUpdate_AnyValue)
{}
ICTypeUpdate_AnyValue* getStub(ICStubSpace* space) override {
@@ -233,7 +1740,7 @@ class ICToBool_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::ToBool_Fallback, Engine::Baseline) {}
+ : ICStubCompiler(cx, ICStub::ToBool_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub(space, getStubCode());
@@ -259,7 +1766,7 @@ class ICToNumber_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::ToNumber_Fallback, Engine::Baseline) {}
+ : ICStubCompiler(cx, ICStub::ToNumber_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub(space, getStubCode());
@@ -303,14 +1810,13 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(hasReceiver_) << 17);
+ return static_cast(kind) |
+ (static_cast(hasReceiver_) << 16);
}
public:
explicit Compiler(JSContext* cx, bool hasReceiver = false)
- : ICStubCompiler(cx, ICStub::GetElem_Fallback, Engine::Baseline),
+ : ICStubCompiler(cx, ICStub::GetElem_Fallback),
hasReceiver_(hasReceiver)
{ }
@@ -349,7 +1855,7 @@ class ICSetElem_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::SetElem_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::SetElem_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -375,7 +1881,7 @@ class ICIn_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::In_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::In_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -401,7 +1907,7 @@ class ICHasOwn_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::HasOwn_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::HasOwn_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -437,7 +1943,7 @@ class ICGetName_Fallback : public ICMonitoredFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::GetName_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::GetName_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -463,7 +1969,7 @@ class ICBindName_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::BindName_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::BindName_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -489,7 +1995,7 @@ class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -498,6 +2004,61 @@ class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub
};
};
+// GetProp
+// JSOP_GETPROP
+// JSOP_GETPROP_SUPER
+
+class ICGetProp_Fallback : public ICMonitoredFallbackStub
+{
+ friend class ICStubSpace;
+
+ explicit ICGetProp_Fallback(JitCode* stubCode)
+ : ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode)
+ { }
+
+ public:
+ static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
+ static const size_t ACCESSED_GETTER_BIT = 1;
+
+ void noteUnoptimizableAccess() {
+ extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
+ }
+ bool hadUnoptimizableAccess() const {
+ return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
+ }
+
+ void noteAccessedGetter() {
+ extra_ |= (1u << ACCESSED_GETTER_BIT);
+ }
+ bool hasAccessedGetter() const {
+ return extra_ & (1u << ACCESSED_GETTER_BIT);
+ }
+
+ class Compiler : public ICStubCompiler {
+ protected:
+ CodeOffset bailoutReturnOffset_;
+ bool hasReceiver_;
+ MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
+ void postGenerateStubCode(MacroAssembler& masm, Handle code) override;
+
+ virtual int32_t getKey() const override {
+ return static_cast(kind) |
+ (static_cast(hasReceiver_) << 16);
+ }
+
+ public:
+ explicit Compiler(JSContext* cx, bool hasReceiver = false)
+ : ICStubCompiler(cx, ICStub::GetProp_Fallback),
+ hasReceiver_(hasReceiver)
+ { }
+
+ ICStub* getStub(ICStubSpace* space) override {
+ return newStub(space, getStubCode());
+ }
+ };
+};
+
+
// SetProp
// JSOP_SETPROP
// JSOP_SETNAME
@@ -529,7 +2090,7 @@ class ICSetProp_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::SetProp_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::SetProp_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -552,7 +2113,7 @@ class ICCallStubCompiler : public ICStubCompiler
{
protected:
ICCallStubCompiler(JSContext* cx, ICStub::Kind kind)
- : ICStubCompiler(cx, kind, Engine::Baseline)
+ : ICStubCompiler(cx, kind)
{ }
enum FunApplyThing {
@@ -613,10 +2174,9 @@ class ICCall_Fallback : public ICMonitoredFallbackStub
void postGenerateStubCode(MacroAssembler& masm, Handle code) override;
virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(isSpread_) << 17) |
- (static_cast(isConstructing_) << 18);
+ return static_cast(kind) |
+ (static_cast(isSpread_) << 16) |
+ (static_cast(isConstructing_) << 17);
}
public:
@@ -703,11 +2263,10 @@ class ICCallScriptedCompiler : public ICCallStubCompiler {
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(isConstructing_) << 17) |
- (static_cast(isSpread_) << 18) |
- (static_cast(maybeCrossRealm_) << 19);
+ return static_cast(kind) |
+ (static_cast(isConstructing_) << 16) |
+ (static_cast(isSpread_) << 17) |
+ (static_cast(maybeCrossRealm_) << 18);
}
public:
@@ -801,12 +2360,11 @@ class ICCall_Native : public ICMonitoredStub
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(isSpread_) << 17) |
- (static_cast(isConstructing_) << 18) |
- (static_cast(ignoresReturnValue_) << 19) |
- (static_cast(isCrossRealm_) << 20);
+ return static_cast(kind) |
+ (static_cast(isSpread_) << 16) |
+ (static_cast(isConstructing_) << 17) |
+ (static_cast(ignoresReturnValue_) << 18) |
+ (static_cast(isCrossRealm_) << 19);
}
public:
@@ -882,9 +2440,8 @@ class ICCall_ClassHook : public ICMonitoredStub
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(isConstructing_) << 17);
+ return static_cast(kind) |
+ (static_cast(isConstructing_) << 16);
}
public:
@@ -942,11 +2499,6 @@ class ICCall_ScriptedApplyArray : public ICMonitoredStub
uint32_t pcOffset_;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
- virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1);
- }
-
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset)
: ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArray),
@@ -990,11 +2542,6 @@ class ICCall_ScriptedApplyArguments : public ICMonitoredStub
uint32_t pcOffset_;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
- virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1);
- }
-
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset)
: ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArguments),
@@ -1037,11 +2584,6 @@ class ICCall_ScriptedFunCall : public ICMonitoredStub
uint32_t pcOffset_;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
- virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1);
- }
-
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset)
: ICCallStubCompiler(cx, ICStub::Call_ScriptedFunCall),
@@ -1108,11 +2650,6 @@ class ICCall_ConstStringSplit : public ICMonitoredStub
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
- virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1);
- }
-
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset, HandleString str,
HandleString sep, HandleArrayObject templateObject)
@@ -1148,7 +2685,7 @@ class ICCall_IsSuspendedGenerator : public ICStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::Call_IsSuspendedGenerator, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::Call_IsSuspendedGenerator)
{}
ICStub* getStub(ICStubSpace* space) override {
return newStub(space, getStubCode());
@@ -1184,7 +2721,7 @@ class ICTableSwitch : public ICStub
public:
Compiler(JSContext* cx, jsbytecode* pc)
- : ICStubCompiler(cx, ICStub::TableSwitch, Engine::Baseline), pc_(pc)
+ : ICStubCompiler(cx, ICStub::TableSwitch), pc_(pc)
{}
ICStub* getStub(ICStubSpace* space) override;
@@ -1207,7 +2744,7 @@ class ICGetIterator_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::GetIterator_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::GetIterator_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -1240,7 +2777,7 @@ class ICIteratorMore_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::IteratorMore_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::IteratorMore_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -1265,7 +2802,7 @@ class ICIteratorMore_Native : public ICStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::IteratorMore_Native, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::IteratorMore_Native)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -1290,7 +2827,7 @@ class ICIteratorClose_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::IteratorClose_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::IteratorClose_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -1326,7 +2863,7 @@ class ICInstanceOf_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::InstanceOf_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::InstanceOf_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -1355,7 +2892,7 @@ class ICTypeOf_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::TypeOf_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::TypeOf_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -1388,7 +2925,7 @@ class ICRest_Fallback : public ICFallbackStub
public:
Compiler(JSContext* cx, ArrayObject* templateObject)
- : ICStubCompiler(cx, ICStub::Rest_Fallback, Engine::Baseline),
+ : ICStubCompiler(cx, ICStub::Rest_Fallback),
templateObject(cx, templateObject)
{ }
@@ -1416,7 +2953,7 @@ class ICRetSub_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::RetSub_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::RetSub_Fallback)
{ }
ICStub* getStub(ICStubSpace* space) override {
@@ -1457,7 +2994,7 @@ class ICRetSub_Resume : public ICStub
public:
Compiler(JSContext* cx, uint32_t pcOffset, uint8_t* addr)
- : ICStubCompiler(cx, ICStub::RetSub_Resume, Engine::Baseline),
+ : ICStubCompiler(cx, ICStub::RetSub_Resume),
pcOffset_(pcOffset),
addr_(addr)
{ }
@@ -1497,7 +3034,7 @@ class ICUnaryArith_Fallback : public ICFallbackStub
public:
explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, ICStub::UnaryArith_Fallback, Engine::Baseline)
+ : ICStubCompiler(cx, ICStub::UnaryArith_Fallback)
{}
ICStub* getStub(ICStubSpace* space) override {
@@ -1506,6 +3043,50 @@ class ICUnaryArith_Fallback : public ICFallbackStub
};
};
+// Compare
+// JSOP_LT
+// JSOP_LE
+// JSOP_GT
+// JSOP_GE
+// JSOP_EQ
+// JSOP_NE
+// JSOP_STRICTEQ
+// JSOP_STRICTNE
+
+class ICCompare_Fallback : public ICFallbackStub
+{
+ friend class ICStubSpace;
+
+ explicit ICCompare_Fallback(JitCode* stubCode)
+ : ICFallbackStub(ICStub::Compare_Fallback, stubCode) {}
+
+ public:
+ static const uint32_t MAX_OPTIMIZED_STUBS = 8;
+
+ static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
+ void noteUnoptimizableAccess() {
+ extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
+ }
+ bool hadUnoptimizableAccess() const {
+ return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
+ }
+
+ // Compiler for this stub kind.
+ class Compiler : public ICStubCompiler {
+ protected:
+ MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
+
+ public:
+ explicit Compiler(JSContext* cx)
+ : ICStubCompiler(cx, ICStub::Compare_Fallback) {}
+
+ ICStub* getStub(ICStubSpace* space) override {
+ return newStub(space, getStubCode());
+ }
+ };
+};
+
+
// BinaryArith
// JSOP_ADD, JSOP_SUB, JSOP_MUL, JOP_DIV, JSOP_MOD
// JSOP_BITAND, JSOP_BITXOR, JSOP_BITOR
@@ -1546,8 +3127,8 @@ class ICBinaryArith_Fallback : public ICFallbackStub
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
- explicit Compiler(JSContext* cx, Engine engine)
- : ICStubCompiler(cx, ICStub::BinaryArith_Fallback, engine) {}
+ explicit Compiler(JSContext* cx)
+ : ICStubCompiler(cx, ICStub::BinaryArith_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub(space, getStubCode());
@@ -1578,8 +3159,8 @@ class ICNewArray_Fallback : public ICFallbackStub
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
- Compiler(JSContext* cx, ObjectGroup* templateGroup, Engine engine)
- : ICStubCompiler(cx, ICStub::NewArray_Fallback, engine),
+ Compiler(JSContext* cx, ObjectGroup* templateGroup)
+ : ICStubCompiler(cx, ICStub::NewArray_Fallback),
templateGroup(cx, templateGroup)
{}
@@ -1625,8 +3206,8 @@ class ICNewObject_Fallback : public ICFallbackStub
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
- explicit Compiler(JSContext* cx, Engine engine)
- : ICStubCompiler(cx, ICStub::NewObject_Fallback, engine)
+ explicit Compiler(JSContext* cx)
+ : ICStubCompiler(cx, ICStub::NewObject_Fallback)
{}
ICStub* getStub(ICStubSpace* space) override {
diff --git a/js/src/jit/BaselineICList.h b/js/src/jit/BaselineICList.h
index e33f09d39db8..0c5c4b52ae0b 100644
--- a/js/src/jit/BaselineICList.h
+++ b/js/src/jit/BaselineICList.h
@@ -75,8 +75,18 @@ namespace jit {
\
_(Rest_Fallback) \
\
+ _(BinaryArith_Fallback) \
+ \
+ _(Compare_Fallback) \
+ \
+ _(GetProp_Fallback) \
+ \
_(RetSub_Fallback) \
- _(RetSub_Resume)
+ _(RetSub_Resume) \
+ \
+ _(CacheIR_Regular) \
+ _(CacheIR_Monitored) \
+ _(CacheIR_Updated) \
} // namespace jit
} // namespace js
diff --git a/js/src/jit/BaselineInspector.h b/js/src/jit/BaselineInspector.h
index 4c3b4cc2930f..4e854c2d4819 100644
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -43,7 +43,7 @@ class BaselineInspector
{
private:
JSScript* script;
- BaselineICEntry* prevLookedUpEntry;
+ ICEntry* prevLookedUpEntry;
public:
explicit BaselineInspector(JSScript* script)
@@ -67,20 +67,20 @@ class BaselineInspector
}
#endif
- BaselineICEntry& icEntryFromPC(jsbytecode* pc) {
+ ICEntry& icEntryFromPC(jsbytecode* pc) {
MOZ_ASSERT(hasBaselineScript());
MOZ_ASSERT(isValidPC(pc));
- BaselineICEntry& ent =
+ ICEntry& ent =
baselineScript()->icEntryFromPCOffset(script->pcToOffset(pc), prevLookedUpEntry);
MOZ_ASSERT(ent.isForOp());
prevLookedUpEntry = &ent;
return ent;
}
- BaselineICEntry* maybeICEntryFromPC(jsbytecode* pc) {
+ ICEntry* maybeICEntryFromPC(jsbytecode* pc) {
MOZ_ASSERT(hasBaselineScript());
MOZ_ASSERT(isValidPC(pc));
- BaselineICEntry* ent =
+ ICEntry* ent =
baselineScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc), prevLookedUpEntry);
if (!ent)
return nullptr;
@@ -91,7 +91,7 @@ class BaselineInspector
template
ICInspectorType makeICInspector(jsbytecode* pc, ICStub::Kind expectedFallbackKind) {
- BaselineICEntry* ent = nullptr;
+ ICEntry* ent = nullptr;
if (hasBaselineScript()) {
ent = &icEntryFromPC(pc);
MOZ_ASSERT(ent->fallbackStub()->kind() == expectedFallbackKind);
diff --git a/js/src/jit/BaselineJIT.cpp b/js/src/jit/BaselineJIT.cpp
index e1db930a43e6..ccd8d74cdb9f 100644
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -244,7 +244,7 @@ jit::EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc)
MethodStatus
jit::BaselineCompile(JSContext* cx, JSScript* script, bool forceDebugInstrumentation)
{
- assertSameCompartment(cx, script);
+ cx->check(script);
MOZ_ASSERT(!script->hasBaselineScript());
MOZ_ASSERT(script->canBaselineCompile());
MOZ_ASSERT(IsBaselineEnabled(cx));
@@ -377,7 +377,7 @@ BaselineScript::New(JSScript* jsscript,
{
static const unsigned DataAlignment = sizeof(uintptr_t);
- size_t icEntriesSize = icEntries * sizeof(BaselineICEntry);
+ size_t icEntriesSize = icEntries * sizeof(ICEntry);
size_t pcMappingIndexEntriesSize = pcMappingIndexEntries * sizeof(PCMappingIndexEntry);
size_t bytecodeTypeMapSize = bytecodeTypeMapEntries * sizeof(uint32_t);
size_t yieldEntriesSize = yieldEntries * sizeof(uintptr_t);
@@ -441,7 +441,7 @@ BaselineScript::trace(JSTracer* trc)
// Mark all IC stub codes hanging off the IC stub entries.
for (size_t i = 0; i < numICEntries(); i++) {
- BaselineICEntry& ent = icEntry(i);
+ ICEntry& ent = icEntry(i);
ent.trace(trc);
}
}
@@ -536,7 +536,7 @@ BaselineScript::removeDependentWasmImport(wasm::Instance& instance, uint32_t idx
}
}
-BaselineICEntry&
+ICEntry&
BaselineScript::icEntry(size_t index)
{
MOZ_ASSERT(index < numICEntries());
@@ -569,12 +569,12 @@ struct ICEntries
explicit ICEntries(BaselineScript* baseline) : baseline_(baseline) {}
- BaselineICEntry& operator[](size_t index) const {
+ ICEntry& operator[](size_t index) const {
return baseline_->icEntry(index);
}
};
-BaselineICEntry&
+ICEntry&
BaselineScript::icEntryFromReturnOffset(CodeOffset returnOffset)
{
size_t loc;
@@ -582,7 +582,7 @@ BaselineScript::icEntryFromReturnOffset(CodeOffset returnOffset)
bool found =
#endif
BinarySearchIf(ICEntries(this), 0, numICEntries(),
- [&returnOffset](BaselineICEntry& entry) {
+ [&returnOffset](ICEntry& entry) {
size_t roffset = returnOffset.offset();
size_t entryRoffset = entry.returnOffset().offset();
if (roffset < entryRoffset)
@@ -603,7 +603,7 @@ static inline bool
ComputeBinarySearchMid(BaselineScript* baseline, uint32_t pcOffset, size_t* loc)
{
return BinarySearchIf(ICEntries(baseline), 0, baseline->numICEntries(),
- [pcOffset](BaselineICEntry& entry) {
+ [pcOffset](ICEntry& entry) {
uint32_t entryOffset = entry.pcOffset();
if (pcOffset < entryOffset)
return -1;
@@ -615,12 +615,12 @@ ComputeBinarySearchMid(BaselineScript* baseline, uint32_t pcOffset, size_t* loc)
}
uint8_t*
-BaselineScript::returnAddressForIC(const BaselineICEntry& ent)
+BaselineScript::returnAddressForIC(const ICEntry& ent)
{
return method()->raw() + ent.returnOffset().offset();
}
-BaselineICEntry*
+ICEntry*
BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset)
{
// Multiple IC entries can have the same PC offset, but this method only looks for
@@ -647,25 +647,25 @@ BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset)
return nullptr;
}
-BaselineICEntry&
+ICEntry&
BaselineScript::icEntryFromPCOffset(uint32_t pcOffset)
{
- BaselineICEntry* entry = maybeICEntryFromPCOffset(pcOffset);
+ ICEntry* entry = maybeICEntryFromPCOffset(pcOffset);
MOZ_RELEASE_ASSERT(entry);
return *entry;
}
-BaselineICEntry*
-BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry)
+ICEntry*
+BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset, ICEntry* prevLookedUpEntry)
{
// Do a linear forward search from the last queried PC offset, or fallback to a
// binary search if the last offset is too far away.
if (prevLookedUpEntry && pcOffset >= prevLookedUpEntry->pcOffset() &&
(pcOffset - prevLookedUpEntry->pcOffset()) <= 10)
{
- BaselineICEntry* firstEntry = &icEntry(0);
- BaselineICEntry* lastEntry = &icEntry(numICEntries() - 1);
- BaselineICEntry* curEntry = prevLookedUpEntry;
+ ICEntry* firstEntry = &icEntry(0);
+ ICEntry* lastEntry = &icEntry(numICEntries() - 1);
+ ICEntry* curEntry = prevLookedUpEntry;
while (curEntry >= firstEntry && curEntry <= lastEntry) {
if (curEntry->pcOffset() == pcOffset && curEntry->isForOp())
return curEntry;
@@ -677,15 +677,15 @@ BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* pre
return maybeICEntryFromPCOffset(pcOffset);
}
-BaselineICEntry&
-BaselineScript::icEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry)
+ICEntry&
+BaselineScript::icEntryFromPCOffset(uint32_t pcOffset, ICEntry* prevLookedUpEntry)
{
- BaselineICEntry* entry = maybeICEntryFromPCOffset(pcOffset, prevLookedUpEntry);
+ ICEntry* entry = maybeICEntryFromPCOffset(pcOffset, prevLookedUpEntry);
MOZ_RELEASE_ASSERT(entry);
return *entry;
}
-BaselineICEntry&
+ICEntry&
BaselineScript::callVMEntryFromPCOffset(uint32_t pcOffset)
{
// Like icEntryFromPCOffset, but only looks for the fake ICEntries
@@ -707,7 +707,7 @@ BaselineScript::callVMEntryFromPCOffset(uint32_t pcOffset)
MOZ_CRASH("Invalid PC offset for callVM entry.");
}
-BaselineICEntry&
+ICEntry&
BaselineScript::stackCheckICEntry(bool earlyCheck)
{
// The stack check will always be at offset 0, so just do a linear search
@@ -722,7 +722,7 @@ BaselineScript::stackCheckICEntry(bool earlyCheck)
MOZ_CRASH("No stack check ICEntry found.");
}
-BaselineICEntry&
+ICEntry&
BaselineScript::warmupCountICEntry()
{
// The stack check will be at a very low offset, so just do a linear search
@@ -734,7 +734,7 @@ BaselineScript::warmupCountICEntry()
MOZ_CRASH("No warmup count ICEntry found.");
}
-BaselineICEntry&
+ICEntry&
BaselineScript::icEntryFromReturnAddress(uint8_t* returnAddr)
{
MOZ_ASSERT(returnAddr > method_->raw());
@@ -755,12 +755,12 @@ BaselineScript::copyYieldAndAwaitEntries(JSScript* script, Vector& yie
}
void
-BaselineScript::copyICEntries(JSScript* script, const BaselineICEntry* entries)
+BaselineScript::copyICEntries(JSScript* script, const ICEntry* entries)
{
// Fix up the return offset in the IC entries and copy them in.
// Also write out the IC entry ptrs in any fallback stubs that were added.
for (uint32_t i = 0; i < numICEntries(); i++) {
- BaselineICEntry& realEntry = icEntry(i);
+ ICEntry& realEntry = icEntry(i);
realEntry = entries[i];
if (!realEntry.hasStub()) {
@@ -1056,7 +1056,7 @@ BaselineScript::purgeOptimizedStubs(Zone* zone)
JitSpew(JitSpew_BaselineIC, "Purging optimized stubs");
for (size_t i = 0; i < numICEntries(); i++) {
- BaselineICEntry& entry = icEntry(i);
+ ICEntry& entry = icEntry(i);
if (!entry.hasStub())
continue;
@@ -1098,7 +1098,7 @@ BaselineScript::purgeOptimizedStubs(Zone* zone)
#ifdef DEBUG
// All remaining stubs must be allocated in the fallback space.
for (size_t i = 0; i < numICEntries(); i++) {
- BaselineICEntry& entry = icEntry(i);
+ ICEntry& entry = icEntry(i);
if (!entry.hasStub())
continue;
diff --git a/js/src/jit/BaselineJIT.h b/js/src/jit/BaselineJIT.h
index 359ff558dbf6..fea59361ef8e 100644
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -22,7 +22,7 @@ namespace js {
namespace jit {
class StackValue;
-class BaselineICEntry;
+class ICEntry;
class ICStub;
class ControlFlowGraph;
@@ -355,8 +355,8 @@ struct BaselineScript
return method_->raw() + postDebugPrologueOffset_;
}
- BaselineICEntry* icEntryList() {
- return (BaselineICEntry*)(reinterpret_cast(this) + icEntriesOffset_);
+ ICEntry* icEntryList() {
+ return (ICEntry*)(reinterpret_cast(this) + icEntriesOffset_);
}
uint8_t** yieldEntryList() {
return (uint8_t**)(reinterpret_cast(this) + yieldEntriesOffset_);
@@ -391,25 +391,25 @@ struct BaselineScript
return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
}
- BaselineICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
- BaselineICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
- BaselineICEntry* prevLookedUpEntry);
+ ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
+ ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
+ ICEntry* prevLookedUpEntry);
- BaselineICEntry& icEntry(size_t index);
- BaselineICEntry& icEntryFromReturnOffset(CodeOffset returnOffset);
- BaselineICEntry& icEntryFromPCOffset(uint32_t pcOffset);
- BaselineICEntry& icEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry);
- BaselineICEntry& callVMEntryFromPCOffset(uint32_t pcOffset);
- BaselineICEntry& stackCheckICEntry(bool earlyCheck);
- BaselineICEntry& warmupCountICEntry();
- BaselineICEntry& icEntryFromReturnAddress(uint8_t* returnAddr);
- uint8_t* returnAddressForIC(const BaselineICEntry& ent);
+ ICEntry& icEntry(size_t index);
+ ICEntry& icEntryFromReturnOffset(CodeOffset returnOffset);
+ ICEntry& icEntryFromPCOffset(uint32_t pcOffset);
+ ICEntry& icEntryFromPCOffset(uint32_t pcOffset, ICEntry* prevLookedUpEntry);
+ ICEntry& callVMEntryFromPCOffset(uint32_t pcOffset);
+ ICEntry& stackCheckICEntry(bool earlyCheck);
+ ICEntry& warmupCountICEntry();
+ ICEntry& icEntryFromReturnAddress(uint8_t* returnAddr);
+ uint8_t* returnAddressForIC(const ICEntry& ent);
size_t numICEntries() const {
return icEntries_;
}
- void copyICEntries(JSScript* script, const BaselineICEntry* entries);
+ void copyICEntries(JSScript* script, const ICEntry* entries);
void adoptFallbackStubs(FallbackICStubSpace* stubSpace);
void copyYieldAndAwaitEntries(JSScript* script, Vector& yieldAndAwaitOffsets);
diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
index 4a15b13509bc..9868403f0193 100644
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -33,8 +33,9 @@ const char* const js::jit::CacheKindNames[] = {
};
void
-CacheIRWriter::assertSameCompartment(JSObject* obj) {
- assertSameCompartmentDebugOnly(cx_, obj);
+CacheIRWriter::assertSameCompartment(JSObject* obj)
+{
+ cx_->debugOnlyCheck(obj);
}
StubField
@@ -5721,4 +5722,4 @@ NewObjectIRGenerator::tryAttachStub()
trackAttached("NewObjectWithTemplate");
return true;
-}
\ No newline at end of file
+}
diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h
index ff5c390cdcfc..5aa506cd8e07 100644
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -14,7 +14,9 @@
#include "gc/Rooting.h"
#include "jit/CompactBuffer.h"
#include "jit/ICState.h"
-#include "jit/SharedIC.h"
+#include "jit/MacroAssembler.h"
+#include "vm/Iteration.h"
+#include "vm/Shape.h"
namespace js {
namespace jit {
@@ -422,6 +424,13 @@ enum class GuardClassKind : uint8_t
// zone, which refer to the actual shape via a reserved slot.
JSObject* NewWrapperWithObjectShape(JSContext* cx, HandleNativeObject obj);
+// Enum for stubs handling a combination of typed arrays and typed objects.
+enum TypedThingLayout {
+ Layout_TypedArray,
+ Layout_OutlineTypedObject,
+ Layout_InlineTypedObject
+};
+
void LoadShapeWrapperContents(MacroAssembler& masm, Register obj, Register dst, Label* failure);
// Class to record CacheIR + some additional metadata for code generation.
@@ -1976,6 +1985,35 @@ class MOZ_RAII NewObjectIRGenerator : public IRGenerator
bool tryAttachStub();
};
+static inline uint32_t
+SimpleTypeDescrKey(SimpleTypeDescr* descr)
+{
+ if (descr->is())
+ return uint32_t(descr->as().type()) << 1;
+ return (uint32_t(descr->as().type()) << 1) | 1;
+}
+
+inline bool
+SimpleTypeDescrKeyIsScalar(uint32_t key)
+{
+ return !(key & 1);
+}
+
+inline ScalarTypeDescr::Type
+ScalarTypeFromSimpleTypeDescrKey(uint32_t key)
+{
+ MOZ_ASSERT(SimpleTypeDescrKeyIsScalar(key));
+ return ScalarTypeDescr::Type(key >> 1);
+}
+
+inline ReferenceType
+ReferenceTypeFromSimpleTypeDescrKey(uint32_t key)
+{
+ MOZ_ASSERT(!SimpleTypeDescrKeyIsScalar(key));
+ return ReferenceType(key >> 1);
+}
+
+
} // namespace jit
} // namespace js
diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp
index 16475c0476a8..24055535969a 100644
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -3798,3 +3798,37 @@ CacheIRCompiler::emitLoadObject()
emitLoadStubField(obj, reg);
return true;
}
+
+void
+js::jit::LoadTypedThingData(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result)
+{
+ switch (layout) {
+ case Layout_TypedArray:
+ masm.loadPtr(Address(obj, TypedArrayObject::dataOffset()), result);
+ break;
+ case Layout_OutlineTypedObject:
+ masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), result);
+ break;
+ case Layout_InlineTypedObject:
+ masm.computeEffectiveAddress(Address(obj, InlineTypedObject::offsetOfDataStart()), result);
+ break;
+ default:
+ MOZ_CRASH();
+ }
+}
+
+void
+js::jit::LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result)
+{
+ switch (layout) {
+ case Layout_TypedArray:
+ masm.unboxInt32(Address(obj, TypedArrayObject::lengthOffset()), result);
+ break;
+ case Layout_OutlineTypedObject:
+ case Layout_InlineTypedObject:
+ masm.loadTypedObjectLength(obj, result);
+ break;
+ default:
+ MOZ_CRASH();
+ }
+}
\ No newline at end of file
diff --git a/js/src/jit/CacheIRCompiler.h b/js/src/jit/CacheIRCompiler.h
index 5d7a0c72ec1c..1b39b9e676fe 100644
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -902,6 +902,12 @@ class CacheIRStubInfo
template
void TraceCacheIRStub(JSTracer* trc, T* stub, const CacheIRStubInfo* stubInfo);
+void
+LoadTypedThingData(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result);
+
+void
+LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result);
+
} // namespace jit
} // namespace js
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 4b6740009721..0d3c3a9a7783 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2864,43 +2864,6 @@ CodeGenerator::visitStringReplace(LStringReplace* lir)
callVM(StringReplaceInfo, lir);
}
-void
-CodeGenerator::emitSharedStub(ICStub::Kind kind, LInstruction* lir)
-{
- JSScript* script = lir->mirRaw()->block()->info().script();
- jsbytecode* pc = lir->mirRaw()->toInstruction()->resumePoint()->pc();
-
-#ifdef JS_USE_LINK_REGISTER
- // Some architectures don't push the return address on the stack but
- // use the link register. In that case the stack isn't aligned. Push
- // to make sure we are aligned.
- masm.Push(Imm32(0));
-#endif
-
- // Create descriptor signifying end of Ion frame.
- uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS,
- JitStubFrameLayout::Size());
- masm.Push(Imm32(descriptor));
-
- // Call into the stubcode.
- CodeOffset patchOffset;
- IonICEntry entry(script->pcToOffset(pc), ICEntry::Kind_Op, script);
- EmitCallIC(&patchOffset, masm);
- entry.setReturnOffset(CodeOffset(masm.currentOffset()));
-
- SharedStub sharedStub(kind, entry, patchOffset);
- masm.propagateOOM(sharedStubs_.append(sharedStub));
-
- // Fix up upon return.
- uint32_t callOffset = masm.currentOffset();
-#ifdef JS_USE_LINK_REGISTER
- masm.freeStack(sizeof(intptr_t) * 2);
-#else
- masm.freeStack(sizeof(intptr_t));
-#endif
- markSafepointAt(callOffset, lir);
-}
-
void
CodeGenerator::visitBinaryCache(LBinaryCache* lir)
{
@@ -2939,34 +2902,6 @@ CodeGenerator::visitBinaryCache(LBinaryCache* lir)
}
}
-void
-CodeGenerator::visitBinarySharedStub(LBinarySharedStub* lir)
-{
- JSOp jsop = JSOp(*lir->mirRaw()->toInstruction()->resumePoint()->pc());
- switch (jsop) {
- case JSOP_ADD:
- case JSOP_SUB:
- case JSOP_MUL:
- case JSOP_DIV:
- case JSOP_MOD:
- case JSOP_POW:
- emitSharedStub(ICStub::Kind::BinaryArith_Fallback, lir);
- break;
- case JSOP_LT:
- case JSOP_LE:
- case JSOP_GT:
- case JSOP_GE:
- case JSOP_EQ:
- case JSOP_NE:
- case JSOP_STRICTEQ:
- case JSOP_STRICTNE:
- emitSharedStub(ICStub::Kind::Compare_Fallback, lir);
- break;
- default:
- MOZ_CRASH("Unsupported jsop in shared stubs.");
- }
-}
-
void
CodeGenerator::visitUnaryCache(LUnaryCache* lir)
{
@@ -2978,32 +2913,6 @@ CodeGenerator::visitUnaryCache(LUnaryCache* lir)
addIC(lir, allocateIC(ic));
}
-void
-CodeGenerator::visitNullarySharedStub(LNullarySharedStub* lir)
-{
- jsbytecode* pc = lir->mir()->resumePoint()->pc();
- JSOp jsop = JSOp(*pc);
- switch (jsop) {
- case JSOP_NEWARRAY: {
- uint32_t length = GET_UINT32(pc);
- MOZ_ASSERT(length <= INT32_MAX,
- "the bytecode emitter must fail to compile code that would "
- "produce JSOP_NEWARRAY with a length exceeding int32_t range");
-
- // Pass length in R0.
- masm.move32(Imm32(AssertedCast(length)), R0.scratchReg());
- emitSharedStub(ICStub::Kind::NewArray_Fallback, lir);
- break;
- }
- case JSOP_NEWINIT:
- case JSOP_NEWOBJECT:
- emitSharedStub(ICStub::Kind::NewObject_Fallback, lir);
- break;
- default:
- MOZ_CRASH("Unsupported jsop in shared stubs.");
- }
-}
-
typedef JSFunction* (*MakeDefaultConstructorFn)(JSContext*, HandleScript,
jsbytecode*, HandleObject);
static const VMFunction MakeDefaultConstructorInfo =
@@ -10386,51 +10295,6 @@ CodeGenerator::generate()
return !masm.oom();
}
-bool
-CodeGenerator::linkSharedStubs(JSContext* cx)
-{
- for (uint32_t i = 0; i < sharedStubs_.length(); i++) {
- ICStub *stub = nullptr;
-
- switch (sharedStubs_[i].kind) {
- case ICStub::Kind::Compare_Fallback: {
- ICCompare_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::IonSharedIC);
- stub = stubCompiler.getStub(&stubSpace_);
- break;
- }
- case ICStub::Kind::GetProp_Fallback: {
- ICGetProp_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::IonSharedIC);
- stub = stubCompiler.getStub(&stubSpace_);
- break;
- }
- case ICStub::Kind::NewArray_Fallback: {
- JSScript* script = sharedStubs_[i].entry.script();
- jsbytecode* pc = sharedStubs_[i].entry.pc(script);
- ObjectGroup* group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
- if (!group)
- return false;
-
- ICNewArray_Fallback::Compiler stubCompiler(cx, group, ICStubCompiler::Engine::IonSharedIC);
- stub = stubCompiler.getStub(&stubSpace_);
- break;
- }
- case ICStub::Kind::NewObject_Fallback: {
- ICNewObject_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::IonSharedIC);
- stub = stubCompiler.getStub(&stubSpace_);
- break;
- }
- default:
- MOZ_CRASH("Unsupported shared stub.");
- }
-
- if (!stub)
- return false;
-
- sharedStubs_[i].entry.setFirstStub(stub);
- }
- return true;
-}
-
bool
CodeGenerator::link(JSContext* cx, CompilerConstraintList* constraints)
{
@@ -10459,9 +10323,6 @@ CodeGenerator::link(JSContext* cx, CompilerConstraintList* constraints)
if (scriptCounts_ && !script->hasScriptCounts() && !script->initScriptCounts(cx))
return false;
- if (!linkSharedStubs(cx))
- return false;
-
// Check to make sure we didn't have a mid-build invalidation. If so, we
// will trickle to jit::Compile() and return Method_Skipped.
uint32_t warmUpCount = script->getWarmUpCount();
@@ -10504,8 +10365,7 @@ CodeGenerator::link(JSContext* cx, CompilerConstraintList* constraints)
recovers_.size(), bailouts_.length(), graph.numConstants(),
safepointIndices_.length(), osiIndices_.length(),
icList_.length(), runtimeData_.length(),
- safepoints_.size(), sharedStubs_.length(),
- optimizationLevel);
+ safepoints_.size(), optimizationLevel);
if (!ionScript)
return false;
auto guardIonScript = mozilla::MakeScopeExit([&ionScript] {
@@ -10603,9 +10463,6 @@ CodeGenerator::link(JSContext* cx, CompilerConstraintList* constraints)
script->setIonScript(cx->runtime(), ionScript);
- // Adopt fallback shared stubs from the compiler into the ion script.
- ionScript->adoptFallbackStubs(&stubSpace_);
-
Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, invalidateEpilogueData_),
ImmPtr(ionScript),
ImmPtr((void*)-1));
@@ -10646,22 +10503,6 @@ CodeGenerator::link(JSContext* cx, CompilerConstraintList* constraints)
}
#endif
- // Patch shared stub IC loads using IC entries
- for (size_t i = 0; i < sharedStubs_.length(); i++) {
- CodeOffset label = sharedStubs_[i].label;
-
- IonICEntry& entry = ionScript->sharedStubList()[i];
- entry = sharedStubs_[i].entry;
- Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, label),
- ImmPtr(&entry),
- ImmPtr((void*)-1));
-
- MOZ_ASSERT(entry.hasStub());
- MOZ_ASSERT(entry.firstStub()->isFallback());
-
- entry.firstStub()->toFallbackStub()->fixupICEntry(&entry);
- }
-
// for generating inline caches during the execution.
if (runtimeData_.length())
ionScript->copyRuntimeData(&runtimeData_[0]);
diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h
index 0d4f4d4506a7..561a1b93baf7 100644
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -76,7 +76,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
wasm::FuncOffsets* offsets);
MOZ_MUST_USE bool link(JSContext* cx, CompilerConstraintList* constraints);
- MOZ_MUST_USE bool linkSharedStubs(JSContext* cx);
void emitOOLTestObject(Register objreg, Label* ifTruthy, Label* ifFalsy, Register scratch);
void emitIntToString(Register input, Register output, Label* ool);
@@ -113,7 +112,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitOutOfLineNewObject(OutOfLineNewObject* ool);
private:
- void emitSharedStub(ICStub::Kind kind, LInstruction* lir);
void emitPostWriteBarrier(const LAllocation* obj);
void emitPostWriteBarrier(Register objreg);
@@ -290,18 +288,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
Vector ionScriptLabels_;
- struct SharedStub {
- ICStub::Kind kind;
- IonICEntry entry;
- CodeOffset label;
-
- SharedStub(ICStub::Kind kind, IonICEntry entry, CodeOffset label)
- : kind(kind), entry(entry), label(label)
- {}
- };
-
- Vector sharedStubs_;
-
void branchIfInvalidated(Register temp, Label* invalidated);
#ifdef DEBUG
diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp
index 0562887a2ab6..e66512fef9e9 100644
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -830,13 +830,10 @@ IonScript::IonScript(IonCompilationId compilationId)
recoversSize_(0),
constantTable_(0),
constantEntries_(0),
- sharedStubList_(0),
- sharedStubEntries_(0),
invalidationCount_(0),
compilationId_(compilationId),
optimizationLevel_(OptimizationLevel::Normal),
- osrPcMismatchCounter_(0),
- fallbackStubSpace_()
+ osrPcMismatchCounter_(0)
{
}
@@ -848,7 +845,7 @@ IonScript::New(JSContext* cx, IonCompilationId compilationId,
size_t constants, size_t safepointIndices,
size_t osiIndices, size_t icEntries,
size_t runtimeSize, size_t safepointsSize,
- size_t sharedStubEntries, OptimizationLevel optimizationLevel)
+ OptimizationLevel optimizationLevel)
{
constexpr size_t DataAlignment = sizeof(void*);
@@ -871,7 +868,6 @@ IonScript::New(JSContext* cx, IonCompilationId compilationId,
size_t paddedICEntriesSize = AlignBytes(icEntries * sizeof(uint32_t), DataAlignment);
size_t paddedRuntimeSize = AlignBytes(runtimeSize, DataAlignment);
size_t paddedSafepointSize = AlignBytes(safepointsSize, DataAlignment);
- size_t paddedSharedStubSize = AlignBytes(sharedStubEntries * sizeof(IonICEntry), DataAlignment);
size_t bytes = paddedSnapshotsSize +
paddedRecoversSize +
@@ -881,8 +877,7 @@ IonScript::New(JSContext* cx, IonCompilationId compilationId,
paddedOsiIndicesSize +
paddedICEntriesSize +
paddedRuntimeSize +
- paddedSafepointSize +
- paddedSharedStubSize;
+ paddedSafepointSize;
IonScript* script = cx->pod_malloc_with_extra(bytes);
if (!script)
return nullptr;
@@ -927,10 +922,6 @@ IonScript::New(JSContext* cx, IonCompilationId compilationId,
script->constantEntries_ = constants;
offsetCursor += paddedConstantsSize;
- script->sharedStubList_ = offsetCursor;
- script->sharedStubEntries_ = sharedStubEntries;
- offsetCursor += paddedSharedStubSize;
-
script->frameSlots_ = frameSlots;
script->argumentSlots_ = argumentSlots;
@@ -941,13 +932,6 @@ IonScript::New(JSContext* cx, IonCompilationId compilationId,
return script;
}
-void
-IonScript::adoptFallbackStubs(FallbackICStubSpace* stubSpace)
-
-{
- fallbackStubSpace()->adoptFrom(stubSpace);
-}
-
void
IonScript::trace(JSTracer* trc)
{
@@ -957,12 +941,6 @@ IonScript::trace(JSTracer* trc)
for (size_t i = 0; i < numConstants(); i++)
TraceEdge(trc, &getConstant(i), "constant");
- // Mark all IC stub codes hanging off the IC stub entries.
- for (size_t i = 0; i < numSharedStubs(); i++) {
- IonICEntry& ent = sharedStubList()[i];
- ent.trace(trc);
- }
-
// Trace caches so that the JSScript pointer can be updated if moved.
for (size_t i = 0; i < numICs(); i++)
getICFromIndex(i).trace(trc);
@@ -1131,16 +1109,6 @@ IonScript::Trace(JSTracer* trc, IonScript* script)
void
IonScript::Destroy(FreeOp* fop, IonScript* script)
{
- /*
- * When the script contains pointers to nursery things, the store buffer can
- * contain entries that point into the fallback stub space. Since we can
- * destroy scripts outside the context of a GC, this situation could result
- * in us trying to mark invalid store buffer entries.
- *
- * Defer freeing any allocated blocks until after the next minor GC.
- */
- script->fallbackStubSpace_.freeAllAfterMinorGC(script->method()->zone());
-
fop->delete_(script);
}
@@ -1150,62 +1118,6 @@ JS::DeletePolicy::operator()(const js::jit::IonScript* scrip
IonScript::Destroy(rt_->defaultFreeOp(), const_cast(script));
}
-void
-IonScript::purgeOptimizedStubs(Zone* zone)
-{
- for (size_t i = 0; i < numSharedStubs(); i++) {
- IonICEntry& entry = sharedStubList()[i];
- if (!entry.hasStub())
- continue;
-
- ICStub* lastStub = entry.firstStub();
- while (lastStub->next())
- lastStub = lastStub->next();
-
- if (lastStub->isFallback()) {
- // Unlink all stubs allocated in the optimized space.
- ICStub* stub = entry.firstStub();
- ICStub* prev = nullptr;
-
- while (stub->next()) {
- if (!stub->allocatedInFallbackSpace()) {
- lastStub->toFallbackStub()->unlinkStub(zone, prev, stub);
- stub = stub->next();
- continue;
- }
-
- prev = stub;
- stub = stub->next();
- }
-
- lastStub->toFallbackStub()->setInvalid();
-
- MOZ_ASSERT(!lastStub->isMonitoredFallback(),
- "None of the shared stubs used in Ion are monitored");
- } else if (lastStub->isTypeMonitor_Fallback()) {
- lastStub->toTypeMonitor_Fallback()->resetMonitorStubChain(zone);
- lastStub->toTypeMonitor_Fallback()->setInvalid();
- } else {
- MOZ_ASSERT(lastStub->isTableSwitch());
- }
- }
-
-#ifdef DEBUG
- // All remaining stubs must be allocated in the fallback space.
- for (size_t i = 0; i < numSharedStubs(); i++) {
- IonICEntry& entry = sharedStubList()[i];
- if (!entry.hasStub())
- continue;
-
- ICStub* stub = entry.firstStub();
- while (stub->next()) {
- MOZ_ASSERT(stub->allocatedInFallbackSpace());
- stub = stub->next();
- }
- }
-#endif
-}
-
void
IonScript::purgeICs(Zone* zone)
{
@@ -2733,7 +2645,6 @@ InvalidateActivation(FreeOp* fop, const JitActivationIterator& activations, bool
// prevent lastJump_ from appearing to be a bogus pointer, just
// in case anyone tries to read it.
ionScript->purgeICs(script->zone());
- ionScript->purgeOptimizedStubs(script->zone());
// This frame needs to be invalidated. We do the following:
//
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index ebe374a5ddde..e6b14f61af33 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -6114,9 +6114,8 @@ IonBuilder::compareTryBinaryStub(bool* emitted, MDefinition* left, MDefinition*
{
MOZ_ASSERT(*emitted == false);
- // Try to emit a shared stub cache.
-
- if (JitOptions.disableSharedStubs)
+ // Try to emit a CacheIR Stub.
+ if (JitOptions.disableCacheIR)
return Ok();
if (JSOp(*pc) == JSOP_CASE || IsCallPC(pc))
@@ -6490,10 +6489,7 @@ IonBuilder::initializeArrayElement(MDefinition* obj, size_t index, MDefinition*
if (needsPostBarrier(value))
current->add(MPostWriteBarrier::New(alloc(), obj, value));
- if ((obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) ||
- (obj->isNullarySharedStub() &&
- obj->resultTypeSet()->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles))
- {
+ if (obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) {
MInstruction* valueDouble = MToDouble::New(alloc(), value);
current->add(valueDouble);
value = valueDouble;
diff --git a/js/src/jit/IonCode.h b/js/src/jit/IonCode.h
index 9b1d528cae48..79e22aa60692 100644
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -26,7 +26,6 @@ namespace jit {
class MacroAssembler;
class IonBuilder;
-class IonICEntry;
class JitCode;
typedef Vector ObjectVector;
@@ -258,10 +257,6 @@ struct IonScript
uint32_t constantTable_;
uint32_t constantEntries_;
- // List of entries to the shared stub.
- uint32_t sharedStubList_;
- uint32_t sharedStubEntries_;
-
// Number of references from invalidation records.
uint32_t invalidationCount_;
@@ -275,9 +270,6 @@ struct IonScript
// a LOOPENTRY pc other than osrPc_.
uint32_t osrPcMismatchCounter_;
- // Allocated space for fallback stubs.
- FallbackICStubSpace fallbackStubSpace_;
-
// TraceLogger events that are baked into the IonScript.
TraceLoggerEventVector traceLoggerEvents_;
@@ -323,12 +315,6 @@ struct IonScript
// Do not call directly, use IonScript::New. This is public for cx->new_.
explicit IonScript(IonCompilationId compilationId);
- ~IonScript() {
- // The contents of the fallback stub space are removed and freed
- // separately after the next minor GC. See IonScript::Destroy.
- MOZ_ASSERT(fallbackStubSpace_.isEmpty());
- }
-
static IonScript* New(JSContext* cx, IonCompilationId compilationId,
uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
size_t snapshotsListSize, size_t snapshotsRVATableSize,
@@ -336,7 +322,7 @@ struct IonScript
size_t constants, size_t safepointIndexEntries,
size_t osiIndexEntries, size_t icEntries,
size_t runtimeSize, size_t safepointsSize,
- size_t sharedStubEntries, OptimizationLevel optimizationLevel);
+ OptimizationLevel optimizationLevel);
static void Trace(JSTracer* trc, IonScript* script);
static void Destroy(FreeOp* fop, IonScript* script);
@@ -491,12 +477,6 @@ struct IonScript
size_t numICs() const {
return icEntries_;
}
- IonICEntry* sharedStubList() {
- return (IonICEntry*) &bottomBuffer()[sharedStubList_];
- }
- size_t numSharedStubs() const {
- return sharedStubEntries_;
- }
size_t runtimeSize() const {
return runtimeSize_;
}
@@ -555,12 +535,6 @@ struct IonScript
recompiling_ = false;
}
- FallbackICStubSpace* fallbackStubSpace() {
- return &fallbackStubSpace_;
- }
- void adoptFallbackStubs(FallbackICStubSpace* stubSpace);
- void purgeOptimizedStubs(Zone* zone);
-
enum ShouldIncreaseAge {
IncreaseAge = true,
KeepAge = false
diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
index 0447934cd400..4e932c40bd70 100644
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -125,9 +125,6 @@ DefaultJitOptions::DefaultJitOptions()
// Toggles whether CacheIR stubs for binary arith operations are used
SET_DEFAULT(disableCacheIRBinaryArith, false);
- // Toggles whether shared stubs are used in Ionmonkey.
- SET_DEFAULT(disableSharedStubs, false);
-
// Toggles whether sincos optimization is globally disabled.
// See bug984018: The MacOS is the only one that has the sincos fast.
#if defined(XP_MACOSX)
diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
index 70ee54800bab..3f6a331feb44 100644
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -63,7 +63,6 @@ struct DefaultJitOptions
bool disableScalarReplacement;
bool disableCacheIR;
bool disableCacheIRBinaryArith;
- bool disableSharedStubs;
bool disableSincos;
bool disableSink;
bool eagerCompilation;
diff --git a/js/src/jit/JitRealm.h b/js/src/jit/JitRealm.h
index 6fd6a38a9db1..b5a8db28c366 100644
--- a/js/src/jit/JitRealm.h
+++ b/js/src/jit/JitRealm.h
@@ -342,12 +342,9 @@ enum class CacheKind : uint8_t;
class CacheIRStubInfo;
enum class ICStubEngine : uint8_t {
- // Baseline IC, see SharedIC.h and BaselineIC.h.
+ // Baseline IC, see BaselineIC.h.
Baseline = 0,
- // Ion IC that reuses Baseline IC code, see SharedIC.h.
- IonSharedIC,
-
// Ion IC, see IonIC.h.
IonIC
};
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index 04c7e0387fba..ff35b60b0d05 100644
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2529,22 +2529,6 @@ LIRGenerator::visitBinaryCache(MBinaryCache* ins)
assignSafepoint(lir, ins);
}
-
-void
-LIRGenerator::visitBinarySharedStub(MBinarySharedStub* ins)
-{
- MDefinition* lhs = ins->getOperand(0);
- MDefinition* rhs = ins->getOperand(1);
-
- MOZ_ASSERT(ins->type() == MIRType::Value);
- MOZ_ASSERT(ins->type() == MIRType::Value);
-
- LBinarySharedStub* lir = new(alloc()) LBinarySharedStub(useBoxFixedAtStart(lhs, R0),
- useBoxFixedAtStart(rhs, R1));
- defineSharedStubReturn(lir, ins);
- assignSafepoint(lir, ins);
-}
-
void
LIRGenerator::visitUnaryCache(MUnaryCache* ins)
{
@@ -2556,17 +2540,6 @@ LIRGenerator::visitUnaryCache(MUnaryCache* ins)
assignSafepoint(lir, ins);
}
-void
-LIRGenerator::visitNullarySharedStub(MNullarySharedStub* ins)
-{
- MOZ_ASSERT(ins->type() == MIRType::Value);
-
- LNullarySharedStub* lir = new(alloc()) LNullarySharedStub();
-
- defineSharedStubReturn(lir, ins);
- assignSafepoint(lir, ins);
-}
-
void
LIRGenerator::visitClassConstructor(MClassConstructor* ins)
{
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 33a033bbdc2a..e424a98fa234 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7112,22 +7112,6 @@ class MOsrReturnValue
}
};
-class MBinarySharedStub
- : public MBinaryInstruction,
- public MixPolicy, BoxPolicy<1> >::Data
-{
- protected:
- explicit MBinarySharedStub(MDefinition* left, MDefinition* right)
- : MBinaryInstruction(classOpcode, left, right)
- {
- setResultType(MIRType::Value);
- }
-
- public:
- INSTRUCTION_HEADER(BinarySharedStub)
- TRIVIAL_NEW_WRAPPERS
-};
-
class MBinaryCache
: public MBinaryInstruction,
public MixPolicy, BoxPolicy<1> >::Data
@@ -7159,20 +7143,6 @@ class MUnaryCache
TRIVIAL_NEW_WRAPPERS
};
-class MNullarySharedStub
- : public MNullaryInstruction
-{
- explicit MNullarySharedStub()
- : MNullaryInstruction(classOpcode)
- {
- setResultType(MIRType::Value);
- }
-
- public:
- INSTRUCTION_HEADER(NullarySharedStub)
- TRIVIAL_NEW_WRAPPERS
-};
-
// Check the current frame for over-recursion past the global stack limit.
class MCheckOverRecursed
: public MNullaryInstruction
diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp
deleted file mode 100644
index bca193b52399..000000000000
--- a/js/src/jit/SharedIC.cpp
+++ /dev/null
@@ -1,1189 +0,0 @@
-/* -*- 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/SharedIC.h"
-
-#include "mozilla/Casting.h"
-#include "mozilla/IntegerPrintfMacros.h"
-#include "mozilla/Sprintf.h"
-
-#include "jslibmath.h"
-#include "jstypes.h"
-
-#include "gc/Policy.h"
-#include "jit/BaselineCacheIRCompiler.h"
-#include "jit/BaselineDebugModeOSR.h"
-#include "jit/BaselineIC.h"
-#include "jit/JitSpewer.h"
-#include "jit/Linker.h"
-#include "jit/SharedICHelpers.h"
-#ifdef JS_ION_PERF
-# include "jit/PerfSpewer.h"
-#endif
-#include "jit/VMFunctions.h"
-#include "vm/Interpreter.h"
-#include "vm/StringType.h"
-
-#include "jit/MacroAssembler-inl.h"
-#include "jit/SharedICHelpers-inl.h"
-#include "vm/Interpreter-inl.h"
-
-using mozilla::BitwiseCast;
-
-namespace js {
-namespace jit {
-
-#ifdef JS_JITSPEW
-void
-FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...)
-{
- if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
- RootedScript script(cx, GetTopJitJSScript(cx));
- jsbytecode* pc = stub->icEntry()->pc(script);
-
- char fmtbuf[100];
- va_list args;
- va_start(args, fmt);
- (void) VsprintfLiteral(fmtbuf, fmt, args);
- va_end(args);
-
- JitSpew(JitSpew_BaselineICFallback,
- "Fallback hit for (%s:%u) (pc=%zu,line=%d,uses=%d,stubs=%zu): %s",
- script->filename(),
- script->lineno(),
- script->pcToOffset(pc),
- PCToLineNumber(script, pc),
- script->getWarmUpCount(),
- stub->numOptimizedStubs(),
- fmtbuf);
- }
-}
-
-void
-TypeFallbackICSpew(JSContext* cx, ICTypeMonitor_Fallback* stub, const char* fmt, ...)
-{
- if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
- RootedScript script(cx, GetTopJitJSScript(cx));
- jsbytecode* pc = stub->icEntry()->pc(script);
-
- char fmtbuf[100];
- va_list args;
- va_start(args, fmt);
- (void) VsprintfLiteral(fmtbuf, fmt, args);
- va_end(args);
-
- JitSpew(JitSpew_BaselineICFallback,
- "Type monitor fallback hit for (%s:%u) (pc=%zu,line=%d,uses=%d,stubs=%d): %s",
- script->filename(),
- script->lineno(),
- script->pcToOffset(pc),
- PCToLineNumber(script, pc),
- script->getWarmUpCount(),
- (int) stub->numOptimizedMonitorStubs(),
- fmtbuf);
- }
-}
-#endif // JS_JITSPEW
-
-ICFallbackStub*
-ICEntry::fallbackStub() const
-{
- return firstStub()->getChainFallback();
-}
-
-void
-IonICEntry::trace(JSTracer* trc)
-{
- TraceManuallyBarrieredEdge(trc, &script_, "IonICEntry::script_");
- traceEntry(trc);
-}
-
-void
-BaselineICEntry::trace(JSTracer* trc)
-{
- traceEntry(trc);
-}
-
-void
-ICEntry::traceEntry(JSTracer* trc)
-{
- if (!hasStub())
- return;
- for (ICStub* stub = firstStub(); stub; stub = stub->next())
- stub->trace(trc);
-}
-
-ICStubConstIterator&
-ICStubConstIterator::operator++()
-{
- MOZ_ASSERT(currentStub_ != nullptr);
- currentStub_ = currentStub_->next();
- return *this;
-}
-
-
-ICStubIterator::ICStubIterator(ICFallbackStub* fallbackStub, bool end)
- : icEntry_(fallbackStub->icEntry()),
- fallbackStub_(fallbackStub),
- previousStub_(nullptr),
- currentStub_(end ? fallbackStub : icEntry_->firstStub()),
- unlinked_(false)
-{ }
-
-ICStubIterator&
-ICStubIterator::operator++()
-{
- MOZ_ASSERT(currentStub_->next() != nullptr);
- if (!unlinked_)
- previousStub_ = currentStub_;
- currentStub_ = currentStub_->next();
- unlinked_ = false;
- return *this;
-}
-
-void
-ICStubIterator::unlink(JSContext* cx)
-{
- MOZ_ASSERT(currentStub_->next() != nullptr);
- MOZ_ASSERT(currentStub_ != fallbackStub_);
- MOZ_ASSERT(!unlinked_);
-
- fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
-
- // Mark the current iterator position as unlinked, so operator++ works properly.
- unlinked_ = true;
-}
-
-/* static */ bool
-ICStub::NonCacheIRStubMakesGCCalls(Kind kind)
-{
- MOZ_ASSERT(IsValidKind(kind));
- MOZ_ASSERT(!IsCacheIRKind(kind));
-
- switch (kind) {
- case Call_Fallback:
- case Call_Scripted:
- case Call_AnyScripted:
- case Call_Native:
- case Call_ClassHook:
- case Call_ScriptedApplyArray:
- case Call_ScriptedApplyArguments:
- case Call_ScriptedFunCall:
- case Call_ConstStringSplit:
- case WarmUpCounter_Fallback:
- case RetSub_Fallback:
- // These two fallback stubs don't actually make non-tail calls,
- // but the fallback code for the bailout path needs to pop the stub frame
- // pushed during the bailout.
- case GetProp_Fallback:
- case SetProp_Fallback:
- return true;
- default:
- return false;
- }
-}
-
-bool
-ICStub::makesGCCalls() const
-{
- switch (kind()) {
- case CacheIR_Regular:
- return toCacheIR_Regular()->stubInfo()->makesGCCalls();
- case CacheIR_Monitored:
- return toCacheIR_Monitored()->stubInfo()->makesGCCalls();
- case CacheIR_Updated:
- return toCacheIR_Updated()->stubInfo()->makesGCCalls();
- default:
- return NonCacheIRStubMakesGCCalls(kind());
- }
-}
-
-void
-ICStub::traceCode(JSTracer* trc, const char* name)
-{
- JitCode* stubJitCode = jitCode();
- TraceManuallyBarrieredEdge(trc, &stubJitCode, name);
-}
-
-void
-ICStub::updateCode(JitCode* code)
-{
- // Write barrier on the old code.
- JitCode::writeBarrierPre(jitCode());
- stubCode_ = code->raw();
-}
-
-/* static */ void
-ICStub::trace(JSTracer* trc)
-{
- traceCode(trc, "shared-stub-jitcode");
-
- // If the stub is a monitored fallback stub, then trace the monitor ICs hanging
- // off of that stub. We don't need to worry about the regular monitored stubs,
- // because the regular monitored stubs will always have a monitored fallback stub
- // that references the same stub chain.
- if (isMonitoredFallback()) {
- ICTypeMonitor_Fallback* lastMonStub =
- toMonitoredFallbackStub()->maybeFallbackMonitorStub();
- if (lastMonStub) {
- for (ICStubConstIterator iter(lastMonStub->firstMonitorStub());
- !iter.atEnd();
- iter++)
- {
- MOZ_ASSERT_IF(iter->next() == nullptr, *iter == lastMonStub);
- iter->trace(trc);
- }
- }
- }
-
- if (isUpdated()) {
- for (ICStubConstIterator iter(toUpdatedStub()->firstUpdateStub()); !iter.atEnd(); iter++) {
- MOZ_ASSERT_IF(iter->next() == nullptr, iter->isTypeUpdate_Fallback());
- iter->trace(trc);
- }
- }
-
- switch (kind()) {
- case ICStub::Call_Scripted: {
- ICCall_Scripted* callStub = toCall_Scripted();
- TraceEdge(trc, &callStub->callee(), "baseline-callscripted-callee");
- TraceNullableEdge(trc, &callStub->templateObject(), "baseline-callscripted-template");
- break;
- }
- case ICStub::Call_Native: {
- ICCall_Native* callStub = toCall_Native();
- TraceEdge(trc, &callStub->callee(), "baseline-callnative-callee");
- TraceNullableEdge(trc, &callStub->templateObject(), "baseline-callnative-template");
- break;
- }
- case ICStub::Call_ClassHook: {
- ICCall_ClassHook* callStub = toCall_ClassHook();
- TraceNullableEdge(trc, &callStub->templateObject(), "baseline-callclasshook-template");
- break;
- }
- case ICStub::Call_ConstStringSplit: {
- ICCall_ConstStringSplit* callStub = toCall_ConstStringSplit();
- TraceEdge(trc, &callStub->templateObject(), "baseline-callstringsplit-template");
- TraceEdge(trc, &callStub->expectedSep(), "baseline-callstringsplit-sep");
- TraceEdge(trc, &callStub->expectedStr(), "baseline-callstringsplit-str");
- break;
- }
- case ICStub::TypeMonitor_SingleObject: {
- ICTypeMonitor_SingleObject* monitorStub = toTypeMonitor_SingleObject();
- TraceEdge(trc, &monitorStub->object(), "baseline-monitor-singleton");
- break;
- }
- case ICStub::TypeMonitor_ObjectGroup: {
- ICTypeMonitor_ObjectGroup* monitorStub = toTypeMonitor_ObjectGroup();
- TraceEdge(trc, &monitorStub->group(), "baseline-monitor-group");
- break;
- }
- case ICStub::TypeUpdate_SingleObject: {
- ICTypeUpdate_SingleObject* updateStub = toTypeUpdate_SingleObject();
- TraceEdge(trc, &updateStub->object(), "baseline-update-singleton");
- break;
- }
- case ICStub::TypeUpdate_ObjectGroup: {
- ICTypeUpdate_ObjectGroup* updateStub = toTypeUpdate_ObjectGroup();
- TraceEdge(trc, &updateStub->group(), "baseline-update-group");
- break;
- }
- case ICStub::NewArray_Fallback: {
- ICNewArray_Fallback* stub = toNewArray_Fallback();
- TraceNullableEdge(trc, &stub->templateObject(), "baseline-newarray-template");
- TraceEdge(trc, &stub->templateGroup(), "baseline-newarray-template-group");
- break;
- }
- case ICStub::NewObject_Fallback: {
- ICNewObject_Fallback* stub = toNewObject_Fallback();
- TraceNullableEdge(trc, &stub->templateObject(), "baseline-newobject-template");
- break;
- }
- case ICStub::Rest_Fallback: {
- ICRest_Fallback* stub = toRest_Fallback();
- TraceEdge(trc, &stub->templateObject(), "baseline-rest-template");
- break;
- }
- case ICStub::CacheIR_Regular:
- TraceCacheIRStub(trc, this, toCacheIR_Regular()->stubInfo());
- break;
- case ICStub::CacheIR_Monitored:
- TraceCacheIRStub(trc, this, toCacheIR_Monitored()->stubInfo());
- break;
- case ICStub::CacheIR_Updated: {
- ICCacheIR_Updated* stub = toCacheIR_Updated();
- TraceNullableEdge(trc, &stub->updateStubGroup(), "baseline-update-stub-group");
- TraceEdge(trc, &stub->updateStubId(), "baseline-update-stub-id");
- TraceCacheIRStub(trc, this, stub->stubInfo());
- break;
- }
- default:
- break;
- }
-}
-
-void
-ICFallbackStub::unlinkStub(Zone* zone, ICStub* prev, ICStub* stub)
-{
- MOZ_ASSERT(stub->next());
-
- // If stub is the last optimized stub, update lastStubPtrAddr.
- if (stub->next() == this) {
- MOZ_ASSERT(lastStubPtrAddr_ == stub->addressOfNext());
- if (prev)
- lastStubPtrAddr_ = prev->addressOfNext();
- else
- lastStubPtrAddr_ = icEntry()->addressOfFirstStub();
- *lastStubPtrAddr_ = this;
- } else {
- if (prev) {
- MOZ_ASSERT(prev->next() == stub);
- prev->setNext(stub->next());
- } else {
- MOZ_ASSERT(icEntry()->firstStub() == stub);
- icEntry()->setFirstStub(stub->next());
- }
- }
-
- state_.trackUnlinkedStub();
-
- if (zone->needsIncrementalBarrier()) {
- // We are removing edges from ICStub to gcthings. Perform one final trace
- // of the stub for incremental GC, as it must know about those edges.
- stub->trace(zone->barrierTracer());
- }
-
- if (stub->makesGCCalls() && stub->isMonitored()) {
- // This stub can make calls so we can return to it if it's on the stack.
- // We just have to reset its firstMonitorStub_ field to avoid a stale
- // pointer when purgeOptimizedStubs destroys all optimized monitor
- // stubs (unlinked stubs won't be updated).
- ICTypeMonitor_Fallback* monitorFallback =
- toMonitoredFallbackStub()->maybeFallbackMonitorStub();
- MOZ_ASSERT(monitorFallback);
- stub->toMonitoredStub()->resetFirstMonitorStub(monitorFallback);
- }
-
-#ifdef DEBUG
- // Poison stub code to ensure we don't call this stub again. However, if
- // this stub can make calls, a pointer to it may be stored in a stub frame
- // on the stack, so we can't touch the stubCode_ or GC will crash when
- // tracing this pointer.
- if (!stub->makesGCCalls())
- stub->stubCode_ = (uint8_t*)0xbad;
-#endif
-}
-
-void
-ICFallbackStub::unlinkStubsWithKind(JSContext* cx, ICStub::Kind kind)
-{
- for (ICStubIterator iter = beginChain(); !iter.atEnd(); iter++) {
- if (iter->kind() == kind)
- iter.unlink(cx);
- }
-}
-
-void
-ICFallbackStub::discardStubs(JSContext* cx)
-{
- for (ICStubIterator iter = beginChain(); !iter.atEnd(); iter++)
- iter.unlink(cx);
-}
-
-void
-ICTypeMonitor_Fallback::resetMonitorStubChain(Zone* zone)
-{
- if (zone->needsIncrementalBarrier()) {
- // We are removing edges from monitored stubs to gcthings (JitCode).
- // Perform one final trace of all monitor stubs for incremental GC,
- // as it must know about those edges.
- for (ICStub* s = firstMonitorStub_; !s->isTypeMonitor_Fallback(); s = s->next())
- s->trace(zone->barrierTracer());
- }
-
- firstMonitorStub_ = this;
- numOptimizedMonitorStubs_ = 0;
-
- if (hasFallbackStub_) {
- lastMonitorStubPtrAddr_ = nullptr;
-
- // Reset firstMonitorStub_ field of all monitored stubs.
- for (ICStubConstIterator iter = mainFallbackStub_->beginChainConst();
- !iter.atEnd(); iter++)
- {
- if (!iter->isMonitored())
- continue;
- iter->toMonitoredStub()->resetFirstMonitorStub(this);
- }
- } else {
- icEntry_->setFirstStub(this);
- lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
- }
-}
-
-void
-ICUpdatedStub::resetUpdateStubChain(Zone* zone)
-{
- while (!firstUpdateStub_->isTypeUpdate_Fallback()) {
- if (zone->needsIncrementalBarrier()) {
- // We are removing edges from update stubs to gcthings (JitCode).
- // Perform one final trace of all update stubs for incremental GC,
- // as it must know about those edges.
- firstUpdateStub_->trace(zone->barrierTracer());
- }
- firstUpdateStub_ = firstUpdateStub_->next();
- }
-
- numOptimizedStubs_ = 0;
-}
-
-ICMonitoredStub::ICMonitoredStub(Kind kind, JitCode* stubCode, ICStub* firstMonitorStub)
- : ICStub(kind, ICStub::Monitored, stubCode),
- firstMonitorStub_(firstMonitorStub)
-{
- // In order to silence Coverity - null pointer dereference checker
- MOZ_ASSERT(firstMonitorStub_);
- // If the first monitored stub is a ICTypeMonitor_Fallback stub, then
- // double check that _its_ firstMonitorStub is the same as this one.
- MOZ_ASSERT_IF(firstMonitorStub_->isTypeMonitor_Fallback(),
- firstMonitorStub_->toTypeMonitor_Fallback()->firstMonitorStub() ==
- firstMonitorStub_);
-}
-
-bool
-ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx, JSScript* script)
-{
- MOZ_ASSERT(fallbackMonitorStub_ == nullptr);
-
- ICTypeMonitor_Fallback::Compiler compiler(cx, this);
- ICStubSpace* space = script->baselineScript()->fallbackStubSpace();
- ICTypeMonitor_Fallback* stub = compiler.getStub(space);
- if (!stub)
- return false;
- fallbackMonitorStub_ = stub;
- return true;
-}
-
-bool
-ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
- StackTypeSet* types, HandleValue val)
-{
- ICTypeMonitor_Fallback* typeMonitorFallback = getFallbackMonitorStub(cx, frame->script());
- if (!typeMonitorFallback)
- return false;
- return typeMonitorFallback->addMonitorStubForValue(cx, frame, types, val);
-}
-
-bool
-ICUpdatedStub::initUpdatingChain(JSContext* cx, ICStubSpace* space)
-{
- MOZ_ASSERT(firstUpdateStub_ == nullptr);
-
- ICTypeUpdate_Fallback::Compiler compiler(cx);
- ICTypeUpdate_Fallback* stub = compiler.getStub(space);
- if (!stub)
- return false;
-
- firstUpdateStub_ = stub;
- return true;
-}
-
-JitCode*
-ICStubCompiler::getStubCode()
-{
- JitRealm* realm = cx->realm()->jitRealm();
-
- // Check for existing cached stubcode.
- uint32_t stubKey = getKey();
- JitCode* stubCode = realm->getStubCode(stubKey);
- if (stubCode)
- return stubCode;
-
- // Compile new stubcode.
- JitContext jctx(cx, nullptr);
- StackMacroAssembler masm;
-#ifndef JS_USE_LINK_REGISTER
- // The first value contains the return addres,
- // which we pull into ICTailCallReg for tail calls.
- masm.adjustFrame(sizeof(intptr_t));
-#endif
-#ifdef JS_CODEGEN_ARM
- masm.setSecondScratchReg(BaselineSecondScratchReg);
-#endif
-
- if (!generateStubCode(masm))
- return nullptr;
- Linker linker(masm);
- AutoFlushICache afc("getStubCode");
- Rooted newStubCode(cx, linker.newCode(cx, CodeKind::Baseline));
- if (!newStubCode)
- return nullptr;
-
- // Cache newly compiled stubcode.
- if (!realm->putStubCode(cx, stubKey, newStubCode))
- return nullptr;
-
- // After generating code, run postGenerateStubCode(). We must not fail
- // after this point.
- postGenerateStubCode(masm, newStubCode);
-
- MOZ_ASSERT(entersStubFrame_ == ICStub::NonCacheIRStubMakesGCCalls(kind));
- MOZ_ASSERT(!inStubFrame_);
-
-#ifdef JS_ION_PERF
- writePerfSpewerJitCodeProfile(newStubCode, "BaselineIC");
-#endif
-
- return newStubCode;
-}
-
-bool
-ICStubCompiler::tailCallVM(const VMFunction& fun, MacroAssembler& masm)
-{
- TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
- MOZ_ASSERT(fun.expectTailCall == TailCall);
- uint32_t argSize = fun.explicitStackSlots() * sizeof(void*);
- if (engine_ == Engine::Baseline) {
- EmitBaselineTailCallVM(code, masm, argSize);
- } else {
- uint32_t stackSize = argSize + fun.extraValuesToPop * sizeof(Value);
- EmitIonTailCallVM(code, masm, stackSize);
- }
- return true;
-}
-
-bool
-ICStubCompiler::callVM(const VMFunction& fun, MacroAssembler& masm)
-{
- MOZ_ASSERT(inStubFrame_);
-
- TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
- MOZ_ASSERT(fun.expectTailCall == NonTailCall);
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
- EmitBaselineCallVM(code, masm);
- return true;
-}
-
-void
-ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch)
-{
- MOZ_ASSERT(engine_ == Engine::Baseline);
- EmitBaselineEnterStubFrame(masm, scratch);
-#ifdef DEBUG
- framePushedAtEnterStubFrame_ = masm.framePushed();
-#endif
-
- MOZ_ASSERT(!inStubFrame_);
- inStubFrame_ = true;
-
-#ifdef DEBUG
- entersStubFrame_ = true;
-#endif
-}
-
-void
-ICStubCompiler::assumeStubFrame()
-{
- MOZ_ASSERT(!inStubFrame_);
- inStubFrame_ = true;
-
-#ifdef DEBUG
- entersStubFrame_ = true;
-
- // |framePushed| isn't tracked precisely in ICStubs, so simply assume it to
- // be STUB_FRAME_SIZE so that assertions don't fail in leaveStubFrame.
- framePushedAtEnterStubFrame_ = STUB_FRAME_SIZE;
-#endif
-}
-
-void
-ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon)
-{
- MOZ_ASSERT(entersStubFrame_ && inStubFrame_);
- inStubFrame_ = false;
-
- MOZ_ASSERT(engine_ == Engine::Baseline);
-#ifdef DEBUG
- masm.setFramePushed(framePushedAtEnterStubFrame_);
- if (calledIntoIon)
- masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
-#endif
- EmitBaselineLeaveStubFrame(masm, calledIntoIon);
-}
-
-void
-ICStubCompiler::pushStubPayload(MacroAssembler& masm, Register scratch)
-{
- if (engine_ == Engine::IonSharedIC) {
- masm.push(Imm32(0));
- return;
- }
-
- if (inStubFrame_) {
- masm.loadPtr(Address(BaselineFrameReg, 0), scratch);
- masm.pushBaselineFramePtr(scratch, scratch);
- } else {
- masm.pushBaselineFramePtr(BaselineFrameReg, scratch);
- }
-}
-
-void
-ICStubCompiler::PushStubPayload(MacroAssembler& masm, Register scratch)
-{
- pushStubPayload(masm, scratch);
- masm.adjustFrame(sizeof(intptr_t));
-}
-
-SharedStubInfo::SharedStubInfo(JSContext* cx, void* payload, ICEntry* icEntry)
- : maybeFrame_(nullptr),
- outerScript_(cx),
- innerScript_(cx),
- icEntry_(icEntry)
-{
- if (payload) {
- maybeFrame_ = (BaselineFrame*) payload;
- outerScript_ = maybeFrame_->script();
- innerScript_ = maybeFrame_->script();
- } else {
- IonICEntry* entry = (IonICEntry*) icEntry;
- innerScript_ = entry->script();
- // outerScript_ is initialized lazily.
- }
-}
-
-HandleScript
-SharedStubInfo::outerScript(JSContext* cx)
-{
- if (!outerScript_) {
- js::jit::JitActivationIterator actIter(cx);
- JSJitFrameIter it(actIter->asJit());
- MOZ_ASSERT(it.isExitFrame());
- ++it;
- MOZ_ASSERT(it.isIonJS());
- outerScript_ = it.script();
- MOZ_ASSERT(!it.ionScript()->invalidated());
- }
- return outerScript_;
-}
-
-//
-void
-LoadTypedThingData(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result)
-{
- switch (layout) {
- case Layout_TypedArray:
- masm.loadPtr(Address(obj, TypedArrayObject::dataOffset()), result);
- break;
- case Layout_OutlineTypedObject:
- masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), result);
- break;
- case Layout_InlineTypedObject:
- masm.computeEffectiveAddress(Address(obj, InlineTypedObject::offsetOfDataStart()), result);
- break;
- default:
- MOZ_CRASH();
- }
-}
-
-void
-BaselineScript::noteAccessedGetter(uint32_t pcOffset)
-{
- ICEntry& entry = icEntryFromPCOffset(pcOffset);
- ICFallbackStub* stub = entry.fallbackStub();
-
- if (stub->isGetProp_Fallback())
- stub->toGetProp_Fallback()->noteAccessedGetter();
-}
-
-// TypeMonitor_Fallback
-//
-
-bool
-ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
- StackTypeSet* types, HandleValue val)
-{
- MOZ_ASSERT(types);
-
- // Don't attach too many SingleObject/ObjectGroup stubs. If the value is a
- // primitive or if we will attach an any-object stub, we can handle this
- // with a single PrimitiveSet or AnyValue stub so we always optimize.
- if (numOptimizedMonitorStubs_ >= MAX_OPTIMIZED_STUBS &&
- val.isObject() &&
- !types->unknownObject())
- {
- return true;
- }
-
- bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr;
- MOZ_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0);
-
- if (types->unknown()) {
- // The TypeSet got marked as unknown so attach a stub that always
- // succeeds.
-
- // Check for existing TypeMonitor_AnyValue stubs.
- for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
- if (iter->isTypeMonitor_AnyValue())
- return true;
- }
-
- // Discard existing stubs.
- resetMonitorStubChain(cx->zone());
- wasDetachedMonitorChain = (lastMonitorStubPtrAddr_ == nullptr);
-
- ICTypeMonitor_AnyValue::Compiler compiler(cx);
- ICStub* stub = compiler.getStub(compiler.getStubSpace(frame->script()));
- if (!stub) {
- ReportOutOfMemory(cx);
- return false;
- }
-
- JitSpew(JitSpew_BaselineIC, " Added TypeMonitor stub %p for any value", stub);
- addOptimizedMonitorStub(stub);
-
- } else if (val.isPrimitive() || types->unknownObject()) {
- if (val.isMagic(JS_UNINITIALIZED_LEXICAL))
- return true;
- MOZ_ASSERT(!val.isMagic());
- JSValueType type = val.isDouble() ? JSVAL_TYPE_DOUBLE : val.extractNonDoubleType();
-
- // Check for existing TypeMonitor stub.
- ICTypeMonitor_PrimitiveSet* existingStub = nullptr;
- for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
- if (iter->isTypeMonitor_PrimitiveSet()) {
- existingStub = iter->toTypeMonitor_PrimitiveSet();
- if (existingStub->containsType(type))
- return true;
- }
- }
-
- if (val.isObject()) {
- // Check for existing SingleObject/ObjectGroup stubs and discard
- // stubs if we find one. Ideally we would discard just these stubs,
- // but unlinking individual type monitor stubs is somewhat
- // complicated.
- MOZ_ASSERT(types->unknownObject());
- bool hasObjectStubs = false;
- for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
- if (iter->isTypeMonitor_SingleObject() || iter->isTypeMonitor_ObjectGroup()) {
- hasObjectStubs = true;
- break;
- }
- }
- if (hasObjectStubs) {
- resetMonitorStubChain(cx->zone());
- wasDetachedMonitorChain = (lastMonitorStubPtrAddr_ == nullptr);
- existingStub = nullptr;
- }
- }
-
- ICTypeMonitor_PrimitiveSet::Compiler compiler(cx, existingStub, type);
- ICStub* stub = existingStub
- ? compiler.updateStub()
- : compiler.getStub(compiler.getStubSpace(frame->script()));
- if (!stub) {
- ReportOutOfMemory(cx);
- return false;
- }
-
- JitSpew(JitSpew_BaselineIC, " %s TypeMonitor stub %p for primitive type %d",
- existingStub ? "Modified existing" : "Created new", stub, type);
-
- if (!existingStub) {
- MOZ_ASSERT(!hasStub(TypeMonitor_PrimitiveSet));
- addOptimizedMonitorStub(stub);
- }
-
- } else if (val.toObject().isSingleton()) {
- RootedObject obj(cx, &val.toObject());
-
- // Check for existing TypeMonitor stub.
- for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
- if (iter->isTypeMonitor_SingleObject() &&
- iter->toTypeMonitor_SingleObject()->object() == obj)
- {
- return true;
- }
- }
-
- ICTypeMonitor_SingleObject::Compiler compiler(cx, obj);
- ICStub* stub = compiler.getStub(compiler.getStubSpace(frame->script()));
- if (!stub) {
- ReportOutOfMemory(cx);
- return false;
- }
-
- JitSpew(JitSpew_BaselineIC, " Added TypeMonitor stub %p for singleton %p",
- stub, obj.get());
-
- addOptimizedMonitorStub(stub);
-
- } else {
- RootedObjectGroup group(cx, val.toObject().group());
-
- // Check for existing TypeMonitor stub.
- for (ICStubConstIterator iter(firstMonitorStub()); !iter.atEnd(); iter++) {
- if (iter->isTypeMonitor_ObjectGroup() &&
- iter->toTypeMonitor_ObjectGroup()->group() == group)
- {
- return true;
- }
- }
-
- ICTypeMonitor_ObjectGroup::Compiler compiler(cx, group);
- ICStub* stub = compiler.getStub(compiler.getStubSpace(frame->script()));
- if (!stub) {
- ReportOutOfMemory(cx);
- return false;
- }
-
- JitSpew(JitSpew_BaselineIC, " Added TypeMonitor stub %p for ObjectGroup %p",
- stub, group.get());
-
- addOptimizedMonitorStub(stub);
- }
-
- bool firstMonitorStubAdded = wasDetachedMonitorChain && (numOptimizedMonitorStubs_ > 0);
-
- if (firstMonitorStubAdded) {
- // Was an empty monitor chain before, but a new stub was added. This is the
- // only time that any main stubs' firstMonitorStub fields need to be updated to
- // refer to the newly added monitor stub.
- ICStub* firstStub = mainFallbackStub_->icEntry()->firstStub();
- for (ICStubConstIterator iter(firstStub); !iter.atEnd(); iter++) {
- // Non-monitored stubs are used if the result has always the same type,
- // e.g. a StringLength stub will always return int32.
- if (!iter->isMonitored())
- continue;
-
- // Since we just added the first optimized monitoring stub, any
- // existing main stub's |firstMonitorStub| MUST be pointing to the fallback
- // monitor stub (i.e. this stub).
- MOZ_ASSERT(iter->toMonitoredStub()->firstMonitorStub() == this);
- iter->toMonitoredStub()->updateFirstMonitorStub(firstMonitorStub_);
- }
- }
-
- return true;
-}
-
-static bool
-DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallback* stub,
- HandleValue value, MutableHandleValue res)
-{
- JSScript* script = frame->script();
- jsbytecode* pc = stub->icEntry()->pc(script);
- TypeFallbackICSpew(cx, stub, "TypeMonitor");
-
- // Copy input value to res.
- res.set(value);
-
- if (MOZ_UNLIKELY(value.isMagic())) {
- // It's possible that we arrived here from bailing out of Ion, and that
- // Ion proved that the value is dead and optimized out. In such cases,
- // do nothing. However, it's also possible that we have an uninitialized
- // this, in which case we should not look for other magic values.
-
- if (value.whyMagic() == JS_OPTIMIZED_OUT) {
- MOZ_ASSERT(!stub->monitorsThis());
- return true;
- }
-
- // In derived class constructors (including nested arrows/eval), the
- // |this| argument or GETALIASEDVAR can return the magic TDZ value.
- MOZ_ASSERT(value.isMagic(JS_UNINITIALIZED_LEXICAL));
- MOZ_ASSERT(frame->isFunctionFrame() || frame->isEvalFrame());
- MOZ_ASSERT(stub->monitorsThis() ||
- *GetNextPc(pc) == JSOP_CHECKTHIS ||
- *GetNextPc(pc) == JSOP_CHECKTHISREINIT ||
- *GetNextPc(pc) == JSOP_CHECKRETURN);
- if (stub->monitorsThis())
- TypeScript::SetThis(cx, script, TypeSet::UnknownType());
- else
- TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType());
- return true;
- }
-
- StackTypeSet* types;
- uint32_t argument;
- if (stub->monitorsArgument(&argument)) {
- MOZ_ASSERT(pc == script->code());
- types = TypeScript::ArgTypes(script, argument);
- TypeScript::SetArgument(cx, script, argument, value);
- } else if (stub->monitorsThis()) {
- MOZ_ASSERT(pc == script->code());
- types = TypeScript::ThisTypes(script);
- TypeScript::SetThis(cx, script, value);
- } else {
- types = TypeScript::BytecodeTypes(script, pc);
- TypeScript::Monitor(cx, script, pc, types, value);
- }
-
- if (MOZ_UNLIKELY(stub->invalid()))
- return true;
-
- return stub->addMonitorStubForValue(cx, frame, types, value);
-}
-
-typedef bool (*DoTypeMonitorFallbackFn)(JSContext*, BaselineFrame*, ICTypeMonitor_Fallback*,
- HandleValue, MutableHandleValue);
-static const VMFunction DoTypeMonitorFallbackInfo =
- FunctionInfo(DoTypeMonitorFallback, "DoTypeMonitorFallback",
- TailCall);
-
-bool
-ICTypeMonitor_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
-{
- MOZ_ASSERT(R0 == JSReturnOperand);
-
- // Restore the tail call register.
- EmitRestoreTailCallReg(masm);
-
- masm.pushValue(R0);
- masm.push(ICStubReg);
- masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
-
- return tailCallVM(DoTypeMonitorFallbackInfo, masm);
-}
-
-bool
-ICTypeMonitor_PrimitiveSet::Compiler::generateStubCode(MacroAssembler& masm)
-{
- Label success;
- if ((flags_ & TypeToFlag(JSVAL_TYPE_INT32)) && !(flags_ & TypeToFlag(JSVAL_TYPE_DOUBLE)))
- masm.branchTestInt32(Assembler::Equal, R0, &success);
-
- if (flags_ & TypeToFlag(JSVAL_TYPE_DOUBLE))
- masm.branchTestNumber(Assembler::Equal, R0, &success);
-
- if (flags_ & TypeToFlag(JSVAL_TYPE_UNDEFINED))
- masm.branchTestUndefined(Assembler::Equal, R0, &success);
-
- if (flags_ & TypeToFlag(JSVAL_TYPE_BOOLEAN))
- masm.branchTestBoolean(Assembler::Equal, R0, &success);
-
- if (flags_ & TypeToFlag(JSVAL_TYPE_STRING))
- masm.branchTestString(Assembler::Equal, R0, &success);
-
- if (flags_ & TypeToFlag(JSVAL_TYPE_SYMBOL))
- masm.branchTestSymbol(Assembler::Equal, R0, &success);
-
- if (flags_ & TypeToFlag(JSVAL_TYPE_OBJECT))
- masm.branchTestObject(Assembler::Equal, R0, &success);
-
- if (flags_ & TypeToFlag(JSVAL_TYPE_NULL))
- masm.branchTestNull(Assembler::Equal, R0, &success);
-
- EmitStubGuardFailure(masm);
-
- masm.bind(&success);
- EmitReturnFromIC(masm);
- return true;
-}
-
-static void
-MaybeWorkAroundAmdBug(MacroAssembler& masm)
-{
- // Attempt to work around an AMD bug (see bug 1034706 and bug 1281759), by
- // inserting 32-bytes of NOPs.
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
- if (CPUInfo::NeedAmdBugWorkaround()) {
- masm.nop(9);
- masm.nop(9);
- masm.nop(9);
- masm.nop(5);
- }
-#endif
-}
-
-bool
-ICTypeMonitor_SingleObject::Compiler::generateStubCode(MacroAssembler& masm)
-{
- Label failure;
- masm.branchTestObject(Assembler::NotEqual, R0, &failure);
- MaybeWorkAroundAmdBug(masm);
-
- // Guard on the object's identity.
- Register obj = masm.extractObject(R0, ExtractTemp0);
- Address expectedObject(ICStubReg, ICTypeMonitor_SingleObject::offsetOfObject());
- masm.branchPtr(Assembler::NotEqual, expectedObject, obj, &failure);
- MaybeWorkAroundAmdBug(masm);
-
- EmitReturnFromIC(masm);
- MaybeWorkAroundAmdBug(masm);
-
- masm.bind(&failure);
- EmitStubGuardFailure(masm);
- return true;
-}
-
-bool
-ICTypeMonitor_ObjectGroup::Compiler::generateStubCode(MacroAssembler& masm)
-{
- Label failure;
- masm.branchTestObject(Assembler::NotEqual, R0, &failure);
- MaybeWorkAroundAmdBug(masm);
-
- // Guard on the object's ObjectGroup. No Spectre mitigations are needed
- // here: we're just recording type information for Ion compilation and
- // it's safe to speculatively return.
- Register obj = masm.extractObject(R0, ExtractTemp0);
- Address expectedGroup(ICStubReg, ICTypeMonitor_ObjectGroup::offsetOfGroup());
- masm.branchTestObjGroupNoSpectreMitigations(Assembler::NotEqual, obj, expectedGroup,
- R1.scratchReg(), &failure);
- MaybeWorkAroundAmdBug(masm);
-
- EmitReturnFromIC(masm);
- MaybeWorkAroundAmdBug(masm);
-
- masm.bind(&failure);
- EmitStubGuardFailure(masm);
- return true;
-}
-
-bool
-ICTypeMonitor_AnyValue::Compiler::generateStubCode(MacroAssembler& masm)
-{
- EmitReturnFromIC(masm);
- return true;
-}
-
-bool
-ICUpdatedStub::addUpdateStubForValue(JSContext* cx, HandleScript outerScript, HandleObject obj,
- HandleObjectGroup group, HandleId id, HandleValue val)
-{
- EnsureTrackPropertyTypes(cx, obj, id);
-
- // Make sure that undefined values are explicitly included in the property
- // types for an object if generating a stub to write an undefined value.
- if (val.isUndefined() && CanHaveEmptyPropertyTypesForOwnProperty(obj)) {
- MOZ_ASSERT(obj->group() == group);
- AddTypePropertyId(cx, obj, id, val);
- }
-
- bool unknown = false, unknownObject = false;
- AutoSweepObjectGroup sweep(group);
- if (group->unknownProperties(sweep)) {
- unknown = unknownObject = true;
- } else {
- if (HeapTypeSet* types = group->maybeGetProperty(sweep, id)) {
- unknown = types->unknown();
- unknownObject = types->unknownObject();
- } else {
- // We don't record null/undefined types for certain TypedObject
- // properties. In these cases |types| is allowed to be nullptr
- // without implying unknown types. See DoTypeUpdateFallback.
- MOZ_ASSERT(obj->is());
- MOZ_ASSERT(val.isNullOrUndefined());
- }
- }
- MOZ_ASSERT_IF(unknown, unknownObject);
-
- // Don't attach too many SingleObject/ObjectGroup stubs unless we can
- // replace them with a single PrimitiveSet or AnyValue stub.
- if (numOptimizedStubs_ >= MAX_OPTIMIZED_STUBS &&
- val.isObject() &&
- !unknownObject)
- {
- return true;
- }
-
- if (unknown) {
- // Attach a stub that always succeeds. We should not have a
- // TypeUpdate_AnyValue stub yet.
- MOZ_ASSERT(!hasTypeUpdateStub(TypeUpdate_AnyValue));
-
- // Discard existing stubs.
- resetUpdateStubChain(cx->zone());
-
- ICTypeUpdate_AnyValue::Compiler compiler(cx);
- ICStub* stub = compiler.getStub(compiler.getStubSpace(outerScript));
- if (!stub)
- return false;
-
- JitSpew(JitSpew_BaselineIC, " Added TypeUpdate stub %p for any value", stub);
- addOptimizedUpdateStub(stub);
-
- } else if (val.isPrimitive() || unknownObject) {
- JSValueType type = val.isDouble() ? JSVAL_TYPE_DOUBLE : val.extractNonDoubleType();
-
- // Check for existing TypeUpdate stub.
- ICTypeUpdate_PrimitiveSet* existingStub = nullptr;
- for (ICStubConstIterator iter(firstUpdateStub_); !iter.atEnd(); iter++) {
- if (iter->isTypeUpdate_PrimitiveSet()) {
- existingStub = iter->toTypeUpdate_PrimitiveSet();
- MOZ_ASSERT(!existingStub->containsType(type));
- }
- }
-
- if (val.isObject()) {
- // Discard existing ObjectGroup/SingleObject stubs.
- resetUpdateStubChain(cx->zone());
- if (existingStub)
- addOptimizedUpdateStub(existingStub);
- }
-
- ICTypeUpdate_PrimitiveSet::Compiler compiler(cx, existingStub, type);
- ICStub* stub = existingStub ? compiler.updateStub()
- : compiler.getStub(compiler.getStubSpace(outerScript));
- if (!stub)
- return false;
- if (!existingStub) {
- MOZ_ASSERT(!hasTypeUpdateStub(TypeUpdate_PrimitiveSet));
- addOptimizedUpdateStub(stub);
- }
-
- JitSpew(JitSpew_BaselineIC, " %s TypeUpdate stub %p for primitive type %d",
- existingStub ? "Modified existing" : "Created new", stub, type);
-
- } else if (val.toObject().isSingleton()) {
- RootedObject obj(cx, &val.toObject());
-
-#ifdef DEBUG
- // We should not have a stub for this object.
- for (ICStubConstIterator iter(firstUpdateStub_); !iter.atEnd(); iter++) {
- MOZ_ASSERT_IF(iter->isTypeUpdate_SingleObject(),
- iter->toTypeUpdate_SingleObject()->object() != obj);
- }
-#endif
-
- ICTypeUpdate_SingleObject::Compiler compiler(cx, obj);
- ICStub* stub = compiler.getStub(compiler.getStubSpace(outerScript));
- if (!stub)
- return false;
-
- JitSpew(JitSpew_BaselineIC, " Added TypeUpdate stub %p for singleton %p", stub, obj.get());
-
- addOptimizedUpdateStub(stub);
-
- } else {
- RootedObjectGroup group(cx, val.toObject().group());
-
-#ifdef DEBUG
- // We should not have a stub for this group.
- for (ICStubConstIterator iter(firstUpdateStub_); !iter.atEnd(); iter++) {
- MOZ_ASSERT_IF(iter->isTypeUpdate_ObjectGroup(),
- iter->toTypeUpdate_ObjectGroup()->group() != group);
- }
-#endif
-
- ICTypeUpdate_ObjectGroup::Compiler compiler(cx, group);
- ICStub* stub = compiler.getStub(compiler.getStubSpace(outerScript));
- if (!stub)
- return false;
-
- JitSpew(JitSpew_BaselineIC, " Added TypeUpdate stub %p for ObjectGroup %p",
- stub, group.get());
-
- addOptimizedUpdateStub(stub);
- }
-
- return true;
-}
-
-} // namespace jit
-} // namespace js
diff --git a/js/src/jit/SharedIC.h b/js/src/jit/SharedIC.h
deleted file mode 100644
index 17e06668691b..000000000000
--- a/js/src/jit/SharedIC.h
+++ /dev/null
@@ -1,1786 +0,0 @@
-/* -*- 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_SharedIC_h
-#define jit_SharedIC_h
-
-#include "gc/GC.h"
-#include "jit/BaselineICList.h"
-#include "jit/BaselineJIT.h"
-#include "jit/ICState.h"
-#include "jit/MacroAssembler.h"
-#include "jit/SharedICList.h"
-#include "jit/SharedICRegisters.h"
-#include "vm/JSContext.h"
-#include "vm/Realm.h"
-#include "vm/ReceiverGuard.h"
-#include "vm/TypedArrayObject.h"
-
-namespace js {
-namespace jit {
-
-// [SMDOC] JIT Inline Caches (ICs)
-//
-// Baseline Inline Caches are polymorphic caches that aggressively
-// share their stub code.
-//
-// Every polymorphic site contains a linked list of stubs which are
-// specific to that site. These stubs are composed of a |StubData|
-// structure that stores parametrization information (e.g.
-// the shape pointer for a shape-check-and-property-get stub), any
-// dynamic information (e.g. warm-up counters), a pointer to the stub code,
-// and a pointer to the next stub state in the linked list.
-//
-// Every BaselineScript keeps an table of |CacheDescriptor| data
-// structures, which store the following:
-// A pointer to the first StubData in the cache.
-// The bytecode PC of the relevant IC.
-// The machine-code PC where the call to the stubcode returns.
-//
-// A diagram:
-//
-// Control flow Pointers
-// =======# ----. .---->
-// # | |
-// #======> \-----/
-//
-//
-// .---------------------------------------.
-// | .-------------------------. |
-// | | .----. | |
-// Baseline | | | | | |
-// JIT Code 0 ^ 1 ^ 2 ^ | | |
-// +--------------+ .-->+-----+ +-----+ +-----+ | | |
-// | | #=|==>| |==>| |==>| FB | | | |
-// | | # | +-----+ +-----+ +-----+ | | |
-// | | # | # # # | | |
-// |==============|==# | # # # | | |
-// |=== IC =======| | # # # | | |
-// .->|==============|<===|======#=========#=========# | | |
-// | | | | | | |
-// | | | | | | |
-// | | | | | | |
-// | | | | v | |
-// | | | | +---------+ | |
-// | | | | | Fallback| | |
-// | | | | | Stub | | |
-// | | | | | Code | | |
-// | | | | +---------+ | |
-// | +--------------+ | | |
-// | |_______ | +---------+ | |
-// | | | | Stub |<---/ |
-// | IC | \--. | Code | |
-// | Descriptor | | +---------+ |
-// | Table v | |
-// | +-----------------+ | +---------+ |
-// \--| Ins | PC | Stub |----/ | Stub |<-------/
-// +-----------------+ | Code |
-// | ... | +---------+
-// +-----------------+
-// Shared
-// Stub Code
-//
-//
-// Type ICs
-// ========
-//
-// Type ICs are otherwise regular ICs that are actually nested within
-// other IC chains. They serve to optimize locations in the code where the
-// baseline compiler would have otherwise had to perform a type Monitor operation
-// (e.g. the result of GetProp, GetElem, etc.), or locations where the baseline
-// compiler would have had to modify a heap typeset using the type of an input
-// value (e.g. SetProp, SetElem, etc.)
-//
-// There are two kinds of Type ICs: Monitor and Update.
-//
-// Note that type stub bodies are no-ops. The stubs only exist for their
-// guards, and their existence simply signifies that the typeset (implicit)
-// that is being checked already contains that type.
-//
-// TypeMonitor ICs
-// ---------------
-// Monitor ICs are shared between stubs in the general IC, and monitor the resulting
-// types of getter operations (call returns, getprop outputs, etc.)
-//
-// +-----------+ +-----------+ +-----------+ +-----------+
-// ---->| Stub 1 |---->| Stub 2 |---->| Stub 3 |---->| FB Stub |
-// +-----------+ +-----------+ +-----------+ +-----------+
-// | | | |
-// |------------------/-----------------/ |
-// v |
-// +-----------+ +-----------+ +-----------+ |
-// | Type 1 |---->| Type 2 |---->| Type FB | |
-// +-----------+ +-----------+ +-----------+ |
-// | | | |
-// <----------/-----------------/------------------/------------------/
-// r e t u r n p a t h
-//
-// After an optimized IC stub successfully executes, it passes control to the type stub
-// chain to check the resulting type. If no type stub succeeds, and the monitor fallback
-// stub is reached, the monitor fallback stub performs a manual monitor, and also adds the
-// appropriate type stub to the chain.
-//
-// The IC's main fallback, in addition to generating new mainline stubs, also generates
-// type stubs as reflected by its returned value.
-//
-// NOTE: The type IC chain returns directly to the mainline code, not back to the
-// stub it was entered from. Thus, entering a type IC is a matter of a |jump|, not
-// a |call|. This allows us to safely call a VM Monitor function from within the monitor IC's
-// fallback chain, since the return address (needed for stack inspection) is preserved.
-//
-//
-// TypeUpdate ICs
-// --------------
-// Update ICs update heap typesets and monitor the input types of setter operations
-// (setelem, setprop inputs, etc.). Unlike monitor ICs, they are not shared
-// between stubs on an IC, but instead are kept track of on a per-stub basis.
-//
-// This is because the main stubs for the operation will each identify a potentially
-// different ObjectGroup to update. New input types must be tracked on a group-to-
-// group basis.
-//
-// Type-update ICs cannot be called in tail position (they must return to the
-// the stub that called them so that the stub may continue to perform its original
-// purpose). This means that any VMCall to perform a manual type update from C++ must be
-// done from within the main IC stub. This necessitates that the stub enter a
-// "BaselineStub" frame before making the call.
-//
-// If the type-update IC chain could itself make the VMCall, then the BaselineStub frame
-// must be entered before calling the type-update chain, and exited afterward. This
-// is very expensive for a common case where we expect the type-update fallback to not
-// be called. To avoid the cost of entering and exiting a BaselineStub frame when
-// using the type-update IC chain, we design the chain to not perform any VM-calls
-// in its fallback.
-//
-// Instead, the type-update IC chain is responsible for returning 1 or 0, depending
-// on if a type is represented in the chain or not. The fallback stub simply returns
-// 0, and all other optimized stubs return 1.
-// If the chain returns 1, then the IC stub goes ahead and performs its operation.
-// If the chain returns 0, then the IC stub performs a call to the fallback function
-// inline (doing the requisite BaselineStub frame enter/exit).
-// This allows us to avoid the expensive subfram enter/exit in the common case.
-//
-// r e t u r n p a t h
-// <--------------.-----------------.-----------------.-----------------.
-// | | | |
-// +-----------+ +-----------+ +-----------+ +-----------+
-// ---->| Stub 1 |---->| Stub 2 |---->| Stub 3 |---->| FB Stub |
-// +-----------+ +-----------+ +-----------+ +-----------+
-// | ^ | ^ | ^
-// | | | | | |
-// | | | | | |----------------.
-// | | | | v |1 |0
-// | | | | +-----------+ +-----------+
-// | | | | | Type 3.1 |--->| FB 3 |
-// | | | | +-----------+ +-----------+
-// | | | |
-// | | | \-------------.-----------------.
-// | | | | | |
-// | | v |1 |1 |0
-// | | +-----------+ +-----------+ +-----------+
-// | | | Type 2.1 |---->| Type 2.2 |---->| FB 2 |
-// | | +-----------+ +-----------+ +-----------+
-// | |
-// | \-------------.-----------------.
-// | | | |
-// v |1 |1 |0
-// +-----------+ +-----------+ +-----------+
-// | Type 1.1 |---->| Type 1.2 |---->| FB 1 |
-// +-----------+ +-----------+ +-----------+
-//
-
-class ICStub;
-class ICFallbackStub;
-
-#define FORWARD_DECLARE_STUBS(kindName) class IC##kindName;
- IC_BASELINE_STUB_KIND_LIST(FORWARD_DECLARE_STUBS)
- IC_SHARED_STUB_KIND_LIST(FORWARD_DECLARE_STUBS)
-#undef FORWARD_DECLARE_STUBS
-
-#ifdef JS_JITSPEW
-void FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...)
- MOZ_FORMAT_PRINTF(3, 4);
-void TypeFallbackICSpew(JSContext* cx, ICTypeMonitor_Fallback* stub, const char* fmt, ...)
- MOZ_FORMAT_PRINTF(3, 4);
-#else
-#define FallbackICSpew(...)
-#define TypeFallbackICSpew(...)
-#endif
-
-//
-// An entry in the JIT IC descriptor table.
-//
-class ICEntry
-{
- private:
- // A pointer to the shared IC stub for this instruction.
- ICStub* firstStub_;
-
- // Offset from the start of the JIT code where the IC
- // load and call instructions are.
- uint32_t returnOffset_;
-
- // The PC of this IC's bytecode op within the JSScript.
- uint32_t pcOffset_ : 28;
-
- public:
- enum Kind {
- // A for-op IC entry.
- Kind_Op = 0,
-
- // A non-op IC entry.
- Kind_NonOp,
-
- // A fake IC entry for returning from a callVM for an op.
- Kind_CallVM,
-
- // A fake IC entry for returning from a callVM not for an op (e.g., in
- // the prologue).
- Kind_NonOpCallVM,
-
- // A fake IC entry for returning from a callVM to after the
- // warmup counter.
- Kind_WarmupCounter,
-
- // A fake IC entry for returning from a callVM to the interrupt
- // handler via the over-recursion check on function entry.
- Kind_StackCheck,
-
- // As above, but for the early check. See emitStackCheck.
- Kind_EarlyStackCheck,
-
- // A fake IC entry for returning from DebugTrapHandler.
- Kind_DebugTrap,
-
- // A fake IC entry for returning from a callVM to
- // Debug{Prologue,AfterYield,Epilogue}.
- Kind_DebugPrologue,
- Kind_DebugAfterYield,
- Kind_DebugEpilogue,
-
- Kind_Invalid
- };
-
- private:
- // What this IC is for.
- Kind kind_ : 4;
-
- // Set the kind and asserts that it's sane.
- void setKind(Kind kind) {
- MOZ_ASSERT(kind < Kind_Invalid);
- kind_ = kind;
- MOZ_ASSERT(this->kind() == kind);
- }
-
- public:
- ICEntry(uint32_t pcOffset, Kind kind)
- : firstStub_(nullptr), returnOffset_(), pcOffset_(pcOffset)
- {
- // The offset must fit in at least 28 bits, since we shave off 4 for
- // the Kind enum.
- MOZ_ASSERT(pcOffset_ == pcOffset);
- JS_STATIC_ASSERT(BaselineScript::MAX_JSSCRIPT_LENGTH <= (1u << 28) - 1);
- MOZ_ASSERT(pcOffset <= BaselineScript::MAX_JSSCRIPT_LENGTH);
- setKind(kind);
- }
-
- CodeOffset returnOffset() const {
- return CodeOffset(returnOffset_);
- }
-
- void setReturnOffset(CodeOffset offset) {
- MOZ_ASSERT(offset.offset() <= (size_t) UINT32_MAX);
- returnOffset_ = (uint32_t) offset.offset();
- }
-
- uint32_t pcOffset() const {
- return pcOffset_;
- }
-
- jsbytecode* pc(JSScript* script) const {
- return script->offsetToPC(pcOffset_);
- }
-
- Kind kind() const {
- // MSVC compiles enums as signed.
- return Kind(kind_ & 0xf);
- }
- bool isForOp() const {
- return kind() == Kind_Op;
- }
-
- void setFakeKind(Kind kind) {
- MOZ_ASSERT(kind != Kind_Op && kind != Kind_NonOp);
- setKind(kind);
- }
-
- bool hasStub() const {
- return firstStub_ != nullptr;
- }
- ICStub* firstStub() const {
- MOZ_ASSERT(hasStub());
- return firstStub_;
- }
-
- ICFallbackStub* fallbackStub() const;
-
- void setFirstStub(ICStub* stub) {
- firstStub_ = stub;
- }
-
- static inline size_t offsetOfFirstStub() {
- return offsetof(ICEntry, firstStub_);
- }
-
- inline ICStub** addressOfFirstStub() {
- return &firstStub_;
- }
-
- protected:
- void traceEntry(JSTracer* trc);
-};
-
-class BaselineICEntry : public ICEntry
-{
- public:
- BaselineICEntry(uint32_t pcOffset, Kind kind)
- : ICEntry(pcOffset, kind)
- { }
-
- void trace(JSTracer* trc);
-};
-
-class IonICEntry : public ICEntry
-{
- JSScript* script_;
-
- public:
- IonICEntry(uint32_t pcOffset, Kind kind, JSScript* script)
- : ICEntry(pcOffset, kind),
- script_(script)
- { }
-
- JSScript* script() {
- return script_;
- }
-
- void trace(JSTracer* trc);
-};
-
-class ICMonitoredStub;
-class ICMonitoredFallbackStub;
-class ICUpdatedStub;
-
-// Constant iterator that traverses arbitrary chains of ICStubs.
-// No requirements are made of the ICStub used to construct this
-// iterator, aside from that the stub be part of a nullptr-terminated
-// chain.
-// The iterator is considered to be at its end once it has been
-// incremented _past_ the last stub. Thus, if 'atEnd()' returns
-// true, the '*' and '->' operations are not valid.
-class ICStubConstIterator
-{
- friend class ICStub;
- friend class ICFallbackStub;
-
- private:
- ICStub* currentStub_;
-
- public:
- explicit ICStubConstIterator(ICStub* currentStub) : currentStub_(currentStub) {}
-
- static ICStubConstIterator StartingAt(ICStub* stub) {
- return ICStubConstIterator(stub);
- }
- static ICStubConstIterator End(ICStub* stub) {
- return ICStubConstIterator(nullptr);
- }
-
- bool operator ==(const ICStubConstIterator& other) const {
- return currentStub_ == other.currentStub_;
- }
- bool operator !=(const ICStubConstIterator& other) const {
- return !(*this == other);
- }
-
- ICStubConstIterator& operator++();
-
- ICStubConstIterator operator++(int) {
- ICStubConstIterator oldThis(*this);
- ++(*this);
- return oldThis;
- }
-
- ICStub* operator*() const {
- MOZ_ASSERT(currentStub_);
- return currentStub_;
- }
-
- ICStub* operator ->() const {
- MOZ_ASSERT(currentStub_);
- return currentStub_;
- }
-
- bool atEnd() const {
- return currentStub_ == nullptr;
- }
-};
-
-// Iterator that traverses "regular" IC chains that start at an ICEntry
-// and are terminated with an ICFallbackStub.
-//
-// The iterator is considered to be at its end once it is _at_ the
-// fallback stub. Thus, unlike the ICStubConstIterator, operators
-// '*' and '->' are valid even if 'atEnd()' returns true - they
-// will act on the fallback stub.
-//
-// This iterator also allows unlinking of stubs being traversed.
-// Note that 'unlink' does not implicitly advance the iterator -
-// it must be advanced explicitly using '++'.
-class ICStubIterator
-{
- friend class ICFallbackStub;
-
- private:
- ICEntry* icEntry_;
- ICFallbackStub* fallbackStub_;
- ICStub* previousStub_;
- ICStub* currentStub_;
- bool unlinked_;
-
- explicit ICStubIterator(ICFallbackStub* fallbackStub, bool end=false);
- public:
-
- bool operator ==(const ICStubIterator& other) const {
- // == should only ever be called on stubs from the same chain.
- MOZ_ASSERT(icEntry_ == other.icEntry_);
- MOZ_ASSERT(fallbackStub_ == other.fallbackStub_);
- return currentStub_ == other.currentStub_;
- }
- bool operator !=(const ICStubIterator& other) const {
- return !(*this == other);
- }
-
- ICStubIterator& operator++();
-
- ICStubIterator operator++(int) {
- ICStubIterator oldThis(*this);
- ++(*this);
- return oldThis;
- }
-
- ICStub* operator*() const {
- return currentStub_;
- }
-
- ICStub* operator ->() const {
- return currentStub_;
- }
-
- bool atEnd() const {
- return currentStub_ == (ICStub*) fallbackStub_;
- }
-
- void unlink(JSContext* cx);
-};
-
-//
-// Base class for all IC stubs.
-//
-class ICStub
-{
- friend class ICFallbackStub;
-
- public:
- enum Kind {
- INVALID = 0,
-#define DEF_ENUM_KIND(kindName) kindName,
- IC_BASELINE_STUB_KIND_LIST(DEF_ENUM_KIND)
- IC_SHARED_STUB_KIND_LIST(DEF_ENUM_KIND)
-#undef DEF_ENUM_KIND
- LIMIT
- };
-
- static bool IsValidKind(Kind k) {
- return (k > INVALID) && (k < LIMIT);
- }
- static bool IsCacheIRKind(Kind k) {
- return k == CacheIR_Regular || k == CacheIR_Monitored || k == CacheIR_Updated;
- }
-
- static const char* KindString(Kind k) {
- switch(k) {
-#define DEF_KIND_STR(kindName) case kindName: return #kindName;
- IC_BASELINE_STUB_KIND_LIST(DEF_KIND_STR)
- IC_SHARED_STUB_KIND_LIST(DEF_KIND_STR)
-#undef DEF_KIND_STR
- default:
- MOZ_CRASH("Invalid kind.");
- }
- }
-
- enum Trait {
- Regular = 0x0,
- Fallback = 0x1,
- Monitored = 0x2,
- MonitoredFallback = 0x3,
- Updated = 0x4
- };
-
- void traceCode(JSTracer* trc, const char* name);
- void updateCode(JitCode* stubCode);
- void trace(JSTracer* trc);
-
- template
- static T* New(JSContext* cx, ICStubSpace* space, JitCode* code, Args&&... args) {
- if (!code)
- return nullptr;
- T* result = space->allocate(code, std::forward(args)...);
- if (!result)
- ReportOutOfMemory(cx);
- return result;
- }
-
- protected:
- // The raw jitcode to call for this stub.
- uint8_t* stubCode_;
-
- // Pointer to next IC stub. This is null for the last IC stub, which should
- // either be a fallback or inert IC stub.
- ICStub* next_;
-
- // A 16-bit field usable by subtypes of ICStub for subtype-specific small-info
- uint16_t extra_;
-
- // The kind of the stub.
- // High bit is 'isFallback' flag.
- // Second high bit is 'isMonitored' flag.
- Trait trait_ : 3;
- Kind kind_ : 13;
-
- inline ICStub(Kind kind, JitCode* stubCode)
- : stubCode_(stubCode->raw()),
- next_(nullptr),
- extra_(0),
- trait_(Regular),
- kind_(kind)
- {
- MOZ_ASSERT(stubCode != nullptr);
- }
-
- inline ICStub(Kind kind, Trait trait, JitCode* stubCode)
- : stubCode_(stubCode->raw()),
- next_(nullptr),
- extra_(0),
- trait_(trait),
- kind_(kind)
- {
- MOZ_ASSERT(stubCode != nullptr);
- }
-
- inline Trait trait() const {
- // Workaround for MSVC reading trait_ as signed value.
- return (Trait)(trait_ & 0x7);
- }
-
- public:
-
- inline Kind kind() const {
- return static_cast(kind_);
- }
-
- inline bool isFallback() const {
- return trait() == Fallback || trait() == MonitoredFallback;
- }
-
- inline bool isMonitored() const {
- return trait() == Monitored;
- }
-
- inline bool isUpdated() const {
- return trait() == Updated;
- }
-
- inline bool isMonitoredFallback() const {
- return trait() == MonitoredFallback;
- }
-
- inline const ICFallbackStub* toFallbackStub() const {
- MOZ_ASSERT(isFallback());
- return reinterpret_cast(this);
- }
-
- inline ICFallbackStub* toFallbackStub() {
- MOZ_ASSERT(isFallback());
- return reinterpret_cast(this);
- }
-
- inline const ICMonitoredStub* toMonitoredStub() const {
- MOZ_ASSERT(isMonitored());
- return reinterpret_cast(this);
- }
-
- inline ICMonitoredStub* toMonitoredStub() {
- MOZ_ASSERT(isMonitored());
- return reinterpret_cast(this);
- }
-
- inline const ICMonitoredFallbackStub* toMonitoredFallbackStub() const {
- MOZ_ASSERT(isMonitoredFallback());
- return reinterpret_cast(this);
- }
-
- inline ICMonitoredFallbackStub* toMonitoredFallbackStub() {
- MOZ_ASSERT(isMonitoredFallback());
- return reinterpret_cast(this);
- }
-
- inline const ICUpdatedStub* toUpdatedStub() const {
- MOZ_ASSERT(isUpdated());
- return reinterpret_cast(this);
- }
-
- inline ICUpdatedStub* toUpdatedStub() {
- MOZ_ASSERT(isUpdated());
- return reinterpret_cast(this);
- }
-
-#define KIND_METHODS(kindName) \
- inline bool is##kindName() const { return kind() == kindName; } \
- inline const IC##kindName* to##kindName() const { \
- MOZ_ASSERT(is##kindName()); \
- return reinterpret_cast(this); \
- } \
- inline IC##kindName* to##kindName() { \
- MOZ_ASSERT(is##kindName()); \
- return reinterpret_cast(this); \
- }
- IC_BASELINE_STUB_KIND_LIST(KIND_METHODS)
- IC_SHARED_STUB_KIND_LIST(KIND_METHODS)
-#undef KIND_METHODS
-
- inline ICStub* next() const {
- return next_;
- }
-
- inline bool hasNext() const {
- return next_ != nullptr;
- }
-
- inline void setNext(ICStub* stub) {
- // Note: next_ only needs to be changed under the compilation lock for
- // non-type-monitor/update ICs.
- next_ = stub;
- }
-
- inline ICStub** addressOfNext() {
- return &next_;
- }
-
- inline JitCode* jitCode() {
- return JitCode::FromExecutable(stubCode_);
- }
-
- inline uint8_t* rawStubCode() const {
- return stubCode_;
- }
-
- // This method is not valid on TypeUpdate stub chains!
- inline ICFallbackStub* getChainFallback() {
- ICStub* lastStub = this;
- while (lastStub->next_)
- lastStub = lastStub->next_;
- MOZ_ASSERT(lastStub->isFallback());
- return lastStub->toFallbackStub();
- }
-
- inline ICStubConstIterator beginHere() {
- return ICStubConstIterator::StartingAt(this);
- }
-
- static inline size_t offsetOfNext() {
- return offsetof(ICStub, next_);
- }
-
- static inline size_t offsetOfStubCode() {
- return offsetof(ICStub, stubCode_);
- }
-
- static inline size_t offsetOfExtra() {
- return offsetof(ICStub, extra_);
- }
-
- static bool NonCacheIRStubMakesGCCalls(Kind kind);
- bool makesGCCalls() const;
-
- // Optimized stubs get purged on GC. But some stubs can be active on the
- // stack during GC - specifically the ones that can make calls. To ensure
- // that these do not get purged, all stubs that can make calls are allocated
- // in the fallback stub space.
- bool allocatedInFallbackSpace() const {
- MOZ_ASSERT(next());
- return makesGCCalls();
- }
-};
-
-class ICFallbackStub : public ICStub
-{
- friend class ICStubConstIterator;
- protected:
- // Fallback stubs need these fields to easily add new stubs to
- // the linked list of stubs for an IC.
-
- // The IC entry for this linked list of stubs.
- ICEntry* icEntry_;
-
- // The number of stubs kept in the IC entry.
- ICState state_;
-
- // A pointer to the location stub pointer that needs to be
- // changed to add a new "last" stub immediately before the fallback
- // stub. This'll start out pointing to the icEntry's "firstStub_"
- // field, and as new stubs are added, it'll point to the current
- // last stub's "next_" field.
- ICStub** lastStubPtrAddr_;
-
- ICFallbackStub(Kind kind, JitCode* stubCode)
- : ICStub(kind, ICStub::Fallback, stubCode),
- icEntry_(nullptr),
- state_(),
- lastStubPtrAddr_(nullptr) {}
-
- ICFallbackStub(Kind kind, Trait trait, JitCode* stubCode)
- : ICStub(kind, trait, stubCode),
- icEntry_(nullptr),
- state_(),
- lastStubPtrAddr_(nullptr)
- {
- MOZ_ASSERT(trait == ICStub::Fallback ||
- trait == ICStub::MonitoredFallback);
- }
-
- public:
- inline ICEntry* icEntry() const {
- return icEntry_;
- }
-
- inline size_t numOptimizedStubs() const {
- return state_.numOptimizedStubs();
- }
-
- void setInvalid() {
- state_.setInvalid();
- }
-
- bool invalid() const {
- return state_.invalid();
- }
-
- ICState& state() {
- return state_;
- }
-
- // The icEntry and lastStubPtrAddr_ fields can't be initialized when the stub is
- // created since the stub is created at compile time, and we won't know the IC entry
- // address until after compile when the JitScript is created. This method
- // allows these fields to be fixed up at that point.
- void fixupICEntry(ICEntry* icEntry) {
- MOZ_ASSERT(icEntry_ == nullptr);
- MOZ_ASSERT(lastStubPtrAddr_ == nullptr);
- icEntry_ = icEntry;
- lastStubPtrAddr_ = icEntry_->addressOfFirstStub();
- }
-
- // Add a new stub to the IC chain terminated by this fallback stub.
- void addNewStub(ICStub* stub) {
- MOZ_ASSERT(!invalid());
- MOZ_ASSERT(*lastStubPtrAddr_ == this);
- MOZ_ASSERT(stub->next() == nullptr);
- stub->setNext(this);
- *lastStubPtrAddr_ = stub;
- lastStubPtrAddr_ = stub->addressOfNext();
- state_.trackAttached();
- }
-
- ICStubConstIterator beginChainConst() const {
- return ICStubConstIterator(icEntry_->firstStub());
- }
-
- ICStubIterator beginChain() {
- return ICStubIterator(this);
- }
-
- bool hasStub(ICStub::Kind kind) const {
- for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
- if (iter->kind() == kind)
- return true;
- }
- return false;
- }
-
- unsigned numStubsWithKind(ICStub::Kind kind) const {
- unsigned count = 0;
- for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
- if (iter->kind() == kind)
- count++;
- }
- return count;
- }
-
- void discardStubs(JSContext* cx);
-
- void unlinkStub(Zone* zone, ICStub* prev, ICStub* stub);
- void unlinkStubsWithKind(JSContext* cx, ICStub::Kind kind);
-};
-
-// Base class for Trait::Regular CacheIR stubs
-class ICCacheIR_Regular : public ICStub
-{
- const CacheIRStubInfo* stubInfo_;
-
- public:
- ICCacheIR_Regular(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
- : ICStub(ICStub::CacheIR_Regular, stubCode),
- stubInfo_(stubInfo)
- {}
-
- static ICCacheIR_Regular* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
- ICCacheIR_Regular& other);
-
- void notePreliminaryObject() {
- extra_ = 1;
- }
- bool hasPreliminaryObject() const {
- return extra_;
- }
-
- const CacheIRStubInfo* stubInfo() const {
- return stubInfo_;
- }
-
- uint8_t* stubDataStart();
-};
-
-// Monitored stubs are IC stubs that feed a single resulting value out to a
-// type monitor operation.
-class ICMonitoredStub : public ICStub
-{
- protected:
- // Pointer to the start of the type monitoring stub chain.
- ICStub* firstMonitorStub_;
-
- ICMonitoredStub(Kind kind, JitCode* stubCode, ICStub* firstMonitorStub);
-
- public:
- inline void updateFirstMonitorStub(ICStub* monitorStub) {
- // This should only be called once: when the first optimized monitor stub
- // is added to the type monitor IC chain.
- MOZ_ASSERT(firstMonitorStub_ && firstMonitorStub_->isTypeMonitor_Fallback());
- firstMonitorStub_ = monitorStub;
- }
- inline void resetFirstMonitorStub(ICStub* monitorFallback) {
- MOZ_ASSERT(monitorFallback->isTypeMonitor_Fallback());
- firstMonitorStub_ = monitorFallback;
- }
- inline ICStub* firstMonitorStub() const {
- return firstMonitorStub_;
- }
-
- static inline size_t offsetOfFirstMonitorStub() {
- return offsetof(ICMonitoredStub, firstMonitorStub_);
- }
-};
-
-class ICCacheIR_Monitored : public ICMonitoredStub
-{
- const CacheIRStubInfo* stubInfo_;
-
- public:
- ICCacheIR_Monitored(JitCode* stubCode, ICStub* firstMonitorStub,
- const CacheIRStubInfo* stubInfo)
- : ICMonitoredStub(ICStub::CacheIR_Monitored, stubCode, firstMonitorStub),
- stubInfo_(stubInfo)
- {}
-
- static ICCacheIR_Monitored* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
- ICCacheIR_Monitored& other);
-
- void notePreliminaryObject() {
- extra_ = 1;
- }
- bool hasPreliminaryObject() const {
- return extra_;
- }
-
- const CacheIRStubInfo* stubInfo() const {
- return stubInfo_;
- }
-
- uint8_t* stubDataStart();
-};
-
-// Updated stubs are IC stubs that use a TypeUpdate IC to track
-// the status of heap typesets that need to be updated.
-class ICUpdatedStub : public ICStub
-{
- protected:
- // Pointer to the start of the type updating stub chain.
- ICStub* firstUpdateStub_;
-
- static const uint32_t MAX_OPTIMIZED_STUBS = 8;
- uint32_t numOptimizedStubs_;
-
- ICUpdatedStub(Kind kind, JitCode* stubCode)
- : ICStub(kind, ICStub::Updated, stubCode),
- firstUpdateStub_(nullptr),
- numOptimizedStubs_(0)
- {}
-
- public:
- MOZ_MUST_USE bool initUpdatingChain(JSContext* cx, ICStubSpace* space);
-
- MOZ_MUST_USE bool addUpdateStubForValue(JSContext* cx, HandleScript script, HandleObject obj,
- HandleObjectGroup group, HandleId id, HandleValue val);
-
- void addOptimizedUpdateStub(ICStub* stub) {
- if (firstUpdateStub_->isTypeUpdate_Fallback()) {
- stub->setNext(firstUpdateStub_);
- firstUpdateStub_ = stub;
- } else {
- ICStub* iter = firstUpdateStub_;
- MOZ_ASSERT(iter->next() != nullptr);
- while (!iter->next()->isTypeUpdate_Fallback())
- iter = iter->next();
- MOZ_ASSERT(iter->next()->next() == nullptr);
- stub->setNext(iter->next());
- iter->setNext(stub);
- }
-
- numOptimizedStubs_++;
- }
-
- inline ICStub* firstUpdateStub() const {
- return firstUpdateStub_;
- }
-
- void resetUpdateStubChain(Zone* zone);
-
- bool hasTypeUpdateStub(ICStub::Kind kind) {
- ICStub* stub = firstUpdateStub_;
- do {
- if (stub->kind() == kind)
- return true;
-
- stub = stub->next();
- } while (stub);
-
- return false;
- }
-
- inline uint32_t numOptimizedStubs() const {
- return numOptimizedStubs_;
- }
-
- static inline size_t offsetOfFirstUpdateStub() {
- return offsetof(ICUpdatedStub, firstUpdateStub_);
- }
-};
-
-class ICCacheIR_Updated : public ICUpdatedStub
-{
- const CacheIRStubInfo* stubInfo_;
- GCPtrObjectGroup updateStubGroup_;
- GCPtrId updateStubId_;
-
- public:
- ICCacheIR_Updated(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
- : ICUpdatedStub(ICStub::CacheIR_Updated, stubCode),
- stubInfo_(stubInfo),
- updateStubGroup_(nullptr),
- updateStubId_(JSID_EMPTY)
- {}
-
- static ICCacheIR_Updated* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
- ICCacheIR_Updated& other);
-
- GCPtrObjectGroup& updateStubGroup() {
- return updateStubGroup_;
- }
- GCPtrId& updateStubId() {
- return updateStubId_;
- }
-
- void notePreliminaryObject() {
- extra_ = 1;
- }
- bool hasPreliminaryObject() const {
- return extra_;
- }
-
- const CacheIRStubInfo* stubInfo() const {
- return stubInfo_;
- }
-
- uint8_t* stubDataStart();
-};
-
-// Base class for stubcode compilers.
-class ICStubCompiler
-{
- // Prevent GC in the middle of stub compilation.
- js::gc::AutoSuppressGC suppressGC;
-
- public:
- using Engine = ICStubEngine;
-
- protected:
- JSContext* cx;
- ICStub::Kind kind;
- Engine engine_;
- bool inStubFrame_;
-
-#ifdef DEBUG
- bool entersStubFrame_;
- uint32_t framePushedAtEnterStubFrame_;
-#endif
-
- // By default the stubcode key is just the kind.
- virtual int32_t getKey() const {
- return static_cast(engine_) |
- (static_cast(kind) << 1);
- }
-
- virtual MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) = 0;
- virtual void postGenerateStubCode(MacroAssembler& masm, Handle genCode) {}
-
- JitCode* getStubCode();
-
- ICStubCompiler(JSContext* cx, ICStub::Kind kind, Engine engine)
- : suppressGC(cx), cx(cx), kind(kind), engine_(engine), inStubFrame_(false)
-#ifdef DEBUG
- , entersStubFrame_(false), framePushedAtEnterStubFrame_(0)
-#endif
- {}
-
- // Push a payload specialized per compiler needed to execute stubs.
- void PushStubPayload(MacroAssembler& masm, Register scratch);
- void pushStubPayload(MacroAssembler& masm, Register scratch);
-
- // Emits a tail call to a VMFunction wrapper.
- MOZ_MUST_USE bool tailCallVM(const VMFunction& fun, MacroAssembler& masm);
-
- // Emits a normal (non-tail) call to a VMFunction wrapper.
- MOZ_MUST_USE bool callVM(const VMFunction& fun, MacroAssembler& masm);
-
- // A stub frame is used when a stub wants to call into the VM without
- // performing a tail call. This is required for the return address
- // to pc mapping to work.
- void enterStubFrame(MacroAssembler& masm, Register scratch);
- void assumeStubFrame();
- void leaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false);
-
- // Some stubs need to emit Gecko Profiler updates. This emits the guarding
- // jitcode for those stubs. If profiling is not enabled, jumps to the
- // given label.
- void guardProfilingEnabled(MacroAssembler& masm, Register scratch, Label* skip);
-
- public:
- static inline AllocatableGeneralRegisterSet availableGeneralRegs(size_t numInputs) {
- AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
-#if defined(JS_CODEGEN_ARM)
- MOZ_ASSERT(!regs.has(BaselineStackReg));
- MOZ_ASSERT(!regs.has(ICTailCallReg));
- regs.take(BaselineSecondScratchReg);
-#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
- MOZ_ASSERT(!regs.has(BaselineStackReg));
- MOZ_ASSERT(!regs.has(ICTailCallReg));
- MOZ_ASSERT(!regs.has(BaselineSecondScratchReg));
-#elif defined(JS_CODEGEN_ARM64)
- MOZ_ASSERT(!regs.has(PseudoStackPointer));
- MOZ_ASSERT(!regs.has(RealStackPointer));
- MOZ_ASSERT(!regs.has(ICTailCallReg));
-#else
- MOZ_ASSERT(!regs.has(BaselineStackReg));
-#endif
- regs.take(BaselineFrameReg);
- regs.take(ICStubReg);
-#ifdef JS_CODEGEN_X64
- regs.take(ExtractTemp0);
- regs.take(ExtractTemp1);
-#endif
-
- switch (numInputs) {
- case 0:
- break;
- case 1:
- regs.take(R0);
- break;
- case 2:
- regs.take(R0);
- regs.take(R1);
- break;
- default:
- MOZ_CRASH("Invalid numInputs");
- }
-
- return regs;
- }
-
- protected:
- template
- T* newStub(Args&&... args) {
- return ICStub::New(cx, std::forward(args)...);
- }
-
- public:
- virtual ICStub* getStub(ICStubSpace* space) = 0;
-
- static ICStubSpace* StubSpaceForStub(bool makesGCCalls, JSScript* outerScript, Engine engine) {
- if (makesGCCalls) {
- if (engine == ICStubCompiler::Engine::Baseline)
- return outerScript->baselineScript()->fallbackStubSpace();
- return outerScript->ionScript()->fallbackStubSpace();
- }
- return outerScript->zone()->jitZone()->optimizedStubSpace();
- }
- ICStubSpace* getStubSpace(JSScript* outerScript) {
- return StubSpaceForStub(ICStub::NonCacheIRStubMakesGCCalls(kind), outerScript, engine_);
- }
-};
-
-class SharedStubInfo
-{
- BaselineFrame* maybeFrame_;
- RootedScript outerScript_;
- RootedScript innerScript_;
- ICEntry* icEntry_;
-
- public:
- SharedStubInfo(JSContext* cx, void* payload, ICEntry* entry);
-
- ICStubCompiler::Engine engine() const {
- return maybeFrame_
- ? ICStubCompiler::Engine::Baseline
- : ICStubCompiler::Engine::IonSharedIC;
- }
-
- HandleScript script() const {
- MOZ_ASSERT(innerScript_);
- return innerScript_;
- }
-
- HandleScript innerScript() const {
- MOZ_ASSERT(innerScript_);
- return innerScript_;
- }
-
- HandleScript outerScript(JSContext* cx);
-
- jsbytecode* pc() const {
- return icEntry()->pc(innerScript());
- }
-
- uint32_t pcOffset() const {
- return script()->pcToOffset(pc());
- }
-
- BaselineFrame* frame() const {
- MOZ_ASSERT(maybeFrame_);
- return maybeFrame_;
- }
-
- BaselineFrame* maybeFrame() const {
- return maybeFrame_;
- }
-
- ICEntry* icEntry() const {
- return icEntry_;
- }
-};
-
-// Monitored fallback stubs - as the name implies.
-class ICMonitoredFallbackStub : public ICFallbackStub
-{
- protected:
- // Pointer to the fallback monitor stub. Created lazily by
- // getFallbackMonitorStub if needed.
- ICTypeMonitor_Fallback* fallbackMonitorStub_;
-
- ICMonitoredFallbackStub(Kind kind, JitCode* stubCode)
- : ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
- fallbackMonitorStub_(nullptr) {}
-
- public:
- MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, JSScript* script);
- MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
- StackTypeSet* types, HandleValue val);
-
- ICTypeMonitor_Fallback* maybeFallbackMonitorStub() const {
- return fallbackMonitorStub_;
- }
- ICTypeMonitor_Fallback* getFallbackMonitorStub(JSContext* cx, JSScript* script) {
- if (!fallbackMonitorStub_ && !initMonitoringChain(cx, script))
- return nullptr;
- MOZ_ASSERT(fallbackMonitorStub_);
- return fallbackMonitorStub_;
- }
-
- static inline size_t offsetOfFallbackMonitorStub() {
- return offsetof(ICMonitoredFallbackStub, fallbackMonitorStub_);
- }
-};
-
-
-// Base class for stub compilers that can generate multiple stubcodes.
-// These compilers need access to the JSOp they are compiling for.
-class ICMultiStubCompiler : public ICStubCompiler
-{
- protected:
- JSOp op;
-
- // Stub keys for multi-stub kinds are composed of both the kind
- // and the op they are compiled for.
- virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(op) << 17);
- }
-
- ICMultiStubCompiler(JSContext* cx, ICStub::Kind kind, JSOp op, Engine engine)
- : ICStubCompiler(cx, kind, engine), op(op) {}
-};
-
-// TypeCheckPrimitiveSetStub
-// Base class for IC stubs (TypeUpdate or TypeMonitor) that check that a given
-// value's type falls within a set of primitive types.
-
-class TypeCheckPrimitiveSetStub : public ICStub
-{
- friend class ICStubSpace;
- protected:
- inline static uint16_t TypeToFlag(JSValueType type) {
- return 1u << static_cast(type);
- }
-
- inline static uint16_t ValidFlags() {
- return ((TypeToFlag(JSVAL_TYPE_OBJECT) << 1) - 1) & ~TypeToFlag(JSVAL_TYPE_MAGIC);
- }
-
- TypeCheckPrimitiveSetStub(Kind kind, JitCode* stubCode, uint16_t flags)
- : ICStub(kind, stubCode)
- {
- MOZ_ASSERT(kind == TypeMonitor_PrimitiveSet || kind == TypeUpdate_PrimitiveSet);
- MOZ_ASSERT(flags && !(flags & ~ValidFlags()));
- extra_ = flags;
- }
-
- TypeCheckPrimitiveSetStub* updateTypesAndCode(uint16_t flags, JitCode* code) {
- MOZ_ASSERT(flags && !(flags & ~ValidFlags()));
- if (!code)
- return nullptr;
- extra_ = flags;
- updateCode(code);
- return this;
- }
-
- public:
- uint16_t typeFlags() const {
- return extra_;
- }
-
- bool containsType(JSValueType type) const {
- MOZ_ASSERT(type <= JSVAL_TYPE_OBJECT);
- MOZ_ASSERT(type != JSVAL_TYPE_MAGIC);
- return extra_ & TypeToFlag(type);
- }
-
- ICTypeMonitor_PrimitiveSet* toMonitorStub() {
- return toTypeMonitor_PrimitiveSet();
- }
-
- ICTypeUpdate_PrimitiveSet* toUpdateStub() {
- return toTypeUpdate_PrimitiveSet();
- }
-
- class Compiler : public ICStubCompiler {
- protected:
- TypeCheckPrimitiveSetStub* existingStub_;
- uint16_t flags_;
-
- virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(flags_) << 17);
- }
-
- public:
- Compiler(JSContext* cx, Kind kind, TypeCheckPrimitiveSetStub* existingStub,
- JSValueType type)
- : ICStubCompiler(cx, kind, Engine::Baseline),
- existingStub_(existingStub),
- flags_((existingStub ? existingStub->typeFlags() : 0) | TypeToFlag(type))
- {
- MOZ_ASSERT_IF(existingStub_, flags_ != existingStub_->typeFlags());
- }
-
- TypeCheckPrimitiveSetStub* updateStub() {
- MOZ_ASSERT(existingStub_);
- return existingStub_->updateTypesAndCode(flags_, getStubCode());
- }
- };
-};
-
-// TypeMonitor
-
-// The TypeMonitor fallback stub is not always a regular fallback stub. When
-// used for monitoring the values pushed by a bytecode it doesn't hold a
-// pointer to the IC entry, but rather back to the main fallback stub for the
-// IC (from which a pointer to the IC entry can be retrieved). When monitoring
-// the types of 'this', arguments or other values with no associated IC, there
-// is no main fallback stub, and the IC entry is referenced directly.
-class ICTypeMonitor_Fallback : public ICStub
-{
- friend class ICStubSpace;
-
- static const uint32_t MAX_OPTIMIZED_STUBS = 8;
-
- // Pointer to the main fallback stub for the IC or to the main IC entry,
- // depending on hasFallbackStub.
- union {
- ICMonitoredFallbackStub* mainFallbackStub_;
- ICEntry* icEntry_;
- };
-
- // Pointer to the first monitor stub.
- ICStub* firstMonitorStub_;
-
- // Address of the last monitor stub's field pointing to this
- // fallback monitor stub. This will get updated when new
- // monitor stubs are created and added.
- ICStub** lastMonitorStubPtrAddr_;
-
- // Count of optimized type monitor stubs in this chain.
- uint32_t numOptimizedMonitorStubs_ : 7;
-
- uint32_t invalid_ : 1;
-
- // Whether this has a fallback stub referring to the IC entry.
- bool hasFallbackStub_ : 1;
-
- // Index of 'this' or argument which is being monitored, or BYTECODE_INDEX
- // if this is monitoring the types of values pushed at some bytecode.
- uint32_t argumentIndex_ : 23;
-
- static const uint32_t BYTECODE_INDEX = (1 << 23) - 1;
-
- ICTypeMonitor_Fallback(JitCode* stubCode, ICMonitoredFallbackStub* mainFallbackStub,
- uint32_t argumentIndex)
- : ICStub(ICStub::TypeMonitor_Fallback, stubCode),
- mainFallbackStub_(mainFallbackStub),
- firstMonitorStub_(thisFromCtor()),
- lastMonitorStubPtrAddr_(nullptr),
- numOptimizedMonitorStubs_(0),
- invalid_(false),
- hasFallbackStub_(mainFallbackStub != nullptr),
- argumentIndex_(argumentIndex)
- { }
-
- ICTypeMonitor_Fallback* thisFromCtor() {
- return this;
- }
-
- void addOptimizedMonitorStub(ICStub* stub) {
- MOZ_ASSERT(!invalid());
- stub->setNext(this);
-
- MOZ_ASSERT((lastMonitorStubPtrAddr_ != nullptr) ==
- (numOptimizedMonitorStubs_ || !hasFallbackStub_));
-
- if (lastMonitorStubPtrAddr_)
- *lastMonitorStubPtrAddr_ = stub;
-
- if (numOptimizedMonitorStubs_ == 0) {
- MOZ_ASSERT(firstMonitorStub_ == this);
- firstMonitorStub_ = stub;
- } else {
- MOZ_ASSERT(firstMonitorStub_ != nullptr);
- }
-
- lastMonitorStubPtrAddr_ = stub->addressOfNext();
- numOptimizedMonitorStubs_++;
- }
-
- public:
- bool hasStub(ICStub::Kind kind) {
- ICStub* stub = firstMonitorStub_;
- do {
- if (stub->kind() == kind)
- return true;
-
- stub = stub->next();
- } while (stub);
-
- return false;
- }
-
- inline ICFallbackStub* mainFallbackStub() const {
- MOZ_ASSERT(hasFallbackStub_);
- return mainFallbackStub_;
- }
-
- inline ICEntry* icEntry() const {
- return hasFallbackStub_ ? mainFallbackStub()->icEntry() : icEntry_;
- }
-
- inline ICStub* firstMonitorStub() const {
- return firstMonitorStub_;
- }
-
- static inline size_t offsetOfFirstMonitorStub() {
- return offsetof(ICTypeMonitor_Fallback, firstMonitorStub_);
- }
-
- inline uint32_t numOptimizedMonitorStubs() const {
- return numOptimizedMonitorStubs_;
- }
-
- void setInvalid() {
- invalid_ = 1;
- }
-
- bool invalid() const {
- return invalid_;
- }
-
- inline bool monitorsThis() const {
- return argumentIndex_ == 0;
- }
-
- inline bool monitorsArgument(uint32_t* pargument) const {
- if (argumentIndex_ > 0 && argumentIndex_ < BYTECODE_INDEX) {
- *pargument = argumentIndex_ - 1;
- return true;
- }
- return false;
- }
-
- inline bool monitorsBytecode() const {
- return argumentIndex_ == BYTECODE_INDEX;
- }
-
- // Fixup the IC entry as for a normal fallback stub, for this/arguments.
- void fixupICEntry(ICEntry* icEntry) {
- MOZ_ASSERT(!hasFallbackStub_);
- MOZ_ASSERT(icEntry_ == nullptr);
- MOZ_ASSERT(lastMonitorStubPtrAddr_ == nullptr);
- icEntry_ = icEntry;
- lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
- }
-
- // Create a new monitor stub for the type of the given value, and
- // add it to this chain.
- MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
- StackTypeSet* types, HandleValue val);
-
- void resetMonitorStubChain(Zone* zone);
-
- // Compiler for this stub kind.
- class Compiler : public ICStubCompiler {
- ICMonitoredFallbackStub* mainFallbackStub_;
- uint32_t argumentIndex_;
-
- protected:
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
-
- public:
- Compiler(JSContext* cx, ICMonitoredFallbackStub* mainFallbackStub)
- : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback, Engine::Baseline),
- mainFallbackStub_(mainFallbackStub),
- argumentIndex_(BYTECODE_INDEX)
- { }
-
- Compiler(JSContext* cx, uint32_t argumentIndex)
- : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback, Engine::Baseline),
- mainFallbackStub_(nullptr),
- argumentIndex_(argumentIndex)
- { }
-
- ICTypeMonitor_Fallback* getStub(ICStubSpace* space) override {
- return newStub(space, getStubCode(), mainFallbackStub_,
- argumentIndex_);
- }
- };
-};
-
-class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub
-{
- friend class ICStubSpace;
-
- ICTypeMonitor_PrimitiveSet(JitCode* stubCode, uint16_t flags)
- : TypeCheckPrimitiveSetStub(TypeMonitor_PrimitiveSet, stubCode, flags)
- {}
-
- public:
- class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
- protected:
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
-
- public:
- Compiler(JSContext* cx, ICTypeMonitor_PrimitiveSet* existingStub,
- JSValueType type)
- : TypeCheckPrimitiveSetStub::Compiler(cx, TypeMonitor_PrimitiveSet, existingStub,
- type)
- {}
-
- ICTypeMonitor_PrimitiveSet* updateStub() {
- TypeCheckPrimitiveSetStub* stub =
- this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
- if (!stub)
- return nullptr;
- return stub->toMonitorStub();
- }
-
- ICTypeMonitor_PrimitiveSet* getStub(ICStubSpace* space) override {
- MOZ_ASSERT(!existingStub_);
- return newStub(space, getStubCode(), flags_);
- }
- };
-};
-
-class ICTypeMonitor_SingleObject : public ICStub
-{
- friend class ICStubSpace;
-
- GCPtrObject obj_;
-
- ICTypeMonitor_SingleObject(JitCode* stubCode, JSObject* obj);
-
- public:
- GCPtrObject& object() {
- return obj_;
- }
-
- static size_t offsetOfObject() {
- return offsetof(ICTypeMonitor_SingleObject, obj_);
- }
-
- class Compiler : public ICStubCompiler {
- protected:
- HandleObject obj_;
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
-
- public:
- Compiler(JSContext* cx, HandleObject obj)
- : ICStubCompiler(cx, TypeMonitor_SingleObject, Engine::Baseline),
- obj_(obj)
- { }
-
- ICTypeMonitor_SingleObject* getStub(ICStubSpace* space) override {
- return newStub(space, getStubCode(), obj_);
- }
- };
-};
-
-class ICTypeMonitor_ObjectGroup : public ICStub
-{
- friend class ICStubSpace;
-
- GCPtrObjectGroup group_;
-
- ICTypeMonitor_ObjectGroup(JitCode* stubCode, ObjectGroup* group);
-
- public:
- GCPtrObjectGroup& group() {
- return group_;
- }
-
- static size_t offsetOfGroup() {
- return offsetof(ICTypeMonitor_ObjectGroup, group_);
- }
-
- class Compiler : public ICStubCompiler {
- protected:
- HandleObjectGroup group_;
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
-
- public:
- Compiler(JSContext* cx, HandleObjectGroup group)
- : ICStubCompiler(cx, TypeMonitor_ObjectGroup, Engine::Baseline),
- group_(group)
- { }
-
- ICTypeMonitor_ObjectGroup* getStub(ICStubSpace* space) override {
- return newStub(space, getStubCode(), group_);
- }
- };
-};
-
-class ICTypeMonitor_AnyValue : public ICStub
-{
- friend class ICStubSpace;
-
- explicit ICTypeMonitor_AnyValue(JitCode* stubCode)
- : ICStub(TypeMonitor_AnyValue, stubCode)
- {}
-
- public:
- class Compiler : public ICStubCompiler {
- protected:
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
-
- public:
- explicit Compiler(JSContext* cx)
- : ICStubCompiler(cx, TypeMonitor_AnyValue, Engine::Baseline)
- { }
-
- ICTypeMonitor_AnyValue* getStub(ICStubSpace* space) override {
- return newStub(space, getStubCode());
- }
- };
-};
-
-// Compare
-// JSOP_LT
-// JSOP_LE
-// JSOP_GT
-// JSOP_GE
-// JSOP_EQ
-// JSOP_NE
-// JSOP_STRICTEQ
-// JSOP_STRICTNE
-
-class ICCompare_Fallback : public ICFallbackStub
-{
- friend class ICStubSpace;
-
- explicit ICCompare_Fallback(JitCode* stubCode)
- : ICFallbackStub(ICStub::Compare_Fallback, stubCode) {}
-
- public:
- static const uint32_t MAX_OPTIMIZED_STUBS = 8;
-
- static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
- void noteUnoptimizableAccess() {
- extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
- }
- bool hadUnoptimizableAccess() const {
- return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
- }
-
- // Compiler for this stub kind.
- class Compiler : public ICStubCompiler {
- protected:
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
-
- public:
- explicit Compiler(JSContext* cx, Engine engine)
- : ICStubCompiler(cx, ICStub::Compare_Fallback, engine) {}
-
- ICStub* getStub(ICStubSpace* space) override {
- return newStub(space, getStubCode());
- }
- };
-};
-
-// Enum for stubs handling a combination of typed arrays and typed objects.
-enum TypedThingLayout {
- Layout_TypedArray,
- Layout_OutlineTypedObject,
- Layout_InlineTypedObject
-};
-
-void
-StripPreliminaryObjectStubs(JSContext* cx, ICFallbackStub* stub);
-
-void
-LoadTypedThingData(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result);
-
-void
-LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result);
-
-class ICGetProp_Fallback : public ICMonitoredFallbackStub
-{
- friend class ICStubSpace;
-
- explicit ICGetProp_Fallback(JitCode* stubCode)
- : ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode)
- { }
-
- public:
- static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
- static const size_t ACCESSED_GETTER_BIT = 1;
-
- void noteUnoptimizableAccess() {
- extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
- }
- bool hadUnoptimizableAccess() const {
- return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
- }
-
- void noteAccessedGetter() {
- extra_ |= (1u << ACCESSED_GETTER_BIT);
- }
- bool hasAccessedGetter() const {
- return extra_ & (1u << ACCESSED_GETTER_BIT);
- }
-
- class Compiler : public ICStubCompiler {
- protected:
- CodeOffset bailoutReturnOffset_;
- bool hasReceiver_;
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
- void postGenerateStubCode(MacroAssembler& masm, Handle code) override;
-
- virtual int32_t getKey() const override {
- return static_cast(engine_) |
- (static_cast(kind) << 1) |
- (static_cast(hasReceiver_) << 17);
- }
-
- public:
- explicit Compiler(JSContext* cx, Engine engine, bool hasReceiver = false)
- : ICStubCompiler(cx, ICStub::GetProp_Fallback, engine),
- hasReceiver_(hasReceiver)
- { }
-
- ICStub* getStub(ICStubSpace* space) override {
- return newStub(space, getStubCode());
- }
- };
-};
-
-static inline uint32_t
-SimpleTypeDescrKey(SimpleTypeDescr* descr)
-{
- if (descr->is