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

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

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

Powered by Google App Engine
This is Rietveld 408576698