Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/builtins/builtins-arguments.cc

Issue 2645743002: [builtins] Port parameter and argument-related code stubs to CSA (Closed)
Patch Set: Review feedback Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-arguments.h ('k') | src/code-factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.h"
6 #include "src/builtins/builtins-utils.h"
7 #include "src/builtins/builtins.h"
8 #include "src/code-factory.h"
9 #include "src/code-stub-assembler.h"
10 #include "src/interface-descriptors.h"
11
12 namespace v8 {
13 namespace internal {
14
15 typedef compiler::Node Node;
16
17 std::tuple<Node*, Node*, Node*>
18 ArgumentsBuiltinsAssembler::GetArgumentsFrameAndCount(Node* function,
19 ParameterMode mode) {
20 CSA_ASSERT(this, HasInstanceType(function, JS_FUNCTION_TYPE));
21
22 Variable frame_ptr(this, MachineType::PointerRepresentation());
23 frame_ptr.Bind(LoadParentFramePointer());
24 CSA_ASSERT(this,
25 WordEqual(function,
26 LoadBufferObject(frame_ptr.value(),
27 StandardFrameConstants::kFunctionOffset,
28 MachineType::Pointer())));
29 Variable argument_count(this, ParameterRepresentation(mode));
30 VariableList list({&frame_ptr, &argument_count}, zone());
31 Label done_argument_count(this, list);
32
33 // Determine the number of passed parameters, which is either the count stored
34 // in an arguments adapter frame or fetched from the shared function info.
35 Node* frame_ptr_above = LoadBufferObject(
36 frame_ptr.value(), StandardFrameConstants::kCallerFPOffset,
37 MachineType::Pointer());
38 Node* shared =
39 LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset);
40 Node* formal_parameter_count = LoadSharedFunctionInfoSpecialField(
41 shared, SharedFunctionInfo::kFormalParameterCountOffset, mode);
42 argument_count.Bind(formal_parameter_count);
43 Node* marker_or_function = LoadBufferObject(
44 frame_ptr_above, CommonFrameConstants::kContextOrFrameTypeOffset);
45 GotoIf(SmiNotEqual(marker_or_function,
46 SmiConstant(StackFrame::ARGUMENTS_ADAPTOR)),
47 &done_argument_count);
48 Node* adapted_parameter_count = LoadBufferObject(
49 frame_ptr_above, ArgumentsAdaptorFrameConstants::kLengthOffset);
50 frame_ptr.Bind(frame_ptr_above);
51 argument_count.Bind(TaggedToParameter(adapted_parameter_count, mode));
52 Goto(&done_argument_count);
53
54 Bind(&done_argument_count);
55 return std::tuple<Node*, Node*, Node*>(
56 frame_ptr.value(), argument_count.value(), formal_parameter_count);
57 }
58
59 std::tuple<Node*, Node*, Node*>
60 ArgumentsBuiltinsAssembler::AllocateArgumentsObject(Node* map,
61 Node* arguments_count,
62 Node* parameter_map_count,
63 ParameterMode mode,
64 int base_size) {
65 // Allocate the parameter object (either a Rest parameter object, a strict
66 // argument object or a sloppy arguments object) and the elements/mapped
67 // arguments together.
68 int elements_offset = base_size;
69 Node* element_count = arguments_count;
70 if (parameter_map_count != nullptr) {
71 base_size += FixedArray::kHeaderSize;
72 element_count = IntPtrOrSmiAdd(element_count, parameter_map_count, mode);
73 }
74 bool empty = IsIntPtrOrSmiConstantZero(arguments_count);
75 DCHECK_IMPLIES(empty, parameter_map_count == nullptr);
76 Node* size =
77 empty ? IntPtrConstant(base_size)
78 : ElementOffsetFromIndex(element_count, FAST_ELEMENTS, mode,
79 base_size + FixedArray::kHeaderSize);
80 Node* result = Allocate(size);
81 Comment("Initialize arguments object");
82 StoreMapNoWriteBarrier(result, map);
83 Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
84 StoreObjectField(result, JSArray::kPropertiesOffset, empty_fixed_array);
85 Node* smi_arguments_count = ParameterToTagged(arguments_count, mode);
86 StoreObjectFieldNoWriteBarrier(result, JSArray::kLengthOffset,
87 smi_arguments_count);
88 Node* arguments = nullptr;
89 if (!empty) {
90 arguments = InnerAllocate(result, elements_offset);
91 StoreObjectFieldNoWriteBarrier(arguments, FixedArray::kLengthOffset,
92 smi_arguments_count);
93 Node* fixed_array_map = LoadRoot(Heap::kFixedArrayMapRootIndex);
94 StoreMapNoWriteBarrier(arguments, fixed_array_map);
95 }
96 Node* parameter_map = nullptr;
97 if (parameter_map_count != nullptr) {
98 Node* parameter_map_offset = ElementOffsetFromIndex(
99 arguments_count, FAST_ELEMENTS, mode, FixedArray::kHeaderSize);
100 parameter_map = InnerAllocate(arguments, parameter_map_offset);
101 StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
102 parameter_map);
103 Node* sloppy_elements_map =
104 LoadRoot(Heap::kSloppyArgumentsElementsMapRootIndex);
105 StoreMapNoWriteBarrier(parameter_map, sloppy_elements_map);
106 parameter_map_count = ParameterToTagged(parameter_map_count, mode);
107 StoreObjectFieldNoWriteBarrier(parameter_map, FixedArray::kLengthOffset,
108 parameter_map_count);
109 } else {
110 if (empty) {
111 StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
112 empty_fixed_array);
113 } else {
114 StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset,
115 arguments);
116 }
117 }
118 return std::tuple<Node*, Node*, Node*>(result, arguments, parameter_map);
119 }
120
121 Node* ArgumentsBuiltinsAssembler::ConstructParametersObjectFromArgs(
122 Node* map, Node* frame_ptr, Node* arg_count, Node* first_arg,
123 Node* rest_count, ParameterMode param_mode, int base_size) {
124 // Allocate the parameter object (either a Rest parameter object, a strict
125 // argument object or a sloppy arguments object) and the elements together and
126 // fill in the contents with the arguments above |formal_parameter_count|.
127 Node* result;
128 Node* elements;
129 Node* unused;
130 std::tie(result, elements, unused) =
131 AllocateArgumentsObject(map, rest_count, nullptr, param_mode, base_size);
132 DCHECK(unused == nullptr);
133 CodeStubArguments arguments(this, arg_count, frame_ptr, param_mode);
134 Variable offset(this, MachineType::PointerRepresentation());
135 offset.Bind(IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag));
136 VariableList list({&offset}, zone());
137 arguments.ForEach(list,
138 [this, elements, &offset](Node* arg) {
139 StoreNoWriteBarrier(MachineRepresentation::kTagged,
140 elements, offset.value(), arg);
141 Increment(offset, kPointerSize);
142 },
143 first_arg, nullptr, param_mode);
144 return result;
145 }
146
147 Node* ArgumentsBuiltinsAssembler::EmitFastNewRestParameter(Node* context,
148 Node* function) {
149 Node* frame_ptr;
150 Node* argument_count;
151 Node* formal_parameter_count;
152
153 ParameterMode mode = OptimalParameterMode();
154 Node* zero = IntPtrOrSmiConstant(0, mode);
155
156 std::tie(frame_ptr, argument_count, formal_parameter_count) =
157 GetArgumentsFrameAndCount(function, mode);
158
159 Variable result(this, MachineRepresentation::kTagged);
160 Label no_rest_parameters(this), runtime(this, Label::kDeferred),
161 done(this, &result);
162
163 Node* rest_count =
164 IntPtrOrSmiSub(argument_count, formal_parameter_count, mode);
165 Node* const native_context = LoadNativeContext(context);
166 Node* const array_map = LoadJSArrayElementsMap(FAST_ELEMENTS, native_context);
167 GotoIf(IntPtrOrSmiLessThanOrEqual(rest_count, zero, mode),
168 &no_rest_parameters);
169
170 GotoIfFixedArraySizeDoesntFitInNewSpace(
171 rest_count, &runtime, JSArray::kSize + FixedArray::kHeaderSize, mode);
172
173 // Allocate the Rest JSArray and the elements together and fill in the
174 // contents with the arguments above |formal_parameter_count|.
175 result.Bind(ConstructParametersObjectFromArgs(
176 array_map, frame_ptr, argument_count, formal_parameter_count, rest_count,
177 mode, JSArray::kSize));
178 Goto(&done);
179
180 Bind(&no_rest_parameters);
181 {
182 Node* arguments;
183 Node* elements;
184 Node* unused;
185 std::tie(arguments, elements, unused) =
186 AllocateArgumentsObject(array_map, zero, nullptr, mode, JSArray::kSize);
187 result.Bind(arguments);
188 Goto(&done);
189 }
190
191 Bind(&runtime);
192 {
193 result.Bind(CallRuntime(Runtime::kNewRestParameter, context, function));
194 Goto(&done);
195 }
196
197 Bind(&done);
198 return result.value();
199 }
200
201 TF_BUILTIN(FastNewRestParameter, ArgumentsBuiltinsAssembler) {
202 Node* function = Parameter(FastNewArgumentsDescriptor::kFunction);
203 Node* context = Parameter(FastNewArgumentsDescriptor::kContext);
204 Return(EmitFastNewRestParameter(context, function));
205 }
206
207 Node* ArgumentsBuiltinsAssembler::EmitFastNewStrictArguments(Node* context,
208 Node* function) {
209 Variable result(this, MachineRepresentation::kTagged);
210 Label done(this, &result), empty(this), runtime(this, Label::kDeferred);
211
212 Node* frame_ptr;
213 Node* argument_count;
214 Node* formal_parameter_count;
215
216 ParameterMode mode = OptimalParameterMode();
217 Node* zero = IntPtrOrSmiConstant(0, mode);
218
219 std::tie(frame_ptr, argument_count, formal_parameter_count) =
220 GetArgumentsFrameAndCount(function, mode);
221
222 GotoIfFixedArraySizeDoesntFitInNewSpace(
223 argument_count, &runtime,
224 JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize, mode);
225
226 Node* const native_context = LoadNativeContext(context);
227 Node* const map =
228 LoadContextElement(native_context, Context::STRICT_ARGUMENTS_MAP_INDEX);
229 GotoIf(WordEqual(argument_count, zero), &empty);
230
231 result.Bind(ConstructParametersObjectFromArgs(
232 map, frame_ptr, argument_count, zero, argument_count, mode,
233 JSStrictArgumentsObject::kSize));
234 Goto(&done);
235
236 Bind(&empty);
237 {
238 Node* arguments;
239 Node* elements;
240 Node* unused;
241 std::tie(arguments, elements, unused) = AllocateArgumentsObject(
242 map, zero, nullptr, mode, JSStrictArgumentsObject::kSize);
243 result.Bind(arguments);
244 Goto(&done);
245 }
246
247 Bind(&runtime);
248 {
249 result.Bind(CallRuntime(Runtime::kNewStrictArguments, context, function));
250 Goto(&done);
251 }
252
253 Bind(&done);
254 return result.value();
255 }
256
257 TF_BUILTIN(FastNewStrictArguments, ArgumentsBuiltinsAssembler) {
258 Node* function = Parameter(FastNewArgumentsDescriptor::kFunction);
259 Node* context = Parameter(FastNewArgumentsDescriptor::kContext);
260 Return(EmitFastNewStrictArguments(context, function));
261 }
262
263 Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context,
264 Node* function) {
265 Node* frame_ptr;
266 Node* argument_count;
267 Node* formal_parameter_count;
268 Variable result(this, MachineRepresentation::kTagged);
269
270 ParameterMode mode = OptimalParameterMode();
271 Node* zero = IntPtrOrSmiConstant(0, mode);
272
273 Label done(this, &result), empty(this), no_parameters(this),
274 runtime(this, Label::kDeferred);
275
276 std::tie(frame_ptr, argument_count, formal_parameter_count) =
277 GetArgumentsFrameAndCount(function, mode);
278
279 GotoIf(WordEqual(argument_count, zero), &empty);
280
281 GotoIf(WordEqual(formal_parameter_count, zero), &no_parameters);
282
283 {
284 Comment("Mapped parameter JSSloppyArgumentsObject");
285
286 Node* mapped_count =
287 IntPtrOrSmiMin(argument_count, formal_parameter_count, mode);
288
289 Node* parameter_map_size =
290 IntPtrOrSmiAdd(mapped_count, IntPtrOrSmiConstant(2, mode), mode);
291
292 // Verify that the overall allocation will fit in new space.
293 Node* elements_allocated =
294 IntPtrOrSmiAdd(argument_count, parameter_map_size, mode);
295 GotoIfFixedArraySizeDoesntFitInNewSpace(
296 elements_allocated, &runtime,
297 JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize * 2, mode);
298
299 Node* const native_context = LoadNativeContext(context);
300 Node* const map = LoadContextElement(
301 native_context, Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
302 Node* argument_object;
303 Node* elements;
304 Node* map_array;
305 std::tie(argument_object, elements, map_array) =
306 AllocateArgumentsObject(map, argument_count, parameter_map_size, mode,
307 JSSloppyArgumentsObject::kSize);
308 StoreObjectFieldNoWriteBarrier(
309 argument_object, JSSloppyArgumentsObject::kCalleeOffset, function);
310 StoreFixedArrayElement(map_array, 0, context, SKIP_WRITE_BARRIER);
311 StoreFixedArrayElement(map_array, 1, elements, SKIP_WRITE_BARRIER);
312
313 Comment("Fill in non-mapped parameters");
314 Node* argument_offset =
315 ElementOffsetFromIndex(argument_count, FAST_ELEMENTS, mode,
316 FixedArray::kHeaderSize - kHeapObjectTag);
317 Node* mapped_offset =
318 ElementOffsetFromIndex(mapped_count, FAST_ELEMENTS, mode,
319 FixedArray::kHeaderSize - kHeapObjectTag);
320 CodeStubArguments arguments(this, argument_count, frame_ptr, mode);
321 Variable current_argument(this, MachineType::PointerRepresentation());
322 current_argument.Bind(arguments.AtIndexPtr(argument_count, mode));
323 VariableList var_list1({&current_argument}, zone());
324 mapped_offset = BuildFastLoop(
325 var_list1, argument_offset, mapped_offset,
326 [this, elements, &current_argument](Node* offset) {
327 Increment(current_argument, kPointerSize);
328 Node* arg = LoadBufferObject(current_argument.value(), 0);
329 StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, offset,
330 arg);
331 },
332 -kPointerSize, INTPTR_PARAMETERS);
333
334 // Copy the parameter slots and the holes in the arguments.
335 // We need to fill in mapped_count slots. They index the context,
336 // where parameters are stored in reverse order, at
337 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+argument_count-1
338 // The mapped parameter thus need to get indices
339 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
340 // MIN_CONTEXT_SLOTS+argument_count-mapped_count
341 // We loop from right to left.
342 Comment("Fill in mapped parameters");
343 Variable context_index(this, OptimalParameterRepresentation());
344 context_index.Bind(IntPtrOrSmiSub(
345 IntPtrOrSmiAdd(IntPtrOrSmiConstant(Context::MIN_CONTEXT_SLOTS, mode),
346 formal_parameter_count, mode),
347 mapped_count, mode));
348 Node* the_hole = TheHoleConstant();
349 VariableList var_list2({&context_index}, zone());
350 const int kParameterMapHeaderSize =
351 FixedArray::kHeaderSize + 2 * kPointerSize;
352 Node* adjusted_map_array = IntPtrAdd(
353 BitcastTaggedToWord(map_array),
354 IntPtrConstant(kParameterMapHeaderSize - FixedArray::kHeaderSize));
355 Node* zero_offset = ElementOffsetFromIndex(
356 zero, FAST_ELEMENTS, mode, FixedArray::kHeaderSize - kHeapObjectTag);
357 BuildFastLoop(var_list2, mapped_offset, zero_offset,
358 [this, the_hole, elements, adjusted_map_array, &context_index,
359 mode](Node* offset) {
360 StoreNoWriteBarrier(MachineRepresentation::kTagged,
361 elements, offset, the_hole);
362 StoreNoWriteBarrier(
363 MachineRepresentation::kTagged, adjusted_map_array,
364 offset, ParameterToTagged(context_index.value(), mode));
365 Increment(context_index, 1, mode);
366 },
367 -kPointerSize, INTPTR_PARAMETERS);
368
369 result.Bind(argument_object);
370 Goto(&done);
371 }
372
373 Bind(&no_parameters);
374 {
375 Comment("No parameters JSSloppyArgumentsObject");
376 GotoIfFixedArraySizeDoesntFitInNewSpace(
377 argument_count, &runtime,
378 JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize, mode);
379 Node* const native_context = LoadNativeContext(context);
380 Node* const map =
381 LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX);
382 result.Bind(ConstructParametersObjectFromArgs(
383 map, frame_ptr, argument_count, zero, argument_count, mode,
384 JSSloppyArgumentsObject::kSize));
385 StoreObjectFieldNoWriteBarrier(
386 result.value(), JSSloppyArgumentsObject::kCalleeOffset, function);
387 Goto(&done);
388 }
389
390 Bind(&empty);
391 {
392 Comment("Empty JSSloppyArgumentsObject");
393 Node* const native_context = LoadNativeContext(context);
394 Node* const map =
395 LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX);
396 Node* arguments;
397 Node* elements;
398 Node* unused;
399 std::tie(arguments, elements, unused) = AllocateArgumentsObject(
400 map, zero, nullptr, mode, JSSloppyArgumentsObject::kSize);
401 result.Bind(arguments);
402 StoreObjectFieldNoWriteBarrier(
403 result.value(), JSSloppyArgumentsObject::kCalleeOffset, function);
404 Goto(&done);
405 }
406
407 Bind(&runtime);
408 {
409 result.Bind(CallRuntime(Runtime::kNewSloppyArguments, context, function));
410 Goto(&done);
411 }
412
413 Bind(&done);
414 return result.value();
415 }
416
417 TF_BUILTIN(FastNewSloppyArguments, ArgumentsBuiltinsAssembler) {
418 Node* function = Parameter(FastNewArgumentsDescriptor::kFunction);
419 Node* context = Parameter(FastNewArgumentsDescriptor::kContext);
420 Return(EmitFastNewSloppyArguments(context, function));
421 }
422
423 } // namespace internal
424 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-arguments.h ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698