// 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.
|
|
#include "src/interface-descriptors.h"
|
|
namespace v8 {
|
namespace internal {
|
|
void CallInterfaceDescriptorData::InitializePlatformSpecific(
|
int register_parameter_count, const Register* registers) {
|
DCHECK(!IsInitializedPlatformIndependent());
|
|
register_param_count_ = register_parameter_count;
|
|
// InterfaceDescriptor owns a copy of the registers array.
|
register_params_ = NewArray<Register>(register_parameter_count, no_reg);
|
for (int i = 0; i < register_parameter_count; i++) {
|
register_params_[i] = registers[i];
|
}
|
}
|
|
void CallInterfaceDescriptorData::InitializePlatformIndependent(
|
Flags flags, int return_count, int parameter_count,
|
const MachineType* machine_types, int machine_types_length) {
|
DCHECK(IsInitializedPlatformSpecific());
|
|
flags_ = flags;
|
return_count_ = return_count;
|
param_count_ = parameter_count;
|
const int types_length = return_count_ + param_count_;
|
|
// Machine types are either fully initialized or null.
|
if (machine_types == nullptr) {
|
machine_types_ =
|
NewArray<MachineType>(types_length, MachineType::AnyTagged());
|
} else {
|
DCHECK_EQ(machine_types_length, types_length);
|
machine_types_ = NewArray<MachineType>(types_length);
|
for (int i = 0; i < types_length; i++) machine_types_[i] = machine_types[i];
|
}
|
|
DCHECK(AllStackParametersAreTagged());
|
}
|
|
#ifdef DEBUG
|
bool CallInterfaceDescriptorData::AllStackParametersAreTagged() const {
|
DCHECK(IsInitialized());
|
const int types_length = return_count_ + param_count_;
|
const int first_stack_param = return_count_ + register_param_count_;
|
for (int i = first_stack_param; i < types_length; i++) {
|
if (!machine_types_[i].IsTagged()) return false;
|
}
|
return true;
|
}
|
#endif // DEBUG
|
|
void CallInterfaceDescriptorData::Reset() {
|
delete[] machine_types_;
|
machine_types_ = nullptr;
|
delete[] register_params_;
|
register_params_ = nullptr;
|
}
|
|
// static
|
CallInterfaceDescriptorData
|
CallDescriptors::call_descriptor_data_[NUMBER_OF_DESCRIPTORS];
|
|
void CallDescriptors::InitializeOncePerProcess() {
|
#define INTERFACE_DESCRIPTOR(name, ...) \
|
name##Descriptor().Initialize(&call_descriptor_data_[CallDescriptors::name]);
|
INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR)
|
#undef INTERFACE_DESCRIPTOR
|
|
DCHECK(ContextOnlyDescriptor{}.HasContextParameter());
|
DCHECK(!NoContextDescriptor{}.HasContextParameter());
|
DCHECK(!AllocateDescriptor{}.HasContextParameter());
|
DCHECK(!AllocateHeapNumberDescriptor{}.HasContextParameter());
|
DCHECK(!AbortDescriptor{}.HasContextParameter());
|
}
|
|
void CallDescriptors::TearDown() {
|
for (CallInterfaceDescriptorData& data : call_descriptor_data_) {
|
data.Reset();
|
}
|
}
|
|
void CallInterfaceDescriptor::JSDefaultInitializePlatformSpecific(
|
CallInterfaceDescriptorData* data, int non_js_register_parameter_count) {
|
DCHECK_LE(static_cast<unsigned>(non_js_register_parameter_count), 1);
|
|
// 3 is for kTarget, kNewTarget and kActualArgumentsCount
|
int register_parameter_count = 3 + non_js_register_parameter_count;
|
|
DCHECK(!AreAliased(
|
kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
|
kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register));
|
|
const Register default_js_stub_registers[] = {
|
kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
|
kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register};
|
|
CHECK_LE(static_cast<size_t>(register_parameter_count),
|
arraysize(default_js_stub_registers));
|
data->InitializePlatformSpecific(register_parameter_count,
|
default_js_stub_registers);
|
}
|
|
const char* CallInterfaceDescriptor::DebugName() const {
|
CallDescriptors::Key key = CallDescriptors::GetKey(data_);
|
switch (key) {
|
#define DEF_CASE(name, ...) \
|
case CallDescriptors::name: \
|
return #name " Descriptor";
|
INTERFACE_DESCRIPTOR_LIST(DEF_CASE)
|
#undef DEF_CASE
|
case CallDescriptors::NUMBER_OF_DESCRIPTORS:
|
break;
|
}
|
return "";
|
}
|
|
|
void VoidDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
data->InitializePlatformSpecific(0, nullptr);
|
}
|
|
void AllocateDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {kAllocateSizeRegister};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void CEntry1ArgvOnStackDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {kRuntimeCallArgCountRegister,
|
kRuntimeCallFunctionRegister};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
namespace {
|
|
void InterpreterCEntryDescriptor_InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {kRuntimeCallArgCountRegister,
|
kRuntimeCallArgvRegister,
|
kRuntimeCallFunctionRegister};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
} // namespace
|
|
void InterpreterCEntry1Descriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
|
}
|
|
void InterpreterCEntry2Descriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
|
}
|
|
void FastNewFunctionContextDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ScopeInfoRegister(), SlotsRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void FastNewObjectDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {TargetRegister(), NewTargetRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
const Register FastNewObjectDescriptor::TargetRegister() {
|
return kJSFunctionRegister;
|
}
|
|
const Register FastNewObjectDescriptor::NewTargetRegister() {
|
return kJavaScriptCallNewTargetRegister;
|
}
|
|
|
void LoadDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void LoadGlobalDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {NameRegister(), SlotRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {NameRegister(), SlotRegister(), VectorRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void StoreGlobalDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {NameRegister(), ValueRegister(), SlotRegister()};
|
|
int len = arraysize(registers) - kStackArgumentsCount;
|
data->InitializePlatformSpecific(len, registers);
|
}
|
|
void StoreGlobalWithVectorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {NameRegister(), ValueRegister(), SlotRegister(),
|
VectorRegister()};
|
int len = arraysize(registers) - kStackArgumentsCount;
|
data->InitializePlatformSpecific(len, registers);
|
}
|
|
void StoreDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
|
SlotRegister()};
|
|
int len = arraysize(registers) - kStackArgumentsCount;
|
data->InitializePlatformSpecific(len, registers);
|
}
|
|
void StoreTransitionDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {
|
ReceiverRegister(), NameRegister(), MapRegister(),
|
ValueRegister(), SlotRegister(), VectorRegister(),
|
};
|
int len = arraysize(registers) - kStackArgumentsCount;
|
data->InitializePlatformSpecific(len, registers);
|
}
|
|
void StringAtDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
}
|
|
void StringSubstringDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
}
|
|
void TypeConversionDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ArgumentRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void TypeConversionStackParameterDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
data->InitializePlatformSpecific(0, nullptr);
|
}
|
|
void LoadWithVectorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister(),
|
VectorRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void StoreWithVectorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
|
SlotRegister(), VectorRegister()};
|
int len = arraysize(registers) - kStackArgumentsCount;
|
data->InitializePlatformSpecific(len, registers);
|
}
|
|
const Register ApiGetterDescriptor::ReceiverRegister() {
|
return LoadDescriptor::ReceiverRegister();
|
}
|
|
void ApiGetterDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ReceiverRegister(), HolderRegister(),
|
CallbackRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void ContextOnlyDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
data->InitializePlatformSpecific(0, nullptr);
|
}
|
|
void NoContextDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
data->InitializePlatformSpecific(0, nullptr);
|
}
|
|
void GrowArrayElementsDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
Register registers[] = {ObjectRegister(), KeyRegister()};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void NewArgumentsElementsDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
DefaultInitializePlatformSpecific(data, 3);
|
}
|
|
void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
// This descriptor must use the same set of registers as the
|
// ArrayNArgumentsConstructorDescriptor.
|
ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
|
}
|
|
void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
// This descriptor must use the same set of registers as the
|
// ArrayNArgumentsConstructorDescriptor.
|
ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
|
}
|
|
void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
// Keep the arguments on the same registers as they were in
|
// ArrayConstructorDescriptor to avoid unnecessary register moves.
|
// kFunction, kAllocationSite, kActualArgumentsCount
|
Register registers[] = {kJavaScriptCallTargetRegister,
|
kJavaScriptCallExtraArg1Register,
|
kJavaScriptCallArgCountRegister};
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
}
|
|
void WasmGrowMemoryDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
}
|
|
void CloneObjectWithVectorDescriptor::InitializePlatformSpecific(
|
CallInterfaceDescriptorData* data) {
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
}
|
|
} // namespace internal
|
} // namespace v8
|