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

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

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

Powered by Google App Engine
This is Rietveld 408576698