/*
 * 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 "check_reference_map_visitor.h"
#include "jni.h"

namespace art {

#define CHECK_REGS_CONTAIN_REFS(dex_pc, abort_if_not_found, ...) do {                 \
  int t[] = {__VA_ARGS__};                                                            \
  int t_size = sizeof(t) / sizeof(*t);                                                \
  const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();       \
  uintptr_t native_quick_pc = method_header->ToNativeQuickPc(GetMethod(),             \
                                                 dex_pc,                              \
                                                 /* is_catch_handler */ false,        \
                                                 abort_if_not_found);                 \
  if (native_quick_pc != UINTPTR_MAX) {                                               \
    CheckReferences(t, t_size, method_header->NativeQuickPcOffset(native_quick_pc));  \
  }                                                                                   \
} while (false);

struct ReferenceMap2Visitor : public CheckReferenceMapVisitor {
  explicit ReferenceMap2Visitor(Thread* thread) SHARED_REQUIRES(Locks::mutator_lock_)
      : CheckReferenceMapVisitor(thread) {}

  bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) {
    if (CheckReferenceMapVisitor::VisitFrame()) {
      return true;
    }
    ArtMethod* m = GetMethod();
    std::string m_name(m->GetName());

    // Given the method name and the number of times the method has been called,
    // we know the Dex registers with live reference values. Assert that what we
    // find is what is expected.
    if (m_name.compare("f") == 0) {
      CHECK_REGS_CONTAIN_REFS(0x03U, true, 8);  // v8: this
      CHECK_REGS_CONTAIN_REFS(0x06U, true, 8, 1);  // v8: this, v1: x
      if (!GetCurrentOatQuickMethodHeader()->IsOptimized()) {
        CHECK_REGS_CONTAIN_REFS(0x08U, true, 8, 3, 1);  // v8: this, v3: y, v1: x
      }
      CHECK_REGS_CONTAIN_REFS(0x0cU, true, 8, 3, 1);  // v8: this, v3: y, v1: x
      if (!GetCurrentOatQuickMethodHeader()->IsOptimized()) {
        CHECK_REGS_CONTAIN_REFS(0x0eU, true, 8, 3, 1);  // v8: this, v3: y, v1: x
      }
      CHECK_REGS_CONTAIN_REFS(0x10U, true, 8, 3, 1);  // v8: this, v3: y, v1: x
      // v2 is added because of the instruction at DexPC 0024. Object merges with 0 is Object. See:
      //   0024: move-object v3, v2
      //   0025: goto 0013
      // Detailed dex instructions for ReferenceMap.java are at the end of this function.
      // CHECK_REGS_CONTAIN_REFS(8, 3, 2, 1);  // v8: this, v3: y, v2: y, v1: x
      // We eliminate the non-live registers at a return, so only v3 is live.
      // Note that it is OK for a compiler to not have a dex map at this dex PC because
      // a return is not necessarily a safepoint.
      CHECK_REGS_CONTAIN_REFS(0x14U, false, 2);  // v2: y
      // Note that v0: ex can be eliminated because it's a dead merge of two different exceptions.
      CHECK_REGS_CONTAIN_REFS(0x18U, true, 8, 2, 1);  // v8: this, v2: y, v1: x (dead v0: ex)
      if (!GetCurrentOatQuickMethodHeader()->IsOptimized()) {
        // v8: this, v4: x[1], v2: y, v1: x (dead v0: ex)
        CHECK_REGS_CONTAIN_REFS(0x1aU, true, 8, 4, 2, 1);
        // v8: this, v4: x[1], v2: y, v1: x (dead v0: ex)
        CHECK_REGS_CONTAIN_REFS(0x1eU, true, 8, 4, 2, 1);
        // v4 is removed from the root set because there is a "merge" operation.
        // See 0016: if-nez v2, 0020.
        CHECK_REGS_CONTAIN_REFS(0x20U, true, 8, 2, 1);  // v8: this, v2: y, v1: x (dead v0: ex)
      }
      CHECK_REGS_CONTAIN_REFS(0x22U, true, 8, 2, 1);  // v8: this, v2: y, v1: x (dead v0: ex)

      if (!GetCurrentOatQuickMethodHeader()->IsOptimized()) {
        CHECK_REGS_CONTAIN_REFS(0x27U, true, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
      }
      CHECK_REGS_CONTAIN_REFS(0x29U, true, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
      CHECK_REGS_CONTAIN_REFS(0x2cU, true, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
      // Note that it is OK for a compiler to not have a dex map at these two dex PCs because
      // a goto is not necessarily a safepoint.
      CHECK_REGS_CONTAIN_REFS(0x2fU, false, 8, 4, 3, 2, 1);  // v8: this, v4: ex, v3: y, v2: y, v1: x
      CHECK_REGS_CONTAIN_REFS(0x32U, false, 8, 3, 2, 1, 0);  // v8: this, v3: y, v2: y, v1: x, v0: ex
    }

    return true;
  }
};

// DEX code
//
// 0000: const/4 v4, #int 2 // #2
// 0001: const/4 v7, #int 0 // #0
// 0002: const/4 v6, #int 1 // #1
// 0003: new-array v1, v4, [Ljava/lang/Object; // type@0007
// 0005: const/4 v2, #int 0 // #0
// 0006: new-instance v3, Ljava/lang/Object; // type@0003
// 0008: invoke-direct {v3}, Ljava/lang/Object;.<init>:()V // method@0004
// 000b: const/4 v4, #int 2 // #2
// 000c: aput-object v3, v1, v4
// 000e: aput-object v3, v1, v6
// 0010: invoke-virtual {v8, v7}, LMain;.refmap:(I)I // method@0003
// 0013: move-object v2, v3
// 0014: return-object v2
// 0015: move-exception v0
// 0016: if-nez v2, 0020 // +000a
// 0018: new-instance v4, Ljava/lang/Object; // type@0003
// 001a: invoke-direct {v4}, Ljava/lang/Object;.<init>:()V // method@0004
// 001d: const/4 v5, #int 1 // #1
// 001e: aput-object v4, v1, v5
// 0020: aput-object v2, v1, v6
// 0022: invoke-virtual {v8, v7}, LMain;.refmap:(I)I // method@0003
// 0025: goto 0014 // -0011
// 0026: move-exception v4
// 0027: aput-object v2, v1, v6
// 0029: invoke-virtual {v8, v7}, LMain;.refmap:(I)I // method@0003
// 002c: throw v4
// 002d: move-exception v4
// 002e: move-object v2, v3
// 002f: goto 0027 // -0008
// 0030: move-exception v0
// 0031: move-object v2, v3
// 0032: goto 0016 // -001c
//    catches       : 3
//      0x0006 - 0x000b
//        Ljava/lang/Exception; -> 0x0015
//        <any> -> 0x0026
//      0x000c - 0x000e
//        Ljava/lang/Exception; -> 0x0030
//        <any> -> 0x002d
//      0x0018 - 0x0020
//        <any> -> 0x0026
//    positions     :
//      0x0003 line=22
//      0x0005 line=23
//      0x0006 line=25
//      0x000b line=26
//      0x000e line=32
//      0x0010 line=33
//      0x0014 line=35
//      0x0015 line=27
//      0x0016 line=28
//      0x0018 line=29
//      0x0020 line=32
//      0x0022 line=33
//      0x0026 line=31
//      0x0027 line=32
//      0x0029 line=33
//      0x002c line=31
//      0x0030 line=27
//    locals        :
//      0x0006 - 0x000b reg=2 y Ljava/lang/Object;
//      0x000b - 0x0014 reg=3 y Ljava/lang/Object;
//      0x0015 - 0x0016 reg=2 y Ljava/lang/Object;
//      0x0016 - 0x0026 reg=0 ex Ljava/lang/Exception;
//      0x002d - 0x002f reg=3 y Ljava/lang/Object;
//      0x002f - 0x0030 reg=2 y Ljava/lang/Object;
//      0x0030 - 0x0032 reg=3 y Ljava/lang/Object;
//      0x0031 - 0x0033 reg=0 ex Ljava/lang/Exception;
//      0x0005 - 0x0033 reg=1 x [Ljava/lang/Object;
//      0x0032 - 0x0033 reg=2 y Ljava/lang/Object;
//      0x0000 - 0x0033 reg=8 this LMain;

extern "C" JNIEXPORT jint JNICALL Java_Main_refmap(JNIEnv*, jobject, jint count) {
  // Visitor
  ScopedObjectAccess soa(Thread::Current());
  ReferenceMap2Visitor mapper(soa.Self());
  mapper.WalkStack();

  return count + 1;
}

}  // namespace art
