Commit a9e62152 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

Add NumberMin/NumberMax methods to CSA

Change-Id: Ib36b6e27476f7cc1e2064e147fbfa7d3d1e28b49

These will be used in subsequent CLs to add spec-compliant builtins
on Array.prototype built with the CSA.

Change-Id: Ib36b6e27476f7cc1e2064e147fbfa7d3d1e28b49
Reviewed-on: https://chromium-review.googlesource.com/700694
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48306}
parent 80159989
......@@ -529,6 +529,44 @@ TNode<Smi> CodeStubAssembler::SmiMin(SloppyTNode<Smi> a, SloppyTNode<Smi> b) {
return SelectTaggedConstant(SmiLessThan(a, b), a, b);
}
TNode<Object> CodeStubAssembler::NumberMax(SloppyTNode<Object> a,
SloppyTNode<Object> b) {
// TODO(danno): This could be optimized by specifically handling smi cases.
VARIABLE(result, MachineRepresentation::kTagged);
Label done(this), greater_than_equal_a(this), greater_than_equal_b(this);
GotoIfNumberGreaterThanOrEqual(a, b, &greater_than_equal_a);
GotoIfNumberGreaterThanOrEqual(b, a, &greater_than_equal_b);
result.Bind(NanConstant());
Goto(&done);
BIND(&greater_than_equal_a);
result.Bind(a);
Goto(&done);
BIND(&greater_than_equal_b);
result.Bind(b);
Goto(&done);
BIND(&done);
return TNode<Object>::UncheckedCast(result.value());
}
TNode<Object> CodeStubAssembler::NumberMin(SloppyTNode<Object> a,
SloppyTNode<Object> b) {
// TODO(danno): This could be optimized by specifically handling smi cases.
VARIABLE(result, MachineRepresentation::kTagged);
Label done(this), greater_than_equal_a(this), greater_than_equal_b(this);
GotoIfNumberGreaterThanOrEqual(a, b, &greater_than_equal_a);
GotoIfNumberGreaterThanOrEqual(b, a, &greater_than_equal_b);
result.Bind(NanConstant());
Goto(&done);
BIND(&greater_than_equal_a);
result.Bind(b);
Goto(&done);
BIND(&greater_than_equal_b);
result.Bind(a);
Goto(&done);
BIND(&done);
return TNode<Object>::UncheckedCast(result.value());
}
Node* CodeStubAssembler::SmiMod(Node* a, Node* b) {
VARIABLE(var_result, MachineRepresentation::kTagged);
Label return_result(this, &var_result),
......
......@@ -195,6 +195,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Float64T> Float64Round(SloppyTNode<Float64T> x);
TNode<Float64T> Float64RoundToEven(SloppyTNode<Float64T> x);
TNode<Float64T> Float64Trunc(SloppyTNode<Float64T> x);
// Select the minimum of the two provided Number values.
TNode<Object> NumberMax(SloppyTNode<Object> left, SloppyTNode<Object> right);
// Select the minimum of the two provided Number values.
TNode<Object> NumberMin(SloppyTNode<Object> left, SloppyTNode<Object> right);
// Tag a Word as a Smi value.
TNode<Smi> SmiTag(SloppyTNode<IntPtrT> value);
......
......@@ -2748,6 +2748,62 @@ TEST(IsNumberArrayIndex) {
}
}
TEST(NumberMinMax) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2;
CodeAssemblerTester asm_tester_min(isolate, kNumParams);
{
CodeStubAssembler m(asm_tester_min.state());
m.Return(m.NumberMin(m.Parameter(0), m.Parameter(1)));
}
FunctionTester ft_min(asm_tester_min.GenerateCode(), kNumParams);
CodeAssemblerTester asm_tester_max(isolate, kNumParams);
{
CodeStubAssembler m(asm_tester_max.state());
m.Return(m.NumberMax(m.Parameter(0), m.Parameter(1)));
}
FunctionTester ft_max(asm_tester_max.GenerateCode(), kNumParams);
// Test smi values.
Handle<Smi> smi_1(Smi::FromInt(1), isolate);
Handle<Smi> smi_2(Smi::FromInt(2), isolate);
Handle<Smi> smi_5(Smi::FromInt(5), isolate);
CHECK_EQ(ft_min.CallChecked<Smi>(smi_1, smi_2)->value(), 1);
CHECK_EQ(ft_min.CallChecked<Smi>(smi_2, smi_1)->value(), 1);
CHECK_EQ(ft_max.CallChecked<Smi>(smi_1, smi_2)->value(), 2);
CHECK_EQ(ft_max.CallChecked<Smi>(smi_2, smi_1)->value(), 2);
// Test double values.
Handle<Object> double_a = isolate->factory()->NewNumber(2.5);
Handle<Object> double_b = isolate->factory()->NewNumber(3.5);
Handle<Object> nan =
isolate->factory()->NewNumber(std::numeric_limits<double>::quiet_NaN());
Handle<Object> infinity = isolate->factory()->NewNumber(V8_INFINITY);
CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_a, double_b)->value(), 2.5);
CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_b, double_a)->value(), 2.5);
CHECK_EQ(ft_min.CallChecked<HeapNumber>(infinity, double_a)->value(), 2.5);
CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_a, infinity)->value(), 2.5);
CHECK(std::isnan(ft_min.CallChecked<HeapNumber>(nan, double_a)->value()));
CHECK(std::isnan(ft_min.CallChecked<HeapNumber>(double_a, nan)->value()));
CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_a, double_b)->value(), 3.5);
CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_b, double_a)->value(), 3.5);
CHECK_EQ(ft_max.CallChecked<HeapNumber>(infinity, double_a)->value(),
V8_INFINITY);
CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_a, infinity)->value(),
V8_INFINITY);
CHECK(std::isnan(ft_max.CallChecked<HeapNumber>(nan, double_a)->value()));
CHECK(std::isnan(ft_max.CallChecked<HeapNumber>(double_a, nan)->value()));
// Mixed smi/double values.
CHECK_EQ(ft_max.CallChecked<HeapNumber>(smi_1, double_b)->value(), 3.5);
CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_b, smi_1)->value(), 3.5);
CHECK_EQ(ft_min.CallChecked<HeapNumber>(smi_5, double_b)->value(), 3.5);
CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_b, smi_5)->value(), 3.5);
}
} // namespace compiler
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment