/*
 * Copyright (C) 2009 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 "indirect_reference_table.h"
#include "jni_internal.h"
#include "reference_table.h"
#include "runtime.h"
#include "thread.h"
#include "utils.h"

#include <cstdlib>

namespace art {

static void AbortMaybe() {
  // If -Xcheck:jni is on, it'll give a more detailed error before aborting.
  if (!Runtime::Current()->GetJavaVM()->check_jni) {
    // Otherwise, we want to abort rather than hand back a bad reference.
    LOG(FATAL) << "JNI ERROR (app bug): see above.";
  }
}

IndirectReferenceTable::IndirectReferenceTable(size_t initialCount,
                                               size_t maxCount, IndirectRefKind desiredKind) {
  CHECK_GT(initialCount, 0U);
  CHECK_LE(initialCount, maxCount);
  CHECK_NE(desiredKind, kSirtOrInvalid);

  table_ = reinterpret_cast<const Object**>(malloc(initialCount * sizeof(const Object*)));
  CHECK(table_ != NULL);
  memset(table_, 0xd1, initialCount * sizeof(const Object*));

  slot_data_ = reinterpret_cast<IndirectRefSlot*>(calloc(initialCount, sizeof(IndirectRefSlot)));
  CHECK(slot_data_ != NULL);

  segment_state_.all = IRT_FIRST_SEGMENT;
  alloc_entries_ = initialCount;
  max_entries_ = maxCount;
  kind_ = desiredKind;
}

IndirectReferenceTable::~IndirectReferenceTable() {
  free(table_);
  free(slot_data_);
  table_ = NULL;
  slot_data_ = NULL;
  alloc_entries_ = max_entries_ = -1;
}

/*
 * Make sure that the entry at "idx" is correctly paired with "iref".
 */
bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int idx) const {
  const Object* obj = table_[idx];
  IndirectRef checkRef = ToIndirectRef(obj, idx);
  if (checkRef != iref) {
    LOG(ERROR) << "JNI ERROR (app bug): attempt to " << what
               << " stale " << kind_ << " " << iref
               << " (should be " << checkRef << ")";
    AbortMaybe();
    return false;
  }
  return true;
}

IndirectRef IndirectReferenceTable::Add(uint32_t cookie, const Object* obj) {
  IRTSegmentState prevState;
  prevState.all = cookie;
  size_t topIndex = segment_state_.parts.topIndex;

  DCHECK(obj != NULL);
  // TODO: stronger sanity check on the object (such as in heap)
  DCHECK_ALIGNED(reinterpret_cast<uintptr_t>(obj), 8);
  DCHECK(table_ != NULL);
  DCHECK_LE(alloc_entries_, max_entries_);
  DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles);

  if (topIndex == alloc_entries_) {
    /* reached end of allocated space; did we hit buffer max? */
    if (topIndex == max_entries_) {
      LOG(ERROR) << "JNI ERROR (app bug): " << kind_ << " table overflow "
                 << "(max=" << max_entries_ << ")";
      Dump();
      LOG(FATAL); // TODO: operator<< for IndirectReferenceTable
    }

    size_t newSize = alloc_entries_ * 2;
    if (newSize > max_entries_) {
      newSize = max_entries_;
    }
    DCHECK_GT(newSize, alloc_entries_);

    table_ = reinterpret_cast<const Object**>(realloc(table_, newSize * sizeof(const Object*)));
    slot_data_ = reinterpret_cast<IndirectRefSlot*>(realloc(slot_data_, newSize * sizeof(IndirectRefSlot)));
    if (table_ == NULL || slot_data_ == NULL) {
      LOG(ERROR) << "JNI ERROR (app bug): unable to expand "
                 << kind_ << " table (from "
                 << alloc_entries_ << " to " << newSize
                 << ", max=" << max_entries_ << ")";
      Dump();
      LOG(FATAL); // TODO: operator<< for IndirectReferenceTable
    }

    // Clear the newly-allocated slot_data_ elements.
    memset(slot_data_ + alloc_entries_, 0, (newSize - alloc_entries_) * sizeof(IndirectRefSlot));

    alloc_entries_ = newSize;
  }

  /*
   * We know there's enough room in the table.  Now we just need to find
   * the right spot.  If there's a hole, find it and fill it; otherwise,
   * add to the end of the list.
   */
  IndirectRef result;
  int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles;
  if (numHoles > 0) {
    DCHECK_GT(topIndex, 1U);
    /* find the first hole; likely to be near the end of the list */
    const Object** pScan = &table_[topIndex - 1];
    DCHECK(*pScan != NULL);
    while (*--pScan != NULL) {
      DCHECK_GE(pScan, table_ + prevState.parts.topIndex);
    }
    UpdateSlotAdd(obj, pScan - table_);
    result = ToIndirectRef(obj, pScan - table_);
    *pScan = obj;
    segment_state_.parts.numHoles--;
  } else {
    /* add to the end */
    UpdateSlotAdd(obj, topIndex);
    result = ToIndirectRef(obj, topIndex);
    table_[topIndex++] = obj;
    segment_state_.parts.topIndex = topIndex;
  }
  if (false) {
    LOG(INFO) << "+++ added at " << ExtractIndex(result) << " top=" << segment_state_.parts.topIndex
              << " holes=" << segment_state_.parts.numHoles;
  }

  DCHECK(result != NULL);
  return result;
}

void IndirectReferenceTable::AssertEmpty() {
  if (begin() != end()) {
    Dump();
    LOG(FATAL) << "Internal Error: non-empty local reference table";
  }
}

/*
 * Verify that the indirect table lookup is valid.
 *
 * Returns "false" if something looks bad.
 */
bool IndirectReferenceTable::GetChecked(IndirectRef iref) const {
  if (iref == NULL) {
    LOG(WARNING) << "Attempt to look up NULL " << kind_;
    return false;
  }
  if (GetIndirectRefKind(iref) == kSirtOrInvalid) {
    LOG(ERROR) << "JNI ERROR (app bug): invalid " << kind_ << " " << iref;
    AbortMaybe();
    return false;
  }

  int topIndex = segment_state_.parts.topIndex;
  int idx = ExtractIndex(iref);
  if (idx >= topIndex) {
    /* bad -- stale reference? */
    LOG(ERROR) << "JNI ERROR (app bug): accessed stale " << kind_ << " "
               << iref << " (index " << idx << " in a table of size " << topIndex << ")";
    AbortMaybe();
    return false;
  }

  if (table_[idx] == NULL) {
    LOG(ERROR) << "JNI ERROR (app bug): accessed deleted " << kind_ << " " << iref;
    AbortMaybe();
    return false;
  }

  if (!CheckEntry("use", iref, idx)) {
    return false;
  }

  return true;
}

static int Find(Object* direct_pointer, int bottomIndex, int topIndex, const Object** table) {
  for (int i = bottomIndex; i < topIndex; ++i) {
    if (table[i] == direct_pointer) {
      return i;
    }
  }
  return -1;
}

bool IndirectReferenceTable::ContainsDirectPointer(Object* direct_pointer) const {
  return Find(direct_pointer, 0, segment_state_.parts.topIndex, table_) != -1;
}

/*
 * Remove "obj" from "pRef".  We extract the table offset bits from "iref"
 * and zap the corresponding entry, leaving a hole if it's not at the top.
 *
 * If the entry is not between the current top index and the bottom index
 * specified by the cookie, we don't remove anything.  This is the behavior
 * required by JNI's DeleteLocalRef function.
 *
 * Note this is NOT called when a local frame is popped.  This is only used
 * for explicit single removals.
 *
 * Returns "false" if nothing was removed.
 */
bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) {
  IRTSegmentState prevState;
  prevState.all = cookie;
  int topIndex = segment_state_.parts.topIndex;
  int bottomIndex = prevState.parts.topIndex;

  DCHECK(table_ != NULL);
  DCHECK_LE(alloc_entries_, max_entries_);
  DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles);

  int idx = ExtractIndex(iref);

  JavaVMExt* vm = Runtime::Current()->GetJavaVM();
  if (GetIndirectRefKind(iref) == kSirtOrInvalid &&
      Thread::Current()->StackReferencesContain(reinterpret_cast<jobject>(iref))) {
    LOG(WARNING) << "Attempt to remove local SIRT entry from IRT, ignoring";
    return true;
  }
  if (GetIndirectRefKind(iref) == kSirtOrInvalid && vm->work_around_app_jni_bugs) {
    Object* direct_pointer = reinterpret_cast<Object*>(iref);
    idx = Find(direct_pointer, bottomIndex, topIndex, table_);
    if (idx == -1) {
      LOG(WARNING) << "trying to work around app JNI bugs, but didn't find " << iref << " in table!";
      return false;
    }
  }

  if (idx < bottomIndex) {
    // Wrong segment.
    LOG(WARNING) << "Attempt to remove index outside index area (" << idx
                 << " vs " << bottomIndex << "-" << topIndex << ")";
    return false;
  }
  if (idx >= topIndex) {
    // Bad --- stale reference?
    LOG(WARNING) << "Attempt to remove invalid index " << idx
                 << " (bottom=" << bottomIndex << " top=" << topIndex << ")";
    return false;
  }

  if (idx == topIndex-1) {
    // Top-most entry.  Scan up and consume holes.

    if (!vm->work_around_app_jni_bugs && !CheckEntry("remove", iref, idx)) {
      return false;
    }

    table_[idx] = NULL;
    int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles;
    if (numHoles != 0) {
      while (--topIndex > bottomIndex && numHoles != 0) {
        if (false) {
          LOG(INFO) << "+++ checking for hole at " << topIndex-1
                    << " (cookie=" << cookie << ") val=" << table_[topIndex - 1];
        }
        if (table_[topIndex-1] != NULL) {
          break;
        }
        if (false) {
          LOG(INFO) << "+++ ate hole at " << (topIndex - 1);
        }
        numHoles--;
      }
      segment_state_.parts.numHoles = numHoles + prevState.parts.numHoles;
      segment_state_.parts.topIndex = topIndex;
    } else {
      segment_state_.parts.topIndex = topIndex-1;
      if (false) {
        LOG(INFO) << "+++ ate last entry " << topIndex - 1;
      }
    }
  } else {
    /*
     * Not the top-most entry.  This creates a hole.  We NULL out the
     * entry to prevent somebody from deleting it twice and screwing up
     * the hole count.
     */
    if (table_[idx] == NULL) {
      LOG(INFO) << "--- WEIRD: removing null entry " << idx;
      return false;
    }
    if (!vm->work_around_app_jni_bugs && !CheckEntry("remove", iref, idx)) {
      return false;
    }

    table_[idx] = NULL;
    segment_state_.parts.numHoles++;
    if (false) {
      LOG(INFO) << "+++ left hole at " << idx << ", holes=" << segment_state_.parts.numHoles;
    }
  }

  return true;
}

void IndirectReferenceTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
  typedef IndirectReferenceTable::iterator It; // TODO: C++0x auto
  for (It it = begin(), end = this->end(); it != end; ++it) {
    visitor(**it, arg);
  }
}

std::ostream& operator<<(std::ostream& os, IndirectRefKind rhs) {
  switch (rhs) {
  case kSirtOrInvalid:
    os << "stack indirect reference table or invalid reference";
    break;
  case kLocal:
    os << "local reference";
    break;
  case kGlobal:
    os << "global reference";
    break;
  case kWeakGlobal:
    os << "weak global reference";
    break;
  default:
    os << "IndirectRefKind[" << static_cast<int>(rhs) << "]";
    break;
  }
  return os;
}

void IndirectReferenceTable::Dump() const {
  LOG(WARNING) << kind_ << " table dump:";
  std::vector<const Object*> entries(table_, table_ + Capacity());
  ReferenceTable::Dump(entries);
}

}  // namespace art
