[asm.js] Fix Math.min/max signatures to take signed.
This fixes the signature of "Math.min" and "Math.max" for integer values from "(int, int...) -> signed" to "(signed, signed..) -> signed" which properly distinguishes signed from unsigned values now. This is in sync with the spec errata (and ECMAScript semantics). R=clemensh@chromium.org TEST=mjsunit/regress/regress-6838-1 BUG=v8:6838 Change-Id: Id72836513dd86e93472a22cf1ac2e2d382ed4f23 Reviewed-on: https://chromium-review.googlesource.com/681357 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#48139}
This commit is contained in:
parent
8d38c15e04
commit
63f9ee1645
@ -119,13 +119,16 @@ void AsmJsParser::InitializeStdlibTypes() {
|
||||
stdlib_ii2s_->AsFunctionType()->AddArgument(i);
|
||||
stdlib_ii2s_->AsFunctionType()->AddArgument(i);
|
||||
|
||||
// The signatures in "9 Standard Library" of the spec draft are outdated and
|
||||
// have been superseded with the following by an errata:
|
||||
// - Math.min/max : (signed, signed...) -> signed
|
||||
// (double, double...) -> double
|
||||
// (float, float...) -> float
|
||||
auto* minmax_d = AsmType::MinMaxType(zone(), d, d);
|
||||
// *VIOLATION* The float variant is not part of the spec, but firefox accepts
|
||||
// it.
|
||||
auto* minmax_f = AsmType::MinMaxType(zone(), f, f);
|
||||
auto* minmax_i = AsmType::MinMaxType(zone(), s, i);
|
||||
auto* minmax_s = AsmType::MinMaxType(zone(), s, s);
|
||||
stdlib_minmax_ = AsmType::OverloadedFunction(zone());
|
||||
stdlib_minmax_->AsOverloadedFunctionType()->AddOverload(minmax_i);
|
||||
stdlib_minmax_->AsOverloadedFunctionType()->AddOverload(minmax_s);
|
||||
stdlib_minmax_->AsOverloadedFunctionType()->AddOverload(minmax_f);
|
||||
stdlib_minmax_->AsOverloadedFunctionType()->AddOverload(minmax_d);
|
||||
|
||||
@ -2248,7 +2251,7 @@ AsmType* AsmJsParser::ValidateCall() {
|
||||
current_function_builder_->Emit(kExprF32Max);
|
||||
}
|
||||
}
|
||||
} else if (param_specific_types[0]->IsA(AsmType::Int())) {
|
||||
} else if (param_specific_types[0]->IsA(AsmType::Signed())) {
|
||||
TemporaryVariableScope tmp_x(this);
|
||||
TemporaryVariableScope tmp_y(this);
|
||||
for (size_t i = 1; i < param_specific_types.size(); ++i) {
|
||||
|
78
test/mjsunit/asm/math-max.js
Normal file
78
test/mjsunit/asm/math-max.js
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
function Module(stdlib) {
|
||||
"use asm";
|
||||
|
||||
var max = stdlib.Math.max;
|
||||
var fround = stdlib.Math.fround;
|
||||
|
||||
// f: double, double -> double
|
||||
function f(a, b) {
|
||||
a = +a; b = +b;
|
||||
return +max(a, b);
|
||||
}
|
||||
|
||||
// g: signed, signed -> signed
|
||||
function g(a, b) {
|
||||
a = a | 0; b = b | 0;
|
||||
return max(a >> 0, b >> 0) | 0;
|
||||
}
|
||||
|
||||
// h: float, float -> float
|
||||
function h(a, b) {
|
||||
a = fround(a); b = fround(b);
|
||||
return fround(max(a, b));
|
||||
}
|
||||
|
||||
return { f: f, g: g, h: h };
|
||||
}
|
||||
|
||||
var m = Module({ Math: Math });
|
||||
var f = m.f;
|
||||
var g = m.g;
|
||||
var h = m.h;
|
||||
|
||||
assertTrue(isNaN(f(0, NaN)));
|
||||
assertFalse(isFinite(f(0, Infinity)));
|
||||
assertTrue(isFinite(f(0, -Infinity)));
|
||||
|
||||
assertTrue(Object.is(+0, f(-0, +0)));
|
||||
assertTrue(Object.is(+0, f(+0, -0)));
|
||||
|
||||
assertEquals(0.1, f( 0, 0.1));
|
||||
assertEquals(0.5, f( 0.1, 0.5));
|
||||
assertEquals(0.5, f( 0.5, -0.1));
|
||||
assertEquals(-0.1, f(-0.1, -0.5));
|
||||
assertEquals(1, f(-0.5, 1));
|
||||
assertEquals(1.1, f( 1, 1.1));
|
||||
assertEquals(1.1, f( 1.1, -1));
|
||||
assertEquals(-1, f(-1, -1.1));
|
||||
assertEquals(0, f(-1.1, 0));
|
||||
|
||||
assertEquals( 1, g( 0, 1));
|
||||
assertEquals( 5, g( 1, 5));
|
||||
assertEquals( 5, g( 5, -1));
|
||||
assertEquals(-1, g(-1, -5));
|
||||
assertEquals( 1, g(-5, 1));
|
||||
assertEquals( 1, g( 1, -1));
|
||||
assertEquals( 0, g(-1, 0));
|
||||
|
||||
assertEquals(Math.fround(0.1), h( 0, 0.1));
|
||||
assertEquals(Math.fround(0.5), h( 0.1, 0.5));
|
||||
assertEquals(Math.fround(0.5), h( 0.5, -0.1));
|
||||
assertEquals(Math.fround(-0.1), h(-0.1, -0.5));
|
||||
assertEquals(Math.fround(1), h(-0.5, 1));
|
||||
assertEquals(Math.fround(1.1), h( 1, 1.1));
|
||||
assertEquals(Math.fround(1.1), h( 1.1, -1));
|
||||
assertEquals(Math.fround(-1), h(-1, -1.1));
|
||||
assertEquals(Math.fround(0), h(-1.1, 0));
|
||||
|
||||
assertEquals(1, g(0, Number.MIN_SAFE_INTEGER));
|
||||
assertEquals(0, g(0, Number.MAX_SAFE_INTEGER));
|
||||
|
||||
assertEquals(Number.MAX_VALUE, f(Number.MIN_VALUE, Number.MAX_VALUE));
|
||||
assertEquals(Number.MAX_VALUE, f(Number.MAX_VALUE, Number.MIN_VALUE));
|
||||
assertEquals(Number.POSITIVE_INFINITY, f(Number.POSITIVE_INFINITY, 0));
|
||||
assertEquals(0, f(Number.NEGATIVE_INFINITY, 0));
|
78
test/mjsunit/asm/math-min.js
vendored
Normal file
78
test/mjsunit/asm/math-min.js
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
function Module(stdlib) {
|
||||
"use asm";
|
||||
|
||||
var min = stdlib.Math.min;
|
||||
var fround = stdlib.Math.fround;
|
||||
|
||||
// f: double, double -> double
|
||||
function f(a, b) {
|
||||
a = +a; b = +b;
|
||||
return +min(a, b);
|
||||
}
|
||||
|
||||
// g: signed, signed -> signed
|
||||
function g(a, b) {
|
||||
a = a | 0; b = b | 0;
|
||||
return min(a >> 0, b >> 0) | 0;
|
||||
}
|
||||
|
||||
// h: float, float -> float
|
||||
function h(a, b) {
|
||||
a = fround(a); b = fround(b);
|
||||
return fround(min(a, b));
|
||||
}
|
||||
|
||||
return { f: f, g: g, h: h };
|
||||
}
|
||||
|
||||
var m = Module({ Math: Math });
|
||||
var f = m.f;
|
||||
var g = m.g;
|
||||
var h = m.h;
|
||||
|
||||
assertTrue(isNaN(f(0, NaN)));
|
||||
assertTrue(isFinite(f(0, Infinity)));
|
||||
assertFalse(isFinite(f(0, -Infinity)));
|
||||
|
||||
assertTrue(Object.is(-0, f(-0, +0)));
|
||||
assertTrue(Object.is(-0, f(+0, -0)));
|
||||
|
||||
assertEquals(0, f( 0, 0.1));
|
||||
assertEquals(0.1, f( 0.1, 0.5));
|
||||
assertEquals(-0.1, f( 0.5, -0.1));
|
||||
assertEquals(-0.5, f(-0.1, -0.5));
|
||||
assertEquals(-0.5, f(-0.5, 1));
|
||||
assertEquals(1, f( 1, 1.1));
|
||||
assertEquals(-1, f( 1.1, -1));
|
||||
assertEquals(-1.1, f(-1, -1.1));
|
||||
assertEquals(-1.1, f(-1.1, 0));
|
||||
|
||||
assertEquals( 0, g( 0, 1));
|
||||
assertEquals( 1, g( 1, 5));
|
||||
assertEquals(-1, g( 5, -1));
|
||||
assertEquals(-5, g(-1, -5));
|
||||
assertEquals(-5, g(-5, 1));
|
||||
assertEquals(-1, g( 1, -1));
|
||||
assertEquals(-1, g(-1, 0));
|
||||
|
||||
assertEquals(Math.fround(0), h( 0, 0.1));
|
||||
assertEquals(Math.fround(0.1), h( 0.1, 0.5));
|
||||
assertEquals(Math.fround(-0.1), h( 0.5, -0.1));
|
||||
assertEquals(Math.fround(-0.5), h(-0.1, -0.5));
|
||||
assertEquals(Math.fround(-0.5), h(-0.5, 1));
|
||||
assertEquals(Math.fround(1), h( 1, 1.1));
|
||||
assertEquals(Math.fround(-1), h( 1.1, -1));
|
||||
assertEquals(Math.fround(-1.1), h(-1, -1.1));
|
||||
assertEquals(Math.fround(-1.1), h(-1.1, 0));
|
||||
|
||||
assertEquals(0, g(0, Number.MIN_SAFE_INTEGER));
|
||||
assertEquals(-1, g(0, Number.MAX_SAFE_INTEGER));
|
||||
|
||||
assertEquals(Number.MIN_VALUE, f(Number.MIN_VALUE, Number.MAX_VALUE));
|
||||
assertEquals(Number.MIN_VALUE, f(Number.MAX_VALUE, Number.MIN_VALUE));
|
||||
assertEquals(0, f(Number.POSITIVE_INFINITY, 0));
|
||||
assertEquals(Number.NEGATIVE_INFINITY, f(Number.NEGATIVE_INFINITY, 0));
|
33
test/mjsunit/regress/regress-6838-1.js
Normal file
33
test/mjsunit/regress/regress-6838-1.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
(function TestMathMaxOnLargeInt() {
|
||||
function Module(stdlib) {
|
||||
"use asm";
|
||||
var max = stdlib.Math.max;
|
||||
function f() {
|
||||
return max(42,0xffffffff);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
var f = Module(this);
|
||||
assertEquals(0xffffffff, f());
|
||||
assertFalse(%IsAsmWasmCode(Module));
|
||||
})();
|
||||
|
||||
(function TestMathMinOnLargeInt() {
|
||||
function Module(stdlib) {
|
||||
"use asm";
|
||||
var min = stdlib.Math.min;
|
||||
function f() {
|
||||
return min(42,0xffffffff);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
var f = Module(this);
|
||||
assertEquals(42, f());
|
||||
assertFalse(%IsAsmWasmCode(Module));
|
||||
})();
|
Loading…
Reference in New Issue
Block a user