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