Chromium Code Reviews| Index: src/builtins/builtins-internal.cc |
| diff --git a/src/builtins/builtins-internal.cc b/src/builtins/builtins-internal.cc |
| index a8c98bf0c15e4fff203754b8f6d7cefbc2da771c..368101339bc71fadfe5afbe226bcea5f87780f72 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; |
| + |
| + // Compute the effective {offset} into the {frame}. |
| + Node* offset = assembler->IntPtrAdd(length, assembler->IntPtrConstant(1)); |
|
Jarin
2016/12/08 07:49:21
Why is this defined here? Would not it be enough t
Benedikt Meurer
2016/12/08 07:58:15
Indeed.
|
| + |
| + // 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); |
| + |
| + // 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 |