// 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/code_patcher.h"
#include "vm/cpu.h"
#include "vm/instructions.h"
#include "vm/object.h"
#include "vm/virtual_memory.h"

namespace dart {

DEFINE_FLAG(bool, write_protect_code, false, "Write protect jitted code");


WritableInstructionsScope::WritableInstructionsScope(uword address,
                                                     intptr_t size)
    : address_(address), size_(size) {
  if (FLAG_write_protect_code) {
    bool status =
        VirtualMemory::Protect(reinterpret_cast<void*>(address),
                               size,
                               VirtualMemory::kReadWrite);
    ASSERT(status);
  }
}


WritableInstructionsScope::~WritableInstructionsScope() {
  if (FLAG_write_protect_code) {
    bool status =
        VirtualMemory::Protect(reinterpret_cast<void*>(address_),
                               size_,
                               VirtualMemory::kReadExecute);
    ASSERT(status);
  }
}


static void SwapCode(intptr_t num_bytes, char* code, char* buffer) {
  uword code_address = reinterpret_cast<uword>(code);
  for (intptr_t i = 0; i < num_bytes; i++) {
    char tmp = *code;
    *code = *buffer;
    *buffer = tmp;
    code++;
    buffer++;
  }
  CPU::FlushICache(code_address, num_bytes);
  // The buffer is not executed. No need to flush.
}


// The patch code buffer contains the jmp code which will be inserted at
// entry point.
void CodePatcher::PatchEntry(const Code& code) {
  const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
                                                PcDescriptors::kEntryPatch);
  ASSERT(patch_addr != 0);
  JumpPattern jmp_entry(patch_addr, code);
  ASSERT(!jmp_entry.IsValid());
  const uword patch_buffer = code.GetPatchCodePc();
  ASSERT(patch_buffer != 0);
  JumpPattern jmp_patch(patch_buffer, code);
  ASSERT(jmp_patch.IsValid());
  const uword jump_target = jmp_patch.TargetAddress();
  intptr_t length = jmp_patch.pattern_length_in_bytes();
  {
    WritableInstructionsScope writable_code(patch_addr, length);
    WritableInstructionsScope writable_buffer(patch_buffer, length);
    SwapCode(jmp_patch.pattern_length_in_bytes(),
             reinterpret_cast<char*>(patch_addr),
             reinterpret_cast<char*>(patch_buffer));
    jmp_entry.SetTargetAddress(jump_target);
  }
}


// The entry point is a jmp instruction, the patch code buffer contains
// original code, the entry point contains the jump instruction.
void CodePatcher::RestoreEntry(const Code& code) {
  const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
                                                PcDescriptors::kEntryPatch);
  ASSERT(patch_addr != 0);
  JumpPattern jmp_entry(patch_addr, code);
  ASSERT(jmp_entry.IsValid());
  const uword jump_target = jmp_entry.TargetAddress();
  const uword patch_buffer = code.GetPatchCodePc();
  ASSERT(patch_buffer != 0);
  // 'patch_buffer' contains original entry code.
  JumpPattern jmp_patch(patch_buffer, code);
  ASSERT(!jmp_patch.IsValid());
  intptr_t length = jmp_patch.pattern_length_in_bytes();
  {
    WritableInstructionsScope writable_code(patch_addr, length);
    WritableInstructionsScope writable_buffer(patch_buffer, length);
    SwapCode(jmp_patch.pattern_length_in_bytes(),
             reinterpret_cast<char*>(patch_addr),
             reinterpret_cast<char*>(patch_buffer));
    ASSERT(jmp_patch.IsValid());
    jmp_patch.SetTargetAddress(jump_target);
  }
}


bool CodePatcher::IsEntryPatched(const Code& code) {
  const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
                                                PcDescriptors::kEntryPatch);
  if (patch_addr == 0) {
    return false;
  }
  JumpPattern jmp_entry(patch_addr, code);
  return jmp_entry.IsValid();
}


bool CodePatcher::CodeIsPatchable(const Code& code) {
  const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
                                                PcDescriptors::kEntryPatch);
  // kEntryPatch may not exist which means the function is not patchable.
  if (patch_addr == 0) {
    return false;
  }
  JumpPattern jmp_entry(patch_addr, code);
  if (code.Size() < (jmp_entry.pattern_length_in_bytes() * 2)) {
    return false;
  }
  const uword limit = patch_addr + jmp_entry.pattern_length_in_bytes();
  // Check no object stored between patch_addr .. limit.
  for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) {
    const uword obj_start = code.GetPointerOffsetAt(i) + code.EntryPoint();
    const uword obj_end  = obj_start + kWordSize;
    if ((obj_start < limit) && (obj_end > patch_addr)) {
      return false;
    }
  }
  return true;
}

}  // namespace dart
