// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler/assembler/assembler_base.h"

#include "platform/utils.h"
#include "vm/compiler/assembler/object_pool_builder.h"
#include "vm/compiler/backend/slot.h"
#include "vm/cpu.h"
#include "vm/flags.h"
#include "vm/heap/heap.h"
#include "vm/memory_region.h"
#include "vm/os.h"
#include "vm/zone.h"

namespace dart {

DEFINE_FLAG(bool,
            check_code_pointer,
            false,
            "Verify instructions offset in code object."
            "NOTE: This breaks the profiler.");
#if defined(TARGET_ARCH_ARM)
DEFINE_FLAG(bool, use_far_branches, false, "Enable far branches for ARM.");
#endif

namespace compiler {

AssemblerBase::~AssemblerBase() {}

void AssemblerBase::LoadFromSlot(Register dst,
                                 Register base,
                                 const Slot& slot,
                                 MemoryOrder memory_order) {
  if (!slot.is_tagged()) {
    // The result cannot be a floating point or SIMD value.
    ASSERT(slot.representation() == kUntagged ||
           RepresentationUtils::IsUnboxedInteger(slot.representation()));
    // Since we only have a single destination register, the result value must
    // fit into a register.
    ASSERT(RepresentationUtils::ValueSize(slot.representation()) <=
           compiler::target::kWordSize);
    auto const sz = RepresentationUtils::OperandSize(slot.representation());
    if (slot.has_untagged_instance()) {
      LoadFromOffset(dst, base, slot.offset_in_bytes(), sz);
    } else {
      LoadFieldFromOffset(dst, base, slot.offset_in_bytes(), sz);
    }
  } else if (slot.has_untagged_instance()) {
    // Non-Dart objects do not contain compressed pointers.
    ASSERT(!slot.is_compressed());
    LoadFromOffset(dst, base, slot.offset_in_bytes());
  } else if (!slot.is_guarded_field() && slot.type().ToCid() == kSmiCid) {
    if (slot.is_compressed()) {
      LoadCompressedSmiFieldFromOffset(dst, base, slot.offset_in_bytes());
    } else {
      LoadSmiFieldFromOffset(dst, base, slot.offset_in_bytes());
    }
  } else {
    if (slot.is_compressed()) {
      if (memory_order == kAcquire) {
        LoadAcquireCompressedFieldFromOffset(dst, base, slot.offset_in_bytes());
      } else {
        LoadCompressedFieldFromOffset(dst, base, slot.offset_in_bytes());
      }
    } else {
      if (memory_order == kAcquire) {
        LoadAcquire(dst, FieldAddress(base, slot.offset_in_bytes()));
      } else {
        LoadFieldFromOffset(dst, base, slot.offset_in_bytes());
      }
    }
  }
}

void AssemblerBase::StoreToSlot(Register src,
                                Register base,
                                const Slot& slot,
                                MemoryOrder memory_order,
                                Register scratch) {
  auto const can_be_smi =
      slot.type().CanBeSmi() ? kValueCanBeSmi : kValueIsNotSmi;
  StoreToSlot(src, base, slot, can_be_smi, memory_order, scratch);
}

void AssemblerBase::StoreToSlot(Register src,
                                Register base,
                                const Slot& slot,
                                CanBeSmi can_be_smi,
                                MemoryOrder memory_order,
                                Register scratch) {
  if (!slot.is_tagged() || slot.has_untagged_instance()) {
    // Same as the no barrier case.
    StoreToSlotNoBarrier(src, base, slot, memory_order);
  } else if (slot.is_compressed()) {
    StoreCompressedIntoObjectOffset(base, slot.offset_in_bytes(), src,
                                    can_be_smi, memory_order, scratch);
  } else {
    StoreIntoObjectOffset(base, slot.offset_in_bytes(), src, can_be_smi,
                          memory_order, scratch);
  }
}

void AssemblerBase::StoreToSlotNoBarrier(Register src,
                                         Register base,
                                         const Slot& slot,
                                         MemoryOrder memory_order) {
  if (!slot.is_tagged()) {
    // The stored value cannot be a SIMD value.
    ASSERT(slot.representation() == kUntagged ||
           RepresentationUtils::IsUnboxedFloat(slot.representation()) ||
           RepresentationUtils::IsUnboxedInteger(slot.representation()));
    // Since we only have a single source register, the stored value must
    // fit into a register.
    ASSERT(RepresentationUtils::ValueSize(slot.representation()) <=
           compiler::target::kWordSize);
    auto const sz = RepresentationUtils::OperandSize(slot.representation());
    if (slot.has_untagged_instance()) {
      StoreToOffset(src, base, slot.offset_in_bytes(), sz);
    } else {
      StoreFieldToOffset(src, base, slot.offset_in_bytes(), sz);
    }
  } else if (slot.has_untagged_instance()) {
    // Non-Dart objects do not contain compressed pointers.
    ASSERT(!slot.is_compressed());
    StoreToOffset(src, base, slot.offset_in_bytes());
  } else if (slot.is_compressed()) {
    StoreCompressedIntoObjectOffsetNoBarrier(base, slot.offset_in_bytes(), src,
                                             memory_order);
  } else {
    StoreIntoObjectOffsetNoBarrier(base, slot.offset_in_bytes(), src,
                                   memory_order);
  }
}

void AssemblerBase::LoadFromOffset(Register dst,
                                   Register base,
                                   int32_t offset,
                                   OperandSize sz) {
  Load(dst, Address(base, offset), sz);
}

void AssemblerBase::StoreToOffset(Register src,
                                  Register base,
                                  int32_t offset,
                                  OperandSize sz) {
  Store(src, Address(base, offset), sz);
}

void AssemblerBase::LoadField(Register dst,
                              const FieldAddress& address,
                              OperandSize sz) {
  Load(dst, address, sz);
}
void AssemblerBase::LoadFieldFromOffset(Register dst,
                                        Register base,
                                        int32_t offset,
                                        OperandSize sz) {
  Load(dst, FieldAddress(base, offset), sz);
}

void AssemblerBase::StoreFieldToOffset(Register src,
                                       Register base,
                                       int32_t offset,
                                       OperandSize sz) {
  Store(src, FieldAddress(base, offset), sz);
}

void AssemblerBase::LoadSmiField(Register dst, const FieldAddress& address) {
  LoadSmi(dst, address);
}
void AssemblerBase::LoadSmiFromOffset(Register dst,
                                      Register base,
                                      int32_t offset) {
  LoadSmi(dst, Address(base, offset));
}
void AssemblerBase::LoadSmiFieldFromOffset(Register dst,
                                           Register base,
                                           int32_t offset) {
  LoadSmi(dst, FieldAddress(base, offset));
}

void AssemblerBase::LoadAcquireCompressedFromOffset(Register dst,
                                                    Register base,
                                                    int32_t offset) {
  LoadAcquireCompressed(dst, Address(base, offset));
}
void AssemblerBase::LoadAcquireCompressedFieldFromOffset(Register dst,
                                                         Register base,
                                                         int32_t offset) {
  LoadAcquireCompressed(dst, FieldAddress(base, offset));
}
void AssemblerBase::LoadCompressedField(Register dst,
                                        const FieldAddress& address) {
  LoadCompressed(dst, address);
}
void AssemblerBase::LoadCompressedFromOffset(Register dst,
                                             Register base,
                                             int32_t offset) {
  LoadCompressed(dst, Address(base, offset));
}
void AssemblerBase::LoadCompressedFieldFromOffset(Register dst,
                                                  Register base,
                                                  int32_t offset) {
  LoadCompressed(dst, FieldAddress(base, offset));
}
void AssemblerBase::LoadCompressedSmiField(Register dst,
                                           const FieldAddress& address) {
  LoadCompressedSmi(dst, address);
}
void AssemblerBase::LoadCompressedSmiFromOffset(Register dst,
                                                Register base,
                                                int32_t offset) {
  LoadCompressedSmi(dst, Address(base, offset));
}
void AssemblerBase::LoadCompressedSmiFieldFromOffset(Register dst,
                                                     Register base,
                                                     int32_t offset) {
  LoadCompressedSmi(dst, FieldAddress(base, offset));
}

void AssemblerBase::LoadAcquireFromOffset(Register dst,
                                          Register base,
                                          int32_t offset,
                                          OperandSize size) {
  LoadAcquire(dst, Address(base, offset), size);
}
void AssemblerBase::StoreReleaseToOffset(Register src,
                                         Register base,
                                         int32_t offset,
                                         OperandSize size) {
  StoreRelease(src, Address(base, offset), size);
}

void AssemblerBase::StoreIntoObject(Register object,
                                    const Address& address,
                                    Register value,
                                    CanBeSmi can_be_smi,
                                    MemoryOrder memory_order,
                                    Register scratch,
                                    OperandSize size) {
  // A write barrier should never be applied when writing a reference to an
  // object into itself.
  ASSERT(object != value);
  ASSERT(object != scratch);
  ASSERT(value != scratch);
  if (memory_order == kRelease) {
    StoreRelease(value, address, size);
  } else {
    Store(value, address, size);
  }
  StoreBarrier(object, value, can_be_smi, scratch);
}

void AssemblerBase::StoreIntoObjectNoBarrier(Register object,
                                             const Address& address,
                                             Register value,
                                             MemoryOrder memory_order,
                                             OperandSize size) {
  if (memory_order == kRelease) {
    StoreRelease(value, address, size);
  } else {
    Store(value, address, size);
  }
  DEBUG_ONLY(VerifyStoreNeedsNoWriteBarrier(object, value));
}

void AssemblerBase::StoreIntoObjectOffset(Register object,
                                          int32_t offset,
                                          Register value,
                                          CanBeSmi can_be_smi,
                                          MemoryOrder memory_order,
                                          Register scratch,
                                          OperandSize size) {
  StoreIntoObject(object, FieldAddress(object, offset), value, can_be_smi,
                  memory_order, scratch, size);
}

void AssemblerBase::StoreIntoObjectOffsetNoBarrier(Register object,
                                                   int32_t offset,
                                                   Register value,
                                                   MemoryOrder memory_order,
                                                   OperandSize size) {
  StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value,
                           memory_order, size);
}
void AssemblerBase::StoreObjectIntoObjectOffsetNoBarrier(
    Register object,
    int32_t offset,
    const Object& value,
    MemoryOrder memory_order,
    OperandSize size) {
  StoreObjectIntoObjectNoBarrier(object, FieldAddress(object, offset), value,
                                 memory_order, size);
}

void AssemblerBase::StoreIntoArray(Register object,
                                   Register slot,
                                   Register value,
                                   CanBeSmi can_be_smi,
                                   Register scratch,
                                   OperandSize size) {
  ASSERT(object != scratch);
  ASSERT(value != object);
  ASSERT(value != scratch);
  ASSERT(slot != object);
  ASSERT(slot != value);
  ASSERT(slot != scratch);
  Store(value, Address(slot, 0), size);
  ArrayStoreBarrier(object, slot, value, can_be_smi, scratch);
}

void AssemblerBase::UnrolledMemCopy(Register dst_base,
                                    intptr_t dst_offset,
                                    Register src_base,
                                    intptr_t src_offset,
                                    intptr_t size,
                                    Register temp) {
  intptr_t offset = 0;
  if (target::kWordSize >= 8) {
    while (offset + 8 <= size) {
      LoadFromOffset(temp, src_base, src_offset + offset, kEightBytes);
      StoreToOffset(temp, dst_base, dst_offset + offset, kEightBytes);
      offset += 8;
    }
  }
  while (offset + 4 <= size) {
    LoadFromOffset(temp, src_base, src_offset + offset, kUnsignedFourBytes);
    StoreToOffset(temp, dst_base, dst_offset + offset, kUnsignedFourBytes);
    offset += 4;
  }
  while (offset + 2 <= size) {
    LoadFromOffset(temp, src_base, src_offset + offset, kUnsignedTwoBytes);
    StoreToOffset(temp, dst_base, dst_offset + offset, kUnsignedTwoBytes);
    offset += 2;
  }
  while (offset + 1 <= size) {
    LoadFromOffset(temp, src_base, src_offset + offset, kUnsignedByte);
    StoreToOffset(temp, dst_base, dst_offset + offset, kUnsignedByte);
    offset += 1;
  }
  ASSERT(offset == size);
}

void AssemblerBase::LoadTypeClassId(Register dst, Register src) {
  if (dst != src) {
    EnsureHasClassIdInDEBUG(kTypeCid, src, dst);
  } else {
#if !defined(TARGET_ARCH_IA32)
    EnsureHasClassIdInDEBUG(kTypeCid, src, TMP);
#else
    // Skip check on IA32 since we don't have TMP.
#endif
  }
  LoadFromSlot(dst, src, Slot::AbstractType_flags());
  LsrImmediate(dst, compiler::target::UntaggedType::kTypeClassIdShift);
}

void AssemblerBase::LoadAbstractTypeNullability(Register dst, Register type) {
  LoadFromSlot(dst, type, Slot::AbstractType_flags());
  AndImmediate(dst, compiler::target::UntaggedAbstractType::kNullabilityMask);
}

void AssemblerBase::CompareAbstractTypeNullabilityWith(Register type,
                                                       int8_t value,
                                                       Register scratch) {
  LoadAbstractTypeNullability(scratch, type);
  CompareImmediate(scratch, value);
}

intptr_t AssemblerBase::InsertAlignedRelocation(BSS::Relocation reloc) {
  // We cannot put a relocation at the very start (it's not a valid
  // instruction)!
  ASSERT(CodeSize() != 0);

  // Align to a target word boundary.
  const intptr_t offset =
      Utils::RoundUp(CodeSize(), compiler::target::kWordSize);

  while (CodeSize() < offset) {
    Breakpoint();
  }
  ASSERT(CodeSize() == offset);

  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
  buffer_.Emit<compiler::target::word>(BSS::RelocationIndex(reloc) *
                                       compiler::target::kWordSize);

  ASSERT(CodeSize() == (offset + compiler::target::kWordSize));

  return offset;
}

void AssemblerBase::MsanUnpoison(Register base, intptr_t length_in_bytes) {
  Comment("MsanUnpoison base %s length_in_bytes %" Pd,
          RegisterNames::RegisterName(base), length_in_bytes);
  LeafRuntimeScope rt(static_cast<Assembler*>(this), /*frame_size=*/0,
                      /*preserve_registers=*/true);
  MoveRegister(CallingConventions::ArgumentRegisters[0], base);
  LoadImmediate(CallingConventions::ArgumentRegisters[1], length_in_bytes);
  rt.Call(kMsanUnpoisonRuntimeEntry, /*argument_count=*/2);
}

void AssemblerBase::MsanUnpoison(Register base, Register length_in_bytes) {
  Comment("MsanUnpoison base %s length_in_bytes %s",
          RegisterNames::RegisterName(base),
          RegisterNames::RegisterName(length_in_bytes));
  LeafRuntimeScope rt(static_cast<Assembler*>(this), /*frame_size=*/0,
                      /*preserve_registers=*/true);
  const Register a0 = CallingConventions::ArgumentRegisters[0];
  const Register a1 = CallingConventions::ArgumentRegisters[1];
  if (length_in_bytes == a0) {
    if (base == a1) {
      MoveRegister(TMP, length_in_bytes);
      MoveRegister(a0, base);
      MoveRegister(a1, TMP);
    } else {
      MoveRegister(a1, length_in_bytes);
      MoveRegister(a0, base);
    }
  } else {
    MoveRegister(a0, base);
    MoveRegister(a1, length_in_bytes);
  }
  rt.Call(kMsanUnpoisonRuntimeEntry, /*argument_count=*/2);
}

#if defined(DEBUG)
static void InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
  ASSERT(Utils::IsAligned(data, 4));
  ASSERT(Utils::IsAligned(length, 4));
  const uword end = data + length;
  while (data < end) {
    *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction;
    data += 4;
  }
#else
  memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length);
#endif
}
#endif

static uword NewContents(intptr_t capacity) {
  Zone* zone = Thread::Current()->zone();
  uword result = zone->AllocUnsafe(capacity);
#if defined(DEBUG)
  // Initialize the buffer with kBreakPointInstruction to force a break
  // point if we ever execute an uninitialized part of the code buffer.
  InitializeMemoryWithBreakpoints(result, capacity);
#endif
  return result;
}

#if defined(DEBUG)
AssemblerBuffer::EnsureCapacity::EnsureCapacity(AssemblerBuffer* buffer) {
  if (buffer->cursor() >= buffer->limit()) buffer->ExtendCapacity();
  // In debug mode, we save the assembler buffer along with the gap
  // size before we start emitting to the buffer. This allows us to
  // check that any single generated instruction doesn't overflow the
  // limit implied by the minimum gap size.
  buffer_ = buffer;
  gap_ = ComputeGap();
  // Make sure that extending the capacity leaves a big enough gap
  // for any kind of instruction.
  ASSERT(gap_ >= kMinimumGap);
  // Mark the buffer as having ensured the capacity.
  ASSERT(!buffer->HasEnsuredCapacity());  // Cannot nest.
  buffer->has_ensured_capacity_ = true;
}

AssemblerBuffer::EnsureCapacity::~EnsureCapacity() {
  // Unmark the buffer, so we cannot emit after this.
  buffer_->has_ensured_capacity_ = false;
  // Make sure the generated instruction doesn't take up more
  // space than the minimum gap.
  intptr_t delta = gap_ - ComputeGap();
  ASSERT(delta <= kMinimumGap);
}
#endif

AssemblerBuffer::AssemblerBuffer()
    : pointer_offsets_(new ZoneGrowableArray<intptr_t>(16)) {
  const intptr_t kInitialBufferCapacity = 4 * KB;
  contents_ = NewContents(kInitialBufferCapacity);
  cursor_ = contents_;
  limit_ = ComputeLimit(contents_, kInitialBufferCapacity);
  fixup_ = nullptr;
#if defined(DEBUG)
  has_ensured_capacity_ = false;
  fixups_processed_ = false;
#endif

  // Verify internal state.
  ASSERT(Capacity() == kInitialBufferCapacity);
  ASSERT(Size() == 0);
}

AssemblerBuffer::~AssemblerBuffer() {}

void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) {
  AssemblerFixup* fixup = fixup_;
  while (fixup != nullptr) {
    fixup->Process(region, fixup->position());
    fixup = fixup->previous();
  }
}

void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) {
  // Copy the instructions from the buffer.
  MemoryRegion from(reinterpret_cast<void*>(contents()), Size());
  instructions.CopyFrom(0, from);

  // Process fixups in the instructions.
  ProcessFixups(instructions);
#if defined(DEBUG)
  fixups_processed_ = true;
#endif
}

void AssemblerBuffer::ExtendCapacity() {
  intptr_t old_size = Size();
  intptr_t old_capacity = Capacity();
  intptr_t new_capacity =
      Utils::Minimum(old_capacity * 2, old_capacity + 1 * MB);
  if (new_capacity < old_capacity) {
    FATAL("Unexpected overflow in AssemblerBuffer::ExtendCapacity");
  }

  // Allocate the new data area and copy contents of the old one to it.
  uword new_contents = NewContents(new_capacity);
  memmove(reinterpret_cast<void*>(new_contents),
          reinterpret_cast<void*>(contents_), old_size);

  // Compute the relocation delta and switch to the new contents area.
  intptr_t delta = new_contents - contents_;
  contents_ = new_contents;

  // Update the cursor and recompute the limit.
  cursor_ += delta;
  limit_ = ComputeLimit(new_contents, new_capacity);

  // Verify internal state.
  ASSERT(Capacity() == new_capacity);
  ASSERT(Size() == old_size);
}

class PatchCodeWithHandle : public AssemblerFixup {
 public:
  PatchCodeWithHandle(ZoneGrowableArray<intptr_t>* pointer_offsets,
                      const Object& object)
      : pointer_offsets_(pointer_offsets), object_(object) {}

  void Process(const MemoryRegion& region, intptr_t position) {
    // Patch the handle into the code. Once the instructions are installed into
    // a raw code object and the pointer offsets are setup, the handle is
    // resolved.
    region.StoreUnaligned<const Object*>(position, &object_);
    pointer_offsets_->Add(position);
  }

  virtual bool IsPointerOffset() const { return true; }

 private:
  ZoneGrowableArray<intptr_t>* pointer_offsets_;
  const Object& object_;
};

intptr_t AssemblerBuffer::CountPointerOffsets() const {
  intptr_t count = 0;
  AssemblerFixup* current = fixup_;
  while (current != nullptr) {
    if (current->IsPointerOffset()) ++count;
    current = current->previous_;
  }
  return count;
}

#if defined(TARGET_ARCH_IA32)
void AssemblerBuffer::EmitObject(const Object& object) {
  // Since we are going to store the handle as part of the fixup information
  // the handle needs to be a zone handle.
  DEBUG_ASSERT(IsNotTemporaryScopedHandle(object));
  ASSERT(IsInOldSpace(object));
  EmitFixup(new PatchCodeWithHandle(pointer_offsets_, object));
  cursor_ += target::kWordSize;  // Reserve space for pointer.
}
#endif

// Shared macros are implemented here.
void AssemblerBase::Unimplemented(const char* message) {
  const char* format = "Unimplemented: %s";
  const intptr_t len = Utils::SNPrint(nullptr, 0, format, message);
  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
  Utils::SNPrint(buffer, len + 1, format, message);
  Stop(buffer);
}

void AssemblerBase::Untested(const char* message) {
  const char* format = "Untested: %s";
  const intptr_t len = Utils::SNPrint(nullptr, 0, format, message);
  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
  Utils::SNPrint(buffer, len + 1, format, message);
  Stop(buffer);
}

void AssemblerBase::Unreachable(const char* message) {
  const char* format = "Unreachable: %s";
  const intptr_t len = Utils::SNPrint(nullptr, 0, format, message);
  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
  Utils::SNPrint(buffer, len + 1, format, message);
  Stop(buffer);
}

void AssemblerBase::Comment(const char* format, ...) {
  if (EmittingComments()) {
    char buffer[1024];

    va_list args;
    va_start(args, format);
    Utils::VSNPrint(buffer, sizeof(buffer), format, args);
    va_end(args);

    comments_.Add(
        new CodeComment(buffer_.GetPosition(), AllocateString(buffer)));
  }
}

bool AssemblerBase::EmittingComments() {
  return FLAG_code_comments || FLAG_disassemble || FLAG_disassemble_optimized ||
         FLAG_disassemble_stubs;
}

void AssemblerBase::Stop(const char* message) {
  Comment("Stop: %s", message);
  Breakpoint();
}

uword ObjIndexPair::Hash(Key key) {
  switch (key.type()) {
    case ObjectPoolBuilderEntry::kImmediate128:
      return key.imm128_.int_storage[0] ^ key.imm128_.int_storage[1] ^
             key.imm128_.int_storage[2] ^ key.imm128_.int_storage[3];

#if defined(TARGET_ARCH_IS_32_BIT)
    case ObjectPoolBuilderEntry::kImmediate64:
      return key.imm64_;
#endif
    case ObjectPoolBuilderEntry::kImmediate:
    case ObjectPoolBuilderEntry::kNativeFunction:
      return key.imm_;
    case ObjectPoolBuilderEntry::kTaggedObject:
      return ObjectHash(*key.obj_);
  }

  UNREACHABLE();
}

void ObjectPoolBuilder::Reset() {
  // Null out the handles we've accumulated.
  for (intptr_t i = 0; i < object_pool_.length(); ++i) {
    if (object_pool_[i].type() == ObjectPoolBuilderEntry::kTaggedObject) {
      SetToNull(const_cast<Object*>(object_pool_[i].obj_));
      SetToNull(const_cast<Object*>(object_pool_[i].equivalence_));
    }
  }

  object_pool_.Clear();
  object_pool_index_table_.Clear();
}

intptr_t ObjectPoolBuilder::AddObject(
    const Object& obj,
    ObjectPoolBuilderEntry::Patchability patchable,
    ObjectPoolBuilderEntry::SnapshotBehavior snapshot_behavior) {
  DEBUG_ASSERT(IsNotTemporaryScopedHandle(obj));
  return AddObject(ObjectPoolBuilderEntry(&obj, patchable, snapshot_behavior));
}

intptr_t ObjectPoolBuilder::AddImmediate(
    uword imm,
    ObjectPoolBuilderEntry::Patchability patchable,
    ObjectPoolBuilderEntry::SnapshotBehavior snapshotability) {
  return AddObject(ObjectPoolBuilderEntry(
      imm, ObjectPoolBuilderEntry::kImmediate, patchable, snapshotability));
}

intptr_t ObjectPoolBuilder::AddImmediate64(uint64_t imm) {
#if defined(TARGET_ARCH_IS_32_BIT)
  return AddObject(
      ObjectPoolBuilderEntry(imm, ObjectPoolBuilderEntry::kImmediate64,
                             ObjectPoolBuilderEntry::kNotPatchable));
#else
  return AddImmediate(imm);
#endif
}

intptr_t ObjectPoolBuilder::AddImmediate128(simd128_value_t imm) {
  return AddObject(
      ObjectPoolBuilderEntry(imm, ObjectPoolBuilderEntry::kImmediate128,
                             ObjectPoolBuilderEntry::kNotPatchable));
}

intptr_t ObjectPoolBuilder::AddObject(ObjectPoolBuilderEntry entry) {
  DEBUG_ASSERT((entry.type() != ObjectPoolBuilderEntry::kTaggedObject) ||
               (IsNotTemporaryScopedHandle(*entry.obj_) &&
                (entry.equivalence_ == nullptr ||
                 IsNotTemporaryScopedHandle(*entry.equivalence_))));

  if (entry.type() == ObjectPoolBuilderEntry::kTaggedObject) {
    // If the owner of the object pool wrapper specified a specific zone we
    // should use we'll do so.
    if (zone_ != nullptr) {
      entry.obj_ = &NewZoneHandle(zone_, *entry.obj_);
      if (entry.equivalence_ != nullptr) {
        entry.equivalence_ = &NewZoneHandle(zone_, *entry.equivalence_);
      }
    }
  }

#if defined(TARGET_ARCH_IS_32_BIT)
  if (entry.type() == ObjectPoolBuilderEntry::kImmediate64) {
    ASSERT(entry.patchable() == ObjectPoolBuilderEntry::kNotPatchable);
    uint64_t imm = entry.imm64_;
    intptr_t idx = AddImmediate(Utils::Low32Bits(imm));
    AddImmediate(Utils::High32Bits(imm));
    object_pool_index_table_.Insert(ObjIndexPair(entry, idx));
    return idx;
  }
  if (entry.type() == ObjectPoolBuilderEntry::kImmediate128) {
    ASSERT(entry.patchable() == ObjectPoolBuilderEntry::kNotPatchable);
    intptr_t idx = AddImmediate(entry.imm128_.int_storage[0]);
    AddImmediate(entry.imm128_.int_storage[1]);
    AddImmediate(entry.imm128_.int_storage[2]);
    AddImmediate(entry.imm128_.int_storage[3]);
    object_pool_index_table_.Insert(ObjIndexPair(entry, idx));
    return idx;
  }
#else
  if (entry.type() == ObjectPoolBuilderEntry::kImmediate128) {
    ASSERT(entry.patchable() == ObjectPoolBuilderEntry::kNotPatchable);
    uword lo64 =
        (static_cast<uword>(entry.imm128_.int_storage[0]) & 0xffffffff) |
        (static_cast<uword>(entry.imm128_.int_storage[1]) << 32);
    uword hi64 =
        (static_cast<uword>(entry.imm128_.int_storage[2]) & 0xffffffff) |
        (static_cast<uword>(entry.imm128_.int_storage[3]) << 32);
    intptr_t idx = AddImmediate(lo64);
    AddImmediate(hi64);
    object_pool_index_table_.Insert(ObjIndexPair(entry, idx));
    return idx;
  }
#endif

  const intptr_t idx = base_index_ + object_pool_.length();
  object_pool_.Add(entry);
  if (entry.patchable() == ObjectPoolBuilderEntry::kNotPatchable) {
    // The object isn't patchable. Record the index for fast lookup.
    object_pool_index_table_.Insert(ObjIndexPair(entry, idx));
  }
  return idx;
}

intptr_t ObjectPoolBuilder::FindObject(ObjectPoolBuilderEntry entry) {
  // If the object is not patchable, check if we've already got it in the
  // object pool.
  if (entry.patchable() == ObjectPoolBuilderEntry::kNotPatchable) {
    // First check in the parent pool if we have one.
    if (parent_ != nullptr) {
      const intptr_t idx = parent_->object_pool_index_table_.LookupValue(entry);
      if (idx != ObjIndexPair::kNoIndex) {
        used_from_parent_.Add(idx);
        return idx;
      }
    }

    const intptr_t idx = object_pool_index_table_.LookupValue(entry);
    if (idx != ObjIndexPair::kNoIndex) {
      return idx;
    }
  }
  return AddObject(entry);
}

intptr_t ObjectPoolBuilder::FindObject(
    const Object& obj,
    ObjectPoolBuilderEntry::Patchability patchable,
    ObjectPoolBuilderEntry::SnapshotBehavior snapshot_behavior) {
  return FindObject(ObjectPoolBuilderEntry(&obj, patchable, snapshot_behavior));
}

intptr_t ObjectPoolBuilder::FindObject(const Object& obj,
                                       const Object& equivalence) {
  return FindObject(ObjectPoolBuilderEntry(
      &obj, &equivalence, ObjectPoolBuilderEntry::kNotPatchable));
}

intptr_t ObjectPoolBuilder::FindImmediate(uword imm) {
  return FindObject(
      ObjectPoolBuilderEntry(imm, ObjectPoolBuilderEntry::kImmediate,
                             ObjectPoolBuilderEntry::kNotPatchable));
}

intptr_t ObjectPoolBuilder::FindImmediate64(uint64_t imm) {
#if defined(TARGET_ARCH_IS_32_BIT)
  return FindObject(
      ObjectPoolBuilderEntry(imm, ObjectPoolBuilderEntry::kImmediate64,
                             ObjectPoolBuilderEntry::kNotPatchable));
#else
  return FindImmediate(imm);
#endif
}

intptr_t ObjectPoolBuilder::FindImmediate128(simd128_value_t imm) {
  return FindObject(
      ObjectPoolBuilderEntry(imm, ObjectPoolBuilderEntry::kImmediate128,
                             ObjectPoolBuilderEntry::kNotPatchable));
}

intptr_t ObjectPoolBuilder::FindNativeFunction(
    const ExternalLabel* label,
    ObjectPoolBuilderEntry::Patchability patchable) {
  return FindObject(ObjectPoolBuilderEntry(
      label->address(), ObjectPoolBuilderEntry::kNativeFunction, patchable));
}

bool ObjectPoolBuilder::TryCommitToParent() {
  ASSERT(parent_ != nullptr);
  if (parent_->CurrentLength() != base_index_) {
    return false;
  }
  for (intptr_t i = 0; i < object_pool_.length(); i++) {
    intptr_t idx = parent_->AddObject(object_pool_[i]);
    ASSERT(idx == (base_index_ + i));
  }
  return true;
}

}  // namespace compiler

}  // namespace dart
