[codegen] Add static interface descriptors

Add a new CRTP StaticCallInterfaceDescriptor class, which provides
static constexpr getters for a descriptor's registers, parameter counts,
and so on. Each CallInterfaceDescriptor subclass is changed to extend
StaticCallInterfaceDescriptor, with StaticCallInterfaceDescriptor itself
extending CallInterfaceDescriptor to still provide a dynamic lookup
where needed.

StaticCallInterfaceDescriptor provides a couple of customisation points,
where it reads its CRTP derived descriptor's static fields and
functions, with default fallbacks where appropriate. With these
customisation points, the definition of CallInterfaceDescriptor
subclasses is simplified to:

    a) Providing parameter names (as before)
    b) Providing parameter types (as before)
    c) Optionally setting flags (like kNoContext or kAllowVarArgs) as
       static booleans on the class.
    d) Optionally providing a `registers()` method that returns a
       std::array<Register, N> of registers that may be used for
       parameters (if not provided, this defaults to the implementation
       specific default register set).

Parameter registers (and register count) are automagically set based on
the number of parameters and number of given registers, with extra magic
to ignore no_reg registers (to reduce ia32 special casing). The
CallInterfaceDescriptorData is initialized based on these static
functions, rather than manual per-descriptor initializers.

This allows us to skip loading descriptors dynamically for CallBuiltin
in Sparkplug, and instead lets us use a bit of template magic to
statically set up arguments for the calls. Any other users of statically
known descriptors will also benefit, thanks to C++ picking the static
methods over the dynamic methods on the base class when available.

Because we can remove various virtual functions and trigger heavier
inlining of constantly known values, binary size slightly decreases with
this change.

Note that torque-generated descriptors are changed to use the same magic,
rather than having Torque-specific magic, for consistency.

Bug: v8:11420
Change-Id: Icc5e238b6313a08734feb564204a13226b450c22
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2814518
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73996}
This commit is contained in:
Leszek Swirski 2021-04-15 15:21:39 +02:00 committed by Commit Bot
parent abe4858b0a
commit ae0752df1b
47 changed files with 2796 additions and 2901 deletions

View File

@ -2337,6 +2337,7 @@ v8_header_set("v8_internal_headers") {
"src/codegen/external-reference.h",
"src/codegen/flush-instruction-cache.h",
"src/codegen/handler-table.h",
"src/codegen/interface-descriptors-inl.h",
"src/codegen/interface-descriptors.h",
"src/codegen/label.h",
"src/codegen/machine-type.h",
@ -4057,7 +4058,7 @@ v8_source_set("v8_base_without_compiler") {
sources += [ ### gcmole(arch:ia32) ###
"src/codegen/ia32/assembler-ia32.cc",
"src/codegen/ia32/cpu-ia32.cc",
"src/codegen/ia32/interface-descriptors-ia32.cc",
"src/codegen/ia32/interface-descriptors-ia32-inl.h",
"src/codegen/ia32/macro-assembler-ia32.cc",
"src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.cc",
"src/compiler/backend/ia32/code-generator-ia32.cc",
@ -4075,7 +4076,7 @@ v8_source_set("v8_base_without_compiler") {
"src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.cc",
"src/codegen/x64/assembler-x64.cc",
"src/codegen/x64/cpu-x64.cc",
"src/codegen/x64/interface-descriptors-x64.cc",
"src/codegen/x64/interface-descriptors-x64-inl.h",
"src/codegen/x64/macro-assembler-x64.cc",
"src/compiler/backend/x64/code-generator-x64.cc",
"src/compiler/backend/x64/instruction-scheduler-x64.cc",
@ -4110,7 +4111,7 @@ v8_source_set("v8_base_without_compiler") {
"src/codegen/arm/assembler-arm.cc",
"src/codegen/arm/constants-arm.cc",
"src/codegen/arm/cpu-arm.cc",
"src/codegen/arm/interface-descriptors-arm.cc",
"src/codegen/arm/interface-descriptors-arm-inl.h",
"src/codegen/arm/macro-assembler-arm.cc",
"src/compiler/backend/arm/code-generator-arm.cc",
"src/compiler/backend/arm/instruction-scheduler-arm.cc",
@ -4132,7 +4133,7 @@ v8_source_set("v8_base_without_compiler") {
"src/codegen/arm64/decoder-arm64.cc",
"src/codegen/arm64/instructions-arm64-constants.cc",
"src/codegen/arm64/instructions-arm64.cc",
"src/codegen/arm64/interface-descriptors-arm64.cc",
"src/codegen/arm64/interface-descriptors-arm64-inl.h",
"src/codegen/arm64/macro-assembler-arm64.cc",
"src/codegen/arm64/register-arm64.cc",
"src/codegen/arm64/utils-arm64.cc",

View File

@ -19,9 +19,9 @@ void BaselineCompiler::Prologue() {
__ masm()->EnterFrame(StackFrame::BASELINE);
DCHECK_EQ(kJSFunctionRegister, kJavaScriptCallTargetRegister);
int max_frame_size = bytecode_->frame_size() + max_call_args_;
CallBuiltin(Builtins::kBaselineOutOfLinePrologue, kContextRegister,
kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
CallBuiltin<Builtins::kBaselineOutOfLinePrologue>(
kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
PrologueFillFrame();
}

View File

@ -18,9 +18,9 @@ void BaselineCompiler::Prologue() {
__ masm()->EnterFrame(StackFrame::BASELINE);
DCHECK_EQ(kJSFunctionRegister, kJavaScriptCallTargetRegister);
int max_frame_size = bytecode_->frame_size() + max_call_args_;
CallBuiltin(Builtins::kBaselineOutOfLinePrologue, kContextRegister,
kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
CallBuiltin<Builtins::kBaselineOutOfLinePrologue>(
kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
__ masm()->AssertSpAligned();
PrologueFillFrame();

View File

@ -14,6 +14,7 @@
#include <unordered_map>
#include "src/baseline/baseline-assembler.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/interpreter/bytecode-register.h"
#include "src/objects/feedback-cell.h"
#include "src/objects/js-function.h"

File diff suppressed because it is too large Load Diff

View File

@ -126,26 +126,16 @@ class BaselineCompiler {
Label::Distance distance = Label::kFar);
// Call helpers.
template <typename... Args>
void CallBuiltin(Builtins::Name builtin, Args... args);
template <Builtins::Name kBuiltin, typename... Args>
void CallBuiltin(Args... args);
template <typename... Args>
void CallRuntime(Runtime::FunctionId function, Args... args);
template <typename... Args>
void TailCallBuiltin(Builtins::Name builtin, Args... args);
template <Builtins::Name kBuiltin, typename... Args>
void TailCallBuiltin(Args... args);
void BuildBinop(
Builtins::Name builtin_name, bool fast_path = false,
bool check_overflow = false,
std::function<void(Register, Register)> instruction = [](Register,
Register) {});
void BuildUnop(Builtins::Name builtin_name);
void BuildCompare(Builtins::Name builtin_name);
void BuildBinopWithConstant(Builtins::Name builtin_name);
template <typename... Args>
void BuildCall(ConvertReceiverMode mode, uint32_t slot, uint32_t arg_count,
Args... args);
template <ConvertReceiverMode kMode, typename... Args>
void BuildCall(uint32_t slot, uint32_t arg_count, Args... args);
#ifdef V8_TRACE_UNOPTIMIZED
void TraceBytecode(Runtime::FunctionId function_id);

View File

@ -18,9 +18,9 @@ namespace baseline {
void BaselineCompiler::Prologue() {
DCHECK_EQ(kJSFunctionRegister, kJavaScriptCallTargetRegister);
int max_frame_size = bytecode_->frame_size() + max_call_args_;
CallBuiltin(Builtins::kBaselineOutOfLinePrologue, kContextRegister,
kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
CallBuiltin<Builtins::kBaselineOutOfLinePrologue>(
kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
PrologueFillFrame();
}

View File

@ -7,7 +7,6 @@
#include "src/base/macros.h"
#include "src/baseline/baseline-assembler.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/x64/register-x64.h"
namespace v8 {

View File

@ -18,9 +18,9 @@ namespace baseline {
void BaselineCompiler::Prologue() {
DCHECK_EQ(kJSFunctionRegister, kJavaScriptCallTargetRegister);
int max_frame_size = bytecode_->frame_size() + max_call_args_;
CallBuiltin(Builtins::kBaselineOutOfLinePrologue, kContextRegister,
kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
CallBuiltin<Builtins::kBaselineOutOfLinePrologue>(
kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
max_frame_size, kJavaScriptCallNewTargetRegister, bytecode_);
PrologueFillFrame();
}

View File

@ -6,6 +6,7 @@
#include "src/api/api-arguments.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors-inl.h"
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
#include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/register-configuration.h"

View File

@ -6,6 +6,7 @@
#include "src/api/api-arguments.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors-inl.h"
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
#include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/register-configuration.h"

View File

@ -10,6 +10,7 @@
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/execution/frame-constants.h"
#include "src/heap/factory-inl.h"
#include "src/objects/allocation-site-inl.h"

View File

@ -7,6 +7,7 @@
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/macro-assembler.h"
#include "src/execution/frame-constants.h"
#include "src/heap/memory-chunk.h"

View File

@ -8,6 +8,7 @@
#include "src/base/bits-iterator.h"
#include "src/base/iterator.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors-inl.h"
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
#include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/register-configuration.h"
@ -1458,7 +1459,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// and edi are used as scratch registers.
Generate_InterpreterPushZeroAndArgsAndReturnAddress(
masm, eax, ecx, edx, edi,
InterpreterPushArgsThenConstructDescriptor::kStackArgumentsCount,
InterpreterPushArgsThenConstructDescriptor::GetStackParameterCount(),
&stack_overflow);
// Call the appropriate constructor. eax and ecx already contain intended

View File

@ -8,18 +8,19 @@
#include "src/base/bits-iterator.h"
#include "src/base/iterator.h"
#include "src/codegen/code-factory.h"
#include "src/common/globals.h"
#include "src/objects/code.h"
#include "src/codegen/interface-descriptors-inl.h"
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
#include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/x64/assembler-x64.h"
#include "src/common/globals.h"
#include "src/deoptimizer/deoptimizer.h"
#include "src/execution/frame-constants.h"
#include "src/execution/frames.h"
#include "src/heap/heap-inl.h"
#include "src/logging/counters.h"
#include "src/objects/cell.h"
#include "src/objects/code.h"
#include "src/objects/debug-objects.h"
#include "src/objects/foreign.h"
#include "src/objects/heap-number.h"

View File

@ -0,0 +1,261 @@
// Copyright 2021 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.
#ifndef V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
#define V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
#if V8_TARGET_ARCH_ARM
#include "src/codegen/interface-descriptors.h"
#include "src/execution/frames.h"
namespace v8 {
namespace internal {
constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
auto registers = RegisterArray(r0, r1, r2, r3, r4);
STATIC_ASSERT(registers.size() == kMaxBuiltinRegisterParams);
return registers;
}
// static
constexpr auto RecordWriteDescriptor::registers() {
return RegisterArray(r0, r1, r2, r3, r4, kReturnRegister0);
}
// static
constexpr auto DynamicCheckMapsDescriptor::registers() {
return RegisterArray(r0, r1, r2, r3, cp);
}
// static
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
return RegisterArray(r0, r1, r2, r3, r4, kReturnRegister0);
}
// static
constexpr Register LoadDescriptor::ReceiverRegister() { return r1; }
// static
constexpr Register LoadDescriptor::NameRegister() { return r2; }
// static
constexpr Register LoadDescriptor::SlotRegister() { return r0; }
// static
constexpr Register LoadWithVectorDescriptor::VectorRegister() { return r3; }
// static
constexpr Register
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
return r4;
}
// static
constexpr Register StoreDescriptor::ReceiverRegister() { return r1; }
// static
constexpr Register StoreDescriptor::NameRegister() { return r2; }
// static
constexpr Register StoreDescriptor::ValueRegister() { return r0; }
// static
constexpr Register StoreDescriptor::SlotRegister() { return r4; }
// static
constexpr Register StoreWithVectorDescriptor::VectorRegister() { return r3; }
// static
constexpr Register StoreTransitionDescriptor::MapRegister() { return r5; }
// static
constexpr Register ApiGetterDescriptor::HolderRegister() { return r0; }
// static
constexpr Register ApiGetterDescriptor::CallbackRegister() { return r3; }
// static
constexpr Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
// static
constexpr Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
// static
constexpr Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
return r3;
}
// static
constexpr Register BaselineLeaveFrameDescriptor::WeightRegister() { return r4; }
// static
// static
constexpr Register TypeConversionDescriptor::ArgumentRegister() { return r0; }
// static
constexpr auto TypeofDescriptor::registers() { return RegisterArray(r3); }
// static
constexpr auto CallTrampolineDescriptor::registers() {
// r0 : number of arguments
// r1 : the target to call
return RegisterArray(r1, r0);
}
// static
constexpr auto CallVarargsDescriptor::registers() {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r4 : arguments list length (untagged)
// r2 : arguments list (FixedArray)
return RegisterArray(r1, r0, r4, r2);
}
// static
constexpr auto CallForwardVarargsDescriptor::registers() {
// r0 : number of arguments
// r2 : start index (to support rest parameters)
// r1 : the target to call
return RegisterArray(r1, r0, r2);
}
// static
constexpr auto CallFunctionTemplateDescriptor::registers() {
// r1 : function template info
// r2 : number of arguments (on the stack, not including receiver)
return RegisterArray(r1, r2);
}
// static
constexpr auto CallWithSpreadDescriptor::registers() {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r2 : the object to spread
return RegisterArray(r1, r0, r2);
}
// static
constexpr auto CallWithArrayLikeDescriptor::registers() {
// r1 : the target to call
// r2 : the arguments list
return RegisterArray(r1, r2);
}
// static
constexpr auto ConstructVarargsDescriptor::registers() {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r3 : the new target
// r4 : arguments list length (untagged)
// r2 : arguments list (FixedArray)
return RegisterArray(r1, r3, r0, r4, r2);
}
// static
constexpr auto ConstructForwardVarargsDescriptor::registers() {
// r0 : number of arguments
// r3 : the new target
// r2 : start index (to support rest parameters)
// r1 : the target to call
return RegisterArray(r1, r3, r0, r2);
}
// static
constexpr auto ConstructWithSpreadDescriptor::registers() {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r3 : the new target
// r2 : the object to spread
return RegisterArray(r1, r3, r0, r2);
}
// static
constexpr auto ConstructWithArrayLikeDescriptor::registers() {
// r1 : the target to call
// r3 : the new target
// r2 : the arguments list
return RegisterArray(r1, r3, r2);
}
// static
constexpr auto ConstructStubDescriptor::registers() {
// r0 : number of arguments
// r1 : the target to call
// r3 : the new target
// r2 : allocation site or undefined
return RegisterArray(r1, r3, r0, r2);
}
// static
constexpr auto AbortDescriptor::registers() { return RegisterArray(r1); }
// static
constexpr auto CompareDescriptor::registers() { return RegisterArray(r1, r0); }
// static
constexpr auto Compare_BaselineDescriptor::registers() {
// r1: left operand
// r0: right operand
// r2: feedback slot
return RegisterArray(r1, r0, r2);
}
// static
constexpr auto BinaryOpDescriptor::registers() { return RegisterArray(r1, r0); }
// static
constexpr auto BinaryOp_BaselineDescriptor::registers() {
// r1: left operand
// r0: right operand
// r2: feedback slot
return RegisterArray(r1, r0, r2);
}
// static
constexpr auto ApiCallbackDescriptor::registers() {
return RegisterArray(r1, // kApiFunctionAddress
r2, // kArgc
r3, // kCallData
r0); // kHolder
}
// static
constexpr auto InterpreterDispatchDescriptor::registers() {
return RegisterArray(
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister);
}
// static
constexpr auto InterpreterPushArgsThenCallDescriptor::registers() {
return RegisterArray(r0, // argument count (not including receiver)
r2, // address of first argument
r1); // the target callable to be call
}
// static
constexpr auto InterpreterPushArgsThenConstructDescriptor::registers() {
return RegisterArray(
r0, // argument count (not including receiver)
r4, // address of the first argument
r1, // constructor to call
r3, // new target
r2); // allocation site feedback if available, undefined otherwise
}
// static
constexpr auto ResumeGeneratorDescriptor::registers() {
return RegisterArray(r0, // the value to pass to the generator
r1); // the JSGeneratorObject to resume
}
// static
constexpr auto FrameDropperTrampolineDescriptor::registers() {
return RegisterArray(r1); // loaded new FP
}
// static
constexpr auto RunMicrotasksEntryDescriptor::registers() {
return RegisterArray(r0, r1);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_ARM
#endif // V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_

View File

@ -1,306 +0,0 @@
// 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_ARM
#include "src/codegen/interface-descriptors.h"
#include "src/execution/frames.h"
namespace v8 {
namespace internal {
const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
CallInterfaceDescriptorData* data, int register_parameter_count) {
const Register default_stub_registers[] = {r0, r1, r2, r3, r4};
CHECK_LE(static_cast<size_t>(register_parameter_count),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(register_parameter_count,
default_stub_registers);
}
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
const Register default_stub_registers[] = {r0, r1, r2, r3, r4};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void DynamicCheckMapsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register default_stub_registers[] = {r0, r1, r2, r3, cp};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void EphemeronKeyBarrierDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
const Register default_stub_registers[] = {r0, r1, r2, r3, r4};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
const Register LoadDescriptor::ReceiverRegister() { return r1; }
const Register LoadDescriptor::NameRegister() { return r2; }
const Register LoadDescriptor::SlotRegister() { return r0; }
const Register LoadWithVectorDescriptor::VectorRegister() { return r3; }
const Register
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
return r4;
}
const Register StoreDescriptor::ReceiverRegister() { return r1; }
const Register StoreDescriptor::NameRegister() { return r2; }
const Register StoreDescriptor::ValueRegister() { return r0; }
const Register StoreDescriptor::SlotRegister() { return r4; }
const Register StoreWithVectorDescriptor::VectorRegister() { return r3; }
const Register StoreTransitionDescriptor::SlotRegister() { return r4; }
const Register StoreTransitionDescriptor::VectorRegister() { return r3; }
const Register StoreTransitionDescriptor::MapRegister() { return r5; }
const Register ApiGetterDescriptor::HolderRegister() { return r0; }
const Register ApiGetterDescriptor::CallbackRegister() { return r3; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
const Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() { return r3; }
const Register BaselineLeaveFrameDescriptor::WeightRegister() { return r4; }
// static
const Register TypeConversionDescriptor::ArgumentRegister() { return r0; }
void TypeofDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments
// r1 : the target to call
Register registers[] = {r1, r0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r4 : arguments list length (untagged)
// r2 : arguments list (FixedArray)
Register registers[] = {r1, r0, r4, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments
// r2 : start index (to support rest parameters)
// r1 : the target to call
Register registers[] = {r1, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionTemplateDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r1 : function template info
// r2 : number of arguments (on the stack, not including receiver)
Register registers[] = {r1, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r2 : the object to spread
Register registers[] = {r1, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r1 : the target to call
// r2 : the arguments list
Register registers[] = {r1, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r3 : the new target
// r4 : arguments list length (untagged)
// r2 : arguments list (FixedArray)
Register registers[] = {r1, r3, r0, r4, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments
// r3 : the new target
// r2 : start index (to support rest parameters)
// r1 : the target to call
Register registers[] = {r1, r3, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments (on the stack, not including receiver)
// r1 : the target to call
// r3 : the new target
// r2 : the object to spread
Register registers[] = {r1, r3, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r1 : the target to call
// r3 : the new target
// r2 : the arguments list
Register registers[] = {r1, r3, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments
// r1 : the target to call
// r3 : the new target
// r2 : allocation site or undefined
Register registers[] = {r1, r3, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void AbortDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CompareDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r1, r0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void Compare_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r1: left operand
// r0: right operand
// r2: feedback slot
Register registers[] = {r1, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r1, r0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOp_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r1: left operand
// r0: right operand
// r2: feedback slot
Register registers[] = {r1, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ApiCallbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r1, // kApiFunctionAddress
r2, // kArgc
r3, // kCallData
r0, // kHolder
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r0, // argument count (not including receiver)
r2, // address of first argument
r1 // the target callable to be call
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r0, // argument count (not including receiver)
r4, // address of the first argument
r1, // constructor to call
r3, // new target
r2, // allocation site feedback if available, undefined otherwise
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ResumeGeneratorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r0, // the value to pass to the generator
r1 // the JSGeneratorObject to resume
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r1, // loaded new FP
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void RunMicrotasksEntryDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r0, r1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_ARM

View File

@ -13,6 +13,7 @@
#include "src/codegen/callable.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/external-reference-table.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/macro-assembler.h"
#include "src/codegen/register-configuration.h"
#include "src/debug/debug.h"

View File

@ -0,0 +1,270 @@
// Copyright 2021 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.
#ifndef V8_CODEGEN_ARM64_INTERFACE_DESCRIPTORS_ARM64_INL_H_
#define V8_CODEGEN_ARM64_INTERFACE_DESCRIPTORS_ARM64_INL_H_
#if V8_TARGET_ARCH_ARM64
#include "src/base/template-utils.h"
#include "src/codegen/interface-descriptors.h"
#include "src/execution/frames.h"
namespace v8 {
namespace internal {
constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
auto registers = RegisterArray(x0, x1, x2, x3, x4);
STATIC_ASSERT(registers.size() == kMaxBuiltinRegisterParams);
return registers;
}
// static
constexpr auto RecordWriteDescriptor::registers() {
return RegisterArray(x0, x1, x2, x3, x4, kReturnRegister0);
}
// static
constexpr auto DynamicCheckMapsDescriptor::registers() {
return RegisterArray(x0, x1, x2, x3, cp);
}
// static
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
return RegisterArray(x0, x1, x2, x3, x4, kReturnRegister0);
}
// static
constexpr Register LoadDescriptor::ReceiverRegister() { return x1; }
// static
constexpr Register LoadDescriptor::NameRegister() { return x2; }
// static
constexpr Register LoadDescriptor::SlotRegister() { return x0; }
// static
constexpr Register LoadWithVectorDescriptor::VectorRegister() { return x3; }
// static
constexpr Register
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
return x4;
}
// static
constexpr Register StoreDescriptor::ReceiverRegister() { return x1; }
// static
constexpr Register StoreDescriptor::NameRegister() { return x2; }
// static
constexpr Register StoreDescriptor::ValueRegister() { return x0; }
// static
constexpr Register StoreDescriptor::SlotRegister() { return x4; }
// static
constexpr Register StoreWithVectorDescriptor::VectorRegister() { return x3; }
// static
constexpr Register StoreTransitionDescriptor::MapRegister() { return x5; }
// static
constexpr Register ApiGetterDescriptor::HolderRegister() { return x0; }
// static
constexpr Register ApiGetterDescriptor::CallbackRegister() { return x3; }
// static
constexpr Register GrowArrayElementsDescriptor::ObjectRegister() { return x0; }
// static
constexpr Register GrowArrayElementsDescriptor::KeyRegister() { return x3; }
// static
constexpr Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
return x3;
}
// static
constexpr Register BaselineLeaveFrameDescriptor::WeightRegister() { return x4; }
// static
// static
constexpr Register TypeConversionDescriptor::ArgumentRegister() { return x0; }
// static
constexpr auto TypeofDescriptor::registers() { return RegisterArray(x3); }
// static
constexpr auto CallTrampolineDescriptor::registers() {
// x1: target
// x0: number of arguments
return RegisterArray(x1, x0);
}
// static
constexpr auto CallVarargsDescriptor::registers() {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x4 : arguments list length (untagged)
// x2 : arguments list (FixedArray)
return RegisterArray(x1, x0, x4, x2);
}
// static
constexpr auto CallForwardVarargsDescriptor::registers() {
// x1: target
// x0: number of arguments
// x2: start index (to supported rest parameters)
return RegisterArray(x1, x0, x2);
}
// static
constexpr auto CallFunctionTemplateDescriptor::registers() {
// x1 : function template info
// x2 : number of arguments (on the stack, not including receiver)
return RegisterArray(x1, x2);
}
// static
constexpr auto CallWithSpreadDescriptor::registers() {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x2 : the object to spread
return RegisterArray(x1, x0, x2);
}
// static
constexpr auto CallWithArrayLikeDescriptor::registers() {
// x1 : the target to call
// x2 : the arguments list
return RegisterArray(x1, x2);
}
// static
constexpr auto ConstructVarargsDescriptor::registers() {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x3 : the new target
// x4 : arguments list length (untagged)
// x2 : arguments list (FixedArray)
return RegisterArray(x1, x3, x0, x4, x2);
}
// static
constexpr auto ConstructForwardVarargsDescriptor::registers() {
// x3: new target
// x1: target
// x0: number of arguments
// x2: start index (to supported rest parameters)
return RegisterArray(x1, x3, x0, x2);
}
// static
constexpr auto ConstructWithSpreadDescriptor::registers() {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x3 : the new target
// x2 : the object to spread
return RegisterArray(x1, x3, x0, x2);
}
// static
constexpr auto ConstructWithArrayLikeDescriptor::registers() {
// x1 : the target to call
// x3 : the new target
// x2 : the arguments list
return RegisterArray(x1, x3, x2);
}
// static
constexpr auto ConstructStubDescriptor::registers() {
// x3: new target
// x1: target
// x0: number of arguments
// x2: allocation site or undefined
return RegisterArray(x1, x3, x0, x2);
}
// static
constexpr auto AbortDescriptor::registers() { return RegisterArray(x1); }
// static
constexpr auto CompareDescriptor::registers() {
// x1: left operand
// x0: right operand
return RegisterArray(x1, x0);
}
// static
constexpr auto Compare_BaselineDescriptor::registers() {
// x1: left operand
// x0: right operand
// x2: feedback slot
return RegisterArray(x1, x0, x2);
}
// static
constexpr auto BinaryOpDescriptor::registers() {
// x1: left operand
// x0: right operand
return RegisterArray(x1, x0);
}
// static
constexpr auto BinaryOp_BaselineDescriptor::registers() {
// x1: left operand
// x0: right operand
// x2: feedback slot
return RegisterArray(x1, x0, x2);
}
// static
constexpr auto ApiCallbackDescriptor::registers() {
return RegisterArray(x1, // kApiFunctionAddress
x2, // kArgc
x3, // kCallData
x0); // kHolder
}
// static
constexpr auto InterpreterDispatchDescriptor::registers() {
return RegisterArray(
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister);
}
// static
constexpr auto InterpreterPushArgsThenCallDescriptor::registers() {
return RegisterArray(x0, // argument count (not including receiver)
x2, // address of first argument
x1); // the target callable to be call
}
// static
constexpr auto InterpreterPushArgsThenConstructDescriptor::registers() {
return RegisterArray(
x0, // argument count (not including receiver)
x4, // address of the first argument
x1, // constructor to call
x3, // new target
x2); // allocation site feedback if available, undefined otherwise
}
// static
constexpr auto ResumeGeneratorDescriptor::registers() {
return RegisterArray(x0, // the value to pass to the generator
x1); // the JSGeneratorObject to resume
}
// static
constexpr auto FrameDropperTrampolineDescriptor::registers() {
return RegisterArray(x1); // loaded new FP
}
// static
constexpr auto RunMicrotasksEntryDescriptor::registers() {
return RegisterArray(x0, x1);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_ARM64
#endif // V8_CODEGEN_ARM64_INTERFACE_DESCRIPTORS_ARM64_INL_H_

View File

@ -1,310 +0,0 @@
// 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_ARM64
#include "src/codegen/interface-descriptors.h"
#include "src/execution/frames.h"
namespace v8 {
namespace internal {
const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
CallInterfaceDescriptorData* data, int register_parameter_count) {
const Register default_stub_registers[] = {x0, x1, x2, x3, x4};
CHECK_LE(static_cast<size_t>(register_parameter_count),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(register_parameter_count,
default_stub_registers);
}
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
const Register default_stub_registers[] = {x0, x1, x2, x3, x4};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void DynamicCheckMapsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register default_stub_registers[] = {x0, x1, x2, x3, cp};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void EphemeronKeyBarrierDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
const Register default_stub_registers[] = {x0, x1, x2, x3, x4};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
const Register LoadDescriptor::ReceiverRegister() { return x1; }
const Register LoadDescriptor::NameRegister() { return x2; }
const Register LoadDescriptor::SlotRegister() { return x0; }
const Register LoadWithVectorDescriptor::VectorRegister() { return x3; }
const Register
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
return x4;
}
const Register StoreDescriptor::ReceiverRegister() { return x1; }
const Register StoreDescriptor::NameRegister() { return x2; }
const Register StoreDescriptor::ValueRegister() { return x0; }
const Register StoreDescriptor::SlotRegister() { return x4; }
const Register StoreWithVectorDescriptor::VectorRegister() { return x3; }
const Register StoreTransitionDescriptor::SlotRegister() { return x4; }
const Register StoreTransitionDescriptor::VectorRegister() { return x3; }
const Register StoreTransitionDescriptor::MapRegister() { return x5; }
const Register ApiGetterDescriptor::HolderRegister() { return x0; }
const Register ApiGetterDescriptor::CallbackRegister() { return x3; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return x0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return x3; }
const Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() { return x3; }
const Register BaselineLeaveFrameDescriptor::WeightRegister() { return x4; }
// static
const Register TypeConversionDescriptor::ArgumentRegister() { return x0; }
void TypeofDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {x3};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1: target
// x0: number of arguments
Register registers[] = {x1, x0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x4 : arguments list length (untagged)
// x2 : arguments list (FixedArray)
Register registers[] = {x1, x0, x4, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1: target
// x0: number of arguments
// x2: start index (to supported rest parameters)
Register registers[] = {x1, x0, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionTemplateDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1 : function template info
// x2 : number of arguments (on the stack, not including receiver)
Register registers[] = {x1, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x2 : the object to spread
Register registers[] = {x1, x0, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1 : the target to call
// x2 : the arguments list
Register registers[] = {x1, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x3 : the new target
// x4 : arguments list length (untagged)
// x2 : arguments list (FixedArray)
Register registers[] = {x1, x3, x0, x4, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x3: new target
// x1: target
// x0: number of arguments
// x2: start index (to supported rest parameters)
Register registers[] = {x1, x3, x0, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x0 : number of arguments (on the stack, not including receiver)
// x1 : the target to call
// x3 : the new target
// x2 : the object to spread
Register registers[] = {x1, x3, x0, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1 : the target to call
// x3 : the new target
// x2 : the arguments list
Register registers[] = {x1, x3, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x3: new target
// x1: target
// x0: number of arguments
// x2: allocation site or undefined
Register registers[] = {x1, x3, x0, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void AbortDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {x1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CompareDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1: left operand
// x0: right operand
Register registers[] = {x1, x0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void Compare_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1: left operand
// x0: right operand
// x2: feedback slot
Register registers[] = {x1, x0, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1: left operand
// x0: right operand
Register registers[] = {x1, x0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOp_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1: left operand
// x0: right operand
// x2: feedback slot
Register registers[] = {x1, x0, x2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ApiCallbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
x1, // kApiFunctionAddress
x2, // kArgc
x3, // kCallData
x0, // kHolder
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
x0, // argument count (not including receiver)
x2, // address of first argument
x1 // the target callable to be call
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
x0, // argument count (not including receiver)
x4, // address of the first argument
x1, // constructor to call
x3, // new target
x2, // allocation site feedback if available, undefined otherwise
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ResumeGeneratorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
x0, // the value to pass to the generator
x1 // the JSGeneratorObject to resume
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
x1, // loaded new FP
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void RunMicrotasksEntryDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {x0, x1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_ARM64

View File

@ -10,6 +10,7 @@
#include "src/codegen/callable.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/external-reference-table.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/reloc-info.h"

View File

@ -0,0 +1,272 @@
// Copyright 2021 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.
#ifndef V8_CODEGEN_IA32_INTERFACE_DESCRIPTORS_IA32_INL_H_
#define V8_CODEGEN_IA32_INTERFACE_DESCRIPTORS_IA32_INL_H_
#if V8_TARGET_ARCH_IA32
#include "src/codegen/interface-descriptors.h"
namespace v8 {
namespace internal {
constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
auto registers = RegisterArray(eax, ecx, edx, edi);
STATIC_ASSERT(registers.size() == kMaxBuiltinRegisterParams);
return registers;
}
// static
constexpr auto RecordWriteDescriptor::registers() {
return RegisterArray(ecx, edx, esi, edi, kReturnRegister0);
}
// static
constexpr auto DynamicCheckMapsDescriptor::registers() {
return RegisterArray(eax, ecx, edx, edi, esi);
}
// static
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
return RegisterArray(ecx, edx, esi, edi, kReturnRegister0);
}
// static
constexpr Register LoadDescriptor::ReceiverRegister() { return edx; }
// static
constexpr Register LoadDescriptor::NameRegister() { return ecx; }
// static
constexpr Register LoadDescriptor::SlotRegister() { return eax; }
// static
constexpr Register LoadWithVectorDescriptor::VectorRegister() { return no_reg; }
// static
constexpr Register
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
return edi;
}
// static
constexpr Register StoreDescriptor::ReceiverRegister() { return edx; }
// static
constexpr Register StoreDescriptor::NameRegister() { return ecx; }
// static
constexpr Register StoreDescriptor::ValueRegister() { return no_reg; }
// static
constexpr Register StoreDescriptor::SlotRegister() { return no_reg; }
// static
constexpr Register StoreWithVectorDescriptor::VectorRegister() {
return no_reg;
}
// static
constexpr Register StoreTransitionDescriptor::MapRegister() { return edi; }
// static
constexpr Register ApiGetterDescriptor::HolderRegister() { return ecx; }
// static
constexpr Register ApiGetterDescriptor::CallbackRegister() { return eax; }
// static
constexpr Register GrowArrayElementsDescriptor::ObjectRegister() { return eax; }
// static
constexpr Register GrowArrayElementsDescriptor::KeyRegister() { return ecx; }
// static
constexpr Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
return esi;
}
// static
constexpr Register BaselineLeaveFrameDescriptor::WeightRegister() {
return edi;
}
// static
constexpr Register TypeConversionDescriptor::ArgumentRegister() { return eax; }
// static
constexpr auto TypeofDescriptor::registers() { return RegisterArray(ecx); }
// static
constexpr auto CallTrampolineDescriptor::registers() {
// eax : number of arguments
// edi : the target to call
return RegisterArray(edi, eax);
}
// static
constexpr auto CallVarargsDescriptor::registers() {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// ecx : arguments list length (untagged)
// On the stack : arguments list (FixedArray)
return RegisterArray(edi, eax, ecx);
}
// static
constexpr auto CallForwardVarargsDescriptor::registers() {
// eax : number of arguments
// ecx : start index (to support rest parameters)
// edi : the target to call
return RegisterArray(edi, eax, ecx);
}
// static
constexpr auto CallFunctionTemplateDescriptor::registers() {
// edx : function template info
// ecx : number of arguments (on the stack, not including receiver)
return RegisterArray(edx, ecx);
}
// static
constexpr auto CallWithSpreadDescriptor::registers() {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// ecx : the object to spread
return RegisterArray(edi, eax, ecx);
}
// static
constexpr auto CallWithArrayLikeDescriptor::registers() {
// edi : the target to call
// edx : the arguments list
return RegisterArray(edi, edx);
}
// static
constexpr auto ConstructVarargsDescriptor::registers() {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// edx : the new target
// ecx : arguments list length (untagged)
// On the stack : arguments list (FixedArray)
return RegisterArray(edi, edx, eax, ecx);
}
// static
constexpr auto ConstructForwardVarargsDescriptor::registers() {
// eax : number of arguments
// edx : the new target
// ecx : start index (to support rest parameters)
// edi : the target to call
return RegisterArray(edi, edx, eax, ecx);
}
// static
constexpr auto ConstructWithSpreadDescriptor::registers() {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// edx : the new target
// ecx : the object to spread
return RegisterArray(edi, edx, eax, ecx);
}
// static
constexpr auto ConstructWithArrayLikeDescriptor::registers() {
// edi : the target to call
// edx : the new target
// ecx : the arguments list
return RegisterArray(edi, edx, ecx);
}
// static
constexpr auto ConstructStubDescriptor::registers() {
// eax : number of arguments
// edx : the new target
// edi : the target to call
// ecx : allocation site or undefined
// TODO(jgruber): Remove the unused allocation site parameter.
return RegisterArray(edi, edx, eax, ecx);
}
// static
constexpr auto AbortDescriptor::registers() { return RegisterArray(edx); }
// static
constexpr auto CompareDescriptor::registers() {
return RegisterArray(edx, eax);
}
// static
constexpr auto Compare_BaselineDescriptor::registers() {
return RegisterArray(edx, eax, ecx);
}
// static
constexpr auto BinaryOpDescriptor::registers() {
return RegisterArray(edx, eax);
}
// static
constexpr auto BinaryOp_BaselineDescriptor::registers() {
return RegisterArray(edx, eax, ecx);
}
// static
constexpr auto ApiCallbackDescriptor::registers() {
return RegisterArray(edx, // kApiFunctionAddress
ecx, // kArgc
eax, // kCallData
edi); // kHolder
}
// static
constexpr auto InterpreterDispatchDescriptor::registers() {
return RegisterArray(
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister);
}
// static
constexpr auto InterpreterPushArgsThenCallDescriptor::registers() {
return RegisterArray(eax, // argument count (not including receiver)
ecx, // address of first argument
edi); // the target callable to be call
}
// static
constexpr auto InterpreterPushArgsThenConstructDescriptor::registers() {
return RegisterArray(eax, // argument count (not including receiver)
ecx); // address of first argument
}
// static
constexpr auto ResumeGeneratorDescriptor::registers() {
return RegisterArray(eax, // the value to pass to the generator
edx); // the JSGeneratorObject to resume
}
// static
constexpr auto FrameDropperTrampolineDescriptor::registers() {
return RegisterArray(eax); // loaded new FP
}
// static
constexpr auto RunMicrotasksEntryDescriptor::registers() {
return RegisterArray();
}
// static
constexpr auto WasmFloat32ToNumberDescriptor::registers() {
// Work around using eax, whose register code is 0, and leads to the FP
// parameter being passed via xmm0, which is not allocatable on ia32.
return RegisterArray(ecx);
}
// static
constexpr auto WasmFloat64ToNumberDescriptor::registers() {
// Work around using eax, whose register code is 0, and leads to the FP
// parameter being passed via xmm0, which is not allocatable on ia32.
return RegisterArray(ecx);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_IA32
#endif // V8_CODEGEN_IA32_INTERFACE_DESCRIPTORS_IA32_INL_H_

View File

@ -1,318 +0,0 @@
// 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_IA32
#include "src/codegen/interface-descriptors.h"
#include "src/execution/frames.h"
namespace v8 {
namespace internal {
const Register CallInterfaceDescriptor::ContextRegister() { return esi; }
void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
CallInterfaceDescriptorData* data, int register_parameter_count) {
constexpr Register default_stub_registers[] = {eax, ecx, edx, edi};
STATIC_ASSERT(arraysize(default_stub_registers) == kMaxBuiltinRegisterParams);
CHECK_LE(static_cast<size_t>(register_parameter_count),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(register_parameter_count,
default_stub_registers);
}
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
static const Register default_stub_registers[] = {ecx, edx, esi, edi,
kReturnRegister0};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void DynamicCheckMapsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register default_stub_registers[] = {eax, ecx, edx, edi, esi};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void EphemeronKeyBarrierDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
static const Register default_stub_registers[] = {ecx, edx, esi, edi,
kReturnRegister0};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
const Register LoadDescriptor::ReceiverRegister() { return edx; }
const Register LoadDescriptor::NameRegister() { return ecx; }
const Register LoadDescriptor::SlotRegister() { return eax; }
const Register LoadWithVectorDescriptor::VectorRegister() { return no_reg; }
const Register
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
return edi;
}
const Register StoreDescriptor::ReceiverRegister() { return edx; }
const Register StoreDescriptor::NameRegister() { return ecx; }
const Register StoreDescriptor::ValueRegister() { return no_reg; }
const Register StoreDescriptor::SlotRegister() { return no_reg; }
const Register StoreWithVectorDescriptor::VectorRegister() { return no_reg; }
const Register StoreTransitionDescriptor::SlotRegister() { return no_reg; }
const Register StoreTransitionDescriptor::VectorRegister() { return no_reg; }
const Register StoreTransitionDescriptor::MapRegister() { return edi; }
const Register ApiGetterDescriptor::HolderRegister() { return ecx; }
const Register ApiGetterDescriptor::CallbackRegister() { return eax; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return eax; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return ecx; }
const Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
return esi;
}
const Register BaselineLeaveFrameDescriptor::WeightRegister() { return edi; }
// static
const Register TypeConversionDescriptor::ArgumentRegister() { return eax; }
void TypeofDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
// edi : the target to call
Register registers[] = {edi, eax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// ecx : arguments list length (untagged)
// On the stack : arguments list (FixedArray)
Register registers[] = {edi, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
// ecx : start index (to support rest parameters)
// edi : the target to call
Register registers[] = {edi, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionTemplateDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// edx : function template info
// ecx : number of arguments (on the stack, not including receiver)
Register registers[] = {edx, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// ecx : the object to spread
Register registers[] = {edi, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// edi : the target to call
// edx : the arguments list
Register registers[] = {edi, edx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// edx : the new target
// ecx : arguments list length (untagged)
// On the stack : arguments list (FixedArray)
Register registers[] = {edi, edx, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
// edx : the new target
// ecx : start index (to support rest parameters)
// edi : the target to call
Register registers[] = {edi, edx, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments (on the stack, not including receiver)
// edi : the target to call
// edx : the new target
// ecx : the object to spread
Register registers[] = {edi, edx, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// edi : the target to call
// edx : the new target
// ecx : the arguments list
Register registers[] = {edi, edx, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
// edx : the new target
// edi : the target to call
// ecx : allocation site or undefined
// TODO(jgruber): Remove the unused allocation site parameter.
Register registers[] = {edi, edx, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void AbortDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {edx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CompareDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {edx, eax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void Compare_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {edx, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {edx, eax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOp_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {edx, eax, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ApiCallbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
edx, // kApiFunctionAddress
ecx, // kArgc
eax, // kCallData
edi, // kHolder
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
eax, // argument count (not including receiver)
ecx, // address of first argument
edi // the target callable to be call
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
eax, // argument count (not including receiver)
ecx, // address of first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ResumeGeneratorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
eax, // the value to pass to the generator
edx // the JSGeneratorObject to resume
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
eax, // loaded new FP
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void RunMicrotasksEntryDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
data->InitializePlatformSpecific(0, nullptr);
}
void WasmFloat32ToNumberDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// Work around using eax, whose register code is 0, and leads to the FP
// parameter being passed via xmm0, which is not allocatable on ia32.
Register registers[] = {ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void WasmFloat64ToNumberDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// Work around using eax, whose register code is 0, and leads to the FP
// parameter being passed via xmm0, which is not allocatable on ia32.
Register registers[] = {ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_IA32

View File

@ -19,7 +19,7 @@
#include "src/codegen/external-reference.h"
#include "src/codegen/ia32/assembler-ia32.h"
#include "src/codegen/ia32/register-ia32.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/label.h"
#include "src/codegen/macro-assembler.h"
#include "src/codegen/register.h"

View File

@ -0,0 +1,471 @@
// Copyright 2021 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.
#ifndef V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_
#define V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_
#include <utility>
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/register-arch.h"
#if V8_TARGET_ARCH_X64
#include "src/codegen/x64/interface-descriptors-x64-inl.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/codegen/arm64/interface-descriptors-arm64-inl.h"
#elif V8_TARGET_ARCH_IA32
#include "src/codegen/ia32/interface-descriptors-ia32-inl.h"
#elif V8_TARGET_ARCH_ARM
#include "src/codegen/arm/interface-descriptors-arm-inl.h"
#else
#error Unsupported target architecture.
#endif
namespace v8 {
namespace internal {
// static
constexpr std::array<Register, kJSBuiltinRegisterParams>
CallInterfaceDescriptor::DefaultJSRegisterArray() {
return RegisterArray(
kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register);
}
// static
template <typename DerivedDescriptor>
constexpr auto StaticCallInterfaceDescriptor<DerivedDescriptor>::registers() {
return CallInterfaceDescriptor::DefaultRegisterArray();
}
// static
template <typename DerivedDescriptor>
constexpr auto StaticJSCallInterfaceDescriptor<DerivedDescriptor>::registers() {
return CallInterfaceDescriptor::DefaultJSRegisterArray();
}
template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::Initialize(
CallInterfaceDescriptorData* data) {
// Static local copy of the Registers array, for platform-specific
// initialization
static auto registers = DerivedDescriptor::registers();
// The passed pointer should be a modifiable pointer to our own data.
DCHECK_EQ(data, this->data());
DCHECK(!data->IsInitialized());
if (DerivedDescriptor::kRestrictAllocatableRegisters) {
data->RestrictAllocatableRegisters(registers.data(), registers.size());
}
data->InitializeRegisters(
DerivedDescriptor::flags(), DerivedDescriptor::kReturnCount,
DerivedDescriptor::GetParameterCount(),
DerivedDescriptor::kStackArgumentOrder,
DerivedDescriptor::GetRegisterParameterCount(), registers.data());
// InitializeTypes is customizable by the DerivedDescriptor subclass.
DerivedDescriptor::InitializeTypes(data);
DCHECK(data->IsInitialized());
DCHECK(this->CheckFloatingPointParameters(data));
}
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetReturnCount() {
static_assert(
DerivedDescriptor::kReturnCount >= 0,
"DerivedDescriptor subclass should override return count with a value "
"that is greater than 0");
return DerivedDescriptor::kReturnCount;
}
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetParameterCount() {
static_assert(
DerivedDescriptor::kParameterCount >= 0,
"DerivedDescriptor subclass should override parameter count with a "
"value that is greater than 0");
return DerivedDescriptor::kParameterCount;
}
namespace detail {
// Helper trait for statically checking if a type is a std::array<Register,N>.
template <typename T>
struct IsRegisterArray : std::false_type {};
template <int i>
struct IsRegisterArray<std::array<Register, i>> : std::true_type {};
template <>
struct IsRegisterArray<EmptyRegisterArray> : std::true_type {};
// Helper for finding the index of the first invalid register in a register
// array.
template <size_t N, size_t Index>
struct FirstInvalidRegisterHelper {
static constexpr int Call(std::array<Register, N> regs) {
if (!std::get<Index>(regs).is_valid()) {
// All registers after the first invalid one have to also be invalid (this
// DCHECK will be checked recursively).
CONSTEXPR_DCHECK((FirstInvalidRegisterHelper<N, Index + 1>::Call(regs)) ==
Index + 1);
return Index;
}
return FirstInvalidRegisterHelper<N, Index + 1>::Call(regs);
}
};
template <size_t N>
struct FirstInvalidRegisterHelper<N, N> {
static constexpr int Call(std::array<Register, N> regs) { return N; }
};
template <size_t N, size_t Index = 0>
constexpr size_t FirstInvalidRegister(std::array<Register, N> regs) {
return FirstInvalidRegisterHelper<N, 0>::Call(regs);
}
constexpr size_t FirstInvalidRegister(EmptyRegisterArray regs) { return 0; }
} // namespace detail
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetRegisterParameterCount() {
static_assert(
detail::IsRegisterArray<decltype(DerivedDescriptor::registers())>::value,
"DerivedDescriptor subclass should define a registers() function "
"returning a std::array<Register>");
// The register parameter count is the minimum of:
// 1. The number of named parameters in the descriptor, and
// 2. The number of valid registers the descriptor provides with its
// registers() function, e.g. for {rax, rbx, no_reg} this number is 2.
// 3. The maximum number of register parameters allowed (
// kMaxBuiltinRegisterParams for most builtins,
// kMaxTFSBuiltinRegisterParams for TFS builtins, customizable by the
// subclass otherwise).
return std::min<int>({DerivedDescriptor::GetParameterCount(),
static_cast<int>(detail::FirstInvalidRegister(
DerivedDescriptor::registers())),
DerivedDescriptor::kMaxRegisterParams});
}
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetStackParameterCount() {
return DerivedDescriptor::GetParameterCount() -
DerivedDescriptor::GetRegisterParameterCount();
}
// static
constexpr Register FastNewObjectDescriptor::TargetRegister() {
return kJSFunctionRegister;
}
// static
constexpr Register FastNewObjectDescriptor::NewTargetRegister() {
return kJavaScriptCallNewTargetRegister;
}
// static
constexpr Register ApiGetterDescriptor::ReceiverRegister() {
return LoadDescriptor::ReceiverRegister();
}
// static
constexpr Register LoadGlobalNoFeedbackDescriptor::ICKindRegister() {
return LoadDescriptor::SlotRegister();
}
// static
constexpr Register LoadNoFeedbackDescriptor::ICKindRegister() {
return LoadGlobalNoFeedbackDescriptor::ICKindRegister();
}
#if V8_TARGET_ARCH_IA32
// On ia32, LoadWithVectorDescriptor passes vector on the stack and thus we
// need to choose a new register here.
// static
constexpr Register LoadGlobalWithVectorDescriptor::VectorRegister() {
STATIC_ASSERT(!LoadWithVectorDescriptor::VectorRegister().is_valid());
return LoadDescriptor::ReceiverRegister();
}
#else
// static
constexpr Register LoadGlobalWithVectorDescriptor::VectorRegister() {
return LoadWithVectorDescriptor::VectorRegister();
}
#endif
// static
constexpr auto LoadDescriptor::registers() {
return RegisterArray(ReceiverRegister(), NameRegister(), SlotRegister());
}
// static
constexpr auto LoadBaselineDescriptor::registers() {
return LoadDescriptor::registers();
}
// static
constexpr auto LoadGlobalDescriptor::registers() {
return RegisterArray(LoadDescriptor::NameRegister(),
LoadDescriptor::SlotRegister());
}
// static
constexpr auto LoadGlobalBaselineDescriptor::registers() {
return LoadGlobalDescriptor::registers();
}
// static
constexpr auto StoreDescriptor::registers() {
return RegisterArray(ReceiverRegister(), NameRegister(), ValueRegister(),
SlotRegister());
}
// static
constexpr auto StoreBaselineDescriptor::registers() {
return StoreDescriptor::registers();
}
// static
constexpr auto StoreGlobalDescriptor::registers() {
return RegisterArray(StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister());
}
// static
constexpr auto StoreGlobalBaselineDescriptor::registers() {
return StoreGlobalDescriptor::registers();
}
// static
constexpr auto LoadWithReceiverBaselineDescriptor::registers() {
return RegisterArray(
LoadDescriptor::ReceiverRegister(),
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister(),
LoadDescriptor::NameRegister(), LoadDescriptor::SlotRegister());
}
// static
constexpr auto BaselineOutOfLinePrologueDescriptor::registers() {
// TODO(v8:11421): Implement on other platforms.
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32 || \
V8_TARGET_ARCH_ARM
return RegisterArray(
kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
kJavaScriptCallExtraArg1Register, kJavaScriptCallNewTargetRegister,
kInterpreterBytecodeArrayRegister);
#else
return DefaultRegisterArray();
#endif
}
// static
constexpr auto BaselineLeaveFrameDescriptor::registers() {
// TODO(v8:11421): Implement on other platforms.
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || \
V8_TARGET_ARCH_ARM
return RegisterArray(ParamsSizeRegister(), WeightRegister());
#else
return DefaultRegisterArray();
#endif
}
// static
constexpr auto VoidDescriptor::registers() { return RegisterArray(); }
// static
constexpr auto AllocateDescriptor::registers() {
return RegisterArray(kAllocateSizeRegister);
}
// static
constexpr auto CEntry1ArgvOnStackDescriptor::registers() {
return RegisterArray(kRuntimeCallArgCountRegister,
kRuntimeCallFunctionRegister);
}
// static
constexpr auto InterpreterCEntry1Descriptor::registers() {
return RegisterArray(kRuntimeCallArgCountRegister, kRuntimeCallArgvRegister,
kRuntimeCallFunctionRegister);
}
// static
constexpr auto InterpreterCEntry2Descriptor::registers() {
return RegisterArray(kRuntimeCallArgCountRegister, kRuntimeCallArgvRegister,
kRuntimeCallFunctionRegister);
}
// static
constexpr auto FastNewObjectDescriptor::registers() {
return RegisterArray(TargetRegister(), NewTargetRegister());
}
// static
constexpr auto TailCallOptimizedCodeSlotDescriptor::registers() {
return RegisterArray(kJavaScriptCallCodeStartRegister);
}
// static
constexpr auto LoadNoFeedbackDescriptor::registers() {
return RegisterArray(LoadDescriptor::ReceiverRegister(),
LoadDescriptor::NameRegister(), ICKindRegister());
}
// static
constexpr auto LoadGlobalNoFeedbackDescriptor::registers() {
return RegisterArray(LoadDescriptor::NameRegister(), ICKindRegister());
}
// static
constexpr auto LoadGlobalWithVectorDescriptor::registers() {
return RegisterArray(LoadDescriptor::NameRegister(),
LoadDescriptor::SlotRegister(), VectorRegister());
}
// static
constexpr auto LoadWithReceiverAndVectorDescriptor::registers() {
return RegisterArray(
LoadDescriptor::ReceiverRegister(), LookupStartObjectRegister(),
LoadDescriptor::NameRegister(), LoadDescriptor::SlotRegister(),
LoadWithVectorDescriptor::VectorRegister());
}
// static
constexpr auto StoreGlobalWithVectorDescriptor::registers() {
return RegisterArray(StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister(),
StoreWithVectorDescriptor::VectorRegister());
}
// static
constexpr auto StoreTransitionDescriptor::registers() {
return RegisterArray(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(), MapRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister(),
StoreWithVectorDescriptor::VectorRegister());
}
// static
constexpr auto TypeConversionDescriptor::registers() {
return RegisterArray(ArgumentRegister());
}
// static
constexpr auto TypeConversionNoContextDescriptor::registers() {
return RegisterArray(TypeConversionDescriptor::ArgumentRegister());
}
// static
constexpr auto SingleParameterOnStackDescriptor::registers() {
return RegisterArray();
}
// static
constexpr auto AsyncFunctionStackParameterDescriptor::registers() {
return RegisterArray();
}
// static
constexpr auto GetIteratorStackParameterDescriptor::registers() {
return RegisterArray();
}
// static
constexpr auto LoadWithVectorDescriptor::registers() {
return RegisterArray(LoadDescriptor::ReceiverRegister(),
LoadDescriptor::NameRegister(),
LoadDescriptor::SlotRegister(), VectorRegister());
}
// static
constexpr auto StoreWithVectorDescriptor::registers() {
return RegisterArray(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister(), VectorRegister());
}
// static
constexpr auto ApiGetterDescriptor::registers() {
return RegisterArray(ReceiverRegister(), HolderRegister(),
CallbackRegister());
}
// static
constexpr auto ContextOnlyDescriptor::registers() { return RegisterArray(); }
// static
constexpr auto NoContextDescriptor::registers() { return RegisterArray(); }
// static
constexpr auto GrowArrayElementsDescriptor::registers() {
return RegisterArray(ObjectRegister(), KeyRegister());
}
// static
constexpr auto ArrayNArgumentsConstructorDescriptor::registers() {
// Keep the arguments on the same registers as they were in
// ArrayConstructorDescriptor to avoid unnecessary register moves.
// kFunction, kAllocationSite, kActualArgumentsCount
return RegisterArray(kJavaScriptCallTargetRegister,
kJavaScriptCallExtraArg1Register,
kJavaScriptCallArgCountRegister);
}
// static
constexpr auto ArrayNoArgumentConstructorDescriptor::registers() {
// This descriptor must use the same set of registers as the
// ArrayNArgumentsConstructorDescriptor.
return ArrayNArgumentsConstructorDescriptor::registers();
}
// static
constexpr auto ArraySingleArgumentConstructorDescriptor::registers() {
// This descriptor must use the same set of registers as the
// ArrayNArgumentsConstructorDescriptor.
return ArrayNArgumentsConstructorDescriptor::registers();
}
// static
// static
constexpr Register RunMicrotasksDescriptor::MicrotaskQueueRegister() {
return GetRegisterParameter(0);
}
#define DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER(Name, DescriptorName) \
template <> \
struct CallInterfaceDescriptorFor<Builtins::k##Name> { \
using type = DescriptorName##Descriptor; \
};
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN,
/*TFC*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, IGNORE_BUILTIN,
/*TFH*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, IGNORE_BUILTIN,
/*ASM*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER)
#undef DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER
#define DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER(Name, ...) \
template <> \
struct CallInterfaceDescriptorFor<Builtins::k##Name> { \
using type = Name##Descriptor; \
};
BUILTIN_LIST_TFS(DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER)
#undef DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_

View File

@ -4,49 +4,48 @@
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/macro-assembler.h"
namespace v8 {
namespace internal {
void CallInterfaceDescriptorData::InitializePlatformSpecific(
int register_parameter_count, const Register* registers) {
DCHECK(!IsInitializedPlatformIndependent());
register_param_count_ = register_parameter_count;
// UBSan doesn't like creating zero-length arrays.
if (register_parameter_count == 0) return;
// 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++) {
// The value of the root register must be reserved, thus any uses
// within the calling convention are disallowed.
#ifdef DEBUG
CHECK_NE(registers[i], kRootRegister);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
CHECK_NE(registers[i], kPtrComprCageBaseRegister);
#endif
// Check for duplicated registers.
for (int j = i + 1; j < register_parameter_count; j++) {
CHECK_NE(registers[i], registers[j]);
}
#endif
register_params_[i] = registers[i];
}
}
void CallInterfaceDescriptorData::InitializePlatformIndependent(
void CallInterfaceDescriptorData::InitializeRegisters(
Flags flags, int return_count, int parameter_count,
const MachineType* machine_types, int machine_types_length,
StackArgumentOrder stack_order) {
DCHECK(IsInitializedPlatformSpecific());
StackArgumentOrder stack_order, int register_parameter_count,
const Register* registers) {
DCHECK(!IsInitializedTypes());
#ifdef DEBUG
{
// Make sure that the registers are all valid, and don't alias each other.
RegList reglist = 0;
for (int i = 0; i < register_parameter_count; ++i) {
Register reg = registers[i];
DCHECK(reg.is_valid());
DCHECK_EQ(reglist & reg.bit(), 0);
DCHECK_NE(reg, kRootRegister);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
DCHECK_NE(reg, kPtrComprCageBaseRegister);
#endif
reglist = CombineRegLists(reglist, reg.bit());
}
}
#endif
flags_ = flags;
stack_order_ = stack_order;
return_count_ = return_count;
param_count_ = parameter_count;
register_param_count_ = register_parameter_count;
// The caller owns the the registers array, so we just set the pointer.
register_params_ = registers;
}
void CallInterfaceDescriptorData::InitializeTypes(
const MachineType* machine_types, int machine_types_length) {
DCHECK(IsInitializedRegisters());
const int types_length = return_count_ + param_count_;
// Machine types are either fully initialized or null.
@ -77,7 +76,6 @@ bool CallInterfaceDescriptorData::AllStackParametersAreTagged() const {
void CallInterfaceDescriptorData::Reset() {
delete[] machine_types_;
machine_types_ = nullptr;
delete[] register_params_;
register_params_ = nullptr;
}
@ -105,27 +103,6 @@ void CallDescriptors::TearDown() {
}
}
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) {
@ -146,487 +123,5 @@ bool CallInterfaceDescriptor::IsValidFloatParameterRegister(Register reg) {
}
#endif
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 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 TailCallOptimizedCodeSlotDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {kJavaScriptCallCodeStartRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LoadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LoadBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {LoadDescriptor::ReceiverRegister(),
LoadDescriptor::NameRegister(),
LoadDescriptor::SlotRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LoadNoFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ReceiverRegister(), NameRegister(), ICKindRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LoadGlobalDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {NameRegister(), SlotRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LoadGlobalBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {LoadGlobalDescriptor::NameRegister(),
LoadGlobalDescriptor::SlotRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LookupBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void LoadGlobalNoFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {NameRegister(), ICKindRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {NameRegister(), SlotRegister(), VectorRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void LoadWithReceiverAndVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DCHECK(!AreAliased(ReceiverRegister(), LookupStartObjectRegister(),
NameRegister(), SlotRegister(), VectorRegister()));
Register registers[] = {ReceiverRegister(), LookupStartObjectRegister(),
NameRegister(), SlotRegister(), VectorRegister()};
int len = arraysize(registers) - kStackArgumentsCount;
data->InitializePlatformSpecific(len, registers);
}
void LoadWithReceiverBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
LoadWithReceiverAndVectorDescriptor::ReceiverRegister(),
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister(),
LoadWithReceiverAndVectorDescriptor::NameRegister(),
LoadWithReceiverAndVectorDescriptor::SlotRegister()};
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 StoreGlobalBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {StoreGlobalDescriptor::NameRegister(),
StoreGlobalDescriptor::ValueRegister(),
StoreGlobalDescriptor::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 StoreBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(), StoreDescriptor::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 BaselineOutOfLinePrologueDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(v8:11421): Implement on other platforms.
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32 || \
V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_RISCV64
Register registers[] = {kContextRegister,
kJSFunctionRegister,
kJavaScriptCallArgCountRegister,
kJavaScriptCallExtraArg1Register,
kJavaScriptCallNewTargetRegister,
kInterpreterBytecodeArrayRegister};
data->InitializePlatformSpecific(kParameterCount - kStackArgumentsCount,
registers);
#else
InitializePlatformUnimplemented(data, kParameterCount);
#endif
}
void BaselineLeaveFrameDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// TODO(v8:11421): Implement on other platforms.
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || \
V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_RISCV64
Register registers[] = {ParamsSizeRegister(), WeightRegister()};
data->InitializePlatformSpecific(kParameterCount, registers);
#else
InitializePlatformUnimplemented(data, kParameterCount);
#endif
}
void StringAtDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void StringAtAsStringDescriptor::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 TypeConversionNoContextDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {TypeConversionDescriptor::ArgumentRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void TypeConversion_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void SingleParameterOnStackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
data->InitializePlatformSpecific(0, nullptr);
}
void AsyncFunctionStackParameterDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
data->InitializePlatformSpecific(0, nullptr);
}
void GetIteratorStackParameterDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
data->InitializePlatformSpecific(0, nullptr);
}
void LoadWithVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister(),
VectorRegister()};
// TODO(jgruber): This DCHECK could be enabled if RegisterBase::ListOf were
// to allow no_reg entries.
// DCHECK(!AreAliased(ReceiverRegister(), NameRegister(), SlotRegister(),
// VectorRegister(), kRootRegister));
int len = arraysize(registers) - kStackArgumentsCount;
data->InitializePlatformSpecific(len, registers);
}
void StoreWithVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
SlotRegister(), VectorRegister()};
// TODO(jgruber): This DCHECK could be enabled if RegisterBase::ListOf were
// to allow no_reg entries.
// DCHECK(!AreAliased(ReceiverRegister(), NameRegister(), kRootRegister));
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 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);
}
#if !V8_TARGET_ARCH_IA32
// We need a custom descriptor on ia32 to avoid using xmm0.
void WasmFloat32ToNumberDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
// We need a custom descriptor on ia32 to avoid using xmm0.
void WasmFloat64ToNumberDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
#endif // !V8_TARGET_ARCH_IA32
#if !defined(V8_TARGET_ARCH_MIPS) && !defined(V8_TARGET_ARCH_MIPS64) && \
!defined(V8_TARGET_ARCH_RISCV64)
void WasmI32AtomicWait32Descriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void WasmI64AtomicWait32Descriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data,
kParameterCount - kStackArgumentsCount);
}
#endif
void CloneObjectWithVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void CloneObjectBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
// static
Register RunMicrotasksDescriptor::MicrotaskQueueRegister() {
return CallDescriptors::call_descriptor_data(CallDescriptors::RunMicrotasks)
->register_param(0);
}
void RunMicrotasksDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void I64ToBigIntDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void I32PairToBigIntDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void BigIntToI64Descriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void BigIntToI32PairDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void BinaryOp_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 4);
}
void CallTrampoline_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void CallTrampoline_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 4);
}
void CallWithArrayLike_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 4);
}
void CallWithSpread_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void CallWithSpread_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 4);
}
void ConstructWithArrayLike_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 4);
}
void ConstructWithSpread_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data,
kParameterCount - kStackArgumentsCount);
}
void ConstructWithSpread_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 4);
}
void Compare_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 4);
}
void UnaryOp_WithFeedbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 3);
}
void UnaryOp_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 2);
}
void ForInPrepareDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void SuspendGeneratorBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void ResumeGeneratorBaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
} // namespace internal
} // namespace v8

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,27 @@ constexpr bool ShouldPadArguments(int argument_count) {
return ArgumentPaddingSlots(argument_count) != 0;
}
#ifdef DEBUG
struct CountIfValidRegisterFunctor {
template <typename RegType>
constexpr int operator()(int count, RegType reg) const {
return count + (reg.is_valid() ? 1 : 0);
}
};
template <typename RegType, typename... RegTypes,
// All arguments must be either Register or DoubleRegister.
typename = typename std::enable_if<
base::is_same<Register, RegType, RegTypes...>::value ||
base::is_same<DoubleRegister, RegType, RegTypes...>::value>::type>
inline constexpr bool AreAliased(RegType first_reg, RegTypes... regs) {
int num_different_regs = NumRegs(RegType::ListOf(first_reg, regs...));
int num_given_regs =
base::fold(CountIfValidRegisterFunctor{}, 0, first_reg, regs...);
return num_different_regs < num_given_regs;
}
#endif
} // namespace internal
} // namespace v8

View File

@ -165,27 +165,6 @@ class V8_NODISCARD HardAbortScope {
bool old_value_;
};
#ifdef DEBUG
struct CountIfValidRegisterFunctor {
template <typename RegType>
constexpr int operator()(int count, RegType reg) const {
return count + (reg.is_valid() ? 1 : 0);
}
};
template <typename RegType, typename... RegTypes,
// All arguments must be either Register or DoubleRegister.
typename = typename std::enable_if<
base::is_same<Register, RegType, RegTypes...>::value ||
base::is_same<DoubleRegister, RegType, RegTypes...>::value>::type>
inline bool AreAliased(RegType first_reg, RegTypes... regs) {
int num_different_regs = NumRegs(RegType::ListOf(first_reg, regs...));
int num_given_regs =
base::fold(CountIfValidRegisterFunctor{}, 0, first_reg, regs...);
return num_different_regs < num_given_regs;
}
#endif
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,263 @@
// Copyright 2021 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.
#ifndef V8_CODEGEN_X64_INTERFACE_DESCRIPTORS_X64_INL_H_
#define V8_CODEGEN_X64_INTERFACE_DESCRIPTORS_X64_INL_H_
#if V8_TARGET_ARCH_X64
#include "src/codegen/interface-descriptors.h"
namespace v8 {
namespace internal {
constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
auto registers = RegisterArray(rax, rbx, rcx, rdx, rdi);
STATIC_ASSERT(registers.size() == kMaxBuiltinRegisterParams);
return registers;
}
// static
constexpr auto RecordWriteDescriptor::registers() {
return RegisterArray(arg_reg_1, arg_reg_2, arg_reg_3, arg_reg_4,
kReturnRegister0);
}
// static
constexpr auto DynamicCheckMapsDescriptor::registers() {
return RegisterArray(kReturnRegister0, arg_reg_1, arg_reg_2, arg_reg_3,
kRuntimeCallFunctionRegister, kContextRegister);
}
// static
constexpr auto EphemeronKeyBarrierDescriptor::registers() {
return RegisterArray(arg_reg_1, arg_reg_2, arg_reg_3, arg_reg_4,
kReturnRegister0);
}
// static
constexpr Register LoadDescriptor::ReceiverRegister() { return rdx; }
// static
constexpr Register LoadDescriptor::NameRegister() { return rcx; }
// static
constexpr Register LoadDescriptor::SlotRegister() { return rax; }
// static
constexpr Register LoadWithVectorDescriptor::VectorRegister() { return rbx; }
// static
constexpr Register
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
return rdi;
}
// static
constexpr Register StoreDescriptor::ReceiverRegister() { return rdx; }
// static
constexpr Register StoreDescriptor::NameRegister() { return rcx; }
// static
constexpr Register StoreDescriptor::ValueRegister() { return rax; }
// static
constexpr Register StoreDescriptor::SlotRegister() { return rdi; }
// static
constexpr Register StoreWithVectorDescriptor::VectorRegister() { return rbx; }
// static
constexpr Register StoreTransitionDescriptor::MapRegister() { return r11; }
// static
constexpr Register ApiGetterDescriptor::HolderRegister() { return rcx; }
// static
constexpr Register ApiGetterDescriptor::CallbackRegister() { return rbx; }
// static
constexpr Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
// static
constexpr Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
// static
constexpr Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
return rbx;
}
// static
constexpr Register BaselineLeaveFrameDescriptor::WeightRegister() {
return rcx;
}
// static
constexpr Register TypeConversionDescriptor::ArgumentRegister() { return rax; }
// static
constexpr auto TypeofDescriptor::registers() { return RegisterArray(rbx); }
// static
constexpr auto CallTrampolineDescriptor::registers() {
// rax : number of arguments
// rdi : the target to call
return RegisterArray(rdi, rax);
}
// static
constexpr auto CallVarargsDescriptor::registers() {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rcx : arguments list length (untagged)
// rbx : arguments list (FixedArray)
return RegisterArray(rdi, rax, rcx, rbx);
}
// static
constexpr auto CallForwardVarargsDescriptor::registers() {
// rax : number of arguments
// rcx : start index (to support rest parameters)
// rdi : the target to call
return RegisterArray(rdi, rax, rcx);
}
// static
constexpr auto CallFunctionTemplateDescriptor::registers() {
// rdx: the function template info
// rcx: number of arguments (on the stack, not including receiver)
return RegisterArray(rdx, rcx);
}
// static
constexpr auto CallWithSpreadDescriptor::registers() {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rbx : the object to spread
return RegisterArray(rdi, rax, rbx);
}
// static
constexpr auto CallWithArrayLikeDescriptor::registers() {
// rdi : the target to call
// rbx : the arguments list
return RegisterArray(rdi, rbx);
}
// static
constexpr auto ConstructVarargsDescriptor::registers() {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rdx : the new target
// rcx : arguments list length (untagged)
// rbx : arguments list (FixedArray)
return RegisterArray(rdi, rdx, rax, rcx, rbx);
}
// static
constexpr auto ConstructForwardVarargsDescriptor::registers() {
// rax : number of arguments
// rdx : the new target
// rcx : start index (to support rest parameters)
// rdi : the target to call
return RegisterArray(rdi, rdx, rax, rcx);
}
// static
constexpr auto ConstructWithSpreadDescriptor::registers() {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rdx : the new target
// rbx : the object to spread
return RegisterArray(rdi, rdx, rax, rbx);
}
// static
constexpr auto ConstructWithArrayLikeDescriptor::registers() {
// rdi : the target to call
// rdx : the new target
// rbx : the arguments list
return RegisterArray(rdi, rdx, rbx);
}
// static
constexpr auto ConstructStubDescriptor::registers() {
// rax : number of arguments
// rdx : the new target
// rdi : the target to call
// rbx : allocation site or undefined
return RegisterArray(rdi, rdx, rax, rbx);
}
// static
constexpr auto AbortDescriptor::registers() { return RegisterArray(rdx); }
// static
constexpr auto CompareDescriptor::registers() {
return RegisterArray(rdx, rax);
}
// static
constexpr auto BinaryOpDescriptor::registers() {
return RegisterArray(rdx, rax);
}
// static
constexpr auto Compare_BaselineDescriptor::registers() {
return RegisterArray(rdx, rax, rbx);
}
// static
constexpr auto BinaryOp_BaselineDescriptor::registers() {
return RegisterArray(rdx, rax, rbx);
}
// static
constexpr auto ApiCallbackDescriptor::registers() {
return RegisterArray(rdx, // api function address
rcx, // argument count (not including receiver)
rbx, // call data
rdi); // holder
}
// static
constexpr auto InterpreterDispatchDescriptor::registers() {
return RegisterArray(
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister);
}
// static
constexpr auto InterpreterPushArgsThenCallDescriptor::registers() {
return RegisterArray(rax, // argument count (not including receiver)
rbx, // address of first argument
rdi); // the target callable to be call
}
// static
constexpr auto InterpreterPushArgsThenConstructDescriptor::registers() {
return RegisterArray(
rax, // argument count (not including receiver)
rcx, // address of first argument
rdi, // constructor to call
rdx, // new target
rbx); // allocation site feedback if available, undefined otherwise
}
// static
constexpr auto ResumeGeneratorDescriptor::registers() {
return RegisterArray(
rax, // the value to pass to the generator
rdx); // the JSGeneratorObject / JSAsyncGeneratorObject to resume
}
// static
constexpr auto FrameDropperTrampolineDescriptor::registers() {
return RegisterArray(rbx); // loaded new FP
}
// static
constexpr auto RunMicrotasksEntryDescriptor::registers() {
return RegisterArray(arg_reg_1, arg_reg_2);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_X64
#endif // V8_CODEGEN_X64_INTERFACE_DESCRIPTORS_X64_INL_H_

View File

@ -1,309 +0,0 @@
// 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/codegen/interface-descriptors.h"
#include "src/execution/frames.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);
}
void RecordWriteDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
const Register default_stub_registers[] = {arg_reg_1, arg_reg_2, arg_reg_3,
arg_reg_4, kReturnRegister0};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void DynamicCheckMapsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register default_stub_registers[] = {kReturnRegister0,
arg_reg_1,
arg_reg_2,
arg_reg_3,
kRuntimeCallFunctionRegister,
kContextRegister};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
void EphemeronKeyBarrierDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
const Register default_stub_registers[] = {arg_reg_1, arg_reg_2, arg_reg_3,
arg_reg_4, kReturnRegister0};
data->RestrictAllocatableRegisters(default_stub_registers,
arraysize(default_stub_registers));
CHECK_LE(static_cast<size_t>(kParameterCount),
arraysize(default_stub_registers));
data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
}
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
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
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 ApiGetterDescriptor::HolderRegister() { return rcx; }
const Register ApiGetterDescriptor::CallbackRegister() { return rbx; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
const Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
return rbx;
}
const Register BaselineLeaveFrameDescriptor::WeightRegister() { return rcx; }
void TypeofDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
// static
const Register TypeConversionDescriptor::ArgumentRegister() { return rax; }
void CallTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments
// rdi : the target to call
Register registers[] = {rdi, rax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rcx : arguments list length (untagged)
// rbx : arguments list (FixedArray)
Register registers[] = {rdi, rax, rcx, rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments
// rcx : start index (to support rest parameters)
// rdi : the target to call
Register registers[] = {rdi, rax, rcx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionTemplateDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rdx: the function template info
// rcx: number of arguments (on the stack, not including receiver)
Register registers[] = {rdx, rcx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rbx : the object to spread
Register registers[] = {rdi, rax, rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rdi : the target to call
// rbx : the arguments list
Register registers[] = {rdi, rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rdx : the new target
// rcx : arguments list length (untagged)
// rbx : arguments list (FixedArray)
Register registers[] = {rdi, rdx, rax, rcx, rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments
// rdx : the new target
// rcx : start index (to support rest parameters)
// rdi : the target to call
Register registers[] = {rdi, rdx, rax, rcx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithSpreadDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments (on the stack, not including receiver)
// rdi : the target to call
// rdx : the new target
// rbx : the object to spread
Register registers[] = {rdi, rdx, rax, rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rdi : the target to call
// rdx : the new target
// rbx : the arguments list
Register registers[] = {rdi, rdx, rbx};
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 AbortDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rdx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CompareDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rdx, rax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void Compare_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rdx, rax, rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rdx, rax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BinaryOp_BaselineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rdx, rax, rbx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ApiCallbackDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
rdx, // api function address
rcx, // argument count (not including receiver)
rbx, // call data
rdi, // holder
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsThenCallDescriptor::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 InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
rax, // argument count (not including receiver)
rcx, // address of first argument
rdi, // constructor to call
rdx, // new target
rbx, // allocation site feedback if available, undefined otherwise
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ResumeGeneratorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
rax, // the value to pass to the generator
rdx // the JSGeneratorObject / JSAsyncGeneratorObject to resume
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
rbx, // loaded new FP
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void RunMicrotasksEntryDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {arg_reg_1, arg_reg_2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_X64

View File

@ -12,6 +12,7 @@
#include "src/codegen/code-factory.h"
#include "src/codegen/cpu-features.h"
#include "src/codegen/external-reference-table.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/macro-assembler.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/string-constants.h"

View File

@ -9,6 +9,7 @@
#include "src/base/iterator.h"
#include "src/base/platform/wrappers.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/backend/instruction-selector-impl.h"
#include "src/compiler/compiler-source-position-table.h"

View File

@ -8,7 +8,7 @@
#include "src/base/bits.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/machine-type.h"
#include "src/codegen/macro-assembler.h"
#include "src/compiler/backend/instruction-selector.h"

View File

@ -7,6 +7,7 @@
#include "include/v8-fast-api-calls.h"
#include "src/base/bits.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/machine-type.h"
#include "src/common/ptr-compr-inl.h"
#include "src/compiler/access-builder.h"

View File

@ -7,6 +7,7 @@
#include "src/ast/ast.h"
#include "src/builtins/builtins-constructor.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/js-graph.h"

View File

@ -7,6 +7,7 @@
#include "src/ast/modules.h"
#include "src/builtins/builtins-utils.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/allocation-builder.h"
#include "src/compiler/graph-assembler.h"

View File

@ -4,7 +4,7 @@
#include "src/compiler/memory-lowering.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/common/external-pointer.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h"

View File

@ -16,7 +16,7 @@
#include "src/codegen/assembler.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/compiler.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/machine-type.h"
#include "src/codegen/optimized-compilation-info.h"
#include "src/compiler/backend/code-generator.h"

View File

@ -8,6 +8,7 @@
#include "src/base/optional.h"
#include "src/builtins/builtins-constructor-gen.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/ic/handler-configuration.h"
#include "src/ic/ic.h"
#include "src/ic/keyed-store-generic.h"
@ -1507,7 +1508,6 @@ void AccessorAssembler::HandleStoreAccessor(const StoreICParameters* p,
LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
CSA_ASSERT(this, Word32BinaryNot(IsTheHole(setter)));
Callable callable = CodeFactory::Call(isolate());
Return(Call(p->context(), setter, p->receiver(), p->value()));
}

View File

@ -8,7 +8,7 @@
#include <ostream>
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/machine-type.h"
#include "src/execution/frames.h"
#include "src/interpreter/bytecodes.h"

View File

@ -6,6 +6,7 @@
#include "src/codegen/assembler-inl.h"
#include "src/codegen/callable.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/objects/objects-inl.h"
#include "src/snapshot/snapshot-utils.h"
#include "src/snapshot/snapshot.h"
@ -187,14 +188,15 @@ bool BuiltinAliasesOffHeapTrampolineRegister(Isolate* isolate, Code code) {
return false;
}
if (CallInterfaceDescriptor::ContextRegister() ==
kOffHeapTrampolineRegister) {
return true;
}
Callable callable = Builtins::CallableFor(
isolate, static_cast<Builtins::Name>(code.builtin_index()));
CallInterfaceDescriptor descriptor = callable.descriptor();
if (descriptor.ContextRegister() == kOffHeapTrampolineRegister) {
return true;
}
for (int i = 0; i < descriptor.GetRegisterParameterCount(); i++) {
Register reg = descriptor.GetRegisterParameter(i);
if (reg == kOffHeapTrampolineRegister) return true;

View File

@ -658,8 +658,8 @@ void ImplementationVisitor::Visit(Builtin* builtin) {
} else {
DCHECK(builtin->IsStub());
bool has_context_parameter = signature.HasContextParameter();
for (size_t i = 0; i < signature.parameter_names.size(); ++i) {
const std::string& parameter_name = signature.parameter_names[i]->value;
const Type* type = signature.types()[i];
const bool mark_as_used = signature.implicit_count > i;
std::string var = AddParameter(i, builtin, &parameters, &parameter_types,
@ -667,14 +667,8 @@ void ImplementationVisitor::Visit(Builtin* builtin) {
csa_ccfile() << " " << type->GetGeneratedTypeName() << " " << var
<< " = "
<< "UncheckedParameter<" << type->GetGeneratedTNodeTypeName()
<< ">(";
if (i == 0 && has_context_parameter) {
csa_ccfile() << "Descriptor::kContext";
} else {
csa_ccfile() << "Descriptor::ParameterIndex<"
<< (has_context_parameter ? i - 1 : i) << ">()";
}
csa_ccfile() << ");\n";
<< ">(Descriptor::k" << CamelifyString(parameter_name)
<< ");\n";
csa_ccfile() << " USE(" << var << ");\n";
}
}
@ -3437,40 +3431,40 @@ void ImplementationVisitor::GenerateBuiltinDefinitionsAndInterfaceDescriptors(
std::string descriptor_name = builtin->ExternalName() + "Descriptor";
bool has_context_parameter = builtin->signature().HasContextParameter();
size_t kFirstNonContextParameter = has_context_parameter ? 1 : 0;
size_t parameter_count =
builtin->parameter_names().size() - kFirstNonContextParameter;
TypeVector return_types = LowerType(builtin->signature().return_type);
interface_descriptors
<< "class " << descriptor_name
<< " : public TorqueInterfaceDescriptor<" << return_types.size()
<< ", " << parameter_count << ", "
<< (has_context_parameter ? "true" : "false") << "> {\n";
interface_descriptors << " DECLARE_DESCRIPTOR_WITH_BASE("
<< descriptor_name
<< ", TorqueInterfaceDescriptor)\n";
interface_descriptors << "class " << descriptor_name
<< " : public StaticCallInterfaceDescriptor<"
<< descriptor_name << "> {\n";
interface_descriptors
<< " std::vector<MachineType> ReturnType() override {\n";
interface_descriptors << " return {{";
PrintCommaSeparatedList(interface_descriptors, return_types,
MachineTypeString);
interface_descriptors << "}};\n";
interface_descriptors << " }\n";
interface_descriptors << " public:\n";
interface_descriptors << " std::array<MachineType, " << parameter_count
<< "> ParameterTypes() override {\n";
interface_descriptors << " return {";
if (has_context_parameter) {
interface_descriptors << " DEFINE_RESULT_AND_PARAMETERS(";
} else {
interface_descriptors << " DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT(";
}
interface_descriptors << return_types.size();
for (size_t i = kFirstNonContextParameter;
i < builtin->parameter_names().size(); ++i) {
bool last = i + 1 == builtin->parameter_names().size();
const Type* type = builtin->signature().parameter_types.types[i];
interface_descriptors << MachineTypeString(type)
<< (last ? "" : ", ");
Identifier* parameter = builtin->parameter_names()[i];
interface_descriptors << ", k" << CamelifyString(parameter->value);
}
interface_descriptors << "};\n";
interface_descriptors << ")\n";
interface_descriptors << " DEFINE_RESULT_AND_PARAMETER_TYPES(";
PrintCommaSeparatedList(interface_descriptors, return_types,
MachineTypeString);
for (size_t i = kFirstNonContextParameter;
i < builtin->parameter_names().size(); ++i) {
const Type* type = builtin->signature().parameter_types.types[i];
interface_descriptors << ", " << MachineTypeString(type);
}
interface_descriptors << ")\n";
interface_descriptors << " DECLARE_DEFAULT_DESCRIPTOR("
<< descriptor_name << ")\n";
interface_descriptors << " }\n";
interface_descriptors << "};\n\n";
} else {
builtin_definitions << "TFJ(" << builtin->ExternalName();

View File

@ -10,7 +10,7 @@
#include "src/codegen/assembler-inl.h"
// TODO(clemensb): Remove dependences on compiler stuff.
#include "src/codegen/external-reference.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/machine-type.h"
#include "src/codegen/macro-assembler-inl.h"
#include "src/compiler/linkage.h"

View File

@ -11,6 +11,7 @@
#include "src/builtins/builtins-string-gen.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/compiler/node.h"
#include "src/debug/debug.h"
#include "src/execution/isolate.h"
@ -2024,7 +2025,7 @@ TEST(PopAndReturnFromTFCBuiltinWithStackParameters) {
// least one argument passed on stack.
using Descriptor = FlatMapIntoArrayDescriptor;
Descriptor descriptor;
CHECK_LT(0, descriptor.GetStackParameterCount());
CHECK_LT(0, Descriptor::GetStackParameterCount());
CodeAssemblerTester asm_tester(isolate, Descriptor());
{

View File

@ -5,7 +5,7 @@
#include "test/unittests/codegen/code-stub-assembler-unittest.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/compiler/node.h"
#include "src/execution/isolate.h"
#include "src/objects/objects-inl.h"

View File

@ -4,7 +4,7 @@
#include "src/compiler/int64-lowering.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/machine-type.h"
#include "src/codegen/signature.h"
#include "src/compiler/common-operator.h"
@ -1063,20 +1063,20 @@ TEST_F(Int64LoweringTest, WasmBigIntSpecialCaseBigIntToI64) {
CallDescriptor* bigint_to_i64_call_descriptor =
Linkage::GetStubCallDescriptor(
zone(), // zone
BigIntToI64Descriptor(), // descriptor
BigIntToI64Descriptor()
.GetStackParameterCount(), // stack parameter count
CallDescriptor::kNoFlags, // flags
Operator::kNoProperties, // properties
StubCallMode::kCallCodeObject); // stub call mode
zone(), // zone
BigIntToI64Descriptor(), // descriptor
BigIntToI64Descriptor::GetStackParameterCount(), // stack parameter
// count
CallDescriptor::kNoFlags, // flags
Operator::kNoProperties, // properties
StubCallMode::kCallCodeObject); // stub call mode
CallDescriptor* bigint_to_i32_pair_call_descriptor =
Linkage::GetStubCallDescriptor(
zone(), // zone
BigIntToI32PairDescriptor(), // descriptor
BigIntToI32PairDescriptor()
.GetStackParameterCount(), // stack parameter count
BigIntToI32PairDescriptor::
GetStackParameterCount(), // stack parameter count
CallDescriptor::kNoFlags, // flags
Operator::kNoProperties, // properties
StubCallMode::kCallCodeObject); // stub call mode
@ -1109,20 +1109,20 @@ TEST_F(Int64LoweringTest, WasmBigIntSpecialCaseI64ToBigInt) {
CallDescriptor* i64_to_bigint_call_descriptor =
Linkage::GetStubCallDescriptor(
zone(), // zone
I64ToBigIntDescriptor(), // descriptor
I64ToBigIntDescriptor()
.GetStackParameterCount(), // stack parameter count
CallDescriptor::kNoFlags, // flags
Operator::kNoProperties, // properties
StubCallMode::kCallCodeObject); // stub call mode
zone(), // zone
I64ToBigIntDescriptor(), // descriptor
I64ToBigIntDescriptor::GetStackParameterCount(), // stack parameter
// count
CallDescriptor::kNoFlags, // flags
Operator::kNoProperties, // properties
StubCallMode::kCallCodeObject); // stub call mode
CallDescriptor* i32_pair_to_bigint_call_descriptor =
Linkage::GetStubCallDescriptor(
zone(), // zone
I32PairToBigIntDescriptor(), // descriptor
I32PairToBigIntDescriptor()
.GetStackParameterCount(), // stack parameter count
I32PairToBigIntDescriptor::
GetStackParameterCount(), // stack parameter count
CallDescriptor::kNoFlags, // flags
Operator::kNoProperties, // properties
StubCallMode::kCallCodeObject); // stub call mode