Commit 0df85278 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Add NewUnmappedArgumentsElements and NewRestParametersArguments.

First step towards making arguments and rest parameters optimizable by
splitting the allocations for the actual object and the elements. The
object allocations can already be escape analyzed this way, the elements
would need special support in the deoptimizer and the escape analysis,
but that can be done as a second separate step.

R=jarin@chromium.org
BUG=v8:5726

Review-Url: https://codereview.chromium.org/2557283002
Cr-Commit-Position: refs/heads/master@{#41573}
parent 00c82cd1
......@@ -141,5 +141,175 @@ void Builtins::Generate_GrowFastSmiOrObjectElements(
assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
}
namespace {
void Generate_NewArgumentsElements(CodeStubAssembler* assembler,
compiler::Node* frame,
compiler::Node* length) {
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;
typedef compiler::Node Node;
// Check if we can allocate in new space.
ElementsKind kind = FAST_ELEMENTS;
int max_elements = FixedArray::GetMaxLengthForNewSpaceAllocation(kind);
Label if_newspace(assembler), if_oldspace(assembler, Label::kDeferred);
assembler->Branch(assembler->IntPtrLessThan(
length, assembler->IntPtrConstant(max_elements)),
&if_newspace, &if_oldspace);
assembler->Bind(&if_newspace);
{
// Prefer EmptyFixedArray in case of non-positive {length} (the {length}
// can be negative here for rest parameters).
Label if_empty(assembler), if_notempty(assembler);
assembler->Branch(
assembler->IntPtrLessThanOrEqual(length, assembler->IntPtrConstant(0)),
&if_empty, &if_notempty);
assembler->Bind(&if_empty);
assembler->Return(assembler->EmptyFixedArrayConstant());
assembler->Bind(&if_notempty);
{
// Allocate a FixedArray in new space.
Node* result = assembler->AllocateFixedArray(
kind, length, CodeStubAssembler::INTPTR_PARAMETERS);
// Compute the effective {offset} into the {frame}.
Node* offset = assembler->IntPtrAdd(length, assembler->IntPtrConstant(1));
// Copy the parameters from {frame} (starting at {offset}) to {result}.
Variable var_index(assembler, MachineType::PointerRepresentation());
Label loop(assembler, &var_index), done_loop(assembler);
var_index.Bind(assembler->IntPtrConstant(0));
assembler->Goto(&loop);
assembler->Bind(&loop);
{
// Load the current {index}.
Node* index = var_index.value();
// Check if we are done.
assembler->GotoIf(assembler->WordEqual(index, length), &done_loop);
// Load the parameter at the given {index}.
Node* value = assembler->Load(
MachineType::AnyTagged(), frame,
assembler->WordShl(assembler->IntPtrSub(offset, index),
assembler->IntPtrConstant(kPointerSizeLog2)));
// Store the {value} into the {result}.
assembler->StoreFixedArrayElement(result, index, value,
SKIP_WRITE_BARRIER, 0,
CodeStubAssembler::INTPTR_PARAMETERS);
// Continue with next {index}.
var_index.Bind(
assembler->IntPtrAdd(index, assembler->IntPtrConstant(1)));
assembler->Goto(&loop);
}
assembler->Bind(&done_loop);
assembler->Return(result);
}
}
assembler->Bind(&if_oldspace);
{
// Allocate in old space (or large object space).
assembler->TailCallRuntime(
Runtime::kNewArgumentsElements, assembler->NoContextConstant(),
assembler->BitcastWordToTagged(frame), assembler->SmiFromWord(length));
}
}
} // namespace
void Builtins::Generate_NewUnmappedArgumentsElements(
compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;
typedef compiler::Node Node;
typedef NewArgumentsElementsDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* formal_parameter_count =
assembler.Parameter(Descriptor::kFormalParameterCount);
// Determine the frame that holds the parameters.
Label done(&assembler);
Variable var_frame(&assembler, MachineType::PointerRepresentation()),
var_length(&assembler, MachineType::PointerRepresentation());
var_frame.Bind(assembler.LoadParentFramePointer());
var_length.Bind(formal_parameter_count);
Node* parent_frame = assembler.Load(
MachineType::Pointer(), var_frame.value(),
assembler.IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
Node* parent_frame_type =
assembler.Load(MachineType::AnyTagged(), parent_frame,
assembler.IntPtrConstant(
CommonFrameConstants::kContextOrFrameTypeOffset));
assembler.GotoUnless(
assembler.WordEqual(
parent_frame_type,
assembler.SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
&done);
{
// Determine the length from the ArgumentsAdaptorFrame.
Node* length = assembler.LoadAndUntagSmi(
parent_frame, ArgumentsAdaptorFrameConstants::kLengthOffset);
// Take the arguments from the ArgumentsAdaptorFrame.
var_frame.Bind(parent_frame);
var_length.Bind(length);
}
assembler.Goto(&done);
// Allocate the actual FixedArray for the elements.
assembler.Bind(&done);
Generate_NewArgumentsElements(&assembler, var_frame.value(),
var_length.value());
}
void Builtins::Generate_NewRestParameterElements(
compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef NewArgumentsElementsDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* formal_parameter_count =
assembler.Parameter(Descriptor::kFormalParameterCount);
// Check if we have an ArgumentsAdaptorFrame, as we will only have rest
// parameters in that case.
Label if_empty(&assembler);
Node* frame = assembler.Load(
MachineType::Pointer(), assembler.LoadParentFramePointer(),
assembler.IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
Node* frame_type =
assembler.Load(MachineType::AnyTagged(), frame,
assembler.IntPtrConstant(
CommonFrameConstants::kContextOrFrameTypeOffset));
assembler.GotoUnless(
assembler.WordEqual(frame_type, assembler.SmiConstant(Smi::FromInt(
StackFrame::ARGUMENTS_ADAPTOR))),
&if_empty);
// Determine the length from the ArgumentsAdaptorFrame.
Node* frame_length = assembler.LoadAndUntagSmi(
frame, ArgumentsAdaptorFrameConstants::kLengthOffset);
// Compute the actual rest parameter length (may be negative).
Node* length = assembler.IntPtrSub(frame_length, formal_parameter_count);
// Allocate the actual FixedArray for the elements.
Generate_NewArgumentsElements(&assembler, frame, length);
// No rest parameters, return an empty FixedArray.
assembler.Bind(&if_empty);
assembler.Return(assembler.EmptyFixedArrayConstant());
}
} // namespace internal
} // namespace v8
......@@ -151,6 +151,10 @@ namespace internal {
TFS(GrowFastDoubleElements, BUILTIN, kNoExtraICState, GrowArrayElements) \
TFS(GrowFastSmiOrObjectElements, BUILTIN, kNoExtraICState, \
GrowArrayElements) \
TFS(NewUnmappedArgumentsElements, BUILTIN, kNoExtraICState, \
NewArgumentsElements) \
TFS(NewRestParameterElements, BUILTIN, kNoExtraICState, \
NewArgumentsElements) \
\
/* Debugger */ \
DBG(FrameDropper_LiveEdit) \
......
......@@ -242,6 +242,8 @@ TFS_BUILTIN(Typeof)
TFS_BUILTIN(InstanceOf)
TFS_BUILTIN(OrdinaryHasInstance)
TFS_BUILTIN(ForInFilter)
TFS_BUILTIN(NewUnmappedArgumentsElements)
TFS_BUILTIN(NewRestParameterElements)
#undef TFS_BUILTIN
......
......@@ -141,6 +141,9 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable GrowFastDoubleElements(Isolate* isolate);
static Callable GrowFastSmiOrObjectElements(Isolate* isolate);
static Callable NewUnmappedArgumentsElements(Isolate* isolate);
static Callable NewRestParameterElements(Isolate* isolate);
static Callable AllocateHeapNumber(Isolate* isolate);
#define SIMD128_ALLOC(TYPE, Type, type, lane_count, lane_type) \
static Callable Allocate##Type(Isolate* isolate);
......
......@@ -730,6 +730,12 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kObjectIsUndetectable:
state = LowerObjectIsUndetectable(node, *effect, *control);
break;
case IrOpcode::kNewRestParameterElements:
state = LowerNewRestParameterElements(node, *effect, *control);
break;
case IrOpcode::kNewUnmappedArgumentsElements:
state = LowerNewUnmappedArgumentsElements(node, *effect, *control);
break;
case IrOpcode::kArrayBufferWasNeutered:
state = LowerArrayBufferWasNeutered(node, *effect, *control);
break;
......@@ -2163,6 +2169,42 @@ EffectControlLinearizer::LowerObjectIsUndetectable(Node* node, Node* effect,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerNewRestParameterElements(Node* node, Node* effect,
Node* control) {
int const formal_parameter_count = ParameterCountOf(node->op());
Callable const callable = CodeFactory::NewRestParameterElements(isolate());
Operator::Properties const properties = node->op()->properties();
CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
Node* value = effect = graph()->NewNode(
common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
jsgraph()->IntPtrConstant(formal_parameter_count),
jsgraph()->NoContextConstant(), effect);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerNewUnmappedArgumentsElements(Node* node,
Node* effect,
Node* control) {
int const formal_parameter_count = ParameterCountOf(node->op());
Callable const callable =
CodeFactory::NewUnmappedArgumentsElements(isolate());
Operator::Properties const properties = node->op()->properties();
CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
Node* value = effect = graph()->NewNode(
common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
jsgraph()->IntPtrConstant(formal_parameter_count),
jsgraph()->NoContextConstant(), effect);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node, Node* effect,
Node* control) {
......
......@@ -143,6 +143,10 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* control);
ValueEffectControl LowerObjectIsUndetectable(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerNewRestParameterElements(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerNewUnmappedArgumentsElements(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerArrayBufferWasNeutered(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerStringCharCodeAt(Node* node, Node* effect,
......
......@@ -295,46 +295,130 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
if (outer_state->opcode() != IrOpcode::kFrameState) {
switch (type) {
case CreateArgumentsType::kMappedArguments: {
// TODO(mstarzinger): Duplicate parameters are not handled yet.
// TODO(bmeurer): Make deoptimization mandatory for the various
// arguments objects, so that we always have a shared_info here.
Handle<SharedFunctionInfo> shared_info;
if (!state_info.shared_info().ToHandle(&shared_info) ||
shared_info->has_duplicate_parameters()) {
return NoChange();
if (state_info.shared_info().ToHandle(&shared_info)) {
// TODO(mstarzinger): Duplicate parameters are not handled yet.
if (shared_info->has_duplicate_parameters()) return NoChange();
// If there is no aliasing, the arguments object elements are not
// special in any way, we can just return an unmapped backing store.
if (shared_info->internal_formal_parameter_count() == 0) {
Node* const callee = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
// Allocate the elements backing store.
Node* const elements = effect = graph()->NewNode(
simplified()->NewUnmappedArgumentsElements(0), effect);
Node* const length = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
elements, effect, control);
// Load the arguments object map.
Node* const arguments_map = jsgraph()->HeapConstant(
handle(native_context()->sloppy_arguments_map(), isolate()));
// Actually allocate and initialize the arguments object.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
a.Allocate(JSSloppyArgumentsObject::kSize);
a.Store(AccessBuilder::ForMap(), arguments_map);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForArgumentsLength(), length);
a.Store(AccessBuilder::ForArgumentsCallee(), callee);
RelaxControls(node);
a.FinishAndChange(node);
} else {
Callable callable = CodeFactory::FastNewSloppyArguments(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNoFlags, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
node->RemoveInput(3); // Remove the frame state.
NodeProperties::ChangeOp(node, new_op);
}
return Changed(node);
}
Callable callable = CodeFactory::FastNewSloppyArguments(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNoFlags, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
node->RemoveInput(3); // Remove the frame state.
NodeProperties::ChangeOp(node, new_op);
return Changed(node);
return NoChange();
}
case CreateArgumentsType::kUnmappedArguments: {
Callable callable = CodeFactory::FastNewStrictArguments(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
NodeProperties::ChangeOp(node, new_op);
Handle<SharedFunctionInfo> shared_info;
if (state_info.shared_info().ToHandle(&shared_info)) {
Node* effect = NodeProperties::GetEffectInput(node);
// Allocate the elements backing store.
Node* const elements = effect = graph()->NewNode(
simplified()->NewUnmappedArgumentsElements(
shared_info->internal_formal_parameter_count()),
effect);
Node* const length = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
elements, effect, control);
// Load the arguments object map.
Node* const arguments_map = jsgraph()->HeapConstant(
handle(native_context()->strict_arguments_map(), isolate()));
// Actually allocate and initialize the arguments object.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
a.Allocate(JSStrictArgumentsObject::kSize);
a.Store(AccessBuilder::ForMap(), arguments_map);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForArgumentsLength(), length);
RelaxControls(node);
a.FinishAndChange(node);
} else {
Callable callable = CodeFactory::FastNewStrictArguments(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
NodeProperties::ChangeOp(node, new_op);
}
return Changed(node);
}
case CreateArgumentsType::kRestParameter: {
Callable callable = CodeFactory::FastNewRestParameter(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
NodeProperties::ChangeOp(node, new_op);
Handle<SharedFunctionInfo> shared_info;
if (state_info.shared_info().ToHandle(&shared_info)) {
Node* effect = NodeProperties::GetEffectInput(node);
// Allocate the elements backing store.
Node* const elements = effect = graph()->NewNode(
simplified()->NewRestParameterElements(
shared_info->internal_formal_parameter_count()),
effect);
Node* const length = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
elements, effect, control);
// Load the JSArray object map.
Node* const jsarray_map = jsgraph()->HeapConstant(handle(
native_context()->js_array_fast_elements_map_index(), isolate()));
// Actually allocate and initialize the jsarray.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
a.Allocate(JSArray::kSize);
a.Store(AccessBuilder::ForMap(), jsarray_map);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), length);
RelaxControls(node);
a.FinishAndChange(node);
} else {
Callable callable = CodeFactory::FastNewRestParameter(isolate());
Operator::Properties properties = node->op()->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, properties);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
NodeProperties::ChangeOp(node, new_op);
}
return Changed(node);
}
}
......
......@@ -323,6 +323,8 @@
V(ObjectIsSmi) \
V(ObjectIsString) \
V(ObjectIsUndetectable) \
V(NewRestParameterElements) \
V(NewUnmappedArgumentsElements) \
V(ArrayBufferWasNeutered) \
V(EnsureWritableFastElements) \
V(MaybeGrowFastElements) \
......
......@@ -2489,6 +2489,12 @@ class RepresentationSelector {
VisitObjectIs(node, Type::Undetectable(), lowering);
return;
}
case IrOpcode::kNewRestParameterElements:
case IrOpcode::kNewUnmappedArgumentsElements: {
ProcessRemainingInputs(node, 0);
SetOutput(node, MachineRepresentation::kTaggedPointer);
return;
}
case IrOpcode::kArrayBufferWasNeutered: {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
return;
......
......@@ -331,6 +331,12 @@ NumberOperationHint NumberOperationHintOf(const Operator* op) {
return OpParameter<NumberOperationHint>(op);
}
int ParameterCountOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kNewUnmappedArgumentsElements ||
op->opcode() == IrOpcode::kNewRestParameterElements);
return OpParameter<int>(op);
}
PretenureFlag PretenureFlagOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
return OpParameter<PretenureFlag>(op);
......@@ -737,6 +743,26 @@ const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
transition); // parameter
}
const Operator* SimplifiedOperatorBuilder::NewUnmappedArgumentsElements(
int parameter_count) {
return new (zone()) Operator1<int>( // --
IrOpcode::kNewUnmappedArgumentsElements, // opcode
Operator::kEliminatable, // flags
"NewUnmappedArgumentsElements", // name
0, 1, 0, 1, 1, 0, // counts
parameter_count); // parameter
}
const Operator* SimplifiedOperatorBuilder::NewRestParameterElements(
int parameter_count) {
return new (zone()) Operator1<int>( // --
IrOpcode::kNewRestParameterElements, // opcode
Operator::kEliminatable, // flags
"NewRestParameterElements", // name
0, 1, 0, 1, 1, 0, // counts
parameter_count); // parameter
}
const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) {
switch (pretenure) {
case NOT_TENURED:
......
......@@ -186,6 +186,8 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, NumberOperationHint);
NumberOperationHint NumberOperationHintOf(const Operator* op)
WARN_UNUSED_RESULT;
int ParameterCountOf(const Operator* op) WARN_UNUSED_RESULT;
PretenureFlag PretenureFlagOf(const Operator* op) WARN_UNUSED_RESULT;
UnicodeEncoding UnicodeEncodingOf(const Operator*) WARN_UNUSED_RESULT;
......@@ -355,6 +357,12 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* ObjectIsString();
const Operator* ObjectIsUndetectable();
// new-rest-parameter-elements
const Operator* NewRestParameterElements(int parameter_count);
// new-unmapped-arguments-elements
const Operator* NewUnmappedArgumentsElements(int parameter_count);
// array-buffer-was-neutered buffer
const Operator* ArrayBufferWasNeutered();
......
......@@ -141,6 +141,10 @@ class TypeCache final {
Type* const kJSDateYearType =
Type::Union(Type::SignedSmall(), Type::NaN(), zone());
// The valid number of arguments for JavaScript functions.
Type* const kArgumentsLengthType =
Type::Range(0.0, Code::kMaxArguments, zone());
private:
template <typename T>
Type* CreateRange() {
......
......@@ -1826,6 +1826,14 @@ Type* Typer::Visitor::TypeObjectIsUndetectable(Node* node) {
return TypeUnaryOp(node, ObjectIsUndetectable);
}
Type* Typer::Visitor::TypeNewUnmappedArgumentsElements(Node* node) {
return Type::OtherInternal();
}
Type* Typer::Visitor::TypeNewRestParameterElements(Node* node) {
return Type::OtherInternal();
}
Type* Typer::Visitor::TypeArrayBufferWasNeutered(Node* node) {
return Type::Boolean();
}
......
......@@ -916,6 +916,10 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::Boolean());
break;
case IrOpcode::kNewRestParameterElements:
case IrOpcode::kNewUnmappedArgumentsElements:
CheckTypeIs(node, Type::OtherInternal());
break;
case IrOpcode::kAllocate:
CheckValueInputIs(node, 0, Type::PlainNumber());
break;
......
......@@ -294,6 +294,18 @@ void GrowArrayElementsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void NewArgumentsElementsDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
MachineType const kMachineTypes[] = {MachineType::IntPtr()};
data->InitializePlatformIndependent(arraysize(kMachineTypes), 0,
kMachineTypes);
}
void NewArgumentsElementsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, 1);
}
void VarArgFunctionDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kActualArgumentsCount
......
......@@ -87,6 +87,7 @@ class PlatformInterfaceDescriptor;
V(MathPowTagged) \
V(MathPowInteger) \
V(GrowArrayElements) \
V(NewArgumentsElements) \
V(InterpreterDispatch) \
V(InterpreterPushArgsAndCall) \
V(InterpreterPushArgsAndConstruct) \
......@@ -779,6 +780,13 @@ class GrowArrayElementsDescriptor : public CallInterfaceDescriptor {
static const Register KeyRegister();
};
class NewArgumentsElementsDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kFormalParameterCount)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(NewArgumentsElementsDescriptor,
CallInterfaceDescriptor)
};
class V8_EXPORT_PRIVATE InterpreterDispatchDescriptor
: public CallInterfaceDescriptor {
public:
......
......@@ -592,6 +592,21 @@ RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
}
RUNTIME_FUNCTION(Runtime_NewArgumentsElements) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
Object** frame = reinterpret_cast<Object**>(args[0]);
CONVERT_SMI_ARG_CHECKED(length, 1);
Handle<FixedArray> result =
isolate->factory()->NewUninitializedFixedArray(length);
int const offset = length + 1;
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int index = 0; index < length; ++index) {
result->set(index, frame[offset - index], mode);
}
return *result;
}
RUNTIME_FUNCTION(Runtime_NewClosure) {
HandleScope scope(isolate);
......
......@@ -489,6 +489,7 @@ namespace internal {
F(NewStrictArguments, 1, 1) \
F(NewRestParameter, 1, 1) \
F(NewSloppyArguments, 3, 1) \
F(NewArgumentsElements, 2, 1) \
F(NewClosure, 1, 1) \
F(NewClosure_Tenured, 1, 1) \
F(NewScriptContext, 2, 1) \
......
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