187e552db94588455c081efd87dbde0cd96d02942Ian Rogers/*
287e552db94588455c081efd87dbde0cd96d02942Ian Rogers * Copyright (C) 2012 The Android Open Source Project
387e552db94588455c081efd87dbde0cd96d02942Ian Rogers *
487e552db94588455c081efd87dbde0cd96d02942Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License");
587e552db94588455c081efd87dbde0cd96d02942Ian Rogers * you may not use this file except in compliance with the License.
687e552db94588455c081efd87dbde0cd96d02942Ian Rogers * You may obtain a copy of the License at
787e552db94588455c081efd87dbde0cd96d02942Ian Rogers *
887e552db94588455c081efd87dbde0cd96d02942Ian Rogers *      http://www.apache.org/licenses/LICENSE-2.0
987e552db94588455c081efd87dbde0cd96d02942Ian Rogers *
1087e552db94588455c081efd87dbde0cd96d02942Ian Rogers * Unless required by applicable law or agreed to in writing, software
1187e552db94588455c081efd87dbde0cd96d02942Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS,
1287e552db94588455c081efd87dbde0cd96d02942Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1387e552db94588455c081efd87dbde0cd96d02942Ian Rogers * See the License for the specific language governing permissions and
1487e552db94588455c081efd87dbde0cd96d02942Ian Rogers * limitations under the License.
1587e552db94588455c081efd87dbde0cd96d02942Ian Rogers */
1687e552db94588455c081efd87dbde0cd96d02942Ian Rogers
1787e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "common_throws.h"
1887e552db94588455c081efd87dbde0cd96d02942Ian Rogers
1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h"
214f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
2275b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz#include "dex_instruction-inl.h"
2387e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "invoke_type.h"
24ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
254f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/class-inl.h"
262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
2887e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "object_utils.h"
2987e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "thread.h"
302d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz#include "verifier/method_verifier.h"
3187e552db94588455c081efd87dbde0cd96d02942Ian Rogers
3287e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include <sstream>
3387e552db94588455c081efd87dbde0cd96d02942Ian Rogers
3487e552db94588455c081efd87dbde0cd96d02942Ian Rogersnamespace art {
3587e552db94588455c081efd87dbde0cd96d02942Ian Rogers
3662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void AddReferrerLocation(std::ostream& os, const mirror::Class* referrer)
37b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3887e552db94588455c081efd87dbde0cd96d02942Ian Rogers  if (referrer != NULL) {
3962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ClassHelper kh(referrer);
4087e552db94588455c081efd87dbde0cd96d02942Ian Rogers    std::string location(kh.GetLocation());
4187e552db94588455c081efd87dbde0cd96d02942Ian Rogers    if (!location.empty()) {
4262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      os << " (declaration of '" << PrettyDescriptor(referrer)
4362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers            << "' appears in " << location << ")";
4487e552db94588455c081efd87dbde0cd96d02942Ian Rogers    }
4587e552db94588455c081efd87dbde0cd96d02942Ian Rogers  }
4687e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
4787e552db94588455c081efd87dbde0cd96d02942Ian Rogers
4862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor,
4962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                           const mirror::Class* referrer, const char* fmt, va_list* args = NULL)
50b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
5162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::ostringstream msg;
5262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (args != NULL) {
5362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    std::string vmsg;
5462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    StringAppendV(&vmsg, fmt, *args);
5562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    msg << vmsg;
5662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  } else {
5762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    msg << fmt;
5862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
5962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  AddReferrerLocation(msg, referrer);
6062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Thread* self = Thread::Current();
6162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (throw_location == NULL) {
6262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow();
6362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    self->ThrowNewException(computed_throw_location, exception_descriptor, msg.str().c_str());
6462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  } else {
6562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    self->ThrowNewException(*throw_location, exception_descriptor, msg.str().c_str());
6687e552db94588455c081efd87dbde0cd96d02942Ian Rogers  }
6787e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
6887e552db94588455c081efd87dbde0cd96d02942Ian Rogers
6956adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz// AbstractMethodError
7056adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz
71ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid ThrowAbstractMethodError(const mirror::ArtMethod* method) {
7256adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz  ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL,
7356adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz                 StringPrintf("abstract method \"%s\"",
7456adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz                              PrettyMethod(method).c_str()).c_str());
7556adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz}
7656adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz
7762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// ArithmeticException
7887e552db94588455c081efd87dbde0cd96d02942Ian Rogers
790a3b863fb1acae912b54f4be2c1928d3afa5e936Sebastien Hertzvoid ThrowArithmeticExceptionDivideByZero() {
8062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/ArithmeticException;", NULL, "divide by zero");
8187e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
8287e552db94588455c081efd87dbde0cd96d02942Ian Rogers
8362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// ArrayIndexOutOfBoundsException
8462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
8562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowArrayIndexOutOfBoundsException(int index, int length) {
8662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/ArrayIndexOutOfBoundsException;", NULL,
8762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 StringPrintf("length=%d; index=%d", length, index).c_str());
8887e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
8987e552db94588455c081efd87dbde0cd96d02942Ian Rogers
9062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// ArrayStoreException
9162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
9262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowArrayStoreException(const mirror::Class* element_class,
9362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                              const mirror::Class* array_class) {
9462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL,
9562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 StringPrintf("%s cannot be stored in an array of type %s",
9662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                              PrettyDescriptor(element_class).c_str(),
9762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                              PrettyDescriptor(array_class).c_str()).c_str());
9862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
9962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
10062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// ClassCastException
10162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
10262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowClassCastException(const mirror::Class* dest_type, const mirror::Class* src_type) {
10362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL,
10462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 StringPrintf("%s cannot be cast to %s",
10562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                              PrettyDescriptor(src_type).c_str(),
10662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                              PrettyDescriptor(dest_type).c_str()).c_str());
10762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
10862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
10962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowClassCastException(const ThrowLocation* throw_location, const char* msg) {
11062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(throw_location, "Ljava/lang/ClassCastException;", NULL, msg);
11162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
11262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
11362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// ClassCircularityError
11462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
11562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowClassCircularityError(mirror::Class* c) {
11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::ostringstream msg;
11762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  msg << PrettyDescriptor(c);
11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/ClassCircularityError;", c, msg.str().c_str());
11987e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
12087e552db94588455c081efd87dbde0cd96d02942Ian Rogers
12162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// ClassFormatError
12262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
12362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowClassFormatError(const mirror::Class* referrer, const char* fmt, ...) {
12462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_list args;
12562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_start(args, fmt);
12662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args);
12762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_end(args);}
12862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
12987e552db94588455c081efd87dbde0cd96d02942Ian Rogers// IllegalAccessError
13087e552db94588455c081efd87dbde0cd96d02942Ian Rogers
1312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) {
13287e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
133b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '"
13487e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << PrettyDescriptor(accessed) << "'";
13562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
13687e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
13787e552db94588455c081efd87dbde0cd96d02942Ian Rogers
1382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
139ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                                   const mirror::ArtMethod* caller,
140ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                                   const mirror::ArtMethod* called,
14187e552db94588455c081efd87dbde0cd96d02942Ian Rogers                                                   InvokeType type) {
14287e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
143b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
144b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      << PrettyDescriptor(accessed) << "') in attempt to invoke " << type
14587e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << " method " << PrettyMethod(called).c_str();
14662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
14787e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
14887e552db94588455c081efd87dbde0cd96d02942Ian Rogers
149ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) {
15087e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
15187e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
15287e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << PrettyDescriptor(referrer) << "'";
15362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
15487e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
15587e552db94588455c081efd87dbde0cd96d02942Ian Rogers
156ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) {
15787e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
15887e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
15987e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << PrettyDescriptor(referrer) << "'";
16062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
16187e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
16287e552db94588455c081efd87dbde0cd96d02942Ian Rogers
163ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid ThrowIllegalAccessErrorFinalField(const mirror::ArtMethod* referrer,
164ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                       mirror::ArtField* accessed) {
16587e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
16687e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
16787e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << PrettyMethod(referrer) << "'";
168ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  ThrowException(NULL, "Ljava/lang/IllegalAccessError;",
169ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                 referrer != NULL ? referrer->GetClass() : NULL,
17062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 msg.str().c_str());
17162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
17262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
1732ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) {
17462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_list args;
17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_start(args, fmt);
17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, fmt, &args);
17762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_end(args);
17887e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
17987e552db94588455c081efd87dbde0cd96d02942Ian Rogers
18062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// IllegalArgumentException
18162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
18262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) {
18362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(throw_location, "Ljava/lang/IllegalArgumentException;", NULL, msg);
18462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
18562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
18662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
18787e552db94588455c081efd87dbde0cd96d02942Ian Rogers// IncompatibleClassChangeError
18887e552db94588455c081efd87dbde0cd96d02942Ian Rogers
18987e552db94588455c081efd87dbde0cd96d02942Ian Rogersvoid ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
190ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                       mirror::ArtMethod* method,
191ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                       const mirror::ArtMethod* referrer) {
19287e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
19387e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
19487e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << expected_type << " but instead was found to be of type " << found_type;
19562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
19662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 referrer != NULL ? referrer->GetClass() : NULL,
19762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 msg.str().c_str());
19887e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
19987e552db94588455c081efd87dbde0cd96d02942Ian Rogers
200ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::ArtMethod* interface_method,
2012dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                                                                mirror::Object* this_object,
202ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                                                const mirror::ArtMethod* referrer) {
20387e552db94588455c081efd87dbde0cd96d02942Ian Rogers  // Referrer is calling interface_method on this_object, however, the interface_method isn't
20487e552db94588455c081efd87dbde0cd96d02942Ian Rogers  // implemented by this_object.
20587e552db94588455c081efd87dbde0cd96d02942Ian Rogers  CHECK(this_object != NULL);
20687e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
20787e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "Class '" << PrettyDescriptor(this_object->GetClass())
20887e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << "' does not implement interface '"
20987e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << PrettyDescriptor(interface_method->GetDeclaringClass())
21087e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << "' in call to '" << PrettyMethod(interface_method) << "'";
21162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
21262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 referrer != NULL ? referrer->GetClass() : NULL,
21362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 msg.str().c_str());
21487e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
21587e552db94588455c081efd87dbde0cd96d02942Ian Rogers
216ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_field, bool is_static,
217ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                            const mirror::ArtMethod* referrer) {
21887e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
21987e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
220b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      << (is_static ? "static" : "instance") << " field" << " rather than a "
221b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      << (is_static ? "instance" : "static") << " field";
22262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(),
22362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 msg.str().c_str());
22462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
22562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
2262ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ThrowIncompatibleClassChangeError(const mirror::Class* referrer, const char* fmt, ...) {
22762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_list args;
22862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_start(args, fmt);
22962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
23062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_end(args);
23162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
23262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
23362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// LinkageError
23462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
23562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowLinkageError(const mirror::Class* referrer, const char* fmt, ...) {
23662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_list args;
23762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_start(args, fmt);
23862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args);
23962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_end(args);
24062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
24162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
24262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// NegativeArraySizeException
24362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
24462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowNegativeArraySizeException(int size) {
245ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL,
246ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                 StringPrintf("%d", size).c_str());
24762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
24862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
24962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowNegativeArraySizeException(const char* msg) {
25062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, msg);
25162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
25262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
25362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// NoSuchFieldError
25462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
25562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
25662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                           const StringPiece& type, const StringPiece& name)
25762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
25862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ClassHelper kh(c);
25962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::ostringstream msg;
26062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  msg << "No " << scope << "field " << name << " of type " << type
26162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      << " in class " << kh.GetDescriptor() << " or its superclasses";
26262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
26387e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
26487e552db94588455c081efd87dbde0cd96d02942Ian Rogers
26587e552db94588455c081efd87dbde0cd96d02942Ian Rogers// NoSuchMethodError
26687e552db94588455c081efd87dbde0cd96d02942Ian Rogers
2672dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
26862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            const StringPiece& signature) {
26987e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
27087e552db94588455c081efd87dbde0cd96d02942Ian Rogers  ClassHelper kh(c);
27187e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "No " << type << " method " << name << signature
27287e552db94588455c081efd87dbde0cd96d02942Ian Rogers      << " in class " << kh.GetDescriptor() << " or its super classes";
27362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
27487e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
27587e552db94588455c081efd87dbde0cd96d02942Ian Rogers
27662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowNoSuchMethodError(uint32_t method_idx) {
27762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Thread* self = Thread::Current();
27862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
27962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
2804445a7e3398a6143939168097a3aa275b734504dIan Rogers  const DexFile& dex_file = *dex_cache->GetDexFile();
28187e552db94588455c081efd87dbde0cd96d02942Ian Rogers  std::ostringstream msg;
28287e552db94588455c081efd87dbde0cd96d02942Ian Rogers  msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
28362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(&throw_location, "Ljava/lang/NoSuchMethodError;",
28462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                 throw_location.GetMethod()->GetDeclaringClass(), msg.str().c_str());
28562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
28662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
28762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// NullPointerException
28862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
28962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowNullPointerExceptionForFieldAccess(const ThrowLocation& throw_location,
290ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                             mirror::ArtField* field, bool is_read) {
29162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::ostringstream msg;
29262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  msg << "Attempt to " << (is_read ? "read from" : "write to")
29362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      << " field '" << PrettyField(field, true) << "' on a null object reference";
29462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
29562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
29662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
2972d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertzstatic void ThrowNullPointerExceptionForMethodAccessImpl(const ThrowLocation& throw_location,
2982d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                                         uint32_t method_idx,
2992d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                                         const DexFile& dex_file,
3002d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                                         InvokeType type)
3012d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
30262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::ostringstream msg;
30362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  msg << "Attempt to invoke " << type << " method '"
30462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
30562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
30662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
30762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
308ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
309ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                              uint32_t method_idx,
3102d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                              InvokeType type) {
3112d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz  mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
3122d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz  const DexFile& dex_file = *dex_cache->GetDexFile();
3132d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz  ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method_idx,
3142d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                               dex_file, type);
3152d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz}
3162d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz
3172d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertzvoid ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
318ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                              mirror::ArtMethod* method,
3192d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                              InvokeType type) {
3202d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz  mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3212d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz  const DexFile& dex_file = *dex_cache->GetDexFile();
3222d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz  ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method->GetDexMethodIndex(),
3232d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                               dex_file, type);
3242d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz}
3252d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz
32662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowNullPointerExceptionFromDexPC(const ThrowLocation& throw_location) {
32762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  const DexFile::CodeItem* code = MethodHelper(throw_location.GetMethod()).GetCodeItem();
32862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint32_t throw_dex_pc = throw_location.GetDexPc();
32962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
33062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
33162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  switch (instr->Opcode()) {
33262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::INVOKE_DIRECT:
33375b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kDirect);
33475b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      break;
33562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::INVOKE_DIRECT_RANGE:
33675b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kDirect);
33762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
33862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::INVOKE_VIRTUAL:
33975b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kVirtual);
34075b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      break;
34162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::INVOKE_VIRTUAL_RANGE:
34275b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kVirtual);
34362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
34462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::INVOKE_INTERFACE:
34575b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kInterface);
34675b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      break;
34762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::INVOKE_INTERFACE_RANGE:
34875b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kInterface);
34962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
3502d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::INVOKE_VIRTUAL_QUICK:
3512d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
3522d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      // Since we replaced the method index, we ask the verifier to tell us which
3532d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      // method is invoked at this location.
354ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtMethod* method =
3552d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz          verifier::MethodVerifier::FindInvokedMethodAtDexPc(throw_location.GetMethod(),
3562d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                                             throw_location.GetDexPc());
3572d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      if (method != NULL) {
3582d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        // NPE with precise message.
3592d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        ThrowNullPointerExceptionForMethodAccess(throw_location, method, kVirtual);
3602d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      } else {
3612d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        // NPE with imprecise message.
3622d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        ThrowNullPointerException(&throw_location,
3632d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                  "Attempt to invoke a virtual method on a null object reference");
3642d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      }
3652d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      break;
3662d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    }
36762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IGET:
36862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IGET_WIDE:
36962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IGET_OBJECT:
37062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IGET_BOOLEAN:
37162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IGET_BYTE:
37262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IGET_CHAR:
37362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IGET_SHORT: {
374ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtField* field =
37575b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz          Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
37662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                             throw_location.GetMethod(), false);
37762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
37862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
37962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
3802d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::IGET_QUICK:
3812d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::IGET_WIDE_QUICK:
3822d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::IGET_OBJECT_QUICK: {
3832d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      // Since we replaced the field index, we ask the verifier to tell us which
3842d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      // field is accessed at this location.
385ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtField* field =
3862d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz          verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
3872d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                                             throw_location.GetDexPc());
3882d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      if (field != NULL) {
3892d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        // NPE with precise message.
3902d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
3912d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      } else {
3922d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        // NPE with imprecise message.
3932d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        ThrowNullPointerException(&throw_location,
3942d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                  "Attempt to read from a field on a null object reference");
3952d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      }
3962d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      break;
3972d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    }
39862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IPUT:
39962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IPUT_WIDE:
40062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IPUT_OBJECT:
40162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IPUT_BOOLEAN:
40262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IPUT_BYTE:
40362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IPUT_CHAR:
40462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::IPUT_SHORT: {
405ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtField* field =
40675b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz          Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
40762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                             throw_location.GetMethod(), false);
40862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
40962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
41062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
4112d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::IPUT_QUICK:
4122d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::IPUT_WIDE_QUICK:
4132d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    case Instruction::IPUT_OBJECT_QUICK: {
4142d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      // Since we replaced the field index, we ask the verifier to tell us which
4152d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      // field is accessed at this location.
416ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtField* field =
4172d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz          verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
4182d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                                             throw_location.GetDexPc());
4192d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      if (field != NULL) {
4202d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        // NPE with precise message.
4212d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
4222d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      } else {
4232d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        // NPE with imprecise message.
4242d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz        ThrowNullPointerException(&throw_location,
4252d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz                                  "Attempt to write to a field on a null object reference");
4262d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      }
4272d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz      break;
4282d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz    }
42962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::AGET:
43062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::AGET_WIDE:
43162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::AGET_OBJECT:
43262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::AGET_BOOLEAN:
43362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::AGET_BYTE:
43462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::AGET_CHAR:
43562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::AGET_SHORT:
43662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
43762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                     "Attempt to read from null array");
43862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
43962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::APUT:
44062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::APUT_WIDE:
44162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::APUT_OBJECT:
44262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::APUT_BOOLEAN:
44362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::APUT_BYTE:
44462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::APUT_CHAR:
44562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::APUT_SHORT:
44662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
44762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                     "Attempt to write to null array");
44862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
44962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case Instruction::ARRAY_LENGTH:
45062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
45162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                     "Attempt to get length of null array");
45262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
45362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    default: {
45462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      // TODO: We should have covered all the cases where we expect a NPE above, this
45562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      //       message/logging is so we can improve any cases we've missed in the future.
45662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      const DexFile& dex_file =
45762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers          *throw_location.GetMethod()->GetDeclaringClass()->GetDexCache()->GetDexFile();
45862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
45962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                     StringPrintf("Null pointer exception during instruction '%s'",
46062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                  instr->DumpString(&dex_file).c_str()).c_str());
46162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
46262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
46362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
46462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
46562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
46662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowNullPointerException(const ThrowLocation* throw_location, const char* msg) {
46762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(throw_location, "Ljava/lang/NullPointerException;", NULL, msg);
46862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
46962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
47062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// RuntimeException
47162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
47262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowRuntimeException(const char* fmt, ...) {
47362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_list args;
47462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_start(args, fmt);
47562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/RuntimeException;", NULL, fmt, &args);
47662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_end(args);
47762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
47862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
47962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// VerifyError
48062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
48162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid ThrowVerifyError(const mirror::Class* referrer, const char* fmt, ...) {
48262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_list args;
48362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_start(args, fmt);
48462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args);
48562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  va_end(args);
48687e552db94588455c081efd87dbde0cd96d02942Ian Rogers}
48787e552db94588455c081efd87dbde0cd96d02942Ian Rogers
48887e552db94588455c081efd87dbde0cd96d02942Ian Rogers}  // namespace art
489