chore: deprecate apply-patches in favour of git-{import,export}-patches (#15300)

This commit is contained in:
Jeremy Apthorp 2018-10-24 11:24:11 -07:00 committed by GitHub
parent 4185efa08f
commit 335e9f68b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
123 changed files with 4368 additions and 4780 deletions

View file

@ -0,0 +1,20 @@
deps_cherry-pick_0dd3390_from_upstream_v8.patch
deps_cherry-pick_09bca09_from_upstream_v8.patch
deps_cherry-pick_c608122_from_upstream_v8.patch
deps_cherry-pick_e1a7699_from_upstream_v8.patch
deps_cherry-pick_ba752ea_from_upstream_v8.patch
deps_cherry-pick_bf5ea81_from_upstream_v8.patch
deps_cherry-pick_a8f6869_from_upstream_v8.patch
deps_backport_detailed_line_info_for_cpu_profiler.patch
deps_cherry-pick_2363cdf_from_upstream_v8.patch
deps_cherry-pick_dbfcc48_from_upstream_v8.patch
deps_add_missing_handlescope_in_fieldtype_printto.patch
add_realloc.patch
build_gn.patch
array_buffer.patch
ostreams.patch
export_platform.patch
dcheck.patch
disable-warning-win.patch
expose_mksnapshot.patch
build-torque-with-x64-toolchain-on-arm.patch

View file

@ -1,72 +0,0 @@
repo: src/v8
patches:
-
author: null
file: node_v8_patches.patch
description: |
Patches that node applies to v8.
Generated with
$ cd third_party/electron_node
$ CURRENT_NODE_VERSION=vX.Y.Z
# Find the last commit with the message "deps: update V8 to <some version>"
# This commit corresponds to node resetting V8 to its pristine upstream
# state at the stated version.
$ LAST_V8_UPDATE="$(git log --grep='^deps: update V8' --format='%H' -1 deps/v8)"
# This creates a patch file containing all changes in deps/v8 from
# $LAST_V8_UPDATE up to the current node version, formatted in a way that
# it will apply cleanly to the V8 repository (i.e. with `deps/v8`
# stripped off the path and excluding the v8/gypfiles directory, which
# isn't present in V8.
$ git format-patch \
--relative=deps/v8 \
$LAST_V8_UPDATE..$CURRENT_NODE_VERSION \
deps/v8 \
':(exclude)deps/v8/gypfiles' \
--stdout
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: add_realloc.patch
description: |
Blink overrides ArrayBuffer's allocator with its own one, while Node simply
uses malloc and free, so we need to use v8's allocator in Node. As part of the
10.6.0 upgrade, we needed to make SerializerDelegate accept an allocator
argument in its constructor, and override ReallocateBufferMemory and
FreeBufferMemory to use the allocator. We cannot simply allocate and then memcpy
when we override ReallocateBufferMemory, so we therefore need to implement
Realloc on the v8 side.
-
author: Ales Pergl <alpergl@microsoft.com>
file: build_gn.patch
description: null
-
author: Cheng Zhao <zcbenz@gmail.com>
file: array_buffer.patch
description: null
-
author: Cheng Zhao <zcbenz@gmail.com>
file: ostreams.patch
description: null
-
author: Aleksei Kuzmin <alkuzmin@microsoft.com>
file: export_platform.patch
description: |
v8::Platform::SystemClockTimeMillis must be exported so that node::NodePlatform can call it
-
author: Ales Pergl <alpergl@microsoft.com>
file: dcheck.patch
description: null
-
author: Nitish Sakhawalkar <nitsakh@icloud.com>
file: disable-warning-win.patch
description:
Disable unit test windows build warning
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: expose_mksnapshot.patch
description: Needed in order to build mksnapshot on arm.
-
author: Aleksei Kuzmin <alkuzmin@microsoft.com>
file: build-torque-with-x64-toolchain-on-arm.patch
description: |
torque binary has to be run during the build.

View file

@ -0,0 +1,27 @@
### Exporting node's patches to v8
```
$ cd third_party/electron_node
$ CURRENT_NODE_VERSION=vX.Y.Z # e.g. v10.11.0
# Find the last commit with the message "deps: update V8 to <some version>"
# This commit corresponds to node resetting V8 to its pristine upstream
# state at the stated version.
$ LAST_V8_UPDATE="$(git log --grep='^deps: update V8' --format='%H' -1 deps/v8)"
# This creates a patch file containing all changes in deps/v8 from
# $LAST_V8_UPDATE up to the current node version, formatted in a way that
# it will apply cleanly to the V8 repository (i.e. with `deps/v8`
# stripped off the path and excluding the v8/gypfiles directory, which
# isn't present in V8.
$ git format-patch \
--relative=deps/v8 \
$LAST_V8_UPDATE..$CURRENT_NODE_VERSION \
deps/v8 \
':(exclude)deps/v8/gypfiles' \
--stdout
```
When upgrading to a new version of node, make sure to match node's patches to
v8 by removing all the `deps_*` patches and re-exporting node's v8 patches
using the process above.

View file

@ -1,8 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Mon, 22 Oct 2018 10:47:11 -0700
Subject: add_realloc.patch
Blink overrides ArrayBuffer's allocator with its own one, while Node simply
uses malloc and free, so we need to use v8's allocator in Node. As part of the
10.6.0 upgrade, we needed to make SerializerDelegate accept an allocator
argument in its constructor, and override ReallocateBufferMemory and
FreeBufferMemory to use the allocator. We cannot simply allocate and then memcpy
when we override ReallocateBufferMemory, so we therefore need to implement
Realloc on the v8 side.
diff --git a/include/v8.h b/include/v8.h
index 573e80176d..5eefe26fe9 100644
index 20a65afcbc61c31360874e45adc03eeda02e9a81..6bba7a177e72b54084b2a52e413c5de6edb26b01 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -4318,6 +4318,13 @@ class V8_EXPORT ArrayBuffer : public Object {
@@ -4618,6 +4618,13 @@ class V8_EXPORT ArrayBuffer : public Object {
*/
virtual void* AllocateUninitialized(size_t length) = 0;
@ -17,10 +30,10 @@ index 573e80176d..5eefe26fe9 100644
* Free the memory block of size |length|, pointed to by |data|.
* That memory is guaranteed to be previously allocated by |Allocate|.
diff --git a/src/api.cc b/src/api.cc
index 8b177d041d..e06ca2a207 100644
index 6155cbb32579effc500b5c475cd478e77b3ecdf4..9fe5268aa5e615fee058d430b6a137dd40fc9226 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -460,6 +460,10 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
@@ -505,6 +505,10 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
i::V8::SetSnapshotBlob(snapshot_blob);
}
@ -31,3 +44,6 @@ index 8b177d041d..e06ca2a207 100644
namespace {
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
--
2.17.0

View file

@ -1,8 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cheng Zhao <zcbenz@gmail.com>
Date: Mon, 22 Oct 2018 10:47:12 -0700
Subject: array_buffer.patch
diff --git a/include/v8.h b/include/v8.h
index 573e80176d..80bfd1d22a 100644
index 6bba7a177e72b54084b2a52e413c5de6edb26b01..b1e192dc009b33484148817be0b0b6bb4dc1bf4b 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -7337,6 +7337,9 @@ class V8_EXPORT Isolate {
@@ -7766,6 +7766,9 @@ class V8_EXPORT Isolate {
*/
void SetIdle(bool is_idle);
@ -13,10 +19,10 @@ index 573e80176d..80bfd1d22a 100644
bool InContext();
diff --git a/src/api.cc b/src/api.cc
index 8b177d041d..f58a350f0f 100644
index 9fe5268aa5e615fee058d430b6a137dd40fc9226..5c1f2410bbab4a0d9f4fcd99f19530ba999a66a2 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -8139,6 +8139,13 @@ void Isolate::SetIdle(bool is_idle) {
@@ -8290,6 +8290,13 @@ void Isolate::SetIdle(bool is_idle) {
isolate->SetIdle(is_idle);
}
@ -30,3 +36,6 @@ index 8b177d041d..f58a350f0f 100644
bool Isolate::InContext() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
return isolate->context() != nullptr;
--
2.17.0

View file

@ -1,8 +1,15 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aleksei Kuzmin <alkuzmin@microsoft.com>
Date: Mon, 22 Oct 2018 10:47:13 -0700
Subject: build-torque-with-x64-toolchain-on-arm.patch
torque binary has to be run during the build.
diff --git a/BUILD.gn b/BUILD.gn
index 456a318..af803ff 100644
index b5eb09cfcb8add19f4de985cbe7b9777c51c4bd3..dbe4338c3a733cb806e420a9bb0b4bcc65cf333b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -870,7 +870,8 @@ action("run_torque") {
@@ -899,7 +899,8 @@ action("run_torque") {
# is the target toolchain and, hence, can't be used.
v8_torque_toolchain = v8_snapshot_toolchain
if (host_cpu == "x64" &&
@ -12,7 +19,7 @@ index 456a318..af803ff 100644
v8_torque_toolchain = "//build/toolchain/linux:clang_x64"
}
@@ -3079,7 +3080,7 @@ if (v8_use_snapshot && current_toolchain == v8_snapshot_toolchain) {
@@ -3149,7 +3150,7 @@ if (v8_use_snapshot && current_toolchain == v8_snapshot_toolchain) {
}
}
@ -21,3 +28,5 @@ index 456a318..af803ff 100644
v8_executable("torque") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
--
2.17.0

View file

@ -1,5 +1,11 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ales Pergl <alpergl@microsoft.com>
Date: Mon, 22 Oct 2018 10:47:12 -0700
Subject: build_gn.patch
diff --git a/BUILD.gn b/BUILD.gn
index 443694d880..d0ba5ed04e 100644
index 443694d88075d59d6e8db7fa4bedc3a812fdafc4..d0ba5ed04e7126deae4a0ab9ee8943cda5ea42e3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -212,7 +212,7 @@ config("internal_config") {
@ -20,3 +26,6 @@ index 443694d880..d0ba5ed04e 100644
deps = [
":v8_base",
":v8_init",
--
2.17.0

View file

@ -1,8 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ales Pergl <alpergl@microsoft.com>
Date: Mon, 22 Oct 2018 10:47:12 -0700
Subject: dcheck.patch
diff --git a/src/api.cc b/src/api.cc
index 8531cd5c05..47254c9f5c 100644
index 5c1f2410bbab4a0d9f4fcd99f19530ba999a66a2..b464a2187c162bac00620f65e9c94deeaf3d6c95 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -8598,7 +8604,7 @@ void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
@@ -8851,7 +8851,7 @@ void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
void Isolate::RunMicrotasks() {
@ -12,10 +18,10 @@ index 8531cd5c05..47254c9f5c 100644
}
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 62a5856f34..c59dfad2c8 100644
index 6830a90482173174266faa0e9a95618c67fad811..78991a26de6d97e3ee14b66913fc079a795b299d 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -5963,9 +5963,9 @@ void Heap::TearDown() {
@@ -5006,9 +5006,9 @@ void Heap::TearDown() {
void Heap::AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
GCType gc_type, void* data) {
DCHECK_NOT_NULL(callback);
@ -28,3 +34,6 @@ index 62a5856f34..c59dfad2c8 100644
gc_prologue_callbacks_.emplace_back(callback, gc_type, data);
}
--
2.17.0

View file

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yang Guo <yangguo@chromium.org>
Date: Mon, 17 Sep 2018 07:43:46 +0200
Subject: deps: add missing HandleScope in FieldType::PrintTo
Refs: https://github.com/nodejs/node/issues/22775
PR-URL: https://github.com/nodejs/node/pull/22890
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
diff --git a/src/field-type.cc b/src/field-type.cc
index 3b51095323c06bf8883ce484566fd263249390ac..2eebebe3d616ea786ed60cd0e9bea853ea764c7b 100644
--- a/src/field-type.cc
+++ b/src/field-type.cc
@@ -78,6 +78,7 @@ void FieldType::PrintTo(std::ostream& os) {
os << "None";
} else {
DCHECK(IsClass());
+ HandleScope scope(Map::cast(this)->GetIsolate());
os << "Class(" << static_cast<void*>(*AsClass()) << ")";
}
}
--
2.17.0

View file

@ -0,0 +1,79 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Marshall <p.s.marshall0@gmail.com>
Date: Tue, 4 Sep 2018 15:48:15 +0200
Subject: deps: backport detailed line info for CPU profiler
[cpu-profiler] Add flag to always generate accurate line info.
https://chromium.googlesource.com/v8/v8/+/
56baf56790de439b3f69e887e94beb3b301ed77c
[cpu-profiler] Turn on detailed line info for optimized code
https://chromium.googlesource.com/v8/v8/+/
84894ce6d2af7feb9e1f5574409355120887326c
[cpu-profiler] Separate the flags for generating extra line information
https://chromium.googlesource.com/v8/v8/+/
30ff6719db441cc7ef220d449970cc169067e256
PR-URL: https://github.com/nodejs/node/pull/22688
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 052869f3081ed662ced727778fefe11231aae6e5..4d5aa6f885465865e0b29c0cd26bcca41571f0bd 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -1243,6 +1243,9 @@ DEFINE_BOOL(log_function_events, false,
DEFINE_BOOL(prof, false,
"Log statistical profiling information (implies --log-code).")
+DEFINE_BOOL(detailed_line_info, true,
+ "Always generate detailed line information for CPU profiling.")
+
#if defined(ANDROID)
// Phones and tablets have processors that are much slower than desktop
// and laptop computers for which current heuristics are tuned.
diff --git a/src/isolate.cc b/src/isolate.cc
index b0a970305e9d4df8257d1e2a29c79d134896b220..b33b713672a6d471652a1b9c1fc508f15278e1cb 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -3247,6 +3247,10 @@ bool Isolate::use_optimizer() {
!is_precise_count_code_coverage() && !is_block_count_code_coverage();
}
+bool Isolate::NeedsDetailedOptimizedCodeLineInfo() const {
+ return NeedsSourcePositionsForProfiling() || FLAG_detailed_line_info;
+}
+
bool Isolate::NeedsSourcePositionsForProfiling() const {
return FLAG_trace_deopt || FLAG_trace_turbo || FLAG_trace_turbo_graph ||
FLAG_turbo_profiling || FLAG_perf_prof || is_profiling() ||
diff --git a/src/isolate.h b/src/isolate.h
index 09aaf996849017c8626118a2cae8adec1ca18c2d..d94c0fde147f50764171c5a2896921c9811fd0b3 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1044,6 +1044,8 @@ class Isolate : private HiddenFactory {
bool NeedsSourcePositionsForProfiling() const;
+ bool NeedsDetailedOptimizedCodeLineInfo() const;
+
bool is_best_effort_code_coverage() const {
return code_coverage_mode() == debug::Coverage::kBestEffort;
}
diff --git a/src/optimized-compilation-info.cc b/src/optimized-compilation-info.cc
index 09b8a0edeae734d5ad9df8666c2bee4cdcebb3f1..77730919f14dc2545b88d140478d7ac05e6db0b0 100644
--- a/src/optimized-compilation-info.cc
+++ b/src/optimized-compilation-info.cc
@@ -38,7 +38,7 @@ OptimizedCompilationInfo::OptimizedCompilationInfo(
// Collect source positions for optimized code when profiling or if debugger
// is active, to be able to get more precise source positions at the price of
// more memory consumption.
- if (isolate->NeedsSourcePositionsForProfiling()) {
+ if (isolate->NeedsDetailedOptimizedCodeLineInfo()) {
MarkAsSourcePositionsEnabled();
}
--
2.17.0

View file

@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matheus Marchini <matheus@sthima.com>
Date: Wed, 1 Aug 2018 15:09:51 -0300
Subject: deps: cherry-pick 09bca09 from upstream V8
Original commit message:
[postmortem] add ScopeInfo and Context types
The metadata introduced in this patch will be useful for postmortem
tools to inspect Contexts and ScopeInfos (see
https://github.com/nodejs/llnode/issues/211).
R=bmeurer@google.com, yangguo@google.com
Change-Id: I927fcab4014d128bd782046c1ecb9ee045723e95
Reviewed-on: https://chromium-review.googlesource.com/1153858
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54768}
Refs: https://github.com/v8/v8/commit/09bca095e38d6e4770ae48e174f59d33c
PR-URL: https://github.com/nodejs/node/pull/22068
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
diff --git a/BUILD.gn b/BUILD.gn
index 4c8c8acd593c8151798a5187c44f56fee3f07977..443694d88075d59d6e8db7fa4bedc3a812fdafc4 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -852,6 +852,7 @@ action("postmortem-metadata") {
"src/objects/js-regexp-string-iterator.h",
"src/objects/map.h",
"src/objects/map-inl.h",
+ "src/objects/scope-info.h",
"src/objects/script.h",
"src/objects/script-inl.h",
"src/objects/shared-function-info.h",
diff --git a/tools/gen-postmortem-metadata.py b/tools/gen-postmortem-metadata.py
index d8ef7b4a158a9c6d5d157169defb47bb82683023..8191c8152f5942858cc3a305bdee72d74c4e55e9 100644
--- a/tools/gen-postmortem-metadata.py
+++ b/tools/gen-postmortem-metadata.py
@@ -58,6 +58,9 @@ consts_misc = [
{ 'name': 'APIObjectType', 'value': 'JS_API_OBJECT_TYPE' },
{ 'name': 'SpecialAPIObjectType', 'value': 'JS_SPECIAL_API_OBJECT_TYPE' },
+ { 'name': 'FirstContextType', 'value': 'FIRST_CONTEXT_TYPE' },
+ { 'name': 'LastContextType', 'value': 'LAST_CONTEXT_TYPE' },
+
{ 'name': 'IsNotStringMask', 'value': 'kIsNotStringMask' },
{ 'name': 'StringTag', 'value': 'kStringTag' },
@@ -282,7 +285,7 @@ extras_accessors = [
expected_classes = [
'ConsString', 'FixedArray', 'HeapNumber', 'JSArray', 'JSFunction',
'JSObject', 'JSRegExp', 'JSValue', 'Map', 'Oddball', 'Script',
- 'SeqOneByteString', 'SharedFunctionInfo'
+ 'SeqOneByteString', 'SharedFunctionInfo', 'ScopeInfo'
];
--
2.17.0

View file

@ -0,0 +1,498 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com>
Date: Wed, 25 Jul 2018 20:03:35 +0200
Subject: deps: cherry-pick 0dd3390 from upstream V8
Original commit message:
Reland "[builtins] Add %IsTraceCategoryEnabled and %Trace builtins"
This is a reland of 8d4572a22b5d2fa0547195bcc40baa18b7565386
Original change's description:
> [builtins] Add %IsTraceCategoryEnabled and %Trace builtins
>
> Adds the builtin Trace and IsTraceCategoryEnabled functions
> exposed via extra bindings. These are intended to use by
> embedders to allow basic trace event support from JavaScript.
>
> ```js
> isTraceCategoryEnabled('v8.some-category')
>
> trace('e'.charCodeAt(0), 'v8.some-category',
> 'Foo', 0, { abc: 'xyz'})
> ```
>
> Bug: v8:7851
> Change-Id: I7bfb9bb059efdf87d92a56a0aae326650730c250
> Reviewed-on: https://chromium-review.googlesource.com/1103294
> Commit-Queue: Yang Guo <yangguo@chromium.org>
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Reviewed-by: Fadi Meawad <fmeawad@chromium.org>
> Reviewed-by: Camillo Bruni <cbruni@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#54121}
TBR=cbruni@chromium.org
Bug: v8:7851
Change-Id: Id063754b2834b3b6a2b2654e76e8637bcd6aa5f8
Reviewed-on: https://chromium-review.googlesource.com/1137071
Commit-Queue: Yang Guo <yangguo@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54532}
Refs: https://github.com/v8/v8/commit/0dd33901a16c7c64290b7e7ddf13945b773c5d79
PR-URL: https://github.com/nodejs/node/pull/21983
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
diff --git a/AUTHORS b/AUTHORS
index b9391a0d28499985ae6a5b93394c6d5afc9ea1cd..3873f0ca6816ef28dbbaf63944d66f278c9aff4b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -87,6 +87,7 @@ Jan de Mooij <jandemooij@gmail.com>
Jan Krems <jan.krems@gmail.com>
Jay Freeman <saurik@saurik.com>
James Pike <g00gle@chilon.net>
+James M Snell <jasnell@gmail.com>
Jianghua Yang <jianghua.yjh@alibaba-inc.com>
Joel Stanley <joel@jms.id.au>
Johan Bergström <johan@bergstroem.nu>
diff --git a/BUILD.gn b/BUILD.gn
index 1e31acb2771e6e4137524ff4ae6a9e962092cd90..4c8c8acd593c8151798a5187c44f56fee3f07977 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1588,6 +1588,7 @@ v8_source_set("v8_base") {
"src/builtins/builtins-sharedarraybuffer.cc",
"src/builtins/builtins-string.cc",
"src/builtins/builtins-symbol.cc",
+ "src/builtins/builtins-trace.cc",
"src/builtins/builtins-typed-array.cc",
"src/builtins/builtins-utils.h",
"src/builtins/builtins.cc",
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 6723f3d5d463327cada8477626562a3c27c3e69f..656650cd6498dd82de02e583f5b83ae04a58b0e7 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -5077,6 +5077,15 @@ bool Genesis::InstallExtraNatives() {
Handle<JSObject> extras_binding =
factory()->NewJSObject(isolate()->object_function());
+
+ // binding.isTraceCategoryEnabled(category)
+ SimpleInstallFunction(isolate(), extras_binding, "isTraceCategoryEnabled",
+ Builtins::kIsTraceCategoryEnabled, 1, true);
+
+ // binding.trace(phase, category, name, id, data)
+ SimpleInstallFunction(isolate(), extras_binding, "trace", Builtins::kTrace, 5,
+ true);
+
native_context()->set_extras_binding_object(*extras_binding);
for (int i = ExtraNatives::GetDebuggerCount();
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 46b02d88d817199620f02afdac753f12f4829e8f..2d7c780c709c55da93797e45e4352598745d0fd0 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -1308,7 +1308,11 @@ namespace internal {
ASM(CallApiGetter) \
ASM(DoubleToI) \
TFC(GetProperty, GetProperty, 1) \
- ASM(MathPowInternal)
+ ASM(MathPowInternal) \
+ \
+ /* Trace */ \
+ CPP(IsTraceCategoryEnabled) \
+ CPP(Trace)
#ifdef V8_INTL_SUPPORT
#define BUILTIN_LIST(CPP, API, TFJ, TFC, TFS, TFH, ASM) \
diff --git a/src/builtins/builtins-trace.cc b/src/builtins/builtins-trace.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cd0f5a77d0a6177069bfa0bd83515f9ded92b491
--- /dev/null
+++ b/src/builtins/builtins-trace.cc
@@ -0,0 +1,191 @@
+// Copyright 2018 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/api.h"
+#include "src/builtins/builtins-utils.h"
+#include "src/builtins/builtins.h"
+#include "src/counters.h"
+#include "src/json-stringifier.h"
+#include "src/objects-inl.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+using v8::tracing::TracedValue;
+
+#define MAX_STACK_LENGTH 100
+
+class MaybeUtf8 {
+ public:
+ explicit MaybeUtf8(Isolate* isolate, Handle<String> string) : buf_(data_) {
+ string = String::Flatten(isolate, string);
+ int len;
+ if (string->IsOneByteRepresentation()) {
+ // Technically this allows unescaped latin1 characters but the trace
+ // events mechanism currently does the same and the current consuming
+ // tools are tolerant of it. A more correct approach here would be to
+ // escape non-ascii characters but this is easier and faster.
+ len = string->length();
+ AllocateSufficientSpace(len);
+ if (len > 0) {
+ // Why copy? Well, the trace event mechanism requires null-terminated
+ // strings, the bytes we get from SeqOneByteString are not. buf_ is
+ // guaranteed to be null terminated.
+ memcpy(buf_, Handle<SeqOneByteString>::cast(string)->GetChars(), len);
+ }
+ } else {
+ Local<v8::String> local = Utils::ToLocal(string);
+ len = local->Utf8Length();
+ AllocateSufficientSpace(len);
+ if (len > 0) {
+ local->WriteUtf8(reinterpret_cast<char*>(buf_));
+ }
+ }
+ buf_[len] = 0;
+ }
+ const char* operator*() const { return reinterpret_cast<const char*>(buf_); }
+
+ private:
+ void AllocateSufficientSpace(int len) {
+ if (len + 1 > MAX_STACK_LENGTH) {
+ allocated_.reset(new uint8_t[len + 1]);
+ buf_ = allocated_.get();
+ }
+ }
+
+ // In the most common cases, the buffer here will be stack allocated.
+ // A heap allocation will only occur if the data is more than MAX_STACK_LENGTH
+ // Given that this is used primarily for trace event categories and names,
+ // the MAX_STACK_LENGTH should be more than enough.
+ uint8_t* buf_;
+ uint8_t data_[MAX_STACK_LENGTH];
+ std::unique_ptr<uint8_t> allocated_;
+};
+
+class JsonTraceValue : public ConvertableToTraceFormat {
+ public:
+ explicit JsonTraceValue(Isolate* isolate, Handle<String> object) {
+ // object is a JSON string serialized using JSON.stringify() from within
+ // the BUILTIN(Trace) method. This may (likely) contain UTF8 values so
+ // to grab the appropriate buffer data we have to serialize it out. We
+ // hold on to the bits until the AppendAsTraceFormat method is called.
+ MaybeUtf8 data(isolate, object);
+ data_ = *data;
+ }
+
+ void AppendAsTraceFormat(std::string* out) const override { *out += data_; }
+
+ private:
+ std::string data_;
+};
+
+const uint8_t* GetCategoryGroupEnabled(Isolate* isolate,
+ Handle<String> string) {
+ MaybeUtf8 category(isolate, string);
+ return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(*category);
+}
+
+#undef MAX_STACK_LENGTH
+
+} // namespace
+
+// Builins::kIsTraceCategoryEnabled(category) : bool
+BUILTIN(IsTraceCategoryEnabled) {
+ HandleScope scope(isolate);
+ Handle<Object> category = args.atOrUndefined(isolate, 1);
+ if (!category->IsString()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kTraceEventCategoryError));
+ }
+ return isolate->heap()->ToBoolean(
+ *GetCategoryGroupEnabled(isolate, Handle<String>::cast(category)));
+}
+
+// Builtins::kTrace(phase, category, name, id, data) : bool
+BUILTIN(Trace) {
+ HandleScope handle_scope(isolate);
+
+ Handle<Object> phase_arg = args.atOrUndefined(isolate, 1);
+ Handle<Object> category = args.atOrUndefined(isolate, 2);
+ Handle<Object> name_arg = args.atOrUndefined(isolate, 3);
+ Handle<Object> id_arg = args.atOrUndefined(isolate, 4);
+ Handle<Object> data_arg = args.atOrUndefined(isolate, 5);
+
+ const uint8_t* category_group_enabled =
+ GetCategoryGroupEnabled(isolate, Handle<String>::cast(category));
+
+ // Exit early if the category group is not enabled.
+ if (!*category_group_enabled) {
+ return ReadOnlyRoots(isolate).false_value();
+ }
+
+ if (!phase_arg->IsNumber()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kTraceEventPhaseError));
+ }
+ if (!category->IsString()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kTraceEventCategoryError));
+ }
+ if (!name_arg->IsString()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kTraceEventNameError));
+ }
+
+ uint32_t flags = TRACE_EVENT_FLAG_COPY;
+ int32_t id = 0;
+ if (!id_arg->IsNullOrUndefined(isolate)) {
+ if (!id_arg->IsNumber()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kTraceEventIDError));
+ }
+ flags |= TRACE_EVENT_FLAG_HAS_ID;
+ id = DoubleToInt32(id_arg->Number());
+ }
+
+ Handle<String> name_str = Handle<String>::cast(name_arg);
+ if (name_str->length() == 0) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kTraceEventNameLengthError));
+ }
+ MaybeUtf8 name(isolate, name_str);
+
+ // We support passing one additional trace event argument with the
+ // name "data". Any JSON serializable value may be passed.
+ static const char* arg_name = "data";
+ int32_t num_args = 0;
+ uint8_t arg_type;
+ uint64_t arg_value;
+
+ if (!data_arg->IsUndefined(isolate)) {
+ // Serializes the data argument as a JSON string, which is then
+ // copied into an object. This eliminates duplicated code but
+ // could have perf costs. It is also subject to all the same
+ // limitations as JSON.stringify() as it relates to circular
+ // references and value limitations (e.g. BigInt is not supported).
+ JsonStringifier stringifier(isolate);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ stringifier.Stringify(data_arg, isolate->factory()->undefined_value(),
+ isolate->factory()->undefined_value()));
+ std::unique_ptr<JsonTraceValue> traced_value;
+ traced_value.reset(
+ new JsonTraceValue(isolate, Handle<String>::cast(result)));
+ tracing::SetTraceValue(std::move(traced_value), &arg_type, &arg_value);
+ num_args++;
+ }
+
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ static_cast<char>(DoubleToInt32(phase_arg->Number())),
+ category_group_enabled, *name, tracing::kGlobalScope, id, tracing::kNoId,
+ num_args, &arg_name, &arg_type, &arg_value, flags);
+
+ return ReadOnlyRoots(isolate).true_value();
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc
index 0dd23037723ff4ebf1158f7ecd4f813ed53e18e0..d263fa45a9a4ea3f2604f8c47085a39963c12a91 100644
--- a/src/debug/debug-evaluate.cc
+++ b/src/debug/debug-evaluate.cc
@@ -567,6 +567,9 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
case Builtins::kArrayMap:
case Builtins::kArrayReduce:
case Builtins::kArrayReduceRight:
+ // Trace builtins.
+ case Builtins::kIsTraceCategoryEnabled:
+ case Builtins::kTrace:
// TypedArray builtins.
case Builtins::kTypedArrayConstructor:
case Builtins::kTypedArrayPrototypeBuffer:
diff --git a/src/messages.h b/src/messages.h
index 1d1a07d7b696f32e7c7d56fceda4739bdf30b8ea..68078bb3736023e688a764709566bbc334e77791 100644
--- a/src/messages.h
+++ b/src/messages.h
@@ -757,7 +757,14 @@ class ErrorUtils : public AllStatic {
T(DataCloneDeserializationError, "Unable to deserialize cloned data.") \
T(DataCloneDeserializationVersionError, \
"Unable to deserialize cloned data due to invalid or unsupported " \
- "version.")
+ "version.") \
+ /* Builtins-Trace Errors */ \
+ T(TraceEventCategoryError, "Trace event category must be a string.") \
+ T(TraceEventNameError, "Trace event name must be a string.") \
+ T(TraceEventNameLengthError, \
+ "Trace event name must not be an empty string.") \
+ T(TraceEventPhaseError, "Trace event phase must be a number.") \
+ T(TraceEventIDError, "Trace event id must be a number.")
class MessageTemplate {
public:
diff --git a/test/cctest/test-trace-event.cc b/test/cctest/test-trace-event.cc
index 7b736b907dd9aebc8c0c505ce5a6542b79050c69..47545af37f89c0fcd648293a5bb1c70a5e6360b0 100644
--- a/test/cctest/test-trace-event.cc
+++ b/test/cctest/test-trace-event.cc
@@ -75,7 +75,7 @@ class MockTracingController : public v8::TracingController {
const char* name, uint64_t handle) override {}
const uint8_t* GetCategoryGroupEnabled(const char* name) override {
- if (strcmp(name, "v8-cat")) {
+ if (strncmp(name, "v8-cat", 6)) {
static uint8_t no = 0;
return &no;
} else {
@@ -282,3 +282,135 @@ TEST(TestEventWithTimestamp) {
CHECK_EQ(20683, GET_TRACE_OBJECT(3)->timestamp);
CHECK_EQ(32832, GET_TRACE_OBJECT(4)->timestamp);
}
+
+TEST(BuiltinsIsTraceCategoryEnabled) {
+ CcTest::InitializeVM();
+ MockTracingPlatform platform;
+
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
+ CHECK(!binding.IsEmpty());
+
+ auto undefined = v8::Undefined(isolate);
+ auto isTraceCategoryEnabled =
+ binding->Get(env.local(), v8_str("isTraceCategoryEnabled"))
+ .ToLocalChecked()
+ .As<v8::Function>();
+
+ {
+ // Test with an enabled category
+ v8::Local<v8::Value> argv[] = {v8_str("v8-cat")};
+ auto result = isTraceCategoryEnabled->Call(env.local(), undefined, 1, argv)
+ .ToLocalChecked()
+ .As<v8::Boolean>();
+
+ CHECK(result->BooleanValue());
+ }
+
+ {
+ // Test with a disabled category
+ v8::Local<v8::Value> argv[] = {v8_str("cat")};
+ auto result = isTraceCategoryEnabled->Call(env.local(), undefined, 1, argv)
+ .ToLocalChecked()
+ .As<v8::Boolean>();
+
+ CHECK(!result->BooleanValue());
+ }
+
+ {
+ // Test with an enabled utf8 category
+ v8::Local<v8::Value> argv[] = {v8_str("v8-cat\u20ac")};
+ auto result = isTraceCategoryEnabled->Call(env.local(), undefined, 1, argv)
+ .ToLocalChecked()
+ .As<v8::Boolean>();
+
+ CHECK(result->BooleanValue());
+ }
+}
+
+TEST(BuiltinsTrace) {
+ CcTest::InitializeVM();
+ MockTracingPlatform platform;
+
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
+ CHECK(!binding.IsEmpty());
+
+ auto undefined = v8::Undefined(isolate);
+ auto trace = binding->Get(env.local(), v8_str("trace"))
+ .ToLocalChecked()
+ .As<v8::Function>();
+
+ // Test with disabled category
+ {
+ v8::Local<v8::String> category = v8_str("cat");
+ v8::Local<v8::String> name = v8_str("name");
+ v8::Local<v8::Value> argv[] = {
+ v8::Integer::New(isolate, 'b'), // phase
+ category, name, v8::Integer::New(isolate, 0), // id
+ undefined // data
+ };
+ auto result = trace->Call(env.local(), undefined, 5, argv)
+ .ToLocalChecked()
+ .As<v8::Boolean>();
+
+ CHECK(!result->BooleanValue());
+ CHECK_EQ(0, GET_TRACE_OBJECTS_LIST->size());
+ }
+
+ // Test with enabled category
+ {
+ v8::Local<v8::String> category = v8_str("v8-cat");
+ v8::Local<v8::String> name = v8_str("name");
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ v8::Local<v8::Object> data = v8::Object::New(isolate);
+ data->Set(context, v8_str("foo"), v8_str("bar")).FromJust();
+ v8::Local<v8::Value> argv[] = {
+ v8::Integer::New(isolate, 'b'), // phase
+ category, name, v8::Integer::New(isolate, 123), // id
+ data // data arg
+ };
+ auto result = trace->Call(env.local(), undefined, 5, argv)
+ .ToLocalChecked()
+ .As<v8::Boolean>();
+
+ CHECK(result->BooleanValue());
+ CHECK_EQ(1, GET_TRACE_OBJECTS_LIST->size());
+
+ CHECK_EQ(123, GET_TRACE_OBJECT(0)->id);
+ CHECK_EQ('b', GET_TRACE_OBJECT(0)->phase);
+ CHECK_EQ("name", GET_TRACE_OBJECT(0)->name);
+ CHECK_EQ(1, GET_TRACE_OBJECT(0)->num_args);
+ }
+
+ // Test with enabled utf8 category
+ {
+ v8::Local<v8::String> category = v8_str("v8-cat\u20ac");
+ v8::Local<v8::String> name = v8_str("name\u20ac");
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ v8::Local<v8::Object> data = v8::Object::New(isolate);
+ data->Set(context, v8_str("foo"), v8_str("bar")).FromJust();
+ v8::Local<v8::Value> argv[] = {
+ v8::Integer::New(isolate, 'b'), // phase
+ category, name, v8::Integer::New(isolate, 123), // id
+ data // data arg
+ };
+ auto result = trace->Call(env.local(), undefined, 5, argv)
+ .ToLocalChecked()
+ .As<v8::Boolean>();
+
+ CHECK(result->BooleanValue());
+ CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->size());
+
+ CHECK_EQ(123, GET_TRACE_OBJECT(1)->id);
+ CHECK_EQ('b', GET_TRACE_OBJECT(1)->phase);
+ CHECK_EQ("name\u20ac", GET_TRACE_OBJECT(1)->name);
+ CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args);
+ }
+}
--
2.17.0

View file

@ -0,0 +1,77 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ali Ijaz Sheikh <ofrobots@google.com>
Date: Tue, 11 Sep 2018 15:40:28 -0700
Subject: deps: cherry-pick 2363cdf from upstream V8
Original commit message:
[tracing] do not add traces when disabled
https://github.com/nodejs/node/issues/21038
Change-Id: Ic4c9f403b5e54a97d3170b2311dd5aab8c8357c8
Reviewed-on: https://chromium-review.googlesource.com/1217726
Commit-Queue: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55809}
Refs: https://github.com/v8/v8/commit/2363cdfefeb643285cbe8593b7c17d80e5d06cd9
PR-URL: https://github.com/nodejs/node/pull/22812
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com>
diff --git a/src/libplatform/tracing/tracing-controller.cc b/src/libplatform/tracing/tracing-controller.cc
index b4aa7baf724d4f29b4df08f3b57fdc018f6a32a7..e0a6a1234c597071b327d051c7da1d2b784529e5 100644
--- a/src/libplatform/tracing/tracing-controller.cc
+++ b/src/libplatform/tracing/tracing-controller.cc
@@ -63,13 +63,15 @@ uint64_t TracingController::AddTraceEvent(
const uint64_t* arg_values,
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
unsigned int flags) {
- uint64_t handle;
- TraceObject* trace_object = trace_buffer_->AddTraceEvent(&handle);
- if (trace_object) {
- trace_object->Initialize(
- phase, category_enabled_flag, name, scope, id, bind_id, num_args,
- arg_names, arg_types, arg_values, arg_convertables, flags,
- CurrentTimestampMicroseconds(), CurrentCpuTimestampMicroseconds());
+ uint64_t handle = 0;
+ if (mode_ != DISABLED) {
+ TraceObject* trace_object = trace_buffer_->AddTraceEvent(&handle);
+ if (trace_object) {
+ trace_object->Initialize(
+ phase, category_enabled_flag, name, scope, id, bind_id, num_args,
+ arg_names, arg_types, arg_values, arg_convertables, flags,
+ CurrentTimestampMicroseconds(), CurrentCpuTimestampMicroseconds());
+ }
}
return handle;
}
@@ -81,13 +83,15 @@ uint64_t TracingController::AddTraceEventWithTimestamp(
const uint64_t* arg_values,
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
unsigned int flags, int64_t timestamp) {
- uint64_t handle;
- TraceObject* trace_object = trace_buffer_->AddTraceEvent(&handle);
- if (trace_object) {
- trace_object->Initialize(phase, category_enabled_flag, name, scope, id,
- bind_id, num_args, arg_names, arg_types,
- arg_values, arg_convertables, flags, timestamp,
- CurrentCpuTimestampMicroseconds());
+ uint64_t handle = 0;
+ if (mode_ != DISABLED) {
+ TraceObject* trace_object = trace_buffer_->AddTraceEvent(&handle);
+ if (trace_object) {
+ trace_object->Initialize(phase, category_enabled_flag, name, scope, id,
+ bind_id, num_args, arg_names, arg_types,
+ arg_values, arg_convertables, flags, timestamp,
+ CurrentCpuTimestampMicroseconds());
+ }
}
return handle;
}
--
2.17.0

View file

@ -0,0 +1,306 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com>
Date: Tue, 4 Sep 2018 21:24:34 +0200
Subject: deps: cherry-pick a8f6869 from upstream V8
Original commit message:
[debug] Fully implement Debug::ArchiveDebug and Debug::RestoreDebug.
I have a project that embeds V8 and uses a single `Isolate` from multiple
threads. The program runs just fine, but sometimes the inspector doesn't
stop on the correct line after stepping over a statement that switches
threads behind the scenes, even though the original thread is restored by
the time the next statement is executed.
After some digging, I discovered that the `Debug::ArchiveDebug` and
`Debug::RestoreDebug` methods, which should be responsible for
saving/restoring this `ThreadLocal` information when switching threads,
currently don't do anything.
This commit implements those methods using MemCopy, in the style of other
Archive/Restore methods in the V8 codebase.
Related: https://groups.google.com/forum/#!topic/v8-users/_Qf2rwljRk8
Note: I believe my employer, Meteor Development Group, has previously
signed the CLA using the group email address google-contrib@meteor.com.
R=yangguo@chromium.org,jgruber@chromium.org
CC=info@bnoordhuis.nl
Bug: v8:7230
Change-Id: Id517c873eb81cd53f7216c7efd441b956cf7f943
Reviewed-on: https://chromium-review.googlesource.com/833260
Commit-Queue: Yang Guo <yangguo@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54902}
Refs: https://github.com/v8/v8/commit/a8f6869177685cfb9c199c454a86f4698c260515
PR-URL: https://github.com/nodejs/node/pull/21983
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
diff --git a/AUTHORS b/AUTHORS
index 3873f0ca6816ef28dbbaf63944d66f278c9aff4b..6179e2230d8011025fa3202327071c5b05fee86f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -32,6 +32,7 @@ Facebook, Inc. <*@fb.com>
Facebook, Inc. <*@oculus.com>
Vewd Software AS <*@vewd.com>
Groupon <*@groupon.com>
+Meteor Development Group <*@meteor.com>
Cloudflare, Inc. <*@cloudflare.com>
Aaron Bieber <deftly@gmail.com>
@@ -49,6 +50,7 @@ Andrei Kashcha <anvaka@gmail.com>
Anna Henningsen <anna@addaleax.net>
Bangfu Tao <bangfu.tao@samsung.com>
Ben Coe <ben@npmjs.com>
+Ben Newman <ben@meteor.com>
Ben Noordhuis <info@bnoordhuis.nl>
Benjamin Tan <demoneaux@gmail.com>
Bert Belder <bertbelder@gmail.com>
diff --git a/src/debug/debug.cc b/src/debug/debug.cc
index 47de9523a50f84bdcf88d35bed7a3602a160b6cd..3877f156efac34279a9f55c0d335468330867380 100644
--- a/src/debug/debug.cc
+++ b/src/debug/debug.cc
@@ -355,19 +355,31 @@ void Debug::ThreadInit() {
char* Debug::ArchiveDebug(char* storage) {
- // Simply reset state. Don't archive anything.
- ThreadInit();
+ MemCopy(storage, reinterpret_cast<char*>(&thread_local_),
+ ArchiveSpacePerThread());
return storage + ArchiveSpacePerThread();
}
-
char* Debug::RestoreDebug(char* storage) {
- // Simply reset state. Don't restore anything.
- ThreadInit();
+ MemCopy(reinterpret_cast<char*>(&thread_local_), storage,
+ ArchiveSpacePerThread());
+
+ // Enter the debugger.
+ DebugScope debug_scope(this);
+
+ // Clear any one-shot breakpoints that may have been set by the other
+ // thread, and reapply breakpoints for this thread.
+ ClearOneShot();
+
+ if (thread_local_.last_step_action_ != StepNone) {
+ // Reset the previous step action for this thread.
+ PrepareStep(thread_local_.last_step_action_);
+ }
+
return storage + ArchiveSpacePerThread();
}
-int Debug::ArchiveSpacePerThread() { return 0; }
+int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
void Debug::Iterate(RootVisitor* v) {
v->VisitRootPointer(Root::kDebug, nullptr, &thread_local_.return_value_);
diff --git a/src/debug/debug.h b/src/debug/debug.h
index 31881fe10696abdfc01b4503f78e3778e6297392..13844769c1434955b8c65b762cce771a360cc7f5 100644
--- a/src/debug/debug.h
+++ b/src/debug/debug.h
@@ -314,6 +314,7 @@ class Debug {
static int ArchiveSpacePerThread();
void FreeThreadResources() { }
void Iterate(RootVisitor* v);
+ void InitThread(const ExecutionAccess& lock) { ThreadInit(); }
bool CheckExecutionState() { return is_active() && break_id() != 0; }
diff --git a/src/v8threads.cc b/src/v8threads.cc
index db927010ef174916921d5ee03b1f2d1df3269e8a..0fb333c1f37572e688560aa7de7f6e478364b6b6 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -45,7 +45,7 @@ void Locker::Initialize(v8::Isolate* isolate) {
} else {
internal::ExecutionAccess access(isolate_);
isolate_->stack_guard()->ClearThread(access);
- isolate_->stack_guard()->InitThread(access);
+ isolate_->thread_manager()->InitThread(access);
}
}
DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
@@ -95,6 +95,10 @@ Unlocker::~Unlocker() {
namespace internal {
+void ThreadManager::InitThread(const ExecutionAccess& lock) {
+ isolate_->stack_guard()->InitThread(lock);
+ isolate_->debug()->InitThread(lock);
+}
bool ThreadManager::RestoreThread() {
DCHECK(IsLockedByCurrentThread());
@@ -127,7 +131,7 @@ bool ThreadManager::RestoreThread() {
isolate_->FindPerThreadDataForThisThread();
if (per_thread == nullptr || per_thread->thread_state() == nullptr) {
// This is a new thread.
- isolate_->stack_guard()->InitThread(access);
+ InitThread(access);
return false;
}
ThreadState* state = per_thread->thread_state();
diff --git a/src/v8threads.h b/src/v8threads.h
index bb87afea7d849766e913fbd137142d0d0144ad55..7fde0c9ec494e77dbbcf8bdbeb3817ab1a9d4c00 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -67,6 +67,7 @@ class ThreadManager {
void Lock();
void Unlock();
+ void InitThread(const ExecutionAccess&);
void ArchiveThread();
bool RestoreThread();
void FreeThreadResources();
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index d3c10822ffe49f46ab829aa0ab1e035c4393fa1e..7430fbf06b802e54233edfb94196a806e2b68d6b 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -3717,6 +3717,133 @@ TEST(DebugBreakOffThreadTerminate) {
CHECK(try_catch.HasTerminated());
}
+class ArchiveRestoreThread : public v8::base::Thread,
+ public v8::debug::DebugDelegate {
+ public:
+ ArchiveRestoreThread(v8::Isolate* isolate, int spawn_count)
+ : Thread(Options("ArchiveRestoreThread")),
+ isolate_(isolate),
+ debug_(reinterpret_cast<i::Isolate*>(isolate_)->debug()),
+ spawn_count_(spawn_count),
+ break_count_(0) {}
+
+ virtual void Run() {
+ v8::Locker locker(isolate_);
+ isolate_->Enter();
+
+ v8::HandleScope scope(isolate_);
+ v8::Local<v8::Context> context = v8::Context::New(isolate_);
+ v8::Context::Scope context_scope(context);
+
+ v8::Local<v8::Function> test = CompileFunction(isolate_,
+ "function test(n) {\n"
+ " debugger;\n"
+ " return n + 1;\n"
+ "}\n",
+ "test");
+
+ debug_->SetDebugDelegate(this);
+ v8::internal::DisableBreak enable_break(debug_, false);
+
+ v8::Local<v8::Value> args[1] = {v8::Integer::New(isolate_, spawn_count_)};
+
+ int result = test->Call(context, context->Global(), 1, args)
+ .ToLocalChecked()
+ ->Int32Value(context)
+ .FromJust();
+
+ // Verify that test(spawn_count_) returned spawn_count_ + 1.
+ CHECK_EQ(spawn_count_ + 1, result);
+
+ isolate_->Exit();
+ }
+
+ void BreakProgramRequested(v8::Local<v8::Context> context,
+ const std::vector<v8::debug::BreakpointId>&) {
+ auto stack_traces = v8::debug::StackTraceIterator::Create(isolate_);
+ if (!stack_traces->Done()) {
+ v8::debug::Location location = stack_traces->GetSourceLocation();
+
+ i::PrintF("ArchiveRestoreThread #%d hit breakpoint at line %d\n",
+ spawn_count_, location.GetLineNumber());
+
+ switch (location.GetLineNumber()) {
+ case 1: // debugger;
+ CHECK_EQ(break_count_, 0);
+
+ // Attempt to stop on the next line after the first debugger
+ // statement. If debug->{Archive,Restore}Debug() improperly reset
+ // thread-local debug information, the debugger will fail to stop
+ // before the test function returns.
+ debug_->PrepareStep(StepNext);
+
+ // Spawning threads while handling the current breakpoint verifies
+ // that the parent thread correctly archived and restored the
+ // state necessary to stop on the next line. If not, then control
+ // will simply continue past the `return n + 1` statement.
+ MaybeSpawnChildThread();
+
+ break;
+
+ case 2: // return n + 1;
+ CHECK_EQ(break_count_, 1);
+ break;
+
+ default:
+ CHECK(false);
+ }
+ }
+
+ ++break_count_;
+ }
+
+ void MaybeSpawnChildThread() {
+ if (spawn_count_ > 1) {
+ v8::Unlocker unlocker(isolate_);
+
+ // Spawn a thread that spawns a thread that spawns a thread (and so
+ // on) so that the ThreadManager is forced to archive and restore
+ // the current thread.
+ ArchiveRestoreThread child(isolate_, spawn_count_ - 1);
+ child.Start();
+ child.Join();
+
+ // The child thread sets itself as the debug delegate, so we need to
+ // usurp it after the child finishes, or else future breakpoints
+ // will be delegated to a destroyed ArchiveRestoreThread object.
+ debug_->SetDebugDelegate(this);
+
+ // This is the most important check in this test, since
+ // child.GetBreakCount() will return 1 if the debugger fails to stop
+ // on the `return n + 1` line after the grandchild thread returns.
+ CHECK_EQ(child.GetBreakCount(), 2);
+ }
+ }
+
+ int GetBreakCount() { return break_count_; }
+
+ private:
+ v8::Isolate* isolate_;
+ v8::internal::Debug* debug_;
+ const int spawn_count_;
+ int break_count_;
+};
+
+TEST(DebugArchiveRestore) {
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
+
+ ArchiveRestoreThread thread(isolate, 5);
+ // Instead of calling thread.Start() and thread.Join() here, we call
+ // thread.Run() directly, to make sure we exercise archive/restore
+ // logic on the *current* thread as well as other threads.
+ thread.Run();
+ CHECK_EQ(thread.GetBreakCount(), 2);
+
+ isolate->Dispose();
+}
+
class DebugEventExpectNoException : public v8::debug::DebugDelegate {
public:
void ExceptionThrown(v8::Local<v8::Context> paused_context,
--
2.17.0

View file

@ -0,0 +1,711 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com>
Date: Tue, 4 Sep 2018 21:22:51 +0200
Subject: deps: cherry-pick ba752ea from upstream V8
Original commit message:
[cpu-profiler] Use instruction start as the key for the CodeMap
Previously we used the start address of the AbstractCode object. This
doesn't make sense for off-heap builtins, where the code isn't contained
in the object itself. It also hides other potential problems - sometimes
the sample.pc is inside the AbstractCode object header - this is
never valid.
There were a few changes necessary to make this happen:
- Change the interface of CodeMoveEvent. Now 'to' and 'from' are both
AbstractCode objects, which is nice because many users were taking
'to' and adding the header offset to it to try and find the
instruction start address. This isn't valid for off-heap builtins.
- Fix a bug in CodeMap::MoveCode where we didn't update the CodeEntry
object to reflect the new instruction_start.
- Rename the 'start' field in all of the CodeEventRecord sub-classes
to make it clear that this is the address of the first instruction.
- Fix the confusion in RecordTickSample between 'tos' and 'pc' which
caused pc_offset to be calculated incorrectly.
Bug: v8:7983
Change-Id: I3e9dddf74e4b2e96a5f031d216ef7008d6f184d1
Reviewed-on: https://chromium-review.googlesource.com/1148457
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54749}
Refs: https://github.com/v8/v8/commit/ba752ea4c50713dff1e94f45a79db3ba968a8d66
PR-URL: https://github.com/nodejs/node/pull/21983
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
diff --git a/src/code-events.h b/src/code-events.h
index 09cd5a62e00beb4320e3e9cb05e07f019f26ab37..ec07a2e107917bce4a3ea3d1f9973ef54f28a2f0 100644
--- a/src/code-events.h
+++ b/src/code-events.h
@@ -83,7 +83,7 @@ class CodeEventListener {
virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0;
virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0;
virtual void RegExpCodeCreateEvent(AbstractCode* code, String* source) = 0;
- virtual void CodeMoveEvent(AbstractCode* from, Address to) = 0;
+ virtual void CodeMoveEvent(AbstractCode* from, AbstractCode* to) = 0;
virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0;
virtual void CodeMovingGCEvent() = 0;
virtual void CodeDisableOptEvent(AbstractCode* code,
@@ -154,7 +154,7 @@ class CodeEventDispatcher {
void RegExpCodeCreateEvent(AbstractCode* code, String* source) {
CODE_EVENT_DISPATCH(RegExpCodeCreateEvent(code, source));
}
- void CodeMoveEvent(AbstractCode* from, Address to) {
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) {
CODE_EVENT_DISPATCH(CodeMoveEvent(from, to));
}
void SharedFunctionInfoMoveEvent(Address from, Address to) {
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
index 48ae74bc5d472a7136ee660af6f100f1f6858bad..2170568e261cbc927bbf217fb67c65dd9e9f191c 100644
--- a/src/heap/mark-compact.cc
+++ b/src/heap/mark-compact.cc
@@ -1149,7 +1149,7 @@ class ProfilingMigrationObserver final : public MigrationObserver {
int size) final {
if (dest == CODE_SPACE || (dest == OLD_SPACE && dst->IsBytecodeArray())) {
PROFILE(heap_->isolate(),
- CodeMoveEvent(AbstractCode::cast(src), dst->address()));
+ CodeMoveEvent(AbstractCode::cast(src), AbstractCode::cast(dst)));
}
heap_->OnMoveEvent(dst, src, size);
}
diff --git a/src/log.cc b/src/log.cc
index 77d68ef94eb6d5f41e881d434e815a28c121410c..f19897b27b14e3cd96e4b8e91d729981cd09113d 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -270,7 +270,7 @@ class PerfBasicLogger : public CodeEventLogger {
explicit PerfBasicLogger(Isolate* isolate);
~PerfBasicLogger() override;
- void CodeMoveEvent(AbstractCode* from, Address to) override {}
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override {}
void CodeDisableOptEvent(AbstractCode* code,
SharedFunctionInfo* shared) override {}
@@ -496,7 +496,7 @@ class LowLevelLogger : public CodeEventLogger {
LowLevelLogger(Isolate* isolate, const char* file_name);
~LowLevelLogger() override;
- void CodeMoveEvent(AbstractCode* from, Address to) override;
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override;
void CodeDisableOptEvent(AbstractCode* code,
SharedFunctionInfo* shared) override {}
void SnapshotPositionEvent(HeapObject* obj, int pos);
@@ -615,11 +615,10 @@ void LowLevelLogger::LogRecordedBuffer(const wasm::WasmCode* code,
code->instructions().length());
}
-void LowLevelLogger::CodeMoveEvent(AbstractCode* from, Address to) {
+void LowLevelLogger::CodeMoveEvent(AbstractCode* from, AbstractCode* to) {
CodeMoveStruct event;
event.from_address = from->InstructionStart();
- size_t header_size = from->InstructionStart() - from->address();
- event.to_address = to + header_size;
+ event.to_address = to->InstructionStart();
LogWriteStruct(event);
}
@@ -641,7 +640,7 @@ class JitLogger : public CodeEventLogger {
public:
JitLogger(Isolate* isolate, JitCodeEventHandler code_event_handler);
- void CodeMoveEvent(AbstractCode* from, Address to) override;
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override;
void CodeDisableOptEvent(AbstractCode* code,
SharedFunctionInfo* shared) override {}
void AddCodeLinePosInfoEvent(void* jit_handler_data, int pc_offset,
@@ -700,7 +699,7 @@ void JitLogger::LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
code_event_handler_(&event);
}
-void JitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
+void JitLogger::CodeMoveEvent(AbstractCode* from, AbstractCode* to) {
base::LockGuard<base::Mutex> guard(&logger_mutex_);
JitCodeEvent event;
@@ -709,12 +708,7 @@ void JitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
from->IsCode() ? JitCodeEvent::JIT_CODE : JitCodeEvent::BYTE_CODE;
event.code_start = reinterpret_cast<void*>(from->InstructionStart());
event.code_len = from->InstructionSize();
-
- // Calculate the header size.
- const size_t header_size = from->InstructionStart() - from->address();
-
- // Calculate the new start address of the instructions.
- event.new_code_start = reinterpret_cast<void*>(to + header_size);
+ event.new_code_start = reinterpret_cast<void*>(to->InstructionStart());
event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
code_event_handler_(&event);
@@ -1431,9 +1425,10 @@ void Logger::RegExpCodeCreateEvent(AbstractCode* code, String* source) {
msg.WriteToLogFile();
}
-void Logger::CodeMoveEvent(AbstractCode* from, Address to) {
+void Logger::CodeMoveEvent(AbstractCode* from, AbstractCode* to) {
if (!is_listening_to_code_events()) return;
- MoveEventInternal(CodeEventListener::CODE_MOVE_EVENT, from->address(), to);
+ MoveEventInternal(CodeEventListener::CODE_MOVE_EVENT, from->address(),
+ to->address());
}
namespace {
diff --git a/src/log.h b/src/log.h
index 485de0f4d17db71cbbe4170dff0155c4eac0105a..3bc54a5926d35cca6b1544c4f7fce52ae96bca95 100644
--- a/src/log.h
+++ b/src/log.h
@@ -222,7 +222,7 @@ class Logger : public CodeEventListener {
// Emits a code create event for a RegExp.
void RegExpCodeCreateEvent(AbstractCode* code, String* source);
// Emits a code move event.
- void CodeMoveEvent(AbstractCode* from, Address to);
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to);
// Emits a code line info record event.
void CodeLinePosInfoRecordEvent(Address code_start,
ByteArray* source_position_table);
@@ -486,7 +486,7 @@ class ExternalCodeEventListener : public CodeEventListener {
void GetterCallbackEvent(Name* name, Address entry_point) override {}
void SetterCallbackEvent(Name* name, Address entry_point) override {}
void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
- void CodeMoveEvent(AbstractCode* from, Address to) override {}
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override {}
void CodeDisableOptEvent(AbstractCode* code,
SharedFunctionInfo* shared) override {}
void CodeMovingGCEvent() override {}
diff --git a/src/perf-jit.cc b/src/perf-jit.cc
index 3aaa36bc12f4ecdbeeab97f4f73adb482ef14211..f6b2cf401a719fd1696f1ac327bcf04b0800092a 100644
--- a/src/perf-jit.cc
+++ b/src/perf-jit.cc
@@ -420,7 +420,7 @@ void PerfJitLogger::LogWriteUnwindingInfo(Code* code) {
LogWriteBytes(padding_bytes, static_cast<int>(padding_size));
}
-void PerfJitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
+void PerfJitLogger::CodeMoveEvent(AbstractCode* from, AbstractCode* to) {
// We may receive a CodeMove event if a BytecodeArray object moves. Otherwise
// code relocation is not supported.
CHECK(from->IsBytecodeArray());
diff --git a/src/perf-jit.h b/src/perf-jit.h
index d08f4b91ab26ef10a55043c84f4694bd1466496a..3b11cf30c23a7027f356c4ab299f88a5efb8dcc9 100644
--- a/src/perf-jit.h
+++ b/src/perf-jit.h
@@ -41,7 +41,7 @@ class PerfJitLogger : public CodeEventLogger {
explicit PerfJitLogger(Isolate* isolate);
virtual ~PerfJitLogger();
- void CodeMoveEvent(AbstractCode* from, Address to) override;
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override;
void CodeDisableOptEvent(AbstractCode* code,
SharedFunctionInfo* shared) override {}
@@ -120,7 +120,7 @@ class PerfJitLogger : public CodeEventLogger {
public:
explicit PerfJitLogger(Isolate* isolate) : CodeEventLogger(isolate) {}
- void CodeMoveEvent(AbstractCode* from, Address to) override {
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override {
UNIMPLEMENTED();
}
diff --git a/src/profiler/cpu-profiler-inl.h b/src/profiler/cpu-profiler-inl.h
index f6eaa8f8a33e72ca28bf7431747607e0c3764b92..9274bc03c66d860bb0754bf46f4692622861ed0c 100644
--- a/src/profiler/cpu-profiler-inl.h
+++ b/src/profiler/cpu-profiler-inl.h
@@ -16,17 +16,17 @@ namespace v8 {
namespace internal {
void CodeCreateEventRecord::UpdateCodeMap(CodeMap* code_map) {
- code_map->AddCode(start, entry, size);
+ code_map->AddCode(instruction_start, entry, instruction_size);
}
void CodeMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
- code_map->MoveCode(from, to);
+ code_map->MoveCode(from_instruction_start, to_instruction_start);
}
void CodeDisableOptEventRecord::UpdateCodeMap(CodeMap* code_map) {
- CodeEntry* entry = code_map->FindEntry(start);
+ CodeEntry* entry = code_map->FindEntry(instruction_start);
if (entry != nullptr) {
entry->set_bailout_reason(bailout_reason);
}
@@ -34,7 +34,7 @@ void CodeDisableOptEventRecord::UpdateCodeMap(CodeMap* code_map) {
void CodeDeoptEventRecord::UpdateCodeMap(CodeMap* code_map) {
- CodeEntry* entry = code_map->FindEntry(start);
+ CodeEntry* entry = code_map->FindEntry(instruction_start);
if (entry == nullptr) return;
std::vector<CpuProfileDeoptFrame> frames_vector(
deopt_frames, deopt_frames + deopt_frame_count);
@@ -44,7 +44,7 @@ void CodeDeoptEventRecord::UpdateCodeMap(CodeMap* code_map) {
void ReportBuiltinEventRecord::UpdateCodeMap(CodeMap* code_map) {
- CodeEntry* entry = code_map->FindEntry(start);
+ CodeEntry* entry = code_map->FindEntry(instruction_start);
if (!entry) {
// Code objects for builtins should already have been added to the map but
// some of them have been filtered out by CpuProfiler.
diff --git a/src/profiler/cpu-profiler.cc b/src/profiler/cpu-profiler.cc
index 463a30f1842c24a1545b198cb230d99199a33374..555c47f2f4e418b2511c6352b2ef639bee1305f6 100644
--- a/src/profiler/cpu-profiler.cc
+++ b/src/profiler/cpu-profiler.cc
@@ -426,7 +426,7 @@ void CpuProfiler::LogBuiltins() {
CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN);
ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_;
Builtins::Name id = static_cast<Builtins::Name>(i);
- rec->start = builtins->builtin(id)->address();
+ rec->instruction_start = builtins->builtin(id)->InstructionStart();
rec->builtin_id = id;
processor_->Enqueue(evt_rec);
}
diff --git a/src/profiler/cpu-profiler.h b/src/profiler/cpu-profiler.h
index febc15480215b7406a4453b74e0106d9885ee537..78bb3b4a25f4807dbefe22c7a226969b476a21ba 100644
--- a/src/profiler/cpu-profiler.h
+++ b/src/profiler/cpu-profiler.h
@@ -53,9 +53,9 @@ class CodeEventRecord {
class CodeCreateEventRecord : public CodeEventRecord {
public:
- Address start;
+ Address instruction_start;
CodeEntry* entry;
- unsigned size;
+ unsigned instruction_size;
V8_INLINE void UpdateCodeMap(CodeMap* code_map);
};
@@ -63,8 +63,8 @@ class CodeCreateEventRecord : public CodeEventRecord {
class CodeMoveEventRecord : public CodeEventRecord {
public:
- Address from;
- Address to;
+ Address from_instruction_start;
+ Address to_instruction_start;
V8_INLINE void UpdateCodeMap(CodeMap* code_map);
};
@@ -72,7 +72,7 @@ class CodeMoveEventRecord : public CodeEventRecord {
class CodeDisableOptEventRecord : public CodeEventRecord {
public:
- Address start;
+ Address instruction_start;
const char* bailout_reason;
V8_INLINE void UpdateCodeMap(CodeMap* code_map);
@@ -81,7 +81,7 @@ class CodeDisableOptEventRecord : public CodeEventRecord {
class CodeDeoptEventRecord : public CodeEventRecord {
public:
- Address start;
+ Address instruction_start;
const char* deopt_reason;
int deopt_id;
Address pc;
@@ -95,7 +95,7 @@ class CodeDeoptEventRecord : public CodeEventRecord {
class ReportBuiltinEventRecord : public CodeEventRecord {
public:
- Address start;
+ Address instruction_start;
Builtins::Name builtin_id;
V8_INLINE void UpdateCodeMap(CodeMap* code_map);
diff --git a/src/profiler/profile-generator.cc b/src/profiler/profile-generator.cc
index 92619f2fbf3cf52c75b812cb97d4ed4e270fd983..845fe97b6473f2b7d3009964e01f81ff042780e0 100644
--- a/src/profiler/profile-generator.cc
+++ b/src/profiler/profile-generator.cc
@@ -529,6 +529,8 @@ void CodeMap::AddCode(Address addr, CodeEntry* entry, unsigned size) {
ClearCodesInRange(addr, addr + size);
unsigned index = AddCodeEntry(addr, entry);
code_map_.emplace(addr, CodeEntryMapInfo{index, size});
+ DCHECK(entry->instruction_start() == kNullAddress ||
+ addr == entry->instruction_start());
}
void CodeMap::ClearCodesInRange(Address start, Address end) {
@@ -550,8 +552,14 @@ CodeEntry* CodeMap::FindEntry(Address addr) {
auto it = code_map_.upper_bound(addr);
if (it == code_map_.begin()) return nullptr;
--it;
- Address end_address = it->first + it->second.size;
- return addr < end_address ? entry(it->second.index) : nullptr;
+ Address start_address = it->first;
+ Address end_address = start_address + it->second.size;
+ CodeEntry* ret = addr < end_address ? entry(it->second.index) : nullptr;
+ if (ret && ret->instruction_start() != kNullAddress) {
+ DCHECK_EQ(start_address, ret->instruction_start());
+ DCHECK(addr >= start_address && addr < end_address);
+ }
+ return ret;
}
void CodeMap::MoveCode(Address from, Address to) {
@@ -563,6 +571,9 @@ void CodeMap::MoveCode(Address from, Address to) {
DCHECK(from + info.size <= to || to + info.size <= from);
ClearCodesInRange(to, to + info.size);
code_map_.emplace(to, info);
+
+ CodeEntry* entry = code_entries_[info.index].entry;
+ entry->set_instruction_start(to);
}
unsigned CodeMap::AddCodeEntry(Address start, CodeEntry* entry) {
@@ -693,26 +704,29 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
if (sample.pc != nullptr) {
if (sample.has_external_callback && sample.state == EXTERNAL) {
// Don't use PC when in external callback code, as it can point
- // inside callback's code, and we will erroneously report
+ // inside a callback's code, and we will erroneously report
// that a callback calls itself.
stack_trace.push_back(
{FindEntry(reinterpret_cast<Address>(sample.external_callback_entry)),
no_line_info});
} else {
- CodeEntry* pc_entry = FindEntry(reinterpret_cast<Address>(sample.pc));
- // If there is no pc_entry we're likely in native code.
- // Find out, if top of stack was pointing inside a JS function
- // meaning that we have encountered a frameless invocation.
+ Address attributed_pc = reinterpret_cast<Address>(sample.pc);
+ CodeEntry* pc_entry = FindEntry(attributed_pc);
+ // If there is no pc_entry, we're likely in native code. Find out if the
+ // top of the stack (the return address) was pointing inside a JS
+ // function, meaning that we have encountered a frameless invocation.
if (!pc_entry && !sample.has_external_callback) {
- pc_entry = FindEntry(reinterpret_cast<Address>(sample.tos));
+ attributed_pc = reinterpret_cast<Address>(sample.tos);
+ pc_entry = FindEntry(attributed_pc);
}
// If pc is in the function code before it set up stack frame or after the
- // frame was destroyed SafeStackFrameIterator incorrectly thinks that
- // ebp contains return address of the current function and skips caller's
- // frame. Check for this case and just skip such samples.
+ // frame was destroyed, SafeStackFrameIterator incorrectly thinks that
+ // ebp contains the return address of the current function and skips the
+ // caller's frame. Check for this case and just skip such samples.
if (pc_entry) {
- int pc_offset = static_cast<int>(reinterpret_cast<Address>(sample.pc) -
- pc_entry->instruction_start());
+ int pc_offset =
+ static_cast<int>(attributed_pc - pc_entry->instruction_start());
+ DCHECK_GE(pc_offset, 0);
src_line = pc_entry->GetSourceLine(pc_offset);
if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
src_line = pc_entry->line_number();
@@ -744,6 +758,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
// Find out if the entry has an inlining stack associated.
int pc_offset =
static_cast<int>(stack_pos - entry->instruction_start());
+ DCHECK_GE(pc_offset, 0);
const std::vector<std::unique_ptr<CodeEntry>>* inline_stack =
entry->GetInlineStack(pc_offset);
if (inline_stack) {
diff --git a/src/profiler/profile-generator.h b/src/profiler/profile-generator.h
index 3e301a40829ea1acbbd8283bed0d3e43dee679e9..8eef05bcdb382600e987608bdcb9270e3307e998 100644
--- a/src/profiler/profile-generator.h
+++ b/src/profiler/profile-generator.h
@@ -108,7 +108,9 @@ class CodeEntry {
const std::vector<std::unique_ptr<CodeEntry>>* GetInlineStack(
int pc_offset) const;
+ void set_instruction_start(Address start) { instruction_start_ = start; }
Address instruction_start() const { return instruction_start_; }
+
CodeEventListener::LogEventsAndTags tag() const {
return TagField::decode(bit_field_);
}
diff --git a/src/profiler/profiler-listener.cc b/src/profiler/profiler-listener.cc
index 9c29da9ec7972ac9a5fb2a6be8065fe30d7dddd1..f90a2e11d3f3a247fdec39abbb1a04e4d86204e5 100644
--- a/src/profiler/profiler-listener.cc
+++ b/src/profiler/profiler-listener.cc
@@ -24,9 +24,9 @@ ProfilerListener::~ProfilerListener() = default;
void ProfilerListener::CallbackEvent(Name* name, Address entry_point) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = entry_point;
+ rec->instruction_start = entry_point;
rec->entry = NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetName(name));
- rec->size = 1;
+ rec->instruction_size = 1;
DispatchCodeEvent(evt_rec);
}
@@ -34,13 +34,13 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
AbstractCode* code, const char* name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = code->address();
+ rec->instruction_start = code->InstructionStart();
rec->entry = NewCodeEntry(tag, GetName(name), CodeEntry::kEmptyResourceName,
CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr,
code->InstructionStart());
RecordInliningInfo(rec->entry, code);
- rec->size = code->ExecutableSize();
+ rec->instruction_size = code->InstructionSize();
DispatchCodeEvent(evt_rec);
}
@@ -48,13 +48,13 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
AbstractCode* code, Name* name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = code->address();
+ rec->instruction_start = code->InstructionStart();
rec->entry = NewCodeEntry(tag, GetName(name), CodeEntry::kEmptyResourceName,
CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr,
code->InstructionStart());
RecordInliningInfo(rec->entry, code);
- rec->size = code->ExecutableSize();
+ rec->instruction_size = code->InstructionSize();
DispatchCodeEvent(evt_rec);
}
@@ -64,7 +64,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
Name* script_name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = code->address();
+ rec->instruction_start = code->InstructionStart();
rec->entry = NewCodeEntry(tag, GetName(shared->DebugName()),
GetName(InferScriptName(script_name, shared)),
CpuProfileNode::kNoLineNumberInfo,
@@ -72,7 +72,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
code->InstructionStart());
RecordInliningInfo(rec->entry, code);
rec->entry->FillFunctionInfo(shared);
- rec->size = code->ExecutableSize();
+ rec->instruction_size = code->InstructionSize();
DispatchCodeEvent(evt_rec);
}
@@ -83,7 +83,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
int column) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = abstract_code->address();
+ rec->instruction_start = abstract_code->InstructionStart();
std::unique_ptr<SourcePositionTable> line_table;
if (shared->script()->IsScript()) {
Script* script = Script::cast(shared->script());
@@ -105,7 +105,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
std::move(line_table), abstract_code->InstructionStart());
RecordInliningInfo(rec->entry, abstract_code);
rec->entry->FillFunctionInfo(shared);
- rec->size = abstract_code->ExecutableSize();
+ rec->instruction_size = abstract_code->InstructionSize();
DispatchCodeEvent(evt_rec);
}
@@ -114,20 +114,20 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
wasm::WasmName name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = code->instruction_start();
+ rec->instruction_start = code->instruction_start();
rec->entry = NewCodeEntry(
tag, GetName(name.start()), CodeEntry::kWasmResourceNamePrefix,
CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
nullptr, code->instruction_start());
- rec->size = code->instructions().length();
+ rec->instruction_size = code->instructions().length();
DispatchCodeEvent(evt_rec);
}
-void ProfilerListener::CodeMoveEvent(AbstractCode* from, Address to) {
+void ProfilerListener::CodeMoveEvent(AbstractCode* from, AbstractCode* to) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
- rec->from = from->address();
- rec->to = to;
+ rec->from_instruction_start = from->InstructionStart();
+ rec->to_instruction_start = to->InstructionStart();
DispatchCodeEvent(evt_rec);
}
@@ -135,7 +135,7 @@ void ProfilerListener::CodeDisableOptEvent(AbstractCode* code,
SharedFunctionInfo* shared) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
- rec->start = code->address();
+ rec->instruction_start = code->InstructionStart();
rec->bailout_reason = GetBailoutReason(shared->disable_optimization_reason());
DispatchCodeEvent(evt_rec);
}
@@ -145,7 +145,7 @@ void ProfilerListener::CodeDeoptEvent(Code* code, DeoptimizeKind kind,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_DEOPT);
CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_;
Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, pc);
- rec->start = code->address();
+ rec->instruction_start = code->InstructionStart();
rec->deopt_reason = DeoptimizeReasonToString(info.deopt_reason);
rec->deopt_id = info.deopt_id;
rec->pc = pc;
@@ -160,10 +160,10 @@ void ProfilerListener::CodeDeoptEvent(Code* code, DeoptimizeKind kind,
void ProfilerListener::GetterCallbackEvent(Name* name, Address entry_point) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = entry_point;
+ rec->instruction_start = entry_point;
rec->entry =
NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetConsName("get ", name));
- rec->size = 1;
+ rec->instruction_size = 1;
DispatchCodeEvent(evt_rec);
}
@@ -171,23 +171,22 @@ void ProfilerListener::RegExpCodeCreateEvent(AbstractCode* code,
String* source) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = code->address();
+ rec->instruction_start = code->InstructionStart();
rec->entry = NewCodeEntry(
CodeEventListener::REG_EXP_TAG, GetConsName("RegExp: ", source),
CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
- CpuProfileNode::kNoColumnNumberInfo, nullptr,
- code->raw_instruction_start());
- rec->size = code->ExecutableSize();
+ CpuProfileNode::kNoColumnNumberInfo, nullptr, code->InstructionStart());
+ rec->instruction_size = code->InstructionSize();
DispatchCodeEvent(evt_rec);
}
void ProfilerListener::SetterCallbackEvent(Name* name, Address entry_point) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = entry_point;
+ rec->instruction_start = entry_point;
rec->entry =
NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetConsName("set ", name));
- rec->size = 1;
+ rec->instruction_size = 1;
DispatchCodeEvent(evt_rec);
}
diff --git a/src/profiler/profiler-listener.h b/src/profiler/profiler-listener.h
index 5cff7cc11d1e91ed773f8e1633b4f4363ba1246b..51fba18a60960f8a65115516401952b46ebb5d71 100644
--- a/src/profiler/profiler-listener.h
+++ b/src/profiler/profiler-listener.h
@@ -44,7 +44,7 @@ class ProfilerListener : public CodeEventListener {
wasm::WasmName name) override;
void CodeMovingGCEvent() override {}
- void CodeMoveEvent(AbstractCode* from, Address to) override;
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override;
void CodeDisableOptEvent(AbstractCode* code,
SharedFunctionInfo* shared) override;
void CodeDeoptEvent(Code* code, DeoptimizeKind kind, Address pc,
diff --git a/src/snapshot/serializer.h b/src/snapshot/serializer.h
index 6a5d1a4aacae64930066405855e079c4d98dacb0..658d37f286c5a103738ebfe22c84d68ea6c7b222 100644
--- a/src/snapshot/serializer.h
+++ b/src/snapshot/serializer.h
@@ -28,8 +28,8 @@ class CodeAddressMap : public CodeEventLogger {
isolate_->logger()->RemoveCodeEventListener(this);
}
- void CodeMoveEvent(AbstractCode* from, Address to) override {
- address_to_name_map_.Move(from->address(), to);
+ void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override {
+ address_to_name_map_.Move(from->address(), to->address());
}
void CodeDisableOptEvent(AbstractCode* code,
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 4e7a70c76f28b1404f03ffb5ad771227425ac43e..f74bdf1ede87f53b4f396bb85f0a792895f8a40a 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -176,27 +176,29 @@ TEST(CodeEvents) {
"comment");
profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code,
"comment2");
- profiler_listener.CodeMoveEvent(comment2_code, moved_code->address());
+ profiler_listener.CodeMoveEvent(comment2_code, moved_code);
// Enqueue a tick event to enable code events processing.
- EnqueueTickSampleEvent(processor, aaa_code->address());
+ EnqueueTickSampleEvent(processor, aaa_code->InstructionStart());
isolate->logger()->RemoveCodeEventListener(&profiler_listener);
processor->StopSynchronously();
// Check the state of profile generator.
- CodeEntry* aaa = generator->code_map()->FindEntry(aaa_code->address());
+ CodeEntry* aaa =
+ generator->code_map()->FindEntry(aaa_code->InstructionStart());
CHECK(aaa);
CHECK_EQ(0, strcmp(aaa_str, aaa->name()));
CodeEntry* comment =
- generator->code_map()->FindEntry(comment_code->address());
+ generator->code_map()->FindEntry(comment_code->InstructionStart());
CHECK(comment);
CHECK_EQ(0, strcmp("comment", comment->name()));
- CHECK(!generator->code_map()->FindEntry(comment2_code->address()));
+ CHECK(!generator->code_map()->FindEntry(comment2_code->InstructionStart()));
- CodeEntry* comment2 = generator->code_map()->FindEntry(moved_code->address());
+ CodeEntry* comment2 =
+ generator->code_map()->FindEntry(moved_code->InstructionStart());
CHECK(comment2);
CHECK_EQ(0, strcmp("comment2", comment2->name()));
}
@@ -298,11 +300,11 @@ TEST(Issue1398) {
profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
v8::TickSample* sample = processor->StartTickSample();
- sample->pc = reinterpret_cast<void*>(code->address());
+ sample->pc = reinterpret_cast<void*>(code->InstructionStart());
sample->tos = nullptr;
sample->frames_count = v8::TickSample::kMaxFramesCount;
for (unsigned i = 0; i < sample->frames_count; ++i) {
- sample->stack[i] = reinterpret_cast<void*>(code->address());
+ sample->stack[i] = reinterpret_cast<void*>(code->InstructionStart());
}
processor->FinishTickSample();
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 0b13a7e6607cc45ab824725cff38a963b10feca8..1dfa22b4cc6f53972b18f14346a9703fe48bf8a0 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -751,7 +751,7 @@ TEST(Issue539892) {
explicit FakeCodeEventLogger(i::Isolate* isolate)
: CodeEventLogger(isolate) {}
- void CodeMoveEvent(i::AbstractCode* from, Address to) override {}
+ void CodeMoveEvent(i::AbstractCode* from, i::AbstractCode* to) override {}
void CodeDisableOptEvent(i::AbstractCode* code,
i::SharedFunctionInfo* shared) override {}
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 9b2d7e3ab2fe9dcc273c0946589a4714768bb86d..b53bf148e615e45581a653438af77d9d3af93909 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -676,7 +676,8 @@ int GetFunctionLineNumber(CpuProfiler& profiler, LocalContext& env,
i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(
v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
env->Global()->Get(env.local(), v8_str(name)).ToLocalChecked())));
- CodeEntry* func_entry = code_map->FindEntry(func->abstract_code()->address());
+ CodeEntry* func_entry =
+ code_map->FindEntry(func->abstract_code()->InstructionStart());
if (!func_entry) FATAL("%s", name);
return func_entry->line_number();
}
--
2.17.0

View file

@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com>
Date: Tue, 4 Sep 2018 21:24:03 +0200
Subject: deps: cherry-pick bf5ea81 from upstream V8
Original commit message:
[tracing] allow dynamic control of tracing
If the trace_buffer_ was null, we were returning a pointer to a static
flag back that permanently disabled that particular trace point.
This implied an assumption that tracing will be statically enabled at
process startup, and once it is disabled, it will never be enabled
again. On Node.js side we want to dynamically enable/disable tracing as per
programmer intent.
Change-Id: Ic7a7839b8450ab5c356d85e8e0826f42824907f4
Reviewed-on: https://chromium-review.googlesource.com/1161518
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Ali Ijaz Sheikh <ofrobots@google.com>
Cr-Commit-Position: refs/heads/master@{#54903}
Refs: https://github.com/v8/v8/commit/bf5ea8138c0726613c9d722a3ccb552a8f477992
PR-URL: https://github.com/nodejs/node/pull/21983
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
diff --git a/src/libplatform/tracing/tracing-controller.cc b/src/libplatform/tracing/tracing-controller.cc
index 647306d62790af5f977c3a74ec272f446f3acabf..b4aa7baf724d4f29b4df08f3b57fdc018f6a32a7 100644
--- a/src/libplatform/tracing/tracing-controller.cc
+++ b/src/libplatform/tracing/tracing-controller.cc
@@ -24,18 +24,17 @@ namespace tracing {
// convert internally to determine the category name from the char enabled
// pointer.
const char* g_category_groups[MAX_CATEGORY_GROUPS] = {
- "toplevel", "tracing already shutdown",
+ "toplevel",
"tracing categories exhausted; must increase MAX_CATEGORY_GROUPS",
"__metadata"};
// The enabled flag is char instead of bool so that the API can be used from C.
unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = {0};
// Indexes here have to match the g_category_groups array indexes above.
-const int g_category_already_shutdown = 1;
-const int g_category_categories_exhausted = 2;
+const int g_category_categories_exhausted = 1;
// Metadata category not used in V8.
-// const int g_category_metadata = 3;
-const int g_num_builtin_categories = 4;
+// const int g_category_metadata = 2;
+const int g_num_builtin_categories = 3;
// Skip default categories.
v8::base::AtomicWord g_category_index = g_num_builtin_categories;
@@ -103,10 +102,6 @@ void TracingController::UpdateTraceEventDuration(
const uint8_t* TracingController::GetCategoryGroupEnabled(
const char* category_group) {
- if (!trace_buffer_) {
- DCHECK(!g_category_group_enabled[g_category_already_shutdown]);
- return &g_category_group_enabled[g_category_already_shutdown];
- }
return GetCategoryGroupEnabledInternal(category_group);
}
--
2.17.0

View file

@ -0,0 +1,308 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com>
Date: Sun, 19 Aug 2018 21:53:40 +0200
Subject: deps: cherry-pick c608122 from upstream V8
Original commit message:
[api][keys] Allow skipping indices for Proxies with GetPropertyNames
Bug: v8:7942
Change-Id: I7b3740b04cbcaa56dc809150900ab8d821b054ce
Reviewed-on: https://chromium-review.googlesource.com/1156544
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54821}
Refs: https://github.com/v8/v8/commit/c608122b85238397a43910246f5ff218eb43fb24
PR-URL: https://github.com/nodejs/node/pull/21983
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
diff --git a/src/keys.cc b/src/keys.cc
index 8ecbe0a1d7b2ad09a12b5c826db4f24efa222bcb..689f4ac3dfeb8d3980946884c57237778724e132 100644
--- a/src/keys.cc
+++ b/src/keys.cc
@@ -38,10 +38,10 @@ static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
// static
MaybeHandle<FixedArray> KeyAccumulator::GetKeys(
Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
- GetKeysConversion keys_conversion, bool is_for_in) {
+ GetKeysConversion keys_conversion, bool is_for_in, bool skip_indices) {
Isolate* isolate = object->GetIsolate();
- FastKeyAccumulator accumulator(isolate, object, mode, filter);
- accumulator.set_is_for_in(is_for_in);
+ FastKeyAccumulator accumulator(isolate, object, mode, filter, is_for_in,
+ skip_indices);
return accumulator.GetKeys(keys_conversion);
}
@@ -355,7 +355,8 @@ Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
template <bool fast_properties>
MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
Handle<JSObject> object,
- GetKeysConversion convert) {
+ GetKeysConversion convert,
+ bool skip_indices) {
Handle<FixedArray> keys;
ElementsAccessor* accessor = object->GetElementsAccessor();
if (fast_properties) {
@@ -364,8 +365,14 @@ MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
// TODO(cbruni): preallocate big enough array to also hold elements.
keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate, object);
}
- MaybeHandle<FixedArray> result =
- accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE);
+
+ MaybeHandle<FixedArray> result;
+ if (skip_indices) {
+ result = keys;
+ } else {
+ result =
+ accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE);
+ }
if (FLAG_trace_for_in_enumerate) {
PrintF("| strings=%d symbols=0 elements=%u || prototypes>=1 ||\n",
@@ -403,7 +410,8 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
// Do not try to use the enum-cache for dict-mode objects.
if (map->is_dictionary_map()) {
- return GetOwnKeysWithElements<false>(isolate_, object, keys_conversion);
+ return GetOwnKeysWithElements<false>(isolate_, object, keys_conversion,
+ skip_indices_);
}
int enum_length = receiver_->map()->EnumLength();
if (enum_length == kInvalidEnumCacheSentinel) {
@@ -421,7 +429,8 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
}
// The properties-only case failed because there were probably elements on the
// receiver.
- return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion);
+ return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion,
+ skip_indices_);
}
MaybeHandle<FixedArray>
@@ -450,6 +459,7 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow(
GetKeysConversion keys_conversion) {
KeyAccumulator accumulator(isolate_, mode_, filter_);
accumulator.set_is_for_in(is_for_in_);
+ accumulator.set_skip_indices(skip_indices_);
accumulator.set_last_non_empty_prototype(last_non_empty_prototype_);
MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_),
@@ -699,13 +709,15 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
Maybe<bool> KeyAccumulator::CollectAccessCheckInterceptorKeys(
Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver,
Handle<JSObject> object) {
- MAYBE_RETURN((CollectInterceptorKeysInternal(
- receiver, object,
- handle(InterceptorInfo::cast(
- access_check_info->indexed_interceptor()),
- isolate_),
- this, kIndexed)),
- Nothing<bool>());
+ if (!skip_indices_) {
+ MAYBE_RETURN((CollectInterceptorKeysInternal(
+ receiver, object,
+ handle(InterceptorInfo::cast(
+ access_check_info->indexed_interceptor()),
+ isolate_),
+ this, kIndexed)),
+ Nothing<bool>());
+ }
MAYBE_RETURN(
(CollectInterceptorKeysInternal(
receiver, object,
@@ -942,9 +954,9 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys(
Handle<FixedArray> keys;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, keys,
- KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly,
- ALL_PROPERTIES,
- GetKeysConversion::kConvertToString, is_for_in_),
+ KeyAccumulator::GetKeys(
+ target, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
+ GetKeysConversion::kConvertToString, is_for_in_, skip_indices_),
Nothing<bool>());
Maybe<bool> result = AddKeysFromJSProxy(proxy, keys);
return result;
diff --git a/src/keys.h b/src/keys.h
index 649d6a95999fc70358f48bb18ec71687f3de8e75..5abbaac5cd0e5af2d9dca0d41d927b4b72c626ec 100644
--- a/src/keys.h
+++ b/src/keys.h
@@ -40,7 +40,7 @@ class KeyAccumulator final BASE_EMBEDDED {
static MaybeHandle<FixedArray> GetKeys(
Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
GetKeysConversion keys_conversion = GetKeysConversion::kKeepNumbers,
- bool is_for_in = false);
+ bool is_for_in = false, bool skip_indices = false);
Handle<FixedArray> GetKeys(
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
@@ -128,14 +128,19 @@ class KeyAccumulator final BASE_EMBEDDED {
class FastKeyAccumulator {
public:
FastKeyAccumulator(Isolate* isolate, Handle<JSReceiver> receiver,
- KeyCollectionMode mode, PropertyFilter filter)
- : isolate_(isolate), receiver_(receiver), mode_(mode), filter_(filter) {
+ KeyCollectionMode mode, PropertyFilter filter,
+ bool is_for_in = false, bool skip_indices = false)
+ : isolate_(isolate),
+ receiver_(receiver),
+ mode_(mode),
+ filter_(filter),
+ is_for_in_(is_for_in),
+ skip_indices_(skip_indices) {
Prepare();
}
bool is_receiver_simple_enum() { return is_receiver_simple_enum_; }
bool has_empty_prototype() { return has_empty_prototype_; }
- void set_is_for_in(bool value) { is_for_in_ = value; }
MaybeHandle<FixedArray> GetKeys(
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
@@ -153,6 +158,7 @@ class FastKeyAccumulator {
KeyCollectionMode mode_;
PropertyFilter filter_;
bool is_for_in_ = false;
+ bool skip_indices_ = false;
bool is_receiver_simple_enum_ = false;
bool has_empty_prototype_ = false;
diff --git a/src/runtime/runtime-forin.cc b/src/runtime/runtime-forin.cc
index 5df16faf46faca09d446a700633917fb76fc02b2..ed1e2260602f42d1dba93d0f26357a30a19bc29f 100644
--- a/src/runtime/runtime-forin.cc
+++ b/src/runtime/runtime-forin.cc
@@ -26,8 +26,7 @@ MaybeHandle<HeapObject> Enumerate(Isolate* isolate,
JSObject::MakePrototypesFast(receiver, kStartAtReceiver, isolate);
FastKeyAccumulator accumulator(isolate, receiver,
KeyCollectionMode::kIncludePrototypes,
- ENUMERABLE_STRINGS);
- accumulator.set_is_for_in(true);
+ ENUMERABLE_STRINGS, true);
// Test if we have an enum cache for {receiver}.
if (!accumulator.is_receiver_simple_enum()) {
Handle<FixedArray> keys;
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index d5d1ae101b38c22036fb92d4af09f53f9a556649..a018e12853199aaff9d4aa914429baa03501a830 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -15360,14 +15360,107 @@ THREADED_TEST(PropertyEnumeration2) {
}
}
-THREADED_TEST(PropertyNames) {
+THREADED_TEST(GetPropertyNames) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
v8::Local<v8::Value> result = CompileRun(
"var result = {0: 0, 1: 1, a: 2, b: 3};"
"result[Symbol('symbol')] = true;"
- "result.__proto__ = {2: 4, 3: 5, c: 6, d: 7};"
+ "result.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
+ "result;");
+ v8::Local<v8::Object> object = result.As<v8::Object>();
+ v8::PropertyFilter default_filter =
+ static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
+ v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
+
+ v8::Local<v8::Array> properties =
+ object->GetPropertyNames(context.local()).ToLocalChecked();
+ const char* expected_properties1[] = {"0", "1", "a", "b", "2", "3", "c", "d"};
+ CheckStringArray(isolate, properties, 8, expected_properties1);
+
+ properties =
+ object
+ ->GetPropertyNames(context.local(),
+ v8::KeyCollectionMode::kIncludePrototypes,
+ default_filter, v8::IndexFilter::kIncludeIndices)
+ .ToLocalChecked();
+ CheckStringArray(isolate, properties, 8, expected_properties1);
+
+ properties = object
+ ->GetPropertyNames(context.local(),
+ v8::KeyCollectionMode::kIncludePrototypes,
+ include_symbols_filter,
+ v8::IndexFilter::kIncludeIndices)
+ .ToLocalChecked();
+ const char* expected_properties1_1[] = {"0", "1", "a", "b", nullptr,
+ "2", "3", "c", "d"};
+ CheckStringArray(isolate, properties, 9, expected_properties1_1);
+ CheckIsSymbolAt(isolate, properties, 4, "symbol");
+
+ properties =
+ object
+ ->GetPropertyNames(context.local(),
+ v8::KeyCollectionMode::kIncludePrototypes,
+ default_filter, v8::IndexFilter::kSkipIndices)
+ .ToLocalChecked();
+ const char* expected_properties2[] = {"a", "b", "c", "d"};
+ CheckStringArray(isolate, properties, 4, expected_properties2);
+
+ properties = object
+ ->GetPropertyNames(context.local(),
+ v8::KeyCollectionMode::kIncludePrototypes,
+ include_symbols_filter,
+ v8::IndexFilter::kSkipIndices)
+ .ToLocalChecked();
+ const char* expected_properties2_1[] = {"a", "b", nullptr, "c", "d"};
+ CheckStringArray(isolate, properties, 5, expected_properties2_1);
+ CheckIsSymbolAt(isolate, properties, 2, "symbol");
+
+ properties =
+ object
+ ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
+ default_filter, v8::IndexFilter::kIncludeIndices)
+ .ToLocalChecked();
+ const char* expected_properties3[] = {"0", "1", "a", "b"};
+ CheckStringArray(isolate, properties, 4, expected_properties3);
+
+ properties = object
+ ->GetPropertyNames(
+ context.local(), v8::KeyCollectionMode::kOwnOnly,
+ include_symbols_filter, v8::IndexFilter::kIncludeIndices)
+ .ToLocalChecked();
+ const char* expected_properties3_1[] = {"0", "1", "a", "b", nullptr};
+ CheckStringArray(isolate, properties, 5, expected_properties3_1);
+ CheckIsSymbolAt(isolate, properties, 4, "symbol");
+
+ properties =
+ object
+ ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
+ default_filter, v8::IndexFilter::kSkipIndices)
+ .ToLocalChecked();
+ const char* expected_properties4[] = {"a", "b"};
+ CheckStringArray(isolate, properties, 2, expected_properties4);
+
+ properties = object
+ ->GetPropertyNames(
+ context.local(), v8::KeyCollectionMode::kOwnOnly,
+ include_symbols_filter, v8::IndexFilter::kSkipIndices)
+ .ToLocalChecked();
+ const char* expected_properties4_1[] = {"a", "b", nullptr};
+ CheckStringArray(isolate, properties, 3, expected_properties4_1);
+ CheckIsSymbolAt(isolate, properties, 2, "symbol");
+}
+
+THREADED_TEST(ProxyGetPropertyNames) {
+ LocalContext context;
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
+ v8::Local<v8::Value> result = CompileRun(
+ "var target = {0: 0, 1: 1, a: 2, b: 3};"
+ "target[Symbol('symbol')] = true;"
+ "target.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
+ "var result = new Proxy(target, {});"
"result;");
v8::Local<v8::Object> object = result.As<v8::Object>();
v8::PropertyFilter default_filter =
--
2.17.0

View file

@ -0,0 +1,757 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Kozyatinskiy <kozyatinskiy@chromium.org>
Date: Fri, 10 Aug 2018 13:09:49 -0700
Subject: deps: cherry-pick dbfcc48 from upstream V8
Original commit message:
```
[inspector] added V8InspectorClient::resourceNameToUrl
Some clients (see Node.js) use platform path as ScriptOrigin.
Reporting platform path in protocol makes using protocol much harder.
This CL introduced V8InspectorClient::resourceNameToUrl method that
is called for any reported using protocol url.
V8Inspector uses url internally as well so protocol client may generate
pattern for blackboxing with file urls only and does not need to build
complicated regexp that covers files urls and platform paths on
different platforms.
R=lushnikov@chromium.org
TBR=yangguo@chromium.org
Bug: none
Change-Id: Iff302e7441df922fa5d689fe510f5a9bfd470b9b
Reviewed-on: https://chromium-review.googlesource.com/1164624
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55029}
```
Refs: https://github.com/v8/v8/commit/dbfcc48
PR-URL: https://github.com/nodejs/node/pull/22251
Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
diff --git a/include/v8-inspector.h b/include/v8-inspector.h
index d879a94373e427892bb6921eafff5139e05509b0..ad04d01bd212583c3ae9c3911c5dcfd0ef07cd79 100644
--- a/include/v8-inspector.h
+++ b/include/v8-inspector.h
@@ -215,6 +215,11 @@ class V8_EXPORT V8InspectorClient {
virtual bool canExecuteScripts(int contextGroupId) { return true; }
virtual void maxAsyncCallStackDepthChanged(int depth) {}
+
+ virtual std::unique_ptr<StringBuffer> resourceNameToUrl(
+ const StringView& resourceName) {
+ return nullptr;
+ }
};
// These stack trace ids are intended to be passed between debuggers and be
diff --git a/src/inspector/v8-debugger-agent-impl.cc b/src/inspector/v8-debugger-agent-impl.cc
index e4e6492b67a0c5a2200875340dca4f3e8f3ab1b7..d9cb49b1d4d2ef354fd2478623a4046cd7c25354 100644
--- a/src/inspector/v8-debugger-agent-impl.cc
+++ b/src/inspector/v8-debugger-agent-impl.cc
@@ -1396,7 +1396,7 @@ void V8DebuggerAgentImpl::didParseSource(
protocol::StringUtil::parseJSON(inspected->auxData()));
}
bool isLiveEdit = script->isLiveEdit();
- bool hasSourceURL = script->hasSourceURL();
+ bool hasSourceURLComment = script->hasSourceURLComment();
bool isModule = script->isModule();
String16 scriptId = script->scriptId();
String16 scriptURL = script->sourceURL();
@@ -1416,7 +1416,8 @@ void V8DebuggerAgentImpl::didParseSource(
Maybe<protocol::DictionaryValue> executionContextAuxDataParam(
std::move(executionContextAuxData));
const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr;
- const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr;
+ const bool* hasSourceURLParam =
+ hasSourceURLComment ? &hasSourceURLComment : nullptr;
const bool* isModuleParam = isModule ? &isModule : nullptr;
std::unique_ptr<V8StackTraceImpl> stack =
V8StackTraceImpl::capture(m_inspector->debugger(), contextGroupId, 1);
diff --git a/src/inspector/v8-debugger-script.cc b/src/inspector/v8-debugger-script.cc
index c40477ae2af74dfea6a950bc7be6e5b4efa42fe8..d861265e148559a16e27b20b371c4d7bba364add 100644
--- a/src/inspector/v8-debugger-script.cc
+++ b/src/inspector/v8-debugger-script.cc
@@ -6,6 +6,7 @@
#include "src/inspector/inspected-context.h"
#include "src/inspector/string-util.h"
+#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/wasm-translation.h"
#include "src/utils.h"
@@ -110,9 +111,9 @@ class ActualScript : public V8DebuggerScript {
public:
ActualScript(v8::Isolate* isolate, v8::Local<v8::debug::Script> script,
- bool isLiveEdit)
+ bool isLiveEdit, V8InspectorClient* client)
: V8DebuggerScript(isolate, String16::fromInteger(script->Id()),
- GetNameOrSourceUrl(script)),
+ GetScriptURL(script, client)),
m_isLiveEdit(isLiveEdit) {
Initialize(script);
}
@@ -218,10 +219,18 @@ class ActualScript : public V8DebuggerScript {
}
private:
- String16 GetNameOrSourceUrl(v8::Local<v8::debug::Script> script) {
- v8::Local<v8::String> name;
- if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name))
- return toProtocolString(name);
+ String16 GetScriptURL(v8::Local<v8::debug::Script> script,
+ V8InspectorClient* client) {
+ v8::Local<v8::String> sourceURL;
+ if (script->SourceURL().ToLocal(&sourceURL) && sourceURL->Length() > 0)
+ return toProtocolString(sourceURL);
+ v8::Local<v8::String> v8Name;
+ if (script->Name().ToLocal(&v8Name) && v8Name->Length() > 0) {
+ String16 name = toProtocolString(v8Name);
+ std::unique_ptr<StringBuffer> url =
+ client->resourceNameToUrl(toStringView(name));
+ return url ? toString16(url->string()) : name;
+ }
return String16();
}
@@ -231,7 +240,8 @@ class ActualScript : public V8DebuggerScript {
void Initialize(v8::Local<v8::debug::Script> script) {
v8::Local<v8::String> tmp;
- if (script->SourceURL().ToLocal(&tmp)) m_sourceURL = toProtocolString(tmp);
+ m_hasSourceURLComment =
+ script->SourceURL().ToLocal(&tmp) && tmp->Length() > 0;
if (script->SourceMappingURL().ToLocal(&tmp))
m_sourceMappingURL = toProtocolString(tmp);
m_startLine = script->LineOffset();
@@ -398,9 +408,9 @@ class WasmVirtualScript : public V8DebuggerScript {
std::unique_ptr<V8DebuggerScript> V8DebuggerScript::Create(
v8::Isolate* isolate, v8::Local<v8::debug::Script> scriptObj,
- bool isLiveEdit) {
+ bool isLiveEdit, V8InspectorClient* client) {
return std::unique_ptr<ActualScript>(
- new ActualScript(isolate, scriptObj, isLiveEdit));
+ new ActualScript(isolate, scriptObj, isLiveEdit, client));
}
std::unique_ptr<V8DebuggerScript> V8DebuggerScript::CreateWasm(
@@ -418,12 +428,11 @@ V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, String16 id,
V8DebuggerScript::~V8DebuggerScript() {}
-const String16& V8DebuggerScript::sourceURL() const {
- return m_sourceURL.isEmpty() ? m_url : m_sourceURL;
-}
-
void V8DebuggerScript::setSourceURL(const String16& sourceURL) {
- m_sourceURL = sourceURL;
+ if (sourceURL.length() > 0) {
+ m_hasSourceURLComment = true;
+ m_url = sourceURL;
+ }
}
bool V8DebuggerScript::setBreakpoint(const String16& condition,
@@ -431,5 +440,4 @@ bool V8DebuggerScript::setBreakpoint(const String16& condition,
v8::HandleScope scope(m_isolate);
return script()->SetBreakpoint(toV8String(m_isolate, condition), loc, id);
}
-
} // namespace v8_inspector
diff --git a/src/inspector/v8-debugger-script.h b/src/inspector/v8-debugger-script.h
index e0e7d93b20275221e873f026a9d44e663fad2e30..38e6448f48d8e8dcdde0935c516b45ddc7cf4db5 100644
--- a/src/inspector/v8-debugger-script.h
+++ b/src/inspector/v8-debugger-script.h
@@ -40,13 +40,14 @@
namespace v8_inspector {
// Forward declaration.
+class V8InspectorClient;
class WasmTranslation;
class V8DebuggerScript {
public:
static std::unique_ptr<V8DebuggerScript> Create(
v8::Isolate* isolate, v8::Local<v8::debug::Script> script,
- bool isLiveEdit);
+ bool isLiveEdit, V8InspectorClient* client);
static std::unique_ptr<V8DebuggerScript> CreateWasm(
v8::Isolate* isolate, WasmTranslation* wasmTranslation,
v8::Local<v8::debug::WasmScript> underlyingScript, String16 id,
@@ -55,9 +56,9 @@ class V8DebuggerScript {
virtual ~V8DebuggerScript();
const String16& scriptId() const { return m_id; }
- const String16& url() const { return m_url; }
- bool hasSourceURL() const { return !m_sourceURL.isEmpty(); }
- const String16& sourceURL() const;
+ bool hasSourceURLComment() const { return m_hasSourceURLComment; }
+ const String16& sourceURL() const { return m_url; }
+
virtual const String16& sourceMappingURL() const = 0;
virtual const String16& source() const = 0;
virtual const String16& hash() const = 0;
@@ -95,7 +96,7 @@ class V8DebuggerScript {
String16 m_id;
String16 m_url;
- String16 m_sourceURL;
+ bool m_hasSourceURLComment = false;
int m_executionContextId = 0;
v8::Isolate* m_isolate;
diff --git a/src/inspector/v8-debugger.cc b/src/inspector/v8-debugger.cc
index 1ceb4210f7f476ddbc1fc795239d6b2153788a55..7d1f7cefd15db3f5482e27fa47880bb6227bb322 100644
--- a/src/inspector/v8-debugger.cc
+++ b/src/inspector/v8-debugger.cc
@@ -226,13 +226,15 @@ void V8Debugger::getCompiledScripts(
v8::Local<v8::debug::Script> script = scripts.Get(i);
if (!script->WasCompiled()) continue;
if (script->IsEmbedded()) {
- result.push_back(V8DebuggerScript::Create(m_isolate, script, false));
+ result.push_back(V8DebuggerScript::Create(m_isolate, script, false,
+ m_inspector->client()));
continue;
}
int contextId;
if (!script->ContextId().To(&contextId)) continue;
if (m_inspector->contextGroupId(contextId) != contextGroupId) continue;
- result.push_back(V8DebuggerScript::Create(m_isolate, script, false));
+ result.push_back(V8DebuggerScript::Create(m_isolate, script, false,
+ m_inspector->client()));
}
}
@@ -585,13 +587,14 @@ void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script,
});
} else if (m_ignoreScriptParsedEventsCounter == 0) {
v8::Isolate* isolate = m_isolate;
+ V8InspectorClient* client = m_inspector->client();
m_inspector->forEachSession(
m_inspector->contextGroupId(contextId),
- [&isolate, &script, &has_compile_error,
- &is_live_edited](V8InspectorSessionImpl* session) {
+ [&isolate, &script, &has_compile_error, &is_live_edited,
+ &client](V8InspectorSessionImpl* session) {
if (!session->debuggerAgent()->enabled()) return;
session->debuggerAgent()->didParseSource(
- V8DebuggerScript::Create(isolate, script, is_live_edited),
+ V8DebuggerScript::Create(isolate, script, is_live_edited, client),
!has_compile_error);
});
}
diff --git a/src/inspector/v8-profiler-agent-impl.cc b/src/inspector/v8-profiler-agent-impl.cc
index 59a99d79d54c2fb8dee1ff3e950a1c995889a8ac..f14815fdc4b031c640795ce10fb4b963310656be 100644
--- a/src/inspector/v8-profiler-agent-impl.cc
+++ b/src/inspector/v8-profiler-agent-impl.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "src/base/atomicops.h"
+#include "src/debug/debug-interface.h"
#include "src/flags.h" // TODO(jgruber): Remove include and DEPS entry.
#include "src/inspector/protocol/Protocol.h"
#include "src/inspector/string-util.h"
@@ -31,6 +32,15 @@ static const char typeProfileStarted[] = "typeProfileStarted";
namespace {
+String16 resourceNameToUrl(V8InspectorImpl* inspector,
+ v8::Local<v8::String> v8Name) {
+ String16 name = toProtocolString(v8Name);
+ if (!inspector) return name;
+ std::unique_ptr<StringBuffer> url =
+ inspector->client()->resourceNameToUrl(toStringView(name));
+ return url ? toString16(url->string()) : name;
+}
+
std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>>
buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) {
unsigned lineCount = node->GetHitLineCount();
@@ -51,13 +61,14 @@ buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) {
}
std::unique_ptr<protocol::Profiler::ProfileNode> buildInspectorObjectFor(
- v8::Isolate* isolate, const v8::CpuProfileNode* node) {
+ V8InspectorImpl* inspector, const v8::CpuProfileNode* node) {
+ v8::Isolate* isolate = inspector->isolate();
v8::HandleScope handleScope(isolate);
auto callFrame =
protocol::Runtime::CallFrame::create()
.setFunctionName(toProtocolString(node->GetFunctionName()))
.setScriptId(String16::fromInteger(node->GetScriptId()))
- .setUrl(toProtocolString(node->GetScriptResourceName()))
+ .setUrl(resourceNameToUrl(inspector, node->GetScriptResourceName()))
.setLineNumber(node->GetLineNumber() - 1)
.setColumnNumber(node->GetColumnNumber() - 1)
.build();
@@ -107,18 +118,19 @@ std::unique_ptr<protocol::Array<int>> buildInspectorObjectForTimestamps(
return array;
}
-void flattenNodesTree(v8::Isolate* isolate, const v8::CpuProfileNode* node,
+void flattenNodesTree(V8InspectorImpl* inspector,
+ const v8::CpuProfileNode* node,
protocol::Array<protocol::Profiler::ProfileNode>* list) {
- list->addItem(buildInspectorObjectFor(isolate, node));
+ list->addItem(buildInspectorObjectFor(inspector, node));
const int childrenCount = node->GetChildrenCount();
for (int i = 0; i < childrenCount; i++)
- flattenNodesTree(isolate, node->GetChild(i), list);
+ flattenNodesTree(inspector, node->GetChild(i), list);
}
std::unique_ptr<protocol::Profiler::Profile> createCPUProfile(
- v8::Isolate* isolate, v8::CpuProfile* v8profile) {
+ V8InspectorImpl* inspector, v8::CpuProfile* v8profile) {
auto nodes = protocol::Array<protocol::Profiler::ProfileNode>::create();
- flattenNodesTree(isolate, v8profile->GetTopDownRoot(), nodes.get());
+ flattenNodesTree(inspector, v8profile->GetTopDownRoot(), nodes.get());
return protocol::Profiler::Profile::create()
.setNodes(std::move(nodes))
.setStartTime(static_cast<double>(v8profile->GetStartTime()))
@@ -320,7 +332,7 @@ std::unique_ptr<protocol::Profiler::CoverageRange> createCoverageRange(
}
Response coverageToProtocol(
- v8::Isolate* isolate, const v8::debug::Coverage& coverage,
+ V8InspectorImpl* inspector, const v8::debug::Coverage& coverage,
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
out_result) {
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>> result =
@@ -361,8 +373,10 @@ Response coverageToProtocol(
}
String16 url;
v8::Local<v8::String> name;
- if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) {
+ if (script->SourceURL().ToLocal(&name) && name->Length()) {
url = toProtocolString(name);
+ } else if (script->Name().ToLocal(&name) && name->Length()) {
+ url = resourceNameToUrl(inspector, name);
}
result->addItem(protocol::Profiler::ScriptCoverage::create()
.setScriptId(String16::fromInteger(script->Id()))
@@ -384,7 +398,7 @@ Response V8ProfilerAgentImpl::takePreciseCoverage(
}
v8::HandleScope handle_scope(m_isolate);
v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(m_isolate);
- return coverageToProtocol(m_isolate, coverage, out_result);
+ return coverageToProtocol(m_session->inspector(), coverage, out_result);
}
Response V8ProfilerAgentImpl::getBestEffortCoverage(
@@ -393,12 +407,12 @@ Response V8ProfilerAgentImpl::getBestEffortCoverage(
v8::HandleScope handle_scope(m_isolate);
v8::debug::Coverage coverage =
v8::debug::Coverage::CollectBestEffort(m_isolate);
- return coverageToProtocol(m_isolate, coverage, out_result);
+ return coverageToProtocol(m_session->inspector(), coverage, out_result);
}
namespace {
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>
-typeProfileToProtocol(v8::Isolate* isolate,
+typeProfileToProtocol(V8InspectorImpl* inspector,
const v8::debug::TypeProfile& type_profile) {
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>
result = protocol::Array<protocol::Profiler::ScriptTypeProfile>::create();
@@ -426,8 +440,10 @@ typeProfileToProtocol(v8::Isolate* isolate,
}
String16 url;
v8::Local<v8::String> name;
- if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) {
+ if (script->SourceURL().ToLocal(&name) && name->Length()) {
url = toProtocolString(name);
+ } else if (script->Name().ToLocal(&name) && name->Length()) {
+ url = resourceNameToUrl(inspector, name);
}
result->addItem(protocol::Profiler::ScriptTypeProfile::create()
.setScriptId(String16::fromInteger(script->Id()))
@@ -462,7 +478,7 @@ Response V8ProfilerAgentImpl::takeTypeProfile(
v8::HandleScope handle_scope(m_isolate);
v8::debug::TypeProfile type_profile =
v8::debug::TypeProfile::Collect(m_isolate);
- *out_result = typeProfileToProtocol(m_isolate, type_profile);
+ *out_result = typeProfileToProtocol(m_session->inspector(), type_profile);
return Response::OK();
}
@@ -491,7 +507,7 @@ std::unique_ptr<protocol::Profiler::Profile> V8ProfilerAgentImpl::stopProfiling(
m_profiler->StopProfiling(toV8String(m_isolate, title));
std::unique_ptr<protocol::Profiler::Profile> result;
if (profile) {
- if (serialize) result = createCPUProfile(m_isolate, profile);
+ if (serialize) result = createCPUProfile(m_session->inspector(), profile);
profile->Delete();
}
--m_startedProfilesCount;
diff --git a/src/inspector/v8-stack-trace-impl.cc b/src/inspector/v8-stack-trace-impl.cc
index 75293c59afee8e09f05a33d8aa806ee79bd01e99..9be0d4fa385f2a02da6ba9865f7d658ac1912a5e 100644
--- a/src/inspector/v8-stack-trace-impl.cc
+++ b/src/inspector/v8-stack-trace-impl.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "src/inspector/v8-debugger.h"
+#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/wasm-translation.h"
namespace v8_inspector {
@@ -73,7 +74,10 @@ std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectCommon(
std::unique_ptr<protocol::Array<protocol::Runtime::CallFrame>>
inspectorFrames = protocol::Array<protocol::Runtime::CallFrame>::create();
for (size_t i = 0; i < frames.size(); i++) {
- inspectorFrames->addItem(frames[i]->buildInspectorObject());
+ V8InspectorClient* client = nullptr;
+ if (debugger && debugger->inspector())
+ client = debugger->inspector()->client();
+ inspectorFrames->addItem(frames[i]->buildInspectorObject(client));
}
std::unique_ptr<protocol::Runtime::StackTrace> stackTrace =
protocol::Runtime::StackTrace::create()
@@ -117,7 +121,9 @@ StackFrame::StackFrame(v8::Local<v8::StackFrame> v8Frame)
m_scriptId(String16::fromInteger(v8Frame->GetScriptId())),
m_sourceURL(toProtocolString(v8Frame->GetScriptNameOrSourceURL())),
m_lineNumber(v8Frame->GetLineNumber() - 1),
- m_columnNumber(v8Frame->GetColumn() - 1) {
+ m_columnNumber(v8Frame->GetColumn() - 1),
+ m_hasSourceURLComment(v8Frame->GetScriptName() !=
+ v8Frame->GetScriptNameOrSourceURL()) {
DCHECK_NE(v8::Message::kNoLineNumberInfo, m_lineNumber + 1);
DCHECK_NE(v8::Message::kNoColumnInfo, m_columnNumber + 1);
}
@@ -137,12 +143,20 @@ int StackFrame::lineNumber() const { return m_lineNumber; }
int StackFrame::columnNumber() const { return m_columnNumber; }
-std::unique_ptr<protocol::Runtime::CallFrame> StackFrame::buildInspectorObject()
- const {
+std::unique_ptr<protocol::Runtime::CallFrame> StackFrame::buildInspectorObject(
+ V8InspectorClient* client) const {
+ String16 frameUrl = m_sourceURL;
+ if (client && !m_hasSourceURLComment && frameUrl.length() > 0) {
+ std::unique_ptr<StringBuffer> url =
+ client->resourceNameToUrl(toStringView(m_sourceURL));
+ if (url) {
+ frameUrl = toString16(url->string());
+ }
+ }
return protocol::Runtime::CallFrame::create()
.setFunctionName(m_functionName)
.setScriptId(m_scriptId)
- .setUrl(m_sourceURL)
+ .setUrl(frameUrl)
.setLineNumber(m_lineNumber)
.setColumnNumber(m_columnNumber)
.build();
diff --git a/src/inspector/v8-stack-trace-impl.h b/src/inspector/v8-stack-trace-impl.h
index a8f23c48b67231f6015d1004ec14995c65967239..019fd469cdd72e1fd03ed7a0ab8554e054fb8498 100644
--- a/src/inspector/v8-stack-trace-impl.h
+++ b/src/inspector/v8-stack-trace-impl.h
@@ -33,7 +33,8 @@ class StackFrame {
const String16& sourceURL() const;
int lineNumber() const; // 0-based.
int columnNumber() const; // 0-based.
- std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject() const;
+ std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject(
+ V8InspectorClient* client) const;
bool isEqual(StackFrame* frame) const;
private:
@@ -42,6 +43,7 @@ class StackFrame {
String16 m_sourceURL;
int m_lineNumber; // 0-based.
int m_columnNumber; // 0-based.
+ bool m_hasSourceURLComment;
};
class V8StackTraceImpl : public V8StackTrace {
diff --git a/test/inspector/debugger/resource-name-to-url-expected.txt b/test/inspector/debugger/resource-name-to-url-expected.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0ecd0b82ef239072ab20a4d8844fa48b4b477586
--- /dev/null
+++ b/test/inspector/debugger/resource-name-to-url-expected.txt
@@ -0,0 +1,122 @@
+Tests V8InspectorClient::resourceNameToUrl.
+Check script with url:
+{
+ method : Debugger.scriptParsed
+ params : {
+ endColumn : 16
+ endLine : 0
+ executionContextId : <executionContextId>
+ hasSourceURL : false
+ hash : 033b33d191ed51ed823355d865eb871d811403e2
+ isLiveEdit : false
+ isModule : false
+ length : 16
+ scriptId : <scriptId>
+ sourceMapURL :
+ startColumn : 0
+ startLine : 0
+ url : prefix://url
+ }
+}
+Check script with sourceURL comment:
+{
+ method : Debugger.scriptParsed
+ params : {
+ endColumn : 37
+ endLine : 0
+ executionContextId : <executionContextId>
+ hasSourceURL : true
+ hash : 06c136ce206c5f505f32af524e6ec71b5baa0bbb
+ isLiveEdit : false
+ isModule : false
+ length : 37
+ scriptId : <scriptId>
+ sourceMapURL :
+ startColumn : 0
+ startLine : 0
+ url : foo.js
+ }
+}
+Check script failed to parse:
+{
+ method : Debugger.scriptFailedToParse
+ params : {
+ endColumn : 15
+ endLine : 0
+ executionContextId : <executionContextId>
+ hasSourceURL : false
+ hash : 033b33d191ed51ed1f44cd0465eb871d811403e2
+ isModule : false
+ length : 15
+ scriptId : <scriptId>
+ sourceMapURL :
+ startColumn : 0
+ startLine : 0
+ url : prefix://url
+ }
+}
+Check script failed to parse with sourceURL comment:
+{
+ method : Debugger.scriptFailedToParse
+ params : {
+ endColumn : 36
+ endLine : 0
+ executionContextId : <executionContextId>
+ hasSourceURL : true
+ hash : 23a2885951475580023e2a742563d78876d8f05e
+ isModule : false
+ length : 36
+ scriptId : <scriptId>
+ sourceMapURL :
+ startColumn : 0
+ startLine : 0
+ url : foo.js
+ }
+}
+Test runtime stack trace:
+{
+ method : Runtime.consoleAPICalled
+ params : {
+ args : [
+ [0] : {
+ description : 42
+ type : number
+ value : 42
+ }
+ ]
+ executionContextId : <executionContextId>
+ stackTrace : {
+ callFrames : [
+ [0] : {
+ columnNumber : 14
+ functionName : foo
+ lineNumber : 2
+ scriptId : <scriptId>
+ url : prefix://url
+ }
+ [1] : {
+ columnNumber : 0
+ functionName :
+ lineNumber : 0
+ scriptId : <scriptId>
+ url : boo.js
+ }
+ [2] : {
+ columnNumber : 4
+ functionName :
+ lineNumber : 4
+ scriptId : <scriptId>
+ url : prefix://url
+ }
+ ]
+ }
+ timestamp : <timestamp>
+ type : log
+ }
+}
+Test debugger stack trace:
+[
+ [0] : prefix://url
+ [1] : boo.js
+ [2] : prefix://url
+]
diff --git a/test/inspector/debugger/resource-name-to-url.js b/test/inspector/debugger/resource-name-to-url.js
new file mode 100644
index 0000000000000000000000000000000000000000..620c7a2864b406539fc7fc0e4b5a89b06a0847f3
--- /dev/null
+++ b/test/inspector/debugger/resource-name-to-url.js
@@ -0,0 +1,49 @@
+// Copyright 2018 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+let {session, contextGroup, Protocol} = InspectorTest.start(
+ 'Tests V8InspectorClient::resourceNameToUrl.');
+
+(async function test(){
+ Protocol.Runtime.enable();
+ await Protocol.Debugger.enable();
+ contextGroup.addScript(`inspector.setResourceNamePrefix('prefix://')`);
+ await Protocol.Debugger.onceScriptParsed();
+
+ InspectorTest.log('Check script with url:');
+ contextGroup.addScript('function foo(){}', 0, 0, 'url');
+ InspectorTest.logMessage(await Protocol.Debugger.onceScriptParsed());
+
+ InspectorTest.log('Check script with sourceURL comment:');
+ contextGroup.addScript('function foo(){} //# sourceURL=foo.js', 0, 0, 'url');
+ InspectorTest.logMessage(await Protocol.Debugger.onceScriptParsed());
+
+ InspectorTest.log('Check script failed to parse:');
+ contextGroup.addScript('function foo(){', 0, 0, 'url');
+ InspectorTest.logMessage(await Protocol.Debugger.onceScriptFailedToParse());
+
+ InspectorTest.log('Check script failed to parse with sourceURL comment:');
+ contextGroup.addScript('function foo(){ //# sourceURL=foo.js', 0, 0, 'url');
+ InspectorTest.logMessage(await Protocol.Debugger.onceScriptFailedToParse());
+
+ InspectorTest.log('Test runtime stack trace:');
+ contextGroup.addScript(`
+ function foo() {
+ console.log(42);
+ }
+ eval('foo(); //# sourceURL=boo.js');
+ `, 0, 0, 'url');
+ InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
+
+ InspectorTest.log('Test debugger stack trace:');
+ contextGroup.addScript(`
+ function foo() {
+ debugger;
+ }
+ eval('foo(); //# sourceURL=boo.js');
+ `, 0, 0, 'url');
+ const {params:{callFrames}} = await Protocol.Debugger.oncePaused();
+ InspectorTest.logMessage(callFrames.map(frame => frame.url));
+ InspectorTest.completeTest();
+})();
diff --git a/test/inspector/inspector-test.cc b/test/inspector/inspector-test.cc
index 668a9463d5b9cf7db0981b6907e303425df6c25c..93a8b1d3f2188015aa153cdc15b3b369d1f353d9 100644
--- a/test/inspector/inspector-test.cc
+++ b/test/inspector/inspector-test.cc
@@ -712,6 +712,9 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
ToV8String(isolate, "setAllowCodeGenerationFromStrings"),
v8::FunctionTemplate::New(
isolate, &InspectorExtension::SetAllowCodeGenerationFromStrings));
+ inspector->Set(ToV8String(isolate, "setResourceNamePrefix"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::SetResourceNamePrefix));
global->Set(ToV8String(isolate, "inspector"), inspector);
}
@@ -973,6 +976,18 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
args.GetIsolate()->GetCurrentContext()->AllowCodeGenerationFromStrings(
args[0].As<v8::Boolean>()->Value());
}
+
+ static void SetResourceNamePrefix(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 1 || !args[0]->IsString()) {
+ fprintf(stderr, "Internal error: setResourceNamePrefix('prefix').");
+ Exit();
+ }
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ IsolateData* data = IsolateData::FromContext(context);
+ data->SetResourceNamePrefix(v8::Local<v8::String>::Cast(args[0]));
+ }
};
bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context,
diff --git a/test/inspector/isolate-data.cc b/test/inspector/isolate-data.cc
index 15eee89a61faa25d6f635b6983d81bdea943c8e1..a669cc41a1f26a2c6a76c59eb081c8ca0a83bfdd 100644
--- a/test/inspector/isolate-data.cc
+++ b/test/inspector/isolate-data.cc
@@ -423,3 +423,32 @@ void IsolateData::maxAsyncCallStackDepthChanged(int depth) {
if (!log_max_async_call_stack_depth_changed_) return;
fprintf(stdout, "maxAsyncCallStackDepthChanged: %d\n", depth);
}
+
+void IsolateData::SetResourceNamePrefix(v8::Local<v8::String> prefix) {
+ resource_name_prefix_.Reset(v8::Isolate::GetCurrent(), prefix);
+}
+
+namespace {
+class StringBufferImpl : public v8_inspector::StringBuffer {
+ public:
+ StringBufferImpl(v8::Isolate* isolate, v8::Local<v8::String> string)
+ : data_(ToVector(string)),
+ view_(data_.start(), data_.length()) {}
+ const v8_inspector::StringView& string() override { return view_; }
+
+ private:
+ v8::internal::Vector<uint16_t> data_;
+ v8_inspector::StringView view_;
+};
+} // anonymous namespace
+
+std::unique_ptr<v8_inspector::StringBuffer> IsolateData::resourceNameToUrl(
+ const v8_inspector::StringView& resourceName) {
+ if (resource_name_prefix_.IsEmpty()) return nullptr;
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope handle_scope(isolate);
+ v8::Local<v8::String> name = ToString(isolate, resourceName);
+ v8::Local<v8::String> prefix = resource_name_prefix_.Get(isolate);
+ v8::Local<v8::String> url = v8::String::Concat(prefix, name);
+ return std::unique_ptr<StringBufferImpl>(new StringBufferImpl(isolate, url));
+}
diff --git a/test/inspector/isolate-data.h b/test/inspector/isolate-data.h
index 5eb9803a7416fb67937283960c90269681403c1f..d0a263e573827c3b22810d70b0cf4f0c6f9243f3 100644
--- a/test/inspector/isolate-data.h
+++ b/test/inspector/isolate-data.h
@@ -76,6 +76,7 @@ class IsolateData : public v8_inspector::V8InspectorClient {
void FireContextCreated(v8::Local<v8::Context> context, int context_group_id);
void FireContextDestroyed(v8::Local<v8::Context> context);
void FreeContext(v8::Local<v8::Context> context);
+ void SetResourceNamePrefix(v8::Local<v8::String> prefix);
private:
struct VectorCompare {
@@ -114,6 +115,8 @@ class IsolateData : public v8_inspector::V8InspectorClient {
v8_inspector::V8StackTrace*) override;
bool isInspectableHeapObject(v8::Local<v8::Object>) override;
void maxAsyncCallStackDepthChanged(int depth) override;
+ std::unique_ptr<v8_inspector::StringBuffer> resourceNameToUrl(
+ const v8_inspector::StringView& resourceName) override;
// The isolate gets deleted by its {Dispose} method, not by the default
// deleter. Therefore we have to define a custom deleter for the unique_ptr to
@@ -141,6 +144,7 @@ class IsolateData : public v8_inspector::V8InspectorClient {
bool log_console_api_message_calls_ = false;
bool log_max_async_call_stack_depth_changed_ = false;
v8::Global<v8::Private> not_inspectable_private_;
+ v8::Global<v8::String> resource_name_prefix_;
DISALLOW_COPY_AND_ASSIGN(IsolateData);
};
--
2.17.0

View file

@ -0,0 +1,367 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Camillo Bruni <cbruni@chromium.org>
Date: Sat, 18 Aug 2018 13:41:51 -0400
Subject: deps: cherry-pick e1a7699 from upstream V8
Original commit message:
[api][runtime] Support all-in ctors of {Named,Indexed}PropertyHandlerConfiguration
- Explicitly allows construction of
{Named,Indexed}PropertyHandlerConfiguration with all the members filled.
Bug: v8:7612
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I426ea33846b5dbf2b3482c722c963a6e4b0abded
Reviewed-on: https://chromium-review.googlesource.com/1163882
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55142}
PR-URL: https://github.com/nodejs/node/pull/22390
Fixes: https://github.com/nodejs/node/issues/17480
Fixes: https://github.com/nodejs/node/issues/17481
Refs: https://github.com/v8/v8/commit/e1a76995ef311eb3ca66e12ef1941ed596034d59
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
diff --git a/include/v8.h b/include/v8.h
index 23d5ba36db97dab2bb706ab90930ee1403a68104..20a65afcbc61c31360874e45adc03eeda02e9a81 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -5994,6 +5994,26 @@ enum class PropertyHandlerFlags {
};
struct NamedPropertyHandlerConfiguration {
+ NamedPropertyHandlerConfiguration(
+ GenericNamedPropertyGetterCallback getter,
+ GenericNamedPropertySetterCallback setter,
+ GenericNamedPropertyQueryCallback query,
+ GenericNamedPropertyDeleterCallback deleter,
+ GenericNamedPropertyEnumeratorCallback enumerator,
+ GenericNamedPropertyDefinerCallback definer,
+ GenericNamedPropertyDescriptorCallback descriptor,
+ Local<Value> data = Local<Value>(),
+ PropertyHandlerFlags flags = PropertyHandlerFlags::kNone)
+ : getter(getter),
+ setter(setter),
+ query(query),
+ deleter(deleter),
+ enumerator(enumerator),
+ definer(definer),
+ descriptor(descriptor),
+ data(data),
+ flags(flags) {}
+
NamedPropertyHandlerConfiguration(
/** Note: getter is required */
GenericNamedPropertyGetterCallback getter = 0,
@@ -6045,6 +6065,25 @@ struct NamedPropertyHandlerConfiguration {
struct IndexedPropertyHandlerConfiguration {
+ IndexedPropertyHandlerConfiguration(
+ IndexedPropertyGetterCallback getter,
+ IndexedPropertySetterCallback setter, IndexedPropertyQueryCallback query,
+ IndexedPropertyDeleterCallback deleter,
+ IndexedPropertyEnumeratorCallback enumerator,
+ IndexedPropertyDefinerCallback definer,
+ IndexedPropertyDescriptorCallback descriptor,
+ Local<Value> data = Local<Value>(),
+ PropertyHandlerFlags flags = PropertyHandlerFlags::kNone)
+ : getter(getter),
+ setter(setter),
+ query(query),
+ deleter(deleter),
+ enumerator(enumerator),
+ definer(definer),
+ descriptor(descriptor),
+ data(data),
+ flags(flags) {}
+
IndexedPropertyHandlerConfiguration(
/** Note: getter is required */
IndexedPropertyGetterCallback getter = 0,
diff --git a/src/api.cc b/src/api.cc
index 7c569e3a9f0824e1c61b665236589e3b7c1cc464..6155cbb32579effc500b5c475cd478e77b3ecdf4 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1879,10 +1879,6 @@ static i::Handle<i::InterceptorInfo> CreateInterceptorInfo(
i::Isolate* isolate, Getter getter, Setter setter, Query query,
Descriptor descriptor, Deleter remover, Enumerator enumerator,
Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
- // Either intercept attributes or descriptor.
- DCHECK(query == nullptr || descriptor == nullptr);
- // Only use descriptor callback with definer callback.
- DCHECK(query == nullptr || definer == nullptr);
auto obj = i::Handle<i::InterceptorInfo>::cast(
isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE, i::TENURED));
obj->set_flags(0);
diff --git a/src/objects.cc b/src/objects.cc
index 01421bacc4495150fe9dc05469e216c66d513c64..0aac39d30427e0a02b8c99b0b08ea40712ab1dad 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -7817,41 +7817,42 @@ Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
}
}
- if (it->state() == LookupIterator::INTERCEPTOR) {
- Isolate* isolate = it->isolate();
- Handle<InterceptorInfo> interceptor = it->GetInterceptor();
- if (!interceptor->descriptor()->IsUndefined(isolate)) {
- Handle<Object> result;
- Handle<JSObject> holder = it->GetHolder<JSObject>();
+ if (it->state() != LookupIterator::INTERCEPTOR) return Just(false);
- Handle<Object> receiver = it->GetReceiver();
- if (!receiver->IsJSReceiver()) {
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, receiver, Object::ConvertReceiver(isolate, receiver),
- Nothing<bool>());
- }
+ Isolate* isolate = it->isolate();
+ Handle<InterceptorInfo> interceptor = it->GetInterceptor();
+ if (interceptor->descriptor()->IsUndefined(isolate)) return Just(false);
- PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
- *holder, kDontThrow);
- if (it->IsElement()) {
- result = args.CallIndexedDescriptor(interceptor, it->index());
- } else {
- result = args.CallNamedDescriptor(interceptor, it->name());
- }
- if (!result.is_null()) {
- // Request successfully intercepted, try to set the property
- // descriptor.
- Utils::ApiCheck(
- PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
- it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
- : "v8::NamedPropertyDescriptorCallback",
- "Invalid property descriptor.");
+ Handle<Object> result;
+ Handle<JSObject> holder = it->GetHolder<JSObject>();
- return Just(true);
- }
- it->Next();
- }
+ Handle<Object> receiver = it->GetReceiver();
+ if (!receiver->IsJSReceiver()) {
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
+ Object::ConvertReceiver(isolate, receiver),
+ Nothing<bool>());
+ }
+
+ PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+ *holder, kDontThrow);
+ if (it->IsElement()) {
+ result = args.CallIndexedDescriptor(interceptor, it->index());
+ } else {
+ result = args.CallNamedDescriptor(interceptor, it->name());
}
+ if (!result.is_null()) {
+ // Request successfully intercepted, try to set the property
+ // descriptor.
+ Utils::ApiCheck(
+ PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
+ it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
+ : "v8::NamedPropertyDescriptorCallback",
+ "Invalid property descriptor.");
+
+ return Just(true);
+ }
+
+ it->Next();
return Just(false);
}
} // namespace
diff --git a/test/unittests/api/interceptor-unittest.cc b/test/unittests/api/interceptor-unittest.cc
index 2f9f0e459e6fed4c688fc0ee7389593cf86e07c8..b13384f18adfefe69dc5be232a5f620a7efd8ba7 100644
--- a/test/unittests/api/interceptor-unittest.cc
+++ b/test/unittests/api/interceptor-unittest.cc
@@ -29,4 +29,180 @@ TEST_F(InterceptorTest, FreezeApiObjectWithInterceptor) {
}
} // namespace
+
+namespace internal {
+namespace {
+
+class InterceptorLoggingTest : public TestWithNativeContext {
+ public:
+ InterceptorLoggingTest() {}
+
+ static const int kTestIndex = 0;
+
+ static void NamedPropertyGetter(Local<v8::Name> name,
+ const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "named getter");
+ }
+
+ static void NamedPropertySetter(Local<v8::Name> name, Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "named setter");
+ }
+
+ static void NamedPropertyQuery(
+ Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ LogCallback(info, "named query");
+ }
+
+ static void NamedPropertyDeleter(
+ Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+ LogCallback(info, "named deleter");
+ }
+
+ static void NamedPropertyEnumerator(
+ const v8::PropertyCallbackInfo<Array>& info) {
+ LogCallback(info, "named enumerator");
+ }
+
+ static void NamedPropertyDefiner(
+ Local<v8::Name> name, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "named definer");
+ }
+
+ static void NamedPropertyDescriptor(
+ Local<v8::Name> name, const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "named descriptor");
+ }
+
+ static void IndexedPropertyGetter(
+ uint32_t index, const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "indexed getter");
+ }
+
+ static void IndexedPropertySetter(
+ uint32_t index, Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "indexed setter");
+ }
+
+ static void IndexedPropertyQuery(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ LogCallback(info, "indexed query");
+ }
+
+ static void IndexedPropertyDeleter(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+ LogCallback(info, "indexed deleter");
+ }
+
+ static void IndexedPropertyEnumerator(
+ const v8::PropertyCallbackInfo<Array>& info) {
+ LogCallback(info, "indexed enumerator");
+ }
+
+ static void IndexedPropertyDefiner(
+ uint32_t index, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "indexed definer");
+ }
+
+ static void IndexedPropertyDescriptor(
+ uint32_t index, const v8::PropertyCallbackInfo<Value>& info) {
+ LogCallback(info, "indexed descriptor");
+ }
+
+ template <class T>
+ static void LogCallback(const v8::PropertyCallbackInfo<T>& info,
+ const char* callback_name) {
+ InterceptorLoggingTest* test = reinterpret_cast<InterceptorLoggingTest*>(
+ info.This()->GetAlignedPointerFromInternalField(kTestIndex));
+ test->Log(callback_name);
+ }
+
+ void Log(const char* callback_name) {
+ if (log_is_empty_) {
+ log_is_empty_ = false;
+ } else {
+ log_ << ", ";
+ }
+ log_ << callback_name;
+ }
+
+ protected:
+ void SetUp() override {
+ // Set up the object that supports full interceptors.
+ v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(v8_isolate());
+ templ->SetInternalFieldCount(1);
+ templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+ NamedPropertyGetter, NamedPropertySetter, NamedPropertyQuery,
+ NamedPropertyDeleter, NamedPropertyEnumerator, NamedPropertyDefiner,
+ NamedPropertyDescriptor));
+ templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
+ IndexedPropertyGetter, IndexedPropertySetter, IndexedPropertyQuery,
+ IndexedPropertyDeleter, IndexedPropertyEnumerator,
+ IndexedPropertyDefiner, IndexedPropertyDescriptor));
+ v8::Local<v8::Object> instance =
+ templ->NewInstance(context()).ToLocalChecked();
+ instance->SetAlignedPointerInInternalField(kTestIndex, this);
+ SetGlobalProperty("obj", instance);
+ }
+
+ std::string Run(const char* script) {
+ log_is_empty_ = true;
+ log_.str(std::string());
+ log_.clear();
+
+ RunJS(script);
+ return log_.str();
+ }
+
+ private:
+ bool log_is_empty_ = false;
+ std::stringstream log_;
+};
+
+TEST_F(InterceptorLoggingTest, DispatchTest) {
+ EXPECT_EQ(Run("for (var p in obj) {}"),
+ "indexed enumerator, named enumerator");
+ EXPECT_EQ(Run("Object.keys(obj)"), "indexed enumerator, named enumerator");
+
+ EXPECT_EQ(Run("obj.foo"), "named getter");
+ EXPECT_EQ(Run("obj[42]"), "indexed getter");
+
+ EXPECT_EQ(Run("obj.foo = null"), "named setter");
+ EXPECT_EQ(Run("obj[42] = null"), "indexed setter");
+
+ EXPECT_EQ(Run("Object.getOwnPropertyDescriptor(obj, 'foo')"),
+ "named descriptor");
+
+ EXPECT_EQ(Run("Object.getOwnPropertyDescriptor(obj, 42)"),
+ "indexed descriptor");
+
+ EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {value: 42})"),
+ "named descriptor, named definer, named setter");
+ EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {get(){} })"),
+ "named descriptor, named definer");
+ EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {set(value){}})"),
+ "named descriptor, named definer");
+ EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {get(){}, set(value){}})"),
+ "named descriptor, named definer");
+
+ EXPECT_EQ(Run("Object.defineProperty(obj, 42, {value: 'foo'})"),
+ "indexed descriptor, "
+ // then attempt definer first and fallback to setter.
+ "indexed definer, indexed setter");
+
+ EXPECT_EQ(Run("Object.prototype.propertyIsEnumerable.call(obj, 'a')"),
+ "named query");
+ EXPECT_EQ(Run("Object.prototype.propertyIsEnumerable.call(obj, 42)"),
+ "indexed query");
+
+ EXPECT_EQ(Run("Object.prototype.hasOwnProperty.call(obj, 'a')"),
+ "named query");
+ // TODO(cbruni): Fix once hasOnwProperty is fixed (https://crbug.com/872628)
+ EXPECT_EQ(Run("Object.prototype.hasOwnProperty.call(obj, '42')"), "");
+}
+} // namespace
+} // namespace internal
} // namespace v8
--
2.17.0

View file

@ -1,5 +1,12 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nitish Sakhawalkar <nitsakh@icloud.com>
Date: Mon, 22 Oct 2018 10:47:12 -0700
Subject: disable-warning-win.patch
Disable unit test windows build warning
diff --git a/test/unittests/base/bits-unittest.cc b/test/unittests/base/bits-unittest.cc
index 45fb921797..8c9f249609 100644
index 6f787eb72783570812f7cbda57b836df56b5f2cb..c36dfcc836d6351d11d2178a8e6c3556b3ff3422 100644
--- a/test/unittests/base/bits-unittest.cc
+++ b/test/unittests/base/bits-unittest.cc
@@ -13,7 +13,9 @@
@ -13,3 +20,6 @@ index 45fb921797..8c9f249609 100644
namespace v8 {
namespace base {
namespace bits {
--
2.17.0

View file

@ -1,5 +1,12 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aleksei Kuzmin <alkuzmin@microsoft.com>
Date: Mon, 22 Oct 2018 10:47:12 -0700
Subject: export_platform.patch
v8::Platform::SystemClockTimeMillis must be exported so that node::NodePlatform can call it
diff --git a/include/v8-platform.h b/include/v8-platform.h
index ddc200abab..046de4e257 100644
index cfeb13b65829f9e0bad2518b8c4b03a645b6223c..2b38e24e233b5ba7061fd4a3d5e49063b0165f11 100644
--- a/include/v8-platform.h
+++ b/include/v8-platform.h
@@ -11,6 +11,7 @@
@ -10,7 +17,7 @@ index ddc200abab..046de4e257 100644
#include "v8config.h" // NOLINT(build/include)
namespace v8 {
@@ -465,7 +466,7 @@ class Platform {
@@ -387,7 +388,7 @@ class Platform {
* since epoch. Useful for implementing |CurrentClockTimeMillis| if
* nothing special needed.
*/
@ -19,3 +26,6 @@ index ddc200abab..046de4e257 100644
};
} // namespace v8
--
2.17.0

View file

@ -1,8 +1,15 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Mon, 22 Oct 2018 10:47:13 -0700
Subject: expose_mksnapshot.patch
Needed in order to build mksnapshot on arm.
diff --git a/BUILD.gn b/BUILD.gn
index 30e9ec34cf..fea543df9c 100644
index d0ba5ed04e7126deae4a0ab9ee8943cda5ea42e3..b5eb09cfcb8add19f4de985cbe7b9777c51c4bd3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2904,8 +2904,6 @@ if (v8_monolithic) {
@@ -3130,8 +3130,6 @@ if (v8_monolithic) {
if (v8_use_snapshot && current_toolchain == v8_snapshot_toolchain) {
v8_executable("mksnapshot") {
@ -11,3 +18,6 @@ index 30e9ec34cf..fea543df9c 100644
sources = [
"src/snapshot/mksnapshot.cc",
]
--
2.17.0

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,11 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cheng Zhao <zcbenz@gmail.com>
Date: Mon, 22 Oct 2018 10:47:12 -0700
Subject: ostreams.patch
diff --git a/src/ostreams.h b/src/ostreams.h
index c6b64a1cd9..236a73d018 100644
index c6b64a1cd95b92ed37abe56d71dd6132c4ff9db4..236a73d01800f58a4f37c8abdd8df346d8fcf2c5 100644
--- a/src/ostreams.h
+++ b/src/ostreams.h
@@ -32,7 +32,7 @@ class OFStreamBase : public std::streambuf {
@ -11,3 +17,6 @@ index c6b64a1cd9..236a73d018 100644
public:
explicit OFStream(FILE* f);
virtual ~OFStream();
--
2.17.0