Reland "[codegen] Add static interface descriptors"

This is a reland of ae0752df1b

Reland fixes:

  * Remove UNREACHABLE() from constexpr switch, since we don't have a
    CONSTEXPR_UNREACHABLE() (it's ok, the switch is exhaustive for the
    enum anyway).
  * Fix IsRegisterArray trait to use public inheritance and size_t for
    std::array size.

Original change's description:
> [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}

TBR=nicohartmann@chromium.org,clemensb@chromium.org,ishell@chromium.org,clemensb@chromium.org

Bug: v8:11420
Change-Id: Icd1f6cdb3c178e74460044b1e9623139929ceba8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2831872
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74010}
This commit is contained in:
Leszek Swirski 2021-04-16 16:52:06 +02:00 committed by Commit Bot
parent f4573682ed
commit 2871e05cc3
48 changed files with 2798 additions and 2905 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 : public std::false_type {};
template <size_t N>
struct IsRegisterArray<std::array<Register, N>> : public std::true_type {};
template <>
struct IsRegisterArray<EmptyRegisterArray> : public 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

@ -3838,13 +3838,13 @@ bool MapRef::is_stable() const {
}
bool MapRef::CanBeDeprecated() const {
IF_ACCESS_FROM_HEAP_WITH_FLAG_C(CanBeDeprecated);
IF_ACCESS_FROM_HEAP_C(CanBeDeprecated);
CHECK_GT(NumberOfOwnDescriptors(), 0);
return data()->AsMap()->can_be_deprecated();
}
bool MapRef::CanTransition() const {
IF_ACCESS_FROM_HEAP_WITH_FLAG_C(CanTransition);
IF_ACCESS_FROM_HEAP_C(CanTransition);
return data()->AsMap()->can_transition();
}

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