/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "stack.h"

#include "compiler.h"
#include "object.h"
#include "object_utils.h"
#include "thread_list.h"

namespace art {

bool Frame::HasMethod() const {
  return GetMethod() != NULL && (!GetMethod()->IsCalleeSaveMethod());
}

void Frame::Next() {
  size_t frame_size = GetMethod()->GetFrameSizeInBytes();
  DCHECK_NE(frame_size, 0u);
  DCHECK_LT(frame_size, 1024u);
  byte* next_sp = reinterpret_cast<byte*>(sp_) + frame_size;
  sp_ = reinterpret_cast<Method**>(next_sp);
  if (*sp_ != NULL) {
    DCHECK((*sp_)->GetClass() == Method::GetMethodClass() ||
        (*sp_)->GetClass() == Method::GetConstructorClass());
  }
}

uintptr_t Frame::GetReturnPC() const {
  byte* pc_addr = reinterpret_cast<byte*>(sp_) + GetMethod()->GetReturnPcOffsetInBytes();
  return *reinterpret_cast<uintptr_t*>(pc_addr);
}

void Frame::SetReturnPC(uintptr_t pc) {
  byte* pc_addr = reinterpret_cast<byte*>(sp_) + GetMethod()->GetReturnPcOffsetInBytes();
  *reinterpret_cast<uintptr_t*>(pc_addr) = pc;
}

/*
 * Return sp-relative offset for a Dalvik virtual register, compiler
 * spill or Method* in bytes using Method*.
 * Note that (reg >= 0) refers to a Dalvik register, (reg == -2)
 * denotes Method* and (reg <= -3) denotes a compiler temp.
 *
 *     +------------------------+
 *     | IN[ins-1]              |  {Note: resides in caller's frame}
 *     |       .                |
 *     | IN[0]                  |
 *     | caller's Method*       |
 *     +========================+  {Note: start of callee's frame}
 *     | core callee-save spill |  {variable sized}
 *     +------------------------+
 *     | fp callee-save spill   |
 *     +------------------------+
 *     | filler word            |  {For compatibility, if V[locals-1] used as wide
 *     +------------------------+
 *     | V[locals-1]            |
 *     | V[locals-2]            |
 *     |      .                 |
 *     |      .                 |  ... (reg == 2)
 *     | V[1]                   |  ... (reg == 1)
 *     | V[0]                   |  ... (reg == 0) <---- "locals_start"
 *     +------------------------+
 *     | Compiler temps         |  ... (reg == -2)
 *     |                        |  ... (reg == -3)
 *     |                        |  ... (reg == -4)
 *     +------------------------+
 *     | stack alignment padding|  {0 to (kStackAlignWords-1) of padding}
 *     +------------------------+
 *     | OUT[outs-1]            |
 *     | OUT[outs-2]            |
 *     |       .                |
 *     | OUT[0]                 |
 *     | curMethod*             |  ... (reg == -1) <<== sp, 16-byte aligned
 *     +========================+
 */
int Frame::GetVRegOffset(const DexFile::CodeItem* code_item,
                         uint32_t core_spills, uint32_t fp_spills,
                         size_t frame_size, int reg) {
  DCHECK_EQ(frame_size & (kStackAlignment - 1), 0U);
  int num_spills = __builtin_popcount(core_spills) + __builtin_popcount(fp_spills) + 1 /* filler */;
  int num_ins = code_item->ins_size_;
  int num_regs = code_item->registers_size_ - num_ins;
  int locals_start = frame_size - ((num_spills + num_regs) * sizeof(uint32_t));
  if (reg == -2) {
    return 0;  // Method*
  } else if (reg <= -3) {
    return locals_start - ((reg + 1) * sizeof(uint32_t));  // Compiler temp
  } else if (reg < num_regs) {
    return locals_start + (reg * sizeof(uint32_t));        // Dalvik local reg
  } else {
    return frame_size + ((reg - num_regs) * sizeof(uint32_t)) + sizeof(uint32_t); // Dalvik in
  }
}

uint32_t Frame::GetVReg(const DexFile::CodeItem* code_item, uint32_t core_spills,
                        uint32_t fp_spills, size_t frame_size, int vreg) const {
  int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
  byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
  return *reinterpret_cast<uint32_t*>(vreg_addr);
}

uint32_t Frame::GetVReg(Method* m, int vreg) const {
  DCHECK(m == GetMethod());
  const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
  DCHECK(code_item != NULL);  // can't be NULL or how would we compile its instructions?
  uint32_t core_spills = m->GetCoreSpillMask();
  uint32_t fp_spills = m->GetFpSpillMask();
  size_t frame_size = m->GetFrameSizeInBytes();
  return GetVReg(code_item, core_spills, fp_spills, frame_size, vreg);
}

void Frame::SetVReg(Method* m, int vreg, uint32_t new_value) {
  DCHECK(m == GetMethod());
  const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
  DCHECK(code_item != NULL);  // can't be NULL or how would we compile its instructions?
  uint32_t core_spills = m->GetCoreSpillMask();
  uint32_t fp_spills = m->GetFpSpillMask();
  size_t frame_size = m->GetFrameSizeInBytes();
  int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
  byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
  *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
}

uintptr_t Frame::LoadCalleeSave(int num) const {
  // Callee saves are held at the top of the frame
  Method* method = GetMethod();
  DCHECK(method != NULL);
  size_t frame_size = method->GetFrameSizeInBytes();
  byte* save_addr = reinterpret_cast<byte*>(sp_) + frame_size - ((num + 1) * kPointerSize);
#if defined(__i386__)
  save_addr -= kPointerSize;  // account for return address
#endif
  return *reinterpret_cast<uintptr_t*>(save_addr);
}

Method* Frame::NextMethod() const {
  byte* next_sp = reinterpret_cast<byte*>(sp_) + GetMethod()->GetFrameSizeInBytes();
  return *reinterpret_cast<Method**>(next_sp);
}

class StackGetter {
 public:
  StackGetter(JNIEnv* env, Thread* thread) : env_(env), thread_(thread), trace_(NULL) {
  }

  static void Callback(void* arg) {
    reinterpret_cast<StackGetter*>(arg)->Callback();
  }

  jobject GetTrace() {
    return trace_;
  }

 private:
  void Callback() {
    trace_ = thread_->CreateInternalStackTrace(env_);
  }

  JNIEnv* env_;
  Thread* thread_;
  jobject trace_;
};

jobject GetThreadStack(JNIEnv* env, Thread* thread) {
  ThreadList* thread_list = Runtime::Current()->GetThreadList();
  StackGetter stack_getter(env, thread);
  thread_list->RunWhileSuspended(thread, StackGetter::Callback, &stack_getter);
  return stack_getter.GetTrace();
}

}  // namespace art
