11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h"
61cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h"
71cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cinamespace v8 {
101cb0ef41Sopenharmony_cinamespace internal {
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci// ES #sec-isfinite-number
131cb0ef41Sopenharmony_ciTF_BUILTIN(GlobalIsFinite, CodeStubAssembler) {
141cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci  Label return_true(this), return_false(this);
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci  // We might need to loop once for ToNumber conversion.
191cb0ef41Sopenharmony_ci  TVARIABLE(Object, var_num);
201cb0ef41Sopenharmony_ci  Label loop(this, &var_num);
211cb0ef41Sopenharmony_ci  var_num = Parameter<Object>(Descriptor::kNumber);
221cb0ef41Sopenharmony_ci  Goto(&loop);
231cb0ef41Sopenharmony_ci  BIND(&loop);
241cb0ef41Sopenharmony_ci  {
251cb0ef41Sopenharmony_ci    TNode<Object> num = var_num.value();
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci    // Check if {num} is a Smi or a HeapObject.
281cb0ef41Sopenharmony_ci    GotoIf(TaggedIsSmi(num), &return_true);
291cb0ef41Sopenharmony_ci    TNode<HeapObject> num_heap_object = CAST(num);
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci    // Check if {num_heap_object} is a HeapNumber.
321cb0ef41Sopenharmony_ci    Label if_numisheapnumber(this),
331cb0ef41Sopenharmony_ci        if_numisnotheapnumber(this, Label::kDeferred);
341cb0ef41Sopenharmony_ci    Branch(IsHeapNumber(num_heap_object), &if_numisheapnumber,
351cb0ef41Sopenharmony_ci           &if_numisnotheapnumber);
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci    BIND(&if_numisheapnumber);
381cb0ef41Sopenharmony_ci    {
391cb0ef41Sopenharmony_ci      // Check if {num_heap_object} contains a finite, non-NaN value.
401cb0ef41Sopenharmony_ci      TNode<Float64T> num_value = LoadHeapNumberValue(num_heap_object);
411cb0ef41Sopenharmony_ci      BranchIfFloat64IsNaN(Float64Sub(num_value, num_value), &return_false,
421cb0ef41Sopenharmony_ci                           &return_true);
431cb0ef41Sopenharmony_ci    }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci    BIND(&if_numisnotheapnumber);
461cb0ef41Sopenharmony_ci    {
471cb0ef41Sopenharmony_ci      // Need to convert {num_heap_object} to a Number first.
481cb0ef41Sopenharmony_ci      var_num =
491cb0ef41Sopenharmony_ci          CallBuiltin(Builtin::kNonNumberToNumber, context, num_heap_object);
501cb0ef41Sopenharmony_ci      Goto(&loop);
511cb0ef41Sopenharmony_ci    }
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  BIND(&return_true);
551cb0ef41Sopenharmony_ci  Return(TrueConstant());
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  BIND(&return_false);
581cb0ef41Sopenharmony_ci  Return(FalseConstant());
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci// ES6 #sec-isnan-number
621cb0ef41Sopenharmony_ciTF_BUILTIN(GlobalIsNaN, CodeStubAssembler) {
631cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  Label return_true(this), return_false(this);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  // We might need to loop once for ToNumber conversion.
681cb0ef41Sopenharmony_ci  TVARIABLE(Object, var_num);
691cb0ef41Sopenharmony_ci  Label loop(this, &var_num);
701cb0ef41Sopenharmony_ci  var_num = Parameter<Object>(Descriptor::kNumber);
711cb0ef41Sopenharmony_ci  Goto(&loop);
721cb0ef41Sopenharmony_ci  BIND(&loop);
731cb0ef41Sopenharmony_ci  {
741cb0ef41Sopenharmony_ci    TNode<Object> num = var_num.value();
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci    // Check if {num} is a Smi or a HeapObject.
771cb0ef41Sopenharmony_ci    GotoIf(TaggedIsSmi(num), &return_false);
781cb0ef41Sopenharmony_ci    TNode<HeapObject> num_heap_object = CAST(num);
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci    // Check if {num_heap_object} is a HeapNumber.
811cb0ef41Sopenharmony_ci    Label if_numisheapnumber(this),
821cb0ef41Sopenharmony_ci        if_numisnotheapnumber(this, Label::kDeferred);
831cb0ef41Sopenharmony_ci    Branch(IsHeapNumber(num_heap_object), &if_numisheapnumber,
841cb0ef41Sopenharmony_ci           &if_numisnotheapnumber);
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci    BIND(&if_numisheapnumber);
871cb0ef41Sopenharmony_ci    {
881cb0ef41Sopenharmony_ci      // Check if {num_heap_object} contains a NaN.
891cb0ef41Sopenharmony_ci      TNode<Float64T> num_value = LoadHeapNumberValue(num_heap_object);
901cb0ef41Sopenharmony_ci      BranchIfFloat64IsNaN(num_value, &return_true, &return_false);
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    BIND(&if_numisnotheapnumber);
941cb0ef41Sopenharmony_ci    {
951cb0ef41Sopenharmony_ci      // Need to convert {num_heap_object} to a Number first.
961cb0ef41Sopenharmony_ci      var_num =
971cb0ef41Sopenharmony_ci          CallBuiltin(Builtin::kNonNumberToNumber, context, num_heap_object);
981cb0ef41Sopenharmony_ci      Goto(&loop);
991cb0ef41Sopenharmony_ci    }
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  BIND(&return_true);
1031cb0ef41Sopenharmony_ci  Return(TrueConstant());
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  BIND(&return_false);
1061cb0ef41Sopenharmony_ci  Return(FalseConstant());
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci}  // namespace internal
1101cb0ef41Sopenharmony_ci}  // namespace v8
111