diff --git a/common.gypi b/common.gypi index cc9107616a65a5..44e41a9753babf 100644 --- a/common.gypi +++ b/common.gypi @@ -39,7 +39,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.15', + 'v8_embedder_string': '-node.16', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/builtins/builtins-regexp-gen.cc b/deps/v8/src/builtins/builtins-regexp-gen.cc index 4bc0b6ad74f1c4..b333f2a820c681 100644 --- a/deps/v8/src/builtins/builtins-regexp-gen.cc +++ b/deps/v8/src/builtins/builtins-regexp-gen.cc @@ -605,13 +605,18 @@ TNode RegExpBuiltinsAssembler::RegExpExecInternal( TNode code_entry = LoadCodeObjectEntry(code); - TNode result = UncheckedCast(CallCFunction( - code_entry, retval_type, std::make_pair(arg0_type, arg0), - std::make_pair(arg1_type, arg1), std::make_pair(arg2_type, arg2), - std::make_pair(arg3_type, arg3), std::make_pair(arg4_type, arg4), - std::make_pair(arg5_type, arg5), std::make_pair(arg6_type, arg6), - std::make_pair(arg7_type, arg7), std::make_pair(arg8_type, arg8), - std::make_pair(arg9_type, arg9))); + // AIX uses function descriptors on CFunction calls. code_entry in this case + // may also point to a Regex interpreter entry trampoline which does not + // have a function descriptor. This method is ineffective on other platforms + // and is equivalent to CallCFunction. + TNode result = + UncheckedCast(CallCFunctionWithoutFunctionDescriptor( + code_entry, retval_type, std::make_pair(arg0_type, arg0), + std::make_pair(arg1_type, arg1), std::make_pair(arg2_type, arg2), + std::make_pair(arg3_type, arg3), std::make_pair(arg4_type, arg4), + std::make_pair(arg5_type, arg5), std::make_pair(arg6_type, arg6), + std::make_pair(arg7_type, arg7), std::make_pair(arg8_type, arg8), + std::make_pair(arg9_type, arg9))); // Check the result. // We expect exactly one result since we force the called regexp to behave diff --git a/deps/v8/src/codegen/ppc/assembler-ppc.cc b/deps/v8/src/codegen/ppc/assembler-ppc.cc index 17a3aba1b2e3e3..03dbb2edaa0dc3 100644 --- a/deps/v8/src/codegen/ppc/assembler-ppc.cc +++ b/deps/v8/src/codegen/ppc/assembler-ppc.cc @@ -1121,20 +1121,6 @@ void Assembler::divdu(Register dst, Register src1, Register src2, OEBit o, } #endif -// Function descriptor for AIX. -// Code address skips the function descriptor "header". -// TOC and static chain are ignored and set to 0. -void Assembler::function_descriptor() { - if (ABI_USES_FUNCTION_DESCRIPTORS) { - Label instructions; - DCHECK_EQ(pc_offset(), 0); - emit_label_addr(&instructions); - dp(0); - dp(0); - bind(&instructions); - } -} - int Assembler::instructions_required_for_mov(Register dst, const Operand& src) const { bool canOptimize = diff --git a/deps/v8/src/codegen/ppc/assembler-ppc.h b/deps/v8/src/codegen/ppc/assembler-ppc.h index 42eda72d4d76d8..c056de9f2feaeb 100644 --- a/deps/v8/src/codegen/ppc/assembler-ppc.h +++ b/deps/v8/src/codegen/ppc/assembler-ppc.h @@ -840,8 +840,6 @@ class Assembler : public AssemblerBase { void mtfprwa(DoubleRegister dst, Register src); #endif - void function_descriptor(); - // Exception-generating instructions and debugging support void stop(Condition cond = al, int32_t code = kDefaultStopCode, CRegister cr = cr7); diff --git a/deps/v8/src/codegen/ppc/constants-ppc.h b/deps/v8/src/codegen/ppc/constants-ppc.h index f6ebc6a7ba53c5..2e499fd2c41357 100644 --- a/deps/v8/src/codegen/ppc/constants-ppc.h +++ b/deps/v8/src/codegen/ppc/constants-ppc.h @@ -60,6 +60,12 @@ namespace internal { // TODO(sigurds): Change this value once we use relative jumps. constexpr size_t kMaxPCRelativeCodeRangeInMB = 0; +// Used to encode a boolean value when emitting 32 bit +// opcodes which will indicate the presence of function descriptors +constexpr int kHasFunctionDescriptorBitShift = 9; +constexpr int kHasFunctionDescriptorBitMask = 1 + << kHasFunctionDescriptorBitShift; + // Number of registers const int kNumRegisters = 32; diff --git a/deps/v8/src/codegen/ppc/macro-assembler-ppc.cc b/deps/v8/src/codegen/ppc/macro-assembler-ppc.cc index 9e41dec2a8fd79..08fb85dd2ced21 100644 --- a/deps/v8/src/codegen/ppc/macro-assembler-ppc.cc +++ b/deps/v8/src/codegen/ppc/macro-assembler-ppc.cc @@ -209,6 +209,12 @@ void TurboAssembler::Jump(const ExternalReference& reference) { UseScratchRegisterScope temps(this); Register scratch = temps.Acquire(); Move(scratch, reference); + if (ABI_USES_FUNCTION_DESCRIPTORS) { + // AIX uses a function descriptor. When calling C code be + // aware of this descriptor and pick up values from it. + LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(scratch, kPointerSize)); + LoadP(scratch, MemOperand(scratch, 0)); + } Jump(scratch); } @@ -1930,28 +1936,35 @@ void TurboAssembler::MovToFloatParameters(DoubleRegister src1, void TurboAssembler::CallCFunction(ExternalReference function, int num_reg_arguments, - int num_double_arguments) { + int num_double_arguments, + bool has_function_descriptor) { Move(ip, function); - CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments); + CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments, + has_function_descriptor); } void TurboAssembler::CallCFunction(Register function, int num_reg_arguments, - int num_double_arguments) { - CallCFunctionHelper(function, num_reg_arguments, num_double_arguments); + int num_double_arguments, + bool has_function_descriptor) { + CallCFunctionHelper(function, num_reg_arguments, num_double_arguments, + has_function_descriptor); } void TurboAssembler::CallCFunction(ExternalReference function, - int num_arguments) { - CallCFunction(function, num_arguments, 0); + int num_arguments, + bool has_function_descriptor) { + CallCFunction(function, num_arguments, 0, has_function_descriptor); } -void TurboAssembler::CallCFunction(Register function, int num_arguments) { - CallCFunction(function, num_arguments, 0); +void TurboAssembler::CallCFunction(Register function, int num_arguments, + bool has_function_descriptor) { + CallCFunction(function, num_arguments, 0, has_function_descriptor); } void TurboAssembler::CallCFunctionHelper(Register function, int num_reg_arguments, - int num_double_arguments) { + int num_double_arguments, + bool has_function_descriptor) { DCHECK_LE(num_reg_arguments + num_double_arguments, kMaxCParameters); DCHECK(has_frame()); @@ -1976,7 +1989,7 @@ void TurboAssembler::CallCFunctionHelper(Register function, // allow preemption, so the return address in the link register // stays correct. Register dest = function; - if (ABI_USES_FUNCTION_DESCRIPTORS) { + if (ABI_USES_FUNCTION_DESCRIPTORS && has_function_descriptor) { // AIX/PPC64BE Linux uses a function descriptor. When calling C code be // aware of this descriptor and pick up values from it LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(function, kPointerSize)); diff --git a/deps/v8/src/codegen/ppc/macro-assembler-ppc.h b/deps/v8/src/codegen/ppc/macro-assembler-ppc.h index 7ff5a6bb4b7803..1c88558fc4a0a3 100644 --- a/deps/v8/src/codegen/ppc/macro-assembler-ppc.h +++ b/deps/v8/src/codegen/ppc/macro-assembler-ppc.h @@ -350,12 +350,16 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { // garbage collection, since that might move the code and invalidate the // return address (unless this is somehow accounted for by the called // function). - void CallCFunction(ExternalReference function, int num_arguments); - void CallCFunction(Register function, int num_arguments); + void CallCFunction(ExternalReference function, int num_arguments, + bool has_function_descriptor = kHasFunctionDescriptor); + void CallCFunction(Register function, int num_arguments, + bool has_function_descriptor = kHasFunctionDescriptor); void CallCFunction(ExternalReference function, int num_reg_arguments, - int num_double_arguments); + int num_double_arguments, + bool has_function_descriptor = kHasFunctionDescriptor); void CallCFunction(Register function, int num_reg_arguments, - int num_double_arguments); + int num_double_arguments, + bool has_function_descriptor = kHasFunctionDescriptor); // Call a runtime routine. This expects {centry} to contain a fitting CEntry // builtin for the target runtime function and uses an indirect call. @@ -642,7 +646,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { int CalculateStackPassedWords(int num_reg_arguments, int num_double_arguments); void CallCFunctionHelper(Register function, int num_reg_arguments, - int num_double_arguments); + int num_double_arguments, + bool has_function_descriptor); void CallRecordWriteStub(Register object, Register address, RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode, Handle code_target, diff --git a/deps/v8/src/common/globals.h b/deps/v8/src/common/globals.h index 20faebfe3a1835..9d5771f6946380 100644 --- a/deps/v8/src/common/globals.h +++ b/deps/v8/src/common/globals.h @@ -400,6 +400,7 @@ enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; // Enums used by CEntry. enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs }; enum ArgvMode { kArgvOnStack, kArgvInRegister }; +enum FunctionDescriptorMode { kNoFunctionDescriptor, kHasFunctionDescriptor }; // This constant is used as an undefined value when passing source positions. constexpr int kNoSourcePosition = -1; diff --git a/deps/v8/src/compiler/backend/instruction-selector.cc b/deps/v8/src/compiler/backend/instruction-selector.cc index 22d81c0c550cd3..e165c6c6a9e93a 100644 --- a/deps/v8/src/compiler/backend/instruction-selector.cc +++ b/deps/v8/src/compiler/backend/instruction-selector.cc @@ -2810,10 +2810,17 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { // Select the appropriate opcode based on the call type. InstructionCode opcode = kArchNop; switch (call_descriptor->kind()) { - case CallDescriptor::kCallAddress: - opcode = kArchCallCFunction | MiscField::encode(static_cast( - call_descriptor->ParameterCount())); + case CallDescriptor::kCallAddress: { + int misc_field = static_cast(call_descriptor->ParameterCount()); +#if defined(_AIX) + // Highest misc_field bit is used on AIX to indicate if a CFunction call + // has function descriptor or not. + misc_field |= call_descriptor->HasFunctionDescriptor() + << kHasFunctionDescriptorBitShift; +#endif + opcode = kArchCallCFunction | MiscField::encode(misc_field); break; + } case CallDescriptor::kCallCodeObject: opcode = kArchCallCodeObject | MiscField::encode(flags); break; diff --git a/deps/v8/src/compiler/backend/instruction.h b/deps/v8/src/compiler/backend/instruction.h index 321f069531ffb2..462b0daf6b9c72 100644 --- a/deps/v8/src/compiler/backend/instruction.h +++ b/deps/v8/src/compiler/backend/instruction.h @@ -807,7 +807,8 @@ class V8_EXPORT_PRIVATE Instruction final { size_t output_count, InstructionOperand* outputs, size_t input_count, InstructionOperand* inputs, size_t temp_count, InstructionOperand* temps) { - DCHECK_LE(0, opcode); + // TODO(9872) + // DCHECK_LE(0, opcode); DCHECK(output_count == 0 || outputs != nullptr); DCHECK(input_count == 0 || inputs != nullptr); DCHECK(temp_count == 0 || temps != nullptr); diff --git a/deps/v8/src/compiler/backend/ppc/code-generator-ppc.cc b/deps/v8/src/compiler/backend/ppc/code-generator-ppc.cc index dde1804adbbeac..964f88881678da 100644 --- a/deps/v8/src/compiler/backend/ppc/code-generator-ppc.cc +++ b/deps/v8/src/compiler/backend/ppc/code-generator-ppc.cc @@ -1019,13 +1019,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( #endif break; case kArchCallCFunction: { - int const num_parameters = MiscField::decode(instr->opcode()); + int misc_field = MiscField::decode(instr->opcode()); + int num_parameters = misc_field; + bool has_function_descriptor = false; Label start_call; bool isWasmCapiFunction = linkage()->GetIncomingDescriptor()->IsWasmCapiFunction(); #if defined(_AIX) // AIX/PPC64BE Linux uses a function descriptor - // and emits 2 extra Load instrcutions under CallCFunctionHelper. + int kNumParametersMask = kHasFunctionDescriptorBitMask - 1; + num_parameters = kNumParametersMask & misc_field; + has_function_descriptor = + (misc_field & kHasFunctionDescriptorBitMask) != 0; + // AIX emits 2 extra Load instructions under CallCFunctionHelper + // due to having function descriptor. constexpr int offset = 11 * kInstrSize; #else constexpr int offset = 9 * kInstrSize; @@ -1041,10 +1048,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( } if (instr->InputAt(0)->IsImmediate()) { ExternalReference ref = i.InputExternalReference(0); - __ CallCFunction(ref, num_parameters); + __ CallCFunction(ref, num_parameters, has_function_descriptor); } else { Register func = i.InputRegister(0); - __ CallCFunction(func, num_parameters); + __ CallCFunction(func, num_parameters, has_function_descriptor); } // TODO(miladfar): In the above block, kScratchReg must be populated with // the strictly-correct PC, which is the return address at this spot. The diff --git a/deps/v8/src/compiler/code-assembler.cc b/deps/v8/src/compiler/code-assembler.cc index 5b89e1b663e8b2..c618daf357ea53 100644 --- a/deps/v8/src/compiler/code-assembler.cc +++ b/deps/v8/src/compiler/code-assembler.cc @@ -1439,6 +1439,13 @@ Node* CodeAssembler::CallCFunction( return raw_assembler()->CallCFunction(function, return_type, args); } +Node* CodeAssembler::CallCFunctionWithoutFunctionDescriptor( + Node* function, MachineType return_type, + std::initializer_list args) { + return raw_assembler()->CallCFunctionWithoutFunctionDescriptor( + function, return_type, args); +} + Node* CodeAssembler::CallCFunctionWithCallerSavedRegisters( Node* function, MachineType return_type, SaveFPRegsMode mode, std::initializer_list args) { diff --git a/deps/v8/src/compiler/code-assembler.h b/deps/v8/src/compiler/code-assembler.h index 036b00b14d8708..8d5b8602854468 100644 --- a/deps/v8/src/compiler/code-assembler.h +++ b/deps/v8/src/compiler/code-assembler.h @@ -1103,6 +1103,18 @@ class V8_EXPORT_PRIVATE CodeAssembler { return CallCFunction(function, return_type, {cargs...}); } + // Call to a C function without a function discriptor on AIX. + template + Node* CallCFunctionWithoutFunctionDescriptor(Node* function, + MachineType return_type, + CArgs... cargs) { + static_assert(v8::internal::conjunction< + std::is_convertible...>::value, + "invalid argument types"); + return CallCFunctionWithoutFunctionDescriptor(function, return_type, + {cargs...}); + } + // Call to a C function, while saving/restoring caller registers. template Node* CallCFunctionWithCallerSavedRegisters(Node* function, @@ -1151,6 +1163,10 @@ class V8_EXPORT_PRIVATE CodeAssembler { Node* CallCFunction(Node* function, MachineType return_type, std::initializer_list args); + Node* CallCFunctionWithoutFunctionDescriptor( + Node* function, MachineType return_type, + std::initializer_list args); + Node* CallCFunctionWithCallerSavedRegisters( Node* function, MachineType return_type, SaveFPRegsMode mode, std::initializer_list args); diff --git a/deps/v8/src/compiler/linkage.h b/deps/v8/src/compiler/linkage.h index 69e7fbfa427fb8..5458d1eb6f6924 100644 --- a/deps/v8/src/compiler/linkage.h +++ b/deps/v8/src/compiler/linkage.h @@ -352,9 +352,18 @@ class V8_EXPORT_PRIVATE CallDescriptor final SaveFPRegsMode get_save_fp_mode() const { return save_fp_mode_; } + void set_has_function_descriptor(bool has_function_descriptor) { + has_function_descriptor_ = has_function_descriptor; + } + + bool HasFunctionDescriptor() const { return has_function_descriptor_; } + private: friend class Linkage; SaveFPRegsMode save_fp_mode_ = kSaveFPRegs; + // AIX has a function descriptor which we will set to true by default + // for all CFunction Calls. + bool has_function_descriptor_ = kHasFunctionDescriptor; const Kind kind_; const MachineType target_type_; diff --git a/deps/v8/src/compiler/raw-machine-assembler.cc b/deps/v8/src/compiler/raw-machine-assembler.cc index c709729081cb9f..7031437cc20bd7 100644 --- a/deps/v8/src/compiler/raw-machine-assembler.cc +++ b/deps/v8/src/compiler/raw-machine-assembler.cc @@ -705,7 +705,8 @@ namespace { Node* CallCFunctionImpl( RawMachineAssembler* rasm, Node* function, MachineType return_type, std::initializer_list args, - bool caller_saved_regs, SaveFPRegsMode mode) { + bool caller_saved_regs, SaveFPRegsMode mode, + bool has_function_descriptor = kHasFunctionDescriptor) { static constexpr std::size_t kNumCArgs = 10; MachineSignature::Builder builder(rasm->zone(), 1, args.size()); @@ -719,6 +720,8 @@ Node* CallCFunctionImpl( if (caller_saved_regs) call_descriptor->set_save_fp_mode(mode); + call_descriptor->set_has_function_descriptor(has_function_descriptor); + base::SmallVector nodes(args.size() + 1); nodes[0] = function; std::transform( @@ -739,6 +742,13 @@ Node* RawMachineAssembler::CallCFunction( kDontSaveFPRegs); } +Node* RawMachineAssembler::CallCFunctionWithoutFunctionDescriptor( + Node* function, MachineType return_type, + std::initializer_list args) { + return CallCFunctionImpl(this, function, return_type, args, false, + kDontSaveFPRegs, kNoFunctionDescriptor); +} + Node* RawMachineAssembler::CallCFunctionWithCallerSavedRegisters( Node* function, MachineType return_type, SaveFPRegsMode mode, std::initializer_list args) { diff --git a/deps/v8/src/compiler/raw-machine-assembler.h b/deps/v8/src/compiler/raw-machine-assembler.h index cbbb719d54da80..c0bfd84a617a6f 100644 --- a/deps/v8/src/compiler/raw-machine-assembler.h +++ b/deps/v8/src/compiler/raw-machine-assembler.h @@ -983,6 +983,22 @@ class V8_EXPORT_PRIVATE RawMachineAssembler { Node* CallCFunction(Node* function, MachineType return_type, std::initializer_list args); + // Call to a C function without a function discriptor on AIX. + template + Node* CallCFunctionWithoutFunctionDescriptor(Node* function, + MachineType return_type, + CArgs... cargs) { + static_assert(v8::internal::conjunction< + std::is_convertible...>::value, + "invalid argument types"); + return CallCFunctionWithoutFunctionDescriptor(function, return_type, + {cargs...}); + } + + Node* CallCFunctionWithoutFunctionDescriptor( + Node* function, MachineType return_type, + std::initializer_list args); + // Call to a C function, while saving/restoring caller registers. template Node* CallCFunctionWithCallerSavedRegisters(Node* function, diff --git a/deps/v8/src/execution/simulator.h b/deps/v8/src/execution/simulator.h index 9c5cae7e9710b6..4000973a24397d 100644 --- a/deps/v8/src/execution/simulator.h +++ b/deps/v8/src/execution/simulator.h @@ -121,13 +121,6 @@ class GeneratedCode { return Simulator::current(isolate_)->template Call( reinterpret_cast
(fn_ptr_), args...); } - - DISABLE_CFI_ICALL Return CallIrregexp(Args... args) { -#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) - FATAL("Generated code execution not possible during cross-compilation."); -#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) - return Call(args...); - } #else DISABLE_CFI_ICALL Return Call(Args... args) { @@ -149,14 +142,6 @@ class GeneratedCode { return fn_ptr_(args...); #endif // V8_OS_AIX } - - DISABLE_CFI_ICALL Return CallIrregexp(Args... args) { - // When running without a simulator we call the entry directly. -#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) - FATAL("Generated code execution not possible during cross-compilation."); -#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) - return fn_ptr_(args...); - } #endif // USE_SIMULATOR private: diff --git a/deps/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc b/deps/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc index 8babb204dd10ba..a7f372ada5f0ef 100644 --- a/deps/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc +++ b/deps/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc @@ -113,8 +113,6 @@ RegExpMacroAssemblerPPC::RegExpMacroAssemblerPPC(Isolate* isolate, Zone* zone, internal_failure_label_() { DCHECK_EQ(0, registers_to_save % 2); - // Because RegExp code respects C ABI, so needs a FD - __ function_descriptor(); __ b(&entry_label_); // We'll write the entry code later. // If the code gets too big or corrupted, an internal exception will be diff --git a/deps/v8/src/regexp/regexp-macro-assembler.cc b/deps/v8/src/regexp/regexp-macro-assembler.cc index 96fb53d2a0464c..30a9955dc38983 100644 --- a/deps/v8/src/regexp/regexp-macro-assembler.cc +++ b/deps/v8/src/regexp/regexp-macro-assembler.cc @@ -289,9 +289,9 @@ int NativeRegExpMacroAssembler::Execute( Address regexp); auto fn = GeneratedCode::FromCode(code); - int result = fn.CallIrregexp(input.ptr(), start_offset, input_start, - input_end, output, output_size, stack_base, - call_origin, isolate, regexp.ptr()); + int result = + fn.Call(input.ptr(), start_offset, input_start, input_end, output, + output_size, stack_base, call_origin, isolate, regexp.ptr()); DCHECK(result >= RETRY); if (result == EXCEPTION && !isolate->has_pending_exception()) {