5 #include "src/builtins/builtins-arguments-gen.h" 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" 20 typedef compiler::Node Node;
22 std::tuple<Node*, Node*, Node*>
23 ArgumentsBuiltinsAssembler::GetArgumentsFrameAndCount(Node*
function,
25 CSA_ASSERT(
this, HasInstanceType(
function, JS_FUNCTION_TYPE));
27 VARIABLE(frame_ptr, MachineType::PointerRepresentation());
28 frame_ptr.Bind(LoadParentFramePointer());
31 LoadBufferObject(frame_ptr.value(),
32 StandardFrameConstants::kFunctionOffset,
33 MachineType::Pointer())));
34 VARIABLE(argument_count, ParameterRepresentation(mode));
35 VariableList list({&frame_ptr, &argument_count}, zone());
36 Label done_argument_count(
this, list);
40 Node* frame_ptr_above = LoadBufferObject(
41 frame_ptr.value(), StandardFrameConstants::kCallerFPOffset,
42 MachineType::Pointer());
44 LoadObjectField(
function, JSFunction::kSharedFunctionInfoOffset);
45 CSA_SLOW_ASSERT(
this, HasInstanceType(shared, SHARED_FUNCTION_INFO_TYPE));
46 Node* formal_parameter_count =
47 LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset,
48 MachineType::Uint16());
49 formal_parameter_count = Int32ToParameter(formal_parameter_count, mode);
51 argument_count.Bind(formal_parameter_count);
52 Node* marker_or_function = LoadBufferObject(
53 frame_ptr_above, CommonFrameConstants::kContextOrFrameTypeOffset);
55 MarkerIsNotFrameType(marker_or_function, StackFrame::ARGUMENTS_ADAPTOR),
56 &done_argument_count);
57 Node* adapted_parameter_count = LoadBufferObject(
58 frame_ptr_above, ArgumentsAdaptorFrameConstants::kLengthOffset);
59 frame_ptr.Bind(frame_ptr_above);
60 argument_count.Bind(TaggedToParameter(adapted_parameter_count, mode));
61 Goto(&done_argument_count);
63 BIND(&done_argument_count);
64 return std::tuple<Node*, Node*, Node*>(
65 frame_ptr.value(), argument_count.value(), formal_parameter_count);
68 std::tuple<Node*, Node*, Node*>
69 ArgumentsBuiltinsAssembler::AllocateArgumentsObject(Node* map,
70 Node* arguments_count,
71 Node* parameter_map_count,
77 int elements_offset = base_size;
78 Node* element_count = arguments_count;
79 if (parameter_map_count !=
nullptr) {
80 base_size += FixedArray::kHeaderSize;
81 element_count = IntPtrOrSmiAdd(element_count, parameter_map_count, mode);
83 bool empty = IsIntPtrOrSmiConstantZero(arguments_count, mode);
84 DCHECK_IMPLIES(empty, parameter_map_count ==
nullptr);
86 empty ? IntPtrConstant(base_size)
87 : ElementOffsetFromIndex(element_count, PACKED_ELEMENTS, mode,
88 base_size + FixedArray::kHeaderSize);
89 TNode<Object> result = Allocate(size);
90 Comment(
"Initialize arguments object");
91 StoreMapNoWriteBarrier(result, map);
92 Node* empty_fixed_array = LoadRoot(RootIndex::kEmptyFixedArray);
93 StoreObjectField(result, JSArray::kPropertiesOrHashOffset, empty_fixed_array);
94 Node* smi_arguments_count = ParameterToTagged(arguments_count, mode);
95 StoreObjectFieldNoWriteBarrier(result, JSArray::kLengthOffset,
97 Node* arguments =
nullptr;
99 arguments = InnerAllocate(CAST(result), elements_offset);
100 StoreObjectFieldNoWriteBarrier(arguments, FixedArray::kLengthOffset,
101 smi_arguments_count);
102 Node* fixed_array_map = LoadRoot(RootIndex::kFixedArrayMap);
103 StoreMapNoWriteBarrier(arguments, fixed_array_map);
105 Node* parameter_map =
nullptr;
106 if (parameter_map_count !=
nullptr) {
107 TNode<IntPtrT> parameter_map_offset = ElementOffsetFromIndex(
108 arguments_count, PACKED_ELEMENTS, mode, FixedArray::kHeaderSize);
109 parameter_map = InnerAllocate(CAST(arguments), parameter_map_offset);
110 StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
112 Node* sloppy_elements_map =
113 LoadRoot(RootIndex::kSloppyArgumentsElementsMap);
114 StoreMapNoWriteBarrier(parameter_map, sloppy_elements_map);
115 parameter_map_count = ParameterToTagged(parameter_map_count, mode);
116 StoreObjectFieldNoWriteBarrier(parameter_map, FixedArray::kLengthOffset,
117 parameter_map_count);
120 StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
123 StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
127 return std::tuple<Node*, Node*, Node*>(result, arguments, parameter_map);
130 Node* ArgumentsBuiltinsAssembler::ConstructParametersObjectFromArgs(
131 Node* map, Node* frame_ptr, Node* arg_count, Node* first_arg,
132 Node* rest_count, ParameterMode param_mode,
int base_size) {
139 std::tie(result, elements, unused) =
140 AllocateArgumentsObject(map, rest_count,
nullptr, param_mode, base_size);
142 CodeStubArguments arguments(
this, arg_count, frame_ptr, param_mode);
143 VARIABLE(offset, MachineType::PointerRepresentation());
144 offset.Bind(IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag));
145 VariableList list({&offset}, zone());
146 arguments.ForEach(list,
147 [
this, elements, &offset](Node* arg) {
148 StoreNoWriteBarrier(MachineRepresentation::kTagged,
149 elements, offset.value(), arg);
150 Increment(&offset, kPointerSize);
152 first_arg,
nullptr, param_mode);
156 Node* ArgumentsBuiltinsAssembler::EmitFastNewRestParameter(Node* context,
159 Node* argument_count;
160 Node* formal_parameter_count;
162 ParameterMode mode = OptimalParameterMode();
163 Node* zero = IntPtrOrSmiConstant(0, mode);
165 std::tie(frame_ptr, argument_count, formal_parameter_count) =
166 GetArgumentsFrameAndCount(
function, mode);
168 VARIABLE(result, MachineRepresentation::kTagged);
169 Label no_rest_parameters(
this), runtime(
this, Label::kDeferred),
173 IntPtrOrSmiSub(argument_count, formal_parameter_count, mode);
174 Node*
const native_context = LoadNativeContext(context);
175 Node*
const array_map =
176 LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
177 GotoIf(IntPtrOrSmiLessThanOrEqual(rest_count, zero, mode),
178 &no_rest_parameters);
180 GotoIfFixedArraySizeDoesntFitInNewSpace(
181 rest_count, &runtime, JSArray::kSize + FixedArray::kHeaderSize, mode);
185 result.Bind(ConstructParametersObjectFromArgs(
186 array_map, frame_ptr, argument_count, formal_parameter_count, rest_count,
187 mode, JSArray::kSize));
190 BIND(&no_rest_parameters);
195 std::tie(arguments, elements, unused) =
196 AllocateArgumentsObject(array_map, zero,
nullptr, mode, JSArray::kSize);
197 result.Bind(arguments);
203 result.Bind(CallRuntime(Runtime::kNewRestParameter, context,
function));
208 return result.value();
211 Node* ArgumentsBuiltinsAssembler::EmitFastNewStrictArguments(Node* context,
213 VARIABLE(result, MachineRepresentation::kTagged);
214 Label done(
this, &result), empty(
this), runtime(
this, Label::kDeferred);
217 Node* argument_count;
218 Node* formal_parameter_count;
220 ParameterMode mode = OptimalParameterMode();
221 Node* zero = IntPtrOrSmiConstant(0, mode);
223 std::tie(frame_ptr, argument_count, formal_parameter_count) =
224 GetArgumentsFrameAndCount(
function, mode);
226 GotoIfFixedArraySizeDoesntFitInNewSpace(
227 argument_count, &runtime,
228 JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize, mode);
230 Node*
const native_context = LoadNativeContext(context);
232 LoadContextElement(native_context, Context::STRICT_ARGUMENTS_MAP_INDEX);
233 GotoIf(WordEqual(argument_count, zero), &empty);
235 result.Bind(ConstructParametersObjectFromArgs(
236 map, frame_ptr, argument_count, zero, argument_count, mode,
237 JSStrictArgumentsObject::kSize));
245 std::tie(arguments, elements, unused) = AllocateArgumentsObject(
246 map, zero,
nullptr, mode, JSStrictArgumentsObject::kSize);
247 result.Bind(arguments);
253 result.Bind(CallRuntime(Runtime::kNewStrictArguments, context,
function));
258 return result.value();
261 Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context,
264 Node* argument_count;
265 Node* formal_parameter_count;
266 VARIABLE(result, MachineRepresentation::kTagged);
268 ParameterMode mode = OptimalParameterMode();
269 Node* zero = IntPtrOrSmiConstant(0, mode);
271 Label done(
this, &result), empty(
this), no_parameters(
this),
272 runtime(
this, Label::kDeferred);
274 std::tie(frame_ptr, argument_count, formal_parameter_count) =
275 GetArgumentsFrameAndCount(
function, mode);
277 GotoIf(WordEqual(argument_count, zero), &empty);
279 GotoIf(WordEqual(formal_parameter_count, zero), &no_parameters);
282 Comment(
"Mapped parameter JSSloppyArgumentsObject");
285 IntPtrOrSmiMin(argument_count, formal_parameter_count, mode);
287 Node* parameter_map_size =
288 IntPtrOrSmiAdd(mapped_count, IntPtrOrSmiConstant(2, mode), mode);
291 Node* elements_allocated =
292 IntPtrOrSmiAdd(argument_count, parameter_map_size, mode);
293 GotoIfFixedArraySizeDoesntFitInNewSpace(
294 elements_allocated, &runtime,
295 JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize * 2, mode);
297 Node*
const native_context = LoadNativeContext(context);
298 Node*
const map = LoadContextElement(
299 native_context, Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
300 Node* argument_object;
303 std::tie(argument_object, elements, map_array) =
304 AllocateArgumentsObject(map, argument_count, parameter_map_size, mode,
305 JSSloppyArgumentsObject::kSize);
306 StoreObjectFieldNoWriteBarrier(
307 argument_object, JSSloppyArgumentsObject::kCalleeOffset,
function);
308 StoreFixedArrayElement(CAST(map_array), 0, context, SKIP_WRITE_BARRIER);
309 StoreFixedArrayElement(CAST(map_array), 1, elements, SKIP_WRITE_BARRIER);
311 Comment(
"Fill in non-mapped parameters");
312 Node* argument_offset =
313 ElementOffsetFromIndex(argument_count, PACKED_ELEMENTS, mode,
314 FixedArray::kHeaderSize - kHeapObjectTag);
315 Node* mapped_offset =
316 ElementOffsetFromIndex(mapped_count, PACKED_ELEMENTS, mode,
317 FixedArray::kHeaderSize - kHeapObjectTag);
318 CodeStubArguments arguments(
this, argument_count, frame_ptr, mode);
319 VARIABLE(current_argument, MachineType::PointerRepresentation());
320 current_argument.Bind(arguments.AtIndexPtr(argument_count, mode));
321 VariableList var_list1({¤t_argument}, zone());
322 mapped_offset = BuildFastLoop(
323 var_list1, argument_offset, mapped_offset,
324 [
this, elements, ¤t_argument](Node* offset) {
325 Increment(¤t_argument, kPointerSize);
326 Node* arg = LoadBufferObject(current_argument.value(), 0);
327 StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, offset,
330 -kPointerSize, INTPTR_PARAMETERS);
340 Comment(
"Fill in mapped parameters");
341 VARIABLE(context_index, OptimalParameterRepresentation());
342 context_index.Bind(IntPtrOrSmiSub(
343 IntPtrOrSmiAdd(IntPtrOrSmiConstant(Context::MIN_CONTEXT_SLOTS, mode),
344 formal_parameter_count, mode),
345 mapped_count, mode));
346 Node* the_hole = TheHoleConstant();
347 VariableList var_list2({&context_index}, zone());
348 const int kParameterMapHeaderSize =
349 FixedArray::kHeaderSize + 2 * kPointerSize;
350 Node* adjusted_map_array = IntPtrAdd(
351 BitcastTaggedToWord(map_array),
352 IntPtrConstant(kParameterMapHeaderSize - FixedArray::kHeaderSize));
353 Node* zero_offset = ElementOffsetFromIndex(
354 zero, PACKED_ELEMENTS, mode, FixedArray::kHeaderSize - kHeapObjectTag);
355 BuildFastLoop(var_list2, mapped_offset, zero_offset,
356 [
this, the_hole, elements, adjusted_map_array, &context_index,
357 mode](Node* offset) {
358 StoreNoWriteBarrier(MachineRepresentation::kTagged,
359 elements, offset, the_hole);
361 MachineRepresentation::kTagged, adjusted_map_array,
362 offset, ParameterToTagged(context_index.value(), mode));
363 Increment(&context_index, 1, mode);
365 -kPointerSize, INTPTR_PARAMETERS);
367 result.Bind(argument_object);
371 BIND(&no_parameters);
373 Comment(
"No parameters JSSloppyArgumentsObject");
374 GotoIfFixedArraySizeDoesntFitInNewSpace(
375 argument_count, &runtime,
376 JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize, mode);
377 Node*
const native_context = LoadNativeContext(context);
379 LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX);
380 result.Bind(ConstructParametersObjectFromArgs(
381 map, frame_ptr, argument_count, zero, argument_count, mode,
382 JSSloppyArgumentsObject::kSize));
383 StoreObjectFieldNoWriteBarrier(
384 result.value(), JSSloppyArgumentsObject::kCalleeOffset,
function);
390 Comment(
"Empty JSSloppyArgumentsObject");
391 Node*
const native_context = LoadNativeContext(context);
393 LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX);
397 std::tie(arguments, elements, unused) = AllocateArgumentsObject(
398 map, zero,
nullptr, mode, JSSloppyArgumentsObject::kSize);
399 result.Bind(arguments);
400 StoreObjectFieldNoWriteBarrier(
401 result.value(), JSSloppyArgumentsObject::kCalleeOffset,
function);
407 result.Bind(CallRuntime(Runtime::kNewSloppyArguments, context,
function));
412 return result.value();