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(
DCHECK(mode != InterpreterPushArgsMode::kArrayFunction);
// ----------- S t a t e -------------
// -- 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
// they are to be pushed onto the stack.
// -- edi : the target to call (can be any Object).
// -----------------------------------
const Register scratch = ebx;
const Register argv = ecx;
Label stack_overflow;
// Compute the expected number of arguments.
__ mov(ecx, eax);
__ add(ecx, Immediate(1)); // Add one for receiver.
__ mov(scratch, eax);
__ add(scratch, Immediate(1)); // Add one for receiver.
// 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
// might cause stack overflow, but it will be detected by the check.
__ Push(edi);
Generate_StackOverflowCheck(masm, ecx, edx, &stack_overflow);
Generate_StackOverflowCheck(masm, scratch, edx, &stack_overflow);
__ Pop(edi);
// Pop return address to allow tail-call after pushing arguments.
__ Pop(edx);
__ PopReturnAddressTo(edx);
// Push "undefined" as the receiver arg if we need to.
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
__ 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.
__ shl(ecx, kPointerSizeLog2);
__ neg(ecx);
__ add(ecx, ebx);
Generate_InterpreterPushArgs(masm, ecx, ebx);
if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
__ Pop(ebx); // Pass the spread in a register
__ sub(eax, Immediate(1)); // Subtract one for spread
}
__ shl(scratch, kPointerSizeLog2);
__ neg(scratch);
__ add(scratch, argv);
Generate_InterpreterPushArgs(masm, scratch, argv);
// Call the target.
__ Push(edx); // Re-push return address.
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),
RelocInfo::CODE_TARGET);
} else {
__ PushReturnAddressFrom(edx);
__ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny),
RelocInfo::CODE_TARGET);
}
......
......@@ -340,7 +340,7 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
void CallApiCallbackStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ebx : call_data
// -- eax : call_data
// -- ecx : holder
// -- edx : api_function_address
// -- esi : context
......@@ -352,10 +352,10 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
Register call_data = ebx;
Register call_data = eax;
Register holder = ecx;
Register api_function_address = edx;
Register return_address = eax;
Register return_address = ebx;
typedef FunctionCallbackArguments FCA;
......
......@@ -217,7 +217,7 @@ void ApiCallbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
JavaScriptFrame::context_register(), // callee context
ebx, // call_data
eax, // call_data
ecx, // holder
edx, // api_function_address
};
......@@ -236,7 +236,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
eax, // argument count (not including receiver)
ebx, // address of first argument
ecx, // address of first argument
edi // the target callable to be call
};
data->InitializePlatformSpecific(arraysize(registers), registers);
......
......@@ -654,6 +654,9 @@ class FastNewObjectDescriptor : public CallInterfaceDescriptor {
class RecordWriteDescriptor final : public CallInterfaceDescriptor {
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_PARAMETER_TYPES(MachineType::TaggedPointer(), // kObject
MachineType::Pointer(), // kSlot
......@@ -930,6 +933,9 @@ class CEntry1ArgvOnStackDescriptor : public CallInterfaceDescriptor {
class ApiCallbackDescriptor : public CallInterfaceDescriptor {
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,
kApiFunctionAddress)
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