Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v12.x] deps: V8: backport 07ee86a5a28b #32619

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -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.33',
'v8_embedder_string': '-node.34',

##### V8 defaults for Node.js #####

Expand Down
19 changes: 12 additions & 7 deletions deps/v8/src/builtins/builtins-regexp-gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -603,13 +603,18 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal(

TNode<RawPtrT> code_entry = LoadCodeObjectEntry(code);

TNode<Int32T> result = UncheckedCast<Int32T>(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<Int32T> result =
UncheckedCast<Int32T>(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
Expand Down
14 changes: 0 additions & 14 deletions deps/v8/src/codegen/ppc/assembler-ppc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
2 changes: 0 additions & 2 deletions deps/v8/src/codegen/ppc/assembler-ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -839,8 +839,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);
Expand Down
6 changes: 6 additions & 0 deletions deps/v8/src/codegen/ppc/constants-ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
33 changes: 23 additions & 10 deletions deps/v8/src/codegen/ppc/macro-assembler-ppc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -1931,28 +1937,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());

Expand All @@ -1977,7 +1990,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));
Expand Down
15 changes: 10 additions & 5 deletions deps/v8/src/codegen/ppc/macro-assembler-ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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> code_target,
Expand Down
1 change: 1 addition & 0 deletions deps/v8/src/common/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,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 };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this have been enum FunctionDescriptorMode : bool { /* ... */ }, or (probably more idiomatic for V8) use the enum instead of bool? Relying on int-to-bool coercion looks a bit footgunny.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing they were ok with it as it's following the previous enums SaveFPRegsMode and ArgvMode.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but those are of type SaveFPRegsMode and ArgvMode in function parameter lists, there's no coercion to bool taking place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's right however the int value 0 (kNoFunctionDescriptor) is implicitly translating to false at all cases, and true otherwise. You're right that marking it as bool could have made it more clear.


// This constant is used as an undefined value when passing source positions.
constexpr int kNoSourcePosition = -1;
Expand Down
13 changes: 10 additions & 3 deletions deps/v8/src/compiler/backend/instruction-selector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2786,10 +2786,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<int>(
call_descriptor->ParameterCount()));
case CallDescriptor::kCallAddress: {
int misc_field = static_cast<int>(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;
Expand Down
3 changes: 2 additions & 1 deletion deps/v8/src/compiler/backend/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,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);
Expand Down
15 changes: 12 additions & 3 deletions deps/v8/src/compiler/backend/ppc/code-generator-ppc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1020,10 +1020,19 @@ 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
int kNumParametersMask = kHasFunctionDescriptorBitMask - 1;
num_parameters = kNumParametersMask & misc_field;
has_function_descriptor =
(misc_field & kHasFunctionDescriptorBitMask) != 0;
#else
constexpr int offset = 9 * kInstrSize;
if (isWasmCapiFunction) {
__ mflr(r0);
Expand All @@ -1036,10 +1045,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
Expand Down
7 changes: 7 additions & 0 deletions deps/v8/src/compiler/code-assembler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<CodeAssembler::CFunctionArg> args) {
return raw_assembler()->CallCFunctionWithoutFunctionDescriptor(
function, return_type, args);
}

Node* CodeAssembler::CallCFunctionWithCallerSavedRegisters(
Node* function, MachineType return_type, SaveFPRegsMode mode,
std::initializer_list<CodeAssembler::CFunctionArg> args) {
Expand Down
16 changes: 16 additions & 0 deletions deps/v8/src/compiler/code-assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,18 @@ class V8_EXPORT_PRIVATE CodeAssembler {
return CallCFunction(function, return_type, {cargs...});
}

// Call to a C function without a function discriptor on AIX.
template <class... CArgs>
Node* CallCFunctionWithoutFunctionDescriptor(Node* function,
MachineType return_type,
CArgs... cargs) {
static_assert(v8::internal::conjunction<
std::is_convertible<CArgs, CFunctionArg>...>::value,
"invalid argument types");
return CallCFunctionWithoutFunctionDescriptor(function, return_type,
{cargs...});
}

// Call to a C function, while saving/restoring caller registers.
template <class... CArgs>
Node* CallCFunctionWithCallerSavedRegisters(Node* function,
Expand Down Expand Up @@ -1486,6 +1498,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
Node* CallCFunction(Node* function, MachineType return_type,
std::initializer_list<CFunctionArg> args);

Node* CallCFunctionWithoutFunctionDescriptor(
Node* function, MachineType return_type,
std::initializer_list<CFunctionArg> args);

Node* CallCFunctionWithCallerSavedRegisters(
Node* function, MachineType return_type, SaveFPRegsMode mode,
std::initializer_list<CFunctionArg> args);
Expand Down
9 changes: 9 additions & 0 deletions deps/v8/src/compiler/linkage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down
12 changes: 11 additions & 1 deletion deps/v8/src/compiler/raw-machine-assembler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,8 @@ namespace {
Node* CallCFunctionImpl(
RawMachineAssembler* rasm, Node* function, MachineType return_type,
std::initializer_list<RawMachineAssembler::CFunctionArg> 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());
Expand All @@ -720,6 +721,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<Node*, kNumCArgs> nodes(args.size() + 1);
nodes[0] = function;
std::transform(
Expand All @@ -740,6 +743,13 @@ Node* RawMachineAssembler::CallCFunction(
kDontSaveFPRegs);
}

Node* RawMachineAssembler::CallCFunctionWithoutFunctionDescriptor(
Node* function, MachineType return_type,
std::initializer_list<RawMachineAssembler::CFunctionArg> args) {
return CallCFunctionImpl(this, function, return_type, args, false,
kDontSaveFPRegs, kNoFunctionDescriptor);
}

Node* RawMachineAssembler::CallCFunctionWithCallerSavedRegisters(
Node* function, MachineType return_type, SaveFPRegsMode mode,
std::initializer_list<RawMachineAssembler::CFunctionArg> args) {
Expand Down
16 changes: 16 additions & 0 deletions deps/v8/src/compiler/raw-machine-assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,22 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
Node* CallCFunction(Node* function, MachineType return_type,
std::initializer_list<CFunctionArg> args);

// Call to a C function without a function discriptor on AIX.
template <class... CArgs>
Node* CallCFunctionWithoutFunctionDescriptor(Node* function,
MachineType return_type,
CArgs... cargs) {
static_assert(v8::internal::conjunction<
std::is_convertible<CArgs, CFunctionArg>...>::value,
"invalid argument types");
return CallCFunctionWithoutFunctionDescriptor(function, return_type,
{cargs...});
}

Node* CallCFunctionWithoutFunctionDescriptor(
Node* function, MachineType return_type,
std::initializer_list<CFunctionArg> args);

// Call to a C function, while saving/restoring caller registers.
template <class... CArgs>
Node* CallCFunctionWithCallerSavedRegisters(Node* function,
Expand Down
7 changes: 0 additions & 7 deletions deps/v8/src/execution/simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ class GeneratedCode {
return Simulator::current(isolate_)->template Call<Return>(
reinterpret_cast<Address>(fn_ptr_), args...);
}

DISABLE_CFI_ICALL Return CallIrregexp(Args... args) { return Call(args...); }
#else

DISABLE_CFI_ICALL Return Call(Args... args) {
Expand All @@ -138,11 +136,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.
return fn_ptr_(args...);
}
#endif // USE_SIMULATOR

private:
Expand Down
2 changes: 0 additions & 2 deletions deps/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,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
Expand Down
Loading