Skip to content

Commit fe99841

Browse files
targosMylesBorins
authored andcommitted
deps: V8: backport 07ee86a5a28b
Original commit message: PPC: allow for calling CFunctions without function descriptors on AIX. The calling conventions on AIX uses function descriptors, which means that pointers to functions do not point to code, but instead point to metadata about them. When calling JITed code, we must assure to use function descriptors instead of raw pointers when needed. Before this CL 213504b, all CallCFunction on AIX were guaranteed to have function descriptors. Starting form the CL mentioned above, CallCFunction can also Jump to a Trampoline which does not have a function descriptor, hence a new "CallCFunctionWithoutFunctionDescriptor" method is proposed to deal with this issue. BUG= v8:9766 Change-Id: I9343c31c812f5d4dda8503a5adf024b24dbde072 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1825961 Commit-Queue: Milad Farazmand <[email protected]> Reviewed-by: Michael Starzinger <[email protected]> Reviewed-by: Jakob Gruber <[email protected]> Cr-Commit-Position: refs/heads/master@{#64357} Refs: v8/v8@07ee86a Backport-PR-URL: #30513 PR-URL: #30020 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Jiawen Geng <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 5131bbe commit fe99841

19 files changed

+138
-68
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
# Reset this number to 0 on major V8 upgrades.
4141
# Increment by one for each non-official patch applied to deps/v8.
42-
'v8_embedder_string': '-node.15',
42+
'v8_embedder_string': '-node.16',
4343

4444
##### V8 defaults for Node.js #####
4545

deps/v8/src/builtins/builtins-regexp-gen.cc

+12-7
Original file line numberDiff line numberDiff line change
@@ -605,13 +605,18 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal(
605605

606606
TNode<RawPtrT> code_entry = LoadCodeObjectEntry(code);
607607

608-
TNode<Int32T> result = UncheckedCast<Int32T>(CallCFunction(
609-
code_entry, retval_type, std::make_pair(arg0_type, arg0),
610-
std::make_pair(arg1_type, arg1), std::make_pair(arg2_type, arg2),
611-
std::make_pair(arg3_type, arg3), std::make_pair(arg4_type, arg4),
612-
std::make_pair(arg5_type, arg5), std::make_pair(arg6_type, arg6),
613-
std::make_pair(arg7_type, arg7), std::make_pair(arg8_type, arg8),
614-
std::make_pair(arg9_type, arg9)));
608+
// AIX uses function descriptors on CFunction calls. code_entry in this case
609+
// may also point to a Regex interpreter entry trampoline which does not
610+
// have a function descriptor. This method is ineffective on other platforms
611+
// and is equivalent to CallCFunction.
612+
TNode<Int32T> result =
613+
UncheckedCast<Int32T>(CallCFunctionWithoutFunctionDescriptor(
614+
code_entry, retval_type, std::make_pair(arg0_type, arg0),
615+
std::make_pair(arg1_type, arg1), std::make_pair(arg2_type, arg2),
616+
std::make_pair(arg3_type, arg3), std::make_pair(arg4_type, arg4),
617+
std::make_pair(arg5_type, arg5), std::make_pair(arg6_type, arg6),
618+
std::make_pair(arg7_type, arg7), std::make_pair(arg8_type, arg8),
619+
std::make_pair(arg9_type, arg9)));
615620

616621
// Check the result.
617622
// We expect exactly one result since we force the called regexp to behave

deps/v8/src/codegen/ppc/assembler-ppc.cc

-14
Original file line numberDiff line numberDiff line change
@@ -1121,20 +1121,6 @@ void Assembler::divdu(Register dst, Register src1, Register src2, OEBit o,
11211121
}
11221122
#endif
11231123

1124-
// Function descriptor for AIX.
1125-
// Code address skips the function descriptor "header".
1126-
// TOC and static chain are ignored and set to 0.
1127-
void Assembler::function_descriptor() {
1128-
if (ABI_USES_FUNCTION_DESCRIPTORS) {
1129-
Label instructions;
1130-
DCHECK_EQ(pc_offset(), 0);
1131-
emit_label_addr(&instructions);
1132-
dp(0);
1133-
dp(0);
1134-
bind(&instructions);
1135-
}
1136-
}
1137-
11381124
int Assembler::instructions_required_for_mov(Register dst,
11391125
const Operand& src) const {
11401126
bool canOptimize =

deps/v8/src/codegen/ppc/assembler-ppc.h

-2
Original file line numberDiff line numberDiff line change
@@ -840,8 +840,6 @@ class Assembler : public AssemblerBase {
840840
void mtfprwa(DoubleRegister dst, Register src);
841841
#endif
842842

843-
void function_descriptor();
844-
845843
// Exception-generating instructions and debugging support
846844
void stop(Condition cond = al, int32_t code = kDefaultStopCode,
847845
CRegister cr = cr7);

deps/v8/src/codegen/ppc/constants-ppc.h

+6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ namespace internal {
6060
// TODO(sigurds): Change this value once we use relative jumps.
6161
constexpr size_t kMaxPCRelativeCodeRangeInMB = 0;
6262

63+
// Used to encode a boolean value when emitting 32 bit
64+
// opcodes which will indicate the presence of function descriptors
65+
constexpr int kHasFunctionDescriptorBitShift = 9;
66+
constexpr int kHasFunctionDescriptorBitMask = 1
67+
<< kHasFunctionDescriptorBitShift;
68+
6369
// Number of registers
6470
const int kNumRegisters = 32;
6571

deps/v8/src/codegen/ppc/macro-assembler-ppc.cc

+23-10
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ void TurboAssembler::Jump(const ExternalReference& reference) {
209209
UseScratchRegisterScope temps(this);
210210
Register scratch = temps.Acquire();
211211
Move(scratch, reference);
212+
if (ABI_USES_FUNCTION_DESCRIPTORS) {
213+
// AIX uses a function descriptor. When calling C code be
214+
// aware of this descriptor and pick up values from it.
215+
LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(scratch, kPointerSize));
216+
LoadP(scratch, MemOperand(scratch, 0));
217+
}
212218
Jump(scratch);
213219
}
214220

@@ -1930,28 +1936,35 @@ void TurboAssembler::MovToFloatParameters(DoubleRegister src1,
19301936

19311937
void TurboAssembler::CallCFunction(ExternalReference function,
19321938
int num_reg_arguments,
1933-
int num_double_arguments) {
1939+
int num_double_arguments,
1940+
bool has_function_descriptor) {
19341941
Move(ip, function);
1935-
CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments);
1942+
CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments,
1943+
has_function_descriptor);
19361944
}
19371945

19381946
void TurboAssembler::CallCFunction(Register function, int num_reg_arguments,
1939-
int num_double_arguments) {
1940-
CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
1947+
int num_double_arguments,
1948+
bool has_function_descriptor) {
1949+
CallCFunctionHelper(function, num_reg_arguments, num_double_arguments,
1950+
has_function_descriptor);
19411951
}
19421952

19431953
void TurboAssembler::CallCFunction(ExternalReference function,
1944-
int num_arguments) {
1945-
CallCFunction(function, num_arguments, 0);
1954+
int num_arguments,
1955+
bool has_function_descriptor) {
1956+
CallCFunction(function, num_arguments, 0, has_function_descriptor);
19461957
}
19471958

1948-
void TurboAssembler::CallCFunction(Register function, int num_arguments) {
1949-
CallCFunction(function, num_arguments, 0);
1959+
void TurboAssembler::CallCFunction(Register function, int num_arguments,
1960+
bool has_function_descriptor) {
1961+
CallCFunction(function, num_arguments, 0, has_function_descriptor);
19501962
}
19511963

19521964
void TurboAssembler::CallCFunctionHelper(Register function,
19531965
int num_reg_arguments,
1954-
int num_double_arguments) {
1966+
int num_double_arguments,
1967+
bool has_function_descriptor) {
19551968
DCHECK_LE(num_reg_arguments + num_double_arguments, kMaxCParameters);
19561969
DCHECK(has_frame());
19571970

@@ -1976,7 +1989,7 @@ void TurboAssembler::CallCFunctionHelper(Register function,
19761989
// allow preemption, so the return address in the link register
19771990
// stays correct.
19781991
Register dest = function;
1979-
if (ABI_USES_FUNCTION_DESCRIPTORS) {
1992+
if (ABI_USES_FUNCTION_DESCRIPTORS && has_function_descriptor) {
19801993
// AIX/PPC64BE Linux uses a function descriptor. When calling C code be
19811994
// aware of this descriptor and pick up values from it
19821995
LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(function, kPointerSize));

deps/v8/src/codegen/ppc/macro-assembler-ppc.h

+10-5
Original file line numberDiff line numberDiff line change
@@ -350,12 +350,16 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
350350
// garbage collection, since that might move the code and invalidate the
351351
// return address (unless this is somehow accounted for by the called
352352
// function).
353-
void CallCFunction(ExternalReference function, int num_arguments);
354-
void CallCFunction(Register function, int num_arguments);
353+
void CallCFunction(ExternalReference function, int num_arguments,
354+
bool has_function_descriptor = kHasFunctionDescriptor);
355+
void CallCFunction(Register function, int num_arguments,
356+
bool has_function_descriptor = kHasFunctionDescriptor);
355357
void CallCFunction(ExternalReference function, int num_reg_arguments,
356-
int num_double_arguments);
358+
int num_double_arguments,
359+
bool has_function_descriptor = kHasFunctionDescriptor);
357360
void CallCFunction(Register function, int num_reg_arguments,
358-
int num_double_arguments);
361+
int num_double_arguments,
362+
bool has_function_descriptor = kHasFunctionDescriptor);
359363

360364
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
361365
// builtin for the target runtime function and uses an indirect call.
@@ -642,7 +646,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
642646
int CalculateStackPassedWords(int num_reg_arguments,
643647
int num_double_arguments);
644648
void CallCFunctionHelper(Register function, int num_reg_arguments,
645-
int num_double_arguments);
649+
int num_double_arguments,
650+
bool has_function_descriptor);
646651
void CallRecordWriteStub(Register object, Register address,
647652
RememberedSetAction remembered_set_action,
648653
SaveFPRegsMode fp_mode, Handle<Code> code_target,

deps/v8/src/common/globals.h

+1
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
400400
// Enums used by CEntry.
401401
enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
402402
enum ArgvMode { kArgvOnStack, kArgvInRegister };
403+
enum FunctionDescriptorMode { kNoFunctionDescriptor, kHasFunctionDescriptor };
403404

404405
// This constant is used as an undefined value when passing source positions.
405406
constexpr int kNoSourcePosition = -1;

deps/v8/src/compiler/backend/instruction-selector.cc

+10-3
Original file line numberDiff line numberDiff line change
@@ -2810,10 +2810,17 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
28102810
// Select the appropriate opcode based on the call type.
28112811
InstructionCode opcode = kArchNop;
28122812
switch (call_descriptor->kind()) {
2813-
case CallDescriptor::kCallAddress:
2814-
opcode = kArchCallCFunction | MiscField::encode(static_cast<int>(
2815-
call_descriptor->ParameterCount()));
2813+
case CallDescriptor::kCallAddress: {
2814+
int misc_field = static_cast<int>(call_descriptor->ParameterCount());
2815+
#if defined(_AIX)
2816+
// Highest misc_field bit is used on AIX to indicate if a CFunction call
2817+
// has function descriptor or not.
2818+
misc_field |= call_descriptor->HasFunctionDescriptor()
2819+
<< kHasFunctionDescriptorBitShift;
2820+
#endif
2821+
opcode = kArchCallCFunction | MiscField::encode(misc_field);
28162822
break;
2823+
}
28172824
case CallDescriptor::kCallCodeObject:
28182825
opcode = kArchCallCodeObject | MiscField::encode(flags);
28192826
break;

deps/v8/src/compiler/backend/instruction.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,8 @@ class V8_EXPORT_PRIVATE Instruction final {
807807
size_t output_count, InstructionOperand* outputs,
808808
size_t input_count, InstructionOperand* inputs,
809809
size_t temp_count, InstructionOperand* temps) {
810-
DCHECK_LE(0, opcode);
810+
// TODO(9872)
811+
// DCHECK_LE(0, opcode);
811812
DCHECK(output_count == 0 || outputs != nullptr);
812813
DCHECK(input_count == 0 || inputs != nullptr);
813814
DCHECK(temp_count == 0 || temps != nullptr);

deps/v8/src/compiler/backend/ppc/code-generator-ppc.cc

+11-4
Original file line numberDiff line numberDiff line change
@@ -1019,13 +1019,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
10191019
#endif
10201020
break;
10211021
case kArchCallCFunction: {
1022-
int const num_parameters = MiscField::decode(instr->opcode());
1022+
int misc_field = MiscField::decode(instr->opcode());
1023+
int num_parameters = misc_field;
1024+
bool has_function_descriptor = false;
10231025
Label start_call;
10241026
bool isWasmCapiFunction =
10251027
linkage()->GetIncomingDescriptor()->IsWasmCapiFunction();
10261028
#if defined(_AIX)
10271029
// AIX/PPC64BE Linux uses a function descriptor
1028-
// and emits 2 extra Load instrcutions under CallCFunctionHelper.
1030+
int kNumParametersMask = kHasFunctionDescriptorBitMask - 1;
1031+
num_parameters = kNumParametersMask & misc_field;
1032+
has_function_descriptor =
1033+
(misc_field & kHasFunctionDescriptorBitMask) != 0;
1034+
// AIX emits 2 extra Load instructions under CallCFunctionHelper
1035+
// due to having function descriptor.
10291036
constexpr int offset = 11 * kInstrSize;
10301037
#else
10311038
constexpr int offset = 9 * kInstrSize;
@@ -1041,10 +1048,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
10411048
}
10421049
if (instr->InputAt(0)->IsImmediate()) {
10431050
ExternalReference ref = i.InputExternalReference(0);
1044-
__ CallCFunction(ref, num_parameters);
1051+
__ CallCFunction(ref, num_parameters, has_function_descriptor);
10451052
} else {
10461053
Register func = i.InputRegister(0);
1047-
__ CallCFunction(func, num_parameters);
1054+
__ CallCFunction(func, num_parameters, has_function_descriptor);
10481055
}
10491056
// TODO(miladfar): In the above block, kScratchReg must be populated with
10501057
// the strictly-correct PC, which is the return address at this spot. The

deps/v8/src/compiler/code-assembler.cc

+7
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,13 @@ Node* CodeAssembler::CallCFunction(
14391439
return raw_assembler()->CallCFunction(function, return_type, args);
14401440
}
14411441

1442+
Node* CodeAssembler::CallCFunctionWithoutFunctionDescriptor(
1443+
Node* function, MachineType return_type,
1444+
std::initializer_list<CodeAssembler::CFunctionArg> args) {
1445+
return raw_assembler()->CallCFunctionWithoutFunctionDescriptor(
1446+
function, return_type, args);
1447+
}
1448+
14421449
Node* CodeAssembler::CallCFunctionWithCallerSavedRegisters(
14431450
Node* function, MachineType return_type, SaveFPRegsMode mode,
14441451
std::initializer_list<CodeAssembler::CFunctionArg> args) {

deps/v8/src/compiler/code-assembler.h

+16
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,18 @@ class V8_EXPORT_PRIVATE CodeAssembler {
11031103
return CallCFunction(function, return_type, {cargs...});
11041104
}
11051105

1106+
// Call to a C function without a function discriptor on AIX.
1107+
template <class... CArgs>
1108+
Node* CallCFunctionWithoutFunctionDescriptor(Node* function,
1109+
MachineType return_type,
1110+
CArgs... cargs) {
1111+
static_assert(v8::internal::conjunction<
1112+
std::is_convertible<CArgs, CFunctionArg>...>::value,
1113+
"invalid argument types");
1114+
return CallCFunctionWithoutFunctionDescriptor(function, return_type,
1115+
{cargs...});
1116+
}
1117+
11061118
// Call to a C function, while saving/restoring caller registers.
11071119
template <class... CArgs>
11081120
Node* CallCFunctionWithCallerSavedRegisters(Node* function,
@@ -1151,6 +1163,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
11511163
Node* CallCFunction(Node* function, MachineType return_type,
11521164
std::initializer_list<CFunctionArg> args);
11531165

1166+
Node* CallCFunctionWithoutFunctionDescriptor(
1167+
Node* function, MachineType return_type,
1168+
std::initializer_list<CFunctionArg> args);
1169+
11541170
Node* CallCFunctionWithCallerSavedRegisters(
11551171
Node* function, MachineType return_type, SaveFPRegsMode mode,
11561172
std::initializer_list<CFunctionArg> args);

deps/v8/src/compiler/linkage.h

+9
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,18 @@ class V8_EXPORT_PRIVATE CallDescriptor final
352352

353353
SaveFPRegsMode get_save_fp_mode() const { return save_fp_mode_; }
354354

355+
void set_has_function_descriptor(bool has_function_descriptor) {
356+
has_function_descriptor_ = has_function_descriptor;
357+
}
358+
359+
bool HasFunctionDescriptor() const { return has_function_descriptor_; }
360+
355361
private:
356362
friend class Linkage;
357363
SaveFPRegsMode save_fp_mode_ = kSaveFPRegs;
364+
// AIX has a function descriptor which we will set to true by default
365+
// for all CFunction Calls.
366+
bool has_function_descriptor_ = kHasFunctionDescriptor;
358367

359368
const Kind kind_;
360369
const MachineType target_type_;

deps/v8/src/compiler/raw-machine-assembler.cc

+11-1
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,8 @@ namespace {
705705
Node* CallCFunctionImpl(
706706
RawMachineAssembler* rasm, Node* function, MachineType return_type,
707707
std::initializer_list<RawMachineAssembler::CFunctionArg> args,
708-
bool caller_saved_regs, SaveFPRegsMode mode) {
708+
bool caller_saved_regs, SaveFPRegsMode mode,
709+
bool has_function_descriptor = kHasFunctionDescriptor) {
709710
static constexpr std::size_t kNumCArgs = 10;
710711

711712
MachineSignature::Builder builder(rasm->zone(), 1, args.size());
@@ -719,6 +720,8 @@ Node* CallCFunctionImpl(
719720

720721
if (caller_saved_regs) call_descriptor->set_save_fp_mode(mode);
721722

723+
call_descriptor->set_has_function_descriptor(has_function_descriptor);
724+
722725
base::SmallVector<Node*, kNumCArgs> nodes(args.size() + 1);
723726
nodes[0] = function;
724727
std::transform(
@@ -739,6 +742,13 @@ Node* RawMachineAssembler::CallCFunction(
739742
kDontSaveFPRegs);
740743
}
741744

745+
Node* RawMachineAssembler::CallCFunctionWithoutFunctionDescriptor(
746+
Node* function, MachineType return_type,
747+
std::initializer_list<RawMachineAssembler::CFunctionArg> args) {
748+
return CallCFunctionImpl(this, function, return_type, args, false,
749+
kDontSaveFPRegs, kNoFunctionDescriptor);
750+
}
751+
742752
Node* RawMachineAssembler::CallCFunctionWithCallerSavedRegisters(
743753
Node* function, MachineType return_type, SaveFPRegsMode mode,
744754
std::initializer_list<RawMachineAssembler::CFunctionArg> args) {

deps/v8/src/compiler/raw-machine-assembler.h

+16
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,22 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
983983
Node* CallCFunction(Node* function, MachineType return_type,
984984
std::initializer_list<CFunctionArg> args);
985985

986+
// Call to a C function without a function discriptor on AIX.
987+
template <class... CArgs>
988+
Node* CallCFunctionWithoutFunctionDescriptor(Node* function,
989+
MachineType return_type,
990+
CArgs... cargs) {
991+
static_assert(v8::internal::conjunction<
992+
std::is_convertible<CArgs, CFunctionArg>...>::value,
993+
"invalid argument types");
994+
return CallCFunctionWithoutFunctionDescriptor(function, return_type,
995+
{cargs...});
996+
}
997+
998+
Node* CallCFunctionWithoutFunctionDescriptor(
999+
Node* function, MachineType return_type,
1000+
std::initializer_list<CFunctionArg> args);
1001+
9861002
// Call to a C function, while saving/restoring caller registers.
9871003
template <class... CArgs>
9881004
Node* CallCFunctionWithCallerSavedRegisters(Node* function,

deps/v8/src/execution/simulator.h

-15
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,6 @@ class GeneratedCode {
121121
return Simulator::current(isolate_)->template Call<Return>(
122122
reinterpret_cast<Address>(fn_ptr_), args...);
123123
}
124-
125-
DISABLE_CFI_ICALL Return CallIrregexp(Args... args) {
126-
#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
127-
FATAL("Generated code execution not possible during cross-compilation.");
128-
#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
129-
return Call(args...);
130-
}
131124
#else
132125

133126
DISABLE_CFI_ICALL Return Call(Args... args) {
@@ -149,14 +142,6 @@ class GeneratedCode {
149142
return fn_ptr_(args...);
150143
#endif // V8_OS_AIX
151144
}
152-
153-
DISABLE_CFI_ICALL Return CallIrregexp(Args... args) {
154-
// When running without a simulator we call the entry directly.
155-
#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
156-
FATAL("Generated code execution not possible during cross-compilation.");
157-
#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
158-
return fn_ptr_(args...);
159-
}
160145
#endif // USE_SIMULATOR
161146

162147
private:

0 commit comments

Comments
 (0)