168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers/*
268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Copyright (C) 2011 The Android Open Source Project
368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Licensed under the Apache License, Version 2.0 (the "License");
568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * you may not use this file except in compliance with the License.
668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * You may obtain a copy of the License at
768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *      http://www.apache.org/licenses/LICENSE-2.0
968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
1068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Unless required by applicable law or agreed to in writing, software
1168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * distributed under the License is distributed on an "AS IS" BASIS,
1268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * See the License for the specific language governing permissions and
1468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * limitations under the License.
1568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers */
1668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#ifndef ART_RUNTIME_JNI_ENV_EXT_H_
1868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define ART_RUNTIME_JNI_ENV_EXT_H_
1968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
2068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include <jni.h>
2168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
2268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "base/macros.h"
2368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "base/mutex.h"
2468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "indirect_reference_table.h"
2568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "object_callbacks.h"
2668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "reference_table.h"
2768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
2868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersnamespace art {
2968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
3068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersclass JavaVMExt;
3168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
3268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers// Maximum number of local references in the indirect reference table. The value is arbitrary but
3368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers// low enough that it forces sanity checks.
3468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersstatic constexpr size_t kLocalsMax = 512;
3568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
3668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersstruct JNIEnvExt : public JNIEnv {
373f5881fda3606b27e30bf903052c73b03910f90bAndreas Gampe  static JNIEnvExt* Create(Thread* self, JavaVMExt* vm);
383f5881fda3606b27e30bf903052c73b03910f90bAndreas Gampe
3968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  ~JNIEnvExt();
4068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
4168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void DumpReferenceTables(std::ostream& os)
4268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
4368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
4468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void SetCheckJniEnabled(bool enabled);
4568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
4668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void PushFrame(int capacity);
4768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void PopFrame();
4868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
4968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  template<typename T>
5068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  T AddLocalReference(mirror::Object* obj)
5168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
5268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
5368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static Offset SegmentStateOffset();
5468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
5568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static Offset LocalRefCookieOffset() {
5668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return Offset(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie));
5768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
5868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
5968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static Offset SelfOffset() {
6068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return Offset(OFFSETOF_MEMBER(JNIEnvExt, self));
6168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
6268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
6368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jobject NewLocalRef(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
6468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void DeleteLocalRef(jobject obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
6568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
6668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  Thread* const self;
6768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JavaVMExt* const vm;
6868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
6968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Cookie used when using the local indirect reference table.
7068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  uint32_t local_ref_cookie;
7168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
7268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // JNI local references.
7368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  IndirectReferenceTable locals GUARDED_BY(Locks::mutator_lock_);
7468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
7568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Stack of cookies corresponding to PushLocalFrame/PopLocalFrame calls.
7668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // TODO: to avoid leaks (and bugs), we need to clear this vector on entry (or return)
7768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // to a native method.
7868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  std::vector<uint32_t> stacked_local_ref_cookies;
7968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
8068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Frequently-accessed fields cached from JavaVM.
8168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool check_jni;
8268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
8368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // How many nested "critical" JNI calls are we in?
8468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  int critical;
8568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
8668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Entered JNI monitors, for bulk exit on thread detach.
8768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  ReferenceTable monitors;
8868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
8968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Used by -Xcheck:jni.
9068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const JNINativeInterface* unchecked_functions;
913f5881fda3606b27e30bf903052c73b03910f90bAndreas Gampe
923f5881fda3606b27e30bf903052c73b03910f90bAndreas Gampe private:
933f5881fda3606b27e30bf903052c73b03910f90bAndreas Gampe  // The constructor should not be called directly. It may leave the object in an erronuous state,
943f5881fda3606b27e30bf903052c73b03910f90bAndreas Gampe  // and the result needs to be checked.
953f5881fda3606b27e30bf903052c73b03910f90bAndreas Gampe  JNIEnvExt(Thread* self, JavaVMExt* vm);
9668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers};
9768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
9868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers// Used to save and restore the JNIEnvExt state when not going through code created by the JNI
9968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers// compiler.
10068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersclass ScopedJniEnvLocalRefState {
10168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers public:
10268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  explicit ScopedJniEnvLocalRefState(JNIEnvExt* env) : env_(env) {
10368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    saved_local_ref_cookie_ = env->local_ref_cookie;
10468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    env->local_ref_cookie = env->locals.GetSegmentState();
10568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
10668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
10768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  ~ScopedJniEnvLocalRefState() {
10868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    env_->locals.SetSegmentState(env_->local_ref_cookie);
10968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    env_->local_ref_cookie = saved_local_ref_cookie_;
11068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
11168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
11268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
11368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JNIEnvExt* const env_;
11468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  uint32_t saved_local_ref_cookie_;
11568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
11668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  DISALLOW_COPY_AND_ASSIGN(ScopedJniEnvLocalRefState);
11768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers};
11868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
11968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers}  // namespace art
12068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
12168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#endif  // ART_RUNTIME_JNI_ENV_EXT_H_
122