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

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

Issue 2165593002: [builtins] Move builtins into own files (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove builtins-error.cc from BUILD.gn Created 4 years, 5 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
« no previous file with comments | « src/builtins/builtins-json.cc ('k') | src/builtins/builtins-number.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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.h"
6 #include "src/builtins/builtins-utils.h"
7
8 #include "src/code-factory.h"
9
10 namespace v8 {
11 namespace internal {
12
13 // -----------------------------------------------------------------------------
14 // ES6 section 20.2.2 Function Properties of the Math Object
15
16 // ES6 section - 20.2.2.1 Math.abs ( x )
17 void Builtins::Generate_MathAbs(CodeStubAssembler* assembler) {
18 using compiler::Node;
19 Node* x = assembler->Parameter(1);
20 Node* context = assembler->Parameter(4);
21 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
22 Node* value = assembler->Float64Abs(x_value);
23 Node* result = assembler->ChangeFloat64ToTagged(value);
24 assembler->Return(result);
25 }
26
27 // ES6 section 20.2.2.2 Math.acos ( x )
28 void Builtins::Generate_MathAcos(CodeStubAssembler* assembler) {
29 using compiler::Node;
30
31 Node* x = assembler->Parameter(1);
32 Node* context = assembler->Parameter(4);
33 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
34 Node* value = assembler->Float64Acos(x_value);
35 Node* result = assembler->ChangeFloat64ToTagged(value);
36 assembler->Return(result);
37 }
38
39 // ES6 section 20.2.2.3 Math.acosh ( x )
40 void Builtins::Generate_MathAcosh(CodeStubAssembler* assembler) {
41 using compiler::Node;
42
43 Node* x = assembler->Parameter(1);
44 Node* context = assembler->Parameter(4);
45 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
46 Node* value = assembler->Float64Acosh(x_value);
47 Node* result = assembler->ChangeFloat64ToTagged(value);
48 assembler->Return(result);
49 }
50
51 // ES6 section 20.2.2.4 Math.asin ( x )
52 void Builtins::Generate_MathAsin(CodeStubAssembler* assembler) {
53 using compiler::Node;
54
55 Node* x = assembler->Parameter(1);
56 Node* context = assembler->Parameter(4);
57 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
58 Node* value = assembler->Float64Asin(x_value);
59 Node* result = assembler->ChangeFloat64ToTagged(value);
60 assembler->Return(result);
61 }
62
63 // ES6 section 20.2.2.5 Math.asinh ( x )
64 void Builtins::Generate_MathAsinh(CodeStubAssembler* assembler) {
65 using compiler::Node;
66
67 Node* x = assembler->Parameter(1);
68 Node* context = assembler->Parameter(4);
69 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
70 Node* value = assembler->Float64Asinh(x_value);
71 Node* result = assembler->ChangeFloat64ToTagged(value);
72 assembler->Return(result);
73 }
74
75 // ES6 section 20.2.2.6 Math.atan ( x )
76 void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
77 using compiler::Node;
78
79 Node* x = assembler->Parameter(1);
80 Node* context = assembler->Parameter(4);
81 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
82 Node* value = assembler->Float64Atan(x_value);
83 Node* result = assembler->ChangeFloat64ToTagged(value);
84 assembler->Return(result);
85 }
86
87 // ES6 section 20.2.2.7 Math.atanh ( x )
88 void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
89 using compiler::Node;
90
91 Node* x = assembler->Parameter(1);
92 Node* context = assembler->Parameter(4);
93 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
94 Node* value = assembler->Float64Atanh(x_value);
95 Node* result = assembler->ChangeFloat64ToTagged(value);
96 assembler->Return(result);
97 }
98
99 // ES6 section 20.2.2.8 Math.atan2 ( y, x )
100 void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
101 using compiler::Node;
102
103 Node* y = assembler->Parameter(1);
104 Node* x = assembler->Parameter(2);
105 Node* context = assembler->Parameter(5);
106 Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
107 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
108 Node* value = assembler->Float64Atan2(y_value, x_value);
109 Node* result = assembler->ChangeFloat64ToTagged(value);
110 assembler->Return(result);
111 }
112
113 namespace {
114
115 void Generate_MathRoundingOperation(
116 CodeStubAssembler* assembler,
117 compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
118 typedef CodeStubAssembler::Label Label;
119 typedef compiler::Node Node;
120 typedef CodeStubAssembler::Variable Variable;
121
122 Node* context = assembler->Parameter(4);
123
124 // We might need to loop once for ToNumber conversion.
125 Variable var_x(assembler, MachineRepresentation::kTagged);
126 Label loop(assembler, &var_x);
127 var_x.Bind(assembler->Parameter(1));
128 assembler->Goto(&loop);
129 assembler->Bind(&loop);
130 {
131 // Load the current {x} value.
132 Node* x = var_x.value();
133
134 // Check if {x} is a Smi or a HeapObject.
135 Label if_xissmi(assembler), if_xisnotsmi(assembler);
136 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
137
138 assembler->Bind(&if_xissmi);
139 {
140 // Nothing to do when {x} is a Smi.
141 assembler->Return(x);
142 }
143
144 assembler->Bind(&if_xisnotsmi);
145 {
146 // Check if {x} is a HeapNumber.
147 Label if_xisheapnumber(assembler),
148 if_xisnotheapnumber(assembler, Label::kDeferred);
149 assembler->Branch(
150 assembler->WordEqual(assembler->LoadMap(x),
151 assembler->HeapNumberMapConstant()),
152 &if_xisheapnumber, &if_xisnotheapnumber);
153
154 assembler->Bind(&if_xisheapnumber);
155 {
156 Node* x_value = assembler->LoadHeapNumberValue(x);
157 Node* value = (assembler->*float64op)(x_value);
158 Node* result = assembler->ChangeFloat64ToTagged(value);
159 assembler->Return(result);
160 }
161
162 assembler->Bind(&if_xisnotheapnumber);
163 {
164 // Need to convert {x} to a Number first.
165 Callable callable =
166 CodeFactory::NonNumberToNumber(assembler->isolate());
167 var_x.Bind(assembler->CallStub(callable, context, x));
168 assembler->Goto(&loop);
169 }
170 }
171 }
172 }
173
174 } // namespace
175
176 // ES6 section 20.2.2.10 Math.ceil ( x )
177 void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
178 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
179 }
180
181 // ES6 section 20.2.2.9 Math.cbrt ( x )
182 void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
183 using compiler::Node;
184
185 Node* x = assembler->Parameter(1);
186 Node* context = assembler->Parameter(4);
187 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
188 Node* value = assembler->Float64Cbrt(x_value);
189 Node* result = assembler->ChangeFloat64ToTagged(value);
190 assembler->Return(result);
191 }
192
193 // ES6 section 20.2.2.11 Math.clz32 ( x )
194 void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
195 typedef CodeStubAssembler::Label Label;
196 typedef compiler::Node Node;
197 typedef CodeStubAssembler::Variable Variable;
198
199 Node* context = assembler->Parameter(4);
200
201 // Shared entry point for the clz32 operation.
202 Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
203 Label do_clz32(assembler);
204
205 // We might need to loop once for ToNumber conversion.
206 Variable var_x(assembler, MachineRepresentation::kTagged);
207 Label loop(assembler, &var_x);
208 var_x.Bind(assembler->Parameter(1));
209 assembler->Goto(&loop);
210 assembler->Bind(&loop);
211 {
212 // Load the current {x} value.
213 Node* x = var_x.value();
214
215 // Check if {x} is a Smi or a HeapObject.
216 Label if_xissmi(assembler), if_xisnotsmi(assembler);
217 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
218
219 assembler->Bind(&if_xissmi);
220 {
221 var_clz32_x.Bind(assembler->SmiToWord32(x));
222 assembler->Goto(&do_clz32);
223 }
224
225 assembler->Bind(&if_xisnotsmi);
226 {
227 // Check if {x} is a HeapNumber.
228 Label if_xisheapnumber(assembler),
229 if_xisnotheapnumber(assembler, Label::kDeferred);
230 assembler->Branch(
231 assembler->WordEqual(assembler->LoadMap(x),
232 assembler->HeapNumberMapConstant()),
233 &if_xisheapnumber, &if_xisnotheapnumber);
234
235 assembler->Bind(&if_xisheapnumber);
236 {
237 var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
238 assembler->Goto(&do_clz32);
239 }
240
241 assembler->Bind(&if_xisnotheapnumber);
242 {
243 // Need to convert {x} to a Number first.
244 Callable callable =
245 CodeFactory::NonNumberToNumber(assembler->isolate());
246 var_x.Bind(assembler->CallStub(callable, context, x));
247 assembler->Goto(&loop);
248 }
249 }
250 }
251
252 assembler->Bind(&do_clz32);
253 {
254 Node* x_value = var_clz32_x.value();
255 Node* value = assembler->Word32Clz(x_value);
256 Node* result = assembler->ChangeInt32ToTagged(value);
257 assembler->Return(result);
258 }
259 }
260
261 // ES6 section 20.2.2.12 Math.cos ( x )
262 void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
263 using compiler::Node;
264
265 Node* x = assembler->Parameter(1);
266 Node* context = assembler->Parameter(4);
267 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
268 Node* value = assembler->Float64Cos(x_value);
269 Node* result = assembler->ChangeFloat64ToTagged(value);
270 assembler->Return(result);
271 }
272
273 // ES6 section 20.2.2.13 Math.cosh ( x )
274 void Builtins::Generate_MathCosh(CodeStubAssembler* assembler) {
275 using compiler::Node;
276
277 Node* x = assembler->Parameter(1);
278 Node* context = assembler->Parameter(4);
279 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
280 Node* value = assembler->Float64Cosh(x_value);
281 Node* result = assembler->ChangeFloat64ToTagged(value);
282 assembler->Return(result);
283 }
284
285 // ES6 section 20.2.2.14 Math.exp ( x )
286 void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
287 using compiler::Node;
288
289 Node* x = assembler->Parameter(1);
290 Node* context = assembler->Parameter(4);
291 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
292 Node* value = assembler->Float64Exp(x_value);
293 Node* result = assembler->ChangeFloat64ToTagged(value);
294 assembler->Return(result);
295 }
296
297 // ES6 section 20.2.2.16 Math.floor ( x )
298 void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
299 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
300 }
301
302 // ES6 section 20.2.2.17 Math.fround ( x )
303 void Builtins::Generate_MathFround(CodeStubAssembler* assembler) {
304 using compiler::Node;
305
306 Node* x = assembler->Parameter(1);
307 Node* context = assembler->Parameter(4);
308 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
309 Node* value32 = assembler->TruncateFloat64ToFloat32(x_value);
310 Node* value = assembler->ChangeFloat32ToFloat64(value32);
311 Node* result = assembler->ChangeFloat64ToTagged(value);
312 assembler->Return(result);
313 }
314
315 // ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values )
316 BUILTIN(MathHypot) {
317 HandleScope scope(isolate);
318 int const length = args.length() - 1;
319 if (length == 0) return Smi::FromInt(0);
320 DCHECK_LT(0, length);
321 double max = 0;
322 bool one_arg_is_nan = false;
323 List<double> abs_values(length);
324 for (int i = 0; i < length; i++) {
325 Handle<Object> x = args.at<Object>(i + 1);
326 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
327 double abs_value = std::abs(x->Number());
328
329 if (std::isnan(abs_value)) {
330 one_arg_is_nan = true;
331 } else {
332 abs_values.Add(abs_value);
333 if (max < abs_value) {
334 max = abs_value;
335 }
336 }
337 }
338
339 if (max == V8_INFINITY) {
340 return *isolate->factory()->NewNumber(V8_INFINITY);
341 }
342
343 if (one_arg_is_nan) {
344 return *isolate->factory()->nan_value();
345 }
346
347 if (max == 0) {
348 return Smi::FromInt(0);
349 }
350 DCHECK_GT(max, 0);
351
352 // Kahan summation to avoid rounding errors.
353 // Normalize the numbers to the largest one to avoid overflow.
354 double sum = 0;
355 double compensation = 0;
356 for (int i = 0; i < length; i++) {
357 double n = abs_values.at(i) / max;
358 double summand = n * n - compensation;
359 double preliminary = sum + summand;
360 compensation = (preliminary - sum) - summand;
361 sum = preliminary;
362 }
363
364 return *isolate->factory()->NewNumber(std::sqrt(sum) * max);
365 }
366
367 // ES6 section 20.2.2.19 Math.imul ( x, y )
368 void Builtins::Generate_MathImul(CodeStubAssembler* assembler) {
369 using compiler::Node;
370
371 Node* x = assembler->Parameter(1);
372 Node* y = assembler->Parameter(2);
373 Node* context = assembler->Parameter(5);
374 Node* x_value = assembler->TruncateTaggedToWord32(context, x);
375 Node* y_value = assembler->TruncateTaggedToWord32(context, y);
376 Node* value = assembler->Int32Mul(x_value, y_value);
377 Node* result = assembler->ChangeInt32ToTagged(value);
378 assembler->Return(result);
379 }
380
381 // ES6 section 20.2.2.20 Math.log ( x )
382 void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
383 using compiler::Node;
384
385 Node* x = assembler->Parameter(1);
386 Node* context = assembler->Parameter(4);
387 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
388 Node* value = assembler->Float64Log(x_value);
389 Node* result = assembler->ChangeFloat64ToTagged(value);
390 assembler->Return(result);
391 }
392
393 // ES6 section 20.2.2.21 Math.log1p ( x )
394 void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
395 using compiler::Node;
396
397 Node* x = assembler->Parameter(1);
398 Node* context = assembler->Parameter(4);
399 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
400 Node* value = assembler->Float64Log1p(x_value);
401 Node* result = assembler->ChangeFloat64ToTagged(value);
402 assembler->Return(result);
403 }
404
405 // ES6 section 20.2.2.22 Math.log10 ( x )
406 void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
407 using compiler::Node;
408
409 Node* x = assembler->Parameter(1);
410 Node* context = assembler->Parameter(4);
411 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
412 Node* value = assembler->Float64Log10(x_value);
413 Node* result = assembler->ChangeFloat64ToTagged(value);
414 assembler->Return(result);
415 }
416
417 // ES6 section 20.2.2.23 Math.log2 ( x )
418 void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
419 using compiler::Node;
420
421 Node* x = assembler->Parameter(1);
422 Node* context = assembler->Parameter(4);
423 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
424 Node* value = assembler->Float64Log2(x_value);
425 Node* result = assembler->ChangeFloat64ToTagged(value);
426 assembler->Return(result);
427 }
428
429 // ES6 section 20.2.2.15 Math.expm1 ( x )
430 void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
431 using compiler::Node;
432
433 Node* x = assembler->Parameter(1);
434 Node* context = assembler->Parameter(4);
435 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
436 Node* value = assembler->Float64Expm1(x_value);
437 Node* result = assembler->ChangeFloat64ToTagged(value);
438 assembler->Return(result);
439 }
440
441 // ES6 section 20.2.2.26 Math.pow ( x, y )
442 void Builtins::Generate_MathPow(CodeStubAssembler* assembler) {
443 using compiler::Node;
444
445 Node* x = assembler->Parameter(1);
446 Node* y = assembler->Parameter(2);
447 Node* context = assembler->Parameter(5);
448 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
449 Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
450 Node* value = assembler->Float64Pow(x_value, y_value);
451 Node* result = assembler->ChangeFloat64ToTagged(value);
452 assembler->Return(result);
453 }
454
455 // ES6 section 20.2.2.28 Math.round ( x )
456 void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
457 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
458 }
459
460 // ES6 section 20.2.2.29 Math.sign ( x )
461 void Builtins::Generate_MathSign(CodeStubAssembler* assembler) {
462 typedef CodeStubAssembler::Label Label;
463 using compiler::Node;
464
465 // Convert the {x} value to a Number.
466 Node* x = assembler->Parameter(1);
467 Node* context = assembler->Parameter(4);
468 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
469
470 // Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself.
471 Label if_xisnegative(assembler), if_xispositive(assembler);
472 assembler->GotoIf(
473 assembler->Float64LessThan(x_value, assembler->Float64Constant(0.0)),
474 &if_xisnegative);
475 assembler->GotoIf(
476 assembler->Float64LessThan(assembler->Float64Constant(0.0), x_value),
477 &if_xispositive);
478 assembler->Return(assembler->ChangeFloat64ToTagged(x_value));
479
480 assembler->Bind(&if_xisnegative);
481 assembler->Return(assembler->SmiConstant(Smi::FromInt(-1)));
482
483 assembler->Bind(&if_xispositive);
484 assembler->Return(assembler->SmiConstant(Smi::FromInt(1)));
485 }
486
487 // ES6 section 20.2.2.30 Math.sin ( x )
488 void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
489 using compiler::Node;
490
491 Node* x = assembler->Parameter(1);
492 Node* context = assembler->Parameter(4);
493 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
494 Node* value = assembler->Float64Sin(x_value);
495 Node* result = assembler->ChangeFloat64ToTagged(value);
496 assembler->Return(result);
497 }
498
499 // ES6 section 20.2.2.31 Math.sinh ( x )
500 void Builtins::Generate_MathSinh(CodeStubAssembler* assembler) {
501 using compiler::Node;
502
503 Node* x = assembler->Parameter(1);
504 Node* context = assembler->Parameter(4);
505 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
506 Node* value = assembler->Float64Sinh(x_value);
507 Node* result = assembler->ChangeFloat64ToTagged(value);
508 assembler->Return(result);
509 }
510
511 // ES6 section 20.2.2.32 Math.sqrt ( x )
512 void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
513 using compiler::Node;
514
515 Node* x = assembler->Parameter(1);
516 Node* context = assembler->Parameter(4);
517 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
518 Node* value = assembler->Float64Sqrt(x_value);
519 Node* result = assembler->ChangeFloat64ToTagged(value);
520 assembler->Return(result);
521 }
522
523 // ES6 section 20.2.2.33 Math.tan ( x )
524 void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
525 using compiler::Node;
526
527 Node* x = assembler->Parameter(1);
528 Node* context = assembler->Parameter(4);
529 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
530 Node* value = assembler->Float64Tan(x_value);
531 Node* result = assembler->ChangeFloat64ToTagged(value);
532 assembler->Return(result);
533 }
534
535 // ES6 section 20.2.2.34 Math.tanh ( x )
536 void Builtins::Generate_MathTanh(CodeStubAssembler* assembler) {
537 using compiler::Node;
538
539 Node* x = assembler->Parameter(1);
540 Node* context = assembler->Parameter(4);
541 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
542 Node* value = assembler->Float64Tanh(x_value);
543 Node* result = assembler->ChangeFloat64ToTagged(value);
544 assembler->Return(result);
545 }
546
547 // ES6 section 20.2.2.35 Math.trunc ( x )
548 void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
549 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
550 }
551
552 void Builtins::Generate_MathMax(MacroAssembler* masm) {
553 Generate_MathMaxMin(masm, MathMaxMinKind::kMax);
554 }
555
556 void Builtins::Generate_MathMin(MacroAssembler* masm) {
557 Generate_MathMaxMin(masm, MathMaxMinKind::kMin);
558 }
559
560 } // namespace internal
561 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-json.cc ('k') | src/builtins/builtins-number.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698