// 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/globals.h"  // Needed here to get TARGET_ARCH_X64.
#if defined(TARGET_ARCH_X64)

#include "vm/assembler.h"
#include "vm/code_patcher.h"
#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/instructions.h"
#include "vm/object.h"
#include "vm/raw_object.h"

namespace dart {

// The expected pattern of a Dart unoptimized call (static and instance):
//  00: 49 8b 9f imm32  mov RBX, [PP + off]
//  07: 4d 8b 9f imm32  mov R11, [PP + off]
//  14: 41 ff d3        call R11
//  17 <- return address
class UnoptimizedCall : public ValueObject {
 public:
  UnoptimizedCall(uword return_address, const Code& code)
      : start_(return_address - kCallPatternSize),
        object_pool_(Array::Handle(code.ObjectPool())) {
    ASSERT(IsValid(return_address));
    ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
  }

  static const int kCallPatternSize = 17;

  static bool IsValid(uword return_address) {
    uint8_t* code_bytes =
        reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
    return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) &&
           (code_bytes[2] == 0x9F) &&
           (code_bytes[7] == 0x4D) && (code_bytes[8] == 0x8B) &&
           (code_bytes[9] == 0x9F) &&
           (code_bytes[14] == 0x41) && (code_bytes[15] == 0xFF) &&
           (code_bytes[16] == 0xD3);
  }

  RawObject* ic_data() const {
    intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
    return object_pool_.At(index);
  }

  uword target() const {
    intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
    return reinterpret_cast<uword>(object_pool_.At(index));
  }

  void set_target(uword target) const {
    intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
    const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
    object_pool_.SetAt(index, smi);
    // No need to flush the instruction cache, since the code is not modified.
  }

 private:
  uword start_;
  const Array& object_pool_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
};


class InstanceCall : public UnoptimizedCall {
 public:
  InstanceCall(uword return_address, const Code& code)
      : UnoptimizedCall(return_address, code) {
#if defined(DEBUG)
    ICData& test_ic_data = ICData::Handle();
    test_ic_data ^= ic_data();
    ASSERT(test_ic_data.num_args_tested() > 0);
#endif  // DEBUG
  }

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
};


class UnoptimizedStaticCall : public UnoptimizedCall {
 public:
  UnoptimizedStaticCall(uword return_address, const Code& code)
      : UnoptimizedCall(return_address, code) {
#if defined(DEBUG)
    ICData& test_ic_data = ICData::Handle();
    test_ic_data ^= ic_data();
    ASSERT(test_ic_data.num_args_tested() >= 0);
#endif  // DEBUG
  }

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
};


// The expected pattern of a dart static call:
//  00 mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
//  11: 4d 8b 9f imm32  mov R11, [PP + off]
//  16: call R11  (3 bytes)
//  <- return address
class StaticCall : public ValueObject {
 public:
  explicit StaticCall(uword return_address, const Code& code)
      : start_(return_address - kCallPatternSize),
        object_pool_(Array::Handle(code.ObjectPool())) {
    ASSERT(IsValid(return_address));
    ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
  }

  static const int kCallPatternSize = 10;

  static bool IsValid(uword return_address) {
    uint8_t* code_bytes =
        reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
    return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) &&
           (code_bytes[2] == 0x9F) &&
           (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
           (code_bytes[9] == 0xD3);
  }

  uword target() const {
    intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
    return reinterpret_cast<uword>(object_pool_.At(index));
  }

  void set_target(uword target) const {
    intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
    const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
    object_pool_.SetAt(index, smi);
    // No need to flush the instruction cache, since the code is not modified.
  }

 private:
  uword start_;
  const Array& object_pool_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
};


// The expected pattern of a call where the target is loaded from
// the object pool:
//  00: 4d 8b 9f imm32  mov R11, [PP + off]
//  07: 41 ff d3        call R11
//  10 <- return address
class PoolPointerCall : public ValueObject {
 public:
  explicit PoolPointerCall(uword return_address)
      : start_(return_address - kCallPatternSize) {
    ASSERT(IsValid(return_address));
  }

  static bool IsValid(uword return_address) {
    uint8_t* code_bytes =
        reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
    return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) &&
           (code_bytes[2] == 0x9F) &&
           (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
           (code_bytes[9] == 0xD3);
  }

  int32_t pp_offset() const {
    return *reinterpret_cast<int32_t*>(start_ + 3);
  }

  void set_pp_offset(int32_t offset) const {
    *reinterpret_cast<int32_t*>(start_ + 3) = offset;
    CPU::FlushICache(start_, kCallPatternSize);
  }

 private:
  static const int kCallPatternSize = 7 + 3;
  uword start_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
};


// The expected code pattern of a Dart closure call:
//  00: 49 ba imm64     mov R10, immediate 2      ; 10 bytes
//  10: 4d 8b 9f imm32  mov R11, [PP + off]
//  17: 41 ff d3        call R11                  ; 3 bytes
//  20: <- return_address
class ClosureCall : public ValueObject {
 public:
  explicit ClosureCall(uword return_address)
      : start_(return_address - kCallPatternSize) {
    ASSERT(IsValid(return_address));
  }

  static bool IsValid(uword return_address) {
    uint8_t* code_bytes =
        reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
    return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
           (code_bytes[10] == 0x4D) && (code_bytes[11] == 0x8B) &&
           (code_bytes[12] == 0x9F) &&
           (code_bytes[17] == 0x41) && (code_bytes[18] == 0xFF) &&
           (code_bytes[19] == 0xD3);
  }

  RawArray* arguments_descriptor() const {
    return *reinterpret_cast<RawArray**>(start_ + 2);
  }

 private:
  static const int kCallPatternSize = 10 + 7 + 3;
  uword start_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
};


RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
                                           const Code& code) {
  ASSERT(code.ContainsInstructionAt(return_address));
  ClosureCall call(return_address);
  return call.arguments_descriptor();
}


uword CodePatcher::GetStaticCallTargetAt(uword return_address,
                                         const Code& code) {
  ASSERT(code.ContainsInstructionAt(return_address));
  StaticCall call(return_address, code);
  return call.target();
}


void CodePatcher::PatchStaticCallAt(uword return_address,
                                    const Code& code,
                                    uword new_target) {
  ASSERT(code.ContainsInstructionAt(return_address));
  StaticCall call(return_address, code);
  call.set_target(new_target);
}


int32_t CodePatcher::GetPoolOffsetAt(uword return_address) {
  PoolPointerCall call(return_address);
  return call.pp_offset();
}


void CodePatcher::SetPoolOffsetAt(uword return_address, int32_t offset) {
  PoolPointerCall call(return_address);
  call.set_pp_offset(offset);
}


void CodePatcher::PatchInstanceCallAt(uword return_address,
                                      const Code& code,
                                      uword new_target) {
  ASSERT(code.ContainsInstructionAt(return_address));
  InstanceCall call(return_address, code);
  call.set_target(new_target);
}


uword CodePatcher::GetInstanceCallAt(uword return_address,
                                     const Code& code,
                                     ICData* ic_data) {
  ASSERT(code.ContainsInstructionAt(return_address));
  InstanceCall call(return_address, code);
  if (ic_data != NULL) {
    *ic_data ^= call.ic_data();
  }
  return call.target();
}


intptr_t CodePatcher::InstanceCallSizeInBytes() {
  return InstanceCall::kCallPatternSize;
}


void CodePatcher::InsertCallAt(uword start, uword target) {
  // The inserted call should not overlap the lazy deopt jump code.
  ASSERT(start + ShortCallPattern::InstructionLength() <= target);
  *reinterpret_cast<uint8_t*>(start) = 0xE8;
  ShortCallPattern call(start);
  call.SetTargetAddress(target);
  CPU::FlushICache(start, ShortCallPattern::InstructionLength());
}


RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
    uword return_address, const Code& code, ICData* ic_data_result) {
  ASSERT(code.ContainsInstructionAt(return_address));
  UnoptimizedStaticCall static_call(return_address, code);
  ICData& ic_data = ICData::Handle();
  ic_data ^= static_call.ic_data();
  if (ic_data_result != NULL) {
    *ic_data_result = ic_data.raw();
  }
  return ic_data.GetTargetAt(0);
}


// The expected code pattern of an edge counter in unoptimized code:
//  49 8b 87 imm32    mov RAX, [PP + offset]
class EdgeCounter : public ValueObject {
 public:
  EdgeCounter(uword pc, const Code& code)
      : end_(pc - kAdjust), object_pool_(Array::Handle(code.ObjectPool())) {
    ASSERT(IsValid(end_));
  }

  static bool IsValid(uword end) {
    uint8_t* bytes = reinterpret_cast<uint8_t*>(end - 7);
    return (bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x87);
  }

  RawObject* edge_counter() const {
    return object_pool_.At(InstructionPattern::IndexFromPPLoad(end_ - 4));
  }

 private:
  // The edge counter load is followed by the fixed-size edge counter
  // incrementing code:
  //     48 83 40 17 02             addq [rax+0x17],0x2
  static const intptr_t kAdjust = 5;

  uword end_;
  const Array& object_pool_;
};


RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) {
  ASSERT(code.ContainsInstructionAt(pc));
  EdgeCounter counter(pc, code);
  return counter.edge_counter();
}

}  // namespace dart

#endif  // defined TARGET_ARCH_X64
