// 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.

#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/codegen/code-stub-assembler.h"

namespace v8 {
namespace internal {

// ES #sec-isfinite-number
TF_BUILTIN(GlobalIsFinite, CodeStubAssembler) {
  auto context = Parameter<Context>(Descriptor::kContext);

  Label return_true(this), return_false(this);

  // We might need to loop once for ToNumber conversion.
  TVARIABLE(Object, var_num);
  Label loop(this, &var_num);
  var_num = Parameter<Object>(Descriptor::kNumber);
  Goto(&loop);
  BIND(&loop);
  {
    TNode<Object> num = var_num.value();

    // Check if {num} is a Smi or a HeapObject.
    GotoIf(TaggedIsSmi(num), &return_true);
    TNode<HeapObject> num_heap_object = CAST(num);

    // Check if {num_heap_object} is a HeapNumber.
    Label if_numisheapnumber(this),
        if_numisnotheapnumber(this, Label::kDeferred);
    Branch(IsHeapNumber(num_heap_object), &if_numisheapnumber,
           &if_numisnotheapnumber);

    BIND(&if_numisheapnumber);
    {
      // Check if {num_heap_object} contains a finite, non-NaN value.
      TNode<Float64T> num_value = LoadHeapNumberValue(num_heap_object);
      BranchIfFloat64IsNaN(Float64Sub(num_value, num_value), &return_false,
                           &return_true);
    }

    BIND(&if_numisnotheapnumber);
    {
      // Need to convert {num_heap_object} to a Number first.
      var_num =
          CallBuiltin(Builtins::kNonNumberToNumber, context, num_heap_object);
      Goto(&loop);
    }
  }

  BIND(&return_true);
  Return(TrueConstant());

  BIND(&return_false);
  Return(FalseConstant());
}

// ES6 #sec-isnan-number
TF_BUILTIN(GlobalIsNaN, CodeStubAssembler) {
  auto context = Parameter<Context>(Descriptor::kContext);

  Label return_true(this), return_false(this);

  // We might need to loop once for ToNumber conversion.
  TVARIABLE(Object, var_num);
  Label loop(this, &var_num);
  var_num = Parameter<Object>(Descriptor::kNumber);
  Goto(&loop);
  BIND(&loop);
  {
    TNode<Object> num = var_num.value();

    // Check if {num} is a Smi or a HeapObject.
    GotoIf(TaggedIsSmi(num), &return_false);
    TNode<HeapObject> num_heap_object = CAST(num);

    // Check if {num_heap_object} is a HeapNumber.
    Label if_numisheapnumber(this),
        if_numisnotheapnumber(this, Label::kDeferred);
    Branch(IsHeapNumber(num_heap_object), &if_numisheapnumber,
           &if_numisnotheapnumber);

    BIND(&if_numisheapnumber);
    {
      // Check if {num_heap_object} contains a NaN.
      TNode<Float64T> num_value = LoadHeapNumberValue(num_heap_object);
      BranchIfFloat64IsNaN(num_value, &return_true, &return_false);
    }

    BIND(&if_numisnotheapnumber);
    {
      // Need to convert {num_heap_object} to a Number first.
      var_num =
          CallBuiltin(Builtins::kNonNumberToNumber, context, num_heap_object);
      Goto(&loop);
    }
  }

  BIND(&return_true);
  Return(TrueConstant());

  BIND(&return_false);
  Return(FalseConstant());
}

}  // namespace internal
}  // namespace v8
