Commit af76779a authored by bmeurer's avatar bmeurer Committed by Commit Bot

[builtins] Start refactoring the Apply builtin.

This splits the monolithic Apply builtin into several smaller builtins,
namely CallVargargs and ConstructVarargs, which accept a length and a
FixedArray of elements and deal with the actual stack manipulation, and
CallWithArrayLike / ConstructWithArrayLike that deal with getting the
elements from the receiver (for Function.prototype.apply, Reflect.apply
and Reflect.construct), which can now be written using the CSA.

The idea is that these builtins can be reused by TurboFan directly in
the future when we optimize apply better, and that we can also reuse the
core logic in the handling of spread calls/constructs.

R=petermarshall@chromium.org
BUG=v8:4587,v8:5269

Review-Url: https://codereview.chromium.org/2930623002
Cr-Commit-Position: refs/heads/master@{#45794}
parent ae947e26
......@@ -933,6 +933,7 @@ v8_source_set("v8_builtins_generators") {
"src/builtins/builtins-async-iterator-gen.cc",
"src/builtins/builtins-boolean-gen.cc",
"src/builtins/builtins-call-gen.cc",
"src/builtins/builtins-call-gen.h",
"src/builtins/builtins-collections-gen.cc",
"src/builtins/builtins-console-gen.cc",
"src/builtins/builtins-constructor-gen.cc",
......
......@@ -157,6 +157,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
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
// r2 : arguments list (FixedArray)
// r4 : arguments list length (untagged)
Register registers[] = {r1, r0, r2, r4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments
......@@ -166,6 +176,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
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
// r2 : arguments list (FixedArray)
// r4 : arguments list length (untagged)
Register registers[] = {r1, r3, r0, r2, r4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r0 : number of arguments
......@@ -176,6 +205,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
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
......
......@@ -2794,6 +2794,17 @@ void MacroAssembler::AssertSmi(Register object) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
tst(object, Operand(kSmiTagMask));
Check(ne, kOperandIsASmiAndNotAFixedArray);
push(object);
CompareObjectType(object, object, object, FIXED_ARRAY_TYPE);
pop(object);
Check(eq, kOperandIsNotAFixedArray);
}
}
void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) {
......
......@@ -1215,6 +1215,9 @@ class MacroAssembler: public Assembler {
void AssertNotSmi(Register object);
void AssertSmi(Register object);
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
// Abort execution if argument is not a JSFunction, enabled via --debug-code.
void AssertFunction(Register object);
......
......@@ -176,6 +176,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
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
// x2 : arguments list (FixedArray)
// x4 : arguments list length (untagged)
Register registers[] = {x1, x0, x2, x4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1: target
......@@ -185,6 +195,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
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
// x2 : arguments list (FixedArray)
// x4 : arguments list length (untagged)
Register registers[] = {x1, x3, x0, x2, x4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x3: new target
......@@ -195,6 +224,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
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
......
......@@ -1781,6 +1781,17 @@ void MacroAssembler::AssertNotSmi(Register object, BailoutReason reason) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
AssertNotSmi(object, kOperandIsASmiAndNotAFixedArray);
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
CompareObjectType(object, temp, temp, FIXED_ARRAY_TYPE);
Check(eq, kOperandIsNotAFixedArray);
}
}
void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) {
......
......@@ -1565,6 +1565,9 @@ class MacroAssembler : public Assembler {
inline void ObjectTag(Register tagged_obj, Register obj);
inline void ObjectUntag(Register untagged_obj, Register obj);
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
// Abort execution if argument is not a JSFunction, enabled via --debug-code.
void AssertFunction(Register object);
......
......@@ -142,6 +142,7 @@ namespace internal {
V(kOffsetOutOfRange, "Offset out of range") \
V(kOperandIsASmiAndNotABoundFunction, \
"Operand is a smi and not a bound function") \
V(kOperandIsASmiAndNotAFixedArray, "Operand is a smi and not a fixed array") \
V(kOperandIsASmiAndNotAFunction, "Operand is a smi and not a function") \
V(kOperandIsASmiAndNotAGeneratorObject, \
"Operand is a smi and not a generator object") \
......@@ -150,6 +151,7 @@ namespace internal {
V(kOperandIsASmiAndNotAString, "Operand is a smi and not a string") \
V(kOperandIsASmi, "Operand is a smi") \
V(kOperandIsNotABoundFunction, "Operand is not a bound function") \
V(kOperandIsNotAFixedArray, "Operand is not a fixed array") \
V(kOperandIsNotAFunction, "Operand is not a function") \
V(kOperandIsNotAGeneratorObject, "Operand is not a generator object") \
V(kOperandIsNotAReceiver, "Operand is not a receiver") \
......
This diff is collapsed.
This diff is collapsed.
......@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/builtins/builtins-call-gen.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/globals.h"
#include "src/isolate.h"
......@@ -82,12 +85,132 @@ void Builtins::Generate_TailCall_ReceiverIsAny(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow);
}
void Builtins::Generate_CallVarargs(MacroAssembler* masm) {
Generate_CallOrConstructVarargs(masm, masm->isolate()->builtins()->Call());
}
void Builtins::Generate_CallForwardVarargs(MacroAssembler* masm) {
Generate_ForwardVarargs(masm, masm->isolate()->builtins()->Call());
Generate_CallOrConstructForwardVarargs(masm,
masm->isolate()->builtins()->Call());
}
void Builtins::Generate_CallFunctionForwardVarargs(MacroAssembler* masm) {
Generate_ForwardVarargs(masm, masm->isolate()->builtins()->CallFunction());
Generate_CallOrConstructForwardVarargs(
masm, masm->isolate()->builtins()->CallFunction());
}
void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike(
Node* target, Node* new_target, Node* arguments_list, Node* context) {
Variable var_elements(this, MachineRepresentation::kTagged);
Variable var_length(this, MachineRepresentation::kWord32);
Label if_done(this), if_arguments(this), if_array(this),
if_holey_array(this, Label::kDeferred),
if_runtime(this, Label::kDeferred);
GotoIf(TaggedIsSmi(arguments_list), &if_runtime);
Node* arguments_list_map = LoadMap(arguments_list);
Node* native_context = LoadNativeContext(context);
// Check if {arguments_list} is an (unmodified) arguments object.
Node* sloppy_arguments_map =
LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX);
GotoIf(WordEqual(arguments_list_map, sloppy_arguments_map), &if_arguments);
Node* strict_arguments_map =
LoadContextElement(native_context, Context::STRICT_ARGUMENTS_MAP_INDEX);
GotoIf(WordEqual(arguments_list_map, strict_arguments_map), &if_arguments);
// Check if {arguments_list} is a fast JSArray.
Branch(IsJSArrayMap(arguments_list_map), &if_array, &if_runtime);
BIND(&if_array);
{
// Try to extract the elements from a JSArray object.
var_elements.Bind(
LoadObjectField(arguments_list, JSArray::kElementsOffset));
var_length.Bind(LoadAndUntagToWord32ObjectField(arguments_list,
JSArray::kLengthOffset));
// Holey arrays and double backing stores need special treatment.
Node* kind = LoadMapElementsKind(arguments_list_map);
STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(FAST_ELEMENTS == 2);
STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
GotoIf(Word32Equal(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)),
&if_holey_array);
GotoIf(Word32Equal(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
&if_holey_array);
Branch(Uint32LessThanOrEqual(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
&if_done, &if_runtime);
}
BIND(&if_holey_array);
{
// For holey JSArrays we need to check that the array prototype chain
// protector is intact and our prototype is the Array.prototype actually.
Node* arguments_list_prototype = LoadMapPrototype(arguments_list_map);
Node* initial_array_prototype = LoadContextElement(
native_context, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
GotoIfNot(WordEqual(arguments_list_prototype, initial_array_prototype),
&if_runtime);
Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
DCHECK(isolate()->heap()->array_protector()->IsPropertyCell());
Branch(
WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset),
SmiConstant(Smi::FromInt(Isolate::kProtectorValid))),
&if_done, &if_runtime);
}
BIND(&if_arguments);
{
// Try to extract the elements from an JSArgumentsObject.
Node* length =
LoadObjectField(arguments_list, JSArgumentsObject::kLengthOffset);
Node* elements =
LoadObjectField(arguments_list, JSArgumentsObject::kElementsOffset);
Node* elements_length =
LoadObjectField(elements, FixedArray::kLengthOffset);
GotoIfNot(WordEqual(length, elements_length), &if_runtime);
var_elements.Bind(elements);
var_length.Bind(SmiToWord32(length));
Goto(&if_done);
}
BIND(&if_runtime);
{
// Ask the runtime to create the list (actually a FixedArray).
Node* elements =
CallRuntime(Runtime::kCreateListFromArrayLike, context, arguments_list);
var_elements.Bind(elements);
var_length.Bind(
LoadAndUntagToWord32ObjectField(elements, FixedArray::kLengthOffset));
Goto(&if_done);
}
// Tail call to the appropriate builtin (depending on whether we have
// a {new_target} passed).
BIND(&if_done);
{
Node* elements = var_elements.value();
Node* length = var_length.value();
if (new_target == nullptr) {
Callable callable = CodeFactory::CallVarargs(isolate());
TailCallStub(callable, context, target, Int32Constant(0), elements,
length);
} else {
Callable callable = CodeFactory::ConstructVarargs(isolate());
TailCallStub(callable, context, target, new_target, Int32Constant(0),
elements, length);
}
}
}
TF_BUILTIN(CallWithArrayLike, CallOrConstructBuiltinsAssembler) {
Node* target = Parameter(CallWithArrayLikeDescriptor::kTarget);
Node* new_target = nullptr;
Node* arguments_list = Parameter(CallWithArrayLikeDescriptor::kArgumentsList);
Node* context = Parameter(CallWithArrayLikeDescriptor::kContext);
CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
}
} // namespace internal
......
// Copyright 2017 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_BUILTINS_BUILTINS_CALL_GEN_H_
#define V8_BUILTINS_BUILTINS_CALL_GEN_H_
#include "src/code-stub-assembler.h"
namespace v8 {
namespace internal {
class CallOrConstructBuiltinsAssembler : public CodeStubAssembler {
public:
explicit CallOrConstructBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
void CallOrConstructWithArrayLike(Node* target, Node* new_target,
Node* arguments_list, Node* context);
};
} // namespace internal
} // namespace v8
#endif // V8_BUILTINS_BUILTINS_CALL_GEN_H_
......@@ -5,6 +5,7 @@
#include "src/builtins/builtins-constructor-gen.h"
#include "src/ast/ast.h"
#include "src/builtins/builtins-call-gen.h"
#include "src/builtins/builtins-constructor.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
......@@ -17,13 +18,28 @@
namespace v8 {
namespace internal {
void Builtins::Generate_ConstructVarargs(MacroAssembler* masm) {
Generate_CallOrConstructVarargs(masm,
masm->isolate()->builtins()->Construct());
}
void Builtins::Generate_ConstructForwardVarargs(MacroAssembler* masm) {
Generate_ForwardVarargs(masm, masm->isolate()->builtins()->Construct());
Generate_CallOrConstructForwardVarargs(
masm, masm->isolate()->builtins()->Construct());
}
void Builtins::Generate_ConstructFunctionForwardVarargs(MacroAssembler* masm) {
Generate_ForwardVarargs(masm,
masm->isolate()->builtins()->ConstructFunction());
Generate_CallOrConstructForwardVarargs(
masm, masm->isolate()->builtins()->ConstructFunction());
}
TF_BUILTIN(ConstructWithArrayLike, CallOrConstructBuiltinsAssembler) {
Node* target = Parameter(ConstructWithArrayLikeDescriptor::kTarget);
Node* new_target = Parameter(ConstructWithArrayLikeDescriptor::kNewTarget);
Node* arguments_list =
Parameter(ConstructWithArrayLikeDescriptor::kArgumentsList);
Node* context = Parameter(ConstructWithArrayLikeDescriptor::kContext);
CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
}
typedef compiler::Node Node;
......
......@@ -75,7 +75,9 @@ namespace internal {
ASM(TailCall_ReceiverIsNullOrUndefined) \
ASM(TailCall_ReceiverIsNotNullOrUndefined) \
ASM(TailCall_ReceiverIsAny) \
ASM(CallVarargs) \
ASM(CallWithSpread) \
TFC(CallWithArrayLike, CallWithArrayLike, 1) \
ASM(CallForwardVarargs) \
ASM(CallFunctionForwardVarargs) \
\
......@@ -89,7 +91,9 @@ namespace internal {
ASM(ConstructProxy) \
/* ES6 section 7.3.13 Construct (F, [argumentsList], [newTarget]) */ \
ASM(Construct) \
ASM(ConstructVarargs) \
ASM(ConstructWithSpread) \
TFC(ConstructWithArrayLike, ConstructWithArrayLike, 1) \
ASM(ConstructForwardVarargs) \
ASM(ConstructFunctionForwardVarargs) \
ASM(JSConstructStubApi) \
......@@ -108,7 +112,6 @@ namespace internal {
TFC(FastCloneShallowObject, FastCloneShallowObject, 1) \
\
/* Apply and entries */ \
ASM(Apply) \
ASM(JSEntryTrampoline) \
ASM(JSConstructEntryTrampoline) \
ASM(ResumeGeneratorTrampoline) \
......
......@@ -132,7 +132,10 @@ class Builtins {
static void Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode,
TailCallMode tail_call_mode);
static void Generate_ForwardVarargs(MacroAssembler* masm, Handle<Code> code);
static void Generate_CallOrConstructVarargs(MacroAssembler* masm,
Handle<Code> code);
static void Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
Handle<Code> code);
static void Generate_InterpreterPushArgsThenCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -409,6 +409,12 @@ Callable CodeFactory::CallFunction(Isolate* isolate, ConvertReceiverMode mode,
CallTrampolineDescriptor(isolate));
}
// static
Callable CodeFactory::CallVarargs(Isolate* isolate) {
return Callable(isolate->builtins()->CallVarargs(),
CallVarargsDescriptor(isolate));
}
// static
Callable CodeFactory::CallForwardVarargs(Isolate* isolate) {
return Callable(isolate->builtins()->CallForwardVarargs(),
......@@ -439,6 +445,12 @@ Callable CodeFactory::ConstructFunction(Isolate* isolate) {
ConstructTrampolineDescriptor(isolate));
}
// static
Callable CodeFactory::ConstructVarargs(Isolate* isolate) {
return Callable(isolate->builtins()->ConstructVarargs(),
ConstructVarargsDescriptor(isolate));
}
// static
Callable CodeFactory::ConstructForwardVarargs(Isolate* isolate) {
return Callable(isolate->builtins()->ConstructForwardVarargs(),
......
......@@ -146,11 +146,13 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable CallFunction(
Isolate* isolate, ConvertReceiverMode mode = ConvertReceiverMode::kAny,
TailCallMode tail_call_mode = TailCallMode::kDisallow);
static Callable CallVarargs(Isolate* isolate);
static Callable CallForwardVarargs(Isolate* isolate);
static Callable CallFunctionForwardVarargs(Isolate* isolate);
static Callable Construct(Isolate* isolate);
static Callable ConstructWithSpread(Isolate* isolate);
static Callable ConstructFunction(Isolate* isolate);
static Callable ConstructVarargs(Isolate* isolate);
static Callable ConstructForwardVarargs(Isolate* isolate);
static Callable ConstructFunctionForwardVarargs(Isolate* isolate);
static Callable CreateIterResultObject(Isolate* isolate);
......
......@@ -156,6 +156,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
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
// ebx : arguments list (FixedArray)
// ecx : arguments list length (untagged)
Register registers[] = {edi, eax, ebx, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
......@@ -165,6 +175,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// edi : the target to call
// ebx : the arguments list
Register registers[] = {edi, ebx};
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
// ebx : arguments list (FixedArray)
// ecx : arguments list length (untagged)
Register registers[] = {edi, edx, eax, ebx, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
......@@ -175,6 +204,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// edi : the target to call
// edx : the new target
// ebx : the arguments list
Register registers[] = {edi, edx, ebx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
......
......@@ -821,6 +821,16 @@ void MacroAssembler::AssertSmi(Register object) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
test(object, Immediate(kSmiTagMask));
Check(not_equal, kOperandIsASmiAndNotAFixedArray);
Push(object);
CmpObjectType(object, FIXED_ARRAY_TYPE, object);
Pop(object);
Check(equal, kOperandIsNotAFixedArray);
}
}
void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) {
......
......@@ -521,6 +521,9 @@ class MacroAssembler: public Assembler {
// Abort execution if argument is a smi, enabled via --debug-code.
void AssertNotSmi(Register object);
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
// Abort execution if argument is not a JSFunction, enabled via --debug-code.
void AssertFunction(Register object);
......
......@@ -459,6 +459,16 @@ void CallTrampolineDescriptor::InitializePlatformIndependent(
machine_types);
}
void CallVarargsDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kTarget, kActualArgumentsCount, kArgumentsList, kArgumentsLength
MachineType machine_types[] = {MachineType::AnyTagged(), MachineType::Int32(),
MachineType::AnyTagged(),
MachineType::Int32()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void CallForwardVarargsDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kTarget, kActualArgumentsCount, kStartIndex
......@@ -468,6 +478,26 @@ void CallForwardVarargsDescriptor::InitializePlatformIndependent(
machine_types);
}
void CallWithArrayLikeDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kTarget, kArgumentsList
MachineType machine_types[] = {MachineType::AnyTagged(),
MachineType::AnyTagged()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void ConstructVarargsDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kTarget, kNewTarget, kActualArgumentsCount, kArgumentsList,
// kArgumentsLength
MachineType machine_types[] = {
MachineType::AnyTagged(), MachineType::AnyTagged(), MachineType::Int32(),
MachineType::AnyTagged(), MachineType::Int32()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void ConstructForwardVarargsDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kTarget, kNewTarget, kActualArgumentsCount, kStartIndex
......@@ -478,6 +508,16 @@ void ConstructForwardVarargsDescriptor::InitializePlatformIndependent(
machine_types);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kTarget, kNewTarget, kArgumentsList
MachineType machine_types[] = {MachineType::AnyTagged(),
MachineType::AnyTagged(),
MachineType::AnyTagged()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void ConstructStubDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kFunction, kNewTarget, kActualArgumentsCount, kAllocationSite
......
......@@ -44,11 +44,15 @@ class PlatformInterfaceDescriptor;
V(CallFunction) \
V(CallIC) \
V(CallICTrampoline) \
V(CallVarargs) \
V(CallForwardVarargs) \
V(CallWithArrayLike) \
V(CallConstruct) \
V(CallTrampoline) \
V(ConstructStub) \
V(ConstructVarargs) \
V(ConstructForwardVarargs) \
V(ConstructWithArrayLike) \
V(ConstructTrampoline) \
V(TransitionElementsKind) \
V(AllocateHeapNumber) \
......@@ -574,6 +578,14 @@ class CallTrampolineDescriptor : public CallInterfaceDescriptor {
CallInterfaceDescriptor)
};
class CallVarargsDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kTarget, kActualArgumentsCount, kArgumentsList,
kArgumentsLength)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CallVarargsDescriptor,
CallInterfaceDescriptor)
};
class CallForwardVarargsDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kTarget, kActualArgumentsCount, kStartIndex)
......@@ -581,6 +593,21 @@ class CallForwardVarargsDescriptor : public CallInterfaceDescriptor {
CallInterfaceDescriptor)
};
class CallWithArrayLikeDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kTarget, kArgumentsList)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CallWithArrayLikeDescriptor,
CallInterfaceDescriptor)
};
class ConstructVarargsDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kTarget, kNewTarget, kActualArgumentsCount, kArgumentsList,
kArgumentsLength)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ConstructVarargsDescriptor,
CallInterfaceDescriptor)
};
class ConstructForwardVarargsDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kTarget, kNewTarget, kActualArgumentsCount, kStartIndex)
......@@ -588,6 +615,13 @@ class ConstructForwardVarargsDescriptor : public CallInterfaceDescriptor {
ConstructForwardVarargsDescriptor, CallInterfaceDescriptor)
};
class ConstructWithArrayLikeDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kTarget, kNewTarget, kArgumentsList)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ConstructWithArrayLikeDescriptor,
CallInterfaceDescriptor)
};
class ConstructStubDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kFunction, kNewTarget, kActualArgumentsCount,
......
......@@ -155,6 +155,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a0 : number of arguments (on the stack, not including receiver)
// a1 : the target to call
// a2 : arguments list (FixedArray)
// t0 : arguments list length (untagged)
Register registers[] = {a1, a0, a2, t0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1: the target to call
......@@ -164,6 +174,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1 : the target to call
// a2 : the arguments list
Register registers[] = {a1, a2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a0 : number of arguments (on the stack, not including receiver)
// a1 : the target to call
// a3 : the new target
// a2 : arguments list (FixedArray)
// t0 : arguments list length (untagged)
Register registers[] = {a1, a3, a0, a2, t0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1: the target to call
......@@ -174,6 +203,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1 : the target to call
// a3 : the new target
// a2 : the arguments list
Register registers[] = {a1, a3, a2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1: target
......
......@@ -5872,6 +5872,15 @@ void MacroAssembler::AssertSmi(Register object) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
SmiTst(object, t8);
Check(ne, kOperandIsASmiAndNotAFixedArray, t8, Operand(zero_reg));
GetObjectType(object, t8, t8);
Check(eq, kOperandIsNotAFixedArray, t8, Operand(FIXED_ARRAY_TYPE));
}
}
void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) {
......
......@@ -1538,6 +1538,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
void AssertNotSmi(Register object);
void AssertSmi(Register object);
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
// Abort execution if argument is not a JSFunction, enabled via --debug-code.
void AssertFunction(Register object);
......
......@@ -155,6 +155,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a0 : number of arguments (on the stack, not including receiver)
// a1 : the target to call
// a2 : arguments list (FixedArray)
// a4 : arguments list length (untagged)
Register registers[] = {a1, a0, a2, a4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1: the target to call
......@@ -164,6 +174,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1 : the target to call
// a2 : the arguments list
Register registers[] = {a1, a2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a0 : number of arguments (on the stack, not including receiver)
// a1 : the target to call
// a3 : the new target
// a2 : arguments list (FixedArray)
// a4 : arguments list length (untagged)
Register registers[] = {a1, a3, a0, a2, a4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1: the target to call
......@@ -174,6 +203,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1 : the target to call
// a3 : the new target
// a2 : the arguments list
Register registers[] = {a1, a3, a2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// a1: target
......
......@@ -6335,6 +6335,15 @@ void MacroAssembler::AssertSmi(Register object) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
SmiTst(object, t8);
Check(ne, kOperandIsASmiAndNotAFixedArray, t8, Operand(zero_reg));
GetObjectType(object, t8, t8);
Check(eq, kOperandIsNotAFixedArray, t8, Operand(FIXED_ARRAY_TYPE));
}
}
void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) {
......
......@@ -1692,6 +1692,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
void AssertNotSmi(Register object);
void AssertSmi(Register object);
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
// Abort execution if argument is not a JSFunction, enabled via --debug-code.
void AssertFunction(Register object);
......
......@@ -180,6 +180,7 @@
'builtins/builtins-async-iterator-gen.cc',
'builtins/builtins-boolean-gen.cc',
'builtins/builtins-call-gen.cc',
'builtins/builtins-call-gen.h',
'builtins/builtins-collections-gen.cc',
'builtins/builtins-console-gen.cc',
'builtins/builtins-constructor-gen.cc',
......
......@@ -155,6 +155,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
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
// rbx : arguments list (FixedArray)
// rcx : arguments list length (untagged)
Register registers[] = {rdi, rax, rbx, rcx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments
......@@ -164,6 +174,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
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
// rbx : arguments list (FixedArray)
// rcx : arguments list length (untagged)
Register registers[] = {rdi, rdx, rax, rbx, rcx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// rax : number of arguments
......@@ -174,6 +203,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
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
......
......@@ -3686,6 +3686,16 @@ void MacroAssembler::AssertSmi(const Operand& object) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
testb(object, Immediate(kSmiTagMask));
Check(not_equal, kOperandIsASmiAndNotAFixedArray);
Push(object);
CmpObjectType(object, FIXED_ARRAY_TYPE, object);
Pop(object);
Check(equal, kOperandIsNotAFixedArray);
}
}
void MacroAssembler::AssertZeroExtended(Register int32_register) {
if (emit_debug_code()) {
......
......@@ -1145,6 +1145,9 @@ class MacroAssembler: public Assembler {
void AssertSmi(Register object);
void AssertSmi(const Operand& object);
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
// Abort execution if a 64 bit register containing a 32 bit payload does not
// have zeros in the top 32 bits, enabled via --debug-code.
void AssertZeroExtended(Register reg);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment