// Copyright 2014 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/compiler/js-graph.h"

#include "src/codegen/code-factory.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/typer.h"
#include "src/objects/objects-inl.h"

namespace v8 {
namespace internal {
namespace compiler {

#define GET_CACHED_FIELD(ptr, expr) (*(ptr)) ? *(ptr) : (*(ptr) = (expr))

#define DEFINE_GETTER(name, expr) \
  Node* JSGraph::name() { return GET_CACHED_FIELD(&name##_, expr); }

Node* JSGraph::CEntryStubConstant(int result_size, SaveFPRegsMode save_doubles,
                                  ArgvMode argv_mode, bool builtin_exit_frame) {
  if (save_doubles == kDontSaveFPRegs && argv_mode == kArgvOnStack) {
    DCHECK(result_size >= 1 && result_size <= 3);
    if (!builtin_exit_frame) {
      Node** ptr = nullptr;
      if (result_size == 1) {
        ptr = &CEntryStub1Constant_;
      } else if (result_size == 2) {
        ptr = &CEntryStub2Constant_;
      } else {
        DCHECK_EQ(3, result_size);
        ptr = &CEntryStub3Constant_;
      }
      return GET_CACHED_FIELD(ptr, HeapConstant(CodeFactory::CEntry(
                                       isolate(), result_size, save_doubles,
                                       argv_mode, builtin_exit_frame)));
    }
    Node** ptr = builtin_exit_frame ? &CEntryStub1WithBuiltinExitFrameConstant_
                                    : &CEntryStub1Constant_;
    return GET_CACHED_FIELD(ptr, HeapConstant(CodeFactory::CEntry(
                                     isolate(), result_size, save_doubles,
                                     argv_mode, builtin_exit_frame)));
  }
  return HeapConstant(CodeFactory::CEntry(isolate(), result_size, save_doubles,
                                          argv_mode, builtin_exit_frame));
}

Node* JSGraph::Constant(Handle<Object> value) {
  // Dereference the handle to determine if a number constant or other
  // canonicalized node can be used.
  if (value->IsNumber()) {
    return Constant(value->Number());
  } else if (value->IsUndefined(isolate())) {
    return UndefinedConstant();
  } else if (value->IsTrue(isolate())) {
    return TrueConstant();
  } else if (value->IsFalse(isolate())) {
    return FalseConstant();
  } else if (value->IsNull(isolate())) {
    return NullConstant();
  } else if (value->IsTheHole(isolate())) {
    return TheHoleConstant();
  } else {
    return HeapConstant(Handle<HeapObject>::cast(value));
  }
}

Node* JSGraph::Constant(const ObjectRef& ref) {
  if (ref.IsSmi()) return Constant(ref.AsSmi());
  OddballType oddball_type =
      ref.AsHeapObject().GetHeapObjectType().oddball_type();
  if (ref.IsHeapNumber()) {
    return Constant(ref.AsHeapNumber().value());
  } else if (oddball_type == OddballType::kUndefined) {
    DCHECK(ref.object().equals(isolate()->factory()->undefined_value()));
    return UndefinedConstant();
  } else if (oddball_type == OddballType::kNull) {
    DCHECK(ref.object().equals(isolate()->factory()->null_value()));
    return NullConstant();
  } else if (oddball_type == OddballType::kHole) {
    DCHECK(ref.object().equals(isolate()->factory()->the_hole_value()));
    return TheHoleConstant();
  } else if (oddball_type == OddballType::kBoolean) {
    if (ref.object().equals(isolate()->factory()->true_value())) {
      return TrueConstant();
    } else {
      DCHECK(ref.object().equals(isolate()->factory()->false_value()));
      return FalseConstant();
    }
  } else {
    return HeapConstant(ref.AsHeapObject().object());
  }
}

Node* JSGraph::Constant(double value) {
  if (bit_cast<int64_t>(value) == bit_cast<int64_t>(0.0)) return ZeroConstant();
  if (bit_cast<int64_t>(value) == bit_cast<int64_t>(1.0)) return OneConstant();
  return NumberConstant(value);
}

Node* JSGraph::NumberConstant(double value) {
  Node** loc = cache_.FindNumberConstant(value);
  if (*loc == nullptr) {
    *loc = graph()->NewNode(common()->NumberConstant(value));
  }
  return *loc;
}

Node* JSGraph::HeapConstant(Handle<HeapObject> value) {
  Node** loc = cache_.FindHeapConstant(value);
  if (*loc == nullptr) {
    *loc = graph()->NewNode(common()->HeapConstant(value));
  }
  return *loc;
}

void JSGraph::GetCachedNodes(NodeVector* nodes) {
  cache_.GetCachedNodes(nodes);
#define DO_CACHED_FIELD(name) \
  if (name##_) nodes->push_back(name##_);

  CACHED_GLOBAL_LIST(DO_CACHED_FIELD)
  CACHED_CENTRY_LIST(DO_CACHED_FIELD)
#undef DO_CACHED_FIELD
}

DEFINE_GETTER(AllocateInYoungGenerationStubConstant,
              HeapConstant(BUILTIN_CODE(isolate(), AllocateInYoungGeneration)))

DEFINE_GETTER(AllocateRegularInYoungGenerationStubConstant,
              HeapConstant(BUILTIN_CODE(isolate(),
                                        AllocateRegularInYoungGeneration)))

DEFINE_GETTER(AllocateInOldGenerationStubConstant,
              HeapConstant(BUILTIN_CODE(isolate(), AllocateInOldGeneration)))

DEFINE_GETTER(AllocateRegularInOldGenerationStubConstant,
              HeapConstant(BUILTIN_CODE(isolate(),
                                        AllocateRegularInOldGeneration)))

DEFINE_GETTER(ArrayConstructorStubConstant,
              HeapConstant(BUILTIN_CODE(isolate(), ArrayConstructorImpl)))

DEFINE_GETTER(BigIntMapConstant, HeapConstant(factory()->bigint_map()))

DEFINE_GETTER(BooleanMapConstant, HeapConstant(factory()->boolean_map()))

DEFINE_GETTER(ToNumberBuiltinConstant,
              HeapConstant(BUILTIN_CODE(isolate(), ToNumber)))

DEFINE_GETTER(EmptyFixedArrayConstant,
              HeapConstant(factory()->empty_fixed_array()))

DEFINE_GETTER(EmptyStringConstant, HeapConstant(factory()->empty_string()))

DEFINE_GETTER(FixedArrayMapConstant, HeapConstant(factory()->fixed_array_map()))

DEFINE_GETTER(PropertyArrayMapConstant,
              HeapConstant(factory()->property_array_map()))

DEFINE_GETTER(FixedDoubleArrayMapConstant,
              HeapConstant(factory()->fixed_double_array_map()))

DEFINE_GETTER(HeapNumberMapConstant, HeapConstant(factory()->heap_number_map()))

DEFINE_GETTER(OptimizedOutConstant, HeapConstant(factory()->optimized_out()))

DEFINE_GETTER(StaleRegisterConstant, HeapConstant(factory()->stale_register()))

DEFINE_GETTER(UndefinedConstant, HeapConstant(factory()->undefined_value()))

DEFINE_GETTER(TheHoleConstant, HeapConstant(factory()->the_hole_value()))

DEFINE_GETTER(TrueConstant, HeapConstant(factory()->true_value()))

DEFINE_GETTER(FalseConstant, HeapConstant(factory()->false_value()))

DEFINE_GETTER(NullConstant, HeapConstant(factory()->null_value()))

DEFINE_GETTER(ZeroConstant, NumberConstant(0.0))

DEFINE_GETTER(OneConstant, NumberConstant(1.0))

DEFINE_GETTER(MinusOneConstant, NumberConstant(-1.0))

DEFINE_GETTER(NaNConstant,
              NumberConstant(std::numeric_limits<double>::quiet_NaN()))

DEFINE_GETTER(EmptyStateValues,
              graph()->NewNode(common()->StateValues(0,
                                                     SparseInputMask::Dense())))

DEFINE_GETTER(SingleDeadTypedStateValues,
              graph()->NewNode(common()->TypedStateValues(
                  new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
                      ZoneVector<MachineType>(0, graph()->zone()),
                  SparseInputMask(SparseInputMask::kEndMarker << 1))))

#undef DEFINE_GETTER
#undef GET_CACHED_FIELD

}  // namespace compiler
}  // namespace internal
}  // namespace v8
