5 #include "src/builtins/builtins-call-gen.h" 7 #include "src/builtins/builtins-utils-gen.h" 8 #include "src/builtins/builtins.h" 9 #include "src/globals.h" 10 #include "src/isolate.h" 11 #include "src/macro-assembler.h" 12 #include "src/objects/arguments.h" 17 void Builtins::Generate_CallFunction_ReceiverIsNullOrUndefined(
18 MacroAssembler* masm) {
19 Generate_CallFunction(masm, ConvertReceiverMode::kNullOrUndefined);
22 void Builtins::Generate_CallFunction_ReceiverIsNotNullOrUndefined(
23 MacroAssembler* masm) {
24 Generate_CallFunction(masm, ConvertReceiverMode::kNotNullOrUndefined);
27 void Builtins::Generate_CallFunction_ReceiverIsAny(MacroAssembler* masm) {
28 Generate_CallFunction(masm, ConvertReceiverMode::kAny);
31 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) {
32 Generate_CallBoundFunctionImpl(masm);
35 void Builtins::Generate_Call_ReceiverIsNullOrUndefined(MacroAssembler* masm) {
36 Generate_Call(masm, ConvertReceiverMode::kNullOrUndefined);
39 void Builtins::Generate_Call_ReceiverIsNotNullOrUndefined(
40 MacroAssembler* masm) {
41 Generate_Call(masm, ConvertReceiverMode::kNotNullOrUndefined);
44 void Builtins::Generate_Call_ReceiverIsAny(MacroAssembler* masm) {
45 Generate_Call(masm, ConvertReceiverMode::kAny);
48 void Builtins::Generate_CallVarargs(MacroAssembler* masm) {
49 Generate_CallOrConstructVarargs(masm, masm->isolate()->builtins()->Call());
52 void Builtins::Generate_CallForwardVarargs(MacroAssembler* masm) {
53 Generate_CallOrConstructForwardVarargs(masm, CallOrConstructMode::kCall,
54 masm->isolate()->builtins()->Call());
57 void Builtins::Generate_CallFunctionForwardVarargs(MacroAssembler* masm) {
58 Generate_CallOrConstructForwardVarargs(
59 masm, CallOrConstructMode::kCall,
60 masm->isolate()->builtins()->CallFunction());
63 void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike(
64 TNode<Object> target, SloppyTNode<Object> new_target,
65 TNode<Object> arguments_list, TNode<Context> context) {
66 Label if_done(
this), if_arguments(
this), if_array(
this),
67 if_holey_array(
this, Label::kDeferred),
68 if_runtime(
this, Label::kDeferred);
71 if (new_target ==
nullptr) {
73 Label if_target_callable(
this),
74 if_target_not_callable(
this, Label::kDeferred);
75 GotoIf(TaggedIsSmi(target), &if_target_not_callable);
76 Branch(IsCallable(CAST(target)), &if_target_callable,
77 &if_target_not_callable);
78 BIND(&if_target_not_callable);
80 CallRuntime(Runtime::kThrowApplyNonFunction, context, target);
83 BIND(&if_target_callable);
86 Label if_target_constructor(
this),
87 if_target_not_constructor(
this, Label::kDeferred);
88 GotoIf(TaggedIsSmi(target), &if_target_not_constructor);
89 Branch(IsConstructor(CAST(target)), &if_target_constructor,
90 &if_target_not_constructor);
91 BIND(&if_target_not_constructor);
93 CallRuntime(Runtime::kThrowNotConstructor, context, target);
96 BIND(&if_target_constructor);
99 Label if_new_target_constructor(
this),
100 if_new_target_not_constructor(
this, Label::kDeferred);
101 GotoIf(TaggedIsSmi(new_target), &if_new_target_not_constructor);
102 Branch(IsConstructor(CAST(new_target)), &if_new_target_constructor,
103 &if_new_target_not_constructor);
104 BIND(&if_new_target_not_constructor);
106 CallRuntime(Runtime::kThrowNotConstructor, context, new_target);
109 BIND(&if_new_target_constructor);
112 GotoIf(TaggedIsSmi(arguments_list), &if_runtime);
114 TNode<Map> arguments_list_map = LoadMap(CAST(arguments_list));
115 TNode<Context> native_context = LoadNativeContext(context);
118 TNode<Map> sloppy_arguments_map = CAST(
119 LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
120 GotoIf(WordEqual(arguments_list_map, sloppy_arguments_map), &if_arguments);
121 TNode<Map> strict_arguments_map = CAST(
122 LoadContextElement(native_context, Context::STRICT_ARGUMENTS_MAP_INDEX));
123 GotoIf(WordEqual(arguments_list_map, strict_arguments_map), &if_arguments);
126 Branch(IsJSArrayMap(arguments_list_map), &if_array, &if_runtime);
128 TVARIABLE(FixedArrayBase, var_elements);
129 TVARIABLE(Int32T, var_length);
133 var_elements = LoadElements(CAST(arguments_list));
135 LoadAndUntagToWord32ObjectField(arguments_list, JSArray::kLengthOffset);
138 STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
139 STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
140 STATIC_ASSERT(PACKED_ELEMENTS == 2);
141 STATIC_ASSERT(HOLEY_ELEMENTS == 3);
142 STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
143 STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
144 STATIC_ASSERT(LAST_FAST_ELEMENTS_KIND == HOLEY_DOUBLE_ELEMENTS);
146 TNode<Int32T> kind = LoadMapElementsKind(arguments_list_map);
148 GotoIf(Int32GreaterThan(kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
150 Branch(Word32And(kind, Int32Constant(1)), &if_holey_array, &if_done);
153 BIND(&if_holey_array);
157 GotoIfNot(IsPrototypeInitialArrayPrototype(context, arguments_list_map),
159 Branch(IsNoElementsProtectorCellInvalid(), &if_runtime, &if_done);
164 TNode<JSArgumentsObject> js_arguments = CAST(arguments_list);
166 TNode<Object> length = LoadObjectField(
167 js_arguments, JSArgumentsObjectWithLength::kLengthOffset);
168 TNode<FixedArrayBase> elements = LoadElements(js_arguments);
169 TNode<Smi> elements_length = LoadFixedArrayBaseLength(elements);
170 GotoIfNot(WordEqual(length, elements_length), &if_runtime);
171 var_elements = elements;
172 var_length = SmiToInt32(CAST(length));
179 var_elements = CAST(CallRuntime(Runtime::kCreateListFromArrayLike, context,
181 var_length = LoadAndUntagToWord32ObjectField(var_elements.value(),
182 FixedArray::kLengthOffset);
190 Label if_not_double(
this), if_double(
this);
191 TNode<Int32T> args_count = Int32Constant(0);
193 TNode<Int32T> length = var_length.value();
195 Label normalize_done(
this);
196 GotoIfNot(Word32Equal(length, Int32Constant(0)), &normalize_done);
200 var_elements = EmptyFixedArrayConstant();
201 Goto(&normalize_done);
203 BIND(&normalize_done);
206 TNode<FixedArrayBase> elements = var_elements.value();
207 Branch(IsFixedDoubleArray(elements), &if_double, &if_not_double);
209 BIND(&if_not_double);
211 if (new_target ==
nullptr) {
212 Callable callable = CodeFactory::CallVarargs(isolate());
213 TailCallStub(callable, context, target, args_count, length, elements);
215 Callable callable = CodeFactory::ConstructVarargs(isolate());
216 TailCallStub(callable, context, target, new_target, args_count, length,
225 CallOrConstructDoubleVarargs(target, new_target, CAST(elements), length,
227 Int32Constant(HOLEY_DOUBLE_ELEMENTS));
235 void CallOrConstructBuiltinsAssembler::CallOrConstructDoubleVarargs(
236 TNode<Object> target, SloppyTNode<Object> new_target,
237 TNode<FixedDoubleArray> elements, TNode<Int32T> length,
238 TNode<Int32T> args_count, TNode<Context> context, TNode<Int32T> kind) {
239 const ElementsKind new_kind = PACKED_ELEMENTS;
240 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
241 TNode<IntPtrT> intptr_length = ChangeInt32ToIntPtr(length);
242 CSA_ASSERT(
this, WordNotEqual(intptr_length, IntPtrConstant(0)));
245 TNode<FixedArray> new_elements = CAST(AllocateFixedArray(
246 new_kind, intptr_length, CodeStubAssembler::kAllowLargeObjectAllocation));
249 CopyFixedArrayElements(PACKED_DOUBLE_ELEMENTS, elements, new_kind,
250 new_elements, intptr_length, intptr_length,
252 if (new_target ==
nullptr) {
253 Callable callable = CodeFactory::CallVarargs(isolate());
254 TailCallStub(callable, context, target, args_count, length, new_elements);
256 Callable callable = CodeFactory::ConstructVarargs(isolate());
257 TailCallStub(callable, context, target, new_target, args_count, length,
262 void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
263 TNode<Object> target, TNode<Object> new_target, TNode<Object> spread,
264 TNode<Int32T> args_count, TNode<Context> context) {
265 Label if_smiorobject(
this), if_double(
this),
266 if_generic(
this, Label::kDeferred);
268 TVARIABLE(Int32T, var_length);
269 TVARIABLE(FixedArrayBase, var_elements);
270 TVARIABLE(Int32T, var_elements_kind);
272 GotoIf(TaggedIsSmi(spread), &if_generic);
273 TNode<Map> spread_map = LoadMap(CAST(spread));
274 GotoIfNot(IsJSArrayMap(spread_map), &if_generic);
275 TNode<JSArray> spread_array = CAST(spread);
278 GotoIfNot(IsPrototypeInitialArrayPrototype(context, spread_map), &if_generic);
281 GotoIf(IsNoElementsProtectorCellInvalid(), &if_generic);
285 TNode<PropertyCell> protector_cell =
286 CAST(LoadRoot(RootIndex::kArrayIteratorProtector));
287 GotoIf(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset),
288 SmiConstant(Isolate::kProtectorInvalid)),
292 TNode<Int32T> spread_kind = LoadMapElementsKind(spread_map);
293 var_elements_kind = spread_kind;
295 LoadAndUntagToWord32ObjectField(spread_array, JSArray::kLengthOffset);
296 var_elements = LoadElements(spread_array);
299 GotoIf(Int32LessThan(spread_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
302 Int32GreaterThan(spread_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
303 &if_generic, &if_double);
308 Label if_iterator_fn_not_callable(
this, Label::kDeferred);
309 TNode<Object> iterator_fn =
310 GetProperty(context, spread, IteratorSymbolConstant());
311 GotoIfNot(TaggedIsCallable(iterator_fn), &if_iterator_fn_not_callable);
312 TNode<JSArray> list =
313 CAST(CallBuiltin(Builtins::kIterableToListMayPreserveHoles, context,
314 spread, iterator_fn));
315 var_length = LoadAndUntagToWord32ObjectField(list, JSArray::kLengthOffset);
317 var_elements = LoadElements(list);
318 var_elements_kind = LoadElementsKind(list);
319 Branch(Int32LessThan(var_elements_kind.value(),
320 Int32Constant(PACKED_DOUBLE_ELEMENTS)),
321 &if_smiorobject, &if_double);
323 BIND(&if_iterator_fn_not_callable);
324 ThrowTypeError(context, MessageTemplate::kIteratorSymbolNonCallable);
327 BIND(&if_smiorobject);
329 TNode<FixedArrayBase> elements = var_elements.value();
330 TNode<Int32T> length = var_length.value();
332 if (new_target ==
nullptr) {
333 Callable callable = CodeFactory::CallVarargs(isolate());
334 TailCallStub(callable, context, target, args_count, length, elements);
336 Callable callable = CodeFactory::ConstructVarargs(isolate());
337 TailCallStub(callable, context, target, new_target, args_count, length,
344 GotoIf(Word32Equal(var_length.value(), Int32Constant(0)), &if_smiorobject);
345 CallOrConstructDoubleVarargs(target, new_target, CAST(var_elements.value()),
346 var_length.value(), args_count, context,
347 var_elements_kind.value());
351 TF_BUILTIN(CallWithArrayLike, CallOrConstructBuiltinsAssembler) {
352 TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
353 SloppyTNode<Object> new_target =
nullptr;
354 TNode<Object> arguments_list = CAST(Parameter(Descriptor::kArgumentsList));
355 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
356 CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
359 TF_BUILTIN(CallWithSpread, CallOrConstructBuiltinsAssembler) {
360 TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
361 SloppyTNode<Object> new_target =
nullptr;
362 TNode<Object> spread = CAST(Parameter(Descriptor::kSpread));
363 TNode<Int32T> args_count =
364 UncheckedCast<Int32T>(Parameter(Descriptor::kArgumentsCount));
365 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
366 CallOrConstructWithSpread(target, new_target, spread, args_count, context);