| Index: src/builtins/builtins-internal.cc
|
| diff --git a/src/builtins/builtins-internal.cc b/src/builtins/builtins-internal.cc
|
| index a8c98bf0c15e4fff203754b8f6d7cefbc2da771c..39b1ca77695a6342bbbf6dd513054556312dc774 100644
|
| --- a/src/builtins/builtins-internal.cc
|
| +++ b/src/builtins/builtins-internal.cc
|
| @@ -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
|
|
|