summaryrefslogtreecommitdiff
path: root/deps/v8/tools
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2019-09-24 11:56:38 -0400
committerMyles Borins <myles.borins@gmail.com>2019-10-07 03:19:23 -0400
commitf7f6c928c1c9c136b7926f892b8a2fda11d8b4b2 (patch)
treef5edbccb3ffda2573d70a6e291e7157f290e0ae0 /deps/v8/tools
parentffd22e81983056d09c064c59343a0e488236272d (diff)
downloadandroid-node-v8-f7f6c928c1c9c136b7926f892b8a2fda11d8b4b2.tar.gz
android-node-v8-f7f6c928c1c9c136b7926f892b8a2fda11d8b4b2.tar.bz2
android-node-v8-f7f6c928c1c9c136b7926f892b8a2fda11d8b4b2.zip
deps: update V8 to 7.8.279.9
PR-URL: https://github.com/nodejs/node/pull/29694 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Diffstat (limited to 'deps/v8/tools')
-rw-r--r--deps/v8/tools/BUILD.gn1
-rw-r--r--deps/v8/tools/OWNERS2
-rw-r--r--deps/v8/tools/clusterfuzz/BUILD.gn1
-rw-r--r--deps/v8/tools/clusterfuzz/OWNERS2
-rw-r--r--deps/v8/tools/clusterfuzz/testdata/failure_output.txt4
-rw-r--r--deps/v8/tools/clusterfuzz/testdata/sanity_check_output.txt4
-rwxr-xr-xdeps/v8/tools/clusterfuzz/v8_foozzie.py2
-rw-r--r--deps/v8/tools/clusterfuzz/v8_suppressions.py1
-rw-r--r--deps/v8/tools/debug_helper/BUILD.gn104
-rw-r--r--deps/v8/tools/debug_helper/DEPS3
-rw-r--r--deps/v8/tools/debug_helper/README.md6
-rw-r--r--deps/v8/tools/debug_helper/debug-helper-internal.cc58
-rw-r--r--deps/v8/tools/debug_helper/debug-helper-internal.h130
-rw-r--r--deps/v8/tools/debug_helper/debug-helper.h177
-rw-r--r--deps/v8/tools/debug_helper/gen-heap-constants.py63
-rw-r--r--deps/v8/tools/debug_helper/get-object-properties.cc535
-rw-r--r--deps/v8/tools/debug_helper/heap-constants.cc51
-rw-r--r--deps/v8/tools/debug_helper/heap-constants.h28
-rw-r--r--deps/v8/tools/gcmole/BUILD.gn4
-rw-r--r--deps/v8/tools/gcmole/GCMOLE.gn6
-rw-r--r--deps/v8/tools/gcmole/README6
-rw-r--r--deps/v8/tools/gcmole/gcmole-test.cc69
-rw-r--r--deps/v8/tools/gcmole/gcmole-tools.tar.gz.sha12
-rw-r--r--deps/v8/tools/gcmole/gcmole.cc91
-rw-r--r--deps/v8/tools/gcmole/gcmole.lua69
-rw-r--r--deps/v8/tools/gcmole/suspects.whitelist4
-rw-r--r--deps/v8/tools/gcmole/test-expectations.txt20
-rw-r--r--deps/v8/tools/gen-postmortem-metadata.py2
-rw-r--r--deps/v8/tools/heap-stats/categories.js2
-rw-r--r--deps/v8/tools/heap-stats/global-timeline.js18
-rw-r--r--deps/v8/tools/heap-stats/trace-file-reader.js17
-rwxr-xr-xdeps/v8/tools/run-wasm-api-tests.py3
-rw-r--r--deps/v8/tools/testrunner/OWNERS2
-rw-r--r--deps/v8/tools/testrunner/base_runner.py6
-rw-r--r--deps/v8/tools/testrunner/local/junit_output.py49
-rw-r--r--deps/v8/tools/testrunner/local/pool.py13
-rw-r--r--deps/v8/tools/testrunner/local/variants.py2
-rw-r--r--deps/v8/tools/testrunner/testproc/base.py14
-rw-r--r--deps/v8/tools/testrunner/testproc/execution.py2
-rw-r--r--deps/v8/tools/testrunner/testproc/progress.py44
-rw-r--r--deps/v8/tools/testrunner/testproc/timeout.py8
-rwxr-xr-xdeps/v8/tools/torque/format-torque.py27
-rw-r--r--deps/v8/tools/turbolizer/info-view.html2
-rw-r--r--deps/v8/tools/turbolizer/package-lock.json47
-rw-r--r--deps/v8/tools/turbolizer/src/disassembly-view.ts58
-rw-r--r--deps/v8/tools/turbolizer/src/sequence-view.ts2
-rw-r--r--deps/v8/tools/turbolizer/src/source-resolver.ts119
-rw-r--r--deps/v8/tools/turbolizer/src/text-view.ts14
-rw-r--r--deps/v8/tools/turbolizer/turbo-visualizer.css58
-rw-r--r--deps/v8/tools/v8heapconst.py654
-rwxr-xr-xdeps/v8/tools/wasm/update-wasm-spec-tests.sh46
-rw-r--r--deps/v8/tools/whitespace.txt4
-rw-r--r--deps/v8/tools/windbg.js448
53 files changed, 2486 insertions, 618 deletions
diff --git a/deps/v8/tools/BUILD.gn b/deps/v8/tools/BUILD.gn
index e6fd743715..8d18f4df75 100644
--- a/deps/v8/tools/BUILD.gn
+++ b/deps/v8/tools/BUILD.gn
@@ -10,6 +10,7 @@ group("gn_all") {
data_deps = [
":v8_check_static_initializers",
+ "debug_helper:v8_debug_helper",
"gcmole:v8_run_gcmole",
"jsfunfuzz:v8_jsfunfuzz",
]
diff --git a/deps/v8/tools/OWNERS b/deps/v8/tools/OWNERS
index bd9cea5b3e..89ee345b00 100644
--- a/deps/v8/tools/OWNERS
+++ b/deps/v8/tools/OWNERS
@@ -1,2 +1,2 @@
-file://COMMON_OWNERS
+file:../COMMON_OWNERS
diff --git a/deps/v8/tools/clusterfuzz/BUILD.gn b/deps/v8/tools/clusterfuzz/BUILD.gn
index 88219600a2..e0c4531555 100644
--- a/deps/v8/tools/clusterfuzz/BUILD.gn
+++ b/deps/v8/tools/clusterfuzz/BUILD.gn
@@ -13,6 +13,7 @@ if (v8_correctness_fuzzer) {
"v8_fuzz_config.py",
"v8_mock.js",
"v8_mock_archs.js",
+ "v8_sanity_checks.js",
"v8_suppressions.js",
"v8_suppressions.py",
]
diff --git a/deps/v8/tools/clusterfuzz/OWNERS b/deps/v8/tools/clusterfuzz/OWNERS
index bdb1d555a4..09e0096a2e 100644
--- a/deps/v8/tools/clusterfuzz/OWNERS
+++ b/deps/v8/tools/clusterfuzz/OWNERS
@@ -1 +1 @@
-file://INFRA_OWNERS
+file:../../INFRA_OWNERS
diff --git a/deps/v8/tools/clusterfuzz/testdata/failure_output.txt b/deps/v8/tools/clusterfuzz/testdata/failure_output.txt
index fe94bb9ecc..de3c15eab2 100644
--- a/deps/v8/tools/clusterfuzz/testdata/failure_output.txt
+++ b/deps/v8/tools/clusterfuzz/testdata/failure_output.txt
@@ -9,9 +9,9 @@
# Compared x64,ignition with x64,ignition_turbo
#
# Flags of x64,ignition:
---correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --turbo-filter=~ --noopt --liftoff --no-wasm-tier-up --flag1 --flag2=0
+--correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --turbo-filter=~ --noopt --liftoff --no-wasm-tier-up --flag1 --flag2=0
# Flags of x64,ignition_turbo:
---correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --flag3
+--correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --flag3
#
# Difference:
- unknown
diff --git a/deps/v8/tools/clusterfuzz/testdata/sanity_check_output.txt b/deps/v8/tools/clusterfuzz/testdata/sanity_check_output.txt
index 636f4c9d9e..1443c61f2b 100644
--- a/deps/v8/tools/clusterfuzz/testdata/sanity_check_output.txt
+++ b/deps/v8/tools/clusterfuzz/testdata/sanity_check_output.txt
@@ -9,9 +9,9 @@
# Compared x64,ignition with x64,ignition_turbo
#
# Flags of x64,ignition:
---correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --turbo-filter=~ --noopt --liftoff --no-wasm-tier-up
+--correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --turbo-filter=~ --noopt --liftoff --no-wasm-tier-up
# Flags of x64,ignition_turbo:
---correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345
+--correctness-fuzzer-suppressions --expose-gc --allow-natives-syntax --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345
#
# Difference:
- unknown
diff --git a/deps/v8/tools/clusterfuzz/v8_foozzie.py b/deps/v8/tools/clusterfuzz/v8_foozzie.py
index 55f76e8bc6..ff481e9370 100755
--- a/deps/v8/tools/clusterfuzz/v8_foozzie.py
+++ b/deps/v8/tools/clusterfuzz/v8_foozzie.py
@@ -105,7 +105,7 @@ SANITY_CHECKS = os.path.join(BASE_PATH, 'v8_sanity_checks.js')
FLAGS = ['--correctness-fuzzer-suppressions', '--expose-gc',
'--allow-natives-syntax', '--invoke-weak-callbacks', '--omit-quit',
- '--es-staging', '--no-wasm-async-compilation',
+ '--es-staging', '--wasm-staging', '--no-wasm-async-compilation',
'--suppress-asm-messages']
SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64']
diff --git a/deps/v8/tools/clusterfuzz/v8_suppressions.py b/deps/v8/tools/clusterfuzz/v8_suppressions.py
index 04f67b2cf9..f1aaa6448a 100644
--- a/deps/v8/tools/clusterfuzz/v8_suppressions.py
+++ b/deps/v8/tools/clusterfuzz/v8_suppressions.py
@@ -101,6 +101,7 @@ ALLOWED_LINE_DIFFS = [
r'^(.*)TypeError: .* is not a function$',
r'^(.*)TypeError: .* is not a constructor$',
r'^(.*)TypeError: (.*) is not .*$',
+ r'^(.*):\d+: TypeError: Message suppressed for fuzzers.*$',
r'^(.*)ReferenceError: .* is not defined$',
r'^(.*):\d+: ReferenceError: .* is not defined$',
diff --git a/deps/v8/tools/debug_helper/BUILD.gn b/deps/v8/tools/debug_helper/BUILD.gn
new file mode 100644
index 0000000000..c81fddc9e5
--- /dev/null
+++ b/deps/v8/tools/debug_helper/BUILD.gn
@@ -0,0 +1,104 @@
+# Copyright 2019 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.
+
+import("../../gni/snapshot_toolchain.gni")
+import("../../gni/v8.gni")
+
+config("internal_config") {
+ visibility = [ ":*" ] # Only targets in this file can depend on this.
+
+ if (is_component_build) {
+ defines = [ "BUILDING_V8_DEBUG_HELPER" ]
+ }
+
+ include_dirs = [
+ ".",
+ "../..",
+ "$target_gen_dir",
+ "$target_gen_dir/../..",
+ ]
+}
+
+# This config should be applied to code using v8_debug_helper.
+config("external_config") {
+ if (is_component_build) {
+ defines = [ "USING_V8_DEBUG_HELPER" ]
+ }
+ include_dirs = [ "." ]
+}
+
+action("run_mkgrokdump") {
+ testonly = true
+ visibility = [ ":*" ]
+
+ deps = [
+ "../../test/mkgrokdump:mkgrokdump($v8_generator_toolchain)",
+ ]
+
+ script = "../run.py"
+
+ outputs = [
+ "$target_gen_dir/v8heapconst.py",
+ ]
+
+ args = [
+ "./" + rebase_path(
+ get_label_info(
+ "../../test/mkgrokdump:mkgrokdump($v8_generator_toolchain)",
+ "root_out_dir") + "/mkgrokdump",
+ root_build_dir),
+ "--outfile",
+ rebase_path("$target_gen_dir/v8heapconst.py", root_build_dir),
+ ]
+}
+
+action("gen_heap_constants") {
+ testonly = true
+ visibility = [ ":*" ]
+ deps = [
+ ":run_mkgrokdump",
+ ]
+ script = "gen-heap-constants.py"
+ outputs = [
+ "$target_gen_dir/heap-constants-gen.cc",
+ ]
+ args = [
+ rebase_path(target_gen_dir, root_build_dir),
+ rebase_path("$target_gen_dir/heap-constants-gen.cc", root_build_dir),
+ ]
+}
+
+v8_component("v8_debug_helper") {
+ testonly = true
+
+ public = [
+ "debug-helper.h",
+ ]
+
+ sources = [
+ "$target_gen_dir/../../torque-generated/class-debug-readers-tq.cc",
+ "$target_gen_dir/../../torque-generated/class-debug-readers-tq.h",
+ "$target_gen_dir/heap-constants-gen.cc",
+ "debug-helper-internal.cc",
+ "debug-helper-internal.h",
+ "debug-helper.h",
+ "get-object-properties.cc",
+ "heap-constants.cc",
+ "heap-constants.h",
+ ]
+
+ deps = [
+ ":gen_heap_constants",
+ "../..:run_torque",
+ "../..:v8_headers",
+ "../..:v8_libbase",
+ ]
+
+ configs = [ ":internal_config" ]
+ if (v8_enable_i18n_support) {
+ configs += [ "//third_party/icu:icu_config" ]
+ }
+
+ public_configs = [ ":external_config" ]
+}
diff --git a/deps/v8/tools/debug_helper/DEPS b/deps/v8/tools/debug_helper/DEPS
new file mode 100644
index 0000000000..2c6adb4df5
--- /dev/null
+++ b/deps/v8/tools/debug_helper/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+torque-generated"
+]
diff --git a/deps/v8/tools/debug_helper/README.md b/deps/v8/tools/debug_helper/README.md
new file mode 100644
index 0000000000..bc99569c43
--- /dev/null
+++ b/deps/v8/tools/debug_helper/README.md
@@ -0,0 +1,6 @@
+# V8 debug helper
+
+This library is for debugging V8 itself, not debugging JavaScript running within
+V8. It is designed to be called from a debugger extension running within a
+native debugger such as WinDbg or LLDB. It can be used on live processes or
+crash dumps, and cannot assume that all memory is available in a dump.
diff --git a/deps/v8/tools/debug_helper/debug-helper-internal.cc b/deps/v8/tools/debug_helper/debug-helper-internal.cc
new file mode 100644
index 0000000000..ee5629b438
--- /dev/null
+++ b/deps/v8/tools/debug_helper/debug-helper-internal.cc
@@ -0,0 +1,58 @@
+// Copyright 2019 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 "debug-helper-internal.h"
+#include "src/common/ptr-compr-inl.h"
+#include "torque-generated/class-debug-readers-tq.h"
+
+namespace i = v8::internal;
+
+namespace v8_debug_helper_internal {
+
+bool IsPointerCompressed(uintptr_t address) {
+#if COMPRESS_POINTERS_BOOL
+ STATIC_ASSERT(i::kPtrComprHeapReservationSize == uintptr_t{1} << 32);
+ intptr_t signed_address = static_cast<intptr_t>(address);
+ return signed_address >= INT32_MIN && signed_address <= INT32_MAX;
+#else
+ return false;
+#endif
+}
+
+uintptr_t Decompress(uintptr_t address, uintptr_t any_uncompressed_ptr) {
+ if (!COMPRESS_POINTERS_BOOL || !IsPointerCompressed(address)) return address;
+ return i::DecompressTaggedAny(any_uncompressed_ptr,
+ static_cast<i::Tagged_t>(address));
+}
+
+d::PropertyKind GetArrayKind(d::MemoryAccessResult mem_result) {
+ d::PropertyKind indexed_field_kind{};
+ switch (mem_result) {
+ case d::MemoryAccessResult::kOk:
+ indexed_field_kind = d::PropertyKind::kArrayOfKnownSize;
+ break;
+ case d::MemoryAccessResult::kAddressNotValid:
+ indexed_field_kind =
+ d::PropertyKind::kArrayOfUnknownSizeDueToInvalidMemory;
+ break;
+ default:
+ indexed_field_kind =
+ d::PropertyKind::kArrayOfUnknownSizeDueToValidButInaccessibleMemory;
+ break;
+ }
+ return indexed_field_kind;
+}
+
+std::vector<std::unique_ptr<ObjectProperty>> TqObject::GetProperties(
+ d::MemoryAccessor accessor) const {
+ return std::vector<std::unique_ptr<ObjectProperty>>();
+}
+
+const char* TqObject::GetName() const { return "v8::internal::Object"; }
+
+void TqObject::Visit(TqObjectVisitor* visitor) const {
+ visitor->VisitObject(this);
+}
+
+} // namespace v8_debug_helper_internal
diff --git a/deps/v8/tools/debug_helper/debug-helper-internal.h b/deps/v8/tools/debug_helper/debug-helper-internal.h
new file mode 100644
index 0000000000..82506c0941
--- /dev/null
+++ b/deps/v8/tools/debug_helper/debug-helper-internal.h
@@ -0,0 +1,130 @@
+// Copyright 2019 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.
+
+// This file defines internal versions of the public API structs. These should
+// all be tidy and simple classes which maintain proper ownership (unique_ptr)
+// of each other. Each contains an instance of its corresponding public type,
+// which can be filled out with GetPublicView.
+
+#ifndef V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_INTERNAL_H_
+#define V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_INTERNAL_H_
+
+#include <string>
+#include <vector>
+
+#include "debug-helper.h"
+#include "src/objects/instance-type.h"
+
+namespace d = v8::debug_helper;
+
+namespace v8_debug_helper_internal {
+
+// A value that was read from the debuggee's memory.
+template <typename TValue>
+struct Value {
+ d::MemoryAccessResult validity;
+ TValue value;
+};
+
+class ObjectProperty {
+ public:
+ inline ObjectProperty(std::string name, std::string type,
+ std::string decompressed_type, uintptr_t address,
+ size_t num_values = 1,
+ d::PropertyKind kind = d::PropertyKind::kSingle)
+ : name_(name),
+ type_(type),
+ decompressed_type_(decompressed_type),
+ address_(address),
+ num_values_(num_values),
+ kind_(kind) {}
+
+ inline d::ObjectProperty* GetPublicView() {
+ public_view_.name = name_.c_str();
+ public_view_.type = type_.c_str();
+ public_view_.decompressed_type = decompressed_type_.c_str();
+ public_view_.address = address_;
+ public_view_.num_values = num_values_;
+ public_view_.kind = kind_;
+ return &public_view_;
+ }
+
+ private:
+ std::string name_;
+ std::string type_;
+ std::string decompressed_type_;
+ uintptr_t address_;
+ size_t num_values_;
+ d::PropertyKind kind_;
+
+ d::ObjectProperty public_view_;
+};
+
+class ObjectPropertiesResult;
+using ObjectPropertiesResultInternal = ObjectPropertiesResult;
+
+struct ObjectPropertiesResultExtended : public d::ObjectPropertiesResult {
+ ObjectPropertiesResultInternal* base; // Back reference for cleanup
+};
+
+class ObjectPropertiesResult {
+ public:
+ inline ObjectPropertiesResult(
+ d::TypeCheckResult type_check_result, std::string brief, std::string type,
+ std::vector<std::unique_ptr<ObjectProperty>> properties)
+ : type_check_result_(type_check_result),
+ brief_(brief),
+ type_(type),
+ properties_(std::move(properties)) {}
+
+ inline void Prepend(const char* prefix) { brief_ = prefix + brief_; }
+
+ inline d::ObjectPropertiesResult* GetPublicView() {
+ public_view_.type_check_result = type_check_result_;
+ public_view_.brief = brief_.c_str();
+ public_view_.type = type_.c_str();
+ public_view_.num_properties = properties_.size();
+ properties_raw_.resize(0);
+ for (const auto& property : properties_) {
+ properties_raw_.push_back(property->GetPublicView());
+ }
+ public_view_.properties = properties_raw_.data();
+ public_view_.base = this;
+ return &public_view_;
+ }
+
+ private:
+ d::TypeCheckResult type_check_result_;
+ std::string brief_;
+ std::string type_;
+ std::vector<std::unique_ptr<ObjectProperty>> properties_;
+
+ ObjectPropertiesResultExtended public_view_;
+ std::vector<d::ObjectProperty*> properties_raw_;
+};
+
+class TqObjectVisitor;
+
+// Base class representing a V8 object in the debuggee's address space.
+// Subclasses for specific object types are generated by the Torque compiler.
+class TqObject {
+ public:
+ inline TqObject(uintptr_t address) : address_(address) {}
+ virtual ~TqObject() = default;
+ virtual std::vector<std::unique_ptr<ObjectProperty>> GetProperties(
+ d::MemoryAccessor accessor) const;
+ virtual const char* GetName() const;
+ virtual void Visit(TqObjectVisitor* visitor) const;
+
+ protected:
+ uintptr_t address_;
+};
+
+bool IsPointerCompressed(uintptr_t address);
+uintptr_t Decompress(uintptr_t address, uintptr_t any_uncompressed_address);
+d::PropertyKind GetArrayKind(d::MemoryAccessResult mem_result);
+
+} // namespace v8_debug_helper_internal
+
+#endif
diff --git a/deps/v8/tools/debug_helper/debug-helper.h b/deps/v8/tools/debug_helper/debug-helper.h
new file mode 100644
index 0000000000..9bbec76c7c
--- /dev/null
+++ b/deps/v8/tools/debug_helper/debug-helper.h
@@ -0,0 +1,177 @@
+// Copyright 2019 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.
+
+// This file defines the public interface to v8_debug_helper.
+
+#ifndef V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_H_
+#define V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_H_
+
+#include <cstdint>
+#include <memory>
+
+#if defined(_WIN32)
+
+#ifdef BUILDING_V8_DEBUG_HELPER
+#define V8_DEBUG_HELPER_EXPORT __declspec(dllexport)
+#elif USING_V8_DEBUG_HELPER
+#define V8_DEBUG_HELPER_EXPORT __declspec(dllimport)
+#else
+#define V8_DEBUG_HELPER_EXPORT
+#endif
+
+#else // defined(_WIN32)
+
+#ifdef BUILDING_V8_DEBUG_HELPER
+#define V8_DEBUG_HELPER_EXPORT __attribute__((visibility("default")))
+#else
+#define V8_DEBUG_HELPER_EXPORT
+#endif
+
+#endif // defined(_WIN32)
+
+namespace v8 {
+namespace debug_helper {
+
+// Possible results when attempting to fetch memory from the debuggee.
+enum class MemoryAccessResult {
+ kOk,
+ kAddressNotValid,
+ kAddressValidButInaccessible, // Possible in incomplete dump.
+};
+
+// Information about how this tool discovered the type of the object.
+enum class TypeCheckResult {
+ // Success cases:
+ kSmi,
+ kWeakRef,
+ kUsedMap,
+ kUsedTypeHint,
+
+ // Failure cases:
+ kUnableToDecompress, // Caller must provide the heap range somehow.
+ kObjectPointerInvalid,
+ kObjectPointerValidButInaccessible, // Possible in incomplete dump.
+ kMapPointerInvalid,
+ kMapPointerValidButInaccessible, // Possible in incomplete dump.
+ kUnknownInstanceType,
+ kUnknownTypeHint,
+};
+
+enum class PropertyKind {
+ kSingle,
+ kArrayOfKnownSize,
+ kArrayOfUnknownSizeDueToInvalidMemory,
+ kArrayOfUnknownSizeDueToValidButInaccessibleMemory,
+};
+
+struct ObjectProperty {
+ const char* name;
+
+ // Statically-determined type, such as from .tq definition.
+ const char* type;
+
+ // In some cases, |type| may be a simple type representing a compressed
+ // pointer such as v8::internal::TaggedValue. In those cases,
+ // |decompressed_type| will contain the type of the object when decompressed.
+ // Otherwise, |decompressed_type| will match |type|. In any case, it is safe
+ // to pass the |decompressed_type| value as the type_hint on a subsequent call
+ // to GetObjectProperties.
+ const char* decompressed_type;
+
+ // The address where the property value can be found in the debuggee's address
+ // space, or the address of the first value for an array.
+ uintptr_t address;
+
+ // If kind indicates an array of unknown size, num_values will be 0 and debug
+ // tools should display this property as a raw pointer. Note that there is a
+ // semantic difference between num_values=1 and kind=kSingle (normal property)
+ // versus num_values=1 and kind=kArrayOfKnownSize (one-element array).
+ size_t num_values;
+
+ PropertyKind kind;
+};
+
+struct ObjectPropertiesResult {
+ TypeCheckResult type_check_result;
+ const char* brief;
+ const char* type; // Runtime type of the object.
+ size_t num_properties;
+ ObjectProperty** properties;
+};
+
+// Copies byte_count bytes of memory from the given address in the debuggee to
+// the destination buffer.
+typedef MemoryAccessResult (*MemoryAccessor)(uintptr_t address,
+ uint8_t* destination,
+ size_t byte_count);
+
+// Additional data that can help GetObjectProperties to be more accurate. Any
+// fields you don't know can be set to zero and this library will do the best it
+// can with the information available.
+struct Roots {
+ // Beginning of allocated space for various kinds of data. These can help us
+ // to detect certain common objects that are placed in memory during startup.
+ // These values might be provided via name-value pairs in CrashPad dumps.
+ // Otherwise, they can be obtained as follows:
+ // 1. Get the Isolate pointer for the current thread. It might be somewhere on
+ // the stack, or it might be accessible from thread-local storage with the
+ // key stored in v8::internal::Isolate::isolate_key_.
+ // 2. Get isolate->heap_.map_space_->memory_chunk_list_.front_ and similar for
+ // old_space_ and read_only_space_.
+ uintptr_t map_space;
+ uintptr_t old_space;
+ uintptr_t read_only_space;
+
+ // Any valid heap pointer address. On platforms where pointer compression is
+ // enabled, this can allow us to get data from compressed pointers even if the
+ // other data above is not provided. The Isolate pointer is valid for this
+ // purpose if you have it.
+ uintptr_t any_heap_pointer;
+};
+
+} // namespace debug_helper
+} // namespace v8
+
+extern "C" {
+// Raw library interface. If possible, use functions in v8::debug_helper
+// namespace instead because they use smart pointers to prevent leaks.
+V8_DEBUG_HELPER_EXPORT v8::debug_helper::ObjectPropertiesResult*
+_v8_debug_helper_GetObjectProperties(
+ uintptr_t object, v8::debug_helper::MemoryAccessor memory_accessor,
+ const v8::debug_helper::Roots& heap_roots, const char* type_hint);
+V8_DEBUG_HELPER_EXPORT void _v8_debug_helper_Free_ObjectPropertiesResult(
+ v8::debug_helper::ObjectPropertiesResult* result);
+}
+
+namespace v8 {
+namespace debug_helper {
+
+struct DebugHelperObjectPropertiesResultDeleter {
+ void operator()(v8::debug_helper::ObjectPropertiesResult* ptr) {
+ _v8_debug_helper_Free_ObjectPropertiesResult(ptr);
+ }
+};
+using ObjectPropertiesResultPtr =
+ std::unique_ptr<ObjectPropertiesResult,
+ DebugHelperObjectPropertiesResultDeleter>;
+
+// Get information about the given object pointer, which could be:
+// - A tagged pointer, strong or weak
+// - A cleared weak pointer
+// - A compressed tagged pointer, sign-extended to 64 bits
+// - A tagged small integer
+// The type hint is only used if the object's Map is missing or corrupt. It
+// should be the fully-qualified name of a class that inherits from
+// v8::internal::Object.
+inline ObjectPropertiesResultPtr GetObjectProperties(
+ uintptr_t object, v8::debug_helper::MemoryAccessor memory_accessor,
+ const Roots& heap_roots, const char* type_hint = nullptr) {
+ return ObjectPropertiesResultPtr(_v8_debug_helper_GetObjectProperties(
+ object, memory_accessor, heap_roots, type_hint));
+}
+
+} // namespace debug_helper
+} // namespace v8
+
+#endif
diff --git a/deps/v8/tools/debug_helper/gen-heap-constants.py b/deps/v8/tools/debug_helper/gen-heap-constants.py
new file mode 100644
index 0000000000..0fd575a994
--- /dev/null
+++ b/deps/v8/tools/debug_helper/gen-heap-constants.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# Copyright 2019 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.
+
+"""This program writes a C++ file that can be used to look up whether a given
+address matches known object locations. The first argument is the directory
+containing the file v8heapconst.py; the second argument is the output .cc file.
+"""
+
+import sys
+sys.path.insert(0, sys.argv[1])
+import v8heapconst
+
+out = """
+#include <cstdint>
+#include <string>
+
+namespace v8_debug_helper_internal {
+"""
+
+def iterate_objects(target_space, camel_space_name):
+ global out
+ result = []
+ for (space, offset), (instance_type, name) in v8heapconst.KNOWN_MAPS.items():
+ if space == target_space:
+ result.append((offset, name))
+ for (space, offset), name in v8heapconst.KNOWN_OBJECTS.items():
+ if space == target_space:
+ result.append((offset, name))
+ out = out + '\nstd::string FindKnownObjectIn' + camel_space_name \
+ + '(uintptr_t offset) {\n switch (offset) {\n'
+ for offset, name in result:
+ out = out + ' case ' + str(offset) + ': return "' + name + '";\n'
+ out = out + ' default: return "";\n }\n}\n'
+
+iterate_objects('map_space', 'MapSpace')
+iterate_objects('read_only_space', 'ReadOnlySpace')
+iterate_objects('old_space', 'OldSpace')
+
+def iterate_maps(target_space, camel_space_name):
+ global out
+ out = out + '\nint FindKnownMapInstanceTypeIn' + camel_space_name \
+ + '(uintptr_t offset) {\n switch (offset) {\n'
+ for (space, offset), (instance_type, name) in v8heapconst.KNOWN_MAPS.items():
+ if space == target_space:
+ out = out + ' case ' + str(offset) + ': return ' + str(instance_type) \
+ + ';\n'
+ out = out + ' default: return -1;\n }\n}\n'
+
+iterate_maps('map_space', 'MapSpace')
+iterate_maps('read_only_space', 'ReadOnlySpace')
+
+out = out + '\n}\n'
+
+try:
+ with open(sys.argv[2], "r") as out_file:
+ if out == out_file.read():
+ sys.exit(0) # No modification needed.
+except:
+ pass # File probably doesn't exist; write it.
+with open(sys.argv[2], "w") as out_file:
+ out_file.write(out)
diff --git a/deps/v8/tools/debug_helper/get-object-properties.cc b/deps/v8/tools/debug_helper/get-object-properties.cc
new file mode 100644
index 0000000000..fbe992c40e
--- /dev/null
+++ b/deps/v8/tools/debug_helper/get-object-properties.cc
@@ -0,0 +1,535 @@
+// Copyright 2019 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 <sstream>
+
+#include "debug-helper-internal.h"
+#include "heap-constants.h"
+#include "include/v8-internal.h"
+#include "src/common/ptr-compr-inl.h"
+#include "src/objects/string-inl.h"
+#include "src/strings/unicode-inl.h"
+#include "torque-generated/class-debug-readers-tq.h"
+
+namespace i = v8::internal;
+
+namespace v8_debug_helper_internal {
+
+// INSTANCE_TYPE_CHECKERS_SINGLE_BASE, trimmed down to only classes that have
+// layouts defined in .tq files (this subset relationship is asserted below).
+// For now, this is a hand-maintained list.
+// TODO(v8:7793): Torque should know enough about instance types to generate
+// this list.
+#define TQ_INSTANCE_TYPES_SINGLE_BASE(V) \
+ V(ByteArray, BYTE_ARRAY_TYPE) \
+ V(BytecodeArray, BYTECODE_ARRAY_TYPE) \
+ V(CallHandlerInfo, CALL_HANDLER_INFO_TYPE) \
+ V(Cell, CELL_TYPE) \
+ V(DescriptorArray, DESCRIPTOR_ARRAY_TYPE) \
+ V(EmbedderDataArray, EMBEDDER_DATA_ARRAY_TYPE) \
+ V(FeedbackCell, FEEDBACK_CELL_TYPE) \
+ V(FeedbackVector, FEEDBACK_VECTOR_TYPE) \
+ V(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) \
+ V(Foreign, FOREIGN_TYPE) \
+ V(FreeSpace, FREE_SPACE_TYPE) \
+ V(HeapNumber, HEAP_NUMBER_TYPE) \
+ V(JSArgumentsObject, JS_ARGUMENTS_TYPE) \
+ V(JSArray, JS_ARRAY_TYPE) \
+ V(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE) \
+ V(JSArrayIterator, JS_ARRAY_ITERATOR_TYPE) \
+ V(JSAsyncFromSyncIterator, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE) \
+ V(JSAsyncFunctionObject, JS_ASYNC_FUNCTION_OBJECT_TYPE) \
+ V(JSAsyncGeneratorObject, JS_ASYNC_GENERATOR_OBJECT_TYPE) \
+ V(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) \
+ V(JSDataView, JS_DATA_VIEW_TYPE) \
+ V(JSDate, JS_DATE_TYPE) \
+ V(JSFunction, JS_FUNCTION_TYPE) \
+ V(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE) \
+ V(JSGlobalProxy, JS_GLOBAL_PROXY_TYPE) \
+ V(JSMap, JS_MAP_TYPE) \
+ V(JSMessageObject, JS_MESSAGE_OBJECT_TYPE) \
+ V(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE) \
+ V(JSPromise, JS_PROMISE_TYPE) \
+ V(JSProxy, JS_PROXY_TYPE) \
+ V(JSRegExp, JS_REGEXP_TYPE) \
+ V(JSRegExpStringIterator, JS_REGEXP_STRING_ITERATOR_TYPE) \
+ V(JSSet, JS_SET_TYPE) \
+ V(JSStringIterator, JS_STRING_ITERATOR_TYPE) \
+ V(JSTypedArray, JS_TYPED_ARRAY_TYPE) \
+ V(JSPrimitiveWrapper, JS_PRIMITIVE_WRAPPER_TYPE) \
+ V(JSFinalizationGroup, JS_FINALIZATION_GROUP_TYPE) \
+ V(JSFinalizationGroupCleanupIterator, \
+ JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE) \
+ V(JSWeakMap, JS_WEAK_MAP_TYPE) \
+ V(JSWeakRef, JS_WEAK_REF_TYPE) \
+ V(JSWeakSet, JS_WEAK_SET_TYPE) \
+ V(Map, MAP_TYPE) \
+ V(Oddball, ODDBALL_TYPE) \
+ V(PreparseData, PREPARSE_DATA_TYPE) \
+ V(PropertyArray, PROPERTY_ARRAY_TYPE) \
+ V(PropertyCell, PROPERTY_CELL_TYPE) \
+ V(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE) \
+ V(Symbol, SYMBOL_TYPE) \
+ V(WasmExceptionObject, WASM_EXCEPTION_TYPE) \
+ V(WasmGlobalObject, WASM_GLOBAL_TYPE) \
+ V(WasmMemoryObject, WASM_MEMORY_TYPE) \
+ V(WasmModuleObject, WASM_MODULE_TYPE) \
+ V(WasmTableObject, WASM_TABLE_TYPE) \
+ V(WeakArrayList, WEAK_ARRAY_LIST_TYPE) \
+ V(WeakCell, WEAK_CELL_TYPE)
+#ifdef V8_INTL_SUPPORT
+
+#define TQ_INSTANCE_TYPES_SINGLE_NOSTRUCTS(V) \
+ TQ_INSTANCE_TYPES_SINGLE_BASE(V) \
+ V(JSV8BreakIterator, JS_INTL_V8_BREAK_ITERATOR_TYPE) \
+ V(JSCollator, JS_INTL_COLLATOR_TYPE) \
+ V(JSDateTimeFormat, JS_INTL_DATE_TIME_FORMAT_TYPE) \
+ V(JSListFormat, JS_INTL_LIST_FORMAT_TYPE) \
+ V(JSLocale, JS_INTL_LOCALE_TYPE) \
+ V(JSNumberFormat, JS_INTL_NUMBER_FORMAT_TYPE) \
+ V(JSPluralRules, JS_INTL_PLURAL_RULES_TYPE) \
+ V(JSRelativeTimeFormat, JS_INTL_RELATIVE_TIME_FORMAT_TYPE) \
+ V(JSSegmentIterator, JS_INTL_SEGMENT_ITERATOR_TYPE) \
+ V(JSSegmenter, JS_INTL_SEGMENTER_TYPE)
+
+#else
+
+#define TQ_INSTANCE_TYPES_SINGLE_NOSTRUCTS(V) TQ_INSTANCE_TYPES_SINGLE_BASE(V)
+
+#endif // V8_INTL_SUPPORT
+
+enum class InstanceTypeCheckersSingle {
+#define ENUM_VALUE(ClassName, INSTANCE_TYPE) k##ClassName = i::INSTANCE_TYPE,
+ INSTANCE_TYPE_CHECKERS_SINGLE(ENUM_VALUE)
+#undef ENUM_VALUE
+};
+
+#define CHECK_VALUE(ClassName, INSTANCE_TYPE) \
+ static_assert( \
+ static_cast<i::InstanceType>( \
+ InstanceTypeCheckersSingle::k##ClassName) == i::INSTANCE_TYPE, \
+ "TQ_INSTANCE_TYPES_SINGLE_NOSTRUCTS must be subset of " \
+ "INSTANCE_TYPE_CHECKERS_SINGLE. Invalid class: " #ClassName);
+TQ_INSTANCE_TYPES_SINGLE_NOSTRUCTS(CHECK_VALUE)
+#undef CHECK_VALUE
+
+// Adapts one STRUCT_LIST_GENERATOR entry to (Name, NAME) format.
+#define STRUCT_INSTANCE_TYPE_ADAPTER(V, NAME, Name, name) V(Name, NAME)
+
+#define TQ_INSTANCE_TYPES_SINGLE(V) \
+ TQ_INSTANCE_TYPES_SINGLE_NOSTRUCTS(V) \
+ STRUCT_LIST_GENERATOR(STRUCT_INSTANCE_TYPE_ADAPTER, V)
+
+// Likewise, these are the subset of INSTANCE_TYPE_CHECKERS_RANGE that have
+// definitions in .tq files, rearranged with more specific things first. Also
+// includes JSObject and JSReceiver, which in the runtime are optimized to use
+// a one-sided check.
+#define TQ_INSTANCE_TYPES_RANGE(V) \
+ V(Context, FIRST_CONTEXT_TYPE, LAST_CONTEXT_TYPE) \
+ V(FixedArray, FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE) \
+ V(Microtask, FIRST_MICROTASK_TYPE, LAST_MICROTASK_TYPE) \
+ V(String, FIRST_STRING_TYPE, LAST_STRING_TYPE) \
+ V(Name, FIRST_NAME_TYPE, LAST_NAME_TYPE) \
+ V(WeakFixedArray, FIRST_WEAK_FIXED_ARRAY_TYPE, LAST_WEAK_FIXED_ARRAY_TYPE) \
+ V(JSObject, FIRST_JS_OBJECT_TYPE, LAST_JS_OBJECT_TYPE) \
+ V(JSReceiver, FIRST_JS_RECEIVER_TYPE, LAST_JS_RECEIVER_TYPE)
+
+std::string AppendAddressAndType(const std::string& brief, uintptr_t address,
+ const char* type) {
+ std::stringstream brief_stream;
+ brief_stream << "0x" << std::hex << address << " <" << type << ">";
+ return brief.empty() ? brief_stream.str()
+ : brief + " (" + brief_stream.str() + ")";
+}
+
+struct TypedObject {
+ TypedObject(d::TypeCheckResult type_check_result,
+ std::unique_ptr<TqObject> object)
+ : type_check_result(type_check_result), object(std::move(object)) {}
+ d::TypeCheckResult type_check_result;
+ std::unique_ptr<TqObject> object;
+};
+
+TypedObject GetTypedObjectByHint(uintptr_t address,
+ std::string type_hint_string) {
+#define TYPE_NAME_CASE(ClassName, ...) \
+ if (type_hint_string == "v8::internal::" #ClassName) { \
+ return {d::TypeCheckResult::kUsedTypeHint, \
+ v8::base::make_unique<Tq##ClassName>(address)}; \
+ }
+
+ TQ_INSTANCE_TYPES_SINGLE(TYPE_NAME_CASE)
+ TQ_INSTANCE_TYPES_RANGE(TYPE_NAME_CASE)
+
+#undef TYPE_NAME_CASE
+
+ return {d::TypeCheckResult::kUnknownTypeHint,
+ v8::base::make_unique<TqHeapObject>(address)};
+}
+
+TypedObject GetTypedObjectForString(uintptr_t address, i::InstanceType type) {
+ class StringGetDispatcher : public i::AllStatic {
+ public:
+#define DEFINE_METHOD(ClassName) \
+ static inline TypedObject Handle##ClassName(uintptr_t address) { \
+ return {d::TypeCheckResult::kUsedMap, \
+ v8::base::make_unique<Tq##ClassName>(address)}; \
+ }
+ STRING_CLASS_TYPES(DEFINE_METHOD)
+#undef DEFINE_METHOD
+ static inline TypedObject HandleInvalidString(uintptr_t address) {
+ return {d::TypeCheckResult::kUnknownInstanceType,
+ v8::base::make_unique<TqString>(address)};
+ }
+ };
+
+ return i::StringShape(type)
+ .DispatchToSpecificTypeWithoutCast<StringGetDispatcher, TypedObject>(
+ address);
+}
+
+TypedObject GetTypedHeapObject(uintptr_t address, d::MemoryAccessor accessor,
+ const char* type_hint) {
+ auto heap_object = v8::base::make_unique<TqHeapObject>(address);
+ Value<uintptr_t> map_ptr = heap_object->GetMapValue(accessor);
+
+ if (map_ptr.validity != d::MemoryAccessResult::kOk) {
+ return {map_ptr.validity == d::MemoryAccessResult::kAddressNotValid
+ ? d::TypeCheckResult::kObjectPointerInvalid
+ : d::TypeCheckResult::kObjectPointerValidButInaccessible,
+ std::move(heap_object)};
+ }
+ Value<i::InstanceType> type =
+ TqMap(map_ptr.value).GetInstanceTypeValue(accessor);
+
+ if (type.validity == d::MemoryAccessResult::kOk) {
+ // Dispatch to the appropriate method for each instance type. After calling
+ // the generated method to fetch properties, we can add custom properties.
+ switch (type.value) {
+#define INSTANCE_TYPE_CASE(ClassName, INSTANCE_TYPE) \
+ case i::INSTANCE_TYPE: \
+ return {d::TypeCheckResult::kUsedMap, \
+ v8::base::make_unique<Tq##ClassName>(address)};
+ TQ_INSTANCE_TYPES_SINGLE(INSTANCE_TYPE_CASE)
+#undef INSTANCE_TYPE_CASE
+
+ default:
+
+ // Special case: concrete subtypes of String are not included in the
+ // main instance type list because they use the low bits of the instance
+ // type enum as flags.
+ if (type.value <= i::LAST_STRING_TYPE) {
+ return GetTypedObjectForString(address, type.value);
+ }
+
+#define INSTANCE_RANGE_CASE(ClassName, FIRST_TYPE, LAST_TYPE) \
+ if (type.value >= i::FIRST_TYPE && type.value <= i::LAST_TYPE) { \
+ return {d::TypeCheckResult::kUsedMap, \
+ v8::base::make_unique<Tq##ClassName>(address)}; \
+ }
+ TQ_INSTANCE_TYPES_RANGE(INSTANCE_RANGE_CASE)
+#undef INSTANCE_RANGE_CASE
+
+ return {d::TypeCheckResult::kUnknownInstanceType,
+ std::move(heap_object)};
+ break;
+ }
+ } else if (type_hint != nullptr) {
+ // Try to use the provided type hint, since the real instance type is
+ // unavailable.
+ return GetTypedObjectByHint(address, type_hint);
+ } else {
+ // TODO(v8:9376): Use known maps here. If known map is just a guess (because
+ // root pointers weren't provided), then create a synthetic property with
+ // the more specific type. Then the caller could presumably ask us again
+ // with the type hint we provided. Otherwise, just go ahead and use it to
+ // generate properties.
+ return {type.validity == d::MemoryAccessResult::kAddressNotValid
+ ? d::TypeCheckResult::kMapPointerInvalid
+ : d::TypeCheckResult::kMapPointerValidButInaccessible,
+ std::move(heap_object)};
+ }
+}
+
+#undef STRUCT_INSTANCE_TYPE_ADAPTER
+#undef TQ_INSTANCE_TYPES_SINGLE_BASE
+#undef TQ_INSTANCE_TYPES_SINGLE
+#undef TQ_INSTANCE_TYPES_SINGLE_NOSTRUCTS
+#undef TQ_INSTANCE_TYPES_RANGE
+
+// An object visitor that accumulates the first few characters of a string.
+class ReadStringVisitor : public TqObjectVisitor {
+ public:
+ ReadStringVisitor(d::MemoryAccessor accessor)
+ : accessor_(accessor), index_(0), limit_(INT32_MAX), done_(false) {}
+
+ // Returns the result as UTF-8 once visiting is complete.
+ std::string GetString() {
+ std::vector<char> result(
+ string_.size() * unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit);
+ unsigned write_index = 0;
+ int prev_char = unibrow::Utf16::kNoPreviousCharacter;
+ for (size_t read_index = 0; read_index < string_.size(); ++read_index) {
+ uint16_t character = string_[read_index];
+ write_index +=
+ unibrow::Utf8::Encode(result.data() + write_index, character,
+ prev_char, /*replace_invalid=*/true);
+ prev_char = character;
+ }
+ return {result.data(), write_index};
+ }
+
+ template <typename T>
+ void ReadSeqString(const T* object) {
+ int32_t length = GetOrFinish(object->GetLengthValue(accessor_));
+ for (; index_ < length && index_ < limit_ && !done_; ++index_) {
+ char16_t c = static_cast<char16_t>(
+ GetOrFinish(object->GetCharsValue(accessor_, index_)));
+ if (!done_) AddCharacter(c);
+ }
+ }
+
+ void VisitSeqOneByteString(const TqSeqOneByteString* object) override {
+ ReadSeqString(object);
+ }
+
+ void VisitSeqTwoByteString(const TqSeqTwoByteString* object) override {
+ ReadSeqString(object);
+ }
+
+ void VisitConsString(const TqConsString* object) override {
+ uintptr_t first_address = GetOrFinish(object->GetFirstValue(accessor_));
+ if (done_) return;
+ auto first = GetTypedHeapObject(first_address, accessor_, nullptr).object;
+ first->Visit(this);
+ if (done_) return;
+ int32_t first_length = GetOrFinish(
+ static_cast<TqString*>(first.get())->GetLengthValue(accessor_));
+ uintptr_t second = GetOrFinish(object->GetSecondValue(accessor_));
+ if (done_) return;
+ IndexModifier modifier(this, -first_length, -first_length);
+ GetTypedHeapObject(second, accessor_, nullptr).object->Visit(this);
+ }
+
+ void VisitSlicedString(const TqSlicedString* object) override {
+ uintptr_t parent = GetOrFinish(object->GetParentValue(accessor_));
+ int32_t length = GetOrFinish(object->GetLengthValue(accessor_));
+ int32_t offset = i::PlatformSmiTagging::SmiToInt(
+ GetOrFinish(object->GetOffsetValue(accessor_)));
+ if (done_) return;
+ int32_t limit_adjust = offset + length - limit_;
+ IndexModifier modifier(this, offset, limit_adjust < 0 ? limit_adjust : 0);
+ GetTypedHeapObject(parent, accessor_, nullptr).object->Visit(this);
+ }
+
+ void VisitThinString(const TqThinString* object) override {
+ uintptr_t actual = GetOrFinish(object->GetActualValue(accessor_));
+ if (done_) return;
+ GetTypedHeapObject(actual, accessor_, nullptr).object->Visit(this);
+ }
+
+ void VisitExternalString(const TqExternalString* object) override {
+ // TODO(v8:9376): External strings are very common and important when
+ // attempting to print the source of a function in the browser. For now
+ // we're just ignoring them, but eventually we'll want some kind of
+ // mechanism where the user of this library can provide a callback function
+ // that fetches data from external strings.
+ AddEllipsisAndFinish();
+ }
+
+ void VisitObject(const TqObject* object) override {
+ // If we fail to find a specific type for a sub-object within a cons string,
+ // sliced string, or thin string, we will end up here.
+ AddEllipsisAndFinish();
+ }
+
+ private:
+ // Unpacks a value that was fetched from the debuggee. If the value indicates
+ // that it couldn't successfully fetch memory, then prevents further work.
+ template <typename T>
+ T GetOrFinish(Value<T> value) {
+ if (value.validity != d::MemoryAccessResult::kOk) {
+ AddEllipsisAndFinish();
+ }
+ return value.value;
+ }
+
+ void AddEllipsisAndFinish() {
+ if (!done_) {
+ string_ += u"...";
+ done_ = true;
+ }
+ }
+
+ void AddCharacter(char16_t c) {
+ if (string_.size() >= kMaxCharacters) {
+ AddEllipsisAndFinish();
+ } else {
+ string_.push_back(c);
+ }
+ }
+
+ // Temporarily adds offsets to both index_ and limit_, to handle ConsString
+ // and SlicedString.
+ class IndexModifier {
+ public:
+ IndexModifier(ReadStringVisitor* that, int32_t index_adjust,
+ int32_t limit_adjust)
+ : that_(that),
+ index_adjust_(index_adjust),
+ limit_adjust_(limit_adjust) {
+ that_->index_ += index_adjust_;
+ that_->limit_ += limit_adjust_;
+ }
+ ~IndexModifier() {
+ that_->index_ -= index_adjust_;
+ that_->limit_ -= limit_adjust_;
+ }
+
+ private:
+ ReadStringVisitor* that_;
+ int32_t index_adjust_;
+ int32_t limit_adjust_;
+ DISALLOW_COPY_AND_ASSIGN(IndexModifier);
+ };
+
+ static constexpr int kMaxCharacters = 80; // How many characters to print.
+
+ std::u16string string_; // Result string.
+ d::MemoryAccessor accessor_;
+ int32_t index_; // Index of next char to read.
+ int32_t limit_; // Don't read past this index (set by SlicedString).
+ bool done_; // Whether to stop further work.
+};
+
+// An object visitor that adds extra debugging information for some types.
+class AddInfoVisitor : public TqObjectVisitor {
+ public:
+ AddInfoVisitor(const std::string& brief, d::MemoryAccessor accessor)
+ : accessor_(accessor), brief_(brief) {}
+
+ // Returns the brief object description, once visiting is complete.
+ const std::string& GetBrief() { return brief_; }
+
+ void VisitString(const TqString* object) override {
+ ReadStringVisitor visitor(accessor_);
+ object->Visit(&visitor);
+ if (!brief_.empty()) brief_ += " ";
+ brief_ += "\"" + visitor.GetString() + "\"";
+ }
+
+ private:
+ d::MemoryAccessor accessor_;
+ std::string brief_;
+};
+
+std::unique_ptr<ObjectPropertiesResult> GetHeapObjectProperties(
+ uintptr_t address, d::MemoryAccessor accessor, const char* type_hint,
+ std::string brief) {
+ TypedObject typed = GetTypedHeapObject(address, accessor, type_hint);
+
+ // TODO(v8:9376): Many object types need additional data that is not included
+ // in their Torque layout definitions. For example, JSObject has an array of
+ // in-object properties after its Torque-defined fields, which at a minimum
+ // should be represented as an array in this response. If the relevant memory
+ // is available, we should instead represent those properties (and any out-of-
+ // object properties) using their JavaScript property names.
+ AddInfoVisitor visitor(brief, accessor);
+ typed.object->Visit(&visitor);
+ brief = visitor.GetBrief();
+
+ brief = AppendAddressAndType(brief, address, typed.object->GetName());
+
+ return v8::base::make_unique<ObjectPropertiesResult>(
+ typed.type_check_result, brief, typed.object->GetName(),
+ typed.object->GetProperties(accessor));
+}
+
+std::unique_ptr<ObjectPropertiesResult> GetHeapObjectProperties(
+ uintptr_t address, d::MemoryAccessor memory_accessor, const d::Roots& roots,
+ const char* type_hint) {
+ // Try to figure out the heap range, for pointer compression (this is unused
+ // if pointer compression is disabled).
+ uintptr_t any_uncompressed_ptr = 0;
+ if (!IsPointerCompressed(address)) any_uncompressed_ptr = address;
+ if (any_uncompressed_ptr == 0) any_uncompressed_ptr = roots.any_heap_pointer;
+ if (any_uncompressed_ptr == 0) any_uncompressed_ptr = roots.map_space;
+ if (any_uncompressed_ptr == 0) any_uncompressed_ptr = roots.old_space;
+ if (any_uncompressed_ptr == 0) any_uncompressed_ptr = roots.read_only_space;
+ if (any_uncompressed_ptr == 0) {
+ // We can't figure out the heap range. Just check for known objects.
+ std::string brief = FindKnownObject(address, roots);
+ brief = AppendAddressAndType(brief, address, "v8::internal::TaggedValue");
+ return v8::base::make_unique<ObjectPropertiesResult>(
+ d::TypeCheckResult::kUnableToDecompress, brief,
+ "v8::internal::TaggedValue",
+ std::vector<std::unique_ptr<ObjectProperty>>());
+ }
+
+ // TODO(v8:9376): It seems that the space roots are at predictable offsets
+ // within the heap reservation block when pointer compression is enabled, so
+ // we should be able to set those here.
+
+ address = Decompress(address, any_uncompressed_ptr);
+ // From here on all addresses should be decompressed.
+
+ // Regardless of whether we can read the object itself, maybe we can find its
+ // pointer in the list of known objects.
+ std::string brief = FindKnownObject(address, roots);
+ return GetHeapObjectProperties(address, memory_accessor, type_hint, brief);
+}
+
+std::unique_ptr<ObjectPropertiesResult> GetObjectPropertiesImpl(
+ uintptr_t address, d::MemoryAccessor memory_accessor, const d::Roots& roots,
+ const char* type_hint) {
+ std::vector<std::unique_ptr<ObjectProperty>> props;
+ if (static_cast<uint32_t>(address) == i::kClearedWeakHeapObjectLower32) {
+ return v8::base::make_unique<ObjectPropertiesResult>(
+ d::TypeCheckResult::kWeakRef, "cleared weak ref",
+ "v8::internal::HeapObject", std::move(props));
+ }
+ bool is_weak = (address & i::kHeapObjectTagMask) == i::kWeakHeapObjectTag;
+ if (is_weak) {
+ address &= ~i::kWeakHeapObjectMask;
+ }
+ if (i::Internals::HasHeapObjectTag(address)) {
+ std::unique_ptr<ObjectPropertiesResult> result =
+ GetHeapObjectProperties(address, memory_accessor, roots, type_hint);
+ if (is_weak) {
+ result->Prepend("weak ref to ");
+ }
+ return result;
+ }
+
+ // For smi values, construct a response with a description representing the
+ // untagged value.
+ int32_t value = i::PlatformSmiTagging::SmiToInt(address);
+ std::stringstream stream;
+ stream << value << " (0x" << std::hex << value << ")";
+ return v8::base::make_unique<ObjectPropertiesResult>(
+ d::TypeCheckResult::kSmi, stream.str(), "v8::internal::Smi",
+ std::move(props));
+}
+
+} // namespace v8_debug_helper_internal
+
+namespace di = v8_debug_helper_internal;
+
+extern "C" {
+V8_DEBUG_HELPER_EXPORT d::ObjectPropertiesResult*
+_v8_debug_helper_GetObjectProperties(uintptr_t object,
+ d::MemoryAccessor memory_accessor,
+ const d::Roots& heap_roots,
+ const char* type_hint) {
+ return di::GetObjectPropertiesImpl(object, memory_accessor, heap_roots,
+ type_hint)
+ .release()
+ ->GetPublicView();
+}
+V8_DEBUG_HELPER_EXPORT void _v8_debug_helper_Free_ObjectPropertiesResult(
+ d::ObjectPropertiesResult* result) {
+ std::unique_ptr<di::ObjectPropertiesResult> ptr(
+ static_cast<di::ObjectPropertiesResultExtended*>(result)->base);
+}
+}
diff --git a/deps/v8/tools/debug_helper/heap-constants.cc b/deps/v8/tools/debug_helper/heap-constants.cc
new file mode 100644
index 0000000000..2bd0420690
--- /dev/null
+++ b/deps/v8/tools/debug_helper/heap-constants.cc
@@ -0,0 +1,51 @@
+// Copyright 2019 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 "heap-constants.h"
+#include "src/common/globals.h"
+
+namespace d = v8::debug_helper;
+
+namespace v8_debug_helper_internal {
+
+std::string FindKnownObject(uintptr_t address, const d::Roots& roots) {
+ uintptr_t containing_page = address & ~i::kPageAlignmentMask;
+ uintptr_t offset_in_page = address & i::kPageAlignmentMask;
+
+ // If there's a match with a known root, then search only that page.
+ if (containing_page == roots.map_space) {
+ return FindKnownObjectInMapSpace(offset_in_page);
+ }
+ if (containing_page == roots.old_space) {
+ return FindKnownObjectInOldSpace(offset_in_page);
+ }
+ if (containing_page == roots.read_only_space) {
+ return FindKnownObjectInReadOnlySpace(offset_in_page);
+ }
+
+ // For any unknown roots, compile a list of things this object might be.
+ std::string result;
+ if (roots.map_space == 0) {
+ std::string sub_result = FindKnownObjectInMapSpace(offset_in_page);
+ if (!sub_result.empty()) {
+ result += "maybe " + sub_result;
+ }
+ }
+ if (roots.old_space == 0) {
+ std::string sub_result = FindKnownObjectInOldSpace(offset_in_page);
+ if (!sub_result.empty()) {
+ result = (result.empty() ? "" : result + ", ") + "maybe " + sub_result;
+ }
+ }
+ if (roots.read_only_space == 0) {
+ std::string sub_result = FindKnownObjectInReadOnlySpace(offset_in_page);
+ if (!sub_result.empty()) {
+ result = (result.empty() ? "" : result + ", ") + "maybe " + sub_result;
+ }
+ }
+
+ return result;
+}
+
+} // namespace v8_debug_helper_internal
diff --git a/deps/v8/tools/debug_helper/heap-constants.h b/deps/v8/tools/debug_helper/heap-constants.h
new file mode 100644
index 0000000000..f3149bbb47
--- /dev/null
+++ b/deps/v8/tools/debug_helper/heap-constants.h
@@ -0,0 +1,28 @@
+// Copyright 2019 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.
+
+#ifndef V8_TOOLS_DEBUG_HELPER_HEAP_CONSTANTS_H_
+#define V8_TOOLS_DEBUG_HELPER_HEAP_CONSTANTS_H_
+
+#include <cstdint>
+#include <string>
+
+#include "debug-helper.h"
+
+namespace d = v8::debug_helper;
+
+namespace v8_debug_helper_internal {
+
+// Functions generated by mkgrokdump:
+std::string FindKnownObjectInOldSpace(uintptr_t offset);
+std::string FindKnownObjectInReadOnlySpace(uintptr_t offset);
+std::string FindKnownObjectInMapSpace(uintptr_t offset);
+std::string FindKnownMapInstanceTypeInMapSpace(uintptr_t offset);
+std::string FindKnownMapInstanceTypeInReadOnlySpace(uintptr_t offset);
+
+std::string FindKnownObject(uintptr_t address, const d::Roots& roots);
+
+} // namespace v8_debug_helper_internal
+
+#endif
diff --git a/deps/v8/tools/gcmole/BUILD.gn b/deps/v8/tools/gcmole/BUILD.gn
index 0434a64ff5..51b9ef527f 100644
--- a/deps/v8/tools/gcmole/BUILD.gn
+++ b/deps/v8/tools/gcmole/BUILD.gn
@@ -9,12 +9,16 @@ group("v8_run_gcmole") {
data = [
"gccause.lua",
+ "GCMOLE.gn",
"gcmole.lua",
"gcmole-tools/",
"parallel.py",
"run-gcmole.py",
+ "suspects.whitelist",
+ "test-expectations.txt",
# The following contains all relevant source and build files.
+ "../debug_helper/debug-helper.h",
"../../BUILD.gn",
"../../base/",
"../../include/",
diff --git a/deps/v8/tools/gcmole/GCMOLE.gn b/deps/v8/tools/gcmole/GCMOLE.gn
new file mode 100644
index 0000000000..62da0a084b
--- /dev/null
+++ b/deps/v8/tools/gcmole/GCMOLE.gn
@@ -0,0 +1,6 @@
+action("gcmole") {
+ sources = [
+ ### gcmole(all) ###
+ "tools/gcmole/gcmole-test.cc",
+ ]
+}
diff --git a/deps/v8/tools/gcmole/README b/deps/v8/tools/gcmole/README
index 578ea56219..48785b871a 100644
--- a/deps/v8/tools/gcmole/README
+++ b/deps/v8/tools/gcmole/README
@@ -71,6 +71,12 @@ can be ignored.
If any errors were found driver exits with non-zero status.
+TESTING -----------------------------------------------------------------------
+
+Tests are automatically run by the main lua runner. Expectations are in
+test-expectations.txt and need to be updated whenever the sources of the tests
+in gcmole-test.cc are modified (line numbers also count).
+
PACKAGING ---------------------------------------------------------------------
gcmole is deployed on V8's buildbot infrastructure to run it as part of the
diff --git a/deps/v8/tools/gcmole/gcmole-test.cc b/deps/v8/tools/gcmole/gcmole-test.cc
index c00c6e5539..3af1bac3b5 100644
--- a/deps/v8/tools/gcmole/gcmole-test.cc
+++ b/deps/v8/tools/gcmole/gcmole-test.cc
@@ -5,26 +5,43 @@
#include "src/execution/isolate.h"
#include "src/handles/handles-inl.h"
#include "src/handles/handles.h"
+#include "src/objects/foreign-inl.h"
+#include "src/objects/managed.h"
#include "src/objects/maybe-object.h"
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
+// ------- Test simple argument evaluation order problems ---------
+
Handle<Object> CauseGC(Handle<Object> obj, Isolate* isolate) {
isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
return obj;
}
+Object CauseGCRaw(Object obj, Isolate* isolate) {
+ isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
+
+ return obj;
+}
+
+Managed<Smi> CauseGCManaged(int i, Isolate* isolate) {
+ isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
+
+ return Managed<Smi>::cast(Smi::FromInt(i));
+}
+
void TwoArgumentsFunction(Object a, Object b) {
- a->Print();
- b->Print();
+ a.Print();
+ b.Print();
}
void TestTwoArguments(Isolate* isolate) {
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
Handle<JSObject> obj2 = isolate->factory()->NewJSObjectWithNullProto();
+ // Should cause warning.
TwoArgumentsFunction(*CauseGC(obj1, isolate), *CauseGC(obj2, isolate));
}
@@ -36,13 +53,16 @@ void TwoSizeTArgumentsFunction(size_t a, size_t b) {
void TestTwoSizeTArguments(Isolate* isolate) {
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
Handle<JSObject> obj2 = isolate->factory()->NewJSObjectWithNullProto();
+ // Should cause warning.
TwoSizeTArgumentsFunction(sizeof(*CauseGC(obj1, isolate)),
sizeof(*CauseGC(obj2, isolate)));
}
+// --------- Test problems with method arguments ----------
+
class SomeObject : public Object {
public:
- void Method(Object a) { a->Print(); }
+ void Method(Object a) { a.Print(); }
SomeObject& operator=(const Object& b) {
this->Print();
@@ -58,14 +78,57 @@ void TestMethodCall(Isolate* isolate) {
SomeObject obj;
Handle<SomeObject> so = handle(obj, isolate);
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
+ // Should cause warning.
so->Method(*CauseGC(obj1, isolate));
+ // Should cause warning.
+ so->Method(CauseGCRaw(*obj1, isolate));
}
void TestOperatorCall(Isolate* isolate) {
SomeObject obj;
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
+ // Should not cause warning.
obj = *CauseGC(obj1, isolate);
}
+// --------- Test for templated sub-classes of Object ----------
+
+void TestFollowingTemplates(Isolate* isolate) {
+ // Should cause warning.
+ CauseGCManaged(42, isolate);
+}
+
+// --------- Test for correctly resolving virtual methods ----------
+
+class BaseObject {
+ public:
+ virtual Handle<Object> VirtualCauseGC(Handle<Object> obj, Isolate* isolate) {
+ return obj;
+ }
+};
+
+class DerivedObject : public BaseObject {
+ public:
+ Handle<Object> VirtualCauseGC(Handle<Object> obj, Isolate* isolate) override {
+ isolate->heap()->CollectGarbage(OLD_SPACE,
+ GarbageCollectionReason::kTesting);
+
+ return obj;
+ }
+};
+
+void TestFollowingVirtualFunctions(Isolate* isolate) {
+ DerivedObject derived;
+ BaseObject* base = &derived;
+ Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
+
+ SomeObject so;
+ Handle<SomeObject> so_handle = handle(so, isolate);
+ // Should cause warning.
+ so_handle->Method(*derived.VirtualCauseGC(obj1, isolate));
+ // Should cause warning.
+ so_handle->Method(*base->VirtualCauseGC(obj1, isolate));
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/tools/gcmole/gcmole-tools.tar.gz.sha1 b/deps/v8/tools/gcmole/gcmole-tools.tar.gz.sha1
index 718e967e3b..8f7876fa51 100644
--- a/deps/v8/tools/gcmole/gcmole-tools.tar.gz.sha1
+++ b/deps/v8/tools/gcmole/gcmole-tools.tar.gz.sha1
@@ -1 +1 @@
-3d4ba1759c3d5bc7e98c466d24fa0c43f186ba79 \ No newline at end of file
+d2f949820bf1ee7343a7b5f46987a3657aaea2e9 \ No newline at end of file
diff --git a/deps/v8/tools/gcmole/gcmole.cc b/deps/v8/tools/gcmole/gcmole.cc
index 6631583478..806100d381 100644
--- a/deps/v8/tools/gcmole/gcmole.cc
+++ b/deps/v8/tools/gcmole/gcmole.cc
@@ -47,6 +47,7 @@ namespace {
typedef std::string MangledName;
typedef std::set<MangledName> CalleesSet;
+typedef std::map<MangledName, MangledName> CalleesMap;
static bool GetMangledName(clang::MangleContext* ctx,
const clang::NamedDecl* decl,
@@ -138,14 +139,16 @@ class CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> {
virtual bool VisitDeclRefExpr(clang::DeclRefExpr* expr) {
// If function mentions EXTERNAL VMState add artificial garbage collection
// mark.
- if (IsExternalVMState(expr->getDecl())) AddCallee("CollectGarbage");
+ if (IsExternalVMState(expr->getDecl()))
+ AddCallee("CollectGarbage", "CollectGarbage");
return true;
}
void AnalyzeFunction(const clang::FunctionDecl* f) {
MangledName name;
if (InV8Namespace(f) && GetMangledName(ctx_, f, &name)) {
- AddCallee(name);
+ const std::string& function = f->getNameAsString();
+ AddCallee(name, function);
const clang::FunctionDecl* body = NULL;
if (f->hasBody(body) && !Analyzed(name)) {
@@ -176,21 +179,22 @@ class CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> {
scopes_.pop();
}
- void AddCallee(const MangledName& name) {
+ void AddCallee(const MangledName& name, const MangledName& function) {
if (!scopes_.empty()) scopes_.top()->insert(name);
+ mangled_to_function_[name] = function;
}
void PrintCallGraph() {
for (Callgraph::const_iterator i = callgraph_.begin(), e = callgraph_.end();
i != e;
++i) {
- std::cout << i->first << "\n";
+ std::cout << i->first << "," << mangled_to_function_[i->first] << "\n";
CalleesSet* callees = i->second;
for (CalleesSet::const_iterator j = callees->begin(), e = callees->end();
j != e;
++j) {
- std::cout << "\t" << *j << "\n";
+ std::cout << "\t" << *j << "," << mangled_to_function_[*j] << "\n";
}
}
}
@@ -200,6 +204,7 @@ class CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> {
std::stack<CalleesSet* > scopes_;
Callgraph callgraph_;
+ CalleesMap mangled_to_function_;
};
@@ -234,23 +239,40 @@ class FunctionDeclarationFinder
CalleesPrinter* callees_printer_;
};
-
-static bool loaded = false;
+static bool gc_suspects_loaded = false;
static CalleesSet gc_suspects;
-
+static CalleesSet gc_functions;
+static bool whitelist_loaded = false;
+static CalleesSet suspects_whitelist;
static void LoadGCSuspects() {
- if (loaded) return;
+ if (gc_suspects_loaded) return;
std::ifstream fin("gcsuspects");
- std::string s;
+ std::string mangled, function;
- while (fin >> s) gc_suspects.insert(s);
+ while (!fin.eof()) {
+ std::getline(fin, mangled, ',');
+ gc_suspects.insert(mangled);
+ std::getline(fin, function);
+ gc_functions.insert(function);
+ }
- loaded = true;
+ gc_suspects_loaded = true;
}
+static void LoadSuspectsWhitelist() {
+ if (whitelist_loaded) return;
+
+ std::ifstream fin("tools/gcmole/suspects.whitelist");
+ std::string s;
+
+ while (fin >> s) suspects_whitelist.insert(s);
+ whitelist_loaded = true;
+}
+
+// Looks for exact match of the mangled name
static bool KnownToCauseGC(clang::MangleContext* ctx,
const clang::FunctionDecl* decl) {
LoadGCSuspects();
@@ -265,6 +287,25 @@ static bool KnownToCauseGC(clang::MangleContext* ctx,
return false;
}
+// Looks for partial match of only the function name
+static bool SuspectedToCauseGC(clang::MangleContext* ctx,
+ const clang::FunctionDecl* decl) {
+ LoadGCSuspects();
+
+ if (!InV8Namespace(decl)) return false;
+
+ LoadSuspectsWhitelist();
+ if (suspects_whitelist.find(decl->getNameAsString()) !=
+ suspects_whitelist.end()) {
+ return false;
+ }
+
+ if (gc_functions.find(decl->getNameAsString()) != gc_functions.end()) {
+ return true;
+ }
+
+ return false;
+}
static const int kNoEffect = 0;
static const int kCausesGC = 1;
@@ -910,8 +951,30 @@ class FunctionAnalyzer {
RepresentsRawPointerType(call->getType()));
clang::FunctionDecl* callee = call->getDirectCallee();
- if ((callee != NULL) && KnownToCauseGC(ctx_, callee)) {
- out.setGC();
+ if (callee != NULL) {
+ if (KnownToCauseGC(ctx_, callee)) {
+ out.setGC();
+ }
+
+ clang::CXXMethodDecl* method =
+ llvm::dyn_cast_or_null<clang::CXXMethodDecl>(callee);
+ if (method != NULL && method->isVirtual()) {
+ clang::CXXMemberCallExpr* memcall =
+ llvm::dyn_cast_or_null<clang::CXXMemberCallExpr>(call);
+ if (memcall != NULL) {
+ clang::CXXMethodDecl* target = method->getDevirtualizedMethod(
+ memcall->getImplicitObjectArgument(), false);
+ if (target != NULL) {
+ if (KnownToCauseGC(ctx_, target)) {
+ out.setGC();
+ }
+ } else {
+ if (SuspectedToCauseGC(ctx_, method)) {
+ out.setGC();
+ }
+ }
+ }
+ }
}
return out;
diff --git a/deps/v8/tools/gcmole/gcmole.lua b/deps/v8/tools/gcmole/gcmole.lua
index ae17fdc5f6..6758973457 100644
--- a/deps/v8/tools/gcmole/gcmole.lua
+++ b/deps/v8/tools/gcmole/gcmole.lua
@@ -183,12 +183,19 @@ end
-------------------------------------------------------------------------------
-local function ParseGNFile()
+local function ParseGNFile(for_test)
local result = {}
- local gn_files = {
- { "BUILD.gn", '"([^"]-%.cc)"', "" },
- { "test/cctest/BUILD.gn", '"(test-[^"]-%.cc)"', "test/cctest/" }
- }
+ local gn_files
+ if for_test then
+ gn_files = {
+ { "tools/gcmole/GCMOLE.gn", '"([^"]-%.cc)"', "" }
+ }
+ else
+ gn_files = {
+ { "BUILD.gn", '"([^"]-%.cc)"', "" },
+ { "test/cctest/BUILD.gn", '"(test-[^"]-%.cc)"', "test/cctest/" }
+ }
+ end
for i = 1, #gn_files do
local filename = gn_files[i][1]
@@ -231,7 +238,8 @@ local function BuildFileList(sources, props)
end
-local gn_sources = ParseGNFile()
+local gn_sources = ParseGNFile(false)
+local gn_test_sources = ParseGNFile(true)
local function FilesForArch(arch)
return BuildFileList(gn_sources, { os = 'linux',
@@ -240,6 +248,13 @@ local function FilesForArch(arch)
simulator = ''})
end
+local function FilesForTest(arch)
+ return BuildFileList(gn_test_sources, { os = 'linux',
+ arch = arch,
+ mode = 'debug',
+ simulator = ''})
+end
+
local mtConfig = {}
mtConfig.__index = mtConfig
@@ -393,8 +408,13 @@ end
--------------------------------------------------------------------------------
-- Analysis
-local function CheckCorrectnessForArch(arch)
- local files = FilesForArch(arch)
+local function CheckCorrectnessForArch(arch, for_test)
+ local files
+ if for_test then
+ files = FilesForTest(arch)
+ else
+ files = FilesForArch(arch)
+ end
local cfg = ARCHITECTURES[arch]
if not FLAGS.reuse_gcsuspects then
@@ -403,6 +423,7 @@ local function CheckCorrectnessForArch(arch)
local processed_files = 0
local errors_found = false
+ local output = ""
local function SearchForErrors(filename, lines)
processed_files = processed_files + 1
for l in lines do
@@ -410,7 +431,11 @@ local function CheckCorrectnessForArch(arch)
l:match "^[^:]+:%d+:%d+:" or
l:match "error" or
l:match "warning"
- print(l)
+ if for_test then
+ output = output.."\n"..l
+ else
+ print(l)
+ end
end
end
@@ -427,18 +452,34 @@ local function CheckCorrectnessForArch(arch)
processed_files,
errors_found and "Errors found" or "No errors found")
- return errors_found
+ return errors_found, output
end
-local function SafeCheckCorrectnessForArch(arch)
- local status, errors = pcall(CheckCorrectnessForArch, arch)
+local function SafeCheckCorrectnessForArch(arch, for_test)
+ local status, errors, output = pcall(CheckCorrectnessForArch, arch, for_test)
if not status then
print(string.format("There was an error: %s", errors))
errors = true
end
- return errors
+ return errors, output
+end
+
+local function TestRun()
+ local errors, output = SafeCheckCorrectnessForArch('x64', true)
+
+ local filename = "tools/gcmole/test-expectations.txt"
+ local exp_file = assert(io.open(filename), "failed to open test expectations file")
+ local expectations = exp_file:read('*all')
+
+ if output ~= expectations then
+ log("** Output mismatch from running tests. Please run them manually.")
+ else
+ log("** Tests ran successfully")
+ end
end
+TestRun()
+
local errors = false
for _, arch in ipairs(ARCHS) do
@@ -446,7 +487,7 @@ for _, arch in ipairs(ARCHS) do
error ("Unknown arch: " .. arch)
end
- errors = SafeCheckCorrectnessForArch(arch, report) or errors
+ errors = SafeCheckCorrectnessForArch(arch, false) or errors
end
os.exit(errors and 1 or 0)
diff --git a/deps/v8/tools/gcmole/suspects.whitelist b/deps/v8/tools/gcmole/suspects.whitelist
new file mode 100644
index 0000000000..01db7401f2
--- /dev/null
+++ b/deps/v8/tools/gcmole/suspects.whitelist
@@ -0,0 +1,4 @@
+IsConstructor
+IsEval
+IsAsync
+IsPromiseAll
diff --git a/deps/v8/tools/gcmole/test-expectations.txt b/deps/v8/tools/gcmole/test-expectations.txt
new file mode 100644
index 0000000000..36a026a12e
--- /dev/null
+++ b/deps/v8/tools/gcmole/test-expectations.txt
@@ -0,0 +1,20 @@
+
+tools/gcmole/gcmole-test.cc:45:3: warning: Possible problem with evaluation order.
+ TwoArgumentsFunction(*CauseGC(obj1, isolate), *CauseGC(obj2, isolate));
+ ^
+tools/gcmole/gcmole-test.cc:57:3: warning: Possible problem with evaluation order.
+ TwoSizeTArgumentsFunction(sizeof(*CauseGC(obj1, isolate)),
+ ^
+tools/gcmole/gcmole-test.cc:82:7: warning: Possible problem with evaluation order.
+ so->Method(*CauseGC(obj1, isolate));
+ ^
+tools/gcmole/gcmole-test.cc:84:7: warning: Possible problem with evaluation order.
+ so->Method(CauseGCRaw(*obj1, isolate));
+ ^
+tools/gcmole/gcmole-test.cc:128:14: warning: Possible problem with evaluation order.
+ so_handle->Method(*derived.VirtualCauseGC(obj1, isolate));
+ ^
+tools/gcmole/gcmole-test.cc:130:14: warning: Possible problem with evaluation order.
+ so_handle->Method(*base->VirtualCauseGC(obj1, isolate));
+ ^
+6 warnings generated.
diff --git a/deps/v8/tools/gen-postmortem-metadata.py b/deps/v8/tools/gen-postmortem-metadata.py
index b5aba23220..0715b07dc1 100644
--- a/deps/v8/tools/gen-postmortem-metadata.py
+++ b/deps/v8/tools/gen-postmortem-metadata.py
@@ -166,7 +166,7 @@ consts_misc = [
{ 'name': 'bit_field3_number_of_own_descriptors_shift',
'value': 'Map::NumberOfOwnDescriptorsBits::kShift' },
{ 'name': 'class_Map__instance_descriptors_offset',
- 'value': 'Map::kInstanceDescriptorsOffset' },
+ 'value': 'Map::kInstanceDescriptorsOffset' },
{ 'name': 'off_fp_context_or_frame_type',
'value': 'CommonFrameConstants::kContextOrFrameTypeOffset'},
diff --git a/deps/v8/tools/heap-stats/categories.js b/deps/v8/tools/heap-stats/categories.js
index e02571b4f8..6560758f3e 100644
--- a/deps/v8/tools/heap-stats/categories.js
+++ b/deps/v8/tools/heap-stats/categories.js
@@ -77,7 +77,7 @@ const CATEGORIES = new Map([
'JS_TO_WASM_FUNCTION',
'JS_TYPED_ARRAY_TYPE',
'JS_WEAK_MAP_TYPE',
- 'MUTABLE_HEAP_NUMBER_TYPE',
+ 'HEAP_NUMBER_TYPE',
'NATIVE_CONTEXT_TYPE',
'OBJECT_PROPERTY_DICTIONARY_TYPE',
'ONE_BYTE_INTERNALIZED_STRING_TYPE',
diff --git a/deps/v8/tools/heap-stats/global-timeline.js b/deps/v8/tools/heap-stats/global-timeline.js
index 3830b7ca33..c34ba2b913 100644
--- a/deps/v8/tools/heap-stats/global-timeline.js
+++ b/deps/v8/tools/heap-stats/global-timeline.js
@@ -63,9 +63,12 @@ class GlobalTimeline extends HTMLElement {
{type: 'number', label: 'Ptr compression benefit'},
{type: 'string', role: 'tooltip'},
{type: 'number', label: 'Embedder fields'},
- {type: 'number', label: 'Tagged fields'},
+ {type: 'number', label: 'Tagged fields (excl. in-object Smis)'},
+ {type: 'number', label: 'In-object Smi-only fields'},
{type: 'number', label: 'Other raw fields'},
- {type: 'number', label: 'Unboxed doubles'}
+ {type: 'number', label: 'Unboxed doubles'},
+ {type: 'number', label: 'Boxed doubles'},
+ {type: 'number', label: 'String data'}
];
const chart_data = [labels];
const isolate_data = this.data[this.selection.isolate];
@@ -78,10 +81,14 @@ class GlobalTimeline extends HTMLElement {
const data = [];
data.push(gc_data.time * kMillis2Seconds);
const total = data_set.tagged_fields +
+ data_set.inobject_smi_fields +
data_set.embedder_fields +
data_set.other_raw_fields +
- data_set.unboxed_double_fields;
- const ptr_compr_benefit = data_set.tagged_fields / 2;
+ data_set.unboxed_double_fields +
+ data_set.boxed_double_fields +
+ data_set.string_data;
+ const ptr_compr_benefit =
+ (data_set.inobject_smi_fields + data_set.tagged_fields) / 2;
const ptr_compr_benefit_perc = ptr_compr_benefit / total * 100;
sum_total += total;
sum_ptr_compr_benefit_perc += ptr_compr_benefit_perc;
@@ -93,8 +100,11 @@ class GlobalTimeline extends HTMLElement {
data.push(tooltip);
data.push(data_set.embedder_fields / KB);
data.push(data_set.tagged_fields / KB);
+ data.push(data_set.inobject_smi_fields / KB);
data.push(data_set.other_raw_fields / KB);
data.push(data_set.unboxed_double_fields / KB);
+ data.push(data_set.boxed_double_fields / KB);
+ data.push(data_set.string_data / KB);
chart_data.push(data);
});
const avg_ptr_compr_benefit_perc =
diff --git a/deps/v8/tools/heap-stats/trace-file-reader.js b/deps/v8/tools/heap-stats/trace-file-reader.js
index 4fec9a1cb9..86d9d7d551 100644
--- a/deps/v8/tools/heap-stats/trace-file-reader.js
+++ b/deps/v8/tools/heap-stats/trace-file-reader.js
@@ -137,11 +137,15 @@ class TraceFileReader extends HTMLElement {
}
addFieldTypeData(data, isolate, gc_id, data_set, tagged_fields,
- embedder_fields, unboxed_double_fields, other_raw_fields) {
+ inobject_smi_fields, embedder_fields, unboxed_double_fields,
+ boxed_double_fields, string_data, other_raw_fields) {
data[isolate].gcs[gc_id][data_set].field_data = {
tagged_fields,
+ inobject_smi_fields,
embedder_fields,
unboxed_double_fields,
+ boxed_double_fields,
+ string_data,
other_raw_fields
};
}
@@ -217,8 +221,12 @@ class TraceFileReader extends HTMLElement {
const field_data = entry.field_data;
this.addFieldTypeData(data, isolate, gc_id, data_set,
- field_data.tagged_fields, field_data.embedder_fields,
+ field_data.tagged_fields,
+ field_data.inobject_smi_fields,
+ field_data.embedder_fields,
field_data.unboxed_double_fields,
+ field_data.boxed_double_fields,
+ field_data.string_data,
field_data.other_raw_fields);
data[isolate].gcs[gc_id][data_set].bucket_sizes =
@@ -282,8 +290,9 @@ class TraceFileReader extends HTMLElement {
this.createOrUpdateEntryIfNeeded(data, entry);
this.createDatasetIfNeeded(data, entry, entry.key);
this.addFieldTypeData(data, entry.isolate, entry.id, entry.key,
- entry.tagged_fields, entry.embedder_fields,
- entry.unboxed_double_fields, entry.other_raw_fields);
+ entry.tagged_fields, entry.embedder_fields, entry.inobject_smi_fields,
+ entry.unboxed_double_fields, entry.boxed_double_fields,
+ entry.string_data, entry.other_raw_fields);
} else if (entry.type === 'instance_type_data') {
if (entry.id in data[entry.isolate].gcs) {
this.createOrUpdateEntryIfNeeded(data, entry);
diff --git a/deps/v8/tools/run-wasm-api-tests.py b/deps/v8/tools/run-wasm-api-tests.py
index 79f53cb927..ff37c8a465 100755
--- a/deps/v8/tools/run-wasm-api-tests.py
+++ b/deps/v8/tools/run-wasm-api-tests.py
@@ -38,7 +38,8 @@ CLANG_PATH = os.path.join(CHECKOUT_PATH, "third_party", "llvm-build",
"Release+Asserts", "bin")
EXAMPLES = ["hello", "callback", "trap", "reflect", "global", "table",
- "memory", "finalize", "serialize", "threads"]
+ "memory", "finalize", "serialize", "threads", "hostref", "multi",
+ "start"]
CLANG = {
"name": "Clang",
diff --git a/deps/v8/tools/testrunner/OWNERS b/deps/v8/tools/testrunner/OWNERS
index bdb1d555a4..09e0096a2e 100644
--- a/deps/v8/tools/testrunner/OWNERS
+++ b/deps/v8/tools/testrunner/OWNERS
@@ -1 +1 @@
-file://INFRA_OWNERS
+file:../../INFRA_OWNERS
diff --git a/deps/v8/tools/testrunner/base_runner.py b/deps/v8/tools/testrunner/base_runner.py
index 15c5335878..7f9b43435f 100644
--- a/deps/v8/tools/testrunner/base_runner.py
+++ b/deps/v8/tools/testrunner/base_runner.py
@@ -349,9 +349,6 @@ class BaseTestRunner(object):
"color, mono)")
parser.add_option("--json-test-results",
help="Path to a file for storing json results.")
- parser.add_option("--junitout", help="File name of the JUnit output")
- parser.add_option("--junittestsuite", default="v8tests",
- help="The testsuite name in the JUnit output file")
parser.add_option("--exit-after-n-failures", type="int", default=100,
help="Exit after the first N failures instead of "
"running all tests. Pass 0 to disable this feature.")
@@ -794,9 +791,6 @@ class BaseTestRunner(object):
def _create_progress_indicators(self, test_count, options):
procs = [PROGRESS_INDICATORS[options.progress]()]
- if options.junitout:
- procs.append(progress.JUnitTestProgressIndicator(options.junitout,
- options.junittestsuite))
if options.json_test_results:
procs.append(progress.JsonTestProgressIndicator(
self.framework_name,
diff --git a/deps/v8/tools/testrunner/local/junit_output.py b/deps/v8/tools/testrunner/local/junit_output.py
deleted file mode 100644
index 52f31ec422..0000000000
--- a/deps/v8/tools/testrunner/local/junit_output.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2013 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials provided
-# with the distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-import xml.etree.ElementTree as xml
-
-
-class JUnitTestOutput:
- def __init__(self, test_suite_name):
- self.root = xml.Element("testsuite")
- self.root.attrib["name"] = test_suite_name
-
- def HasRunTest(self, test_name, test_cmd, test_duration, test_failure):
- testCaseElement = xml.Element("testcase")
- testCaseElement.attrib["name"] = test_name
- testCaseElement.attrib["cmd"] = test_cmd
- testCaseElement.attrib["time"] = str(round(test_duration, 3))
- if len(test_failure):
- failureElement = xml.Element("failure")
- failureElement.text = test_failure
- testCaseElement.append(failureElement)
- self.root.append(testCaseElement)
-
- def FinishAndWrite(self, f):
- xml.ElementTree(self.root).write(f, "UTF-8")
diff --git a/deps/v8/tools/testrunner/local/pool.py b/deps/v8/tools/testrunner/local/pool.py
index e0b0ec41c7..9defdd30ee 100644
--- a/deps/v8/tools/testrunner/local/pool.py
+++ b/deps/v8/tools/testrunner/local/pool.py
@@ -115,7 +115,15 @@ class Pool():
# Necessary to not overflow the queue's pipe if a keyboard interrupt happens.
BUFFER_FACTOR = 4
- def __init__(self, num_workers, heartbeat_timeout=1):
+ def __init__(self, num_workers, heartbeat_timeout=1, notify_fun=None):
+ """
+ Args:
+ num_workers: Number of worker processes to run in parallel.
+ heartbeat_timeout: Timeout in seconds for waiting for results. Each time
+ the timeout is reached, a heartbeat is signalled and timeout is reset.
+ notify_fun: Callable called to signale some events like termination. The
+ event name is passed as string.
+ """
self.num_workers = num_workers
self.processes = []
self.terminated = False
@@ -130,6 +138,7 @@ class Pool():
# work_queue.
self.processing_count = 0
self.heartbeat_timeout = heartbeat_timeout
+ self.notify = notify_fun or (lambda x: x)
# Disable sigint and sigterm to prevent subprocesses from capturing the
# signals.
@@ -261,11 +270,13 @@ class Pool():
for p in self.processes:
os.kill(p.pid, signal.SIGTERM)
+ self.notify("Joining workers")
for p in self.processes:
p.join()
# Drain the queues to prevent stderr chatter when queues are garbage
# collected.
+ self.notify("Draining queues")
try:
while True: self.work_queue.get(False)
except:
diff --git a/deps/v8/tools/testrunner/local/variants.py b/deps/v8/tools/testrunner/local/variants.py
index 4b0cf1553b..fe63d0b935 100644
--- a/deps/v8/tools/testrunner/local/variants.py
+++ b/deps/v8/tools/testrunner/local/variants.py
@@ -23,7 +23,7 @@ ALL_VARIANT_FLAGS = {
"nooptimization": [["--no-opt", "--liftoff", "--no-wasm-tier-up"]],
"slow_path": [["--force-slow-path"]],
"stress": [["--stress-opt", "--always-opt", "--no-liftoff",
- "--no-wasm-tier-up"]],
+ "--no-wasm-tier-up", '--stress-lazy-source-positions']],
"stress_js_bg_compile_wasm_code_gc": [["--stress-background-compile",
"--wasm-code-gc",
"--stress-wasm-code-gc"]],
diff --git a/deps/v8/tools/testrunner/testproc/base.py b/deps/v8/tools/testrunner/testproc/base.py
index c52c779752..6048ef5d15 100644
--- a/deps/v8/tools/testrunner/testproc/base.py
+++ b/deps/v8/tools/testrunner/testproc/base.py
@@ -109,6 +109,19 @@ class TestProc(object):
### Communication
+ def notify_previous(self, event):
+ self._on_event(event)
+ if self._prev_proc:
+ self._prev_proc.notify_previous(event)
+
+ def _on_event(self, event):
+ """Called when processors to the right signal events, e.g. termination.
+
+ Args:
+ event: A text describing the signalled event.
+ """
+ pass
+
def _send_test(self, test):
"""Helper method for sending test to the next processor."""
return self._next_proc.next_test(test)
@@ -120,7 +133,6 @@ class TestProc(object):
self._prev_proc.result_for(test, result)
-
class TestProcObserver(TestProc):
"""Processor used for observing the data."""
def __init__(self):
diff --git a/deps/v8/tools/testrunner/testproc/execution.py b/deps/v8/tools/testrunner/testproc/execution.py
index 68ecf45a37..aaf0db1f8f 100644
--- a/deps/v8/tools/testrunner/testproc/execution.py
+++ b/deps/v8/tools/testrunner/testproc/execution.py
@@ -45,7 +45,7 @@ class ExecutionProc(base.TestProc):
def __init__(self, jobs, outproc_factory=None):
super(ExecutionProc, self).__init__()
- self._pool = pool.Pool(jobs)
+ self._pool = pool.Pool(jobs, notify_fun=self.notify_previous)
self._outproc_factory = outproc_factory or (lambda t: t.output_proc)
self._tests = {}
diff --git a/deps/v8/tools/testrunner/testproc/progress.py b/deps/v8/tools/testrunner/testproc/progress.py
index 3ba10f9528..8826c36ea4 100644
--- a/deps/v8/tools/testrunner/testproc/progress.py
+++ b/deps/v8/tools/testrunner/testproc/progress.py
@@ -13,7 +13,6 @@ import sys
import time
from . import base
-from ..local import junit_output
# Base dir of the build products for Release and Debug.
@@ -150,6 +149,10 @@ class VerboseProgressIndicator(SimpleProgressIndicator):
self._print('Still working...')
self._print_processes_linux()
+ def _on_event(self, event):
+ self._print(event)
+ self._print_processes_linux()
+
class DotsProgressIndicator(SimpleProgressIndicator):
def __init__(self):
@@ -282,45 +285,6 @@ class MonochromeProgressIndicator(CompactProgressIndicator):
print(("\r" + (" " * last_length) + "\r"), end='')
-class JUnitTestProgressIndicator(ProgressIndicator):
- def __init__(self, junitout, junittestsuite):
- super(JUnitTestProgressIndicator, self).__init__()
- self._requirement = base.DROP_PASS_STDOUT
-
- self.outputter = junit_output.JUnitTestOutput(junittestsuite)
- if junitout:
- self.outfile = open(junitout, "w")
- else:
- self.outfile = sys.stdout
-
- def _on_result_for(self, test, result):
- # TODO(majeski): Support for dummy/grouped results
- fail_text = ""
- output = result.output
- if result.has_unexpected_output:
- stdout = output.stdout.strip()
- if len(stdout):
- fail_text += "stdout:\n%s\n" % stdout
- stderr = output.stderr.strip()
- if len(stderr):
- fail_text += "stderr:\n%s\n" % stderr
- fail_text += "Command: %s" % result.cmd.to_string()
- if output.HasCrashed():
- fail_text += "exit code: %d\n--- CRASHED ---" % output.exit_code
- if output.HasTimedOut():
- fail_text += "--- TIMEOUT ---"
- self.outputter.HasRunTest(
- test_name=str(test),
- test_cmd=result.cmd.to_string(relative=True),
- test_duration=output.duration,
- test_failure=fail_text)
-
- def finished(self):
- self.outputter.FinishAndWrite(self.outfile)
- if self.outfile != sys.stdout:
- self.outfile.close()
-
-
class JsonTestProgressIndicator(ProgressIndicator):
def __init__(self, framework_name, json_test_results, arch, mode):
super(JsonTestProgressIndicator, self).__init__()
diff --git a/deps/v8/tools/testrunner/testproc/timeout.py b/deps/v8/tools/testrunner/testproc/timeout.py
index 54dc60e9b4..9a4e88c8f0 100644
--- a/deps/v8/tools/testrunner/testproc/timeout.py
+++ b/deps/v8/tools/testrunner/testproc/timeout.py
@@ -14,15 +14,15 @@ class TimeoutProc(base.TestProcObserver):
self._start = time.time()
def _on_next_test(self, test):
- self._on_event()
+ self.__on_event()
def _on_result_for(self, test, result):
- self._on_event()
+ self.__on_event()
def _on_heartbeat(self):
- self._on_event()
+ self.__on_event()
- def _on_event(self):
+ def __on_event(self):
if not self.is_stopped:
if time.time() - self._start > self._duration_sec:
print('>>> Total timeout reached.')
diff --git a/deps/v8/tools/torque/format-torque.py b/deps/v8/tools/torque/format-torque.py
index 2150d7e0cc..2e04e659c1 100755
--- a/deps/v8/tools/torque/format-torque.py
+++ b/deps/v8/tools/torque/format-torque.py
@@ -20,18 +20,9 @@ kPercentEscape = r'α'; # Unicode alpha
def preprocess(input):
input = re.sub(r'(if\s+)constexpr(\s*\()', r'\1/*COxp*/\2', input)
input = re.sub(r'(\s+)operator\s*(\'[^\']+\')', r'\1/*_OPE \2*/', input)
-
- # Mangle typeswitches to look like switch statements with the extra type
- # information and syntax encoded in comments.
- input = re.sub(r'(\s+)typeswitch\s*\(', r'\1/*_TYPE*/switch (', input)
- input = re.sub(r'(\s+)case\s*\(\s*([^\:]+)\s*\)(\s*)\:\s*deferred',
- r'\1case \2: /*_TSXDEFERRED_*/', input)
- input = re.sub(r'(\s+)case\s*\(\s*([^\:]+)\s*\)(\s*)\:',
- r'\1case \2: /*_TSX*/', input)
- input = re.sub(r'(\s+)case\s*\(\s*([^\s]+)\s*\:\s*([^\:]+)\s*\)(\s*)\:\s*deferred',
- r'\1case \3: /*_TSVDEFERRED_\2:*/', input)
- input = re.sub(r'(\s+)case\s*\(\s*([^\s]+)\s*\:\s*([^\:]+)\s*\)(\s*)\:',
- r'\1case \3: /*_TSV\2:*/', input)
+ input = re.sub(r'\btypeswitch\s*(\([^{]*\))\s{', r' if /*tPsW*/ \1 {', input)
+ input = re.sub(r'\bcase\s*(\([^{]*\))\s*:\s*deferred\s*{', r' if /*cAsEdEfF*/ \1 {', input)
+ input = re.sub(r'\bcase\s*(\([^{]*\))\s*:\s*{', r' if /*cA*/ \1 {', input)
# Add extra space around | operators to fix union types later.
while True:
@@ -65,15 +56,9 @@ def postprocess(output):
output = re.sub(r'(\S+)\s*: type([,>])', r'\1: type\2', output)
output = re.sub(r'(\n\s*)labels( [A-Z])', r'\1 labels\2', output)
output = re.sub(r'\/\*_OPE \'([^\']+)\'\*\/', r"operator '\1'", output)
- output = re.sub(r'\/\*_TYPE\*\/(\s*)switch', r'typeswitch', output)
- output = re.sub(r'case (\w+)\:\s*\/\*_TSXDEFERRED_\*\/',
- r'case (\1): deferred', output)
- output = re.sub(r'case (\w+)\:\s*\/\*_TSX\*\/',
- r'case (\1):', output)
- output = re.sub(r'case (\w+)\:\s*\/\*_TSVDEFERRED_([^\:]+)\:\*\/',
- r'case (\2: \1): deferred', output)
- output = re.sub(r'case (\w+)\:\s*\/\*_TSV([^\:]+)\:\*\/',
- r'case (\2: \1):', output)
+ output = re.sub(r'\bif\s*\/\*tPsW\*\/', r'typeswitch', output)
+ output = re.sub(r'\bif\s*\/\*cA\*\/\s*(\([^{]*\))\s*{', r'case \1: {', output)
+ output = re.sub(r'\bif\s*\/\*cAsEdEfF\*\/\s*(\([^{]*\))\s*{', r'case \1: deferred {', output)
output = re.sub(r'\n_GeNeRaTeS00_\s*\/\*([^@]+)@\*\/',
r"\n generates '\1'", output)
output = re.sub(r'_GeNeRaTeS00_\s*\/\*([^@]+)@\*\/',
diff --git a/deps/v8/tools/turbolizer/info-view.html b/deps/v8/tools/turbolizer/info-view.html
index b523e655aa..dc9c177f60 100644
--- a/deps/v8/tools/turbolizer/info-view.html
+++ b/deps/v8/tools/turbolizer/info-view.html
@@ -107,7 +107,7 @@
</tr>
<tr>
<td>^42:</td>
- <td>Select exactly the node with id 14.</td>
+ <td>Select exactly the node with id 42.</td>
</tr>
<tr>
<td>Origin:&nbsp;#42&nbsp;</td>
diff --git a/deps/v8/tools/turbolizer/package-lock.json b/deps/v8/tools/turbolizer/package-lock.json
index 9c8049fdb5..e30838aa3b 100644
--- a/deps/v8/tools/turbolizer/package-lock.json
+++ b/deps/v8/tools/turbolizer/package-lock.json
@@ -1687,9 +1687,9 @@
"dev": true
},
"js-yaml": {
- "version": "3.12.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz",
- "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==",
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
@@ -2344,9 +2344,9 @@
"dev": true
},
"mixin-deep": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
- "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
"requires": {
"for-in": "^1.0.2",
"is-extendable": "^1.0.1"
@@ -2872,9 +2872,9 @@
}
},
"set-value": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
- "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
"requires": {
"extend-shallow": "^2.0.1",
"is-extendable": "^0.1.1",
@@ -3407,35 +3407,14 @@
"dev": true
},
"union-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
- "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
"requires": {
"arr-union": "^3.1.0",
"get-value": "^2.0.6",
"is-extendable": "^0.1.1",
- "set-value": "^0.4.3"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "set-value": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
- "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-extendable": "^0.1.1",
- "is-plain-object": "^2.0.1",
- "to-object-path": "^0.3.0"
- }
- }
+ "set-value": "^2.0.1"
}
},
"universalify": {
diff --git a/deps/v8/tools/turbolizer/src/disassembly-view.ts b/deps/v8/tools/turbolizer/src/disassembly-view.ts
index 4b8fc6ea2d..0455437002 100644
--- a/deps/v8/tools/turbolizer/src/disassembly-view.ts
+++ b/deps/v8/tools/turbolizer/src/disassembly-view.ts
@@ -13,6 +13,7 @@ const toolboxHTML = `<div id="disassembly-toolbox">
<form>
<label><input id="show-instruction-address" type="checkbox" name="instruction-address">Show addresses</label>
<label><input id="show-instruction-binary" type="checkbox" name="instruction-binary">Show binary literal</label>
+ <label><input id="highlight-gap-instructions" type="checkbox" name="instruction-binary">Highlight gap instructions</label>
</form>
</div>`;
@@ -26,13 +27,14 @@ export class DisassemblyView extends TextView {
offsetSelection: MySelection;
showInstructionAddressHandler: () => void;
showInstructionBinaryHandler: () => void;
+ highlightGapInstructionsHandler: () => void;
createViewElement() {
const pane = document.createElement('div');
pane.setAttribute('id', "disassembly");
pane.innerHTML =
`<pre id='disassembly-text-pre' class='prettyprint prettyprinted'>
- <ul id='disassembly-list' class='nolinenums noindent'>
+ <ul class='disassembly-list nolinenums noindent'>
</ul>
</pre>`;
@@ -46,6 +48,19 @@ export class DisassemblyView extends TextView {
associateData: (text, fragment: HTMLElement) => {
const matches = text.match(/(?<address>0?x?[0-9a-fA-F]{8,16})(?<addressSpace>\s+)(?<offset>[0-9a-f]+)(?<offsetSpace>\s*)/);
const offset = Number.parseInt(matches.groups["offset"], 16);
+ const instructionKind = view.sourceResolver.getInstructionKindForPCOffset(offset);
+ fragment.dataset.instructionKind = instructionKind;
+ fragment.title = view.sourceResolver.instructionKindToReadableName(instructionKind);
+ const blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
+ const blockIdElement = document.createElement("SPAN");
+ blockIdElement.className = "block-id com linkable-text";
+ blockIdElement.innerText = "";
+ if (blockIds && blockIds.length > 0) {
+ blockIds.forEach(blockId => view.addHtmlElementForBlockId(blockId, fragment));
+ blockIdElement.innerText = `B${blockIds.join(",")}:`;
+ blockIdElement.dataset.blockId = `${blockIds.join(",")}`;
+ }
+ fragment.appendChild(blockIdElement);
const addressElement = document.createElement("SPAN");
addressElement.className = "instruction-address";
addressElement.innerText = matches.groups["address"];
@@ -58,11 +73,13 @@ export class DisassemblyView extends TextView {
fragment.classList.add('tag');
if (!Number.isNaN(offset)) {
- const pcOffset = view.sourceResolver.getKeyPcOffset(offset);
+ let pcOffset = view.sourceResolver.getKeyPcOffset(offset);
+ if (pcOffset == -1) pcOffset = Number(offset);
fragment.dataset.pcOffset = `${pcOffset}`;
addressElement.classList.add('linkable-text');
offsetElement.classList.add('linkable-text');
}
+ return true;
}
};
const UNCLASSIFIED_STYLE = {
@@ -79,11 +96,20 @@ export class DisassemblyView extends TextView {
fragment.innerHTML = text;
const replacer = (match, hexOffset) => {
const offset = Number.parseInt(hexOffset, 16);
- const keyOffset = view.sourceResolver.getKeyPcOffset(offset);
- return `<span class="tag linkable-text" data-pc-offset="${keyOffset}">${match}</span>`;
+ let keyOffset = view.sourceResolver.getKeyPcOffset(offset);
+ if (keyOffset == -1) keyOffset = Number(offset);
+ const blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
+ let block = "";
+ let blockIdData = "";
+ if (blockIds && blockIds.length > 0) {
+ block = `B${blockIds.join(",")} `;
+ blockIdData = `data-block-id="${blockIds.join(",")}"`;
+ }
+ return `<span class="tag linkable-text" data-pc-offset="${keyOffset}" ${blockIdData}>${block}${match}</span>`;
};
const html = text.replace(/<.0?x?([0-9a-fA-F]+)>/g, replacer);
fragment.innerHTML = html;
+ return true;
}
};
const OPCODE_STYLE = {
@@ -91,12 +117,14 @@ export class DisassemblyView extends TextView {
};
const BLOCK_HEADER_STYLE = {
associateData: function (text, fragment) {
+ if (view.sourceResolver.hasBlockStartInfo()) return false;
const matches = /\d+/.exec(text);
- if (!matches) return;
+ if (!matches) return true;
const blockId = matches[0];
fragment.dataset.blockId = blockId;
fragment.innerHTML = text;
fragment.className = "com block";
+ return true;
}
};
const SOURCE_POSITION_HEADER_STYLE = {
@@ -135,7 +163,7 @@ export class DisassemblyView extends TextView {
const linkHandler = (e: MouseEvent) => {
if (!(e.target instanceof HTMLElement)) return;
- const offsetAsString = e.target.dataset.pcOffset ? e.target.dataset.pcOffset : e.target.parentElement.dataset.pcOffset;
+ const offsetAsString = typeof e.target.dataset.pcOffset != "undefined" ? e.target.dataset.pcOffset : e.target.parentElement.dataset.pcOffset;
const offset = Number.parseInt(offsetAsString, 10);
if ((typeof offsetAsString) != "undefined" && !Number.isNaN(offset)) {
view.offsetSelection.select([offset], true);
@@ -156,12 +184,12 @@ export class DisassemblyView extends TextView {
const linkHandlerBlock = e => {
const blockId = e.target.dataset.blockId;
- if (typeof blockId != "undefined" && !Number.isNaN(blockId)) {
- e.stopPropagation();
+ if (typeof blockId != "undefined") {
+ const blockIds = blockId.split(",");
if (!e.shiftKey) {
view.selectionHandler.clear();
}
- view.blockSelectionHandler.select([blockId], true);
+ view.blockSelectionHandler.select(blockIds, true);
}
};
view.divNode.addEventListener('click', linkHandlerBlock);
@@ -219,6 +247,17 @@ export class DisassemblyView extends TextView {
};
instructionBinaryInput.addEventListener("change", showInstructionBinaryHandler);
this.showInstructionBinaryHandler = showInstructionBinaryHandler;
+
+ const highlightGapInstructionsInput: HTMLInputElement = view.divNode.querySelector("#highlight-gap-instructions");
+ const lastHighlightGapInstructions = window.sessionStorage.getItem("highlight-gap-instructions");
+ highlightGapInstructionsInput.checked = lastHighlightGapInstructions == 'true';
+ const highlightGapInstructionsHandler = () => {
+ window.sessionStorage.setItem("highlight-gap-instructions", `${highlightGapInstructionsInput.checked}`);
+ view.divNode.classList.toggle("highlight-gap-instructions", highlightGapInstructionsInput.checked);
+ };
+
+ highlightGapInstructionsInput.addEventListener("change", highlightGapInstructionsHandler);
+ this.highlightGapInstructionsHandler = highlightGapInstructionsHandler;
}
updateSelection(scrollIntoView: boolean = false) {
@@ -285,6 +324,7 @@ export class DisassemblyView extends TextView {
super.initializeContent(data, null);
this.showInstructionAddressHandler();
this.showInstructionBinaryHandler();
+ this.highlightGapInstructionsHandler();
console.timeEnd("disassembly-view");
}
diff --git a/deps/v8/tools/turbolizer/src/sequence-view.ts b/deps/v8/tools/turbolizer/src/sequence-view.ts
index e7691c688f..1319f3ae1e 100644
--- a/deps/v8/tools/turbolizer/src/sequence-view.ts
+++ b/deps/v8/tools/turbolizer/src/sequence-view.ts
@@ -98,8 +98,10 @@ export class SequenceView extends TextView {
const instNodeEl = createElement("div", "instruction-node");
const instId = createElement("div", "instruction-id", instruction.id);
+ const offsets = view.sourceResolver.instructionToPcOffsets(instruction.id);
instId.classList.add("clickable");
instId.dataset.instructionId = instruction.id;
+ instId.setAttribute("title", `This instruction generated gap code at pc-offset 0x${offsets.gap.toString(16)}, code at pc-offset 0x${offsets.arch.toString(16)}, condition handling at pc-offset 0x${offsets.condition.toString(16)}.`);
instNodeEl.appendChild(instId);
const instContentsEl = createElement("div", "instruction-contents");
diff --git a/deps/v8/tools/turbolizer/src/source-resolver.ts b/deps/v8/tools/turbolizer/src/source-resolver.ts
index 67f9c088a2..588eea5b99 100644
--- a/deps/v8/tools/turbolizer/src/source-resolver.ts
+++ b/deps/v8/tools/turbolizer/src/source-resolver.ts
@@ -83,6 +83,7 @@ interface InstructionsPhase {
instructionOffsetToPCOffset?: any;
blockIdtoInstructionRange?: any;
nodeIdToInstructionRange?: any;
+ codeOffsetsInfo?: CodeOffsetsInfo
}
interface GraphPhase {
@@ -103,6 +104,22 @@ export interface Sequence {
blocks: Array<any>;
}
+class CodeOffsetsInfo {
+ codeStartRegisterCheck: number;
+ deoptCheck: number;
+ initPoison: number;
+ blocksStart: number;
+ outOfLineCode: number;
+ deoptimizationExits: number;
+ pools: number;
+ jumpTables: number;
+}
+export class TurbolizerInstructionStartInfo {
+ gap: number;
+ arch: number;
+ condition: number;
+}
+
export class SourceResolver {
nodePositionMap: Array<AnyPosition>;
sources: Array<Source>;
@@ -115,9 +132,12 @@ export class SourceResolver {
lineToSourcePositions: Map<string, Array<AnyPosition>>;
nodeIdToInstructionRange: Array<[number, number]>;
blockIdToInstructionRange: Array<[number, number]>;
- instructionToPCOffset: Array<number>;
+ instructionToPCOffset: Array<TurbolizerInstructionStartInfo>;
pcOffsetToInstructions: Map<number, Array<number>>;
pcOffsets: Array<number>;
+ blockIdToPCOffset: Array<number>;
+ blockStartPCtoBlockIds: Map<number, Array<number>>;
+ codeOffsetsInfo: CodeOffsetsInfo;
constructor() {
// Maps node ids to source positions.
@@ -147,6 +167,17 @@ export class SourceResolver {
// Maps PC offsets to instructions.
this.pcOffsetToInstructions = new Map();
this.pcOffsets = [];
+ this.blockIdToPCOffset = [];
+ this.blockStartPCtoBlockIds = new Map();
+ this.codeOffsetsInfo = null;
+ }
+
+ getBlockIdsForOffset(offset): Array<number> {
+ return this.blockStartPCtoBlockIds.get(offset);
+ }
+
+ hasBlockStartInfo() {
+ return this.blockIdToPCOffset.length > 0;
}
setSources(sources, mainBackup) {
@@ -369,12 +400,18 @@ export class SourceResolver {
}
readInstructionOffsetToPCOffset(instructionToPCOffset) {
- for (const [instruction, offset] of Object.entries<number>(instructionToPCOffset)) {
- this.instructionToPCOffset[instruction] = offset;
- if (!this.pcOffsetToInstructions.has(offset)) {
- this.pcOffsetToInstructions.set(offset, []);
+ for (const [instruction, numberOrInfo] of Object.entries<number | TurbolizerInstructionStartInfo>(instructionToPCOffset)) {
+ let info: TurbolizerInstructionStartInfo;
+ if (typeof numberOrInfo == "number") {
+ info = { gap: numberOrInfo, arch: numberOrInfo, condition: numberOrInfo };
+ } else {
+ info = numberOrInfo;
+ }
+ this.instructionToPCOffset[instruction] = info;
+ if (!this.pcOffsetToInstructions.has(info.gap)) {
+ this.pcOffsetToInstructions.set(info.gap, []);
}
- this.pcOffsetToInstructions.get(offset).push(Number(instruction));
+ this.pcOffsetToInstructions.get(info.gap).push(Number(instruction));
}
this.pcOffsets = Array.from(this.pcOffsetToInstructions.keys()).sort((a, b) => b - a);
}
@@ -393,15 +430,67 @@ export class SourceResolver {
return -1;
}
- instructionRangeToKeyPcOffsets([start, end]: [number, number]) {
+ getInstructionKindForPCOffset(offset: number) {
+ if (this.codeOffsetsInfo) {
+ if (offset >= this.codeOffsetsInfo.deoptimizationExits) {
+ if (offset >= this.codeOffsetsInfo.pools) {
+ return "pools";
+ } else if (offset >= this.codeOffsetsInfo.jumpTables) {
+ return "jump-tables";
+ } else {
+ return "deoptimization-exits";
+ }
+ }
+ if (offset < this.codeOffsetsInfo.deoptCheck) {
+ return "code-start-register";
+ } else if (offset < this.codeOffsetsInfo.initPoison) {
+ return "deopt-check";
+ } else if (offset < this.codeOffsetsInfo.blocksStart) {
+ return "init-poison";
+ }
+ }
+ const keyOffset = this.getKeyPcOffset(offset);
+ if (keyOffset != -1) {
+ const infos = this.pcOffsetToInstructions.get(keyOffset).map(instrId => this.instructionToPCOffset[instrId]).filter(info => info.gap != info.condition);
+ if (infos.length > 0) {
+ const info = infos[0];
+ if (!info || info.gap == info.condition) return "unknown";
+ if (offset < info.arch) return "gap";
+ if (offset < info.condition) return "arch";
+ return "condition";
+ }
+ }
+ return "unknown";
+ }
+
+ instructionKindToReadableName(instructionKind) {
+ switch (instructionKind) {
+ case "code-start-register": return "Check code register for right value";
+ case "deopt-check": return "Check if function was marked for deoptimization";
+ case "init-poison": return "Initialization of poison register";
+ case "gap": return "Instruction implementing a gap move";
+ case "arch": return "Instruction implementing the actual machine operation";
+ case "condition": return "Code implementing conditional after instruction";
+ case "pools": return "Data in a pool (e.g. constant pool)";
+ case "jump-tables": return "Part of a jump table";
+ case "deoptimization-exits": return "Jump to deoptimization exit";
+ }
+ return null;
+ }
+
+ instructionRangeToKeyPcOffsets([start, end]: [number, number]): Array<TurbolizerInstructionStartInfo> {
if (start == end) return [this.instructionToPCOffset[start]];
return this.instructionToPCOffset.slice(start, end);
}
- instructionsToKeyPcOffsets(instructionIds: Iterable<number>) {
+ instructionToPcOffsets(instr: number): TurbolizerInstructionStartInfo {
+ return this.instructionToPCOffset[instr];
+ }
+
+ instructionsToKeyPcOffsets(instructionIds: Iterable<number>): Array<number> {
const keyPcOffsets = [];
for (const instructionId of instructionIds) {
- keyPcOffsets.push(this.instructionToPCOffset[instructionId]);
+ keyPcOffsets.push(this.instructionToPCOffset[instructionId].gap);
}
return keyPcOffsets;
}
@@ -447,6 +536,15 @@ export class SourceResolver {
switch (phase.type) {
case 'disassembly':
this.disassemblyPhase = phase;
+ if (phase['blockIdToOffset']) {
+ for (const [blockId, pc] of Object.entries<number>(phase['blockIdToOffset'])) {
+ this.blockIdToPCOffset[blockId] = pc;
+ if (!this.blockStartPCtoBlockIds.has(pc)) {
+ this.blockStartPCtoBlockIds.set(pc, []);
+ }
+ this.blockStartPCtoBlockIds.get(pc).push(Number(blockId));
+ }
+ }
break;
case 'schedule':
this.phaseNames.set(phase.name, this.phases.length);
@@ -466,6 +564,9 @@ export class SourceResolver {
if (phase.instructionOffsetToPCOffset) {
this.readInstructionOffsetToPCOffset(phase.instructionOffsetToPCOffset);
}
+ if (phase.codeOffsetsInfo) {
+ this.codeOffsetsInfo = phase.codeOffsetsInfo;
+ }
break;
case 'graph':
const graphPhase: GraphPhase = Object.assign(phase, { highestNodeId: 0 });
diff --git a/deps/v8/tools/turbolizer/src/text-view.ts b/deps/v8/tools/turbolizer/src/text-view.ts
index 41a06eae77..761a16bff4 100644
--- a/deps/v8/tools/turbolizer/src/text-view.ts
+++ b/deps/v8/tools/turbolizer/src/text-view.ts
@@ -129,6 +129,10 @@ export abstract class TextView extends PhaseView {
if (this.divNode.parentNode == null) return;
const mkVisible = new ViewElements(this.divNode.parentNode as HTMLElement);
const view = this;
+ const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset]`);
+ for (const el of elementsToSelect) {
+ el.classList.toggle("selected", false);
+ }
for (const [blockId, elements] of this.blockIdToHtmlElementsMap.entries()) {
const isSelected = view.blockSelection.isSelected(blockId);
for (const element of elements) {
@@ -136,10 +140,6 @@ export abstract class TextView extends PhaseView {
element.classList.toggle("selected", isSelected);
}
}
- const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset]`);
- for (const el of elementsToSelect) {
- el.classList.toggle("selected", false);
- }
for (const key of this.nodeIdToHtmlElementsMap.keys()) {
for (const element of this.nodeIdToHtmlElementsMap.get(key)) {
element.classList.toggle("selected", false);
@@ -170,7 +170,9 @@ export abstract class TextView extends PhaseView {
const fragment = document.createElement("SPAN");
if (typeof style.associateData == 'function') {
- style.associateData(text, fragment);
+ if (style.associateData(text, fragment) === false) {
+ return null;
+ }
} else {
if (style.css != undefined) {
const css = isIterable(style.css) ? style.css : [style.css];
@@ -198,7 +200,7 @@ export abstract class TextView extends PhaseView {
const text = matches[0];
if (text != '') {
const fragment = view.createFragment(matches[0], style);
- result.push(fragment);
+ if (fragment !== null) result.push(fragment);
}
line = line.substr(matches[0].length);
}
diff --git a/deps/v8/tools/turbolizer/turbo-visualizer.css b/deps/v8/tools/turbolizer/turbo-visualizer.css
index 216ca13d04..f89e716ce9 100644
--- a/deps/v8/tools/turbolizer/turbo-visualizer.css
+++ b/deps/v8/tools/turbolizer/turbo-visualizer.css
@@ -696,3 +696,61 @@ text {
padding-left: .5ex;
outline: 1px dotted grey;
}
+
+ul.disassembly-list .block-id {
+ width: 4ex;
+ display: block;
+ padding-top: 2px;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="gap"]+span+span {
+ background-color: #FAEEEE;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="arch"]+span+span {
+ background-color: #EEFFEE;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="condition"]+span+span {
+ background-color: #FFFFEE;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="gap"] {
+ background-color: #FAEEEE;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="arch"] {
+ background-color: #EEFFEE;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="condition"] {
+ background-color: #FFFFEE;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="deopt-check"] {
+ background-color: #FAEEFA;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="init-poison"] {
+ background-color: #EEFFAA;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="pools"] {
+ background-color: #6AA84F;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="code-start-register"] {
+ background-color: #FFCCCC;
+}
+
+div.highlight-gap-instructions [data-instruction-kind="deoptimization-exits"] {
+ background-color: #CCCCFF;
+}
+
+[data-instruction-kind].selected {
+ background-color: yellow;
+}
+
+div.highlight-gap-instructions [data-instruction-kind].selected {
+ background-color: yellow;
+}
diff --git a/deps/v8/tools/v8heapconst.py b/deps/v8/tools/v8heapconst.py
index c6c98c04c3..53aaaf74df 100644
--- a/deps/v8/tools/v8heapconst.py
+++ b/deps/v8/tools/v8heapconst.py
@@ -31,107 +31,105 @@ INSTANCE_TYPES = {
67: "ODDBALL_TYPE",
68: "MAP_TYPE",
69: "CODE_TYPE",
- 70: "MUTABLE_HEAP_NUMBER_TYPE",
- 71: "FOREIGN_TYPE",
- 72: "BYTE_ARRAY_TYPE",
- 73: "BYTECODE_ARRAY_TYPE",
- 74: "FREE_SPACE_TYPE",
- 75: "FIXED_DOUBLE_ARRAY_TYPE",
- 76: "FEEDBACK_METADATA_TYPE",
- 77: "FILLER_TYPE",
- 78: "ACCESS_CHECK_INFO_TYPE",
- 79: "ACCESSOR_INFO_TYPE",
- 80: "ACCESSOR_PAIR_TYPE",
- 81: "ALIASED_ARGUMENTS_ENTRY_TYPE",
- 82: "ALLOCATION_MEMENTO_TYPE",
- 83: "ARRAY_BOILERPLATE_DESCRIPTION_TYPE",
- 84: "ASM_WASM_DATA_TYPE",
- 85: "ASYNC_GENERATOR_REQUEST_TYPE",
- 86: "CLASS_POSITIONS_TYPE",
- 87: "DEBUG_INFO_TYPE",
- 88: "ENUM_CACHE_TYPE",
- 89: "FUNCTION_TEMPLATE_INFO_TYPE",
- 90: "FUNCTION_TEMPLATE_RARE_DATA_TYPE",
- 91: "INTERCEPTOR_INFO_TYPE",
- 92: "INTERPRETER_DATA_TYPE",
- 93: "OBJECT_TEMPLATE_INFO_TYPE",
- 94: "PROMISE_CAPABILITY_TYPE",
- 95: "PROMISE_REACTION_TYPE",
- 96: "PROTOTYPE_INFO_TYPE",
- 97: "SCRIPT_TYPE",
- 98: "SOURCE_POSITION_TABLE_WITH_FRAME_CACHE_TYPE",
- 99: "SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE",
- 100: "STACK_FRAME_INFO_TYPE",
- 101: "STACK_TRACE_FRAME_TYPE",
- 102: "TEMPLATE_OBJECT_DESCRIPTION_TYPE",
- 103: "TUPLE2_TYPE",
- 104: "TUPLE3_TYPE",
- 105: "WASM_CAPI_FUNCTION_DATA_TYPE",
- 106: "WASM_DEBUG_INFO_TYPE",
- 107: "WASM_EXCEPTION_TAG_TYPE",
- 108: "WASM_EXPORTED_FUNCTION_DATA_TYPE",
- 109: "WASM_INDIRECT_FUNCTION_TABLE_TYPE",
- 110: "WASM_JS_FUNCTION_DATA_TYPE",
- 111: "CALLABLE_TASK_TYPE",
- 112: "CALLBACK_TASK_TYPE",
- 113: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
- 114: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
- 115: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE",
- 116: "FINALIZATION_GROUP_CLEANUP_JOB_TASK_TYPE",
- 117: "INTERNAL_CLASS_TYPE",
- 118: "SMI_PAIR_TYPE",
- 119: "SMI_BOX_TYPE",
- 120: "SORT_STATE_TYPE",
- 121: "SOURCE_TEXT_MODULE_TYPE",
- 122: "SYNTHETIC_MODULE_TYPE",
- 123: "ALLOCATION_SITE_TYPE",
- 124: "EMBEDDER_DATA_ARRAY_TYPE",
- 125: "FIXED_ARRAY_TYPE",
- 126: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE",
- 127: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE",
- 128: "HASH_TABLE_TYPE",
- 129: "ORDERED_HASH_MAP_TYPE",
- 130: "ORDERED_HASH_SET_TYPE",
- 131: "ORDERED_NAME_DICTIONARY_TYPE",
- 132: "NAME_DICTIONARY_TYPE",
- 133: "GLOBAL_DICTIONARY_TYPE",
- 134: "NUMBER_DICTIONARY_TYPE",
- 135: "SIMPLE_NUMBER_DICTIONARY_TYPE",
- 136: "STRING_TABLE_TYPE",
- 137: "EPHEMERON_HASH_TABLE_TYPE",
- 138: "SCOPE_INFO_TYPE",
- 139: "SCRIPT_CONTEXT_TABLE_TYPE",
- 140: "AWAIT_CONTEXT_TYPE",
- 141: "BLOCK_CONTEXT_TYPE",
- 142: "CATCH_CONTEXT_TYPE",
- 143: "DEBUG_EVALUATE_CONTEXT_TYPE",
- 144: "EVAL_CONTEXT_TYPE",
- 145: "FUNCTION_CONTEXT_TYPE",
- 146: "MODULE_CONTEXT_TYPE",
- 147: "NATIVE_CONTEXT_TYPE",
- 148: "SCRIPT_CONTEXT_TYPE",
- 149: "WITH_CONTEXT_TYPE",
- 150: "WEAK_FIXED_ARRAY_TYPE",
- 151: "TRANSITION_ARRAY_TYPE",
- 152: "CALL_HANDLER_INFO_TYPE",
- 153: "CELL_TYPE",
- 154: "CODE_DATA_CONTAINER_TYPE",
- 155: "DESCRIPTOR_ARRAY_TYPE",
- 156: "FEEDBACK_CELL_TYPE",
- 157: "FEEDBACK_VECTOR_TYPE",
- 158: "LOAD_HANDLER_TYPE",
- 159: "PREPARSE_DATA_TYPE",
- 160: "PROPERTY_ARRAY_TYPE",
- 161: "PROPERTY_CELL_TYPE",
- 162: "SHARED_FUNCTION_INFO_TYPE",
- 163: "SMALL_ORDERED_HASH_MAP_TYPE",
- 164: "SMALL_ORDERED_HASH_SET_TYPE",
- 165: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
- 166: "STORE_HANDLER_TYPE",
- 167: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
- 168: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
- 169: "WEAK_ARRAY_LIST_TYPE",
- 170: "WEAK_CELL_TYPE",
+ 70: "FOREIGN_TYPE",
+ 71: "BYTE_ARRAY_TYPE",
+ 72: "BYTECODE_ARRAY_TYPE",
+ 73: "FREE_SPACE_TYPE",
+ 74: "FIXED_DOUBLE_ARRAY_TYPE",
+ 75: "FEEDBACK_METADATA_TYPE",
+ 76: "FILLER_TYPE",
+ 77: "ACCESS_CHECK_INFO_TYPE",
+ 78: "ACCESSOR_INFO_TYPE",
+ 79: "ACCESSOR_PAIR_TYPE",
+ 80: "ALIASED_ARGUMENTS_ENTRY_TYPE",
+ 81: "ALLOCATION_MEMENTO_TYPE",
+ 82: "ARRAY_BOILERPLATE_DESCRIPTION_TYPE",
+ 83: "ASM_WASM_DATA_TYPE",
+ 84: "ASYNC_GENERATOR_REQUEST_TYPE",
+ 85: "CLASS_POSITIONS_TYPE",
+ 86: "DEBUG_INFO_TYPE",
+ 87: "ENUM_CACHE_TYPE",
+ 88: "FUNCTION_TEMPLATE_INFO_TYPE",
+ 89: "FUNCTION_TEMPLATE_RARE_DATA_TYPE",
+ 90: "INTERCEPTOR_INFO_TYPE",
+ 91: "INTERPRETER_DATA_TYPE",
+ 92: "OBJECT_TEMPLATE_INFO_TYPE",
+ 93: "PROMISE_CAPABILITY_TYPE",
+ 94: "PROMISE_REACTION_TYPE",
+ 95: "PROTOTYPE_INFO_TYPE",
+ 96: "SCRIPT_TYPE",
+ 97: "SOURCE_POSITION_TABLE_WITH_FRAME_CACHE_TYPE",
+ 98: "SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE",
+ 99: "STACK_FRAME_INFO_TYPE",
+ 100: "STACK_TRACE_FRAME_TYPE",
+ 101: "TEMPLATE_OBJECT_DESCRIPTION_TYPE",
+ 102: "TUPLE2_TYPE",
+ 103: "TUPLE3_TYPE",
+ 104: "WASM_CAPI_FUNCTION_DATA_TYPE",
+ 105: "WASM_DEBUG_INFO_TYPE",
+ 106: "WASM_EXCEPTION_TAG_TYPE",
+ 107: "WASM_EXPORTED_FUNCTION_DATA_TYPE",
+ 108: "WASM_INDIRECT_FUNCTION_TABLE_TYPE",
+ 109: "WASM_JS_FUNCTION_DATA_TYPE",
+ 110: "CALLABLE_TASK_TYPE",
+ 111: "CALLBACK_TASK_TYPE",
+ 112: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
+ 113: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
+ 114: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE",
+ 115: "INTERNAL_CLASS_TYPE",
+ 116: "SMI_PAIR_TYPE",
+ 117: "SMI_BOX_TYPE",
+ 118: "SORT_STATE_TYPE",
+ 119: "SOURCE_TEXT_MODULE_TYPE",
+ 120: "SYNTHETIC_MODULE_TYPE",
+ 121: "ALLOCATION_SITE_TYPE",
+ 122: "EMBEDDER_DATA_ARRAY_TYPE",
+ 123: "FIXED_ARRAY_TYPE",
+ 124: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE",
+ 125: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE",
+ 126: "HASH_TABLE_TYPE",
+ 127: "ORDERED_HASH_MAP_TYPE",
+ 128: "ORDERED_HASH_SET_TYPE",
+ 129: "ORDERED_NAME_DICTIONARY_TYPE",
+ 130: "NAME_DICTIONARY_TYPE",
+ 131: "GLOBAL_DICTIONARY_TYPE",
+ 132: "NUMBER_DICTIONARY_TYPE",
+ 133: "SIMPLE_NUMBER_DICTIONARY_TYPE",
+ 134: "STRING_TABLE_TYPE",
+ 135: "EPHEMERON_HASH_TABLE_TYPE",
+ 136: "SCOPE_INFO_TYPE",
+ 137: "SCRIPT_CONTEXT_TABLE_TYPE",
+ 138: "AWAIT_CONTEXT_TYPE",
+ 139: "BLOCK_CONTEXT_TYPE",
+ 140: "CATCH_CONTEXT_TYPE",
+ 141: "DEBUG_EVALUATE_CONTEXT_TYPE",
+ 142: "EVAL_CONTEXT_TYPE",
+ 143: "FUNCTION_CONTEXT_TYPE",
+ 144: "MODULE_CONTEXT_TYPE",
+ 145: "NATIVE_CONTEXT_TYPE",
+ 146: "SCRIPT_CONTEXT_TYPE",
+ 147: "WITH_CONTEXT_TYPE",
+ 148: "WEAK_FIXED_ARRAY_TYPE",
+ 149: "TRANSITION_ARRAY_TYPE",
+ 150: "CALL_HANDLER_INFO_TYPE",
+ 151: "CELL_TYPE",
+ 152: "CODE_DATA_CONTAINER_TYPE",
+ 153: "DESCRIPTOR_ARRAY_TYPE",
+ 154: "FEEDBACK_CELL_TYPE",
+ 155: "FEEDBACK_VECTOR_TYPE",
+ 156: "LOAD_HANDLER_TYPE",
+ 157: "PREPARSE_DATA_TYPE",
+ 158: "PROPERTY_ARRAY_TYPE",
+ 159: "PROPERTY_CELL_TYPE",
+ 160: "SHARED_FUNCTION_INFO_TYPE",
+ 161: "SMALL_ORDERED_HASH_MAP_TYPE",
+ 162: "SMALL_ORDERED_HASH_SET_TYPE",
+ 163: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
+ 164: "STORE_HANDLER_TYPE",
+ 165: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
+ 166: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
+ 167: "WEAK_ARRAY_LIST_TYPE",
+ 168: "WEAK_CELL_TYPE",
1024: "JS_PROXY_TYPE",
1025: "JS_GLOBAL_OBJECT_TYPE",
1026: "JS_GLOBAL_PROXY_TYPE",
@@ -192,237 +190,237 @@ INSTANCE_TYPES = {
# List of known V8 maps.
KNOWN_MAPS = {
- ("read_only_space", 0x00111): (74, "FreeSpaceMap"),
- ("read_only_space", 0x00161): (68, "MetaMap"),
- ("read_only_space", 0x001e1): (67, "NullMap"),
- ("read_only_space", 0x00249): (155, "DescriptorArrayMap"),
- ("read_only_space", 0x002a9): (150, "WeakFixedArrayMap"),
- ("read_only_space", 0x002f9): (77, "OnePointerFillerMap"),
- ("read_only_space", 0x00349): (77, "TwoPointerFillerMap"),
- ("read_only_space", 0x003c9): (67, "UninitializedMap"),
- ("read_only_space", 0x00439): (8, "OneByteInternalizedStringMap"),
- ("read_only_space", 0x004d9): (67, "UndefinedMap"),
- ("read_only_space", 0x00539): (65, "HeapNumberMap"),
- ("read_only_space", 0x005b9): (67, "TheHoleMap"),
- ("read_only_space", 0x00661): (67, "BooleanMap"),
- ("read_only_space", 0x00739): (72, "ByteArrayMap"),
- ("read_only_space", 0x00789): (125, "FixedArrayMap"),
- ("read_only_space", 0x007d9): (125, "FixedCOWArrayMap"),
- ("read_only_space", 0x00829): (128, "HashTableMap"),
- ("read_only_space", 0x00879): (64, "SymbolMap"),
- ("read_only_space", 0x008c9): (40, "OneByteStringMap"),
- ("read_only_space", 0x00919): (138, "ScopeInfoMap"),
- ("read_only_space", 0x00969): (162, "SharedFunctionInfoMap"),
- ("read_only_space", 0x009b9): (69, "CodeMap"),
- ("read_only_space", 0x00a09): (145, "FunctionContextMap"),
- ("read_only_space", 0x00a59): (153, "CellMap"),
- ("read_only_space", 0x00aa9): (161, "GlobalPropertyCellMap"),
- ("read_only_space", 0x00af9): (71, "ForeignMap"),
- ("read_only_space", 0x00b49): (151, "TransitionArrayMap"),
- ("read_only_space", 0x00b99): (157, "FeedbackVectorMap"),
- ("read_only_space", 0x00c39): (67, "ArgumentsMarkerMap"),
- ("read_only_space", 0x00cd9): (67, "ExceptionMap"),
- ("read_only_space", 0x00d79): (67, "TerminationExceptionMap"),
- ("read_only_space", 0x00e21): (67, "OptimizedOutMap"),
- ("read_only_space", 0x00ec1): (67, "StaleRegisterMap"),
- ("read_only_space", 0x00f31): (147, "NativeContextMap"),
- ("read_only_space", 0x00f81): (146, "ModuleContextMap"),
- ("read_only_space", 0x00fd1): (144, "EvalContextMap"),
- ("read_only_space", 0x01021): (148, "ScriptContextMap"),
- ("read_only_space", 0x01071): (140, "AwaitContextMap"),
- ("read_only_space", 0x010c1): (141, "BlockContextMap"),
- ("read_only_space", 0x01111): (142, "CatchContextMap"),
- ("read_only_space", 0x01161): (149, "WithContextMap"),
- ("read_only_space", 0x011b1): (143, "DebugEvaluateContextMap"),
- ("read_only_space", 0x01201): (139, "ScriptContextTableMap"),
- ("read_only_space", 0x01251): (127, "ClosureFeedbackCellArrayMap"),
- ("read_only_space", 0x012a1): (76, "FeedbackMetadataArrayMap"),
- ("read_only_space", 0x012f1): (125, "ArrayListMap"),
- ("read_only_space", 0x01341): (66, "BigIntMap"),
- ("read_only_space", 0x01391): (126, "ObjectBoilerplateDescriptionMap"),
- ("read_only_space", 0x013e1): (73, "BytecodeArrayMap"),
- ("read_only_space", 0x01431): (154, "CodeDataContainerMap"),
- ("read_only_space", 0x01481): (75, "FixedDoubleArrayMap"),
- ("read_only_space", 0x014d1): (133, "GlobalDictionaryMap"),
- ("read_only_space", 0x01521): (156, "ManyClosuresCellMap"),
- ("read_only_space", 0x01571): (125, "ModuleInfoMap"),
- ("read_only_space", 0x015c1): (70, "MutableHeapNumberMap"),
- ("read_only_space", 0x01611): (132, "NameDictionaryMap"),
- ("read_only_space", 0x01661): (156, "NoClosuresCellMap"),
- ("read_only_space", 0x016b1): (134, "NumberDictionaryMap"),
- ("read_only_space", 0x01701): (156, "OneClosureCellMap"),
- ("read_only_space", 0x01751): (129, "OrderedHashMapMap"),
- ("read_only_space", 0x017a1): (130, "OrderedHashSetMap"),
- ("read_only_space", 0x017f1): (131, "OrderedNameDictionaryMap"),
- ("read_only_space", 0x01841): (159, "PreparseDataMap"),
- ("read_only_space", 0x01891): (160, "PropertyArrayMap"),
- ("read_only_space", 0x018e1): (152, "SideEffectCallHandlerInfoMap"),
- ("read_only_space", 0x01931): (152, "SideEffectFreeCallHandlerInfoMap"),
- ("read_only_space", 0x01981): (152, "NextCallSideEffectFreeCallHandlerInfoMap"),
- ("read_only_space", 0x019d1): (135, "SimpleNumberDictionaryMap"),
- ("read_only_space", 0x01a21): (125, "SloppyArgumentsElementsMap"),
- ("read_only_space", 0x01a71): (163, "SmallOrderedHashMapMap"),
- ("read_only_space", 0x01ac1): (164, "SmallOrderedHashSetMap"),
- ("read_only_space", 0x01b11): (165, "SmallOrderedNameDictionaryMap"),
- ("read_only_space", 0x01b61): (121, "SourceTextModuleMap"),
- ("read_only_space", 0x01bb1): (136, "StringTableMap"),
- ("read_only_space", 0x01c01): (122, "SyntheticModuleMap"),
- ("read_only_space", 0x01c51): (167, "UncompiledDataWithoutPreparseDataMap"),
- ("read_only_space", 0x01ca1): (168, "UncompiledDataWithPreparseDataMap"),
- ("read_only_space", 0x01cf1): (169, "WeakArrayListMap"),
- ("read_only_space", 0x01d41): (137, "EphemeronHashTableMap"),
- ("read_only_space", 0x01d91): (124, "EmbedderDataArrayMap"),
- ("read_only_space", 0x01de1): (170, "WeakCellMap"),
- ("read_only_space", 0x01e31): (58, "NativeSourceStringMap"),
- ("read_only_space", 0x01e81): (32, "StringMap"),
- ("read_only_space", 0x01ed1): (41, "ConsOneByteStringMap"),
- ("read_only_space", 0x01f21): (33, "ConsStringMap"),
- ("read_only_space", 0x01f71): (45, "ThinOneByteStringMap"),
- ("read_only_space", 0x01fc1): (37, "ThinStringMap"),
- ("read_only_space", 0x02011): (35, "SlicedStringMap"),
- ("read_only_space", 0x02061): (43, "SlicedOneByteStringMap"),
- ("read_only_space", 0x020b1): (34, "ExternalStringMap"),
- ("read_only_space", 0x02101): (42, "ExternalOneByteStringMap"),
- ("read_only_space", 0x02151): (50, "UncachedExternalStringMap"),
- ("read_only_space", 0x021a1): (0, "InternalizedStringMap"),
- ("read_only_space", 0x021f1): (2, "ExternalInternalizedStringMap"),
- ("read_only_space", 0x02241): (10, "ExternalOneByteInternalizedStringMap"),
- ("read_only_space", 0x02291): (18, "UncachedExternalInternalizedStringMap"),
- ("read_only_space", 0x022e1): (26, "UncachedExternalOneByteInternalizedStringMap"),
- ("read_only_space", 0x02331): (58, "UncachedExternalOneByteStringMap"),
- ("read_only_space", 0x02381): (67, "SelfReferenceMarkerMap"),
- ("read_only_space", 0x023e9): (88, "EnumCacheMap"),
- ("read_only_space", 0x02489): (83, "ArrayBoilerplateDescriptionMap"),
- ("read_only_space", 0x02679): (91, "InterceptorInfoMap"),
- ("read_only_space", 0x04e59): (78, "AccessCheckInfoMap"),
- ("read_only_space", 0x04ea9): (79, "AccessorInfoMap"),
- ("read_only_space", 0x04ef9): (80, "AccessorPairMap"),
- ("read_only_space", 0x04f49): (81, "AliasedArgumentsEntryMap"),
- ("read_only_space", 0x04f99): (82, "AllocationMementoMap"),
- ("read_only_space", 0x04fe9): (84, "AsmWasmDataMap"),
- ("read_only_space", 0x05039): (85, "AsyncGeneratorRequestMap"),
- ("read_only_space", 0x05089): (86, "ClassPositionsMap"),
- ("read_only_space", 0x050d9): (87, "DebugInfoMap"),
- ("read_only_space", 0x05129): (89, "FunctionTemplateInfoMap"),
- ("read_only_space", 0x05179): (90, "FunctionTemplateRareDataMap"),
- ("read_only_space", 0x051c9): (92, "InterpreterDataMap"),
- ("read_only_space", 0x05219): (93, "ObjectTemplateInfoMap"),
- ("read_only_space", 0x05269): (94, "PromiseCapabilityMap"),
- ("read_only_space", 0x052b9): (95, "PromiseReactionMap"),
- ("read_only_space", 0x05309): (96, "PrototypeInfoMap"),
- ("read_only_space", 0x05359): (97, "ScriptMap"),
- ("read_only_space", 0x053a9): (98, "SourcePositionTableWithFrameCacheMap"),
- ("read_only_space", 0x053f9): (99, "SourceTextModuleInfoEntryMap"),
- ("read_only_space", 0x05449): (100, "StackFrameInfoMap"),
- ("read_only_space", 0x05499): (101, "StackTraceFrameMap"),
- ("read_only_space", 0x054e9): (102, "TemplateObjectDescriptionMap"),
- ("read_only_space", 0x05539): (103, "Tuple2Map"),
- ("read_only_space", 0x05589): (104, "Tuple3Map"),
- ("read_only_space", 0x055d9): (105, "WasmCapiFunctionDataMap"),
- ("read_only_space", 0x05629): (106, "WasmDebugInfoMap"),
- ("read_only_space", 0x05679): (107, "WasmExceptionTagMap"),
- ("read_only_space", 0x056c9): (108, "WasmExportedFunctionDataMap"),
- ("read_only_space", 0x05719): (109, "WasmIndirectFunctionTableMap"),
- ("read_only_space", 0x05769): (110, "WasmJSFunctionDataMap"),
- ("read_only_space", 0x057b9): (111, "CallableTaskMap"),
- ("read_only_space", 0x05809): (112, "CallbackTaskMap"),
- ("read_only_space", 0x05859): (113, "PromiseFulfillReactionJobTaskMap"),
- ("read_only_space", 0x058a9): (114, "PromiseRejectReactionJobTaskMap"),
- ("read_only_space", 0x058f9): (115, "PromiseResolveThenableJobTaskMap"),
- ("read_only_space", 0x05949): (116, "FinalizationGroupCleanupJobTaskMap"),
- ("read_only_space", 0x05999): (117, "InternalClassMap"),
- ("read_only_space", 0x059e9): (118, "SmiPairMap"),
- ("read_only_space", 0x05a39): (119, "SmiBoxMap"),
- ("read_only_space", 0x05a89): (120, "SortStateMap"),
- ("read_only_space", 0x05ad9): (123, "AllocationSiteWithWeakNextMap"),
- ("read_only_space", 0x05b29): (123, "AllocationSiteWithoutWeakNextMap"),
- ("read_only_space", 0x05b79): (158, "LoadHandler1Map"),
- ("read_only_space", 0x05bc9): (158, "LoadHandler2Map"),
- ("read_only_space", 0x05c19): (158, "LoadHandler3Map"),
- ("read_only_space", 0x05c69): (166, "StoreHandler0Map"),
- ("read_only_space", 0x05cb9): (166, "StoreHandler1Map"),
- ("read_only_space", 0x05d09): (166, "StoreHandler2Map"),
- ("read_only_space", 0x05d59): (166, "StoreHandler3Map"),
- ("map_space", 0x00111): (1057, "ExternalMap"),
- ("map_space", 0x00161): (1073, "JSMessageObjectMap"),
+ ("read_only_space", 0x00119): (73, "FreeSpaceMap"),
+ ("read_only_space", 0x00169): (68, "MetaMap"),
+ ("read_only_space", 0x001e9): (67, "NullMap"),
+ ("read_only_space", 0x00251): (153, "DescriptorArrayMap"),
+ ("read_only_space", 0x002b1): (148, "WeakFixedArrayMap"),
+ ("read_only_space", 0x00301): (76, "OnePointerFillerMap"),
+ ("read_only_space", 0x00351): (76, "TwoPointerFillerMap"),
+ ("read_only_space", 0x003d1): (67, "UninitializedMap"),
+ ("read_only_space", 0x00441): (8, "OneByteInternalizedStringMap"),
+ ("read_only_space", 0x004e1): (67, "UndefinedMap"),
+ ("read_only_space", 0x00541): (65, "HeapNumberMap"),
+ ("read_only_space", 0x005c1): (67, "TheHoleMap"),
+ ("read_only_space", 0x00669): (67, "BooleanMap"),
+ ("read_only_space", 0x00741): (71, "ByteArrayMap"),
+ ("read_only_space", 0x00791): (123, "FixedArrayMap"),
+ ("read_only_space", 0x007e1): (123, "FixedCOWArrayMap"),
+ ("read_only_space", 0x00831): (126, "HashTableMap"),
+ ("read_only_space", 0x00881): (64, "SymbolMap"),
+ ("read_only_space", 0x008d1): (40, "OneByteStringMap"),
+ ("read_only_space", 0x00921): (136, "ScopeInfoMap"),
+ ("read_only_space", 0x00971): (160, "SharedFunctionInfoMap"),
+ ("read_only_space", 0x009c1): (69, "CodeMap"),
+ ("read_only_space", 0x00a11): (143, "FunctionContextMap"),
+ ("read_only_space", 0x00a61): (151, "CellMap"),
+ ("read_only_space", 0x00ab1): (159, "GlobalPropertyCellMap"),
+ ("read_only_space", 0x00b01): (70, "ForeignMap"),
+ ("read_only_space", 0x00b51): (149, "TransitionArrayMap"),
+ ("read_only_space", 0x00ba1): (155, "FeedbackVectorMap"),
+ ("read_only_space", 0x00c41): (67, "ArgumentsMarkerMap"),
+ ("read_only_space", 0x00ce1): (67, "ExceptionMap"),
+ ("read_only_space", 0x00d81): (67, "TerminationExceptionMap"),
+ ("read_only_space", 0x00e29): (67, "OptimizedOutMap"),
+ ("read_only_space", 0x00ec9): (67, "StaleRegisterMap"),
+ ("read_only_space", 0x00f39): (145, "NativeContextMap"),
+ ("read_only_space", 0x00f89): (144, "ModuleContextMap"),
+ ("read_only_space", 0x00fd9): (142, "EvalContextMap"),
+ ("read_only_space", 0x01029): (146, "ScriptContextMap"),
+ ("read_only_space", 0x01079): (138, "AwaitContextMap"),
+ ("read_only_space", 0x010c9): (139, "BlockContextMap"),
+ ("read_only_space", 0x01119): (140, "CatchContextMap"),
+ ("read_only_space", 0x01169): (147, "WithContextMap"),
+ ("read_only_space", 0x011b9): (141, "DebugEvaluateContextMap"),
+ ("read_only_space", 0x01209): (137, "ScriptContextTableMap"),
+ ("read_only_space", 0x01259): (125, "ClosureFeedbackCellArrayMap"),
+ ("read_only_space", 0x012a9): (75, "FeedbackMetadataArrayMap"),
+ ("read_only_space", 0x012f9): (123, "ArrayListMap"),
+ ("read_only_space", 0x01349): (66, "BigIntMap"),
+ ("read_only_space", 0x01399): (124, "ObjectBoilerplateDescriptionMap"),
+ ("read_only_space", 0x013e9): (72, "BytecodeArrayMap"),
+ ("read_only_space", 0x01439): (152, "CodeDataContainerMap"),
+ ("read_only_space", 0x01489): (74, "FixedDoubleArrayMap"),
+ ("read_only_space", 0x014d9): (131, "GlobalDictionaryMap"),
+ ("read_only_space", 0x01529): (154, "ManyClosuresCellMap"),
+ ("read_only_space", 0x01579): (123, "ModuleInfoMap"),
+ ("read_only_space", 0x015c9): (130, "NameDictionaryMap"),
+ ("read_only_space", 0x01619): (154, "NoClosuresCellMap"),
+ ("read_only_space", 0x01669): (132, "NumberDictionaryMap"),
+ ("read_only_space", 0x016b9): (154, "OneClosureCellMap"),
+ ("read_only_space", 0x01709): (127, "OrderedHashMapMap"),
+ ("read_only_space", 0x01759): (128, "OrderedHashSetMap"),
+ ("read_only_space", 0x017a9): (129, "OrderedNameDictionaryMap"),
+ ("read_only_space", 0x017f9): (157, "PreparseDataMap"),
+ ("read_only_space", 0x01849): (158, "PropertyArrayMap"),
+ ("read_only_space", 0x01899): (150, "SideEffectCallHandlerInfoMap"),
+ ("read_only_space", 0x018e9): (150, "SideEffectFreeCallHandlerInfoMap"),
+ ("read_only_space", 0x01939): (150, "NextCallSideEffectFreeCallHandlerInfoMap"),
+ ("read_only_space", 0x01989): (133, "SimpleNumberDictionaryMap"),
+ ("read_only_space", 0x019d9): (123, "SloppyArgumentsElementsMap"),
+ ("read_only_space", 0x01a29): (161, "SmallOrderedHashMapMap"),
+ ("read_only_space", 0x01a79): (162, "SmallOrderedHashSetMap"),
+ ("read_only_space", 0x01ac9): (163, "SmallOrderedNameDictionaryMap"),
+ ("read_only_space", 0x01b19): (119, "SourceTextModuleMap"),
+ ("read_only_space", 0x01b69): (134, "StringTableMap"),
+ ("read_only_space", 0x01bb9): (120, "SyntheticModuleMap"),
+ ("read_only_space", 0x01c09): (165, "UncompiledDataWithoutPreparseDataMap"),
+ ("read_only_space", 0x01c59): (166, "UncompiledDataWithPreparseDataMap"),
+ ("read_only_space", 0x01ca9): (167, "WeakArrayListMap"),
+ ("read_only_space", 0x01cf9): (135, "EphemeronHashTableMap"),
+ ("read_only_space", 0x01d49): (122, "EmbedderDataArrayMap"),
+ ("read_only_space", 0x01d99): (168, "WeakCellMap"),
+ ("read_only_space", 0x01de9): (58, "NativeSourceStringMap"),
+ ("read_only_space", 0x01e39): (32, "StringMap"),
+ ("read_only_space", 0x01e89): (41, "ConsOneByteStringMap"),
+ ("read_only_space", 0x01ed9): (33, "ConsStringMap"),
+ ("read_only_space", 0x01f29): (45, "ThinOneByteStringMap"),
+ ("read_only_space", 0x01f79): (37, "ThinStringMap"),
+ ("read_only_space", 0x01fc9): (35, "SlicedStringMap"),
+ ("read_only_space", 0x02019): (43, "SlicedOneByteStringMap"),
+ ("read_only_space", 0x02069): (34, "ExternalStringMap"),
+ ("read_only_space", 0x020b9): (42, "ExternalOneByteStringMap"),
+ ("read_only_space", 0x02109): (50, "UncachedExternalStringMap"),
+ ("read_only_space", 0x02159): (0, "InternalizedStringMap"),
+ ("read_only_space", 0x021a9): (2, "ExternalInternalizedStringMap"),
+ ("read_only_space", 0x021f9): (10, "ExternalOneByteInternalizedStringMap"),
+ ("read_only_space", 0x02249): (18, "UncachedExternalInternalizedStringMap"),
+ ("read_only_space", 0x02299): (26, "UncachedExternalOneByteInternalizedStringMap"),
+ ("read_only_space", 0x022e9): (58, "UncachedExternalOneByteStringMap"),
+ ("read_only_space", 0x02339): (67, "SelfReferenceMarkerMap"),
+ ("read_only_space", 0x023a1): (87, "EnumCacheMap"),
+ ("read_only_space", 0x02441): (82, "ArrayBoilerplateDescriptionMap"),
+ ("read_only_space", 0x02631): (90, "InterceptorInfoMap"),
+ ("read_only_space", 0x04eb1): (77, "AccessCheckInfoMap"),
+ ("read_only_space", 0x04f01): (78, "AccessorInfoMap"),
+ ("read_only_space", 0x04f51): (79, "AccessorPairMap"),
+ ("read_only_space", 0x04fa1): (80, "AliasedArgumentsEntryMap"),
+ ("read_only_space", 0x04ff1): (81, "AllocationMementoMap"),
+ ("read_only_space", 0x05041): (83, "AsmWasmDataMap"),
+ ("read_only_space", 0x05091): (84, "AsyncGeneratorRequestMap"),
+ ("read_only_space", 0x050e1): (85, "ClassPositionsMap"),
+ ("read_only_space", 0x05131): (86, "DebugInfoMap"),
+ ("read_only_space", 0x05181): (88, "FunctionTemplateInfoMap"),
+ ("read_only_space", 0x051d1): (89, "FunctionTemplateRareDataMap"),
+ ("read_only_space", 0x05221): (91, "InterpreterDataMap"),
+ ("read_only_space", 0x05271): (92, "ObjectTemplateInfoMap"),
+ ("read_only_space", 0x052c1): (93, "PromiseCapabilityMap"),
+ ("read_only_space", 0x05311): (94, "PromiseReactionMap"),
+ ("read_only_space", 0x05361): (95, "PrototypeInfoMap"),
+ ("read_only_space", 0x053b1): (96, "ScriptMap"),
+ ("read_only_space", 0x05401): (97, "SourcePositionTableWithFrameCacheMap"),
+ ("read_only_space", 0x05451): (98, "SourceTextModuleInfoEntryMap"),
+ ("read_only_space", 0x054a1): (99, "StackFrameInfoMap"),
+ ("read_only_space", 0x054f1): (100, "StackTraceFrameMap"),
+ ("read_only_space", 0x05541): (101, "TemplateObjectDescriptionMap"),
+ ("read_only_space", 0x05591): (102, "Tuple2Map"),
+ ("read_only_space", 0x055e1): (103, "Tuple3Map"),
+ ("read_only_space", 0x05631): (104, "WasmCapiFunctionDataMap"),
+ ("read_only_space", 0x05681): (105, "WasmDebugInfoMap"),
+ ("read_only_space", 0x056d1): (106, "WasmExceptionTagMap"),
+ ("read_only_space", 0x05721): (107, "WasmExportedFunctionDataMap"),
+ ("read_only_space", 0x05771): (108, "WasmIndirectFunctionTableMap"),
+ ("read_only_space", 0x057c1): (109, "WasmJSFunctionDataMap"),
+ ("read_only_space", 0x05811): (110, "CallableTaskMap"),
+ ("read_only_space", 0x05861): (111, "CallbackTaskMap"),
+ ("read_only_space", 0x058b1): (112, "PromiseFulfillReactionJobTaskMap"),
+ ("read_only_space", 0x05901): (113, "PromiseRejectReactionJobTaskMap"),
+ ("read_only_space", 0x05951): (114, "PromiseResolveThenableJobTaskMap"),
+ ("read_only_space", 0x059a1): (115, "InternalClassMap"),
+ ("read_only_space", 0x059f1): (116, "SmiPairMap"),
+ ("read_only_space", 0x05a41): (117, "SmiBoxMap"),
+ ("read_only_space", 0x05a91): (118, "SortStateMap"),
+ ("read_only_space", 0x05ae1): (121, "AllocationSiteWithWeakNextMap"),
+ ("read_only_space", 0x05b31): (121, "AllocationSiteWithoutWeakNextMap"),
+ ("read_only_space", 0x05b81): (156, "LoadHandler1Map"),
+ ("read_only_space", 0x05bd1): (156, "LoadHandler2Map"),
+ ("read_only_space", 0x05c21): (156, "LoadHandler3Map"),
+ ("read_only_space", 0x05c71): (164, "StoreHandler0Map"),
+ ("read_only_space", 0x05cc1): (164, "StoreHandler1Map"),
+ ("read_only_space", 0x05d11): (164, "StoreHandler2Map"),
+ ("read_only_space", 0x05d61): (164, "StoreHandler3Map"),
+ ("map_space", 0x00119): (1057, "ExternalMap"),
+ ("map_space", 0x00169): (1073, "JSMessageObjectMap"),
}
# List of known V8 objects.
KNOWN_OBJECTS = {
- ("read_only_space", 0x001b1): "NullValue",
- ("read_only_space", 0x00231): "EmptyDescriptorArray",
- ("read_only_space", 0x00299): "EmptyWeakFixedArray",
- ("read_only_space", 0x00399): "UninitializedValue",
- ("read_only_space", 0x004a9): "UndefinedValue",
- ("read_only_space", 0x00529): "NanValue",
- ("read_only_space", 0x00589): "TheHoleValue",
- ("read_only_space", 0x00621): "HoleNanValue",
- ("read_only_space", 0x00631): "TrueValue",
- ("read_only_space", 0x006e1): "FalseValue",
- ("read_only_space", 0x00729): "empty_string",
- ("read_only_space", 0x00be9): "EmptyScopeInfo",
- ("read_only_space", 0x00bf9): "EmptyFixedArray",
- ("read_only_space", 0x00c09): "ArgumentsMarker",
- ("read_only_space", 0x00ca9): "Exception",
- ("read_only_space", 0x00d49): "TerminationException",
- ("read_only_space", 0x00df1): "OptimizedOut",
- ("read_only_space", 0x00e91): "StaleRegister",
- ("read_only_space", 0x023d1): "EmptyEnumCache",
- ("read_only_space", 0x02439): "EmptyPropertyArray",
- ("read_only_space", 0x02449): "EmptyByteArray",
- ("read_only_space", 0x02459): "EmptyObjectBoilerplateDescription",
- ("read_only_space", 0x02471): "EmptyArrayBoilerplateDescription",
- ("read_only_space", 0x024d9): "EmptyClosureFeedbackCellArray",
- ("read_only_space", 0x024e9): "EmptySloppyArgumentsElements",
- ("read_only_space", 0x02509): "EmptySlowElementDictionary",
- ("read_only_space", 0x02551): "EmptyOrderedHashMap",
- ("read_only_space", 0x02579): "EmptyOrderedHashSet",
- ("read_only_space", 0x025a1): "EmptyFeedbackMetadata",
- ("read_only_space", 0x025b1): "EmptyPropertyCell",
- ("read_only_space", 0x025d9): "EmptyPropertyDictionary",
- ("read_only_space", 0x02629): "NoOpInterceptorInfo",
- ("read_only_space", 0x026c9): "EmptyWeakArrayList",
- ("read_only_space", 0x026e1): "InfinityValue",
- ("read_only_space", 0x026f1): "MinusZeroValue",
- ("read_only_space", 0x02701): "MinusInfinityValue",
- ("read_only_space", 0x02711): "SelfReferenceMarker",
- ("read_only_space", 0x02769): "OffHeapTrampolineRelocationInfo",
- ("read_only_space", 0x02781): "TrampolineTrivialCodeDataContainer",
- ("read_only_space", 0x02799): "TrampolinePromiseRejectionCodeDataContainer",
- ("read_only_space", 0x027b1): "HashSeed",
- ("old_space", 0x00111): "ArgumentsIteratorAccessor",
- ("old_space", 0x00181): "ArrayLengthAccessor",
- ("old_space", 0x001f1): "BoundFunctionLengthAccessor",
- ("old_space", 0x00261): "BoundFunctionNameAccessor",
- ("old_space", 0x002d1): "ErrorStackAccessor",
- ("old_space", 0x00341): "FunctionArgumentsAccessor",
- ("old_space", 0x003b1): "FunctionCallerAccessor",
- ("old_space", 0x00421): "FunctionNameAccessor",
- ("old_space", 0x00491): "FunctionLengthAccessor",
- ("old_space", 0x00501): "FunctionPrototypeAccessor",
- ("old_space", 0x00571): "StringLengthAccessor",
- ("old_space", 0x005e1): "InvalidPrototypeValidityCell",
- ("old_space", 0x005f1): "EmptyScript",
- ("old_space", 0x00671): "ManyClosuresCell",
- ("old_space", 0x00689): "ArrayConstructorProtector",
- ("old_space", 0x00699): "NoElementsProtector",
- ("old_space", 0x006c1): "IsConcatSpreadableProtector",
- ("old_space", 0x006d1): "ArraySpeciesProtector",
- ("old_space", 0x006f9): "TypedArraySpeciesProtector",
- ("old_space", 0x00721): "PromiseSpeciesProtector",
- ("old_space", 0x00749): "StringLengthProtector",
- ("old_space", 0x00759): "ArrayIteratorProtector",
- ("old_space", 0x00781): "ArrayBufferDetachingProtector",
- ("old_space", 0x007a9): "PromiseHookProtector",
- ("old_space", 0x007d1): "PromiseResolveProtector",
- ("old_space", 0x007e1): "MapIteratorProtector",
- ("old_space", 0x00809): "PromiseThenProtector",
- ("old_space", 0x00831): "SetIteratorProtector",
- ("old_space", 0x00859): "StringIteratorProtector",
- ("old_space", 0x00881): "SingleCharacterStringCache",
- ("old_space", 0x01091): "StringSplitCache",
- ("old_space", 0x018a1): "RegExpMultipleCache",
- ("old_space", 0x020b1): "BuiltinsConstantsTable",
+ ("read_only_space", 0x001b9): "NullValue",
+ ("read_only_space", 0x00239): "EmptyDescriptorArray",
+ ("read_only_space", 0x002a1): "EmptyWeakFixedArray",
+ ("read_only_space", 0x003a1): "UninitializedValue",
+ ("read_only_space", 0x004b1): "UndefinedValue",
+ ("read_only_space", 0x00531): "NanValue",
+ ("read_only_space", 0x00591): "TheHoleValue",
+ ("read_only_space", 0x00629): "HoleNanValue",
+ ("read_only_space", 0x00639): "TrueValue",
+ ("read_only_space", 0x006e9): "FalseValue",
+ ("read_only_space", 0x00731): "empty_string",
+ ("read_only_space", 0x00bf1): "EmptyScopeInfo",
+ ("read_only_space", 0x00c01): "EmptyFixedArray",
+ ("read_only_space", 0x00c11): "ArgumentsMarker",
+ ("read_only_space", 0x00cb1): "Exception",
+ ("read_only_space", 0x00d51): "TerminationException",
+ ("read_only_space", 0x00df9): "OptimizedOut",
+ ("read_only_space", 0x00e99): "StaleRegister",
+ ("read_only_space", 0x02389): "EmptyEnumCache",
+ ("read_only_space", 0x023f1): "EmptyPropertyArray",
+ ("read_only_space", 0x02401): "EmptyByteArray",
+ ("read_only_space", 0x02411): "EmptyObjectBoilerplateDescription",
+ ("read_only_space", 0x02429): "EmptyArrayBoilerplateDescription",
+ ("read_only_space", 0x02491): "EmptyClosureFeedbackCellArray",
+ ("read_only_space", 0x024a1): "EmptySloppyArgumentsElements",
+ ("read_only_space", 0x024c1): "EmptySlowElementDictionary",
+ ("read_only_space", 0x02509): "EmptyOrderedHashMap",
+ ("read_only_space", 0x02531): "EmptyOrderedHashSet",
+ ("read_only_space", 0x02559): "EmptyFeedbackMetadata",
+ ("read_only_space", 0x02569): "EmptyPropertyCell",
+ ("read_only_space", 0x02591): "EmptyPropertyDictionary",
+ ("read_only_space", 0x025e1): "NoOpInterceptorInfo",
+ ("read_only_space", 0x02681): "EmptyWeakArrayList",
+ ("read_only_space", 0x02699): "InfinityValue",
+ ("read_only_space", 0x026a9): "MinusZeroValue",
+ ("read_only_space", 0x026b9): "MinusInfinityValue",
+ ("read_only_space", 0x026c9): "SelfReferenceMarker",
+ ("read_only_space", 0x02721): "OffHeapTrampolineRelocationInfo",
+ ("read_only_space", 0x02739): "TrampolineTrivialCodeDataContainer",
+ ("read_only_space", 0x02751): "TrampolinePromiseRejectionCodeDataContainer",
+ ("read_only_space", 0x02769): "GlobalThisBindingScopeInfo",
+ ("read_only_space", 0x027d1): "EmptyFunctionScopeInfo",
+ ("read_only_space", 0x02821): "HashSeed",
+ ("old_space", 0x00119): "ArgumentsIteratorAccessor",
+ ("old_space", 0x00189): "ArrayLengthAccessor",
+ ("old_space", 0x001f9): "BoundFunctionLengthAccessor",
+ ("old_space", 0x00269): "BoundFunctionNameAccessor",
+ ("old_space", 0x002d9): "ErrorStackAccessor",
+ ("old_space", 0x00349): "FunctionArgumentsAccessor",
+ ("old_space", 0x003b9): "FunctionCallerAccessor",
+ ("old_space", 0x00429): "FunctionNameAccessor",
+ ("old_space", 0x00499): "FunctionLengthAccessor",
+ ("old_space", 0x00509): "FunctionPrototypeAccessor",
+ ("old_space", 0x00579): "StringLengthAccessor",
+ ("old_space", 0x005e9): "InvalidPrototypeValidityCell",
+ ("old_space", 0x005f9): "EmptyScript",
+ ("old_space", 0x00679): "ManyClosuresCell",
+ ("old_space", 0x00691): "ArrayConstructorProtector",
+ ("old_space", 0x006a1): "NoElementsProtector",
+ ("old_space", 0x006c9): "IsConcatSpreadableProtector",
+ ("old_space", 0x006d9): "ArraySpeciesProtector",
+ ("old_space", 0x00701): "TypedArraySpeciesProtector",
+ ("old_space", 0x00729): "PromiseSpeciesProtector",
+ ("old_space", 0x00751): "StringLengthProtector",
+ ("old_space", 0x00761): "ArrayIteratorProtector",
+ ("old_space", 0x00789): "ArrayBufferDetachingProtector",
+ ("old_space", 0x007b1): "PromiseHookProtector",
+ ("old_space", 0x007d9): "PromiseResolveProtector",
+ ("old_space", 0x007e9): "MapIteratorProtector",
+ ("old_space", 0x00811): "PromiseThenProtector",
+ ("old_space", 0x00839): "SetIteratorProtector",
+ ("old_space", 0x00861): "StringIteratorProtector",
+ ("old_space", 0x00889): "SingleCharacterStringCache",
+ ("old_space", 0x01099): "StringSplitCache",
+ ("old_space", 0x018a9): "RegExpMultipleCache",
+ ("old_space", 0x020b9): "BuiltinsConstantsTable",
}
# List of known V8 Frame Markers.
diff --git a/deps/v8/tools/wasm/update-wasm-spec-tests.sh b/deps/v8/tools/wasm/update-wasm-spec-tests.sh
index d029ffe604..01688648eb 100755
--- a/deps/v8/tools/wasm/update-wasm-spec-tests.sh
+++ b/deps/v8/tools/wasm/update-wasm-spec-tests.sh
@@ -30,6 +30,8 @@ V8_DIR="${TOOLS_WASM_DIR}/../.."
SPEC_TEST_DIR=${V8_DIR}/test/wasm-spec-tests
TMP_DIR=${SPEC_TEST_DIR}/tmp
+JS_API_TEST_DIR=${V8_DIR}/test/wasm-js
+
log_and_run cd ${V8_DIR}
log_and_run rm -rf ${SPEC_TEST_DIR}/tests
@@ -40,29 +42,40 @@ log_and_run mkdir ${SPEC_TEST_DIR}/tests/proposals
log_and_run rm -rf ${TMP_DIR}
log_and_run mkdir ${TMP_DIR}
+log_and_run rm -rf ${JS_API_TEST_DIR}/tests
+log_and_run mkdir ${JS_API_TEST_DIR}/tests
+log_and_run mkdir ${JS_API_TEST_DIR}/tests/proposals
+
###############################################################################
# Generate the spec tests.
###############################################################################
-log_and_run cd ${V8_DIR}/test/wasm-js/data/interpreter
+echo Process spec
+log_and_run cd ${TMP_DIR}
+log_and_run git clone https://github.com/WebAssembly/spec
+log_and_run cd spec/interpreter
+
# The next step requires that ocaml is installed. See the README.md in
-# ${V8_DIR}/test/wasm-js/data/interpreter/.
+# https://github.com/WebAssembly/spec/tree/master/interpreter/.
log_and_run make clean opt
-log_and_run cd ${V8_DIR}/test/wasm-js/data/test/core
+log_and_run cd ${TMP_DIR}/spec/test/core
log_and_run cp *.wast ${SPEC_TEST_DIR}/tests/
-log_and_run ./run.py --wasm ${V8_DIR}/test/wasm-js/data/interpreter/wasm --out ${TMP_DIR}
+log_and_run ./run.py --wasm ${TMP_DIR}/spec/interpreter/wasm --out ${TMP_DIR}
log_and_run cp ${TMP_DIR}/*.js ${SPEC_TEST_DIR}/tests/
+log_and_run cp -r ${TMP_DIR}/spec/test/js-api/* ${JS_API_TEST_DIR}/tests
+
###############################################################################
# Generate the proposal tests.
###############################################################################
-repos='bulk-memory-operations reference-types'
+repos='bulk-memory-operations reference-types js-types'
for repo in ${repos}; do
echo "Process ${repo}"
+ echo ">> Process core tests"
log_and_run cd ${TMP_DIR}
log_and_run git clone https://github.com/WebAssembly/${repo}
# Compile the spec interpreter to generate the .js test cases later.
@@ -76,13 +89,27 @@ for repo in ${repos}; do
for abs_filename in ${TMP_DIR}/${repo}/test/core/*.wast; do
rel_filename="$(basename -- $abs_filename)"
test_name=${rel_filename%.wast}
- spec_filename=${V8_DIR}/test/wasm-js/data/test/core/${rel_filename}
+ spec_filename=${TMP_DIR}/spec/test/core/${rel_filename}
if [ ! -f "$spec_filename" ] || ! cmp -s $abs_filename $spec_filename ; then
log_and_run cp ${rel_filename} ${SPEC_TEST_DIR}/tests/proposals/${repo}/
log_and_run ./run.py --wasm ../../interpreter/wasm ${rel_filename} --out _build 2> /dev/null
fi
done
log_and_run cp _build/*.js ${SPEC_TEST_DIR}/tests/proposals/${repo}/
+
+ echo ">> Process js-api tests"
+ log_and_run mkdir ${JS_API_TEST_DIR}/tests/proposals/${repo}
+ log_and_run cp -r ${TMP_DIR}/${repo}/test/js-api/* ${JS_API_TEST_DIR}/tests/proposals/${repo}
+ # Delete duplicate tests
+ log_and_run cd ${JS_API_TEST_DIR}/tests
+ for spec_test_name in $(find ./ -name '*.any.js' -not -wholename '*/proposals/*'); do
+ proposal_test_name="proposals/${repo}/${spec_test_name}"
+ if [ -f "$proposal_test_name" ] && cmp -s $spec_test_name $proposal_test_name ; then
+ log_and_run rm $proposal_test_name
+ elif [ -f "$proposal_test_name" ]; then
+ echo "keep" $proposal_test_name
+ fi
+ done
done
###############################################################################
@@ -95,6 +122,10 @@ echo "The following files will get uploaded:"
ls -R tests
echo
+cd ${JS_API_TEST_DIR}
+ls -R tests
+echo
+
log_and_run rm -rf ${TMP_DIR}
###############################################################################
@@ -111,3 +142,6 @@ echo "* When the script asks you for your project-id, use 0."
echo "****************************************************************************"
log_and_run cd ${SPEC_TEST_DIR}
log_and_run upload_to_google_storage.py -a -b v8-wasm-spec-tests tests
+
+log_and_run cd ${JS_API_TEST_DIR}
+log_and_run upload_to_google_storage.py -a -b v8-wasm-spec-tests tests
diff --git a/deps/v8/tools/whitespace.txt b/deps/v8/tools/whitespace.txt
index 9a80a32344..1540f5f52a 100644
--- a/deps/v8/tools/whitespace.txt
+++ b/deps/v8/tools/whitespace.txt
@@ -7,4 +7,6 @@ A Smi balks into a war and says:
The doubles heard this and started to unbox.
The Smi looked at them when a crazy v8-autoroll account showed up...
The autoroller bought a round of Himbeerbrause. Suddenly.....
-The bartender starts to shake the bottles..........
+The bartender starts to shake the bottles..............
+I can't add trailing whitespaces, so I'm adding this line.
+I'm starting to think that just adding trailing whitespaces might not be bad.
diff --git a/deps/v8/tools/windbg.js b/deps/v8/tools/windbg.js
index 3df14f4a2e..91877b4c61 100644
--- a/deps/v8/tools/windbg.js
+++ b/deps/v8/tools/windbg.js
@@ -1,4 +1,4 @@
-// Copyright 2019 the V8 project authors. All rights reserved.
+// Copyright 2019 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.
@@ -11,6 +11,7 @@
=============================================================================*/
function help() {
+ if (supports_call_command()) {
print("--------------------------------------------------------------------");
print(" LIVE debugging only");
print("--------------------------------------------------------------------");
@@ -27,11 +28,22 @@ function help() {
print(" !jsbp() or !jsbp");
print(" sets bp in v8::internal::Execution::Call");
print("");
+ }
+
print("--------------------------------------------------------------------");
- print(" Managed heap");
+ print(" Setup of the script");
print("--------------------------------------------------------------------");
+ print(" !set_module(\"module_name_no_extension\")");
+ print(" we'll try the usual suspects for where v8's code might have");
+ print(" been linked into, but you can also set it manually,");
+ print(" e.g. !set_module(\"v8_for_testing\")");
print(" !set_iso(isolate_address)");
print(" call this function before using !mem or other heap routines");
+ print("");
+
+ print("--------------------------------------------------------------------");
+ print(" Managed heap");
+ print("--------------------------------------------------------------------");
print(" !mem or !mem(\"space1[ space2 ...]\")");
print(" prints memory chunks from the 'space' owned by the heap in the");
print(" isolate set by !set_iso; valid values for 'space' are:");
@@ -42,16 +54,60 @@ function help() {
print(" prints name of the space and address of the MemoryChunk the");
print(" 'address' is from, e.g. !where(0x235cb869f9)");
print("");
+
+ print("--------------------------------------------------------------------");
+ print(" Managed objects");
+ print("--------------------------------------------------------------------");
+ print(" !jot(tagged_addr, depth)");
+ print(" dumps the tree of objects using 'tagged_addr' as a root,");
+ print(" assumes that pointer fields are aligned at ptr_size boundary,");
+ print(" unspecified depth means 'unlimited',");
+ print(" e.g. !jot(0x235cb869f9, 2), !jot 0x235cb869f9");
+ print(" !jo_in_range(start_addr, end_addr)");
+ print(" prints address/map pointers of objects found inside the range");
+ print(" specified by 'start_addr' and 'end_addr', assumes the object");
+ print(" pointers to be aligned at ptr_size boundary,");
+ print(" e.g. !jo_in_range(0x235cb869f8 - 0x100, 0x235cb869f8 + 0x1a0");
+ print(" !jo_prev(address, max_slots = 100)");
+ print(" prints address and map pointer of the nearest object within");
+ print(" 'max_slots' before the given 'address', assumes the object");
+ print(" pointers to be aligned at ptr_size boundary,");
+ print(" e.g. !jo_prev 0x235cb869f8, !jo_prev(0x235cb869f9, 16)");
+ print(" !jo_next(address, max_slots = 100)");
+ print(" prints address and map pointer of the nearest object within");
+ print(" 'max_slots' following the given 'address', assumes the object");
+ print(" pointers to be aligned at ptr_size boundary,");
+ print(" e.g. !jo_next 0x235cb869f8, !jo_next(0x235cb869f9, 20)");
+ print("");
+
+ print("--------------------------------------------------------------------");
+ print(" Miscellaneous");
+ print("--------------------------------------------------------------------");
+ print(" !dp(address, count = 10)");
+ print(" similar to the built-in 'dp' command but augments output with");
+ print(" more data for values that are managed pointers, note that it");
+ print(" aligns the given 'address' at ptr_sized boundary,");
+ print(" e.g. !dp 0x235cb869f9, !dp(0x235cb869f9, 500), !dp @rsp");
+ print(" !handles(print_handles = false)");
+ print(" prints stats for handles, if 'print_handles' is true will");
+ print(" output all handles as well,");
+ print(" e.g. !handles, !handles(), !handles(true)");
+ print("");
+
print("--------------------------------------------------------------------");
print(" To run any function from this script (live or postmortem):");
print("");
print(" dx @$scriptContents.function_name(args)");
print(" e.g. dx @$scriptContents.pointer_size()");
- print(" e.g. dx @$scriptContents.module_name(\"v8_for_test\")");
+ print(" e.g. dx @$scriptContents.is_map(0x235cb869f9)");
print("--------------------------------------------------------------------");
}
/*=============================================================================
+ On scrip load
+=============================================================================*/
+
+/*=============================================================================
Output
=============================================================================*/
function print(s) {
@@ -67,27 +123,60 @@ function print_filtered(obj, filter) {
}
function inspect(s) {
- for (var k of Reflect.ownKeys(s)) {
- print(k + " => " + Reflect.get(s, k));
+ for (let k of Reflect.ownKeys(s)) {
+ // Attempting to print either of:
+ // 'Reflect.get(s, k)', 'typeof Reflect.get(s, k)', 's[k]'
+ // might throw: "Error: Object does not have a size",
+ // while 'typeof s[k]' returns 'undefined' and prints the full list of
+ // properties. Oh well...
+ print(`${k} => ${typeof s[k]}`);
}
}
+function hex(number) {
+ return `0x${number.toString(16)}`;
+}
/*=============================================================================
Utils (postmortem and live)
=============================================================================*/
+// WinDbg wraps large integers into objects that fail isInteger test (and,
+// consequently fail isSafeInteger test even if the original value was a safe
+// integer). I cannot figure out how to extract the original value from the
+// wrapper object so doing it via conversion to a string. Brrr. Ugly.
+function int(val) {
+ if (typeof val === 'number') {
+ return Number.isInteger(val) ? val : undefined;
+ }
+ if (typeof val === 'object') {
+ let n = parseInt(val.toString());
+ return isNaN(n) ? undefined : n;
+ }
+ return undefined;
+}
+
+function is_live_session() {
+ // Assume that there is a single session (not sure how to get multiple ones
+ // going, maybe, in kernel debugging?).
+ return (host.namespace.Debugger.Sessions[0].Attributes.Target.IsLiveTarget);
+}
+
+function is_TTD_session() {
+ // Assume that there is a single session (not sure how to get multiple ones
+ // going, maybe, in kernel debugging?).
+ return (host.namespace.Debugger.Sessions[0].Attributes.Target.IsTTDTarget);
+}
+
+function supports_call_command() {
+ return is_live_session() && !is_TTD_session();
+}
+
function cast(address, type_name) {
return host.createTypedObject(address, module_name(), type_name);
}
-// Failed to figure out how to get pointer size from the debugger's data model,
-// so we parse it out from sizeof(void*) output.
function pointer_size() {
- let ctl = host.namespace.Debugger.Utility.Control;
- let sizeof = ctl.ExecuteCommand("?? sizeof(void*)");
- let output = "";
- for (output of sizeof) {} // unsigned int64 8
- return parseInt(output.trim().split(" ").pop());
+ return host.namespace.Debugger.Sessions[0].Attributes.Machine.PointerSize;
}
function poi(address) {
@@ -105,8 +194,7 @@ function get_register(name) {
// In debug builds v8 code is compiled into v8.dll, and in release builds
// the code is compiled directly into the executable. If you are debugging some
-// other embedder, invoke module_name explicitly from the debugger and provide
-// the module name to use.
+// other embedder, run !set_module and provide the module name to use.
const known_exes = ["d8", "unittests", "mksnapshot", "chrome", "chromium"];
let module_name_cache;
function module_name(use_this_module) {
@@ -138,10 +226,20 @@ function module_name(use_this_module) {
}
}
}
+
+ if (!module_name_cache) {
+ print(`ERROR. Couldn't determine module name for v8's symbols.`);
+ print(`Please run !set_module (e.g. "!set_module \"v8_for_testing\"")`);
+ }
return module_name_cache;
};
function make_call(fn) {
+ if (!supports_call_command()) {
+ print("ERROR: This command is supported in live sessions only!");
+ return;
+ }
+
// .call resets current frame to the top one, so have to manually remember
// and restore it after making the call.
let curframe = host.namespace.Debugger.State.DebuggerVariables.curframe;
@@ -151,21 +249,6 @@ function make_call(fn) {
return output;
}
-// Skips the meta output about the .call invocation.
-function make_call_and_print_return(fn) {
- let output = make_call(fn);
- let print_line = false;
- for (let line of output) {
- if (print_line) {
- print(line);
- break;
- }
- if (line.includes(".call returns")) {
- print_line = true;
- }
- }
-}
-
/*=============================================================================
Wrappers around V8's printing functions and other utils for live-debugging
@@ -206,11 +289,11 @@ function print_object_from_handle(handle_to_object) {
point at any continuous memory that contains Object pointers.
-----------------------------------------------------------------------------*/
function print_objects_array(start_address, count) {
+ const ptr_size = pointer_size();
let ctl = host.namespace.Debugger.Utility.Control;
- let psize = pointer_size();
let addr_int = start_address;
for (let i = 0; i < count; i++) {
- const addr_hex = `0x${addr_int.toString(16)}`;
+ const addr_hex = hex(addr_int);
// TODO: Tried using createPointerObject but it throws unknown exception
// from ChakraCore. Why?
@@ -223,7 +306,7 @@ function print_objects_array(start_address, count) {
print(`${addr_hex} -> ${deref}`);
print_object(deref);
- addr_int += psize;
+ addr_int += ptr_size;
}
}
@@ -245,6 +328,168 @@ function set_isolate_address(addr) {
isolate_address = addr;
}
+function is_map(addr) {
+ let address = int(addr);
+ if (!Number.isSafeInteger(address) || address % 2 == 0) return false;
+
+ // the first field in all objects, including maps, is a map pointer, but for
+ // maps the pointer is always the same - the meta map that points to itself.
+ const map_addr = int(poi(address - 1));
+ if (!Number.isSafeInteger(map_addr)) return false;
+
+ const map_map_addr = int(poi(map_addr - 1));
+ if (!Number.isSafeInteger(map_map_addr)) return false;
+
+ return (map_addr === map_map_addr);
+}
+
+function is_likely_object(addr) {
+ let address = int(addr);
+ if (!Number.isSafeInteger(address) || address % 2 == 0) return false;
+
+ // the first field in all objects must be a map pointer
+ return is_map(poi(address - 1));
+}
+
+function find_object_near(aligned_addr, max_distance, step_op) {
+ if (!step_op) {
+ const step = pointer_size();
+ const prev =
+ find_object_near(aligned_addr, max_distance, x => x - step);
+ const next =
+ find_object_near(aligned_addr, max_distance, x => x + step);
+
+ if (!prev) return next;
+ if (!next) return prev;
+ return (addr - prev <= next - addr) ? prev : next;
+ }
+
+ let maybe_map_addr = poi(aligned_addr);
+ let iters = 0;
+ while (maybe_map_addr && iters < max_distance) {
+ if (is_map(maybe_map_addr)) {
+ return aligned_addr;
+ }
+ aligned_addr = step_op(aligned_addr);
+ maybe_map_addr = poi(aligned_addr);
+ iters++;
+ }
+}
+
+function find_object_prev(addr, max_distance) {
+ if (!Number.isSafeInteger(int(addr))) return;
+
+ const ptr_size = pointer_size();
+ const aligned_addr = addr - (addr % ptr_size);
+ return find_object_near(aligned_addr, max_distance, x => x - ptr_size);
+}
+
+function find_object_next(addr, max_distance) {
+ if (!Number.isSafeInteger(int(addr))) return;
+
+ const ptr_size = pointer_size();
+ const aligned_addr = addr - (addr % ptr_size) + ptr_size;
+ return find_object_near(aligned_addr, max_distance, x => x + ptr_size);
+}
+
+function print_object_prev(addr, max_slots = 100) {
+ let obj_addr = find_object_prev(addr, max_slots);
+ if (!obj_addr) {
+ print(
+ `No object found within ${max_slots} slots prior to ${hex(addr)}`);
+ }
+ else {
+ print(
+ `found object: ${hex(obj_addr + 1)} : ${hex(poi(obj_addr))}`);
+ }
+}
+
+function print_object_next(addr, max_slots = 100) {
+ let obj_addr = find_object_next(addr, max_slots);
+ if (!obj_addr) {
+ print(
+ `No object found within ${max_slots} slots following ${hex(addr)}`);
+ }
+ else {
+ print(
+ `found object: ${hex(obj_addr + 1)} : ${hex(poi(obj_addr))}`);
+ }
+}
+
+// This function assumes that pointers to objects are stored at ptr-size aligned
+// boundaries.
+function print_objects_in_range(start, end){
+ if (!Number.isSafeInteger(int(start)) || !Number.isSafeInteger(int(end))) {
+ return;
+ }
+
+ const ptr_size = pointer_size();
+ let iters = (end - start) / ptr_size;
+ let cur = start;
+ print(`===============================================`);
+ print(`objects in range ${hex(start)} - ${hex(end)}`);
+ print(`===============================================`);
+ let count = 0;
+ while (cur && cur < end) {
+ let obj = find_object_next(cur, iters);
+ if (obj) {
+ count++;
+ print(`${hex(obj + 1)} : ${hex(poi(obj))}`);
+ iters = (end - cur) / ptr_size;
+ }
+ cur = obj + ptr_size;
+ }
+ print(`===============================================`);
+ print(`found ${count} objects in range ${hex(start)} - ${hex(end)}`)
+ print(`===============================================`);
+}
+
+// This function assumes the pointer fields to be ptr-size aligned.
+function print_objects_tree(root, depth_limit) {
+ if(!is_likely_object(root)) {
+ print(`${hex(root)} doesn't look like an object`);
+ return;
+ }
+
+ let path = [];
+
+ function impl(obj, depth, depth_limit) {
+ const ptr_size = pointer_size();
+ // print the current object and its map pointer
+ const this_obj =
+ `${" ".repeat(2 * depth)}${hex(obj)} : ${hex(poi(obj - 1))}`;
+ const cutoff = depth_limit && depth == depth_limit - 1;
+ print(`${this_obj}${cutoff ? " (...)" : ""}`);
+ if (cutoff) return;
+
+ path[depth] = obj;
+ path.length = depth + 1;
+ let cur = obj - 1 + ptr_size;
+
+ // Scan downwards until an address that is likely to be at the start of
+ // another object, in which case it's time to pop out from the recursion.
+ let iter = 0; // an arbitrary guard to avoid hanging the debugger
+ let seen = new Set(path);
+ while (!is_likely_object(cur + 1) && iter < 100) {
+ iter++;
+ let field = poi(cur);
+ if (is_likely_object(field)) {
+ if (seen.has(field)) {
+ print(
+ `${" ".repeat(2 * depth + 2)}cycle: ${hex(cur)}->${hex(field)}`);
+ }
+ else {
+ impl(field, depth + 1, depth_limit);
+ }
+ }
+ cur += ptr_size;
+ }
+ }
+ print(`===============================================`);
+ impl(root, 0, depth_limit);
+ print(`===============================================`);
+}
+
/*-----------------------------------------------------------------------------
Memory in each Space is organized into a linked list of memory chunks
-----------------------------------------------------------------------------*/
@@ -262,11 +507,10 @@ function print_memory_chunk_list(space_type, front, top, age_mark) {
let cur = front;
while (!cur.isNull) {
let imm = cur.flags_ & NEVER_EVACUATE ? "*" : " ";
- let addr = `0x${cur.address.toString(16)}`;
- let area =
- `0x${cur.area_start_.toString(16)} - 0x${cur.area_end_.toString(16)}`;
+ let addr = hex(cur.address);
+ let area = `${hex(cur.area_start_)} - ${hex(cur.area_end_)}`;
let dt = `dt ${addr} ${module_name()}!v8::internal::MemoryChunk`;
- print(`${imm} ${addr}:\t ${area} (0x${cur.size_.toString(16)}) : ${dt}`);
+ print(`${imm} ${addr}:\t ${area} (${hex(cur.size_)}) : ${dt}`);
cur = cur.list_node_.next_;
}
print("");
@@ -307,18 +551,16 @@ function get_chunks() {
}
function find_chunk(address) {
- // if 'address' is greater than Number.MAX_SAFE_INTEGER, comparison ops on it
- // throw "Error: 64 bit value loses precision on conversion to number"
- try {
- let chunks = get_chunks(isolate_address);
- for (let c of chunks) {
- let chunk = cast(c.address, "v8::internal::MemoryChunk");
- if (address >= chunk.area_start_ && address < chunk.area_end_) {
- return c;
- }
+ if (!Number.isSafeInteger(int(address))) return undefined;
+
+ let chunks = get_chunks(isolate_address);
+ for (let c of chunks) {
+ let chunk = cast(c.address, "v8::internal::MemoryChunk");
+ if (address >= chunk.area_start_ && address < chunk.area_end_) {
+ return c;
}
}
- catch (e) { }
+
return undefined;
}
@@ -391,12 +633,111 @@ function print_owning_space(address) {
}
let c = find_chunk(address);
- let addr = `0x${address.toString(16)}`;
if (c) {
- print(`${addr} is in ${c.space} (chunk: 0x${c.address.toString(16)})`);
+ print(`${hex(address)} is in ${c.space} (chunk: ${hex(c.address)})`);
}
else {
- print(`Address ${addr} is not in managed heap`);
+ print(`Address ${hex(address)} is not in managed heap`);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------*/
+function print_handles_data(print_handles = false) {
+ if (isolate_address == 0) {
+ print("Please call !set_iso(isolate_address) first.");
+ return;
+ }
+
+ let iso = cast(isolate_address, "v8::internal::Isolate");
+ let hsd = iso.handle_scope_data_;
+ let hsimpl = iso.handle_scope_implementer_;
+
+ // depth level
+ print(`Nested depth level: ${hsd.level}`);
+
+ // count of handles
+ const ptr_size = pointer_size();
+ let blocks = hsimpl.blocks_;
+ const block_size = 1022; // v8::internal::KB - 2
+ const first_block = blocks.data_.address;
+ const last_block = (blocks.size_ == 0)
+ ? first_block
+ : first_block + ptr_size * (blocks.size_ - 1);
+
+ const count = (blocks.size_ == 0)
+ ? 0
+ : (blocks.size_ - 1) * block_size +
+ (hsd.next.address - poi(last_block))/ptr_size;
+ print(`Currently tracking ${count} local handles`);
+
+ // print the handles
+ if (print_handles && count > 0) {
+ for (let block = first_block; block < last_block;
+ block += block_size * ptr_size) {
+ print(`Handles in block at ${hex(block)}`);
+ for (let i = 0; i < block_size; i++) {
+ const location = poi(block + i * ptr_size);
+ print(` ${hex(location)}->${hex(poi(location))}`);
+ }
+ }
+
+ let location = poi(last_block);
+ print(`Handles in block at ${hex(last_block)}`);
+ for (let location = poi(last_block); location < hsd.next.address;
+ location += ptr_size) {
+ print(` ${hex(location)}->${hex(poi(location))}`);
+ }
+ }
+
+ // where will the next handle allocate at?
+ const prefix = "Next handle's location will be";
+ if (hsd.next.address < hsd.limit.address) {
+ print(`${prefix} at ${hex(hsd.next.address)}`);
+ }
+ else if (hsimpl.spare_) {
+ const location = hsimpl.spare_.address;
+ print(`${prefix} from the spare block at ${hex(location)}`);
+ }
+ else {
+ print(`${prefix} from a new block to be allocated`);
+ }
+}
+
+function pad_right(addr) {
+ let addr_hex = hex(addr);
+ return `${addr_hex}${" ".repeat(pointer_size() * 2 + 2 - addr_hex.length)}`;
+}
+
+// TODO irinayat: would be nice to identify handles and smi as well
+function dp(addr, count = 10) {
+ if (isolate_address == 0) {
+ print(`To see where objects are located, run !set_iso.`);
+ }
+
+ if (!Number.isSafeInteger(int(addr))) {
+ print(`${hex(addr)} doesn't look like a valid address`);
+ return;
+ }
+
+ const ptr_size = pointer_size();
+ let aligned_addr = addr - (addr % ptr_size);
+ let val = poi(aligned_addr);
+ let iter = 0;
+ while (val && iter < count) {
+ const augm_map = is_map(val) ? "map" : "";
+ const augm_obj = is_likely_object(val) && !is_map(val) ? "obj" : "";
+ const augm_other = !is_map(val) && !is_likely_object(val) ? "val" : "";
+ let c = find_chunk(val);
+ const augm_space = c ? ` in ${c.space}` : "";
+ const augm = `${augm_map}${augm_obj}${augm_other}${augm_space}`;
+
+ print(`${pad_right(aligned_addr)} ${pad_right(val)} ${augm}`);
+
+ aligned_addr += ptr_size;
+ val = poi(aligned_addr);
+ iter++;
}
}
@@ -412,8 +753,17 @@ function initializeScript() {
new host.functionAlias(print_js_stack, "jst"),
new host.functionAlias(set_isolate_address, "set_iso"),
+ new host.functionAlias(module_name, "set_module"),
new host.functionAlias(print_memory, "mem"),
new host.functionAlias(print_owning_space, "where"),
+ new host.functionAlias(print_handles_data, "handles"),
+
+ new host.functionAlias(print_object_prev, "jo_prev"),
+ new host.functionAlias(print_object_next, "jo_next"),
+ new host.functionAlias(print_objects_in_range, "jo_in_range"),
+ new host.functionAlias(print_objects_tree, "jot"),
+
+ new host.functionAlias(dp, "dp"),
new host.functionAlias(set_user_js_bp, "jsbp"),
]