Commit fdb31302 authored by jgruber's avatar jgruber Committed by Commit Bot

[ia32] Unalias kRootRegister in ApiCallback,InterpreterPushArgsThenCall

In preparation for kRootRegister support on ia32.

For both descriptors we simply shuffle registers around to remove ebx
from the calling convention.

Possible follow-up work: The ApiCallbackDescriptor could be simplified
by passing call_data (and the Undefined constant) on the stack. This
currently happens in the builtin body.

Drive-by: Minor refactoring in InterpreterPushArgsMode to deobfuscate
the different paths (spread/no-spread). Also use
{Push,Pop}ReturnAddress helpers.

Bug: v8:6666
Change-Id: I25fd738501fff71c038a0745cec04363f90df660
Reviewed-on: https://chromium-review.googlesource.com/1196552Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55554}
parent b1bd6beb
...@@ -954,51 +954,52 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl( ...@@ -954,51 +954,52 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
DCHECK(mode != InterpreterPushArgsMode::kArrayFunction); DCHECK(mode != InterpreterPushArgsMode::kArrayFunction);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver) // -- eax : the number of arguments (not including the receiver)
// -- ebx : the address of the first argument to be pushed. Subsequent // -- ecx : the address of the first argument to be pushed. Subsequent
// arguments should be consecutive above this, in the same order as // arguments should be consecutive above this, in the same order as
// they are to be pushed onto the stack. // they are to be pushed onto the stack.
// -- edi : the target to call (can be any Object). // -- edi : the target to call (can be any Object).
// ----------------------------------- // -----------------------------------
const Register scratch = ebx;
const Register argv = ecx;
Label stack_overflow; Label stack_overflow;
// Compute the expected number of arguments. // Compute the expected number of arguments.
__ mov(ecx, eax); __ mov(scratch, eax);
__ add(ecx, Immediate(1)); // Add one for receiver. __ add(scratch, Immediate(1)); // Add one for receiver.
// Add a stack check before pushing the arguments. We need an extra register // Add a stack check before pushing the arguments. We need an extra register
// to perform a stack check. So push it onto the stack temporarily. This // to perform a stack check. So push it onto the stack temporarily. This
// might cause stack overflow, but it will be detected by the check. // might cause stack overflow, but it will be detected by the check.
__ Push(edi); __ Push(edi);
Generate_StackOverflowCheck(masm, ecx, edx, &stack_overflow); Generate_StackOverflowCheck(masm, scratch, edx, &stack_overflow);
__ Pop(edi); __ Pop(edi);
// Pop return address to allow tail-call after pushing arguments. // Pop return address to allow tail-call after pushing arguments.
__ Pop(edx); __ PopReturnAddressTo(edx);
// Push "undefined" as the receiver arg if we need to. // Push "undefined" as the receiver arg if we need to.
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
__ PushRoot(Heap::kUndefinedValueRootIndex); __ PushRoot(Heap::kUndefinedValueRootIndex);
__ sub(ecx, Immediate(1)); // Subtract one for receiver. __ sub(scratch, Immediate(1)); // Subtract one for receiver.
} }
// Find the address of the last argument. // Find the address of the last argument.
__ shl(ecx, kPointerSizeLog2); __ shl(scratch, kPointerSizeLog2);
__ neg(ecx); __ neg(scratch);
__ add(ecx, ebx); __ add(scratch, argv);
Generate_InterpreterPushArgs(masm, ecx, ebx); Generate_InterpreterPushArgs(masm, scratch, argv);
if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
__ Pop(ebx); // Pass the spread in a register
__ sub(eax, Immediate(1)); // Subtract one for spread
}
// Call the target. // Call the target.
__ Push(edx); // Re-push return address.
if (mode == InterpreterPushArgsMode::kWithFinalSpread) { if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
__ MoveForRootRegisterRefactoring(ecx, ebx); __ Pop(ecx); // Pass the spread in a register
__ sub(eax, Immediate(1)); // Subtract one for spread
__ PushReturnAddressFrom(edx);
__ Jump(BUILTIN_CODE(masm->isolate(), CallWithSpread), __ Jump(BUILTIN_CODE(masm->isolate(), CallWithSpread),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} else { } else {
__ PushReturnAddressFrom(edx);
__ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny), __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} }
......
...@@ -340,7 +340,7 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm, ...@@ -340,7 +340,7 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
void CallApiCallbackStub::Generate(MacroAssembler* masm) { void CallApiCallbackStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ebx : call_data // -- eax : call_data
// -- ecx : holder // -- ecx : holder
// -- edx : api_function_address // -- edx : api_function_address
// -- esi : context // -- esi : context
...@@ -352,10 +352,10 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) { ...@@ -352,10 +352,10 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
// -- esp[(argc + 1) * 4] : receiver // -- esp[(argc + 1) * 4] : receiver
// ----------------------------------- // -----------------------------------
Register call_data = ebx; Register call_data = eax;
Register holder = ecx; Register holder = ecx;
Register api_function_address = edx; Register api_function_address = edx;
Register return_address = eax; Register return_address = ebx;
typedef FunctionCallbackArguments FCA; typedef FunctionCallbackArguments FCA;
......
...@@ -217,7 +217,7 @@ void ApiCallbackDescriptor::InitializePlatformSpecific( ...@@ -217,7 +217,7 @@ void ApiCallbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
JavaScriptFrame::context_register(), // callee context JavaScriptFrame::context_register(), // callee context
ebx, // call_data eax, // call_data
ecx, // holder ecx, // holder
edx, // api_function_address edx, // api_function_address
}; };
...@@ -236,7 +236,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( ...@@ -236,7 +236,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
ebx, // address of first argument ecx, // address of first argument
edi // the target callable to be call edi // the target callable to be call
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
......
...@@ -654,6 +654,9 @@ class FastNewObjectDescriptor : public CallInterfaceDescriptor { ...@@ -654,6 +654,9 @@ class FastNewObjectDescriptor : public CallInterfaceDescriptor {
class RecordWriteDescriptor final : public CallInterfaceDescriptor { class RecordWriteDescriptor final : public CallInterfaceDescriptor {
public: public:
// TODO(v8:6666): Remove the isolate argument once kRootRegister is
// fully supported on ia32. Then the isolate can be determined through a
// simple register addition instead.
DEFINE_PARAMETERS(kObject, kSlot, kIsolate, kRememberedSet, kFPMode) DEFINE_PARAMETERS(kObject, kSlot, kIsolate, kRememberedSet, kFPMode)
DEFINE_PARAMETER_TYPES(MachineType::TaggedPointer(), // kObject DEFINE_PARAMETER_TYPES(MachineType::TaggedPointer(), // kObject
MachineType::Pointer(), // kSlot MachineType::Pointer(), // kSlot
...@@ -930,6 +933,9 @@ class CEntry1ArgvOnStackDescriptor : public CallInterfaceDescriptor { ...@@ -930,6 +933,9 @@ class CEntry1ArgvOnStackDescriptor : public CallInterfaceDescriptor {
class ApiCallbackDescriptor : public CallInterfaceDescriptor { class ApiCallbackDescriptor : public CallInterfaceDescriptor {
public: public:
// TODO(jgruber): This could be simplified to pass call data on the stack
// since this is what the CallApiCallbackStub anyways. This would free a
// register.
DEFINE_PARAMETERS_NO_CONTEXT(kTargetContext, kCallData, kHolder, DEFINE_PARAMETERS_NO_CONTEXT(kTargetContext, kCallData, kHolder,
kApiFunctionAddress) kApiFunctionAddress)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTargetContext DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTargetContext
......
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