// 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, true, "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) {
  ASSERT(!IsEntryPatched(code));
  const uword patch_addr = code.GetEntryPatchPc();
  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) {
  if (!IsEntryPatched(code)) return;
  const uword patch_addr = code.GetEntryPatchPc();
  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.GetEntryPatchPc();
  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.GetEntryPatchPc();
  // Zero means means that 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
