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

#include "art_method.h"
#include "class_linker.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "invoke_type.h"
#include "mirror/dex_cache-inl.h"
#include "nodes.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"

namespace art {

// Function that returns whether an intrinsic is static/direct or virtual.
static inline InvokeType GetIntrinsicInvokeType(Intrinsics i) {
  switch (i) {
    case Intrinsics::kNone:
      return kInterface;  // Non-sensical for intrinsic.
#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
    case Intrinsics::k ## Name: \
      return IsStatic;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef INTRINSICS_LIST
#undef OPTIMIZING_INTRINSICS
  }
  return kInterface;
}

// Function that returns whether an intrinsic needs an environment or not.
static inline IntrinsicNeedsEnvironmentOrCache NeedsEnvironmentOrCache(Intrinsics i) {
  switch (i) {
    case Intrinsics::kNone:
      return kNeedsEnvironmentOrCache;  // Non-sensical for intrinsic.
#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
    case Intrinsics::k ## Name: \
      return NeedsEnvironmentOrCache;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef INTRINSICS_LIST
#undef OPTIMIZING_INTRINSICS
  }
  return kNeedsEnvironmentOrCache;
}

// Function that returns whether an intrinsic has side effects.
static inline IntrinsicSideEffects GetSideEffects(Intrinsics i) {
  switch (i) {
    case Intrinsics::kNone:
      return kAllSideEffects;
#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
    case Intrinsics::k ## Name: \
      return SideEffects;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef INTRINSICS_LIST
#undef OPTIMIZING_INTRINSICS
  }
  return kAllSideEffects;
}

// Function that returns whether an intrinsic can throw exceptions.
static inline IntrinsicExceptions GetExceptions(Intrinsics i) {
  switch (i) {
    case Intrinsics::kNone:
      return kCanThrow;
#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
    case Intrinsics::k ## Name: \
      return Exceptions;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef INTRINSICS_LIST
#undef OPTIMIZING_INTRINSICS
  }
  return kCanThrow;
}

static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke) {
  // Whenever the intrinsic is marked as static, report an error if we find an InvokeVirtual.
  //
  // Whenever the intrinsic is marked as direct and we find an InvokeVirtual, a devirtualization
  // failure occured. We might be in a situation where we have inlined a method that calls an
  // intrinsic, but that method is in a different dex file on which we do not have a
  // verified_method that would have helped the compiler driver sharpen the call. In that case,
  // make sure that the intrinsic is actually for some final method (or in a final class), as
  // otherwise the intrinsics setup is broken.
  //
  // For the last direction, we have intrinsics for virtual functions that will perform a check
  // inline. If the precise type is known, however, the instruction will be sharpened to an
  // InvokeStaticOrDirect.
  InvokeType intrinsic_type = GetIntrinsicInvokeType(intrinsic);
  InvokeType invoke_type = invoke->GetInvokeType();
  switch (intrinsic_type) {
    case kStatic:
      return (invoke_type == kStatic);

    case kDirect:
      if (invoke_type == kDirect) {
        return true;
      }
      if (invoke_type == kVirtual) {
        ArtMethod* art_method = invoke->GetResolvedMethod();
        ScopedObjectAccess soa(Thread::Current());
        return (art_method->IsFinal() || art_method->GetDeclaringClass()->IsFinal());
      }
      return false;

    case kVirtual:
      // Call might be devirtualized.
      return (invoke_type == kVirtual || invoke_type == kDirect);

    default:
      return false;
  }
}

void IntrinsicsRecognizer::Run() {
  ScopedObjectAccess soa(Thread::Current());
  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
    for (HInstructionIterator inst_it(block->GetInstructions()); !inst_it.Done();
         inst_it.Advance()) {
      HInstruction* inst = inst_it.Current();
      if (inst->IsInvoke()) {
        HInvoke* invoke = inst->AsInvoke();
        ArtMethod* art_method = invoke->GetResolvedMethod();
        if (art_method != nullptr && art_method->IsIntrinsic()) {
          Intrinsics intrinsic = static_cast<Intrinsics>(art_method->GetIntrinsic());
          if (!CheckInvokeType(intrinsic, invoke)) {
            LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
                << intrinsic << " for "
                << art_method->PrettyMethod()
                << invoke->DebugName();
          } else {
            invoke->SetIntrinsic(intrinsic,
                                 NeedsEnvironmentOrCache(intrinsic),
                                 GetSideEffects(intrinsic),
                                 GetExceptions(intrinsic));
            MaybeRecordStat(MethodCompilationStat::kIntrinsicRecognized);
          }
        }
      }
    }
  }
}

std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic) {
  switch (intrinsic) {
    case Intrinsics::kNone:
      os << "None";
      break;
#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
    case Intrinsics::k ## Name: \
      os << # Name; \
      break;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef STATIC_INTRINSICS_LIST
#undef VIRTUAL_INTRINSICS_LIST
#undef OPTIMIZING_INTRINSICS
  }
  return os;
}

void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke,
                                                      CodeGenerator* codegen,
                                                      Location return_location,
                                                      Location first_argument_location) {
  if (Runtime::Current()->IsAotCompiler()) {
    if (codegen->GetCompilerOptions().IsBootImage() ||
        codegen->GetCompilerOptions().GetCompilePic()) {
      // TODO(ngeoffray): Support boot image compilation.
      return;
    }
  }

  IntegerValueOfInfo info = ComputeIntegerValueOfInfo();

  // Most common case is that we have found all we needed (classes are initialized
  // and in the boot image). Bail if not.
  if (info.integer_cache == nullptr ||
      info.integer == nullptr ||
      info.cache == nullptr ||
      info.value_offset == 0 ||
      // low and high cannot be 0, per the spec.
      info.low == 0 ||
      info.high == 0) {
    LOG(INFO) << "Integer.valueOf will not be optimized";
    return;
  }

  // The intrinsic will call if it needs to allocate a j.l.Integer.
  LocationSummary* locations = new (invoke->GetBlock()->GetGraph()->GetArena()) LocationSummary(
      invoke, LocationSummary::kCallOnMainOnly, kIntrinsified);
  if (!invoke->InputAt(0)->IsConstant()) {
    locations->SetInAt(0, Location::RequiresRegister());
  }
  locations->AddTemp(first_argument_location);
  locations->SetOut(return_location);
}

IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo() {
  // Note that we could cache all of the data looked up here. but there's no good
  // location for it. We don't want to add it to WellKnownClasses, to avoid creating global
  // jni values. Adding it as state to the compiler singleton seems like wrong
  // separation of concerns.
  // The need for this data should be pretty rare though.

  // The most common case is that the classes are in the boot image and initialized,
  // which is easy to generate code for. We bail if not.
  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);
  Runtime* runtime = Runtime::Current();
  ClassLinker* class_linker = runtime->GetClassLinker();
  gc::Heap* heap = runtime->GetHeap();
  IntegerValueOfInfo info;
  info.integer_cache = class_linker->FindSystemClass(self, "Ljava/lang/Integer$IntegerCache;");
  if (info.integer_cache == nullptr) {
    self->ClearException();
    return info;
  }
  if (!heap->ObjectIsInBootImageSpace(info.integer_cache) || !info.integer_cache->IsInitialized()) {
    // Optimization only works if the class is initialized and in the boot image.
    return info;
  }
  info.integer = class_linker->FindSystemClass(self, "Ljava/lang/Integer;");
  if (info.integer == nullptr) {
    self->ClearException();
    return info;
  }
  if (!heap->ObjectIsInBootImageSpace(info.integer) || !info.integer->IsInitialized()) {
    // Optimization only works if the class is initialized and in the boot image.
    return info;
  }

  ArtField* field = info.integer_cache->FindDeclaredStaticField("cache", "[Ljava/lang/Integer;");
  if (field == nullptr) {
    return info;
  }
  info.cache = static_cast<mirror::ObjectArray<mirror::Object>*>(
      field->GetObject(info.integer_cache).Ptr());
  if (info.cache == nullptr) {
    return info;
  }

  if (!heap->ObjectIsInBootImageSpace(info.cache)) {
    // Optimization only works if the object is in the boot image.
    return info;
  }

  field = info.integer->FindDeclaredInstanceField("value", "I");
  if (field == nullptr) {
    return info;
  }
  info.value_offset = field->GetOffset().Int32Value();

  field = info.integer_cache->FindDeclaredStaticField("low", "I");
  if (field == nullptr) {
    return info;
  }
  info.low = field->GetInt(info.integer_cache);

  field = info.integer_cache->FindDeclaredStaticField("high", "I");
  if (field == nullptr) {
    return info;
  }
  info.high = field->GetInt(info.integer_cache);

  DCHECK_EQ(info.cache->GetLength(), info.high - info.low + 1);
  return info;
}

}  // namespace art
