LCOV - code coverage report
Current view: top level - src/builtins - builtins-arguments-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 168 168 100.0 %
Date: 2019-04-18 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-arguments-gen.h"
       6             : 
       7             : #include "src/arguments.h"
       8             : #include "src/builtins/builtins-utils-gen.h"
       9             : #include "src/builtins/builtins.h"
      10             : #include "src/code-factory.h"
      11             : #include "src/code-stub-assembler.h"
      12             : #include "src/frame-constants.h"
      13             : #include "src/interface-descriptors.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/arguments.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : typedef compiler::Node Node;
      21             : 
      22             : std::tuple<Node*, Node*, Node*>
      23         392 : ArgumentsBuiltinsAssembler::AllocateArgumentsObject(Node* map,
      24             :                                                     Node* arguments_count,
      25             :                                                     Node* parameter_map_count,
      26             :                                                     ParameterMode mode,
      27             :                                                     int base_size) {
      28             :   // Allocate the parameter object (either a Rest parameter object, a strict
      29             :   // argument object or a sloppy arguments object) and the elements/mapped
      30             :   // arguments together.
      31             :   int elements_offset = base_size;
      32             :   Node* element_count = arguments_count;
      33         392 :   if (parameter_map_count != nullptr) {
      34          56 :     base_size += FixedArray::kHeaderSize;
      35          56 :     element_count = IntPtrOrSmiAdd(element_count, parameter_map_count, mode);
      36             :   }
      37         392 :   bool empty = IsIntPtrOrSmiConstantZero(arguments_count, mode);
      38             :   DCHECK_IMPLIES(empty, parameter_map_count == nullptr);
      39             :   TNode<IntPtrT> size =
      40         168 :       empty ? IntPtrConstant(base_size)
      41             :             : ElementOffsetFromIndex(element_count, PACKED_ELEMENTS, mode,
      42         560 :                                      base_size + FixedArray::kHeaderSize);
      43         784 :   TNode<Object> result = Allocate(size);
      44         392 :   Comment("Initialize arguments object");
      45         392 :   StoreMapNoWriteBarrier(result, map);
      46         784 :   Node* empty_fixed_array = LoadRoot(RootIndex::kEmptyFixedArray);
      47         392 :   StoreObjectField(result, JSArray::kPropertiesOrHashOffset, empty_fixed_array);
      48             :   Node* smi_arguments_count = ParameterToTagged(arguments_count, mode);
      49             :   StoreObjectFieldNoWriteBarrier(result, JSArray::kLengthOffset,
      50         392 :                                  smi_arguments_count);
      51             :   Node* arguments = nullptr;
      52         392 :   if (!empty) {
      53         448 :     arguments = InnerAllocate(CAST(result), elements_offset);
      54             :     StoreObjectFieldNoWriteBarrier(arguments, FixedArray::kLengthOffset,
      55         224 :                                    smi_arguments_count);
      56         448 :     Node* fixed_array_map = LoadRoot(RootIndex::kFixedArrayMap);
      57         224 :     StoreMapNoWriteBarrier(arguments, fixed_array_map);
      58             :   }
      59             :   Node* parameter_map = nullptr;
      60         392 :   if (parameter_map_count != nullptr) {
      61             :     TNode<IntPtrT> parameter_map_offset = ElementOffsetFromIndex(
      62          56 :         arguments_count, PACKED_ELEMENTS, mode, FixedArray::kHeaderSize);
      63         112 :     parameter_map = InnerAllocate(CAST(arguments), parameter_map_offset);
      64             :     StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
      65          56 :                                    parameter_map);
      66             :     Node* sloppy_elements_map =
      67         112 :         LoadRoot(RootIndex::kSloppyArgumentsElementsMap);
      68          56 :     StoreMapNoWriteBarrier(parameter_map, sloppy_elements_map);
      69             :     parameter_map_count = ParameterToTagged(parameter_map_count, mode);
      70             :     StoreObjectFieldNoWriteBarrier(parameter_map, FixedArray::kLengthOffset,
      71          56 :                                    parameter_map_count);
      72             :   } else {
      73         336 :     if (empty) {
      74             :       StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
      75         168 :                                      empty_fixed_array);
      76             :     } else {
      77             :       StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
      78         168 :                                      arguments);
      79             :     }
      80             :   }
      81         392 :   return std::tuple<Node*, Node*, Node*>(result, arguments, parameter_map);
      82             : }
      83             : 
      84         168 : Node* ArgumentsBuiltinsAssembler::ConstructParametersObjectFromArgs(
      85             :     Node* map, Node* frame_ptr, Node* arg_count, Node* first_arg,
      86             :     Node* rest_count, ParameterMode param_mode, int base_size) {
      87             :   // Allocate the parameter object (either a Rest parameter object, a strict
      88             :   // argument object or a sloppy arguments object) and the elements together and
      89             :   // fill in the contents with the arguments above |formal_parameter_count|.
      90             :   Node* result;
      91             :   Node* elements;
      92             :   Node* unused;
      93             :   std::tie(result, elements, unused) =
      94         336 :       AllocateArgumentsObject(map, rest_count, nullptr, param_mode, base_size);
      95             :   DCHECK_NULL(unused);
      96         168 :   CodeStubArguments arguments(this, arg_count, frame_ptr, param_mode);
      97         336 :   VARIABLE(offset, MachineType::PointerRepresentation());
      98         336 :   offset.Bind(IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag));
      99         336 :   VariableList list({&offset}, zone());
     100         168 :   arguments.ForEach(list,
     101         504 :                     [this, elements, &offset](Node* arg) {
     102         336 :                       StoreNoWriteBarrier(MachineRepresentation::kTagged,
     103         168 :                                           elements, offset.value(), arg);
     104         168 :                       Increment(&offset, kTaggedSize);
     105         168 :                     },
     106         168 :                     first_arg, nullptr, param_mode);
     107         168 :   return result;
     108             : }
     109             : 
     110          56 : Node* ArgumentsBuiltinsAssembler::EmitFastNewRestParameter(Node* context,
     111             :                                                            Node* function) {
     112             :   ParameterMode mode = OptimalParameterMode();
     113          56 :   Node* zero = IntPtrOrSmiConstant(0, mode);
     114             : 
     115             :   ArgumentsBuiltinsFromDSLAssembler::ArgumentsInfo info =
     116             :       GetArgumentsFrameAndCount(CAST(context),
     117          56 :                                 UncheckedCast<JSFunction>(function));
     118             : 
     119         112 :   VARIABLE(result, MachineRepresentation::kTagged);
     120          56 :   Label no_rest_parameters(this), runtime(this, Label::kDeferred),
     121          56 :       done(this, &result);
     122             : 
     123             :   Node* rest_count =
     124          56 :       IntPtrOrSmiSub(info.argument_count, info.formal_parameter_count, mode);
     125         112 :   Node* const native_context = LoadNativeContext(context);
     126             :   Node* const array_map =
     127         112 :       LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
     128         112 :   GotoIf(IntPtrOrSmiLessThanOrEqual(rest_count, zero, mode),
     129          56 :          &no_rest_parameters);
     130             : 
     131             :   GotoIfFixedArraySizeDoesntFitInNewSpace(
     132          56 :       rest_count, &runtime, JSArray::kSize + FixedArray::kHeaderSize, mode);
     133             : 
     134             :   // Allocate the Rest JSArray and the elements together and fill in the
     135             :   // contents with the arguments above |formal_parameter_count|.
     136          56 :   result.Bind(ConstructParametersObjectFromArgs(
     137             :       array_map, info.frame, info.argument_count, info.formal_parameter_count,
     138          56 :       rest_count, mode, JSArray::kSize));
     139          56 :   Goto(&done);
     140             : 
     141          56 :   BIND(&no_rest_parameters);
     142             :   {
     143             :     Node* arguments;
     144             :     Node* elements;
     145             :     Node* unused;
     146             :     std::tie(arguments, elements, unused) =
     147         112 :         AllocateArgumentsObject(array_map, zero, nullptr, mode, JSArray::kSize);
     148          56 :     result.Bind(arguments);
     149          56 :     Goto(&done);
     150             :   }
     151             : 
     152          56 :   BIND(&runtime);
     153             :   {
     154          56 :     result.Bind(CallRuntime(Runtime::kNewRestParameter, context, function));
     155          56 :     Goto(&done);
     156             :   }
     157             : 
     158          56 :   BIND(&done);
     159         112 :   return result.value();
     160             : }
     161             : 
     162          56 : Node* ArgumentsBuiltinsAssembler::EmitFastNewStrictArguments(Node* context,
     163             :                                                              Node* function) {
     164         112 :   VARIABLE(result, MachineRepresentation::kTagged);
     165          56 :   Label done(this, &result), empty(this), runtime(this, Label::kDeferred);
     166             : 
     167             :   ParameterMode mode = OptimalParameterMode();
     168          56 :   Node* zero = IntPtrOrSmiConstant(0, mode);
     169             : 
     170             :   ArgumentsBuiltinsFromDSLAssembler::ArgumentsInfo info =
     171             :       GetArgumentsFrameAndCount(CAST(context),
     172          56 :                                 UncheckedCast<JSFunction>(function));
     173             : 
     174             :   GotoIfFixedArraySizeDoesntFitInNewSpace(
     175             :       info.argument_count, &runtime,
     176          56 :       JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize, mode);
     177             : 
     178         112 :   Node* const native_context = LoadNativeContext(context);
     179             :   Node* const map =
     180         112 :       LoadContextElement(native_context, Context::STRICT_ARGUMENTS_MAP_INDEX);
     181         112 :   GotoIf(WordEqual(info.argument_count, zero), &empty);
     182             : 
     183          56 :   result.Bind(ConstructParametersObjectFromArgs(
     184             :       map, info.frame, info.argument_count, zero, info.argument_count, mode,
     185          56 :       JSStrictArgumentsObject::kSize));
     186          56 :   Goto(&done);
     187             : 
     188          56 :   BIND(&empty);
     189             :   {
     190             :     Node* arguments;
     191             :     Node* elements;
     192             :     Node* unused;
     193         112 :     std::tie(arguments, elements, unused) = AllocateArgumentsObject(
     194             :         map, zero, nullptr, mode, JSStrictArgumentsObject::kSize);
     195          56 :     result.Bind(arguments);
     196          56 :     Goto(&done);
     197             :   }
     198             : 
     199          56 :   BIND(&runtime);
     200             :   {
     201          56 :     result.Bind(CallRuntime(Runtime::kNewStrictArguments, context, function));
     202          56 :     Goto(&done);
     203             :   }
     204             : 
     205          56 :   BIND(&done);
     206         112 :   return result.value();
     207             : }
     208             : 
     209          56 : Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context,
     210             :                                                              Node* function) {
     211         112 :   VARIABLE(result, MachineRepresentation::kTagged);
     212             : 
     213             :   ParameterMode mode = OptimalParameterMode();
     214          56 :   Node* zero = IntPtrOrSmiConstant(0, mode);
     215             : 
     216          56 :   Label done(this, &result), empty(this), no_parameters(this),
     217          56 :       runtime(this, Label::kDeferred);
     218             : 
     219             :   ArgumentsBuiltinsFromDSLAssembler::ArgumentsInfo info =
     220             :       GetArgumentsFrameAndCount(CAST(context),
     221          56 :                                 UncheckedCast<JSFunction>(function));
     222             : 
     223         112 :   GotoIf(WordEqual(info.argument_count, zero), &empty);
     224             : 
     225         112 :   GotoIf(WordEqual(info.formal_parameter_count, zero), &no_parameters);
     226             : 
     227             :   {
     228          56 :     Comment("Mapped parameter JSSloppyArgumentsObject");
     229             : 
     230             :     Node* mapped_count =
     231          56 :         IntPtrOrSmiMin(info.argument_count, info.formal_parameter_count, mode);
     232             : 
     233             :     Node* parameter_map_size =
     234          56 :         IntPtrOrSmiAdd(mapped_count, IntPtrOrSmiConstant(2, mode), mode);
     235             : 
     236             :     // Verify that the overall allocation will fit in new space.
     237             :     Node* elements_allocated =
     238          56 :         IntPtrOrSmiAdd(info.argument_count, parameter_map_size, mode);
     239             :     GotoIfFixedArraySizeDoesntFitInNewSpace(
     240             :         elements_allocated, &runtime,
     241          56 :         JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize * 2, mode);
     242             : 
     243         112 :     Node* const native_context = LoadNativeContext(context);
     244         112 :     Node* const map = LoadContextElement(
     245          56 :         native_context, Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
     246             :     Node* argument_object;
     247             :     Node* elements;
     248             :     Node* map_array;
     249             :     std::tie(argument_object, elements, map_array) =
     250         112 :         AllocateArgumentsObject(map, info.argument_count, parameter_map_size,
     251             :                                 mode, JSSloppyArgumentsObject::kSize);
     252             :     StoreObjectFieldNoWriteBarrier(
     253          56 :         argument_object, JSSloppyArgumentsObject::kCalleeOffset, function);
     254          56 :     StoreFixedArrayElement(CAST(map_array), 0, context, SKIP_WRITE_BARRIER);
     255          56 :     StoreFixedArrayElement(CAST(map_array), 1, elements, SKIP_WRITE_BARRIER);
     256             : 
     257          56 :     Comment("Fill in non-mapped parameters");
     258             :     Node* argument_offset =
     259         112 :         ElementOffsetFromIndex(info.argument_count, PACKED_ELEMENTS, mode,
     260             :                                FixedArray::kHeaderSize - kHeapObjectTag);
     261             :     Node* mapped_offset =
     262         112 :         ElementOffsetFromIndex(mapped_count, PACKED_ELEMENTS, mode,
     263             :                                FixedArray::kHeaderSize - kHeapObjectTag);
     264          56 :     CodeStubArguments arguments(this, info.argument_count, info.frame, mode);
     265         112 :     VARIABLE(current_argument, MachineType::PointerRepresentation());
     266         112 :     current_argument.Bind(arguments.AtIndexPtr(info.argument_count, mode));
     267         112 :     VariableList var_list1({&current_argument}, zone());
     268          56 :     mapped_offset = BuildFastLoop(
     269             :         var_list1, argument_offset, mapped_offset,
     270         224 :         [this, elements, &current_argument](Node* offset) {
     271          56 :           Increment(&current_argument, kSystemPointerSize);
     272         112 :           Node* arg = LoadBufferObject(current_argument.value(), 0);
     273          56 :           StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, offset,
     274          56 :                               arg);
     275          56 :         },
     276          56 :         -kTaggedSize, INTPTR_PARAMETERS);
     277             : 
     278             :     // Copy the parameter slots and the holes in the arguments.
     279             :     // We need to fill in mapped_count slots. They index the context,
     280             :     // where parameters are stored in reverse order, at
     281             :     //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+argument_count-1
     282             :     // The mapped parameter thus need to get indices
     283             :     //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
     284             :     //       MIN_CONTEXT_SLOTS+argument_count-mapped_count
     285             :     // We loop from right to left.
     286          56 :     Comment("Fill in mapped parameters");
     287         112 :     VARIABLE(context_index, OptimalParameterRepresentation());
     288          56 :     context_index.Bind(IntPtrOrSmiSub(
     289             :         IntPtrOrSmiAdd(IntPtrOrSmiConstant(Context::MIN_CONTEXT_SLOTS, mode),
     290             :                        info.formal_parameter_count, mode),
     291          56 :         mapped_count, mode));
     292         112 :     Node* the_hole = TheHoleConstant();
     293         112 :     VariableList var_list2({&context_index}, zone());
     294             :     const int kParameterMapHeaderSize = FixedArray::OffsetOfElementAt(2);
     295             :     Node* adjusted_map_array = IntPtrAdd(
     296             :         BitcastTaggedToWord(map_array),
     297         168 :         IntPtrConstant(kParameterMapHeaderSize - FixedArray::kHeaderSize));
     298         112 :     Node* zero_offset = ElementOffsetFromIndex(
     299             :         zero, PACKED_ELEMENTS, mode, FixedArray::kHeaderSize - kHeapObjectTag);
     300          56 :     BuildFastLoop(
     301             :         var_list2, mapped_offset, zero_offset,
     302         168 :         [=, &context_index](Node* offset) {
     303         112 :           StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, offset,
     304         336 :                               the_hole);
     305          56 :           StoreNoWriteBarrier(MachineRepresentation::kTagged,
     306          56 :                               adjusted_map_array, offset,
     307         224 :                               ParameterToTagged(context_index.value(), mode));
     308          56 :           Increment(&context_index, 1, mode);
     309          56 :         },
     310          56 :         -kTaggedSize, INTPTR_PARAMETERS);
     311             : 
     312          56 :     result.Bind(argument_object);
     313          56 :     Goto(&done);
     314             :   }
     315             : 
     316          56 :   BIND(&no_parameters);
     317             :   {
     318          56 :     Comment("No parameters JSSloppyArgumentsObject");
     319             :     GotoIfFixedArraySizeDoesntFitInNewSpace(
     320             :         info.argument_count, &runtime,
     321          56 :         JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize, mode);
     322         112 :     Node* const native_context = LoadNativeContext(context);
     323             :     Node* const map =
     324         112 :         LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX);
     325          56 :     result.Bind(ConstructParametersObjectFromArgs(
     326             :         map, info.frame, info.argument_count, zero, info.argument_count, mode,
     327          56 :         JSSloppyArgumentsObject::kSize));
     328          56 :     StoreObjectFieldNoWriteBarrier(
     329          56 :         result.value(), JSSloppyArgumentsObject::kCalleeOffset, function);
     330          56 :     Goto(&done);
     331             :   }
     332             : 
     333          56 :   BIND(&empty);
     334             :   {
     335          56 :     Comment("Empty JSSloppyArgumentsObject");
     336         112 :     Node* const native_context = LoadNativeContext(context);
     337             :     Node* const map =
     338         112 :         LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX);
     339             :     Node* arguments;
     340             :     Node* elements;
     341             :     Node* unused;
     342         112 :     std::tie(arguments, elements, unused) = AllocateArgumentsObject(
     343             :         map, zero, nullptr, mode, JSSloppyArgumentsObject::kSize);
     344          56 :     result.Bind(arguments);
     345          56 :     StoreObjectFieldNoWriteBarrier(
     346          56 :         result.value(), JSSloppyArgumentsObject::kCalleeOffset, function);
     347          56 :     Goto(&done);
     348             :   }
     349             : 
     350          56 :   BIND(&runtime);
     351             :   {
     352          56 :     result.Bind(CallRuntime(Runtime::kNewSloppyArguments, context, function));
     353          56 :     Goto(&done);
     354             :   }
     355             : 
     356          56 :   BIND(&done);
     357         112 :   return result.value();
     358             : }
     359             : 
     360             : }  // namespace internal
     361       59480 : }  // namespace v8

Generated by: LCOV version 1.10