// 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(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(PlainPrimitiveToNumberBuiltinConstant,
              HeapConstant(BUILTIN_CODE(isolate(), PlainPrimitiveToNumber)))

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(WeakFixedArrayMapConstant,
              HeapConstant(factory()->weak_fixed_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(MinusZeroConstant, 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(
        graph()->zone()->New<ZoneVector<MachineType>>(0, graph()->zone()),
        SparseInputMask(SparseInputMask::kEndMarker << 1))))

#undef DEFINE_GETTER
#undef GET_CACHED_FIELD

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