diff --git a/common.gypi b/common.gypi index a41ffea805b..758d6818a63 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.8', + 'v8_embedder_string': '-node.9', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/base/fpu.cc b/deps/v8/src/base/fpu.cc index 10590de42d1..2e5102d9d10 100644 --- a/deps/v8/src/base/fpu.cc +++ b/deps/v8/src/base/fpu.cc @@ -57,13 +57,21 @@ void FPU::SetFlushDenormals(bool value) { #elif defined(V8_HOST_ARCH_ARM64) || defined(V8_HOST_ARCH_ARM) namespace { +#if defined(V8_HOST_ARCH_ARM64) && defined(_MSC_VER) && !defined(__clang__) +#include +#endif + // Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes // denormals to 0. constexpr int kFlushDenormToZeroBit = (1 << 24); int GetStatusWord() { int result; #if defined(V8_HOST_ARCH_ARM64) - asm volatile("mrs %x[result], FPCR" : [result] "=r"(result)); +# if defined(_MSC_VER) && !defined(__clang__) + result = _ReadStatusReg(ARM64_FPCR); +# else + asm volatile("mrs %x[result], FPCR" : [result] "=r"(result)); +# endif #else asm volatile("vmrs %[result], FPSCR" : [result] "=r"(result)); #endif @@ -72,7 +80,11 @@ int GetStatusWord() { void SetStatusWord(int a) { #if defined(V8_HOST_ARCH_ARM64) - asm volatile("msr FPCR, %x[src]" : : [src] "r"(a)); +# if defined(_MSC_VER) && !defined(__clang__) + _WriteStatusReg(ARM64_FPCR, a); +# else + asm volatile("msr FPCR, %x[src]" : : [src] "r"(a)); +# endif #else asm volatile("vmsr FPSCR, %[src]" : : [src] "r"(a)); #endif diff --git a/deps/v8/src/codegen/arm64/assembler-arm64.h b/deps/v8/src/codegen/arm64/assembler-arm64.h index d720a4377eb..b83e1d6ee74 100644 --- a/deps/v8/src/codegen/arm64/assembler-arm64.h +++ b/deps/v8/src/codegen/arm64/assembler-arm64.h @@ -168,14 +168,10 @@ class AssemblerZone { public: explicit AssemblerZone(const MaybeAssemblerZone& zone) // Create a fresh Zone unless one is already provided. - : maybe_local_zone_( - std::holds_alternative(zone) - ? std::nullopt - : std::make_optional(std::get(zone), - ZONE_NAME)), + : maybe_local_zone_(), zone_(std::holds_alternative(zone) ? std::get(zone) - : &maybe_local_zone_.value()) {} + : &maybe_local_zone_.emplace(std::get(zone), ZONE_NAME)) {} Zone* get() const { return zone_; } diff --git a/deps/v8/src/compiler/js-heap-broker.cc b/deps/v8/src/compiler/js-heap-broker.cc index 3a7949ce8e4..43d5d58c142 100644 --- a/deps/v8/src/compiler/js-heap-broker.cc +++ b/deps/v8/src/compiler/js-heap-broker.cc @@ -879,7 +879,7 @@ ElementAccessFeedback const& JSHeapBroker::ProcessFeedbackMapsForElementAccess( Tagged transition_target; // Don't generate elements kind transitions from stable maps. - if (!map.is_stable()) { + if (!map.is_stable() && possible_transition_targets.begin() != possible_transition_targets.end()) { // The lock is needed for UnusedPropertyFields (called deep inside // FindElementsKindTransitionedMap). MapUpdaterGuardIfNeeded mumd_scope(this); diff --git a/deps/v8/src/execution/frames.h b/deps/v8/src/execution/frames.h index d105cf614db..65020b593d6 100644 --- a/deps/v8/src/execution/frames.h +++ b/deps/v8/src/execution/frames.h @@ -1292,11 +1292,11 @@ class WasmFrame : public TypedFrame { FrameSummaries Summarize() const override; static WasmFrame* cast(StackFrame* frame) { - DCHECK(frame->is_wasm() #ifdef V8_ENABLE_DRUMBRAKE - && !frame->is_wasm_interpreter_entry() + DCHECK(frame->is_wasm() && !frame->is_wasm_interpreter_entry()); +#else + DCHECK(frame->is_wasm()); #endif // V8_ENABLE_DRUMBRAKE - ); return static_cast(frame); } diff --git a/deps/v8/src/execution/isolate.h b/deps/v8/src/execution/isolate.h index 5cc3efbc140..afeab908ac1 100644 --- a/deps/v8/src/execution/isolate.h +++ b/deps/v8/src/execution/isolate.h @@ -574,10 +574,14 @@ using DebugObjectCache = std::vector>; #define THREAD_LOCAL_TOP_ADDRESS(type, name) \ inline type* name##_address() { return &thread_local_top()->name##_; } +#if defined(_MSC_VER) +extern thread_local Isolate* g_current_isolate_ V8_CONSTINIT; +#else // Do not use this variable directly, use Isolate::Current() instead. // Defined outside of Isolate because Isolate uses V8_EXPORT_PRIVATE. __attribute__((tls_model(V8_TLS_MODEL))) extern thread_local Isolate* g_current_isolate_ V8_CONSTINIT; +#endif // defined(_MSC_VER) // HiddenFactory exists so Isolate can privately inherit from it without making // Factory's members available to Isolate directly. diff --git a/deps/v8/src/heap/base/asm/arm64/push_registers_masm.S b/deps/v8/src/heap/base/asm/arm64/push_registers_masm.S new file mode 100644 index 00000000000..9773654ffcf --- /dev/null +++ b/deps/v8/src/heap/base/asm/arm64/push_registers_masm.S @@ -0,0 +1,32 @@ +; Copyright 2020 the V8 project authors. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. + +; This file is exactly the same as push_registers_asm.cc, just formatted for +; the Microsoft Arm Assembler. + + AREA |.text|, CODE, ALIGN=4, READONLY + EXPORT PushAllRegistersAndIterateStack +PushAllRegistersAndIterateStack + ; x19-x29 are callee-saved + STP x19, x20, [sp, #-16]! + STP x21, x22, [sp, #-16]! + STP x23, x24, [sp, #-16]! + STP x25, x26, [sp, #-16]! + STP x27, x28, [sp, #-16]! + STP fp, lr, [sp, #-16]! + ; Maintain frame pointer + MOV fp, sp + ; Pass 1st parameter (x0) unchanged (Stack*). + ; Pass 2nd parameter (x1) unchanged (StackVisitor*). + ; Save 3rd parameter (x2; IterateStackCallback) + MOV x7, x2 + ; Pass 3rd parameter as sp (stack pointer) + MOV x2, sp + BLR x7 + ; Load return address + LDR lr, [sp, #8] + ; Restore frame pointer and pop all callee-saved registers. + LDR fp, [sp], #96 + RET + END \ No newline at end of file diff --git a/deps/v8/src/heap/local-heap.h b/deps/v8/src/heap/local-heap.h index 5c83008f322..955ffa91385 100644 --- a/deps/v8/src/heap/local-heap.h +++ b/deps/v8/src/heap/local-heap.h @@ -33,10 +33,14 @@ class MarkingBarrier; class MutablePageMetadata; class Safepoint; +#if defined(_MSC_VER) +extern thread_local LocalHeap* g_current_local_heap_ V8_CONSTINIT; +#else // Do not use this variable directly, use LocalHeap::Current() instead. // Defined outside of LocalHeap because LocalHeap uses V8_EXPORT_PRIVATE. __attribute__((tls_model(V8_TLS_MODEL))) extern thread_local LocalHeap* g_current_local_heap_ V8_CONSTINIT; +#endif // defined(_MSC_VER) // LocalHeap is used by the GC to track all threads with heap access in order to // stop them before performing a collection. LocalHeaps can be either Parked or diff --git a/deps/v8/src/maglev/maglev-graph-builder.cc b/deps/v8/src/maglev/maglev-graph-builder.cc index db081bfde62..44f5a9a0b61 100644 --- a/deps/v8/src/maglev/maglev-graph-builder.cc +++ b/deps/v8/src/maglev/maglev-graph-builder.cc @@ -11003,13 +11003,19 @@ MaybeReduceResult MaglevGraphBuilder::TryReduceCallForNewClosure( return BuildCallRuntime(Runtime::kThrowConstructorNonCallableError, {target_node}); } + +#ifdef V8_ENABLE_LEAPTIERING + RETURN_IF_DONE(TryBuildCallKnownJSFunction( + target_context, target_node, + GetRootConstant(RootIndex::kUndefinedValue), + dispatch_handle, + shared, feedback_cell, args, feedback_source)); +#else RETURN_IF_DONE(TryBuildCallKnownJSFunction( target_context, target_node, GetRootConstant(RootIndex::kUndefinedValue), -#ifdef V8_ENABLE_LEAPTIERING - dispatch_handle, -#endif shared, feedback_cell, args, feedback_source)); +#endif } return BuildGenericCall(target_node, Call::TargetType::kJSFunction, args); } diff --git a/deps/v8/src/objects/instance-type-inl.h b/deps/v8/src/objects/instance-type-inl.h index 36388d74a55..a904c042212 100644 --- a/deps/v8/src/objects/instance-type-inl.h +++ b/deps/v8/src/objects/instance-type-inl.h @@ -42,13 +42,13 @@ HEAP_OBJECT_TYPE_LIST(DECL_TYPE) // Instance types which are associated with one unique map. template -V8_INLINE consteval std::optional UniqueMapOfInstanceTypeCheck() { +V8_INLINE constexpr std::optional UniqueMapOfInstanceTypeCheck() { return {}; } #define INSTANCE_TYPE_MAP(V, rootIndexName, rootAccessorName, class_name) \ template <> \ - V8_INLINE consteval std::optional \ + V8_INLINE constexpr std::optional \ UniqueMapOfInstanceTypeCheck() { \ return {RootIndex::k##rootIndexName}; \ } diff --git a/deps/v8/src/objects/tagged-field.h b/deps/v8/src/objects/tagged-field.h index 0d0654b8467..0a11067b43b 100644 --- a/deps/v8/src/objects/tagged-field.h +++ b/deps/v8/src/objects/tagged-field.h @@ -121,12 +121,10 @@ static_assert(sizeof(UnalignedDoubleMember) == sizeof(double)); #define FLEXIBLE_ARRAY_MEMBER(Type, name) \ using FlexibleDataReturnType = Type[0]; \ FlexibleDataReturnType& name() { \ - static_assert(alignof(Type) <= alignof(decltype(*this))); \ using ReturnType = Type[0]; \ return reinterpret_cast(*(this + 1)); \ } \ const FlexibleDataReturnType& name() const { \ - static_assert(alignof(Type) <= alignof(decltype(*this))); \ using ReturnType = Type[0]; \ return reinterpret_cast(*(this + 1)); \ } \ diff --git a/deps/v8/src/runtime/runtime-test.cc b/deps/v8/src/runtime/runtime-test.cc index 23501c0c38c..c5aba6690e8 100644 --- a/deps/v8/src/runtime/runtime-test.cc +++ b/deps/v8/src/runtime/runtime-test.cc @@ -1204,8 +1204,8 @@ RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) { namespace { int FixedArrayLenFromSize(int size) { - return std::min({(size - OFFSET_OF_DATA_START(FixedArray)) / kTaggedSize, - FixedArray::kMaxRegularLength}); +return std::min((size - OFFSET_OF_DATA_START(FixedArray)) / kTaggedSize, + static_cast(FixedArray::kMaxRegularLength)); } void FillUpOneNewSpacePage(Isolate* isolate, Heap* heap, diff --git a/deps/v8/src/wasm/wasm-objects.cc b/deps/v8/src/wasm/wasm-objects.cc index 91ebf45a50b..aaf65e44768 100644 --- a/deps/v8/src/wasm/wasm-objects.cc +++ b/deps/v8/src/wasm/wasm-objects.cc @@ -3009,15 +3009,21 @@ DirectHandle WasmExportedFunction::New( DirectHandle func_ref, DirectHandle internal_function, int arity, DirectHandle export_wrapper) { +#if V8_ENABLE_DRUMBRAKE DCHECK(CodeKind::JS_TO_WASM_FUNCTION == export_wrapper->kind() || (export_wrapper->is_builtin() && (export_wrapper->builtin_id() == Builtin::kJSToWasmWrapper || -#if V8_ENABLE_DRUMBRAKE export_wrapper->builtin_id() == Builtin::kGenericJSToWasmInterpreterWrapper || -#endif // V8_ENABLE_DRUMBRAKE export_wrapper->builtin_id() == Builtin::kWasmPromising || export_wrapper->builtin_id() == Builtin::kWasmStressSwitch))); +#else + DCHECK(CodeKind::JS_TO_WASM_FUNCTION == export_wrapper->kind() || + (export_wrapper->is_builtin() && + (export_wrapper->builtin_id() == Builtin::kJSToWasmWrapper || + export_wrapper->builtin_id() == Builtin::kWasmPromising || + export_wrapper->builtin_id() == Builtin::kWasmStressSwitch))); +#endif // V8_ENABLE_DRUMBRAKE int func_index = internal_function->function_index(); Factory* factory = isolate->factory(); DirectHandle rtt; diff --git a/deps/v8/third_party/rapidhash-v8/rapidhash.h b/deps/v8/third_party/rapidhash-v8/rapidhash.h index 74ee12b8664..1f2a1dd4743 100644 --- a/deps/v8/third_party/rapidhash-v8/rapidhash.h +++ b/deps/v8/third_party/rapidhash-v8/rapidhash.h @@ -153,8 +153,13 @@ struct PlainHashReader { /* * Likely and unlikely macros. */ -#define _likely_(x) __builtin_expect(x, 1) -#define _unlikely_(x) __builtin_expect(x, 0) +#if defined(_MSC_VER) && !defined(__clang__) + #define _likely_(x) (x) + #define _unlikely_(x) (x) +#else + #define _likely_(x) __builtin_expect(x, 1) + #define _unlikely_(x) __builtin_expect(x, 0) +#endif /* * Default seed. diff --git a/test/addons/esm/binding-export-default.cc b/test/addons/esm-export/binding-export-default.cc similarity index 100% rename from test/addons/esm/binding-export-default.cc rename to test/addons/esm-export/binding-export-default.cc diff --git a/test/addons/esm/binding-export-primitive.cc b/test/addons/esm-export/binding-export-primitive.cc similarity index 100% rename from test/addons/esm/binding-export-primitive.cc rename to test/addons/esm-export/binding-export-primitive.cc diff --git a/test/addons/esm-export/binding.gyp b/test/addons/esm-export/binding.gyp new file mode 100644 index 00000000000..df8e2d516e0 --- /dev/null +++ b/test/addons/esm-export/binding.gyp @@ -0,0 +1,14 @@ +{ + 'targets': [ + { + 'target_name': 'binding-export-default', + 'sources': [ 'binding-export-default.cc' ], + 'includes': ['../common.gypi'], + }, + { + 'target_name': 'binding-export-primitive', + 'sources': [ 'binding-export-primitive.cc' ], + 'includes': ['../common.gypi'], + }, + ] +} diff --git a/test/addons/esm-export/test-esm.mjs b/test/addons/esm-export/test-esm.mjs new file mode 100644 index 00000000000..d524ef8d547 --- /dev/null +++ b/test/addons/esm-export/test-esm.mjs @@ -0,0 +1,37 @@ +/** + * This file is supposed to be loaded by `test-import.js` and `test-require.js` + * to verify that `import('*.node')` is working properly either been loaded with + * the ESM loader or the CJS loader. + */ + +import { buildType } from '../../common/index.mjs'; +import assert from 'node:assert'; +import { createRequire } from 'node:module'; +import { pathToFileURL } from 'node:url'; + +const require = createRequire(import.meta.url); + +export async function run() { + // binding-export-default.node + { + const bindingPath = require.resolve(`./build/${buildType}/binding-export-default.node`); + // Test with order of require+import + const bindingRequire = require(bindingPath); + const ns = await import(pathToFileURL(bindingPath)); + assert.strictEqual(ns.default, bindingRequire); + + // As same as ESM-import-CJS, the default export is the value of `module.exports`. + assert.strictEqual(ns.default, ns['module.exports']); + assert.strictEqual(ns.default.default(), 'hello world'); + } + + // binding-export-primitive.node + { + const bindingPath = require.resolve(`./build/${buildType}/binding-export-primitive.node`); + const ns = await import(pathToFileURL(bindingPath)); + + // As same as ESM-import-CJS, the default export is the value of `module.exports`. + assert.strictEqual(ns.default, ns['module.exports']); + assert.strictEqual(ns.default, 'hello world'); + } +} diff --git a/test/addons/esm-export/test-require.js b/test/addons/esm-export/test-require.js new file mode 100644 index 00000000000..79a0904ebd1 --- /dev/null +++ b/test/addons/esm-export/test-require.js @@ -0,0 +1,6 @@ +// Flags: --experimental-addon-modules +'use strict'; +const common = require('../../common'); + +require('./test-esm.mjs') + .run().then(common.mustCall()); diff --git a/test/addons/esm/binding.gyp b/test/addons/esm/binding.gyp index f94ca7392ea..8b9bcda194c 100644 --- a/test/addons/esm/binding.gyp +++ b/test/addons/esm/binding.gyp @@ -1,6 +1,6 @@ { 'variables': { - 'source_dir': '