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-math-gen.h"
6 :
7 : #include "src/builtins/builtins-utils-gen.h"
8 : #include "src/builtins/builtins.h"
9 : #include "src/code-factory.h"
10 : #include "src/code-stub-assembler.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : // -----------------------------------------------------------------------------
16 : // ES6 section 20.2.2 Function Properties of the Math Object
17 :
18 : // ES6 #sec-math.abs
19 336 : TF_BUILTIN(MathAbs, CodeStubAssembler) {
20 56 : Node* context = Parameter(Descriptor::kContext);
21 :
22 : // We might need to loop once for ToNumber conversion.
23 112 : VARIABLE(var_x, MachineRepresentation::kTagged);
24 112 : Label loop(this, &var_x);
25 56 : var_x.Bind(Parameter(Descriptor::kX));
26 56 : Goto(&loop);
27 56 : BIND(&loop);
28 : {
29 : // Load the current {x} value.
30 56 : Node* x = var_x.value();
31 :
32 : // Check if {x} is a Smi or a HeapObject.
33 112 : Label if_xissmi(this), if_xisnotsmi(this);
34 56 : Branch(TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
35 :
36 56 : BIND(&if_xissmi);
37 : {
38 112 : Label if_overflow(this, Label::kDeferred);
39 :
40 : // check if support abs function
41 56 : if (IsIntPtrAbsWithOverflowSupported()) {
42 0 : Node* pair = IntPtrAbsWithOverflow(x);
43 0 : Node* overflow = Projection(1, pair);
44 0 : GotoIf(overflow, &if_overflow);
45 :
46 : // There is a Smi representation for negated {x}.
47 0 : Node* result = Projection(0, pair);
48 0 : Return(BitcastWordToTagged(result));
49 :
50 : } else {
51 : // Check if {x} is already positive.
52 112 : Label if_xispositive(this), if_xisnotpositive(this);
53 112 : BranchIfSmiLessThanOrEqual(SmiConstant(0), CAST(x), &if_xispositive,
54 56 : &if_xisnotpositive);
55 :
56 56 : BIND(&if_xispositive);
57 : {
58 : // Just return the input {x}.
59 56 : Return(x);
60 : }
61 :
62 56 : BIND(&if_xisnotpositive);
63 : {
64 : // Try to negate the {x} value.
65 56 : TNode<Smi> result = TrySmiSub(SmiConstant(0), CAST(x), &if_overflow);
66 56 : Return(result);
67 : }
68 : }
69 :
70 56 : BIND(&if_overflow);
71 56 : { Return(NumberConstant(0.0 - Smi::kMinValue)); }
72 : }
73 :
74 56 : BIND(&if_xisnotsmi);
75 : {
76 : // Check if {x} is a HeapNumber.
77 112 : Label if_xisheapnumber(this), if_xisnotheapnumber(this, Label::kDeferred);
78 56 : Branch(IsHeapNumber(x), &if_xisheapnumber, &if_xisnotheapnumber);
79 :
80 56 : BIND(&if_xisheapnumber);
81 : {
82 56 : Node* x_value = LoadHeapNumberValue(x);
83 56 : Node* value = Float64Abs(x_value);
84 56 : Node* result = AllocateHeapNumberWithValue(value);
85 56 : Return(result);
86 : }
87 :
88 56 : BIND(&if_xisnotheapnumber);
89 : {
90 : // Need to convert {x} to a Number first.
91 56 : var_x.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, x));
92 56 : Goto(&loop);
93 : }
94 : }
95 : }
96 56 : }
97 :
98 224 : void MathBuiltinsAssembler::MathRoundingOperation(
99 : Node* context, Node* x,
100 : TNode<Float64T> (CodeStubAssembler::*float64op)(SloppyTNode<Float64T>)) {
101 : // We might need to loop once for ToNumber conversion.
102 448 : VARIABLE(var_x, MachineRepresentation::kTagged, x);
103 448 : Label loop(this, &var_x);
104 224 : Goto(&loop);
105 224 : BIND(&loop);
106 : {
107 : // Load the current {x} value.
108 224 : Node* x = var_x.value();
109 :
110 : // Check if {x} is a Smi or a HeapObject.
111 448 : Label if_xissmi(this), if_xisnotsmi(this);
112 224 : Branch(TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
113 :
114 224 : BIND(&if_xissmi);
115 : {
116 : // Nothing to do when {x} is a Smi.
117 224 : Return(x);
118 : }
119 :
120 224 : BIND(&if_xisnotsmi);
121 : {
122 : // Check if {x} is a HeapNumber.
123 448 : Label if_xisheapnumber(this), if_xisnotheapnumber(this, Label::kDeferred);
124 224 : Branch(IsHeapNumber(x), &if_xisheapnumber, &if_xisnotheapnumber);
125 :
126 224 : BIND(&if_xisheapnumber);
127 : {
128 224 : Node* x_value = LoadHeapNumberValue(x);
129 224 : Node* value = (this->*float64op)(x_value);
130 224 : Node* result = ChangeFloat64ToTagged(value);
131 224 : Return(result);
132 : }
133 :
134 224 : BIND(&if_xisnotheapnumber);
135 : {
136 : // Need to convert {x} to a Number first.
137 224 : var_x.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, x));
138 224 : Goto(&loop);
139 : }
140 : }
141 : }
142 224 : }
143 :
144 1120 : void MathBuiltinsAssembler::MathUnaryOperation(
145 : Node* context, Node* x,
146 : TNode<Float64T> (CodeStubAssembler::*float64op)(SloppyTNode<Float64T>)) {
147 1120 : Node* x_value = TruncateTaggedToFloat64(context, x);
148 1120 : Node* value = (this->*float64op)(x_value);
149 1120 : Node* result = AllocateHeapNumberWithValue(value);
150 1120 : Return(result);
151 1120 : }
152 :
153 112 : void MathBuiltinsAssembler::MathMaxMin(
154 : Node* context, Node* argc,
155 : TNode<Float64T> (CodeStubAssembler::*float64op)(SloppyTNode<Float64T>,
156 : SloppyTNode<Float64T>),
157 : double default_val) {
158 112 : CodeStubArguments arguments(this, ChangeInt32ToIntPtr(argc));
159 112 : argc = arguments.GetLength(INTPTR_PARAMETERS);
160 :
161 224 : VARIABLE(result, MachineRepresentation::kFloat64);
162 112 : result.Bind(Float64Constant(default_val));
163 :
164 224 : CodeStubAssembler::VariableList vars({&result}, zone());
165 560 : arguments.ForEach(vars, [=, &result](Node* arg) {
166 224 : Node* float_value = TruncateTaggedToFloat64(context, arg);
167 448 : result.Bind((this->*float64op)(result.value(), float_value));
168 224 : });
169 :
170 112 : arguments.PopAndReturn(ChangeFloat64ToTagged(result.value()));
171 112 : }
172 :
173 : // ES6 #sec-math.acos
174 336 : TF_BUILTIN(MathAcos, MathBuiltinsAssembler) {
175 56 : Node* context = Parameter(Descriptor::kContext);
176 56 : Node* x = Parameter(Descriptor::kX);
177 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Acos);
178 56 : }
179 :
180 : // ES6 #sec-math.acosh
181 336 : TF_BUILTIN(MathAcosh, MathBuiltinsAssembler) {
182 56 : Node* context = Parameter(Descriptor::kContext);
183 56 : Node* x = Parameter(Descriptor::kX);
184 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Acosh);
185 56 : }
186 :
187 : // ES6 #sec-math.asin
188 336 : TF_BUILTIN(MathAsin, MathBuiltinsAssembler) {
189 56 : Node* context = Parameter(Descriptor::kContext);
190 56 : Node* x = Parameter(Descriptor::kX);
191 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Asin);
192 56 : }
193 :
194 : // ES6 #sec-math.asinh
195 336 : TF_BUILTIN(MathAsinh, MathBuiltinsAssembler) {
196 56 : Node* context = Parameter(Descriptor::kContext);
197 56 : Node* x = Parameter(Descriptor::kX);
198 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Asinh);
199 56 : }
200 :
201 : // ES6 #sec-math.atan
202 336 : TF_BUILTIN(MathAtan, MathBuiltinsAssembler) {
203 56 : Node* context = Parameter(Descriptor::kContext);
204 56 : Node* x = Parameter(Descriptor::kX);
205 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Atan);
206 56 : }
207 :
208 : // ES6 #sec-math.atanh
209 336 : TF_BUILTIN(MathAtanh, MathBuiltinsAssembler) {
210 56 : Node* context = Parameter(Descriptor::kContext);
211 56 : Node* x = Parameter(Descriptor::kX);
212 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Atanh);
213 56 : }
214 :
215 : // ES6 #sec-math.atan2
216 392 : TF_BUILTIN(MathAtan2, CodeStubAssembler) {
217 56 : Node* context = Parameter(Descriptor::kContext);
218 56 : Node* y = Parameter(Descriptor::kY);
219 56 : Node* x = Parameter(Descriptor::kX);
220 :
221 56 : Node* y_value = TruncateTaggedToFloat64(context, y);
222 56 : Node* x_value = TruncateTaggedToFloat64(context, x);
223 56 : Node* value = Float64Atan2(y_value, x_value);
224 56 : Node* result = AllocateHeapNumberWithValue(value);
225 56 : Return(result);
226 56 : }
227 :
228 : // ES6 #sec-math.ceil
229 336 : TF_BUILTIN(MathCeil, MathBuiltinsAssembler) {
230 56 : Node* context = Parameter(Descriptor::kContext);
231 56 : Node* x = Parameter(Descriptor::kX);
232 56 : MathRoundingOperation(context, x, &CodeStubAssembler::Float64Ceil);
233 56 : }
234 :
235 : // ES6 #sec-math.cbrt
236 336 : TF_BUILTIN(MathCbrt, MathBuiltinsAssembler) {
237 56 : Node* context = Parameter(Descriptor::kContext);
238 56 : Node* x = Parameter(Descriptor::kX);
239 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Cbrt);
240 56 : }
241 :
242 : // ES6 #sec-math.clz32
243 336 : TF_BUILTIN(MathClz32, CodeStubAssembler) {
244 56 : Node* context = Parameter(Descriptor::kContext);
245 :
246 : // Shared entry point for the clz32 operation.
247 112 : VARIABLE(var_clz32_x, MachineRepresentation::kWord32);
248 112 : Label do_clz32(this);
249 :
250 : // We might need to loop once for ToNumber conversion.
251 112 : VARIABLE(var_x, MachineRepresentation::kTagged);
252 112 : Label loop(this, &var_x);
253 56 : var_x.Bind(Parameter(Descriptor::kX));
254 56 : Goto(&loop);
255 56 : BIND(&loop);
256 : {
257 : // Load the current {x} value.
258 56 : Node* x = var_x.value();
259 :
260 : // Check if {x} is a Smi or a HeapObject.
261 112 : Label if_xissmi(this), if_xisnotsmi(this);
262 56 : Branch(TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
263 :
264 56 : BIND(&if_xissmi);
265 : {
266 56 : var_clz32_x.Bind(SmiToInt32(x));
267 56 : Goto(&do_clz32);
268 : }
269 :
270 56 : BIND(&if_xisnotsmi);
271 : {
272 : // Check if {x} is a HeapNumber.
273 112 : Label if_xisheapnumber(this), if_xisnotheapnumber(this, Label::kDeferred);
274 56 : Branch(IsHeapNumber(x), &if_xisheapnumber, &if_xisnotheapnumber);
275 :
276 56 : BIND(&if_xisheapnumber);
277 : {
278 56 : var_clz32_x.Bind(TruncateHeapNumberValueToWord32(x));
279 56 : Goto(&do_clz32);
280 : }
281 :
282 56 : BIND(&if_xisnotheapnumber);
283 : {
284 : // Need to convert {x} to a Number first.
285 56 : var_x.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, x));
286 56 : Goto(&loop);
287 : }
288 : }
289 : }
290 :
291 56 : BIND(&do_clz32);
292 : {
293 56 : Node* x_value = var_clz32_x.value();
294 56 : Node* value = Word32Clz(x_value);
295 56 : Node* result = ChangeInt32ToTagged(value);
296 56 : Return(result);
297 : }
298 56 : }
299 :
300 : // ES6 #sec-math.cos
301 336 : TF_BUILTIN(MathCos, MathBuiltinsAssembler) {
302 56 : Node* context = Parameter(Descriptor::kContext);
303 56 : Node* x = Parameter(Descriptor::kX);
304 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Cos);
305 56 : }
306 :
307 : // ES6 #sec-math.cosh
308 336 : TF_BUILTIN(MathCosh, MathBuiltinsAssembler) {
309 56 : Node* context = Parameter(Descriptor::kContext);
310 56 : Node* x = Parameter(Descriptor::kX);
311 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Cosh);
312 56 : }
313 :
314 : // ES6 #sec-math.exp
315 336 : TF_BUILTIN(MathExp, MathBuiltinsAssembler) {
316 56 : Node* context = Parameter(Descriptor::kContext);
317 56 : Node* x = Parameter(Descriptor::kX);
318 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Exp);
319 56 : }
320 :
321 : // ES6 #sec-math.expm1
322 336 : TF_BUILTIN(MathExpm1, MathBuiltinsAssembler) {
323 56 : Node* context = Parameter(Descriptor::kContext);
324 56 : Node* x = Parameter(Descriptor::kX);
325 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Expm1);
326 56 : }
327 :
328 : // ES6 #sec-math.floor
329 336 : TF_BUILTIN(MathFloor, MathBuiltinsAssembler) {
330 56 : Node* context = Parameter(Descriptor::kContext);
331 56 : Node* x = Parameter(Descriptor::kX);
332 56 : MathRoundingOperation(context, x, &CodeStubAssembler::Float64Floor);
333 56 : }
334 :
335 : // ES6 #sec-math.fround
336 336 : TF_BUILTIN(MathFround, CodeStubAssembler) {
337 56 : Node* context = Parameter(Descriptor::kContext);
338 56 : Node* x = Parameter(Descriptor::kX);
339 56 : Node* x_value = TruncateTaggedToFloat64(context, x);
340 56 : Node* value32 = TruncateFloat64ToFloat32(x_value);
341 56 : Node* value = ChangeFloat32ToFloat64(value32);
342 56 : Node* result = AllocateHeapNumberWithValue(value);
343 56 : Return(result);
344 56 : }
345 :
346 : // ES6 #sec-math.imul
347 392 : TF_BUILTIN(MathImul, CodeStubAssembler) {
348 56 : Node* context = Parameter(Descriptor::kContext);
349 56 : Node* x = Parameter(Descriptor::kX);
350 56 : Node* y = Parameter(Descriptor::kY);
351 56 : Node* x_value = TruncateTaggedToWord32(context, x);
352 56 : Node* y_value = TruncateTaggedToWord32(context, y);
353 56 : Node* value = Int32Mul(x_value, y_value);
354 56 : Node* result = ChangeInt32ToTagged(value);
355 56 : Return(result);
356 56 : }
357 :
358 : // ES6 #sec-math.log
359 336 : TF_BUILTIN(MathLog, MathBuiltinsAssembler) {
360 56 : Node* context = Parameter(Descriptor::kContext);
361 56 : Node* x = Parameter(Descriptor::kX);
362 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Log);
363 56 : }
364 :
365 : // ES6 #sec-math.log1p
366 336 : TF_BUILTIN(MathLog1p, MathBuiltinsAssembler) {
367 56 : Node* context = Parameter(Descriptor::kContext);
368 56 : Node* x = Parameter(Descriptor::kX);
369 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Log1p);
370 56 : }
371 :
372 : // ES6 #sec-math.log10
373 336 : TF_BUILTIN(MathLog10, MathBuiltinsAssembler) {
374 56 : Node* context = Parameter(Descriptor::kContext);
375 56 : Node* x = Parameter(Descriptor::kX);
376 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Log10);
377 56 : }
378 :
379 : // ES6 #sec-math.log2
380 336 : TF_BUILTIN(MathLog2, MathBuiltinsAssembler) {
381 56 : Node* context = Parameter(Descriptor::kContext);
382 56 : Node* x = Parameter(Descriptor::kX);
383 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Log2);
384 56 : }
385 :
386 112 : CodeStubAssembler::Node* MathBuiltinsAssembler::MathPow(Node* context,
387 : Node* base,
388 : Node* exponent) {
389 112 : Node* base_value = TruncateTaggedToFloat64(context, base);
390 112 : Node* exponent_value = TruncateTaggedToFloat64(context, exponent);
391 112 : Node* value = Float64Pow(base_value, exponent_value);
392 112 : return ChangeFloat64ToTagged(value);
393 : }
394 :
395 : // ES6 #sec-math.pow
396 392 : TF_BUILTIN(MathPow, MathBuiltinsAssembler) {
397 112 : Return(MathPow(Parameter(Descriptor::kContext), Parameter(Descriptor::kBase),
398 56 : Parameter(Descriptor::kExponent)));
399 56 : }
400 :
401 : // ES6 #sec-math.random
402 280 : TF_BUILTIN(MathRandom, CodeStubAssembler) {
403 56 : Node* context = Parameter(Descriptor::kContext);
404 56 : Node* native_context = LoadNativeContext(context);
405 :
406 : // Load cache index.
407 112 : TVARIABLE(Smi, smi_index);
408 112 : smi_index = CAST(
409 56 : LoadContextElement(native_context, Context::MATH_RANDOM_INDEX_INDEX));
410 :
411 : // Cached random numbers are exhausted if index is 0. Go to slow path.
412 112 : Label if_cached(this);
413 56 : GotoIf(SmiAbove(smi_index.value(), SmiConstant(0)), &if_cached);
414 :
415 : // Cache exhausted, populate the cache. Return value is the new index.
416 : Node* const refill_math_random =
417 56 : ExternalConstant(ExternalReference::refill_math_random());
418 : Node* const isolate_ptr =
419 56 : ExternalConstant(ExternalReference::isolate_address(isolate()));
420 56 : MachineType type_tagged = MachineType::AnyTagged();
421 56 : MachineType type_ptr = MachineType::Pointer();
422 :
423 56 : smi_index =
424 112 : CAST(CallCFunction2(type_tagged, type_ptr, type_tagged,
425 56 : refill_math_random, isolate_ptr, native_context));
426 56 : Goto(&if_cached);
427 :
428 : // Compute next index by decrement.
429 56 : BIND(&if_cached);
430 56 : TNode<Smi> new_smi_index = SmiSub(smi_index.value(), SmiConstant(1));
431 112 : StoreContextElement(native_context, Context::MATH_RANDOM_INDEX_INDEX,
432 56 : new_smi_index);
433 :
434 : // Load and return next cached random number.
435 : Node* array =
436 56 : LoadContextElement(native_context, Context::MATH_RANDOM_CACHE_INDEX);
437 112 : Node* random = LoadFixedDoubleArrayElement(
438 168 : array, new_smi_index, MachineType::Float64(), 0, SMI_PARAMETERS);
439 56 : Return(AllocateHeapNumberWithValue(random));
440 56 : }
441 :
442 : // ES6 #sec-math.round
443 336 : TF_BUILTIN(MathRound, MathBuiltinsAssembler) {
444 56 : Node* context = Parameter(Descriptor::kContext);
445 56 : Node* x = Parameter(Descriptor::kX);
446 56 : MathRoundingOperation(context, x, &CodeStubAssembler::Float64Round);
447 56 : }
448 :
449 : // ES6 #sec-math.sign
450 336 : TF_BUILTIN(MathSign, CodeStubAssembler) {
451 : // Convert the {x} value to a Number.
452 56 : Node* context = Parameter(Descriptor::kContext);
453 56 : Node* x = Parameter(Descriptor::kX);
454 56 : Node* x_value = TruncateTaggedToFloat64(context, x);
455 :
456 : // Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself.
457 112 : Label if_xisnegative(this), if_xispositive(this);
458 56 : GotoIf(Float64LessThan(x_value, Float64Constant(0.0)), &if_xisnegative);
459 56 : GotoIf(Float64LessThan(Float64Constant(0.0), x_value), &if_xispositive);
460 56 : Return(ChangeFloat64ToTagged(x_value));
461 :
462 56 : BIND(&if_xisnegative);
463 56 : Return(SmiConstant(-1));
464 :
465 56 : BIND(&if_xispositive);
466 56 : Return(SmiConstant(1));
467 56 : }
468 :
469 : // ES6 #sec-math.sin
470 336 : TF_BUILTIN(MathSin, MathBuiltinsAssembler) {
471 56 : Node* context = Parameter(Descriptor::kContext);
472 56 : Node* x = Parameter(Descriptor::kX);
473 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Sin);
474 56 : }
475 :
476 : // ES6 #sec-math.sinh
477 336 : TF_BUILTIN(MathSinh, MathBuiltinsAssembler) {
478 56 : Node* context = Parameter(Descriptor::kContext);
479 56 : Node* x = Parameter(Descriptor::kX);
480 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Sinh);
481 56 : }
482 :
483 : // ES6 #sec-math.sqrt
484 336 : TF_BUILTIN(MathSqrt, MathBuiltinsAssembler) {
485 56 : Node* context = Parameter(Descriptor::kContext);
486 56 : Node* x = Parameter(Descriptor::kX);
487 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Sqrt);
488 56 : }
489 :
490 : // ES6 #sec-math.tan
491 336 : TF_BUILTIN(MathTan, MathBuiltinsAssembler) {
492 56 : Node* context = Parameter(Descriptor::kContext);
493 56 : Node* x = Parameter(Descriptor::kX);
494 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Tan);
495 56 : }
496 :
497 : // ES6 #sec-math.tanh
498 336 : TF_BUILTIN(MathTanh, MathBuiltinsAssembler) {
499 56 : Node* context = Parameter(Descriptor::kContext);
500 56 : Node* x = Parameter(Descriptor::kX);
501 56 : MathUnaryOperation(context, x, &CodeStubAssembler::Float64Tanh);
502 56 : }
503 :
504 : // ES6 #sec-math.trunc
505 336 : TF_BUILTIN(MathTrunc, MathBuiltinsAssembler) {
506 56 : Node* context = Parameter(Descriptor::kContext);
507 56 : Node* x = Parameter(Descriptor::kX);
508 56 : MathRoundingOperation(context, x, &CodeStubAssembler::Float64Trunc);
509 56 : }
510 :
511 : // ES6 #sec-math.max
512 336 : TF_BUILTIN(MathMax, MathBuiltinsAssembler) {
513 : // TODO(ishell): use constants from Descriptor once the JSFunction linkage
514 : // arguments are reordered.
515 56 : Node* context = Parameter(Descriptor::kContext);
516 56 : Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);
517 56 : MathMaxMin(context, argc, &CodeStubAssembler::Float64Max, -1.0 * V8_INFINITY);
518 56 : }
519 :
520 : // ES6 #sec-math.min
521 336 : TF_BUILTIN(MathMin, MathBuiltinsAssembler) {
522 : // TODO(ishell): use constants from Descriptor once the JSFunction linkage
523 : // arguments are reordered.
524 56 : Node* context = Parameter(Descriptor::kContext);
525 56 : Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);
526 56 : MathMaxMin(context, argc, &CodeStubAssembler::Float64Min, V8_INFINITY);
527 56 : }
528 :
529 : } // namespace internal
530 87414 : } // namespace v8
|