blob: 887e743a0fa7c7c48627195e1d6e90397b230edb [file] [log] [blame]
Ian Rogers57b86d42012-03-27 16:05:41 -07001/*
Elliott Hughes0f3c5532012-03-30 14:51:51 -07002 * Copyright (C) 2012 The Android Open Source Project
Ian Rogers57b86d42012-03-27 16:05:41 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "callee_save_frame.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070018#include "object.h"
19#include "object_utils.h"
20#include "runtime_support.h"
21#include "thread.h"
Ian Rogers120f1c72012-09-28 17:17:10 -070022#include "well_known_classes.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070023
24namespace art {
25
Ian Rogers474b6da2012-09-25 00:20:38 -070026// Used to implement MOVE_EXCEPTION.
27extern "C" void* GetAndClearException(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
28 DCHECK(self->IsExceptionPending());
29 Throwable* exception = self->GetException();
30 self->ClearException();
31 return exception;
32}
33
Ian Rogers57b86d42012-03-27 16:05:41 -070034// Deliver an exception that's pending on thread helping set up a callee save frame on the way.
Mathieu Chartier66f19252012-09-18 08:57:04 -070035extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -070036 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -070037 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
38 thread->DeliverException();
39}
40
41// Called by generated call to throw an exception.
Mathieu Chartier66f19252012-09-18 08:57:04 -070042extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread,
43 AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -070044 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -070045 /*
46 * exception may be NULL, in which case this routine should
47 * throw NPE. NOTE: this is a convenience for generated code,
48 * which previously did the null check inline and constructed
49 * and threw a NPE if NULL. This routine responsible for setting
50 * exception_ in thread and delivering the exception.
51 */
52 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
53 if (exception == NULL) {
54 thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
55 } else {
56 thread->SetException(exception);
57 }
58 thread->DeliverException();
59}
60
61// Called by generated call to throw a NPE exception.
Mathieu Chartier66f19252012-09-18 08:57:04 -070062extern "C" void artThrowNullPointerExceptionFromCode(Thread* self,
63 AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -070064 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -070065 FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
Ian Rogers0399dde2012-06-06 17:09:28 -070066 uint32_t dex_pc;
Mathieu Chartier66f19252012-09-18 08:57:04 -070067 AbstractMethod* throw_method = self->GetCurrentMethod(&dex_pc);
Ian Rogers87e552d2012-08-31 15:54:48 -070068 ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -070069 self->DeliverException();
70}
71
72// Called by generated call to throw an arithmetic divide by zero exception.
Mathieu Chartier66f19252012-09-18 08:57:04 -070073extern "C" void artThrowDivZeroFromCode(Thread* thread,
74 AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -070075 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -070076 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
77 thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
78 thread->DeliverException();
79}
80
81// Called by generated call to throw an array index out of bounds exception.
Mathieu Chartier66f19252012-09-18 08:57:04 -070082extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread,
83 AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -070084 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -070085 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
86 thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
87 "length=%d; index=%d", limit, index);
88 thread->DeliverException();
89}
90
Ian Rogers120f1c72012-09-28 17:17:10 -070091extern "C" void artThrowStackOverflowFromCode(Thread* self, AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -070092 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers120f1c72012-09-28 17:17:10 -070093 FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
94 CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow.";
Elliott Hughes6cf23882012-06-15 15:42:07 -070095 // Remove extra entry pushed onto second stack during method tracing.
Ian Rogers57b86d42012-03-27 16:05:41 -070096 if (Runtime::Current()->IsMethodTracingActive()) {
Ian Rogers120f1c72012-09-28 17:17:10 -070097 TraceMethodUnwindFromCode(self);
Ian Rogers57b86d42012-03-27 16:05:41 -070098 }
Ian Rogers120f1c72012-09-28 17:17:10 -070099 self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute.
100 JNIEnvExt* env = self->GetJniEnv();
101 std::string msg("stack size ");
102 msg += PrettySize(self->GetStackSize());
103 // Use low-level JNI routine and pre-baked error class to avoid class linking operations that
104 // would consume more stack.
105 int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError,
106 msg.c_str(), NULL);
107 if (rc != JNI_OK) {
108 // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME
109 // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError
110 // instead.
111 LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed.";
112 CHECK(self->IsExceptionPending());
113 }
114 self->ResetDefaultStackEnd(); // Return to default stack size.
115 self->DeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -0700116}
117
Mathieu Chartier66f19252012-09-18 08:57:04 -0700118extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self,
119 AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700120 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700121 FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
Mathieu Chartier66f19252012-09-18 08:57:04 -0700122 AbstractMethod* method = self->GetCurrentMethod();
Ian Rogers87e552d2012-08-31 15:54:48 -0700123 ThrowNoSuchMethodError(method_idx, method);
Ian Rogers57b86d42012-03-27 16:05:41 -0700124 self->DeliverException();
125}
126
Ian Rogers57b86d42012-03-27 16:05:41 -0700127} // namespace art