Skip to content

Commit bdf66e6

Browse files
Gumichocopengin8Constellation
authored andcommitted
Math.hypot() is significantly slower than Math.sqrt()
https://bugs.webkit.org/show_bug.cgi?id=284631 Reviewed by Yusuke Suzuki. optimized `Math.hypot()` for cases with 1, 2 or 3 arguments * JSTests/microbenchmarks/math-hypot.js: Added. (hypot): * Source/JavaScriptCore/runtime/MathObject.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): Canonical link: https://commits.webkit.org/292549@main
1 parent c12c372 commit bdf66e6

3 files changed

Lines changed: 55 additions & 0 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
function hypot2(arg1, arg2) {
2+
return Math.hypot(arg1, arg2);
3+
}
4+
5+
function hypot3(arg1, arg2, arg3) {
6+
return Math.hypot(arg1, arg2, arg3);
7+
}
8+
noInline(hypot2);
9+
noInline(hypot3);
10+
11+
for (var i = 0; i < testLoopCount; ++i) {
12+
hypot2(3, 4);
13+
hypot2(9, 12);
14+
hypot3(400.2, -3.4, 3);
15+
hypot3(-24.3, -400.2, -0.4);
16+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function sqrt(arg) {
2+
return Math.sqrt(arg);
3+
}
4+
5+
noInline(sqrt);
6+
7+
for (var i = 0; i < testLoopCount; ++i) {
8+
sqrt(3);
9+
sqrt(9);
10+
sqrt(400.2);
11+
sqrt(-24.3);
12+
}

Source/JavaScriptCore/runtime/MathObject.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,33 @@ JSC_DEFINE_HOST_FUNCTION(mathProtoFuncHypot, (JSGlobalObject* globalObject, Call
199199
auto scope = DECLARE_THROW_SCOPE(vm);
200200

201201
unsigned argsCount = callFrame->argumentCount();
202+
203+
if (argsCount == 1) {
204+
double arg0 = callFrame->uncheckedArgument(0).toNumber(globalObject);
205+
RETURN_IF_EXCEPTION(scope, { });
206+
return JSValue::encode(jsDoubleNumber(std::fabs(arg0)));
207+
}
208+
if (argsCount == 2) {
209+
double arg0 = callFrame->uncheckedArgument(0).toNumber(globalObject);
210+
RETURN_IF_EXCEPTION(scope, { });
211+
double arg1 = callFrame->uncheckedArgument(1).toNumber(globalObject);
212+
RETURN_IF_EXCEPTION(scope, { });
213+
if (std::isinf(arg0) || std::isinf(arg1))
214+
return JSValue::encode(jsDoubleNumber(+std::numeric_limits<double>::infinity()));
215+
return JSValue::encode(jsDoubleNumber(std::hypot(arg0, arg1)));
216+
}
217+
if (argsCount == 3) {
218+
double arg0 = callFrame->uncheckedArgument(0).toNumber(globalObject);
219+
RETURN_IF_EXCEPTION(scope, { });
220+
double arg1 = callFrame->uncheckedArgument(1).toNumber(globalObject);
221+
RETURN_IF_EXCEPTION(scope, { });
222+
double arg2 = callFrame->uncheckedArgument(2).toNumber(globalObject);
223+
RETURN_IF_EXCEPTION(scope, { });
224+
if (std::isinf(arg0) || std::isinf(arg1) || std::isinf(arg2))
225+
return JSValue::encode(jsDoubleNumber(+std::numeric_limits<double>::infinity()));
226+
return JSValue::encode(jsDoubleNumber(std::hypotl(std::hypotl(arg0, arg1), arg2)));
227+
}
228+
202229
Vector<double, 8> args(argsCount, [&](size_t i) -> std::optional<double> {
203230
double argument = callFrame->uncheckedArgument(i).toNumber(globalObject);
204231
RETURN_IF_EXCEPTION(scope, std::nullopt);

0 commit comments

Comments
 (0)