Bug 1028704 - IonMonkey: Implement RMinMax recover instruction. r=nbp

This commit is contained in:
Paali Tandia 2014-07-02 06:05:51 -07:00
parent 38f3c3177a
commit eb9814aa24
6 changed files with 135 additions and 7 deletions

View File

@ -419,6 +419,45 @@ function rpowhalf_object(i) {
return i;
}
var uceFault_min_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_min_number'));
function rmin_number(i) {
var x = Math.min(i, i-1, i-2.1);
if (uceFault_min_number(i) || uceFault_min_number(i))
assertEq(x, i-2.1);
return i;
}
var uceFault_min_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_min_object'));
function rmin_object(i) {
var t = i;
var o = { valueOf: function () { return t; } };
var x = Math.min(o, o-1, o-2.1)
t = 1000;
if (uceFault_min_object(i) || uceFault_min_object(i))
assertEq(x, i-2.1);
return i;
}
var uceFault_max_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_max_number'));
function rmax_number(i) {
var x = Math.max(i, i-1, i-2.1);
if (uceFault_max_number(i) || uceFault_max_number(i))
assertEq(x, i);
return i;
}
var uceFault_max_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_max_object'));
function rmax_object(i) {
var t = i;
var o = { valueOf: function () { return t; } };
var x = Math.max(o, o-1, o-2.1)
t = 1000;
if (uceFault_max_object(i) || uceFault_max_object(i))
assertEq(x, i);
return i;
}
for (i = 0; i < 100; i++) {
rbitnot_number(i);
rbitnot_object(i);
@ -464,6 +503,10 @@ for (i = 0; i < 100; i++) {
rpow_object(i);
rpowhalf_number(i);
rpowhalf_object(i);
rmin_number(i);
rmin_object(i);
rmax_number(i);
rmax_object(i);
}
// Test that we can refer multiple time to the same recover instruction, as well

View File

@ -3936,6 +3936,10 @@ class MMinMax
return AliasSet::None();
}
void computeRange(TempAllocator &alloc);
bool writeRecoverData(CompactBufferWriter &writer) const;
bool canRecoverOnBailout() const {
return true;
}
};
class MAbs

View File

@ -710,6 +710,34 @@ RPowHalf::recover(JSContext *cx, SnapshotIterator &iter) const
return true;
}
bool
MMinMax::writeRecoverData(CompactBufferWriter &writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_MinMax));
writer.writeByte(isMax_);
return true;
}
RMinMax::RMinMax(CompactBufferReader &reader)
{
isMax_ = reader.readByte();
}
bool
RMinMax::recover(JSContext *cx, SnapshotIterator &iter) const
{
RootedValue a(cx, iter.read());
RootedValue b(cx, iter.read());
RootedValue result(cx);
if (!js_minmax_impl(cx, isMax_, a, b, &result))
return false;
iter.storeInstructionResult(result);
return true;
}
bool
MMathFunction::writeRecoverData(CompactBufferWriter &writer) const
{

View File

@ -39,6 +39,7 @@ namespace jit {
_(FromCharCode) \
_(Pow) \
_(PowHalf) \
_(MinMax) \
_(NewObject) \
_(NewDerivedTypedObject)
@ -372,6 +373,21 @@ class RPowHalf MOZ_FINAL : public RInstruction
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RMinMax MOZ_FINAL : public RInstruction
{
private:
bool isMax_;
public:
RINSTRUCTION_HEADER_(MinMax)
virtual uint32_t numOperands() const {
return 2;
}
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RNewObject MOZ_FINAL : public RInstruction
{
private:

View File

@ -552,6 +552,15 @@ js::math_log(JSContext *cx, unsigned argc, Value *vp)
return true;
}
static double
max_double(double x, double y)
{
// Math.max(num, NaN) => NaN, Math.max(-0, +0) => +0
if (x > y || IsNaN(x) || (x == y && IsNegative(y)))
return x;
return y;
}
bool
js_math_max(JSContext *cx, unsigned argc, Value *vp)
{
@ -562,14 +571,21 @@ js_math_max(JSContext *cx, unsigned argc, Value *vp)
double x;
if (!ToNumber(cx, args[i], &x))
return false;
// Math.max(num, NaN) => NaN, Math.max(-0, +0) => +0
if (x > maxval || IsNaN(x) || (x == maxval && IsNegative(maxval)))
maxval = x;
maxval = max_double(x, maxval);
}
args.rval().setNumber(maxval);
return true;
}
static double
min_double(double x, double y)
{
// Math.min(num, NaN) => NaN, Math.min(-0, +0) => -0
if (x < y || IsNaN(x) || (x == y && IsNegativeZero(x)))
return x;
return y;
}
bool
js_math_min(JSContext *cx, unsigned argc, Value *vp)
{
@ -580,14 +596,30 @@ js_math_min(JSContext *cx, unsigned argc, Value *vp)
double x;
if (!ToNumber(cx, args[i], &x))
return false;
// Math.min(num, NaN) => NaN, Math.min(-0, +0) => -0
if (x < minval || IsNaN(x) || (x == minval && IsNegativeZero(x)))
minval = x;
minval = min_double(x, minval);
}
args.rval().setNumber(minval);
return true;
}
bool
js_minmax_impl(JSContext *cx, bool max, HandleValue a, HandleValue b, MutableHandleValue res)
{
double x, y;
if (!ToNumber(cx, a, &x))
return false;
if (!ToNumber(cx, b, &y))
return false;
if (max)
res.setNumber(max_double(x, y));
else
res.setNumber(min_double(x, y));
return true;
}
// Disable PGO for Math.pow() and related functions (see bug 791214).
#if defined(_MSC_VER)
# pragma optimize("g", off)

View File

@ -111,11 +111,16 @@ extern bool
js_math_sqrt(JSContext *cx, unsigned argc, js::Value *vp);
extern bool
js_math_pow_handle(JSContext *cx, js::HandleValue base, js::HandleValue power, js::MutableHandleValue result);
js_math_pow_handle(JSContext *cx, js::HandleValue base, js::HandleValue power,
js::MutableHandleValue result);
extern bool
js_math_pow(JSContext *cx, unsigned argc, js::Value *vp);
extern bool
js_minmax_impl(JSContext *cx, bool max, js::HandleValue a, js::HandleValue b,
js::MutableHandleValue res);
namespace js {
extern bool