/*
 * Copyright (C) 2012 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 "art_method-inl.h"
#include "callee_save_frame.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_instruction-inl.h"
#include "common_throws.h"
#include "mirror/object-inl.h"
#include "nth_caller_visitor.h"
#include "thread.h"
#include "well_known_classes.h"

namespace art HIDDEN {

// Deliver an exception that's pending on thread helping set up a callee save frame on the way.
extern "C" NO_RETURN void artDeliverPendingExceptionFromCode(Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  self->QuickDeliverException();
}

extern "C" NO_RETURN uint64_t artInvokeObsoleteMethod(ArtMethod* method, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(method->IsObsolete());
  ScopedQuickEntrypointChecks sqec(self);
  ThrowInternalError("Attempting to invoke obsolete version of '%s'.",
                     method->PrettyMethod().c_str());
  self->QuickDeliverException();
}

// Called by generated code to throw an exception.
extern "C" NO_RETURN void artDeliverExceptionFromCode(mirror::Throwable* exception, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  /*
   * exception may be null, in which case this routine should
   * throw NPE.  NOTE: this is a convenience for generated code,
   * which previously did the null check inline and constructed
   * and threw a NPE if null.  This routine responsible for setting
   * exception_ in thread and delivering the exception.
   */
  ScopedQuickEntrypointChecks sqec(self);
  if (exception == nullptr) {
    self->ThrowNewException("Ljava/lang/NullPointerException;", nullptr);
  } else {
    self->SetException(exception);
  }
  self->QuickDeliverException();
}

// Called by generated code to throw a NPE exception.
extern "C" NO_RETURN void artThrowNullPointerExceptionFromCode(Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  // We come from an explicit check in the generated code. This path is triggered
  // only if the object is indeed null.
  ThrowNullPointerExceptionFromDexPC(/* check_address= */ false, 0U);
  self->QuickDeliverException();
}

// Installed by a signal handler to throw a NPE exception.
extern "C" NO_RETURN void artThrowNullPointerExceptionFromSignal(uintptr_t addr, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  ThrowNullPointerExceptionFromDexPC(/* check_address= */ true, addr);
  self->QuickDeliverException();
}

// Called by generated code to throw an arithmetic divide by zero exception.
extern "C" NO_RETURN void artThrowDivZeroFromCode(Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  ThrowArithmeticExceptionDivideByZero();
  self->QuickDeliverException();
}

// Called by generated code to throw an array index out of bounds exception.
extern "C" NO_RETURN void artThrowArrayBoundsFromCode(int index, int length, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  ThrowArrayIndexOutOfBoundsException(index, length);
  self->QuickDeliverException();
}

// Called by generated code to throw a string index out of bounds exception.
extern "C" NO_RETURN void artThrowStringBoundsFromCode(int index, int length, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  ThrowStringIndexOutOfBoundsException(index, length);
  self->QuickDeliverException();
}

extern "C" NO_RETURN void artThrowStackOverflowFromCode(Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  ThrowStackOverflowError(self);
  self->QuickDeliverException();
}

extern "C" NO_RETURN void artThrowClassCastException(mirror::Class* dest_type,
                                                     mirror::Class* src_type,
                                                     Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  if (dest_type == nullptr) {
    // Find the target class for check cast using the bitstring check (dest_type == null).
    NthCallerVisitor visitor(self, 0u);
    visitor.WalkStack();
    DCHECK(visitor.caller != nullptr);
    uint32_t dex_pc = visitor.GetDexPc();
    CodeItemDataAccessor accessor(*visitor.caller->GetDexFile(), visitor.caller->GetCodeItem());
    const Instruction& check_cast = accessor.InstructionAt(dex_pc);
    DCHECK_EQ(check_cast.Opcode(), Instruction::CHECK_CAST);
    dex::TypeIndex type_index(check_cast.VRegB_21c());
    ClassLinker* linker = Runtime::Current()->GetClassLinker();
    dest_type = linker->LookupResolvedType(type_index, visitor.caller).Ptr();
    CHECK(dest_type != nullptr) << "Target class should have been previously resolved: "
        << visitor.caller->GetDexFile()->PrettyType(type_index);
    CHECK(!dest_type->IsAssignableFrom(src_type))
        << " " << std::hex << dest_type->PrettyDescriptor() << ";" << dest_type->Depth()
        << "/" << dest_type->GetField32(mirror::Class::StatusOffset())
        << " <: " << src_type->PrettyDescriptor() << ";" << src_type->Depth()
        << "/" << src_type->GetField32(mirror::Class::StatusOffset());
  }
  DCHECK(!dest_type->IsAssignableFrom(src_type));
  ThrowClassCastException(dest_type, src_type);
  self->QuickDeliverException();
}

extern "C" NO_RETURN void artThrowClassCastExceptionForObject(mirror::Object* obj,
                                                              mirror::Class* dest_type,
                                                              Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(obj != nullptr);
  artThrowClassCastException(dest_type, obj->GetClass(), self);
}

extern "C" NO_RETURN void artThrowArrayStoreException(mirror::Object* array, mirror::Object* value,
                                                      Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  ThrowArrayStoreException(value->GetClass(), array->GetClass());
  self->QuickDeliverException();
}

}  // namespace art
