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:
parent
f4573682ed
commit
2871e05cc3
9
BUILD.gn
9
BUILD.gn
@ -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",
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
261
src/codegen/arm/interface-descriptors-arm-inl.h
Normal file
261
src/codegen/arm/interface-descriptors-arm-inl.h
Normal 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_
|
@ -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
|
@ -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"
|
||||
|
270
src/codegen/arm64/interface-descriptors-arm64-inl.h
Normal file
270
src/codegen/arm64/interface-descriptors-arm64-inl.h
Normal 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_
|
@ -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
|
@ -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"
|
||||
|
272
src/codegen/ia32/interface-descriptors-ia32-inl.h
Normal file
272
src/codegen/ia32/interface-descriptors-ia32-inl.h
Normal 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_
|
@ -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
|
@ -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"
|
||||
|
471
src/codegen/interface-descriptors-inl.h
Normal file
471
src/codegen/interface-descriptors-inl.h
Normal 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_
|
@ -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
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
263
src/codegen/x64/interface-descriptors-x64-inl.h
Normal file
263
src/codegen/x64/interface-descriptors-x64-inl.h
Normal 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_
|
@ -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
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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, ¶meters, ¶meter_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();
|
||||
|
@ -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"
|
||||
|
@ -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());
|
||||
{
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user