diff --git a/common.gypi b/common.gypi index 46b4633f5d7e85..99baed035beed9 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.16', + 'v8_embedder_string': '-node.15', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index 47a83c5ff1c905..7c43c60fc13af2 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -118,6 +118,7 @@ Joel Stanley Johan Bergström Jonathan Liu Julien Brianceau +Junha Park JunHo Seo Junming Huang Kang-Hao (Kenny) Lu @@ -196,6 +197,7 @@ Tobias Burnus Tobias Nießen Ujjwal Sharma Vadim Gorbachev +Varun Varada Victor Costan Vlad Burlik Vladimir Krivosheev @@ -213,4 +215,5 @@ Zhao Jiazhong Zhongping Wang 柳荣一 Yanbo Li -Gilang Mentari Hamidy \ No newline at end of file +Gilang Mentari Hamidy +Zeynep Cankara \ No newline at end of file diff --git a/deps/v8/BUILD.gn b/deps/v8/BUILD.gn index 167e63503c5535..9f5b8db2f23d43 100644 --- a/deps/v8/BUILD.gn +++ b/deps/v8/BUILD.gn @@ -109,6 +109,9 @@ declare_args() { v8_enable_pointer_compression = "" v8_enable_31bit_smis_on_64bit_arch = false + # Reverse JS arguments order in the stack (sets -dV8_REVERSE_JSARGS). + v8_enable_reverse_jsargs = false + # Sets -dOBJECT_PRINT. v8_enable_object_print = "" @@ -130,6 +133,17 @@ declare_args() { # Sets -dV8_ARRAY_BUFFER_EXTENSION v8_enable_array_buffer_extension = true + # Runs mksnapshot with --turbo-profiling. After building in this + # configuration, any subsequent run of d8 will output information about usage + # of basic blocks in builtins. + v8_enable_builtins_profiling = false + + # Runs mksnapshot with --turbo-profiling-verbose. After building in this + # configuration, any subsequent run of d8 will output information about usage + # of basic blocks in builtins, including the schedule and disassembly of all + # used builtins. + v8_enable_builtins_profiling_verbose = false + # Enables various testing features. v8_enable_test_features = "" @@ -222,6 +236,12 @@ declare_args() { # Enable object names in cppgc for debug purposes. cppgc_enable_object_names = false + # Enable heap reservation of size 4GB. Only possible for 64bit archs. + cppgc_enable_caged_heap = v8_current_cpu == "x64" || v8_current_cpu == "arm64" + + # Enable young generation in cppgc. + cppgc_enable_young_generation = false + # Enable V8 heap sandbox experimental feature. # Sets -DV8_HEAP_SANDBOX. v8_enable_heap_sandbox = "" @@ -258,7 +278,6 @@ if (v8_enable_snapshot_native_code_counters == "") { v8_enable_snapshot_native_code_counters = v8_enable_debugging_features } if (v8_enable_pointer_compression == "") { - # TODO(v8:v7703): temporarily enable pointer compression on arm64 and on x64 v8_enable_pointer_compression = v8_current_cpu == "arm64" || v8_current_cpu == "x64" } @@ -300,6 +319,13 @@ assert( assert(!v8_enable_heap_sandbox || v8_enable_pointer_compression, "V8 Heap Sandbox requires pointer compression") +assert(!cppgc_enable_caged_heap || v8_current_cpu == "x64" || + v8_current_cpu == "arm64", + "CppGC caged heap requires 64bit platforms") + +assert(!cppgc_enable_young_generation || cppgc_enable_caged_heap, + "Young generation in CppGC requires caged heap") + v8_random_seed = "314159265" v8_toolset_for_shell = "host" @@ -370,6 +396,12 @@ config("cppgc_base_config") { if (cppgc_enable_object_names) { defines += [ "CPPGC_SUPPORTS_OBJECT_NAMES" ] } + if (cppgc_enable_caged_heap) { + defines += [ "CPPGC_CAGED_HEAP" ] + } + if (cppgc_enable_young_generation) { + defines += [ "CPPGC_YOUNG_GENERATION" ] + } } # This config should be applied to code using the libsampler. @@ -424,6 +456,9 @@ config("v8_header_features") { if (v8_imminent_deprecation_warnings) { defines += [ "V8_IMMINENT_DEPRECATION_WARNINGS" ] } + if (v8_enable_reverse_jsargs) { + defines += [ "V8_REVERSE_JSARGS" ] + } } # Put defines here that are only used in our internal files and NEVER in @@ -556,6 +591,9 @@ config("features") { if (v8_enable_nci_code) { defines += [ "V8_ENABLE_NCI_CODE" ] } + if (v8_fuzzilli) { + defines += [ "V8_FUZZILLI" ] + } } config("toolchain") { @@ -1005,6 +1043,7 @@ action("postmortem-metadata") { } torque_files = [ + "src/builtins/aggregate-error.tq", "src/builtins/array-copywithin.tq", "src/builtins/array-every.tq", "src/builtins/array-filter.tq", @@ -1030,18 +1069,21 @@ torque_files = [ "src/builtins/bigint.tq", "src/builtins/boolean.tq", "src/builtins/builtins-string.tq", - "src/builtins/collections.tq", "src/builtins/cast.tq", + "src/builtins/collections.tq", + "src/builtins/conversion.tq", "src/builtins/convert.tq", "src/builtins/console.tq", "src/builtins/data-view.tq", "src/builtins/finalization-registry.tq", "src/builtins/frames.tq", "src/builtins/frame-arguments.tq", + "src/builtins/function.tq", "src/builtins/growable-fixed-array.tq", "src/builtins/ic-callable.tq", "src/builtins/ic.tq", "src/builtins/internal-coverage.tq", + "src/builtins/internal.tq", "src/builtins/iterator.tq", "src/builtins/math.tq", "src/builtins/number.tq", @@ -1095,11 +1137,13 @@ torque_files = [ "src/builtins/torque-internal.tq", "src/builtins/typed-array-createtypedarray.tq", "src/builtins/typed-array-every.tq", + "src/builtins/typed-array-entries.tq", "src/builtins/typed-array-filter.tq", "src/builtins/typed-array-find.tq", "src/builtins/typed-array-findindex.tq", "src/builtins/typed-array-foreach.tq", "src/builtins/typed-array-from.tq", + "src/builtins/typed-array-keys.tq", "src/builtins/typed-array-of.tq", "src/builtins/typed-array-reduce.tq", "src/builtins/typed-array-reduceright.tq", @@ -1108,6 +1152,7 @@ torque_files = [ "src/builtins/typed-array-some.tq", "src/builtins/typed-array-sort.tq", "src/builtins/typed-array-subarray.tq", + "src/builtins/typed-array-values.tq", "src/builtins/typed-array.tq", "src/builtins/wasm.tq", "src/ic/handler-configuration.tq", @@ -1129,7 +1174,6 @@ torque_files = [ "src/objects/heap-number.tq", "src/objects/heap-object.tq", "src/objects/intl-objects.tq", - "src/objects/js-aggregate-error.tq", "src/objects/js-array-buffer.tq", "src/objects/js-array.tq", "src/objects/js-collection-iterator.tq", @@ -1408,6 +1452,13 @@ template("run_mksnapshot") { rebase_path("$target_gen_dir/embedded${suffix}.S", root_build_dir), ] + if (v8_enable_builtins_profiling) { + args += [ "--turbo-profiling" ] + } + if (v8_enable_builtins_profiling_verbose) { + args += [ "--turbo-profiling-verbose" ] + } + # This is needed to distinguish between generating code for the simulator # and cross-compiling. The latter may need to run code on the host with the # simulator but cannot use simulator-specific instructions. @@ -1632,7 +1683,6 @@ v8_source_set("v8_initializers") { "src/builtins/builtins-data-view-gen.h", "src/builtins/builtins-date-gen.cc", "src/builtins/builtins-debug-gen.cc", - "src/builtins/builtins-function-gen.cc", "src/builtins/builtins-generator-gen.cc", "src/builtins/builtins-global-gen.cc", "src/builtins/builtins-handler-gen.cc", @@ -1673,6 +1723,8 @@ v8_source_set("v8_initializers") { "src/ic/binary-op-assembler.h", "src/ic/keyed-store-generic.cc", "src/ic/keyed-store-generic.h", + "src/ic/unary-op-assembler.cc", + "src/ic/unary-op-assembler.h", "src/interpreter/interpreter-assembler.cc", "src/interpreter/interpreter-assembler.h", "src/interpreter/interpreter-generator.cc", @@ -2391,6 +2443,7 @@ v8_source_set("v8_base_without_compiler") { "src/handles/maybe-handles.h", "src/handles/persistent-handles.cc", "src/handles/persistent-handles.h", + "src/heap/allocation-stats.h", "src/heap/array-buffer-collector.cc", "src/heap/array-buffer-collector.h", "src/heap/array-buffer-sweeper.cc", @@ -2399,8 +2452,12 @@ v8_source_set("v8_base_without_compiler") { "src/heap/array-buffer-tracker.cc", "src/heap/array-buffer-tracker.h", "src/heap/barrier.h", + "src/heap/base-space.cc", + "src/heap/base-space.h", "src/heap/basic-memory-chunk.cc", "src/heap/basic-memory-chunk.h", + "src/heap/code-object-registry.cc", + "src/heap/code-object-registry.h", "src/heap/code-stats.cc", "src/heap/code-stats.h", "src/heap/combined-heap.cc", @@ -2410,6 +2467,8 @@ v8_source_set("v8_base_without_compiler") { "src/heap/concurrent-allocator.h", "src/heap/concurrent-marking.cc", "src/heap/concurrent-marking.h", + "src/heap/cppgc-js/cpp-heap.cc", + "src/heap/cppgc-js/cpp-heap.h", "src/heap/embedder-tracing.cc", "src/heap/embedder-tracing.h", "src/heap/factory-base.cc", @@ -2419,6 +2478,9 @@ v8_source_set("v8_base_without_compiler") { "src/heap/factory.h", "src/heap/finalization-registry-cleanup-task.cc", "src/heap/finalization-registry-cleanup-task.h", + "src/heap/free-list-inl.h", + "src/heap/free-list.cc", + "src/heap/free-list.h", "src/heap/gc-idle-time-handler.cc", "src/heap/gc-idle-time-handler.h", "src/heap/gc-tracer.cc", @@ -2456,6 +2518,8 @@ v8_source_set("v8_base_without_compiler") { "src/heap/marking-worklist.h", "src/heap/marking.cc", "src/heap/marking.h", + "src/heap/memory-allocator.cc", + "src/heap/memory-allocator.h", "src/heap/memory-chunk-inl.h", "src/heap/memory-chunk.cc", "src/heap/memory-chunk.h", @@ -2464,6 +2528,9 @@ v8_source_set("v8_base_without_compiler") { "src/heap/memory-measurement.h", "src/heap/memory-reducer.cc", "src/heap/memory-reducer.h", + "src/heap/new-spaces-inl.h", + "src/heap/new-spaces.cc", + "src/heap/new-spaces.h", "src/heap/object-stats.cc", "src/heap/object-stats.h", "src/heap/objects-visiting-inl.h", @@ -2473,11 +2540,15 @@ v8_source_set("v8_base_without_compiler") { "src/heap/off-thread-factory.h", "src/heap/off-thread-heap.cc", "src/heap/off-thread-heap.h", + "src/heap/paged-spaces-inl.h", + "src/heap/paged-spaces.cc", + "src/heap/paged-spaces.h", "src/heap/read-only-heap-inl.h", "src/heap/read-only-heap.cc", "src/heap/read-only-heap.h", "src/heap/read-only-spaces.cc", "src/heap/read-only-spaces.h", + "src/heap/remembered-set-inl.h", "src/heap/remembered-set.h", "src/heap/safepoint.cc", "src/heap/safepoint.h", @@ -2582,6 +2653,8 @@ v8_source_set("v8_base_without_compiler") { "src/logging/log.cc", "src/logging/log.h", "src/logging/off-thread-logger.h", + "src/logging/tracing-flags.cc", + "src/logging/tracing-flags.h", "src/numbers/bignum-dtoa.cc", "src/numbers/bignum-dtoa.h", "src/numbers/bignum.cc", @@ -2672,8 +2745,6 @@ v8_source_set("v8_base_without_compiler") { "src/objects/internal-index.h", "src/objects/intl-objects.cc", "src/objects/intl-objects.h", - "src/objects/js-aggregate-error-inl.h", - "src/objects/js-aggregate-error.h", "src/objects/js-array-buffer-inl.h", "src/objects/js-array-buffer.cc", "src/objects/js-array-buffer.h", @@ -3108,6 +3179,7 @@ v8_source_set("v8_base_without_compiler") { "src/wasm/streaming-decoder.cc", "src/wasm/streaming-decoder.h", "src/wasm/struct-types.h", + "src/wasm/sync-streaming-decoder.cc", "src/wasm/value-type.h", "src/wasm/wasm-arguments.h", "src/wasm/wasm-code-manager.cc", @@ -3125,8 +3197,6 @@ v8_source_set("v8_base_without_compiler") { "src/wasm/wasm-features.h", "src/wasm/wasm-import-wrapper-cache.cc", "src/wasm/wasm-import-wrapper-cache.h", - "src/wasm/wasm-interpreter.cc", - "src/wasm/wasm-interpreter.h", "src/wasm/wasm-js.cc", "src/wasm/wasm-js.h", "src/wasm/wasm-limits.h", @@ -3146,6 +3216,8 @@ v8_source_set("v8_base_without_compiler") { "src/wasm/wasm-result.h", "src/wasm/wasm-serialization.cc", "src/wasm/wasm-serialization.h", + "src/wasm/wasm-subtyping.cc", + "src/wasm/wasm-subtyping.h", "src/wasm/wasm-tier.h", "src/wasm/wasm-value.h", "src/zone/accounting-allocator.cc", @@ -3192,6 +3264,13 @@ v8_source_set("v8_base_without_compiler") { ] } + if (v8_fuzzilli) { + sources += [ + "src/d8/cov.cc", + "src/d8/cov.h", + ] + } + if (v8_check_header_includes) { # This file will be generated by tools/generate-header-include-checks.py # if the "check_v8_header_includes" gclient variable is set. @@ -3500,10 +3579,14 @@ v8_source_set("v8_base_without_compiler") { ] } - configs = [ ":internal_config" ] + configs = [ + ":internal_config", + ":cppgc_base_config", + ] defines = [] deps = [ + ":cppgc_base", ":torque_generated_definitions", ":v8_headers", ":v8_libbase", @@ -4026,6 +4109,45 @@ v8_source_set("fuzzer_support") { ] } +v8_source_set("v8_cppgc_shared") { + sources = [ + "src/heap/base/stack.cc", + "src/heap/base/stack.h", + ] + + if (is_clang || !is_win) { + if (current_cpu == "x64") { + sources += [ "src/heap/base/asm/x64/push_registers_asm.cc" ] + } else if (current_cpu == "x86") { + sources += [ "src/heap/base/asm/ia32/push_registers_asm.cc" ] + } else if (current_cpu == "arm") { + sources += [ "src/heap/base/asm/arm/push_registers_asm.cc" ] + } else if (current_cpu == "arm64") { + sources += [ "src/heap/base/asm/arm64/push_registers_asm.cc" ] + } else if (current_cpu == "ppc64") { + sources += [ "src/heap/base/asm/ppc/push_registers_asm.cc" ] + } else if (current_cpu == "s390x") { + sources += [ "src/heap/base/asm/s390/push_registers_asm.cc" ] + } else if (current_cpu == "mipsel") { + sources += [ "src/heap/base/asm/mips/push_registers_asm.cc" ] + } else if (current_cpu == "mips64el") { + sources += [ "src/heap/base/asm/mips64/push_registers_asm.cc" ] + } + } else if (is_win) { + if (current_cpu == "x64") { + sources += [ "src/heap/base/asm/x64/push_registers_masm.S" ] + } else if (current_cpu == "x86") { + sources += [ "src/heap/base/asm/ia32/push_registers_masm.S" ] + } else if (current_cpu == "arm64") { + sources += [ "src/heap/base/asm/arm64/push_registers_masm.S" ] + } + } + + configs = [ ":internal_config" ] + + public_deps = [ ":v8_libbase" ] +} + v8_source_set("cppgc_base") { visibility = [ ":*" ] @@ -4035,14 +4157,16 @@ v8_source_set("cppgc_base") { "include/cppgc/custom-space.h", "include/cppgc/garbage-collected.h", "include/cppgc/heap.h", - "include/cppgc/internal/accessors.h", - "include/cppgc/internal/api-contants.h", + "include/cppgc/internal/api-constants.h", + "include/cppgc/internal/atomic-entry-flag.h", "include/cppgc/internal/compiler-specific.h", - "include/cppgc/internal/finalizer-traits.h", + "include/cppgc/internal/finalizer-trait.h", "include/cppgc/internal/gc-info.h", "include/cppgc/internal/persistent-node.h", "include/cppgc/internal/pointer-policies.h", "include/cppgc/internal/prefinalizer-handler.h", + "include/cppgc/internal/process-heap.h", + "include/cppgc/internal/write-barrier.h", "include/cppgc/liveness-broker.h", "include/cppgc/liveness-broker.h", "include/cppgc/macros.h", @@ -4058,13 +4182,20 @@ v8_source_set("cppgc_base") { "src/heap/cppgc/allocation.cc", "src/heap/cppgc/free-list.cc", "src/heap/cppgc/free-list.h", + "src/heap/cppgc/garbage-collector.h", "src/heap/cppgc/gc-info-table.cc", "src/heap/cppgc/gc-info-table.h", "src/heap/cppgc/gc-info.cc", - "src/heap/cppgc/heap-inl.h", + "src/heap/cppgc/gc-invoker.cc", + "src/heap/cppgc/gc-invoker.h", + "src/heap/cppgc/heap-base.cc", + "src/heap/cppgc/heap-base.h", + "src/heap/cppgc/heap-growing.cc", + "src/heap/cppgc/heap-growing.h", "src/heap/cppgc/heap-object-header-inl.h", "src/heap/cppgc/heap-object-header.cc", "src/heap/cppgc/heap-object-header.h", + "src/heap/cppgc/heap-page-inl.h", "src/heap/cppgc/heap-page.cc", "src/heap/cppgc/heap-page.h", "src/heap/cppgc/heap-space.cc", @@ -4091,43 +4222,30 @@ v8_source_set("cppgc_base") { "src/heap/cppgc/pointer-policies.cc", "src/heap/cppgc/prefinalizer-handler.cc", "src/heap/cppgc/prefinalizer-handler.h", + "src/heap/cppgc/process-heap.cc", "src/heap/cppgc/raw-heap.cc", "src/heap/cppgc/raw-heap.h", "src/heap/cppgc/sanitizers.h", "src/heap/cppgc/source-location.cc", - "src/heap/cppgc/stack.cc", - "src/heap/cppgc/stack.h", + "src/heap/cppgc/stats-collector.cc", + "src/heap/cppgc/stats-collector.h", "src/heap/cppgc/sweeper.cc", "src/heap/cppgc/sweeper.h", + "src/heap/cppgc/task-handle.h", + "src/heap/cppgc/virtual-memory.cc", + "src/heap/cppgc/virtual-memory.h", + "src/heap/cppgc/visitor.cc", "src/heap/cppgc/worklist.h", + "src/heap/cppgc/write-barrier.cc", ] - if (is_clang || !is_win) { - if (target_cpu == "x64") { - sources += [ "src/heap/cppgc/asm/x64/push_registers_asm.cc" ] - } else if (target_cpu == "x86") { - sources += [ "src/heap/cppgc/asm/ia32/push_registers_asm.cc" ] - } else if (target_cpu == "arm") { - sources += [ "src/heap/cppgc/asm/arm/push_registers_asm.cc" ] - } else if (target_cpu == "arm64") { - sources += [ "src/heap/cppgc/asm/arm64/push_registers_asm.cc" ] - } else if (target_cpu == "ppc64") { - sources += [ "src/heap/cppgc/asm/ppc/push_registers_asm.cc" ] - } else if (target_cpu == "s390x") { - sources += [ "src/heap/cppgc/asm/s390/push_registers_asm.cc" ] - } else if (target_cpu == "mipsel") { - sources += [ "src/heap/cppgc/asm/mips/push_registers_asm.cc" ] - } else if (target_cpu == "mips64el") { - sources += [ "src/heap/cppgc/asm/mips64/push_registers_asm.cc" ] - } - } else if (is_win) { - if (target_cpu == "x64") { - sources += [ "src/heap/cppgc/asm/x64/push_registers_masm.S" ] - } else if (target_cpu == "x86") { - sources += [ "src/heap/cppgc/asm/ia32/push_registers_masm.S" ] - } else if (target_cpu == "arm64") { - sources += [ "src/heap/cppgc/asm/arm64/push_registers_masm.S" ] - } + if (cppgc_enable_caged_heap) { + sources += [ + "include/cppgc/internal/caged-heap-local-data.h", + "src/heap/cppgc/caged-heap-local-data.cc", + "src/heap/cppgc/caged-heap.cc", + "src/heap/cppgc/caged-heap.h", + ] } configs = [ @@ -4135,7 +4253,10 @@ v8_source_set("cppgc_base") { ":cppgc_base_config", ] - public_deps = [ ":v8_libbase" ] + public_deps = [ + ":v8_cppgc_shared", + ":v8_libbase", + ] } ############################################################################### @@ -4634,6 +4755,23 @@ if (want_v8_shell) { } } +v8_executable("cppgc_for_v8_embedders") { + sources = [ "samples/cppgc/cppgc-for-v8-embedders.cc" ] + + configs = [ + # Note: don't use :internal_config here because this target will get + # the :external_config applied to it by virtue of depending on :cppgc, and + # you can't have both applied to the same target. + ":internal_config_base", + ] + + deps = [ + ":cppgc", + ":v8_libplatform", + "//build/win:default_exe_manifest", + ] +} + template("v8_fuzzer") { name = target_name forward_variables_from(invoker, "*") @@ -4722,8 +4860,10 @@ v8_source_set("regexp_fuzzer") { v8_fuzzer("regexp_fuzzer") { } -v8_source_set("wasm_module_runner") { +v8_source_set("wasm_test_common") { sources = [ + "test/common/wasm/wasm-interpreter.cc", + "test/common/wasm/wasm-interpreter.h", "test/common/wasm/wasm-module-runner.cc", "test/common/wasm/wasm-module-runner.h", ] @@ -4748,7 +4888,7 @@ v8_source_set("wasm_fuzzer") { deps = [ ":fuzzer_support", ":lib_wasm_fuzzer_common", - ":wasm_module_runner", + ":wasm_test_common", ] configs = [ @@ -4766,7 +4906,7 @@ v8_source_set("wasm_async_fuzzer") { deps = [ ":fuzzer_support", ":lib_wasm_fuzzer_common", - ":wasm_module_runner", + ":wasm_test_common", ] configs = [ @@ -4787,7 +4927,7 @@ v8_source_set("wasm_code_fuzzer") { deps = [ ":fuzzer_support", ":lib_wasm_fuzzer_common", - ":wasm_module_runner", + ":wasm_test_common", ] configs = [ @@ -4828,7 +4968,7 @@ v8_source_set("wasm_compile_fuzzer") { deps = [ ":fuzzer_support", ":lib_wasm_fuzzer_common", - ":wasm_module_runner", + ":wasm_test_common", ] configs = [ diff --git a/deps/v8/COMMON_OWNERS b/deps/v8/COMMON_OWNERS index 1319a579173c3c..bfd539fb42076e 100644 --- a/deps/v8/COMMON_OWNERS +++ b/deps/v8/COMMON_OWNERS @@ -9,6 +9,7 @@ clemensb@chromium.org danno@chromium.org delphick@chromium.org dinfuehr@chromium.org +ecmziegler@chromium.org gdeepti@chromium.org gsathya@chromium.org hablich@chromium.org @@ -34,6 +35,7 @@ solanes@chromium.org syg@chromium.org szuend@chromium.org tebbi@chromium.org +thibaudm@chromium.org ulan@chromium.org verwaest@chromium.org victorgomes@chromium.org diff --git a/deps/v8/DEPS b/deps/v8/DEPS index 7b38c3dcd07b17..4c02904d70c117 100644 --- a/deps/v8/DEPS +++ b/deps/v8/DEPS @@ -24,6 +24,8 @@ vars = { 'checkout_instrumented_libraries': False, 'checkout_ittapi': False, + # Fetch clang-tidy into the same bin/ directory as our clang binary. + 'checkout_clang_tidy': False, 'chromium_url': 'https://chromium.googlesource.com', 'android_url': 'https://android.googlesource.com', 'download_gcmole': False, @@ -31,7 +33,7 @@ vars = { 'check_v8_header_includes': False, # GN CIPD package version. - 'gn_version': 'git_revision:5ed3c9cc67b090d5e311e4bd2aba072173e82db9', + 'gn_version': 'git_revision:7d7e8deea36d126397bda2cf924682504271f0e1', # luci-go CIPD package version. 'luci_go': 'git_revision:56ae79476e3caf14da59d75118408aa778637936', @@ -67,20 +69,20 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_tools-lint_version # and whatever else without interference from each other. - 'android_sdk_cmdline-tools_version': 'CR25ixsRhwuRnhdgDpGFyl9S0C_0HO9SUgFrwX46zq8C', + 'android_sdk_cmdline-tools_version': 'uM0XtAW9BHh8phcbhBDA9GfzP3bku2SP7AiMahhimnoC', } deps = { 'v8/build': - Var('chromium_url') + '/chromium/src/build.git' + '@' + '1b904cc30093c25d5fd48389bd58e3f7409bcf80', + Var('chromium_url') + '/chromium/src/build.git' + '@' + '2dc7c7abc04253e340b60fa339151a92519f93d1', 'v8/third_party/depot_tools': - Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '454f4ba4b3a69feb03c73f93d789062033433b4c', + Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '35c62742f96d56afa1bb72c7504cf6591265028d', 'v8/third_party/icu': - Var('chromium_url') + '/chromium/deps/icu.git' + '@' + 'f2223961702f00a8833874b0560d615a2cc42738', + Var('chromium_url') + '/chromium/deps/icu.git' + '@' + '79326efe26e5440f530963704c3c0ff965b3a4ac', 'v8/third_party/instrumented_libraries': Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + 'bb3f1802c237dd19105dd0f7919f99e536a39d10', 'v8/buildtools': - Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '204a35a2a64f7179f8b76d7a0385653690839e21', + Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '1ed99573d57d4b6041261b531cdf876e631cf0bc', 'v8/buildtools/clang_format/script': Var('chromium_url') + '/chromium/llvm-project/cfe/tools/clang-format.git' + '@' + '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'v8/buildtools/linux64': { @@ -120,13 +122,13 @@ deps = { 'condition': 'host_os == "win"', }, 'v8/base/trace_event/common': - Var('chromium_url') + '/chromium/src/base/trace_event/common.git' + '@' + 'dab187b372fc17e51f5b9fad8201813d0aed5129', + Var('chromium_url') + '/chromium/src/base/trace_event/common.git' + '@' + 'ef3586804494b7e402b6c1791d5dccdf2971afff', 'v8/third_party/android_ndk': { 'url': Var('chromium_url') + '/android_ndk.git' + '@' + '27c0a8d090c666a50e40fceb4ee5b40b1a2d3f87', 'condition': 'checkout_android', }, 'v8/third_party/android_platform': { - 'url': Var('chromium_url') + '/chromium/src/third_party/android_platform.git' + '@' + '716366f5685ad8aaf1208c64941e440e8e117441', + 'url': Var('chromium_url') + '/chromium/src/third_party/android_platform.git' + '@' + 'c1f84dcf41795fba13a53c86de608fc0cf6f813e', 'condition': 'checkout_android', }, 'v8/third_party/android_sdk/public': { @@ -168,7 +170,7 @@ deps = { 'dep_type': 'cipd', }, 'v8/third_party/catapult': { - 'url': Var('chromium_url') + '/catapult.git' + '@' + 'e9a8d378c950ee44beec5dd5207e151f48e5b5be', + 'url': Var('chromium_url') + '/catapult.git' + '@' + '95c1f426155576790a73778571c34a0f3cd6d608', 'condition': 'checkout_android', }, 'v8/third_party/colorama/src': { @@ -176,23 +178,23 @@ deps = { 'condition': 'checkout_android', }, 'v8/third_party/fuchsia-sdk': { - 'url': Var('chromium_url') + '/chromium/src/third_party/fuchsia-sdk.git' + '@' + '277fe9120cce5f7a42d43554646fa447f88a1598', + 'url': Var('chromium_url') + '/chromium/src/third_party/fuchsia-sdk.git' + '@' + '8ce22865fbbc501198e0dc9d3ca2eeaa46471d11', 'condition': 'checkout_fuchsia', }, 'v8/third_party/googletest/src': - Var('chromium_url') + '/external/github.com/google/googletest.git' + '@' + 'a09ea700d32bab83325aff9ff34d0582e50e3997', + Var('chromium_url') + '/external/github.com/google/googletest.git' + '@' + '4fe018038f87675c083d0cfb6a6b57c274fb1753', 'v8/third_party/jinja2': Var('chromium_url') + '/chromium/src/third_party/jinja2.git' + '@' + '3f90fa05c85718505e28c9c3426c1ba52843b9b7', 'v8/third_party/markupsafe': Var('chromium_url') + '/chromium/src/third_party/markupsafe.git' + '@' + '8f45f5cfa0009d2a70589bcda0349b8cb2b72783', 'v8/tools/swarming_client': - Var('chromium_url') + '/infra/luci/client-py.git' + '@' + '160b445a44e0daacf6f3f8570ca2707ec451f374', + Var('chromium_url') + '/infra/luci/client-py.git' + '@' + '4c095d04179dc725a300085ae21fe3b79900d072', 'v8/test/benchmarks/data': Var('chromium_url') + '/v8/deps/third_party/benchmarks.git' + '@' + '05d7188267b4560491ff9155c5ee13e207ecd65f', 'v8/test/mozilla/data': Var('chromium_url') + '/v8/deps/third_party/mozilla-tests.git' + '@' + 'f6c578a10ea707b1a8ab0b88943fe5115ce2b9be', 'v8/test/test262/data': - Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + 'd2f7d4285c4a5267f5be37a9c823a397daadad1b', + Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + '8d3dd2d1a0a5b79dc61b72a1817f4c2bd512d156', 'v8/test/test262/harness': Var('chromium_url') + '/external/github.com/test262-utils/test262-harness-py.git' + '@' + '4555345a943d0c99a9461182705543fb171dda4b', 'v8/third_party/qemu-linux-x64': { @@ -219,7 +221,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': '5LzaFiFYMxwWXcgus5JjF74yr90M5oz9IMo29pTdoLgC' + 'version': 'UoYLOT0X6577j70eB9nPqYQs9Z3Nh5lA4I-pRtTchO0C' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -236,7 +238,7 @@ deps = { 'dep_type': 'cipd', }, 'v8/tools/clang': - Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + 'de3e20662b84f0ee361a5ae11c99a9513df7c8e8', + Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + '42b285fe752983290c9c74bafa83b50e3ba09c01', 'v8/tools/luci-go': { 'packages': [ { @@ -270,7 +272,7 @@ deps = { 'v8/third_party/protobuf': Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + 'b68a347f56137b4b1a746e8c7438495a6ac1bd91', 'v8/third_party/zlib': - Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + '90fc47e6eed7bd1a59ad1603761303ef24705593', + Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + '02daed1bb93a34cf89d68913f88708228e12a0ab', 'v8/third_party/jsoncpp/source': Var('chromium_url') + '/external/github.com/open-source-parsers/jsoncpp.git'+ '@' + '645250b6690785be60ab6780ce4b58698d884d11', 'v8/third_party/ittapi': { @@ -485,6 +487,13 @@ hooks = [ 'condition': 'host_os != "aix"', 'action': ['python', 'v8/tools/clang/scripts/update.py'], }, + { + 'name': 'clang_tidy', + 'pattern': '.', + 'condition': 'checkout_clang_tidy', + 'action': ['python', 'v8/tools/clang/scripts/update.py', + '--package=clang-tidy'], + }, { # Update LASTCHANGE. 'name': 'lastchange', diff --git a/deps/v8/base/trace_event/common/trace_event_common.h b/deps/v8/base/trace_event/common/trace_event_common.h index a7bffbdbeb44c7..28b7275345c434 100644 --- a/deps/v8/base/trace_event/common/trace_event_common.h +++ b/deps/v8/base/trace_event/common/trace_event_common.h @@ -837,6 +837,14 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \ + category_group, name, id, \ + TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \ + category_group, name, id, \ + TRACE_EVENT_FLAG_COPY) #define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( \ category_group, name, id, timestamp) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ diff --git a/deps/v8/gni/v8.gni b/deps/v8/gni/v8.gni index 9d286ebbfc0226..db76f3098691d7 100644 --- a/deps/v8/gni/v8.gni +++ b/deps/v8/gni/v8.gni @@ -57,11 +57,14 @@ declare_args() { # Implement tracing using Perfetto (https://perfetto.dev). v8_use_perfetto = false - # Override global symbol level setting for v8 + # Override global symbol level setting for v8. v8_symbol_level = symbol_level # Enable WebAssembly debugging via GDB-remote protocol. v8_enable_wasm_gdb_remote_debugging = false + + # Add fuzzilli fuzzer support. + v8_fuzzilli = false } if (v8_use_external_startup_data == "") { diff --git a/deps/v8/include/OWNERS b/deps/v8/include/OWNERS index 4f90a5c8c70692..9bb043db7c2a3e 100644 --- a/deps/v8/include/OWNERS +++ b/deps/v8/include/OWNERS @@ -1,4 +1,5 @@ adamk@chromium.org +cbruni@chromium.org danno@chromium.org mlippautz@chromium.org ulan@chromium.org @@ -16,4 +17,9 @@ per-file v8-inspector-protocol.h=kozyatinskiy@chromium.org per-file js_protocol.pdl=dgozman@chromium.org per-file js_protocol.pdl=pfeldman@chromium.org +# For branch updates: +per-file v8-version.h=file:../INFRA_OWNERS +per-file v8-version.h=hablich@chromium.org +per-file v8-version.h=vahl@chromium.org + # COMPONENT: Blink>JavaScript>API diff --git a/deps/v8/include/cppgc/allocation.h b/deps/v8/include/cppgc/allocation.h index 49ad49c34d6bc9..ac5062ad01a55e 100644 --- a/deps/v8/include/cppgc/allocation.h +++ b/deps/v8/include/cppgc/allocation.h @@ -11,7 +11,6 @@ #include "cppgc/custom-space.h" #include "cppgc/garbage-collected.h" -#include "cppgc/heap.h" #include "cppgc/internal/api-constants.h" #include "cppgc/internal/gc-info.h" @@ -20,6 +19,15 @@ namespace cppgc { template class MakeGarbageCollectedTraitBase; +namespace internal { +class ObjectAllocator; +} // namespace internal + +/** + * AllocationHandle is used to allocate garbage-collected objects. + */ +class AllocationHandle; + namespace internal { class V8_EXPORT MakeGarbageCollectedTraitInternal { @@ -36,9 +44,10 @@ class V8_EXPORT MakeGarbageCollectedTraitInternal { atomic_mutable_bitfield->store(value, std::memory_order_release); } - static void* Allocate(cppgc::Heap* heap, size_t size, GCInfoIndex index); - static void* Allocate(cppgc::Heap* heapx, size_t size, GCInfoIndex index, - CustomSpaceIndex space_inde); + static void* Allocate(cppgc::AllocationHandle& handle, size_t size, + GCInfoIndex index); + static void* Allocate(cppgc::AllocationHandle& handle, size_t size, + GCInfoIndex index, CustomSpaceIndex space_index); friend class HeapObjectHeader; }; @@ -58,22 +67,22 @@ class MakeGarbageCollectedTraitBase private: template struct SpacePolicy { - static void* Allocate(Heap* heap, size_t size) { + static void* Allocate(AllocationHandle& handle, size_t size) { // Custom space. static_assert(std::is_base_of::value, "Custom space must inherit from CustomSpaceBase."); return internal::MakeGarbageCollectedTraitInternal::Allocate( - heap, size, internal::GCInfoTrait::Index(), + handle, size, internal::GCInfoTrait::Index(), CustomSpace::kSpaceIndex); } }; template struct SpacePolicy { - static void* Allocate(Heap* heap, size_t size) { + static void* Allocate(AllocationHandle& handle, size_t size) { // Default space. return internal::MakeGarbageCollectedTraitInternal::Allocate( - heap, size, internal::GCInfoTrait::Index()); + handle, size, internal::GCInfoTrait::Index()); } }; @@ -81,12 +90,14 @@ class MakeGarbageCollectedTraitBase /** * Allocates memory for an object of type T. * - * \param heap The heap to allocate this object on. + * \param handle AllocationHandle identifying the heap to allocate the object + * on. * \param size The size that should be reserved for the object. * \returns the memory to construct an object of type T on. */ - static void* Allocate(Heap* heap, size_t size) { - return SpacePolicy::Space>::Allocate(heap, size); + static void* Allocate(AllocationHandle& handle, size_t size) { + return SpacePolicy::Space>::Allocate(handle, + size); } /** @@ -115,14 +126,15 @@ template class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase { public: template - static T* Call(Heap* heap, Args&&... args) { + static T* Call(AllocationHandle& handle, Args&&... args) { static_assert(internal::IsGarbageCollectedType::value, "T needs to be a garbage collected object"); static_assert( !internal::IsGarbageCollectedMixinType::value || sizeof(T) <= internal::api_constants::kLargeObjectSizeThreshold, "GarbageCollectedMixin may not be a large object"); - void* memory = MakeGarbageCollectedTraitBase::Allocate(heap, sizeof(T)); + void* memory = + MakeGarbageCollectedTraitBase::Allocate(handle, sizeof(T)); T* object = ::new (memory) T(std::forward(args)...); MakeGarbageCollectedTraitBase::MarkObjectAsFullyConstructed(object); return object; @@ -149,9 +161,9 @@ struct PostConstructionCallbackTrait { * \returns an instance of type T. */ template -T* MakeGarbageCollected(Heap* heap, Args&&... args) { +T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) { T* object = - MakeGarbageCollectedTrait::Call(heap, std::forward(args)...); + MakeGarbageCollectedTrait::Call(handle, std::forward(args)...); PostConstructionCallbackTrait::Call(object); return object; } diff --git a/deps/v8/include/cppgc/garbage-collected.h b/deps/v8/include/cppgc/garbage-collected.h index c263a9fecf0d96..299b861d845d0d 100644 --- a/deps/v8/include/cppgc/garbage-collected.h +++ b/deps/v8/include/cppgc/garbage-collected.h @@ -8,7 +8,6 @@ #include #include "cppgc/internal/api-constants.h" -#include "cppgc/macros.h" #include "cppgc/platform.h" #include "cppgc/trace-trait.h" #include "cppgc/type-traits.h" @@ -161,7 +160,7 @@ class GarbageCollectedMixin : public internal::GarbageCollectedBase { } \ \ private: \ - friend class internal::__thisIsHereToForceASemicolonAfterThisMacro + static_assert(true, "Force semicolon.") /** * Merge two or more Mixins into one. @@ -185,7 +184,7 @@ class GarbageCollectedMixin : public internal::GarbageCollectedBase { } \ \ private: \ - friend class internal::__thisIsHereToForceASemicolonAfterThisMacro + static_assert(true, "Force semicolon.") } // namespace cppgc diff --git a/deps/v8/include/cppgc/heap.h b/deps/v8/include/cppgc/heap.h index 90046c35055e2e..ca0dbeca7ffe01 100644 --- a/deps/v8/include/cppgc/heap.h +++ b/deps/v8/include/cppgc/heap.h @@ -10,9 +10,21 @@ #include "cppgc/common.h" #include "cppgc/custom-space.h" +#include "cppgc/platform.h" #include "v8config.h" // NOLINT(build/include_directory) +/** + * cppgc - A C++ garbage collection library. + */ namespace cppgc { + +class AllocationHandle; + +/** + * Implementation details of cppgc. Those details are considered internal and + * may change at any point in time without notice. Users should never rely on + * the contents of this namespace. + */ namespace internal { class Heap; } // namespace internal @@ -24,7 +36,44 @@ class V8_EXPORT Heap { */ using StackState = EmbedderStackState; + /** + * Specifies whether conservative stack scanning is supported. + */ + enum class StackSupport : uint8_t { + /** + * Conservative stack scan is supported. + */ + kSupportsConservativeStackScan, + /** + * Conservative stack scan is not supported. Embedders may use this option + * when using custom infrastructure that is unsupported by the library. + */ + kNoConservativeStackScan, + }; + + /** + * Constraints for a Heap setup. + */ + struct ResourceConstraints { + /** + * Allows the heap to grow to some initial size in bytes before triggering + * garbage collections. This is useful when it is known that applications + * need a certain minimum heap to run to avoid repeatedly invoking the + * garbage collector when growing the heap. + */ + size_t initial_heap_size_bytes = 0; + }; + + /** + * Options specifying Heap properties (e.g. custom spaces) when initializing a + * heap through Heap::Create(). + */ struct HeapOptions { + /** + * Creates reasonable defaults for instantiating a Heap. + * + * \returns the HeapOptions that can be passed to Heap::Create(). + */ static HeapOptions Default() { return {}; } /** @@ -33,9 +82,34 @@ class V8_EXPORT Heap { * to the index they reside in the vector. */ std::vector> custom_spaces; + + /** + * Specifies whether conserative stack scan is supported. When conservative + * stack scan is not supported, the collector may try to invoke + * garbage collections using non-nestable task, which are guaranteed to have + * no interesting stack, through the provided Platform. If such tasks are + * not supported by the Platform, the embedder must take care of invoking + * the GC through ForceGarbageCollectionSlow(). + */ + StackSupport stack_support = StackSupport::kSupportsConservativeStackScan; + + /** + * Resource constraints specifying various properties that the internal + * GC scheduler follows. + */ + ResourceConstraints resource_constraints; }; - static std::unique_ptr Create(HeapOptions = HeapOptions::Default()); + /** + * Creates a new heap that can be used for object allocation. + * + * \param platform implemented and provided by the embedder. + * \param options HeapOptions specifying various properties for the Heap. + * \returns a new Heap instance. + */ + static std::unique_ptr Create( + std::shared_ptr platform, + HeapOptions options = HeapOptions::Default()); virtual ~Heap() = default; @@ -52,6 +126,8 @@ class V8_EXPORT Heap { const char* source, const char* reason, StackState stack_state = StackState::kMayContainHeapPointers); + AllocationHandle& GetAllocationHandle(); + private: Heap() = default; diff --git a/deps/v8/include/cppgc/internal/accessors.h b/deps/v8/include/cppgc/internal/accessors.h deleted file mode 100644 index ee0a0042fe07b7..00000000000000 --- a/deps/v8/include/cppgc/internal/accessors.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 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 INCLUDE_CPPGC_INTERNAL_ACCESSORS_H_ -#define INCLUDE_CPPGC_INTERNAL_ACCESSORS_H_ - -#include "cppgc/internal/api-constants.h" - -namespace cppgc { - -class Heap; - -namespace internal { - -inline cppgc::Heap* GetHeapFromPayload(const void* payload) { - return *reinterpret_cast( - ((reinterpret_cast(payload) & api_constants::kPageBaseMask) + - api_constants::kGuardPageSize) + - api_constants::kHeapOffset); -} - -} // namespace internal -} // namespace cppgc - -#endif // INCLUDE_CPPGC_INTERNAL_ACCESSORS_H_ diff --git a/deps/v8/include/cppgc/internal/api-constants.h b/deps/v8/include/cppgc/internal/api-constants.h index ef910a48571f46..1303b8b861f648 100644 --- a/deps/v8/include/cppgc/internal/api-constants.h +++ b/deps/v8/include/cppgc/internal/api-constants.h @@ -17,6 +17,11 @@ namespace internal { // Internal constants to avoid exposing internal types on the API surface. namespace api_constants { + +constexpr size_t kKB = 1024; +constexpr size_t kMB = kKB * 1024; +constexpr size_t kGB = kMB * 1024; + // Offset of the uint16_t bitfield from the payload contaning the // in-construction bit. This is subtracted from the payload pointer to get // to the right bitfield. @@ -25,17 +30,15 @@ static constexpr size_t kFullyConstructedBitFieldOffsetFromPayload = // Mask for in-construction bit. static constexpr size_t kFullyConstructedBitMask = size_t{1}; -// Page constants used to align pointers to page begin. static constexpr size_t kPageSize = size_t{1} << 17; -static constexpr size_t kPageAlignment = kPageSize; -static constexpr size_t kPageBaseMask = ~(kPageAlignment - 1); -static constexpr size_t kGuardPageSize = 4096; - -// Offset of the Heap backref. -static constexpr size_t kHeapOffset = 0; static constexpr size_t kLargeObjectSizeThreshold = kPageSize / 2; +#if defined(CPPGC_CAGED_HEAP) +constexpr size_t kCagedHeapReservationSize = static_cast(4) * kGB; +constexpr size_t kCagedHeapReservationAlignment = kCagedHeapReservationSize; +#endif + } // namespace api_constants } // namespace internal diff --git a/deps/v8/include/cppgc/internal/atomic-entry-flag.h b/deps/v8/include/cppgc/internal/atomic-entry-flag.h new file mode 100644 index 00000000000000..5a7d3b8f8ac4c1 --- /dev/null +++ b/deps/v8/include/cppgc/internal/atomic-entry-flag.h @@ -0,0 +1,48 @@ +// Copyright 2020 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 INCLUDE_CPPGC_INTERNAL_ATOMIC_ENTRY_FLAG_H_ +#define INCLUDE_CPPGC_INTERNAL_ATOMIC_ENTRY_FLAG_H_ + +#include + +namespace cppgc { +namespace internal { + +// A flag which provides a fast check whether a scope may be entered on the +// current thread, without needing to access thread-local storage or mutex. Can +// have false positives (i.e., spuriously report that it might be entered), so +// it is expected that this will be used in tandem with a precise check that the +// scope is in fact entered on that thread. +// +// Example: +// g_frobnicating_flag.MightBeEntered() && +// ThreadLocalFrobnicator().IsFrobnicating() +// +// Relaxed atomic operations are sufficient, since: +// - all accesses remain atomic +// - each thread must observe its own operations in order +// - no thread ever exits the flag more times than it enters (if used correctly) +// And so if a thread observes zero, it must be because it has observed an equal +// number of exits as entries. +class AtomicEntryFlag final { + public: + void Enter() { entries_.fetch_add(1, std::memory_order_relaxed); } + void Exit() { entries_.fetch_sub(1, std::memory_order_relaxed); } + + // Returns false only if the current thread is not between a call to Enter + // and a call to Exit. Returns true if this thread or another thread may + // currently be in the scope guarded by this flag. + bool MightBeEntered() const { + return entries_.load(std::memory_order_relaxed) != 0; + } + + private: + std::atomic_int entries_{0}; +}; + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_INTERNAL_ATOMIC_ENTRY_FLAG_H_ diff --git a/deps/v8/include/cppgc/internal/caged-heap-local-data.h b/deps/v8/include/cppgc/internal/caged-heap-local-data.h new file mode 100644 index 00000000000000..8c421477384c2e --- /dev/null +++ b/deps/v8/include/cppgc/internal/caged-heap-local-data.h @@ -0,0 +1,67 @@ +// Copyright 2020 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 INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ +#define INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ + +#include + +#include "cppgc/internal/api-constants.h" +#include "cppgc/internal/logging.h" +#include "cppgc/platform.h" + +namespace cppgc { +namespace internal { + +class HeapBase; + +#if defined(CPPGC_YOUNG_GENERATION) + +// AgeTable contains entries that correspond to 4KB memory regions. Each entry +// can be in one of three states: kOld, kYoung or kUnknown. +class AgeTable final { + static constexpr size_t kGranularityBits = 12; // 4KiB per byte. + + public: + enum class Age : uint8_t { kOld, kYoung, kUnknown }; + + static constexpr size_t kEntrySizeInBytes = 1 << kGranularityBits; + + Age& operator[](uintptr_t offset) { return table_[entry(offset)]; } + Age operator[](uintptr_t offset) const { return table_[entry(offset)]; } + + void Reset(PageAllocator* allocator); + + private: + static constexpr size_t kAgeTableSize = + api_constants::kCagedHeapReservationSize >> kGranularityBits; + + size_t entry(uintptr_t offset) const { + const size_t entry = offset >> kGranularityBits; + CPPGC_DCHECK(table_.size() > entry); + return entry; + } + + std::array table_; +}; + +static_assert(sizeof(AgeTable) == 1 * api_constants::kMB, + "Size of AgeTable is 1MB"); + +#endif // CPPGC_YOUNG_GENERATION + +struct CagedHeapLocalData final { + explicit CagedHeapLocalData(HeapBase* heap_base) : heap_base(heap_base) {} + + bool is_marking_in_progress = false; + HeapBase* heap_base = nullptr; +#if defined(CPPGC_YOUNG_GENERATION) + AgeTable age_table; +#endif +}; + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ diff --git a/deps/v8/include/cppgc/internal/compiler-specific.h b/deps/v8/include/cppgc/internal/compiler-specific.h index e1f5c1d57fb850..c580894b35d0fe 100644 --- a/deps/v8/include/cppgc/internal/compiler-specific.h +++ b/deps/v8/include/cppgc/internal/compiler-specific.h @@ -7,6 +7,12 @@ namespace cppgc { +#if defined(__has_attribute) +#define CPPGC_HAS_ATTRIBUTE(FEATURE) __has_attribute(FEATURE) +#else +#define CPPGC_HAS_ATTRIBUTE(FEATURE) 0 +#endif + #if defined(__has_cpp_attribute) #define CPPGC_HAS_CPP_ATTRIBUTE(FEATURE) __has_cpp_attribute(FEATURE) #else @@ -21,6 +27,12 @@ namespace cppgc { #define CPPGC_NO_UNIQUE_ADDRESS #endif +#if CPPGC_HAS_ATTRIBUTE(unused) // NOLINTNEXTLINE +#define CPPGC_UNUSED __attribute__((unused)) +#else +#define CPPGC_UNUSED +#endif + } // namespace cppgc #endif // INCLUDE_CPPGC_INTERNAL_COMPILER_SPECIFIC_H_ diff --git a/deps/v8/include/cppgc/internal/gc-info.h b/deps/v8/include/cppgc/internal/gc-info.h index 9aac1361c61afd..3d361e6d71adb6 100644 --- a/deps/v8/include/cppgc/internal/gc-info.h +++ b/deps/v8/include/cppgc/internal/gc-info.h @@ -8,6 +8,7 @@ #include #include "cppgc/internal/finalizer-trait.h" +#include "cppgc/trace-trait.h" #include "v8config.h" // NOLINT(build/include_directory) namespace cppgc { @@ -18,7 +19,7 @@ using GCInfoIndex = uint16_t; class V8_EXPORT RegisteredGCInfoIndex final { public: RegisteredGCInfoIndex(FinalizationCallback finalization_callback, - bool has_v_table); + TraceCallback trace_callback, bool has_v_table); GCInfoIndex GetIndex() const { return index_; } private: @@ -32,7 +33,8 @@ struct GCInfoTrait { static GCInfoIndex Index() { static_assert(sizeof(T), "T must be fully defined"); static const RegisteredGCInfoIndex registered_index( - FinalizerTrait::kCallback, std::is_polymorphic::value); + FinalizerTrait::kCallback, TraceTrait::Trace, + std::is_polymorphic::value); return registered_index.GetIndex(); } }; diff --git a/deps/v8/include/cppgc/internal/persistent-node.h b/deps/v8/include/cppgc/internal/persistent-node.h index 11cf69623e8dad..e05efe362131d8 100644 --- a/deps/v8/include/cppgc/internal/persistent-node.h +++ b/deps/v8/include/cppgc/internal/persistent-node.h @@ -56,6 +56,11 @@ class PersistentNode final { bool IsUsed() const { return trace_; } + void* owner() const { + CPPGC_DCHECK(IsUsed()); + return owner_; + } + private: // PersistentNode acts as a designated union: // If trace_ != nullptr, owner_ points to the corresponding Persistent handle. @@ -67,11 +72,13 @@ class PersistentNode final { TraceCallback trace_ = nullptr; }; -class V8_EXPORT PersistentRegion { +class V8_EXPORT PersistentRegion final { using PersistentNodeSlots = std::array; public: PersistentRegion() = default; + // Clears Persistent fields to avoid stale pointers after heap teardown. + ~PersistentRegion(); PersistentRegion(const PersistentRegion&) = delete; PersistentRegion& operator=(const PersistentRegion&) = delete; diff --git a/deps/v8/include/cppgc/internal/pointer-policies.h b/deps/v8/include/cppgc/internal/pointer-policies.h index fe8d94b57a68bb..a6cd4e8586d9cf 100644 --- a/deps/v8/include/cppgc/internal/pointer-policies.h +++ b/deps/v8/include/cppgc/internal/pointer-policies.h @@ -8,6 +8,7 @@ #include #include +#include "cppgc/internal/write-barrier.h" #include "cppgc/source-location.h" #include "v8config.h" // NOLINT(build/include_directory) @@ -26,8 +27,8 @@ struct DijkstraWriteBarrierPolicy { // Since in initializing writes the source object is always white, having no // barrier doesn't break the tri-color invariant. } - static void AssigningBarrier(const void*, const void*) { - // TODO(chromium:1056170): Add actual implementation. + static void AssigningBarrier(const void* slot, const void* value) { + WriteBarrier::MarkingBarrier(slot, value); } }; @@ -116,7 +117,7 @@ class BasicMember; struct SentinelPointer { template operator T*() const { // NOLINT - static constexpr intptr_t kSentinelValue = -1; + static constexpr intptr_t kSentinelValue = 1; return reinterpret_cast(kSentinelValue); } // Hidden friends. diff --git a/deps/v8/include/cppgc/internal/prefinalizer-handler.h b/deps/v8/include/cppgc/internal/prefinalizer-handler.h index 939a9b8ff0a8fd..ea0eca02a0e492 100644 --- a/deps/v8/include/cppgc/internal/prefinalizer-handler.h +++ b/deps/v8/include/cppgc/internal/prefinalizer-handler.h @@ -15,14 +15,13 @@ class V8_EXPORT PreFinalizerRegistrationDispatcher final { public: using PreFinalizerCallback = bool (*)(const LivenessBroker&, void*); struct PreFinalizer { - void* object_; - PreFinalizerCallback callback_; + void* object; + PreFinalizerCallback callback; bool operator==(const PreFinalizer& other); }; - static void RegisterPrefinalizer(cppgc::Heap* heap, - PreFinalizer prefinalzier); + static void RegisterPrefinalizer(PreFinalizer pre_finalizer); }; } // namespace internal diff --git a/deps/v8/include/cppgc/internal/process-heap.h b/deps/v8/include/cppgc/internal/process-heap.h new file mode 100644 index 00000000000000..0f742a50a9cb97 --- /dev/null +++ b/deps/v8/include/cppgc/internal/process-heap.h @@ -0,0 +1,34 @@ +// Copyright 2020 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 INCLUDE_CPPGC_INTERNAL_PROCESS_HEAP_H_ +#define INCLUDE_CPPGC_INTERNAL_PROCESS_HEAP_H_ + +#include "cppgc/internal/atomic-entry-flag.h" +#include "v8config.h" // NOLINT(build/include_directory) + +namespace cppgc { +namespace internal { + +class V8_EXPORT ProcessHeap final { + public: + static void EnterIncrementalOrConcurrentMarking() { + concurrent_marking_flag_.Enter(); + } + static void ExitIncrementalOrConcurrentMarking() { + concurrent_marking_flag_.Exit(); + } + + static bool IsAnyIncrementalOrConcurrentMarking() { + return concurrent_marking_flag_.MightBeEntered(); + } + + private: + static AtomicEntryFlag concurrent_marking_flag_; +}; + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_INTERNAL_PROCESS_HEAP_H_ diff --git a/deps/v8/include/cppgc/internal/write-barrier.h b/deps/v8/include/cppgc/internal/write-barrier.h new file mode 100644 index 00000000000000..5bf550b02610dd --- /dev/null +++ b/deps/v8/include/cppgc/internal/write-barrier.h @@ -0,0 +1,78 @@ +// Copyright 2020 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 INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_ +#define INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_ + +#include "cppgc/internal/api-constants.h" +#include "cppgc/internal/process-heap.h" +#include "v8config.h" // NOLINT(build/include_directory) + +#if defined(CPPGC_CAGED_HEAP) +#include "cppgc/internal/caged-heap-local-data.h" +#endif + +namespace cppgc { +namespace internal { + +class V8_EXPORT WriteBarrier final { + public: + static V8_INLINE void MarkingBarrier(const void* slot, const void* value) { +#if defined(CPPGC_CAGED_HEAP) + const uintptr_t start = + reinterpret_cast(value) & + ~(api_constants::kCagedHeapReservationAlignment - 1); + const uintptr_t slot_offset = reinterpret_cast(slot) - start; + if (slot_offset > api_constants::kCagedHeapReservationSize) { + // Check if slot is on stack or value is sentinel or nullptr. This relies + // on the fact that kSentinelPointer is encoded as 0x1. + return; + } + + CagedHeapLocalData* local_data = + reinterpret_cast(start); + if (V8_UNLIKELY(local_data->is_marking_in_progress)) { + MarkingBarrierSlow(value); + return; + } +#if defined(CPPGC_YOUNG_GENERATION) + GenerationalBarrier(local_data, slot, slot_offset, + reinterpret_cast(value) - start); +#endif +#else + if (V8_LIKELY(!ProcessHeap::IsAnyIncrementalOrConcurrentMarking())) return; + + MarkingBarrierSlowWithSentinelCheck(value); +#endif // CPPGC_CAGED_HEAP + } + + private: + WriteBarrier() = delete; + + static void MarkingBarrierSlow(const void* value); + static void MarkingBarrierSlowWithSentinelCheck(const void* value); + +#if defined(CPPGC_YOUNG_GENERATION) + static V8_INLINE void GenerationalBarrier(CagedHeapLocalData* local_data, + const void* slot, + uintptr_t slot_offset, + uintptr_t value_offset) { + const AgeTable& age_table = local_data->age_table; + + // Bail out if the slot is in young generation. + if (V8_LIKELY(age_table[slot_offset] == AgeTable::Age::kYoung)) return; + + GenerationalBarrierSlow(local_data, age_table, slot, value_offset); + } + + static void GenerationalBarrierSlow(CagedHeapLocalData* local_data, + const AgeTable& ageTable, + const void* slot, uintptr_t value_offset); +#endif +}; + +} // namespace internal +} // namespace cppgc + +#endif // INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_ diff --git a/deps/v8/include/cppgc/liveness-broker.h b/deps/v8/include/cppgc/liveness-broker.h index 69dbc11f1f4a95..883be46240ff86 100644 --- a/deps/v8/include/cppgc/liveness-broker.h +++ b/deps/v8/include/cppgc/liveness-broker.h @@ -16,6 +16,30 @@ namespace internal { class LivenessBrokerFactory; } // namespace internal +/** + * The broker is passed to weak callbacks to allow (temporarily) querying + * the liveness state of an object. References to non-live objects must be + * cleared when IsHeapObjectAlive() returns false. + * + * \code + * class GCedWithCustomWeakCallback final + * : public GarbageCollected { + * public: + * UntracedMember bar; + * + * void CustomWeakCallbackMethod(const LivenessBroker& broker) { + * if (!broker.IsHeapObjectAlive(bar)) + * bar = nullptr; + * } + * + * void Trace(cppgc::Visitor* visitor) const { + * visitor->RegisterWeakCallbackMethod< + * GCedWithCustomWeakCallback, + * &GCedWithCustomWeakCallback::CustomWeakCallbackMethod>(this); + * } + * }; + * \endcode + */ class V8_EXPORT LivenessBroker final { public: template @@ -25,12 +49,6 @@ class V8_EXPORT LivenessBroker final { TraceTrait::GetTraceDescriptor(object).base_object_payload); } - template - bool IsHeapObjectAlive(const WeakMember& weak_member) const { - return (weak_member != kSentinelPointer) && - IsHeapObjectAlive(weak_member.Get()); - } - template bool IsHeapObjectAlive(const UntracedMember& untraced_member) const { return (untraced_member != kSentinelPointer) && diff --git a/deps/v8/include/cppgc/macros.h b/deps/v8/include/cppgc/macros.h index 7c7a10e433a894..c0b1814e294cfa 100644 --- a/deps/v8/include/cppgc/macros.h +++ b/deps/v8/include/cppgc/macros.h @@ -5,21 +5,19 @@ #ifndef INCLUDE_CPPGC_MACROS_H_ #define INCLUDE_CPPGC_MACROS_H_ -namespace cppgc { +#include "cppgc/internal/compiler-specific.h" -namespace internal { -class __thisIsHereToForceASemicolonAfterThisMacro {}; -} // namespace internal +namespace cppgc { // Use if the object is only stack allocated. -#define CPPGC_STACK_ALLOCATED() \ - public: \ - using IsStackAllocatedTypeMarker = int; \ - \ - private: \ - void* operator new(size_t) = delete; \ - void* operator new(size_t, void*) = delete; \ - friend class internal::__thisIsHereToForceASemicolonAfterThisMacro +#define CPPGC_STACK_ALLOCATED() \ + public: \ + using IsStackAllocatedTypeMarker CPPGC_UNUSED = int; \ + \ + private: \ + void* operator new(size_t) = delete; \ + void* operator new(size_t, void*) = delete; \ + static_assert(true, "Force semicolon.") } // namespace cppgc diff --git a/deps/v8/include/cppgc/member.h b/deps/v8/include/cppgc/member.h index a183edb96fd030..22c1adc0af7c3c 100644 --- a/deps/v8/include/cppgc/member.h +++ b/deps/v8/include/cppgc/member.h @@ -19,19 +19,43 @@ class Visitor; namespace internal { +class MemberBase { + protected: + MemberBase() = default; + explicit MemberBase(void* value) : raw_(value) {} + + void* const* GetRawSlot() const { return &raw_; } + void* GetRaw() const { return raw_; } + void SetRaw(void* value) { raw_ = value; } + + void* GetRawAtomic() const { + return reinterpret_cast*>(&raw_)->load( + std::memory_order_relaxed); + } + void SetRawAtomic(void* value) { + reinterpret_cast*>(&raw_)->store( + value, std::memory_order_relaxed); + } + + void ClearFromGC() const { raw_ = nullptr; } + + private: + mutable void* raw_ = nullptr; +}; + // The basic class from which all Member classes are 'generated'. template -class BasicMember : private CheckingPolicy { +class BasicMember final : private MemberBase, private CheckingPolicy { public: using PointeeType = T; constexpr BasicMember() = default; constexpr BasicMember(std::nullptr_t) {} // NOLINT - BasicMember(SentinelPointer s) : raw_(s) {} // NOLINT - BasicMember(T* raw) : raw_(raw) { // NOLINT + BasicMember(SentinelPointer s) : MemberBase(s) {} // NOLINT + BasicMember(T* raw) : MemberBase(raw) { // NOLINT InitializingWriteBarrier(); - this->CheckPointer(raw_); + this->CheckPointer(Get()); } BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT BasicMember(const BasicMember& other) : BasicMember(other.Get()) {} @@ -106,9 +130,12 @@ class BasicMember : private CheckingPolicy { T* operator->() const { return Get(); } T& operator*() const { return *Get(); } - T* Get() const { + // CFI cast exemption to allow passing SentinelPointer through T* and support + // heterogeneous assignments between different Member and Persistent handles + // based on their actual types. + V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const { // Executed by the mutator, hence non atomic load. - return raw_; + return static_cast(MemberBase::GetRaw()); } void Clear() { SetRawAtomic(nullptr); } @@ -120,25 +147,18 @@ class BasicMember : private CheckingPolicy { } private: - void SetRawAtomic(T* raw) { - reinterpret_cast*>(&raw_)->store(raw, - std::memory_order_relaxed); - } T* GetRawAtomic() const { - return reinterpret_cast*>(&raw_)->load( - std::memory_order_relaxed); + return static_cast(MemberBase::GetRawAtomic()); } void InitializingWriteBarrier() const { - WriteBarrierPolicy::InitializingBarrier( - reinterpret_cast(&raw_), static_cast(raw_)); + WriteBarrierPolicy::InitializingBarrier(GetRawSlot(), GetRaw()); } void AssigningWriteBarrier() const { - WriteBarrierPolicy::AssigningBarrier(reinterpret_cast(&raw_), - static_cast(raw_)); + WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), GetRaw()); } - T* raw_ = nullptr; + void ClearFromGC() const { MemberBase::ClearFromGC(); } friend class cppgc::Visitor; }; diff --git a/deps/v8/include/cppgc/persistent.h b/deps/v8/include/cppgc/persistent.h index fc6b0b9d92efa1..c2d8a7a5a642c6 100644 --- a/deps/v8/include/cppgc/persistent.h +++ b/deps/v8/include/cppgc/persistent.h @@ -15,14 +15,43 @@ #include "v8config.h" // NOLINT(build/include_directory) namespace cppgc { + +class Visitor; + namespace internal { +class PersistentBase { + protected: + PersistentBase() = default; + explicit PersistentBase(void* raw) : raw_(raw) {} + + void* GetValue() const { return raw_; } + void SetValue(void* value) { raw_ = value; } + + PersistentNode* GetNode() const { return node_; } + void SetNode(PersistentNode* node) { node_ = node; } + + // Performs a shallow clear which assumes that internal persistent nodes are + // destroyed elsewhere. + void ClearFromGC() const { + raw_ = nullptr; + node_ = nullptr; + } + + private: + mutable void* raw_ = nullptr; + mutable PersistentNode* node_ = nullptr; + + friend class PersistentRegion; +}; + // The basic class from which all Persistent classes are generated. template -class BasicPersistent : public LocationPolicy, - private WeaknessPolicy, - private CheckingPolicy { +class BasicPersistent final : public PersistentBase, + public LocationPolicy, + private WeaknessPolicy, + private CheckingPolicy { public: using typename WeaknessPolicy::IsStrongPersistent; using PointeeType = T; @@ -38,15 +67,15 @@ class BasicPersistent : public LocationPolicy, BasicPersistent( // NOLINT SentinelPointer s, const SourceLocation& loc = SourceLocation::Current()) - : LocationPolicy(loc), raw_(s) {} + : PersistentBase(s), LocationPolicy(loc) {} - // Raw value contstructors. + // Raw value constructors. BasicPersistent(T* raw, // NOLINT const SourceLocation& loc = SourceLocation::Current()) - : LocationPolicy(loc), raw_(raw) { + : PersistentBase(raw), LocationPolicy(loc) { if (!IsValid()) return; - node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode( - this, &BasicPersistent::Trace); + SetNode(WeaknessPolicy::GetPersistentRegion(GetValue()) + .AllocateNode(this, &BasicPersistent::Trace)); this->CheckPointer(Get()); } @@ -74,13 +103,11 @@ class BasicPersistent : public LocationPolicy, BasicPersistent( BasicPersistent&& other, const SourceLocation& loc = SourceLocation::Current()) noexcept - : LocationPolicy(std::move(other)), - raw_(std::move(other.raw_)), - node_(std::move(other.node_)) { + : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) { if (!IsValid()) return; - node_->UpdateOwner(this); - other.raw_ = nullptr; - other.node_ = nullptr; + GetNode()->UpdateOwner(this); + other.SetValue(nullptr); + other.SetNode(nullptr); this->CheckPointer(Get()); } @@ -114,13 +141,12 @@ class BasicPersistent : public LocationPolicy, BasicPersistent& operator=(BasicPersistent&& other) { if (this == &other) return *this; Clear(); + PersistentBase::operator=(std::move(other)); LocationPolicy::operator=(std::move(other)); - raw_ = std::move(other.raw_); - node_ = std::move(other.node_); if (!IsValid()) return *this; - node_->UpdateOwner(this); - other.raw_ = nullptr; - other.node_ = nullptr; + GetNode()->UpdateOwner(this); + other.SetValue(nullptr); + other.SetNode(nullptr); this->CheckPointer(Get()); return *this; } @@ -156,7 +182,12 @@ class BasicPersistent : public LocationPolicy, T* operator->() const { return Get(); } T& operator*() const { return *Get(); } - T* Get() const { return raw_; } + // CFI cast exemption to allow passing SentinelPointer through T* and support + // heterogeneous assignments between different Member and Persistent handles + // based on their actual types. + V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const { + return static_cast(GetValue()); + } void Clear() { Assign(nullptr); } @@ -176,29 +207,35 @@ class BasicPersistent : public LocationPolicy, // Ideally, handling kSentinelPointer would be done by the embedder. On the // other hand, having Persistent aware of it is beneficial since no node // gets wasted. - return raw_ != nullptr && raw_ != kSentinelPointer; + return GetValue() != nullptr && GetValue() != kSentinelPointer; } void Assign(T* ptr) { if (IsValid()) { if (ptr && ptr != kSentinelPointer) { // Simply assign the pointer reusing the existing node. - raw_ = ptr; + SetValue(ptr); this->CheckPointer(ptr); return; } - WeaknessPolicy::GetPersistentRegion(raw_).FreeNode(node_); - node_ = nullptr; + WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode()); + SetNode(nullptr); } - raw_ = ptr; + SetValue(ptr); if (!IsValid()) return; - node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode( - this, &BasicPersistent::Trace); + SetNode(WeaknessPolicy::GetPersistentRegion(GetValue()) + .AllocateNode(this, &BasicPersistent::Trace)); this->CheckPointer(Get()); } - T* raw_ = nullptr; - PersistentNode* node_ = nullptr; + void ClearFromGC() const { + if (IsValid()) { + WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode()); + PersistentBase::ClearFromGC(); + } + } + + friend class cppgc::Visitor; }; template GetForegroundTaskRunner() { + return nullptr; + } + + /** + * Posts |job_task| to run in parallel. Returns a JobHandle associated with + * the Job, which can be joined or canceled. + * This avoids degenerate cases: + * - Calling CallOnWorkerThread() for each work item, causing significant + * overhead. + * - Fixed number of CallOnWorkerThread() calls that split the work and might + * run for a long time. This is problematic when many components post + * "num cores" tasks and all expect to use all the cores. In these cases, + * the scheduler lacks context to be fair to multiple same-priority requests + * and/or ability to request lower priority work to yield when high priority + * work comes in. + * A canonical implementation of |job_task| looks like: + * class MyJobTask : public JobTask { + * public: + * MyJobTask(...) : worker_queue_(...) {} + * // JobTask: + * void Run(JobDelegate* delegate) override { + * while (!delegate->ShouldYield()) { + * // Smallest unit of work. + * auto work_item = worker_queue_.TakeWorkItem(); // Thread safe. + * if (!work_item) return; + * ProcessWork(work_item); + * } + * } + * + * size_t GetMaxConcurrency() const override { + * return worker_queue_.GetSize(); // Thread safe. + * } + * }; + * auto handle = PostJob(TaskPriority::kUserVisible, + * std::make_unique(...)); + * handle->Join(); + * + * PostJob() and methods of the returned JobHandle/JobDelegate, must never be + * called while holding a lock that could be acquired by JobTask::Run or + * JobTask::GetMaxConcurrency -- that could result in a deadlock. This is + * because [1] JobTask::GetMaxConcurrency may be invoked while holding + * internal lock (A), hence JobTask::GetMaxConcurrency can only use a lock (B) + * if that lock is *never* held while calling back into JobHandle from any + * thread (A=>B/B=>A deadlock) and [2] JobTask::Run or + * JobTask::GetMaxConcurrency may be invoked synchronously from JobHandle + * (B=>JobHandle::foo=>B deadlock). + * + * A sufficient PostJob() implementation that uses the default Job provided in + * libplatform looks like: + * std::unique_ptr PostJob( + * TaskPriority priority, std::unique_ptr job_task) override { + * return std::make_unique( + * std::make_shared( + * this, std::move(job_task), kNumThreads)); + * } + */ + virtual std::unique_ptr PostJob( + TaskPriority priority, std::unique_ptr job_task) { + return nullptr; + } +}; + +/** + * Process-global initialization of the garbage collector. Must be called before + * creating a Heap. + */ +V8_EXPORT void InitializeProcess(PageAllocator*); + +/** + * Must be called after destroying the last used heap. + */ +V8_EXPORT void ShutdownProcess(); namespace internal { diff --git a/deps/v8/include/cppgc/prefinalizer.h b/deps/v8/include/cppgc/prefinalizer.h index 2f6d68a1dac808..75764d02cde076 100644 --- a/deps/v8/include/cppgc/prefinalizer.h +++ b/deps/v8/include/cppgc/prefinalizer.h @@ -5,11 +5,9 @@ #ifndef INCLUDE_CPPGC_PREFINALIZER_H_ #define INCLUDE_CPPGC_PREFINALIZER_H_ -#include "cppgc/internal/accessors.h" #include "cppgc/internal/compiler-specific.h" #include "cppgc/internal/prefinalizer-handler.h" #include "cppgc/liveness-broker.h" -#include "cppgc/macros.h" namespace cppgc { @@ -23,7 +21,7 @@ class PrefinalizerRegistration final { "USING_PRE_FINALIZER(T) must be defined."); cppgc::internal::PreFinalizerRegistrationDispatcher::RegisterPrefinalizer( - internal::GetHeapFromPayload(self), {self, T::InvokePreFinalizer}); + {self, T::InvokePreFinalizer}); } void* operator new(size_t, void* location) = delete; @@ -47,7 +45,7 @@ class PrefinalizerRegistration final { private: \ CPPGC_NO_UNIQUE_ADDRESS internal::PrefinalizerRegistration \ prefinalizer_dummy_{this}; \ - friend class internal::__thisIsHereToForceASemicolonAfterThisMacro + static_assert(true, "Force semicolon.") } // namespace cppgc diff --git a/deps/v8/include/cppgc/source-location.h b/deps/v8/include/cppgc/source-location.h index 8cc52d6a539c2f..139c9d86c08140 100644 --- a/deps/v8/include/cppgc/source-location.h +++ b/deps/v8/include/cppgc/source-location.h @@ -23,10 +23,16 @@ namespace cppgc { -// Encapsulates source location information. Mimics C++20's -// std::source_location. +/** + * Encapsulates source location information. Mimics C++20's + * std::source_location. + */ class V8_EXPORT SourceLocation final { public: + /** + * Construct source location information corresponding to the location of the + * call site. + */ #if CPPGC_SUPPORTS_SOURCE_LOCATION static constexpr SourceLocation Current( const char* function = __builtin_FUNCTION(), @@ -37,12 +43,38 @@ class V8_EXPORT SourceLocation final { static constexpr SourceLocation Current() { return SourceLocation(); } #endif // CPPGC_SUPPORTS_SOURCE_LOCATION + /** + * Constructs unspecified source location information. + */ constexpr SourceLocation() = default; + /** + * Returns the name of the function associated with the position represented + * by this object, if any. + * + * \returns the function name as cstring. + */ constexpr const char* Function() const { return function_; } + + /** + * Returns the name of the current source file represented by this object. + * + * \returns the file name as cstring. + */ constexpr const char* FileName() const { return file_; } + + /** + * Returns the line number represented by this object. + * + * \returns the line number. + */ constexpr size_t Line() const { return line_; } + /** + * Returns a human-readable string representing this object. + * + * \returns a human-readable string representing source location information. + */ std::string ToString() const; private: diff --git a/deps/v8/include/cppgc/trace-trait.h b/deps/v8/include/cppgc/trace-trait.h index e246bc53b7d9aa..59e0b14c4517a9 100644 --- a/deps/v8/include/cppgc/trace-trait.h +++ b/deps/v8/include/cppgc/trace-trait.h @@ -14,6 +14,8 @@ class Visitor; namespace internal { +// Implementation of the default TraceTrait handling GarbageCollected and +// GarbageCollectedMixin. template ::type>> @@ -21,25 +23,57 @@ struct TraceTraitImpl; } // namespace internal -using TraceCallback = void (*)(Visitor*, const void*); - -// TraceDescriptor is used to describe how to trace an object. +/** + * Callback for invoking tracing on a given object. + * + * \param visitor The visitor to dispatch to. + * \param object The object to invoke tracing on. + */ +using TraceCallback = void (*)(Visitor* visitor, const void* object); + +/** + * Describes how to trace an object, i.e., how to visit all Oilpan-relevant + * fields of an object. + */ struct TraceDescriptor { - // The adjusted base pointer of the object that should be traced. + /** + * Adjusted base pointer, i.e., the pointer to the class inheriting directly + * from GarbageCollected, of the object that is being traced. + */ const void* base_object_payload; - // A callback for tracing the object. + /** + * Callback for tracing the object. + */ TraceCallback callback; }; +/** + * Trait specifying how the garbage collector processes an object of type T. + * + * Advanced users may override handling by creating a specialization for their + * type. + */ template struct TraceTrait { static_assert(internal::IsTraceableV, "T must have a Trace() method"); + /** + * Accessor for retrieving a TraceDescriptor to process an object of type T. + * + * \param self The object to be processed. + * \returns a TraceDescriptor to process the object. + */ static TraceDescriptor GetTraceDescriptor(const void* self) { return internal::TraceTraitImpl::GetTraceDescriptor( static_cast(self)); } + /** + * Function invoking the tracing for an object of type T. + * + * \param visitor The visitor to dispatch to. + * \param self The object to invoke tracing on. + */ static void Trace(Visitor* visitor, const void* self) { static_cast(self)->Trace(visitor); } diff --git a/deps/v8/include/cppgc/visitor.h b/deps/v8/include/cppgc/visitor.h index a73a4abb2bdb7c..b70fde537bd28f 100644 --- a/deps/v8/include/cppgc/visitor.h +++ b/deps/v8/include/cppgc/visitor.h @@ -14,7 +14,11 @@ #include "cppgc/trace-trait.h" namespace cppgc { + namespace internal { +template +class BasicPersistent; class VisitorBase; } // namespace internal @@ -22,10 +26,28 @@ using WeakCallback = void (*)(const LivenessBroker&, const void*); /** * Visitor passed to trace methods. All managed pointers must have called the - * visitor's trace method on them. + * Visitor's trace method on them. + * + * \code + * class Foo final : public GarbageCollected { + * public: + * void Trace(Visitor* visitor) const { + * visitor->Trace(foo_); + * visitor->Trace(weak_foo_); + * } + * private: + * Member foo_; + * WeakMember weak_foo_; + * }; + * \endcode */ class Visitor { public: + /** + * Trace method for Member. + * + * \param member Member reference retaining an object. + */ template void Trace(const Member& member) { const T* value = member.GetRawAtomic(); @@ -33,11 +55,16 @@ class Visitor { Trace(value); } + /** + * Trace method for WeakMember. + * + * \param weak_member WeakMember reference weakly retaining an object. + */ template void Trace(const WeakMember& weak_member) { - static_assert(sizeof(T), "T must be fully defined"); + static_assert(sizeof(T), "Pointee type must be fully defined."); static_assert(internal::IsGarbageCollectedType::value, - "T must be GarabgeCollected or GarbageCollectedMixin type"); + "T must be GarbageCollected or GarbageCollectedMixin type"); const T* value = weak_member.GetRawAtomic(); @@ -52,41 +79,42 @@ class Visitor { &HandleWeak>, &weak_member); } - template * = nullptr> - void TraceRoot(const Persistent& p, const SourceLocation& loc) { - using PointeeType = typename Persistent::PointeeType; - static_assert(sizeof(PointeeType), - "Persistent's pointee type must be fully defined"); - static_assert(internal::IsGarbageCollectedType::value, - "Persisent's pointee type must be GarabgeCollected or " - "GarbageCollectedMixin"); - if (!p.Get()) { - return; - } - VisitRoot(p.Get(), TraceTrait::GetTraceDescriptor(p.Get())); - } - - template < - typename WeakPersistent, - std::enable_if_t* = nullptr> - void TraceRoot(const WeakPersistent& p, const SourceLocation& loc) { - using PointeeType = typename WeakPersistent::PointeeType; - static_assert(sizeof(PointeeType), - "Persistent's pointee type must be fully defined"); - static_assert(internal::IsGarbageCollectedType::value, - "Persisent's pointee type must be GarabgeCollected or " - "GarbageCollectedMixin"); - VisitWeakRoot(p.Get(), TraceTrait::GetTraceDescriptor(p.Get()), - &HandleWeak, &p); + /** + * Trace method for inlined objects that are not allocated themselves but + * otherwise follow managed heap layout and have a Trace() method. + * + * \param object reference of the inlined object. + */ + template + void Trace(const T& object) { +#if V8_ENABLE_CHECKS + // This object is embedded in potentially multiple nested objects. The + // outermost object must not be in construction as such objects are (a) not + // processed immediately, and (b) only processed conservatively if not + // otherwise possible. + CheckObjectNotInConstruction(&object); +#endif // V8_ENABLE_CHECKS + TraceTrait::Trace(this, &object); } + /** + * Registers a weak callback method on the object of type T. See + * LivenessBroker for an usage example. + * + * \param object of type T specifying a weak callback method. + */ template - void RegisterWeakCallbackMethod(const T* obj) { - RegisterWeakCallback(&WeakCallbackMethodDelegate, obj); + void RegisterWeakCallbackMethod(const T* object) { + RegisterWeakCallback(&WeakCallbackMethodDelegate, object); } - virtual void RegisterWeakCallback(WeakCallback, const void*) {} + /** + * Registers a weak callback that is invoked during garbage collection. + * + * \param callback to be invoked. + * \param data custom data that is passed to the callback. + */ + virtual void RegisterWeakCallback(WeakCallback callback, const void* data) {} protected: virtual void Visit(const void* self, TraceDescriptor) {} @@ -108,29 +136,64 @@ class Visitor { template static void HandleWeak(const LivenessBroker& info, const void* object) { const PointerType* weak = static_cast(object); + // Sentinel values are preserved for weak pointers. + if (*weak == kSentinelPointer) return; const auto* raw = weak->Get(); - if (raw && !info.IsHeapObjectAlive(raw)) { - // Object is passed down through the marker as const. Alternatives are - // - non-const Trace method; - // - mutable pointer in MemberBase; - const_cast(weak)->Clear(); + if (!info.IsHeapObjectAlive(raw)) { + weak->ClearFromGC(); } } Visitor() = default; + template * = nullptr> + void TraceRoot(const Persistent& p, const SourceLocation& loc) { + using PointeeType = typename Persistent::PointeeType; + static_assert(sizeof(PointeeType), + "Persistent's pointee type must be fully defined"); + static_assert(internal::IsGarbageCollectedType::value, + "Persistent's pointee type must be GarbageCollected or " + "GarbageCollectedMixin"); + if (!p.Get()) { + return; + } + VisitRoot(p.Get(), TraceTrait::GetTraceDescriptor(p.Get())); + } + + template < + typename WeakPersistent, + std::enable_if_t* = nullptr> + void TraceRoot(const WeakPersistent& p, const SourceLocation& loc) { + using PointeeType = typename WeakPersistent::PointeeType; + static_assert(sizeof(PointeeType), + "Persistent's pointee type must be fully defined"); + static_assert(internal::IsGarbageCollectedType::value, + "Persistent's pointee type must be GarbageCollected or " + "GarbageCollectedMixin"); + VisitWeakRoot(p.Get(), TraceTrait::GetTraceDescriptor(p.Get()), + &HandleWeak, &p); + } + template void Trace(const T* t) { - static_assert(sizeof(T), "T must be fully defined"); + static_assert(sizeof(T), "Pointee type must be fully defined."); static_assert(internal::IsGarbageCollectedType::value, - "T must be GarabgeCollected or GarbageCollectedMixin type"); + "T must be GarbageCollected or GarbageCollectedMixin type"); if (!t) { return; } Visit(t, TraceTrait::GetTraceDescriptor(t)); } +#if V8_ENABLE_CHECKS + V8_EXPORT void CheckObjectNotInConstruction(const void* address); +#endif // V8_ENABLE_CHECKS + friend class internal::VisitorBase; + template + friend class internal::BasicPersistent; }; } // namespace cppgc diff --git a/deps/v8/include/js_protocol.pdl b/deps/v8/include/js_protocol.pdl index 706c37f958e4a0..aaeb22518daf2d 100644 --- a/deps/v8/include/js_protocol.pdl +++ b/deps/v8/include/js_protocol.pdl @@ -1009,7 +1009,7 @@ domain Runtime f32 f64 v128 - anyref + externref # Object class (constructor) name. Specified for `object` type values only. optional string className # Remote object value in case of primitive values or JSON values (if it was requested). @@ -1370,6 +1370,11 @@ domain Runtime # Note that `let` variables can only be re-declared if they originate from # `replMode` themselves. experimental optional boolean replMode + # The Content Security Policy (CSP) for the target might block 'unsafe-eval' + # which includes eval(), Function(), setTimeout() and setInterval() + # when called with non-callable arguments. This flag bypasses CSP for this + # evaluation and allows unsafe-eval. Defaults to true. + experimental optional boolean allowUnsafeEvalBlockedByCSP returns # Evaluation result. RemoteObject result diff --git a/deps/v8/include/libplatform/libplatform.h b/deps/v8/include/libplatform/libplatform.h index c7ea4c2bd38575..9d0849f01f292b 100644 --- a/deps/v8/include/libplatform/libplatform.h +++ b/deps/v8/include/libplatform/libplatform.h @@ -43,6 +43,16 @@ V8_PLATFORM_EXPORT std::unique_ptr NewDefaultPlatform( InProcessStackDumping::kDisabled, std::unique_ptr tracing_controller = {}); +/** + * Returns a new instance of the default v8::JobHandle implementation. + * + * The job will be executed by spawning up to |num_worker_threads| many worker + * threads on the provided |platform| with the given |priority|. + */ +V8_PLATFORM_EXPORT std::unique_ptr NewDefaultJobHandle( + v8::Platform* platform, v8::TaskPriority priority, + std::unique_ptr job_task, size_t num_worker_threads); + /** * Pumps the message loop for the given isolate. * diff --git a/deps/v8/include/v8-fast-api-calls.h b/deps/v8/include/v8-fast-api-calls.h index f74406493bcf2a..fb3e9bddb4145c 100644 --- a/deps/v8/include/v8-fast-api-calls.h +++ b/deps/v8/include/v8-fast-api-calls.h @@ -120,8 +120,7 @@ * v8::ObjectTemplate::New(isolate); * object_template->SetInternalFieldCount( * kV8EmbedderWrapperObjectIndex + 1); - * object_template->Set( - v8::String::NewFromUtf8Literal(isolate, "method"), method_template); + * object_template->Set(isolate, "method", method_template); * * // Instantiate the wrapper JS object. * v8::Local object = @@ -379,6 +378,11 @@ class V8_EXPORT CFunction { return ArgUnwrap::Make(func); } + template + static CFunction Make(F* func, const CFunctionInfo* type_info) { + return CFunction(reinterpret_cast(func), type_info); + } + private: const void* address_; const CFunctionInfo* type_info_; diff --git a/deps/v8/include/v8-platform.h b/deps/v8/include/v8-platform.h index 7cfd18b5708d57..03be1c8cdd64dd 100644 --- a/deps/v8/include/v8-platform.h +++ b/deps/v8/include/v8-platform.h @@ -80,6 +80,14 @@ class TaskRunner { * implementation takes ownership of |task|. The |task| cannot be nested * within other task executions. * + * Tasks which shouldn't be interleaved with JS execution must be posted with + * |PostNonNestableTask| or |PostNonNestableDelayedTask|. This is because the + * embedder may process tasks in a callback which is called during JS + * execution. + * + * In particular, tasks which execute JS must be non-nestable, since JS + * execution is not allowed to nest. + * * Requires that |TaskRunner::NonNestableTasksEnabled()| is true. */ virtual void PostNonNestableTask(std::unique_ptr task) {} @@ -98,6 +106,14 @@ class TaskRunner { * implementation takes ownership of |task|. The |task| cannot be nested * within other task executions. * + * Tasks which shouldn't be interleaved with JS execution must be posted with + * |PostNonNestableTask| or |PostNonNestableDelayedTask|. This is because the + * embedder may process tasks in a callback which is called during JS + * execution. + * + * In particular, tasks which execute JS must be non-nestable, since JS + * execution is not allowed to nest. + * * Requires that |TaskRunner::NonNestableDelayedTasksEnabled()| is true. */ virtual void PostNonNestableDelayedTask(std::unique_ptr task, @@ -519,9 +535,8 @@ class Platform { * libplatform looks like: * std::unique_ptr PostJob( * TaskPriority priority, std::unique_ptr job_task) override { - * return std::make_unique( - * std::make_shared( - * this, std::move(job_task), kNumThreads)); + * return v8::platform::NewDefaultJobHandle( + * this, priority, std::move(job_task), NumberOfWorkerThreads()); * } */ virtual std::unique_ptr PostJob( diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index cee7990e4bc193..50c35d185c2ce6 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -9,9 +9,9 @@ // NOTE these macros are used by some of the tool scripts and the build // system so their names cannot be changed without changing the scripts. #define V8_MAJOR_VERSION 8 -#define V8_MINOR_VERSION 4 -#define V8_BUILD_NUMBER 371 -#define V8_PATCH_LEVEL 19 +#define V8_MINOR_VERSION 5 +#define V8_BUILD_NUMBER 210 +#define V8_PATCH_LEVEL 20 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 43420e60d90a15..897fa870d475f3 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -1545,6 +1545,23 @@ class V8_EXPORT Module : public Data { */ Local GetUnboundModuleScript(); + /** + * Returns the underlying script's id. + * + * The module must be a SourceTextModule and must not have a kErrored status. + */ + int ScriptId(); + + /** + * Returns whether the module is a SourceTextModule. + */ + bool IsSourceTextModule() const; + + /** + * Returns whether the module is a SyntheticModule. + */ + bool IsSyntheticModule() const; + /* * Callback defined in the embedder. This is responsible for setting * the module's exported values with calls to SetSyntheticModuleExport(). @@ -3618,11 +3635,11 @@ enum PropertyFilter { /** * Options for marking whether callbacks may trigger JS-observable side effects. - * Side-effect-free callbacks are whitelisted during debug evaluation with + * Side-effect-free callbacks are allowlisted during debug evaluation with * throwOnSideEffect. It applies when calling a Function, FunctionTemplate, * or an Accessor callback. For Interceptors, please see * PropertyHandlerFlags's kHasNoSideEffect. - * Callbacks that only cause side effects to the receiver are whitelisted if + * Callbacks that only cause side effects to the receiver are allowlisted if * invoked on receiver objects that are created within the same debug-evaluate * call, as these objects are temporary and the side effect does not escape. */ @@ -5350,9 +5367,10 @@ class V8_EXPORT TypedArray : public ArrayBufferView { /* * The largest typed array size that can be constructed using New. */ - static constexpr size_t kMaxLength = internal::kApiSystemPointerSize == 4 - ? internal::kSmiMaxValue - : 0xFFFFFFFF; + static constexpr size_t kMaxLength = + internal::kApiSystemPointerSize == 4 + ? internal::kSmiMaxValue + : static_cast(uint64_t{1} << 32); /** * Number of elements in this typed array @@ -8309,7 +8327,7 @@ class V8_EXPORT Isolate { /** * This scope allows terminations inside direct V8 API calls and forbid them - * inside any recursice API calls without explicit SafeForTerminationScope. + * inside any recursive API calls without explicit SafeForTerminationScope. */ class V8_EXPORT SafeForTerminationScope { public: @@ -8448,6 +8466,9 @@ class V8_EXPORT Isolate { kInvalidatedTypedArraySpeciesLookupChainProtector = 105, kWasmSimdOpcodes = 106, kVarRedeclaredCatchBinding = 107, + kWasmRefTypes = 108, + kWasmBulkMemory = 109, + kWasmMultiValue = 110, // If you add new values here, you'll also need to update Chromium's: // web_feature.mojom, use_counter_callback.cc, and enums.xml. V8 changes to @@ -8544,7 +8565,7 @@ class V8_EXPORT Isolate { HostImportModuleDynamicallyCallback callback); /** - * This specifies the callback called by the upcoming importa.meta + * This specifies the callback called by the upcoming import.meta * language feature to retrieve host-defined meta data for a module. */ void SetHostInitializeImportMetaObjectCallback( @@ -9500,12 +9521,16 @@ class V8_EXPORT StartupData { * Only valid for StartupData returned by SnapshotCreator::CreateBlob(). */ bool CanBeRehashed() const; + /** + * Allows embedders to verify whether the data is valid for the current + * V8 instance. + */ + bool IsValid() const; const char* data; int raw_size; }; - /** * EntropySource is used as a callback function when v8 needs a source * of entropy. @@ -10805,8 +10830,15 @@ V8_INLINE void PersistentBase::SetWeak( P* parameter, typename WeakCallbackInfo

::Callback callback, WeakCallbackType type) { typedef typename WeakCallbackInfo::Callback Callback; +#if (__GNUC__ >= 8) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif V8::MakeWeak(reinterpret_cast(this->val_), parameter, reinterpret_cast(callback), type); +#if (__GNUC__ >= 8) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif } template diff --git a/deps/v8/include/v8config.h b/deps/v8/include/v8config.h index 9825232d6a10ac..bbd1d6ce978e6c 100644 --- a/deps/v8/include/v8config.h +++ b/deps/v8/include/v8config.h @@ -433,6 +433,16 @@ #define V8_WARN_UNUSED_RESULT /* NOT SUPPORTED */ #endif +// Helper macro to define no_sanitize attributes only with clang. +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(no_sanitize) +#define V8_CLANG_NO_SANITIZE(what) __attribute__((no_sanitize(what))) +#endif +#endif +#if !defined(V8_CLANG_NO_SANITIZE) +#define V8_CLANG_NO_SANITIZE(what) +#endif + #if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED) #error Inconsistent build configuration: To build the V8 shared library \ set BUILDING_V8_SHARED, to include its headers for linking against the \ diff --git a/deps/v8/infra/mb/mb_config.pyl b/deps/v8/infra/mb/mb_config.pyl index d4abcf89eb15e9..c7c251a9e67e52 100644 --- a/deps/v8/infra/mb/mb_config.pyl +++ b/deps/v8/infra/mb/mb_config.pyl @@ -211,13 +211,12 @@ 'v8_linux_dbg_ng': 'debug_x86_trybot', 'v8_linux_noi18n_compile_dbg': 'debug_x86_no_i18n', 'v8_linux_noi18n_rel_ng': 'release_x86_no_i18n_trybot', - 'v8_linux_gc_stress_dbg': 'debug_x86_trybot', + 'v8_linux_gc_stress_dbg_ng': 'debug_x86_trybot', 'v8_linux_gcc_compile_rel': 'release_x86_gcc_minimal_symbols', - 'v8_linux_gcc_rel': 'release_x86_gcc_minimal_symbols', + 'v8_linux_gcc_rel_ng': 'release_x86_gcc_minimal_symbols', 'v8_linux_shared_compile_rel': 'release_x86_shared_verify_heap', 'v8_linux64_arm64_pointer_compression_rel_ng': 'release_simulate_arm64_pointer_compression', - 'v8_linux64_compile_rel_xg': 'release_x64_test_features_trybot', 'v8_linux64_dbg_ng': 'debug_x64_trybot', 'v8_linux64_gc_stress_custom_snapshot_dbg_ng': 'debug_x64_trybot_custom', 'v8_linux64_gcc_compile_dbg': 'debug_x64_gcc', @@ -231,39 +230,37 @@ 'v8_linux64_verify_csa_rel_ng': 'release_x64_verify_csa', 'v8_linux64_asan_rel_ng': 'release_x64_asan_minimal_symbols', 'v8_linux64_cfi_rel_ng': 'release_x64_cfi', - 'v8_linux64_msan_rel': 'release_simulate_arm64_msan_minimal_symbols', - 'v8_linux64_sanitizer_coverage_rel': - 'release_x64_asan_minimal_symbols_coverage', - 'v8_linux64_tsan_rel': 'release_x64_tsan_minimal_symbols', + 'v8_linux64_msan_rel_ng': 'release_simulate_arm64_msan_minimal_symbols', + 'v8_linux64_tsan_rel_ng': 'release_x64_tsan_minimal_symbols', 'v8_linux64_tsan_isolates_rel_ng': 'release_x64_tsan_minimal_symbols', 'v8_linux64_ubsan_rel_ng': 'release_x64_ubsan_minimal_symbols', 'v8_odroid_arm_rel_ng': 'release_arm', 'v8_linux_torque_compare': 'torque_compare', # TODO(machenbach): Remove after switching to x64 on infra side. - 'v8_win_dbg': 'debug_x86_trybot', + 'v8_win_dbg_ng': 'debug_x86_trybot', 'v8_win_compile_dbg': 'debug_x86_trybot', 'v8_win_rel_ng': 'release_x86_trybot', 'v8_win64_asan_rel_ng': 'release_x64_asan_no_lsan', 'v8_win64_msvc_compile_rel': 'release_x64_msvc', - 'v8_win64_dbg': 'debug_x64_minimal_symbols', + 'v8_win64_dbg_ng': 'debug_x64_minimal_symbols', 'v8_win64_msvc_rel_ng': 'release_x64_msvc', 'v8_win64_rel_ng': 'release_x64_trybot', - 'v8_mac64_gc_stress_dbg': 'debug_x64_trybot', + 'v8_mac64_gc_stress_dbg_ng': 'debug_x64_trybot', 'v8_mac64_rel_ng': 'release_x64_trybot', 'v8_mac64_dbg': 'debug_x64', 'v8_mac64_dbg_ng': 'debug_x64', 'v8_mac64_compile_full_dbg_ng': 'full_debug_x64', - 'v8_mac64_asan_rel': 'release_x64_asan_no_lsan', + 'v8_mac64_asan_rel_ng': 'release_x64_asan_no_lsan', 'v8_linux_arm_rel_ng': 'release_simulate_arm_trybot', 'v8_linux_arm_lite_rel_ng': 'release_simulate_arm_lite_trybot', - 'v8_linux_arm_dbg': 'debug_simulate_arm', + 'v8_linux_arm_dbg_ng': 'debug_simulate_arm', 'v8_linux_arm_armv8a_rel': 'release_simulate_arm_trybot', 'v8_linux_arm_armv8a_dbg': 'debug_simulate_arm', 'v8_linux_arm64_rel_ng': 'release_simulate_arm64_trybot', 'v8_linux_arm64_cfi_rel_ng' : 'release_simulate_arm64_cfi', - 'v8_linux_arm64_dbg': 'debug_simulate_arm64', - 'v8_linux_arm64_gc_stress_dbg': 'debug_simulate_arm64', + 'v8_linux_arm64_dbg_ng': 'debug_simulate_arm64', + 'v8_linux_arm64_gc_stress_dbg_ng': 'debug_simulate_arm64', 'v8_linux_mipsel_compile_rel': 'release_simulate_mipsel', 'v8_linux_mips64el_compile_rel': 'release_simulate_mips64el', }, @@ -431,8 +428,6 @@ 'release_bot', 'x64', 'asan', 'lsan'], 'release_x64_asan_minimal_symbols': [ 'release_bot', 'x64', 'asan', 'lsan', 'minimal_symbols'], - 'release_x64_asan_minimal_symbols_coverage': [ - 'release_bot', 'x64', 'asan', 'bb', 'coverage', 'lsan', 'minimal_symbols'], 'release_x64_asan_no_lsan': [ 'release_bot', 'x64', 'asan'], 'release_x64_asan_no_lsan_verify_heap': [ @@ -593,10 +588,6 @@ 'gn_args': 'is_asan=true', }, - 'bb': { - 'gn_args': 'sanitizer_coverage_flags="bb,trace-pc-guard"', - }, - 'cfi': { 'mixins': ['v8_enable_test_features'], 'gn_args': ('is_cfi=true use_cfi_cast=true use_cfi_icall=true ' diff --git a/deps/v8/infra/testing/builders.pyl b/deps/v8/infra/testing/builders.pyl index 72f739487ccec3..773ef614c9197c 100644 --- a/deps/v8/infra/testing/builders.pyl +++ b/deps/v8/infra/testing/builders.pyl @@ -83,7 +83,7 @@ {'name': 'v8testing', 'variant': 'extra', 'shards': 2}, ], }, - 'v8_linux_gc_stress_dbg': { + 'v8_linux_gc_stress_dbg_ng_triggered': { 'swarming_dimensions' : { 'os': 'Ubuntu-16.04', }, @@ -92,7 +92,7 @@ {'name': 'd8testing', 'test_args': ['--gc-stress'], 'shards': 5}, ], }, - 'v8_linux_gcc_rel': { + 'v8_linux_gcc_rel_ng_triggered': { 'swarming_dimensions' : { 'os': 'Ubuntu-16.04', }, @@ -214,7 +214,7 @@ }, ############################################################################## # Linux32 with arm simulators - 'v8_linux_arm_dbg': { + 'v8_linux_arm_dbg_ng_triggered': { 'swarming_dimensions' : { 'os': 'Ubuntu-16.04', }, @@ -321,7 +321,7 @@ {'name': 'mjsunit', 'variant': 'stress_snapshot'}, ], }, - 'v8_linux64_msan_rel': { + 'v8_linux64_msan_rel_ng_triggered': { 'swarming_dimensions' : { 'os': 'Ubuntu-16.04', }, @@ -391,27 +391,7 @@ {'name': 'v8testing', 'variant': 'stress_instruction_scheduling'}, ], }, - # TODO(machenbach): Experimental builder with incomplete configs. Should be - # similar to v8_linux64_rel_ng_triggered after testing. - 'v8_linux64_rel_xg': { - 'swarming_dimensions' : { - 'cpu': 'x86-64-avx2', - 'os': 'Ubuntu-16.04', - }, - 'tests': [ - {'name': 'v8initializers'}, - {'name': 'v8testing', 'shards': 2}, - ], - }, - 'v8_linux64_sanitizer_coverage_rel': { - 'swarming_dimensions' : { - 'os': 'Ubuntu-16.04', - }, - 'tests': [ - {'name': 'v8testing', 'shards': 3}, - ], - }, - 'v8_linux64_tsan_rel': { + 'v8_linux64_tsan_rel_ng_triggered': { 'swarming_dimensions' : { 'os': 'Ubuntu-16.04', }, @@ -450,7 +430,7 @@ }, ############################################################################## # Linux64 with arm64 simulators - 'v8_linux_arm64_dbg': { + 'v8_linux_arm64_dbg_ng_triggered': { 'swarming_dimensions' : { 'os': 'Ubuntu-16.04', }, @@ -463,7 +443,7 @@ {'name': 'v8testing', 'variant': 'trusted', 'shards': 5}, ], }, - 'v8_linux_arm64_gc_stress_dbg': { + 'v8_linux_arm64_gc_stress_dbg_ng_triggered': { 'swarming_dimensions' : { 'os': 'Ubuntu-16.04', }, @@ -521,7 +501,7 @@ }, ############################################################################## # Win32 - 'v8_win_dbg': { + 'v8_win_dbg_ng_triggered': { 'swarming_dimensions' : { 'cpu': 'x86-64', 'os': 'Windows-7-SP1', @@ -552,7 +532,7 @@ {'name': 'v8testing', 'shards': 5}, ], }, - 'v8_win64_dbg': { + 'v8_win64_dbg_ng_triggered': { 'swarming_dimensions' : { 'cpu': 'x86-64', 'os': 'Windows-10-15063', @@ -589,7 +569,7 @@ }, ############################################################################## # Mac64 - 'v8_mac64_asan_rel': { + 'v8_mac64_asan_rel_ng_triggered': { 'swarming_dimensions' : { 'cpu': 'x86-64', 'os': 'Mac-10.13', @@ -610,7 +590,7 @@ {'name': 'v8testing', 'variant': 'extra', 'shards': 2}, ], }, - 'v8_mac64_gc_stress_dbg': { + 'v8_mac64_gc_stress_dbg_ng_triggered': { 'swarming_dimensions' : { 'cpu': 'x86-64', 'os': 'Mac-10.13', diff --git a/deps/v8/samples/cppgc/cppgc-for-v8-embedders.cc b/deps/v8/samples/cppgc/cppgc-for-v8-embedders.cc new file mode 100644 index 00000000000000..8aaa9cd39ce654 --- /dev/null +++ b/deps/v8/samples/cppgc/cppgc-for-v8-embedders.cc @@ -0,0 +1,106 @@ +// Copyright 2020 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/** + * This sample program shows how to set up a stand-alone cppgc heap as an + * embedder of V8. Most importantly, this example shows how to reuse V8's + * platform for cppgc. + */ + +/** + * Platform used by cppgc. Can just redirect to v8::Platform for most calls. + * Exception: GetForegroundTaskRunner(), see below. + * + * This example uses V8's default platform implementation to drive the cppgc + * platform. + */ +class Platform final : public cppgc::Platform { + public: + Platform() : v8_platform_(v8::platform::NewDefaultPlatform()) {} + + cppgc::PageAllocator* GetPageAllocator() final { + return v8_platform_->GetPageAllocator(); + } + + double MonotonicallyIncreasingTime() final { + return v8_platform_->MonotonicallyIncreasingTime(); + } + + std::shared_ptr GetForegroundTaskRunner() final { + // V8's default platform creates a new task runner when passed the + // v8::Isolate pointer the first time. For non-default platforms this will + // require getting the appropriate task runner. + return v8_platform_->GetForegroundTaskRunner(nullptr); + } + + std::unique_ptr PostJob( + cppgc::TaskPriority priority, + std::unique_ptr job_task) final { + return v8_platform_->PostJob(priority, std::move(job_task)); + } + + private: + std::unique_ptr v8_platform_; +}; + +/** + * Simple string rope to illustrate allocation and garbage collection below. The + * rope keeps the next parts alive via regular managed reference. + */ +class Rope final : public cppgc::GarbageCollected { + public: + explicit Rope(std::string part, Rope* next = nullptr) + : part_(part), next_(next) {} + + void Trace(cppgc::Visitor* visitor) const { visitor->Trace(next_); } + + private: + std::string part_; + cppgc::Member next_; + + friend std::ostream& operator<<(std::ostream& os, const Rope& rope); +}; + +std::ostream& operator<<(std::ostream& os, const Rope& rope) { + os << rope.part_; + if (rope.next_) { + os << *rope.next_; + } + return os; +} + +int main(int argc, char* argv[]) { + // Create a platform that is used by cppgc::Heap for execution and backend + // allocation. + auto cppgc_platform = std::make_shared(); + // Initialize the process. This must happen before any cppgc::Heap::Create() + // calls. + cppgc::InitializeProcess(cppgc_platform->GetPageAllocator()); + // Create a managed heap. + std::unique_ptr heap = cppgc::Heap::Create(cppgc_platform); + // Allocate a string rope on the managed heap. + auto* greeting = cppgc::MakeGarbageCollected( + heap->GetAllocationHandle(), "Hello ", + cppgc::MakeGarbageCollected(heap->GetAllocationHandle(), "World!")); + // Manually trigger garbage collection. The object greeting is held alive + // through conservative stack scanning. + heap->ForceGarbageCollectionSlow("V8 embedders example", "Testing"); + std::cout << *greeting << std::endl; + // Gracefully shutdown the process. + cppgc::ShutdownProcess(); + return 0; +} diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc index aed050ceccd283..70450296c76389 100644 --- a/deps/v8/samples/shell.cc +++ b/deps/v8/samples/shell.cc @@ -108,21 +108,15 @@ v8::Local CreateShellContext(v8::Isolate* isolate) { // Create a template for the global object. v8::Local global = v8::ObjectTemplate::New(isolate); // Bind the global 'print' function to the C++ Print callback. - global->Set(v8::String::NewFromUtf8Literal(isolate, "print"), - v8::FunctionTemplate::New(isolate, Print)); + global->Set(isolate, "print", v8::FunctionTemplate::New(isolate, Print)); // Bind the global 'read' function to the C++ Read callback. - global->Set(v8::String::NewFromUtf8Literal(isolate, "read"), - v8::FunctionTemplate::New(isolate, Read)); + global->Set(isolate, "read", v8::FunctionTemplate::New(isolate, Read)); // Bind the global 'load' function to the C++ Load callback. - global->Set(v8::String::NewFromUtf8Literal(isolate, "load"), - v8::FunctionTemplate::New(isolate, Load)); + global->Set(isolate, "load", v8::FunctionTemplate::New(isolate, Load)); // Bind the 'quit' function - global->Set(v8::String::NewFromUtf8Literal(isolate, "quit"), - v8::FunctionTemplate::New(isolate, Quit)); + global->Set(isolate, "quit", v8::FunctionTemplate::New(isolate, Quit)); // Bind the 'version' function - global->Set(v8::String::NewFromUtf8Literal(isolate, "version"), - v8::FunctionTemplate::New(isolate, Version)); - + global->Set(isolate, "version", v8::FunctionTemplate::New(isolate, Version)); return v8::Context::New(isolate, NULL, global); } diff --git a/deps/v8/src/api/api-natives.cc b/deps/v8/src/api/api-natives.cc index 410c37ce98d754..e21dbd0eeedbb3 100644 --- a/deps/v8/src/api/api-natives.cc +++ b/deps/v8/src/api/api-natives.cc @@ -371,7 +371,7 @@ MaybeHandle InstantiateObject(Isolate* isolate, Handle new_target, bool is_prototype) { Handle constructor; - int serial_number = Smi::ToInt(info->serial_number()); + int serial_number = info->serial_number(); if (!new_target.is_null()) { if (IsSimpleInstantiation(isolate, *info, *new_target)) { constructor = Handle::cast(new_target); @@ -462,7 +462,7 @@ MaybeHandle GetInstancePrototype(Isolate* isolate, MaybeHandle InstantiateFunction( Isolate* isolate, Handle native_context, Handle data, MaybeHandle maybe_name) { - int serial_number = Smi::ToInt(data->serial_number()); + int serial_number = data->serial_number(); if (serial_number) { Handle result; if (ProbeInstantiationsCache(isolate, native_context, serial_number, diff --git a/deps/v8/src/api/api.cc b/deps/v8/src/api/api.cc index 0097683120a566..eb0a6aaa74ca4e 100644 --- a/deps/v8/src/api/api.cc +++ b/deps/v8/src/api/api.cc @@ -11,11 +11,10 @@ #include // For move #include -#include "src/api/api-inl.h" - #include "include/v8-fast-api-calls.h" #include "include/v8-profiler.h" #include "include/v8-util.h" +#include "src/api/api-inl.h" #include "src/api/api-natives.h" #include "src/base/functional.h" #include "src/base/logging.h" @@ -58,6 +57,7 @@ #include "src/json/json-parser.h" #include "src/json/json-stringifier.h" #include "src/logging/counters.h" +#include "src/logging/tracing-flags.h" #include "src/numbers/conversions-inl.h" #include "src/objects/api-callbacks.h" #include "src/objects/contexts.h" @@ -107,6 +107,7 @@ #include "src/utils/detachable-vector.h" #include "src/utils/version.h" #include "src/wasm/streaming-decoder.h" +#include "src/wasm/value-type.h" #include "src/wasm/wasm-engine.h" #include "src/wasm/wasm-objects-inl.h" #include "src/wasm/wasm-result.h" @@ -503,7 +504,11 @@ void Utils::ReportOOMFailure(i::Isolate* isolate, const char* location, if (fatal_callback == nullptr) { base::OS::PrintError("\n#\n# Fatal %s OOM in %s\n#\n\n", is_heap_oom ? "javascript" : "process", location); +#ifdef V8_FUZZILLI + exit(0); +#else base::OS::Abort(); +#endif // V8_FUZZILLI } else { fatal_callback(location, is_heap_oom @@ -823,6 +828,8 @@ bool StartupData::CanBeRehashed() const { return i::Snapshot::ExtractRehashability(this); } +bool StartupData::IsValid() const { return i::Snapshot::VersionIsValid(this); } + void V8::SetDcheckErrorHandler(DcheckErrorCallback that) { v8::base::SetDcheckFunction(that); } @@ -1274,7 +1281,7 @@ void Context::SetAlignedPointerInEmbedderData(int index, void* value) { static void InitializeTemplate(i::Handle that, int type) { that->set_number_of_properties(0); - that->set_tag(i::Smi::FromInt(type)); + that->set_tag(type); } void Template::Set(v8::Local name, v8::Local value, @@ -1286,7 +1293,7 @@ void Template::Set(v8::Local name, v8::Local value, auto value_obj = Utils::OpenHandle(*value); CHECK(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo()); if (value_obj->IsObjectTemplateInfo()) { - templ->set_serial_number(i::Smi::zero()); + templ->set_serial_number(0); if (templ->IsFunctionTemplateInfo()) { i::Handle::cast(templ)->set_do_not_cache(true); } @@ -1336,7 +1343,7 @@ Local FunctionTemplate::PrototypeTemplate() { auto self = Utils::OpenHandle(this); i::Isolate* i_isolate = self->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); - i::Handle result(self->GetPrototypeTemplate(), i_isolate); + i::Handle result(self->GetPrototypeTemplate(), i_isolate); if (result->IsUndefined(i_isolate)) { // Do not cache prototype objects. result = Utils::OpenHandle( @@ -1351,7 +1358,8 @@ void FunctionTemplate::SetPrototypeProviderTemplate( auto self = Utils::OpenHandle(this); i::Isolate* i_isolate = self->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); - i::Handle result = Utils::OpenHandle(*prototype_provider); + i::Handle result = + Utils::OpenHandle(*prototype_provider); CHECK(self->GetPrototypeTemplate().IsUndefined(i_isolate)); CHECK(self->GetParentTemplate().IsUndefined(i_isolate)); i::FunctionTemplateInfo::SetPrototypeProviderTemplate(i_isolate, self, @@ -1394,7 +1402,7 @@ static Local FunctionTemplateNew( if (!do_not_cache) { next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); } - obj->set_serial_number(i::Smi::FromInt(next_serial_number)); + obj->set_serial_number(next_serial_number); } if (callback != nullptr) { Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type, @@ -1605,15 +1613,19 @@ static Local ObjectTemplateNew( i::OBJECT_TEMPLATE_INFO_TYPE, i::AllocationType::kOld); i::Handle obj = i::Handle::cast(struct_obj); - InitializeTemplate(obj, Consts::OBJECT_TEMPLATE); - int next_serial_number = 0; - if (!do_not_cache) { - next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); + { + // Disallow GC until all fields of obj have acceptable types. + i::DisallowHeapAllocation no_gc; + InitializeTemplate(obj, Consts::OBJECT_TEMPLATE); + int next_serial_number = 0; + if (!do_not_cache) { + next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); + } + obj->set_serial_number(next_serial_number); + obj->set_data(0); } - obj->set_serial_number(i::Smi::FromInt(next_serial_number)); if (!constructor.IsEmpty()) obj->set_constructor(*Utils::OpenHandle(*constructor)); - obj->set_data(i::Smi::zero()); return Utils::ToLocal(obj); } @@ -2234,6 +2246,28 @@ Local Module::GetUnboundModuleScript() { self->GetIsolate())); } +int Module::ScriptId() { + i::Handle self = Utils::OpenHandle(this); + Utils::ApiCheck(self->IsSourceTextModule(), "v8::Module::ScriptId", + "v8::Module::ScriptId must be used on an SourceTextModule"); + + // The SharedFunctionInfo is not available for errored modules. + Utils::ApiCheck(GetStatus() != kErrored, "v8::Module::ScriptId", + "v8::Module::ScriptId must not be used on an errored module"); + i::Handle sfi( + i::Handle::cast(self)->GetSharedFunctionInfo(), + self->GetIsolate()); + return ToApiHandle(sfi)->GetId(); +} + +bool Module::IsSourceTextModule() const { + return Utils::OpenHandle(this)->IsSourceTextModule(); +} + +bool Module::IsSyntheticModule() const { + return Utils::OpenHandle(this)->IsSyntheticModule(); +} + int Module::GetIdentityHash() const { return Utils::OpenHandle(this)->hash(); } Maybe Module::InstantiateModule(Local context, @@ -5804,9 +5838,9 @@ static i::Handle CreateEnvironment( v8::Local proxy_template; i::Handle proxy_constructor; i::Handle global_constructor; - i::Handle named_interceptor( + i::Handle named_interceptor( isolate->factory()->undefined_value()); - i::Handle indexed_interceptor( + i::Handle indexed_interceptor( isolate->factory()->undefined_value()); if (!maybe_global_template.IsEmpty()) { @@ -8417,8 +8451,7 @@ void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) { i::ReadOnlySpace* ro_space = heap->read_only_space(); heap_statistics->total_heap_size_ += ro_space->CommittedMemory(); heap_statistics->total_physical_size_ += ro_space->CommittedPhysicalMemory(); - heap_statistics->total_available_size_ += ro_space->Available(); - heap_statistics->used_heap_size_ += ro_space->SizeOfObjects(); + heap_statistics->used_heap_size_ += ro_space->Size(); #endif // V8_SHARED_RO_HEAP heap_statistics->total_heap_size_executable_ = @@ -8452,18 +8485,26 @@ bool Isolate::GetHeapSpaceStatistics(HeapSpaceStatistics* space_statistics, i::Isolate* isolate = reinterpret_cast(this); i::Heap* heap = isolate->heap(); - i::Space* space = heap->space(static_cast(index)); i::AllocationSpace allocation_space = static_cast(index); - space_statistics->space_name_ = i::Heap::GetSpaceName(allocation_space); - - if (allocation_space == i::RO_SPACE && V8_SHARED_RO_HEAP_BOOL) { - // RO_SPACE memory is accounted for elsewhere when ReadOnlyHeap is shared. - space_statistics->space_size_ = 0; - space_statistics->space_used_size_ = 0; - space_statistics->space_available_size_ = 0; - space_statistics->physical_space_size_ = 0; + space_statistics->space_name_ = i::BaseSpace::GetSpaceName(allocation_space); + + if (allocation_space == i::RO_SPACE) { + if (V8_SHARED_RO_HEAP_BOOL) { + // RO_SPACE memory is accounted for elsewhere when ReadOnlyHeap is shared. + space_statistics->space_size_ = 0; + space_statistics->space_used_size_ = 0; + space_statistics->space_available_size_ = 0; + space_statistics->physical_space_size_ = 0; + } else { + i::ReadOnlySpace* space = heap->read_only_space(); + space_statistics->space_size_ = space->CommittedMemory(); + space_statistics->space_used_size_ = space->Size(); + space_statistics->space_available_size_ = 0; + space_statistics->physical_space_size_ = space->CommittedPhysicalMemory(); + } } else { + i::Space* space = heap->space(static_cast(index)); space_statistics->space_size_ = space->CommittedMemory(); space_statistics->space_used_size_ = space->SizeOfObjects(); space_statistics->space_available_size_ = space->Available(); @@ -10307,9 +10348,11 @@ int debug::WasmValue::value_type() { v8::Local debug::WasmValue::bytes() { i::Handle obj = Utils::OpenHandle(this); - // Should only be called on i32, i64, f32, f64, s128. - DCHECK_GE(1, obj->value_type()); - DCHECK_LE(5, obj->value_type()); + DCHECK(i::wasm::ValueType::Kind::kI32 == obj->value_type() || + i::wasm::ValueType::Kind::kI64 == obj->value_type() || + i::wasm::ValueType::Kind::kF32 == obj->value_type() || + i::wasm::ValueType::Kind::kF64 == obj->value_type() || + i::wasm::ValueType::Kind::kS128 == obj->value_type()); i::Isolate* isolate = obj->GetIsolate(); i::Handle bytes_or_ref(obj->bytes_or_ref(), isolate); @@ -10331,8 +10374,7 @@ v8::Local debug::WasmValue::bytes() { v8::Local debug::WasmValue::ref() { i::Handle obj = Utils::OpenHandle(this); - // Should only be called on anyref. - DCHECK_EQ(6, obj->value_type()); + DCHECK_EQ(i::wasm::kHeapExtern, obj->value_type()); i::Isolate* isolate = obj->GetIsolate(); i::Handle bytes_or_ref(obj->bytes_or_ref(), isolate); diff --git a/deps/v8/src/asmjs/asm-scanner.cc b/deps/v8/src/asmjs/asm-scanner.cc index 73140867084c7a..3ac9ef2d6fe9a0 100644 --- a/deps/v8/src/asmjs/asm-scanner.cc +++ b/deps/v8/src/asmjs/asm-scanner.cc @@ -99,7 +99,7 @@ void AsmJsScanner::Next() { preceded_by_newline_ = true; break; - case kEndOfInput: + case kEndOfInputU: token_ = kEndOfInput; return; @@ -354,7 +354,7 @@ bool AsmJsScanner::ConsumeCComment() { if (ch == '\n') { preceded_by_newline_ = true; } - if (ch == kEndOfInput) { + if (ch == kEndOfInputU) { return false; } } @@ -367,7 +367,7 @@ void AsmJsScanner::ConsumeCPPComment() { preceded_by_newline_ = true; return; } - if (ch == kEndOfInput) { + if (ch == kEndOfInputU) { return; } } @@ -377,7 +377,7 @@ void AsmJsScanner::ConsumeString(uc32 quote) { // Only string allowed is 'use asm' / "use asm". const char* expected = "use asm"; for (; *expected != '\0'; ++expected) { - if (stream_->Advance() != *expected) { + if (stream_->Advance() != static_cast(*expected)) { token_ = kParseError; return; } diff --git a/deps/v8/src/asmjs/asm-scanner.h b/deps/v8/src/asmjs/asm-scanner.h index 076a7607e38624..9e7250ff2cd72f 100644 --- a/deps/v8/src/asmjs/asm-scanner.h +++ b/deps/v8/src/asmjs/asm-scanner.h @@ -135,6 +135,8 @@ class V8_EXPORT_PRIVATE AsmJsScanner { }; // clang-format on + static constexpr uc32 kEndOfInputU = static_cast(kEndOfInput); + private: Utf16CharacterStream* stream_; token_t token_; diff --git a/deps/v8/src/ast/ast.cc b/deps/v8/src/ast/ast.cc index 651508b677f05d..8cd1140154ae92 100644 --- a/deps/v8/src/ast/ast.cc +++ b/deps/v8/src/ast/ast.cc @@ -927,6 +927,7 @@ Call::CallType Call::GetCallType() const { } if (property != nullptr) { if (property->IsPrivateReference()) { + if (is_optional_chain) return PRIVATE_OPTIONAL_CHAIN_CALL; return PRIVATE_CALL; } bool is_super = property->IsSuperAccess(); diff --git a/deps/v8/src/ast/ast.h b/deps/v8/src/ast/ast.h index 6fcf30499a5f0d..dab3981c63856e 100644 --- a/deps/v8/src/ast/ast.h +++ b/deps/v8/src/ast/ast.h @@ -1630,6 +1630,7 @@ class Call final : public Expression { NAMED_SUPER_PROPERTY_CALL, KEYED_SUPER_PROPERTY_CALL, PRIVATE_CALL, + PRIVATE_OPTIONAL_CHAIN_CALL, SUPER_CALL, OTHER_CALL, }; diff --git a/deps/v8/src/ast/scopes.h b/deps/v8/src/ast/scopes.h index 11f44bb498436f..babb90bdd01366 100644 --- a/deps/v8/src/ast/scopes.h +++ b/deps/v8/src/ast/scopes.h @@ -102,6 +102,10 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { } inline explicit Snapshot(Scope* scope); + // Disallow copy and move. + Snapshot(const Snapshot&) = delete; + Snapshot(Snapshot&&) = delete; + ~Snapshot() { // If we're still active, there was no arrow function. In that case outer // calls eval if it already called eval before this snapshot started, or @@ -142,10 +146,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { Scope* top_inner_scope_; UnresolvedList::Iterator top_unresolved_; base::ThreadedList::Iterator top_local_; - - // Disallow copy and move. - Snapshot(const Snapshot&) = delete; - Snapshot(Snapshot&&) = delete; }; enum class DeserializationMode { kIncludingVariables, kScopesOnly }; diff --git a/deps/v8/src/base/bit-field.h b/deps/v8/src/base/bit-field.h index 9cebac32de49aa..ca5fb459210ec2 100644 --- a/deps/v8/src/base/bit-field.h +++ b/deps/v8/src/base/bit-field.h @@ -52,9 +52,7 @@ class BitField final { // Returns a type U with the bit field value encoded. static constexpr U encode(T value) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK(is_valid(value)); -#endif + CONSTEXPR_DCHECK(is_valid(value)); return static_cast(value) << kShift; } diff --git a/deps/v8/src/base/bits.h b/deps/v8/src/base/bits.h index b74b98e1069bf9..cf4b77fa1862ff 100644 --- a/deps/v8/src/base/bits.h +++ b/deps/v8/src/base/bits.h @@ -32,22 +32,27 @@ constexpr inline return sizeof(T) == 8 ? __builtin_popcountll(static_cast(value)) : __builtin_popcount(static_cast(value)); #else + // Fall back to divide-and-conquer popcount (see "Hacker's Delight" by Henry + // S. Warren, Jr.), chapter 5-1. constexpr uint64_t mask[] = {0x5555555555555555, 0x3333333333333333, 0x0f0f0f0f0f0f0f0f}; - // Start with 1 bit wide buckets of [0,1]. + // Start with 64 buckets of 1 bits, holding values from [0,1]. value = ((value >> 1) & mask[0]) + (value & mask[0]); - // Having 2 bit wide buckets of [0,2] now. + // Having 32 buckets of 2 bits, holding values from [0,2] now. value = ((value >> 2) & mask[1]) + (value & mask[1]); - // Having 4 bit wide buckets of [0,4] now. - value = (value >> 4) + value; - // Having 4 bit wide buckets of [0,8] now. - if (sizeof(T) > 1) - value = ((value >> (sizeof(T) > 1 ? 8 : 0)) & mask[2]) + (value & mask[2]); - // Having 8 bit wide buckets of [0,16] now. + // Having 16 buckets of 4 bits, holding values from [0,4] now. + value = ((value >> 4) & mask[2]) + (value & mask[2]); + // Having 8 buckets of 8 bits, holding values from [0,8] now. + // From this point on, the buckets are bigger than the number of bits + // required to hold the values, and the buckets are bigger the maximum + // result, so there's no need to mask value anymore, since there's no + // more risk of overflow between buckets. + if (sizeof(T) > 1) value = (value >> (sizeof(T) > 1 ? 8 : 0)) + value; + // Having 4 buckets of 16 bits, holding values from [0,16] now. if (sizeof(T) > 2) value = (value >> (sizeof(T) > 2 ? 16 : 0)) + value; - // Having 8 bit wide buckets of [0,32] now. + // Having 2 buckets of 32 bits, holding values from [0,32] now. if (sizeof(T) > 4) value = (value >> (sizeof(T) > 4 ? 32 : 0)) + value; - // Having 8 bit wide buckets of [0,64] now. + // Having 1 buckets of 64 bits, holding values from [0,64] now. return static_cast(value & 0xff); #endif } @@ -140,9 +145,7 @@ constexpr inline bool IsPowerOfTwo(T value) { template ::value>::type> inline constexpr int WhichPowerOfTwo(T value) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK(IsPowerOfTwo(value)); -#endif + CONSTEXPR_DCHECK(IsPowerOfTwo(value)); #if V8_HAS_BUILTIN_CTZ STATIC_ASSERT(sizeof(T) <= 8); return sizeof(T) == 8 ? __builtin_ctzll(static_cast(value)) diff --git a/deps/v8/src/base/bounds.h b/deps/v8/src/base/bounds.h index 236e29b7ccd945..fb8c968d660eca 100644 --- a/deps/v8/src/base/bounds.h +++ b/deps/v8/src/base/bounds.h @@ -15,9 +15,7 @@ namespace base { // branch. template inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK_LE(lower_limit, higher_limit); -#endif + CONSTEXPR_DCHECK(lower_limit <= higher_limit); STATIC_ASSERT(sizeof(U) <= sizeof(T)); using unsigned_T = typename std::make_unsigned::type; // Use static_cast to support enum classes. @@ -29,7 +27,9 @@ inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) { // Checks if [index, index+length) is in range [0, max). Note that this check // works even if {index+length} would wrap around. -inline constexpr bool IsInBounds(size_t index, size_t length, size_t max) { +template ::value>::type> +inline constexpr bool IsInBounds(T index, T length, T max) { return length <= max && index <= (max - length); } diff --git a/deps/v8/src/base/cpu.cc b/deps/v8/src/base/cpu.cc index bbdae525e30b39..bae1afe7d1d8ce 100644 --- a/deps/v8/src/base/cpu.cc +++ b/deps/v8/src/base/cpu.cc @@ -75,7 +75,8 @@ static V8_INLINE void __cpuid(int cpu_info[4], int info_type) { #endif // !V8_LIBC_MSVCRT -#elif V8_HOST_ARCH_ARM || V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 +#elif V8_HOST_ARCH_ARM || V8_HOST_ARCH_ARM64 || V8_HOST_ARCH_MIPS || \ + V8_HOST_ARCH_MIPS64 #if V8_OS_LINUX @@ -108,6 +109,51 @@ static V8_INLINE void __cpuid(int cpu_info[4], int info_type) { #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) #define HWCAP_LPAE (1 << 20) +#endif // V8_HOST_ARCH_ARM + +#if V8_HOST_ARCH_ARM64 + +// See kernel header. +/* + * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP + */ +#define HWCAP_FP (1 << 0) +#define HWCAP_ASIMD (1 << 1) +#define HWCAP_EVTSTRM (1 << 2) +#define HWCAP_AES (1 << 3) +#define HWCAP_PMULL (1 << 4) +#define HWCAP_SHA1 (1 << 5) +#define HWCAP_SHA2 (1 << 6) +#define HWCAP_CRC32 (1 << 7) +#define HWCAP_ATOMICS (1 << 8) +#define HWCAP_FPHP (1 << 9) +#define HWCAP_ASIMDHP (1 << 10) +#define HWCAP_CPUID (1 << 11) +#define HWCAP_ASIMDRDM (1 << 12) +#define HWCAP_JSCVT (1 << 13) +#define HWCAP_FCMA (1 << 14) +#define HWCAP_LRCPC (1 << 15) +#define HWCAP_DCPOP (1 << 16) +#define HWCAP_SHA3 (1 << 17) +#define HWCAP_SM3 (1 << 18) +#define HWCAP_SM4 (1 << 19) +#define HWCAP_ASIMDDP (1 << 20) +#define HWCAP_SHA512 (1 << 21) +#define HWCAP_SVE (1 << 22) +#define HWCAP_ASIMDFHM (1 << 23) +#define HWCAP_DIT (1 << 24) +#define HWCAP_USCAT (1 << 25) +#define HWCAP_ILRCPC (1 << 26) +#define HWCAP_FLAGM (1 << 27) +#define HWCAP_SSBS (1 << 28) +#define HWCAP_SB (1 << 29) +#define HWCAP_PACA (1 << 30) +#define HWCAP_PACG (1UL << 31) + +#endif // V8_HOST_ARCH_ARM64 + +#if V8_HOST_ARCH_ARM || V8_HOST_ARCH_ARM64 + static uint32_t ReadELFHWCaps() { uint32_t result = 0; #if V8_GLIBC_PREREQ(2, 16) @@ -136,7 +182,7 @@ static uint32_t ReadELFHWCaps() { return result; } -#endif // V8_HOST_ARCH_ARM +#endif // V8_HOST_ARCH_ARM || V8_HOST_ARCH_ARM64 #if V8_HOST_ARCH_MIPS int __detect_fp64_mode(void) { @@ -298,7 +344,8 @@ static bool HasListItem(const char* list, const char* item) { #endif // V8_OS_LINUX -#endif // V8_HOST_ARCH_ARM || V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 +#endif // V8_HOST_ARCH_ARM || V8_HOST_ARCH_ARM64 || + // V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 CPU::CPU() : stepping_(0), @@ -337,6 +384,7 @@ CPU::CPU() has_vfp_(false), has_vfp3_(false), has_vfp3_d32_(false), + has_jscvt_(false), is_fp64_mode_(false), has_non_stop_time_stamp_counter_(false), has_msa_(false) { @@ -609,6 +657,19 @@ CPU::CPU() // Windows makes high-resolution thread timing information available in // user-space. has_non_stop_time_stamp_counter_ = true; + +#elif V8_OS_LINUX + // Try to extract the list of CPU features from ELF hwcaps. + uint32_t hwcaps = ReadELFHWCaps(); + if (hwcaps != 0) { + has_jscvt_ = (hwcaps & HWCAP_JSCVT) != 0; + } else { + // Try to fallback to "Features" CPUInfo field + CPUInfo cpu_info; + char* features = cpu_info.ExtractField("Features"); + has_jscvt_ = HasListItem(features, "jscvt"); + delete[] features; + } #endif // V8_OS_WIN #elif V8_HOST_ARCH_PPC || V8_HOST_ARCH_PPC64 diff --git a/deps/v8/src/base/cpu.h b/deps/v8/src/base/cpu.h index 4b4becfa204937..8cec23c8e8e4bc 100644 --- a/deps/v8/src/base/cpu.h +++ b/deps/v8/src/base/cpu.h @@ -110,6 +110,7 @@ class V8_BASE_EXPORT CPU final { bool has_vfp() const { return has_vfp_; } bool has_vfp3() const { return has_vfp3_; } bool has_vfp3_d32() const { return has_vfp3_d32_; } + bool has_jscvt() const { return has_jscvt_; } // mips features bool is_fp64_mode() const { return is_fp64_mode_; } @@ -153,6 +154,7 @@ class V8_BASE_EXPORT CPU final { bool has_vfp_; bool has_vfp3_; bool has_vfp3_d32_; + bool has_jscvt_; bool is_fp64_mode_; bool has_non_stop_time_stamp_counter_; bool has_msa_; diff --git a/deps/v8/src/base/enum-set.h b/deps/v8/src/base/enum-set.h index 927a8f87fe0ce6..2415f1c500bd3f 100644 --- a/deps/v8/src/base/enum-set.h +++ b/deps/v8/src/base/enum-set.h @@ -63,9 +63,7 @@ class EnumSet { explicit constexpr EnumSet(T bits) : bits_(bits) {} static constexpr T Mask(E element) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK_GT(sizeof(T) * 8, static_cast(element)); -#endif + CONSTEXPR_DCHECK(sizeof(T) * 8 > static_cast(element)); return T{1} << static_cast::type>(element); } diff --git a/deps/v8/src/base/iterator.h b/deps/v8/src/base/iterator.h index 86d4b068d336f3..0bec8725227107 100644 --- a/deps/v8/src/base/iterator.h +++ b/deps/v8/src/base/iterator.h @@ -36,8 +36,7 @@ class iterator_range { typename std::iterator_traits::difference_type; iterator_range() : begin_(), end_() {} - template - iterator_range(ForwardIterator1 begin, ForwardIterator2 end) + iterator_range(ForwardIterator begin, ForwardIterator end) : begin_(begin), end_(end) {} iterator begin() { return begin_; } diff --git a/deps/v8/src/base/logging.h b/deps/v8/src/base/logging.h index 790018c98e9889..fe39f988225e96 100644 --- a/deps/v8/src/base/logging.h +++ b/deps/v8/src/base/logging.h @@ -134,6 +134,12 @@ V8_BASE_EXPORT void SetDcheckFunction(void (*dcheck_Function)(const char*, int, #endif +#if V8_HAS_CXX14_CONSTEXPR +#define CONSTEXPR_DCHECK(cond) DCHECK(cond) +#else +#define CONSTEXPR_DCHECK(cond) +#endif + // Define PrintCheckOperand for each T which defines operator<< for ostream. template typename std::enable_if< diff --git a/deps/v8/src/base/macros.h b/deps/v8/src/base/macros.h index e22dd00895ab7b..4eb652cae559af 100644 --- a/deps/v8/src/base/macros.h +++ b/deps/v8/src/base/macros.h @@ -171,22 +171,12 @@ V8_INLINE Dest bit_cast(Source const& source) { #endif #endif -// Helper macro to define no_sanitize attributes only with clang. -#if defined(__clang__) && defined(__has_attribute) -#if __has_attribute(no_sanitize) -#define CLANG_NO_SANITIZE(what) __attribute__((no_sanitize(what))) -#endif -#endif -#if !defined(CLANG_NO_SANITIZE) -#define CLANG_NO_SANITIZE(what) -#endif - // DISABLE_CFI_PERF -- Disable Control Flow Integrity checks for Perf reasons. -#define DISABLE_CFI_PERF CLANG_NO_SANITIZE("cfi") +#define DISABLE_CFI_PERF V8_CLANG_NO_SANITIZE("cfi") // DISABLE_CFI_ICALL -- Disable Control Flow Integrity indirect call checks, // useful because calls into JITed code can not be CFI verified. -#define DISABLE_CFI_ICALL CLANG_NO_SANITIZE("cfi-icall") +#define DISABLE_CFI_ICALL V8_CLANG_NO_SANITIZE("cfi-icall") #if V8_CC_GNU #define V8_IMMEDIATE_CRASH() __builtin_trap() diff --git a/deps/v8/src/base/optional.h b/deps/v8/src/base/optional.h index 6610c7ffc33623..3c13e654c80cf5 100644 --- a/deps/v8/src/base/optional.h +++ b/deps/v8/src/base/optional.h @@ -557,33 +557,33 @@ class OPTIONAL_DECLSPEC_EMPTY_BASES Optional return *this; } - const T* operator->() const { - DCHECK(storage_.is_populated_); + constexpr const T* operator->() const { + CONSTEXPR_DCHECK(storage_.is_populated_); return &storage_.value_; } - T* operator->() { - DCHECK(storage_.is_populated_); + constexpr T* operator->() { + CONSTEXPR_DCHECK(storage_.is_populated_); return &storage_.value_; } - const T& operator*() const & { - DCHECK(storage_.is_populated_); + constexpr const T& operator*() const& { + CONSTEXPR_DCHECK(storage_.is_populated_); return storage_.value_; } - T& operator*() & { - DCHECK(storage_.is_populated_); + constexpr T& operator*() & { + CONSTEXPR_DCHECK(storage_.is_populated_); return storage_.value_; } - const T&& operator*() const && { - DCHECK(storage_.is_populated_); + constexpr const T&& operator*() const&& { + CONSTEXPR_DCHECK(storage_.is_populated_); return std::move(storage_.value_); } - T&& operator*() && { - DCHECK(storage_.is_populated_); + constexpr T&& operator*() && { + CONSTEXPR_DCHECK(storage_.is_populated_); return std::move(storage_.value_); } diff --git a/deps/v8/src/base/platform/platform-posix.cc b/deps/v8/src/base/platform/platform-posix.cc index 17fc5b508394c8..238750bab16b61 100644 --- a/deps/v8/src/base/platform/platform-posix.cc +++ b/deps/v8/src/base/platform/platform-posix.cc @@ -531,7 +531,7 @@ OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, size_t size, void* initial) { if (FILE* file = fopen(name, "w+")) { - if (size == 0) return new PosixMemoryMappedFile(file, 0, 0); + if (size == 0) return new PosixMemoryMappedFile(file, nullptr, 0); size_t result = fwrite(initial, 1, size, file); if (result == size && !ferror(file)) { void* memory = mmap(OS::GetRandomMmapAddr(), result, diff --git a/deps/v8/src/base/platform/time.h b/deps/v8/src/base/platform/time.h index 5f69129ecbc4cc..63a5e8a0591b35 100644 --- a/deps/v8/src/base/platform/time.h +++ b/deps/v8/src/base/platform/time.h @@ -14,6 +14,7 @@ #include "src/base/base-export.h" #include "src/base/bits.h" #include "src/base/macros.h" +#include "src/base/safe_conversions.h" #if V8_OS_WIN #include "src/base/win32-headers.h" #endif @@ -90,6 +91,11 @@ class V8_BASE_EXPORT TimeDelta final { return TimeDelta(nanoseconds / TimeConstants::kNanosecondsPerMicrosecond); } + static TimeDelta FromMillisecondsD(double milliseconds) { + return FromDouble(milliseconds * + TimeConstants::kMicrosecondsPerMillisecond); + } + // Returns the maximum time delta, which should be greater than any reasonable // time delta we might compare it to. Adding or subtracting the maximum time // delta to a time or another time delta has an undefined result. @@ -201,6 +207,9 @@ class V8_BASE_EXPORT TimeDelta final { } private: + // TODO(v8:10620): constexpr requires constexpr saturated_cast. + static inline TimeDelta FromDouble(double value); + template friend class time_internal::TimeBase; // Constructs a delta given the duration in microseconds. This is private // to avoid confusion by callers with an integer constructor. Use @@ -211,6 +220,11 @@ class V8_BASE_EXPORT TimeDelta final { int64_t delta_; }; +// static +TimeDelta TimeDelta::FromDouble(double value) { + return TimeDelta(saturated_cast(value)); +} + // static constexpr TimeDelta TimeDelta::Max() { return TimeDelta(std::numeric_limits::max()); diff --git a/deps/v8/src/base/template-utils.h b/deps/v8/src/base/template-utils.h index 8f89672e1af66e..617ef6ce34bce1 100644 --- a/deps/v8/src/base/template-utils.h +++ b/deps/v8/src/base/template-utils.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -22,6 +23,12 @@ constexpr inline auto make_array_helper(Function f, return {{f(Indexes)...}}; } +template