Chromium Code Reviews| Index: src/builtins.cc |
| diff --git a/src/builtins.cc b/src/builtins.cc |
| index ebb17106df6d9b6bd944d06743e35684827f48b7..527b4e950c26cd4c457a95aa8a7bf86f2159609b 100644 |
| --- a/src/builtins.cc |
| +++ b/src/builtins.cc |
| @@ -2252,97 +2252,61 @@ void Builtins::Generate_MathAbs(CodeStubAssembler* assembler) { |
| } |
| // ES6 section 20.2.2.2 Math.acos ( x ) |
| -BUILTIN(MathAcos) { |
| - HandleScope scope(isolate); |
| - DCHECK_EQ(2, args.length()); |
| - Handle<Object> x = args.at<Object>(1); |
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x)); |
| - return *isolate->factory()->NewHeapNumber(std::acos(x->Number())); |
| -} |
| +void Builtins::Generate_MathAcos(CodeStubAssembler* assembler) { |
| + using compiler::Node; |
| -// ES6 section 20.2.2.4 Math.asin ( x ) |
| -BUILTIN(MathAsin) { |
| - HandleScope scope(isolate); |
| - DCHECK_EQ(2, args.length()); |
| - Handle<Object> x = args.at<Object>(1); |
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x)); |
| - return *isolate->factory()->NewHeapNumber(std::asin(x->Number())); |
| + Node* x = assembler->Parameter(1); |
| + Node* context = assembler->Parameter(4); |
| + Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| + Node* value = assembler->Float64Acos(x_value); |
| + Node* result = assembler->ChangeFloat64ToTagged(value); |
| + assembler->Return(result); |
| } |
| -// ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values ) |
| -BUILTIN(MathHypot) { |
| - HandleScope scope(isolate); |
| - int const length = args.length() - 1; |
| - if (length == 0) return Smi::FromInt(0); |
| - DCHECK_LT(0, length); |
| - double max = 0; |
| - bool one_arg_is_nan = false; |
| - List<double> abs_values(length); |
| - for (int i = 0; i < length; i++) { |
| - Handle<Object> x = args.at<Object>(i + 1); |
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x)); |
| - double abs_value = std::abs(x->Number()); |
| - |
| - if (std::isnan(abs_value)) { |
| - one_arg_is_nan = true; |
| - } else { |
| - abs_values.Add(abs_value); |
| - if (max < abs_value) { |
| - max = abs_value; |
| - } |
| - } |
| - } |
| - |
| - if (max == V8_INFINITY) { |
| - return *isolate->factory()->NewNumber(V8_INFINITY); |
| - } |
| - |
| - if (one_arg_is_nan) { |
| - return *isolate->factory()->nan_value(); |
| - } |
| +// ES6 section 20.2.2.3 Math.acosh ( x ) |
| +void Builtins::Generate_MathAcosh(CodeStubAssembler* assembler) { |
| + using compiler::Node; |
| - if (max == 0) { |
| - return Smi::FromInt(0); |
| - } |
| - DCHECK_GT(max, 0); |
| + Node* x = assembler->Parameter(1); |
| + Node* context = assembler->Parameter(4); |
| + Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| + Node* value = assembler->Float64Acosh(x_value); |
| + Node* result = assembler->ChangeFloat64ToTagged(value); |
| + assembler->Return(result); |
| +} |
| - // Kahan summation to avoid rounding errors. |
| - // Normalize the numbers to the largest one to avoid overflow. |
| - double sum = 0; |
| - double compensation = 0; |
| - for (int i = 0; i < length; i++) { |
| - double n = abs_values.at(i) / max; |
| - double summand = n * n - compensation; |
| - double preliminary = sum + summand; |
| - compensation = (preliminary - sum) - summand; |
| - sum = preliminary; |
| - } |
| +// ES6 section 20.2.2.4 Math.asin ( x ) |
| +void Builtins::Generate_MathAsin(CodeStubAssembler* assembler) { |
| + using compiler::Node; |
| - return *isolate->factory()->NewNumber(std::sqrt(sum) * max); |
| + Node* x = assembler->Parameter(1); |
| + Node* context = assembler->Parameter(4); |
| + Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| + Node* value = assembler->Float64Asin(x_value); |
| + Node* result = assembler->ChangeFloat64ToTagged(value); |
| + assembler->Return(result); |
| } |
| -// ES6 section 20.2.2.6 Math.atan ( x ) |
| -void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) { |
| +// ES6 section 20.2.2.5 Math.asinh ( x ) |
| +void Builtins::Generate_MathAsinh(CodeStubAssembler* assembler) { |
| using compiler::Node; |
| Node* x = assembler->Parameter(1); |
| Node* context = assembler->Parameter(4); |
| Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| - Node* value = assembler->Float64Atan(x_value); |
| + Node* value = assembler->Float64Asinh(x_value); |
| Node* result = assembler->ChangeFloat64ToTagged(value); |
| assembler->Return(result); |
| } |
| -// ES6 section 20.2.2.8 Math.atan2 ( y, x ) |
| -void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) { |
| +// ES6 section 20.2.2.6 Math.atan ( x ) |
| +void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) { |
| using compiler::Node; |
| - Node* y = assembler->Parameter(1); |
| - Node* x = assembler->Parameter(2); |
| - Node* context = assembler->Parameter(5); |
| - Node* y_value = assembler->TruncateTaggedToFloat64(context, y); |
| + Node* x = assembler->Parameter(1); |
| + Node* context = assembler->Parameter(4); |
| Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| - Node* value = assembler->Float64Atan2(y_value, x_value); |
| + Node* value = assembler->Float64Atan(x_value); |
| Node* result = assembler->ChangeFloat64ToTagged(value); |
| assembler->Return(result); |
| } |
| @@ -2359,6 +2323,20 @@ void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) { |
| assembler->Return(result); |
| } |
| +// ES6 section 20.2.2.8 Math.atan2 ( y, x ) |
| +void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) { |
| + using compiler::Node; |
| + |
| + Node* y = assembler->Parameter(1); |
| + Node* x = assembler->Parameter(2); |
| + Node* context = assembler->Parameter(5); |
| + Node* y_value = assembler->TruncateTaggedToFloat64(context, y); |
| + Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| + Node* value = assembler->Float64Atan2(y_value, x_value); |
| + Node* result = assembler->ChangeFloat64ToTagged(value); |
| + assembler->Return(result); |
| +} |
| + |
| namespace { |
| void Generate_MathRoundingOperation( |
| @@ -2549,25 +2527,82 @@ void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) { |
| } |
| // ES6 section 20.2.2.17 Math.fround ( x ) |
| -BUILTIN(MathFround) { |
| +void Builtins::Generate_MathFround(CodeStubAssembler* assembler) { |
| + using compiler::Node; |
| + |
| + Node* x = assembler->Parameter(1); |
| + Node* context = assembler->Parameter(4); |
| + Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| + Node* value32 = assembler->TruncateFloat64ToFloat32(x_value); |
| + Node* value = assembler->ChangeFloat32ToFloat64(value32); |
| + Node* result = assembler->ChangeFloat64ToTagged(value); |
| + assembler->Return(result); |
| +} |
| + |
| +// ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values ) |
| +BUILTIN(MathHypot) { |
| HandleScope scope(isolate); |
| - DCHECK_EQ(2, args.length()); |
| - Handle<Object> x = args.at<Object>(1); |
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x)); |
| - float x32 = DoubleToFloat32(x->Number()); |
| - return *isolate->factory()->NewNumber(x32); |
| + int const length = args.length() - 1; |
| + if (length == 0) return Smi::FromInt(0); |
| + DCHECK_LT(0, length); |
| + double max = 0; |
| + bool one_arg_is_nan = false; |
| + List<double> abs_values(length); |
| + for (int i = 0; i < length; i++) { |
| + Handle<Object> x = args.at<Object>(i + 1); |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x)); |
| + double abs_value = std::abs(x->Number()); |
| + |
| + if (std::isnan(abs_value)) { |
| + one_arg_is_nan = true; |
| + } else { |
| + abs_values.Add(abs_value); |
| + if (max < abs_value) { |
| + max = abs_value; |
| + } |
| + } |
| + } |
| + |
| + if (max == V8_INFINITY) { |
| + return *isolate->factory()->NewNumber(V8_INFINITY); |
| + } |
| + |
| + if (one_arg_is_nan) { |
| + return *isolate->factory()->nan_value(); |
| + } |
| + |
| + if (max == 0) { |
| + return Smi::FromInt(0); |
| + } |
| + DCHECK_GT(max, 0); |
| + |
| + // Kahan summation to avoid rounding errors. |
| + // Normalize the numbers to the largest one to avoid overflow. |
| + double sum = 0; |
| + double compensation = 0; |
| + for (int i = 0; i < length; i++) { |
| + double n = abs_values.at(i) / max; |
| + double summand = n * n - compensation; |
| + double preliminary = sum + summand; |
| + compensation = (preliminary - sum) - summand; |
| + sum = preliminary; |
| + } |
| + |
| + return *isolate->factory()->NewNumber(std::sqrt(sum) * max); |
| } |
| // ES6 section 20.2.2.19 Math.imul ( x, y ) |
| -BUILTIN(MathImul) { |
| - HandleScope scope(isolate); |
| - DCHECK_EQ(3, args.length()); |
| - Handle<Object> x = args.at<Object>(1); |
| - Handle<Object> y = args.at<Object>(2); |
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x)); |
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, y, Object::ToNumber(y)); |
| - int product = static_cast<int>(NumberToUint32(*x) * NumberToUint32(*y)); |
| - return *isolate->factory()->NewNumberFromInt(product); |
| +void Builtins::Generate_MathImul(CodeStubAssembler* assembler) { |
| + using compiler::Node; |
| + |
| + Node* x = assembler->Parameter(1); |
| + Node* y = assembler->Parameter(2); |
| + Node* context = assembler->Parameter(5); |
| + Node* x_value = assembler->TruncateTaggedToWord32(context, x); |
| + Node* y_value = assembler->TruncateTaggedToWord32(context, y); |
| + Node* value = assembler->Int32Mul(x_value, y_value); |
| + Node* result = assembler->ChangeInt32ToTagged(value); |
| + assembler->Return(result); |
| } |
| // ES6 section 20.2.2.20 Math.log ( x ) |
| @@ -2594,26 +2629,26 @@ void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) { |
| assembler->Return(result); |
| } |
| -// ES6 section 20.2.2.23 Math.log2 ( x ) |
| -void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) { |
| +// ES6 section 20.2.2.22 Math.log10 ( x ) |
| +void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) { |
| using compiler::Node; |
| Node* x = assembler->Parameter(1); |
| Node* context = assembler->Parameter(4); |
| Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| - Node* value = assembler->Float64Log2(x_value); |
| + Node* value = assembler->Float64Log10(x_value); |
| Node* result = assembler->ChangeFloat64ToTagged(value); |
| assembler->Return(result); |
| } |
| -// ES6 section 20.2.2.22 Math.log10 ( x ) |
| -void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) { |
| +// ES6 section 20.2.2.23 Math.log2 ( x ) |
| +void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) { |
| using compiler::Node; |
| Node* x = assembler->Parameter(1); |
| Node* context = assembler->Parameter(4); |
| Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| - Node* value = assembler->Float64Log10(x_value); |
| + Node* value = assembler->Float64Log2(x_value); |
| Node* result = assembler->ChangeFloat64ToTagged(value); |
| assembler->Return(result); |
| } |
| @@ -2630,11 +2665,6 @@ void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) { |
| assembler->Return(result); |
| } |
| -// ES6 section 20.2.2.28 Math.round ( x ) |
| -void Builtins::Generate_MathRound(CodeStubAssembler* assembler) { |
| - Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round); |
| -} |
| - |
| // ES6 section 20.2.2.26 Math.pow ( x, y ) |
| void Builtins::Generate_MathPow(CodeStubAssembler* assembler) { |
| using compiler::Node; |
| @@ -2649,6 +2679,38 @@ void Builtins::Generate_MathPow(CodeStubAssembler* assembler) { |
| assembler->Return(result); |
| } |
| +// ES6 section 20.2.2.28 Math.round ( x ) |
| +void Builtins::Generate_MathRound(CodeStubAssembler* assembler) { |
| + Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round); |
| +} |
| + |
| +// ES6 section 20.2.2.29 Math.sign ( x ) |
| +void Builtins::Generate_MathSign(CodeStubAssembler* assembler) { |
| + typedef CodeStubAssembler::Label Label; |
| + using compiler::Node; |
| + |
| + // Convert the {x} value to a Number. |
| + Node* x = assembler->Parameter(1); |
| + Node* context = assembler->Parameter(4); |
| + Node* x_value = assembler->TruncateTaggedToFloat64(context, x); |
| + |
| + // Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself. |
| + Label if_xisnegative(assembler), if_xispositive(assembler); |
| + assembler->GotoIf( |
| + assembler->Float64LessThan(x_value, assembler->Float64Constant(0.0)), |
| + &if_xisnegative); |
| + assembler->GotoIf( |
| + assembler->Float64LessThan(assembler->Float64Constant(0.0), x_value), |
| + &if_xispositive); |
| + assembler->Return(assembler->ChangeFloat64ToTagged(x_value)); |
|
Franzi
2016/07/01 09:09:48
Can we return x instead of converting the float ba
Benedikt Meurer
2016/07/01 10:48:33
No we can't because x can be anything, not even a
|
| + |
| + assembler->Bind(&if_xisnegative); |
| + assembler->Return(assembler->SmiConstant(Smi::FromInt(-1))); |
| + |
| + assembler->Bind(&if_xispositive); |
| + assembler->Return(assembler->SmiConstant(Smi::FromInt(1))); |
| +} |
| + |
| // ES6 section 20.2.2.30 Math.sin ( x ) |
| void Builtins::Generate_MathSin(CodeStubAssembler* assembler) { |
| using compiler::Node; |