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