From d639321acd987394063eac9b6dcf7400d80c926b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 20 Mar 2021 07:58:06 +0100 Subject: [PATCH] deps: patch V8 to 9.0.257.13 Refs: https://github.com/v8/v8/compare/9.0.257.11...9.0.257.13 PR-URL: https://github.com/nodejs/node/pull/37830 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/builtins/mips/builtins-mips.cc | 26 ++++--- .../v8/src/builtins/mips64/builtins-mips64.cc | 71 +++++++++++++------ deps/v8/src/codegen/mips64/register-mips64.h | 4 +- deps/v8/src/deoptimizer/translated-state.cc | 58 ++++++++++++--- deps/v8/src/deoptimizer/translated-state.h | 19 ++++- deps/v8/test/message/message.status | 4 +- .../test/mjsunit/compiler/regress-1182647.js | 25 +++++++ deps/v8/tools/testrunner/base_runner.py | 4 ++ 9 files changed, 166 insertions(+), 47 deletions(-) create mode 100644 deps/v8/test/mjsunit/compiler/regress-1182647.js diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index ec959c40b4e2e4..e135e011bc31af 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 9 #define V8_MINOR_VERSION 0 #define V8_BUILD_NUMBER 257 -#define V8_PATCH_LEVEL 11 +#define V8_PATCH_LEVEL 13 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/builtins/mips/builtins-mips.cc b/deps/v8/src/builtins/mips/builtins-mips.cc index 670238a45a9f20..235ca01f98e81c 100644 --- a/deps/v8/src/builtins/mips/builtins-mips.cc +++ b/deps/v8/src/builtins/mips/builtins-mips.cc @@ -2299,15 +2299,23 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { // Save all parameter registers (see wasm-linkage.h). They might be // overwritten in the runtime call below. We don't have any callee-saved // registers in wasm, so no need to store anything else. - constexpr RegList gp_regs = Register::ListOf(a0, a2, a3); - constexpr RegList fp_regs = - DoubleRegister::ListOf(f2, f4, f6, f8, f10, f12, f14); - constexpr int16_t num_to_push = base::bits::CountPopulation(gp_regs) + - base::bits::CountPopulation(fp_regs); - // The number of regs to be pushed before kWasmInstanceRegister should be - // equal to kNumberOfSavedAllParamRegs. - STATIC_ASSERT(num_to_push == - WasmCompileLazyFrameConstants::kNumberOfSavedAllParamRegs); + RegList gp_regs = 0; + for (Register gp_param_reg : wasm::kGpParamRegisters) { + gp_regs |= gp_param_reg.bit(); + } + + RegList fp_regs = 0; + for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) { + fp_regs |= fp_param_reg.bit(); + } + + CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters)); + CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters)); + CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs, + NumRegs(gp_regs)); + CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs, + NumRegs(fp_regs)); + __ MultiPush(gp_regs); __ MultiPushFPU(fp_regs); diff --git a/deps/v8/src/builtins/mips64/builtins-mips64.cc b/deps/v8/src/builtins/mips64/builtins-mips64.cc index c33f46d1c1ef36..55c8eb70742e76 100644 --- a/deps/v8/src/builtins/mips64/builtins-mips64.cc +++ b/deps/v8/src/builtins/mips64/builtins-mips64.cc @@ -1478,7 +1478,9 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm, bool with_result) { const RegisterConfiguration* config(RegisterConfiguration::Default()); int allocatable_register_count = config->num_allocatable_general_registers(); - Register scratch = t3; + UseScratchRegisterScope temps(masm); + Register scratch = temps.Acquire(); + if (with_result) { if (java_script_builtin) { __ mov(scratch, v0); @@ -2363,24 +2365,41 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { // Save all parameter registers (see wasm-linkage.h). They might be // overwritten in the runtime call below. We don't have any callee-saved // registers in wasm, so no need to store anything else. - constexpr RegList gp_regs = - Register::ListOf(a0, a2, a3, a4, a5, a6, a7); - constexpr RegList fp_regs = - DoubleRegister::ListOf(f2, f4, f6, f8, f10, f12, f14); - constexpr int16_t num_to_push = base::bits::CountPopulation(gp_regs) + - base::bits::CountPopulation(fp_regs); - // The number of regs to be pushed before kWasmInstanceRegister should be - // equal to kNumberOfSavedAllParamRegs. - STATIC_ASSERT(num_to_push == - WasmCompileLazyFrameConstants::kNumberOfSavedAllParamRegs); - __ MultiPush(gp_regs); - if (CpuFeatures::IsSupported(MIPS_SIMD)) { - __ MultiPushMSA(fp_regs); - } else { - __ MultiPushFPU(fp_regs); - __ Dsubu(sp, sp, base::bits::CountPopulation(fp_regs) * kDoubleSize); + RegList gp_regs = 0; + for (Register gp_param_reg : wasm::kGpParamRegisters) { + gp_regs |= gp_param_reg.bit(); + } + + RegList fp_regs = 0; + for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) { + fp_regs |= fp_param_reg.bit(); } + CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters)); + CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters)); + CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs, + NumRegs(gp_regs)); + CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs, + NumRegs(fp_regs)); + + __ MultiPush(gp_regs); + // Check if machine has simd enabled, if so push vector registers. If not + // then only push double registers. + Label push_doubles, simd_pushed; + __ li(a1, ExternalReference::supports_wasm_simd_128_address()); + // If > 0 then simd is available. + __ Lbu(a1, MemOperand(a1)); + __ Branch(&push_doubles, le, a1, Operand(zero_reg)); + // Save vector registers. + __ MultiPushMSA(fp_regs); + __ Branch(&simd_pushed); + __ bind(&push_doubles); + __ MultiPushFPU(fp_regs); + // kFixedFrameSizeFromFp is hard coded to include space for Simd + // registers, so we still need to allocate extra (unused) space on the stack + // as if they were saved. + __ Dsubu(sp, sp, base::bits::CountPopulation(fp_regs) * kDoubleSize); + __ bind(&simd_pushed); // Pass instance and function index as an explicit arguments to the runtime // function. __ Push(kWasmInstanceRegister, kWasmCompileLazyFuncIndexRegister); @@ -2390,12 +2409,18 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { __ CallRuntime(Runtime::kWasmCompileLazy, 2); // Restore registers. - if (CpuFeatures::IsSupported(MIPS_SIMD)) { - __ MultiPopMSA(fp_regs); - } else { - __ Daddu(sp, sp, base::bits::CountPopulation(fp_regs) * kDoubleSize); - __ MultiPopFPU(fp_regs); - } + Label pop_doubles, simd_popped; + __ li(a1, ExternalReference::supports_wasm_simd_128_address()); + // If > 0 then simd is available. + __ Lbu(a1, MemOperand(a1)); + __ Branch(&pop_doubles, le, a1, Operand(zero_reg)); + // Pop vector registers. + __ MultiPopMSA(fp_regs); + __ Branch(&simd_popped); + __ bind(&pop_doubles); + __ Daddu(sp, sp, base::bits::CountPopulation(fp_regs) * kDoubleSize); + __ MultiPopFPU(fp_regs); + __ bind(&simd_popped); __ MultiPop(gp_regs); } // Finally, jump to the entrypoint. diff --git a/deps/v8/src/codegen/mips64/register-mips64.h b/deps/v8/src/codegen/mips64/register-mips64.h index d7b45eda3838db..8267d6b2ffae75 100644 --- a/deps/v8/src/codegen/mips64/register-mips64.h +++ b/deps/v8/src/codegen/mips64/register-mips64.h @@ -21,7 +21,7 @@ namespace internal { #define ALLOCATABLE_GENERAL_REGISTERS(V) \ V(a0) V(a1) V(a2) V(a3) \ - V(a4) V(a5) V(a6) V(a7) V(t0) V(t1) V(t2) V(s7) \ + V(a4) V(a5) V(a6) V(a7) V(t0) V(t1) V(t2) V(t3) V(s7) \ V(v0) V(v1) #define DOUBLE_REGISTERS(V) \ @@ -368,7 +368,7 @@ constexpr Register kReturnRegister2 = a0; constexpr Register kJSFunctionRegister = a1; constexpr Register kContextRegister = s7; constexpr Register kAllocateSizeRegister = a0; -constexpr Register kSpeculationPoisonRegister = a7; +constexpr Register kSpeculationPoisonRegister = t3; constexpr Register kInterpreterAccumulatorRegister = v0; constexpr Register kInterpreterBytecodeOffsetRegister = t0; constexpr Register kInterpreterBytecodeArrayRegister = t1; diff --git a/deps/v8/src/deoptimizer/translated-state.cc b/deps/v8/src/deoptimizer/translated-state.cc index daaf449acd95d5..cb423d09e8a423 100644 --- a/deps/v8/src/deoptimizer/translated-state.cc +++ b/deps/v8/src/deoptimizer/translated-state.cc @@ -1282,7 +1282,8 @@ Address TranslatedState::DecompressIfNeeded(intptr_t value) { } } -TranslatedState::TranslatedState(const JavaScriptFrame* frame) { +TranslatedState::TranslatedState(const JavaScriptFrame* frame) + : purpose_(kFrameInspection) { int deopt_index = Safepoint::kNoDeoptimizationIndex; DeoptimizationData data = static_cast(frame)->GetDeoptimizationData( @@ -1672,25 +1673,63 @@ void TranslatedState::EnsureCapturedObjectAllocatedAt( } default: - CHECK(map->IsJSObjectMap()); EnsureJSObjectAllocated(slot, map); - TranslatedValue* properties_slot = &(frame->values_[value_index]); - value_index++; + int remaining_children_count = slot->GetChildrenCount() - 1; + + TranslatedValue* properties_slot = frame->ValueAt(value_index); + value_index++, remaining_children_count--; if (properties_slot->kind() == TranslatedValue::kCapturedObject) { - // If we are materializing the property array, make sure we put - // the mutable heap numbers at the right places. + // We are materializing the property array, so make sure we put the + // mutable heap numbers at the right places. EnsurePropertiesAllocatedAndMarked(properties_slot, map); EnsureChildrenAllocated(properties_slot->GetChildrenCount(), frame, &value_index, worklist); + } else { + CHECK_EQ(properties_slot->kind(), TranslatedValue::kTagged); } - // Make sure all the remaining children (after the map and properties) are - // allocated. - return EnsureChildrenAllocated(slot->GetChildrenCount() - 2, frame, + + TranslatedValue* elements_slot = frame->ValueAt(value_index); + value_index++, remaining_children_count--; + if (elements_slot->kind() == TranslatedValue::kCapturedObject || + !map->IsJSArrayMap()) { + // Handle this case with the other remaining children below. + value_index--, remaining_children_count++; + } else { + CHECK_EQ(elements_slot->kind(), TranslatedValue::kTagged); + elements_slot->GetValue(); + if (purpose_ == kFrameInspection) { + // We are materializing a JSArray for the purpose of frame inspection. + // If we were to construct it with the above elements value then an + // actual deopt later on might create another JSArray instance with + // the same elements store. That would violate the key assumption + // behind left-trimming. + elements_slot->ReplaceElementsArrayWithCopy(); + } + } + + // Make sure all the remaining children (after the map, properties store, + // and possibly elements store) are allocated. + return EnsureChildrenAllocated(remaining_children_count, frame, &value_index, worklist); } UNREACHABLE(); } +void TranslatedValue::ReplaceElementsArrayWithCopy() { + DCHECK_EQ(kind(), TranslatedValue::kTagged); + DCHECK_EQ(materialization_state(), TranslatedValue::kFinished); + auto elements = Handle::cast(GetValue()); + DCHECK(elements->IsFixedArray() || elements->IsFixedDoubleArray()); + if (elements->IsFixedDoubleArray()) { + DCHECK(!elements->IsCowArray()); + set_storage(isolate()->factory()->CopyFixedDoubleArray( + Handle::cast(elements))); + } else if (!elements->IsCowArray()) { + set_storage(isolate()->factory()->CopyFixedArray( + Handle::cast(elements))); + } +} + void TranslatedState::EnsureChildrenAllocated(int count, TranslatedFrame* frame, int* value_index, std::stack* worklist) { @@ -1755,6 +1794,7 @@ Handle TranslatedState::AllocateStorageFor(TranslatedValue* slot) { void TranslatedState::EnsureJSObjectAllocated(TranslatedValue* slot, Handle map) { + CHECK(map->IsJSObjectMap()); CHECK_EQ(map->instance_size(), slot->GetChildrenCount() * kTaggedSize); Handle object_storage = AllocateStorageFor(slot); diff --git a/deps/v8/src/deoptimizer/translated-state.h b/deps/v8/src/deoptimizer/translated-state.h index eb8188a0edfcc5..a818979ad71fa0 100644 --- a/deps/v8/src/deoptimizer/translated-state.h +++ b/deps/v8/src/deoptimizer/translated-state.h @@ -125,6 +125,8 @@ class TranslatedValue { return storage_; } + void ReplaceElementsArrayWithCopy(); + Kind kind_; MaterializationState materialization_state_ = kUninitialized; TranslatedState* container_; // This is only needed for materialization of @@ -335,7 +337,15 @@ class TranslatedFrame { class TranslatedState { public: - TranslatedState() = default; + // There are two constructors, each for a different purpose: + + // The default constructor is for the purpose of deoptimizing an optimized + // frame (replacing it with one or several unoptimized frames). It is used by + // the Deoptimizer. + TranslatedState() : purpose_(kDeoptimization) {} + + // This constructor is for the purpose of merely inspecting an optimized + // frame. It is used by stack trace generation and various debugging features. explicit TranslatedState(const JavaScriptFrame* frame); void Prepare(Address stack_frame_pointer); @@ -370,6 +380,12 @@ class TranslatedState { private: friend TranslatedValue; + // See the description of the constructors for an explanation of the two + // purposes. The only actual difference is that in the kFrameInspection case + // extra work is needed to not violate assumptions made by left-trimming. For + // details, see the code around ReplaceElementsArrayWithCopy. + enum Purpose { kDeoptimization, kFrameInspection }; + TranslatedFrame CreateNextTranslatedFrame(TranslationArrayIterator* iterator, FixedArray literal_array, Address fp, FILE* trace_file); @@ -426,6 +442,7 @@ class TranslatedState { static Float32 GetFloatSlot(Address fp, int slot_index); static Float64 GetDoubleSlot(Address fp, int slot_index); + Purpose const purpose_; std::vector frames_; Isolate* isolate_ = nullptr; Address stack_frame_pointer_ = kNullAddress; diff --git a/deps/v8/test/message/message.status b/deps/v8/test/message/message.status index 633eadddcd334e..d5d57e0b29c89c 100644 --- a/deps/v8/test/message/message.status +++ b/deps/v8/test/message/message.status @@ -70,10 +70,10 @@ }], ################################################################################ -['arch == ppc64', { +['arch == ppc64 or arch == mips64el or arch == mipsel', { # Tests that require Simd enabled. 'wasm-trace-memory': [SKIP], -}], +}], # arch == ppc64 or arch == mips64el or arch == mipsel ] diff --git a/deps/v8/test/mjsunit/compiler/regress-1182647.js b/deps/v8/test/mjsunit/compiler/regress-1182647.js new file mode 100644 index 00000000000000..e0582f7cbfb4f1 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-1182647.js @@ -0,0 +1,25 @@ +// Copyright 2021 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. + +// Flags: --allow-natives-syntax --verify-heap + +function foo() { + const arr = Array(1000); + + function bar() { + try { ({a: p4nda, b: arr.length}); } catch(e) {} + } + + for (var i = 0; i < 25; i++) bar(); + + /p4nda/.test({}); // Deopt here. + + arr.shift(); +} + +%PrepareFunctionForOptimization(foo); +foo(); +foo(); +%OptimizeFunctionOnNextCall(foo); +foo(); diff --git a/deps/v8/tools/testrunner/base_runner.py b/deps/v8/tools/testrunner/base_runner.py index da9d26fa46f3a5..295633258b74b4 100644 --- a/deps/v8/tools/testrunner/base_runner.py +++ b/deps/v8/tools/testrunner/base_runner.py @@ -653,6 +653,10 @@ def _get_statusfile_variables(self, options): if self.build_config.arch == 'ppc64': no_simd_sse = True + if self.build_config.arch == 'mips64el' or \ + self.build_config.arch == 'mipsel': + no_simd_sse = not simd_mips + return { "arch": self.build_config.arch, "asan": self.build_config.asan,