deabb19abc
LOG=Y BUG=v8:4124,v8:5948 R=bradnelson@chromium.org,bmeurer@chromium.org,jochen@chromium.org,hpayer@chromium.org,danno@chromium.org Review-Url: https://codereview.chromium.org/2684313003 Cr-Original-Original-Commit-Position: refs/heads/master@{#43162} Committed:d170c57ab9
Review-Url: https://codereview.chromium.org/2684313003 Cr-Original-Commit-Position: refs/heads/master@{#43169} Committed:a9b59a11f1
Review-Url: https://codereview.chromium.org/2684313003 Cr-Commit-Position: refs/heads/master@{#43176}
408 lines
13 KiB
C++
408 lines
13 KiB
C++
// Copyright 2012 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#if V8_TARGET_ARCH_X64
|
|
|
|
#include "src/interface-descriptors.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
const Register CallInterfaceDescriptor::ContextRegister() { return rsi; }
|
|
|
|
void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data, int register_parameter_count) {
|
|
const Register default_stub_registers[] = {rax, rbx, rcx, rdx, rdi};
|
|
CHECK_LE(static_cast<size_t>(register_parameter_count),
|
|
arraysize(default_stub_registers));
|
|
data->InitializePlatformSpecific(register_parameter_count,
|
|
default_stub_registers);
|
|
}
|
|
|
|
const Register FastNewFunctionContextDescriptor::FunctionRegister() {
|
|
return rdi;
|
|
}
|
|
const Register FastNewFunctionContextDescriptor::SlotsRegister() { return rax; }
|
|
|
|
const Register LoadDescriptor::ReceiverRegister() { return rdx; }
|
|
const Register LoadDescriptor::NameRegister() { return rcx; }
|
|
const Register LoadDescriptor::SlotRegister() { return rax; }
|
|
|
|
const Register LoadWithVectorDescriptor::VectorRegister() { return rbx; }
|
|
|
|
const Register LoadICProtoArrayDescriptor::HandlerRegister() { return rdi; }
|
|
|
|
const Register StoreDescriptor::ReceiverRegister() { return rdx; }
|
|
const Register StoreDescriptor::NameRegister() { return rcx; }
|
|
const Register StoreDescriptor::ValueRegister() { return rax; }
|
|
const Register StoreDescriptor::SlotRegister() { return rdi; }
|
|
|
|
const Register StoreWithVectorDescriptor::VectorRegister() { return rbx; }
|
|
|
|
const Register StoreTransitionDescriptor::SlotRegister() { return rdi; }
|
|
const Register StoreTransitionDescriptor::VectorRegister() { return rbx; }
|
|
const Register StoreTransitionDescriptor::MapRegister() { return r11; }
|
|
|
|
const Register StringCompareDescriptor::LeftRegister() { return rdx; }
|
|
const Register StringCompareDescriptor::RightRegister() { return rax; }
|
|
|
|
const Register ApiGetterDescriptor::HolderRegister() { return rcx; }
|
|
const Register ApiGetterDescriptor::CallbackRegister() { return rbx; }
|
|
|
|
const Register MathPowTaggedDescriptor::exponent() { return rdx; }
|
|
|
|
|
|
const Register MathPowIntegerDescriptor::exponent() {
|
|
return MathPowTaggedDescriptor::exponent();
|
|
}
|
|
|
|
|
|
const Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
|
|
const Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
|
|
|
|
|
|
void FastNewClosureDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// SharedFunctionInfo, vector, slot index.
|
|
Register registers[] = {rbx, rcx, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void TypeofDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
// static
|
|
const Register TypeConversionDescriptor::ArgumentRegister() { return rax; }
|
|
|
|
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi, rax, rcx, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax, rbx, rcx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax, rbx, rcx, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CreateAllocationSiteDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rbx, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CreateWeakCellDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rbx, rdx, rdi};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallFunctionDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void CallICTrampolineDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi, rax, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void CallICDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi, rax, rdx, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallConstructDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// rax : number of arguments
|
|
// rbx : feedback vector
|
|
// rdx : slot in feedback vector (Smi, for RecordCallTarget)
|
|
// rdi : constructor function
|
|
// TODO(turbofan): So far we don't gather type feedback and hence skip the
|
|
// slot parameter, but ArrayConstructStub needs the vector to be undefined.
|
|
Register registers[] = {rax, rdi, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallTrampolineDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// rax : number of arguments
|
|
// rdi : the target to call
|
|
Register registers[] = {rdi, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// rcx : start index (to support rest parameters)
|
|
// rdi : the target to call
|
|
Register registers[] = {rdi, rcx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void ConstructStubDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// rax : number of arguments
|
|
// rdx : the new target
|
|
// rdi : the target to call
|
|
// rbx : allocation site or undefined
|
|
Register registers[] = {rdi, rdx, rax, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ConstructTrampolineDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// rax : number of arguments
|
|
// rdx : the new target
|
|
// rdi : the target to call
|
|
Register registers[] = {rdi, rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void TransitionElementsKindDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void AllocateHeapNumberDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
data->InitializePlatformSpecific(0, nullptr, nullptr);
|
|
}
|
|
|
|
void ArrayConstructorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// kTarget, kNewTarget, kActualArgumentsCount, kAllocationSite
|
|
Register registers[] = {rdi, rdx, rax, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
|
|
}
|
|
|
|
void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// register state
|
|
// rax -- number of arguments
|
|
// rdi -- function
|
|
// rbx -- allocation site with elements kind
|
|
Register registers[] = {rdi, rbx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
|
|
}
|
|
|
|
void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// register state
|
|
// rax -- number of arguments
|
|
// rdi -- function
|
|
// rbx -- allocation site with elements kind
|
|
Register registers[] = {rdi, rbx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
|
|
}
|
|
|
|
void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// register state
|
|
// rax -- number of arguments
|
|
// rdi -- function
|
|
// rbx -- allocation site with elements kind
|
|
Register registers[] = {rdi, rbx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
|
|
}
|
|
|
|
void VarArgFunctionDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// stack param count needs (arg count)
|
|
Register registers[] = {rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void CompareDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void BinaryOpDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rcx, rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void BinaryOpWithVectorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// register state
|
|
// rdx -- lhs
|
|
// rax -- rhs
|
|
// rdi -- slot id
|
|
// rbx -- vector
|
|
Register registers[] = {rdx, rax, rdi, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void CountOpDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void StringAddDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void KeyedDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rcx, // key
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void NamedDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rcx, // name
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallHandlerDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdx, // receiver
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ArgumentAdaptorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdi, // JSFunction
|
|
rdx, // the new target
|
|
rax, // actual number of arguments
|
|
rbx, // expected number of arguments
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void ApiCallbackDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdi, // callee
|
|
rbx, // call_data
|
|
rcx, // holder
|
|
rdx, // api_function_address
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void InterpreterDispatchDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
|
|
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rax, // argument count (not including receiver)
|
|
rbx, // address of first argument
|
|
rdi // the target callable to be call
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rax, // argument count (not including receiver)
|
|
rdx, // new target
|
|
rdi, // constructor
|
|
rbx, // allocation site feedback if available, undefined otherwise
|
|
rcx, // address of first argument
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rax, // argument count (not including receiver)
|
|
rdx, // target to the call. It is checked to be Array function.
|
|
rbx, // allocation site feedback
|
|
rcx, // address of first argument
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rax, // argument count (argc)
|
|
r15, // address of first argument (argv)
|
|
rbx // the runtime function to call
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void ResumeGeneratorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rax, // the value to pass to the generator
|
|
rbx, // the JSGeneratorObject to resume
|
|
rdx // the resume mode (tagged)
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rbx, // loaded new FP
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_TARGET_ARCH_X64
|