Home | History | Annotate | Download | only in interpreter
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      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 "lock_count_data.h"
     18 
     19 #include <algorithm>
     20 #include <string>
     21 
     22 #include "android-base/logging.h"
     23 #include "mirror/object-inl.h"
     24 #include "thread.h"
     25 
     26 namespace art {
     27 
     28 void LockCountData::AddMonitor(Thread* self, mirror::Object* obj) {
     29   if (obj == nullptr) {
     30     return;
     31   }
     32 
     33   // If there's an error during enter, we won't have locked the monitor. So check there's no
     34   // exception.
     35   if (self->IsExceptionPending()) {
     36     return;
     37   }
     38 
     39   if (monitors_ == nullptr) {
     40     monitors_.reset(new std::vector<mirror::Object*>());
     41   }
     42   monitors_->push_back(obj);
     43 }
     44 
     45 void LockCountData::RemoveMonitorOrThrow(Thread* self, const mirror::Object* obj) {
     46   if (obj == nullptr) {
     47     return;
     48   }
     49   bool found_object = false;
     50   if (monitors_ != nullptr) {
     51     // We need to remove one pointer to ref, as duplicates are used for counting recursive locks.
     52     // We arbitrarily choose the first one.
     53     auto it = std::find(monitors_->begin(), monitors_->end(), obj);
     54     if (it != monitors_->end()) {
     55       monitors_->erase(it);
     56       found_object = true;
     57     }
     58   }
     59   if (!found_object) {
     60     // The object wasn't found. Time for an IllegalMonitorStateException.
     61     // The order here isn't fully clear. Assume that any other pending exception is swallowed.
     62     // TODO: Maybe make already pending exception a suppressed exception.
     63     self->ClearException();
     64     self->ThrowNewExceptionF("Ljava/lang/IllegalMonitorStateException;",
     65                              "did not lock monitor on object of type '%s' before unlocking",
     66                              const_cast<mirror::Object*>(obj)->PrettyTypeOf().c_str());
     67   }
     68 }
     69 
     70 // Helper to unlock a monitor. Must be NO_THREAD_SAFETY_ANALYSIS, as we can't statically show
     71 // that the object was locked.
     72 void MonitorExitHelper(Thread* self, mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS {
     73   DCHECK(self != nullptr);
     74   DCHECK(obj != nullptr);
     75   obj->MonitorExit(self);
     76 }
     77 
     78 bool LockCountData::CheckAllMonitorsReleasedOrThrow(Thread* self) {
     79   DCHECK(self != nullptr);
     80   if (monitors_ != nullptr) {
     81     if (!monitors_->empty()) {
     82       // There may be an exception pending, if the method is terminating abruptly. Clear it.
     83       // TODO: Should we add this as a suppressed exception?
     84       self->ClearException();
     85 
     86       // OK, there are monitors that are still locked. To enforce structured locking (and avoid
     87       // deadlocks) we unlock all of them before we raise the IllegalMonitorState exception.
     88       for (mirror::Object* obj : *monitors_) {
     89         MonitorExitHelper(self, obj);
     90         // If this raised an exception, ignore. TODO: Should we add this as suppressed
     91         // exceptions?
     92         if (self->IsExceptionPending()) {
     93           self->ClearException();
     94         }
     95       }
     96       // Raise an exception, just give the first object as the sample.
     97       mirror::Object* first = (*monitors_)[0];
     98       self->ThrowNewExceptionF("Ljava/lang/IllegalMonitorStateException;",
     99                                "did not unlock monitor on object of type '%s'",
    100                                mirror::Object::PrettyTypeOf(first).c_str());
    101 
    102       // To make sure this path is not triggered again, clean out the monitors.
    103       monitors_->clear();
    104 
    105       return false;
    106     }
    107   }
    108   return true;
    109 }
    110 
    111 }  // namespace art
    112