/*
 * Copyright (C) 2013 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 "verification_results.h"

#include "base/stl_util.h"
#include "base/mutex.h"
#include "base/mutex-inl.h"
#include "thread.h"
#include "thread-inl.h"
#include "verified_method.h"
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"

namespace art {

VerificationResults::VerificationResults()
    : verified_methods_lock_("compiler verified methods lock"),
      verified_methods_(),
      rejected_classes_lock_("compiler rejected classes lock"),
      rejected_classes_() {
}

VerificationResults::~VerificationResults() {
  Thread* self = Thread::Current();
  {
    WriterMutexLock mu(self, verified_methods_lock_);
    STLDeleteValues(&verified_methods_);
  }
}

bool VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) {
  MethodReference ref = method_verifier->GetMethodReference();
  bool compile = IsCandidateForCompilation(ref, method_verifier->GetAccessFlags());
  // TODO: Check also for virtual/interface invokes when DEX-to-DEX supports devirtualization.
  if (!compile && !method_verifier->HasCheckCasts()) {
    return true;
  }

  const VerifiedMethod* verified_method = VerifiedMethod::Create(method_verifier, compile);
  if (verified_method == nullptr) {
    DCHECK(method_verifier->HasFailures());
    return false;
  }

  WriterMutexLock mu(Thread::Current(), verified_methods_lock_);
  auto it = verified_methods_.find(ref);
  if (it != verified_methods_.end()) {
    // TODO: Investigate why are we doing the work again for this method and try to avoid it.
    LOG(WARNING) << "Method processed more than once: "
        << PrettyMethod(ref.dex_method_index, *ref.dex_file);
    DCHECK_EQ(it->second->GetDevirtMap().size(), verified_method->GetDevirtMap().size());
    DCHECK_EQ(it->second->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size());
    DCHECK_EQ(it->second->GetDexGcMap().size(), verified_method->GetDexGcMap().size());
    delete it->second;
    verified_methods_.erase(it);
  }
  verified_methods_.Put(ref, verified_method);
  DCHECK(verified_methods_.find(ref) != verified_methods_.end());
  return true;
}

const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) {
  ReaderMutexLock mu(Thread::Current(), verified_methods_lock_);
  auto it = verified_methods_.find(ref);
  return (it != verified_methods_.end()) ? it->second : nullptr;
}

void VerificationResults::AddRejectedClass(ClassReference ref) {
  {
    WriterMutexLock mu(Thread::Current(), rejected_classes_lock_);
    rejected_classes_.insert(ref);
  }
  DCHECK(IsClassRejected(ref));
}

bool VerificationResults::IsClassRejected(ClassReference ref) {
  ReaderMutexLock mu(Thread::Current(), rejected_classes_lock_);
  return (rejected_classes_.find(ref) != rejected_classes_.end());
}

bool VerificationResults::IsCandidateForCompilation(MethodReference& method_ref,
                                                    const uint32_t access_flags) {
#ifdef ART_SEA_IR_MODE
    bool use_sea = Runtime::Current()->IsSeaIRMode();
    use_sea = use_sea && (std::string::npos != PrettyMethod(
                          method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci"));
    if (use_sea) return true;
#endif
  // Don't compile class initializers, ever.
  if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) {
    return false;
  }
  return (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly);
}

}  // namespace art
