15c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko/*
25c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Copyright (C) 2013 The Android Open Source Project
35c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko *
45c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Licensed under the Apache License, Version 2.0 (the "License");
55c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * you may not use this file except in compliance with the License.
65c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * You may obtain a copy of the License at
75c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko *
85c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko *      http://www.apache.org/licenses/LICENSE-2.0
95c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko *
105c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * Unless required by applicable law or agreed to in writing, software
115c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * distributed under the License is distributed on an "AS IS" BASIS,
125c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * See the License for the specific language governing permissions and
145c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko * limitations under the License.
155c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko */
165c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
175c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include <algorithm>
185c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include <utility>
195c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include "thread.h"
205c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include "thread-inl.h"
215c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include "base/mutex.h"
225c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include "base/mutex-inl.h"
235c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include "base/logging.h"
245c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include "driver/compiler_driver.h"
255c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
265c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko#include "dex_file_to_method_inliner_map.h"
275c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
285c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Markonamespace art {
295c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
30867a2b35e67ddcbec089964e8f3cd9a827186e48Vladimir MarkoDexFileToMethodInlinerMap::DexFileToMethodInlinerMap()
31e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    : lock_("DexFileToMethodInlinerMap lock", kDexFileToMethodInlinerMapLock) {
325c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}
335c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
345c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir MarkoDexFileToMethodInlinerMap::~DexFileToMethodInlinerMap() {
355c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko  for (auto& entry : inliners_) {
365c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko    delete entry.second;
375c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko  }
385c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}
395c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
40e13717e796d338b08ea66f6a7e3470ca44de707fVladimir MarkoDexFileMethodInliner* DexFileToMethodInlinerMap::GetMethodInliner(const DexFile* dex_file) {
415c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko  Thread* self = Thread::Current();
425c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko  {
43e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    ReaderMutexLock mu(self, lock_);
445c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko    auto it = inliners_.find(dex_file);
455c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko    if (it != inliners_.end()) {
46e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko      return it->second;
475c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko    }
485c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko  }
495c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
50e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  // We need to acquire our lock_ to modify inliners_ but we want to release it
51e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  // before we initialize the new inliner. However, we need to acquire the
52e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  // new inliner's lock_ before we release our lock_ to prevent another thread
53e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  // from using the uninitialized inliner. This requires explicit calls to
54e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  // ExclusiveLock()/ExclusiveUnlock() on one of the locks, the other one
55e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  // can use WriterMutexLock.
56e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  DexFileMethodInliner* locked_inliner;
57e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  {
58e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    WriterMutexLock mu(self, lock_);
59e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    DexFileMethodInliner** inliner = &inliners_[dex_file];  // inserts new entry if not found
60e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    if (*inliner) {
61e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko      return *inliner;
62e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    }
63e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    *inliner = new DexFileMethodInliner;
64e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    DCHECK(*inliner != nullptr);
65e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    locked_inliner = *inliner;
66e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko    locked_inliner->lock_.ExclusiveLock(self);  // Acquire inliner's lock_ before releasing lock_.
675c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko  }
68e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  locked_inliner->FindIntrinsics(dex_file);
69e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  locked_inliner->lock_.ExclusiveUnlock(self);
70e13717e796d338b08ea66f6a7e3470ca44de707fVladimir Marko  return locked_inliner;
715c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}
725c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko
735c96e6b4dc354a7439b211b93462fbe8edea5e57Vladimir Marko}  // namespace art
74