deps: update V8 to 12.3.219.16

PR-URL: https://github.com/nodejs/node/pull/52293
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
This commit is contained in:
Michaël Zasso 2024-04-18 07:06:43 +02:00 committed by Node.js GitHub Bot
parent 07f481cfcf
commit 1d29d81c69
1088 changed files with 35820 additions and 19770 deletions

12
deps/v8/.gitignore vendored
View File

@ -63,13 +63,10 @@
/test/wasm-spec-tests/tests.tar.gz /test/wasm-spec-tests/tests.tar.gz
/third_party/* /third_party/*
!/third_party/antlr4 !/third_party/antlr4
!/third_party/cpu_features
/third_party/cpu_features/src
!/third_party/inspector_protocol
!/third_party/jsoncpp
/third_party/jsoncpp/source
!/third_party/colorama !/third_party/colorama
/third_party/colorama/src /third_party/colorama/src
!/third_party/cpu_features
/third_party/cpu_features/src
!/third_party/glibc !/third_party/glibc
!/third_party/googletest !/third_party/googletest
/third_party/googletest/src/* /third_party/googletest/src/*
@ -80,6 +77,11 @@
!/third_party/googletest/src/googletest/include/gtest !/third_party/googletest/src/googletest/include/gtest
/third_party/googletest/src/googletest/include/gtest/* /third_party/googletest/src/googletest/include/gtest/*
!/third_party/googletest/src/googletest/include/gtest/gtest_prod.h !/third_party/googletest/src/googletest/include/gtest/gtest_prod.h
!/third_party/inspector_protocol
!/third_party/jsoncpp
/third_party/jsoncpp/source
!/third_party/re2
/third_party/re2/src
!/third_party/test262-harness !/third_party/test262-harness
!/third_party/v8 !/third_party/v8
!/third_party/wasm-api !/third_party/wasm-api

1
deps/v8/AUTHORS vendored
View File

@ -311,3 +311,4 @@ Zhongping Wang <kewpie.w.zp@gmail.com>
Yang Xiang <xiangyangemail@gmail.com> Yang Xiang <xiangyangemail@gmail.com>
Kotaro Ohsugi <dec4m4rk@gmail.com> Kotaro Ohsugi <dec4m4rk@gmail.com>
Jing Peiyang <jingpeiyang@eswincomputing.com> Jing Peiyang <jingpeiyang@eswincomputing.com>
magic-akari <akari.ccino@gmail.com>

17
deps/v8/BUILD.bazel vendored
View File

@ -1689,6 +1689,8 @@ filegroup(
"src/heap/memory-balancer.h", "src/heap/memory-balancer.h",
"src/heap/memory-chunk.cc", "src/heap/memory-chunk.cc",
"src/heap/memory-chunk.h", "src/heap/memory-chunk.h",
"src/heap/memory-chunk-header.cc",
"src/heap/memory-chunk-header.h",
"src/heap/memory-chunk-inl.h", "src/heap/memory-chunk-inl.h",
"src/heap/memory-chunk-layout.cc", "src/heap/memory-chunk-layout.cc",
"src/heap/memory-chunk-layout.h", "src/heap/memory-chunk-layout.h",
@ -2792,6 +2794,7 @@ filegroup(
"src/wasm/code-space-access.cc", "src/wasm/code-space-access.cc",
"src/wasm/code-space-access.h", "src/wasm/code-space-access.h",
"src/wasm/compilation-environment.h", "src/wasm/compilation-environment.h",
"src/wasm/compilation-environment-inl.h",
"src/wasm/constant-expression.cc", "src/wasm/constant-expression.cc",
"src/wasm/constant-expression.h", "src/wasm/constant-expression.h",
"src/wasm/constant-expression-interface.cc", "src/wasm/constant-expression-interface.cc",
@ -2883,6 +2886,7 @@ filegroup(
"src/wasm/wasm-value.h", "src/wasm/wasm-value.h",
"src/wasm/well-known-imports.cc", "src/wasm/well-known-imports.cc",
"src/wasm/well-known-imports.h", "src/wasm/well-known-imports.h",
"src/wasm/wrappers.cc",
], ],
"//conditions:default": [], "//conditions:default": [],
}), }),
@ -3011,6 +3015,8 @@ filegroup(
"src/compiler/compiler-source-position-table.h", "src/compiler/compiler-source-position-table.h",
"src/compiler/constant-folding-reducer.cc", "src/compiler/constant-folding-reducer.cc",
"src/compiler/constant-folding-reducer.h", "src/compiler/constant-folding-reducer.h",
"src/compiler/const-tracking-let-helpers.cc",
"src/compiler/const-tracking-let-helpers.h",
"src/compiler/control-equivalence.cc", "src/compiler/control-equivalence.cc",
"src/compiler/control-equivalence.h", "src/compiler/control-equivalence.h",
"src/compiler/control-flow-optimizer.cc", "src/compiler/control-flow-optimizer.cc",
@ -3185,7 +3191,7 @@ filegroup(
"src/compiler/turboshaft/builtin-call-descriptors.h", "src/compiler/turboshaft/builtin-call-descriptors.h",
"src/compiler/turboshaft/csa-optimize-phase.cc", "src/compiler/turboshaft/csa-optimize-phase.cc",
"src/compiler/turboshaft/csa-optimize-phase.h", "src/compiler/turboshaft/csa-optimize-phase.h",
"src/compiler/turboshaft/dataview-reducer.h", "src/compiler/turboshaft/dataview-lowering-reducer.h",
"src/compiler/turboshaft/code-elimination-and-simplification-phase.cc", "src/compiler/turboshaft/code-elimination-and-simplification-phase.cc",
"src/compiler/turboshaft/code-elimination-and-simplification-phase.h", "src/compiler/turboshaft/code-elimination-and-simplification-phase.h",
"src/compiler/turboshaft/dead-code-elimination-reducer.h", "src/compiler/turboshaft/dead-code-elimination-reducer.h",
@ -3199,7 +3205,7 @@ filegroup(
"src/compiler/turboshaft/define-assembler-macros.inc", "src/compiler/turboshaft/define-assembler-macros.inc",
"src/compiler/turboshaft/deopt-data.h", "src/compiler/turboshaft/deopt-data.h",
"src/compiler/turboshaft/explicit-truncation-reducer.h", "src/compiler/turboshaft/explicit-truncation-reducer.h",
"src/compiler/turboshaft/fast-api-call-reducer.h", "src/compiler/turboshaft/fast-api-call-lowering-reducer.h",
"src/compiler/turboshaft/fast-hash.h", "src/compiler/turboshaft/fast-hash.h",
"src/compiler/turboshaft/graph.cc", "src/compiler/turboshaft/graph.cc",
"src/compiler/turboshaft/graph.h", "src/compiler/turboshaft/graph.h",
@ -3249,7 +3255,6 @@ filegroup(
"src/compiler/turboshaft/recreate-schedule.h", "src/compiler/turboshaft/recreate-schedule.h",
"src/compiler/turboshaft/recreate-schedule-phase.cc", "src/compiler/turboshaft/recreate-schedule-phase.cc",
"src/compiler/turboshaft/recreate-schedule-phase.h", "src/compiler/turboshaft/recreate-schedule-phase.h",
"src/compiler/turboshaft/reduce-args-helper.h",
"src/compiler/turboshaft/reducer-traits.h", "src/compiler/turboshaft/reducer-traits.h",
"src/compiler/turboshaft/representations.cc", "src/compiler/turboshaft/representations.cc",
"src/compiler/turboshaft/representations.h", "src/compiler/turboshaft/representations.h",
@ -3265,7 +3270,7 @@ filegroup(
"src/compiler/turboshaft/simplify-tf-loops.h", "src/compiler/turboshaft/simplify-tf-loops.h",
"src/compiler/turboshaft/snapshot-table.h", "src/compiler/turboshaft/snapshot-table.h",
"src/compiler/turboshaft/snapshot-table-opindex.h", "src/compiler/turboshaft/snapshot-table-opindex.h",
"src/compiler/turboshaft/stack-check-reducer.h", "src/compiler/turboshaft/stack-check-lowering-reducer.h",
"src/compiler/turboshaft/store-store-elimination-phase.cc", "src/compiler/turboshaft/store-store-elimination-phase.cc",
"src/compiler/turboshaft/store-store-elimination-phase.h", "src/compiler/turboshaft/store-store-elimination-phase.h",
"src/compiler/turboshaft/store-store-elimination-reducer.h", "src/compiler/turboshaft/store-store-elimination-reducer.h",
@ -3374,8 +3379,8 @@ filegroup(
"src/compiler/turboshaft/wasm-assembler-helpers.h", "src/compiler/turboshaft/wasm-assembler-helpers.h",
"src/compiler/turboshaft/wasm-gc-optimize-phase.cc", "src/compiler/turboshaft/wasm-gc-optimize-phase.cc",
"src/compiler/turboshaft/wasm-gc-optimize-phase.h", "src/compiler/turboshaft/wasm-gc-optimize-phase.h",
"src/compiler/turboshaft/wasm-gc-type-reducer.cc", "src/compiler/turboshaft/wasm-gc-typed-optimization-reducer.cc",
"src/compiler/turboshaft/wasm-gc-type-reducer.h", "src/compiler/turboshaft/wasm-gc-typed-optimization-reducer.h",
"src/compiler/turboshaft/wasm-load-elimination-reducer.h", "src/compiler/turboshaft/wasm-load-elimination-reducer.h",
"src/compiler/turboshaft/wasm-lowering-phase.cc", "src/compiler/turboshaft/wasm-lowering-phase.cc",
"src/compiler/turboshaft/wasm-lowering-phase.h", "src/compiler/turboshaft/wasm-lowering-phase.h",

68
deps/v8/BUILD.gn vendored
View File

@ -1149,6 +1149,9 @@ config("features") {
if (v8_fuzzilli) { if (v8_fuzzilli) {
defines += [ "V8_FUZZILLI" ] defines += [ "V8_FUZZILLI" ]
} }
if (v8_enable_fuzztest) {
defines += [ "V8_ENABLE_FUZZTEST" ]
}
if (v8_enable_short_builtin_calls) { if (v8_enable_short_builtin_calls) {
defines += [ "V8_SHORT_BUILTIN_CALLS" ] defines += [ "V8_SHORT_BUILTIN_CALLS" ]
} }
@ -1482,7 +1485,6 @@ config("toolchain") {
if (is_clang) { if (is_clang) {
cflags += [ cflags += [
"-Wmissing-field-initializers",
"-Wunreachable-code", "-Wunreachable-code",
# TODO(v8:12245): Fix shadowing instances and remove. # TODO(v8:12245): Fix shadowing instances and remove.
@ -1496,11 +1498,6 @@ config("toolchain") {
# warning. # warning.
cflags += [ "-Wctad-maybe-unsupported" ] cflags += [ "-Wctad-maybe-unsupported" ]
} }
if (v8_current_cpu == "x64" || v8_current_cpu == "arm64" ||
v8_current_cpu == "mips64el" || v8_current_cpu == "riscv64") {
cflags += [ "-Wshorten-64-to-32" ]
}
} }
if (is_clang || !is_win) { if (is_clang || !is_win) {
@ -1700,20 +1697,6 @@ config("toolchain") {
# Fix build with older versions of GCC # Fix build with older versions of GCC
# Ported from v8 bazel: https://crrev.com/c/3368869 # Ported from v8 bazel: https://crrev.com/c/3368869
"-Wno-stringop-overflow", "-Wno-stringop-overflow",
# Fix a number of bogus errors with gcc12
# TODO(miladfarca): re-evaluate for future gcc upgrades
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111499
"-Wno-stringop-overread",
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104336
"-Wno-restrict",
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523
"-Wno-array-bounds",
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108517
"-Wno-nonnull",
] ]
} }
@ -1723,6 +1706,17 @@ config("toolchain") {
} }
} }
config("strict_warnings") {
cflags = []
if (is_clang) {
if (v8_current_cpu == "x64" || v8_current_cpu == "arm64" ||
v8_current_cpu == "mips64el" || v8_current_cpu == "riscv64") {
cflags += [ "-Wshorten-64-to-32" ]
}
cflags += [ "-Wmissing-field-initializers" ]
}
}
# For code that is hot during mksnapshot. In fast-mksnapshot builds, we # For code that is hot during mksnapshot. In fast-mksnapshot builds, we
# optimize some files even in debug builds to speed up mksnapshot times. # optimize some files even in debug builds to speed up mksnapshot times.
config("always_turbofanimize") { config("always_turbofanimize") {
@ -3304,6 +3298,7 @@ v8_header_set("v8_internal_headers") {
"src/compiler/common-operator.h", "src/compiler/common-operator.h",
"src/compiler/compilation-dependencies.h", "src/compiler/compilation-dependencies.h",
"src/compiler/compiler-source-position-table.h", "src/compiler/compiler-source-position-table.h",
"src/compiler/const-tracking-let-helpers.h",
"src/compiler/constant-folding-reducer.h", "src/compiler/constant-folding-reducer.h",
"src/compiler/control-equivalence.h", "src/compiler/control-equivalence.h",
"src/compiler/control-flow-optimizer.h", "src/compiler/control-flow-optimizer.h",
@ -3401,7 +3396,7 @@ v8_header_set("v8_internal_headers") {
"src/compiler/turboshaft/code-elimination-and-simplification-phase.h", "src/compiler/turboshaft/code-elimination-and-simplification-phase.h",
"src/compiler/turboshaft/copying-phase.h", "src/compiler/turboshaft/copying-phase.h",
"src/compiler/turboshaft/csa-optimize-phase.h", "src/compiler/turboshaft/csa-optimize-phase.h",
"src/compiler/turboshaft/dataview-reducer.h", "src/compiler/turboshaft/dataview-lowering-reducer.h",
"src/compiler/turboshaft/dead-code-elimination-reducer.h", "src/compiler/turboshaft/dead-code-elimination-reducer.h",
"src/compiler/turboshaft/debug-feature-lowering-phase.h", "src/compiler/turboshaft/debug-feature-lowering-phase.h",
"src/compiler/turboshaft/debug-feature-lowering-reducer.h", "src/compiler/turboshaft/debug-feature-lowering-reducer.h",
@ -3411,7 +3406,7 @@ v8_header_set("v8_internal_headers") {
"src/compiler/turboshaft/deopt-data.h", "src/compiler/turboshaft/deopt-data.h",
"src/compiler/turboshaft/duplication-optimization-reducer.h", "src/compiler/turboshaft/duplication-optimization-reducer.h",
"src/compiler/turboshaft/explicit-truncation-reducer.h", "src/compiler/turboshaft/explicit-truncation-reducer.h",
"src/compiler/turboshaft/fast-api-call-reducer.h", "src/compiler/turboshaft/fast-api-call-lowering-reducer.h",
"src/compiler/turboshaft/fast-hash.h", "src/compiler/turboshaft/fast-hash.h",
"src/compiler/turboshaft/graph-builder.h", "src/compiler/turboshaft/graph-builder.h",
"src/compiler/turboshaft/graph-visualizer.h", "src/compiler/turboshaft/graph-visualizer.h",
@ -3440,7 +3435,6 @@ v8_header_set("v8_internal_headers") {
"src/compiler/turboshaft/pretenuring-propagation-reducer.h", "src/compiler/turboshaft/pretenuring-propagation-reducer.h",
"src/compiler/turboshaft/recreate-schedule-phase.h", "src/compiler/turboshaft/recreate-schedule-phase.h",
"src/compiler/turboshaft/recreate-schedule.h", "src/compiler/turboshaft/recreate-schedule.h",
"src/compiler/turboshaft/reduce-args-helper.h",
"src/compiler/turboshaft/reducer-traits.h", "src/compiler/turboshaft/reducer-traits.h",
"src/compiler/turboshaft/representations.h", "src/compiler/turboshaft/representations.h",
"src/compiler/turboshaft/required-optimization-reducer.h", "src/compiler/turboshaft/required-optimization-reducer.h",
@ -3452,7 +3446,7 @@ v8_header_set("v8_internal_headers") {
"src/compiler/turboshaft/simplify-tf-loops.h", "src/compiler/turboshaft/simplify-tf-loops.h",
"src/compiler/turboshaft/snapshot-table-opindex.h", "src/compiler/turboshaft/snapshot-table-opindex.h",
"src/compiler/turboshaft/snapshot-table.h", "src/compiler/turboshaft/snapshot-table.h",
"src/compiler/turboshaft/stack-check-reducer.h", "src/compiler/turboshaft/stack-check-lowering-reducer.h",
"src/compiler/turboshaft/store-store-elimination-phase.h", "src/compiler/turboshaft/store-store-elimination-phase.h",
"src/compiler/turboshaft/store-store-elimination-reducer.h", "src/compiler/turboshaft/store-store-elimination-reducer.h",
"src/compiler/turboshaft/structural-optimization-reducer.h", "src/compiler/turboshaft/structural-optimization-reducer.h",
@ -3640,6 +3634,7 @@ v8_header_set("v8_internal_headers") {
"src/heap/marking.h", "src/heap/marking.h",
"src/heap/memory-allocator.h", "src/heap/memory-allocator.h",
"src/heap/memory-balancer.h", "src/heap/memory-balancer.h",
"src/heap/memory-chunk-header.h",
"src/heap/memory-chunk-inl.h", "src/heap/memory-chunk-inl.h",
"src/heap/memory-chunk-layout.h", "src/heap/memory-chunk-layout.h",
"src/heap/memory-chunk.h", "src/heap/memory-chunk.h",
@ -4136,6 +4131,12 @@ v8_header_set("v8_internal_headers") {
if (v8_use_perfetto) { if (v8_use_perfetto) {
sources -= [ "//base/trace_event/common/trace_event_common.h" ] sources -= [ "//base/trace_event/common/trace_event_common.h" ]
sources += [
"src/tracing/code-data-source.h",
"src/tracing/code-trace-context.h",
"src/tracing/perfetto-logger.h",
"src/tracing/perfetto-utils.h",
]
} }
if (v8_enable_sparkplug) { if (v8_enable_sparkplug) {
@ -4195,7 +4196,7 @@ v8_header_set("v8_internal_headers") {
"src/compiler/turboshaft/int64-lowering-reducer.h", "src/compiler/turboshaft/int64-lowering-reducer.h",
"src/compiler/turboshaft/wasm-assembler-helpers.h", "src/compiler/turboshaft/wasm-assembler-helpers.h",
"src/compiler/turboshaft/wasm-gc-optimize-phase.h", "src/compiler/turboshaft/wasm-gc-optimize-phase.h",
"src/compiler/turboshaft/wasm-gc-type-reducer.h", "src/compiler/turboshaft/wasm-gc-typed-optimization-reducer.h",
"src/compiler/turboshaft/wasm-js-lowering-reducer.h", "src/compiler/turboshaft/wasm-js-lowering-reducer.h",
"src/compiler/turboshaft/wasm-load-elimination-reducer.h", "src/compiler/turboshaft/wasm-load-elimination-reducer.h",
"src/compiler/turboshaft/wasm-lowering-phase.h", "src/compiler/turboshaft/wasm-lowering-phase.h",
@ -4230,6 +4231,7 @@ v8_header_set("v8_internal_headers") {
"src/wasm/baseline/parallel-move.h", "src/wasm/baseline/parallel-move.h",
"src/wasm/canonical-types.h", "src/wasm/canonical-types.h",
"src/wasm/code-space-access.h", "src/wasm/code-space-access.h",
"src/wasm/compilation-environment-inl.h",
"src/wasm/compilation-environment.h", "src/wasm/compilation-environment.h",
"src/wasm/constant-expression-interface.h", "src/wasm/constant-expression-interface.h",
"src/wasm/constant-expression.h", "src/wasm/constant-expression.h",
@ -4759,6 +4761,7 @@ v8_compiler_sources = [
"src/compiler/common-operator.cc", "src/compiler/common-operator.cc",
"src/compiler/compilation-dependencies.cc", "src/compiler/compilation-dependencies.cc",
"src/compiler/compiler-source-position-table.cc", "src/compiler/compiler-source-position-table.cc",
"src/compiler/const-tracking-let-helpers.cc",
"src/compiler/constant-folding-reducer.cc", "src/compiler/constant-folding-reducer.cc",
"src/compiler/control-equivalence.cc", "src/compiler/control-equivalence.cc",
"src/compiler/control-flow-optimizer.cc", "src/compiler/control-flow-optimizer.cc",
@ -4935,7 +4938,7 @@ if (v8_enable_webassembly) {
"src/compiler/int64-lowering.cc", "src/compiler/int64-lowering.cc",
"src/compiler/turboshaft/int64-lowering-phase.cc", "src/compiler/turboshaft/int64-lowering-phase.cc",
"src/compiler/turboshaft/wasm-gc-optimize-phase.cc", "src/compiler/turboshaft/wasm-gc-optimize-phase.cc",
"src/compiler/turboshaft/wasm-gc-type-reducer.cc", "src/compiler/turboshaft/wasm-gc-typed-optimization-reducer.cc",
"src/compiler/turboshaft/wasm-lowering-phase.cc", "src/compiler/turboshaft/wasm-lowering-phase.cc",
"src/compiler/turboshaft/wasm-optimize-phase.cc", "src/compiler/turboshaft/wasm-optimize-phase.cc",
"src/compiler/turboshaft/wasm-turboshaft-compiler.cc", "src/compiler/turboshaft/wasm-turboshaft-compiler.cc",
@ -5330,6 +5333,7 @@ v8_source_set("v8_base_without_compiler") {
"src/heap/marking.cc", "src/heap/marking.cc",
"src/heap/memory-allocator.cc", "src/heap/memory-allocator.cc",
"src/heap/memory-balancer.cc", "src/heap/memory-balancer.cc",
"src/heap/memory-chunk-header.cc",
"src/heap/memory-chunk-layout.cc", "src/heap/memory-chunk-layout.cc",
"src/heap/memory-chunk.cc", "src/heap/memory-chunk.cc",
"src/heap/memory-measurement.cc", "src/heap/memory-measurement.cc",
@ -5651,6 +5655,14 @@ v8_source_set("v8_base_without_compiler") {
} }
} }
if (v8_use_perfetto) {
sources += [
"src/tracing/code-data-source.cc",
"src/tracing/perfetto-logger.cc",
"src/tracing/perfetto-utils.cc",
]
}
if (v8_enable_webassembly) { if (v8_enable_webassembly) {
sources += [ sources += [
### gcmole(all) ### ### gcmole(all) ###
@ -5706,6 +5718,7 @@ v8_source_set("v8_base_without_compiler") {
"src/wasm/wasm-serialization.cc", "src/wasm/wasm-serialization.cc",
"src/wasm/wasm-subtyping.cc", "src/wasm/wasm-subtyping.cc",
"src/wasm/well-known-imports.cc", "src/wasm/well-known-imports.cc",
"src/wasm/wrappers.cc",
] ]
} }
@ -8131,7 +8144,6 @@ if (!build_with_chromium && v8_use_perfetto) {
"//third_party/perfetto/src/tracing/core", "//third_party/perfetto/src/tracing/core",
# TODO(skyostil): Support non-POSIX platforms. # TODO(skyostil): Support non-POSIX platforms.
"//third_party/perfetto/protos/perfetto/config:cpp",
"//third_party/perfetto/protos/perfetto/trace/track_event:zero", "//third_party/perfetto/protos/perfetto/trace/track_event:zero",
"//third_party/perfetto/src/tracing:in_process_backend", "//third_party/perfetto/src/tracing:in_process_backend",
"//third_party/perfetto/src/tracing:platform_impl", "//third_party/perfetto/src/tracing:platform_impl",
@ -8139,6 +8151,8 @@ if (!build_with_chromium && v8_use_perfetto) {
public_deps = [ public_deps = [
"//third_party/perfetto/include/perfetto/trace_processor", "//third_party/perfetto/include/perfetto/trace_processor",
"//third_party/perfetto/protos/perfetto/config:cpp",
"//third_party/perfetto/protos/perfetto/trace/chrome:zero",
"//third_party/perfetto/src/trace_processor:export_json", "//third_party/perfetto/src/trace_processor:export_json",
"//third_party/perfetto/src/tracing:client_api", "//third_party/perfetto/src/tracing:client_api",
] ]

59
deps/v8/DEPS vendored
View File

@ -27,6 +27,7 @@ vars = {
'checkout_fuchsia_boot_images': "terminal.x64", 'checkout_fuchsia_boot_images': "terminal.x64",
'checkout_fuchsia_product_bundles': '"{checkout_fuchsia_boot_images}" != ""', 'checkout_fuchsia_product_bundles': '"{checkout_fuchsia_boot_images}" != ""',
'checkout_centipede_deps': False,
'checkout_instrumented_libraries': False, 'checkout_instrumented_libraries': False,
'checkout_ittapi': False, 'checkout_ittapi': False,
@ -41,8 +42,9 @@ vars = {
# Fetch and build V8 builtins with PGO profiles # Fetch and build V8 builtins with PGO profiles
'checkout_v8_builtins_pgo_profiles': False, 'checkout_v8_builtins_pgo_profiles': False,
'chromium_url': 'https://chromium.googlesource.com',
'android_url': 'https://android.googlesource.com', 'android_url': 'https://android.googlesource.com',
'boringssl_url': 'https://boringssl.googlesource.com',
'chromium_url': 'https://chromium.googlesource.com',
'download_gcmole': False, 'download_gcmole': False,
'download_jsfunfuzz': False, 'download_jsfunfuzz': False,
'download_prebuilt_bazel': False, 'download_prebuilt_bazel': False,
@ -55,7 +57,7 @@ vars = {
'checkout_fuchsia_no_hooks': False, 'checkout_fuchsia_no_hooks': False,
# reclient CIPD package version # reclient CIPD package version
'reclient_version': 're_client_version:0.126.0.4aaef37-gomaip', 'reclient_version': 're_client_version:0.131.1.784ddbb-gomaip',
# Fetch configuration files required for the 'use_remoteexec' gn arg # Fetch configuration files required for the 'use_remoteexec' gn arg
'download_remoteexec_cfg': False, 'download_remoteexec_cfg': False,
@ -71,19 +73,19 @@ vars = {
'build_with_chromium': False, 'build_with_chromium': False,
# GN CIPD package version. # GN CIPD package version.
'gn_version': 'git_revision:b5adfe5f574d7110b80feb9aae6fae97c366840b', 'gn_version': 'git_revision:0a2b8eac80f164f10b2cbc126890db0d295790cd',
# ninja CIPD package version # ninja CIPD package version
# https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja # https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja
'ninja_version': 'version:2@1.11.1.chromium.6', 'ninja_version': 'version:2@1.11.1.chromium.6',
# luci-go CIPD package version. # luci-go CIPD package version.
'luci_go': 'git_revision:0d11be367258bfe14a13ff1afcf43a0bc6aedb45', 'luci_go': 'git_revision:3df60a11d33a59614c0e8d2bccc58d8c30984901',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Fuchsia sdk # the commit queue can handle CLs rolling Fuchsia sdk
# and whatever else without interference from each other. # and whatever else without interference from each other.
'fuchsia_version': 'version:17.20240120.1.1', 'fuchsia_version': 'version:18.20240215.1.1',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_build-tools_version # the commit queue can handle CLs rolling android_sdk_build-tools_version
@ -123,9 +125,9 @@ deps = {
'base/trace_event/common': 'base/trace_event/common':
Var('chromium_url') + '/chromium/src/base/trace_event/common.git' + '@' + '29ac73db520575590c3aceb0a6f1f58dda8934f6', Var('chromium_url') + '/chromium/src/base/trace_event/common.git' + '@' + '29ac73db520575590c3aceb0a6f1f58dda8934f6',
'build': 'build':
Var('chromium_url') + '/chromium/src/build.git' + '@' + '28cd6ea727d171ec990e6174308451d4178d7f8e', Var('chromium_url') + '/chromium/src/build.git' + '@' + 'e5cf1b3ceb3fec6aa5c57b34dede99d36cede32d',
'buildtools': 'buildtools':
Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '17ce6d2f0416038de7989bc71d055c07d333ccb5', Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '342659133d7d0b33f4e24b640a9ad78c0c423633',
'buildtools/linux64': { 'buildtools/linux64': {
'packages': [ 'packages': [
{ {
@ -171,7 +173,7 @@ deps = {
'test/mozilla/data': 'test/mozilla/data':
Var('chromium_url') + '/v8/deps/third_party/mozilla-tests.git' + '@' + 'f6c578a10ea707b1a8ab0b88943fe5115ce2b9be', Var('chromium_url') + '/v8/deps/third_party/mozilla-tests.git' + '@' + 'f6c578a10ea707b1a8ab0b88943fe5115ce2b9be',
'test/test262/data': 'test/test262/data':
Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + 'a1ba783ca340e4bf3d80b5f5e11fa54f2ee5f1ef', Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + 'e4f91b6381d7694265031caad0c71d733ac132f3',
'third_party/android_platform': { 'third_party/android_platform': {
'url': Var('chromium_url') + '/chromium/src/third_party/android_platform.git' + '@' + 'eeb2d566f963bb66212fdc0d9bbe1dde550b4969', 'url': Var('chromium_url') + '/chromium/src/third_party/android_platform.git' + '@' + 'eeb2d566f963bb66212fdc0d9bbe1dde550b4969',
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -224,8 +226,16 @@ deps = {
'condition': 'checkout_android', 'condition': 'checkout_android',
'dep_type': 'cipd', 'dep_type': 'cipd',
}, },
'third_party/boringssl': {
'url': Var('chromium_url') + '/chromium/src/third_party/boringssl.git' + '@' + '9ead20bdbf0ecc33219d25fd3a426876c54d126e',
'condition': "checkout_centipede_deps",
},
'third_party/boringssl/src': {
'url': Var('boringssl_url') + '/boringssl.git' + '@' + '414f69504d30d0848b69f6453ea7fb5e88004cb4',
'condition': "checkout_centipede_deps",
},
'third_party/catapult': { 'third_party/catapult': {
'url': Var('chromium_url') + '/catapult.git' + '@' + '3e413d7b62c09fda8713146714ba2146a0369d86', 'url': Var('chromium_url') + '/catapult.git' + '@' + '3d6c15240b480da1e498a64a72ea77a61ba335e1',
'condition': 'checkout_android', 'condition': 'checkout_android',
}, },
'third_party/clang-format/script': 'third_party/clang-format/script':
@ -239,11 +249,11 @@ deps = {
'condition': 'checkout_android', 'condition': 'checkout_android',
}, },
'third_party/depot_tools': 'third_party/depot_tools':
Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '46cb7d0aca592cd20ddc2f6cb16ee386b2abbf0d', Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '9d7c8e76f82ddc6a3bbc307217e31dec44a0f73a',
'third_party/fp16/src': 'third_party/fp16/src':
Var('chromium_url') + '/external/github.com/Maratyszcza/FP16.git' + '@' + '0a92994d729ff76a58f692d3028ca1b64b145d91', Var('chromium_url') + '/external/github.com/Maratyszcza/FP16.git' + '@' + '0a92994d729ff76a58f692d3028ca1b64b145d91',
'third_party/fuchsia-gn-sdk': { 'third_party/fuchsia-gn-sdk': {
'url': Var('chromium_url') + '/chromium/src/third_party/fuchsia-gn-sdk.git' + '@' + '6ad82eadcb1a4404964a8d86c544fda1dab7af94', 'url': Var('chromium_url') + '/chromium/src/third_party/fuchsia-gn-sdk.git' + '@' + 'fa3c41d7a15127a989111fcede8dae9265f8566b',
'condition': 'checkout_fuchsia', 'condition': 'checkout_fuchsia',
}, },
# Exists for rolling the Fuchsia SDK. Check out of the SDK should always # Exists for rolling the Fuchsia SDK. Check out of the SDK should always
@ -259,17 +269,21 @@ deps = {
'dep_type': 'cipd', 'dep_type': 'cipd',
}, },
'third_party/google_benchmark_chrome': { 'third_party/google_benchmark_chrome': {
'url': Var('chromium_url') + '/chromium/src/third_party/google_benchmark.git' + '@' + '992199c3cb1076d307816e963ed4b5102df53c65', 'url': Var('chromium_url') + '/chromium/src/third_party/google_benchmark.git' + '@' + 'c300add93460c31efe53fa71e61427fa1bc09e6a',
}, },
'third_party/google_benchmark_chrome/src': { 'third_party/google_benchmark_chrome/src': {
'url': Var('chromium_url') + '/external/github.com/google/benchmark.git' + '@' + 'b177433f3ee2513b1075140c723d73ab8901790f', 'url': Var('chromium_url') + '/external/github.com/google/benchmark.git' + '@' + 'b177433f3ee2513b1075140c723d73ab8901790f',
}, },
'third_party/fuzztest':
Var('chromium_url') + '/chromium/src/third_party/fuzztest.git' + '@' + '9fc64e5930915bfb5a593b7e12487d78283e8221',
'third_party/fuzztest/src':
Var('chromium_url') + '/external/github.com/google/fuzztest.git' + '@' + '61d95200e7ece7d121cab26f0c39fbf392e6566e',
'third_party/googletest/src': 'third_party/googletest/src':
Var('chromium_url') + '/external/github.com/google/googletest.git' + '@' + 'af29db7ec28d6df1c7f0f745186884091e602e07', Var('chromium_url') + '/external/github.com/google/googletest.git' + '@' + 'af29db7ec28d6df1c7f0f745186884091e602e07',
'third_party/icu': 'third_party/icu':
Var('chromium_url') + '/chromium/deps/icu.git' + '@' + 'a622de35ac311c5ad390a7af80724634e5dc61ed', Var('chromium_url') + '/chromium/deps/icu.git' + '@' + 'a622de35ac311c5ad390a7af80724634e5dc61ed',
'third_party/instrumented_libraries': 'third_party/instrumented_libraries':
Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + '0011c28c8d35fc5093bb29631d05428932cd1206', Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + '0893d760101b3ddf9a2408b9d20f15ec2b80b2c1',
'third_party/ittapi': { 'third_party/ittapi': {
# Force checkout ittapi libraries to pass v8 header includes check on # Force checkout ittapi libraries to pass v8 header includes check on
# bots that has check_v8_header_includes enabled. # bots that has check_v8_header_includes enabled.
@ -277,19 +291,19 @@ deps = {
'condition': "checkout_ittapi or check_v8_header_includes", 'condition': "checkout_ittapi or check_v8_header_includes",
}, },
'third_party/jinja2': 'third_party/jinja2':
Var('chromium_url') + '/chromium/src/third_party/jinja2.git' + '@' + 'e2d024354e11cc6b041b0cff032d73f0c7e43a07', Var('chromium_url') + '/chromium/src/third_party/jinja2.git' + '@' + 'c9c77525ea20c871a1d4658f8d312b51266d4bad',
'third_party/jsoncpp/source': 'third_party/jsoncpp/source':
Var('chromium_url') + '/external/github.com/open-source-parsers/jsoncpp.git'+ '@' + '42e892d96e47b1f6e29844cc705e148ec4856448', Var('chromium_url') + '/external/github.com/open-source-parsers/jsoncpp.git'+ '@' + '42e892d96e47b1f6e29844cc705e148ec4856448',
'third_party/libc++/src': 'third_party/libc++/src':
Var('chromium_url') + '/external/github.com/llvm/llvm-project/libcxx.git' + '@' + '28aa23ffb4c7344914a5b4ac7169f12e5a12333f', Var('chromium_url') + '/external/github.com/llvm/llvm-project/libcxx.git' + '@' + '6d83791af99ea95f04986d64f111b84ce0b3c6f5',
'third_party/libc++abi/src': 'third_party/libc++abi/src':
Var('chromium_url') + '/external/github.com/llvm/llvm-project/libcxxabi.git' + '@' + 'ea028d4d2b8a901f6302f5371c68a24480766e2b', Var('chromium_url') + '/external/github.com/llvm/llvm-project/libcxxabi.git' + '@' + 'a7b3d968a3a923886fea64b424bd770e69dc4ea4',
'third_party/libunwind/src': 'third_party/libunwind/src':
Var('chromium_url') + '/external/github.com/llvm/llvm-project/libunwind.git' + '@' + 'f400fdb561d4416b59b8f8a33d8ec8b79da60495', Var('chromium_url') + '/external/github.com/llvm/llvm-project/libunwind.git' + '@' + '8bad7bd6ec30f94bce82f7cb5b58ecbd6ce02996',
'third_party/logdog/logdog': 'third_party/logdog/logdog':
Var('chromium_url') + '/infra/luci/luci-py/client/libs/logdog' + '@' + '0b2078a90f7a638d576b3a7c407d136f2fb62399', Var('chromium_url') + '/infra/luci/luci-py/client/libs/logdog' + '@' + '0b2078a90f7a638d576b3a7c407d136f2fb62399',
'third_party/markupsafe': 'third_party/markupsafe':
Var('chromium_url') + '/chromium/src/third_party/markupsafe.git' + '@' + '0bad08bb207bbfc1d6f3bbc82b9242b0c50e5794', Var('chromium_url') + '/chromium/src/third_party/markupsafe.git' + '@' + 'e582d7f0edb9d67499b0f5abd6ae5550e91da7f2',
'third_party/ninja': { 'third_party/ninja': {
'packages': [ 'packages': [
{ {
@ -304,14 +318,16 @@ deps = {
Var('android_url') + '/platform/external/perfetto.git' + '@' + '6fc824d618d2f06b5d9cd8655ba0419b6b3b366e', Var('android_url') + '/platform/external/perfetto.git' + '@' + '6fc824d618d2f06b5d9cd8655ba0419b6b3b366e',
'third_party/protobuf': 'third_party/protobuf':
Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + '6a59a2ad1f61d9696092f79b6d74368b4d7970a3', Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + '6a59a2ad1f61d9696092f79b6d74368b4d7970a3',
'third_party/re2/src':
Var('chromium_url') + '/external/github.com/google/re2.git' + '@' + 'd00d1e93781e6ebe415771a952689dff8f260d44',
'third_party/requests': { 'third_party/requests': {
'url': Var('chromium_url') + '/external/github.com/kennethreitz/requests.git' + '@' + 'c7e0fc087ceeadb8b4c84a0953a422c474093d6d', 'url': Var('chromium_url') + '/external/github.com/kennethreitz/requests.git' + '@' + 'c7e0fc087ceeadb8b4c84a0953a422c474093d6d',
'condition': 'checkout_android', 'condition': 'checkout_android',
}, },
'third_party/zlib': 'third_party/zlib':
Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + '63c0cec0344e6ba70f22bd690187088299baaa94', Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + '4b5807f344182fd392849b820642457212618e5f',
'tools/clang': 'tools/clang':
Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + 'f0b1beffd512e855db0f46571958cfc83c8b05a9', Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + 'a4df104173dae7d49205ed8abefc920b7c5162d2',
'tools/luci-go': { 'tools/luci-go': {
'packages': [ 'packages': [
{ {
@ -327,7 +343,7 @@ deps = {
'dep_type': 'cipd', 'dep_type': 'cipd',
}, },
'third_party/abseil-cpp': { 'third_party/abseil-cpp': {
'url': Var('chromium_url') + '/chromium/src/third_party/abseil-cpp.git' + '@' + '5ff8c1facf6b2e54811969ae7b90152bc1f44269', 'url': Var('chromium_url') + '/chromium/src/third_party/abseil-cpp.git' + '@' + 'f1c5751a2cb4102efbffc4110ee7551b3c54cfea',
'condition': 'not build_with_chromium', 'condition': 'not build_with_chromium',
} }
} }
@ -338,6 +354,7 @@ include_rules = [
'+unicode', '+unicode',
'+third_party/fdlibm', '+third_party/fdlibm',
'+third_party/ittapi/include', '+third_party/ittapi/include',
'+third_party/fuzztest',
# Abseil features are allow-listed. Please use your best judgement when adding # Abseil features are allow-listed. Please use your best judgement when adding
# to this set -- if in doubt, email v8-dev@. For general guidance, refer to # to this set -- if in doubt, email v8-dev@. For general guidance, refer to
# the Chromium guidelines (though note that some requirements in V8 may be # the Chromium guidelines (though note that some requirements in V8 may be

View File

@ -443,10 +443,7 @@ def _CheckCommitMessageBugEntry(input_api, output_api):
continue continue
if ':' not in bug and not bug.startswith('b/'): if ':' not in bug and not bug.startswith('b/'):
try: try:
if int(bug) > 10000000: if int(bug) < 10000000:
results.append(
'Buganizer entry requires issue tracker prefix b/{}'.format(bug))
else:
if int(bug) > 200000: if int(bug) > 200000:
prefix_guess = 'chromium' prefix_guess = 'chromium'
else: else:

View File

@ -6,6 +6,13 @@
# Chromium specific targets in a client project's GN file etc. # Chromium specific targets in a client project's GN file etc.
build_with_chromium = false build_with_chromium = false
# Variable that can be used to support multiple build scenarios, like when
# V8 is embedded within a target.
build_with_v8_embedder = false
# Not all of V8's dependencies are available in V8's Node.js build.
build_with_node = false
# Used by perfetto to distinguish from its own standalone build and the # Used by perfetto to distinguish from its own standalone build and the
# chromium build. # chromium build.
perfetto_build_with_embedder = true perfetto_build_with_embedder = true

7
deps/v8/gni/v8.gni vendored
View File

@ -8,6 +8,7 @@ import("//build/config/gclient_args.gni")
import("//build/config/ios/config.gni") import("//build/config/ios/config.gni")
import("//build/config/sanitizers/sanitizers.gni") import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/v8_target_cpu.gni") import("//build/config/v8_target_cpu.gni")
import("//build_overrides/build.gni")
import("release_branch_toggle.gni") import("release_branch_toggle.gni")
import("split_static_library.gni") import("split_static_library.gni")
@ -96,6 +97,11 @@ declare_args() {
# Add fuzzilli fuzzer support. # Add fuzzilli fuzzer support.
v8_fuzzilli = false v8_fuzzilli = false
# Enable FuzzTest
v8_enable_fuzztest = !build_with_v8_embedder &&
!(defined(build_with_node) && build_with_node) &&
!(is_win && is_component_build) && is_clang
# Scan the call stack conservatively during garbage collection. # Scan the call stack conservatively during garbage collection.
v8_enable_conservative_stack_scanning = false v8_enable_conservative_stack_scanning = false
@ -228,6 +234,7 @@ v8_remove_configs = []
v8_add_configs = [ v8_add_configs = [
v8_path_prefix + ":features", v8_path_prefix + ":features",
v8_path_prefix + ":toolchain", v8_path_prefix + ":toolchain",
v8_path_prefix + ":strict_warnings",
] ]
if (is_debug && !v8_optimized_debug) { if (is_debug && !v8_optimized_debug) {

View File

@ -32,7 +32,7 @@ static constexpr uint16_t kFullyConstructedBitMask = uint16_t{1};
static constexpr size_t kPageSize = size_t{1} << 17; static constexpr size_t kPageSize = size_t{1} << 17;
#if defined(V8_TARGET_ARCH_ARM64) && defined(V8_OS_DARWIN) #if defined(V8_HOST_ARCH_ARM64) && defined(V8_OS_DARWIN)
constexpr size_t kGuardPageSize = 0; constexpr size_t kGuardPageSize = 0;
#else #else
constexpr size_t kGuardPageSize = 4096; constexpr size_t kGuardPageSize = 4096;

View File

@ -318,6 +318,12 @@ class V8_EXPORT ArrayBuffer : public Object {
*/ */
std::shared_ptr<BackingStore> GetBackingStore(); std::shared_ptr<BackingStore> GetBackingStore();
/**
* More efficient shortcut for
* GetBackingStore()->IsResizableByUserJavaScript().
*/
bool IsResizableByUserJavaScript() const;
/** /**
* More efficient shortcut for GetBackingStore()->Data(). The returned pointer * More efficient shortcut for GetBackingStore()->Data(). The returned pointer
* is valid as long as the ArrayBuffer is alive. * is valid as long as the ArrayBuffer is alive.

View File

@ -327,10 +327,6 @@ using WasmAsyncResolvePromiseCallback = void (*)(
using WasmLoadSourceMapCallback = Local<String> (*)(Isolate* isolate, using WasmLoadSourceMapCallback = Local<String> (*)(Isolate* isolate,
const char* name); const char* name);
// --- Callback for checking if WebAssembly GC is enabled ---
// If the callback returns true, it will also enable Wasm stringrefs.
using WasmGCEnabledCallback = bool (*)(Local<Context> context);
// --- Callback for checking if WebAssembly imported strings are enabled --- // --- Callback for checking if WebAssembly imported strings are enabled ---
using WasmImportedStringsEnabledCallback = bool (*)(Local<Context> context); using WasmImportedStringsEnabledCallback = bool (*)(Local<Context> context);
@ -342,6 +338,9 @@ using SharedArrayBufferConstructorEnabledCallback =
using JavaScriptCompileHintsMagicEnabledCallback = using JavaScriptCompileHintsMagicEnabledCallback =
bool (*)(Local<Context> context); bool (*)(Local<Context> context);
// --- Callback for checking if WebAssembly JSPI is enabled ---
using WasmJSPIEnabledCallback = bool (*)(Local<Context> context);
/** /**
* HostImportModuleDynamicallyCallback is called when we * HostImportModuleDynamicallyCallback is called when we
* require the embedder to load a module. This is used as part of the dynamic * require the embedder to load a module. This is used as part of the dynamic
@ -352,11 +351,11 @@ using JavaScriptCompileHintsMagicEnabledCallback =
* *
* The specifier is the name of the module that should be imported. * The specifier is the name of the module that should be imported.
* *
* The import_assertions are import assertions for this request in the form: * The import_attributes are import attributes for this request in the form:
* [key1, value1, key2, value2, ...] where the keys and values are of type * [key1, value1, key2, value2, ...] where the keys and values are of type
* v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and * v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and
* returned from ModuleRequest::GetImportAssertions(), this array does not * returned from ModuleRequest::GetImportAssertions(), this array does not
* contain the source Locations of the assertions. * contain the source Locations of the attributes.
* *
* The embedder must compile, instantiate, evaluate the Module, and * The embedder must compile, instantiate, evaluate the Module, and
* obtain its namespace object. * obtain its namespace object.
@ -368,15 +367,10 @@ using JavaScriptCompileHintsMagicEnabledCallback =
* fails (e.g. due to stack overflow), the embedder must propagate * fails (e.g. due to stack overflow), the embedder must propagate
* that exception by returning an empty MaybeLocal. * that exception by returning an empty MaybeLocal.
*/ */
using HostImportModuleDynamicallyWithImportAssertionsCallback =
MaybeLocal<Promise> (*)(Local<Context> context,
Local<ScriptOrModule> referrer,
Local<String> specifier,
Local<FixedArray> import_assertions);
using HostImportModuleDynamicallyCallback = MaybeLocal<Promise> (*)( using HostImportModuleDynamicallyCallback = MaybeLocal<Promise> (*)(
Local<Context> context, Local<Data> host_defined_options, Local<Context> context, Local<Data> host_defined_options,
Local<Value> resource_name, Local<String> specifier, Local<Value> resource_name, Local<String> specifier,
Local<FixedArray> import_assertions); Local<FixedArray> import_attributes);
/** /**
* Callback for requesting a compile hint for a function from the embedder. The * Callback for requesting a compile hint for a function from the embedder. The

View File

@ -459,12 +459,12 @@ void* Context::GetAlignedPointerFromEmbedderData(int index) {
template <class T> template <class T>
MaybeLocal<T> Context::GetDataFromSnapshotOnce(size_t index) { MaybeLocal<T> Context::GetDataFromSnapshotOnce(size_t index) {
auto slot = GetDataFromSnapshotOnce(index); if (auto slot = GetDataFromSnapshotOnce(index); slot) {
if (slot) {
internal::PerformCastCheck( internal::PerformCastCheck(
internal::ValueHelper::SlotAsValue<T, false>(slot)); internal::ValueHelper::SlotAsValue<T, false>(slot));
return Local<T>::FromSlot(slot);
} }
return Local<T>::FromSlot(slot); return {};
} }
Context* Context::Cast(v8::Data* data) { Context* Context::Cast(v8::Data* data) {

View File

@ -27,6 +27,7 @@ class Context;
class DataView; class DataView;
class Data; class Data;
class Date; class Date;
class DictionaryTemplate;
class Extension; class Extension;
class External; class External;
class FixedArray; class FixedArray;

View File

@ -475,7 +475,8 @@ Local<Value> ReturnValue<T>::Get() const {
#endif // V8_STATIC_ROOTS_BOOL #endif // V8_STATIC_ROOTS_BOOL
return Undefined(GetIsolate()); return Undefined(GetIsolate());
} }
return Local<Value>::New(GetIsolate(), reinterpret_cast<Value*>(value_)); return Local<Value>::New(GetIsolate(),
internal::ValueHelper::SlotAsValue<Value>(value_));
} }
template <typename T> template <typename T>

View File

@ -616,8 +616,6 @@ constexpr bool kAllCodeObjectsLiveInTrustedSpace =
kRuntimeGeneratedCodeObjectsLiveInTrustedSpace && kRuntimeGeneratedCodeObjectsLiveInTrustedSpace &&
kBuiltinCodeObjectsLiveInTrustedSpace; kBuiltinCodeObjectsLiveInTrustedSpace;
constexpr bool kInterpreterDataObjectsLiveInTrustedSpace = false;
// {obj} must be the raw tagged pointer representation of a HeapObject // {obj} must be the raw tagged pointer representation of a HeapObject
// that's guaranteed to never be in ReadOnlySpace. // that's guaranteed to never be in ReadOnlySpace.
V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj); V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
@ -781,8 +779,6 @@ class Internals {
static const int kNodeStateMask = 0x3; static const int kNodeStateMask = 0x3;
static const int kNodeStateIsWeakValue = 2; static const int kNodeStateIsWeakValue = 2;
static const int kTracedNodeClassIdOffset = kApiSystemPointerSize;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83; static const int kOddballType = 0x83;
static const int kForeignType = 0xcc; static const int kForeignType = 0xcc;

View File

@ -1579,19 +1579,14 @@ class V8_EXPORT Isolate {
void SetWasmLoadSourceMapCallback(WasmLoadSourceMapCallback callback); void SetWasmLoadSourceMapCallback(WasmLoadSourceMapCallback callback);
/**
* Register callback to control whether Wasm GC is enabled.
* The callback overwrites the value of the flag.
* If the callback returns true, it will also enable Wasm stringrefs.
*/
void SetWasmGCEnabledCallback(WasmGCEnabledCallback callback);
void SetWasmImportedStringsEnabledCallback( void SetWasmImportedStringsEnabledCallback(
WasmImportedStringsEnabledCallback callback); WasmImportedStringsEnabledCallback callback);
void SetSharedArrayBufferConstructorEnabledCallback( void SetSharedArrayBufferConstructorEnabledCallback(
SharedArrayBufferConstructorEnabledCallback callback); SharedArrayBufferConstructorEnabledCallback callback);
void SetWasmJSPIEnabledCallback(WasmJSPIEnabledCallback callback);
/** /**
* Register callback to control whether compile hints magic comments are * Register callback to control whether compile hints magic comments are
* enabled. * enabled.
@ -1751,12 +1746,12 @@ uint32_t Isolate::GetNumberOfDataSlots() {
template <class T> template <class T>
MaybeLocal<T> Isolate::GetDataFromSnapshotOnce(size_t index) { MaybeLocal<T> Isolate::GetDataFromSnapshotOnce(size_t index) {
auto slot = GetDataFromSnapshotOnce(index); if (auto slot = GetDataFromSnapshotOnce(index); slot) {
if (slot) {
internal::PerformCastCheck( internal::PerformCastCheck(
internal::ValueHelper::SlotAsValue<T, false>(slot)); internal::ValueHelper::SlotAsValue<T, false>(slot));
return Local<T>::FromSlot(slot);
} }
return Local<T>::FromSlot(slot); return {};
} }
} // namespace v8 } // namespace v8

View File

@ -62,6 +62,7 @@ class ReturnValue;
class String; class String;
template <class F> template <class F>
class Traced; class Traced;
class TypecheckWitness;
class Utils; class Utils;
namespace debug { namespace debug {
@ -405,6 +406,8 @@ class V8_TRIVIAL_ABI Local : public LocalBase<T>,
} }
#ifdef V8_ENABLE_DIRECT_LOCAL #ifdef V8_ENABLE_DIRECT_LOCAL
friend class TypecheckWitness;
V8_INLINE static Local<T> FromAddress(internal::Address ptr) { V8_INLINE static Local<T> FromAddress(internal::Address ptr) {
return Local<T>(LocalBase<T>(ptr)); return Local<T>(LocalBase<T>(ptr));
} }

View File

@ -241,7 +241,7 @@ class NonCopyablePersistentTraits {
* This will clone the contents of storage cell, but not any of the flags, etc. * This will clone the contents of storage cell, but not any of the flags, etc.
*/ */
template <class T> template <class T>
struct CopyablePersistentTraits { struct V8_DEPRECATED("Use v8::Global instead") CopyablePersistentTraits {
using CopyablePersistent = Persistent<T, CopyablePersistentTraits<T>>; using CopyablePersistent = Persistent<T, CopyablePersistentTraits<T>>;
static const bool kResetInDestructor = true; static const bool kResetInDestructor = true;
template <class S, class M> template <class S, class M>

View File

@ -136,19 +136,24 @@ class V8_EXPORT ModuleRequest : public Data {
int GetSourceOffset() const; int GetSourceOffset() const;
/** /**
* Contains the import assertions for this request in the form: * Contains the import attributes for this request in the form:
* [key1, value1, source_offset1, key2, value2, source_offset2, ...]. * [key1, value1, source_offset1, key2, value2, source_offset2, ...].
* The keys and values are of type v8::String, and the source offsets are of * The keys and values are of type v8::String, and the source offsets are of
* type Int32. Use Module::SourceOffsetToLocation to convert the source * type Int32. Use Module::SourceOffsetToLocation to convert the source
* offsets to Locations with line/column numbers. * offsets to Locations with line/column numbers.
* *
* All assertions present in the module request will be supplied in this * All attributes present in the module request will be supplied in this
* list, regardless of whether they are supported by the host. Per * list, regardless of whether they are supported by the host. Per
* https://tc39.es/proposal-import-attributes/#sec-hostgetsupportedimportattributes, * https://tc39.es/proposal-import-attributes/#sec-hostgetsupportedimportattributes,
* hosts are expected to throw for assertions that they do not support (as * hosts are expected to throw for attributes that they do not support (as
* opposed to, for example, ignoring them). * opposed to, for example, ignoring them).
*/ */
Local<FixedArray> GetImportAssertions() const; Local<FixedArray> GetImportAttributes() const;
V8_DEPRECATE_SOON("Use GetImportAttributes instead")
Local<FixedArray> GetImportAssertions() const {
return GetImportAttributes();
}
V8_INLINE static ModuleRequest* Cast(Data* data); V8_INLINE static ModuleRequest* Cast(Data* data);

View File

@ -14,6 +14,10 @@ namespace v8 {
class Object; class Object;
namespace internal {
class SnapshotCreatorImpl;
} // namespace internal
class V8_EXPORT StartupData { class V8_EXPORT StartupData {
public: public:
/** /**
@ -206,7 +210,8 @@ class V8_EXPORT SnapshotCreator {
size_t AddData(Local<Context> context, internal::Address object); size_t AddData(Local<Context> context, internal::Address object);
size_t AddData(internal::Address object); size_t AddData(internal::Address object);
void* data_; internal::SnapshotCreatorImpl* impl_;
friend class internal::SnapshotCreatorImpl;
}; };
template <class T> template <class T>

View File

@ -5,6 +5,9 @@
#ifndef INCLUDE_V8_TEMPLATE_H_ #ifndef INCLUDE_V8_TEMPLATE_H_
#define INCLUDE_V8_TEMPLATE_H_ #define INCLUDE_V8_TEMPLATE_H_
#include <cstddef>
#include <string_view>
#include "v8-data.h" // NOLINT(build/include_directory) #include "v8-data.h" // NOLINT(build/include_directory)
#include "v8-function-callback.h" // NOLINT(build/include_directory) #include "v8-function-callback.h" // NOLINT(build/include_directory)
#include "v8-local-handle.h" // NOLINT(build/include_directory) #include "v8-local-handle.h" // NOLINT(build/include_directory)
@ -778,7 +781,11 @@ class V8_EXPORT ObjectTemplate : public Template {
Isolate* isolate, Isolate* isolate,
Local<FunctionTemplate> constructor = Local<FunctionTemplate>()); Local<FunctionTemplate> constructor = Local<FunctionTemplate>());
/** Creates a new instance of this template.*/ /**
* Creates a new instance of this template.
*
* \param context The context in which the instance is created.
*/
V8_WARN_UNUSED_RESULT MaybeLocal<Object> NewInstance(Local<Context> context); V8_WARN_UNUSED_RESULT MaybeLocal<Object> NewInstance(Local<Context> context);
/** /**
@ -950,6 +957,41 @@ class V8_EXPORT ObjectTemplate : public Template {
friend class FunctionTemplate; friend class FunctionTemplate;
}; };
/**
* A template to create dictionary objects at runtime.
*/
class V8_EXPORT DictionaryTemplate final {
public:
/** Creates a new template. Also declares data properties that can be passed
* on instantiation of the template. Properties can only be declared on
* construction and are then immutable. The values are passed on creating the
* object via `NewInstance()`.
*
* \param names the keys that can be passed on instantiation.
*/
static Local<DictionaryTemplate> New(
Isolate* isolate, MemorySpan<const std::string_view> names);
/**
* Creates a new instance of this template.
*
* \param context The context used to create the dictionary object.
* \param property_values Values of properties that were declared using
* `DeclareDataProperties()`. The span only passes values and expectes the
* order to match the declaration. Non-existent properties are signaled via
* empty `MaybeLocal`s.
*/
V8_WARN_UNUSED_RESULT Local<Object> NewInstance(
Local<Context> context, MemorySpan<MaybeLocal<Value>> property_values);
V8_INLINE static DictionaryTemplate* Cast(Data* data);
private:
static void CheckCast(Data* that);
DictionaryTemplate();
};
/** /**
* A Signature specifies which receiver is valid for a function. * A Signature specifies which receiver is valid for a function.
* *
@ -995,6 +1037,13 @@ ObjectTemplate* ObjectTemplate::Cast(Data* data) {
return reinterpret_cast<ObjectTemplate*>(data); return reinterpret_cast<ObjectTemplate*>(data);
} }
DictionaryTemplate* DictionaryTemplate::Cast(Data* data) {
#ifdef V8_ENABLE_CHECKS
CheckCast(data);
#endif
return reinterpret_cast<DictionaryTemplate*>(data);
}
Signature* Signature::Cast(Data* data) { Signature* Signature::Cast(Data* data) {
#ifdef V8_ENABLE_CHECKS #ifdef V8_ENABLE_CHECKS
CheckCast(data); CheckCast(data);

View File

@ -77,19 +77,6 @@ class TracedReferenceBase : public api_internal::IndirectHandleBase {
return this->GetSlotThreadSafe() == nullptr; return this->GetSlotThreadSafe() == nullptr;
} }
/**
* Assigns a wrapper class ID to the handle.
*/
V8_DEPRECATED("Embedders need to maintain state for references themselves.")
V8_INLINE void SetWrapperClassId(uint16_t class_id);
/**
* Returns the class ID previously assigned to this handle or 0 if no class ID
* was previously assigned.
*/
V8_DEPRECATED("Embedders need to maintain state for references themselves.")
V8_INLINE uint16_t WrapperClassId() const;
protected: protected:
V8_INLINE TracedReferenceBase() = default; V8_INLINE TracedReferenceBase() = default;
@ -440,22 +427,6 @@ TracedReference<T>& TracedReference<T>::operator=(const TracedReference& rhs) {
return *this; return *this;
} }
void TracedReferenceBase::SetWrapperClassId(uint16_t class_id) {
using I = internal::Internals;
if (IsEmpty()) return;
uint8_t* addr =
reinterpret_cast<uint8_t*>(slot()) + I::kTracedNodeClassIdOffset;
*reinterpret_cast<uint16_t*>(addr) = class_id;
}
uint16_t TracedReferenceBase::WrapperClassId() const {
using I = internal::Internals;
if (IsEmpty()) return 0;
uint8_t* addr =
reinterpret_cast<uint8_t*>(slot()) + I::kTracedNodeClassIdOffset;
return *reinterpret_cast<uint16_t*>(addr);
}
} // namespace v8 } // namespace v8
#endif // INCLUDE_V8_TRACED_HANDLE_H_ #endif // INCLUDE_V8_TRACED_HANDLE_H_

View File

@ -240,8 +240,9 @@ class PersistentValueMapBase {
: value_(other.value_) { } : value_(other.value_) { }
Local<V> NewLocal(Isolate* isolate) const { Local<V> NewLocal(Isolate* isolate) const {
return Local<V>::New( return Local<V>::New(isolate,
isolate, internal::ValueHelper::SlotAsValue<V>(FromVal(value_))); internal::ValueHelper::SlotAsValue<V>(
reinterpret_cast<internal::Address*>(value_)));
} }
bool IsEmpty() const { bool IsEmpty() const {
return value_ == kPersistentContainerNotFound; return value_ == kPersistentContainerNotFound;
@ -298,7 +299,8 @@ class PersistentValueMapBase {
typename Traits::Impl* impl() { return &impl_; } typename Traits::Impl* impl() { return &impl_; }
static V* FromVal(PersistentContainerValue v) { static V* FromVal(PersistentContainerValue v) {
return reinterpret_cast<V*>(v); return internal::ValueHelper::SlotAsValue<V>(
reinterpret_cast<internal::Address*>(v));
} }
static PersistentContainerValue ClearAndLeak(Global<V>* persistent) { static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
@ -318,7 +320,7 @@ class PersistentValueMapBase {
*/ */
static Global<V> Release(PersistentContainerValue v) { static Global<V> Release(PersistentContainerValue v) {
Global<V> p; Global<V> p;
p.slot() = reinterpret_cast<internal::Address*>(FromVal(v)); p.slot() = reinterpret_cast<internal::Address*>(v);
if (Traits::kCallbackType != kNotWeak && p.IsWeak()) { if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
Traits::DisposeCallbackData( Traits::DisposeCallbackData(
p.template ClearWeak<typename Traits::WeakCallbackDataType>()); p.template ClearWeak<typename Traits::WeakCallbackDataType>());
@ -328,8 +330,8 @@ class PersistentValueMapBase {
void RemoveWeak(const K& key) { void RemoveWeak(const K& key) {
Global<V> p; Global<V> p;
p.slot() = reinterpret_cast<internal::Address*>( p.slot() =
FromVal(Traits::Remove(&impl_, key))); reinterpret_cast<internal::Address*>(Traits::Remove(&impl_, key));
p.Reset(); p.Reset();
} }
@ -345,8 +347,7 @@ class PersistentValueMapBase {
PersistentContainerValue value) { PersistentContainerValue value) {
bool hasValue = value != kPersistentContainerNotFound; bool hasValue = value != kPersistentContainerNotFound;
if (hasValue) { if (hasValue) {
returnValue->SetInternal( returnValue->SetInternal(*reinterpret_cast<internal::Address*>(value));
*reinterpret_cast<internal::Address*>(FromVal(value)));
} }
return hasValue; return hasValue;
} }
@ -620,7 +621,7 @@ class V8_DEPRECATE_SOON("Use std::vector<Global<V>>.") PersistentValueVector {
*/ */
Local<V> Get(size_t index) const { Local<V> Get(size_t index) const {
return Local<V>::New(isolate_, internal::ValueHelper::SlotAsValue<V>( return Local<V>::New(isolate_, internal::ValueHelper::SlotAsValue<V>(
FromVal(Traits::Get(&impl_, index)))); Traits::Get(&impl_, index)));
} }
/** /**
@ -630,8 +631,7 @@ class V8_DEPRECATE_SOON("Use std::vector<Global<V>>.") PersistentValueVector {
size_t length = Traits::Size(&impl_); size_t length = Traits::Size(&impl_);
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
Global<V> p; Global<V> p;
p.slot() = p.slot() = reinterpret_cast<internal::Address>(Traits::Get(&impl_, i));
reinterpret_cast<internal::Address>(FromVal(Traits::Get(&impl_, i)));
} }
Traits::Clear(&impl_); Traits::Clear(&impl_);
} }
@ -652,7 +652,8 @@ class V8_DEPRECATE_SOON("Use std::vector<Global<V>>.") PersistentValueVector {
} }
static V* FromVal(PersistentContainerValue v) { static V* FromVal(PersistentContainerValue v) {
return reinterpret_cast<V*>(v); return internal::ValueHelper::SlotAsValue<V>(
reinterpret_cast<internal::Address*>(v));
} }
Isolate* isolate_; Isolate* isolate_;

View File

@ -9,9 +9,9 @@
// NOTE these macros are used by some of the tool scripts and the build // 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. // system so their names cannot be changed without changing the scripts.
#define V8_MAJOR_VERSION 12 #define V8_MAJOR_VERSION 12
#define V8_MINOR_VERSION 2 #define V8_MINOR_VERSION 3
#define V8_BUILD_NUMBER 281 #define V8_BUILD_NUMBER 219
#define V8_PATCH_LEVEL 27 #define V8_PATCH_LEVEL 16
// Use 1 for candidates and 0 otherwise. // Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.) // (Boolean macro values are not supported by all preprocessors.)

View File

@ -376,7 +376,6 @@
}, },
'tests': [ 'tests': [
{'name': 'v8testing', 'variant': 'default'}, {'name': 'v8testing', 'variant': 'default'},
{'name': 'v8testing', 'variant': 'future'},
], ],
}, },
'v8_linux64_coverage_rel': { 'v8_linux64_coverage_rel': {
@ -1435,7 +1434,6 @@
}, },
'tests': [ 'tests': [
{'name': 'v8testing', 'variant': 'default'}, {'name': 'v8testing', 'variant': 'default'},
{'name': 'v8testing', 'variant': 'future'},
], ],
}, },
'V8 Linux64 - custom snapshot - debug': { 'V8 Linux64 - custom snapshot - debug': {

View File

@ -48,11 +48,11 @@
* For a more sophisticated shell, consider using the debug shell D8. * For a more sophisticated shell, consider using the debug shell D8.
*/ */
v8::Global<v8::Context> CreateShellContext(v8::Isolate* isolate);
v8::Local<v8::Context> CreateShellContext(v8::Isolate* isolate); void RunShell(v8::Isolate* isolate, const v8::Global<v8::Context>& context,
void RunShell(v8::Local<v8::Context> context, v8::Platform* platform); v8::Platform* platform);
int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc, int RunMain(v8::Isolate* isolate, const v8::Global<v8::Context>& context,
char* argv[]); v8::Platform* platform, int argc, char* argv[]);
bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source, bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source,
v8::Local<v8::Value> name, bool print_result, v8::Local<v8::Value> name, bool print_result,
bool report_exceptions); bool report_exceptions);
@ -64,10 +64,8 @@ void Version(const v8::FunctionCallbackInfo<v8::Value>& info);
v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name); v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name);
void ReportException(v8::Isolate* isolate, v8::TryCatch* handler); void ReportException(v8::Isolate* isolate, v8::TryCatch* handler);
static bool run_shell; static bool run_shell;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
v8::V8::InitializeICUDefaultLocation(argv[0]); v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]); v8::V8::InitializeExternalStartupData(argv[0]);
@ -83,15 +81,13 @@ int main(int argc, char* argv[]) {
int result; int result;
{ {
v8::Isolate::Scope isolate_scope(isolate); v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate); v8::Global<v8::Context> context = CreateShellContext(isolate);
v8::Local<v8::Context> context = CreateShellContext(isolate);
if (context.IsEmpty()) { if (context.IsEmpty()) {
fprintf(stderr, "Error creating context\n"); fprintf(stderr, "Error creating context\n");
return 1; return 1;
} }
v8::Context::Scope context_scope(context); result = RunMain(isolate, context, platform.get(), argc, argv);
result = RunMain(isolate, platform.get(), argc, argv); if (run_shell) RunShell(isolate, context, platform.get());
if (run_shell) RunShell(context, platform.get());
} }
isolate->Dispose(); isolate->Dispose();
v8::V8::Dispose(); v8::V8::Dispose();
@ -100,16 +96,15 @@ int main(int argc, char* argv[]) {
return result; return result;
} }
// Extracts a C string from a V8 Utf8Value. // Extracts a C string from a V8 Utf8Value.
const char* ToCString(const v8::String::Utf8Value& value) { const char* ToCString(const v8::String::Utf8Value& value) {
return *value ? *value : "<string conversion failed>"; return *value ? *value : "<string conversion failed>";
} }
// Creates a new execution environment containing the built-in // Creates a new execution environment containing the built-in
// functions. // functions.
v8::Local<v8::Context> CreateShellContext(v8::Isolate* isolate) { v8::Global<v8::Context> CreateShellContext(v8::Isolate* isolate) {
v8::HandleScope handle_scope(isolate);
// Create a template for the global object. // Create a template for the global object.
v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
// Bind the global 'print' function to the C++ Print callback. // Bind the global 'print' function to the C++ Print callback.
@ -122,10 +117,11 @@ v8::Local<v8::Context> CreateShellContext(v8::Isolate* isolate) {
global->Set(isolate, "quit", v8::FunctionTemplate::New(isolate, Quit)); global->Set(isolate, "quit", v8::FunctionTemplate::New(isolate, Quit));
// Bind the 'version' function // Bind the 'version' function
global->Set(isolate, "version", v8::FunctionTemplate::New(isolate, Version)); global->Set(isolate, "version", v8::FunctionTemplate::New(isolate, Version));
return v8::Context::New(isolate, NULL, global); // Return the context.
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
return v8::Global<v8::Context>(isolate, context);
} }
// The callback that is invoked by v8 whenever the JavaScript 'print' // The callback that is invoked by v8 whenever the JavaScript 'print'
// function is called. Prints its arguments on stdout separated by // function is called. Prints its arguments on stdout separated by
// spaces and ending with a newline. // spaces and ending with a newline.
@ -155,7 +151,7 @@ void Read(const v8::FunctionCallbackInfo<v8::Value>& info) {
return; return;
} }
v8::String::Utf8Value file(info.GetIsolate(), info[0]); v8::String::Utf8Value file(info.GetIsolate(), info[0]);
if (*file == NULL) { if (*file == nullptr) {
info.GetIsolate()->ThrowError("Error loading file"); info.GetIsolate()->ThrowError("Error loading file");
return; return;
} }
@ -175,7 +171,7 @@ void Load(const v8::FunctionCallbackInfo<v8::Value>& info) {
for (int i = 0; i < info.Length(); i++) { for (int i = 0; i < info.Length(); i++) {
v8::HandleScope handle_scope(info.GetIsolate()); v8::HandleScope handle_scope(info.GetIsolate());
v8::String::Utf8Value file(info.GetIsolate(), info[i]); v8::String::Utf8Value file(info.GetIsolate(), info[i]);
if (*file == NULL) { if (*file == nullptr) {
info.GetIsolate()->ThrowError("Error loading file"); info.GetIsolate()->ThrowError("Error loading file");
return; return;
} }
@ -203,6 +199,8 @@ void Quit(const v8::FunctionCallbackInfo<v8::Value>& info) {
exit(exit_code); exit(exit_code);
} }
// The callback that is invoked by v8 whenever the JavaScript 'version'
// function is called. Returns a string containing the current V8 version.
void Version(const v8::FunctionCallbackInfo<v8::Value>& info) { void Version(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set( info.GetReturnValue().Set(
v8::String::NewFromUtf8(info.GetIsolate(), v8::V8::GetVersion()) v8::String::NewFromUtf8(info.GetIsolate(), v8::V8::GetVersion())
@ -212,7 +210,7 @@ void Version(const v8::FunctionCallbackInfo<v8::Value>& info) {
// Reads a file into a v8 string. // Reads a file into a v8 string.
v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name) { v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name) {
FILE* file = fopen(name, "rb"); FILE* file = fopen(name, "rb");
if (file == NULL) return v8::MaybeLocal<v8::String>(); if (file == nullptr) return {};
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
size_t size = ftell(file); size_t size = ftell(file);
@ -224,7 +222,7 @@ v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name) {
i += fread(&chars[i], 1, size - i, file); i += fread(&chars[i], 1, size - i, file);
if (ferror(file)) { if (ferror(file)) {
fclose(file); fclose(file);
return v8::MaybeLocal<v8::String>(); return {};
} }
} }
fclose(file); fclose(file);
@ -234,10 +232,9 @@ v8::MaybeLocal<v8::String> ReadFile(v8::Isolate* isolate, const char* name) {
return result; return result;
} }
// Process remaining command line arguments and execute files // Process remaining command line arguments and execute files
int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc, int RunMain(v8::Isolate* isolate, const v8::Global<v8::Context>& context,
char* argv[]) { v8::Platform* platform, int argc, char* argv[]) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
const char* str = argv[i]; const char* str = argv[i];
if (strcmp(str, "--shell") == 0) { if (strcmp(str, "--shell") == 0) {
@ -251,25 +248,41 @@ int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc,
"Warning: unknown flag %s.\nTry --help for options\n", str); "Warning: unknown flag %s.\nTry --help for options\n", str);
} else if (strcmp(str, "-e") == 0 && i + 1 < argc) { } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
// Execute argument given to -e option directly. // Execute argument given to -e option directly.
v8::Local<v8::String> file_name = bool success;
v8::String::NewFromUtf8Literal(isolate, "unnamed"); {
v8::Local<v8::String> source; // Enter the execution environment before evaluating any code.
if (!v8::String::NewFromUtf8(isolate, argv[++i]).ToLocal(&source)) { v8::HandleScope handle_scope(isolate);
return 1; v8::Context::Scope context_scope(context.Get(isolate));
v8::Local<v8::String> file_name =
v8::String::NewFromUtf8Literal(isolate, "unnamed");
v8::Local<v8::String> source;
if (!v8::String::NewFromUtf8(isolate, argv[++i]).ToLocal(&source)) {
return 1;
}
success = ExecuteString(isolate, source, file_name, false, true);
} }
bool success = ExecuteString(isolate, source, file_name, false, true); // It is important not to pump the message loop when there are v8::Local
// handles on the stack, as this may trigger a stackless GC.
while (v8::platform::PumpMessageLoop(platform, isolate)) continue; while (v8::platform::PumpMessageLoop(platform, isolate)) continue;
if (!success) return 1; if (!success) return 1;
} else { } else {
// Use all other arguments as names of files to load and run. // Use all other arguments as names of files to load and run.
v8::Local<v8::String> file_name = bool success;
v8::String::NewFromUtf8(isolate, str).ToLocalChecked(); {
v8::Local<v8::String> source; // Enter the execution environment before evaluating any code.
if (!ReadFile(isolate, str).ToLocal(&source)) { v8::HandleScope handle_scope(isolate);
fprintf(stderr, "Error reading '%s'\n", str); v8::Context::Scope context_scope(context.Get(isolate));
continue; v8::Local<v8::String> file_name =
v8::String::NewFromUtf8(isolate, str).ToLocalChecked();
v8::Local<v8::String> source;
if (!ReadFile(isolate, str).ToLocal(&source)) {
fprintf(stderr, "Error reading '%s'\n", str);
continue;
}
success = ExecuteString(isolate, source, file_name, false, true);
} }
bool success = ExecuteString(isolate, source, file_name, false, true); // It is important not to pump the message loop when there are v8::Local
// handles on the stack, as this may trigger a stackless GC.
while (v8::platform::PumpMessageLoop(platform, isolate)) continue; while (v8::platform::PumpMessageLoop(platform, isolate)) continue;
if (!success) return 1; if (!success) return 1;
} }
@ -277,32 +290,33 @@ int RunMain(v8::Isolate* isolate, v8::Platform* platform, int argc,
return 0; return 0;
} }
// The read-eval-execute loop of the shell. // The read-eval-execute loop of the shell.
void RunShell(v8::Local<v8::Context> context, v8::Platform* platform) { void RunShell(v8::Isolate* isolate, const v8::Global<v8::Context>& context,
v8::Platform* platform) {
fprintf(stderr, "V8 version %s [sample shell]\n", v8::V8::GetVersion()); fprintf(stderr, "V8 version %s [sample shell]\n", v8::V8::GetVersion());
static const int kBufferSize = 256; static const int kBufferSize = 256;
// Enter the execution environment before evaluating any code.
v8::Context::Scope context_scope(context);
v8::Local<v8::String> name(
v8::String::NewFromUtf8Literal(context->GetIsolate(), "(shell)"));
while (true) { while (true) {
char buffer[kBufferSize]; char buffer[kBufferSize];
fprintf(stderr, "> "); fprintf(stderr, "> ");
char* str = fgets(buffer, kBufferSize, stdin); char* str = fgets(buffer, kBufferSize, stdin);
if (str == NULL) break; if (str == nullptr) break;
v8::HandleScope handle_scope(context->GetIsolate()); {
ExecuteString( // Enter the execution environment before evaluating any code.
context->GetIsolate(), v8::HandleScope handle_scope(isolate);
v8::String::NewFromUtf8(context->GetIsolate(), str).ToLocalChecked(), v8::Context::Scope context_scope(context.Get(isolate));
name, true, true); v8::Local<v8::String> name(
while (v8::platform::PumpMessageLoop(platform, context->GetIsolate())) v8::String::NewFromUtf8Literal(isolate, "(shell)"));
continue; ExecuteString(isolate,
v8::String::NewFromUtf8(isolate, str).ToLocalChecked(),
name, true, true);
}
// It is important not to pump the message loop when there are v8::Local
// handles on the stack, as this may trigger a stackless GC.
while (v8::platform::PumpMessageLoop(platform, isolate)) continue;
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
// Executes a string within the current v8 context. // Executes a string within the current v8 context.
bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source, bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source,
v8::Local<v8::Value> name, bool print_result, v8::Local<v8::Value> name, bool print_result,
@ -339,7 +353,6 @@ bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source,
} }
} }
void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) { void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
v8::String::Utf8Value exception(isolate, try_catch->Exception()); v8::String::Utf8Value exception(isolate, try_catch->Exception());

7
deps/v8/src/DEPS vendored
View File

@ -39,6 +39,7 @@ include_rules = [
# TODO(v8:10496): Don't expose memory chunk outside of heap/. # TODO(v8:10496): Don't expose memory chunk outside of heap/.
"+src/heap/memory-chunk.h", "+src/heap/memory-chunk.h",
"+src/heap/memory-chunk-inl.h", "+src/heap/memory-chunk-inl.h",
"+src/heap/memory-chunk-header.h",
"+src/heap/paged-spaces-inl.h", "+src/heap/paged-spaces-inl.h",
"+src/heap/parked-scope-inl.h", "+src/heap/parked-scope-inl.h",
"+src/heap/parked-scope.h", "+src/heap/parked-scope.h",
@ -107,6 +108,12 @@ specific_include_rules = {
"external-pointer-table\.cc": [ "external-pointer-table\.cc": [
"+src/heap/read-only-spaces.h", "+src/heap/read-only-spaces.h",
], ],
# keep the includes to a minimum since this header will be included via write barriers.
"memory-chunk-header\.h": [
"-src",
"+src/base/build_config.h",
"+src/flags/flags.h",
],
"script\.h": [ "script\.h": [
"+src/heap/factory.h", "+src/heap/factory.h",
"+src/heap/factory-base.h", "+src/heap/factory-base.h",

View File

@ -179,7 +179,7 @@ class V8_NODISCARD CallDepthScope {
CallDepthScope(i::Isolate* isolate, Local<Context> context) CallDepthScope(i::Isolate* isolate, Local<Context> context)
: isolate_(isolate), saved_context_(isolate->context(), isolate_) { : isolate_(isolate), saved_context_(isolate->context(), isolate_) {
isolate_->thread_local_top()->IncrementCallDepth<do_callback>(this); isolate_->thread_local_top()->IncrementCallDepth<do_callback>(this);
i::Tagged<i::NativeContext> env = *Utils::OpenHandle(*context); i::Tagged<i::NativeContext> env = *Utils::OpenDirectHandle(*context);
isolate->set_context(env); isolate->set_context(env);
if (do_callback) isolate_->FireBeforeCallEnteredCallback(); if (do_callback) isolate_->FireBeforeCallEnteredCallback();
@ -304,7 +304,7 @@ bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
} }
i::DisallowGarbageCollection no_gc; i::DisallowGarbageCollection no_gc;
i::Tagged<i::JSArray> obj = *Utils::OpenHandle(*src); i::Tagged<i::JSArray> obj = *Utils::OpenDirectHandle(*src);
if (i::Object::IterationHasObservableEffects(obj)) { if (i::Object::IterationHasObservableEffects(obj)) {
// The array has a custom iterator. // The array has a custom iterator.
return false; return false;

157
deps/v8/src/api/api.cc vendored
View File

@ -24,6 +24,7 @@
#include "include/v8-primitive-object.h" #include "include/v8-primitive-object.h"
#include "include/v8-profiler.h" #include "include/v8-profiler.h"
#include "include/v8-source-location.h" #include "include/v8-source-location.h"
#include "include/v8-template.h"
#include "include/v8-unwinder-state.h" #include "include/v8-unwinder-state.h"
#include "include/v8-util.h" #include "include/v8-util.h"
#include "include/v8-wasm.h" #include "include/v8-wasm.h"
@ -86,6 +87,7 @@
#include "src/objects/js-array-buffer-inl.h" #include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h" #include "src/objects/js-array-inl.h"
#include "src/objects/js-collection-inl.h" #include "src/objects/js-collection-inl.h"
#include "src/objects/js-objects.h"
#include "src/objects/js-promise-inl.h" #include "src/objects/js-promise-inl.h"
#include "src/objects/js-regexp-inl.h" #include "src/objects/js-regexp-inl.h"
#include "src/objects/js-weak-refs-inl.h" #include "src/objects/js-weak-refs-inl.h"
@ -101,6 +103,7 @@
#include "src/objects/shared-function-info.h" #include "src/objects/shared-function-info.h"
#include "src/objects/slots.h" #include "src/objects/slots.h"
#include "src/objects/smi.h" #include "src/objects/smi.h"
#include "src/objects/string.h"
#include "src/objects/synthetic-module-inl.h" #include "src/objects/synthetic-module-inl.h"
#include "src/objects/templates.h" #include "src/objects/templates.h"
#include "src/objects/value-serializer.h" #include "src/objects/value-serializer.h"
@ -537,7 +540,7 @@ SnapshotCreator::SnapshotCreator(Isolate* v8_isolate,
const intptr_t* external_references, const intptr_t* external_references,
const StartupData* existing_snapshot, const StartupData* existing_snapshot,
bool owns_isolate) bool owns_isolate)
: data_(new i::SnapshotCreatorImpl( : impl_(new i::SnapshotCreatorImpl(
reinterpret_cast<i::Isolate*>(v8_isolate), external_references, reinterpret_cast<i::Isolate*>(v8_isolate), external_references,
existing_snapshot, owns_isolate)) {} existing_snapshot, owns_isolate)) {}
@ -546,50 +549,43 @@ SnapshotCreator::SnapshotCreator(const intptr_t* external_references,
: SnapshotCreator(nullptr, external_references, existing_snapshot) {} : SnapshotCreator(nullptr, external_references, existing_snapshot) {}
SnapshotCreator::SnapshotCreator(const v8::Isolate::CreateParams& params) SnapshotCreator::SnapshotCreator(const v8::Isolate::CreateParams& params)
: data_(new i::SnapshotCreatorImpl(params)) {} : impl_(new i::SnapshotCreatorImpl(params)) {}
SnapshotCreator::SnapshotCreator(v8::Isolate* isolate, SnapshotCreator::SnapshotCreator(v8::Isolate* isolate,
const v8::Isolate::CreateParams& params) const v8::Isolate::CreateParams& params)
: data_(new i::SnapshotCreatorImpl(reinterpret_cast<i::Isolate*>(isolate), : impl_(new i::SnapshotCreatorImpl(reinterpret_cast<i::Isolate*>(isolate),
params)) {} params)) {}
SnapshotCreator::~SnapshotCreator() { SnapshotCreator::~SnapshotCreator() {
DCHECK_NOT_NULL(data_); DCHECK_NOT_NULL(impl_);
auto impl = static_cast<i::SnapshotCreatorImpl*>(data_); delete impl_;
delete impl;
} }
Isolate* SnapshotCreator::GetIsolate() { Isolate* SnapshotCreator::GetIsolate() {
auto impl = static_cast<i::SnapshotCreatorImpl*>(data_); return reinterpret_cast<v8::Isolate*>(impl_->isolate());
return reinterpret_cast<v8::Isolate*>(impl->isolate());
} }
void SnapshotCreator::SetDefaultContext( void SnapshotCreator::SetDefaultContext(
Local<Context> context, SerializeInternalFieldsCallback callback) { Local<Context> context, SerializeInternalFieldsCallback callback) {
auto impl = static_cast<i::SnapshotCreatorImpl*>(data_); impl_->SetDefaultContext(Utils::OpenHandle(*context), callback);
impl->SetDefaultContext(Utils::OpenHandle(*context), callback);
} }
size_t SnapshotCreator::AddContext(Local<Context> context, size_t SnapshotCreator::AddContext(Local<Context> context,
SerializeInternalFieldsCallback callback) { SerializeInternalFieldsCallback callback) {
auto impl = static_cast<i::SnapshotCreatorImpl*>(data_); return impl_->AddContext(Utils::OpenHandle(*context), callback);
return impl->AddContext(Utils::OpenHandle(*context), callback);
} }
size_t SnapshotCreator::AddData(i::Address object) { size_t SnapshotCreator::AddData(i::Address object) {
auto impl = static_cast<i::SnapshotCreatorImpl*>(data_); return impl_->AddData(object);
return impl->AddData(object);
} }
size_t SnapshotCreator::AddData(Local<Context> context, i::Address object) { size_t SnapshotCreator::AddData(Local<Context> context, i::Address object) {
auto impl = static_cast<i::SnapshotCreatorImpl*>(data_); return impl_->AddData(Utils::OpenHandle(*context), object);
return impl->AddData(Utils::OpenHandle(*context), object);
} }
StartupData SnapshotCreator::CreateBlob( StartupData SnapshotCreator::CreateBlob(
SnapshotCreator::FunctionCodeHandling function_code_handling) { SnapshotCreator::FunctionCodeHandling function_code_handling) {
auto impl = static_cast<i::SnapshotCreatorImpl*>(data_); return impl_->CreateBlob(function_code_handling);
return impl->CreateBlob(function_code_handling);
} }
bool StartupData::CanBeRehashed() const { bool StartupData::CanBeRehashed() const {
@ -1949,6 +1945,24 @@ void ObjectTemplate::SetCodeLike() {
self->set_code_like(true); self->set_code_like(true);
} }
Local<DictionaryTemplate> DictionaryTemplate::New(
Isolate* isolate, MemorySpan<const std::string_view> names) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
API_RCS_SCOPE(i_isolate, DictionaryTemplate, New);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
return Utils::ToLocal(i::DictionaryTemplateInfo::Create(i_isolate, names));
}
Local<Object> DictionaryTemplate::NewInstance(
Local<Context> context, MemorySpan<MaybeLocal<Value>> property_values) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
API_RCS_SCOPE(i_isolate, DictionaryTemplate, NewInstance);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
auto self = Utils::OpenDirectHandle(this);
return ToApiHandle<Object>(i::DictionaryTemplateInfo::NewInstance(
Utils::OpenHandle(*context), self, property_values));
}
// --- S c r i p t s --- // --- S c r i p t s ---
// Internally, UnboundScript and UnboundModuleScript are SharedFunctionInfos, // Internally, UnboundScript and UnboundModuleScript are SharedFunctionInfos,
@ -2294,11 +2308,11 @@ int ModuleRequest::GetSourceOffset() const {
return Utils::OpenDirectHandle(this)->position(); return Utils::OpenDirectHandle(this)->position();
} }
Local<FixedArray> ModuleRequest::GetImportAssertions() const { Local<FixedArray> ModuleRequest::GetImportAttributes() const {
auto self = Utils::OpenDirectHandle(this); auto self = Utils::OpenDirectHandle(this);
i::Isolate* i_isolate = self->GetIsolate(); i::Isolate* i_isolate = self->GetIsolate();
return ToApiHandle<FixedArray>( return ToApiHandle<FixedArray>(
i::direct_handle(self->import_assertions(), i_isolate), i_isolate); i::direct_handle(self->import_attributes(), i_isolate), i_isolate);
} }
Module::Status Module::GetStatus() const { Module::Status Module::GetStatus() const {
@ -3866,7 +3880,7 @@ bool Value::IsInt32() const {
} }
bool Value::IsUint32() const { bool Value::IsUint32() const {
auto obj = *Utils::OpenHandle(this); auto obj = *Utils::OpenDirectHandle(this);
if (i::IsSmi(obj)) return i::Smi::ToInt(obj) >= 0; if (i::IsSmi(obj)) return i::Smi::ToInt(obj) >= 0;
if (i::IsNumber(obj)) { if (i::IsNumber(obj)) {
double value = i::Object::Number(obj); double value = i::Object::Number(obj);
@ -4271,6 +4285,10 @@ void* v8::ArrayBuffer::Data() const {
return Utils::OpenDirectHandle(this)->backing_store(); return Utils::OpenDirectHandle(this)->backing_store();
} }
bool v8::ArrayBuffer::IsResizableByUserJavaScript() const {
return Utils::OpenDirectHandle(this)->is_resizable_by_js();
}
std::shared_ptr<v8::BackingStore> v8::SharedArrayBuffer::GetBackingStore() { std::shared_ptr<v8::BackingStore> v8::SharedArrayBuffer::GetBackingStore() {
auto self = Utils::OpenDirectHandle(this); auto self = Utils::OpenDirectHandle(this);
std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore(); std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore();
@ -4306,7 +4324,7 @@ void v8::TypedArray::CheckCast(Value* that) {
#define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype) \ #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype) \
void v8::Type##Array::CheckCast(Value* that) { \ void v8::Type##Array::CheckCast(Value* that) { \
auto obj = *Utils::OpenHandle(that); \ auto obj = *Utils::OpenDirectHandle(that); \
Utils::ApiCheck( \ Utils::ApiCheck( \
i::IsJSTypedArray(obj) && \ i::IsJSTypedArray(obj) && \
i::JSTypedArray::cast(obj)->type() == i::kExternal##Type##Array, \ i::JSTypedArray::cast(obj)->type() == i::kExternal##Type##Array, \
@ -5359,6 +5377,30 @@ bool v8::Object::IsUndetectable() const {
return i::IsUndetectable(*self); return i::IsUndetectable(*self);
} }
namespace {
#ifdef V8_ENABLE_DIRECT_LOCAL
// A newly allocated vector is required to convert from an array of direct
// locals to an array of indirect handles.
std::vector<i::Handle<i::Object>> PrepareArguments(int argc,
Local<Value> argv[]) {
std::vector<i::Handle<i::Object>> args(argc);
for (int i = 0; i < argc; ++i) {
args[i] = Utils::OpenHandle(*argv[i]);
}
return args;
}
#else // !V8_ENABLE_DIRECT_LOCAL
// A simple cast is used to convert from an array of indirect locals to an
// array of indirect handles. A MemorySpan object is returned, as no
// deallocation is necessary.
v8::MemorySpan<i::Handle<i::Object>> PrepareArguments(int argc,
Local<Value> argv[]) {
return {reinterpret_cast<i::Handle<i::Object>*>(argv),
static_cast<size_t>(argc)};
}
#endif // V8_ENABLE_DIRECT_LOCAL
} // namespace
MaybeLocal<Value> Object::CallAsFunction(Local<Context> context, MaybeLocal<Value> Object::CallAsFunction(Local<Context> context,
Local<Value> recv, int argc, Local<Value> recv, int argc,
Local<Value> argv[]) { Local<Value> argv[]) {
@ -5371,10 +5413,11 @@ MaybeLocal<Value> Object::CallAsFunction(Local<Context> context,
auto self = Utils::OpenHandle(this); auto self = Utils::OpenHandle(this);
auto recv_obj = Utils::OpenHandle(*recv); auto recv_obj = Utils::OpenHandle(*recv);
static_assert(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>)); static_assert(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); auto args = PrepareArguments(argc, argv);
Local<Value> result; Local<Value> result;
has_exception = !ToLocal<Value>( has_exception = !ToLocal<Value>(
i::Execution::Call(i_isolate, self, recv_obj, argc, args), &result); i::Execution::Call(i_isolate, self, recv_obj, argc, args.data()),
&result);
RETURN_ON_FAILED_EXECUTION(Value); RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result); RETURN_ESCAPED(result);
} }
@ -5390,10 +5433,10 @@ MaybeLocal<Value> Object::CallAsConstructor(Local<Context> context, int argc,
i_isolate); i_isolate);
auto self = Utils::OpenHandle(this); auto self = Utils::OpenHandle(this);
static_assert(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>)); static_assert(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); auto args = PrepareArguments(argc, argv);
Local<Value> result; Local<Value> result;
has_exception = !ToLocal<Value>( has_exception = !ToLocal<Value>(
i::Execution::New(i_isolate, self, self, argc, args), &result); i::Execution::New(i_isolate, self, self, argc, args.data()), &result);
RETURN_ON_FAILED_EXECUTION(Value); RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result); RETURN_ESCAPED(result);
} }
@ -5446,10 +5489,10 @@ MaybeLocal<Object> Function::NewInstanceWithSideEffectType(
} }
} }
} }
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); auto args = PrepareArguments(argc, argv);
Local<Object> result; Local<Object> result;
has_exception = !ToLocal<Object>( has_exception = !ToLocal<Object>(
i::Execution::New(i_isolate, self, self, argc, args), &result); i::Execution::New(i_isolate, self, self, argc, args.data()), &result);
RETURN_ON_FAILED_EXECUTION(Object); RETURN_ON_FAILED_EXECUTION(Object);
RETURN_ESCAPED(result); RETURN_ESCAPED(result);
} }
@ -5468,19 +5511,11 @@ MaybeLocal<v8::Value> Function::Call(Local<Context> context,
"Function to be called is a null pointer"); "Function to be called is a null pointer");
auto recv_obj = Utils::OpenHandle(*recv); auto recv_obj = Utils::OpenHandle(*recv);
static_assert(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>)); static_assert(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
auto args = PrepareArguments(argc, argv);
#ifdef V8_ENABLE_DIRECT_LOCAL
i::Handle<i::Object>* args = new i::Handle<i::Object>[argc];
for (int i = 0; i < argc; ++i) {
args[i] = Utils::OpenHandle(*argv[i]);
}
#else // !V8_ENABLE_DIRECT_LOCAL
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
#endif // V8_ENABLE_DIRECT_LOCAL
Local<Value> result; Local<Value> result;
has_exception = !ToLocal<Value>( has_exception = !ToLocal<Value>(
i::Execution::Call(i_isolate, self, recv_obj, argc, args), &result); i::Execution::Call(i_isolate, self, recv_obj, argc, args.data()),
&result);
RETURN_ON_FAILED_EXECUTION(Value); RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result); RETURN_ESCAPED(result);
} }
@ -7328,6 +7363,13 @@ void v8::ObjectTemplate::CheckCast(Data* that) {
"Value is not an ObjectTemplate"); "Value is not an ObjectTemplate");
} }
void v8::DictionaryTemplate::CheckCast(Data* that) {
auto obj = Utils::OpenDirectHandle(that);
Utils::ApiCheck(i::IsDictionaryTemplateInfo(*obj),
"v8::DictionaryTemplate::Cast",
"Value is not an DictionaryTemplate");
}
void v8::FunctionTemplate::CheckCast(Data* that) { void v8::FunctionTemplate::CheckCast(Data* that) {
auto obj = Utils::OpenDirectHandle(that); auto obj = Utils::OpenDirectHandle(that);
Utils::ApiCheck(i::IsFunctionTemplateInfo(*obj), "v8::FunctionTemplate::Cast", Utils::ApiCheck(i::IsFunctionTemplateInfo(*obj), "v8::FunctionTemplate::Cast",
@ -8087,7 +8129,7 @@ uint32_t GetLength(Tagged<JSArray> array) {
} // namespace internal } // namespace internal
uint32_t v8::Array::Length() const { uint32_t v8::Array::Length() const {
return i::GetLength(*Utils::OpenHandle(this)); return i::GetLength(*Utils::OpenDirectHandle(this));
} }
namespace internal { namespace internal {
@ -8259,13 +8301,27 @@ Maybe<void> v8::Array::Iterate(Local<Context> context,
} }
v8::TypecheckWitness::TypecheckWitness(Isolate* isolate) v8::TypecheckWitness::TypecheckWitness(Isolate* isolate)
#ifdef V8_ENABLE_DIRECT_LOCAL
// An empty local suffices.
: cached_map_()
#else
// We need to reserve a handle that we can patch later. // We need to reserve a handle that we can patch later.
// TODO(13270): When we switch to CSS, we can use a direct pointer // We initialize it with something that cannot compare equal to any map.
// instead of a handle. : cached_map_(v8::Number::New(isolate, 1))
: cached_map_(v8::Number::New(isolate, 1)) {} #endif
{
}
void v8::TypecheckWitness::Update(Local<Value> baseline) { void v8::TypecheckWitness::Update(Local<Value> baseline) {
i::Tagged<i::Object> obj = *Utils::OpenDirectHandle(*baseline); i::Tagged<i::Object> obj = *Utils::OpenDirectHandle(*baseline);
#ifdef V8_ENABLE_DIRECT_LOCAL
if (IsSmi(obj)) {
cached_map_ = Local<Data>();
} else {
i::Tagged<i::HeapObject> map = i::HeapObject::cast(obj)->map();
cached_map_ = Local<Data>::FromAddress(map->ptr());
}
#else
i::Tagged<i::Object> map = i::Smi::zero(); i::Tagged<i::Object> map = i::Smi::zero();
if (!IsSmi(obj)) map = i::HeapObject::cast(obj)->map(); if (!IsSmi(obj)) map = i::HeapObject::cast(obj)->map();
// Design overview: in the {TypecheckWitness} constructor, we create // Design overview: in the {TypecheckWitness} constructor, we create
@ -8274,12 +8330,12 @@ void v8::TypecheckWitness::Update(Local<Value> baseline) {
// to allow having short-lived HandleScopes (e.g. in {FastIterateArray} // to allow having short-lived HandleScopes (e.g. in {FastIterateArray}
// above) while a {TypecheckWitness} is alive: it therefore cannot hold // above) while a {TypecheckWitness} is alive: it therefore cannot hold
// on to one of the short-lived handles. // on to one of the short-lived handles.
// Calling {OpenHandle} on the {cached_map_} only serves to "reinterpret_cast" // Calling {OpenIndirectHandle} on the {cached_map_} only serves to
// it to an {i::Handle} on which we can call {PatchValue}. // "reinterpret_cast" it to an {i::IndirectHandle} on which we can call
// TODO(13270): When we switch to CSS, this can become simpler: we can // {PatchValue}.
// then simply overwrite the direct pointer.
auto cache = Utils::OpenIndirectHandle(*cached_map_); auto cache = Utils::OpenIndirectHandle(*cached_map_);
cache.PatchValue(map); cache.PatchValue(map);
#endif
} }
Local<v8::Map> v8::Map::New(Isolate* v8_isolate) { Local<v8::Map> v8::Map::New(Isolate* v8_isolate) {
@ -10384,13 +10440,13 @@ CALLBACK_SETTER(WasmAsyncResolvePromiseCallback,
CALLBACK_SETTER(WasmLoadSourceMapCallback, WasmLoadSourceMapCallback, CALLBACK_SETTER(WasmLoadSourceMapCallback, WasmLoadSourceMapCallback,
wasm_load_source_map_callback) wasm_load_source_map_callback)
CALLBACK_SETTER(WasmGCEnabledCallback, WasmGCEnabledCallback,
wasm_gc_enabled_callback)
CALLBACK_SETTER(WasmImportedStringsEnabledCallback, CALLBACK_SETTER(WasmImportedStringsEnabledCallback,
WasmImportedStringsEnabledCallback, WasmImportedStringsEnabledCallback,
wasm_imported_strings_enabled_callback) wasm_imported_strings_enabled_callback)
CALLBACK_SETTER(WasmJSPIEnabledCallback, WasmJSPIEnabledCallback,
wasm_jspi_enabled_callback)
CALLBACK_SETTER(SharedArrayBufferConstructorEnabledCallback, CALLBACK_SETTER(SharedArrayBufferConstructorEnabledCallback,
SharedArrayBufferConstructorEnabledCallback, SharedArrayBufferConstructorEnabledCallback,
sharedarraybuffer_constructor_enabled_callback) sharedarraybuffer_constructor_enabled_callback)
@ -10410,6 +10466,7 @@ void Isolate::InstallConditionalFeatures(Local<Context> context) {
i::WasmJs::InstallConditionalFeatures(i_isolate, i::WasmJs::InstallConditionalFeatures(i_isolate,
Utils::OpenHandle(*context)); Utils::OpenHandle(*context));
} }
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
} }

181
deps/v8/src/api/api.h vendored
View File

@ -30,6 +30,7 @@
namespace v8 { namespace v8 {
class DictionaryTemplate;
class Extension; class Extension;
class Signature; class Signature;
class Template; class Template;
@ -96,97 +97,99 @@ class RegisteredExtension {
static RegisteredExtension* first_extension_; static RegisteredExtension* first_extension_;
}; };
#define TO_LOCAL_LIST(V) \ #define TO_LOCAL_LIST(V) \
V(ToLocal, AccessorPair, debug::AccessorPair) \ V(ToLocal, AccessorPair, debug::AccessorPair) \
V(ToLocal, NativeContext, Context) \ V(ToLocal, NativeContext, Context) \
V(ToLocal, Object, Value) \ V(ToLocal, Object, Value) \
V(ToLocal, Module, Module) \ V(ToLocal, Module, Module) \
V(ToLocal, Name, Name) \ V(ToLocal, Name, Name) \
V(ToLocal, String, String) \ V(ToLocal, String, String) \
V(ToLocal, Symbol, Symbol) \ V(ToLocal, Symbol, Symbol) \
V(ToLocal, JSRegExp, RegExp) \ V(ToLocal, JSRegExp, RegExp) \
V(ToLocal, JSReceiver, Object) \ V(ToLocal, JSReceiver, Object) \
V(ToLocal, JSObject, Object) \ V(ToLocal, JSObject, Object) \
V(ToLocal, JSFunction, Function) \ V(ToLocal, JSFunction, Function) \
V(ToLocal, JSArray, Array) \ V(ToLocal, JSArray, Array) \
V(ToLocal, JSMap, Map) \ V(ToLocal, JSMap, Map) \
V(ToLocal, JSSet, Set) \ V(ToLocal, JSSet, Set) \
V(ToLocal, JSProxy, Proxy) \ V(ToLocal, JSProxy, Proxy) \
V(ToLocal, JSArrayBuffer, ArrayBuffer) \ V(ToLocal, JSArrayBuffer, ArrayBuffer) \
V(ToLocal, JSArrayBufferView, ArrayBufferView) \ V(ToLocal, JSArrayBufferView, ArrayBufferView) \
V(ToLocal, JSDataView, DataView) \ V(ToLocal, JSDataView, DataView) \
V(ToLocal, JSRabGsabDataView, DataView) \ V(ToLocal, JSRabGsabDataView, DataView) \
V(ToLocal, JSTypedArray, TypedArray) \ V(ToLocal, JSTypedArray, TypedArray) \
V(ToLocalShared, JSArrayBuffer, SharedArrayBuffer) \ V(ToLocalShared, JSArrayBuffer, SharedArrayBuffer) \
V(ToLocal, FunctionTemplateInfo, FunctionTemplate) \ V(ToLocal, FunctionTemplateInfo, FunctionTemplate) \
V(ToLocal, ObjectTemplateInfo, ObjectTemplate) \ V(ToLocal, ObjectTemplateInfo, ObjectTemplate) \
V(SignatureToLocal, FunctionTemplateInfo, Signature) \ V(ToLocal, DictionaryTemplateInfo, DictionaryTemplate) \
V(MessageToLocal, Object, Message) \ V(SignatureToLocal, FunctionTemplateInfo, Signature) \
V(PromiseToLocal, JSObject, Promise) \ V(MessageToLocal, Object, Message) \
V(StackTraceToLocal, FixedArray, StackTrace) \ V(PromiseToLocal, JSObject, Promise) \
V(StackFrameToLocal, StackFrameInfo, StackFrame) \ V(StackTraceToLocal, FixedArray, StackTrace) \
V(NumberToLocal, Object, Number) \ V(StackFrameToLocal, StackFrameInfo, StackFrame) \
V(IntegerToLocal, Object, Integer) \ V(NumberToLocal, Object, Number) \
V(Uint32ToLocal, Object, Uint32) \ V(IntegerToLocal, Object, Integer) \
V(ToLocal, BigInt, BigInt) \ V(Uint32ToLocal, Object, Uint32) \
V(ExternalToLocal, JSObject, External) \ V(ToLocal, BigInt, BigInt) \
V(CallableToLocal, JSReceiver, Function) \ V(ExternalToLocal, JSObject, External) \
V(ToLocalPrimitive, Object, Primitive) \ V(CallableToLocal, JSReceiver, Function) \
V(FixedArrayToLocal, FixedArray, FixedArray) \ V(ToLocalPrimitive, Object, Primitive) \
V(PrimitiveArrayToLocal, FixedArray, PrimitiveArray) \ V(FixedArrayToLocal, FixedArray, FixedArray) \
V(PrimitiveArrayToLocal, FixedArray, PrimitiveArray) \
V(ToLocal, ScriptOrModule, ScriptOrModule) V(ToLocal, ScriptOrModule, ScriptOrModule)
#define OPEN_HANDLE_LIST(V) \ #define OPEN_HANDLE_LIST(V) \
V(Template, TemplateInfo) \ V(Template, TemplateInfo) \
V(FunctionTemplate, FunctionTemplateInfo) \ V(FunctionTemplate, FunctionTemplateInfo) \
V(ObjectTemplate, ObjectTemplateInfo) \ V(ObjectTemplate, ObjectTemplateInfo) \
V(Signature, FunctionTemplateInfo) \ V(DictionaryTemplate, DictionaryTemplateInfo) \
V(Data, Object) \ V(Signature, FunctionTemplateInfo) \
V(RegExp, JSRegExp) \ V(Data, Object) \
V(Object, JSReceiver) \ V(RegExp, JSRegExp) \
V(Array, JSArray) \ V(Object, JSReceiver) \
V(Map, JSMap) \ V(Array, JSArray) \
V(Set, JSSet) \ V(Map, JSMap) \
V(ArrayBuffer, JSArrayBuffer) \ V(Set, JSSet) \
V(ArrayBufferView, JSArrayBufferView) \ V(ArrayBuffer, JSArrayBuffer) \
V(TypedArray, JSTypedArray) \ V(ArrayBufferView, JSArrayBufferView) \
V(Uint8Array, JSTypedArray) \ V(TypedArray, JSTypedArray) \
V(Uint8ClampedArray, JSTypedArray) \ V(Uint8Array, JSTypedArray) \
V(Int8Array, JSTypedArray) \ V(Uint8ClampedArray, JSTypedArray) \
V(Uint16Array, JSTypedArray) \ V(Int8Array, JSTypedArray) \
V(Int16Array, JSTypedArray) \ V(Uint16Array, JSTypedArray) \
V(Uint32Array, JSTypedArray) \ V(Int16Array, JSTypedArray) \
V(Int32Array, JSTypedArray) \ V(Uint32Array, JSTypedArray) \
V(Float32Array, JSTypedArray) \ V(Int32Array, JSTypedArray) \
V(Float64Array, JSTypedArray) \ V(Float32Array, JSTypedArray) \
V(DataView, JSDataViewOrRabGsabDataView) \ V(Float64Array, JSTypedArray) \
V(SharedArrayBuffer, JSArrayBuffer) \ V(DataView, JSDataViewOrRabGsabDataView) \
V(Name, Name) \ V(SharedArrayBuffer, JSArrayBuffer) \
V(String, String) \ V(Name, Name) \
V(Symbol, Symbol) \ V(String, String) \
V(Script, JSFunction) \ V(Symbol, Symbol) \
V(UnboundModuleScript, SharedFunctionInfo) \ V(Script, JSFunction) \
V(UnboundScript, SharedFunctionInfo) \ V(UnboundModuleScript, SharedFunctionInfo) \
V(Module, Module) \ V(UnboundScript, SharedFunctionInfo) \
V(Function, JSReceiver) \ V(Module, Module) \
V(Message, JSMessageObject) \ V(Function, JSReceiver) \
V(Context, NativeContext) \ V(Message, JSMessageObject) \
V(External, Object) \ V(Context, NativeContext) \
V(StackTrace, FixedArray) \ V(External, Object) \
V(StackFrame, StackFrameInfo) \ V(StackTrace, FixedArray) \
V(Proxy, JSProxy) \ V(StackFrame, StackFrameInfo) \
V(debug::GeneratorObject, JSGeneratorObject) \ V(Proxy, JSProxy) \
V(debug::ScriptSource, HeapObject) \ V(debug::GeneratorObject, JSGeneratorObject) \
V(debug::Script, Script) \ V(debug::ScriptSource, HeapObject) \
V(debug::EphemeronTable, EphemeronHashTable) \ V(debug::Script, Script) \
V(debug::AccessorPair, AccessorPair) \ V(debug::EphemeronTable, EphemeronHashTable) \
V(Promise, JSPromise) \ V(debug::AccessorPair, AccessorPair) \
V(Primitive, Object) \ V(Promise, JSPromise) \
V(PrimitiveArray, FixedArray) \ V(Primitive, Object) \
V(BigInt, BigInt) \ V(PrimitiveArray, FixedArray) \
V(ScriptOrModule, ScriptOrModule) \ V(BigInt, BigInt) \
V(FixedArray, FixedArray) \ V(ScriptOrModule, ScriptOrModule) \
V(ModuleRequest, ModuleRequest) \ V(FixedArray, FixedArray) \
V(ModuleRequest, ModuleRequest) \
IF_WASM(V, WasmMemoryObject, WasmMemoryObject) IF_WASM(V, WasmMemoryObject, WasmMemoryObject)
class Utils { class Utils {

View File

@ -46,6 +46,7 @@ struct SourceRange {
V(BinaryOperation) \ V(BinaryOperation) \
V(Block) \ V(Block) \
V(CaseClause) \ V(CaseClause) \
V(ConditionalChain) \
V(Conditional) \ V(Conditional) \
V(Expression) \ V(Expression) \
V(FunctionLiteral) \ V(FunctionLiteral) \
@ -142,6 +143,39 @@ class CaseClauseSourceRanges final : public AstNodeSourceRanges {
SourceRange body_range_; SourceRange body_range_;
}; };
class ConditionalChainSourceRanges final : public AstNodeSourceRanges {
public:
explicit ConditionalChainSourceRanges(Zone* zone)
: then_ranges_(zone), else_ranges_(zone) {}
SourceRange GetRangeAtIndex(SourceRangeKind kind, size_t index) {
if (kind == SourceRangeKind::kThen) {
DCHECK_LT(index, then_ranges_.size());
return then_ranges_[index];
}
DCHECK_EQ(kind, SourceRangeKind::kElse);
DCHECK_LT(index, else_ranges_.size());
return else_ranges_[index];
}
void AddThenRanges(const SourceRange& range) {
then_ranges_.push_back(range);
}
void AddElseRange(const SourceRange& else_range) {
else_ranges_.push_back(else_range);
}
size_t RangeCount() const { return then_ranges_.size(); }
SourceRange GetRange(SourceRangeKind kind) override { UNREACHABLE(); }
bool HasRange(SourceRangeKind kind) override { return false; }
private:
ZoneVector<SourceRange> then_ranges_;
ZoneVector<SourceRange> else_ranges_;
};
class ConditionalSourceRanges final : public AstNodeSourceRanges { class ConditionalSourceRanges final : public AstNodeSourceRanges {
public: public:
explicit ConditionalSourceRanges(const SourceRange& then_range, explicit ConditionalSourceRanges(const SourceRange& then_range,

View File

@ -295,6 +295,17 @@ void AstTraversalVisitor<Subclass>::VisitNativeFunctionLiteral(
PROCESS_EXPRESSION(expr); PROCESS_EXPRESSION(expr);
} }
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitConditionalChain(
ConditionalChain* expr) {
PROCESS_EXPRESSION(expr);
for (size_t i = 0; i < expr->conditional_chain_length(); ++i) {
RECURSE_EXPRESSION(Visit(expr->condition_at(i)));
RECURSE_EXPRESSION(Visit(expr->then_expression_at(i)));
}
RECURSE(Visit(expr->else_expression()));
}
template <class Subclass> template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitConditional(Conditional* expr) { void AstTraversalVisitor<Subclass>::VisitConditional(Conditional* expr) {
PROCESS_EXPRESSION(expr); PROCESS_EXPRESSION(expr);
@ -561,8 +572,8 @@ void AstTraversalVisitor<Subclass>::VisitImportCallExpression(
ImportCallExpression* expr) { ImportCallExpression* expr) {
PROCESS_EXPRESSION(expr); PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->specifier())); RECURSE_EXPRESSION(Visit(expr->specifier()));
if (expr->import_assertions()) { if (expr->import_options()) {
RECURSE_EXPRESSION(Visit(expr->import_assertions())); RECURSE_EXPRESSION(Visit(expr->import_options()));
} }
} }

View File

@ -60,7 +60,7 @@ class OneByteStringStream {
template <typename IsolateT> template <typename IsolateT>
void AstRawString::Internalize(IsolateT* isolate) { void AstRawString::Internalize(IsolateT* isolate) {
DCHECK(!has_string_); DCHECK(!has_string_);
if (literal_bytes_.length() == 0) { if (literal_bytes_.empty()) {
set_string(isolate->factory()->empty_string()); set_string(isolate->factory()->empty_string());
} else if (is_one_byte()) { } else if (is_one_byte()) {
OneByteStringKey key(raw_hash_field_, literal_bytes_); OneByteStringKey key(raw_hash_field_, literal_bytes_);

View File

@ -847,8 +847,8 @@ template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT)
static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) { static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
// Add is not commutative due to potential for string addition. // Add is not commutative due to potential for string addition.
return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR || return op == Token::kMul || op == Token::kBitAnd || op == Token::kBitOr ||
op == Token::BIT_XOR; op == Token::kBitXor;
} }
// Check for the pattern: x + 1. // Check for the pattern: x + 1.
@ -869,32 +869,9 @@ bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
MatchSmiLiteralOperation(right_, left_, subexpr, literal)); MatchSmiLiteralOperation(right_, left_, subexpr, literal));
} }
static bool IsTypeof(Expression* expr) {
UnaryOperation* maybe_unary = expr->AsUnaryOperation();
return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
}
// Check for the pattern: typeof <expression> equals <string literal>.
static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
Expression* right, Expression** expr,
Literal** literal) {
if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
*expr = left->AsUnaryOperation()->expression();
*literal = right->AsLiteral();
return true;
}
return false;
}
bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
Literal** literal) {
return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
}
static bool IsVoidOfLiteral(Expression* expr) { static bool IsVoidOfLiteral(Expression* expr) {
UnaryOperation* maybe_unary = expr->AsUnaryOperation(); UnaryOperation* maybe_unary = expr->AsUnaryOperation();
return maybe_unary != nullptr && maybe_unary->op() == Token::VOID && return maybe_unary != nullptr && maybe_unary->op() == Token::kVoid &&
maybe_unary->expression()->IsLiteral(); maybe_unary->expression()->IsLiteral();
} }
@ -902,7 +879,7 @@ static bool MatchLiteralStrictCompareBoolean(Expression* left, Token::Value op,
Expression* right, Expression* right,
Expression** expr, Expression** expr,
Literal** literal) { Literal** literal) {
if (left->IsBooleanLiteral() && op == Token::EQ_STRICT) { if (left->IsBooleanLiteral() && op == Token::kEqStrict) {
*expr = right; *expr = right;
*literal = left->AsLiteral(); *literal = left->AsLiteral();
return true; return true;

97
deps/v8/src/ast/ast.h vendored
View File

@ -91,6 +91,7 @@ namespace internal {
V(ClassLiteral) \ V(ClassLiteral) \
V(CompareOperation) \ V(CompareOperation) \
V(CompoundAssignment) \ V(CompoundAssignment) \
V(ConditionalChain) \
V(Conditional) \ V(Conditional) \
V(CountOperation) \ V(CountOperation) \
V(EmptyParentheses) \ V(EmptyParentheses) \
@ -1938,7 +1939,7 @@ class NaryOperation final : public Expression {
subsequent_(zone) { subsequent_(zone) {
bit_field_ |= OperatorField::encode(op); bit_field_ |= OperatorField::encode(op);
DCHECK(Token::IsBinaryOp(op)); DCHECK(Token::IsBinaryOp(op));
DCHECK_NE(op, Token::EXP); DCHECK_NE(op, Token::kExp);
subsequent_.reserve(initial_subsequent_size); subsequent_.reserve(initial_subsequent_size);
} }
@ -2002,7 +2003,6 @@ class CompareOperation final : public Expression {
Expression* right() const { return right_; } Expression* right() const { return right_; }
// Match special cases. // Match special cases.
bool IsLiteralCompareTypeof(Expression** expr, Literal** literal);
bool IsLiteralStrictCompareBoolean(Expression** expr, Literal** literal); bool IsLiteralStrictCompareBoolean(Expression** expr, Literal** literal);
bool IsLiteralCompareUndefined(Expression** expr); bool IsLiteralCompareUndefined(Expression** expr);
bool IsLiteralCompareNull(Expression** expr); bool IsLiteralCompareNull(Expression** expr);
@ -2045,6 +2045,77 @@ class Spread final : public Expression {
Expression* expression_; Expression* expression_;
}; };
class ConditionalChain : public Expression {
public:
Expression* condition_at(size_t index) const {
return conditional_chain_entries_[index].condition;
}
Expression* then_expression_at(size_t index) const {
return conditional_chain_entries_[index].then_expression;
}
int condition_position_at(size_t index) const {
return conditional_chain_entries_[index].condition_position;
}
size_t conditional_chain_length() const {
return conditional_chain_entries_.size();
}
Expression* else_expression() const { return else_expression_; }
void set_else_expression(Expression* s) { else_expression_ = s; }
void AddChainEntry(Expression* cond, Expression* then, int pos) {
conditional_chain_entries_.emplace_back(cond, then, pos);
}
private:
friend class AstNodeFactory;
friend Zone;
ConditionalChain(Zone* zone, size_t initial_size, int pos)
: Expression(pos, kConditionalChain),
conditional_chain_entries_(zone),
else_expression_(nullptr) {
conditional_chain_entries_.reserve(initial_size);
}
// Conditional Chain Expression stores the conditional chain entries out of
// line, along with their operation's position. The else expression is stored
// inline. This Expression is reserved for ternary operations that have more
// than one conditional chain entry. For ternary operations with only one
// conditional chain entry, the Conditional Expression is used instead.
//
// So an conditional chain:
//
// cond ? then : cond ? then : cond ? then : else
//
// is stored as:
//
// [(cond, then), (cond, then),...] else
// '-----------------------------' '----'
// conditional chain entries else
//
// Example:
//
// Expression: v1 == 1 ? "a" : v2 == 2 ? "b" : "c"
//
// conditionat_chain_entries_: [(v1 == 1, "a", 0), (v2 == 2, "b", 14)]
// else_expression_: "c"
//
// Example of a _not_ expected expression (only one chain entry):
//
// Expression: v1 == 1 ? "a" : "b"
//
struct ConditionalChainEntry {
Expression* condition;
Expression* then_expression;
int condition_position;
ConditionalChainEntry(Expression* cond, Expression* then, int pos)
: condition(cond), then_expression(then), condition_position(pos) {}
};
ZoneVector<ConditionalChainEntry> conditional_chain_entries_;
Expression* else_expression_;
};
class Conditional final : public Expression { class Conditional final : public Expression {
public: public:
Expression* condition() const { return condition_; } Expression* condition() const { return condition_; }
@ -2666,7 +2737,7 @@ class SuperCallReference final : public Expression {
class ImportCallExpression final : public Expression { class ImportCallExpression final : public Expression {
public: public:
Expression* specifier() const { return specifier_; } Expression* specifier() const { return specifier_; }
Expression* import_assertions() const { return import_assertions_; } Expression* import_options() const { return import_options_; }
private: private:
friend class AstNodeFactory; friend class AstNodeFactory;
@ -2675,16 +2746,16 @@ class ImportCallExpression final : public Expression {
ImportCallExpression(Expression* specifier, int pos) ImportCallExpression(Expression* specifier, int pos)
: Expression(pos, kImportCallExpression), : Expression(pos, kImportCallExpression),
specifier_(specifier), specifier_(specifier),
import_assertions_(nullptr) {} import_options_(nullptr) {}
ImportCallExpression(Expression* specifier, Expression* import_assertions, ImportCallExpression(Expression* specifier, Expression* import_options,
int pos) int pos)
: Expression(pos, kImportCallExpression), : Expression(pos, kImportCallExpression),
specifier_(specifier), specifier_(specifier),
import_assertions_(import_assertions) {} import_options_(import_options) {}
Expression* specifier_; Expression* specifier_;
Expression* import_assertions_; Expression* import_options_;
}; };
// This class is produced when parsing the () in arrow functions without any // This class is produced when parsing the () in arrow functions without any
@ -3216,6 +3287,10 @@ class AstNodeFactory final {
return zone_->New<Spread>(expression, pos, expr_pos); return zone_->New<Spread>(expression, pos, expr_pos);
} }
ConditionalChain* NewConditionalChain(size_t initial_size, int pos) {
return zone_->New<ConditionalChain>(zone_, initial_size, pos);
}
Conditional* NewConditional(Expression* condition, Conditional* NewConditional(Expression* condition,
Expression* then_expression, Expression* then_expression,
Expression* else_expression, Expression* else_expression,
@ -3232,11 +3307,11 @@ class AstNodeFactory final {
DCHECK_NOT_NULL(target); DCHECK_NOT_NULL(target);
DCHECK_NOT_NULL(value); DCHECK_NOT_NULL(value);
if (op != Token::INIT && target->IsVariableProxy()) { if (op != Token::kInit && target->IsVariableProxy()) {
target->AsVariableProxy()->set_is_assigned(); target->AsVariableProxy()->set_is_assigned();
} }
if (op == Token::ASSIGN || op == Token::INIT) { if (op == Token::kAssign || op == Token::kInit) {
return zone_->New<Assignment>(AstNode::kAssignment, op, target, value, return zone_->New<Assignment>(AstNode::kAssignment, op, target, value,
pos); pos);
} else { } else {
@ -3371,9 +3446,9 @@ class AstNodeFactory final {
} }
ImportCallExpression* NewImportCallExpression(Expression* specifier, ImportCallExpression* NewImportCallExpression(Expression* specifier,
Expression* import_assertions, Expression* import_options,
int pos) { int pos) {
return zone_->New<ImportCallExpression>(specifier, import_assertions, pos); return zone_->New<ImportCallExpression>(specifier, import_options, pos);
} }
InitializeClassMembersStatement* NewInitializeClassMembersStatement( InitializeClassMembersStatement* NewInitializeClassMembersStatement(

View File

@ -27,10 +27,10 @@ bool SourceTextModuleDescriptor::ModuleRequestComparer::operator()(
return specifier_comparison < 0; return specifier_comparison < 0;
} }
auto lhsIt = lhs->import_assertions()->cbegin(); auto lhsIt = lhs->import_attributes()->cbegin();
auto rhsIt = rhs->import_assertions()->cbegin(); auto rhsIt = rhs->import_attributes()->cbegin();
for (; lhsIt != lhs->import_assertions()->cend() && for (; lhsIt != lhs->import_attributes()->cend() &&
rhsIt != rhs->import_assertions()->cend(); rhsIt != rhs->import_attributes()->cend();
++lhsIt, ++rhsIt) { ++lhsIt, ++rhsIt) {
if (int assertion_key_comparison = if (int assertion_key_comparison =
AstRawString::Compare(lhsIt->first, rhsIt->first)) { AstRawString::Compare(lhsIt->first, rhsIt->first)) {
@ -43,9 +43,9 @@ bool SourceTextModuleDescriptor::ModuleRequestComparer::operator()(
} }
} }
if (lhs->import_assertions()->size() != rhs->import_assertions()->size()) { if (lhs->import_attributes()->size() != rhs->import_attributes()->size()) {
return (lhs->import_assertions()->size() < return (lhs->import_attributes()->size() <
rhs->import_assertions()->size()); rhs->import_attributes()->size());
} }
return false; return false;
@ -54,32 +54,32 @@ bool SourceTextModuleDescriptor::ModuleRequestComparer::operator()(
void SourceTextModuleDescriptor::AddImport( void SourceTextModuleDescriptor::AddImport(
const AstRawString* import_name, const AstRawString* local_name, const AstRawString* import_name, const AstRawString* local_name,
const AstRawString* module_request, const AstRawString* module_request,
const ImportAssertions* import_assertions, const Scanner::Location loc, const ImportAttributes* import_attributes, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone) { const Scanner::Location specifier_loc, Zone* zone) {
Entry* entry = zone->New<Entry>(loc); Entry* entry = zone->New<Entry>(loc);
entry->local_name = local_name; entry->local_name = local_name;
entry->import_name = import_name; entry->import_name = import_name;
entry->module_request = entry->module_request =
AddModuleRequest(module_request, import_assertions, specifier_loc, zone); AddModuleRequest(module_request, import_attributes, specifier_loc, zone);
AddRegularImport(entry); AddRegularImport(entry);
} }
void SourceTextModuleDescriptor::AddStarImport( void SourceTextModuleDescriptor::AddStarImport(
const AstRawString* local_name, const AstRawString* module_request, const AstRawString* local_name, const AstRawString* module_request,
const ImportAssertions* import_assertions, const Scanner::Location loc, const ImportAttributes* import_attributes, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone) { const Scanner::Location specifier_loc, Zone* zone) {
Entry* entry = zone->New<Entry>(loc); Entry* entry = zone->New<Entry>(loc);
entry->local_name = local_name; entry->local_name = local_name;
entry->module_request = entry->module_request =
AddModuleRequest(module_request, import_assertions, specifier_loc, zone); AddModuleRequest(module_request, import_attributes, specifier_loc, zone);
AddNamespaceImport(entry, zone); AddNamespaceImport(entry, zone);
} }
void SourceTextModuleDescriptor::AddEmptyImport( void SourceTextModuleDescriptor::AddEmptyImport(
const AstRawString* module_request, const AstRawString* module_request,
const ImportAssertions* import_assertions, const ImportAttributes* import_attributes,
const Scanner::Location specifier_loc, Zone* zone) { const Scanner::Location specifier_loc, Zone* zone) {
AddModuleRequest(module_request, import_assertions, specifier_loc, zone); AddModuleRequest(module_request, import_attributes, specifier_loc, zone);
} }
void SourceTextModuleDescriptor::AddExport(const AstRawString* local_name, void SourceTextModuleDescriptor::AddExport(const AstRawString* local_name,
@ -94,7 +94,7 @@ void SourceTextModuleDescriptor::AddExport(const AstRawString* local_name,
void SourceTextModuleDescriptor::AddExport( void SourceTextModuleDescriptor::AddExport(
const AstRawString* import_name, const AstRawString* export_name, const AstRawString* import_name, const AstRawString* export_name,
const AstRawString* module_request, const AstRawString* module_request,
const ImportAssertions* import_assertions, const Scanner::Location loc, const ImportAttributes* import_attributes, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone) { const Scanner::Location specifier_loc, Zone* zone) {
DCHECK_NOT_NULL(import_name); DCHECK_NOT_NULL(import_name);
DCHECK_NOT_NULL(export_name); DCHECK_NOT_NULL(export_name);
@ -102,17 +102,17 @@ void SourceTextModuleDescriptor::AddExport(
entry->export_name = export_name; entry->export_name = export_name;
entry->import_name = import_name; entry->import_name = import_name;
entry->module_request = entry->module_request =
AddModuleRequest(module_request, import_assertions, specifier_loc, zone); AddModuleRequest(module_request, import_attributes, specifier_loc, zone);
AddSpecialExport(entry, zone); AddSpecialExport(entry, zone);
} }
void SourceTextModuleDescriptor::AddStarExport( void SourceTextModuleDescriptor::AddStarExport(
const AstRawString* module_request, const AstRawString* module_request,
const ImportAssertions* import_assertions, const Scanner::Location loc, const ImportAttributes* import_attributes, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone) { const Scanner::Location specifier_loc, Zone* zone) {
Entry* entry = zone->New<Entry>(loc); Entry* entry = zone->New<Entry>(loc);
entry->module_request = entry->module_request =
AddModuleRequest(module_request, import_assertions, specifier_loc, zone); AddModuleRequest(module_request, import_attributes, specifier_loc, zone);
AddSpecialExport(entry, zone); AddSpecialExport(entry, zone);
} }
@ -128,28 +128,28 @@ Handle<PrimitiveHeapObject> ToStringOrUndefined(IsolateT* isolate,
template <typename IsolateT> template <typename IsolateT>
Handle<ModuleRequest> SourceTextModuleDescriptor::AstModuleRequest::Serialize( Handle<ModuleRequest> SourceTextModuleDescriptor::AstModuleRequest::Serialize(
IsolateT* isolate) const { IsolateT* isolate) const {
// The import assertions will be stored in this array in the form: // The import attributes will be stored in this array in the form:
// [key1, value1, location1, key2, value2, location2, ...] // [key1, value1, location1, key2, value2, location2, ...]
Handle<FixedArray> import_assertions_array = Handle<FixedArray> import_attributes_array =
isolate->factory()->NewFixedArray( isolate->factory()->NewFixedArray(
static_cast<int>(import_assertions()->size() * static_cast<int>(import_attributes()->size() *
ModuleRequest::kAssertionEntrySize), ModuleRequest::kAttributeEntrySize),
AllocationType::kOld); AllocationType::kOld);
{ {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
Tagged<FixedArray> raw_import_assertions = *import_assertions_array; Tagged<FixedArray> raw_import_attributes = *import_attributes_array;
int i = 0; int i = 0;
for (auto iter = import_assertions()->cbegin(); for (auto iter = import_attributes()->cbegin();
iter != import_assertions()->cend(); iter != import_attributes()->cend();
++iter, i += ModuleRequest::kAssertionEntrySize) { ++iter, i += ModuleRequest::kAttributeEntrySize) {
raw_import_assertions->set(i, *iter->first->string()); raw_import_attributes->set(i, *iter->first->string());
raw_import_assertions->set(i + 1, *iter->second.first->string()); raw_import_attributes->set(i + 1, *iter->second.first->string());
raw_import_assertions->set(i + 2, raw_import_attributes->set(i + 2,
Smi::FromInt(iter->second.second.beg_pos)); Smi::FromInt(iter->second.second.beg_pos));
} }
} }
return v8::internal::ModuleRequest::New(isolate, specifier()->string(), return v8::internal::ModuleRequest::New(isolate, specifier()->string(),
import_assertions_array, position()); import_attributes_array, position());
} }
template Handle<ModuleRequest> template Handle<ModuleRequest>
SourceTextModuleDescriptor::AstModuleRequest::Serialize(Isolate* isolate) const; SourceTextModuleDescriptor::AstModuleRequest::Serialize(Isolate* isolate) const;

View File

@ -38,14 +38,14 @@ class SourceTextModuleDescriptor : public ZoneObject {
void AddImport(const AstRawString* import_name, void AddImport(const AstRawString* import_name,
const AstRawString* local_name, const AstRawString* local_name,
const AstRawString* module_request, const AstRawString* module_request,
const ImportAssertions* import_assertions, const ImportAttributes* import_attributes,
const Scanner::Location loc, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone); const Scanner::Location specifier_loc, Zone* zone);
// import * as x from "foo.js"; // import * as x from "foo.js";
void AddStarImport(const AstRawString* local_name, void AddStarImport(const AstRawString* local_name,
const AstRawString* module_request, const AstRawString* module_request,
const ImportAssertions* import_assertions, const ImportAttributes* import_attributes,
const Scanner::Location loc, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone); const Scanner::Location specifier_loc, Zone* zone);
@ -53,7 +53,7 @@ class SourceTextModuleDescriptor : public ZoneObject {
// import {} from "foo.js"; // import {} from "foo.js";
// export {} from "foo.js"; (sic!) // export {} from "foo.js"; (sic!)
void AddEmptyImport(const AstRawString* module_request, void AddEmptyImport(const AstRawString* module_request,
const ImportAssertions* import_assertions, const ImportAttributes* import_attributes,
const Scanner::Location specifier_loc, Zone* zone); const Scanner::Location specifier_loc, Zone* zone);
// export {x}; // export {x};
@ -70,13 +70,13 @@ class SourceTextModuleDescriptor : public ZoneObject {
void AddExport(const AstRawString* export_name, void AddExport(const AstRawString* export_name,
const AstRawString* import_name, const AstRawString* import_name,
const AstRawString* module_request, const AstRawString* module_request,
const ImportAssertions* import_assertions, const ImportAttributes* import_attributes,
const Scanner::Location loc, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone); const Scanner::Location specifier_loc, Zone* zone);
// export * from "foo.js"; // export * from "foo.js";
void AddStarExport(const AstRawString* module_request, void AddStarExport(const AstRawString* module_request,
const ImportAssertions* import_assertions, const ImportAttributes* import_attributes,
const Scanner::Location loc, const Scanner::Location loc,
const Scanner::Location specifier_loc, Zone* zone); const Scanner::Location specifier_loc, Zone* zone);
@ -125,10 +125,10 @@ class SourceTextModuleDescriptor : public ZoneObject {
class AstModuleRequest : public ZoneObject { class AstModuleRequest : public ZoneObject {
public: public:
AstModuleRequest(const AstRawString* specifier, AstModuleRequest(const AstRawString* specifier,
const ImportAssertions* import_assertions, int position, const ImportAttributes* import_attributes, int position,
int index) int index)
: specifier_(specifier), : specifier_(specifier),
import_assertions_(import_assertions), import_attributes_(import_attributes),
position_(position), position_(position),
index_(index) {} index_(index) {}
@ -136,8 +136,8 @@ class SourceTextModuleDescriptor : public ZoneObject {
Handle<v8::internal::ModuleRequest> Serialize(IsolateT* isolate) const; Handle<v8::internal::ModuleRequest> Serialize(IsolateT* isolate) const;
const AstRawString* specifier() const { return specifier_; } const AstRawString* specifier() const { return specifier_; }
const ImportAssertions* import_assertions() const { const ImportAttributes* import_attributes() const {
return import_assertions_; return import_attributes_;
} }
int position() const { return position_; } int position() const { return position_; }
@ -145,7 +145,7 @@ class SourceTextModuleDescriptor : public ZoneObject {
private: private:
const AstRawString* specifier_; const AstRawString* specifier_;
const ImportAssertions* import_assertions_; const ImportAttributes* import_attributes_;
// The JS source code position of the request, used for reporting errors. // The JS source code position of the request, used for reporting errors.
int position_; int position_;
@ -264,13 +264,13 @@ class SourceTextModuleDescriptor : public ZoneObject {
void AssignCellIndices(); void AssignCellIndices();
int AddModuleRequest(const AstRawString* specifier, int AddModuleRequest(const AstRawString* specifier,
const ImportAssertions* import_assertions, const ImportAttributes* import_attributes,
Scanner::Location specifier_loc, Zone* zone) { Scanner::Location specifier_loc, Zone* zone) {
DCHECK_NOT_NULL(specifier); DCHECK_NOT_NULL(specifier);
int module_requests_count = static_cast<int>(module_requests_.size()); int module_requests_count = static_cast<int>(module_requests_.size());
auto it = module_requests_ auto it = module_requests_
.insert(zone->New<AstModuleRequest>( .insert(zone->New<AstModuleRequest>(
specifier, import_assertions, specifier_loc.beg_pos, specifier, import_attributes, specifier_loc.beg_pos,
module_requests_count)) module_requests_count))
.first; .first;
return (*it)->index(); return (*it)->index();

View File

@ -256,6 +256,13 @@ void CallPrinter::VisitInitializeClassStaticElementsStatement(
void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {} void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
void CallPrinter::VisitConditionalChain(ConditionalChain* node) {
for (size_t i = 0; i < node->conditional_chain_length(); ++i) {
Find(node->condition_at(i));
Find(node->then_expression_at(i));
}
Find(node->else_expression());
}
void CallPrinter::VisitConditional(Conditional* node) { void CallPrinter::VisitConditional(Conditional* node) {
Find(node->condition()); Find(node->condition());
@ -500,7 +507,7 @@ void CallPrinter::VisitSuperCallForwardArgs(SuperCallForwardArgs* node) {
void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
Token::Value op = node->op(); Token::Value op = node->op();
bool needsSpace = bool needsSpace =
op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; op == Token::kDelete || op == Token::kTypeOf || op == Token::kVoid;
Print("("); Print("(");
Print(Token::String(op)); Print(Token::String(op));
if (needsSpace) Print(" "); if (needsSpace) Print(" ");
@ -572,8 +579,8 @@ void CallPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) { void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) {
Print("ImportCall("); Print("ImportCall(");
Find(node->specifier(), true); Find(node->specifier(), true);
if (node->import_assertions()) { if (node->import_options()) {
Find(node->import_assertions(), true); Find(node->import_options(), true);
} }
Print(")"); Print(")");
} }
@ -1176,6 +1183,17 @@ void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
PrintLiteralIndented("NAME", node->raw_name(), false); PrintLiteralIndented("NAME", node->raw_name(), false);
} }
void AstPrinter::VisitConditionalChain(ConditionalChain* node) {
IndentedScope indent(this, "CONDITIONAL_CHAIN", node->position());
PrintIndentedVisit("CONDITION", node->condition_at(0));
PrintIndentedVisit("THEN", node->then_expression_at(0));
for (size_t i = 1; i < node->conditional_chain_length(); ++i) {
IndentedScope indent(this, "ELSE IF", node->condition_position_at(i));
PrintIndentedVisit("CONDITION", node->condition_at(i));
PrintIndentedVisit("THEN", node->then_expression_at(i));
}
PrintIndentedVisit("ELSE", node->else_expression());
}
void AstPrinter::VisitConditional(Conditional* node) { void AstPrinter::VisitConditional(Conditional* node) {
IndentedScope indent(this, "CONDITIONAL", node->position()); IndentedScope indent(this, "CONDITIONAL", node->position());
@ -1471,8 +1489,8 @@ void AstPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) { void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) {
IndentedScope indent(this, "IMPORT-CALL", node->position()); IndentedScope indent(this, "IMPORT-CALL", node->position());
Visit(node->specifier()); Visit(node->specifier());
if (node->import_assertions()) { if (node->import_options()) {
Visit(node->import_assertions()); Visit(node->import_options());
} }
} }

View File

@ -679,7 +679,7 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
DCHECK(is_being_lazily_parsed_); DCHECK(is_being_lazily_parsed_);
bool was_added; bool was_added;
Variable* var = DeclareVariableName(name, VariableMode::kVar, &was_added); Variable* var = DeclareVariableName(name, VariableMode::kVar, &was_added);
if (sloppy_block_function->init() == Token::ASSIGN) { if (sloppy_block_function->init() == Token::kAssign) {
var->SetMaybeAssigned(); var->SetMaybeAssigned();
} }
} }
@ -1077,14 +1077,15 @@ Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
DCHECK(!already_resolved_); DCHECK(!already_resolved_);
// Private methods should be declared with ClassScope::DeclarePrivateName() // Private methods should be declared with ClassScope::DeclarePrivateName()
DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode)); DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode));
// This function handles VariableMode::kVar, VariableMode::kLet, and // This function handles VariableMode::kVar, VariableMode::kLet,
// VariableMode::kConst modes. VariableMode::kDynamic variables are // VariableMode::kConst, and VariableMode::kUsing modes.
// introduced during variable allocation, and VariableMode::kTemporary // VariableMode::kDynamic variables are introduced during variable allocation,
// variables are allocated via NewTemporary(). // and VariableMode::kTemporary variables are allocated via NewTemporary().
DCHECK(IsDeclaredVariableMode(mode)); DCHECK(IsDeclaredVariableMode(mode));
DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(), DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
mode == VariableMode::kVar || mode == VariableMode::kLet || mode == VariableMode::kVar || mode == VariableMode::kLet ||
mode == VariableMode::kConst); mode == VariableMode::kConst ||
mode == VariableMode::kUsing);
DCHECK(!GetDeclarationScope()->was_lazily_parsed()); DCHECK(!GetDeclarationScope()->was_lazily_parsed());
Variable* var = Variable* var =
Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added); Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added);

View File

@ -486,6 +486,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
switch (scope_type_) { switch (scope_type_) {
case MODULE_SCOPE: case MODULE_SCOPE:
case WITH_SCOPE: // DebugEvaluateContext as well case WITH_SCOPE: // DebugEvaluateContext as well
case SCRIPT_SCOPE: // Side data for const tracking let.
return true; return true;
default: default:
DCHECK_IMPLIES(sloppy_eval_can_extend_vars_, DCHECK_IMPLIES(sloppy_eval_can_extend_vars_,

View File

@ -25,6 +25,20 @@ inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) {
static_cast<unsigned_T>(lower_limit)); static_cast<unsigned_T>(lower_limit));
} }
// Like IsInRange but for the half-open range [lower_limit, higher_limit).
template <typename T, typename U>
inline constexpr bool IsInHalfOpenRange(T value, U lower_limit,
U higher_limit) {
DCHECK_LE(lower_limit, higher_limit);
static_assert(sizeof(U) <= sizeof(T));
using unsigned_T = typename std::make_unsigned<T>::type;
// Use static_cast to support enum classes.
return static_cast<unsigned_T>(static_cast<unsigned_T>(value) -
static_cast<unsigned_T>(lower_limit)) <
static_cast<unsigned_T>(static_cast<unsigned_T>(higher_limit) -
static_cast<unsigned_T>(lower_limit));
}
// Checks if [index, index+length) is in range [0, max). Note that this check // Checks if [index, index+length) is in range [0, max). Note that this check
// works even if {index+length} would wrap around. // works even if {index+length} would wrap around.
template <typename T, template <typename T,

View File

@ -368,9 +368,9 @@ bool is_inbounds(float_t v) {
// Setup for Windows shared library export. // Setup for Windows shared library export.
#define V8_EXPORT_ENUM #define V8_EXPORT_ENUM
#ifdef BUILDING_V8_SHARED_PRIVATE #ifdef BUILDING_V8_SHARED_PRIVATE
#define V8_EXPORT_PRIVATE #define V8_EXPORT_PRIVATE __declspec(dllexport)
#elif USING_V8_SHARED_PRIVATE #elif USING_V8_SHARED_PRIVATE
#define V8_EXPORT_PRIVATE #define V8_EXPORT_PRIVATE __declspec(dllimport)
#else #else
#define V8_EXPORT_PRIVATE #define V8_EXPORT_PRIVATE
#endif // BUILDING_V8_SHARED #endif // BUILDING_V8_SHARED
@ -380,8 +380,8 @@ bool is_inbounds(float_t v) {
// Setup for Linux shared library export. // Setup for Linux shared library export.
#if V8_HAS_ATTRIBUTE_VISIBILITY #if V8_HAS_ATTRIBUTE_VISIBILITY
#ifdef BUILDING_V8_SHARED_PRIVATE #ifdef BUILDING_V8_SHARED_PRIVATE
#define V8_EXPORT_PRIVATE #define V8_EXPORT_PRIVATE __attribute__((visibility("default")))
#define V8_EXPORT_ENUM #define V8_EXPORT_ENUM V8_EXPORT_PRIVATE
#else #else
#define V8_EXPORT_PRIVATE #define V8_EXPORT_PRIVATE
#define V8_EXPORT_ENUM #define V8_EXPORT_ENUM

View File

@ -9,872 +9,19 @@
#ifndef V8_BASE_OPTIONAL_H_ #ifndef V8_BASE_OPTIONAL_H_
#define V8_BASE_OPTIONAL_H_ #define V8_BASE_OPTIONAL_H_
#include <type_traits> #include <optional>
#include <utility>
#include "src/base/logging.h"
namespace v8 { namespace v8 {
namespace base { namespace base {
// Specification: // These aliases are deprecated, use std::optional directly.
// http://en.cppreference.com/w/cpp/utility/optional/in_place_t
struct in_place_t {};
// Specification:
// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
struct nullopt_t {
constexpr explicit nullopt_t(int) {}
};
// Specification:
// http://en.cppreference.com/w/cpp/utility/optional/in_place
constexpr in_place_t in_place = {};
// Specification:
// http://en.cppreference.com/w/cpp/utility/optional/nullopt
constexpr nullopt_t nullopt(0);
// Forward declaration, which is referred by following helpers.
template <typename T> template <typename T>
class Optional; using Optional [[deprecated]] = std::optional<T>;
namespace internal { using std::in_place;
using std::make_optional;
template <typename T, bool = std::is_trivially_destructible<T>::value> using std::nullopt;
struct OptionalStorageBase { using std::nullopt_t;
// Initializing |empty_| here instead of using default member initializing
// to avoid errors in g++ 4.8.
constexpr OptionalStorageBase() : empty_('\0') {}
template <class... Args>
constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
: is_populated_(true), value_(std::forward<Args>(args)...) {}
// When T is not trivially destructible we must call its
// destructor before deallocating its memory.
// Note that this hides the (implicitly declared) move constructor, which
// would be used for constexpr move constructor in OptionalStorage<T>.
// It is needed iff T is trivially move constructible. However, the current
// is_trivially_{copy,move}_constructible implementation requires
// is_trivially_destructible (which looks a bug, cf:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
// http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
// necessary for this case at the moment. Please see also the destructor
// comment in "is_trivially_destructible = true" specialization below.
~OptionalStorageBase() {
if (is_populated_) value_.~T();
}
template <class... Args>
void Init(Args&&... args) {
DCHECK(!is_populated_);
::new (&value_) T(std::forward<Args>(args)...);
is_populated_ = true;
}
bool is_populated_ = false;
union {
// |empty_| exists so that the union will always be initialized, even when
// it doesn't contain a value. Union members must be initialized for the
// constructor to be 'constexpr'.
char empty_;
T value_;
};
};
template <typename T>
struct OptionalStorageBase<T, true /* trivially destructible */> {
// Initializing |empty_| here instead of using default member initializing
// to avoid errors in g++ 4.8.
constexpr OptionalStorageBase() : empty_('\0') {}
template <class... Args>
constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
: is_populated_(true), value_(std::forward<Args>(args)...) {}
// When T is trivially destructible (i.e. its destructor does nothing) there
// is no need to call it. Implicitly defined destructor is trivial, because
// both members (bool and union containing only variants which are trivially
// destructible) are trivially destructible.
// Explicitly-defaulted destructor is also trivial, but do not use it here,
// because it hides the implicit move constructor. It is needed to implement
// constexpr move constructor in OptionalStorage iff T is trivially move
// constructible. Note that, if T is trivially move constructible, the move
// constructor of OptionalStorageBase<T> is also implicitly defined and it is
// trivially move constructor. If T is not trivially move constructible,
// "not declaring move constructor without destructor declaration" here means
// "delete move constructor", which works because any move constructor of
// OptionalStorage will not refer to it in that case.
template <class... Args>
void Init(Args&&... args) {
DCHECK(!is_populated_);
::new (&value_) T(std::forward<Args>(args)...);
is_populated_ = true;
}
bool is_populated_ = false;
union {
// |empty_| exists so that the union will always be initialized, even when
// it doesn't contain a value. Union members must be initialized for the
// constructor to be 'constexpr'.
char empty_;
T value_;
};
};
// Implement conditional constexpr copy and move constructors. These are
// constexpr if is_trivially_{copy,move}_constructible<T>::value is true
// respectively. If each is true, the corresponding constructor is defined as
// "= default;", which generates a constexpr constructor (In this case,
// the condition of constexpr-ness is satisfied because the base class also has
// compiler generated constexpr {copy,move} constructors). Note that
// placement-new is prohibited in constexpr.
template <typename T, bool = std::is_trivially_copy_constructible<T>::value,
bool = std::is_trivially_move_constructible<T>::value>
struct OptionalStorage : OptionalStorageBase<T> {
// This is no trivially {copy,move} constructible case. Other cases are
// defined below as specializations.
// Accessing the members of template base class requires explicit
// declaration.
using OptionalStorageBase<T>::is_populated_;
using OptionalStorageBase<T>::value_;
using OptionalStorageBase<T>::Init;
// Inherit constructors (specifically, the in_place constructor).
using OptionalStorageBase<T>::OptionalStorageBase;
// User defined constructor deletes the default constructor.
// Define it explicitly.
OptionalStorage() = default;
OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT {
if (other.is_populated_) Init(other.value_);
}
OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT {
if (other.is_populated_) Init(std::move(other.value_));
}
};
template <typename T>
struct OptionalStorage<T, true /* trivially copy constructible */,
false /* trivially move constructible */>
: OptionalStorageBase<T> {
using OptionalStorageBase<T>::is_populated_;
using OptionalStorageBase<T>::value_;
using OptionalStorageBase<T>::Init;
using OptionalStorageBase<T>::OptionalStorageBase;
OptionalStorage() = default;
OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT = default;
OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT {
if (other.is_populated_) Init(std::move(other.value_));
}
};
template <typename T>
struct OptionalStorage<T, false /* trivially copy constructible */,
true /* trivially move constructible */>
: OptionalStorageBase<T> {
using OptionalStorageBase<T>::is_populated_;
using OptionalStorageBase<T>::value_;
using OptionalStorageBase<T>::Init;
using OptionalStorageBase<T>::OptionalStorageBase;
OptionalStorage() = default;
OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT = default;
OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT {
if (other.is_populated_) Init(other.value_);
}
};
template <typename T>
struct OptionalStorage<T, true /* trivially copy constructible */,
true /* trivially move constructible */>
: OptionalStorageBase<T> {
// If both trivially {copy,move} constructible are true, it is not necessary
// to use user-defined constructors. So, just inheriting constructors
// from the base class works.
using OptionalStorageBase<T>::OptionalStorageBase;
};
// Base class to support conditionally usable copy-/move- constructors
// and assign operators.
template <typename T>
class OptionalBase {
// This class provides implementation rather than public API, so everything
// should be hidden. Often we use composition, but we cannot in this case
// because of C++ language restriction.
protected:
constexpr OptionalBase() = default;
constexpr OptionalBase(const OptionalBase& other) V8_NOEXCEPT = default;
constexpr OptionalBase(OptionalBase&& other) V8_NOEXCEPT = default;
template <class... Args>
constexpr explicit OptionalBase(in_place_t, Args&&... args)
: storage_(in_place, std::forward<Args>(args)...) {}
// Implementation of converting constructors.
template <typename U>
explicit OptionalBase(const OptionalBase<U>& other) V8_NOEXCEPT {
if (other.storage_.is_populated_) storage_.Init(other.storage_.value_);
}
template <typename U>
explicit OptionalBase(OptionalBase<U>&& other) V8_NOEXCEPT {
if (other.storage_.is_populated_)
storage_.Init(std::move(other.storage_.value_));
}
~OptionalBase() = default;
OptionalBase& operator=(const OptionalBase& other) V8_NOEXCEPT {
CopyAssign(other);
return *this;
}
OptionalBase& operator=(OptionalBase&& other) V8_NOEXCEPT {
MoveAssign(std::move(other));
return *this;
}
template <typename U>
void CopyAssign(const OptionalBase<U>& other) {
if (other.storage_.is_populated_)
InitOrAssign(other.storage_.value_);
else
FreeIfNeeded();
}
template <typename U>
void MoveAssign(OptionalBase<U>&& other) {
if (other.storage_.is_populated_)
InitOrAssign(std::move(other.storage_.value_));
else
FreeIfNeeded();
}
template <typename U>
void InitOrAssign(U&& value) {
if (storage_.is_populated_)
storage_.value_ = std::forward<U>(value);
else
storage_.Init(std::forward<U>(value));
}
void FreeIfNeeded() {
if (!storage_.is_populated_) return;
storage_.value_.~T();
storage_.is_populated_ = false;
}
// For implementing conversion, allow access to other typed OptionalBase
// class.
template <typename U>
friend class OptionalBase;
OptionalStorage<T> storage_;
};
// The following {Copy,Move}{Constructible,Assignable} structs are helpers to
// implement constructor/assign-operator overloading. Specifically, if T is
// is not movable but copyable, Optional<T>'s move constructor should not
// participate in overload resolution. This inheritance trick implements that.
template <bool is_copy_constructible>
struct CopyConstructible {};
template <>
struct CopyConstructible<false> {
constexpr CopyConstructible() = default;
constexpr CopyConstructible(const CopyConstructible&) V8_NOEXCEPT = delete;
constexpr CopyConstructible(CopyConstructible&&) V8_NOEXCEPT = default;
CopyConstructible& operator=(const CopyConstructible&) V8_NOEXCEPT = default;
CopyConstructible& operator=(CopyConstructible&&) V8_NOEXCEPT = default;
};
template <bool is_move_constructible>
struct MoveConstructible {};
template <>
struct MoveConstructible<false> {
constexpr MoveConstructible() = default;
constexpr MoveConstructible(const MoveConstructible&) V8_NOEXCEPT = default;
constexpr MoveConstructible(MoveConstructible&&) V8_NOEXCEPT = delete;
MoveConstructible& operator=(const MoveConstructible&) V8_NOEXCEPT = default;
MoveConstructible& operator=(MoveConstructible&&) V8_NOEXCEPT = default;
};
template <bool is_copy_assignable>
struct CopyAssignable {};
template <>
struct CopyAssignable<false> {
constexpr CopyAssignable() = default;
constexpr CopyAssignable(const CopyAssignable&) V8_NOEXCEPT = default;
constexpr CopyAssignable(CopyAssignable&&) V8_NOEXCEPT = default;
CopyAssignable& operator=(const CopyAssignable&) V8_NOEXCEPT = delete;
CopyAssignable& operator=(CopyAssignable&&) V8_NOEXCEPT = default;
};
template <bool is_move_assignable>
struct MoveAssignable {};
template <>
struct MoveAssignable<false> {
constexpr MoveAssignable() = default;
constexpr MoveAssignable(const MoveAssignable&) V8_NOEXCEPT = default;
constexpr MoveAssignable(MoveAssignable&&) V8_NOEXCEPT = default;
MoveAssignable& operator=(const MoveAssignable&) V8_NOEXCEPT = default;
MoveAssignable& operator=(MoveAssignable&&) V8_NOEXCEPT = delete;
};
// Helper to conditionally enable converting constructors and assign operators.
template <typename T, typename U>
struct IsConvertibleFromOptional
: std::integral_constant<
bool, std::is_constructible<T, Optional<U>&>::value ||
std::is_constructible<T, const Optional<U>&>::value ||
std::is_constructible<T, Optional<U>&&>::value ||
std::is_constructible<T, const Optional<U>&&>::value ||
std::is_convertible<Optional<U>&, T>::value ||
std::is_convertible<const Optional<U>&, T>::value ||
std::is_convertible<Optional<U>&&, T>::value ||
std::is_convertible<const Optional<U>&&, T>::value> {};
template <typename T, typename U>
struct IsAssignableFromOptional
: std::integral_constant<
bool, IsConvertibleFromOptional<T, U>::value ||
std::is_assignable<T&, Optional<U>&>::value ||
std::is_assignable<T&, const Optional<U>&>::value ||
std::is_assignable<T&, Optional<U>&&>::value ||
std::is_assignable<T&, const Optional<U>&&>::value> {};
// Forward compatibility for C++17.
// Introduce one more deeper nested namespace to avoid leaking using std::swap.
namespace swappable_impl {
using std::swap;
struct IsSwappableImpl {
// Tests if swap can be called. Check<T&>(0) returns true_type iff swap
// is available for T. Otherwise, Check's overload resolution falls back
// to Check(...) declared below thanks to SFINAE, so returns false_type.
template <typename T>
static auto Check(int i)
-> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());
template <typename T>
static std::false_type Check(...);
};
} // namespace swappable_impl
template <typename T>
struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};
// Forward compatibility for C++20.
template <typename T>
using RemoveCvRefT =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
} // namespace internal
// On Windows, by default, empty-base class optimization does not work,
// which means even if the base class is empty struct, it still consumes one
// byte for its body. __declspec(empty_bases) enables the optimization.
// cf)
// https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
#ifdef OS_WIN
#define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
#else
#define OPTIONAL_DECLSPEC_EMPTY_BASES
#endif
// base::Optional is a Chromium version of the C++17 optional class:
// std::optional documentation:
// http://en.cppreference.com/w/cpp/utility/optional
// Chromium documentation:
// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
//
// These are the differences between the specification and the implementation:
// - Constructors do not use 'constexpr' as it is a C++14 extension.
// - 'constexpr' might be missing in some places for reasons specified locally.
// - No exceptions are thrown, because they are banned from Chromium.
// All copy/move constructors or assignment operators are marked V8_NOEXCEPT.
// - All the non-members are in the 'base' namespace instead of 'std'.
//
// Note that T cannot have a constructor T(Optional<T>) etc. Optional<T> checks
// T's constructor (specifically via IsConvertibleFromOptional), and in the
// check whether T can be constructible from Optional<T>, which is recursive
// so it does not work. As of Feb 2018, std::optional C++17 implementation in
// both clang and gcc has same limitation. MSVC SFINAE looks to have different
// behavior, but anyway it reports an error, too.
template <typename T>
class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
: public internal::OptionalBase<T>,
public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
public internal::MoveConstructible<std::is_move_constructible<T>::value>,
public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
std::is_copy_assignable<T>::value>,
public internal::MoveAssignable<std::is_move_constructible<T>::value &&
std::is_move_assignable<T>::value> {
public:
#undef OPTIONAL_DECLSPEC_EMPTY_BASES
using value_type = T;
// Defer default/copy/move constructor implementation to OptionalBase.
constexpr Optional() = default;
constexpr Optional(const Optional& other) V8_NOEXCEPT = default;
constexpr Optional(Optional&& other) V8_NOEXCEPT = default;
constexpr Optional(nullopt_t) {} // NOLINT(runtime/explicit)
// Converting copy constructor. "explicit" only if
// std::is_convertible<const U&, T>::value is false. It is implemented by
// declaring two almost same constructors, but that condition in enable_if
// is different, so that either one is chosen, thanks to SFINAE.
template <typename U,
typename std::enable_if<
std::is_constructible<T, const U&>::value &&
!internal::IsConvertibleFromOptional<T, U>::value &&
std::is_convertible<const U&, T>::value,
bool>::type = false>
Optional(const Optional<U>& other) V8_NOEXCEPT
: internal::OptionalBase<T>(other) {}
template <typename U,
typename std::enable_if<
std::is_constructible<T, const U&>::value &&
!internal::IsConvertibleFromOptional<T, U>::value &&
!std::is_convertible<const U&, T>::value,
bool>::type = false>
explicit Optional(const Optional<U>& other) V8_NOEXCEPT
: internal::OptionalBase<T>(other) {}
// Converting move constructor. Similar to converting copy constructor,
// declaring two (explicit and non-explicit) constructors.
template <typename U,
typename std::enable_if<
std::is_constructible<T, U&&>::value &&
!internal::IsConvertibleFromOptional<T, U>::value &&
std::is_convertible<U&&, T>::value,
bool>::type = false>
Optional(Optional<U>&& other) V8_NOEXCEPT
: internal::OptionalBase<T>(std::move(other)) {}
template <typename U,
typename std::enable_if<
std::is_constructible<T, U&&>::value &&
!internal::IsConvertibleFromOptional<T, U>::value &&
!std::is_convertible<U&&, T>::value,
bool>::type = false>
explicit Optional(Optional<U>&& other) V8_NOEXCEPT
: internal::OptionalBase<T>(std::move(other)) {}
template <class... Args>
constexpr explicit Optional(in_place_t, Args&&... args)
: internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
template <class U, class... Args,
class = typename std::enable_if<std::is_constructible<
value_type, std::initializer_list<U>&, Args...>::value>::type>
constexpr explicit Optional(in_place_t, std::initializer_list<U> il,
Args&&... args)
: internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
// Forward value constructor. Similar to converting constructors,
// conditionally explicit.
template <
typename U = value_type,
typename std::enable_if<
std::is_constructible<T, U&&>::value &&
!std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
!std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
std::is_convertible<U&&, T>::value,
bool>::type = false>
constexpr Optional(U&& value) // NOLINT(runtime/explicit)
: internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
template <
typename U = value_type,
typename std::enable_if<
std::is_constructible<T, U&&>::value &&
!std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
!std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
!std::is_convertible<U&&, T>::value,
bool>::type = false>
constexpr explicit Optional(U&& value)
: internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
~Optional() = default;
// Defer copy-/move- assign operator implementation to OptionalBase.
Optional& operator=(const Optional& other) V8_NOEXCEPT = default;
Optional& operator=(Optional&& other) V8_NOEXCEPT = default;
Optional& operator=(nullopt_t) {
FreeIfNeeded();
return *this;
}
// Perfect-forwarded assignment.
template <typename U>
typename std::enable_if<
!std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
std::is_constructible<T, U>::value &&
std::is_assignable<T&, U>::value &&
(!std::is_scalar<T>::value ||
!std::is_same<typename std::decay<U>::type, T>::value),
Optional&>::type
operator=(U&& value) V8_NOEXCEPT {
InitOrAssign(std::forward<U>(value));
return *this;
}
// Copy assign the state of other.
template <typename U>
typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
std::is_constructible<T, const U&>::value &&
std::is_assignable<T&, const U&>::value,
Optional&>::type
operator=(const Optional<U>& other) V8_NOEXCEPT {
CopyAssign(other);
return *this;
}
// Move assign the state of other.
template <typename U>
typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
std::is_constructible<T, U>::value &&
std::is_assignable<T&, U>::value,
Optional&>::type
operator=(Optional<U>&& other) V8_NOEXCEPT {
MoveAssign(std::move(other));
return *this;
}
constexpr const T* operator->() const {
DCHECK(storage_.is_populated_);
return &storage_.value_;
}
constexpr T* operator->() {
DCHECK(storage_.is_populated_);
return &storage_.value_;
}
constexpr const T& operator*() const& {
DCHECK(storage_.is_populated_);
return storage_.value_;
}
constexpr T& operator*() & {
DCHECK(storage_.is_populated_);
return storage_.value_;
}
constexpr const T&& operator*() const&& {
DCHECK(storage_.is_populated_);
return std::move(storage_.value_);
}
constexpr T&& operator*() && {
DCHECK(storage_.is_populated_);
return std::move(storage_.value_);
}
constexpr explicit operator bool() const { return storage_.is_populated_; }
constexpr bool has_value() const { return storage_.is_populated_; }
T& value() & {
CHECK(storage_.is_populated_);
return storage_.value_;
}
const T& value() const & {
CHECK(storage_.is_populated_);
return storage_.value_;
}
T&& value() && {
CHECK(storage_.is_populated_);
return std::move(storage_.value_);
}
const T&& value() const && {
CHECK(storage_.is_populated_);
return std::move(storage_.value_);
}
template <class U>
constexpr T value_or(U&& default_value) const & {
// TODO(mlamouri): add the following assert when possible:
// static_assert(std::is_copy_constructible<T>::value,
// "T must be copy constructible");
static_assert(std::is_convertible<U, T>::value,
"U must be convertible to T");
return storage_.is_populated_
? storage_.value_
: static_cast<T>(std::forward<U>(default_value));
}
template <class U>
constexpr T value_or(U&& default_value) && {
// TODO(mlamouri): add the following assert when possible:
// static_assert(std::is_move_constructible<T>::value,
// "T must be move constructible");
static_assert(std::is_convertible<U, T>::value,
"U must be convertible to T");
return storage_.is_populated_
? std::move(storage_.value_)
: static_cast<T>(std::forward<U>(default_value));
}
void swap(Optional& other) {
if (!storage_.is_populated_ && !other.storage_.is_populated_) return;
if (storage_.is_populated_ != other.storage_.is_populated_) {
if (storage_.is_populated_) {
other.storage_.Init(std::move(storage_.value_));
FreeIfNeeded();
} else {
storage_.Init(std::move(other.storage_.value_));
other.FreeIfNeeded();
}
return;
}
DCHECK(storage_.is_populated_ && other.storage_.is_populated_);
using std::swap;
swap(**this, *other);
}
void reset() { FreeIfNeeded(); }
template <class... Args>
T& emplace(Args&&... args) {
FreeIfNeeded();
storage_.Init(std::forward<Args>(args)...);
return storage_.value_;
}
template <class U, class... Args>
typename std::enable_if<
std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
T&>::type
emplace(std::initializer_list<U> il, Args&&... args) {
FreeIfNeeded();
storage_.Init(il, std::forward<Args>(args)...);
return storage_.value_;
}
private:
// Accessing template base class's protected member needs explicit
// declaration to do so.
using internal::OptionalBase<T>::CopyAssign;
using internal::OptionalBase<T>::FreeIfNeeded;
using internal::OptionalBase<T>::InitOrAssign;
using internal::OptionalBase<T>::MoveAssign;
using internal::OptionalBase<T>::storage_;
};
// Here after defines comparation operators. The definition follows
// http://en.cppreference.com/w/cpp/utility/optional/operator_cmp
// while bool() casting is replaced by has_value() to meet the chromium
// style guide.
template <class T, class U>
bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) {
if (lhs.has_value() != rhs.has_value()) return false;
if (!lhs.has_value()) return true;
return *lhs == *rhs;
}
template <class T, class U>
bool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) {
if (lhs.has_value() != rhs.has_value()) return true;
if (!lhs.has_value()) return false;
return *lhs != *rhs;
}
template <class T, class U>
bool operator<(const Optional<T>& lhs, const Optional<U>& rhs) {
if (!rhs.has_value()) return false;
if (!lhs.has_value()) return true;
return *lhs < *rhs;
}
template <class T, class U>
bool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) {
if (!lhs.has_value()) return true;
if (!rhs.has_value()) return false;
return *lhs <= *rhs;
}
template <class T, class U>
bool operator>(const Optional<T>& lhs, const Optional<U>& rhs) {
if (!lhs.has_value()) return false;
if (!rhs.has_value()) return true;
return *lhs > *rhs;
}
template <class T, class U>
bool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) {
if (!rhs.has_value()) return true;
if (!lhs.has_value()) return false;
return *lhs >= *rhs;
}
template <class T>
constexpr bool operator==(const Optional<T>& opt, nullopt_t) {
return !opt;
}
template <class T>
constexpr bool operator==(nullopt_t, const Optional<T>& opt) {
return !opt;
}
template <class T>
constexpr bool operator!=(const Optional<T>& opt, nullopt_t) {
return opt.has_value();
}
template <class T>
constexpr bool operator!=(nullopt_t, const Optional<T>& opt) {
return opt.has_value();
}
template <class T>
constexpr bool operator<(const Optional<T>& opt, nullopt_t) {
return false;
}
template <class T>
constexpr bool operator<(nullopt_t, const Optional<T>& opt) {
return opt.has_value();
}
template <class T>
constexpr bool operator<=(const Optional<T>& opt, nullopt_t) {
return !opt;
}
template <class T>
constexpr bool operator<=(nullopt_t, const Optional<T>& opt) {
return true;
}
template <class T>
constexpr bool operator>(const Optional<T>& opt, nullopt_t) {
return opt.has_value();
}
template <class T>
constexpr bool operator>(nullopt_t, const Optional<T>& opt) {
return false;
}
template <class T>
constexpr bool operator>=(const Optional<T>& opt, nullopt_t) {
return true;
}
template <class T>
constexpr bool operator>=(nullopt_t, const Optional<T>& opt) {
return !opt;
}
template <class T, class U>
constexpr bool operator==(const Optional<T>& opt, const U& value) {
return opt.has_value() ? *opt == value : false;
}
template <class T, class U>
constexpr bool operator==(const U& value, const Optional<T>& opt) {
return opt.has_value() ? value == *opt : false;
}
template <class T, class U>
constexpr bool operator!=(const Optional<T>& opt, const U& value) {
return opt.has_value() ? *opt != value : true;
}
template <class T, class U>
constexpr bool operator!=(const U& value, const Optional<T>& opt) {
return opt.has_value() ? value != *opt : true;
}
template <class T, class U>
constexpr bool operator<(const Optional<T>& opt, const U& value) {
return opt.has_value() ? *opt < value : true;
}
template <class T, class U>
constexpr bool operator<(const U& value, const Optional<T>& opt) {
return opt.has_value() ? value < *opt : false;
}
template <class T, class U>
constexpr bool operator<=(const Optional<T>& opt, const U& value) {
return opt.has_value() ? *opt <= value : true;
}
template <class T, class U>
constexpr bool operator<=(const U& value, const Optional<T>& opt) {
return opt.has_value() ? value <= *opt : false;
}
template <class T, class U>
constexpr bool operator>(const Optional<T>& opt, const U& value) {
return opt.has_value() ? *opt > value : false;
}
template <class T, class U>
constexpr bool operator>(const U& value, const Optional<T>& opt) {
return opt.has_value() ? value > *opt : true;
}
template <class T, class U>
constexpr bool operator>=(const Optional<T>& opt, const U& value) {
return opt.has_value() ? *opt >= value : false;
}
template <class T, class U>
constexpr bool operator>=(const U& value, const Optional<T>& opt) {
return opt.has_value() ? value >= *opt : true;
}
template <class T>
constexpr Optional<typename std::decay<T>::type> make_optional(T&& value) {
return Optional<typename std::decay<T>::type>(std::forward<T>(value));
}
template <class T, class... Args>
constexpr Optional<T> make_optional(Args&&... args) {
return Optional<T>(in_place, std::forward<Args>(args)...);
}
template <class T, class U, class... Args>
constexpr Optional<T> make_optional(std::initializer_list<U> il,
Args&&... args) {
return Optional<T>(in_place, il, std::forward<Args>(args)...);
}
// Partial specialization for a function template is not allowed. Also, it is
// not allowed to add overload function to std namespace, while it is allowed
// to specialize the template in std. Thus, swap() (kind of) overloading is
// defined in base namespace, instead.
template <class T>
typename std::enable_if<std::is_move_constructible<T>::value &&
internal::IsSwappable<T>::value>::type
swap(Optional<T>& lhs, Optional<T>& rhs) {
lhs.swap(rhs);
}
} // namespace base } // namespace base
} // namespace v8 } // namespace v8

View File

@ -190,7 +190,7 @@ void ConditionVariable::Wait(Mutex* mutex) {
} }
bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) { bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
SbTime microseconds = static_cast<SbTime>(rel_time.InMicroseconds()); int64_t microseconds = static_cast<int64_t>(rel_time.InMicroseconds());
SbConditionVariableResult result = SbConditionVariableWaitTimed( SbConditionVariableResult result = SbConditionVariableWaitTimed(
&native_handle_, &mutex->native_handle(), microseconds); &native_handle_, &mutex->native_handle(), microseconds);
DCHECK(result != kSbConditionVariableFailed); DCHECK(result != kSbConditionVariableFailed);

View File

@ -83,8 +83,6 @@ inline void* AlignedAlloc(size_t size, size_t alignment) {
// posix_memalign is not exposed in some Android versions, so we fall back to // posix_memalign is not exposed in some Android versions, so we fall back to
// memalign. See http://code.google.com/p/android/issues/detail?id=35391. // memalign. See http://code.google.com/p/android/issues/detail?id=35391.
return memalign(alignment, size); return memalign(alignment, size);
#elif V8_OS_STARBOARD
return SbMemoryAllocateAligned(alignment, size);
#else // POSIX #else // POSIX
void* ptr; void* ptr;
if (posix_memalign(&ptr, alignment, size)) ptr = nullptr; if (posix_memalign(&ptr, alignment, size)) ptr = nullptr;
@ -95,8 +93,6 @@ inline void* AlignedAlloc(size_t size, size_t alignment) {
inline void AlignedFree(void* ptr) { inline void AlignedFree(void* ptr) {
#if V8_OS_WIN #if V8_OS_WIN
_aligned_free(ptr); _aligned_free(ptr);
#elif V8_OS_STARBOARD
SbMemoryFreeAligned(ptr);
#else #else
// Using regular Free() is not correct in general. For most platforms, // Using regular Free() is not correct in general. For most platforms,
// including V8_LIBC_BIONIC, it is though. // including V8_LIBC_BIONIC, it is though.

View File

@ -967,6 +967,7 @@ void OS::PrintError(const char* format, ...) {
va_start(args, format); va_start(args, format);
VPrintError(format, args); VPrintError(format, args);
va_end(args); va_end(args);
fflush(stderr);
} }

View File

@ -6,6 +6,9 @@
// abstraction layer for Cobalt, an HTML5 container used mainly by YouTube // abstraction layer for Cobalt, an HTML5 container used mainly by YouTube
// apps in the living room. // apps in the living room.
#include <stdio.h>
#include <sys/mman.h>
#include "src/base/lazy-instance.h" #include "src/base/lazy-instance.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
@ -16,10 +19,9 @@
#include "starboard/common/condition_variable.h" #include "starboard/common/condition_variable.h"
#include "starboard/common/log.h" #include "starboard/common/log.h"
#include "starboard/common/string.h" #include "starboard/common/string.h"
#include "starboard/common/time.h"
#include "starboard/configuration.h" #include "starboard/configuration.h"
#include "starboard/configuration_constants.h" #include "starboard/configuration_constants.h"
#include "starboard/memory.h"
#include "starboard/time.h"
#include "starboard/time_zone.h" #include "starboard/time_zone.h"
namespace v8 { namespace v8 {
@ -82,18 +84,11 @@ void OS::Initialize(AbortMode abort_mode, const char* const gc_fake_mmap) {
} }
int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
#if SB_API_VERSION >= 12 const int64_t us_time = starboard::CurrentMonotonicThreadTime();
if (!SbTimeIsTimeThreadNowSupported()) return -1; if (us_time == 0) return -1;
#endif *secs = us_time / TimeConstants::kMicroSecondsPerSecond;
*usecs = us_time % TimeConstants::kMicroSecondsPerSecond;
#if SB_API_VERSION >= 12 || SB_HAS(TIME_THREAD_NOW)
SbTimeMonotonic thread_now = SbTimeGetMonotonicThreadNow();
*secs = thread_now / kSbTimeSecond;
*usecs = thread_now % kSbTimeSecond;
return 0; return 0;
#else
return -1;
#endif
} }
double OS::TimeCurrentMillis() { return Time::Now().ToJsTime(); } double OS::TimeCurrentMillis() { return Time::Now().ToJsTime(); }
@ -130,13 +125,13 @@ void OS::SetRandomMmapSeed(int64_t seed) { SB_NOTIMPLEMENTED(); }
void* OS::GetRandomMmapAddr() { return nullptr; } void* OS::GetRandomMmapAddr() { return nullptr; }
void* Allocate(void* address, size_t size, OS::MemoryPermission access) { void* Allocate(void* address, size_t size, OS::MemoryPermission access) {
SbMemoryMapFlags sb_flags; int prot_flags;
switch (access) { switch (access) {
case OS::MemoryPermission::kNoAccess: case OS::MemoryPermission::kNoAccess:
sb_flags = SbMemoryMapFlags(0); prot_flags = PROT_NONE;
break; break;
case OS::MemoryPermission::kReadWrite: case OS::MemoryPermission::kReadWrite:
sb_flags = SbMemoryMapFlags(kSbMemoryMapProtectReadWrite); prot_flags = PROT_READ | PROT_WRITE;
break; break;
default: default:
SB_LOG(ERROR) << "The requested memory allocation access is not" SB_LOG(ERROR) << "The requested memory allocation access is not"
@ -144,8 +139,8 @@ void* Allocate(void* address, size_t size, OS::MemoryPermission access) {
<< static_cast<int>(access); << static_cast<int>(access);
return nullptr; return nullptr;
} }
void* result = SbMemoryMap(size, sb_flags, "v8::Base::Allocate"); void* result = mmap(nullptr, size, prot_flags, MAP_PRIVATE | MAP_ANON, -1, 0);
if (result == SB_MEMORY_MAP_FAILED) { if (result == MAP_FAILED) {
return nullptr; return nullptr;
} }
return result; return result;
@ -188,30 +183,29 @@ void* OS::Allocate(void* address, size_t size, size_t alignment,
// static // static
void OS::Free(void* address, const size_t size) { void OS::Free(void* address, const size_t size) {
CHECK(SbMemoryUnmap(address, size)); CHECK_EQ(munmap(address, size), 0);
} }
// static // static
void OS::Release(void* address, size_t size) { void OS::Release(void* address, size_t size) {
CHECK(SbMemoryUnmap(address, size)); CHECK_EQ(munmap(address, size), 0);
} }
// static // static
bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) { bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) {
SbMemoryMapFlags new_protection; int new_protection;
switch (access) { switch (access) {
case OS::MemoryPermission::kNoAccess: case OS::MemoryPermission::kNoAccess:
new_protection = SbMemoryMapFlags(0); new_protection = PROT_NONE;
break; break;
case OS::MemoryPermission::kRead: case OS::MemoryPermission::kRead:
new_protection = SbMemoryMapFlags(kSbMemoryMapProtectRead); new_protection = PROT_READ;
case OS::MemoryPermission::kReadWrite: case OS::MemoryPermission::kReadWrite:
new_protection = SbMemoryMapFlags(kSbMemoryMapProtectReadWrite); new_protection = PROT_READ | PROT_WRITE;
break; break;
case OS::MemoryPermission::kReadExecute: case OS::MemoryPermission::kReadExecute:
#if SB_CAN(MAP_EXECUTABLE_MEMORY) #if SB_CAN(MAP_EXECUTABLE_MEMORY)
new_protection = new_protection = PROT_READ | PROT_EXEC;
SbMemoryMapFlags(kSbMemoryMapProtectRead | kSbMemoryMapProtectExec);
#else #else
UNREACHABLE(); UNREACHABLE();
#endif #endif
@ -220,7 +214,7 @@ bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) {
// All other types are not supported by Starboard. // All other types are not supported by Starboard.
return false; return false;
} }
return SbMemoryProtect(address, size, new_protection); return mprotect(address, size, new_protection) == 0;
} }
// static // static
@ -348,7 +342,7 @@ int OS::SNPrintF(char* str, int length, const char* format, ...) {
} }
int OS::VSNPrintF(char* str, int length, const char* format, va_list args) { int OS::VSNPrintF(char* str, int length, const char* format, va_list args) {
int n = SbStringFormat(str, length, format, args); int n = vsnprintf(str, length, format, args);
if (n < 0 || n >= length) { if (n < 0 || n >= length) {
// If the length is zero, the assignment fails. // If the length is zero, the assignment fails.
if (length > 0) str[length - 1] = '\0'; if (length > 0) str[length - 1] = '\0';
@ -363,7 +357,7 @@ int OS::VSNPrintF(char* str, int length, const char* format, va_list args) {
// //
void OS::StrNCpy(char* dest, int length, const char* src, size_t n) { void OS::StrNCpy(char* dest, int length, const char* src, size_t n) {
SbStringCopy(dest, src, n); strncpy(dest, src, n);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -448,14 +442,18 @@ class StarboardDefaultTimezoneCache : public StarboardTimezoneCache {
return SbTimeZoneGetName(); return SbTimeZoneGetName();
} }
double LocalTimeOffset(double time_ms, bool is_utc) override { double LocalTimeOffset(double time_ms, bool is_utc) override {
// SbTimeZOneGetCurrent returns an offset west of Greenwich, which has the // SbTimeZoneGetCurrent returns an offset west of Greenwich, which has the
// opposite sign V8 expects. // opposite sign V8 expects.
// The starboard function returns offset in minutes. We convert to return // The starboard function returns offset in minutes. We convert to return
// value in milliseconds. // value in milliseconds.
return SbTimeZoneGetCurrent() * 60.0 * msPerSecond * (-1); return SbTimeZoneGetCurrent() * 60.0 * msPerSecond * (-1);
} }
double DaylightSavingsOffset(double time_ms) override { double DaylightSavingsOffset(double time_ms) override {
EzTimeValue value = EzTimeValueFromSbTime(SbTimeGetNow()); int64_t posix_microseconds = starboard::CurrentPosixTime();
EzTimeValue value = {
posix_microseconds / TimeConstants::kMicroSecondsPerSecond,
(int32_t)(posix_microseconds % TimeConstants::kMicroSecondsPerSecond)
};
EzTimeExploded ez_exploded; EzTimeExploded ez_exploded;
bool result = bool result =
EzTimeValueExplode(&value, kEzTimeZoneLocal, &ez_exploded, NULL); EzTimeValueExplode(&value, kEzTimeZoneLocal, &ez_exploded, NULL);
@ -489,6 +487,12 @@ bool OS::DiscardSystemPages(void* address, size_t size) {
return true; return true;
} }
// static
Stack::StackSlot Stack::GetStackStart() {
SB_NOTIMPLEMENTED();
return nullptr;
}
// static // static
Stack::StackSlot Stack::GetCurrentStackPosition() { Stack::StackSlot Stack::GetCurrentStackPosition() {
void* addresses[kStackSize]; void* addresses[kStackSize];

View File

@ -702,6 +702,7 @@ void OS::PrintError(const char* format, ...) {
va_start(args, format); va_start(args, format);
VPrintError(format, args); VPrintError(format, args);
va_end(args); va_end(args);
fflush(stderr);
} }

View File

@ -170,7 +170,7 @@ void Semaphore::Signal() { native_handle_.Put(); }
void Semaphore::Wait() { native_handle_.Take(); } void Semaphore::Wait() { native_handle_.Take(); }
bool Semaphore::WaitFor(const TimeDelta& rel_time) { bool Semaphore::WaitFor(const TimeDelta& rel_time) {
SbTime microseconds = rel_time.InMicroseconds(); int64_t microseconds = rel_time.InMicroseconds();
return native_handle_.TakeWait(microseconds); return native_handle_.TakeWait(microseconds);
} }

View File

@ -22,6 +22,10 @@
#include <zircon/threads.h> #include <zircon/threads.h>
#endif #endif
#if V8_OS_STARBOARD
#include <sys/time.h>
#endif // V8_OS_STARBOARD
#include <cstring> #include <cstring>
#include <ostream> #include <ostream>
@ -41,7 +45,7 @@
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#if V8_OS_STARBOARD #if V8_OS_STARBOARD
#include "starboard/time.h" #include "starboard/common/time.h"
#endif #endif
namespace { namespace {
@ -402,7 +406,7 @@ FILETIME Time::ToFiletime() const {
return ft; return ft;
} }
#elif V8_OS_POSIX #elif V8_OS_POSIX || V8_OS_STARBOARD
Time Time::Now() { Time Time::Now() {
struct timeval tv; struct timeval tv;
@ -482,13 +486,7 @@ struct timeval Time::ToTimeval() const {
return tv; return tv;
} }
#elif V8_OS_STARBOARD #endif // V8_OS_POSIX || V8_OS_STARBOARD
Time Time::Now() { return Time(SbTimeToPosix(SbTimeGetNow())); }
Time Time::NowFromSystemTime() { return Now(); }
#endif // V8_OS_STARBOARD
Time Time::FromJsTime(double ms_since_epoch) { Time Time::FromJsTime(double ms_since_epoch) {
// The epoch is a valid time, so this constructor doesn't interpret // The epoch is a valid time, so this constructor doesn't interpret
@ -753,7 +751,7 @@ TimeTicks TimeTicks::Now() {
#elif V8_OS_POSIX #elif V8_OS_POSIX
ticks = ClockNow(CLOCK_MONOTONIC); ticks = ClockNow(CLOCK_MONOTONIC);
#elif V8_OS_STARBOARD #elif V8_OS_STARBOARD
ticks = SbTimeGetMonotonicNow(); ticks = starboard::CurrentMonotonicTime();
#else #else
#error platform does not implement TimeTicks::Now. #error platform does not implement TimeTicks::Now.
#endif // V8_OS_DARWIN #endif // V8_OS_DARWIN
@ -780,13 +778,7 @@ bool TimeTicks::IsHighResolution() {
bool ThreadTicks::IsSupported() { bool ThreadTicks::IsSupported() {
#if V8_OS_STARBOARD #if V8_OS_STARBOARD
#if SB_API_VERSION >= 12 return starboard::CurrentMonotonicThreadTime() != 0;
return SbTimeIsTimeThreadNowSupported();
#elif SB_HAS(TIME_THREAD_NOW)
return true;
#else
return false;
#endif
#elif defined(__PASE__) #elif defined(__PASE__)
// Thread CPU time accounting is unavailable in PASE // Thread CPU time accounting is unavailable in PASE
return false; return false;
@ -803,15 +795,10 @@ bool ThreadTicks::IsSupported() {
ThreadTicks ThreadTicks::Now() { ThreadTicks ThreadTicks::Now() {
#if V8_OS_STARBOARD #if V8_OS_STARBOARD
#if SB_API_VERSION >= 12 const int64_t now = starboard::CurrentMonotonicThreadTime();
if (SbTimeIsTimeThreadNowSupported()) if (now != 0)
return ThreadTicks(SbTimeGetMonotonicThreadNow()); return ThreadTicks(now);
UNREACHABLE(); UNREACHABLE();
#elif SB_HAS(TIME_THREAD_NOW)
return ThreadTicks(SbTimeGetMonotonicThreadNow());
#else
UNREACHABLE();
#endif
#elif V8_OS_DARWIN #elif V8_OS_DARWIN
return ThreadTicks(ComputeThreadTicks()); return ThreadTicks(ComputeThreadTicks());
#elif V8_OS_FUCHSIA #elif V8_OS_FUCHSIA

View File

@ -422,6 +422,9 @@ Tagged<Smi> BaselineCompiler::IndexAsSmi(int operand_index) {
Tagged<Smi> BaselineCompiler::IntAsSmi(int operand_index) { Tagged<Smi> BaselineCompiler::IntAsSmi(int operand_index) {
return Smi::FromInt(Int(operand_index)); return Smi::FromInt(Int(operand_index));
} }
Tagged<Smi> BaselineCompiler::UintAsSmi(int operand_index) {
return Smi::FromInt(Uint(operand_index));
}
Tagged<Smi> BaselineCompiler::Flag8AsSmi(int operand_index) { Tagged<Smi> BaselineCompiler::Flag8AsSmi(int operand_index) {
return Smi::FromInt(Flag8(operand_index)); return Smi::FromInt(Flag8(operand_index));
} }
@ -647,6 +650,8 @@ constexpr static bool BuiltinMayDeopt(Builtin id) {
case Builtin::kBaselineOutOfLinePrologue: case Builtin::kBaselineOutOfLinePrologue:
case Builtin::kIncBlockCounter: case Builtin::kIncBlockCounter:
case Builtin::kToObject: case Builtin::kToObject:
case Builtin::kStoreScriptContextSlotBaseline:
case Builtin::kStoreCurrentScriptContextSlotBaseline:
// This one explicitly skips the construct if the debugger is enabled. // This one explicitly skips the construct if the debugger is enabled.
case Builtin::kFindNonDefaultConstructorOrConstruct: case Builtin::kFindNonDefaultConstructorOrConstruct:
return false; return false;
@ -812,6 +817,30 @@ void BaselineCompiler::VisitStaCurrentContextSlot() {
context, Context::OffsetOfElementAt(Index(0)), value); context, Context::OffsetOfElementAt(Index(0)), value);
} }
void BaselineCompiler::VisitStaScriptContextSlot() {
Register value = WriteBarrierDescriptor::ValueRegister();
Register context = WriteBarrierDescriptor::ObjectRegister();
DCHECK(!AreAliased(value, context, kInterpreterAccumulatorRegister));
__ Move(value, kInterpreterAccumulatorRegister);
LoadRegister(context, 0);
SaveAccumulatorScope accumulator_scope(this, &basm_);
CallBuiltin<Builtin::kStoreScriptContextSlotBaseline>(
context, // context
value, // value
IndexAsSmi(1), // slot
UintAsTagged(2)); // depth
}
void BaselineCompiler::VisitStaCurrentScriptContextSlot() {
Register value = WriteBarrierDescriptor::ValueRegister();
DCHECK(!AreAliased(value, kInterpreterAccumulatorRegister));
SaveAccumulatorScope accumulator_scope(this, &basm_);
__ Move(value, kInterpreterAccumulatorRegister);
CallBuiltin<Builtin::kStoreCurrentScriptContextSlotBaseline>(
value, // value
IndexAsSmi(0)); // slot
}
void BaselineCompiler::VisitLdaLookupSlot() { void BaselineCompiler::VisitLdaLookupSlot() {
CallRuntime(Runtime::kLoadLookupSlot, Constant<Name>(0)); CallRuntime(Runtime::kLoadLookupSlot, Constant<Name>(0));
} }

View File

@ -91,6 +91,7 @@ class BaselineCompiler {
Tagged<TaggedIndex> UintAsTagged(int operand_index); Tagged<TaggedIndex> UintAsTagged(int operand_index);
Tagged<Smi> IndexAsSmi(int operand_index); Tagged<Smi> IndexAsSmi(int operand_index);
Tagged<Smi> IntAsSmi(int operand_index); Tagged<Smi> IntAsSmi(int operand_index);
Tagged<Smi> UintAsSmi(int operand_index);
Tagged<Smi> Flag8AsSmi(int operand_index); Tagged<Smi> Flag8AsSmi(int operand_index);
Tagged<Smi> Flag16AsSmi(int operand_index); Tagged<Smi> Flag16AsSmi(int operand_index);

View File

@ -151,7 +151,8 @@ void Accessors::ArrayLengthGetter(
RCS_SCOPE(isolate, RuntimeCallCounterId::kArrayLengthGetter); RCS_SCOPE(isolate, RuntimeCallCounterId::kArrayLengthGetter);
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
HandleScope scope(isolate); HandleScope scope(isolate);
Tagged<JSArray> holder = JSArray::cast(*Utils::OpenHandle(*info.Holder())); Tagged<JSArray> holder =
JSArray::cast(*Utils::OpenDirectHandle(*info.Holder()));
Tagged<Object> result = holder->length(); Tagged<Object> result = holder->length();
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
} }
@ -163,7 +164,7 @@ void Accessors::ArrayLengthSetter(
RCS_SCOPE(isolate, RuntimeCallCounterId::kArrayLengthSetter); RCS_SCOPE(isolate, RuntimeCallCounterId::kArrayLengthSetter);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(Object::SameValue(*Utils::OpenHandle(*name), DCHECK(Object::SameValue(*Utils::OpenDirectHandle(*name),
ReadOnlyRoots(isolate).length_string())); ReadOnlyRoots(isolate).length_string()));
Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder()); Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder());
@ -233,7 +234,7 @@ void Accessors::ModuleNamespaceEntryGetter(
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate); HandleScope scope(isolate);
Tagged<JSModuleNamespace> holder = Tagged<JSModuleNamespace> holder =
JSModuleNamespace::cast(*Utils::OpenHandle(*info.Holder())); JSModuleNamespace::cast(*Utils::OpenDirectHandle(*info.Holder()));
Handle<Object> result; Handle<Object> result;
if (holder->GetExport(isolate, Handle<String>::cast(Utils::OpenHandle(*name))) if (holder->GetExport(isolate, Handle<String>::cast(Utils::OpenHandle(*name)))
.ToHandle(&result)) { .ToHandle(&result)) {
@ -281,12 +282,13 @@ void Accessors::StringLengthGetter(
// v8::Object, but internally we have callbacks on entities which are higher // v8::Object, but internally we have callbacks on entities which are higher
// in the hierarchy, in this case for String values. // in the hierarchy, in this case for String values.
Tagged<Object> value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This())); Tagged<Object> value =
*Utils::OpenDirectHandle(*v8::Local<v8::Value>(info.This()));
if (!IsString(value)) { if (!IsString(value)) {
// Not a string value. That means that we either got a String wrapper or // Not a string value. That means that we either got a String wrapper or
// a Value with a String wrapper in its prototype chain. // a Value with a String wrapper in its prototype chain.
value = value = JSPrimitiveWrapper::cast(*Utils::OpenDirectHandle(*info.Holder()))
JSPrimitiveWrapper::cast(*Utils::OpenHandle(*info.Holder()))->value(); ->value();
} }
Tagged<Object> result = Smi::FromInt(String::cast(value)->length()); Tagged<Object> result = Smi::FromInt(String::cast(value)->length());
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));

View File

@ -930,7 +930,7 @@ void ResetFeedbackVectorOsrUrgency(MacroAssembler* masm,
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) { void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
UseScratchRegisterScope temps(masm); UseScratchRegisterScope temps(masm);
// Need a few extra registers // Need a few extra registers
temps.Include({r4, r8, r9}); temps.Include({r4, r5, r8, r9});
auto descriptor = auto descriptor =
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue); Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
@ -943,7 +943,11 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
FieldMemOperand(closure, JSFunction::kFeedbackCellOffset)); FieldMemOperand(closure, JSFunction::kFeedbackCellOffset));
__ ldr(feedback_vector, __ ldr(feedback_vector,
FieldMemOperand(feedback_cell, FeedbackCell::kValueOffset)); FieldMemOperand(feedback_cell, FeedbackCell::kValueOffset));
__ AssertFeedbackVector(feedback_vector); {
UseScratchRegisterScope temps(masm);
Register temporary = temps.Acquire();
__ AssertFeedbackVector(feedback_vector, temporary);
}
// Check the tiering state. // Check the tiering state.
Label flags_need_processing; Label flags_need_processing;

View File

@ -491,9 +491,8 @@ static void GetSharedFunctionInfoBytecodeOrBaseline(
&done); &done);
} }
__ LoadTrustedPointerField( __ LoadProtectedPointerField(
bytecode, FieldMemOperand(data, InterpreterData::kBytecodeArrayOffset), bytecode, FieldMemOperand(data, InterpreterData::kBytecodeArrayOffset));
kBytecodeArrayIndirectPointerTag);
__ Bind(&done); __ Bind(&done);
__ IsObjectType(bytecode, scratch1, scratch1, BYTECODE_ARRAY_TYPE); __ IsObjectType(bytecode, scratch1, scratch1, BYTECODE_ARRAY_TYPE);
@ -1557,7 +1556,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(
__ Move(x2, kInterpreterBytecodeArrayRegister); __ Move(x2, kInterpreterBytecodeArrayRegister);
static_assert(kJavaScriptCallCodeStartRegister == x2, "ABI mismatch"); static_assert(kJavaScriptCallCodeStartRegister == x2, "ABI mismatch");
__ ReplaceClosureCodeWithOptimizedCode(x2, closure); __ ReplaceClosureCodeWithOptimizedCode(x2, closure);
__ JumpCodeObject(x2); __ JumpCodeObject(x2, kJSEntrypointTag);
__ bind(&install_baseline_code); __ bind(&install_baseline_code);
__ GenerateTailCallToReturnedCode(Runtime::kInstallBaselineCode); __ GenerateTailCallToReturnedCode(Runtime::kInstallBaselineCode);
@ -2026,9 +2025,9 @@ static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
kInterpreterDispatchTableRegister, INTERPRETER_DATA_TYPE); kInterpreterDispatchTableRegister, INTERPRETER_DATA_TYPE);
__ B(ne, &builtin_trampoline); __ B(ne, &builtin_trampoline);
__ LoadCodePointerField( __ LoadProtectedPointerField(
x1, FieldMemOperand(x1, InterpreterData::kInterpreterTrampolineOffset)); x1, FieldMemOperand(x1, InterpreterData::kInterpreterTrampolineOffset));
__ LoadCodeInstructionStart(x1, x1); __ LoadCodeInstructionStart(x1, x1, kJSEntrypointTag);
__ B(&trampoline_loaded); __ B(&trampoline_loaded);
__ Bind(&builtin_trampoline); __ Bind(&builtin_trampoline);
@ -2280,17 +2279,17 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source,
// Load deoptimization data from the code object. // Load deoptimization data from the code object.
// <deopt_data> = <code>[#deoptimization_data_offset] // <deopt_data> = <code>[#deoptimization_data_offset]
__ LoadTaggedField( __ LoadProtectedPointerField(
x1, x1,
FieldMemOperand(x0, Code::kDeoptimizationDataOrInterpreterDataOffset)); FieldMemOperand(x0, Code::kDeoptimizationDataOrInterpreterDataOffset));
// Load the OSR entrypoint offset from the deoptimization data. // Load the OSR entrypoint offset from the deoptimization data.
// <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset] // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
__ SmiUntagField( __ SmiUntagField(
x1, FieldMemOperand(x1, FixedArray::OffsetOfElementAt( x1, FieldMemOperand(x1, TrustedFixedArray::OffsetOfElementAt(
DeoptimizationData::kOsrPcOffsetIndex))); DeoptimizationData::kOsrPcOffsetIndex)));
__ LoadCodeInstructionStart(x0, x0); __ LoadCodeInstructionStart(x0, x0, kJSEntrypointTag);
// Compute the target address = code_entry + osr_offset // Compute the target address = code_entry + osr_offset
// <entry_addr> = <code_entry> + <osr_offset> // <entry_addr> = <code_entry> + <osr_offset>
@ -5509,7 +5508,7 @@ void Generate_BaselineOrInterpreterEntry(MacroAssembler* masm,
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
__ CallCFunction(get_baseline_pc, 3, 0); __ CallCFunction(get_baseline_pc, 3, 0);
} }
__ LoadCodeInstructionStart(code_obj, code_obj); __ LoadCodeInstructionStart(code_obj, code_obj, kJSEntrypointTag);
__ Add(code_obj, code_obj, kReturnRegister0); __ Add(code_obj, code_obj, kReturnRegister0);
__ Pop(kInterpreterAccumulatorRegister, padreg); __ Pop(kInterpreterAccumulatorRegister, padreg);

View File

@ -243,7 +243,10 @@ type IndirectPointer
generates 'TNode<IndirectPointerHandleT>' generates 'TNode<IndirectPointerHandleT>'
constexpr 'IndirectPointerHandle'; constexpr 'IndirectPointerHandle';
// TODO(saelo): implement accessors and type checkers for these fields. // TODO(saelo): implement accessors and type checkers for these fields.
type IndirectPointer<To: type> extends IndirectPointer; type IndirectPointer<To : type extends ExposedTrustedObject> extends
IndirectPointer;
type ProtectedPointer extends Tagged;
type ProtectedPointer<To : type extends TrustedObject> extends ProtectedPointer;
extern class InstructionStream extends TrustedObject; extern class InstructionStream extends TrustedObject;
type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>'; type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>';
@ -419,6 +422,7 @@ extern enum MessageTemplate {
kTypedArraySetOffsetOutOfBounds, kTypedArraySetOffsetOutOfBounds,
kInvalidArgument, kInvalidArgument,
kInvalidRegExpExecResult, kInvalidRegExpExecResult,
kInvalidSizeValue,
kRegExpNonRegExp, kRegExpNonRegExp,
kRegExpNonObject, kRegExpNonObject,
kPromiseNonCallable, kPromiseNonCallable,
@ -477,6 +481,7 @@ extern enum MessageTemplate {
kIteratorResultNotAnObject, kIteratorResultNotAnObject,
kFlattenPastSafeLength, kFlattenPastSafeLength,
kStrictReadOnlyProperty, kStrictReadOnlyProperty,
kInvalidUsingInForInLoop,
... ...
} }

View File

@ -413,8 +413,10 @@ TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) { TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) {
auto value = Parameter<Object>(Descriptor::kValue); auto value = Parameter<Object>(Descriptor::kValue);
auto context = Parameter<Context>(Descriptor::kContext); auto context = Parameter<Context>(Descriptor::kContext);
// Restart in Rethrow mode, as this exception was already thrown and we don't
// want to trigger a second debug break event or change the message location.
AsyncGeneratorAwaitResumeClosure(context, value, AsyncGeneratorAwaitResumeClosure(context, value,
JSAsyncGeneratorObject::kThrow); JSAsyncGeneratorObject::kRethrow);
} }
TF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) { TF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) {

View File

@ -2782,9 +2782,10 @@ TNode<Word32T> WeakCollectionsBuiltinsAssembler::ShouldShrink(
TNode<IntPtrT> WeakCollectionsBuiltinsAssembler::ValueIndexFromKeyIndex( TNode<IntPtrT> WeakCollectionsBuiltinsAssembler::ValueIndexFromKeyIndex(
TNode<IntPtrT> key_index) { TNode<IntPtrT> key_index) {
return IntPtrAdd(key_index, return IntPtrAdd(
IntPtrConstant(EphemeronHashTable::ShapeT::kEntryValueIndex - key_index,
EphemeronHashTable::kEntryKeyIndex)); IntPtrConstant(EphemeronHashTable::TodoShape::kEntryValueIndex -
EphemeronHashTable::kEntryKeyIndex));
} }
TF_BUILTIN(WeakMapConstructor, WeakCollectionsBuiltinsAssembler) { TF_BUILTIN(WeakMapConstructor, WeakCollectionsBuiltinsAssembler) {

View File

@ -373,12 +373,8 @@ TNode<JSObject> ConstructorBuiltinsAssembler::FastNewObject(
} }
BIND(&allocate_properties); BIND(&allocate_properties);
{ {
if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { properties =
properties = AllocatePropertyDictionary(PropertyDictionary::kInitialCapacity);
AllocateSwissNameDictionary(SwissNameDictionary::kInitialCapacity);
} else {
properties = AllocateNameDictionary(NameDictionary::kInitialCapacity);
}
Goto(&instantiate_map); Goto(&instantiate_map);
} }

View File

@ -665,7 +665,9 @@ namespace internal {
TFH(StoreGlobalICTrampoline, StoreGlobal) \ TFH(StoreGlobalICTrampoline, StoreGlobal) \
TFH(StoreGlobalICBaseline, StoreGlobalBaseline) \ TFH(StoreGlobalICBaseline, StoreGlobalBaseline) \
TFH(StoreIC, StoreWithVector) \ TFH(StoreIC, StoreWithVector) \
TFH(StoreIC_Megamorphic, StoreWithVector) \
TFH(StoreICTrampoline, Store) \ TFH(StoreICTrampoline, Store) \
TFH(StoreICTrampoline_Megamorphic, Store) \
TFH(StoreICBaseline, StoreBaseline) \ TFH(StoreICBaseline, StoreBaseline) \
TFH(DefineNamedOwnIC, StoreWithVector) \ TFH(DefineNamedOwnIC, StoreWithVector) \
TFH(DefineNamedOwnICTrampoline, Store) \ TFH(DefineNamedOwnICTrampoline, Store) \
@ -892,8 +894,8 @@ namespace internal {
kMatchInfo) \ kMatchInfo) \
TFS(RegExpExecInternal, NeedsContext::kYes, kRegExp, kString, kLastIndex, \ TFS(RegExpExecInternal, NeedsContext::kYes, kRegExp, kString, kLastIndex, \
kMatchInfo) \ kMatchInfo) \
ASM(RegExpInterpreterTrampoline, CCall) \ ASM(RegExpInterpreterTrampoline, RegExpTrampoline) \
ASM(RegExpExperimentalTrampoline, CCall) \ ASM(RegExpExperimentalTrampoline, RegExpTrampoline) \
\ \
/* Set */ \ /* Set */ \
TFS(FindOrderedHashSetEntry, NeedsContext::kYes, kTable, kKey) \ TFS(FindOrderedHashSetEntry, NeedsContext::kYes, kTable, kKey) \
@ -2029,14 +2031,6 @@ namespace internal {
BUILTIN_LIST(V, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \ BUILTIN_LIST(V, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN) IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
#define BUILTIN_LIST_A(V) \
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
IGNORE_BUILTIN, IGNORE_BUILTIN, V)
#define BUILTIN_LIST_TFS(V) \
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, V, \
IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
#define BUILTIN_LIST_TFJ(V) \ #define BUILTIN_LIST_TFJ(V) \
BUILTIN_LIST(IGNORE_BUILTIN, V, IGNORE_BUILTIN, IGNORE_BUILTIN, \ BUILTIN_LIST(IGNORE_BUILTIN, V, IGNORE_BUILTIN, IGNORE_BUILTIN, \
IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN) IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
@ -2045,6 +2039,22 @@ namespace internal {
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, V, IGNORE_BUILTIN, \ BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, V, IGNORE_BUILTIN, \
IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN) IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
#define BUILTIN_LIST_TFS(V) \
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, V, \
IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
#define BUILTIN_LIST_TFH(V) \
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
V, IGNORE_BUILTIN, IGNORE_BUILTIN)
#define BUILTIN_LIST_BCH(V) \
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
IGNORE_BUILTIN, V, IGNORE_BUILTIN)
#define BUILTIN_LIST_A(V) \
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
IGNORE_BUILTIN, IGNORE_BUILTIN, V)
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -106,6 +106,9 @@ void GeneratorBuiltinsAssembler::InnerResume(
case JSGeneratorObject::kThrow: case JSGeneratorObject::kThrow:
builtin_result = CallRuntime(Runtime::kThrow, context, value); builtin_result = CallRuntime(Runtime::kThrow, context, value);
break; break;
case JSGeneratorObject::kRethrow:
// Currently only async generators use this mode.
UNREACHABLE();
} }
args->PopAndReturn(builtin_result); args->PopAndReturn(builtin_result);
} }

View File

@ -101,10 +101,20 @@ void Builtins::Generate_StoreIC(compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state); AccessorAssembler assembler(state);
assembler.GenerateStoreIC(); assembler.GenerateStoreIC();
} }
void Builtins::Generate_StoreIC_Megamorphic(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateStoreIC_Megamorphic();
}
void Builtins::Generate_StoreICTrampoline(compiler::CodeAssemblerState* state) { void Builtins::Generate_StoreICTrampoline(compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state); AccessorAssembler assembler(state);
assembler.GenerateStoreICTrampoline(); assembler.GenerateStoreICTrampoline();
} }
void Builtins::Generate_StoreICTrampoline_Megamorphic(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateStoreICTrampoline_Megamorphic();
}
void Builtins::Generate_StoreICBaseline(compiler::CodeAssemblerState* state) { void Builtins::Generate_StoreICBaseline(compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state); AccessorAssembler assembler(state);
assembler.GenerateStoreICBaseline(); assembler.GenerateStoreICBaseline();

View File

@ -137,10 +137,10 @@ class WriteBarrierCodeStubAssembler : public CodeStubAssembler {
} }
TNode<BoolT> IsPageFlagSet(TNode<IntPtrT> object, int mask) { TNode<BoolT> IsPageFlagSet(TNode<IntPtrT> object, int mask) {
TNode<IntPtrT> page = PageFromAddress(object); TNode<IntPtrT> header = PageHeaderFromAddress(object);
TNode<IntPtrT> flags = UncheckedCast<IntPtrT>( TNode<IntPtrT> flags = UncheckedCast<IntPtrT>(
Load(MachineType::Pointer(), page, Load(MachineType::Pointer(), header,
IntPtrConstant(BasicMemoryChunk::kFlagsOffset))); IntPtrConstant(MemoryChunkLayout::kFlagsOffset)));
return WordNotEqual(WordAnd(flags, IntPtrConstant(mask)), return WordNotEqual(WordAnd(flags, IntPtrConstant(mask)),
IntPtrConstant(0)); IntPtrConstant(0));
} }
@ -156,8 +156,8 @@ class WriteBarrierCodeStubAssembler : public CodeStubAssembler {
void GetMarkBit(TNode<IntPtrT> object, TNode<IntPtrT>* cell, void GetMarkBit(TNode<IntPtrT> object, TNode<IntPtrT>* cell,
TNode<IntPtrT>* mask) { TNode<IntPtrT>* mask) {
TNode<IntPtrT> page = PageFromAddress(object); TNode<IntPtrT> page = PageFromAddress(object);
TNode<IntPtrT> bitmap = TNode<IntPtrT> bitmap = IntPtrAdd(
IntPtrAdd(page, IntPtrConstant(MemoryChunk::kMarkingBitmapOffset)); page, IntPtrConstant(MemoryChunkLayout::kMarkingBitmapOffset));
{ {
// Temp variable to calculate cell offset in bitmap. // Temp variable to calculate cell offset in bitmap.
@ -165,8 +165,10 @@ class WriteBarrierCodeStubAssembler : public CodeStubAssembler {
int shift = MarkingBitmap::kBitsPerCellLog2 + kTaggedSizeLog2 - int shift = MarkingBitmap::kBitsPerCellLog2 + kTaggedSizeLog2 -
MarkingBitmap::kBytesPerCellLog2; MarkingBitmap::kBytesPerCellLog2;
r0 = WordShr(object, IntPtrConstant(shift)); r0 = WordShr(object, IntPtrConstant(shift));
r0 = WordAnd(r0, IntPtrConstant((kPageAlignmentMask >> shift) & r0 = WordAnd(
~(MarkingBitmap::kBytesPerCell - 1))); r0, IntPtrConstant(
(MemoryChunkHeader::GetAlignmentMaskForAssembler() >> shift) &
~(MarkingBitmap::kBytesPerCell - 1)));
*cell = IntPtrAdd(bitmap, Signed(r0)); *cell = IntPtrAdd(bitmap, Signed(r0));
} }
{ {
@ -185,11 +187,12 @@ class WriteBarrierCodeStubAssembler : public CodeStubAssembler {
void InsertIntoRememberedSet(TNode<IntPtrT> object, TNode<IntPtrT> slot, void InsertIntoRememberedSet(TNode<IntPtrT> object, TNode<IntPtrT> slot,
SaveFPRegsMode fp_mode) { SaveFPRegsMode fp_mode) {
Label slow_path(this), next(this); Label slow_path(this), next(this);
TNode<IntPtrT> page = PageFromAddress(object); TNode<IntPtrT> page_header = PageHeaderFromAddress(object);
TNode<IntPtrT> page = PageFromPageHeader(page_header);
// Load address of SlotSet // Load address of SlotSet
TNode<IntPtrT> slot_set = LoadSlotSet(page, &slow_path); TNode<IntPtrT> slot_set = LoadSlotSet(page, &slow_path);
TNode<IntPtrT> slot_offset = IntPtrSub(slot, page); TNode<IntPtrT> slot_offset = IntPtrSub(slot, page_header);
// Load bucket // Load bucket
TNode<IntPtrT> bucket = LoadBucket(slot_set, slot_offset, &slow_path); TNode<IntPtrT> bucket = LoadBucket(slot_set, slot_offset, &slow_path);
@ -1423,7 +1426,8 @@ void Builtins::Generate_MaglevOptimizeCodeOrTailCallOptimizedCodeSlot(
using D = MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor; using D = MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor;
Register flags = D::GetRegisterParameter(D::kFlags); Register flags = D::GetRegisterParameter(D::kFlags);
Register feedback_vector = D::GetRegisterParameter(D::kFeedbackVector); Register feedback_vector = D::GetRegisterParameter(D::kFeedbackVector);
masm->AssertFeedbackVector(feedback_vector); Register temporary = D::GetRegisterParameter(D::kTemporary);
masm->AssertFeedbackVector(feedback_vector, temporary);
masm->OptimizeCodeOrTailCallOptimizedCodeSlot(flags, feedback_vector); masm->OptimizeCodeOrTailCallOptimizedCodeSlot(flags, feedback_vector);
masm->Trap(); masm->Trap();
} }

View File

@ -1072,13 +1072,8 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
BIND(&null_proto); BIND(&null_proto);
{ {
map = LoadSlowObjectWithNullPrototypeMap(native_context); map = LoadSlowObjectWithNullPrototypeMap(native_context);
if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { new_properties =
new_properties = AllocatePropertyDictionary(PropertyDictionary::kInitialCapacity);
AllocateSwissNameDictionary(SwissNameDictionary::kInitialCapacity);
} else {
new_properties =
AllocateNameDictionary(NameDictionary::kInitialCapacity);
}
Goto(&instantiate_map); Goto(&instantiate_map);
} }
@ -1419,10 +1414,7 @@ TNode<JSObject> ObjectBuiltinsAssembler::FromPropertyDescriptor(
native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP)); native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP));
// We want to preallocate the slots for value, writable, get, set, // We want to preallocate the slots for value, writable, get, set,
// enumerable and configurable - a total of 6 // enumerable and configurable - a total of 6
TNode<HeapObject> properties = TNode<HeapObject> properties = AllocatePropertyDictionary(6);
V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
? TNode<HeapObject>(AllocateSwissNameDictionary(6))
: AllocateNameDictionary(6);
TNode<JSObject> js_desc = AllocateJSObjectFromMap(map, properties); TNode<JSObject> js_desc = AllocateJSObjectFromMap(map, properties);
Label bailout(this, Label::kDeferred); Label bailout(this, Label::kDeferred);

View File

@ -115,10 +115,9 @@ Tagged<Object> ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
LookupIterator it(isolate, object, lookup_key, LookupIterator it(isolate, object, lookup_key,
LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
for (; it.IsFound(); it.Next()) { for (;; it.Next()) {
switch (it.state()) { switch (it.state()) {
case LookupIterator::INTERCEPTOR: case LookupIterator::INTERCEPTOR:
case LookupIterator::NOT_FOUND:
case LookupIterator::TRANSITION: case LookupIterator::TRANSITION:
UNREACHABLE(); UNREACHABLE();
@ -151,8 +150,9 @@ Tagged<Object> ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
return ObjectLookupAccessor(isolate, prototype, key, component); return ObjectLookupAccessor(isolate, prototype, key, component);
} }
case LookupIterator::WASM_OBJECT: case LookupIterator::WASM_OBJECT:
case LookupIterator::INTEGER_INDEXED_EXOTIC: case LookupIterator::TYPED_ARRAY_INDEX_NOT_FOUND:
case LookupIterator::DATA: case LookupIterator::DATA:
case LookupIterator::NOT_FOUND:
return ReadOnlyRoots(isolate).undefined_value(); return ReadOnlyRoots(isolate).undefined_value();
case LookupIterator::ACCESSOR: { case LookupIterator::ACCESSOR: {
@ -165,11 +165,11 @@ Tagged<Object> ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
isolate, holder_realm, Handle<AccessorPair>::cast(maybe_pair), isolate, holder_realm, Handle<AccessorPair>::cast(maybe_pair),
component); component);
} }
continue;
} }
} }
UNREACHABLE();
} }
return ReadOnlyRoots(isolate).undefined_value();
} }
} // namespace } // namespace

View File

@ -312,19 +312,45 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
// implementation of CreateDataProperty instead. // implementation of CreateDataProperty instead.
// At this point the spec says to call CreateDataProperty. However, we can // At this point the spec says to call CreateDataProperty. However, we can
// skip most of the steps and go straight to adding a dictionary entry // skip most of the steps and go straight to adding/updating a dictionary
// because we know a bunch of useful facts: // entry because we know a bunch of useful facts:
// - All keys are non-numeric internalized strings // - All keys are non-numeric internalized strings
// - No keys repeat
// - Receiver has no prototype // - Receiver has no prototype
// - Receiver isn't used as a prototype // - Receiver isn't used as a prototype
// - Receiver isn't any special object like a Promise intrinsic object // - Receiver isn't any special object like a Promise intrinsic object
// - Receiver is extensible // - Receiver is extensible
// - Receiver has no interceptors // - Receiver has no interceptors
Label add_dictionary_property_slow(this, Label::kDeferred); Label add_dictionary_property_slow(this, Label::kDeferred);
AddToDictionary<PropertyDictionary>(CAST(properties), name, capture, TVARIABLE(IntPtrT, var_name_index);
&add_dictionary_property_slow); Label add_name_entry_find_index(this),
add_name_entry_known_index(this, &var_name_index),
duplicate_name(this, &var_name_index), next(this);
NameDictionaryLookup<PropertyDictionary>(
CAST(properties), name, &duplicate_name, &var_name_index,
&add_name_entry_find_index, kFindExisting,
&add_name_entry_known_index);
BIND(&duplicate_name);
GotoIf(IsUndefined(capture), &next);
CSA_DCHECK(this,
TaggedEqual(LoadValueByKeyIndex<PropertyDictionary>(
CAST(properties), var_name_index.value()),
UndefinedConstant()));
StoreValueByKeyIndex<PropertyDictionary>(CAST(properties),
var_name_index.value(), capture);
Goto(&next);
BIND(&add_name_entry_find_index);
FindInsertionEntry<PropertyDictionary>(CAST(properties), name,
&var_name_index);
Goto(&add_name_entry_known_index);
BIND(&add_name_entry_known_index);
AddToDictionary<PropertyDictionary>(CAST(properties), name, capture,
&add_dictionary_property_slow,
var_name_index.value());
Goto(&next);
BIND(&next);
var_i = i_plus_2; var_i = i_plus_2;
Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length),
&maybe_build_indices, &inner_loop); &maybe_build_indices, &inner_loop);
@ -578,7 +604,8 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal(
// instead of referencing the CodeWrapper object, we could directly load // instead of referencing the CodeWrapper object, we could directly load
// the entrypoint from that via LoadCodeEntrypointViaCodePointerField. This // the entrypoint from that via LoadCodeEntrypointViaCodePointerField. This
// will save an indirection when the sandbox is enabled. // will save an indirection when the sandbox is enabled.
TNode<RawPtrT> code_entry = LoadCodeInstructionStart(code); TNode<RawPtrT> code_entry =
LoadCodeInstructionStart(code, kRegExpEntrypointTag);
// AIX uses function descriptors on CFunction calls. code_entry in this case // AIX uses function descriptors on CFunction calls. code_entry in this case
// may also point to a Regex interpreter entry trampoline which does not // may also point to a Regex interpreter entry trampoline which does not

View File

@ -462,6 +462,28 @@ bool Builtins::IsCpp(Builtin builtin) {
return Builtins::KindOf(builtin) == CPP; return Builtins::KindOf(builtin) == CPP;
} }
// static
CodeEntrypointTag Builtins::EntrypointTagFor(Builtin builtin) {
if (builtin == Builtin::kNoBuiltinId) {
// Special case needed for example for tests.
return kDefaultCodeEntrypointTag;
}
Kind kind = Builtins::KindOf(builtin);
switch (kind) {
case BCH:
return kBytecodeHandlerEntrypointTag;
case TFH:
return kICHandlerEntrypointTag;
case ASM:
// TODO(saelo) consider using this approach for the other kinds as well.
return CallInterfaceDescriptorFor(builtin).tag();
default:
// TODO(saelo): use more fine-grained tags here.
return kDefaultCodeEntrypointTag;
}
}
// static // static
bool Builtins::AllowDynamicFunction(Isolate* isolate, Handle<JSFunction> target, bool Builtins::AllowDynamicFunction(Isolate* isolate, Handle<JSFunction> target,
Handle<JSObject> target_global_proxy) { Handle<JSObject> target_global_proxy) {

View File

@ -9,6 +9,7 @@
#include "src/builtins/builtins-definitions.h" #include "src/builtins/builtins-definitions.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/objects/type-hints.h" #include "src/objects/type-hints.h"
#include "src/sandbox/code-entrypoint-tag.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -193,6 +194,9 @@ class Builtins {
static Kind KindOf(Builtin builtin); static Kind KindOf(Builtin builtin);
static const char* KindNameOf(Builtin builtin); static const char* KindNameOf(Builtin builtin);
// The tag for the builtins entrypoint.
V8_EXPORT_PRIVATE static CodeEntrypointTag EntrypointTagFor(Builtin builtin);
static bool IsCpp(Builtin builtin); static bool IsCpp(Builtin builtin);
// True, iff the given code object is a builtin. Note that this does not // True, iff the given code object is a builtin. Note that this does not

View File

@ -288,21 +288,26 @@ transitioning macro GetSetRecord(
// 6. Let intSize be ! ToIntegerOrInfinity(numSize). // 6. Let intSize be ! ToIntegerOrInfinity(numSize).
const intSize = ToInteger_Inline(numSize); const intSize = ToInteger_Inline(numSize);
// 7. Let has be ? Get(obj, "has"). // 7. If intSize < 0, throw a RangeError exception.
if (intSize < 0) {
ThrowRangeError(MessageTemplate::kInvalidSizeValue, intSize);
}
// 8. Let has be ? Get(obj, "has").
let has = GetProperty(obj, kHasString); let has = GetProperty(obj, kHasString);
// 8. If IsCallable(has) is false, throw a TypeError exception. // 9. If IsCallable(has) is false, throw a TypeError exception.
has = Cast<Callable>(has) has = Cast<Callable>(has)
otherwise ThrowCalledNonCallable(kHasString); otherwise ThrowCalledNonCallable(kHasString);
// 9. Let keys be ? Get(obj, "keys"). // 10. Let keys be ? Get(obj, "keys").
let keys = GetProperty(obj, kKeysString); let keys = GetProperty(obj, kKeysString);
// 10. If IsCallable(keys) is false, throw a TypeError exception. // 11. If IsCallable(keys) is false, throw a TypeError exception.
keys = Cast<Callable>(keys) keys = Cast<Callable>(keys)
otherwise ThrowCalledNonCallable(kKeysString); otherwise ThrowCalledNonCallable(kKeysString);
// 11. Return a new Set Record { [[Set]]: obj, [[Size]]: intSize, [[Has]]: // 12. Return a new Set Record { [[Set]]: obj, [[Size]]: intSize, [[Has]]:
// has, [[Keys]]: keys }. // has, [[Keys]]: keys }.
return SetRecord{object: obj, size: intSize, has: has, keys: keys}; return SetRecord{object: obj, size: intSize, has: has, keys: keys};
} }

View File

@ -42,6 +42,8 @@ macro ConvertToAndFromWasm(context: Context, wasmType: int32, value: JSAny):
} else if (wasmType == kWasmF64Type) { } else if (wasmType == kWasmF64Type) {
return Convert<Number>(WasmTaggedToFloat64(value)); return Convert<Number>(WasmTaggedToFloat64(value));
} else { } else {
const wasmKind = wasmType & kValueTypeKindBitsMask;
dcheck(wasmKind == ValueKind::kRef || wasmKind == ValueKind::kRefNull);
if (value == Null) { if (value == Null) {
// At the moment it is not possible to define non-nullable types for // At the moment it is not possible to define non-nullable types for
// WebAssembly.Functions. // WebAssembly.Functions.
@ -61,6 +63,13 @@ macro ConvertToAndFromWasm(context: Context, wasmType: int32, value: JSAny):
} }
} }
extern runtime WasmThrowJSTypeError(Context): never;
transitioning javascript builtin JSToJSWrapperInvalidSig(
js-implicit context: NativeContext)(): JSAny {
runtime::WasmThrowJSTypeError(context);
}
transitioning javascript builtin JSToJSWrapper( transitioning javascript builtin JSToJSWrapper(
js-implicit context: NativeContext, receiver: JSAny, target: JSFunction)( js-implicit context: NativeContext, receiver: JSAny, target: JSFunction)(
...arguments): JSAny { ...arguments): JSAny {

View File

@ -504,6 +504,8 @@ macro JSToWasmWrapperHelper(
} else if (retType == kWasmF64Type) { } else if (retType == kWasmF64Type) {
allocator.AllocFP64(); allocator.AllocFP64();
} else { } else {
const retKind = retType & kValueTypeKindBitsMask;
dcheck(retKind == ValueKind::kRef || retKind == ValueKind::kRefNull);
// Also check if there are any reference return values, as this allows // Also check if there are any reference return values, as this allows
// us to skip code when we process return values. // us to skip code when we process return values.
hasRefReturns = true; hasRefReturns = true;
@ -600,6 +602,8 @@ macro JSToWasmWrapperHelper(
*toHighRef = Signed(pair.high); *toHighRef = Signed(pair.high);
} }
} else { } else {
const paramKind = paramType & kValueTypeKindBitsMask;
dcheck(paramKind == ValueKind::kRef || paramKind == ValueKind::kRefNull);
// The byte array where we store converted parameters is not GC-safe. // The byte array where we store converted parameters is not GC-safe.
// Therefore we can only copy references into this array once no GC can // Therefore we can only copy references into this array once no GC can
// happen anymore. Any conversion of a primitive type can execute // happen anymore. Any conversion of a primitive type can execute

View File

@ -305,6 +305,7 @@ macro CreatePromiseCapability(
struct PromiseResolvingFunctions { struct PromiseResolvingFunctions {
resolve: JSFunction; resolve: JSFunction;
reject: JSFunction; reject: JSFunction;
context: Context;
} }
@export @export
@ -322,7 +323,11 @@ macro CreatePromiseResolvingFunctions(
const rejectInfo = PromiseCapabilityDefaultRejectSharedFunConstant(); const rejectInfo = PromiseCapabilityDefaultRejectSharedFunConstant();
const reject: JSFunction = const reject: JSFunction =
AllocateFunctionWithMapAndContext(map, rejectInfo, promiseContext); AllocateFunctionWithMapAndContext(map, rejectInfo, promiseContext);
return PromiseResolvingFunctions{resolve: resolve, reject: reject}; return PromiseResolvingFunctions{
resolve: resolve,
reject: reject,
context: promiseContext
};
} }
transitioning macro InnerNewPromiseCapability( transitioning macro InnerNewPromiseCapability(

View File

@ -82,6 +82,13 @@ transitioning javascript builtin PromiseConstructor(
try { try {
Call(context, UnsafeCast<Callable>(executor), Undefined, resolve, reject); Call(context, UnsafeCast<Callable>(executor), Undefined, resolve, reject);
} catch (e, _message) { } catch (e, _message) {
// We need to disable the debug event, as we have already paused on this
// exception.
const promiseContext =
%RawDownCast<PromiseResolvingFunctionContext>(funcs.context);
*ContextSlot(
promiseContext, PromiseResolvingFunctionContextSlot::kDebugEventSlot) =
False;
Call(context, reject, Undefined, e); Call(context, reject, Undefined, e);
} }

View File

@ -3028,7 +3028,10 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// Check result for exception sentinel. // Check result for exception sentinel.
Label exception_returned; Label exception_returned;
__ Branch(&exception_returned, eq, a0, RootIndex::kException); // The returned value may be a trusted object, living outside of the main
// pointer compression cage, so we need to use full pointer comparison here.
__ CompareRootAndBranch(a0, RootIndex::kException, eq, &exception_returned,
ComparisonMode::kFullPointer);
// Check that there is no exception, otherwise we // Check that there is no exception, otherwise we
// should have returned the exception sentinel. // should have returned the exception sentinel.

View File

@ -63,6 +63,16 @@ transitioning javascript builtin WebAssemblyStringIntoUtf8Array(
} }
} }
transitioning javascript builtin WebAssemblyStringToUtf8Array(
js-implicit context: Context)(...arguments): JSAny {
try {
const string = Cast<String>(arguments[0]) otherwise goto IllegalCast;
return runtime::WasmStringToUtf8Array(context, string);
} label IllegalCast deferred {
Trap(context, MessageTemplate::kWasmTrapIllegalCast);
}
}
transitioning javascript builtin WebAssemblyStringToWtf16Array( transitioning javascript builtin WebAssemblyStringToWtf16Array(
js-implicit context: Context)(...arguments): JSAny { js-implicit context: Context)(...arguments): JSAny {
try { try {

View File

@ -81,6 +81,7 @@ transitioning macro WasmToJSWrapper(ref: WasmApiFunctionRef): WasmToJSResult {
const returnCount = const returnCount =
Convert<intptr>(*torque_internal::unsafe::NewReference<int32>( Convert<intptr>(*torque_internal::unsafe::NewReference<int32>(
serializedSig.object, serializedSig.offset)); serializedSig.object, serializedSig.offset));
dcheck(returnCount < serializedSig.length);
const paramCount: intptr = serializedSig.length - returnCount - 1; const paramCount: intptr = serializedSig.length - returnCount - 1;
const returnTypes = Subslice(serializedSig, Convert<intptr>(1), returnCount) const returnTypes = Subslice(serializedSig, Convert<intptr>(1), returnCount)
otherwise unreachable; otherwise unreachable;
@ -261,6 +262,8 @@ transitioning macro WasmToJSWrapper(ref: WasmApiFunctionRef): WasmToJSResult {
*toHighRef = Signed(pair.high); *toHighRef = Signed(pair.high);
} }
} else { } else {
const retKind = retType & kValueTypeKindBitsMask;
dcheck(retKind == ValueKind::kRef || retKind == ValueKind::kRefNull);
dcheck(ref.instance == Undefined || Is<WasmInstanceObject>(ref.instance)); dcheck(ref.instance == Undefined || Is<WasmInstanceObject>(ref.instance));
const trustedData = ref.instance == Undefined ? const trustedData = ref.instance == Undefined ?
Undefined : Undefined :

View File

@ -62,6 +62,7 @@ extern runtime WasmStringEncodeWtf8(
Context, WasmTrustedInstanceData, Smi, Smi, String, Number): Number; Context, WasmTrustedInstanceData, Smi, Smi, String, Number): Number;
extern runtime WasmStringEncodeWtf8Array( extern runtime WasmStringEncodeWtf8Array(
Context, Smi, String, WasmArray, Number): Number; Context, Smi, String, WasmArray, Number): Number;
extern runtime WasmStringToUtf8Array(Context, String): WasmArray;
extern runtime WasmStringEncodeWtf16( extern runtime WasmStringEncodeWtf16(
Context, WasmTrustedInstanceData, Smi, String, Number, Smi, Smi): JSAny; Context, WasmTrustedInstanceData, Smi, String, Number, Smi, Smi): JSAny;
extern runtime WasmStringAsWtf8(Context, String): ByteArray; extern runtime WasmStringAsWtf8(Context, String): ByteArray;
@ -995,6 +996,9 @@ builtin WasmStringEncodeWtf8Array(
WasmUint32ToNumber(start)); WasmUint32ToNumber(start));
return ChangeNumberToUint32(result); return ChangeNumberToUint32(result);
} }
builtin WasmStringToUtf8Array(string: String): WasmArray {
return runtime::WasmStringToUtf8Array(LoadContextFromFrame(), string);
}
builtin WasmStringEncodeWtf16(string: String, offset: uint32, memory: Smi): builtin WasmStringEncodeWtf16(string: String, offset: uint32, memory: Smi):
uint32 { uint32 {
const trustedData = LoadInstanceDataFromFrame(); const trustedData = LoadInstanceDataFromFrame();

View File

@ -759,9 +759,8 @@ static void GetSharedFunctionInfoBytecodeOrBaseline(
&done); &done);
} }
__ LoadTrustedPointerField( __ LoadProtectedPointerField(
bytecode, FieldOperand(data, InterpreterData::kBytecodeArrayOffset), bytecode, FieldOperand(data, InterpreterData::kBytecodeArrayOffset));
kBytecodeArrayIndirectPointerTag, scratch1);
__ bind(&done); __ bind(&done);
__ IsObjectType(bytecode, BYTECODE_ARRAY_TYPE, scratch1); __ IsObjectType(bytecode, BYTECODE_ARRAY_TYPE, scratch1);
@ -1298,7 +1297,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(
__ ReplaceClosureCodeWithOptimizedCode( __ ReplaceClosureCodeWithOptimizedCode(
rcx, closure, kInterpreterBytecodeArrayRegister, rcx, closure, kInterpreterBytecodeArrayRegister,
WriteBarrierDescriptor::SlotAddressRegister()); WriteBarrierDescriptor::SlotAddressRegister());
__ JumpCodeObject(rcx); __ JumpCodeObject(rcx, kJSEntrypointTag);
__ bind(&install_baseline_code); __ bind(&install_baseline_code);
__ GenerateTailCallToReturnedCode(Runtime::kInstallBaselineCode); __ GenerateTailCallToReturnedCode(Runtime::kInstallBaselineCode);
@ -1707,11 +1706,9 @@ static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
GetSharedFunctionInfoData(masm, rbx, shared_function_info, kScratchRegister); GetSharedFunctionInfoData(masm, rbx, shared_function_info, kScratchRegister);
__ IsObjectType(rbx, INTERPRETER_DATA_TYPE, kScratchRegister); __ IsObjectType(rbx, INTERPRETER_DATA_TYPE, kScratchRegister);
__ j(not_equal, &builtin_trampoline, Label::kNear); __ j(not_equal, &builtin_trampoline, Label::kNear);
__ LoadProtectedPointerField(
__ LoadCodePointerField( rbx, FieldOperand(rbx, InterpreterData::kInterpreterTrampolineOffset));
rbx, FieldOperand(rbx, InterpreterData::kInterpreterTrampolineOffset), __ LoadCodeInstructionStart(rbx, rbx, kJSEntrypointTag);
kScratchRegister);
__ LoadCodeInstructionStart(rbx, rbx);
__ jmp(&trampoline_loaded, Label::kNear); __ jmp(&trampoline_loaded, Label::kNear);
__ bind(&builtin_trampoline); __ bind(&builtin_trampoline);
@ -1841,7 +1838,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
FieldOperand(closure, JSFunction::kFeedbackCellOffset)); FieldOperand(closure, JSFunction::kFeedbackCellOffset));
__ LoadTaggedField(feedback_vector, __ LoadTaggedField(feedback_vector,
FieldOperand(feedback_cell, FeedbackCell::kValueOffset)); FieldOperand(feedback_cell, FeedbackCell::kValueOffset));
__ AssertFeedbackVector(feedback_vector); __ AssertFeedbackVector(feedback_vector, kScratchRegister);
// Check the tiering state. // Check the tiering state.
Label flags_need_processing; Label flags_need_processing;
@ -2935,18 +2932,18 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source,
} }
// Load deoptimization data from the code object. // Load deoptimization data from the code object.
const TaggedRegister deopt_data(rbx); const Register deopt_data(rbx);
__ LoadTaggedField( __ LoadProtectedPointerField(
deopt_data, deopt_data,
FieldOperand(rax, Code::kDeoptimizationDataOrInterpreterDataOffset)); FieldOperand(rax, Code::kDeoptimizationDataOrInterpreterDataOffset));
// Load the OSR entrypoint offset from the deoptimization data. // Load the OSR entrypoint offset from the deoptimization data.
__ SmiUntagField( __ SmiUntagField(
rbx, rbx,
FieldOperand(deopt_data, FixedArray::OffsetOfElementAt( FieldOperand(deopt_data, TrustedFixedArray::OffsetOfElementAt(
DeoptimizationData::kOsrPcOffsetIndex))); DeoptimizationData::kOsrPcOffsetIndex)));
__ LoadCodeInstructionStart(rax, rax); __ LoadCodeInstructionStart(rax, rax, kJSEntrypointTag);
// Compute the target address = code_entry + osr_offset // Compute the target address = code_entry + osr_offset
__ addq(rax, rbx); __ addq(rax, rbx);
@ -4990,7 +4987,7 @@ void Generate_BaselineOrInterpreterEntry(MacroAssembler* masm,
__ movq(kCArgRegs[2], kInterpreterBytecodeArrayRegister); __ movq(kCArgRegs[2], kInterpreterBytecodeArrayRegister);
__ CallCFunction(get_baseline_pc, 3); __ CallCFunction(get_baseline_pc, 3);
} }
__ LoadCodeInstructionStart(code_obj, code_obj); __ LoadCodeInstructionStart(code_obj, code_obj, kJSEntrypointTag);
__ addq(code_obj, kReturnRegister0); __ addq(code_obj, kReturnRegister0);
__ popq(kInterpreterAccumulatorRegister); __ popq(kInterpreterAccumulatorRegister);

View File

@ -1250,7 +1250,7 @@ void Assembler::AddrMode1(Instr instr, Register rd, Register rn,
// pool only for a MOV instruction which does not set the flags. // pool only for a MOV instruction which does not set the flags.
DCHECK(!rn.is_valid()); DCHECK(!rn.is_valid());
Move32BitImmediate(rd, x, cond); Move32BitImmediate(rd, x, cond);
} else if ((opcode == ADD) && !set_flags && (rd == rn) && } else if ((opcode == ADD || opcode == SUB) && !set_flags && (rd == rn) &&
!temps.CanAcquire()) { !temps.CanAcquire()) {
// Split the operation into a sequence of additions if we cannot use a // Split the operation into a sequence of additions if we cannot use a
// scratch register. In this case, we cannot re-use rn and the assembler // scratch register. In this case, we cannot re-use rn and the assembler
@ -1266,10 +1266,20 @@ void Assembler::AddrMode1(Instr instr, Register rd, Register rn,
// immediate allows us to more efficiently split it: // immediate allows us to more efficiently split it:
int trailing_zeroes = base::bits::CountTrailingZeros(imm) & ~1u; int trailing_zeroes = base::bits::CountTrailingZeros(imm) & ~1u;
uint32_t mask = (0xFF << trailing_zeroes); uint32_t mask = (0xFF << trailing_zeroes);
add(rd, rd, Operand(imm & mask), LeaveCC, cond); if (opcode == ADD) {
add(rd, rd, Operand(imm & mask), LeaveCC, cond);
} else {
DCHECK_EQ(opcode, SUB);
sub(rd, rd, Operand(imm & mask), LeaveCC, cond);
}
imm = imm & ~mask; imm = imm & ~mask;
} while (!ImmediateFitsAddrMode1Instruction(imm)); } while (!ImmediateFitsAddrMode1Instruction(imm));
add(rd, rd, Operand(imm), LeaveCC, cond); if (opcode == ADD) {
add(rd, rd, Operand(imm), LeaveCC, cond);
} else {
DCHECK_EQ(opcode, SUB);
sub(rd, rd, Operand(imm), LeaveCC, cond);
}
} else { } else {
// The immediate operand cannot be encoded as a shifter operand, so load // The immediate operand cannot be encoded as a shifter operand, so load
// it first to a scratch register and change the original instruction to // it first to a scratch register and change the original instruction to

View File

@ -164,6 +164,11 @@ constexpr Register MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor::
FeedbackVectorRegister() { FeedbackVectorRegister() {
return r5; return r5;
} }
// static
constexpr Register
MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor::TemporaryRegister() {
return r4;
}
// static // static
constexpr auto CallTrampolineDescriptor::registers() { constexpr auto CallTrampolineDescriptor::registers() {

View File

@ -363,7 +363,8 @@ void MacroAssembler::TailCallBuiltin(Builtin builtin, Condition cond) {
} }
void MacroAssembler::LoadCodeInstructionStart(Register destination, void MacroAssembler::LoadCodeInstructionStart(Register destination,
Register code_object) { Register code_object,
CodeEntrypointTag tag) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
ldr(destination, FieldMemOperand(code_object, Code::kInstructionStartOffset)); ldr(destination, FieldMemOperand(code_object, Code::kInstructionStartOffset));
} }
@ -2006,10 +2007,8 @@ void MacroAssembler::AssertFeedbackCell(Register object, Register scratch) {
Assert(eq, AbortReason::kExpectedFeedbackCell); Assert(eq, AbortReason::kExpectedFeedbackCell);
} }
} }
void MacroAssembler::AssertFeedbackVector(Register object) { void MacroAssembler::AssertFeedbackVector(Register object, Register scratch) {
if (v8_flags.debug_code) { if (v8_flags.debug_code) {
UseScratchRegisterScope temps(this);
Register scratch = temps.Acquire();
CompareObjectType(object, scratch, scratch, FEEDBACK_VECTOR_TYPE); CompareObjectType(object, scratch, scratch, FEEDBACK_VECTOR_TYPE);
Assert(eq, AbortReason::kExpectedFeedbackVector); Assert(eq, AbortReason::kExpectedFeedbackVector);
} }
@ -2729,20 +2728,22 @@ void MacroAssembler::MovToFloatParameters(DwVfpRegister src1,
} }
} }
void MacroAssembler::CallCFunction(ExternalReference function, int MacroAssembler::CallCFunction(ExternalReference function,
int num_reg_arguments, int num_reg_arguments,
int num_double_arguments, int num_double_arguments,
SetIsolateDataSlots set_isolate_data_slots) { SetIsolateDataSlots set_isolate_data_slots,
Label* return_label) {
UseScratchRegisterScope temps(this); UseScratchRegisterScope temps(this);
Register scratch = temps.Acquire(); Register scratch = temps.Acquire();
Move(scratch, function); Move(scratch, function);
CallCFunction(scratch, num_reg_arguments, num_double_arguments, return CallCFunction(scratch, num_reg_arguments, num_double_arguments,
set_isolate_data_slots); set_isolate_data_slots, return_label);
} }
void MacroAssembler::CallCFunction(Register function, int num_reg_arguments, int MacroAssembler::CallCFunction(Register function, int num_reg_arguments,
int num_double_arguments, int num_double_arguments,
SetIsolateDataSlots set_isolate_data_slots) { SetIsolateDataSlots set_isolate_data_slots,
Label* return_label) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
DCHECK_LE(num_reg_arguments + num_double_arguments, kMaxCParameters); DCHECK_LE(num_reg_arguments + num_double_arguments, kMaxCParameters);
DCHECK(has_frame()); DCHECK(has_frame());
@ -2767,13 +2768,19 @@ void MacroAssembler::CallCFunction(Register function, int num_reg_arguments,
} }
#endif #endif
Label get_pc;
if (set_isolate_data_slots == SetIsolateDataSlots::kYes) { if (set_isolate_data_slots == SetIsolateDataSlots::kYes) {
Register pc_scratch = r5;
Push(pc_scratch);
GetLabelAddress(pc_scratch, &get_pc);
// Save the frame pointer and PC so that the stack layout remains iterable, // Save the frame pointer and PC so that the stack layout remains iterable,
// even without an ExitFrame which normally exists between JS and C frames. // even without an ExitFrame which normally exists between JS and C frames.
// See x64 code for reasoning about how to address the isolate data fields. // See x64 code for reasoning about how to address the isolate data fields.
if (root_array_available()) { if (root_array_available()) {
str(pc, MemOperand(kRootRegister, str(pc_scratch, MemOperand(kRootRegister,
IsolateData::fast_c_call_caller_pc_offset())); IsolateData::fast_c_call_caller_pc_offset()));
str(fp, MemOperand(kRootRegister, str(fp, MemOperand(kRootRegister,
IsolateData::fast_c_call_caller_fp_offset())); IsolateData::fast_c_call_caller_fp_offset()));
} else { } else {
@ -2783,19 +2790,24 @@ void MacroAssembler::CallCFunction(Register function, int num_reg_arguments,
Move(addr_scratch, Move(addr_scratch,
ExternalReference::fast_c_call_caller_pc_address(isolate())); ExternalReference::fast_c_call_caller_pc_address(isolate()));
str(pc, MemOperand(addr_scratch)); str(pc_scratch, MemOperand(addr_scratch));
Move(addr_scratch, Move(addr_scratch,
ExternalReference::fast_c_call_caller_fp_address(isolate())); ExternalReference::fast_c_call_caller_fp_address(isolate()));
str(fp, MemOperand(addr_scratch)); str(fp, MemOperand(addr_scratch));
Pop(addr_scratch); Pop(addr_scratch);
} }
Pop(pc_scratch);
} }
// Just call directly. The function called cannot cause a GC, or // Just call directly. The function called cannot cause a GC, or
// allow preemption, so the return address in the link register // allow preemption, so the return address in the link register
// stays correct. // stays correct.
Call(function); Call(function);
int call_pc_offset = pc_offset();
bind(&get_pc);
if (return_label) bind(return_label);
if (set_isolate_data_slots == SetIsolateDataSlots::kYes) { if (set_isolate_data_slots == SetIsolateDataSlots::kYes) {
// We don't unset the PC; the FP is the source of truth. // We don't unset the PC; the FP is the source of truth.
@ -2827,17 +2839,22 @@ void MacroAssembler::CallCFunction(Register function, int num_reg_arguments,
} else { } else {
add(sp, sp, Operand(stack_passed_arguments * kPointerSize)); add(sp, sp, Operand(stack_passed_arguments * kPointerSize));
} }
return call_pc_offset;
} }
void MacroAssembler::CallCFunction(ExternalReference function, int MacroAssembler::CallCFunction(ExternalReference function, int num_arguments,
int num_arguments, SetIsolateDataSlots set_isolate_data_slots,
SetIsolateDataSlots set_isolate_data_slots) { Label* return_label) {
CallCFunction(function, num_arguments, 0, set_isolate_data_slots); return CallCFunction(function, num_arguments, 0, set_isolate_data_slots,
return_label);
} }
void MacroAssembler::CallCFunction(Register function, int num_arguments, int MacroAssembler::CallCFunction(Register function, int num_arguments,
SetIsolateDataSlots set_isolate_data_slots) { SetIsolateDataSlots set_isolate_data_slots,
CallCFunction(function, num_arguments, 0, set_isolate_data_slots); Label* return_label) {
return CallCFunction(function, num_arguments, 0, set_isolate_data_slots,
return_label);
} }
void MacroAssembler::CheckPageFlag(Register object, int mask, Condition cc, void MacroAssembler::CheckPageFlag(Register object, int mask, Condition cc,
@ -2848,7 +2865,7 @@ void MacroAssembler::CheckPageFlag(Register object, int mask, Condition cc,
DCHECK(!AreAliased(object, scratch)); DCHECK(!AreAliased(object, scratch));
DCHECK(cc == eq || cc == ne); DCHECK(cc == eq || cc == ne);
Bfc(scratch, object, 0, kPageSizeBits); Bfc(scratch, object, 0, kPageSizeBits);
ldr(scratch, MemOperand(scratch, BasicMemoryChunk::kFlagsOffset)); ldr(scratch, MemOperand(scratch, MemoryChunkLayout::kFlagsOffset));
tst(scratch, Operand(mask)); tst(scratch, Operand(mask));
b(cc, condition_met); b(cc, condition_met);
} }

View File

@ -252,23 +252,23 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
// garbage collection, since that might move the code and invalidate the // garbage collection, since that might move the code and invalidate the
// return address (unless this is somehow accounted for by the called // return address (unless this is somehow accounted for by the called
// function). // function).
enum class SetIsolateDataSlots { int CallCFunction(
kNo,
kYes,
};
void CallCFunction(
ExternalReference function, int num_arguments, ExternalReference function, int num_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
void CallCFunction( Label* return_label = nullptr);
int CallCFunction(
Register function, int num_arguments, Register function, int num_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
void CallCFunction( Label* return_label = nullptr);
int CallCFunction(
ExternalReference function, int num_reg_arguments, ExternalReference function, int num_reg_arguments,
int num_double_arguments, int num_double_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
void CallCFunction( Label* return_label = nullptr);
int CallCFunction(
Register function, int num_reg_arguments, int num_double_arguments, Register function, int num_reg_arguments, int num_double_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
Label* return_label = nullptr);
void MovFromFloatParameter(DwVfpRegister dst); void MovFromFloatParameter(DwVfpRegister dst);
void MovFromFloatResult(DwVfpRegister dst); void MovFromFloatResult(DwVfpRegister dst);
@ -337,7 +337,9 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
void TailCallBuiltin(Builtin builtin, Condition cond = al); void TailCallBuiltin(Builtin builtin, Condition cond = al);
// Load the code entry point from the Code object. // Load the code entry point from the Code object.
void LoadCodeInstructionStart(Register destination, Register code_object); void LoadCodeInstructionStart(
Register destination, Register code_object,
CodeEntrypointTag tag = kDefaultCodeEntrypointTag);
void CallCodeObject(Register code_object); void CallCodeObject(Register code_object);
void JumpCodeObject(Register code_object, void JumpCodeObject(Register code_object,
JumpMode jump_mode = JumpMode::kJump); JumpMode jump_mode = JumpMode::kJump);
@ -875,7 +877,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
// Tiering support. // Tiering support.
void AssertFeedbackCell(Register object, void AssertFeedbackCell(Register object,
Register scratch) NOOP_UNLESS_DEBUG_CODE; Register scratch) NOOP_UNLESS_DEBUG_CODE;
void AssertFeedbackVector(Register object) NOOP_UNLESS_DEBUG_CODE; void AssertFeedbackVector(Register object,
Register scratch) NOOP_UNLESS_DEBUG_CODE;
void ReplaceClosureCodeWithOptimizedCode(Register optimized_code, void ReplaceClosureCodeWithOptimizedCode(Register optimized_code,
Register closure); Register closure);
void GenerateTailCallToReturnedCode(Runtime::FunctionId function_id); void GenerateTailCallToReturnedCode(Runtime::FunctionId function_id);

View File

@ -154,6 +154,11 @@ constexpr Register MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor::
FeedbackVectorRegister() { FeedbackVectorRegister() {
return x9; return x9;
} }
// static
constexpr Register
MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor::TemporaryRegister() {
return x4;
}
// static // static
constexpr auto TypeofDescriptor::registers() { return RegisterArray(x0); } constexpr auto TypeofDescriptor::registers() { return RegisterArray(x0); }

View File

@ -1440,7 +1440,7 @@ void TailCallOptimizedCodeSlot(MacroAssembler* masm,
__ ReplaceClosureCodeWithOptimizedCode(optimized_code_entry, closure); __ ReplaceClosureCodeWithOptimizedCode(optimized_code_entry, closure);
static_assert(kJavaScriptCallCodeStartRegister == x2, "ABI mismatch"); static_assert(kJavaScriptCallCodeStartRegister == x2, "ABI mismatch");
__ Move(x2, optimized_code_entry); __ Move(x2, optimized_code_entry);
__ JumpCodeObject(x2); __ JumpCodeObject(x2, kJSEntrypointTag);
// Optimized code slot contains deoptimized code or code is cleared and // Optimized code slot contains deoptimized code or code is cleared and
// optimized code marker isn't updated. Evict the code, update the marker // optimized code marker isn't updated. Evict the code, update the marker
@ -1507,7 +1507,7 @@ void MacroAssembler::GenerateTailCallToReturnedCode(
} }
static_assert(kJavaScriptCallCodeStartRegister == x2, "ABI mismatch"); static_assert(kJavaScriptCallCodeStartRegister == x2, "ABI mismatch");
JumpCodeObject(x2); JumpCodeObject(x2, kJSEntrypointTag);
} }
// Read off the flags in the feedback vector and check if there // Read off the flags in the feedback vector and check if there
@ -2061,31 +2061,37 @@ int MacroAssembler::ActivationFrameAlignment() {
#endif // V8_HOST_ARCH_ARM64 #endif // V8_HOST_ARCH_ARM64
} }
void MacroAssembler::CallCFunction(ExternalReference function, int MacroAssembler::CallCFunction(ExternalReference function,
int num_of_reg_args, int num_of_reg_args,
SetIsolateDataSlots set_isolate_data_slots) { SetIsolateDataSlots set_isolate_data_slots,
CallCFunction(function, num_of_reg_args, 0, set_isolate_data_slots); Label* return_location) {
return CallCFunction(function, num_of_reg_args, 0, set_isolate_data_slots,
return_location);
} }
void MacroAssembler::CallCFunction(ExternalReference function, int MacroAssembler::CallCFunction(ExternalReference function,
int num_of_reg_args, int num_of_double_args, int num_of_reg_args, int num_of_double_args,
SetIsolateDataSlots set_isolate_data_slots) { SetIsolateDataSlots set_isolate_data_slots,
Label* return_location) {
// Note: The "CallCFunction" code comment will be generated by the other // Note: The "CallCFunction" code comment will be generated by the other
// CallCFunction method called below. // CallCFunction method called below.
UseScratchRegisterScope temps(this); UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX(); Register temp = temps.AcquireX();
Mov(temp, function); Mov(temp, function);
CallCFunction(temp, num_of_reg_args, num_of_double_args, return CallCFunction(temp, num_of_reg_args, num_of_double_args,
set_isolate_data_slots); set_isolate_data_slots, return_location);
} }
void MacroAssembler::CallCFunction(Register function, int num_of_reg_args, int MacroAssembler::CallCFunction(Register function, int num_of_reg_args,
int num_of_double_args, int num_of_double_args,
SetIsolateDataSlots set_isolate_data_slots) { SetIsolateDataSlots set_isolate_data_slots,
Label* return_location) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
DCHECK_LE(num_of_reg_args + num_of_double_args, kMaxCParameters); DCHECK_LE(num_of_reg_args + num_of_double_args, kMaxCParameters);
DCHECK(has_frame()); DCHECK(has_frame());
Label get_pc;
if (set_isolate_data_slots == SetIsolateDataSlots::kYes) { if (set_isolate_data_slots == SetIsolateDataSlots::kYes) {
// Save the frame pointer and PC so that the stack layout remains iterable, // Save the frame pointer and PC so that the stack layout remains iterable,
// even without an ExitFrame which normally exists between JS and C frames. // even without an ExitFrame which normally exists between JS and C frames.
@ -2093,8 +2099,6 @@ void MacroAssembler::CallCFunction(Register function, int num_of_reg_args,
Register addr_scratch = x5; Register addr_scratch = x5;
Push(pc_scratch, addr_scratch); Push(pc_scratch, addr_scratch);
Label get_pc;
Bind(&get_pc);
Adr(pc_scratch, &get_pc); Adr(pc_scratch, &get_pc);
// See x64 code for reasoning about how to address the isolate data fields. // See x64 code for reasoning about how to address the isolate data fields.
@ -2119,6 +2123,9 @@ void MacroAssembler::CallCFunction(Register function, int num_of_reg_args,
// Call directly. The function called cannot cause a GC, or allow preemption, // Call directly. The function called cannot cause a GC, or allow preemption,
// so the return address in the link register stays correct. // so the return address in the link register stays correct.
Call(function); Call(function);
int call_pc_offset = pc_offset();
bind(&get_pc);
if (return_location) bind(return_location);
if (set_isolate_data_slots == SetIsolateDataSlots::kYes) { if (set_isolate_data_slots == SetIsolateDataSlots::kYes) {
// We don't unset the PC; the FP is the source of truth. // We don't unset the PC; the FP is the source of truth.
@ -2148,6 +2155,8 @@ void MacroAssembler::CallCFunction(Register function, int num_of_reg_args,
RoundUp(num_of_double_args - kFPRegisterPassedArguments, 2); RoundUp(num_of_double_args - kFPRegisterPassedArguments, 2);
Drop(claim_slots); Drop(claim_slots);
} }
return call_pc_offset;
} }
void MacroAssembler::LoadFromConstantsTable(Register destination, void MacroAssembler::LoadFromConstantsTable(Register destination,
@ -2459,27 +2468,30 @@ void MacroAssembler::TailCallBuiltin(Builtin builtin, Condition cond) {
} }
void MacroAssembler::LoadCodeInstructionStart(Register destination, void MacroAssembler::LoadCodeInstructionStart(Register destination,
Register code_object) { Register code_object,
CodeEntrypointTag tag) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
#ifdef V8_ENABLE_SANDBOX #ifdef V8_ENABLE_SANDBOX
LoadCodeEntrypointViaCodePointer( LoadCodeEntrypointViaCodePointer(
destination, destination,
FieldMemOperand(code_object, Code::kSelfIndirectPointerOffset)); FieldMemOperand(code_object, Code::kSelfIndirectPointerOffset), tag);
#else #else
Ldr(destination, FieldMemOperand(code_object, Code::kInstructionStartOffset)); Ldr(destination, FieldMemOperand(code_object, Code::kInstructionStartOffset));
#endif #endif
} }
void MacroAssembler::CallCodeObject(Register code_object) { void MacroAssembler::CallCodeObject(Register code_object,
CodeEntrypointTag tag) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
LoadCodeInstructionStart(code_object, code_object); LoadCodeInstructionStart(code_object, code_object, tag);
Call(code_object); Call(code_object);
} }
void MacroAssembler::JumpCodeObject(Register code_object, JumpMode jump_mode) { void MacroAssembler::JumpCodeObject(Register code_object, CodeEntrypointTag tag,
JumpMode jump_mode) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
DCHECK_EQ(JumpMode::kJump, jump_mode); DCHECK_EQ(JumpMode::kJump, jump_mode);
LoadCodeInstructionStart(code_object, code_object); LoadCodeInstructionStart(code_object, code_object, tag);
// We jump through x17 here because for Branch Identification (BTI) we use // We jump through x17 here because for Branch Identification (BTI) we use
// "Call" (`bti c`) rather than "Jump" (`bti j`) landing pads for tail-called // "Call" (`bti c`) rather than "Jump" (`bti j`) landing pads for tail-called
// code. See TailCallBuiltin for more information. // code. See TailCallBuiltin for more information.
@ -2496,12 +2508,13 @@ void MacroAssembler::CallJSFunction(Register function_object) {
// from the code pointer table instead of going through the Code object. In // from the code pointer table instead of going through the Code object. In
// this way, we avoid one memory load on this code path. // this way, we avoid one memory load on this code path.
LoadCodeEntrypointViaCodePointer( LoadCodeEntrypointViaCodePointer(
code, FieldMemOperand(function_object, JSFunction::kCodeOffset)); code, FieldMemOperand(function_object, JSFunction::kCodeOffset),
kJSEntrypointTag);
Call(code); Call(code);
#else #else
LoadTaggedField(code, LoadTaggedField(code,
FieldMemOperand(function_object, JSFunction::kCodeOffset)); FieldMemOperand(function_object, JSFunction::kCodeOffset));
CallCodeObject(code); CallCodeObject(code, kJSEntrypointTag);
#endif #endif
} }
@ -2513,7 +2526,8 @@ void MacroAssembler::JumpJSFunction(Register function_object,
// from the code pointer table instead of going through the Code object. In // from the code pointer table instead of going through the Code object. In
// this way, we avoid one memory load on this code path. // this way, we avoid one memory load on this code path.
LoadCodeEntrypointViaCodePointer( LoadCodeEntrypointViaCodePointer(
code, FieldMemOperand(function_object, JSFunction::kCodeOffset)); code, FieldMemOperand(function_object, JSFunction::kCodeOffset),
kJSEntrypointTag);
DCHECK_EQ(jump_mode, JumpMode::kJump); DCHECK_EQ(jump_mode, JumpMode::kJump);
// We jump through x17 here because for Branch Identification (BTI) we use // We jump through x17 here because for Branch Identification (BTI) we use
// "Call" (`bti c`) rather than "Jump" (`bti j`) landing pads for tail-called // "Call" (`bti c`) rather than "Jump" (`bti j`) landing pads for tail-called
@ -2524,7 +2538,7 @@ void MacroAssembler::JumpJSFunction(Register function_object,
#else #else
LoadTaggedField(code, LoadTaggedField(code,
FieldMemOperand(function_object, JSFunction::kCodeOffset)); FieldMemOperand(function_object, JSFunction::kCodeOffset));
JumpCodeObject(code, jump_mode); JumpCodeObject(code, kJSEntrypointTag, jump_mode);
#endif #endif
} }
@ -3479,8 +3493,8 @@ void MacroAssembler::CheckPageFlag(const Register& object, int mask,
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
UseScratchRegisterScope temps(this); UseScratchRegisterScope temps(this);
Register scratch = temps.AcquireX(); Register scratch = temps.AcquireX();
And(scratch, object, ~kPageAlignmentMask); And(scratch, object, ~MemoryChunkHeader::GetAlignmentMaskForAssembler());
Ldr(scratch, MemOperand(scratch, BasicMemoryChunk::kFlagsOffset)); Ldr(scratch, MemOperand(scratch, MemoryChunkLayout::kFlagsOffset));
if (cc == ne) { if (cc == ne) {
TestAndBranchIfAnySet(scratch, mask, condition_met); TestAndBranchIfAnySet(scratch, mask, condition_met);
} else { } else {
@ -3705,17 +3719,23 @@ void MacroAssembler::ResolveCodePointerHandle(Register destination,
Orr(destination, destination, Immediate(kHeapObjectTag)); Orr(destination, destination, Immediate(kHeapObjectTag));
} }
void MacroAssembler::LoadCodeEntrypointViaCodePointer( void MacroAssembler::LoadCodeEntrypointViaCodePointer(Register destination,
Register destination, MemOperand field_operand) { MemOperand field_operand,
CodeEntrypointTag tag) {
DCHECK_NE(tag, kInvalidEntrypointTag);
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
UseScratchRegisterScope temps(this); UseScratchRegisterScope temps(this);
Register table = temps.AcquireX(); Register scratch = temps.AcquireX();
Mov(table, ExternalReference::code_pointer_table_address()); Mov(scratch, ExternalReference::code_pointer_table_address());
Ldr(destination.W(), field_operand); Ldr(destination.W(), field_operand);
// TODO(saelo): can the offset computation be done more efficiently? // TODO(saelo): can the offset computation be done more efficiently?
Mov(destination, Operand(destination, LSR, kCodePointerHandleShift)); Mov(destination, Operand(destination, LSR, kCodePointerHandleShift));
Mov(destination, Operand(destination, LSL, kCodePointerTableEntrySizeLog2)); Mov(destination, Operand(destination, LSL, kCodePointerTableEntrySizeLog2));
Ldr(destination, MemOperand(table, destination)); Ldr(destination, MemOperand(scratch, destination));
if (tag != 0) {
Mov(scratch, Immediate(tag));
Eor(destination, destination, scratch);
}
} }
#endif // V8_ENABLE_SANDBOX #endif // V8_ENABLE_SANDBOX

View File

@ -1063,9 +1063,10 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
void TailCallBuiltin(Builtin builtin, Condition cond = al); void TailCallBuiltin(Builtin builtin, Condition cond = al);
// Load code entry point from the Code object. // Load code entry point from the Code object.
void LoadCodeInstructionStart(Register destination, Register code_object); void LoadCodeInstructionStart(Register destination, Register code_object,
void CallCodeObject(Register code_object); CodeEntrypointTag tag);
void JumpCodeObject(Register code_object, void CallCodeObject(Register code_object, CodeEntrypointTag tag);
void JumpCodeObject(Register code_object, CodeEntrypointTag tag,
JumpMode jump_mode = JumpMode::kJump); JumpMode jump_mode = JumpMode::kJump);
// Convenience functions to call/jmp to the code of a JSFunction object. // Convenience functions to call/jmp to the code of a JSFunction object.
@ -1083,25 +1084,24 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
DeoptimizeKind kind, Label* ret, DeoptimizeKind kind, Label* ret,
Label* jump_deoptimization_entry_label); Label* jump_deoptimization_entry_label);
// Calls a C function. // Calls a C function and cleans up the space for arguments allocated
// The called function is not allowed to trigger a // by PrepareCallCFunction. The called function is not allowed to trigger a
// garbage collection, since that might move the code and invalidate the // garbage collection, since that might move the code and invalidate the
// return address (unless this is somehow accounted for by the called // return address (unless this is somehow accounted for by the called
// function). // function).
enum class SetIsolateDataSlots { int CallCFunction(
kNo,
kYes,
};
void CallCFunction(
ExternalReference function, int num_reg_arguments, ExternalReference function, int num_reg_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
void CallCFunction( Label* return_location = nullptr);
int CallCFunction(
ExternalReference function, int num_reg_arguments, ExternalReference function, int num_reg_arguments,
int num_double_arguments, int num_double_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
void CallCFunction( Label* return_location = nullptr);
int CallCFunction(
Register function, int num_reg_arguments, int num_double_arguments, Register function, int num_reg_arguments, int num_double_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
Label* return_location = nullptr);
// Performs a truncating conversion of a floating point number as used by // Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32. // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
@ -1632,7 +1632,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
// Only available when the sandbox is enabled as it requires the code pointer // Only available when the sandbox is enabled as it requires the code pointer
// table. // table.
void LoadCodeEntrypointViaCodePointer(Register destination, void LoadCodeEntrypointViaCodePointer(Register destination,
MemOperand field_operand); MemOperand field_operand,
CodeEntrypointTag tag);
#endif #endif
// Load a protected pointer field. // Load a protected pointer field.

View File

@ -1842,12 +1842,12 @@ void CodeStubAssembler::StoreExternalPointerToObject(TNode<HeapObject> object,
#endif // V8_ENABLE_SANDBOX #endif // V8_ENABLE_SANDBOX
} }
TNode<HeapObject> CodeStubAssembler::LoadTrustedPointerFromObject( TNode<TrustedObject> CodeStubAssembler::LoadTrustedPointerFromObject(
TNode<HeapObject> object, int field_offset, IndirectPointerTag tag) { TNode<HeapObject> object, int field_offset, IndirectPointerTag tag) {
#ifdef V8_ENABLE_SANDBOX #ifdef V8_ENABLE_SANDBOX
return LoadIndirectPointerFromObject(object, field_offset, tag); return LoadIndirectPointerFromObject(object, field_offset, tag);
#else #else
return LoadObjectField<HeapObject>(object, field_offset); return LoadObjectField<TrustedObject>(object, field_offset);
#endif // V8_ENABLE_SANDBOX #endif // V8_ENABLE_SANDBOX
} }
@ -1858,7 +1858,7 @@ TNode<Code> CodeStubAssembler::LoadCodePointerFromObject(
} }
#ifdef V8_ENABLE_SANDBOX #ifdef V8_ENABLE_SANDBOX
TNode<HeapObject> CodeStubAssembler::LoadIndirectPointerFromObject( TNode<TrustedObject> CodeStubAssembler::LoadIndirectPointerFromObject(
TNode<HeapObject> object, int field_offset, IndirectPointerTag tag) { TNode<HeapObject> object, int field_offset, IndirectPointerTag tag) {
TNode<IndirectPointerHandleT> handle = TNode<IndirectPointerHandleT> handle =
LoadObjectField<IndirectPointerHandleT>(object, field_offset); LoadObjectField<IndirectPointerHandleT>(object, field_offset);
@ -1871,13 +1871,13 @@ TNode<BoolT> CodeStubAssembler::IsTrustedPointerHandle(
Int32Constant(0)); Int32Constant(0));
} }
TNode<HeapObject> CodeStubAssembler::ResolveIndirectPointerHandle( TNode<TrustedObject> CodeStubAssembler::ResolveIndirectPointerHandle(
TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag) { TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag) {
// The tag implies which pointer table to use. // The tag implies which pointer table to use.
if (tag == kUnknownIndirectPointerTag) { if (tag == kUnknownIndirectPointerTag) {
// In this case we have to rely on the handle marking to determine which // In this case we have to rely on the handle marking to determine which
// pointer table to use. // pointer table to use.
return Select<HeapObject>( return Select<TrustedObject>(
IsTrustedPointerHandle(handle), IsTrustedPointerHandle(handle),
[=] { return ResolveTrustedPointerHandle(handle, tag); }, [=] { return ResolveTrustedPointerHandle(handle, tag); },
[=] { return ResolveCodePointerHandle(handle); }); [=] { return ResolveCodePointerHandle(handle); });
@ -1903,7 +1903,7 @@ TNode<Code> CodeStubAssembler::ResolveCodePointerHandle(
return UncheckedCast<Code>(BitcastWordToTagged(value)); return UncheckedCast<Code>(BitcastWordToTagged(value));
} }
TNode<HeapObject> CodeStubAssembler::ResolveTrustedPointerHandle( TNode<TrustedObject> CodeStubAssembler::ResolveTrustedPointerHandle(
TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag) { TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag) {
TNode<RawPtrT> table = ExternalConstant( TNode<RawPtrT> table = ExternalConstant(
ExternalReference::trusted_pointer_table_base_address(isolate())); ExternalReference::trusted_pointer_table_base_address(isolate()));
@ -1919,7 +1919,7 @@ TNode<HeapObject> CodeStubAssembler::ResolveTrustedPointerHandle(
// to set it using a bitwise OR as it may or may not be set. // to set it using a bitwise OR as it may or may not be set.
value = value =
UncheckedCast<UintPtrT>(WordOr(value, UintPtrConstant(kHeapObjectTag))); UncheckedCast<UintPtrT>(WordOr(value, UintPtrConstant(kHeapObjectTag)));
return UncheckedCast<HeapObject>(BitcastWordToTagged(value)); return UncheckedCast<TrustedObject>(BitcastWordToTagged(value));
} }
TNode<UintPtrT> CodeStubAssembler::ComputeCodePointerTableEntryOffset( TNode<UintPtrT> CodeStubAssembler::ComputeCodePointerTableEntryOffset(
@ -1935,16 +1935,36 @@ TNode<UintPtrT> CodeStubAssembler::ComputeCodePointerTableEntryOffset(
} }
TNode<RawPtrT> CodeStubAssembler::LoadCodeEntrypointViaCodePointerField( TNode<RawPtrT> CodeStubAssembler::LoadCodeEntrypointViaCodePointerField(
TNode<HeapObject> object, TNode<IntPtrT> field_offset) { TNode<HeapObject> object, TNode<IntPtrT> field_offset,
CodeEntrypointTag tag) {
TNode<IndirectPointerHandleT> handle = TNode<IndirectPointerHandleT> handle =
LoadObjectField<IndirectPointerHandleT>(object, field_offset); LoadObjectField<IndirectPointerHandleT>(object, field_offset);
TNode<RawPtrT> table = TNode<RawPtrT> table =
ExternalConstant(ExternalReference::code_pointer_table_address()); ExternalConstant(ExternalReference::code_pointer_table_address());
TNode<UintPtrT> offset = ComputeCodePointerTableEntryOffset(handle); TNode<UintPtrT> offset = ComputeCodePointerTableEntryOffset(handle);
return Load<RawPtrT>(table, offset); TNode<UintPtrT> entry = Load<UintPtrT>(table, offset);
if (tag != 0) {
entry = UncheckedCast<UintPtrT>(WordXor(entry, UintPtrConstant(tag)));
}
return UncheckedCast<RawPtrT>(UncheckedCast<WordT>(entry));
} }
#endif // V8_ENABLE_SANDBOX #endif // V8_ENABLE_SANDBOX
TNode<TrustedObject> CodeStubAssembler::LoadProtectedPointerFromObject(
TNode<TrustedObject> object, int offset) {
#ifdef V8_ENABLE_SANDBOX
TNode<RawPtrT> trusted_cage_base = LoadPointerFromRootRegister(
IntPtrConstant(IsolateData::trusted_cage_base_offset()));
TNode<UintPtrT> offset_from_cage_base =
ChangeUint32ToWord(LoadObjectField<Uint32T>(object, offset));
TNode<UintPtrT> pointer =
UncheckedCast<UintPtrT>(WordOr(trusted_cage_base, offset_from_cage_base));
return UncheckedCast<TrustedObject>(BitcastWordToTagged(pointer));
#else
return LoadObjectField<TrustedObject>(object, offset);
#endif
}
TNode<Object> CodeStubAssembler::LoadFromParentFrame(int offset) { TNode<Object> CodeStubAssembler::LoadFromParentFrame(int offset) {
TNode<RawPtrT> frame_pointer = LoadParentFramePointer(); TNode<RawPtrT> frame_pointer = LoadParentFramePointer();
return LoadFullTagged(frame_pointer, IntPtrConstant(offset)); return LoadFullTagged(frame_pointer, IntPtrConstant(offset));
@ -2099,13 +2119,8 @@ TNode<HeapObject> CodeStubAssembler::LoadSlowProperties(
}; };
NodeGenerator<HeapObject> cast_properties = [=] { NodeGenerator<HeapObject> cast_properties = [=] {
TNode<HeapObject> dict = CAST(properties); TNode<HeapObject> dict = CAST(properties);
if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { CSA_DCHECK(this,
CSA_DCHECK(this, Word32Or(IsSwissNameDictionary(dict), Word32Or(IsPropertyDictionary(dict), IsGlobalDictionary(dict)));
IsGlobalDictionary(dict)));
} else {
CSA_DCHECK(this,
Word32Or(IsNameDictionary(dict), IsGlobalDictionary(dict)));
}
return dict; return dict;
}; };
return Select<HeapObject>(TaggedIsSmi(properties), make_empty, return Select<HeapObject>(TaggedIsSmi(properties), make_empty,
@ -2640,6 +2655,12 @@ TNode<IntPtrT> CodeStubAssembler::LoadArrayLength(
return LoadAndUntagWeakFixedArrayLength(array); return LoadAndUntagWeakFixedArrayLength(array);
} }
template <>
TNode<IntPtrT> CodeStubAssembler::LoadArrayLength(
TNode<TrustedFixedArray> array) {
return SmiUntag(LoadArrayCapacity(array));
}
template <typename Array, typename TIndex, typename TValue> template <typename Array, typename TIndex, typename TValue>
TNode<TValue> CodeStubAssembler::LoadArrayElement(TNode<Array> array, TNode<TValue> CodeStubAssembler::LoadArrayElement(TNode<Array> array,
int array_header_size, int array_header_size,
@ -2673,6 +2694,9 @@ template V8_EXPORT_PRIVATE TNode<Smi> CodeStubAssembler::LoadArrayElement<
template V8_EXPORT_PRIVATE TNode<Context> template V8_EXPORT_PRIVATE TNode<Context>
CodeStubAssembler::LoadArrayElement<ScriptContextTable, IntPtrT>( CodeStubAssembler::LoadArrayElement<ScriptContextTable, IntPtrT>(
TNode<ScriptContextTable>, int, TNode<IntPtrT>, int); TNode<ScriptContextTable>, int, TNode<IntPtrT>, int);
template V8_EXPORT_PRIVATE TNode<MaybeObject>
CodeStubAssembler::LoadArrayElement<TrustedFixedArray, IntPtrT>(
TNode<TrustedFixedArray>, int, TNode<IntPtrT>, int);
template <typename TIndex> template <typename TIndex>
TNode<Object> CodeStubAssembler::LoadFixedArrayElement( TNode<Object> CodeStubAssembler::LoadFixedArrayElement(
@ -3468,27 +3492,17 @@ TNode<BytecodeArray> CodeStubAssembler::LoadSharedFunctionInfoBytecodeArray(
this, Word32Equal(DecodeWord32<Code::KindField>(code_flags), this, Word32Equal(DecodeWord32<Code::KindField>(code_flags),
Int32Constant(static_cast<int>(CodeKind::BASELINE)))); Int32Constant(static_cast<int>(CodeKind::BASELINE))));
#endif // DEBUG #endif // DEBUG
TNode<HeapObject> baseline_data = LoadObjectField<HeapObject>( TNode<HeapObject> baseline_data = LoadProtectedPointerFromObject(
code, Code::kDeoptimizationDataOrInterpreterDataOffset); code, Code::kDeoptimizationDataOrInterpreterDataOffset);
var_result = baseline_data; var_result = baseline_data;
// As long as InterpreterData objects still live inside the sandbox, Code
// references BytecodeArrays through their in-sandbox wrapper object.
static_assert(!kInterpreterDataObjectsLiveInTrustedSpace);
GotoIfNot(HasInstanceType(var_result.value(), BYTECODE_WRAPPER_TYPE),
&check_for_interpreter_data);
TNode<HeapObject> bytecode = LoadTrustedPointerFromObject(
var_result.value(), BytecodeWrapper::kBytecodeOffset,
kBytecodeArrayIndirectPointerTag);
var_result = bytecode;
Goto(&done);
} }
Goto(&check_for_interpreter_data);
BIND(&check_for_interpreter_data); BIND(&check_for_interpreter_data);
GotoIfNot(HasInstanceType(var_result.value(), INTERPRETER_DATA_TYPE), &done); GotoIfNot(HasInstanceType(var_result.value(), INTERPRETER_DATA_TYPE), &done);
TNode<BytecodeArray> bytecode_array = CAST(LoadTrustedPointerFromObject( TNode<BytecodeArray> bytecode_array = CAST(LoadProtectedPointerFromObject(
var_result.value(), InterpreterData::kBytecodeArrayOffset, CAST(var_result.value()), InterpreterData::kBytecodeArrayOffset));
kBytecodeArrayIndirectPointerTag));
var_result = bytecode_array; var_result = bytecode_array;
Goto(&done); Goto(&done);
@ -4229,6 +4243,40 @@ TNode<NameDictionary> CodeStubAssembler::AllocateNameDictionaryWithCapacity(
return result; return result;
} }
TNode<PropertyDictionary> CodeStubAssembler::AllocatePropertyDictionary(
int at_least_space_for) {
TNode<HeapObject> dict;
if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
dict = AllocateSwissNameDictionary(at_least_space_for);
} else {
dict = AllocateNameDictionary(at_least_space_for);
}
return TNode<PropertyDictionary>::UncheckedCast(dict);
}
TNode<PropertyDictionary> CodeStubAssembler::AllocatePropertyDictionary(
TNode<IntPtrT> at_least_space_for, AllocationFlags flags) {
TNode<HeapObject> dict;
if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
dict = AllocateSwissNameDictionary(at_least_space_for);
} else {
dict = AllocateNameDictionary(at_least_space_for, flags);
}
return TNode<PropertyDictionary>::UncheckedCast(dict);
}
TNode<PropertyDictionary>
CodeStubAssembler::AllocatePropertyDictionaryWithCapacity(
TNode<IntPtrT> capacity, AllocationFlags flags) {
TNode<HeapObject> dict;
if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
dict = AllocateSwissNameDictionaryWithCapacity(capacity);
} else {
dict = AllocateNameDictionaryWithCapacity(capacity, flags);
}
return TNode<PropertyDictionary>::UncheckedCast(dict);
}
TNode<NameDictionary> CodeStubAssembler::CopyNameDictionary( TNode<NameDictionary> CodeStubAssembler::CopyNameDictionary(
TNode<NameDictionary> dictionary, Label* large_object_fallback) { TNode<NameDictionary> dictionary, Label* large_object_fallback) {
Comment("Copy boilerplate property dict"); Comment("Copy boilerplate property dict");
@ -4423,9 +4471,8 @@ void CodeStubAssembler::InitializeJSObjectFromMap(
StoreObjectFieldRoot(object, JSObject::kPropertiesOrHashOffset, StoreObjectFieldRoot(object, JSObject::kPropertiesOrHashOffset,
RootIndex::kEmptyFixedArray); RootIndex::kEmptyFixedArray);
} else { } else {
CSA_DCHECK(this, Word32Or(Word32Or(Word32Or(IsPropertyArray(*properties), CSA_DCHECK(this, Word32Or(Word32Or(IsPropertyArray(*properties),
IsNameDictionary(*properties)), IsPropertyDictionary(*properties)),
IsSwissNameDictionary(*properties)),
IsEmptyFixedArray(*properties))); IsEmptyFixedArray(*properties)));
StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOrHashOffset, StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOrHashOffset,
*properties); *properties);
@ -5013,9 +5060,9 @@ TNode<FixedArray> CodeStubAssembler::ExtractToFixedArray(
#ifndef V8_ENABLE_SINGLE_GENERATION #ifndef V8_ENABLE_SINGLE_GENERATION
#ifdef DEBUG #ifdef DEBUG
TNode<IntPtrT> object_word = BitcastTaggedToWord(to_elements); TNode<IntPtrT> object_word = BitcastTaggedToWord(to_elements);
TNode<IntPtrT> object_page = PageFromAddress(object_word); TNode<IntPtrT> object_page_header = PageHeaderFromAddress(object_word);
TNode<IntPtrT> page_flags = TNode<IntPtrT> page_flags = Load<IntPtrT>(
Load<IntPtrT>(object_page, IntPtrConstant(Page::kFlagsOffset)); object_page_header, IntPtrConstant(MemoryChunkLayout::kFlagsOffset));
CSA_DCHECK( CSA_DCHECK(
this, this,
WordNotEqual( WordNotEqual(
@ -5414,9 +5461,10 @@ void CodeStubAssembler::JumpIfPointersFromHereAreInteresting(
TNode<Object> object, Label* interesting) { TNode<Object> object, Label* interesting) {
Label finished(this); Label finished(this);
TNode<IntPtrT> object_word = BitcastTaggedToWord(object); TNode<IntPtrT> object_word = BitcastTaggedToWord(object);
TNode<IntPtrT> object_page = PageFromAddress(object_word); TNode<IntPtrT> object_page_header = PageHeaderFromAddress(object_word);
TNode<IntPtrT> page_flags = UncheckedCast<IntPtrT>(Load( TNode<IntPtrT> page_flags = UncheckedCast<IntPtrT>(
MachineType::IntPtr(), object_page, IntPtrConstant(Page::kFlagsOffset))); Load(MachineType::IntPtr(), object_page_header,
IntPtrConstant(MemoryChunkLayout::kFlagsOffset)));
Branch( Branch(
WordEqual(WordAnd(page_flags, WordEqual(WordAnd(page_flags,
IntPtrConstant( IntPtrConstant(
@ -7617,19 +7665,15 @@ TNode<BoolT> CodeStubAssembler::IsEphemeronHashTable(TNode<HeapObject> object) {
return HasInstanceType(object, EPHEMERON_HASH_TABLE_TYPE); return HasInstanceType(object, EPHEMERON_HASH_TABLE_TYPE);
} }
TNode<BoolT> CodeStubAssembler::IsNameDictionary(TNode<HeapObject> object) { TNode<BoolT> CodeStubAssembler::IsPropertyDictionary(TNode<HeapObject> object) {
return HasInstanceType(object, NAME_DICTIONARY_TYPE); return HasInstanceType(object, PROPERTY_DICTIONARY_TYPE);
} }
TNode<BoolT> CodeStubAssembler::IsOrderedNameDictionary( TNode<BoolT> CodeStubAssembler::IsOrderedNameDictionary(
TNode<HeapObject> object) { TNode<HeapObject> object) {
return HasInstanceType(object, ORDERED_NAME_DICTIONARY_TYPE); return HasInstanceType(object, ORDERED_NAME_DICTIONARY_TYPE);
} }
TNode<BoolT> CodeStubAssembler::IsSwissNameDictionary(
TNode<HeapObject> object) {
return HasInstanceType(object, SWISS_NAME_DICTIONARY_TYPE);
}
TNode<BoolT> CodeStubAssembler::IsGlobalDictionary(TNode<HeapObject> object) { TNode<BoolT> CodeStubAssembler::IsGlobalDictionary(TNode<HeapObject> object) {
return HasInstanceType(object, GLOBAL_DICTIONARY_TYPE); return HasInstanceType(object, GLOBAL_DICTIONARY_TYPE);
} }
@ -7823,10 +7867,10 @@ TNode<BoolT> CodeStubAssembler::IsNumberArrayIndex(TNode<Number> number) {
TNode<IntPtrT> CodeStubAssembler::LoadBasicMemoryChunkFlags( TNode<IntPtrT> CodeStubAssembler::LoadBasicMemoryChunkFlags(
TNode<HeapObject> object) { TNode<HeapObject> object) {
TNode<IntPtrT> object_word = BitcastTaggedToWord(object); TNode<IntPtrT> object_word = BitcastTaggedToWord(object);
TNode<IntPtrT> page = PageFromAddress(object_word); TNode<IntPtrT> page_header = PageHeaderFromAddress(object_word);
return UncheckedCast<IntPtrT>( return UncheckedCast<IntPtrT>(
Load(MachineType::Pointer(), page, Load(MachineType::Pointer(), page_header,
IntPtrConstant(BasicMemoryChunk::kFlagsOffset))); IntPtrConstant(MemoryChunkLayout::kFlagsOffset)));
} }
template <typename TIndex> template <typename TIndex>
@ -9410,7 +9454,8 @@ TNode<IntPtrT> CodeStubAssembler::NameToIndexHashTableLookup(
template <typename Dictionary> template <typename Dictionary>
void CodeStubAssembler::NameDictionaryLookup( void CodeStubAssembler::NameDictionaryLookup(
TNode<Dictionary> dictionary, TNode<Name> unique_name, Label* if_found, TNode<Dictionary> dictionary, TNode<Name> unique_name, Label* if_found,
TVariable<IntPtrT>* var_name_index, Label* if_not_found, LookupMode mode) { TVariable<IntPtrT>* var_name_index, Label* if_not_found_no_insertion_index,
LookupMode mode, Label* if_not_found_with_insertion_index) {
static_assert(std::is_same<Dictionary, NameDictionary>::value || static_assert(std::is_same<Dictionary, NameDictionary>::value ||
std::is_same<Dictionary, GlobalDictionary>::value || std::is_same<Dictionary, GlobalDictionary>::value ||
std::is_same<Dictionary, NameToIndexHashTable>::value, std::is_same<Dictionary, NameToIndexHashTable>::value,
@ -9418,8 +9463,13 @@ void CodeStubAssembler::NameDictionaryLookup(
DCHECK_IMPLIES(var_name_index != nullptr, DCHECK_IMPLIES(var_name_index != nullptr,
MachineType::PointerRepresentation() == var_name_index->rep()); MachineType::PointerRepresentation() == var_name_index->rep());
DCHECK_IMPLIES(mode == kFindInsertionIndex, if_found == nullptr); DCHECK_IMPLIES(mode == kFindInsertionIndex, if_found == nullptr);
DCHECK_IMPLIES(if_not_found_with_insertion_index != nullptr,
var_name_index != nullptr);
Comment("NameDictionaryLookup"); Comment("NameDictionaryLookup");
CSA_DCHECK(this, IsUniqueName(unique_name)); CSA_DCHECK(this, IsUniqueName(unique_name));
if (if_not_found_with_insertion_index == nullptr) {
if_not_found_with_insertion_index = if_not_found_no_insertion_index;
}
Label if_not_computed(this, Label::kDeferred); Label if_not_computed(this, Label::kDeferred);
@ -9453,16 +9503,17 @@ void CodeStubAssembler::NameDictionaryLookup(
TNode<HeapObject> current = TNode<HeapObject> current =
CAST(UnsafeLoadFixedArrayElement(dictionary, index)); CAST(UnsafeLoadFixedArrayElement(dictionary, index));
GotoIf(TaggedEqual(current, undefined), if_not_found); GotoIf(TaggedEqual(current, undefined), if_not_found_with_insertion_index);
if (mode == kFindExisting) { if (mode == kFindExisting) {
if (Dictionary::ShapeT::kMatchNeedsHoleCheck) { if (Dictionary::TodoShape::kMatchNeedsHoleCheck) {
GotoIf(TaggedEqual(current, TheHoleConstant()), &next_probe); GotoIf(TaggedEqual(current, TheHoleConstant()), &next_probe);
} }
current = LoadName<Dictionary>(current); current = LoadName<Dictionary>(current);
GotoIf(TaggedEqual(current, unique_name), if_found); GotoIf(TaggedEqual(current, unique_name), if_found);
} else { } else {
DCHECK_EQ(kFindInsertionIndex, mode); DCHECK_EQ(kFindInsertionIndex, mode);
GotoIf(TaggedEqual(current, TheHoleConstant()), if_not_found); GotoIf(TaggedEqual(current, TheHoleConstant()),
if_not_found_with_insertion_index);
} }
Goto(&next_probe); Goto(&next_probe);
@ -9507,14 +9558,19 @@ void CodeStubAssembler::NameDictionaryLookup(
std::make_pair(MachineType::Pointer(), isolate_ptr), std::make_pair(MachineType::Pointer(), isolate_ptr),
std::make_pair(MachineType::TaggedPointer(), dictionary), std::make_pair(MachineType::TaggedPointer(), dictionary),
std::make_pair(MachineType::TaggedPointer(), unique_name))); std::make_pair(MachineType::TaggedPointer(), unique_name)));
if (var_name_index) *var_name_index = EntryToIndex<Dictionary>(entry); if (var_name_index) *var_name_index = EntryToIndex<Dictionary>(entry);
if (mode == kFindExisting) { if (mode == kFindExisting) {
GotoIf(IntPtrEqual(entry, GotoIf(IntPtrEqual(entry,
IntPtrConstant(InternalIndex::NotFound().raw_value())), IntPtrConstant(InternalIndex::NotFound().raw_value())),
if_not_found); if_not_found_no_insertion_index);
Goto(if_found); Goto(if_found);
} else { } else {
Goto(if_not_found); CSA_DCHECK(
this,
WordNotEqual(entry,
IntPtrConstant(InternalIndex::NotFound().raw_value())));
Goto(if_not_found_with_insertion_index);
} }
} }
} }
@ -9524,10 +9580,11 @@ template V8_EXPORT_PRIVATE void
CodeStubAssembler::NameDictionaryLookup<NameDictionary>(TNode<NameDictionary>, CodeStubAssembler::NameDictionaryLookup<NameDictionary>(TNode<NameDictionary>,
TNode<Name>, Label*, TNode<Name>, Label*,
TVariable<IntPtrT>*, TVariable<IntPtrT>*,
Label*, LookupMode); Label*, LookupMode,
Label*);
template V8_EXPORT_PRIVATE void CodeStubAssembler::NameDictionaryLookup< template V8_EXPORT_PRIVATE void CodeStubAssembler::NameDictionaryLookup<
GlobalDictionary>(TNode<GlobalDictionary>, TNode<Name>, Label*, GlobalDictionary>(TNode<GlobalDictionary>, TNode<Name>, Label*,
TVariable<IntPtrT>*, Label*, LookupMode); TVariable<IntPtrT>*, Label*, LookupMode, Label*);
TNode<Word32T> CodeStubAssembler::ComputeSeededHash(TNode<IntPtrT> key) { TNode<Word32T> CodeStubAssembler::ComputeSeededHash(TNode<IntPtrT> key) {
const TNode<ExternalReference> function_addr = const TNode<ExternalReference> function_addr =
@ -9547,10 +9604,13 @@ TNode<Word32T> CodeStubAssembler::ComputeSeededHash(TNode<IntPtrT> key) {
template <> template <>
void CodeStubAssembler::NameDictionaryLookup( void CodeStubAssembler::NameDictionaryLookup(
TNode<SwissNameDictionary> dictionary, TNode<Name> unique_name, TNode<SwissNameDictionary> dictionary, TNode<Name> unique_name,
Label* if_found, TVariable<IntPtrT>* var_name_index, Label* if_not_found, Label* if_found, TVariable<IntPtrT>* var_name_index,
LookupMode mode) { Label* if_not_found_no_insertion_index, LookupMode mode,
Label* if_not_found_with_insertion_index) {
// TODO(pthier): Support path for not found with valid insertion index for
// SwissNameDictionary.
SwissNameDictionaryFindEntry(dictionary, unique_name, if_found, SwissNameDictionaryFindEntry(dictionary, unique_name, if_found,
var_name_index, if_not_found); var_name_index, if_not_found_no_insertion_index);
} }
void CodeStubAssembler::NumberDictionaryLookup( void CodeStubAssembler::NumberDictionaryLookup(
@ -9707,9 +9767,9 @@ void CodeStubAssembler::InsertEntry<GlobalDictionary>(
} }
template <class Dictionary> template <class Dictionary>
void CodeStubAssembler::AddToDictionary(TNode<Dictionary> dictionary, void CodeStubAssembler::AddToDictionary(
TNode<Name> key, TNode<Object> value, TNode<Dictionary> dictionary, TNode<Name> key, TNode<Object> value,
Label* bailout) { Label* bailout, base::Optional<TNode<IntPtrT>> insertion_index) {
CSA_DCHECK(this, Word32BinaryNot(IsEmptyPropertyDictionary(dictionary))); CSA_DCHECK(this, Word32BinaryNot(IsEmptyPropertyDictionary(dictionary)));
TNode<Smi> capacity = GetCapacity<Dictionary>(dictionary); TNode<Smi> capacity = GetCapacity<Dictionary>(dictionary);
TNode<Smi> nof = GetNumberOfElements<Dictionary>(dictionary); TNode<Smi> nof = GetNumberOfElements<Dictionary>(dictionary);
@ -9737,16 +9797,21 @@ void CodeStubAssembler::AddToDictionary(TNode<Dictionary> dictionary,
SetNextEnumerationIndex<Dictionary>(dictionary, new_enum_index); SetNextEnumerationIndex<Dictionary>(dictionary, new_enum_index);
SetNumberOfElements<Dictionary>(dictionary, new_nof); SetNumberOfElements<Dictionary>(dictionary, new_nof);
TVARIABLE(IntPtrT, var_key_index); if (insertion_index.has_value()) {
FindInsertionEntry<Dictionary>(dictionary, key, &var_key_index); InsertEntry<Dictionary>(dictionary, key, value, *insertion_index,
InsertEntry<Dictionary>(dictionary, key, value, var_key_index.value(), enum_index);
enum_index); } else {
TVARIABLE(IntPtrT, var_key_index);
FindInsertionEntry<Dictionary>(dictionary, key, &var_key_index);
InsertEntry<Dictionary>(dictionary, key, value, var_key_index.value(),
enum_index);
}
} }
template <> template <>
void CodeStubAssembler::AddToDictionary(TNode<SwissNameDictionary> dictionary, void CodeStubAssembler::AddToDictionary(
TNode<Name> key, TNode<Object> value, TNode<SwissNameDictionary> dictionary, TNode<Name> key, TNode<Object> value,
Label* bailout) { Label* bailout, base::Optional<TNode<IntPtrT>> insertion_index) {
PropertyDetails d(PropertyKind::kData, NONE, PropertyDetails d(PropertyKind::kData, NONE,
PropertyDetails::kConstIfDictConstnessTracking); PropertyDetails::kConstIfDictConstnessTracking);
@ -9765,11 +9830,13 @@ void CodeStubAssembler::AddToDictionary(TNode<SwissNameDictionary> dictionary,
Goto(&not_private); Goto(&not_private);
BIND(&not_private); BIND(&not_private);
// TODO(pthier): Use insertion_index if it was provided.
SwissNameDictionaryAdd(dictionary, key, value, var_details.value(), bailout); SwissNameDictionaryAdd(dictionary, key, value, var_details.value(), bailout);
} }
template void CodeStubAssembler::AddToDictionary<NameDictionary>( template void CodeStubAssembler::AddToDictionary<NameDictionary>(
TNode<NameDictionary>, TNode<Name>, TNode<Object>, Label*); TNode<NameDictionary>, TNode<Name>, TNode<Object>, Label*,
base::Optional<TNode<IntPtrT>>);
template <class Dictionary> template <class Dictionary>
TNode<Smi> CodeStubAssembler::GetNumberOfElements( TNode<Smi> CodeStubAssembler::GetNumberOfElements(
@ -11083,9 +11150,9 @@ TNode<Object> CodeStubAssembler::GetInterestingProperty(
TNode<Object> properties = TNode<Object> properties =
LoadObjectField(holder, JSObject::kPropertiesOrHashOffset); LoadObjectField(holder, JSObject::kPropertiesOrHashOffset);
CSA_DCHECK(this, TaggedIsNotSmi(properties)); CSA_DCHECK(this, TaggedIsNotSmi(properties));
CSA_DCHECK(this, IsPropertyDictionary(CAST(properties)));
// TODO(pthier): Support swiss dictionaries. // TODO(pthier): Support swiss dictionaries.
if constexpr (!V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { if constexpr (!V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
CSA_DCHECK(this, IsNameDictionary(CAST(properties)));
TNode<Smi> flags = TNode<Smi> flags =
GetNameDictionaryFlags<NameDictionary>(CAST(properties)); GetNameDictionaryFlags<NameDictionary>(CAST(properties));
GotoIf(IsSetSmi(flags, GotoIf(IsSetSmi(flags,
@ -12748,10 +12815,10 @@ void CodeStubAssembler::TrapAllocationMemento(TNode<JSObject> object,
TNode<IntPtrT> object_word = BitcastTaggedToWord(object); TNode<IntPtrT> object_word = BitcastTaggedToWord(object);
// TODO(v8:11641): Skip TrapAllocationMemento when allocation-site // TODO(v8:11641): Skip TrapAllocationMemento when allocation-site
// tracking is disabled. // tracking is disabled.
TNode<IntPtrT> object_page = PageFromAddress(object_word); TNode<IntPtrT> object_page_header = PageHeaderFromAddress(object_word);
{ {
TNode<IntPtrT> page_flags = TNode<IntPtrT> page_flags = Load<IntPtrT>(
Load<IntPtrT>(object_page, IntPtrConstant(Page::kFlagsOffset)); object_page_header, IntPtrConstant(MemoryChunkLayout::kFlagsOffset));
GotoIf(WordEqual( GotoIf(WordEqual(
WordAnd(page_flags, WordAnd(page_flags,
IntPtrConstant(MemoryChunk::kIsInYoungGenerationMask)), IntPtrConstant(MemoryChunk::kIsInYoungGenerationMask)),
@ -12767,20 +12834,23 @@ void CodeStubAssembler::TrapAllocationMemento(TNode<JSObject> object,
TNode<IntPtrT> memento_last_word = IntPtrAdd( TNode<IntPtrT> memento_last_word = IntPtrAdd(
object_word, IntPtrConstant(kMementoLastWordOffset - kHeapObjectTag)); object_word, IntPtrConstant(kMementoLastWordOffset - kHeapObjectTag));
TNode<IntPtrT> memento_last_word_page = PageFromAddress(memento_last_word); TNode<IntPtrT> memento_last_word_page_header =
PageHeaderFromAddress(memento_last_word);
TNode<IntPtrT> new_space_top = Load<IntPtrT>(new_space_top_address); TNode<IntPtrT> new_space_top = Load<IntPtrT>(new_space_top_address);
TNode<IntPtrT> new_space_top_page = PageFromAddress(new_space_top); TNode<IntPtrT> new_space_top_page_header =
PageHeaderFromAddress(new_space_top);
// If the object is in new space, we need to check whether respective // If the object is in new space, we need to check whether respective
// potential memento object is on the same page as the current top. // potential memento object is on the same page as the current top.
GotoIf(WordEqual(memento_last_word_page, new_space_top_page), &top_check); GotoIf(WordEqual(memento_last_word_page_header, new_space_top_page_header),
&top_check);
// The object is on a different page than allocation top. Bail out if the // The object is on a different page than allocation top. Bail out if the
// object sits on the page boundary as no memento can follow and we cannot // object sits on the page boundary as no memento can follow and we cannot
// touch the memory following it. // touch the memory following it.
Branch(WordEqual(object_page, memento_last_word_page), &map_check, Branch(WordEqual(object_page_header, memento_last_word_page_header),
&no_memento_found); &map_check, &no_memento_found);
// If top is on the same page as the current object, we need to check whether // If top is on the same page as the current object, we need to check whether
// we are below top. // we are below top.
@ -12804,9 +12874,22 @@ void CodeStubAssembler::TrapAllocationMemento(TNode<JSObject> object,
Comment("] TrapAllocationMemento"); Comment("] TrapAllocationMemento");
} }
TNode<IntPtrT> CodeStubAssembler::PageHeaderFromAddress(
TNode<IntPtrT> address) {
DCHECK(!V8_ENABLE_THIRD_PARTY_HEAP_BOOL);
return WordAnd(
address,
IntPtrConstant(~MemoryChunkHeader::GetAlignmentMaskForAssembler()));
}
TNode<IntPtrT> CodeStubAssembler::PageFromPageHeader(TNode<IntPtrT> address) {
DCHECK(!V8_ENABLE_THIRD_PARTY_HEAP_BOOL);
return address;
}
TNode<IntPtrT> CodeStubAssembler::PageFromAddress(TNode<IntPtrT> address) { TNode<IntPtrT> CodeStubAssembler::PageFromAddress(TNode<IntPtrT> address) {
DCHECK(!V8_ENABLE_THIRD_PARTY_HEAP_BOOL); DCHECK(!V8_ENABLE_THIRD_PARTY_HEAP_BOOL);
return WordAnd(address, IntPtrConstant(~kPageAlignmentMask)); return PageFromPageHeader(PageHeaderFromAddress(address));
} }
TNode<AllocationSite> CodeStubAssembler::CreateAllocationSiteInFeedbackVector( TNode<AllocationSite> CodeStubAssembler::CreateAllocationSiteInFeedbackVector(
@ -13230,6 +13313,18 @@ TNode<Context> CodeStubAssembler::GotoIfHasContextExtensionUpToDepth(
Goto(&context_search); Goto(&context_search);
BIND(&context_search); BIND(&context_search);
{ {
#if DEBUG
// Const tracking let data is stored in the extension slot of a
// ScriptContext - however, it's unrelated to the sloppy eval variable
// extension. We should never iterate through a ScriptContext here.
auto scope_info = LoadScopeInfo(cur_context.value());
TNode<Int32T> flags =
LoadAndUntagToWord32ObjectField(scope_info, ScopeInfo::kFlagsOffset);
auto scope_type = DecodeWord32<ScopeInfo::ScopeTypeBits>(flags);
CSA_DCHECK(this, Word32NotEqual(scope_type,
Int32Constant(ScopeType::SCRIPT_SCOPE)));
#endif
// Check if context has an extension slot. // Check if context has an extension slot.
TNode<BoolT> has_extension = TNode<BoolT> has_extension =
LoadScopeInfoHasExtensionField(LoadScopeInfo(cur_context.value())); LoadScopeInfoHasExtensionField(LoadScopeInfo(cur_context.value()));
@ -16301,8 +16396,8 @@ TNode<Code> CodeStubAssembler::GetSharedFunctionInfoCode(
CSA_DCHECK(this, CSA_DCHECK(this,
Word32Equal(data_type, Int32Constant(INTERPRETER_DATA_TYPE))); Word32Equal(data_type, Int32Constant(INTERPRETER_DATA_TYPE)));
{ {
TNode<Code> trampoline = LoadCodePointerFromObject( TNode<Code> trampoline = CAST(LoadProtectedPointerFromObject(
CAST(sfi_data), InterpreterData::kInterpreterTrampolineOffset); CAST(sfi_data), InterpreterData::kInterpreterTrampolineOffset));
sfi_code = trampoline; sfi_code = trampoline;
} }
Goto(&done); Goto(&done);
@ -16329,12 +16424,13 @@ TNode<Code> CodeStubAssembler::GetSharedFunctionInfoCode(
return sfi_code.value(); return sfi_code.value();
} }
TNode<RawPtrT> CodeStubAssembler::LoadCodeInstructionStart(TNode<Code> code) { TNode<RawPtrT> CodeStubAssembler::LoadCodeInstructionStart(
TNode<Code> code, CodeEntrypointTag tag) {
#ifdef V8_ENABLE_SANDBOX #ifdef V8_ENABLE_SANDBOX
// In this case, the entrypoint is stored in the code pointer table entry // In this case, the entrypoint is stored in the code pointer table entry
// referenced via the Code object's 'self' indirect pointer. // referenced via the Code object's 'self' indirect pointer.
return LoadCodeEntrypointViaCodePointerField( return LoadCodeEntrypointViaCodePointerField(
code, Code::kSelfIndirectPointerOffset); code, Code::kSelfIndirectPointerOffset, tag);
#else #else
return LoadObjectField<RawPtrT>(code, Code::kInstructionStartOffset); return LoadObjectField<RawPtrT>(code, Code::kInstructionStartOffset);
#endif #endif
@ -16439,15 +16535,14 @@ TNode<Map> CodeStubAssembler::CheckEnumCache(TNode<JSReceiver> receiver,
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85149 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85149
// TODO(miladfarca): Use `if constexpr` once all compilers handle this // TODO(miladfarca): Use `if constexpr` once all compilers handle this
// properly. // properly.
CSA_DCHECK(this, Word32Or(IsPropertyDictionary(properties),
IsGlobalDictionary(properties)));
if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
CSA_DCHECK(this, Word32Or(IsSwissNameDictionary(properties),
IsGlobalDictionary(properties)));
length = Select<Smi>( length = Select<Smi>(
IsSwissNameDictionary(properties), IsPropertyDictionary(properties),
[=] { [=] {
return GetNumberOfElements( return GetNumberOfElements(
UncheckedCast<SwissNameDictionary>(properties)); UncheckedCast<PropertyDictionary>(properties));
}, },
[=] { [=] {
return GetNumberOfElements( return GetNumberOfElements(
@ -16455,8 +16550,6 @@ TNode<Map> CodeStubAssembler::CheckEnumCache(TNode<JSReceiver> receiver,
}); });
} else { } else {
CSA_DCHECK(this, Word32Or(IsNameDictionary(properties),
IsGlobalDictionary(properties)));
static_assert(static_cast<int>(NameDictionary::kNumberOfElementsIndex) == static_assert(static_cast<int>(NameDictionary::kNumberOfElementsIndex) ==
static_cast<int>(GlobalDictionary::kNumberOfElementsIndex)); static_cast<int>(GlobalDictionary::kNumberOfElementsIndex));
length = GetNumberOfElements(UncheckedCast<HashTableBase>(properties)); length = GetNumberOfElements(UncheckedCast<HashTableBase>(properties));

View File

@ -18,6 +18,7 @@
#include "src/objects/arguments.h" #include "src/objects/arguments.h"
#include "src/objects/bigint.h" #include "src/objects/bigint.h"
#include "src/objects/cell.h" #include "src/objects/cell.h"
#include "src/objects/dictionary.h"
#include "src/objects/feedback-vector.h" #include "src/objects/feedback-vector.h"
#include "src/objects/heap-number.h" #include "src/objects/heap-number.h"
#include "src/objects/hole.h" #include "src/objects/hole.h"
@ -358,6 +359,14 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
#define CSA_SLOW_DCHECK(csa, ...) ((void)0) #define CSA_SLOW_DCHECK(csa, ...) ((void)0)
#endif #endif
// Similar to SBXCHECK in C++, these become a CSA_CHECK in sandbox-enabled
// builds, otherwise a CSA_DCHECK.
#ifdef V8_ENABLE_SANDBOX
#define CSA_SBXCHECK(csa, ...) CSA_CHECK(csa, __VA_ARGS__)
#else
#define CSA_SBXCHECK(csa, ...) CSA_DCHECK(csa, __VA_ARGS__)
#endif
// Provides JavaScript-specific "macro-assembler" functionality on top of the // Provides JavaScript-specific "macro-assembler" functionality on top of the
// CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler, // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
// it's possible to add JavaScript-specific useful CodeAssembler "macros" // it's possible to add JavaScript-specific useful CodeAssembler "macros"
@ -922,7 +931,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
void FastCheck(TNode<BoolT> condition); void FastCheck(TNode<BoolT> condition);
TNode<RawPtrT> LoadCodeInstructionStart(TNode<Code> code); TNode<RawPtrT> LoadCodeInstructionStart(TNode<Code> code,
CodeEntrypointTag tag);
TNode<BoolT> IsMarkedForDeoptimization(TNode<Code> code); TNode<BoolT> IsMarkedForDeoptimization(TNode<Code> code);
// The following Call wrappers call an object according to the semantics that // The following Call wrappers call an object according to the semantics that
@ -1193,9 +1203,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Load a trusted pointer field. // Load a trusted pointer field.
// When the sandbox is enabled, these are indirect pointers using the trusted // When the sandbox is enabled, these are indirect pointers using the trusted
// pointer table. Otherwise they are regular tagged fields. // pointer table. Otherwise they are regular tagged fields.
TNode<HeapObject> LoadTrustedPointerFromObject(TNode<HeapObject> object, TNode<TrustedObject> LoadTrustedPointerFromObject(TNode<HeapObject> object,
int offset, int offset,
IndirectPointerTag tag); IndirectPointerTag tag);
// Load a code pointer field. // Load a code pointer field.
// These are special versions of trusted pointers that, when the sandbox is // These are special versions of trusted pointers that, when the sandbox is
@ -1204,9 +1214,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
#ifdef V8_ENABLE_SANDBOX #ifdef V8_ENABLE_SANDBOX
// Load an indirect pointer field. // Load an indirect pointer field.
TNode<HeapObject> LoadIndirectPointerFromObject(TNode<HeapObject> object, TNode<TrustedObject> LoadIndirectPointerFromObject(TNode<HeapObject> object,
int offset, int offset,
IndirectPointerTag tag); IndirectPointerTag tag);
// Determines whether the given indirect pointer handle is a trusted pointer // Determines whether the given indirect pointer handle is a trusted pointer
// handle or a code pointer handle. // handle or a code pointer handle.
@ -1214,14 +1224,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Retrieve the heap object referenced by the given indirect pointer handle, // Retrieve the heap object referenced by the given indirect pointer handle,
// which can either be a trusted pointer handle or a code pointer handle. // which can either be a trusted pointer handle or a code pointer handle.
TNode<HeapObject> ResolveIndirectPointerHandle( TNode<TrustedObject> ResolveIndirectPointerHandle(
TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag); TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag);
// Retrieve the Code object referenced by the given trusted pointer handle. // Retrieve the Code object referenced by the given trusted pointer handle.
TNode<Code> ResolveCodePointerHandle(TNode<IndirectPointerHandleT> handle); TNode<Code> ResolveCodePointerHandle(TNode<IndirectPointerHandleT> handle);
// Retrieve the heap object referenced by the given trusted pointer handle. // Retrieve the heap object referenced by the given trusted pointer handle.
TNode<HeapObject> ResolveTrustedPointerHandle( TNode<TrustedObject> ResolveTrustedPointerHandle(
TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag); TNode<IndirectPointerHandleT> handle, IndirectPointerTag tag);
// Helper function to compute the offset into the code pointer table from a // Helper function to compute the offset into the code pointer table from a
@ -1233,14 +1243,19 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Only available when the sandbox is enabled as it requires the code pointer // Only available when the sandbox is enabled as it requires the code pointer
// table. // table.
TNode<RawPtrT> LoadCodeEntrypointViaCodePointerField(TNode<HeapObject> object, TNode<RawPtrT> LoadCodeEntrypointViaCodePointerField(TNode<HeapObject> object,
int offset) { int offset,
return LoadCodeEntrypointViaCodePointerField(object, CodeEntrypointTag tag) {
IntPtrConstant(offset)); return LoadCodeEntrypointViaCodePointerField(object, IntPtrConstant(offset),
tag);
} }
TNode<RawPtrT> LoadCodeEntrypointViaCodePointerField(TNode<HeapObject> object, TNode<RawPtrT> LoadCodeEntrypointViaCodePointerField(TNode<HeapObject> object,
TNode<IntPtrT> offset); TNode<IntPtrT> offset,
CodeEntrypointTag tag);
#endif #endif
TNode<TrustedObject> LoadProtectedPointerFromObject(
TNode<TrustedObject> object, int offset);
TNode<RawPtrT> LoadForeignForeignAddressPtr(TNode<Foreign> object) { TNode<RawPtrT> LoadForeignForeignAddressPtr(TNode<Foreign> object) {
return LoadExternalPointerFromObject(object, Foreign::kForeignAddressOffset, return LoadExternalPointerFromObject(object, Foreign::kForeignAddressOffset,
kForeignForeignAddressTag); kForeignForeignAddressTag);
@ -1289,11 +1304,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<WasmInternalFunction> object) { TNode<WasmInternalFunction> object) {
#ifdef V8_ENABLE_SANDBOX #ifdef V8_ENABLE_SANDBOX
return LoadCodeEntrypointViaCodePointerField( return LoadCodeEntrypointViaCodePointerField(
object, WasmInternalFunction::kCodeOffset); object, WasmInternalFunction::kCodeOffset, kWasmEntrypointTag);
#else #else
TNode<Code> code = TNode<Code> code =
LoadObjectField<Code>(object, WasmInternalFunction::kCodeOffset); LoadObjectField<Code>(object, WasmInternalFunction::kCodeOffset);
return LoadCodeInstructionStart(code); return LoadCodeInstructionStart(code, kWasmEntrypointTag);
#endif // V8_ENABLE_SANDBOX #endif // V8_ENABLE_SANDBOX
} }
@ -2192,6 +2207,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
AllocationFlags = AllocationFlag::kNone); AllocationFlags = AllocationFlag::kNone);
TNode<NameDictionary> AllocateNameDictionaryWithCapacity( TNode<NameDictionary> AllocateNameDictionaryWithCapacity(
TNode<IntPtrT> capacity, AllocationFlags = AllocationFlag::kNone); TNode<IntPtrT> capacity, AllocationFlags = AllocationFlag::kNone);
TNode<PropertyDictionary> AllocatePropertyDictionary(int at_least_space_for);
TNode<PropertyDictionary> AllocatePropertyDictionary(
TNode<IntPtrT> at_least_space_for,
AllocationFlags = AllocationFlag::kNone);
TNode<PropertyDictionary> AllocatePropertyDictionaryWithCapacity(
TNode<IntPtrT> capacity, AllocationFlags = AllocationFlag::kNone);
TNode<NameDictionary> CopyNameDictionary(TNode<NameDictionary> dictionary, TNode<NameDictionary> CopyNameDictionary(TNode<NameDictionary> dictionary,
Label* large_object_fallback); Label* large_object_fallback);
@ -2865,7 +2888,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> IsConstructorMap(TNode<Map> map); TNode<BoolT> IsConstructorMap(TNode<Map> map);
TNode<BoolT> IsConstructor(TNode<HeapObject> object); TNode<BoolT> IsConstructor(TNode<HeapObject> object);
TNode<BoolT> IsDeprecatedMap(TNode<Map> map); TNode<BoolT> IsDeprecatedMap(TNode<Map> map);
TNode<BoolT> IsNameDictionary(TNode<HeapObject> object); TNode<BoolT> IsPropertyDictionary(TNode<HeapObject> object);
TNode<BoolT> IsOrderedNameDictionary(TNode<HeapObject> object); TNode<BoolT> IsOrderedNameDictionary(TNode<HeapObject> object);
TNode<BoolT> IsGlobalDictionary(TNode<HeapObject> object); TNode<BoolT> IsGlobalDictionary(TNode<HeapObject> object);
TNode<BoolT> IsExtensibleMap(TNode<Map> map); TNode<BoolT> IsExtensibleMap(TNode<Map> map);
@ -2978,7 +3001,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> IsStringInstanceType(TNode<Int32T> instance_type); TNode<BoolT> IsStringInstanceType(TNode<Int32T> instance_type);
TNode<BoolT> IsString(TNode<HeapObject> object); TNode<BoolT> IsString(TNode<HeapObject> object);
TNode<BoolT> IsSeqOneByteString(TNode<HeapObject> object); TNode<BoolT> IsSeqOneByteString(TNode<HeapObject> object);
TNode<BoolT> IsSwissNameDictionary(TNode<HeapObject> object);
TNode<BoolT> IsSymbolInstanceType(TNode<Int32T> instance_type); TNode<BoolT> IsSymbolInstanceType(TNode<Int32T> instance_type);
TNode<BoolT> IsInternalizedStringInstanceType(TNode<Int32T> instance_type); TNode<BoolT> IsInternalizedStringInstanceType(TNode<Int32T> instance_type);
@ -3511,24 +3533,40 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
template <class Dictionary> template <class Dictionary>
void SetNameDictionaryFlags(TNode<Dictionary>, TNode<Smi> flags); void SetNameDictionaryFlags(TNode<Dictionary>, TNode<Smi> flags);
// Looks up an entry in a NameDictionaryBase successor. If the entry is found
// control goes to {if_found} and {var_name_index} contains an index of the
// key field of the entry found. If the key is not found control goes to
// {if_not_found}.
enum LookupMode { kFindExisting, kFindInsertionIndex }; enum LookupMode { kFindExisting, kFindInsertionIndex };
template <typename Dictionary> template <typename Dictionary>
TNode<HeapObject> LoadName(TNode<HeapObject> key); TNode<HeapObject> LoadName(TNode<HeapObject> key);
// Looks up an entry in a NameDictionaryBase successor.
// For {mode} == kFindExisting:
// If the entry is found control goes to {if_found} and {var_name_index}
// contains an index of the key field of the entry found.
// If the key is not found and {if_not_found_with_insertion_index} is
// provided, control goes to {if_not_found_with_insertion_index} and
// {var_name_index} contains the index of the key field to insert the given
// name at.
// Otherwise control goes to {if_not_found_no_insertion_index}.
// For {mode} == kFindInsertionIndex:
// {if_not_found_no_insertion_index} and {if_not_found_with_insertion_index}
// are treated equally. If {if_not_found_with_insertion_index} is provided,
// control goes to {if_not_found_with_insertion_index}, otherwise control
// goes to {if_not_found_no_insertion_index}. In both cases {var_name_index}
// contains the index of the key field to insert the given name at.
template <typename Dictionary> template <typename Dictionary>
void NameDictionaryLookup(TNode<Dictionary> dictionary, void NameDictionaryLookup(TNode<Dictionary> dictionary,
TNode<Name> unique_name, Label* if_found, TNode<Name> unique_name, Label* if_found,
TVariable<IntPtrT>* var_name_index, TVariable<IntPtrT>* var_name_index,
Label* if_not_found, Label* if_not_found_no_insertion_index,
LookupMode mode = kFindExisting); LookupMode mode = kFindExisting,
Label* if_not_found_with_insertion_index = nullptr);
TNode<Word32T> ComputeSeededHash(TNode<IntPtrT> key); TNode<Word32T> ComputeSeededHash(TNode<IntPtrT> key);
// Looks up an entry in a NameDictionaryBase successor. If the entry is found
// control goes to {if_found} and {var_name_index} contains an index of the
// key field of the entry found. If the key is not found control goes to
// {if_not_found}.
void NumberDictionaryLookup(TNode<NumberDictionary> dictionary, void NumberDictionaryLookup(TNode<NumberDictionary> dictionary,
TNode<IntPtrT> intptr_index, Label* if_found, TNode<IntPtrT> intptr_index, Label* if_found,
TVariable<IntPtrT>* var_entry, TVariable<IntPtrT>* var_entry,
@ -3548,8 +3586,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Smi> enum_index); TNode<Smi> enum_index);
template <class Dictionary> template <class Dictionary>
void AddToDictionary(TNode<Dictionary> dictionary, TNode<Name> key, void AddToDictionary(
TNode<Object> value, Label* bailout); TNode<Dictionary> dictionary, TNode<Name> key, TNode<Object> value,
Label* bailout,
base::Optional<TNode<IntPtrT>> insertion_index = base::nullopt);
// Tries to check if {object} has own {unique_name} property. // Tries to check if {object} has own {unique_name} property.
void TryHasOwnProperty(TNode<HeapObject> object, TNode<Map> map, void TryHasOwnProperty(TNode<HeapObject> object, TNode<Map> map,
@ -3875,6 +3915,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
void TrapAllocationMemento(TNode<JSObject> object, Label* memento_found); void TrapAllocationMemento(TNode<JSObject> object, Label* memento_found);
// Helpers to look up MemoryChunk/Page metadata for a given address.
// Equivalent to MemoryChunkHeader::FromAddress().
TNode<IntPtrT> PageHeaderFromAddress(TNode<IntPtrT> address);
// Equivalent to MemoryChunkHeader::MemoryChunk().
TNode<IntPtrT> PageFromPageHeader(TNode<IntPtrT> address);
// Equivalent to BasicMemoryChunk::FromAddress().
TNode<IntPtrT> PageFromAddress(TNode<IntPtrT> address); TNode<IntPtrT> PageFromAddress(TNode<IntPtrT> address);
// Store a weak in-place reference into the FeedbackVector. // Store a weak in-place reference into the FeedbackVector.

View File

@ -1720,8 +1720,10 @@ BackgroundCompileTask::BackgroundCompileTask(
BackgroundCompileTask::~BackgroundCompileTask() = default; BackgroundCompileTask::~BackgroundCompileTask() = default;
namespace {
void SetScriptFieldsFromDetails(Isolate* isolate, Tagged<Script> script, void SetScriptFieldsFromDetails(Isolate* isolate, Tagged<Script> script,
const ScriptDetails& script_details, ScriptDetails script_details,
DisallowGarbageCollection* no_gc) { DisallowGarbageCollection* no_gc) {
Handle<Object> script_name; Handle<Object> script_name;
if (script_details.name_obj.ToHandle(&script_name)) { if (script_details.name_obj.ToHandle(&script_name)) {
@ -1747,8 +1749,6 @@ void SetScriptFieldsFromDetails(Isolate* isolate, Tagged<Script> script,
} }
} }
namespace {
#ifdef ENABLE_SLOW_DCHECKS #ifdef ENABLE_SLOW_DCHECKS
// A class which traverses the object graph for a newly compiled Script and // A class which traverses the object graph for a newly compiled Script and
@ -2032,34 +2032,44 @@ class ConstantPoolPointerForwarder {
for (Handle<BytecodeArray> bytecode_array : bytecode_arrays_to_update_) { for (Handle<BytecodeArray> bytecode_array : bytecode_arrays_to_update_) {
local_heap_->Safepoint(); local_heap_->Safepoint();
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
Tagged<FixedArray> constant_pool = bytecode_array->constant_pool(); IterateConstantPool(bytecode_array->constant_pool());
IterateConstantPool(constant_pool);
} }
} }
bool HasAnythingToForward() const { return !forwarding_table_.empty(); } bool HasAnythingToForward() const { return !forwarding_table_.empty(); }
private: private:
void IterateConstantPool(Tagged<FixedArray> constant_pool) { template <typename TArray>
for (int i = 0, length = constant_pool->length(); i < length; ++i) { void IterateConstantPoolEntry(Tagged<TArray> constant_pool, int i) {
Tagged<Object> obj = constant_pool->get(i); Tagged<Object> obj = constant_pool->get(i);
if (IsSmi(obj)) continue; if (IsSmi(obj)) return;
Tagged<HeapObject> heap_obj = HeapObject::cast(obj); Tagged<HeapObject> heap_obj = HeapObject::cast(obj);
if (IsFixedArray(heap_obj, cage_base_)) { if (IsFixedArray(heap_obj, cage_base_)) {
// Constant pools can have nested fixed arrays, but such relationships // Constant pools can have nested fixed arrays, but such relationships
// are acyclic and never more than a few layers deep, so recursion is // are acyclic and never more than a few layers deep, so recursion is
// fine here. // fine here.
IterateConstantPool(FixedArray::cast(heap_obj)); IterateConstantPoolNestedArray(FixedArray::cast(heap_obj));
} else if (IsSharedFunctionInfo(heap_obj, cage_base_)) { } else if (IsSharedFunctionInfo(heap_obj, cage_base_)) {
auto it = forwarding_table_.find( auto it = forwarding_table_.find(
SharedFunctionInfo::cast(heap_obj)->function_literal_id()); SharedFunctionInfo::cast(heap_obj)->function_literal_id());
if (it != forwarding_table_.end()) { if (it != forwarding_table_.end()) {
constant_pool->set(i, *it->second); constant_pool->set(i, *it->second);
}
} }
} }
} }
void IterateConstantPool(Tagged<TrustedFixedArray> constant_pool) {
for (int i = 0, length = constant_pool->length(); i < length; ++i) {
IterateConstantPoolEntry(constant_pool, i);
}
}
void IterateConstantPoolNestedArray(Tagged<FixedArray> nested_array) {
for (int i = 0, length = nested_array->length(); i < length; ++i) {
IterateConstantPoolEntry(nested_array, i);
}
}
PtrComprCageBase cage_base_; PtrComprCageBase cage_base_;
LocalHeap* local_heap_; LocalHeap* local_heap_;
std::vector<Handle<BytecodeArray>> bytecode_arrays_to_update_; std::vector<Handle<BytecodeArray>> bytecode_arrays_to_update_;
@ -2450,10 +2460,10 @@ void BackgroundDeserializeTask::MergeWithExistingScript() {
MaybeHandle<SharedFunctionInfo> BackgroundDeserializeTask::Finish( MaybeHandle<SharedFunctionInfo> BackgroundDeserializeTask::Finish(
Isolate* isolate, Handle<String> source, Isolate* isolate, Handle<String> source,
const ScriptDetails& script_details) { ScriptOriginOptions origin_options) {
return CodeSerializer::FinishOffThreadDeserialize( return CodeSerializer::FinishOffThreadDeserialize(
isolate, std::move(off_thread_data_), &cached_data_, source, isolate, std::move(off_thread_data_), &cached_data_, source,
script_details, &background_merge_task_); origin_options, &background_merge_task_);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -3630,8 +3640,8 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
"V8.CompileDeserialize"); "V8.CompileDeserialize");
if (deserialize_task) { if (deserialize_task) {
// If there's a cache consume task, finish it. // If there's a cache consume task, finish it.
maybe_result = maybe_result = deserialize_task->Finish(isolate, source,
deserialize_task->Finish(isolate, source, script_details); script_details.origin_options);
// It is possible at this point that there is a Script object for this // It is possible at this point that there is a Script object for this
// script in the compilation cache (held in the variable maybe_script), // script in the compilation cache (held in the variable maybe_script),
// which does not match maybe_result->script(). This could happen any of // which does not match maybe_result->script(). This could happen any of
@ -3652,7 +3662,8 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
// would be non-trivial. // would be non-trivial.
} else { } else {
maybe_result = CodeSerializer::Deserialize( maybe_result = CodeSerializer::Deserialize(
isolate, cached_data, source, script_details, maybe_script); isolate, cached_data, source, script_details.origin_options,
maybe_script);
} }
bool consuming_code_cache_succeeded = false; bool consuming_code_cache_succeeded = false;
@ -3828,7 +3839,7 @@ MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileDeserialize"); "V8.CompileDeserialize");
maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source, maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source,
script_details); script_details.origin_options);
bool consuming_code_cache_succeeded = false; bool consuming_code_cache_succeeded = false;
if (maybe_result.ToHandle(&result)) { if (maybe_result.ToHandle(&result)) {
is_compiled_scope = result->is_compiled_scope(isolate); is_compiled_scope = result->is_compiled_scope(isolate);

View File

@ -682,7 +682,7 @@ class V8_EXPORT_PRIVATE BackgroundDeserializeTask {
MaybeHandle<SharedFunctionInfo> Finish(Isolate* isolate, MaybeHandle<SharedFunctionInfo> Finish(Isolate* isolate,
Handle<String> source, Handle<String> source,
const ScriptDetails& script_details); ScriptOriginOptions origin_options);
bool rejected() const { return cached_data_.rejected(); } bool rejected() const { return cached_data_.rejected(); }

View File

@ -288,26 +288,19 @@ void ExternalReferenceTable::AddStubCache(Isolate* isolate, int* index) {
kIsolateAddressReferenceCount, kIsolateAddressReferenceCount,
*index); *index);
StubCache* load_stub_cache = isolate->load_stub_cache();
// Stub cache tables // Stub cache tables
Add(load_stub_cache->key_reference(StubCache::kPrimary).address(), index); std::array<StubCache*, 3> stub_caches{isolate->load_stub_cache(),
Add(load_stub_cache->value_reference(StubCache::kPrimary).address(), index); isolate->store_stub_cache(),
Add(load_stub_cache->map_reference(StubCache::kPrimary).address(), index); isolate->define_own_stub_cache()};
Add(load_stub_cache->key_reference(StubCache::kSecondary).address(), index);
Add(load_stub_cache->value_reference(StubCache::kSecondary).address(), index);
Add(load_stub_cache->map_reference(StubCache::kSecondary).address(), index);
StubCache* store_stub_cache = isolate->store_stub_cache(); for (StubCache* stub_cache : stub_caches) {
Add(stub_cache->key_reference(StubCache::kPrimary).address(), index);
// Stub cache tables Add(stub_cache->value_reference(StubCache::kPrimary).address(), index);
Add(store_stub_cache->key_reference(StubCache::kPrimary).address(), index); Add(stub_cache->map_reference(StubCache::kPrimary).address(), index);
Add(store_stub_cache->value_reference(StubCache::kPrimary).address(), index); Add(stub_cache->key_reference(StubCache::kSecondary).address(), index);
Add(store_stub_cache->map_reference(StubCache::kPrimary).address(), index); Add(stub_cache->value_reference(StubCache::kSecondary).address(), index);
Add(store_stub_cache->key_reference(StubCache::kSecondary).address(), index); Add(stub_cache->map_reference(StubCache::kSecondary).address(), index);
Add(store_stub_cache->value_reference(StubCache::kSecondary).address(), }
index);
Add(store_stub_cache->map_reference(StubCache::kSecondary).address(), index);
CHECK_EQ(kSizeIsolateIndependent + kExternalReferenceCountIsolateDependent + CHECK_EQ(kSizeIsolateIndependent + kExternalReferenceCountIsolateDependent +
kIsolateAddressReferenceCount + kStubCacheReferenceCount, kIsolateAddressReferenceCount + kStubCacheReferenceCount,

View File

@ -38,7 +38,7 @@ class ExternalReferenceTable {
Accessors::kAccessorInfoCount + Accessors::kAccessorGetterCount + Accessors::kAccessorInfoCount + Accessors::kAccessorGetterCount +
Accessors::kAccessorSetterCount + Accessors::kAccessorCallbackCount; Accessors::kAccessorSetterCount + Accessors::kAccessorCallbackCount;
// The number of stub cache external references, see AddStubCache. // The number of stub cache external references, see AddStubCache.
static constexpr int kStubCacheReferenceCount = 12; static constexpr int kStubCacheReferenceCount = 6 * 3; // 3 stub caches
static constexpr int kStatsCountersReferenceCount = static constexpr int kStatsCountersReferenceCount =
#define SC(...) +1 #define SC(...) +1
STATS_COUNTER_NATIVE_CODE_LIST(SC); STATS_COUNTER_NATIVE_CODE_LIST(SC);

View File

@ -1948,18 +1948,20 @@ void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
} }
} }
void MacroAssembler::CallCFunction(ExternalReference function, int MacroAssembler::CallCFunction(ExternalReference function, int num_arguments,
int num_arguments, SetIsolateDataSlots set_isolate_data_slots,
SetIsolateDataSlots set_isolate_data_slots) { Label* return_location) {
// Note: The "CallCFunction" code comment will be generated by the other // Note: The "CallCFunction" code comment will be generated by the other
// CallCFunction method called below. // CallCFunction method called below.
// Trashing eax is ok as it will be the return value. // Trashing eax is ok as it will be the return value.
Move(eax, Immediate(function)); Move(eax, Immediate(function));
CallCFunction(eax, num_arguments); return CallCFunction(eax, num_arguments, set_isolate_data_slots,
return_location);
} }
void MacroAssembler::CallCFunction(Register function, int num_arguments, int MacroAssembler::CallCFunction(Register function, int num_arguments,
SetIsolateDataSlots set_isolate_data_slots) { SetIsolateDataSlots set_isolate_data_slots,
Label* return_location) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
DCHECK_LE(num_arguments, kMaxCParameters); DCHECK_LE(num_arguments, kMaxCParameters);
DCHECK(has_frame()); DCHECK(has_frame());
@ -1968,6 +1970,8 @@ void MacroAssembler::CallCFunction(Register function, int num_arguments,
CheckStackAlignment(); CheckStackAlignment();
} }
Label get_pc;
if (set_isolate_data_slots == SetIsolateDataSlots::kYes) { if (set_isolate_data_slots == SetIsolateDataSlots::kYes) {
// Save the frame pointer and PC so that the stack layout remains iterable, // Save the frame pointer and PC so that the stack layout remains iterable,
// even without an ExitFrame which normally exists between JS and C frames. // even without an ExitFrame which normally exists between JS and C frames.
@ -1976,8 +1980,7 @@ void MacroAssembler::CallCFunction(Register function, int num_arguments,
Register scratch = ecx; Register scratch = ecx;
if (function == eax) pc_scratch = edx; if (function == eax) pc_scratch = edx;
if (function == ecx) scratch = edx; if (function == ecx) scratch = edx;
PushPC(); LoadLabelAddress(pc_scratch, &get_pc);
pop(pc_scratch);
// See x64 code for reasoning about how to address the isolate data fields. // See x64 code for reasoning about how to address the isolate data fields.
DCHECK_IMPLIES(!root_array_available(), isolate() != nullptr); DCHECK_IMPLIES(!root_array_available(), isolate() != nullptr);
@ -1998,6 +2001,9 @@ void MacroAssembler::CallCFunction(Register function, int num_arguments,
} }
call(function); call(function);
int call_pc_offset = pc_offset();
bind(&get_pc);
if (return_location) bind(return_location);
if (set_isolate_data_slots == SetIsolateDataSlots::kYes) { if (set_isolate_data_slots == SetIsolateDataSlots::kYes) {
// We don't unset the PC; the FP is the source of truth. // We don't unset the PC; the FP is the source of truth.
@ -2016,6 +2022,8 @@ void MacroAssembler::CallCFunction(Register function, int num_arguments,
} else { } else {
add(esp, Immediate(num_arguments * kSystemPointerSize)); add(esp, Immediate(num_arguments * kSystemPointerSize));
} }
return call_pc_offset;
} }
void MacroAssembler::PushPC() { void MacroAssembler::PushPC() {
@ -2112,7 +2120,8 @@ Operand MacroAssembler::EntryFromBuiltinAsOperand(Builtin builtin) {
} }
void MacroAssembler::LoadCodeInstructionStart(Register destination, void MacroAssembler::LoadCodeInstructionStart(Register destination,
Register code_object) { Register code_object,
CodeEntrypointTag tag) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
mov(destination, FieldOperand(code_object, Code::kInstructionStartOffset)); mov(destination, FieldOperand(code_object, Code::kInstructionStartOffset));
} }
@ -2185,21 +2194,28 @@ void MacroAssembler::LoadLabelAddress(Register dst, Label* lbl) {
DCHECK(pc_offset() - kStart == kInsDelta); DCHECK(pc_offset() - kStart == kInsDelta);
} }
void MacroAssembler::MemoryChunkHeaderFromObject(Register object,
Register header) {
constexpr intptr_t alignment_mask =
MemoryChunkHeader::GetAlignmentMaskForAssembler();
if (header == object) {
and_(header, Immediate(~alignment_mask));
} else {
mov(header, Immediate(~alignment_mask));
and_(header, object);
}
}
void MacroAssembler::CheckPageFlag(Register object, Register scratch, int mask, void MacroAssembler::CheckPageFlag(Register object, Register scratch, int mask,
Condition cc, Label* condition_met, Condition cc, Label* condition_met,
Label::Distance condition_met_distance) { Label::Distance condition_met_distance) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
DCHECK(cc == zero || cc == not_zero); DCHECK(cc == zero || cc == not_zero);
if (scratch == object) { MemoryChunkHeaderFromObject(object, scratch);
and_(scratch, Immediate(~kPageAlignmentMask));
} else {
mov(scratch, Immediate(~kPageAlignmentMask));
and_(scratch, object);
}
if (mask < (1 << kBitsPerByte)) { if (mask < (1 << kBitsPerByte)) {
test_b(Operand(scratch, BasicMemoryChunk::kFlagsOffset), Immediate(mask)); test_b(Operand(scratch, MemoryChunkLayout::kFlagsOffset), Immediate(mask));
} else { } else {
test(Operand(scratch, BasicMemoryChunk::kFlagsOffset), Immediate(mask)); test(Operand(scratch, MemoryChunkLayout::kFlagsOffset), Immediate(mask));
} }
j(cc, condition_met, condition_met_distance); j(cc, condition_met, condition_met_distance);
} }

View File

@ -74,6 +74,7 @@ class V8_EXPORT_PRIVATE MacroAssembler
public: public:
using SharedMacroAssembler<MacroAssembler>::SharedMacroAssembler; using SharedMacroAssembler<MacroAssembler>::SharedMacroAssembler;
void MemoryChunkHeaderFromObject(Register object, Register header);
void CheckPageFlag(Register object, Register scratch, int mask, Condition cc, void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
Label* condition_met, Label* condition_met,
Label::Distance condition_met_distance = Label::kFar); Label::Distance condition_met_distance = Label::kFar);
@ -162,7 +163,8 @@ class V8_EXPORT_PRIVATE MacroAssembler
void TailCallBuiltin(Builtin builtin); void TailCallBuiltin(Builtin builtin);
// Load the code entry point from the Code object. // Load the code entry point from the Code object.
void LoadCodeInstructionStart(Register destination, Register code_object); void LoadCodeInstructionStart(Register destination, Register code_object,
CodeEntrypointTag = kDefaultCodeEntrypointTag);
void CallCodeObject(Register code_object); void CallCodeObject(Register code_object);
void JumpCodeObject(Register code_object, void JumpCodeObject(Register code_object,
JumpMode jump_mode = JumpMode::kJump); JumpMode jump_mode = JumpMode::kJump);
@ -234,16 +236,14 @@ class V8_EXPORT_PRIVATE MacroAssembler
// garbage collection, since that might move the code and invalidate the // garbage collection, since that might move the code and invalidate the
// return address (unless this is somehow accounted for by the called // return address (unless this is somehow accounted for by the called
// function). // function).
enum class SetIsolateDataSlots { int CallCFunction(
kNo,
kYes,
};
void CallCFunction(
ExternalReference function, int num_arguments, ExternalReference function, int num_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
void CallCFunction( Label* return_location = nullptr);
int CallCFunction(
Register function, int num_arguments, Register function, int num_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes,
Label* return_location = nullptr);
void ShlPair(Register high, Register low, uint8_t imm8); void ShlPair(Register high, Register low, uint8_t imm8);
void ShlPair_cl(Register high, Register low); void ShlPair_cl(Register high, Register low);

View File

@ -115,8 +115,8 @@ void StaticCallInterfaceDescriptor<DerivedDescriptor>::Initialize(
DCHECK_GE(return_registers.size(), DerivedDescriptor::kReturnCount); DCHECK_GE(return_registers.size(), DerivedDescriptor::kReturnCount);
DCHECK_GE(return_double_registers.size(), DerivedDescriptor::kReturnCount); DCHECK_GE(return_double_registers.size(), DerivedDescriptor::kReturnCount);
data->InitializeRegisters( data->InitializeRegisters(
DerivedDescriptor::flags(), DerivedDescriptor::kReturnCount, DerivedDescriptor::flags(), DerivedDescriptor::kEntrypointTag,
DerivedDescriptor::GetParameterCount(), DerivedDescriptor::kReturnCount, DerivedDescriptor::GetParameterCount(),
DerivedDescriptor::kStackArgumentOrder, DerivedDescriptor::kStackArgumentOrder,
DerivedDescriptor::GetRegisterParameterCount(), registers.data(), DerivedDescriptor::GetRegisterParameterCount(), registers.data(),
double_registers.data(), return_registers.data(), double_registers.data(), return_registers.data(),
@ -138,7 +138,7 @@ StaticCallInterfaceDescriptor<DerivedDescriptor>::GetReturnCount() {
static_assert( static_assert(
DerivedDescriptor::kReturnCount >= 0, DerivedDescriptor::kReturnCount >= 0,
"DerivedDescriptor subclass should override return count with a value " "DerivedDescriptor subclass should override return count with a value "
"that is greater than 0"); "that is greater than or equal to 0");
return DerivedDescriptor::kReturnCount; return DerivedDescriptor::kReturnCount;
} }
@ -150,7 +150,7 @@ StaticCallInterfaceDescriptor<DerivedDescriptor>::GetParameterCount() {
static_assert( static_assert(
DerivedDescriptor::kParameterCount >= 0, DerivedDescriptor::kParameterCount >= 0,
"DerivedDescriptor subclass should override parameter count with a " "DerivedDescriptor subclass should override parameter count with a "
"value that is greater than 0"); "value that is greater than or equal to 0");
return DerivedDescriptor::kParameterCount; return DerivedDescriptor::kParameterCount;
} }
@ -502,7 +502,8 @@ constexpr auto OnStackReplacementDescriptor::registers() {
constexpr auto constexpr auto
MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor::registers() { MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor::registers() {
#ifdef V8_ENABLE_MAGLEV #ifdef V8_ENABLE_MAGLEV
return RegisterArray(FlagsRegister(), FeedbackVectorRegister()); return RegisterArray(FlagsRegister(), FeedbackVectorRegister(),
TemporaryRegister());
#else #else
return DefaultRegisterArray(); return DefaultRegisterArray();
#endif #endif

View File

@ -37,7 +37,7 @@ void CheckRegisterConfiguration(int count, const Register* registers,
#endif #endif
void CallInterfaceDescriptorData::InitializeRegisters( void CallInterfaceDescriptorData::InitializeRegisters(
Flags flags, int return_count, int parameter_count, Flags flags, CodeEntrypointTag tag, int return_count, int parameter_count,
StackArgumentOrder stack_order, int register_parameter_count, StackArgumentOrder stack_order, int register_parameter_count,
const Register* registers, const DoubleRegister* double_registers, const Register* registers, const DoubleRegister* double_registers,
const Register* return_registers, const Register* return_registers,
@ -52,6 +52,7 @@ void CallInterfaceDescriptorData::InitializeRegisters(
#endif #endif
flags_ = flags; flags_ = flags;
tag_ = tag;
stack_order_ = stack_order; stack_order_ = stack_order;
return_count_ = return_count; return_count_ = return_count;
param_count_ = parameter_count; param_count_ = parameter_count;

View File

@ -53,6 +53,8 @@ namespace internal {
V(CallWithSpread) \ V(CallWithSpread) \
V(CallWithSpread_Baseline) \ V(CallWithSpread_Baseline) \
V(CallWithSpread_WithFeedback) \ V(CallWithSpread_WithFeedback) \
V(CCall) \
V(CEntryDummy) \
V(CEntry1ArgvOnStack) \ V(CEntry1ArgvOnStack) \
V(CloneObjectBaseline) \ V(CloneObjectBaseline) \
V(CloneObjectWithVector) \ V(CloneObjectWithVector) \
@ -117,6 +119,7 @@ namespace internal {
V(NewHeapNumber) \ V(NewHeapNumber) \
V(NoContext) \ V(NoContext) \
V(OnStackReplacement) \ V(OnStackReplacement) \
V(RegExpTrampoline) \
V(RestartFrameTrampoline) \ V(RestartFrameTrampoline) \
V(ResumeGenerator) \ V(ResumeGenerator) \
V(ResumeGeneratorBaseline) \ V(ResumeGeneratorBaseline) \
@ -141,6 +144,7 @@ namespace internal {
V(UnaryOp_Baseline) \ V(UnaryOp_Baseline) \
V(UnaryOp_WithFeedback) \ V(UnaryOp_WithFeedback) \
V(Void) \ V(Void) \
V(WasmDummy) \
V(WasmFloat32ToNumber) \ V(WasmFloat32ToNumber) \
V(WasmFloat64ToTagged) \ V(WasmFloat64ToTagged) \
V(WasmJSToWasmWrapper) \ V(WasmJSToWasmWrapper) \
@ -191,8 +195,8 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
// The passed registers are owned by the caller, and their lifetime is // The passed registers are owned by the caller, and their lifetime is
// expected to exceed that of this data. In practice, they are expected to // expected to exceed that of this data. In practice, they are expected to
// be in a static local. // be in a static local.
void InitializeRegisters(Flags flags, int return_count, int parameter_count, void InitializeRegisters(Flags flags, CodeEntrypointTag tag, int return_count,
StackArgumentOrder stack_order, int parameter_count, StackArgumentOrder stack_order,
int register_parameter_count, int register_parameter_count,
const Register* registers, const Register* registers,
const DoubleRegister* double_registers, const DoubleRegister* double_registers,
@ -217,6 +221,7 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
} }
Flags flags() const { return flags_; } Flags flags() const { return flags_; }
CodeEntrypointTag tag() const { return tag_; }
int return_count() const { return return_count_; } int return_count() const { return return_count_; }
int param_count() const { return param_count_; } int param_count() const { return param_count_; }
int register_param_count() const { return register_param_count_; } int register_param_count() const { return register_param_count_; }
@ -271,6 +276,7 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
int return_count_ = kUninitializedCount; int return_count_ = kUninitializedCount;
int param_count_ = kUninitializedCount; int param_count_ = kUninitializedCount;
Flags flags_ = kNoFlags; Flags flags_ = kNoFlags;
CodeEntrypointTag tag_ = kDefaultCodeEntrypointTag;
StackArgumentOrder stack_order_ = StackArgumentOrder::kDefault; StackArgumentOrder stack_order_ = StackArgumentOrder::kDefault;
// Specifying the set of registers that could be used by the register // Specifying the set of registers that could be used by the register
@ -354,6 +360,8 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptor {
Flags flags() const { return data()->flags(); } Flags flags() const { return data()->flags(); }
CodeEntrypointTag tag() const { return data()->tag(); }
bool HasContextParameter() const { bool HasContextParameter() const {
return (flags() & CallInterfaceDescriptorData::kNoContext) == 0; return (flags() & CallInterfaceDescriptorData::kNoContext) == 0;
} }
@ -474,6 +482,9 @@ class StaticCallInterfaceDescriptor : public CallInterfaceDescriptor {
static constexpr bool kNoContext = false; static constexpr bool kNoContext = false;
static constexpr bool kAllowVarArgs = false; static constexpr bool kAllowVarArgs = false;
static constexpr bool kNoStackScan = false; static constexpr bool kNoStackScan = false;
// TODO(saelo): we should not have a default value here to force all interface
// descriptors to define a (unique) tag.
static constexpr CodeEntrypointTag kEntrypointTag = kDefaultCodeEntrypointTag;
static constexpr auto kStackArgumentOrder = StackArgumentOrder::kDefault; static constexpr auto kStackArgumentOrder = StackArgumentOrder::kDefault;
// The set of registers available to the parameters, as a // The set of registers available to the parameters, as a
@ -752,6 +763,7 @@ constexpr EmptyDoubleRegisterArray DoubleRegisterArray() { return {}; }
class V8_EXPORT_PRIVATE VoidDescriptor class V8_EXPORT_PRIVATE VoidDescriptor
: public StaticCallInterfaceDescriptor<VoidDescriptor> { : public StaticCallInterfaceDescriptor<VoidDescriptor> {
public: public:
static constexpr CodeEntrypointTag kEntrypointTag = kInvalidEntrypointTag;
// The void descriptor could (and indeed probably should) also be NO_CONTEXT, // The void descriptor could (and indeed probably should) also be NO_CONTEXT,
// but this breaks some code assembler unittests. // but this breaks some code assembler unittests.
DEFINE_PARAMETERS() DEFINE_PARAMETERS()
@ -761,10 +773,6 @@ class V8_EXPORT_PRIVATE VoidDescriptor
static constexpr auto registers(); static constexpr auto registers();
}; };
// Dummy descriptor that marks builtins with C calling convention.
// TODO(jgruber): Define real descriptors for C calling conventions.
using CCallDescriptor = VoidDescriptor;
// Marks deoptimization entry builtins. Precise calling conventions currently // Marks deoptimization entry builtins. Precise calling conventions currently
// differ based on the platform. // differ based on the platform.
// TODO(jgruber): Once this is unified, we could create a better description // TODO(jgruber): Once this is unified, we could create a better description
@ -777,15 +785,39 @@ using JSEntryDescriptor = VoidDescriptor;
// TODO(jgruber): Consider filling in the details here; however, this doesn't // TODO(jgruber): Consider filling in the details here; however, this doesn't
// make too much sense as long as the descriptor isn't used or verified. // make too much sense as long as the descriptor isn't used or verified.
using CEntryDummyDescriptor = VoidDescriptor; using ContinueToBuiltinDescriptor = VoidDescriptor;
// Dummy descriptor that marks builtins with C calling convention.
// TODO(jgruber): Define real descriptors for C calling conventions.
class CCallDescriptor : public StaticCallInterfaceDescriptor<CCallDescriptor> {
public:
static constexpr CodeEntrypointTag kEntrypointTag = kDefaultCodeEntrypointTag;
DEFINE_PARAMETERS()
DEFINE_PARAMETER_TYPES()
DECLARE_DESCRIPTOR(CCallDescriptor)
};
// TODO(jgruber): Consider filling in the details here; however, this doesn't // TODO(jgruber): Consider filling in the details here; however, this doesn't
// make too much sense as long as the descriptor isn't used or verified. // make too much sense as long as the descriptor isn't used or verified.
using ContinueToBuiltinDescriptor = VoidDescriptor; class CEntryDummyDescriptor
: public StaticCallInterfaceDescriptor<CEntryDummyDescriptor> {
public:
static constexpr CodeEntrypointTag kEntrypointTag = kDefaultCodeEntrypointTag;
DEFINE_PARAMETERS()
DEFINE_PARAMETER_TYPES()
DECLARE_DESCRIPTOR(CEntryDummyDescriptor)
};
// TODO(wasm): Consider filling in details / defining real descriptors for all // TODO(wasm): Consider filling in details / defining real descriptors for all
// builtins still using this placeholder descriptor. // builtins still using this placeholder descriptor.
using WasmDummyDescriptor = VoidDescriptor; class WasmDummyDescriptor
: public StaticCallInterfaceDescriptor<WasmDummyDescriptor> {
public:
static constexpr CodeEntrypointTag kEntrypointTag = kWasmEntrypointTag;
DEFINE_PARAMETERS()
DEFINE_PARAMETER_TYPES()
DECLARE_DESCRIPTOR(WasmDummyDescriptor)
};
class AllocateDescriptor class AllocateDescriptor
: public StaticCallInterfaceDescriptor<AllocateDescriptor> { : public StaticCallInterfaceDescriptor<AllocateDescriptor> {
@ -819,6 +851,17 @@ class JSTrampolineDescriptor
DECLARE_JS_COMPATIBLE_DESCRIPTOR(JSTrampolineDescriptor) DECLARE_JS_COMPATIBLE_DESCRIPTOR(JSTrampolineDescriptor)
}; };
// Descriptor used for code using the RegExp calling convention, in particular
// the RegExp interpreter trampolines.
class RegExpTrampolineDescriptor
: public StaticCallInterfaceDescriptor<RegExpTrampolineDescriptor> {
public:
static constexpr CodeEntrypointTag kEntrypointTag = kRegExpEntrypointTag;
DEFINE_PARAMETERS()
DEFINE_PARAMETER_TYPES()
DECLARE_DESCRIPTOR(RegExpTrampolineDescriptor)
};
class ContextOnlyDescriptor class ContextOnlyDescriptor
: public StaticCallInterfaceDescriptor<ContextOnlyDescriptor> { : public StaticCallInterfaceDescriptor<ContextOnlyDescriptor> {
public: public:
@ -953,14 +996,17 @@ class MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor
: public StaticCallInterfaceDescriptor< : public StaticCallInterfaceDescriptor<
MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor> { MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor> {
public: public:
DEFINE_PARAMETERS_NO_CONTEXT(kFlags, kFeedbackVector) DEFINE_PARAMETERS_NO_CONTEXT(kFlags, kFeedbackVector, kTemporary)
DEFINE_PARAMETER_TYPES(MachineType::Int32(), // kFlags DEFINE_PARAMETER_TYPES(MachineType::Int32(), // kFlags
MachineType::TaggedPointer()) // kFeedbackVector MachineType::TaggedPointer(), // kFeedbackVector
MachineType::AnyTagged()) // kTemporary
DECLARE_DESCRIPTOR(MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor) DECLARE_DESCRIPTOR(MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor)
static constexpr inline Register FlagsRegister(); static constexpr inline Register FlagsRegister();
static constexpr inline Register FeedbackVectorRegister(); static constexpr inline Register FeedbackVectorRegister();
static constexpr inline Register TemporaryRegister();
static constexpr inline auto registers(); static constexpr inline auto registers();
}; };
@ -1009,6 +1055,8 @@ class StoreBaselineDescriptor
class StoreTransitionDescriptor class StoreTransitionDescriptor
: public StaticCallInterfaceDescriptor<StoreTransitionDescriptor> { : public StaticCallInterfaceDescriptor<StoreTransitionDescriptor> {
public: public:
static constexpr CodeEntrypointTag kEntrypointTag = kICHandlerEntrypointTag;
DEFINE_PARAMETERS(kReceiver, kName, kMap, kValue, kSlot, kVector) DEFINE_PARAMETERS(kReceiver, kName, kMap, kValue, kSlot, kVector)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver
MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kName
@ -1026,6 +1074,8 @@ class StoreTransitionDescriptor
class StoreWithVectorDescriptor class StoreWithVectorDescriptor
: public StaticCallInterfaceDescriptor<StoreWithVectorDescriptor> { : public StaticCallInterfaceDescriptor<StoreWithVectorDescriptor> {
public: public:
static constexpr CodeEntrypointTag kEntrypointTag = kICHandlerEntrypointTag;
DEFINE_PARAMETERS(kReceiver, kName, kValue, kSlot, kVector) DEFINE_PARAMETERS(kReceiver, kName, kValue, kSlot, kVector)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver
MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kName
@ -1127,6 +1177,8 @@ class DefineKeyedOwnWithVectorDescriptor
class LoadWithVectorDescriptor class LoadWithVectorDescriptor
: public StaticCallInterfaceDescriptor<LoadWithVectorDescriptor> { : public StaticCallInterfaceDescriptor<LoadWithVectorDescriptor> {
public: public:
static constexpr CodeEntrypointTag kEntrypointTag = kICHandlerEntrypointTag;
// TODO(v8:9497): Revert the Machine type for kSlot to the // TODO(v8:9497): Revert the Machine type for kSlot to the
// TaggedSigned once Torque can emit better call descriptors // TaggedSigned once Torque can emit better call descriptors
DEFINE_PARAMETERS(kReceiver, kName, kSlot, kVector) DEFINE_PARAMETERS(kReceiver, kName, kSlot, kVector)

View File

@ -4555,8 +4555,9 @@ void MacroAssembler::CheckPageFlag(Register object, int mask, Condition cc,
UseScratchRegisterScope temps(this); UseScratchRegisterScope temps(this);
temps.Include(t8); temps.Include(t8);
Register scratch = temps.Acquire(); Register scratch = temps.Acquire();
And(scratch, object, Operand(~kPageAlignmentMask)); And(scratch, object,
Ld_d(scratch, MemOperand(scratch, BasicMemoryChunk::kFlagsOffset)); Operand(~MemoryChunkHeader::GetAlignmentMaskForAssembler()));
Ld_d(scratch, MemOperand(scratch, MemoryChunkLayout::kFlagsOffset));
And(scratch, scratch, Operand(mask)); And(scratch, scratch, Operand(mask));
Branch(condition_met, cc, scratch, Operand(zero_reg)); Branch(condition_met, cc, scratch, Operand(zero_reg));
} }

View File

@ -518,10 +518,6 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
// garbage collection, since that might move the code and invalidate the // garbage collection, since that might move the code and invalidate the
// return address (unless this is somehow accounted for by the called // return address (unless this is somehow accounted for by the called
// function). // function).
enum class SetIsolateDataSlots {
kNo,
kYes,
};
void CallCFunction( void CallCFunction(
ExternalReference function, int num_arguments, ExternalReference function, int num_arguments,
SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes); SetIsolateDataSlots set_isolate_data_slots = SetIsolateDataSlots::kYes);

View File

@ -45,6 +45,11 @@ enum class ComparisonMode {
kFullPointer, kFullPointer,
}; };
enum class SetIsolateDataSlots {
kNo,
kYes,
};
// This is the only place allowed to include the platform-specific headers. // This is the only place allowed to include the platform-specific headers.
#define INCLUDED_FROM_MACRO_ASSEMBLER_H #define INCLUDED_FROM_MACRO_ASSEMBLER_H
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32

View File

@ -6172,8 +6172,9 @@ void MacroAssembler::CallCFunctionHelper(
void MacroAssembler::CheckPageFlag(Register object, Register scratch, int mask, void MacroAssembler::CheckPageFlag(Register object, Register scratch, int mask,
Condition cc, Label* condition_met) { Condition cc, Label* condition_met) {
ASM_CODE_COMMENT(this); ASM_CODE_COMMENT(this);
And(scratch, object, Operand(~kPageAlignmentMask)); And(scratch, object,
Ld(scratch, MemOperand(scratch, BasicMemoryChunk::kFlagsOffset)); Operand(~MemoryChunkHeader::GetAlignmentMaskForAssembler()));
Ld(scratch, MemOperand(scratch, MemoryChunkLayout::kFlagsOffset));
And(scratch, scratch, Operand(mask)); And(scratch, scratch, Operand(mask));
Branch(condition_met, cc, scratch, Operand(zero_reg)); Branch(condition_met, cc, scratch, Operand(zero_reg));
} }

Some files were not shown because too many files have changed in this diff Show More