// Copyright 2015 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/fast-accessor-assembler.h"

#include "src/base/logging.h"
#include "src/code-stub-assembler.h"
#include "src/code-stubs.h"  // For CallApiCallbackStub.
#include "src/handles-inl.h"
#include "src/objects.h"  // For FAA::LoadInternalField impl.

using v8::internal::CodeStubAssembler;
using v8::internal::compiler::Node;

namespace v8 {
namespace internal {

FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate)
    : zone_(isolate->allocator(), ZONE_NAME),
      isolate_(isolate),
      assembler_(new CodeStubAssembler(isolate, zone(), 1,
                                       Code::ComputeFlags(Code::STUB),
                                       "FastAccessorAssembler")),
      state_(kBuilding) {}

FastAccessorAssembler::~FastAccessorAssembler() { Clear(); }

FastAccessorAssembler::ValueId FastAccessorAssembler::IntegerConstant(
    int const_value) {
  CHECK_EQ(kBuilding, state_);
  return FromRaw(assembler_->NumberConstant(const_value));
}

FastAccessorAssembler::ValueId FastAccessorAssembler::GetReceiver() {
  CHECK_EQ(kBuilding, state_);

  // For JS functions, the receiver is parameter 0.
  return FromRaw(assembler_->Parameter(0));
}

FastAccessorAssembler::ValueId FastAccessorAssembler::LoadInternalField(
    ValueId value, int field_no) {
  CHECK_EQ(kBuilding, state_);

  CodeStubAssembler::Variable result(assembler_.get(),
                                     MachineRepresentation::kTagged);
  LabelId is_not_jsobject = MakeLabel();
  CodeStubAssembler::Label merge(assembler_.get(), &result);

  CheckIsJSObjectOrJump(value, is_not_jsobject);

  Node* internal_field = assembler_->LoadObjectField(
      FromId(value), JSObject::kHeaderSize + kPointerSize * field_no,
      MachineType::Pointer());

  result.Bind(internal_field);
  assembler_->Goto(&merge);

  // Return null, mimicking the C++ counterpart.
  SetLabel(is_not_jsobject);
  result.Bind(assembler_->NullConstant());
  assembler_->Goto(&merge);

  // Return.
  assembler_->Bind(&merge);
  return FromRaw(result.value());
}

FastAccessorAssembler::ValueId
FastAccessorAssembler::LoadInternalFieldUnchecked(ValueId value, int field_no) {
  CHECK_EQ(kBuilding, state_);

  // Defensive debug checks.
  if (FLAG_debug_code) {
    LabelId is_jsobject = MakeLabel();
    LabelId is_not_jsobject = MakeLabel();
    CheckIsJSObjectOrJump(value, is_not_jsobject);
    assembler_->Goto(FromId(is_jsobject));

    SetLabel(is_not_jsobject);
    assembler_->DebugBreak();
    assembler_->Goto(FromId(is_jsobject));

    SetLabel(is_jsobject);
  }

  Node* result = assembler_->LoadObjectField(
      FromId(value), JSObject::kHeaderSize + kPointerSize * field_no,
      MachineType::Pointer());

  return FromRaw(result);
}

FastAccessorAssembler::ValueId FastAccessorAssembler::LoadValue(ValueId value,
                                                                int offset) {
  CHECK_EQ(kBuilding, state_);
  return FromRaw(assembler_->LoadBufferObject(FromId(value), offset,
                                              MachineType::IntPtr()));
}

FastAccessorAssembler::ValueId FastAccessorAssembler::LoadObject(ValueId value,
                                                                 int offset) {
  CHECK_EQ(kBuilding, state_);
  return FromRaw(assembler_->LoadBufferObject(
      assembler_->LoadBufferObject(FromId(value), offset,
                                   MachineType::Pointer()),
      0, MachineType::AnyTagged()));
}

FastAccessorAssembler::ValueId FastAccessorAssembler::ToSmi(ValueId value) {
  CHECK_EQ(kBuilding, state_);
  return FromRaw(assembler_->SmiTag(FromId(value)));
}

void FastAccessorAssembler::ReturnValue(ValueId value) {
  CHECK_EQ(kBuilding, state_);
  assembler_->Return(FromId(value));
}

void FastAccessorAssembler::CheckFlagSetOrReturnNull(ValueId value, int mask) {
  CHECK_EQ(kBuilding, state_);
  CodeStubAssembler::Label pass(assembler_.get());
  CodeStubAssembler::Label fail(assembler_.get());
  assembler_->Branch(
      assembler_->Word32Equal(
          assembler_->Word32And(FromId(value), assembler_->Int32Constant(mask)),
          assembler_->Int32Constant(0)),
      &fail, &pass);
  assembler_->Bind(&fail);
  assembler_->Return(assembler_->NullConstant());
  assembler_->Bind(&pass);
}

void FastAccessorAssembler::CheckNotZeroOrReturnNull(ValueId value) {
  CHECK_EQ(kBuilding, state_);
  CodeStubAssembler::Label is_null(assembler_.get());
  CodeStubAssembler::Label not_null(assembler_.get());
  assembler_->Branch(
      assembler_->WordEqual(FromId(value), assembler_->IntPtrConstant(0)),
      &is_null, &not_null);
  assembler_->Bind(&is_null);
  assembler_->Return(assembler_->NullConstant());
  assembler_->Bind(&not_null);
}

FastAccessorAssembler::LabelId FastAccessorAssembler::MakeLabel() {
  CHECK_EQ(kBuilding, state_);
  return FromRaw(new CodeStubAssembler::Label(assembler_.get()));
}

void FastAccessorAssembler::SetLabel(LabelId label_id) {
  CHECK_EQ(kBuilding, state_);
  assembler_->Bind(FromId(label_id));
}

void FastAccessorAssembler::Goto(LabelId label_id) {
  CHECK_EQ(kBuilding, state_);
  assembler_->Goto(FromId(label_id));
}

void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id,
                                               LabelId label_id) {
  CHECK_EQ(kBuilding, state_);
  CodeStubAssembler::Label pass(assembler_.get());
  assembler_->Branch(
      assembler_->WordEqual(FromId(value_id), assembler_->IntPtrConstant(0)),
      FromId(label_id), &pass);
  assembler_->Bind(&pass);
}

FastAccessorAssembler::ValueId FastAccessorAssembler::Call(
    FunctionCallback callback_function, ValueId arg) {
  CHECK_EQ(kBuilding, state_);

  // Wrap the FunctionCallback in an ExternalReference.
  ApiFunction callback_api_function(FUNCTION_ADDR(callback_function));
  ExternalReference callback(&callback_api_function,
                             ExternalReference::DIRECT_API_CALL, isolate());

  // Create & call API callback via stub.
  const int kJSParameterCount = 1;
  CallApiCallbackStub stub(isolate(), kJSParameterCount, true, true);
  CallInterfaceDescriptor descriptor = stub.GetCallInterfaceDescriptor();
  DCHECK_EQ(4, descriptor.GetParameterCount());
  DCHECK_EQ(0, descriptor.GetStackParameterCount());
  // TODO(vogelheim): There is currently no clean way to retrieve the context
  //     parameter for a stub and the implementation details are hidden in
  //     compiler/*. The context_paramter is computed as:
  //       Linkage::GetJSCallContextParamIndex(descriptor->JSParameterCount())
  const int kContextParameter = 3;
  Node* context = assembler_->Parameter(kContextParameter);
  Node* target = assembler_->HeapConstant(stub.GetCode());

  int param_count = descriptor.GetParameterCount();
  Node** args = zone()->NewArray<Node*>(param_count + 1 + kJSParameterCount);
  // Stub/register parameters:
  args[0] = assembler_->UndefinedConstant();  // callee (there's no JSFunction)
  args[1] = assembler_->UndefinedConstant();  // call_data (undefined)
  args[2] = assembler_->Parameter(0);  // receiver (same as holder in this case)
  args[3] = assembler_->ExternalConstant(callback);  // API callback function

  // JS arguments, on stack:
  args[4] = FromId(arg);

  // Context.
  args[5] = context;

  Node* call =
      assembler_->CallStubN(descriptor, kJSParameterCount, target, args);

  return FromRaw(call);
}

void FastAccessorAssembler::CheckIsJSObjectOrJump(ValueId value_id,
                                                  LabelId label_id) {
  CHECK_EQ(kBuilding, state_);

  // Determine the 'value' object's instance type.
  Node* object_map = assembler_->LoadObjectField(
      FromId(value_id), Internals::kHeapObjectMapOffset,
      MachineType::Pointer());

  Node* instance_type = assembler_->WordAnd(
      assembler_->LoadObjectField(object_map,
                                  Internals::kMapInstanceTypeAndBitFieldOffset,
                                  MachineType::Uint16()),
      assembler_->IntPtrConstant(0xff));

  CodeStubAssembler::Label is_jsobject(assembler_.get());

  // Check whether we have a proper JSObject.
  assembler_->GotoIf(
      assembler_->WordEqual(
          instance_type, assembler_->IntPtrConstant(Internals::kJSObjectType)),
      &is_jsobject);

  // JSApiObject?.
  assembler_->GotoUnless(
      assembler_->WordEqual(instance_type, assembler_->IntPtrConstant(
                                               Internals::kJSApiObjectType)),
      FromId(label_id));

  // Continue.
  assembler_->Goto(&is_jsobject);
  assembler_->Bind(&is_jsobject);
}

MaybeHandle<Code> FastAccessorAssembler::Build() {
  CHECK_EQ(kBuilding, state_);
  Handle<Code> code = assembler_->GenerateCode();
  state_ = !code.is_null() ? kBuilt : kError;
  Clear();
  return code;
}

FastAccessorAssembler::ValueId FastAccessorAssembler::FromRaw(Node* node) {
  nodes_.push_back(node);
  ValueId value = {nodes_.size() - 1};
  return value;
}

FastAccessorAssembler::LabelId FastAccessorAssembler::FromRaw(
    CodeStubAssembler::Label* label) {
  labels_.push_back(label);
  LabelId label_id = {labels_.size() - 1};
  return label_id;
}

Node* FastAccessorAssembler::FromId(ValueId value) const {
  CHECK_LT(value.value_id, nodes_.size());
  CHECK_NOT_NULL(nodes_.at(value.value_id));
  return nodes_.at(value.value_id);
}

CodeStubAssembler::Label* FastAccessorAssembler::FromId(LabelId label) const {
  CHECK_LT(label.label_id, labels_.size());
  CHECK_NOT_NULL(labels_.at(label.label_id));
  return labels_.at(label.label_id);
}

void FastAccessorAssembler::Clear() {
  for (auto label : labels_) {
    delete label;
  }
  nodes_.clear();
  labels_.clear();
}

}  // namespace internal
}  // namespace v8
