Commit c1d06eb3 authored by Victor Gomes's avatar Victor Gomes Committed by Commit Bot

[compiler] Fix extra arguments position when reversed stack

When the interface descriptor of a builtin uses DEFINE_JS_PARAMETERS, the extra stack arguments must be positioned just above the return address, otherwise we would need to calculate its offset depending on the actual number of the arguments, we currently use a fixed offset to access them in CSA.

Therefore, these extra arguments are either the first arguments when V8_REVERSE_JSARGS is enabled or otherwise the last arguments.

Change-Id: If38ac7fd7f0079fc0e4fdccdb6cfb26e0425eb84
Bug: v8:10825
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2379854Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69714}
parent 0017c7bb
...@@ -608,6 +608,7 @@ extern macro CodeStubAssembler::AllocateNameDictionary(constexpr int32): ...@@ -608,6 +608,7 @@ extern macro CodeStubAssembler::AllocateNameDictionary(constexpr int32):
extern builtin ToObject(Context, JSAny): JSReceiver; extern builtin ToObject(Context, JSAny): JSReceiver;
extern macro ToObject_Inline(Context, JSAny): JSReceiver; extern macro ToObject_Inline(Context, JSAny): JSReceiver;
extern macro IsUndefined(Object): bool;
extern macro IsNullOrUndefined(Object): bool; extern macro IsNullOrUndefined(Object): bool;
extern macro IsString(HeapObject): bool; extern macro IsString(HeapObject): bool;
extern macro IsSeqOneByteString(HeapObject): bool; extern macro IsSeqOneByteString(HeapObject): bool;
......
...@@ -53,6 +53,12 @@ macro TransitionToMegamorphic(implicit context: Context)( ...@@ -53,6 +53,12 @@ macro TransitionToMegamorphic(implicit context: Context)(
macro CollectCallFeedback( macro CollectCallFeedback(
maybeTarget: JSAny, context: Context, maybeTarget: JSAny, context: Context,
maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void { maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void {
// TODO(v8:9891): Remove this assert once all callers are ported to Torque.
// This assert ensures correctness of maybeFeedbackVector's type which can
// be easily broken for calls from CSA.
assert(
IsUndefined(maybeFeedbackVector) ||
Is<FeedbackVector>(maybeFeedbackVector));
const feedbackVector = const feedbackVector =
Cast<FeedbackVector>(maybeFeedbackVector) otherwise return; Cast<FeedbackVector>(maybeFeedbackVector) otherwise return;
IncrementCallCount(feedbackVector, slotId); IncrementCallCount(feedbackVector, slotId);
...@@ -97,6 +103,12 @@ macro CollectCallFeedback( ...@@ -97,6 +103,12 @@ macro CollectCallFeedback(
macro CollectInstanceOfFeedback( macro CollectInstanceOfFeedback(
maybeTarget: JSAny, context: Context, maybeTarget: JSAny, context: Context,
maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void { maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void {
// TODO(v8:9891): Remove this assert once all callers are ported to Torque.
// This assert ensures correctness of maybeFeedbackVector's type which can
// be easily broken for calls from CSA.
assert(
IsUndefined(maybeFeedbackVector) ||
Is<FeedbackVector>(maybeFeedbackVector));
const feedbackVector = const feedbackVector =
Cast<FeedbackVector>(maybeFeedbackVector) otherwise return; Cast<FeedbackVector>(maybeFeedbackVector) otherwise return;
// Note: The call count is not incremented. // Note: The call count is not incremented.
...@@ -134,6 +146,12 @@ macro CollectConstructFeedback(implicit context: Context)( ...@@ -134,6 +146,12 @@ macro CollectConstructFeedback(implicit context: Context)(
maybeFeedbackVector: Undefined|FeedbackVector, maybeFeedbackVector: Undefined|FeedbackVector,
slotId: uintptr): never labels ConstructGeneric, slotId: uintptr): never labels ConstructGeneric,
ConstructArray(AllocationSite) { ConstructArray(AllocationSite) {
// TODO(v8:9891): Remove this assert once all callers are ported to Torque.
// This assert ensures correctness of maybeFeedbackVector's type which can
// be easily broken for calls from CSA.
assert(
IsUndefined(maybeFeedbackVector) ||
Is<FeedbackVector>(maybeFeedbackVector));
const feedbackVector = Cast<FeedbackVector>(maybeFeedbackVector) const feedbackVector = Cast<FeedbackVector>(maybeFeedbackVector)
otherwise goto ConstructGeneric; otherwise goto ConstructGeneric;
IncrementCallCount(feedbackVector, slotId); IncrementCallCount(feedbackVector, slotId);
......
...@@ -14,11 +14,17 @@ extern runtime BytecodeBudgetInterruptFromCode(implicit context: Context)( ...@@ -14,11 +14,17 @@ extern runtime BytecodeBudgetInterruptFromCode(implicit context: Context)(
builtin GetTemplateObject( builtin GetTemplateObject(
context: Context, shared: SharedFunctionInfo, context: Context, shared: SharedFunctionInfo,
description: TemplateObjectDescription, slot: uintptr, description: TemplateObjectDescription, slot: uintptr,
maybeFeedbackVector: FeedbackVector|Undefined): JSArray { maybeFeedbackVector: Undefined|FeedbackVector): JSArray {
// TODO(jgruber): Consider merging with the GetTemplateObject bytecode // TODO(jgruber): Consider merging with the GetTemplateObject bytecode
// handler; the current advantage of the split implementation is that the // handler; the current advantage of the split implementation is that the
// bytecode can skip most work if feedback exists. // bytecode can skip most work if feedback exists.
// TODO(v8:9891): Remove this assert once all callers are ported to Torque.
// This assert ensures correctness of maybeFeedbackVector's type which can
// be easily broken for calls from CSA.
assert(
IsUndefined(maybeFeedbackVector) ||
Is<FeedbackVector>(maybeFeedbackVector));
try { try {
const vector = const vector =
Cast<FeedbackVector>(maybeFeedbackVector) otherwise CallRuntime; Cast<FeedbackVector>(maybeFeedbackVector) otherwise CallRuntime;
......
...@@ -50,9 +50,16 @@ extern builtin IterableToFixedArrayWithSymbolLookupSlow( ...@@ -50,9 +50,16 @@ extern builtin IterableToFixedArrayWithSymbolLookupSlow(
transitioning builtin GetIteratorWithFeedback( transitioning builtin GetIteratorWithFeedback(
context: Context, receiver: JSAny, loadSlot: TaggedIndex, context: Context, receiver: JSAny, loadSlot: TaggedIndex,
callSlot: TaggedIndex, feedback: Undefined|FeedbackVector): JSAny { callSlot: TaggedIndex,
maybeFeedbackVector: Undefined|FeedbackVector): JSAny {
// TODO(v8:9891): Remove this assert once all callers are ported to Torque.
// This assert ensures correctness of maybeFeedbackVector's type which can
// be easily broken for calls from CSA.
assert(
IsUndefined(maybeFeedbackVector) ||
Is<FeedbackVector>(maybeFeedbackVector));
let iteratorMethod: JSAny; let iteratorMethod: JSAny;
typeswitch (feedback) { typeswitch (maybeFeedbackVector) {
case (Undefined): { case (Undefined): {
iteratorMethod = GetProperty(receiver, IteratorSymbolConstant()); iteratorMethod = GetProperty(receiver, IteratorSymbolConstant());
} }
...@@ -64,7 +71,7 @@ transitioning builtin GetIteratorWithFeedback( ...@@ -64,7 +71,7 @@ transitioning builtin GetIteratorWithFeedback(
// TODO(v8:10047): Use TaggedIndex here once TurboFan supports it. // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it.
const callSlotSmi: Smi = TaggedIndexToSmi(callSlot); const callSlotSmi: Smi = TaggedIndexToSmi(callSlot);
return CallIteratorWithFeedback( return CallIteratorWithFeedback(
context, receiver, iteratorMethod, callSlotSmi, feedback); context, receiver, iteratorMethod, callSlotSmi, maybeFeedbackVector);
} }
transitioning builtin CallIteratorWithFeedback( transitioning builtin CallIteratorWithFeedback(
......
...@@ -503,6 +503,10 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams); ...@@ -503,6 +503,10 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged() /* result */, \ DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged() /* result */, \
##__VA_ARGS__) ##__VA_ARGS__)
// When the extra arguments described here are located in the stack, they are
// just above the return address in the frame. Therefore, they are either the
// first arguments when V8_REVERSE_JSARGS is enabled, or otherwise the last
// arguments.
#define DEFINE_JS_PARAMETERS(...) \ #define DEFINE_JS_PARAMETERS(...) \
static constexpr int kDescriptorFlags = \ static constexpr int kDescriptorFlags = \
CallInterfaceDescriptorData::kAllowVarArgs; \ CallInterfaceDescriptorData::kAllowVarArgs; \
......
...@@ -529,9 +529,14 @@ void JSGenericLowering::LowerJSCreateArguments(Node* node) { ...@@ -529,9 +529,14 @@ void JSGenericLowering::LowerJSCreateArguments(Node* node) {
void JSGenericLowering::LowerJSCreateArray(Node* node) { void JSGenericLowering::LowerJSCreateArray(Node* node) {
CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
int const arity = static_cast<int>(p.arity()); int const arity = static_cast<int>(p.arity());
auto interface_descriptor = ArrayConstructorDescriptor{};
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), ArrayConstructorDescriptor{}, arity + 1, zone(), interface_descriptor, arity + 1, CallDescriptor::kNeedsFrameState,
CallDescriptor::kNeedsFrameState, node->op()->properties()); node->op()->properties());
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(interface_descriptor.GetStackParameterCount(), 0);
Node* stub_code = jsgraph()->ArrayConstructorStubConstant(); Node* stub_code = jsgraph()->ArrayConstructorStubConstant();
Node* stub_arity = jsgraph()->Int32Constant(arity); Node* stub_arity = jsgraph()->Int32Constant(arity);
MaybeHandle<AllocationSite> const maybe_site = p.site(); MaybeHandle<AllocationSite> const maybe_site = p.site();
...@@ -780,6 +785,10 @@ void JSGenericLowering::LowerJSConstructForwardVarargs(Node* node) { ...@@ -780,6 +785,10 @@ void JSGenericLowering::LowerJSConstructForwardVarargs(Node* node) {
int const arg_count = static_cast<int>(p.arity() - 2); int const arg_count = static_cast<int>(p.arity() - 2);
CallDescriptor::Flags flags = FrameStateFlagForCall(node); CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable = CodeFactory::ConstructForwardVarargs(isolate()); Callable callable = CodeFactory::ConstructForwardVarargs(isolate());
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(), 0);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), arg_count + 1, flags); zone(), callable.descriptor(), arg_count + 1, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
...@@ -808,12 +817,20 @@ void JSGenericLowering::LowerJSConstruct(Node* node) { ...@@ -808,12 +817,20 @@ void JSGenericLowering::LowerJSConstruct(Node* node) {
arg_count + kReceiver + kMaybeFeedbackVector; arg_count + kReceiver + kMaybeFeedbackVector;
Callable callable = Callable callable =
Builtins::CallableFor(isolate(), Builtins::kConstruct_WithFeedback); Builtins::CallableFor(isolate(), Builtins::kConstruct_WithFeedback);
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(),
kMaybeFeedbackVector);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), stack_argument_count, flags); zone(), callable.descriptor(), stack_argument_count, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* stub_arity = jsgraph()->Int32Constant(arg_count); Node* stub_arity = jsgraph()->Int32Constant(arg_count);
Node* slot = jsgraph()->Int32Constant(p.feedback().index()); Node* slot = jsgraph()->Int32Constant(p.feedback().index());
Node* receiver = jsgraph()->UndefinedConstant(); Node* receiver = jsgraph()->UndefinedConstant();
#ifdef V8_REVERSE_JSARGS
Node* feedback_vector = node->RemoveInput(n.FeedbackVectorIndex());
#endif
// Register argument inputs are followed by stack argument inputs (such as // Register argument inputs are followed by stack argument inputs (such as
// feedback_vector). Both are listed in ascending order. Note that // feedback_vector). Both are listed in ascending order. Note that
// the receiver is implicitly placed on the stack and is thus inserted // the receiver is implicitly placed on the stack and is thus inserted
...@@ -822,10 +839,16 @@ void JSGenericLowering::LowerJSConstruct(Node* node) { ...@@ -822,10 +839,16 @@ void JSGenericLowering::LowerJSConstruct(Node* node) {
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->InsertInput(zone(), 3, stub_arity); node->InsertInput(zone(), 3, stub_arity);
node->InsertInput(zone(), 4, slot); node->InsertInput(zone(), 4, slot);
#ifdef V8_REVERSE_JSARGS
node->InsertInput(zone(), 5, feedback_vector);
node->InsertInput(zone(), 6, receiver);
// After: {code, target, new_target, arity, slot, vector, receiver,
// ...args}.
#else
node->InsertInput(zone(), 5, receiver); node->InsertInput(zone(), 5, receiver);
// After: {code, target, new_target, arity, slot, receiver, ...args, // After: {code, target, new_target, arity, slot, receiver, ...args,
// vector}. // vector}.
#endif
NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
} else { } else {
...@@ -864,12 +887,19 @@ void JSGenericLowering::LowerJSConstructWithArrayLike(Node* node) { ...@@ -864,12 +887,19 @@ void JSGenericLowering::LowerJSConstructWithArrayLike(Node* node) {
arg_count - kArgumentList + kReceiver + kMaybeFeedbackVector; arg_count - kArgumentList + kReceiver + kMaybeFeedbackVector;
Callable callable = Builtins::CallableFor( Callable callable = Builtins::CallableFor(
isolate(), Builtins::kConstructWithArrayLike_WithFeedback); isolate(), Builtins::kConstructWithArrayLike_WithFeedback);
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(),
kMaybeFeedbackVector);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), stack_argument_count, flags); zone(), callable.descriptor(), stack_argument_count, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* receiver = jsgraph()->UndefinedConstant(); Node* receiver = jsgraph()->UndefinedConstant();
Node* slot = jsgraph()->Int32Constant(p.feedback().index()); Node* slot = jsgraph()->Int32Constant(p.feedback().index());
#ifdef V8_REVERSE_JSARGS
Node* feedback_vector = node->RemoveInput(n.FeedbackVectorIndex());
#endif
// Register argument inputs are followed by stack argument inputs (such as // Register argument inputs are followed by stack argument inputs (such as
// feedback_vector). Both are listed in ascending order. Note that // feedback_vector). Both are listed in ascending order. Note that
// the receiver is implicitly placed on the stack and is thus inserted // the receiver is implicitly placed on the stack and is thus inserted
...@@ -877,16 +907,26 @@ void JSGenericLowering::LowerJSConstructWithArrayLike(Node* node) { ...@@ -877,16 +907,26 @@ void JSGenericLowering::LowerJSConstructWithArrayLike(Node* node) {
// TODO(jgruber): Implement a simpler way to specify these mutations. // TODO(jgruber): Implement a simpler way to specify these mutations.
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->InsertInput(zone(), 4, slot); node->InsertInput(zone(), 4, slot);
#ifdef V8_REVERSE_JSARGS
node->InsertInput(zone(), 5, feedback_vector);
node->InsertInput(zone(), 6, receiver);
// After: {code, target, new_target, arguments_list, slot, vector,
// receiver}.
#else
node->InsertInput(zone(), 5, receiver); node->InsertInput(zone(), 5, receiver);
// After: {code, target, new_target, arguments_list, slot, receiver, // After: {code, target, new_target, arguments_list, slot, receiver,
// vector}. // vector}.
#endif
NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
} else { } else {
const int stack_argument_count = arg_count - kArgumentList + kReceiver; const int stack_argument_count = arg_count - kArgumentList + kReceiver;
Callable callable = Callable callable =
Builtins::CallableFor(isolate(), Builtins::kConstructWithArrayLike); Builtins::CallableFor(isolate(), Builtins::kConstructWithArrayLike);
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(), 0);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), stack_argument_count, flags); zone(), callable.descriptor(), stack_argument_count, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
...@@ -918,6 +958,11 @@ void JSGenericLowering::LowerJSConstructWithSpread(Node* node) { ...@@ -918,6 +958,11 @@ void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
arg_count + kReceiver + kMaybeFeedbackVector; arg_count + kReceiver + kMaybeFeedbackVector;
Callable callable = Builtins::CallableFor( Callable callable = Builtins::CallableFor(
isolate(), Builtins::kConstructWithSpread_WithFeedback); isolate(), Builtins::kConstructWithSpread_WithFeedback);
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(),
kTheSpread + kMaybeFeedbackVector);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), stack_argument_count, flags); zone(), callable.descriptor(), stack_argument_count, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
...@@ -927,6 +972,10 @@ void JSGenericLowering::LowerJSConstructWithSpread(Node* node) { ...@@ -927,6 +972,10 @@ void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
// on the stack here. // on the stack here.
Node* stub_arity = jsgraph()->Int32Constant(arg_count - kTheSpread); Node* stub_arity = jsgraph()->Int32Constant(arg_count - kTheSpread);
Node* receiver = jsgraph()->UndefinedConstant(); Node* receiver = jsgraph()->UndefinedConstant();
#ifdef V8_REVERSE_JSARGS
Node* feedback_vector = node->RemoveInput(n.FeedbackVectorIndex());
Node* spread = node->RemoveInput(n.LastArgumentIndex());
#endif
// Register argument inputs are followed by stack argument inputs (such as // Register argument inputs are followed by stack argument inputs (such as
// feedback_vector). Both are listed in ascending order. Note that // feedback_vector). Both are listed in ascending order. Note that
...@@ -936,15 +985,26 @@ void JSGenericLowering::LowerJSConstructWithSpread(Node* node) { ...@@ -936,15 +985,26 @@ void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->InsertInput(zone(), 3, stub_arity); node->InsertInput(zone(), 3, stub_arity);
node->InsertInput(zone(), 4, slot); node->InsertInput(zone(), 4, slot);
#ifdef V8_REVERSE_JSARGS
node->InsertInput(zone(), 5, spread);
node->InsertInput(zone(), 6, feedback_vector);
node->InsertInput(zone(), 7, receiver);
// After: {code, target, new_target, arity, slot, spread, vector, receiver,
// ...args}.
#else
node->InsertInput(zone(), 5, receiver); node->InsertInput(zone(), 5, receiver);
// After: {code, target, new_target, arity, slot, receiver, ...args, spread, // After: {code, target, new_target, arity, slot, receiver, ...args, spread,
// vector}. // vector}.
#endif
NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
} else { } else {
const int stack_argument_count = arg_count + kReceiver - kTheSpread; const int stack_argument_count = arg_count + kReceiver - kTheSpread;
Callable callable = CodeFactory::ConstructWithSpread(isolate()); Callable callable = CodeFactory::ConstructWithSpread(isolate());
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(), 0);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), stack_argument_count, flags); zone(), callable.descriptor(), stack_argument_count, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
...@@ -1098,6 +1158,11 @@ void JSGenericLowering::LowerJSCallWithSpread(Node* node) { ...@@ -1098,6 +1158,11 @@ void JSGenericLowering::LowerJSCallWithSpread(Node* node) {
arg_count - kTheSpread + kReceiver + kMaybeFeedbackVector; arg_count - kTheSpread + kReceiver + kMaybeFeedbackVector;
Callable callable = Builtins::CallableFor( Callable callable = Builtins::CallableFor(
isolate(), Builtins::kCallWithSpread_WithFeedback); isolate(), Builtins::kCallWithSpread_WithFeedback);
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(),
kMaybeFeedbackVector);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), stack_argument_count, flags); zone(), callable.descriptor(), stack_argument_count, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
...@@ -1114,22 +1179,29 @@ void JSGenericLowering::LowerJSCallWithSpread(Node* node) { ...@@ -1114,22 +1179,29 @@ void JSGenericLowering::LowerJSCallWithSpread(Node* node) {
// Shuffling inputs. // Shuffling inputs.
// Before: {target, receiver, ...args, spread, vector}. // Before: {target, receiver, ...args, spread, vector}.
#ifdef V8_REVERSE_JSARGS
Node* feedback_vector = node->RemoveInput(n.FeedbackVectorIndex());
#endif
Node* spread = node->RemoveInput(n.LastArgumentIndex()); Node* spread = node->RemoveInput(n.LastArgumentIndex());
// Now: {target, receiver, ...args, vector}.
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->InsertInput(zone(), 2, stub_arity); node->InsertInput(zone(), 2, stub_arity);
node->InsertInput(zone(), 3, spread); node->InsertInput(zone(), 3, spread);
node->InsertInput(zone(), 4, slot); node->InsertInput(zone(), 4, slot);
#ifdef V8_REVERSE_JSARGS
node->InsertInput(zone(), 5, feedback_vector);
// After: {code, target, arity, spread, slot, vector, receiver, ...args}.
#else
// After: {code, target, arity, spread, slot, receiver, ...args, vector}. // After: {code, target, arity, spread, slot, receiver, ...args, vector}.
#endif
NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
} else { } else {
const int stack_argument_count = arg_count - kTheSpread + kReceiver; const int stack_argument_count = arg_count - kTheSpread + kReceiver;
Callable callable = CodeFactory::CallWithSpread(isolate()); Callable callable = CodeFactory::CallWithSpread(isolate());
// If this fails, we might need to update the parameter reordering code
// to ensure that the additional arguments passed via stack are pushed
// between top of stack and JS arguments.
DCHECK_EQ(callable.descriptor().GetStackParameterCount(), 0);
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), callable.descriptor(), stack_argument_count, flags); zone(), callable.descriptor(), stack_argument_count, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment