jvm.cpp revision 356:1ee8caae33af
1130561Sobrien/*
2218822Sdim * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
3130561Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
468765Sobrien *
5130561Sobrien * This code is free software; you can redistribute it and/or modify it
677298Sobrien * under the terms of the GNU General Public License version 2 only, as
7130561Sobrien * published by the Free Software Foundation.
868765Sobrien *
968765Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT
1068765Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1168765Sobrien * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12104834Sobrien * version 2 for more details (a copy is included in the LICENSE file that
13104834Sobrien * accompanied this code).
14104834Sobrien *
15104834Sobrien * You should have received a copy of the GNU General Public License version
16104834Sobrien * 2 along with this work; if not, write to the Free Software Foundation,
17104834Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18104834Sobrien *
19104834Sobrien * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20104834Sobrien * CA 95054 USA or visit www.sun.com if you need additional information or
2168765Sobrien * have any questions.
2268765Sobrien *
2368765Sobrien */
2468765Sobrien
2568765Sobrien#include "incls/_precompiled.incl"
2668765Sobrien#include "incls/_jvm.cpp.incl"
2768765Sobrien#include <errno.h>
28218822Sdim
2968765Sobrien/*
3068765Sobrien  NOTE about use of any ctor or function call that can trigger a safepoint/GC:
31130561Sobrien  such ctors and calls MUST NOT come between an oop declaration/init and its
32130561Sobrien  usage because if objects are move this may cause various memory stomps, bus
33130561Sobrien  errors and segfaults. Here is a cookbook for causing so called "naked oop
3468765Sobrien  failures":
35130561Sobrien
36130561Sobrien      JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields<etc> {
37130561Sobrien          JVMWrapper("JVM_GetClassDeclaredFields");
38130561Sobrien
39130561Sobrien          // Object address to be held directly in mirror & not visible to GC
40130561Sobrien          oop mirror = JNIHandles::resolve_non_null(ofClass);
41130561Sobrien
42130561Sobrien          // If this ctor can hit a safepoint, moving objects around, then
43130561Sobrien          ComplexConstructor foo;
44130561Sobrien
45218822Sdim          // Boom! mirror may point to JUNK instead of the intended object
46218822Sdim          (some dereference of mirror)
47218822Sdim
48218822Sdim          // Here's another call that may block for GC, making mirror stale
49130561Sobrien          MutexLocker ml(some_lock);
50130561Sobrien
51130561Sobrien          // And here's an initializer that can result in a stale oop
52130561Sobrien          // all in one step.
53130561Sobrien          oop o = call_that_can_throw_exception(TRAPS);
54130561Sobrien
55130561Sobrien
56130561Sobrien  The solution is to keep the oop declaration BELOW the ctor or function
57218822Sdim  call that might cause a GC, do another resolve to reassign the oop, or
58130561Sobrien  consider use of a Handle instead of an oop so there is immunity from object
59130561Sobrien  motion. But note that the "QUICK" entries below do not have a handlemark
60130561Sobrien  and thus can only support use of handles passed in.
61130561Sobrien*/
62130561Sobrien
63130561Sobrienstatic void trace_class_resolution_impl(klassOop to_class, TRAPS) {
64218822Sdim  ResourceMark rm;
65130561Sobrien  int line_number = -1;
66130561Sobrien  const char * source_file = NULL;
67130561Sobrien  klassOop caller = NULL;
68130561Sobrien  JavaThread* jthread = JavaThread::current();
69130561Sobrien  if (jthread->has_last_Java_frame()) {
70130561Sobrien    vframeStream vfst(jthread);
71130561Sobrien
72130561Sobrien    // scan up the stack skipping ClassLoader, AccessController and PrivilegedAction frames
73218822Sdim    symbolHandle access_controller = oopFactory::new_symbol_handle("java/security/AccessController", CHECK);
74130561Sobrien    klassOop access_controller_klass = SystemDictionary::resolve_or_fail(access_controller, false, CHECK);
75130561Sobrien    symbolHandle privileged_action = oopFactory::new_symbol_handle("java/security/PrivilegedAction", CHECK);
76218822Sdim    klassOop privileged_action_klass = SystemDictionary::resolve_or_fail(privileged_action, false, CHECK);
77218822Sdim
78218822Sdim    methodOop last_caller = NULL;
79218822Sdim
80218822Sdim    while (!vfst.at_end()) {
81218822Sdim      methodOop m = vfst.method();
82130561Sobrien      if (!vfst.method()->method_holder()->klass_part()->is_subclass_of(SystemDictionary::classloader_klass())&&
83130561Sobrien          !vfst.method()->method_holder()->klass_part()->is_subclass_of(access_controller_klass) &&
84218822Sdim          !vfst.method()->method_holder()->klass_part()->is_subclass_of(privileged_action_klass)) {
85218822Sdim        break;
86218822Sdim      }
87130561Sobrien      last_caller = m;
88130561Sobrien      vfst.next();
89130561Sobrien    }
90130561Sobrien    // if this is called from Class.forName0 and that is called from Class.forName,
91130561Sobrien    // then print the caller of Class.forName.  If this is Class.loadClass, then print
92130561Sobrien    // that caller, otherwise keep quiet since this should be picked up elsewhere.
93130561Sobrien    bool found_it = false;
94130561Sobrien    if (!vfst.at_end() &&
95130561Sobrien        instanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class() &&
96130561Sobrien        vfst.method()->name() == vmSymbols::forName0_name()) {
97218822Sdim      vfst.next();
98218822Sdim      if (!vfst.at_end() &&
99218822Sdim          instanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class() &&
100218822Sdim          vfst.method()->name() == vmSymbols::forName_name()) {
10168765Sobrien        vfst.next();
10268765Sobrien        found_it = true;
10368765Sobrien      }
10468765Sobrien    } else if (last_caller != NULL &&
105130561Sobrien               instanceKlass::cast(last_caller->method_holder())->name() ==
10668765Sobrien               vmSymbols::java_lang_ClassLoader() &&
10768765Sobrien               (last_caller->name() == vmSymbols::loadClassInternal_name() ||
10868765Sobrien                last_caller->name() == vmSymbols::loadClass_name())) {
10968765Sobrien      found_it = true;
11068765Sobrien    }
11168765Sobrien    if (found_it && !vfst.at_end()) {
11268765Sobrien      // found the caller
11368765Sobrien      caller = vfst.method()->method_holder();
114218822Sdim      line_number = vfst.method()->line_number_from_bci(vfst.bci());
115218822Sdim      symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
116218822Sdim      if (s != NULL) {
117218822Sdim        source_file = s->as_C_string();
118218822Sdim      }
119218822Sdim    }
120218822Sdim  }
121218822Sdim  if (caller != NULL) {
122218822Sdim    if (to_class != caller) {
123218822Sdim      const char * from = Klass::cast(caller)->external_name();
124218822Sdim      const char * to = Klass::cast(to_class)->external_name();
125218822Sdim      // print in a single call to reduce interleaving between threads
12668765Sobrien      if (source_file != NULL) {
12768765Sobrien        tty->print("RESOLVE %s %s %s:%d (explicit)\n", from, to, source_file, line_number);
12868765Sobrien      } else {
129130561Sobrien        tty->print("RESOLVE %s %s (explicit)\n", from, to);
13068765Sobrien      }
131130561Sobrien    }
132130561Sobrien  }
133130561Sobrien}
134130561Sobrien
135130561Sobrienstatic void trace_class_resolution(klassOop to_class) {
136130561Sobrien  EXCEPTION_MARK;
137130561Sobrien  trace_class_resolution_impl(to_class, THREAD);
138130561Sobrien  if (HAS_PENDING_EXCEPTION) {
139130561Sobrien    CLEAR_PENDING_EXCEPTION;
140218822Sdim  }
141130561Sobrien}
142130561Sobrien
143130561Sobrien// Wrapper to trace JVM functions
144218822Sdim
145218822Sdim#ifdef ASSERT
146130561Sobrien  class JVMTraceWrapper : public StackObj {
147130561Sobrien   public:
148130561Sobrien    JVMTraceWrapper(const char* format, ...) {
149218822Sdim      if (TraceJVMCalls) {
150218822Sdim        va_list ap;
151130561Sobrien        va_start(ap, format);
152130561Sobrien        tty->print("JVM ");
153130561Sobrien        tty->vprint_cr(format, ap);
154218822Sdim        va_end(ap);
155218822Sdim      }
156130561Sobrien    }
157130561Sobrien  };
158218822Sdim
159130561Sobrien  Histogram* JVMHistogram;
160130561Sobrien  volatile jint JVMHistogram_lock = 0;
161218822Sdim
162130561Sobrien  class JVMHistogramElement : public HistogramElement {
163130561Sobrien    public:
164218822Sdim     JVMHistogramElement(const char* name);
165130561Sobrien  };
166218822Sdim
167218822Sdim  JVMHistogramElement::JVMHistogramElement(const char* elementName) {
168218822Sdim    _name = elementName;
169218822Sdim    uintx count = 0;
170130561Sobrien
171218822Sdim    while (Atomic::cmpxchg(1, &JVMHistogram_lock, 0) != 0) {
172130561Sobrien      while (OrderAccess::load_acquire(&JVMHistogram_lock) != 0) {
173130561Sobrien        count +=1;
174130561Sobrien        if ( (WarnOnStalledSpinLock > 0)
175130561Sobrien          && (count % WarnOnStalledSpinLock == 0)) {
176130561Sobrien          warning("JVMHistogram_lock seems to be stalled");
177130561Sobrien        }
178130561Sobrien      }
179130561Sobrien     }
180130561Sobrien
18168765Sobrien    if(JVMHistogram == NULL)
182130561Sobrien      JVMHistogram = new Histogram("JVM Call Counts",100);
183130561Sobrien
184130561Sobrien    JVMHistogram->add_element(this);
185130561Sobrien    Atomic::dec(&JVMHistogram_lock);
186130561Sobrien  }
187130561Sobrien
188130561Sobrien  #define JVMCountWrapper(arg) \
189130561Sobrien      static JVMHistogramElement* e = new JVMHistogramElement(arg); \
19068765Sobrien      if (e != NULL) e->increment_count();  // Due to bug in VC++, we need a NULL check here eventhough it should never happen!
191130561Sobrien
192130561Sobrien  #define JVMWrapper(arg1)                    JVMCountWrapper(arg1); JVMTraceWrapper(arg1)
193130561Sobrien  #define JVMWrapper2(arg1, arg2)             JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2)
194130561Sobrien  #define JVMWrapper3(arg1, arg2, arg3)       JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3)
19568765Sobrien  #define JVMWrapper4(arg1, arg2, arg3, arg4) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3, arg4)
196130561Sobrien#else
197218822Sdim  #define JVMWrapper(arg1)
198218822Sdim  #define JVMWrapper2(arg1, arg2)
199130561Sobrien  #define JVMWrapper3(arg1, arg2, arg3)
200130561Sobrien  #define JVMWrapper4(arg1, arg2, arg3, arg4)
201130561Sobrien#endif
202130561Sobrien
203130561Sobrien
20477298Sobrien// Interface version /////////////////////////////////////////////////////////////////////
20577298Sobrien
20677298Sobrien
207130561SobrienJVM_LEAF(jint, JVM_GetInterfaceVersion())
208130561Sobrien  return JVM_INTERFACE_VERSION;
20977298SobrienJVM_END
210130561Sobrien
21189857Sobrien
212130561Sobrien// java.lang.System //////////////////////////////////////////////////////////////////////
213130561Sobrien
214130561Sobrien
215130561SobrienJVM_LEAF(jlong, JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored))
216130561Sobrien  JVMWrapper("JVM_CurrentTimeMillis");
217130561Sobrien  return os::javaTimeMillis();
218130561SobrienJVM_END
219130561Sobrien
220130561SobrienJVM_LEAF(jlong, JVM_NanoTime(JNIEnv *env, jclass ignored))
221130561Sobrien  JVMWrapper("JVM_NanoTime");
222130561Sobrien  return os::javaTimeNanos();
223130561SobrienJVM_END
224130561Sobrien
225130561Sobrien
226130561SobrienJVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
227130561Sobrien                               jobject dst, jint dst_pos, jint length))
228130561Sobrien  JVMWrapper("JVM_ArrayCopy");
229130561Sobrien  // Check if we have null pointers
230130561Sobrien  if (src == NULL || dst == NULL) {
231130561Sobrien    THROW(vmSymbols::java_lang_NullPointerException());
23268765Sobrien  }
233130561Sobrien  arrayOop s = arrayOop(JNIHandles::resolve_non_null(src));
23468765Sobrien  arrayOop d = arrayOop(JNIHandles::resolve_non_null(dst));
235130561Sobrien  assert(s->is_oop(), "JVM_ArrayCopy: src not an oop");
236130561Sobrien  assert(d->is_oop(), "JVM_ArrayCopy: dst not an oop");
23768765Sobrien  // Do copy
238130561Sobrien  Klass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, thread);
239130561SobrienJVM_END
240130561Sobrien
24168765Sobrien
242130561Sobrienstatic void set_property(Handle props, const char* key, const char* value, TRAPS) {
243130561Sobrien  JavaValue r(T_OBJECT);
244130561Sobrien  // public synchronized Object put(Object key, Object value);
245218822Sdim  HandleMark hm(THREAD);
246130561Sobrien  Handle key_str    = java_lang_String::create_from_platform_dependent_str(key, CHECK);
24777298Sobrien  Handle value_str  = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : ""), CHECK);
248130561Sobrien  JavaCalls::call_virtual(&r,
24977298Sobrien                          props,
250130561Sobrien                          KlassHandle(THREAD, SystemDictionary::properties_klass()),
251130561Sobrien                          vmSymbolHandles::put_name(),
252130561Sobrien                          vmSymbolHandles::object_object_object_signature(),
253130561Sobrien                          key_str,
254130561Sobrien                          value_str,
255130561Sobrien                          THREAD);
256130561Sobrien}
257130561Sobrien
258130561Sobrien
259130561Sobrien#define PUTPROP(props, name, value) set_property((props), (name), (value), CHECK_(properties));
260130561Sobrien
26168765Sobrien
26268765SobrienJVM_ENTRY(jobject, JVM_InitProperties(JNIEnv *env, jobject properties))
263218822Sdim  JVMWrapper("JVM_InitProperties");
26468765Sobrien  ResourceMark rm;
265218822Sdim
26668765Sobrien  Handle props(THREAD, JNIHandles::resolve_non_null(properties));
267130561Sobrien
268130561Sobrien  // System property list includes both user set via -D option and
269130561Sobrien  // jvm system specific properties.
270130561Sobrien  for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
271130561Sobrien    PUTPROP(props, p->key(), p->value());
272130561Sobrien  }
273218822Sdim
274218822Sdim  // Convert the -XX:MaxDirectMemorySize= command line flag
275218822Sdim  // to the sun.nio.MaxDirectMemorySize property.
276218822Sdim  // Do this after setting user properties to prevent people
277218822Sdim  // from setting the value with a -D option, as requested.
278218822Sdim  {
279218822Sdim    char as_chars[256];
280218822Sdim    jio_snprintf(as_chars, sizeof(as_chars), INTX_FORMAT, MaxDirectMemorySize);
281218822Sdim    PUTPROP(props, "sun.nio.MaxDirectMemorySize", as_chars);
282218822Sdim  }
283218822Sdim
284218822Sdim  // JVM monitoring and management support
285218822Sdim  // Add the sun.management.compiler property for the compiler's name
286218822Sdim  {
287218822Sdim#undef CSIZE
288218822Sdim#if defined(_LP64) || defined(_WIN64)
289218822Sdim  #define CSIZE "64-Bit "
290218822Sdim#else
291218822Sdim  #define CSIZE
292218822Sdim#endif // 64bit
293218822Sdim
294130561Sobrien#ifdef TIERED
295130561Sobrien    const char* compiler_name = "HotSpot " CSIZE "Tiered Compilers";
296130561Sobrien#else
297130561Sobrien#if defined(COMPILER1)
298130561Sobrien    const char* compiler_name = "HotSpot " CSIZE "Client Compiler";
299218822Sdim#elif defined(COMPILER2)
300218822Sdim    const char* compiler_name = "HotSpot " CSIZE "Server Compiler";
30168765Sobrien#else
30268765Sobrien    const char* compiler_name = "";
303130561Sobrien#endif // compilers
304218822Sdim#endif // TIERED
305130561Sobrien
30668765Sobrien    if (*compiler_name != '\0' &&
307130561Sobrien        (Arguments::mode() != Arguments::_int)) {
308218822Sdim      PUTPROP(props, "sun.management.compiler", compiler_name);
30968765Sobrien    }
310130561Sobrien  }
311218822Sdim
312218822Sdim  return properties;
313218822SdimJVM_END
31468765Sobrien
315130561Sobrien
316218822Sdim// java.lang.Runtime /////////////////////////////////////////////////////////////////////////
31768765Sobrien
318130561Sobrienextern volatile jint vm_created;
319218822Sdim
320218822SdimJVM_ENTRY_NO_ENV(void, JVM_Exit(jint code))
32168765Sobrien  if (vm_created != 0 && (code == 0)) {
322130561Sobrien    // The VM is about to exit. We call back into Java to check whether finalizers should be run
323218822Sdim    Universe::run_finalizers_on_exit();
324218822Sdim  }
32568765Sobrien  before_exit(thread);
326130561Sobrien  vm_exit(code);
327218822SdimJVM_END
328218822Sdim
32968765Sobrien
330130561SobrienJVM_ENTRY_NO_ENV(void, JVM_Halt(jint code))
331218822Sdim  before_exit(thread);
332218822Sdim  vm_exit(code);
33368765SobrienJVM_END
334130561Sobrien
335218822Sdim
336218822SdimJVM_LEAF(void, JVM_OnExit(void (*func)(void)))
33768765Sobrien  register_on_exit_function(func);
338130561SobrienJVM_END
339218822Sdim
34068765Sobrien
341130561SobrienJVM_ENTRY_NO_ENV(void, JVM_GC(void))
342218822Sdim  JVMWrapper("JVM_GC");
34368765Sobrien  if (!DisableExplicitGC) {
344130561Sobrien    Universe::heap()->collect(GCCause::_java_lang_system_gc);
345218822Sdim  }
34689857SobrienJVM_END
347130561Sobrien
348218822Sdim
34989857SobrienJVM_LEAF(jlong, JVM_MaxObjectInspectionAge(void))
350218822Sdim  JVMWrapper("JVM_MaxObjectInspectionAge");
35189857Sobrien  return Universe::heap()->millis_since_last_gc();
352218822SdimJVM_END
35368765Sobrien
354218822Sdim
35568765SobrienJVM_LEAF(void, JVM_TraceInstructions(jboolean on))
356218822Sdim  if (PrintJVMWarnings) warning("JVM_TraceInstructions not supported");
35768765SobrienJVM_END
358218822Sdim
35968765Sobrien
360218822SdimJVM_LEAF(void, JVM_TraceMethodCalls(jboolean on))
36168765Sobrien  if (PrintJVMWarnings) warning("JVM_TraceMethodCalls not supported");
362218822SdimJVM_END
36368765Sobrien
364218822Sdimstatic inline jlong convert_size_t_to_jlong(size_t val) {
36568765Sobrien  // In the 64-bit vm, a size_t can overflow a jlong (which is signed).
366218822Sdim  NOT_LP64 (return (jlong)val;)
36768765Sobrien  LP64_ONLY(return (jlong)MIN2(val, (size_t)max_jlong);)
368218822Sdim}
36968765Sobrien
370218822SdimJVM_ENTRY_NO_ENV(jlong, JVM_TotalMemory(void))
37168765Sobrien  JVMWrapper("JVM_TotalMemory");
372218822Sdim  size_t n = Universe::heap()->capacity();
37368765Sobrien  return convert_size_t_to_jlong(n);
374130561SobrienJVM_END
375218822Sdim
37668765Sobrien
377130561SobrienJVM_ENTRY_NO_ENV(jlong, JVM_FreeMemory(void))
378218822Sdim  JVMWrapper("JVM_FreeMemory");
37968765Sobrien  CollectedHeap* ch = Universe::heap();
380130561Sobrien  size_t n;
381218822Sdim  {
38268765Sobrien     MutexLocker x(Heap_lock);
383130561Sobrien     n = ch->capacity() - ch->used();
384218822Sdim  }
38568765Sobrien  return convert_size_t_to_jlong(n);
386218822SdimJVM_END
38768765Sobrien
388130561Sobrien
389218822SdimJVM_ENTRY_NO_ENV(jlong, JVM_MaxMemory(void))
39068765Sobrien  JVMWrapper("JVM_MaxMemory");
391130561Sobrien  size_t n = Universe::heap()->max_capacity();
392218822Sdim  return convert_size_t_to_jlong(n);
39377298SobrienJVM_END
394218822Sdim
39568765Sobrien
396130561SobrienJVM_ENTRY_NO_ENV(jint, JVM_ActiveProcessorCount(void))
397218822Sdim  JVMWrapper("JVM_ActiveProcessorCount");
39868765Sobrien  return os::active_processor_count();
399218822SdimJVM_END
40068765Sobrien
401218822Sdim
40277298Sobrien
403218822Sdim// java.lang.Throwable //////////////////////////////////////////////////////
40477298Sobrien
405218822Sdim
40677298SobrienJVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver))
407130561Sobrien  JVMWrapper("JVM_FillInStackTrace");
408218822Sdim  Handle exception(thread, JNIHandles::resolve_non_null(receiver));
40968765Sobrien  java_lang_Throwable::fill_in_stack_trace(exception);
410218822SdimJVM_END
41168765Sobrien
412218822Sdim
41368765SobrienJVM_ENTRY(void, JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable))
414218822Sdim  JVMWrapper("JVM_PrintStackTrace");
415218822Sdim  // Note: This is no longer used in Merlin, but we still support it for compatibility.
41668765Sobrien  oop exception = JNIHandles::resolve_non_null(receiver);
417218822Sdim  oop stream    = JNIHandles::resolve_non_null(printable);
418218822Sdim  java_lang_Throwable::print_stack_trace(exception, stream);
419218822SdimJVM_END
420130561Sobrien
421218822Sdim
42268765SobrienJVM_ENTRY(jint, JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable))
423130561Sobrien  JVMWrapper("JVM_GetStackTraceDepth");
424218822Sdim  oop exception = JNIHandles::resolve(throwable);
42568765Sobrien  return java_lang_Throwable::get_stack_trace_depth(exception, THREAD);
426218822SdimJVM_END
427218822Sdim
428218822Sdim
429218822SdimJVM_ENTRY(jobject, JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index))
430218822Sdim  JVMWrapper("JVM_GetStackTraceElement");
431218822Sdim  JvmtiVMObjectAllocEventCollector oam; // This ctor (throughout this module) may trigger a safepoint/GC
432218822Sdim  oop exception = JNIHandles::resolve(throwable);
433218822Sdim  oop element = java_lang_Throwable::get_stack_trace_element(exception, index, CHECK_NULL);
434218822Sdim  return JNIHandles::make_local(env, element);
435218822SdimJVM_END
436218822Sdim
437218822Sdim
438218822Sdim// java.lang.Object ///////////////////////////////////////////////
439218822Sdim
440218822Sdim
441130561SobrienJVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
442218822Sdim  JVMWrapper("JVM_IHashCode");
44368765Sobrien  // as implemented in the classic virtual machine; return 0 if object is NULL
444130561Sobrien  return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
445218822SdimJVM_END
44668765Sobrien
447130561Sobrien
448218822SdimJVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
44968765Sobrien  JVMWrapper("JVM_MonitorWait");
450130561Sobrien  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
451218822Sdim  assert(obj->is_instance() || obj->is_array(), "JVM_MonitorWait must apply to an object");
45268765Sobrien  JavaThreadInObjectWaitState jtiows(thread, ms != 0);
453130561Sobrien  if (JvmtiExport::should_post_monitor_wait()) {
454218822Sdim    JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
455218822Sdim  }
456218822Sdim  ObjectSynchronizer::wait(obj, ms, CHECK);
45768765SobrienJVM_END
458130561Sobrien
459218822Sdim
460218822SdimJVM_ENTRY(void, JVM_MonitorNotify(JNIEnv* env, jobject handle))
461218822Sdim  JVMWrapper("JVM_MonitorNotify");
46268765Sobrien  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
463130561Sobrien  assert(obj->is_instance() || obj->is_array(), "JVM_MonitorNotify must apply to an object");
464218822Sdim  ObjectSynchronizer::notify(obj, CHECK);
46568765SobrienJVM_END
46668765Sobrien
467218822Sdim
46868765SobrienJVM_ENTRY(void, JVM_MonitorNotifyAll(JNIEnv* env, jobject handle))
469218822Sdim  JVMWrapper("JVM_MonitorNotifyAll");
470218822Sdim  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
471218822Sdim  assert(obj->is_instance() || obj->is_array(), "JVM_MonitorNotifyAll must apply to an object");
47268765Sobrien  ObjectSynchronizer::notifyall(obj, CHECK);
473130561SobrienJVM_END
474130561Sobrien
475130561Sobrien
476218822SdimJVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
47768765Sobrien  JVMWrapper("JVM_Clone");
478130561Sobrien  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
47968765Sobrien  const KlassHandle klass (THREAD, obj->klass());
480130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
481218822Sdim
482218822Sdim#ifdef ASSERT
483218822Sdim  // Just checking that the cloneable flag is set correct
484218822Sdim  if (obj->is_javaArray()) {
485218822Sdim    guarantee(klass->is_cloneable(), "all arrays are cloneable");
48668765Sobrien  } else {
487130561Sobrien    guarantee(obj->is_instance(), "should be instanceOop");
488130561Sobrien    bool cloneable = klass->is_subtype_of(SystemDictionary::cloneable_klass());
48968765Sobrien    guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag");
490130561Sobrien  }
491130561Sobrien#endif
492130561Sobrien
493130561Sobrien  // Check if class of obj supports the Cloneable interface.
494130561Sobrien  // All arrays are considered to be cloneable (See JLS 20.1.5)
495130561Sobrien  if (!klass->is_cloneable()) {
496130561Sobrien    ResourceMark rm(THREAD);
497130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name());
498130561Sobrien  }
499130561Sobrien
500130561Sobrien  // Make shallow object copy
501130561Sobrien  const int size = obj->size();
502130561Sobrien  oop new_obj = NULL;
503130561Sobrien  if (obj->is_javaArray()) {
504130561Sobrien    const int length = ((arrayOop)obj())->length();
505130561Sobrien    new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
506130561Sobrien  } else {
507130561Sobrien    new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
508130561Sobrien  }
509130561Sobrien  // 4839641 (4840070): We must do an oop-atomic copy, because if another thread
510130561Sobrien  // is modifying a reference field in the clonee, a non-oop-atomic copy might
511130561Sobrien  // be suspended in the middle of copying the pointer and end up with parts
512130561Sobrien  // of two different pointers in the field.  Subsequent dereferences will crash.
513130561Sobrien  // 4846409: an oop-copy of objects with long or double fields or arrays of same
514130561Sobrien  // won't copy the longs/doubles atomically in 32-bit vm's, so we copy jlongs instead
515130561Sobrien  // of oops.  We know objects are aligned on a minimum of an jlong boundary.
516130561Sobrien  // The same is true of StubRoutines::object_copy and the various oop_copy
517130561Sobrien  // variants, and of the code generated by the inline_native_clone intrinsic.
518130561Sobrien  assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned");
519130561Sobrien  Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj,
52068765Sobrien                               (size_t)align_object_size(size) / HeapWordsPerLong);
521130561Sobrien  // Clear the header
522130561Sobrien  new_obj->init_mark();
523130561Sobrien
524130561Sobrien  // Store check (mark entire object and let gc sort it out)
525130561Sobrien  BarrierSet* bs = Universe::heap()->barrier_set();
526130561Sobrien  assert(bs->has_write_region_opt(), "Barrier set does not have write_region");
527130561Sobrien  bs->write_region(MemRegion((HeapWord*)new_obj, size));
528130561Sobrien
529130561Sobrien  // Caution: this involves a java upcall, so the clone should be
530130561Sobrien  // "gc-robust" by this stage.
531130561Sobrien  if (klass->has_finalizer()) {
532130561Sobrien    assert(obj->is_instance(), "should be instanceOop");
533130561Sobrien    new_obj = instanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL);
534130561Sobrien  }
535130561Sobrien
536130561Sobrien  return JNIHandles::make_local(env, oop(new_obj));
537130561SobrienJVM_END
538130561Sobrien
539130561Sobrien// java.lang.Compiler ////////////////////////////////////////////////////
540130561Sobrien
541130561Sobrien// The initial cuts of the HotSpot VM will not support JITs, and all existing
542130561Sobrien// JITs would need extensive changes to work with HotSpot.  The JIT-related JVM
543130561Sobrien// functions are all silently ignored unless JVM warnings are printed.
544130561Sobrien
545130561SobrienJVM_LEAF(void, JVM_InitializeCompiler (JNIEnv *env, jclass compCls))
546130561Sobrien  if (PrintJVMWarnings) warning("JVM_InitializeCompiler not supported");
547130561SobrienJVM_END
548130561Sobrien
549130561Sobrien
550130561SobrienJVM_LEAF(jboolean, JVM_IsSilentCompiler(JNIEnv *env, jclass compCls))
551130561Sobrien  if (PrintJVMWarnings) warning("JVM_IsSilentCompiler not supported");
552130561Sobrien  return JNI_FALSE;
553130561SobrienJVM_END
554130561Sobrien
555130561Sobrien
556130561SobrienJVM_LEAF(jboolean, JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls))
557130561Sobrien  if (PrintJVMWarnings) warning("JVM_CompileClass not supported");
558130561Sobrien  return JNI_FALSE;
559130561SobrienJVM_END
560130561Sobrien
561130561Sobrien
562130561SobrienJVM_LEAF(jboolean, JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname))
563130561Sobrien  if (PrintJVMWarnings) warning("JVM_CompileClasses not supported");
564130561Sobrien  return JNI_FALSE;
565130561SobrienJVM_END
566130561Sobrien
567130561Sobrien
568130561SobrienJVM_LEAF(jobject, JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg))
569218822Sdim  if (PrintJVMWarnings) warning("JVM_CompilerCommand not supported");
570218822Sdim  return NULL;
571218822SdimJVM_END
572130561Sobrien
573130561Sobrien
574130561SobrienJVM_LEAF(void, JVM_EnableCompiler(JNIEnv *env, jclass compCls))
575130561Sobrien  if (PrintJVMWarnings) warning("JVM_EnableCompiler not supported");
576130561SobrienJVM_END
577130561Sobrien
578130561Sobrien
579130561SobrienJVM_LEAF(void, JVM_DisableCompiler(JNIEnv *env, jclass compCls))
580130561Sobrien  if (PrintJVMWarnings) warning("JVM_DisableCompiler not supported");
581130561SobrienJVM_END
582130561Sobrien
583130561Sobrien
584130561Sobrien
585130561Sobrien// Error message support //////////////////////////////////////////////////////
586130561Sobrien
587130561SobrienJVM_LEAF(jint, JVM_GetLastErrorString(char *buf, int len))
588130561Sobrien  JVMWrapper("JVM_GetLastErrorString");
589130561Sobrien  return hpi::lasterror(buf, len);
590130561SobrienJVM_END
591130561Sobrien
592130561Sobrien
593130561Sobrien// java.io.File ///////////////////////////////////////////////////////////////
594130561Sobrien
595130561SobrienJVM_LEAF(char*, JVM_NativePath(char* path))
596130561Sobrien  JVMWrapper2("JVM_NativePath (%s)", path);
597130561Sobrien  return hpi::native_path(path);
598130561SobrienJVM_END
599130561Sobrien
600130561Sobrien
601130561Sobrien// Misc. class handling ///////////////////////////////////////////////////////////
602130561Sobrien
603130561Sobrien
604130561SobrienJVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
605130561Sobrien  JVMWrapper("JVM_GetCallerClass");
606130561Sobrien  klassOop k = thread->security_get_caller_class(depth);
607130561Sobrien  return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror());
608130561SobrienJVM_END
609130561Sobrien
610130561Sobrien
611130561SobrienJVM_ENTRY(jclass, JVM_FindPrimitiveClass(JNIEnv* env, const char* utf))
612130561Sobrien  JVMWrapper("JVM_FindPrimitiveClass");
613130561Sobrien  oop mirror = NULL;
614130561Sobrien  BasicType t = name2type(utf);
615130561Sobrien  if (t != T_ILLEGAL && t != T_OBJECT && t != T_ARRAY) {
616130561Sobrien    mirror = Universe::java_mirror(t);
617130561Sobrien  }
618130561Sobrien  if (mirror == NULL) {
619130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), (char*) utf);
620130561Sobrien  } else {
621130561Sobrien    return (jclass) JNIHandles::make_local(env, mirror);
622130561Sobrien  }
623130561SobrienJVM_END
624130561Sobrien
625130561Sobrien
626130561SobrienJVM_ENTRY(void, JVM_ResolveClass(JNIEnv* env, jclass cls))
627130561Sobrien  JVMWrapper("JVM_ResolveClass");
628130561Sobrien  if (PrintJVMWarnings) warning("JVM_ResolveClass not implemented");
629130561SobrienJVM_END
630130561Sobrien
631130561Sobrien// Rationale behind JVM_FindClassFromBootLoader
632130561Sobrien// a> JVM_FindClassFromClassLoader was never exported in the export tables.
633130561Sobrien// b> because of (a) java.dll has a direct dependecy on the  unexported
634130561Sobrien//    private symbol "_JVM_FindClassFromClassLoader@20".
635130561Sobrien// c> the launcher cannot use the private symbol as it dynamically opens
636130561Sobrien//    the entry point, so if something changes, the launcher will fail
637130561Sobrien//    unexpectedly at runtime, it is safest for the launcher to dlopen a
638130561Sobrien//    stable exported interface.
639130561Sobrien// d> re-exporting JVM_FindClassFromClassLoader as public, will cause its
640130561Sobrien//    signature to change from _JVM_FindClassFromClassLoader@20 to
641130561Sobrien//    JVM_FindClassFromClassLoader and will not be backward compatible
642130561Sobrien//    with older JDKs.
643130561Sobrien// Thus a public/stable exported entry point is the right solution,
644130561Sobrien// public here means public in linker semantics, and is exported only
645130561Sobrien// to the JDK, and is not intended to be a public API.
646130561Sobrien
647130561SobrienJVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env,
648130561Sobrien                                              const char* name,
649130561Sobrien                                              jboolean throwError))
650130561Sobrien  JVMWrapper3("JVM_FindClassFromBootLoader %s throw %s", name,
65168765Sobrien              throwError ? "error" : "exception");
652130561Sobrien  return JVM_FindClassFromClassLoader(env, name, JNI_FALSE,
653130561Sobrien                                      (jobject)NULL, throwError);
65468765SobrienJVM_END
65568765Sobrien
656130561SobrienJVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name,
65768765Sobrien                                               jboolean init, jobject loader,
658130561Sobrien                                               jboolean throwError))
659130561Sobrien  JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name,
660130561Sobrien               throwError ? "error" : "exception");
661130561Sobrien  // Java libraries should ensure that name is never null...
662218822Sdim  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
66368765Sobrien    // It's impossible to create this class;  the name cannot fit
664130561Sobrien    // into the constant pool.
665130561Sobrien    if (throwError) {
666130561Sobrien      THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
667130561Sobrien    } else {
668130561Sobrien      THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name);
669130561Sobrien    }
67068765Sobrien  }
67168765Sobrien  symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL);
672130561Sobrien  Handle h_loader(THREAD, JNIHandles::resolve(loader));
67377298Sobrien  jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
674130561Sobrien                                               Handle(), throwError, thread);
675130561Sobrien
676218822Sdim  if (TraceClassResolution && result != NULL) {
677218822Sdim    trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
67877298Sobrien  }
679130561Sobrien
680130561Sobrien  return result;
681130561SobrienJVM_END
682130561Sobrien
683130561Sobrien
684130561SobrienJVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name,
68577298Sobrien                                         jboolean init, jclass from))
68677298Sobrien  JVMWrapper2("JVM_FindClassFromClass %s", name);
687130561Sobrien  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
68877298Sobrien    // It's impossible to create this class;  the name cannot fit
689130561Sobrien    // into the constant pool.
690130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
691218822Sdim  }
692218822Sdim  symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL);
693218822Sdim  oop from_class_oop = JNIHandles::resolve(from);
69477298Sobrien  klassOop from_class = (from_class_oop == NULL)
695130561Sobrien                           ? (klassOop)NULL
696130561Sobrien                           : java_lang_Class::as_klassOop(from_class_oop);
697130561Sobrien  oop class_loader = NULL;
698130561Sobrien  oop protection_domain = NULL;
699130561Sobrien  if (from_class != NULL) {
700130561Sobrien    class_loader = Klass::cast(from_class)->class_loader();
701130561Sobrien    protection_domain = Klass::cast(from_class)->protection_domain();
702130561Sobrien  }
703130561Sobrien  Handle h_loader(THREAD, class_loader);
70477298Sobrien  Handle h_prot  (THREAD, protection_domain);
70577298Sobrien  jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
706130561Sobrien                                               h_prot, true, thread);
70777298Sobrien
708130561Sobrien  if (TraceClassResolution && result != NULL) {
709130561Sobrien    // this function is generally only used for class loading during verification.
710218822Sdim    ResourceMark rm;
711218822Sdim    oop from_mirror = JNIHandles::resolve_non_null(from);
712218822Sdim    klassOop from_class = java_lang_Class::as_klassOop(from_mirror);
71377298Sobrien    const char * from_name = Klass::cast(from_class)->external_name();
714130561Sobrien
715130561Sobrien    oop mirror = JNIHandles::resolve_non_null(result);
716130561Sobrien    klassOop to_class = java_lang_Class::as_klassOop(mirror);
717130561Sobrien    const char * to = Klass::cast(to_class)->external_name();
718130561Sobrien    tty->print("RESOLVE %s %s (verification)\n", from_name, to);
719130561Sobrien  }
720130561Sobrien
721130561Sobrien  return result;
722130561SobrienJVM_END
72377298Sobrien
72477298Sobrienstatic void is_lock_held_by_thread(Handle loader, PerfCounter* counter, TRAPS) {
725130561Sobrien  if (loader.is_null()) {
72677298Sobrien    return;
727130561Sobrien  }
728218822Sdim
72977298Sobrien  // check whether the current caller thread holds the lock or not.
730130561Sobrien  // If not, increment the corresponding counter
731130561Sobrien  if (ObjectSynchronizer::query_lock_ownership((JavaThread*)THREAD, loader) !=
732130561Sobrien      ObjectSynchronizer::owner_self) {
733130561Sobrien    counter->inc();
734130561Sobrien  }
735130561Sobrien}
736130561Sobrien
73777298Sobrien// common code for JVM_DefineClass() and JVM_DefineClassWithSource()
73877298Sobrienstatic jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) {
739130561Sobrien
74068765Sobrien  // Since exceptions can be thrown, class initialization can take place
741130561Sobrien  // if name is NULL no check for class name in .class stream has to be made.
742218822Sdim  symbolHandle class_name;
743218822Sdim  if (name != NULL) {
744218822Sdim    const int str_len = (int)strlen(name);
74568765Sobrien    if (str_len > symbolOopDesc::max_length()) {
746130561Sobrien      // It's impossible to create this class;  the name cannot fit
74768765Sobrien      // into the constant pool.
748130561Sobrien      THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
749130561Sobrien    }
750130561Sobrien    class_name = oopFactory::new_symbol_handle(name, str_len, CHECK_NULL);
751130561Sobrien  }
752130561Sobrien
753130561Sobrien  ResourceMark rm(THREAD);
754130561Sobrien  ClassFileStream st((u1*) buf, len, (char *)source);
755130561Sobrien  Handle class_loader (THREAD, JNIHandles::resolve(loader));
756130561Sobrien  if (UsePerfData) {
757130561Sobrien    is_lock_held_by_thread(class_loader,
758130561Sobrien                           ClassLoader::sync_JVMDefineClassLockFreeCounter(),
759130561Sobrien                           THREAD);
760130561Sobrien  }
761130561Sobrien  Handle protection_domain (THREAD, JNIHandles::resolve(pd));
762130561Sobrien  klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader,
763130561Sobrien                                                     protection_domain, &st,
764130561Sobrien                                                     CHECK_NULL);
765130561Sobrien
766130561Sobrien  if (TraceClassResolution && k != NULL) {
767130561Sobrien    trace_class_resolution(k);
768130561Sobrien  }
769130561Sobrien
770130561Sobrien  return (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror());
771130561Sobrien}
77268765Sobrien
773130561Sobrien
774130561SobrienJVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
775130561Sobrien  JVMWrapper2("JVM_DefineClass %s", name);
776130561Sobrien
777130561Sobrien  return jvm_define_class_common(env, name, loader, buf, len, pd, "__JVM_DefineClass__", THREAD);
778130561SobrienJVM_END
779130561Sobrien
780130561Sobrien
781130561SobrienJVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source))
782130561Sobrien  JVMWrapper2("JVM_DefineClassWithSource %s", name);
783130561Sobrien
784130561Sobrien  return jvm_define_class_common(env, name, loader, buf, len, pd, source, THREAD);
785218822SdimJVM_END
786130561Sobrien
787130561Sobrien
788130561SobrienJVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name))
789130561Sobrien  JVMWrapper("JVM_FindLoadedClass");
790130561Sobrien  ResourceMark rm(THREAD);
791130561Sobrien
792130561Sobrien  Handle h_name (THREAD, JNIHandles::resolve_non_null(name));
793130561Sobrien  Handle string = java_lang_String::internalize_classname(h_name, CHECK_NULL);
794130561Sobrien
795130561Sobrien  const char* str   = java_lang_String::as_utf8_string(string());
796130561Sobrien  // Sanity check, don't expect null
79768765Sobrien  if (str == NULL) return NULL;
798130561Sobrien
799130561Sobrien  const int str_len = (int)strlen(str);
800130561Sobrien  if (str_len > symbolOopDesc::max_length()) {
801130561Sobrien    // It's impossible to create this class;  the name cannot fit
802130561Sobrien    // into the constant pool.
803130561Sobrien    return NULL;
80468765Sobrien  }
805130561Sobrien  symbolHandle klass_name = oopFactory::new_symbol_handle(str, str_len,CHECK_NULL);
806130561Sobrien
807130561Sobrien  // Security Note:
808130561Sobrien  //   The Java level wrapper will perform the necessary security check allowing
809130561Sobrien  //   us to pass the NULL as the initiating class loader.
810130561Sobrien  Handle h_loader(THREAD, JNIHandles::resolve(loader));
811130561Sobrien  if (UsePerfData) {
812130561Sobrien    is_lock_held_by_thread(h_loader,
813130561Sobrien                           ClassLoader::sync_JVMFindLoadedClassLockFreeCounter(),
814130561Sobrien                           THREAD);
815130561Sobrien  }
816130561Sobrien
817130561Sobrien  klassOop k = SystemDictionary::find_instance_or_array_klass(klass_name,
818130561Sobrien                                                              h_loader,
81968765Sobrien                                                              Handle(),
82068765Sobrien                                                              CHECK_NULL);
821130561Sobrien
822130561Sobrien  return (k == NULL) ? NULL :
82368765Sobrien            (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror());
824130561SobrienJVM_END
825130561Sobrien
826130561Sobrien
82768765Sobrien// Reflection support //////////////////////////////////////////////////////////////////////////////
828130561Sobrien
829130561SobrienJVM_ENTRY(jstring, JVM_GetClassName(JNIEnv *env, jclass cls))
83068765Sobrien  assert (cls != NULL, "illegal class");
831130561Sobrien  JVMWrapper("JVM_GetClassName");
83268765Sobrien  JvmtiVMObjectAllocEventCollector oam;
833130561Sobrien  ResourceMark rm(THREAD);
834218822Sdim  const char* name;
835130561Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
836130561Sobrien    name = type2name(java_lang_Class::primitive_type(JNIHandles::resolve(cls)));
83768765Sobrien  } else {
838130561Sobrien    // Consider caching interned string in Klass
839130561Sobrien    klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls));
840130561Sobrien    assert(k->is_klass(), "just checking");
841130561Sobrien    name = Klass::cast(k)->external_name();
84268765Sobrien  }
84368765Sobrien  oop result = StringTable::intern((char*) name, CHECK_NULL);
844130561Sobrien  return (jstring) JNIHandles::make_local(env, result);
84568765SobrienJVM_END
846130561Sobrien
847218822Sdim
848218822SdimJVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls))
84968765Sobrien  JVMWrapper("JVM_GetClassInterfaces");
850130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
85168765Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
852130561Sobrien
85368765Sobrien  // Special handling for primitive objects
854130561Sobrien  if (java_lang_Class::is_primitive(mirror)) {
855130561Sobrien    // Primitive objects does not have any interfaces
856130561Sobrien    objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL);
857130561Sobrien    return (jobjectArray) JNIHandles::make_local(env, r);
858130561Sobrien  }
859130561Sobrien
860130561Sobrien  KlassHandle klass(thread, java_lang_Class::as_klassOop(mirror));
86168765Sobrien  // Figure size of result array
86268765Sobrien  int size;
863130561Sobrien  if (klass->oop_is_instance()) {
86468765Sobrien    size = instanceKlass::cast(klass())->local_interfaces()->length();
865130561Sobrien  } else {
866218822Sdim    assert(klass->oop_is_objArray() || klass->oop_is_typeArray(), "Illegal mirror klass");
86768765Sobrien    size = 2;
868130561Sobrien  }
86968765Sobrien
870130561Sobrien  // Allocate result array
871130561Sobrien  objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), size, CHECK_NULL);
87268765Sobrien  objArrayHandle result (THREAD, r);
873130561Sobrien  // Fill in result
874130561Sobrien  if (klass->oop_is_instance()) {
87568765Sobrien    // Regular instance klass, fill in all local interfaces
876130561Sobrien    for (int index = 0; index < size; index++) {
87768765Sobrien      klassOop k = klassOop(instanceKlass::cast(klass())->local_interfaces()->obj_at(index));
87868765Sobrien      result->obj_at_put(index, Klass::cast(k)->java_mirror());
879130561Sobrien    }
88068765Sobrien  } else {
881130561Sobrien    // All arrays implement java.lang.Cloneable and java.io.Serializable
882218822Sdim    result->obj_at_put(0, Klass::cast(SystemDictionary::cloneable_klass())->java_mirror());
883218822Sdim    result->obj_at_put(1, Klass::cast(SystemDictionary::serializable_klass())->java_mirror());
884130561Sobrien  }
885130561Sobrien  return (jobjectArray) JNIHandles::make_local(env, result());
88668765SobrienJVM_END
887130561Sobrien
888130561Sobrien
88968765SobrienJVM_ENTRY(jobject, JVM_GetClassLoader(JNIEnv *env, jclass cls))
890130561Sobrien  JVMWrapper("JVM_GetClassLoader");
89168765Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
89268765Sobrien    return NULL;
893130561Sobrien  }
89468765Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
895130561Sobrien  oop loader = Klass::cast(k)->class_loader();
896218822Sdim  return JNIHandles::make_local(env, loader);
897218822SdimJVM_END
89868765Sobrien
899130561Sobrien
900130561SobrienJVM_QUICK_ENTRY(jboolean, JVM_IsInterface(JNIEnv *env, jclass cls))
901130561Sobrien  JVMWrapper("JVM_IsInterface");
902130561Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
903130561Sobrien  if (java_lang_Class::is_primitive(mirror)) {
904130561Sobrien    return JNI_FALSE;
90568765Sobrien  }
90668765Sobrien  klassOop k = java_lang_Class::as_klassOop(mirror);
907130561Sobrien  jboolean result = Klass::cast(k)->is_interface();
90868765Sobrien  assert(!result || Klass::cast(k)->oop_is_instance(),
909130561Sobrien         "all interfaces are instance types");
910218822Sdim  // The compiler intrinsic for isInterface tests the
911218822Sdim  // Klass::_access_flags bits in the same way.
91268765Sobrien  return result;
913130561SobrienJVM_END
91468765Sobrien
915130561Sobrien
916130561SobrienJVM_ENTRY(jobjectArray, JVM_GetClassSigners(JNIEnv *env, jclass cls))
917130561Sobrien  JVMWrapper("JVM_GetClassSigners");
918130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
91968765Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
92068765Sobrien    // There are no signers for primitive types
921130561Sobrien    return NULL;
92268765Sobrien  }
923130561Sobrien
924218822Sdim  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
92568765Sobrien  objArrayOop signers = NULL;
926130561Sobrien  if (Klass::cast(k)->oop_is_instance()) {
92768765Sobrien    signers = instanceKlass::cast(k)->signers();
928130561Sobrien  }
929130561Sobrien
93068765Sobrien  // If there are no signers set in the class, or if the class
931130561Sobrien  // is an array, return NULL.
932130561Sobrien  if (signers == NULL) return NULL;
93368765Sobrien
934130561Sobrien  // copy of the signers array
93568765Sobrien  klassOop element = objArrayKlass::cast(signers->klass())->element_klass();
93668765Sobrien  objArrayOop signers_copy = oopFactory::new_objArray(element, signers->length(), CHECK_NULL);
937130561Sobrien  for (int index = 0; index < signers->length(); index++) {
93868765Sobrien    signers_copy->obj_at_put(index, signers->obj_at(index));
939130561Sobrien  }
940218822Sdim
94168765Sobrien  // return the copy
942130561Sobrien  return (jobjectArray) JNIHandles::make_local(env, signers_copy);
94368765SobrienJVM_END
944130561Sobrien
945130561Sobrien
94668765SobrienJVM_ENTRY(void, JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers))
947130561Sobrien  JVMWrapper("JVM_SetClassSigners");
948130561Sobrien  if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
949130561Sobrien    // This call is ignored for primitive types and arrays.
95068765Sobrien    // Signers are only set once, ClassLoader.java, and thus shouldn't
951130561Sobrien    // be called with an array.  Only the bootstrap loader creates arrays.
95268765Sobrien    klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
95368765Sobrien    if (Klass::cast(k)->oop_is_instance()) {
954130561Sobrien      instanceKlass::cast(k)->set_signers(objArrayOop(JNIHandles::resolve(signers)));
95568765Sobrien    }
956130561Sobrien  }
95768765SobrienJVM_END
958130561Sobrien
959130561Sobrien
960218822SdimJVM_ENTRY(jobject, JVM_GetProtectionDomain(JNIEnv *env, jclass cls))
96168765Sobrien  JVMWrapper("JVM_GetProtectionDomain");
962218822Sdim  if (JNIHandles::resolve(cls) == NULL) {
963130561Sobrien    THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
964218822Sdim  }
965130561Sobrien
966130561Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
96768765Sobrien    // Primitive types does not have a protection domain.
96868765Sobrien    return NULL;
969130561Sobrien  }
970130561Sobrien
971130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls));
972130561Sobrien  return (jobject) JNIHandles::make_local(env, Klass::cast(k)->protection_domain());
973130561SobrienJVM_END
974130561Sobrien
975130561Sobrien
976130561Sobrien// Obsolete since 1.2 (Class.setProtectionDomain removed), although
97768765Sobrien// still defined in core libraries as of 1.5.
978130561SobrienJVM_ENTRY(void, JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain))
979218822Sdim  JVMWrapper("JVM_SetProtectionDomain");
98068765Sobrien  if (JNIHandles::resolve(cls) == NULL) {
981130561Sobrien    THROW(vmSymbols::java_lang_NullPointerException());
982130561Sobrien  }
983130561Sobrien  if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
98468765Sobrien    // Call is ignored for primitive types
985130561Sobrien    klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls));
986130561Sobrien
987130561Sobrien    // cls won't be an array, as this called only from ClassLoader.defineClass
988130561Sobrien    if (Klass::cast(k)->oop_is_instance()) {
989130561Sobrien      oop pd = JNIHandles::resolve(protection_domain);
990130561Sobrien      assert(pd == NULL || pd->is_oop(), "just checking");
991130561Sobrien      instanceKlass::cast(k)->set_protection_domain(pd);
992130561Sobrien    }
99368765Sobrien  }
99468765SobrienJVM_END
99568765Sobrien
996130561Sobrien
997130561SobrienJVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException))
99868765Sobrien  JVMWrapper("JVM_DoPrivileged");
999130561Sobrien
1000218822Sdim  if (action == NULL) {
100168765Sobrien    THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), "Null action");
1002130561Sobrien  }
1003130561Sobrien
1004130561Sobrien  // Stack allocated list of privileged stack elements
100568765Sobrien  PrivilegedElement pi;
1006130561Sobrien
1007130561Sobrien  // Check that action object understands "Object run()"
1008130561Sobrien  Handle object (THREAD, JNIHandles::resolve(action));
1009130561Sobrien
1010130561Sobrien  // get run() method
1011130561Sobrien  methodOop m_oop = Klass::cast(object->klass())->uncached_lookup_method(
1012130561Sobrien                                           vmSymbols::run_method_name(),
1013130561Sobrien                                           vmSymbols::void_object_signature());
1014130561Sobrien  methodHandle m (THREAD, m_oop);
101568765Sobrien  if (m.is_null() || !m->is_method() || !methodOop(m())->is_public() || methodOop(m())->is_static()) {
101668765Sobrien    THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method");
101768765Sobrien  }
1018130561Sobrien
1019130561Sobrien  // Compute the frame initiating the do privileged operation and setup the privileged stack
1020130561Sobrien  vframeStream vfst(thread);
102168765Sobrien  vfst.security_get_caller_frame(1);
1022130561Sobrien
1023130561Sobrien  if (!vfst.at_end()) {
1024130561Sobrien    pi.initialize(&vfst, JNIHandles::resolve(context), thread->privileged_stack_top(), CHECK_NULL);
1025130561Sobrien    thread->set_privileged_stack_top(&pi);
102668765Sobrien  }
1027130561Sobrien
1028218822Sdim
102968765Sobrien  // invoke the Object run() in the action object. We cannot use call_interface here, since the static type
1030130561Sobrien  // is not really known - it is either java.security.PrivilegedAction or java.security.PrivilegedExceptionAction
103168765Sobrien  Handle pending_exception;
1032130561Sobrien  JavaValue result(T_OBJECT);
1033130561Sobrien  JavaCallArguments args(object);
103468765Sobrien  JavaCalls::call(&result, m, &args, THREAD);
103568765Sobrien
1036130561Sobrien  // done with action, remove ourselves from the list
103768765Sobrien  if (!vfst.at_end()) {
1038130561Sobrien    assert(thread->privileged_stack_top() != NULL && thread->privileged_stack_top() == &pi, "wrong top element");
103968765Sobrien    thread->set_privileged_stack_top(thread->privileged_stack_top()->next());
1040130561Sobrien  }
1041130561Sobrien
1042130561Sobrien  if (HAS_PENDING_EXCEPTION) {
1043130561Sobrien    pending_exception = Handle(THREAD, PENDING_EXCEPTION);
1044130561Sobrien    CLEAR_PENDING_EXCEPTION;
1045130561Sobrien
1046130561Sobrien    if ( pending_exception->is_a(SystemDictionary::exception_klass()) &&
1047130561Sobrien        !pending_exception->is_a(SystemDictionary::runtime_exception_klass())) {
1048130561Sobrien      // Throw a java.security.PrivilegedActionException(Exception e) exception
104968765Sobrien      JavaCallArguments args(pending_exception);
1050130561Sobrien      THROW_ARG_0(vmSymbolHandles::java_security_PrivilegedActionException(),
1051130561Sobrien                  vmSymbolHandles::exception_void_signature(),
1052130561Sobrien                  &args);
1053130561Sobrien    }
1054130561Sobrien  }
1055130561Sobrien
1056130561Sobrien  if (pending_exception.not_null()) THROW_OOP_0(pending_exception());
105768765Sobrien  return JNIHandles::make_local(env, (oop) result.get_jobject());
1058130561SobrienJVM_END
1059130561Sobrien
1060130561Sobrien
1061130561Sobrien// Returns the inherited_access_control_context field of the running thread.
1062130561SobrienJVM_ENTRY(jobject, JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls))
1063130561Sobrien  JVMWrapper("JVM_GetInheritedAccessControlContext");
1064130561Sobrien  oop result = java_lang_Thread::inherited_access_control_context(thread->threadObj());
106568765Sobrien  return JNIHandles::make_local(env, result);
1066130561SobrienJVM_END
1067130561Sobrien
106868765Sobrienclass RegisterArrayForGC {
1069130561Sobrien private:
1070218822Sdim  JavaThread *_thread;
1071130561Sobrien public:
1072130561Sobrien  RegisterArrayForGC(JavaThread *thread, GrowableArray<oop>* array)  {
1073130561Sobrien    _thread = thread;
107468765Sobrien    _thread->register_array_for_gc(array);
107568765Sobrien  }
107668765Sobrien
1077130561Sobrien  ~RegisterArrayForGC() {
1078130561Sobrien    _thread->register_array_for_gc(NULL);
1079130561Sobrien  }
1080130561Sobrien};
108168765Sobrien
1082130561Sobrien
1083130561SobrienJVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls))
108468765Sobrien  JVMWrapper("JVM_GetStackAccessControlContext");
1085130561Sobrien  if (!UsePrivilegedStack) return NULL;
1086130561Sobrien
1087130561Sobrien  ResourceMark rm(THREAD);
108868765Sobrien  GrowableArray<oop>* local_array = new GrowableArray<oop>(12);
1089130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1090218822Sdim
109168765Sobrien  // count the protection domains on the execution stack. We collapse
1092130561Sobrien  // duplicate consecutive protection domains into a single one, as
1093130561Sobrien  // well as stopping when we hit a privileged frame.
109468765Sobrien
109577298Sobrien  // Use vframeStream to iterate through Java frames
109668765Sobrien  vframeStream vfst(thread);
109768765Sobrien
1098130561Sobrien  oop previous_protection_domain = NULL;
109968765Sobrien  Handle privileged_context(thread, NULL);
110068765Sobrien  bool is_privileged = false;
1101130561Sobrien  oop protection_domain = NULL;
110268765Sobrien
1103218822Sdim  for(; !vfst.at_end(); vfst.next()) {
1104218822Sdim    // get method of frame
1105218822Sdim    methodOop method = vfst.method();
110668765Sobrien    intptr_t* frame_id   = vfst.frame_id();
1107130561Sobrien
1108130561Sobrien    // check the privileged frames to see if we have a match
110977298Sobrien    if (thread->privileged_stack_top() && thread->privileged_stack_top()->frame_id() == frame_id) {
1110130561Sobrien      // this frame is privileged
1111130561Sobrien      is_privileged = true;
1112130561Sobrien      privileged_context = Handle(thread, thread->privileged_stack_top()->privileged_context());
1113130561Sobrien      protection_domain  = thread->privileged_stack_top()->protection_domain();
1114130561Sobrien    } else {
1115130561Sobrien      protection_domain = instanceKlass::cast(method->method_holder())->protection_domain();
1116130561Sobrien    }
1117130561Sobrien
1118130561Sobrien    if ((previous_protection_domain != protection_domain) && (protection_domain != NULL)) {
1119130561Sobrien      local_array->push(protection_domain);
1120130561Sobrien      previous_protection_domain = protection_domain;
1121130561Sobrien    }
1122130561Sobrien
1123130561Sobrien    if (is_privileged) break;
112468765Sobrien  }
1125130561Sobrien
1126130561Sobrien
1127130561Sobrien  // either all the domains on the stack were system domains, or
1128130561Sobrien  // we had a privileged system domain
1129130561Sobrien  if (local_array->is_empty()) {
1130130561Sobrien    if (is_privileged && privileged_context.is_null()) return NULL;
1131130561Sobrien
1132130561Sobrien    oop result = java_security_AccessControlContext::create(objArrayHandle(), is_privileged, privileged_context, CHECK_NULL);
1133130561Sobrien    return JNIHandles::make_local(env, result);
1134130561Sobrien  }
1135130561Sobrien
1136130561Sobrien  // the resource area must be registered in case of a gc
1137130561Sobrien  RegisterArrayForGC ragc(thread, local_array);
1138130561Sobrien  objArrayOop context = oopFactory::new_objArray(SystemDictionary::protectionDomain_klass(),
1139130561Sobrien                                                 local_array->length(), CHECK_NULL);
1140130561Sobrien  objArrayHandle h_context(thread, context);
1141130561Sobrien  for (int index = 0; index < local_array->length(); index++) {
1142130561Sobrien    h_context->obj_at_put(index, local_array->at(index));
1143130561Sobrien  }
1144130561Sobrien
1145130561Sobrien  oop result = java_security_AccessControlContext::create(h_context, is_privileged, privileged_context, CHECK_NULL);
1146130561Sobrien
1147130561Sobrien  return JNIHandles::make_local(env, result);
1148130561SobrienJVM_END
114968765Sobrien
1150130561Sobrien
1151130561SobrienJVM_QUICK_ENTRY(jboolean, JVM_IsArrayClass(JNIEnv *env, jclass cls))
115268765Sobrien  JVMWrapper("JVM_IsArrayClass");
1153130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
1154130561Sobrien  return (k != NULL) && Klass::cast(k)->oop_is_javaArray() ? true : false;
1155130561SobrienJVM_END
1156130561Sobrien
1157130561Sobrien
1158130561SobrienJVM_QUICK_ENTRY(jboolean, JVM_IsPrimitiveClass(JNIEnv *env, jclass cls))
1159130561Sobrien  JVMWrapper("JVM_IsPrimitiveClass");
116068765Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
1161130561Sobrien  return (jboolean) java_lang_Class::is_primitive(mirror);
116268765SobrienJVM_END
116368765Sobrien
116468765Sobrien
1165130561SobrienJVM_ENTRY(jclass, JVM_GetComponentType(JNIEnv *env, jclass cls))
1166130561Sobrien  JVMWrapper("JVM_GetComponentType");
1167130561Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
116868765Sobrien  oop result = Reflection::array_component_type(mirror, CHECK_NULL);
1169130561Sobrien  return (jclass) JNIHandles::make_local(env, result);
1170218822SdimJVM_END
117168765Sobrien
1172130561Sobrien
1173130561SobrienJVM_ENTRY(jint, JVM_GetClassModifiers(JNIEnv *env, jclass cls))
117468765Sobrien  JVMWrapper("JVM_GetClassModifiers");
1175218822Sdim  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
1176130561Sobrien    // Primitive type
117768765Sobrien    return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
1178130561Sobrien  }
1179130561Sobrien
1180130561Sobrien  Klass* k = Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)));
118168765Sobrien  debug_only(int computed_modifiers = k->compute_modifier_flags(CHECK_0));
1182130561Sobrien  assert(k->modifier_flags() == computed_modifiers, "modifiers cache is OK");
1183130561Sobrien  return k->modifier_flags();
1184130561SobrienJVM_END
118568765Sobrien
1186218822Sdim
1187130561Sobrien// Inner class reflection ///////////////////////////////////////////////////////////////////////////////
118868765Sobrien
1189130561SobrienJVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
119068765Sobrien  const int inner_class_info_index = 0;
119168765Sobrien  const int outer_class_info_index = 1;
1192130561Sobrien
1193130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1194130561Sobrien  // ofClass is a reference to a java_lang_Class object. The mirror object
1195130561Sobrien  // of an instanceKlass
1196130561Sobrien
119768765Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
1198130561Sobrien      ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) {
1199130561Sobrien    oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL);
1200130561Sobrien    return (jobjectArray)JNIHandles::make_local(env, result);
1201130561Sobrien  }
120268765Sobrien
1203130561Sobrien  instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
1204218822Sdim
120568765Sobrien  if (k->inner_classes()->length() == 0) {
1206130561Sobrien    // Neither an inner nor outer class
120768765Sobrien    oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL);
120868765Sobrien    return (jobjectArray)JNIHandles::make_local(env, result);
120968765Sobrien  }
121068765Sobrien
1211130561Sobrien  // find inner class info
1212130561Sobrien  typeArrayHandle    icls(thread, k->inner_classes());
121368765Sobrien  constantPoolHandle cp(thread, k->constants());
1214130561Sobrien  int length = icls->length();
1215130561Sobrien
1216130561Sobrien  // Allocate temp. result array
121768765Sobrien  objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), length/4, CHECK_NULL);
1218130561Sobrien  objArrayHandle result (THREAD, r);
1219130561Sobrien  int members = 0;
1220130561Sobrien
122177298Sobrien  for(int i = 0; i < length; i += 4) {
1222130561Sobrien    int ioff = icls->ushort_at(i + inner_class_info_index);
1223130561Sobrien    int ooff = icls->ushort_at(i + outer_class_info_index);
1224130561Sobrien
1225130561Sobrien    if (ioff != 0 && ooff != 0) {
1226218822Sdim      // Check to see if the name matches the class we're looking for
1227218822Sdim      // before attempting to find the class.
1228130561Sobrien      if (cp->klass_name_at_matches(k, ooff)) {
1229130561Sobrien        klassOop outer_klass = cp->klass_at(ooff, CHECK_NULL);
1230130561Sobrien        if (outer_klass == k()) {
123168765Sobrien           klassOop ik = cp->klass_at(ioff, CHECK_NULL);
123268765Sobrien           instanceKlassHandle inner_klass (THREAD, ik);
1233130561Sobrien
1234130561Sobrien           // Throws an exception if outer klass has not declared k as
1235130561Sobrien           // an inner klass
1236130561Sobrien           Reflection::check_for_inner_class(k, inner_klass, CHECK_NULL);
123768765Sobrien
1238130561Sobrien           result->obj_at_put(members, inner_klass->java_mirror());
1239130561Sobrien           members++;
124068765Sobrien        }
1241130561Sobrien      }
124268765Sobrien    }
1243130561Sobrien  }
124468765Sobrien
1245130561Sobrien  if (members != length) {
1246130561Sobrien    // Return array of right length
1247130561Sobrien    objArrayOop res = oopFactory::new_objArray(SystemDictionary::class_klass(), members, CHECK_NULL);
1248130561Sobrien    for(int i = 0; i < members; i++) {
1249130561Sobrien      res->obj_at_put(i, result->obj_at(i));
1250130561Sobrien    }
1251130561Sobrien    return (jobjectArray)JNIHandles::make_local(env, res);
1252130561Sobrien  }
1253130561Sobrien
1254130561Sobrien  return (jobjectArray)JNIHandles::make_local(env, result());
125568765SobrienJVM_END
125668765Sobrien
125768765Sobrien
1258130561SobrienJVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass))
1259130561Sobrien  const int inner_class_info_index = 0;
1260130561Sobrien  const int outer_class_info_index = 1;
1261218822Sdim
1262218822Sdim  // ofClass is a reference to a java_lang_Class object.
1263218822Sdim  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
1264130561Sobrien      ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) {
126568765Sobrien    return NULL;
1266130561Sobrien  }
1267218822Sdim
126868765Sobrien  instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
1269130561Sobrien
127068765Sobrien  if (k->inner_classes()->length() == 0) {
1271130561Sobrien    // No inner class info => no declaring class
1272130561Sobrien    return NULL;
1273130561Sobrien  }
1274130561Sobrien
127568765Sobrien  typeArrayHandle i_icls(thread, k->inner_classes());
1276130561Sobrien  constantPoolHandle i_cp(thread, k->constants());
127777298Sobrien  int i_length = i_icls->length();
1278130561Sobrien
1279130561Sobrien  bool found = false;
1280130561Sobrien  klassOop ok;
1281130561Sobrien  instanceKlassHandle outer_klass;
128268765Sobrien
128368765Sobrien  // Find inner_klass attribute
1284130561Sobrien  for(int i = 0; i < i_length && !found; i+= 4) {
1285218822Sdim    int ioff = i_icls->ushort_at(i + inner_class_info_index);
1286218822Sdim    int ooff = i_icls->ushort_at(i + outer_class_info_index);
1287218822Sdim
1288218822Sdim    if (ioff != 0 && ooff != 0) {
1289218822Sdim      // Check to see if the name matches the class we're looking for
1290218822Sdim      // before attempting to find the class.
1291218822Sdim      if (i_cp->klass_name_at_matches(k, ioff)) {
1292218822Sdim        klassOop inner_klass = i_cp->klass_at(ioff, CHECK_NULL);
1293218822Sdim        if (k() == inner_klass) {
1294218822Sdim          found = true;
1295218822Sdim          ok = i_cp->klass_at(ooff, CHECK_NULL);
1296218822Sdim          outer_klass = instanceKlassHandle(thread, ok);
1297218822Sdim        }
129868765Sobrien      }
1299130561Sobrien    }
130068765Sobrien  }
130168765Sobrien
1302130561Sobrien  // If no inner class attribute found for this class.
130368765Sobrien  if (!found) return NULL;
1304130561Sobrien
1305218822Sdim  // Throws an exception if outer klass has not declared k as an inner klass
130668765Sobrien  Reflection::check_for_inner_class(outer_klass, k, CHECK_NULL);
1307130561Sobrien
1308130561Sobrien  return (jclass)JNIHandles::make_local(env, outer_klass->java_mirror());
130968765SobrienJVM_END
1310130561Sobrien
1311130561Sobrien
1312130561SobrienJVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls))
1313130561Sobrien  assert (cls != NULL, "illegal class");
1314130561Sobrien  JVMWrapper("JVM_GetClassSignature");
1315130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1316130561Sobrien  ResourceMark rm(THREAD);
131768765Sobrien  // Return null for arrays and primatives
1318130561Sobrien  if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
131968765Sobrien    klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls));
1320130561Sobrien    if (Klass::cast(k)->oop_is_instance()) {
1321218822Sdim      symbolHandle sym = symbolHandle(THREAD, instanceKlass::cast(k)->generic_signature());
1322130561Sobrien      if (sym.is_null()) return NULL;
1323130561Sobrien      Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
1324130561Sobrien      return (jstring) JNIHandles::make_local(env, str());
1325130561Sobrien    }
132668765Sobrien  }
1327130561Sobrien  return NULL;
1328130561SobrienJVM_END
1329130561Sobrien
1330130561Sobrien
1331130561SobrienJVM_ENTRY(jbyteArray, JVM_GetClassAnnotations(JNIEnv *env, jclass cls))
1332130561Sobrien  assert (cls != NULL, "illegal class");
1333130561Sobrien  JVMWrapper("JVM_GetClassAnnotations");
1334130561Sobrien  ResourceMark rm(THREAD);
133568765Sobrien  // Return null for arrays and primitives
1336130561Sobrien  if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
1337130561Sobrien    klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls));
1338130561Sobrien    if (Klass::cast(k)->oop_is_instance()) {
1339130561Sobrien      return (jbyteArray) JNIHandles::make_local(env,
1340130561Sobrien                                  instanceKlass::cast(k)->class_annotations());
1341130561Sobrien    }
1342130561Sobrien  }
1343130561Sobrien  return NULL;
1344130561SobrienJVM_END
1345130561Sobrien
1346130561Sobrien
1347130561SobrienJVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field))
1348130561Sobrien  assert(field != NULL, "illegal field");
134968765Sobrien  JVMWrapper("JVM_GetFieldAnnotations");
135068765Sobrien
1351130561Sobrien  // some of this code was adapted from from jni_FromReflectedField
135268765Sobrien
1353130561Sobrien  // field is a handle to a java.lang.reflect.Field object
1354218822Sdim  oop reflected = JNIHandles::resolve_non_null(field);
1355130561Sobrien  oop mirror    = java_lang_reflect_Field::clazz(reflected);
1356130561Sobrien  klassOop k    = java_lang_Class::as_klassOop(mirror);
135768765Sobrien  int slot      = java_lang_reflect_Field::slot(reflected);
1358130561Sobrien  int modifiers = java_lang_reflect_Field::modifiers(reflected);
135968765Sobrien
1360130561Sobrien  fieldDescriptor fd;
1361130561Sobrien  KlassHandle kh(THREAD, k);
136268765Sobrien  intptr_t offset = instanceKlass::cast(kh())->offset_from_fields(slot);
1363130561Sobrien
136468765Sobrien  if (modifiers & JVM_ACC_STATIC) {
1365130561Sobrien    // for static fields we only look in the current class
1366130561Sobrien    if (!instanceKlass::cast(kh())->find_local_field_from_offset(offset,
1367130561Sobrien                                                                 true, &fd)) {
1368130561Sobrien      assert(false, "cannot find static field");
1369130561Sobrien      return NULL;  // robustness
1370130561Sobrien    }
137168765Sobrien  } else {
1372130561Sobrien    // for instance fields we start with the current class and work
1373130561Sobrien    // our way up through the superclass chain
1374130561Sobrien    if (!instanceKlass::cast(kh())->find_field_from_offset(offset, false,
1375130561Sobrien                                                           &fd)) {
1376130561Sobrien      assert(false, "cannot find instance field");
1377130561Sobrien      return NULL;  // robustness
1378130561Sobrien    }
1379130561Sobrien  }
138068765Sobrien
1381130561Sobrien  return (jbyteArray) JNIHandles::make_local(env, fd.annotations());
1382130561SobrienJVM_END
1383130561Sobrien
1384130561Sobrien
1385130561Sobrienstatic methodOop jvm_get_method_common(jobject method, TRAPS) {
1386130561Sobrien  // some of this code was adapted from from jni_FromReflectedMethod
1387130561Sobrien
1388130561Sobrien  oop reflected = JNIHandles::resolve_non_null(method);
1389130561Sobrien  oop mirror    = NULL;
1390130561Sobrien  int slot      = 0;
1391130561Sobrien
139268765Sobrien  if (reflected->klass() == SystemDictionary::reflect_constructor_klass()) {
139368765Sobrien    mirror = java_lang_reflect_Constructor::clazz(reflected);
1394130561Sobrien    slot   = java_lang_reflect_Constructor::slot(reflected);
1395130561Sobrien  } else {
1396130561Sobrien    assert(reflected->klass() == SystemDictionary::reflect_method_klass(),
1397130561Sobrien           "wrong type");
139868765Sobrien    mirror = java_lang_reflect_Method::clazz(reflected);
1399130561Sobrien    slot   = java_lang_reflect_Method::slot(reflected);
1400130561Sobrien  }
1401130561Sobrien  klassOop k = java_lang_Class::as_klassOop(mirror);
1402130561Sobrien
140368765Sobrien  KlassHandle kh(THREAD, k);
1404130561Sobrien  methodOop m = instanceKlass::cast(kh())->method_with_idnum(slot);
1405130561Sobrien  if (m == NULL) {
1406130561Sobrien    assert(false, "cannot find method");
1407130561Sobrien    return NULL;  // robustness
1408130561Sobrien  }
1409130561Sobrien
1410130561Sobrien  return m;
1411130561Sobrien}
1412130561Sobrien
1413130561Sobrien
1414130561SobrienJVM_ENTRY(jbyteArray, JVM_GetMethodAnnotations(JNIEnv *env, jobject method))
1415130561Sobrien  JVMWrapper("JVM_GetMethodAnnotations");
1416130561Sobrien
1417130561Sobrien  // method is a handle to a java.lang.reflect.Method object
1418130561Sobrien  methodOop m = jvm_get_method_common(method, CHECK_NULL);
1419130561Sobrien  return (jbyteArray) JNIHandles::make_local(env, m->annotations());
1420130561SobrienJVM_END
1421130561Sobrien
1422130561Sobrien
1423130561SobrienJVM_ENTRY(jbyteArray, JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject method))
1424130561Sobrien  JVMWrapper("JVM_GetMethodDefaultAnnotationValue");
1425130561Sobrien
1426130561Sobrien  // method is a handle to a java.lang.reflect.Method object
1427130561Sobrien  methodOop m = jvm_get_method_common(method, CHECK_NULL);
1428130561Sobrien  return (jbyteArray) JNIHandles::make_local(env, m->annotation_default());
1429130561SobrienJVM_END
1430130561Sobrien
1431130561Sobrien
1432130561SobrienJVM_ENTRY(jbyteArray, JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject method))
1433130561Sobrien  JVMWrapper("JVM_GetMethodParameterAnnotations");
1434130561Sobrien
1435130561Sobrien  // method is a handle to a java.lang.reflect.Method object
1436130561Sobrien  methodOop m = jvm_get_method_common(method, CHECK_NULL);
1437130561Sobrien  return (jbyteArray) JNIHandles::make_local(env, m->parameter_annotations());
1438130561SobrienJVM_END
1439130561Sobrien
1440130561Sobrien
1441130561Sobrien// New (JDK 1.4) reflection implementation /////////////////////////////////////
1442130561Sobrien
1443130561SobrienJVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly))
1444130561Sobrien{
1445130561Sobrien  JVMWrapper("JVM_GetClassDeclaredFields");
1446130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1447130561Sobrien
1448130561Sobrien  // Exclude primitive types and array types
1449130561Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
1450130561Sobrien      Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) {
1451130561Sobrien    // Return empty array
1452130561Sobrien    oop res = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), 0, CHECK_NULL);
1453130561Sobrien    return (jobjectArray) JNIHandles::make_local(env, res);
1454130561Sobrien  }
145568765Sobrien
1456130561Sobrien  instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
1457218822Sdim  constantPoolHandle cp(THREAD, k->constants());
1458130561Sobrien
1459130561Sobrien  // Ensure class is linked
1460130561Sobrien  k->link_class(CHECK_NULL);
146168765Sobrien
1462130561Sobrien  typeArrayHandle fields(THREAD, k->fields());
1463130561Sobrien  int fields_len = fields->length();
1464130561Sobrien
1465130561Sobrien  // 4496456 We need to filter out java.lang.Throwable.backtrace
1466130561Sobrien  bool skip_backtrace = false;
1467130561Sobrien
1468130561Sobrien  // Allocate result
1469130561Sobrien  int num_fields;
147068765Sobrien
1471130561Sobrien  if (publicOnly) {
1472130561Sobrien    num_fields = 0;
1473130561Sobrien    for (int i = 0, j = 0; i < fields_len; i += instanceKlass::next_offset, j++) {
1474130561Sobrien      int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
1475130561Sobrien      if (mods & JVM_ACC_PUBLIC) ++num_fields;
1476130561Sobrien    }
1477130561Sobrien  } else {
147868765Sobrien    num_fields = fields_len / instanceKlass::next_offset;
1479130561Sobrien
148068765Sobrien    if (k() == SystemDictionary::throwable_klass()) {
1481130561Sobrien      num_fields--;
1482130561Sobrien      skip_backtrace = true;
1483130561Sobrien    }
1484130561Sobrien  }
1485130561Sobrien
1486130561Sobrien  objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), num_fields, CHECK_NULL);
1487130561Sobrien  objArrayHandle result (THREAD, r);
1488130561Sobrien
1489130561Sobrien  int out_idx = 0;
1490130561Sobrien  fieldDescriptor fd;
1491130561Sobrien  for (int i = 0; i < fields_len; i += instanceKlass::next_offset) {
1492130561Sobrien    if (skip_backtrace) {
1493130561Sobrien      // 4496456 skip java.lang.Throwable.backtrace
1494130561Sobrien      int offset = k->offset_from_fields(i);
1495130561Sobrien      if (offset == java_lang_Throwable::get_backtrace_offset()) continue;
149668765Sobrien    }
149768765Sobrien
149868765Sobrien    int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
149968765Sobrien    if (!publicOnly || (mods & JVM_ACC_PUBLIC)) {
1500130561Sobrien      fd.initialize(k(), i);
1501130561Sobrien      oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL);
1502130561Sobrien      result->obj_at_put(out_idx, field);
1503130561Sobrien      ++out_idx;
1504130561Sobrien    }
1505130561Sobrien  }
1506130561Sobrien  assert(out_idx == num_fields, "just checking");
1507130561Sobrien  return (jobjectArray) JNIHandles::make_local(env, result());
1508130561Sobrien}
1509130561SobrienJVM_END
1510130561Sobrien
1511130561SobrienJVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly))
1512218822Sdim{
1513130561Sobrien  JVMWrapper("JVM_GetClassDeclaredMethods");
151468765Sobrien  JvmtiVMObjectAllocEventCollector oam;
1515130561Sobrien
1516218822Sdim  // Exclude primitive types and array types
151768765Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass))
1518130561Sobrien      || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) {
1519218822Sdim    // Return empty array
152068765Sobrien    oop res = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), 0, CHECK_NULL);
1521130561Sobrien    return (jobjectArray) JNIHandles::make_local(env, res);
1522130561Sobrien  }
1523130561Sobrien
1524130561Sobrien  instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
1525130561Sobrien
1526130561Sobrien  // Ensure class is linked
1527130561Sobrien  k->link_class(CHECK_NULL);
1528130561Sobrien
1529130561Sobrien  objArrayHandle methods (THREAD, k->methods());
1530130561Sobrien  int methods_length = methods->length();
1531130561Sobrien  int num_methods = 0;
1532130561Sobrien
1533130561Sobrien  int i;
1534130561Sobrien  for (i = 0; i < methods_length; i++) {
1535130561Sobrien    methodHandle method(THREAD, (methodOop) methods->obj_at(i));
1536130561Sobrien    if (!method->is_initializer()) {
1537104834Sobrien      if (!publicOnly || method->is_public()) {
1538130561Sobrien        ++num_methods;
1539130561Sobrien      }
1540130561Sobrien    }
1541130561Sobrien  }
1542130561Sobrien
1543130561Sobrien  // Allocate result
1544130561Sobrien  objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), num_methods, CHECK_NULL);
1545130561Sobrien  objArrayHandle result (THREAD, r);
1546130561Sobrien
1547130561Sobrien  int out_idx = 0;
1548130561Sobrien  for (i = 0; i < methods_length; i++) {
1549130561Sobrien    methodHandle method(THREAD, (methodOop) methods->obj_at(i));
1550130561Sobrien    if (!method->is_initializer()) {
1551130561Sobrien      if (!publicOnly || method->is_public()) {
1552130561Sobrien        oop m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL);
1553130561Sobrien        result->obj_at_put(out_idx, m);
1554130561Sobrien        ++out_idx;
1555130561Sobrien      }
1556130561Sobrien    }
1557130561Sobrien  }
1558130561Sobrien  assert(out_idx == num_methods, "just checking");
1559130561Sobrien  return (jobjectArray) JNIHandles::make_local(env, result());
1560130561Sobrien}
1561130561SobrienJVM_END
1562130561Sobrien
1563130561SobrienJVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly))
1564130561Sobrien{
1565130561Sobrien  JVMWrapper("JVM_GetClassDeclaredConstructors");
1566130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1567130561Sobrien
1568218822Sdim  // Exclude primitive types and array types
1569130561Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass))
1570130561Sobrien      || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) {
1571130561Sobrien    // Return empty array
1572130561Sobrien    oop res = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), 0 , CHECK_NULL);
1573130561Sobrien    return (jobjectArray) JNIHandles::make_local(env, res);
1574130561Sobrien  }
1575130561Sobrien
1576130561Sobrien  instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
1577130561Sobrien
1578130561Sobrien  // Ensure class is linked
1579130561Sobrien  k->link_class(CHECK_NULL);
1580130561Sobrien
1581130561Sobrien  objArrayHandle methods (THREAD, k->methods());
1582130561Sobrien  int methods_length = methods->length();
1583130561Sobrien  int num_constructors = 0;
1584130561Sobrien
1585130561Sobrien  int i;
1586130561Sobrien  for (i = 0; i < methods_length; i++) {
1587104834Sobrien    methodHandle method(THREAD, (methodOop) methods->obj_at(i));
158868765Sobrien    if (method->is_initializer() && !method->is_static()) {
1589218822Sdim      if (!publicOnly || method->is_public()) {
159077298Sobrien        ++num_constructors;
1591130561Sobrien      }
1592130561Sobrien    }
1593130561Sobrien  }
1594130561Sobrien
159577298Sobrien  // Allocate result
1596130561Sobrien  objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), num_constructors, CHECK_NULL);
1597130561Sobrien  objArrayHandle result(THREAD, r);
1598130561Sobrien
1599130561Sobrien  int out_idx = 0;
1600218822Sdim  for (i = 0; i < methods_length; i++) {
1601218822Sdim    methodHandle method(THREAD, (methodOop) methods->obj_at(i));
1602218822Sdim    if (method->is_initializer() && !method->is_static()) {
1603218822Sdim      if (!publicOnly || method->is_public()) {
1604130561Sobrien        oop m = Reflection::new_constructor(method, CHECK_NULL);
1605130561Sobrien        result->obj_at_put(out_idx, m);
160677298Sobrien        ++out_idx;
160777298Sobrien      }
1608130561Sobrien    }
1609130561Sobrien  }
161068765Sobrien  assert(out_idx == num_constructors, "just checking");
161168765Sobrien  return (jobjectArray) JNIHandles::make_local(env, result());
1612130561Sobrien}
1613130561SobrienJVM_END
161468765Sobrien
1615130561SobrienJVM_ENTRY(jint, JVM_GetClassAccessFlags(JNIEnv *env, jclass cls))
161668765Sobrien{
1617130561Sobrien  JVMWrapper("JVM_GetClassAccessFlags");
161868765Sobrien  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
1619130561Sobrien    // Primitive type
1620130561Sobrien    return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
162168765Sobrien  }
1622130561Sobrien
1623130561Sobrien  Klass* k = Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)));
162468765Sobrien  return k->access_flags().as_int() & JVM_ACC_WRITTEN_FLAGS;
1625130561Sobrien}
1626218822SdimJVM_END
1627130561Sobrien
1628130561Sobrien
1629130561Sobrien// Constant pool access //////////////////////////////////////////////////////////
163068765Sobrien
1631130561SobrienJVM_ENTRY(jobject, JVM_GetClassConstantPool(JNIEnv *env, jclass cls))
1632218822Sdim{
1633130561Sobrien  JVMWrapper("JVM_GetClassConstantPool");
163468765Sobrien  JvmtiVMObjectAllocEventCollector oam;
1635218822Sdim
1636218822Sdim  // Return null for primitives and arrays
1637130561Sobrien  if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
1638218822Sdim    klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
163968765Sobrien    if (Klass::cast(k)->oop_is_instance()) {
1640130561Sobrien      instanceKlassHandle k_h(THREAD, k);
1641130561Sobrien      Handle jcp = sun_reflect_ConstantPool::create(CHECK_NULL);
164268765Sobrien      sun_reflect_ConstantPool::set_cp_oop(jcp(), k_h->constants());
1643218822Sdim      return JNIHandles::make_local(jcp());
1644130561Sobrien    }
164568765Sobrien  }
1646130561Sobrien  return NULL;
1647130561Sobrien}
1648130561SobrienJVM_END
1649130561Sobrien
1650130561Sobrien
1651130561SobrienJVM_ENTRY(jint, JVM_ConstantPoolGetSize(JNIEnv *env, jobject unused, jobject jcpool))
1652130561Sobrien{
1653130561Sobrien  JVMWrapper("JVM_ConstantPoolGetSize");
1654130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1655130561Sobrien  return cp->length();
1656130561Sobrien}
1657130561SobrienJVM_END
1658218822Sdim
1659130561Sobrien
1660130561Sobrienstatic void bounds_check(constantPoolHandle cp, jint index, TRAPS) {
1661104834Sobrien  if (!cp->is_within_bounds(index)) {
1662130561Sobrien    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds");
1663130561Sobrien  }
1664130561Sobrien}
1665130561Sobrien
1666104834Sobrien
1667218822SdimJVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
166868765Sobrien{
1669130561Sobrien  JVMWrapper("JVM_ConstantPoolGetClassAt");
1670130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1671130561Sobrien  bounds_check(cp, index, CHECK_NULL);
167268765Sobrien  constantTag tag = cp->tag_at(index);
1673218822Sdim  if (!tag.is_klass() && !tag.is_unresolved_klass()) {
1674130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1675130561Sobrien  }
1676130561Sobrien  klassOop k = cp->klass_at(index, CHECK_NULL);
1677130561Sobrien  return (jclass) JNIHandles::make_local(k->klass_part()->java_mirror());
1678130561Sobrien}
1679130561SobrienJVM_END
1680130561Sobrien
1681130561Sobrien
1682130561SobrienJVM_ENTRY(jclass, JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1683130561Sobrien{
1684130561Sobrien  JVMWrapper("JVM_ConstantPoolGetClassAtIfLoaded");
1685130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1686130561Sobrien  bounds_check(cp, index, CHECK_NULL);
1687218822Sdim  constantTag tag = cp->tag_at(index);
1688130561Sobrien  if (!tag.is_klass() && !tag.is_unresolved_klass()) {
1689130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
169068765Sobrien  }
1691130561Sobrien  klassOop k = constantPoolOopDesc::klass_at_if_loaded(cp, index);
1692130561Sobrien  if (k == NULL) return NULL;
1693130561Sobrien  return (jclass) JNIHandles::make_local(k->klass_part()->java_mirror());
169468765Sobrien}
1695218822SdimJVM_END
1696130561Sobrien
1697130561Sobrienstatic jobject get_method_at_helper(constantPoolHandle cp, jint index, bool force_resolution, TRAPS) {
1698130561Sobrien  constantTag tag = cp->tag_at(index);
1699130561Sobrien  if (!tag.is_method() && !tag.is_interface_method()) {
1700130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1701130561Sobrien  }
1702130561Sobrien  int klass_ref  = cp->uncached_klass_ref_index_at(index);
1703130561Sobrien  klassOop k_o;
1704130561Sobrien  if (force_resolution) {
1705130561Sobrien    k_o = cp->klass_at(klass_ref, CHECK_NULL);
1706130561Sobrien  } else {
1707130561Sobrien    k_o = constantPoolOopDesc::klass_at_if_loaded(cp, klass_ref);
1708130561Sobrien    if (k_o == NULL) return NULL;
1709218822Sdim  }
1710130561Sobrien  instanceKlassHandle k(THREAD, k_o);
1711130561Sobrien  symbolOop name = cp->uncached_name_ref_at(index);
171268765Sobrien  symbolOop sig  = cp->uncached_signature_ref_at(index);
1713130561Sobrien  methodHandle m (THREAD, k->find_method(name, sig));
1714130561Sobrien  if (m.is_null()) {
171568765Sobrien    THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class");
171668765Sobrien  }
171768765Sobrien  oop method;
1718130561Sobrien  if (!m->is_initializer() || m->is_static()) {
1719130561Sobrien    method = Reflection::new_method(m, true, true, CHECK_NULL);
1720130561Sobrien  } else {
1721130561Sobrien    method = Reflection::new_constructor(m, CHECK_NULL);
1722130561Sobrien  }
1723130561Sobrien  return JNIHandles::make_local(method);
1724130561Sobrien}
1725130561Sobrien
1726130561SobrienJVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1727130561Sobrien{
1728130561Sobrien  JVMWrapper("JVM_ConstantPoolGetMethodAt");
1729130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1730130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1731130561Sobrien  bounds_check(cp, index, CHECK_NULL);
173277298Sobrien  jobject res = get_method_at_helper(cp, index, true, CHECK_NULL);
1733130561Sobrien  return res;
1734130561Sobrien}
1735130561SobrienJVM_END
173677298Sobrien
1737130561SobrienJVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1738130561Sobrien{
1739130561Sobrien  JVMWrapper("JVM_ConstantPoolGetMethodAtIfLoaded");
174077298Sobrien  JvmtiVMObjectAllocEventCollector oam;
1741218822Sdim  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1742130561Sobrien  bounds_check(cp, index, CHECK_NULL);
1743218822Sdim  jobject res = get_method_at_helper(cp, index, false, CHECK_NULL);
1744218822Sdim  return res;
1745218822Sdim}
1746218822SdimJVM_END
1747218822Sdim
1748218822Sdimstatic jobject get_field_at_helper(constantPoolHandle cp, jint index, bool force_resolution, TRAPS) {
1749130561Sobrien  constantTag tag = cp->tag_at(index);
1750218822Sdim  if (!tag.is_field()) {
1751130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1752130561Sobrien  }
1753218822Sdim  int klass_ref  = cp->uncached_klass_ref_index_at(index);
1754130561Sobrien  klassOop k_o;
1755218822Sdim  if (force_resolution) {
1756218822Sdim    k_o = cp->klass_at(klass_ref, CHECK_NULL);
1757130561Sobrien  } else {
1758130561Sobrien    k_o = constantPoolOopDesc::klass_at_if_loaded(cp, klass_ref);
1759130561Sobrien    if (k_o == NULL) return NULL;
1760218822Sdim  }
1761218822Sdim  instanceKlassHandle k(THREAD, k_o);
1762130561Sobrien  symbolOop name = cp->uncached_name_ref_at(index);
1763130561Sobrien  symbolOop sig  = cp->uncached_signature_ref_at(index);
1764218822Sdim  fieldDescriptor fd;
1765218822Sdim  klassOop target_klass = k->find_field(name, sig, &fd);
1766218822Sdim  if (target_klass == NULL) {
1767218822Sdim    THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class");
1768130561Sobrien  }
1769130561Sobrien  oop field = Reflection::new_field(&fd, true, CHECK_NULL);
177077298Sobrien  return JNIHandles::make_local(field);
1771130561Sobrien}
1772130561Sobrien
1773218822SdimJVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1774130561Sobrien{
1775130561Sobrien  JVMWrapper("JVM_ConstantPoolGetFieldAt");
1776130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1777130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
177877298Sobrien  bounds_check(cp, index, CHECK_NULL);
1779130561Sobrien  jobject res = get_field_at_helper(cp, index, true, CHECK_NULL);
1780130561Sobrien  return res;
1781130561Sobrien}
1782130561SobrienJVM_END
1783130561Sobrien
1784130561SobrienJVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index))
178577298Sobrien{
1786130561Sobrien  JVMWrapper("JVM_ConstantPoolGetFieldAtIfLoaded");
1787130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1788130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1789130561Sobrien  bounds_check(cp, index, CHECK_NULL);
1790130561Sobrien  jobject res = get_field_at_helper(cp, index, false, CHECK_NULL);
1791130561Sobrien  return res;
1792130561Sobrien}
1793130561SobrienJVM_END
1794130561Sobrien
1795130561SobrienJVM_ENTRY(jobjectArray, JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
179677298Sobrien{
1797130561Sobrien  JVMWrapper("JVM_ConstantPoolGetMemberRefInfoAt");
1798130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1799130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1800130561Sobrien  bounds_check(cp, index, CHECK_NULL);
1801130561Sobrien  constantTag tag = cp->tag_at(index);
1802130561Sobrien  if (!tag.is_field_or_method()) {
1803218822Sdim    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1804130561Sobrien  }
1805130561Sobrien  int klass_ref = cp->uncached_klass_ref_index_at(index);
180677298Sobrien  symbolHandle klass_name (THREAD, cp->klass_name_at(klass_ref));
180777298Sobrien  symbolHandle member_name(THREAD, cp->uncached_name_ref_at(index));
1808130561Sobrien  symbolHandle member_sig (THREAD, cp->uncached_signature_ref_at(index));
180977298Sobrien  objArrayOop  dest_o = oopFactory::new_objArray(SystemDictionary::string_klass(), 3, CHECK_NULL);
1810130561Sobrien  objArrayHandle dest(THREAD, dest_o);
1811130561Sobrien  Handle str = java_lang_String::create_from_symbol(klass_name, CHECK_NULL);
1812130561Sobrien  dest->obj_at_put(0, str());
1813130561Sobrien  str = java_lang_String::create_from_symbol(member_name, CHECK_NULL);
1814130561Sobrien  dest->obj_at_put(1, str());
1815130561Sobrien  str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL);
1816130561Sobrien  dest->obj_at_put(2, str());
1817130561Sobrien  return (jobjectArray) JNIHandles::make_local(dest());
1818130561Sobrien}
1819130561SobrienJVM_END
1820130561Sobrien
1821130561SobrienJVM_ENTRY(jint, JVM_ConstantPoolGetIntAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
182277298Sobrien{
1823130561Sobrien  JVMWrapper("JVM_ConstantPoolGetIntAt");
1824130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1825130561Sobrien  bounds_check(cp, index, CHECK_0);
1826130561Sobrien  constantTag tag = cp->tag_at(index);
1827130561Sobrien  if (!tag.is_int()) {
182877298Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1829130561Sobrien  }
1830130561Sobrien  return cp->int_at(index);
1831130561Sobrien}
183277298SobrienJVM_END
1833130561Sobrien
1834130561SobrienJVM_ENTRY(jlong, JVM_ConstantPoolGetLongAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1835130561Sobrien{
1836130561Sobrien  JVMWrapper("JVM_ConstantPoolGetLongAt");
1837130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1838130561Sobrien  bounds_check(cp, index, CHECK_(0L));
183977298Sobrien  constantTag tag = cp->tag_at(index);
1840130561Sobrien  if (!tag.is_long()) {
1841130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1842130561Sobrien  }
184377298Sobrien  return cp->long_at(index);
1844130561Sobrien}
1845130561SobrienJVM_END
1846130561Sobrien
184777298SobrienJVM_ENTRY(jfloat, JVM_ConstantPoolGetFloatAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1848130561Sobrien{
1849130561Sobrien  JVMWrapper("JVM_ConstantPoolGetFloatAt");
1850130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1851130561Sobrien  bounds_check(cp, index, CHECK_(0.0f));
1852130561Sobrien  constantTag tag = cp->tag_at(index);
1853130561Sobrien  if (!tag.is_float()) {
1854130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1855130561Sobrien  }
1856130561Sobrien  return cp->float_at(index);
1857130561Sobrien}
1858130561SobrienJVM_END
1859130561Sobrien
1860130561SobrienJVM_ENTRY(jdouble, JVM_ConstantPoolGetDoubleAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
186177298Sobrien{
1862130561Sobrien  JVMWrapper("JVM_ConstantPoolGetDoubleAt");
1863130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1864130561Sobrien  bounds_check(cp, index, CHECK_(0.0));
1865130561Sobrien  constantTag tag = cp->tag_at(index);
1866130561Sobrien  if (!tag.is_double()) {
186777298Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1868130561Sobrien  }
1869130561Sobrien  return cp->double_at(index);
1870130561Sobrien}
1871130561SobrienJVM_END
1872130561Sobrien
1873130561SobrienJVM_ENTRY(jstring, JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1874130561Sobrien{
1875130561Sobrien  JVMWrapper("JVM_ConstantPoolGetStringAt");
1876130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1877130561Sobrien  bounds_check(cp, index, CHECK_NULL);
1878130561Sobrien  constantTag tag = cp->tag_at(index);
1879130561Sobrien  if (!tag.is_string() && !tag.is_unresolved_string()) {
1880130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1881130561Sobrien  }
1882130561Sobrien  oop str = cp->string_at(index, CHECK_NULL);
1883130561Sobrien  return (jstring) JNIHandles::make_local(str);
1884130561Sobrien}
1885130561SobrienJVM_END
1886130561Sobrien
1887130561SobrienJVM_ENTRY(jstring, JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject unused, jobject jcpool, jint index))
1888130561Sobrien{
1889130561Sobrien  JVMWrapper("JVM_ConstantPoolGetUTF8At");
1890130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
1891130561Sobrien  constantPoolHandle cp = constantPoolHandle(THREAD, constantPoolOop(JNIHandles::resolve_non_null(jcpool)));
1892130561Sobrien  bounds_check(cp, index, CHECK_NULL);
1893130561Sobrien  constantTag tag = cp->tag_at(index);
1894130561Sobrien  if (!tag.is_symbol()) {
1895130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
1896130561Sobrien  }
1897130561Sobrien  symbolOop sym_o = cp->symbol_at(index);
1898130561Sobrien  symbolHandle sym(THREAD, sym_o);
1899130561Sobrien  Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
1900130561Sobrien  return (jstring) JNIHandles::make_local(str());
1901130561Sobrien}
1902130561SobrienJVM_END
1903130561Sobrien
1904130561Sobrien
1905130561Sobrien// Assertion support. //////////////////////////////////////////////////////////
1906130561Sobrien
1907130561SobrienJVM_ENTRY(jboolean, JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls))
1908130561Sobrien  JVMWrapper("JVM_DesiredAssertionStatus");
1909130561Sobrien  assert(cls != NULL, "bad class");
1910130561Sobrien
1911130561Sobrien  oop r = JNIHandles::resolve(cls);
1912130561Sobrien  assert(! java_lang_Class::is_primitive(r), "primitive classes not allowed");
1913130561Sobrien  if (java_lang_Class::is_primitive(r)) return false;
1914130561Sobrien
1915130561Sobrien  klassOop k = java_lang_Class::as_klassOop(r);
1916130561Sobrien  assert(Klass::cast(k)->oop_is_instance(), "must be an instance klass");
1917130561Sobrien  if (! Klass::cast(k)->oop_is_instance()) return false;
1918130561Sobrien
1919130561Sobrien  ResourceMark rm(THREAD);
1920130561Sobrien  const char* name = Klass::cast(k)->name()->as_C_string();
1921130561Sobrien  bool system_class = Klass::cast(k)->class_loader() == NULL;
1922130561Sobrien  return JavaAssertions::enabled(name, system_class);
1923130561Sobrien
1924130561SobrienJVM_END
1925130561Sobrien
1926130561Sobrien
1927130561Sobrien// Return a new AssertionStatusDirectives object with the fields filled in with
1928130561Sobrien// command-line assertion arguments (i.e., -ea, -da).
1929130561SobrienJVM_ENTRY(jobject, JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused))
1930130561Sobrien  JVMWrapper("JVM_AssertionStatusDirectives");
193177298Sobrien  JvmtiVMObjectAllocEventCollector oam;
1932130561Sobrien  oop asd = JavaAssertions::createAssertionStatusDirectives(CHECK_NULL);
1933130561Sobrien  return JNIHandles::make_local(env, asd);
193477298SobrienJVM_END
193577298Sobrien
1936130561Sobrien// Verification ////////////////////////////////////////////////////////////////////////////////
193777298Sobrien
193877298Sobrien// Reflection for the verifier /////////////////////////////////////////////////////////////////
1939130561Sobrien
194077298Sobrien// RedefineClasses support: bug 6214132 caused verification to fail.
1941130561Sobrien// All functions from this section should call the jvmtiThreadSate function:
1942218822Sdim//   klassOop class_to_verify_considering_redefinition(klassOop klass).
1943218822Sdim// The function returns a klassOop of the _scratch_class if the verifier
194477298Sobrien// was invoked in the middle of the class redefinition.
1945130561Sobrien// Otherwise it returns its argument value which is the _the_class klassOop.
194677298Sobrien// Please, refer to the description in the jvmtiThreadSate.hpp.
1947130561Sobrien
1948130561SobrienJVM_ENTRY(const char*, JVM_GetClassNameUTF(JNIEnv *env, jclass cls))
194977298Sobrien  JVMWrapper("JVM_GetClassNameUTF");
1950130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
195177298Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
1952130561Sobrien  return Klass::cast(k)->name()->as_utf8();
1953130561SobrienJVM_END
1954130561Sobrien
1955130561Sobrien
1956130561SobrienJVM_QUICK_ENTRY(void, JVM_GetClassCPTypes(JNIEnv *env, jclass cls, unsigned char *types))
1957130561Sobrien  JVMWrapper("JVM_GetClassCPTypes");
1958130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
1959130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
1960130561Sobrien  // types will have length zero if this is not an instanceKlass
1961130561Sobrien  // (length is determined by call to JVM_GetClassCPEntriesCount)
1962130561Sobrien  if (Klass::cast(k)->oop_is_instance()) {
1963130561Sobrien    constantPoolOop cp = instanceKlass::cast(k)->constants();
1964130561Sobrien    for (int index = cp->length() - 1; index >= 0; index--) {
1965130561Sobrien      constantTag tag = cp->tag_at(index);
1966130561Sobrien      types[index] = (tag.is_unresolved_klass()) ? JVM_CONSTANT_Class :
1967130561Sobrien                     (tag.is_unresolved_string()) ? JVM_CONSTANT_String : tag.value();
1968130561Sobrien  }
1969130561Sobrien  }
1970130561SobrienJVM_END
1971130561Sobrien
1972130561Sobrien
1973130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cls))
197477298Sobrien  JVMWrapper("JVM_GetClassCPEntriesCount");
1975130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
1976130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
1977130561Sobrien  if (!Klass::cast(k)->oop_is_instance())
1978130561Sobrien    return 0;
1979130561Sobrien  return instanceKlass::cast(k)->constants()->length();
1980130561SobrienJVM_END
198177298Sobrien
198277298Sobrien
1983130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetClassFieldsCount(JNIEnv *env, jclass cls))
198477298Sobrien  JVMWrapper("JVM_GetClassFieldsCount");
198577298Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
1986130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
198768765Sobrien  if (!Klass::cast(k)->oop_is_instance())
1988130561Sobrien    return 0;
1989218822Sdim  return instanceKlass::cast(k)->fields()->length() / instanceKlass::next_offset;
1990130561SobrienJVM_END
1991130561Sobrien
199268765Sobrien
1993218822SdimJVM_QUICK_ENTRY(jint, JVM_GetClassMethodsCount(JNIEnv *env, jclass cls))
1994130561Sobrien  JVMWrapper("JVM_GetClassMethodsCount");
1995130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
1996130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
1997130561Sobrien  if (!Klass::cast(k)->oop_is_instance())
1998130561Sobrien    return 0;
1999130561Sobrien  return instanceKlass::cast(k)->methods()->length();
2000130561SobrienJVM_END
2001130561Sobrien
2002218822Sdim
2003130561Sobrien// The following methods, used for the verifier, are never called with
2004130561Sobrien// array klasses, so a direct cast to instanceKlass is safe.
2005130561Sobrien// Typically, these methods are called in a loop with bounds determined
200677298Sobrien// by the results of JVM_GetClass{Fields,Methods}Count, which return
2007218822Sdim// zero for arrays.
200877298SobrienJVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cls, jint method_index, unsigned short *exceptions))
2009130561Sobrien  JVMWrapper("JVM_GetMethodIxExceptionIndexes");
2010218822Sdim  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2011130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2012130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2013130561Sobrien  int length = methodOop(method)->checked_exceptions_length();
2014130561Sobrien  if (length > 0) {
2015218822Sdim    CheckedExceptionElement* table= methodOop(method)->checked_exceptions_start();
201677298Sobrien    for (int i = 0; i < length; i++) {
2017218822Sdim      exceptions[i] = table[i].class_cp_index;
2018218822Sdim    }
2019218822Sdim  }
2020218822SdimJVM_END
2021218822Sdim
2022218822Sdim
2023218822SdimJVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cls, jint method_index))
2024218822Sdim  JVMWrapper("JVM_GetMethodIxExceptionsCount");
2025218822Sdim  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2026130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2027130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2028130561Sobrien  return methodOop(method)->checked_exceptions_length();
2029130561SobrienJVM_END
2030130561Sobrien
2031130561Sobrien
203277298SobrienJVM_QUICK_ENTRY(void, JVM_GetMethodIxByteCode(JNIEnv *env, jclass cls, jint method_index, unsigned char *code))
2033130561Sobrien  JVMWrapper("JVM_GetMethodIxByteCode");
2034130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2035130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2036130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2037130561Sobrien  memcpy(code, methodOop(method)->code_base(), methodOop(method)->code_size());
2038130561SobrienJVM_END
2039130561Sobrien
2040130561Sobrien
2041130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cls, jint method_index))
2042130561Sobrien  JVMWrapper("JVM_GetMethodIxByteCodeLength");
2043130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2044130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2045130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2046130561Sobrien  return methodOop(method)->code_size();
2047130561SobrienJVM_END
2048130561Sobrien
2049130561Sobrien
2050130561SobrienJVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cls, jint method_index, jint entry_index, JVM_ExceptionTableEntryType *entry))
2051130561Sobrien  JVMWrapper("JVM_GetMethodIxExceptionTableEntry");
205277298Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2053130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2054130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2055130561Sobrien  typeArrayOop extable = methodOop(method)->exception_table();
2056130561Sobrien  entry->start_pc   = extable->int_at(entry_index * 4);
2057130561Sobrien  entry->end_pc     = extable->int_at(entry_index * 4 + 1);
205868765Sobrien  entry->handler_pc = extable->int_at(entry_index * 4 + 2);
2059130561Sobrien  entry->catchType  = extable->int_at(entry_index * 4 + 3);
2060130561SobrienJVM_END
2061130561Sobrien
2062130561Sobrien
2063130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cls, int method_index))
2064130561Sobrien  JVMWrapper("JVM_GetMethodIxExceptionTableLength");
2065130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2066130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
206768765Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2068130561Sobrien  return methodOop(method)->exception_table()->length() / 4;
2069130561SobrienJVM_END
2070130561Sobrien
2071130561Sobrien
2072130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetMethodIxModifiers(JNIEnv *env, jclass cls, int method_index))
2073130561Sobrien  JVMWrapper("JVM_GetMethodIxModifiers");
2074218822Sdim  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
207568765Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2076130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2077130561Sobrien  return methodOop(method)->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
207868765SobrienJVM_END
2079130561Sobrien
2080130561Sobrien
2081130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index))
208268765Sobrien  JVMWrapper("JVM_GetFieldIxModifiers");
2083130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2084218822Sdim  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2085130561Sobrien  typeArrayOop fields = instanceKlass::cast(k)->fields();
2086130561Sobrien  return fields->ushort_at(field_index * instanceKlass::next_offset + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
2087130561SobrienJVM_END
2088130561Sobrien
2089218822Sdim
2090130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index))
2091130561Sobrien  JVMWrapper("JVM_GetMethodIxLocalsCount");
2092130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2093130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2094130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2095130561Sobrien  return methodOop(method)->max_locals();
209668765SobrienJVM_END
2097130561Sobrien
2098130561Sobrien
2099130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cls, int method_index))
2100130561Sobrien  JVMWrapper("JVM_GetMethodIxArgsSize");
210189857Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2102130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2103130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
210489857Sobrien  return methodOop(method)->size_of_parameters();
2105130561SobrienJVM_END
2106130561Sobrien
2107130561Sobrien
2108130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cls, int method_index))
210968765Sobrien  JVMWrapper("JVM_GetMethodIxMaxStack");
2110130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
211168765Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2112130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2113130561Sobrien  return methodOop(method)->max_stack();
2114130561SobrienJVM_END
2115130561Sobrien
211668765Sobrien
2117218822SdimJVM_QUICK_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index))
2118130561Sobrien  JVMWrapper("JVM_IsConstructorIx");
211968765Sobrien  ResourceMark rm(THREAD);
2120130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2121130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2122130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
212368765Sobrien  return methodOop(method)->name() == vmSymbols::object_initializer_name();
2124130561SobrienJVM_END
212568765Sobrien
2126130561Sobrien
2127218822SdimJVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index))
2128130561Sobrien  JVMWrapper("JVM_GetMethodIxIxUTF");
2129130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2130130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2131130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
213268765Sobrien  return methodOop(method)->name()->as_utf8();
2133218822SdimJVM_END
2134130561Sobrien
213568765Sobrien
2136130561SobrienJVM_ENTRY(const char*, JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cls, jint method_index))
213768765Sobrien  JVMWrapper("JVM_GetMethodIxSignatureUTF");
2138130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2139130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2140130561Sobrien  oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
2141130561Sobrien  return methodOop(method)->signature()->as_utf8();
2142130561SobrienJVM_END
2143130561Sobrien
2144130561Sobrien/**
2145130561Sobrien * All of these JVM_GetCP-xxx methods are used by the old verifier to
2146130561Sobrien * read entries in the constant pool.  Since the old verifier always
2147130561Sobrien * works on a copy of the code, it will not see any rewriting that
2148130561Sobrien * may possibly occur in the middle of verification.  So it is important
2149218822Sdim * that nothing it calls tries to use the cpCache instead of the raw
2150218822Sdim * constant pool, so we must use cp->uncached_x methods when appropriate.
2151218822Sdim */
2152218822SdimJVM_ENTRY(const char*, JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cls, jint cp_index))
215368765Sobrien  JVMWrapper("JVM_GetCPFieldNameUTF");
2154130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2155130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2156130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2157130561Sobrien  switch (cp->tag_at(cp_index).value()) {
2158218822Sdim    case JVM_CONSTANT_Fieldref:
2159218822Sdim      return cp->uncached_name_ref_at(cp_index)->as_utf8();
216068765Sobrien    default:
2161218822Sdim      fatal("JVM_GetCPFieldNameUTF: illegal constant");
2162218822Sdim  }
2163218822Sdim  ShouldNotReachHere();
2164218822Sdim  return NULL;
2165218822SdimJVM_END
2166218822Sdim
2167130561Sobrien
2168130561SobrienJVM_ENTRY(const char*, JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_index))
216968765Sobrien  JVMWrapper("JVM_GetCPMethodNameUTF");
2170130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2171130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2172130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
217377298Sobrien  switch (cp->tag_at(cp_index).value()) {
2174130561Sobrien    case JVM_CONSTANT_InterfaceMethodref:
2175218822Sdim    case JVM_CONSTANT_Methodref:
2176130561Sobrien      return cp->uncached_name_ref_at(cp_index)->as_utf8();
2177130561Sobrien    default:
217868765Sobrien      fatal("JVM_GetCPMethodNameUTF: illegal constant");
2179218822Sdim  }
2180130561Sobrien  ShouldNotReachHere();
218168765Sobrien  return NULL;
2182130561SobrienJVM_END
2183130561Sobrien
2184130561Sobrien
2185130561SobrienJVM_ENTRY(const char*, JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint cp_index))
2186130561Sobrien  JVMWrapper("JVM_GetCPMethodSignatureUTF");
2187130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2188130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2189130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2190130561Sobrien  switch (cp->tag_at(cp_index).value()) {
219168765Sobrien    case JVM_CONSTANT_InterfaceMethodref:
2192218822Sdim    case JVM_CONSTANT_Methodref:
2193130561Sobrien      return cp->uncached_signature_ref_at(cp_index)->as_utf8();
219468765Sobrien    default:
2195130561Sobrien      fatal("JVM_GetCPMethodSignatureUTF: illegal constant");
219668765Sobrien  }
2197130561Sobrien  ShouldNotReachHere();
2198130561Sobrien  return NULL;
219968765SobrienJVM_END
2200130561Sobrien
220168765Sobrien
2202130561SobrienJVM_ENTRY(const char*, JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cls, jint cp_index))
2203218822Sdim  JVMWrapper("JVM_GetCPFieldSignatureUTF");
2204130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2205130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2206130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2207130561Sobrien  switch (cp->tag_at(cp_index).value()) {
2208130561Sobrien    case JVM_CONSTANT_Fieldref:
2209130561Sobrien      return cp->uncached_signature_ref_at(cp_index)->as_utf8();
2210130561Sobrien    default:
2211130561Sobrien      fatal("JVM_GetCPFieldSignatureUTF: illegal constant");
2212130561Sobrien  }
2213130561Sobrien  ShouldNotReachHere();
2214218822Sdim  return NULL;
2215130561SobrienJVM_END
2216130561Sobrien
2217130561Sobrien
2218130561SobrienJVM_ENTRY(const char*, JVM_GetCPClassNameUTF(JNIEnv *env, jclass cls, jint cp_index))
2219130561Sobrien  JVMWrapper("JVM_GetCPClassNameUTF");
2220130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2221130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2222130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2223130561Sobrien  symbolOop classname = cp->klass_name_at(cp_index);
2224130561Sobrien  return classname->as_utf8();
2225130561SobrienJVM_END
2226130561Sobrien
2227130561Sobrien
2228130561SobrienJVM_ENTRY(const char*, JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cls, jint cp_index))
2229130561Sobrien  JVMWrapper("JVM_GetCPFieldClassNameUTF");
2230130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2231130561Sobrien  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2232130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2233130561Sobrien  switch (cp->tag_at(cp_index).value()) {
2234130561Sobrien    case JVM_CONSTANT_Fieldref: {
2235130561Sobrien      int class_index = cp->uncached_klass_ref_index_at(cp_index);
223668765Sobrien      symbolOop classname = cp->klass_name_at(class_index);
223768765Sobrien      return classname->as_utf8();
223868765Sobrien    }
2239130561Sobrien    default:
2240130561Sobrien      fatal("JVM_GetCPFieldClassNameUTF: illegal constant");
2241130561Sobrien  }
224268765Sobrien  ShouldNotReachHere();
224368765Sobrien  return NULL;
2244130561SobrienJVM_END
2245130561Sobrien
2246130561Sobrien
2247130561SobrienJVM_ENTRY(const char*, JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint cp_index))
224868765Sobrien  JVMWrapper("JVM_GetCPMethodClassNameUTF");
2249130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2250218822Sdim  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
225168765Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2252130561Sobrien  switch (cp->tag_at(cp_index).value()) {
225368765Sobrien    case JVM_CONSTANT_Methodref:
2254130561Sobrien    case JVM_CONSTANT_InterfaceMethodref: {
2255130561Sobrien      int class_index = cp->uncached_klass_ref_index_at(cp_index);
2256130561Sobrien      symbolOop classname = cp->klass_name_at(class_index);
2257130561Sobrien      return classname->as_utf8();
2258130561Sobrien    }
2259218822Sdim    default:
2260130561Sobrien      fatal("JVM_GetCPMethodClassNameUTF: illegal constant");
2261130561Sobrien  }
226268765Sobrien  ShouldNotReachHere();
2263130561Sobrien  return NULL;
2264130561SobrienJVM_END
2265130561Sobrien
2266130561Sobrien
2267130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls))
2268130561Sobrien  JVMWrapper("JVM_GetCPFieldModifiers");
2269130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2270130561Sobrien  klassOop k_called = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(called_cls));
2271130561Sobrien  k        = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2272130561Sobrien  k_called = JvmtiThreadState::class_to_verify_considering_redefinition(k_called, thread);
2273130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2274130561Sobrien  constantPoolOop cp_called = instanceKlass::cast(k_called)->constants();
2275130561Sobrien  switch (cp->tag_at(cp_index).value()) {
2276130561Sobrien    case JVM_CONSTANT_Fieldref: {
2277130561Sobrien      symbolOop name      = cp->uncached_name_ref_at(cp_index);
2278130561Sobrien      symbolOop signature = cp->uncached_signature_ref_at(cp_index);
2279130561Sobrien      typeArrayOop fields = instanceKlass::cast(k_called)->fields();
2280130561Sobrien      int fields_count = fields->length();
2281130561Sobrien      for (int i = 0; i < fields_count; i += instanceKlass::next_offset) {
2282218822Sdim        if (cp_called->symbol_at(fields->ushort_at(i + instanceKlass::name_index_offset)) == name &&
2283130561Sobrien            cp_called->symbol_at(fields->ushort_at(i + instanceKlass::signature_index_offset)) == signature) {
2284130561Sobrien          return fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
2285130561Sobrien        }
2286130561Sobrien      }
2287130561Sobrien      return -1;
2288130561Sobrien    }
2289130561Sobrien    default:
2290130561Sobrien      fatal("JVM_GetCPFieldModifiers: illegal constant");
2291130561Sobrien  }
229268765Sobrien  ShouldNotReachHere();
2293130561Sobrien  return 0;
2294130561SobrienJVM_END
2295130561Sobrien
2296130561Sobrien
2297130561SobrienJVM_QUICK_ENTRY(jint, JVM_GetCPMethodModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls))
2298130561Sobrien  JVMWrapper("JVM_GetCPMethodModifiers");
2299130561Sobrien  klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
2300130561Sobrien  klassOop k_called = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(called_cls));
2301130561Sobrien  k        = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
2302130561Sobrien  k_called = JvmtiThreadState::class_to_verify_considering_redefinition(k_called, thread);
2303130561Sobrien  constantPoolOop cp = instanceKlass::cast(k)->constants();
2304130561Sobrien  switch (cp->tag_at(cp_index).value()) {
230568765Sobrien    case JVM_CONSTANT_Methodref:
2306130561Sobrien    case JVM_CONSTANT_InterfaceMethodref: {
230768765Sobrien      symbolOop name      = cp->uncached_name_ref_at(cp_index);
2308130561Sobrien      symbolOop signature = cp->uncached_signature_ref_at(cp_index);
2309130561Sobrien      objArrayOop methods = instanceKlass::cast(k_called)->methods();
2310130561Sobrien      int methods_count = methods->length();
2311130561Sobrien      for (int i = 0; i < methods_count; i++) {
2312130561Sobrien        methodOop method = methodOop(methods->obj_at(i));
2313130561Sobrien        if (method->name() == name && method->signature() == signature) {
2314130561Sobrien            return method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
2315130561Sobrien        }
2316130561Sobrien      }
2317130561Sobrien      return -1;
2318130561Sobrien    }
2319130561Sobrien    default:
2320130561Sobrien      fatal("JVM_GetCPMethodModifiers: illegal constant");
2321130561Sobrien  }
2322130561Sobrien  ShouldNotReachHere();
2323130561Sobrien  return 0;
232489857SobrienJVM_END
2325130561Sobrien
2326130561Sobrien
2327130561Sobrien// Misc //////////////////////////////////////////////////////////////////////////////////////////////
2328130561Sobrien
232989857SobrienJVM_LEAF(void, JVM_ReleaseUTF(const char *utf))
2330130561Sobrien  // So long as UTF8::convert_to_utf8 returns resource strings, we don't have to do anything
2331130561SobrienJVM_END
233289857Sobrien
2333130561Sobrien
2334130561SobrienJVM_ENTRY(jboolean, JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2))
233589857Sobrien  JVMWrapper("JVM_IsSameClassPackage");
233689857Sobrien  oop class1_mirror = JNIHandles::resolve_non_null(class1);
2337130561Sobrien  oop class2_mirror = JNIHandles::resolve_non_null(class2);
2338130561Sobrien  klassOop klass1 = java_lang_Class::as_klassOop(class1_mirror);
233968765Sobrien  klassOop klass2 = java_lang_Class::as_klassOop(class2_mirror);
2340130561Sobrien  return (jboolean) Reflection::is_same_class_package(klass1, klass2);
2341130561SobrienJVM_END
2342130561Sobrien
2343130561Sobrien
2344130561Sobrien// IO functions ////////////////////////////////////////////////////////////////////////////////////////
2345130561Sobrien
2346130561SobrienJVM_LEAF(jint, JVM_Open(const char *fname, jint flags, jint mode))
2347130561Sobrien  JVMWrapper2("JVM_Open (%s)", fname);
2348130561Sobrien
2349130561Sobrien  //%note jvm_r6
2350130561Sobrien  int result = hpi::open(fname, flags, mode);
2351130561Sobrien  if (result >= 0) {
2352130561Sobrien    return result;
2353130561Sobrien  } else {
2354130561Sobrien    switch(errno) {
2355130561Sobrien      case EEXIST:
2356130561Sobrien        return JVM_EEXIST;
2357130561Sobrien      default:
2358130561Sobrien        return -1;
2359130561Sobrien    }
2360130561Sobrien  }
2361130561SobrienJVM_END
2362130561Sobrien
2363130561Sobrien
2364130561SobrienJVM_LEAF(jint, JVM_Close(jint fd))
2365130561Sobrien  JVMWrapper2("JVM_Close (0x%x)", fd);
2366130561Sobrien  //%note jvm_r6
2367130561Sobrien  return hpi::close(fd);
2368130561SobrienJVM_END
2369130561Sobrien
2370130561Sobrien
2371130561SobrienJVM_LEAF(jint, JVM_Read(jint fd, char *buf, jint nbytes))
237268765Sobrien  JVMWrapper2("JVM_Read (0x%x)", fd);
237368765Sobrien
2374130561Sobrien  //%note jvm_r6
2375130561Sobrien  return (jint)hpi::read(fd, buf, nbytes);
2376130561SobrienJVM_END
2377130561Sobrien
2378130561Sobrien
2379130561SobrienJVM_LEAF(jint, JVM_Write(jint fd, char *buf, jint nbytes))
2380130561Sobrien  JVMWrapper2("JVM_Write (0x%x)", fd);
2381130561Sobrien
2382218822Sdim  //%note jvm_r6
2383130561Sobrien  return (jint)hpi::write(fd, buf, nbytes);
2384130561SobrienJVM_END
2385130561Sobrien
2386218822Sdim
2387130561SobrienJVM_LEAF(jint, JVM_Available(jint fd, jlong *pbytes))
2388130561Sobrien  JVMWrapper2("JVM_Available (0x%x)", fd);
2389130561Sobrien  //%note jvm_r6
239068765Sobrien  return hpi::available(fd, pbytes);
2391130561SobrienJVM_END
2392130561Sobrien
2393130561Sobrien
2394130561SobrienJVM_LEAF(jlong, JVM_Lseek(jint fd, jlong offset, jint whence))
239568765Sobrien  JVMWrapper4("JVM_Lseek (0x%x, %Ld, %d)", fd, offset, whence);
2396130561Sobrien  //%note jvm_r6
2397175790Sobrien  return hpi::lseek(fd, offset, whence);
2398175790SobrienJVM_END
239968765Sobrien
2400130561Sobrien
2401130561SobrienJVM_LEAF(jint, JVM_SetLength(jint fd, jlong length))
2402130561Sobrien  JVMWrapper3("JVM_SetLength (0x%x, %Ld)", fd, length);
2403130561Sobrien  return hpi::ftruncate(fd, length);
2404130561SobrienJVM_END
240568765Sobrien
2406130561Sobrien
2407130561SobrienJVM_LEAF(jint, JVM_Sync(jint fd))
2408130561Sobrien  JVMWrapper2("JVM_Sync (0x%x)", fd);
2409130561Sobrien  //%note jvm_r6
2410130561Sobrien  return hpi::fsync(fd);
2411130561SobrienJVM_END
2412130561Sobrien
2413130561Sobrien
2414130561Sobrien// Printing support //////////////////////////////////////////////////
2415130561Sobrienextern "C" {
241677298Sobrien
2417130561Sobrienint jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) {
2418130561Sobrien  // see bug 4399518, 4417214
2419130561Sobrien  if ((intptr_t)count <= 0) return -1;
2420130561Sobrien  return vsnprintf(str, count, fmt, args);
2421130561Sobrien}
2422130561Sobrien
2423130561Sobrien
2424130561Sobrienint jio_snprintf(char *str, size_t count, const char *fmt, ...) {
2425218822Sdim  va_list args;
2426218822Sdim  int len;
2427218822Sdim  va_start(args, fmt);
2428218822Sdim  len = jio_vsnprintf(str, count, fmt, args);
2429218822Sdim  va_end(args);
2430130561Sobrien  return len;
2431130561Sobrien}
2432218822Sdim
2433130561Sobrien
2434130561Sobrienint jio_fprintf(FILE* f, const char *fmt, ...) {
2435130561Sobrien  int len;
243677298Sobrien  va_list args;
2437130561Sobrien  va_start(args, fmt);
2438130561Sobrien  len = jio_vfprintf(f, fmt, args);
2439130561Sobrien  va_end(args);
244068765Sobrien  return len;
2441130561Sobrien}
2442218822Sdim
244368765Sobrien
2444130561Sobrienint jio_vfprintf(FILE* f, const char *fmt, va_list args) {
244568765Sobrien  if (Arguments::vfprintf_hook() != NULL) {
2446218822Sdim     return Arguments::vfprintf_hook()(f, fmt, args);
2447130561Sobrien  } else {
244868765Sobrien    return vfprintf(f, fmt, args);
2449130561Sobrien  }
245068765Sobrien}
2451218822Sdim
2452130561Sobrien
245368765Sobrienint jio_printf(const char *fmt, ...) {
2454130561Sobrien  int len;
245577298Sobrien  va_list args;
2456130561Sobrien  va_start(args, fmt);
2457130561Sobrien  len = jio_vfprintf(defaultStream::output_stream(), fmt, args);
2458130561Sobrien  va_end(args);
2459130561Sobrien  return len;
2460130561Sobrien}
2461130561Sobrien
2462130561Sobrien
2463130561Sobrien// HotSpot specific jio method
2464130561Sobrienvoid jio_print(const char* s) {
2465130561Sobrien  // Try to make this function as atomic as possible.
246668765Sobrien  if (Arguments::vfprintf_hook() != NULL) {
2467130561Sobrien    jio_fprintf(defaultStream::output_stream(), "%s", s);
2468130561Sobrien  } else {
2469130561Sobrien    ::write(defaultStream::output_fd(), s, (int)strlen(s));
2470130561Sobrien  }
2471130561Sobrien}
2472130561Sobrien
247368765Sobrien} // Extern C
2474130561Sobrien
247568765Sobrien// java.lang.Thread //////////////////////////////////////////////////////////////////////////////
2476130561Sobrien
2477130561Sobrien// In most of the JVM Thread support functions we need to be sure to lock the Threads_lock
247877298Sobrien// to prevent the target thread from exiting after we have a pointer to the C++ Thread or
2479130561Sobrien// OSThread objects.  The exception to this rule is when the target object is the thread
2480218822Sdim// doing the operation, in which case we know that the thread won't exit until the
2481130561Sobrien// operation is done (all exits being voluntary).  There are a few cases where it is
2482130561Sobrien// rather silly to do operations on yourself, like resuming yourself or asking whether
248377298Sobrien// you are alive.  While these can still happen, they are not subject to deadlocks if
2484130561Sobrien// the lock is held while the operation occurs (this is not the case for suspend, for
2485130561Sobrien// instance), and are very unlikely.  Because IsAlive needs to be fast and its
2486130561Sobrien// implementation is local to this file, we always lock Threads_lock for that one.
2487130561Sobrien
2488130561Sobrienstatic void thread_entry(JavaThread* thread, TRAPS) {
2489130561Sobrien  HandleMark hm(THREAD);
2490130561Sobrien  Handle obj(THREAD, thread->threadObj());
2491130561Sobrien  JavaValue result(T_VOID);
249277298Sobrien  JavaCalls::call_virtual(&result,
2493130561Sobrien                          obj,
2494130561Sobrien                          KlassHandle(THREAD, SystemDictionary::thread_klass()),
2495130561Sobrien                          vmSymbolHandles::run_method_name(),
2496218822Sdim                          vmSymbolHandles::void_method_signature(),
2497130561Sobrien                          THREAD);
2498130561Sobrien}
2499130561Sobrien
2500130561Sobrien
2501130561SobrienJVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
2502130561Sobrien  JVMWrapper("JVM_StartThread");
2503130561Sobrien  JavaThread *native_thread = NULL;
2504130561Sobrien
250568765Sobrien  // We cannot hold the Threads_lock when we throw an exception,
250668765Sobrien  // due to rank ordering issues. Example:  we might need to grab the
2507130561Sobrien  // Heap_lock while we construct the exception.
2508130561Sobrien  bool throw_illegal_thread_state = false;
2509130561Sobrien
2510130561Sobrien  // We must release the Threads_lock before we can post a jvmti event
2511130561Sobrien  // in Thread::start.
2512130561Sobrien  {
2513130561Sobrien    // Ensure that the C++ Thread and OSThread structures aren't freed before
2514130561Sobrien    // we operate.
2515130561Sobrien    MutexLocker mu(Threads_lock);
251668765Sobrien
2517130561Sobrien    // Check to see if we're running a thread that's already exited or was
2518130561Sobrien    // stopped (is_stillborn) or is still active (thread is not NULL).
2519130561Sobrien    if (java_lang_Thread::is_stillborn(JNIHandles::resolve_non_null(jthread)) ||
2520130561Sobrien        java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
2521130561Sobrien        throw_illegal_thread_state = true;
2522130561Sobrien    } else {
2523130561Sobrien      jlong size =
2524130561Sobrien             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
252568765Sobrien      // Allocate the C++ Thread structure and create the native thread.  The
2526130561Sobrien      // stack size retrieved from java is signed, but the constructor takes
252768765Sobrien      // size_t (an unsigned type), so avoid passing negative values which would
2528130561Sobrien      // result in really large stacks.
2529130561Sobrien      size_t sz = size > 0 ? (size_t) size : 0;
2530130561Sobrien      native_thread = new JavaThread(&thread_entry, sz);
2531130561Sobrien
2532130561Sobrien      // At this point it may be possible that no osthread was created for the
2533130561Sobrien      // JavaThread due to lack of memory. Check for this situation and throw
2534130561Sobrien      // an exception if necessary. Eventually we may want to change this so
2535130561Sobrien      // that we only grab the lock if the thread was created successfully -
2536130561Sobrien      // then we can also do this check and throw the exception in the
2537130561Sobrien      // JavaThread constructor.
2538130561Sobrien      if (native_thread->osthread() != NULL) {
2539130561Sobrien        // Note: the current thread is not being used within "prepare".
2540130561Sobrien        native_thread->prepare(jthread);
2541130561Sobrien      }
2542130561Sobrien    }
2543130561Sobrien  }
2544130561Sobrien
2545130561Sobrien  if (throw_illegal_thread_state) {
2546130561Sobrien    THROW(vmSymbols::java_lang_IllegalThreadStateException());
2547130561Sobrien  }
2548130561Sobrien
2549130561Sobrien  assert(native_thread != NULL, "Starting null thread?");
255068765Sobrien
2551130561Sobrien  if (native_thread->osthread() == NULL) {
2552218822Sdim    // No one should hold a reference to the 'native_thread'.
2553130561Sobrien    delete native_thread;
2554130561Sobrien    if (JvmtiExport::should_post_resource_exhausted()) {
255577298Sobrien      JvmtiExport::post_resource_exhausted(
2556218822Sdim        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,
2557130561Sobrien        "unable to create new native thread");
255868765Sobrien    }
2559130561Sobrien    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
2560130561Sobrien              "unable to create new native thread");
256168765Sobrien  }
2562130561Sobrien
2563130561Sobrien  Thread::start(native_thread);
2564130561Sobrien
2565130561SobrienJVM_END
256668765Sobrien
2567130561Sobrien// JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints
2568130561Sobrien// before the quasi-asynchronous exception is delivered.  This is a little obtrusive,
2569130561Sobrien// but is thought to be reliable and simple. In the case, where the receiver is the
2570130561Sobrien// save thread as the sender, no safepoint is needed.
2571130561SobrienJVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
2572130561Sobrien  JVMWrapper("JVM_StopThread");
2573130561Sobrien
2574130561Sobrien  oop java_throwable = JNIHandles::resolve(throwable);
2575218822Sdim  if (java_throwable == NULL) {
2576218822Sdim    THROW(vmSymbols::java_lang_NullPointerException());
2577130561Sobrien  }
2578130561Sobrien  oop java_thread = JNIHandles::resolve_non_null(jthread);
2579130561Sobrien  JavaThread* receiver = java_lang_Thread::thread(java_thread);
258068765Sobrien  Events::log("JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable);
2581130561Sobrien  // First check if thread already exited
2582130561Sobrien  if (receiver != NULL) {
258368765Sobrien    // Check if exception is getting thrown at self (use oop equality, since the
2584130561Sobrien    // target object might exit)
2585130561Sobrien    if (java_thread == thread->threadObj()) {
258668765Sobrien      // This is a change from JDK 1.1, but JDK 1.2 will also do it:
2587130561Sobrien      // NOTE (from JDK 1.2): this is done solely to prevent stopped
258868765Sobrien      // threads from being restarted.
2589130561Sobrien      // Fix for 4314342, 4145910, perhaps others: it now doesn't have
2590130561Sobrien      // any effect on the "liveness" of a thread; see
2591130561Sobrien      // JVM_IsThreadAlive, below.
2592130561Sobrien      if (java_throwable->is_a(SystemDictionary::threaddeath_klass())) {
2593130561Sobrien        java_lang_Thread::set_stillborn(java_thread);
2594130561Sobrien      }
2595130561Sobrien      THROW_OOP(java_throwable);
259668765Sobrien    } else {
2597130561Sobrien      // Enques a VM_Operation to stop all threads and then deliver the exception...
2598130561Sobrien      Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable));
2599130561Sobrien    }
2600130561Sobrien  }
260168765SobrienJVM_END
2602130561Sobrien
2603130561Sobrien
2604130561SobrienJVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread))
2605130561Sobrien  JVMWrapper("JVM_IsThreadAlive");
260668765Sobrien
2607130561Sobrien  oop thread_oop = JNIHandles::resolve_non_null(jthread);
2608130561Sobrien  return java_lang_Thread::is_alive(thread_oop);
2609130561SobrienJVM_END
2610130561Sobrien
2611130561Sobrien
2612130561SobrienJVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread))
2613130561Sobrien  JVMWrapper("JVM_SuspendThread");
2614130561Sobrien  oop java_thread = JNIHandles::resolve_non_null(jthread);
261577298Sobrien  JavaThread* receiver = java_lang_Thread::thread(java_thread);
2616130561Sobrien
2617130561Sobrien  if (receiver != NULL) {
2618130561Sobrien    // thread has run and has not exited (still on threads list)
2619130561Sobrien
2620130561Sobrien    {
2621130561Sobrien      MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag);
2622130561Sobrien      if (receiver->is_external_suspend()) {
2623130561Sobrien        // Don't allow nested external suspend requests. We can't return
2624130561Sobrien        // an error from this interface so just ignore the problem.
2625130561Sobrien        return;
2626130561Sobrien      }
2627130561Sobrien      if (receiver->is_exiting()) { // thread is in the process of exiting
2628130561Sobrien        return;
2629130561Sobrien      }
2630130561Sobrien      receiver->set_external_suspend();
2631130561Sobrien    }
2632130561Sobrien
263377298Sobrien    // java_suspend() will catch threads in the process of exiting
2634130561Sobrien    // and will ignore them.
2635130561Sobrien    receiver->java_suspend();
2636130561Sobrien
263777298Sobrien    // It would be nice to have the following assertion in all the
2638218822Sdim    // time, but it is possible for a racing resume request to have
263968765Sobrien    // resumed this thread right after we suspended it. Temporarily
2640130561Sobrien    // enable this assertion if you are chasing a different kind of
2641218822Sdim    // bug.
2642130561Sobrien    //
2643218822Sdim    // assert(java_lang_Thread::thread(receiver->threadObj()) == NULL ||
2644218822Sdim    //   receiver->is_being_ext_suspended(), "thread is not suspended");
2645218822Sdim  }
2646218822SdimJVM_END
264777298Sobrien
2648218822Sdim
2649218822SdimJVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread))
2650218822Sdim  JVMWrapper("JVM_ResumeThread");
2651218822Sdim  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate.
2652218822Sdim  // We need to *always* get the threads lock here, since this operation cannot be allowed during
2653218822Sdim  // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other
2654218822Sdim  // threads randomly resumes threads, then a thread might not be suspended when the safepoint code
2655218822Sdim  // looks at it.
2656218822Sdim  MutexLocker ml(Threads_lock);
2657218822Sdim  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
2658218822Sdim  if (thr != NULL) {
2659218822Sdim    // the thread has run and is not in the process of exiting
2660218822Sdim    thr->java_resume();
2661130561Sobrien  }
2662218822SdimJVM_END
2663218822Sdim
2664218822Sdim
2665218822SdimJVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))
2666218822Sdim  JVMWrapper("JVM_SetThreadPriority");
2667218822Sdim  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
2668218822Sdim  MutexLocker ml(Threads_lock);
2669218822Sdim  oop java_thread = JNIHandles::resolve_non_null(jthread);
2670218822Sdim  java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);
2671218822Sdim  JavaThread* thr = java_lang_Thread::thread(java_thread);
2672130561Sobrien  if (thr != NULL) {                  // Thread not yet started; priority pushed down when it is
2673218822Sdim    Thread::set_priority(thr, (ThreadPriority)prio);
2674218822Sdim  }
2675218822SdimJVM_END
2676218822Sdim
2677218822Sdim
2678218822SdimJVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass))
2679130561Sobrien  JVMWrapper("JVM_Yield");
2680218822Sdim  if (os::dont_yield()) return;
2681218822Sdim  // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield.
2682130561Sobrien  // Critical for similar threading behaviour
268368765Sobrien  if (ConvertYieldToSleep) {
2684218822Sdim    os::sleep(thread, MinSleepInterval, false);
268568765Sobrien  } else {
2686218822Sdim    os::yield();
2687218822Sdim  }
2688218822SdimJVM_END
2689130561Sobrien
2690218822Sdim
269168765SobrienJVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
2692218822Sdim  JVMWrapper("JVM_Sleep");
2693218822Sdim
2694218822Sdim  if (millis < 0) {
2695218822Sdim    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
2696218822Sdim  }
2697218822Sdim
2698218822Sdim  if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) {
2699218822Sdim    THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
2700218822Sdim  }
2701218822Sdim
2702130561Sobrien  // Save current thread state and restore it at the end of this block.
270368765Sobrien  // And set new thread state to SLEEPING.
2704218822Sdim  JavaThreadSleepState jtss(thread);
270568765Sobrien
2706130561Sobrien  if (millis == 0) {
2707218822Sdim    // When ConvertSleepToYield is on, this matches the classic VM implementation of
2708130561Sobrien    // JVM_Sleep. Critical for similar threading behaviour (Win32)
2709218822Sdim    // It appears that in certain GUI contexts, it may be beneficial to do a short sleep
271068765Sobrien    // for SOLARIS
2711218822Sdim    if (ConvertSleepToYield) {
2712130561Sobrien      os::yield();
271368765Sobrien    } else {
2714218822Sdim      ThreadState old_state = thread->osthread()->get_state();
271568765Sobrien      thread->osthread()->set_state(SLEEPING);
2716130561Sobrien      os::sleep(thread, MinSleepInterval, false);
2717218822Sdim      thread->osthread()->set_state(old_state);
2718218822Sdim    }
2719130561Sobrien  } else {
2720218822Sdim    ThreadState old_state = thread->osthread()->get_state();
2721218822Sdim    thread->osthread()->set_state(SLEEPING);
2722218822Sdim    if (os::sleep(thread, millis, true) == OS_INTRPT) {
2723218822Sdim      // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on
2724218822Sdim      // us while we were sleeping. We do not overwrite those.
2725218822Sdim      if (!HAS_PENDING_EXCEPTION) {
2726218822Sdim        // TODO-FIXME: THROW_MSG returns which means we will not call set_state()
2727218822Sdim        // to properly restore the thread state.  That's likely wrong.
2728218822Sdim        THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
2729218822Sdim      }
273068765Sobrien    }
273168765Sobrien    thread->osthread()->set_state(old_state);
2732218822Sdim  }
2733218822SdimJVM_END
2734218822Sdim
2735218822SdimJVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))
2736218822Sdim  JVMWrapper("JVM_CurrentThread");
2737218822Sdim  oop jthread = thread->threadObj();
2738218822Sdim  assert (thread != NULL, "no current thread!");
2739218822Sdim  return JNIHandles::make_local(env, jthread);
2740218822SdimJVM_END
2741218822Sdim
2742218822Sdim
2743218822SdimJVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread))
2744218822Sdim  JVMWrapper("JVM_CountStackFrames");
2745218822Sdim
2746218822Sdim  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
2747218822Sdim  oop java_thread = JNIHandles::resolve_non_null(jthread);
2748218822Sdim  bool throw_illegal_thread_state = false;
2749218822Sdim  int count = 0;
2750218822Sdim
2751218822Sdim  {
2752218822Sdim    MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
2753218822Sdim    // We need to re-resolve the java_thread, since a GC might have happened during the
2754218822Sdim    // acquire of the lock
2755218822Sdim    JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
2756218822Sdim
2757218822Sdim    if (thr == NULL) {
2758218822Sdim      // do nothing
2759218822Sdim    } else if(! thr->is_external_suspend() || ! thr->frame_anchor()->walkable()) {
2760218822Sdim      // Check whether this java thread has been suspended already. If not, throws
2761218822Sdim      // IllegalThreadStateException. We defer to throw that exception until
2762218822Sdim      // Threads_lock is released since loading exception class has to leave VM.
2763218822Sdim      // The correct way to test a thread is actually suspended is
2764218822Sdim      // wait_for_ext_suspend_completion(), but we can't call that while holding
2765218822Sdim      // the Threads_lock. The above tests are sufficient for our purposes
2766218822Sdim      // provided the walkability of the stack is stable - which it isn't
2767218822Sdim      // 100% but close enough for most practical purposes.
2768218822Sdim      throw_illegal_thread_state = true;
2769218822Sdim    } else {
2770218822Sdim      // Count all java activation, i.e., number of vframes
2771218822Sdim      for(vframeStream vfst(thr); !vfst.at_end(); vfst.next()) {
2772218822Sdim        // Native frames are not counted
2773218822Sdim        if (!vfst.method()->is_native()) count++;
2774218822Sdim       }
2775218822Sdim    }
2776218822Sdim  }
2777218822Sdim
2778218822Sdim  if (throw_illegal_thread_state) {
2779218822Sdim    THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(),
2780218822Sdim                "this thread is not suspended");
2781218822Sdim  }
2782218822Sdim  return count;
2783218822SdimJVM_END
2784218822Sdim
2785218822Sdim// Consider: A better way to implement JVM_Interrupt() is to acquire
2786218822Sdim// Threads_lock to resolve the jthread into a Thread pointer, fetch
2787218822Sdim// Thread->platformevent, Thread->native_thr, Thread->parker, etc.,
2788218822Sdim// drop Threads_lock, and the perform the unpark() and thr_kill() operations
2789130561Sobrien// outside the critical section.  Threads_lock is hot so we want to minimize
2790130561Sobrien// the hold-time.  A cleaner interface would be to decompose interrupt into
2791218822Sdim// two steps.  The 1st phase, performed under Threads_lock, would return
2792218822Sdim// a closure that'd be invoked after Threads_lock was dropped.
2793218822Sdim// This tactic is safe as PlatformEvent and Parkers are type-stable (TSM) and
2794218822Sdim// admit spurious wakeups.
2795218822Sdim
2796218822SdimJVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread))
2797218822Sdim  JVMWrapper("JVM_Interrupt");
2798218822Sdim
2799218822Sdim  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
2800218822Sdim  oop java_thread = JNIHandles::resolve_non_null(jthread);
2801218822Sdim  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
2802218822Sdim  // We need to re-resolve the java_thread, since a GC might have happened during the
2803218822Sdim  // acquire of the lock
2804218822Sdim  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
2805218822Sdim  if (thr != NULL) {
2806218822Sdim    Thread::interrupt(thr);
2807218822Sdim  }
2808218822SdimJVM_END
2809218822Sdim
2810218822Sdim
2811218822SdimJVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted))
2812218822Sdim  JVMWrapper("JVM_IsInterrupted");
2813218822Sdim
2814218822Sdim  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
2815218822Sdim  oop java_thread = JNIHandles::resolve_non_null(jthread);
2816218822Sdim  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
2817130561Sobrien  // We need to re-resolve the java_thread, since a GC might have happened during the
2818130561Sobrien  // acquire of the lock
2819130561Sobrien  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
2820130561Sobrien  if (thr == NULL) {
2821130561Sobrien    return JNI_FALSE;
282268765Sobrien  } else {
2823130561Sobrien    return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0);
2824130561Sobrien  }
2825218822SdimJVM_END
2826218822Sdim
282789857Sobrien
2828218822Sdim// Return true iff the current thread has locked the object passed in
282989857Sobrien
2830218822SdimJVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj))
283168765Sobrien  JVMWrapper("JVM_HoldsLock");
2832218822Sdim  assert(THREAD->is_Java_thread(), "sanity check");
2833218822Sdim  if (obj == NULL) {
2834218822Sdim    THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
2835130561Sobrien  }
2836218822Sdim  Handle h_obj(THREAD, JNIHandles::resolve(obj));
2837218822Sdim  return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj);
2838130561SobrienJVM_END
2839130561Sobrien
284068765Sobrien
2841218822SdimJVM_ENTRY(void, JVM_DumpAllStacks(JNIEnv* env, jclass))
2842218822Sdim  JVMWrapper("JVM_DumpAllStacks");
284368765Sobrien  VM_PrintThreads op;
284468765Sobrien  VMThread::execute(&op);
2845130561Sobrien  if (JvmtiExport::should_post_data_dump()) {
284668765Sobrien    JvmtiExport::post_data_dump();
2847130561Sobrien  }
2848218822SdimJVM_END
2849218822Sdim
285068765Sobrien
2851130561Sobrien// java.lang.SecurityManager ///////////////////////////////////////////////////////////////////////
2852130561Sobrien
2853130561Sobrienstatic bool is_trusted_frame(JavaThread* jthread, vframeStream* vfst) {
2854130561Sobrien  assert(jthread->is_Java_thread(), "must be a Java thread");
2855130561Sobrien  if (jthread->privileged_stack_top() == NULL) return false;
2856130561Sobrien  if (jthread->privileged_stack_top()->frame_id() == vfst->frame_id()) {
2857130561Sobrien    oop loader = jthread->privileged_stack_top()->class_loader();
285868765Sobrien    if (loader == NULL) return true;
2859130561Sobrien    bool trusted = java_lang_ClassLoader::is_trusted_loader(loader);
286068765Sobrien    if (trusted) return true;
2861130561Sobrien  }
2862130561Sobrien  return false;
2863130561Sobrien}
2864130561Sobrien
2865130561SobrienJVM_ENTRY(jclass, JVM_CurrentLoadedClass(JNIEnv *env))
2866130561Sobrien  JVMWrapper("JVM_CurrentLoadedClass");
286768765Sobrien  ResourceMark rm(THREAD);
2868130561Sobrien
2869130561Sobrien  for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
2870130561Sobrien    // if a method in a class in a trusted loader is in a doPrivileged, return NULL
2871130561Sobrien    bool trusted = is_trusted_frame(thread, &vfst);
2872218822Sdim    if (trusted) return NULL;
2873130561Sobrien
2874130561Sobrien    methodOop m = vfst.method();
2875130561Sobrien    if (!m->is_native()) {
2876130561Sobrien      klassOop holder = m->method_holder();
287768765Sobrien      oop      loader = instanceKlass::cast(holder)->class_loader();
2878130561Sobrien      if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
2879130561Sobrien        return (jclass) JNIHandles::make_local(env, Klass::cast(holder)->java_mirror());
2880130561Sobrien      }
2881130561Sobrien    }
2882130561Sobrien  }
2883130561Sobrien  return NULL;
2884130561SobrienJVM_END
288568765Sobrien
2886130561Sobrien
2887130561SobrienJVM_ENTRY(jobject, JVM_CurrentClassLoader(JNIEnv *env))
2888130561Sobrien  JVMWrapper("JVM_CurrentClassLoader");
2889130561Sobrien  ResourceMark rm(THREAD);
2890130561Sobrien
2891130561Sobrien  for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
2892130561Sobrien
2893130561Sobrien    // if a method in a class in a trusted loader is in a doPrivileged, return NULL
2894130561Sobrien    bool trusted = is_trusted_frame(thread, &vfst);
2895130561Sobrien    if (trusted) return NULL;
2896130561Sobrien
2897130561Sobrien    methodOop m = vfst.method();
2898130561Sobrien    if (!m->is_native()) {
289968765Sobrien      klassOop holder = m->method_holder();
2900130561Sobrien      assert(holder->is_klass(), "just checking");
2901130561Sobrien      oop loader = instanceKlass::cast(holder)->class_loader();
2902130561Sobrien      if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
2903130561Sobrien        return JNIHandles::make_local(env, loader);
2904130561Sobrien      }
2905130561Sobrien    }
290668765Sobrien  }
2907130561Sobrien  return NULL;
2908130561SobrienJVM_END
2909130561Sobrien
2910130561Sobrien
291168765Sobrien// Utility object for collecting method holders walking down the stack
2912130561Sobrienclass KlassLink: public ResourceObj {
2913130561Sobrien public:
291468765Sobrien  KlassHandle klass;
2915130561Sobrien  KlassLink*  next;
2916130561Sobrien
2917130561Sobrien  KlassLink(KlassHandle k) { klass = k; next = NULL; }
2918130561Sobrien};
2919130561Sobrien
2920130561Sobrien
2921218822SdimJVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env))
2922130561Sobrien  JVMWrapper("JVM_GetClassContext");
292368765Sobrien  ResourceMark rm(THREAD);
2924130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
2925130561Sobrien  // Collect linked list of (handles to) method holders
2926130561Sobrien  KlassLink* first = NULL;
2927130561Sobrien  KlassLink* last  = NULL;
2928130561Sobrien  int depth = 0;
2929130561Sobrien
2930130561Sobrien  for(vframeStream vfst(thread); !vfst.at_end(); vfst.security_get_caller_frame(1)) {
293168765Sobrien    // Native frames are not returned
2932130561Sobrien    if (!vfst.method()->is_native()) {
2933130561Sobrien      klassOop holder = vfst.method()->method_holder();
2934130561Sobrien      assert(holder->is_klass(), "just checking");
2935130561Sobrien      depth++;
2936130561Sobrien      KlassLink* l = new KlassLink(KlassHandle(thread, holder));
2937130561Sobrien      if (first == NULL) {
2938130561Sobrien        first = last = l;
2939130561Sobrien      } else {
2940130561Sobrien        last->next = l;
2941130561Sobrien        last = l;
294268765Sobrien      }
2943130561Sobrien    }
2944130561Sobrien  }
2945130561Sobrien
294668765Sobrien  // Create result array of type [Ljava/lang/Class;
2947130561Sobrien  objArrayOop result = oopFactory::new_objArray(SystemDictionary::class_klass(), depth, CHECK_NULL);
2948130561Sobrien  // Fill in mirrors corresponding to method holders
2949130561Sobrien  int index = 0;
2950130561Sobrien  while (first != NULL) {
295168765Sobrien    result->obj_at_put(index++, Klass::cast(first->klass())->java_mirror());
2952130561Sobrien    first = first->next;
2953130561Sobrien  }
2954130561Sobrien  assert(index == depth, "just checking");
295568765Sobrien
2956130561Sobrien  return (jobjectArray) JNIHandles::make_local(env, result);
295768765SobrienJVM_END
2958130561Sobrien
2959130561Sobrien
296068765SobrienJVM_ENTRY(jint, JVM_ClassDepth(JNIEnv *env, jstring name))
2961130561Sobrien  JVMWrapper("JVM_ClassDepth");
2962130561Sobrien  ResourceMark rm(THREAD);
2963130561Sobrien  Handle h_name (THREAD, JNIHandles::resolve_non_null(name));
2964130561Sobrien  Handle class_name_str = java_lang_String::internalize_classname(h_name, CHECK_0);
2965130561Sobrien
2966130561Sobrien  const char* str = java_lang_String::as_utf8_string(class_name_str());
2967130561Sobrien  symbolHandle class_name_sym =
2968130561Sobrien                symbolHandle(THREAD, SymbolTable::probe(str, (int)strlen(str)));
2969130561Sobrien  if (class_name_sym.is_null()) {
2970130561Sobrien    return -1;
2971130561Sobrien  }
297268765Sobrien
2973130561Sobrien  int depth = 0;
297468765Sobrien
2975130561Sobrien  for(vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
2976130561Sobrien    if (!vfst.method()->is_native()) {
297777298Sobrien      klassOop holder = vfst.method()->method_holder();
2978130561Sobrien      assert(holder->is_klass(), "just checking");
2979130561Sobrien      if (instanceKlass::cast(holder)->name() == class_name_sym()) {
2980130561Sobrien        return depth;
2981218822Sdim      }
298268765Sobrien      depth++;
2983130561Sobrien    }
2984130561Sobrien  }
2985130561Sobrien  return -1;
298668765SobrienJVM_END
2987130561Sobrien
2988130561Sobrien
298968765SobrienJVM_ENTRY(jint, JVM_ClassLoaderDepth(JNIEnv *env))
2990218822Sdim  JVMWrapper("JVM_ClassLoaderDepth");
299168765Sobrien  ResourceMark rm(THREAD);
2992218822Sdim  int depth = 0;
2993218822Sdim  for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
2994218822Sdim    // if a method in a class in a trusted loader is in a doPrivileged, return -1
2995218822Sdim    bool trusted = is_trusted_frame(thread, &vfst);
2996218822Sdim    if (trusted) return -1;
2997218822Sdim
2998218822Sdim    methodOop m = vfst.method();
2999218822Sdim    if (!m->is_native()) {
3000218822Sdim      klassOop holder = m->method_holder();
3001218822Sdim      assert(holder->is_klass(), "just checking");
3002218822Sdim      oop loader = instanceKlass::cast(holder)->class_loader();
3003218822Sdim      if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
3004218822Sdim        return depth;
3005218822Sdim      }
3006218822Sdim      depth++;
3007218822Sdim    }
3008218822Sdim  }
3009218822Sdim  return -1;
3010218822SdimJVM_END
3011218822Sdim
3012218822Sdim
3013218822Sdim// java.lang.Package ////////////////////////////////////////////////////////////////
3014218822Sdim
3015218822Sdim
3016218822SdimJVM_ENTRY(jstring, JVM_GetSystemPackage(JNIEnv *env, jstring name))
3017130561Sobrien  JVMWrapper("JVM_GetSystemPackage");
301868765Sobrien  ResourceMark rm(THREAD);
3019130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
3020130561Sobrien  char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
302168765Sobrien  oop result = ClassLoader::get_system_package(str, CHECK_NULL);
3022130561Sobrien  return (jstring) JNIHandles::make_local(result);
3023130561SobrienJVM_END
3024130561Sobrien
3025130561Sobrien
3026130561SobrienJVM_ENTRY(jobjectArray, JVM_GetSystemPackages(JNIEnv *env))
302768765Sobrien  JVMWrapper("JVM_GetSystemPackages");
3028130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
3029130561Sobrien  objArrayOop result = ClassLoader::get_system_packages(CHECK_NULL);
3030130561Sobrien  return (jobjectArray) JNIHandles::make_local(result);
3031130561SobrienJVM_END
3032130561Sobrien
3033130561Sobrien
3034218822Sdim// ObjectInputStream ///////////////////////////////////////////////////////////////
3035130561Sobrien
3036130561Sobrienbool force_verify_field_access(klassOop current_class, klassOop field_class, AccessFlags access, bool classloader_only) {
3037130561Sobrien  if (current_class == NULL) {
3038130561Sobrien    return true;
3039130561Sobrien  }
3040130561Sobrien  if ((current_class == field_class) || access.is_public()) {
3041130561Sobrien    return true;
3042130561Sobrien  }
3043130561Sobrien
3044130561Sobrien  if (access.is_protected()) {
3045130561Sobrien    // See if current_class is a subclass of field_class
3046130561Sobrien    if (Klass::cast(current_class)->is_subclass_of(field_class)) {
3047130561Sobrien      return true;
3048130561Sobrien    }
3049130561Sobrien  }
3050130561Sobrien
3051130561Sobrien  return (!access.is_private() && instanceKlass::cast(current_class)->is_same_class_package(field_class));
305277298Sobrien}
3053130561Sobrien
3054130561Sobrien
3055130561Sobrien// JVM_AllocateNewObject and JVM_AllocateNewArray are unused as of 1.4
3056130561SobrienJVM_ENTRY(jobject, JVM_AllocateNewObject(JNIEnv *env, jobject receiver, jclass currClass, jclass initClass))
305777298Sobrien  JVMWrapper("JVM_AllocateNewObject");
3058130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
3059130561Sobrien  // Receiver is not used
306068765Sobrien  oop curr_mirror = JNIHandles::resolve_non_null(currClass);
3061130561Sobrien  oop init_mirror = JNIHandles::resolve_non_null(initClass);
306268765Sobrien
3063130561Sobrien  // Cannot instantiate primitive types
306468765Sobrien  if (java_lang_Class::is_primitive(curr_mirror) || java_lang_Class::is_primitive(init_mirror)) {
3065130561Sobrien    ResourceMark rm(THREAD);
3066130561Sobrien    THROW_0(vmSymbols::java_lang_InvalidClassException());
306768765Sobrien  }
3068130561Sobrien
3069130561Sobrien  // Arrays not allowed here, must use JVM_AllocateNewArray
3070130561Sobrien  if (Klass::cast(java_lang_Class::as_klassOop(curr_mirror))->oop_is_javaArray() ||
307168765Sobrien      Klass::cast(java_lang_Class::as_klassOop(init_mirror))->oop_is_javaArray()) {
3072130561Sobrien    ResourceMark rm(THREAD);
3073130561Sobrien    THROW_0(vmSymbols::java_lang_InvalidClassException());
3074130561Sobrien  }
3075130561Sobrien
307677298Sobrien  instanceKlassHandle curr_klass (THREAD, java_lang_Class::as_klassOop(curr_mirror));
3077130561Sobrien  instanceKlassHandle init_klass (THREAD, java_lang_Class::as_klassOop(init_mirror));
3078218822Sdim
3079130561Sobrien  assert(curr_klass->is_subclass_of(init_klass()), "just checking");
3080130561Sobrien
308168765Sobrien  // Interfaces, abstract classes, and java.lang.Class classes cannot be instantiated directly.
3082130561Sobrien  curr_klass->check_valid_for_instantiation(false, CHECK_NULL);
3083218822Sdim
3084130561Sobrien  // Make sure klass is initialized, since we are about to instantiate one of them.
3085130561Sobrien  curr_klass->initialize(CHECK_NULL);
308668765Sobrien
3087130561Sobrien methodHandle m (THREAD,
3088218822Sdim                 init_klass->find_method(vmSymbols::object_initializer_name(),
3089130561Sobrien                                         vmSymbols::void_method_signature()));
3090218822Sdim  if (m.is_null()) {
3091130561Sobrien    ResourceMark rm(THREAD);
3092130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(),
309368765Sobrien                methodOopDesc::name_and_sig_as_C_string(Klass::cast(init_klass()),
3094130561Sobrien                                          vmSymbols::object_initializer_name(),
3095218822Sdim                                          vmSymbols::void_method_signature()));
3096130561Sobrien  }
3097130561Sobrien
309868765Sobrien  if (curr_klass ==  init_klass && !m->is_public()) {
3099130561Sobrien    // Calling the constructor for class 'curr_klass'.
3100218822Sdim    // Only allow calls to a public no-arg constructor.
3101130561Sobrien    // This path corresponds to creating an Externalizable object.
3102130561Sobrien    THROW_0(vmSymbols::java_lang_IllegalAccessException());
310368765Sobrien  }
3104130561Sobrien
3105218822Sdim  if (!force_verify_field_access(curr_klass(), init_klass(), m->access_flags(), false)) {
3106130561Sobrien    // subclass 'curr_klass' does not have access to no-arg constructor of 'initcb'
3107130561Sobrien    THROW_0(vmSymbols::java_lang_IllegalAccessException());
310868765Sobrien  }
3109130561Sobrien
3110218822Sdim  Handle obj = curr_klass->allocate_instance_handle(CHECK_NULL);
3111130561Sobrien  // Call constructor m. This might call a constructor higher up in the hierachy
3112130561Sobrien  JavaCalls::call_default_constructor(thread, m, obj, CHECK_NULL);
311368765Sobrien
3114130561Sobrien  return JNIHandles::make_local(obj());
3115218822SdimJVM_END
3116130561Sobrien
3117130561Sobrien
311868765SobrienJVM_ENTRY(jobject, JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint length))
3119130561Sobrien  JVMWrapper("JVM_AllocateNewArray");
3120218822Sdim  JvmtiVMObjectAllocEventCollector oam;
3121130561Sobrien  oop mirror = JNIHandles::resolve_non_null(currClass);
3122130561Sobrien
312368765Sobrien  if (java_lang_Class::is_primitive(mirror)) {
3124130561Sobrien    THROW_0(vmSymbols::java_lang_InvalidClassException());
3125218822Sdim  }
3126130561Sobrien  klassOop k = java_lang_Class::as_klassOop(mirror);
3127130561Sobrien  oop result;
312868765Sobrien
3129130561Sobrien  if (k->klass_part()->oop_is_typeArray()) {
3130218822Sdim    // typeArray
3131130561Sobrien    result = typeArrayKlass::cast(k)->allocate(length, CHECK_NULL);
3132130561Sobrien  } else if (k->klass_part()->oop_is_objArray()) {
313368765Sobrien    // objArray
3134130561Sobrien    objArrayKlassHandle oak(THREAD, k);
3135218822Sdim    oak->initialize(CHECK_NULL); // make sure class is initialized (matches Classic VM behavior)
3136130561Sobrien    result = oak->allocate(length, CHECK_NULL);
3137130561Sobrien  } else {
313868765Sobrien    THROW_0(vmSymbols::java_lang_InvalidClassException());
3139218822Sdim  }
3140218822Sdim  return JNIHandles::make_local(env, result);
3141218822SdimJVM_END
3142218822Sdim
3143218822Sdim
3144130561Sobrien// Return the first non-null class loader up the execution stack, or null
3145130561Sobrien// if only code from the null class loader is on the stack.
3146130561Sobrien
314768765SobrienJVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env))
3148130561Sobrien  for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
3149130561Sobrien    // UseNewReflection
3150130561Sobrien    vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection
3151218822Sdim    klassOop holder = vfst.method()->method_holder();
3152218822Sdim    oop loader = instanceKlass::cast(holder)->class_loader();
3153218822Sdim    if (loader != NULL) {
3154218822Sdim      return JNIHandles::make_local(env, loader);
3155218822Sdim    }
3156218822Sdim  }
3157218822Sdim  return NULL;
3158218822SdimJVM_END
3159218822Sdim
3160218822Sdim
3161218822Sdim// Load a class relative to the most recent class on the stack  with a non-null
3162218822Sdim// classloader.
3163218822Sdim// This function has been deprecated and should not be considered part of the
3164218822Sdim// specified JVM interface.
3165218822Sdim
3166218822SdimJVM_ENTRY(jclass, JVM_LoadClass0(JNIEnv *env, jobject receiver,
3167218822Sdim                                 jclass currClass, jstring currClassName))
3168218822Sdim  JVMWrapper("JVM_LoadClass0");
3169218822Sdim  // Receiver is not used
3170218822Sdim  ResourceMark rm(THREAD);
3171218822Sdim
3172218822Sdim  // Class name argument is not guaranteed to be in internal format
3173218822Sdim  Handle classname (THREAD, JNIHandles::resolve_non_null(currClassName));
3174218822Sdim  Handle string = java_lang_String::internalize_classname(classname, CHECK_NULL);
3175130561Sobrien
3176130561Sobrien  const char* str = java_lang_String::as_utf8_string(string());
3177130561Sobrien
3178130561Sobrien  if (str == NULL || (int)strlen(str) > symbolOopDesc::max_length()) {
3179130561Sobrien    // It's impossible to create this class;  the name cannot fit
3180130561Sobrien    // into the constant pool.
3181130561Sobrien    THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), str);
3182130561Sobrien  }
3183130561Sobrien
3184130561Sobrien  symbolHandle name = oopFactory::new_symbol_handle(str, CHECK_NULL);
3185130561Sobrien  Handle curr_klass (THREAD, JNIHandles::resolve(currClass));
318668765Sobrien  // Find the most recent class on the stack with a non-null classloader
3187130561Sobrien  oop loader = NULL;
3188130561Sobrien  oop protection_domain = NULL;
3189130561Sobrien  if (curr_klass.is_null()) {
3190130561Sobrien    for (vframeStream vfst(thread);
3191130561Sobrien         !vfst.at_end() && loader == NULL;
319268765Sobrien         vfst.next()) {
3193130561Sobrien      if (!vfst.method()->is_native()) {
319468765Sobrien        klassOop holder = vfst.method()->method_holder();
3195130561Sobrien        loader             = instanceKlass::cast(holder)->class_loader();
3196130561Sobrien        protection_domain  = instanceKlass::cast(holder)->protection_domain();
3197130561Sobrien      }
3198130561Sobrien    }
319968765Sobrien  } else {
3200130561Sobrien    klassOop curr_klass_oop = java_lang_Class::as_klassOop(curr_klass());
320168765Sobrien    loader            = instanceKlass::cast(curr_klass_oop)->class_loader();
3202130561Sobrien    protection_domain = instanceKlass::cast(curr_klass_oop)->protection_domain();
3203130561Sobrien  }
3204130561Sobrien  Handle h_loader(THREAD, loader);
3205130561Sobrien  Handle h_prot  (THREAD, protection_domain);
3206130561Sobrien  return find_class_from_class_loader(env, name, true, h_loader, h_prot,
3207130561Sobrien                                      false, thread);
3208130561SobrienJVM_END
320968765Sobrien
3210130561Sobrien
3211130561Sobrien// Array ///////////////////////////////////////////////////////////////////////////////////////////
3212130561Sobrien
321368765Sobrien
3214130561Sobrien// resolve array handle and check arguments
3215130561Sobrienstatic inline arrayOop check_array(JNIEnv *env, jobject arr, bool type_array_only, TRAPS) {
3216130561Sobrien  if (arr == NULL) {
321768765Sobrien    THROW_0(vmSymbols::java_lang_NullPointerException());
3218130561Sobrien  }
3219130561Sobrien  oop a = JNIHandles::resolve_non_null(arr);
3220218822Sdim  if (!a->is_javaArray() || (type_array_only && !a->is_typeArray())) {
3221218822Sdim    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array");
3222218822Sdim  }
3223218822Sdim  return arrayOop(a);
3224130561Sobrien}
3225130561Sobrien
3226130561Sobrien
322768765SobrienJVM_ENTRY(jint, JVM_GetArrayLength(JNIEnv *env, jobject arr))
3228130561Sobrien  JVMWrapper("JVM_GetArrayLength");
3229130561Sobrien  arrayOop a = check_array(env, arr, false, CHECK_0);
3230130561Sobrien  return a->length();
3231130561SobrienJVM_END
3232130561Sobrien
3233130561Sobrien
3234130561SobrienJVM_ENTRY(jobject, JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index))
323568765Sobrien  JVMWrapper("JVM_Array_Get");
3236130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
323768765Sobrien  arrayOop a = check_array(env, arr, false, CHECK_NULL);
3238130561Sobrien  jvalue value;
323968765Sobrien  BasicType type = Reflection::array_get(&value, a, index, CHECK_NULL);
3240130561Sobrien  oop box = Reflection::box(&value, type, CHECK_NULL);
3241130561Sobrien  return JNIHandles::make_local(env, box);
324268765SobrienJVM_END
3243218822Sdim
3244218822Sdim
3245218822SdimJVM_ENTRY(jvalue, JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode))
3246218822Sdim  JVMWrapper("JVM_GetPrimitiveArrayElement");
3247130561Sobrien  jvalue value;
324868765Sobrien  value.i = 0; // to initialize value before getting used in CHECK
3249218822Sdim  arrayOop a = check_array(env, arr, true, CHECK_(value));
3250218822Sdim  assert(a->is_typeArray(), "just checking");
325168765Sobrien  BasicType type = Reflection::array_get(&value, a, index, CHECK_(value));
3252130561Sobrien  BasicType wide_type = (BasicType) wCode;
3253130561Sobrien  if (type != wide_type) {
325468765Sobrien    Reflection::widen(&value, type, wide_type, CHECK_(value));
3255130561Sobrien  }
3256130561Sobrien  return value;
3257218822SdimJVM_END
3258218822Sdim
3259218822Sdim
3260218822SdimJVM_ENTRY(void, JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val))
326168765Sobrien  JVMWrapper("JVM_SetArrayElement");
3262130561Sobrien  arrayOop a = check_array(env, arr, false, CHECK);
3263218822Sdim  oop box = JNIHandles::resolve(val);
3264218822Sdim  jvalue value;
3265218822Sdim  value.i = 0; // to initialize value before getting used in CHECK
3266218822Sdim  BasicType value_type;
3267218822Sdim  if (a->is_objArray()) {
3268218822Sdim    // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array
326968765Sobrien    value_type = Reflection::unbox_for_regular_object(box, &value);
3270218822Sdim  } else {
327168765Sobrien    value_type = Reflection::unbox_for_primitive(box, &value, CHECK);
3272218822Sdim  }
3273218822Sdim  Reflection::array_set(&value, a, index, value_type, CHECK);
3274218822SdimJVM_END
3275218822Sdim
3276218822Sdim
3277218822SdimJVM_ENTRY(void, JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v, unsigned char vCode))
3278218822Sdim  JVMWrapper("JVM_SetPrimitiveArrayElement");
3279218822Sdim  arrayOop a = check_array(env, arr, true, CHECK);
3280218822Sdim  assert(a->is_typeArray(), "just checking");
3281218822Sdim  BasicType value_type = (BasicType) vCode;
3282218822Sdim  Reflection::array_set(&v, a, index, value_type, CHECK);
3283218822SdimJVM_END
3284218822Sdim
3285218822Sdim
3286218822SdimJVM_ENTRY(jobject, JVM_NewArray(JNIEnv *env, jclass eltClass, jint length))
3287218822Sdim  JVMWrapper("JVM_NewArray");
3288218822Sdim  JvmtiVMObjectAllocEventCollector oam;
3289218822Sdim  oop element_mirror = JNIHandles::resolve(eltClass);
3290218822Sdim  oop result = Reflection::reflect_new_array(element_mirror, length, CHECK_NULL);
3291218822Sdim  return JNIHandles::make_local(env, result);
3292218822SdimJVM_END
3293218822Sdim
3294218822Sdim
3295218822SdimJVM_ENTRY(jobject, JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim))
3296218822Sdim  JVMWrapper("JVM_NewMultiArray");
3297218822Sdim  JvmtiVMObjectAllocEventCollector oam;
3298218822Sdim  arrayOop dim_array = check_array(env, dim, true, CHECK_NULL);
3299218822Sdim  oop element_mirror = JNIHandles::resolve(eltClass);
3300218822Sdim  assert(dim_array->is_typeArray(), "just checking");
3301218822Sdim  oop result = Reflection::reflect_new_multi_array(element_mirror, typeArrayOop(dim_array), CHECK_NULL);
3302218822Sdim  return JNIHandles::make_local(env, result);
3303130561SobrienJVM_END
330468765Sobrien
3305218822Sdim
3306130561Sobrien// Networking library support ////////////////////////////////////////////////////////////////////
3307218822Sdim
3308130561SobrienJVM_LEAF(jint, JVM_InitializeSocketLibrary())
3309130561Sobrien  JVMWrapper("JVM_InitializeSocketLibrary");
3310218822Sdim  return hpi::initialize_socket_library();
3311218822SdimJVM_END
3312218822Sdim
3313218822Sdim
3314218822SdimJVM_LEAF(jint, JVM_Socket(jint domain, jint type, jint protocol))
3315218822Sdim  JVMWrapper("JVM_Socket");
3316130561Sobrien  return hpi::socket(domain, type, protocol);
3317130561SobrienJVM_END
3318130561Sobrien
3319130561Sobrien
3320130561SobrienJVM_LEAF(jint, JVM_SocketClose(jint fd))
3321130561Sobrien  JVMWrapper2("JVM_SocketClose (0x%x)", fd);
3322130561Sobrien  //%note jvm_r6
3323130561Sobrien  return hpi::socket_close(fd);
3324130561SobrienJVM_END
3325130561Sobrien
3326130561Sobrien
3327130561SobrienJVM_LEAF(jint, JVM_SocketShutdown(jint fd, jint howto))
3328130561Sobrien  JVMWrapper2("JVM_SocketShutdown (0x%x)", fd);
3329130561Sobrien  //%note jvm_r6
3330130561Sobrien  return hpi::socket_shutdown(fd, howto);
3331130561SobrienJVM_END
3332130561Sobrien
3333130561Sobrien
3334130561SobrienJVM_LEAF(jint, JVM_Recv(jint fd, char *buf, jint nBytes, jint flags))
3335130561Sobrien  JVMWrapper2("JVM_Recv (0x%x)", fd);
3336130561Sobrien  //%note jvm_r6
3337130561Sobrien  return hpi::recv(fd, buf, nBytes, flags);
3338130561SobrienJVM_END
3339218822Sdim
3340130561Sobrien
3341130561SobrienJVM_LEAF(jint, JVM_Send(jint fd, char *buf, jint nBytes, jint flags))
3342130561Sobrien  JVMWrapper2("JVM_Send (0x%x)", fd);
3343130561Sobrien  //%note jvm_r6
3344130561Sobrien  return hpi::send(fd, buf, nBytes, flags);
3345130561SobrienJVM_END
3346130561Sobrien
3347130561Sobrien
3348130561SobrienJVM_LEAF(jint, JVM_Timeout(int fd, long timeout))
3349130561Sobrien  JVMWrapper2("JVM_Timeout (0x%x)", fd);
3350130561Sobrien  //%note jvm_r6
335168765Sobrien  return hpi::timeout(fd, timeout);
3352218822SdimJVM_END
3353130561Sobrien
335468765Sobrien
3355130561SobrienJVM_LEAF(jint, JVM_Listen(jint fd, jint count))
335668765Sobrien  JVMWrapper2("JVM_Listen (0x%x)", fd);
3357130561Sobrien  //%note jvm_r6
3358130561Sobrien  return hpi::listen(fd, count);
3359130561SobrienJVM_END
336068765Sobrien
3361218822Sdim
3362130561SobrienJVM_LEAF(jint, JVM_Connect(jint fd, struct sockaddr *him, jint len))
3363130561Sobrien  JVMWrapper2("JVM_Connect (0x%x)", fd);
3364130561Sobrien  //%note jvm_r6
3365130561Sobrien  return hpi::connect(fd, him, len);
3366130561SobrienJVM_END
3367130561Sobrien
3368130561Sobrien
336968765SobrienJVM_LEAF(jint, JVM_Bind(jint fd, struct sockaddr *him, jint len))
3370130561Sobrien  JVMWrapper2("JVM_Bind (0x%x)", fd);
3371218822Sdim  //%note jvm_r6
3372130561Sobrien  return hpi::bind(fd, him, len);
3373130561SobrienJVM_END
3374130561Sobrien
3375130561Sobrien
3376218822SdimJVM_LEAF(jint, JVM_Accept(jint fd, struct sockaddr *him, jint *len))
3377130561Sobrien  JVMWrapper2("JVM_Accept (0x%x)", fd);
3378130561Sobrien  //%note jvm_r6
3379130561Sobrien  return hpi::accept(fd, him, (int *)len);
3380130561SobrienJVM_END
3381130561Sobrien
3382130561Sobrien
3383130561SobrienJVM_LEAF(jint, JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen))
3384130561Sobrien  JVMWrapper2("JVM_RecvFrom (0x%x)", fd);
3385218822Sdim  //%note jvm_r6
3386130561Sobrien  return hpi::recvfrom(fd, buf, nBytes, flags, from, fromlen);
3387130561SobrienJVM_END
338868765Sobrien
3389130561Sobrien
3390130561SobrienJVM_LEAF(jint, JVM_GetSockName(jint fd, struct sockaddr *him, int *len))
3391130561Sobrien  JVMWrapper2("JVM_GetSockName (0x%x)", fd);
3392130561Sobrien  //%note jvm_r6
339368765Sobrien  return hpi::get_sock_name(fd, him, len);
3394130561SobrienJVM_END
3395130561Sobrien
3396130561Sobrien
3397130561SobrienJVM_LEAF(jint, JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen))
3398130561Sobrien  JVMWrapper2("JVM_SendTo (0x%x)", fd);
3399130561Sobrien  //%note jvm_r6
340068765Sobrien  return hpi::sendto(fd, buf, len, flags, to, tolen);
3401130561SobrienJVM_END
3402130561Sobrien
3403130561Sobrien
3404130561SobrienJVM_LEAF(jint, JVM_SocketAvailable(jint fd, jint *pbytes))
3405130561Sobrien  JVMWrapper2("JVM_SocketAvailable (0x%x)", fd);
3406130561Sobrien  //%note jvm_r6
3407130561Sobrien  return hpi::socket_available(fd, pbytes);
340868765SobrienJVM_END
3409130561Sobrien
3410130561Sobrien
3411218822SdimJVM_LEAF(jint, JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen))
3412130561Sobrien  JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
3413218822Sdim  //%note jvm_r6
3414130561Sobrien  return hpi::get_sock_opt(fd, level, optname, optval, optlen);
3415130561SobrienJVM_END
341668765Sobrien
3417130561Sobrien
3418130561SobrienJVM_LEAF(jint, JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen))
3419130561Sobrien  JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
3420130561Sobrien  //%note jvm_r6
342168765Sobrien  return hpi::set_sock_opt(fd, level, optname, optval, optlen);
3422130561SobrienJVM_END
342368765Sobrien
3424130561SobrienJVM_LEAF(int, JVM_GetHostName(char* name, int namelen))
3425130561Sobrien  JVMWrapper("JVM_GetHostName");
3426130561Sobrien  return hpi::get_host_name(name, namelen);
3427130561SobrienJVM_END
342868765Sobrien
3429130561Sobrien#ifdef _WINDOWS
3430130561Sobrien
3431130561SobrienJVM_LEAF(struct hostent*, JVM_GetHostByAddr(const char* name, int len, int type))
3432130561Sobrien  JVMWrapper("JVM_GetHostByAddr");
3433130561Sobrien  return hpi::get_host_by_addr(name, len, type);
3434130561SobrienJVM_END
3435130561Sobrien
3436130561Sobrien
3437130561SobrienJVM_LEAF(struct hostent*, JVM_GetHostByName(char* name))
3438218822Sdim  JVMWrapper("JVM_GetHostByName");
3439130561Sobrien  return hpi::get_host_by_name(name);
3440218822SdimJVM_END
3441130561Sobrien
3442218822Sdim
3443130561SobrienJVM_LEAF(struct protoent*, JVM_GetProtoByName(char* name))
3444130561Sobrien  JVMWrapper("JVM_GetProtoByName");
3445130561Sobrien  return hpi::get_proto_by_name(name);
344668765SobrienJVM_END
3447130561Sobrien
3448130561Sobrien#endif
3449130561Sobrien
3450130561Sobrien// Library support ///////////////////////////////////////////////////////////////////////////
3451130561Sobrien
345268765SobrienJVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name))
3453130561Sobrien  //%note jvm_ct
3454130561Sobrien  JVMWrapper2("JVM_LoadLibrary (%s)", name);
3455218822Sdim  char ebuf[1024];
3456218822Sdim  void *load_result;
3457130561Sobrien  {
3458218822Sdim    ThreadToNativeFromVM ttnfvm(thread);
3459218822Sdim    load_result = hpi::dll_load(name, ebuf, sizeof ebuf);
3460218822Sdim  }
3461218822Sdim  if (load_result == NULL) {
3462218822Sdim    char msg[1024];
3463218822Sdim    jio_snprintf(msg, sizeof msg, "%s: %s", name, ebuf);
3464218822Sdim    // Since 'ebuf' may contain a string encoded using
3465218822Sdim    // platform encoding scheme, we need to pass
3466218822Sdim    // Exceptions::unsafe_to_utf8 to the new_exception method
3467218822Sdim    // as the last argument. See bug 6367357.
3468218822Sdim    Handle h_exception =
3469218822Sdim      Exceptions::new_exception(thread,
3470218822Sdim                                vmSymbols::java_lang_UnsatisfiedLinkError(),
3471218822Sdim                                msg, Exceptions::unsafe_to_utf8);
3472218822Sdim
3473218822Sdim    THROW_HANDLE_0(h_exception);
3474218822Sdim  }
3475218822Sdim  return load_result;
3476218822SdimJVM_END
3477218822Sdim
3478218822Sdim
3479218822SdimJVM_LEAF(void, JVM_UnloadLibrary(void* handle))
3480218822Sdim  JVMWrapper("JVM_UnloadLibrary");
3481218822Sdim  hpi::dll_unload(handle);
3482218822SdimJVM_END
3483218822Sdim
3484218822Sdim
3485218822SdimJVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name))
3486218822Sdim  JVMWrapper2("JVM_FindLibraryEntry (%s)", name);
3487218822Sdim  return hpi::dll_lookup(handle, name);
3488218822SdimJVM_END
3489218822Sdim
3490218822Sdim// Floating point support ////////////////////////////////////////////////////////////////////
3491218822Sdim
3492218822SdimJVM_LEAF(jboolean, JVM_IsNaN(jdouble a))
3493218822Sdim  JVMWrapper("JVM_IsNaN");
3494218822Sdim  return g_isnan(a);
3495218822SdimJVM_END
3496218822Sdim
3497218822Sdim
3498218822Sdim
3499130561Sobrien// JNI version ///////////////////////////////////////////////////////////////////////////////
3500218822Sdim
3501218822SdimJVM_LEAF(jboolean, JVM_IsSupportedJNIVersion(jint version))
3502218822Sdim  JVMWrapper2("JVM_IsSupportedJNIVersion (%d)", version);
3503218822Sdim  return Threads::is_supported_jni_version_including_1_1(version);
3504218822SdimJVM_END
3505218822Sdim
3506218822Sdim
3507218822Sdim// String support ///////////////////////////////////////////////////////////////////////////
3508218822Sdim
3509218822SdimJVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str))
3510218822Sdim  JVMWrapper("JVM_InternString");
3511218822Sdim  JvmtiVMObjectAllocEventCollector oam;
3512218822Sdim  if (str == NULL) return NULL;
3513218822Sdim  oop string = JNIHandles::resolve_non_null(str);
3514218822Sdim  oop result = StringTable::intern(string, CHECK_NULL);
3515218822Sdim  return (jstring) JNIHandles::make_local(env, result);
3516218822SdimJVM_END
3517218822Sdim
3518130561Sobrien
3519218822Sdim// Raw monitor support //////////////////////////////////////////////////////////////////////
3520218822Sdim
3521218822Sdim// The lock routine below calls lock_without_safepoint_check in order to get a raw lock
3522218822Sdim// without interfering with the safepoint mechanism. The routines are not JVM_LEAF because
352368765Sobrien// they might be called by non-java threads. The JVM_LEAF installs a NoHandleMark check
3524218822Sdim// that only works with java threads.
3525218822Sdim
3526218822Sdim
3527218822SdimJNIEXPORT void* JNICALL JVM_RawMonitorCreate(void) {
3528218822Sdim  VM_Exit::block_if_vm_exited();
3529218822Sdim  JVMWrapper("JVM_RawMonitorCreate");
3530218822Sdim  return new Mutex(Mutex::native, "JVM_RawMonitorCreate");
3531218822Sdim}
3532218822Sdim
3533218822Sdim
3534218822SdimJNIEXPORT void JNICALL  JVM_RawMonitorDestroy(void *mon) {
3535130561Sobrien  VM_Exit::block_if_vm_exited();
353668765Sobrien  JVMWrapper("JVM_RawMonitorDestroy");
353768765Sobrien  delete ((Mutex*) mon);
3538130561Sobrien}
3539130561Sobrien
354068765Sobrien
354168765SobrienJNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon) {
354268765Sobrien  VM_Exit::block_if_vm_exited();
3543130561Sobrien  JVMWrapper("JVM_RawMonitorEnter");
3544130561Sobrien  ((Mutex*) mon)->jvm_raw_lock();
3545130561Sobrien  return 0;
3546130561Sobrien}
354768765Sobrien
3548130561Sobrien
3549218822SdimJNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon) {
355068765Sobrien  VM_Exit::block_if_vm_exited();
3551130561Sobrien  JVMWrapper("JVM_RawMonitorExit");
3552130561Sobrien  ((Mutex*) mon)->jvm_raw_unlock();
355368765Sobrien}
3554130561Sobrien
3555130561Sobrien
355668765Sobrien// Support for Serialization
3557130561Sobrien
3558130561Sobrientypedef jfloat  (JNICALL *IntBitsToFloatFn  )(JNIEnv* env, jclass cb, jint    value);
3559130561Sobrientypedef jdouble (JNICALL *LongBitsToDoubleFn)(JNIEnv* env, jclass cb, jlong   value);
3560130561Sobrientypedef jint    (JNICALL *FloatToIntBitsFn  )(JNIEnv* env, jclass cb, jfloat  value);
3561130561Sobrientypedef jlong   (JNICALL *DoubleToLongBitsFn)(JNIEnv* env, jclass cb, jdouble value);
3562130561Sobrien
3563130561Sobrienstatic IntBitsToFloatFn   int_bits_to_float_fn   = NULL;
356468765Sobrienstatic LongBitsToDoubleFn long_bits_to_double_fn = NULL;
3565130561Sobrienstatic FloatToIntBitsFn   float_to_int_bits_fn   = NULL;
3566130561Sobrienstatic DoubleToLongBitsFn double_to_long_bits_fn = NULL;
3567130561Sobrien
3568130561Sobrien
356968765Sobrienvoid initialize_converter_functions() {
3570130561Sobrien  if (JDK_Version::is_gte_jdk14x_version()) {
3571130561Sobrien    // These functions only exist for compatibility with 1.3.1 and earlier
3572130561Sobrien    return;
3573130561Sobrien  }
3574130561Sobrien
3575130561Sobrien  // called from universe_post_init()
3576130561Sobrien  assert(
3577130561Sobrien    int_bits_to_float_fn   == NULL &&
3578130561Sobrien    long_bits_to_double_fn == NULL &&
3579130561Sobrien    float_to_int_bits_fn   == NULL &&
3580130561Sobrien    double_to_long_bits_fn == NULL ,
3581130561Sobrien    "initialization done twice"
3582130561Sobrien  );
3583130561Sobrien  // initialize
3584130561Sobrien  int_bits_to_float_fn   = CAST_TO_FN_PTR(IntBitsToFloatFn  , NativeLookup::base_library_lookup("java/lang/Float" , "intBitsToFloat"  , "(I)F"));
3585130561Sobrien  long_bits_to_double_fn = CAST_TO_FN_PTR(LongBitsToDoubleFn, NativeLookup::base_library_lookup("java/lang/Double", "longBitsToDouble", "(J)D"));
3586130561Sobrien  float_to_int_bits_fn   = CAST_TO_FN_PTR(FloatToIntBitsFn  , NativeLookup::base_library_lookup("java/lang/Float" , "floatToIntBits"  , "(F)I"));
3587130561Sobrien  double_to_long_bits_fn = CAST_TO_FN_PTR(DoubleToLongBitsFn, NativeLookup::base_library_lookup("java/lang/Double", "doubleToLongBits", "(D)J"));
3588130561Sobrien  // verify
358968765Sobrien  assert(
359068765Sobrien    int_bits_to_float_fn   != NULL &&
3591130561Sobrien    long_bits_to_double_fn != NULL &&
359268765Sobrien    float_to_int_bits_fn   != NULL &&
359368765Sobrien    double_to_long_bits_fn != NULL ,
359468765Sobrien    "initialization failed"
3595130561Sobrien  );
3596130561Sobrien}
359768765Sobrien
3598130561Sobrien
3599218822Sdim// Serialization
3600218822SdimJVM_ENTRY(void, JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj,
360168765Sobrien                                            jlongArray fieldIDs, jcharArray typecodes, jbyteArray data))
3602130561Sobrien  assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier");
360368765Sobrien
3604130561Sobrien  typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes));
3605130561Sobrien  typeArrayOop dbuf   = typeArrayOop(JNIHandles::resolve(data));
360668765Sobrien  typeArrayOop fids   = typeArrayOop(JNIHandles::resolve(fieldIDs));
3607130561Sobrien  oop          o      = JNIHandles::resolve(obj);
3608130561Sobrien
3609130561Sobrien  if (o == NULL || fids == NULL  || dbuf == NULL  || tcodes == NULL) {
3610130561Sobrien    THROW(vmSymbols::java_lang_NullPointerException());
3611130561Sobrien  }
3612130561Sobrien
3613130561Sobrien  jsize nfids = fids->length();
3614130561Sobrien  if (nfids == 0) return;
3615130561Sobrien
361668765Sobrien  if (tcodes->length() < nfids) {
3617130561Sobrien    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
361868765Sobrien  }
3619130561Sobrien
3620130561Sobrien  jsize off = 0;
362168765Sobrien  /* loop through fields, setting values */
3622130561Sobrien  for (jsize i = 0; i < nfids; i++) {
362368765Sobrien    jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i);
3624130561Sobrien    int field_offset;
3625130561Sobrien    if (fid != NULL) {
3626130561Sobrien      // NULL is a legal value for fid, but retrieving the field offset
3627130561Sobrien      // trigger assertion in that case
3628130561Sobrien      field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid);
3629130561Sobrien    }
3630130561Sobrien
3631130561Sobrien    switch (tcodes->char_at(i)) {
3632130561Sobrien      case 'Z':
3633130561Sobrien        if (fid != NULL) {
3634130561Sobrien          jboolean val = (dbuf->byte_at(off) != 0) ? JNI_TRUE : JNI_FALSE;
3635130561Sobrien          o->bool_field_put(field_offset, val);
3636130561Sobrien        }
3637130561Sobrien        off++;
363868765Sobrien        break;
3639130561Sobrien
3640130561Sobrien      case 'B':
3641130561Sobrien        if (fid != NULL) {
3642130561Sobrien          o->byte_field_put(field_offset, dbuf->byte_at(off));
3643130561Sobrien        }
3644130561Sobrien        off++;
3645130561Sobrien        break;
3646130561Sobrien
3647130561Sobrien      case 'C':
3648130561Sobrien        if (fid != NULL) {
3649130561Sobrien          jchar val = ((dbuf->byte_at(off + 0) & 0xFF) << 8)
3650218822Sdim                    + ((dbuf->byte_at(off + 1) & 0xFF) << 0);
365168765Sobrien          o->char_field_put(field_offset, val);
3652130561Sobrien        }
365368765Sobrien        off += 2;
3654130561Sobrien        break;
3655130561Sobrien
3656130561Sobrien      case 'S':
3657130561Sobrien        if (fid != NULL) {
3658130561Sobrien          jshort val = ((dbuf->byte_at(off + 0) & 0xFF) << 8)
3659130561Sobrien                     + ((dbuf->byte_at(off + 1) & 0xFF) << 0);
3660130561Sobrien          o->short_field_put(field_offset, val);
3661130561Sobrien        }
3662130561Sobrien        off += 2;
3663130561Sobrien        break;
366468765Sobrien
366568765Sobrien      case 'I':
3666130561Sobrien        if (fid != NULL) {
366768765Sobrien          jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24)
3668130561Sobrien                    + ((dbuf->byte_at(off + 1) & 0xFF) << 16)
366968765Sobrien                    + ((dbuf->byte_at(off + 2) & 0xFF) << 8)
3670130561Sobrien                    + ((dbuf->byte_at(off + 3) & 0xFF) << 0);
3671130561Sobrien          o->int_field_put(field_offset, ival);
367268765Sobrien        }
3673130561Sobrien        off += 4;
367468765Sobrien        break;
3675130561Sobrien
3676218822Sdim      case 'F':
3677218822Sdim        if (fid != NULL) {
367868765Sobrien          jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24)
3679130561Sobrien                    + ((dbuf->byte_at(off + 1) & 0xFF) << 16)
3680130561Sobrien                    + ((dbuf->byte_at(off + 2) & 0xFF) << 8)
3681130561Sobrien                    + ((dbuf->byte_at(off + 3) & 0xFF) << 0);
3682130561Sobrien          jfloat fval = (*int_bits_to_float_fn)(env, NULL, ival);
3683218822Sdim          o->float_field_put(field_offset, fval);
3684130561Sobrien        }
3685130561Sobrien        off += 4;
3686130561Sobrien        break;
3687218822Sdim
3688130561Sobrien      case 'J':
3689130561Sobrien        if (fid != NULL) {
3690130561Sobrien          jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56)
3691218822Sdim                     + (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48)
3692130561Sobrien                     + (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40)
3693130561Sobrien                     + (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32)
3694130561Sobrien                     + (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24)
3695130561Sobrien                     + (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16)
3696130561Sobrien                     + (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8)
3697130561Sobrien                     + (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0);
3698130561Sobrien          o->long_field_put(field_offset, lval);
3699130561Sobrien        }
3700130561Sobrien        off += 8;
3701130561Sobrien        break;
3702130561Sobrien
3703130561Sobrien      case 'D':
3704130561Sobrien        if (fid != NULL) {
3705130561Sobrien          jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56)
3706218822Sdim                     + (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48)
3707130561Sobrien                     + (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40)
3708130561Sobrien                     + (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32)
3709218822Sdim                     + (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24)
3710130561Sobrien                     + (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16)
3711130561Sobrien                     + (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8)
3712130561Sobrien                     + (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0);
3713130561Sobrien          jdouble dval = (*long_bits_to_double_fn)(env, NULL, lval);
3714130561Sobrien          o->double_field_put(field_offset, dval);
3715218822Sdim        }
3716130561Sobrien        off += 8;
3717130561Sobrien        break;
3718130561Sobrien
3719130561Sobrien      default:
3720130561Sobrien        // Illegal typecode
3721130561Sobrien        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode");
3722130561Sobrien    }
3723130561Sobrien  }
3724130561SobrienJVM_END
3725130561Sobrien
3726130561Sobrien
372768765SobrienJVM_ENTRY(void, JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj,
3728130561Sobrien                            jlongArray fieldIDs, jcharArray typecodes, jbyteArray data))
372968765Sobrien  assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier");
3730130561Sobrien
3731218822Sdim  typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes));
3732218822Sdim  typeArrayOop dbuf   = typeArrayOop(JNIHandles::resolve(data));
3733218822Sdim  typeArrayOop fids   = typeArrayOop(JNIHandles::resolve(fieldIDs));
3734130561Sobrien  oop          o      = JNIHandles::resolve(obj);
3735130561Sobrien
3736130561Sobrien  if (o == NULL || fids == NULL  || dbuf == NULL  || tcodes == NULL) {
3737218822Sdim    THROW(vmSymbols::java_lang_NullPointerException());
3738130561Sobrien  }
3739130561Sobrien
374068765Sobrien  jsize nfids = fids->length();
3741130561Sobrien  if (nfids == 0) return;
3742130561Sobrien
3743218822Sdim  if (tcodes->length() < nfids) {
3744130561Sobrien    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
374568765Sobrien  }
3746130561Sobrien
3747130561Sobrien  /* loop through fields, fetching values */
374868765Sobrien  jsize off = 0;
3749130561Sobrien  for (jsize i = 0; i < nfids; i++) {
3750130561Sobrien    jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i);
375168765Sobrien    if (fid == NULL) {
3752218822Sdim      THROW(vmSymbols::java_lang_NullPointerException());
3753218822Sdim    }
3754218822Sdim    int field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid);
3755218822Sdim
3756130561Sobrien     switch (tcodes->char_at(i)) {
3757130561Sobrien       case 'Z':
3758130561Sobrien         {
3759130561Sobrien           jboolean val = o->bool_field(field_offset);
3760130561Sobrien           dbuf->byte_at_put(off++, (val != 0) ? 1 : 0);
3761130561Sobrien         }
3762130561Sobrien         break;
3763218822Sdim
3764130561Sobrien       case 'B':
376568765Sobrien         dbuf->byte_at_put(off++, o->byte_field(field_offset));
3766130561Sobrien         break;
3767130561Sobrien
3768130561Sobrien       case 'C':
376968765Sobrien         {
3770130561Sobrien           jchar val = o->char_field(field_offset);
377168765Sobrien           dbuf->byte_at_put(off++, (val >> 8) & 0xFF);
3772130561Sobrien           dbuf->byte_at_put(off++, (val >> 0) & 0xFF);
3773130561Sobrien         }
3774130561Sobrien         break;
3775130561Sobrien
377668765Sobrien       case 'S':
3777130561Sobrien         {
3778130561Sobrien           jshort val = o->short_field(field_offset);
3779130561Sobrien           dbuf->byte_at_put(off++, (val >> 8) & 0xFF);
3780130561Sobrien           dbuf->byte_at_put(off++, (val >> 0) & 0xFF);
3781130561Sobrien         }
3782218822Sdim         break;
3783130561Sobrien
3784218822Sdim       case 'I':
3785218822Sdim         {
3786218822Sdim           jint val = o->int_field(field_offset);
3787130561Sobrien           dbuf->byte_at_put(off++, (val >> 24) & 0xFF);
3788218822Sdim           dbuf->byte_at_put(off++, (val >> 16) & 0xFF);
3789218822Sdim           dbuf->byte_at_put(off++, (val >> 8)  & 0xFF);
3790130561Sobrien           dbuf->byte_at_put(off++, (val >> 0)  & 0xFF);
3791130561Sobrien         }
3792130561Sobrien         break;
3793130561Sobrien
3794130561Sobrien       case 'F':
3795130561Sobrien         {
3796130561Sobrien           jfloat fval = o->float_field(field_offset);
3797130561Sobrien           jint ival = (*float_to_int_bits_fn)(env, NULL, fval);
3798130561Sobrien           dbuf->byte_at_put(off++, (ival >> 24) & 0xFF);
3799130561Sobrien           dbuf->byte_at_put(off++, (ival >> 16) & 0xFF);
3800130561Sobrien           dbuf->byte_at_put(off++, (ival >> 8)  & 0xFF);
3801130561Sobrien           dbuf->byte_at_put(off++, (ival >> 0)  & 0xFF);
3802130561Sobrien         }
3803130561Sobrien         break;
3804130561Sobrien
3805130561Sobrien       case 'J':
3806130561Sobrien         {
3807130561Sobrien           jlong val = o->long_field(field_offset);
3808130561Sobrien           dbuf->byte_at_put(off++, (val >> 56) & 0xFF);
3809130561Sobrien           dbuf->byte_at_put(off++, (val >> 48) & 0xFF);
3810130561Sobrien           dbuf->byte_at_put(off++, (val >> 40) & 0xFF);
3811130561Sobrien           dbuf->byte_at_put(off++, (val >> 32) & 0xFF);
3812130561Sobrien           dbuf->byte_at_put(off++, (val >> 24) & 0xFF);
3813130561Sobrien           dbuf->byte_at_put(off++, (val >> 16) & 0xFF);
3814130561Sobrien           dbuf->byte_at_put(off++, (val >> 8)  & 0xFF);
3815130561Sobrien           dbuf->byte_at_put(off++, (val >> 0)  & 0xFF);
3816218822Sdim         }
3817218822Sdim         break;
3818218822Sdim
3819130561Sobrien       case 'D':
3820130561Sobrien         {
3821130561Sobrien           jdouble dval = o->double_field(field_offset);
3822130561Sobrien           jlong lval = (*double_to_long_bits_fn)(env, NULL, dval);
3823130561Sobrien           dbuf->byte_at_put(off++, (lval >> 56) & 0xFF);
3824130561Sobrien           dbuf->byte_at_put(off++, (lval >> 48) & 0xFF);
3825130561Sobrien           dbuf->byte_at_put(off++, (lval >> 40) & 0xFF);
3826130561Sobrien           dbuf->byte_at_put(off++, (lval >> 32) & 0xFF);
3827130561Sobrien           dbuf->byte_at_put(off++, (lval >> 24) & 0xFF);
3828130561Sobrien           dbuf->byte_at_put(off++, (lval >> 16) & 0xFF);
3829130561Sobrien           dbuf->byte_at_put(off++, (lval >> 8)  & 0xFF);
3830130561Sobrien           dbuf->byte_at_put(off++, (lval >> 0)  & 0xFF);
3831218822Sdim         }
383268765Sobrien         break;
3833218822Sdim
3834218822Sdim       default:
3835218822Sdim         // Illegal typecode
3836218822Sdim         THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode");
3837218822Sdim     }
3838218822Sdim  }
3839218822SdimJVM_END
3840218822Sdim
3841218822Sdim
3842218822Sdim// Shared JNI/JVM entry points //////////////////////////////////////////////////////////////
3843218822Sdim
384468765Sobrienjclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) {
384568765Sobrien  // Security Note:
384668765Sobrien  //   The Java level wrapper will perform the necessary security check allowing
3847130561Sobrien  //   us to pass the NULL as the initiating class loader.
3848218822Sdim  klassOop klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL);
384968765Sobrien  KlassHandle klass_handle(THREAD, klass);
3850130561Sobrien  // Check if we should initialize the class
3851130561Sobrien  if (init && klass_handle->oop_is_instance()) {
3852130561Sobrien    klass_handle->initialize(CHECK_NULL);
3853130561Sobrien  }
385468765Sobrien  return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror());
385568765Sobrien}
3856130561Sobrien
3857130561Sobrien
385868765Sobrien// Internal SQE debugging support ///////////////////////////////////////////////////////////
3859130561Sobrien
386068765Sobrien#ifndef PRODUCT
3861130561Sobrien
3862130561Sobrienextern "C" {
3863130561Sobrien  JNIEXPORT jboolean JNICALL JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get);
3864130561Sobrien  JNIEXPORT jboolean JNICALL JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get);
386568765Sobrien  JNIEXPORT void JNICALL JVM_VMBreakPoint(JNIEnv *env, jobject obj);
386668765Sobrien}
3867130561Sobrien
386868765SobrienJVM_LEAF(jboolean, JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get))
3869130561Sobrien  JVMWrapper("JVM_AccessBoolVMFlag");
3870218822Sdim  return is_get ? CommandLineFlags::boolAt((char*) name, (bool*) value) : CommandLineFlags::boolAtPut((char*) name, (bool*) value, INTERNAL);
3871218822SdimJVM_END
387268765Sobrien
3873130561SobrienJVM_LEAF(jboolean, JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get))
3874130561Sobrien  JVMWrapper("JVM_AccessVMIntFlag");
3875130561Sobrien  intx v;
3876130561Sobrien  jboolean result = is_get ? CommandLineFlags::intxAt((char*) name, &v) : CommandLineFlags::intxAtPut((char*) name, &v, INTERNAL);
3877130561Sobrien  *value = (jint)v;
3878130561Sobrien  return result;
387968765SobrienJVM_END
3880130561Sobrien
388168765Sobrien
3882130561SobrienJVM_ENTRY(void, JVM_VMBreakPoint(JNIEnv *env, jobject obj))
3883218822Sdim  JVMWrapper("JVM_VMBreakPoint");
3884218822Sdim  oop the_obj = JNIHandles::resolve(obj);
3885130561Sobrien  BREAKPOINT;
3886130561SobrienJVM_END
3887130561Sobrien
388868765Sobrien
388968765Sobrien#endif
3890130561Sobrien
3891130561Sobrien
389268765Sobrien//---------------------------------------------------------------------------
3893130561Sobrien//
3894130561Sobrien// Support for old native code-based reflection (pre-JDK 1.4)
3895130561Sobrien// Disabled by default in the product build.
3896130561Sobrien//
389768765Sobrien// See reflection.hpp for information on SUPPORT_OLD_REFLECTION
3898130561Sobrien//
3899130561Sobrien//---------------------------------------------------------------------------
390068765Sobrien
3901130561Sobrien#ifdef SUPPORT_OLD_REFLECTION
3902130561Sobrien
3903218822SdimJVM_ENTRY(jobjectArray, JVM_GetClassFields(JNIEnv *env, jclass cls, jint which))
390468765Sobrien  JVMWrapper("JVM_GetClassFields");
3905130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
390668765Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
3907130561Sobrien  objArrayOop result = Reflection::reflect_fields(mirror, which, CHECK_NULL);
3908130561Sobrien  return (jobjectArray) JNIHandles::make_local(env, result);
3909130561SobrienJVM_END
3910130561Sobrien
3911130561Sobrien
3912130561SobrienJVM_ENTRY(jobjectArray, JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which))
3913130561Sobrien  JVMWrapper("JVM_GetClassMethods");
3914130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
3915130561Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
3916130561Sobrien  objArrayOop result = Reflection::reflect_methods(mirror, which, CHECK_NULL);
3917130561Sobrien  //%note jvm_r4
3918130561Sobrien  return (jobjectArray) JNIHandles::make_local(env, result);
3919130561SobrienJVM_END
392068765Sobrien
3921130561Sobrien
392268765SobrienJVM_ENTRY(jobjectArray, JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which))
3923130561Sobrien  JVMWrapper("JVM_GetClassConstructors");
3924130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
3925130561Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
3926130561Sobrien  objArrayOop result = Reflection::reflect_constructors(mirror, which, CHECK_NULL);
3927130561Sobrien  //%note jvm_r4
3928218822Sdim  return (jobjectArray) JNIHandles::make_local(env, result);
3929218822SdimJVM_END
3930130561Sobrien
3931130561Sobrien
3932130561SobrienJVM_ENTRY(jobject, JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which))
3933130561Sobrien  JVMWrapper("JVM_GetClassField");
3934130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
3935130561Sobrien  if (name == NULL) return NULL;
3936130561Sobrien  Handle str (THREAD, JNIHandles::resolve_non_null(name));
3937130561Sobrien
3938130561Sobrien  const char* cstr = java_lang_String::as_utf8_string(str());
3939130561Sobrien  symbolHandle field_name =
3940130561Sobrien           symbolHandle(THREAD, SymbolTable::probe(cstr, (int)strlen(cstr)));
3941130561Sobrien  if (field_name.is_null()) {
3942130561Sobrien    THROW_0(vmSymbols::java_lang_NoSuchFieldException());
3943130561Sobrien  }
3944130561Sobrien
3945130561Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
3946130561Sobrien  oop result = Reflection::reflect_field(mirror, field_name(), which, CHECK_NULL);
3947130561Sobrien  if (result == NULL) {
3948130561Sobrien    THROW_0(vmSymbols::java_lang_NoSuchFieldException());
3949130561Sobrien  }
3950130561Sobrien  return JNIHandles::make_local(env, result);
3951130561SobrienJVM_END
395268765Sobrien
395368765Sobrien
3954218822SdimJVM_ENTRY(jobject, JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which))
3955218822Sdim  JVMWrapper("JVM_GetClassMethod");
3956218822Sdim  JvmtiVMObjectAllocEventCollector oam;
3957218822Sdim  if (name == NULL) {
395868765Sobrien    THROW_0(vmSymbols::java_lang_NullPointerException());
3959218822Sdim  }
3960218822Sdim  Handle str (THREAD, JNIHandles::resolve_non_null(name));
3961218822Sdim
396268765Sobrien  const char* cstr = java_lang_String::as_utf8_string(str());
3963130561Sobrien  symbolHandle method_name =
3964130561Sobrien          symbolHandle(THREAD, SymbolTable::probe(cstr, (int)strlen(cstr)));
3965130561Sobrien  if (method_name.is_null()) {
3966218822Sdim    THROW_0(vmSymbols::java_lang_NoSuchMethodException());
396768765Sobrien  }
3968130561Sobrien
3969130561Sobrien  oop mirror = JNIHandles::resolve_non_null(cls);
3970130561Sobrien  objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
3971130561Sobrien  oop result = Reflection::reflect_method(mirror, method_name, tarray,
3972130561Sobrien                                          which, CHECK_NULL);
3973130561Sobrien  if (result == NULL) {
397468765Sobrien    THROW_0(vmSymbols::java_lang_NoSuchMethodException());
3975218822Sdim  }
397668765Sobrien  return JNIHandles::make_local(env, result);
3977218822SdimJVM_END
3978218822Sdim
3979218822Sdim
3980218822SdimJVM_ENTRY(jobject, JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which))
3981218822Sdim  JVMWrapper("JVM_GetClassConstructor");
3982218822Sdim  JvmtiVMObjectAllocEventCollector oam;
3983218822Sdim  oop mirror = JNIHandles::resolve_non_null(cls);
398468765Sobrien  objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
398568765Sobrien  oop result = Reflection::reflect_constructor(mirror, tarray, which, CHECK_NULL);
398668765Sobrien  if (result == NULL) {
3987130561Sobrien    THROW_0(vmSymbols::java_lang_NoSuchMethodException());
3988218822Sdim  }
3989130561Sobrien  return (jobject) JNIHandles::make_local(env, result);
399068765SobrienJVM_END
399168765Sobrien
3992218822Sdim
399368765Sobrien// Instantiation ///////////////////////////////////////////////////////////////////////////////
3994130561Sobrien
3995130561SobrienJVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls))
3996130561Sobrien  JVMWrapper("JVM_NewInstance");
3997130561Sobrien  Handle mirror(THREAD, JNIHandles::resolve_non_null(cls));
399868765Sobrien
3999218822Sdim  methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror());
4000218822Sdim  if (resolved_constructor == NULL) {
4001130561Sobrien    klassOop k = java_lang_Class::as_klassOop(mirror());
4002218822Sdim    // The java.lang.Class object caches a resolved constructor if all the checks
4003218822Sdim    // below were done successfully and a constructor was found.
4004130561Sobrien
400568765Sobrien    // Do class based checks
4006218822Sdim    if (java_lang_Class::is_primitive(mirror())) {
4007218822Sdim      const char* msg = "";
4008218822Sdim      if      (mirror == Universe::bool_mirror())   msg = "java/lang/Boolean";
4009130561Sobrien      else if (mirror == Universe::char_mirror())   msg = "java/lang/Character";
401068765Sobrien      else if (mirror == Universe::float_mirror())  msg = "java/lang/Float";
4011130561Sobrien      else if (mirror == Universe::double_mirror()) msg = "java/lang/Double";
4012130561Sobrien      else if (mirror == Universe::byte_mirror())   msg = "java/lang/Byte";
4013130561Sobrien      else if (mirror == Universe::short_mirror())  msg = "java/lang/Short";
4014130561Sobrien      else if (mirror == Universe::int_mirror())    msg = "java/lang/Integer";
4015130561Sobrien      else if (mirror == Universe::long_mirror())   msg = "java/lang/Long";
4016130561Sobrien      THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg);
401768765Sobrien    }
4018130561Sobrien
4019218822Sdim    // Check whether we are allowed to instantiate this class
4020130561Sobrien    Klass::cast(k)->check_valid_for_instantiation(false, CHECK_NULL); // Array classes get caught here
402168765Sobrien    instanceKlassHandle klass(THREAD, k);
4022218822Sdim    // Make sure class is initialized (also so all methods are rewritten)
4023218822Sdim    klass->initialize(CHECK_NULL);
4024218822Sdim
4025218822Sdim    // Lookup default constructor
402668765Sobrien    resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
4027218822Sdim    if (resolved_constructor == NULL) {
4028218822Sdim      ResourceMark rm(THREAD);
4029130561Sobrien      THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name());
4030218822Sdim    }
4031218822Sdim
4032218822Sdim    // Cache result in java.lang.Class object. Does not have to be MT safe.
4033218822Sdim    java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor);
4034218822Sdim  }
4035218822Sdim
4036130561Sobrien  assert(resolved_constructor != NULL, "sanity check");
4037218822Sdim  methodHandle constructor = methodHandle(THREAD, resolved_constructor);
4038218822Sdim
4039218822Sdim  // We have an initialized instanceKlass with a default constructor
4040218822Sdim  instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)));
4041218822Sdim  assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check");
4042130561Sobrien
4043218822Sdim  // Do security check
4044130561Sobrien  klassOop caller_klass = NULL;
4045218822Sdim  if (UsePrivilegedStack) {
4046218822Sdim    caller_klass = thread->security_get_caller_class(2);
4047218822Sdim
4048218822Sdim    if (!Reflection::verify_class_access(caller_klass, klass(), false) ||
4049218822Sdim        !Reflection::verify_field_access(caller_klass,
4050218822Sdim                                         klass(),
4051218822Sdim                                         klass(),
4052218822Sdim                                         constructor->access_flags(),
4053218822Sdim                                         false,
4054218822Sdim                                         true)) {
4055218822Sdim      ResourceMark rm(THREAD);
405668765Sobrien      THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name());
405768765Sobrien    }
4058104834Sobrien  }
4059130561Sobrien
4060218822Sdim  // Allocate object and call constructor
406168765Sobrien  Handle receiver = klass->allocate_instance_handle(CHECK_NULL);
4062130561Sobrien  JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL);
4063130561Sobrien
4064130561Sobrien  jobject res = JNIHandles::make_local(env, receiver());
406568765Sobrien  if (JvmtiExport::should_post_vm_object_alloc()) {
406668765Sobrien    JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver());
406768765Sobrien  }
406868765Sobrien  return res;
406968765SobrienJVM_END
4070130561Sobrien
407168765Sobrien
4072218822Sdim// Field ////////////////////////////////////////////////////////////////////////////////////////////
4073130561Sobrien
407468765SobrienJVM_ENTRY(jobject, JVM_GetField(JNIEnv *env, jobject field, jobject obj))
407568765Sobrien  JVMWrapper("JVM_GetField");
407668765Sobrien  JvmtiVMObjectAllocEventCollector oam;
4077130561Sobrien  Handle field_mirror(thread, JNIHandles::resolve(field));
407868765Sobrien  Handle receiver    (thread, JNIHandles::resolve(obj));
407968765Sobrien  fieldDescriptor fd;
408068765Sobrien  Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_NULL);
4081130561Sobrien  jvalue value;
408268765Sobrien  BasicType type = Reflection::field_get(&value, &fd, receiver);
408368765Sobrien  oop box = Reflection::box(&value, type, CHECK_NULL);
408468765Sobrien  return JNIHandles::make_local(env, box);
4085130561SobrienJVM_END
408668765Sobrien
408768765Sobrien
408868765SobrienJVM_ENTRY(jvalue, JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode))
4089218822Sdim  JVMWrapper("JVM_GetPrimitiveField");
4090218822Sdim  Handle field_mirror(thread, JNIHandles::resolve(field));
409168765Sobrien  Handle receiver    (thread, JNIHandles::resolve(obj));
4092130561Sobrien  fieldDescriptor fd;
4093130561Sobrien  jvalue value;
409468765Sobrien  value.j = 0;
4095130561Sobrien  Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_(value));
4096130561Sobrien  BasicType type = Reflection::field_get(&value, &fd, receiver);
4097218822Sdim  BasicType wide_type = (BasicType) wCode;
4098218822Sdim  if (type != wide_type) {
4099130561Sobrien    Reflection::widen(&value, type, wide_type, CHECK_(value));
4100130561Sobrien  }
410168765Sobrien  return value;
4102130561SobrienJVM_END // should really be JVM_END, but that doesn't work for union types!
4103130561Sobrien
4104218822Sdim
4105218822SdimJVM_ENTRY(void, JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val))
410668765Sobrien  JVMWrapper("JVM_SetField");
410768765Sobrien  Handle field_mirror(thread, JNIHandles::resolve(field));
410868765Sobrien  Handle receiver    (thread, JNIHandles::resolve(obj));
4109218822Sdim  oop box = JNIHandles::resolve(val);
411068765Sobrien  fieldDescriptor fd;
4111130561Sobrien  Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
411268765Sobrien  BasicType field_type = fd.field_type();
4113218822Sdim  jvalue value;
4114218822Sdim  BasicType value_type;
4115218822Sdim  if (field_type == T_OBJECT || field_type == T_ARRAY) {
4116218822Sdim    // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array
4117218822Sdim    value_type = Reflection::unbox_for_regular_object(box, &value);
4118218822Sdim    Reflection::field_set(&value, &fd, receiver, field_type, CHECK);
4119218822Sdim  } else {
4120130561Sobrien    value_type = Reflection::unbox_for_primitive(box, &value, CHECK);
412168765Sobrien    Reflection::field_set(&value, &fd, receiver, value_type, CHECK);
4122130561Sobrien  }
4123130561SobrienJVM_END
412468765Sobrien
4125130561Sobrien
4126130561SobrienJVM_ENTRY(void, JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode))
412768765Sobrien  JVMWrapper("JVM_SetPrimitiveField");
412868765Sobrien  Handle field_mirror(thread, JNIHandles::resolve(field));
412968765Sobrien  Handle receiver    (thread, JNIHandles::resolve(obj));
4130130561Sobrien  fieldDescriptor fd;
4131130561Sobrien  Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
4132130561Sobrien  BasicType value_type = (BasicType) vCode;
4133130561Sobrien  Reflection::field_set(&v, &fd, receiver, value_type, CHECK);
4134130561SobrienJVM_END
4135130561Sobrien
4136130561Sobrien
4137130561Sobrien// Method ///////////////////////////////////////////////////////////////////////////////////////////
4138130561Sobrien
4139130561SobrienJVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
4140130561Sobrien  JVMWrapper("JVM_InvokeMethod");
414168765Sobrien  Handle method_handle;
4142130561Sobrien  if (thread->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) {
4143218822Sdim    method_handle = Handle(THREAD, JNIHandles::resolve(method));
4144218822Sdim    Handle receiver(THREAD, JNIHandles::resolve(obj));
4145130561Sobrien    objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
4146130561Sobrien    oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL);
414768765Sobrien    jobject res = JNIHandles::make_local(env, result);
414868765Sobrien    if (JvmtiExport::should_post_vm_object_alloc()) {
4149218822Sdim      oop ret_type = java_lang_reflect_Method::return_type(method_handle());
4150218822Sdim      assert(ret_type != NULL, "sanity check: ret_type oop must not be NULL!");
4151218822Sdim      if (java_lang_Class::is_primitive(ret_type)) {
4152218822Sdim        // Only for primitive type vm allocates memory for java object.
4153218822Sdim        // See box() method.
4154218822Sdim        JvmtiExport::post_vm_object_alloc(JavaThread::current(), result);
4155218822Sdim      }
4156218822Sdim    }
4157218822Sdim    return res;
4158218822Sdim  } else {
4159218822Sdim    THROW_0(vmSymbols::java_lang_StackOverflowError());
4160218822Sdim  }
4161218822SdimJVM_END
4162218822Sdim
4163218822Sdim
4164218822SdimJVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0))
4165218822Sdim  JVMWrapper("JVM_NewInstanceFromConstructor");
4166218822Sdim  oop constructor_mirror = JNIHandles::resolve(c);
4167218822Sdim  objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
4168218822Sdim  oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);
4169218822Sdim  jobject res = JNIHandles::make_local(env, result);
4170218822Sdim  if (JvmtiExport::should_post_vm_object_alloc()) {
4171218822Sdim    JvmtiExport::post_vm_object_alloc(JavaThread::current(), result);
4172218822Sdim  }
4173218822Sdim  return res;
4174218822SdimJVM_END
4175218822Sdim
4176218822Sdim#endif /* SUPPORT_OLD_REFLECTION */
4177218822Sdim
4178218822Sdim// Atomic ///////////////////////////////////////////////////////////////////////////////////////////
4179218822Sdim
4180218822SdimJVM_LEAF(jboolean, JVM_SupportsCX8())
4181218822Sdim  JVMWrapper("JVM_SupportsCX8");
4182218822Sdim  return VM_Version::supports_cx8();
4183218822SdimJVM_END
4184218822Sdim
4185218822Sdim
4186218822SdimJVM_ENTRY(jboolean, JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong oldVal, jlong newVal))
4187218822Sdim  JVMWrapper("JVM_CX8Field");
4188218822Sdim  jlong res;
4189218822Sdim  oop             o       = JNIHandles::resolve(obj);
4190218822Sdim  intptr_t        fldOffs = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid);
4191104834Sobrien  volatile jlong* addr    = (volatile jlong*)((address)o + fldOffs);
419268765Sobrien
4193130561Sobrien  assert(VM_Version::supports_cx8(), "cx8 not supported");
4194130561Sobrien  res = Atomic::cmpxchg(newVal, addr, oldVal);
4195130561Sobrien
419668765Sobrien  return res == oldVal;
419768765SobrienJVM_END
4198218822Sdim
419968765Sobrien// DTrace ///////////////////////////////////////////////////////////////////
4200130561Sobrien
420177298SobrienJVM_ENTRY(jint, JVM_DTraceGetVersion(JNIEnv* env))
4202130561Sobrien  JVMWrapper("JVM_DTraceGetVersion");
420368765Sobrien  return (jint)JVM_TRACING_DTRACE_VERSION;
420468765SobrienJVM_END
4205218822Sdim
4206218822SdimJVM_ENTRY(jlong,JVM_DTraceActivate(
4207218822Sdim    JNIEnv* env, jint version, jstring module_name, jint providers_count,
4208218822Sdim    JVM_DTraceProvider* providers))
4209218822Sdim  JVMWrapper("JVM_DTraceActivate");
4210218822Sdim  return DTraceJSDT::activate(
4211218822Sdim    version, module_name, providers_count, providers, CHECK_0);
421289857SobrienJVM_END
421389857Sobrien
4214218822SdimJVM_ENTRY(jboolean,JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method))
4215218822Sdim  JVMWrapper("JVM_DTraceIsProbeEnabled");
4216218822Sdim  return DTraceJSDT::is_probe_enabled(method);
421789857SobrienJVM_END
421889857Sobrien
4219218822SdimJVM_ENTRY(void,JVM_DTraceDispose(JNIEnv* env, jlong handle))
422089857Sobrien  JVMWrapper("JVM_DTraceDispose");
4221130561Sobrien  DTraceJSDT::dispose(handle);
422289857SobrienJVM_END
4223218822Sdim
4224218822SdimJVM_ENTRY(jboolean,JVM_DTraceIsSupported(JNIEnv* env))
422589857Sobrien  JVMWrapper("JVM_DTraceIsSupported");
4226218822Sdim  return DTraceJSDT::is_supported();
4227218822SdimJVM_END
4228218822Sdim
4229218822Sdim// Returns an array of all live Thread objects (VM internal JavaThreads,
4230218822Sdim// jvmti agent threads, and JNI attaching threads  are skipped)
4231218822Sdim// See CR 6404306 regarding JNI attaching threads
4232218822SdimJVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy))
423389857Sobrien  ResourceMark rm(THREAD);
423489857Sobrien  ThreadsListEnumerator tle(THREAD, false, false);
4235104834Sobrien  JvmtiVMObjectAllocEventCollector oam;
423668765Sobrien
4237130561Sobrien  int num_threads = tle.num_threads();
423889857Sobrien  objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NULL);
4239130561Sobrien  objArrayHandle threads_ah(THREAD, r);
4240130561Sobrien
4241130561Sobrien  for (int i = 0; i < num_threads; i++) {
4242130561Sobrien    Handle h = tle.get_threadObj(i);
4243130561Sobrien    threads_ah->obj_at_put(i, h());
4244218822Sdim  }
4245218822Sdim
4246218822Sdim  return (jobjectArray) JNIHandles::make_local(env, threads_ah());
424789857SobrienJVM_END
4248130561Sobrien
4249130561Sobrien
4250130561Sobrien// Support for java.lang.Thread.getStackTrace() and getAllStackTraces() methods
425189857Sobrien// Return StackTraceElement[][], each element is the stack trace of a thread in
4252130561Sobrien// the corresponding entry in the given threads array
4253130561SobrienJVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads))
425489857Sobrien  JVMWrapper("JVM_DumpThreads");
4255130561Sobrien  JvmtiVMObjectAllocEventCollector oam;
425689857Sobrien
4257130561Sobrien  // Check if threads is null
4258130561Sobrien  if (threads == NULL) {
4259130561Sobrien    THROW_(vmSymbols::java_lang_NullPointerException(), 0);
4260130561Sobrien  }
426189857Sobrien
4262218822Sdim  objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(threads));
4263218822Sdim  objArrayHandle ah(THREAD, a);
4264130561Sobrien  int num_threads = ah->length();
4265218822Sdim  // check if threads is non-empty array
4266218822Sdim  if (num_threads == 0) {
4267130561Sobrien    THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0);
426889857Sobrien  }
4269130561Sobrien
4270130561Sobrien  // check if threads is not an array of objects of Thread class
4271130561Sobrien  klassOop k = objArrayKlass::cast(ah->klass())->element_klass();
4272130561Sobrien  if (k != SystemDictionary::thread_klass()) {
4273130561Sobrien    THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0);
4274130561Sobrien  }
4275130561Sobrien
4276130561Sobrien  ResourceMark rm(THREAD);
4277130561Sobrien
4278130561Sobrien  GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
4279130561Sobrien  for (int i = 0; i < num_threads; i++) {
4280130561Sobrien    oop thread_obj = ah->obj_at(i);
4281130561Sobrien    instanceHandle h(THREAD, (instanceOop) thread_obj);
4282130561Sobrien    thread_handle_array->append(h);
4283130561Sobrien  }
4284130561Sobrien
4285130561Sobrien  Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL);
4286130561Sobrien  return (jobjectArray)JNIHandles::make_local(env, stacktraces());
4287130561Sobrien
4288130561SobrienJVM_END
4289130561Sobrien
4290130561Sobrien// JVM monitoring and management support
4291130561SobrienJVM_ENTRY_NO_ENV(void*, JVM_GetManagement(jint version))
4292130561Sobrien  return Management::get_jmm_interface(version);
4293130561SobrienJVM_END
4294130561Sobrien
4295130561Sobrien// com.sun.tools.attach.VirtualMachine agent properties support
4296130561Sobrien//
4297130561Sobrien// Initialize the agent properties with the properties maintained in the VM
4298130561SobrienJVM_ENTRY(jobject, JVM_InitAgentProperties(JNIEnv *env, jobject properties))
4299130561Sobrien  JVMWrapper("JVM_InitAgentProperties");
4300130561Sobrien  ResourceMark rm;
4301130561Sobrien
4302130561Sobrien  Handle props(THREAD, JNIHandles::resolve_non_null(properties));
4303130561Sobrien
4304130561Sobrien  PUTPROP(props, "sun.java.command", Arguments::java_command());
4305130561Sobrien  PUTPROP(props, "sun.jvm.flags", Arguments::jvm_flags());
4306130561Sobrien  PUTPROP(props, "sun.jvm.args", Arguments::jvm_args());
4307130561Sobrien  return properties;
430889857SobrienJVM_END
430989857Sobrien
4310130561SobrienJVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass))
4311130561Sobrien{
431289857Sobrien  JVMWrapper("JVM_GetEnclosingMethodInfo");
431389857Sobrien  JvmtiVMObjectAllocEventCollector oam;
4314218822Sdim
431589857Sobrien  if (ofClass == NULL) {
4316130561Sobrien    return NULL;
4317130561Sobrien  }
431889857Sobrien  Handle mirror(THREAD, JNIHandles::resolve_non_null(ofClass));
4319130561Sobrien  // Special handling for primitive objects
4320130561Sobrien  if (java_lang_Class::is_primitive(mirror())) {
4321130561Sobrien    return NULL;
432289857Sobrien  }
432389857Sobrien  klassOop k = java_lang_Class::as_klassOop(mirror());
432489857Sobrien  if (!Klass::cast(k)->oop_is_instance()) {
4325130561Sobrien    return NULL;
4326130561Sobrien  }
4327130561Sobrien  instanceKlassHandle ik_h(THREAD, k);
432889857Sobrien  int encl_method_class_idx = ik_h->enclosing_method_class_index();
4329218822Sdim  if (encl_method_class_idx == 0) {
433089857Sobrien    return NULL;
4331130561Sobrien  }
4332130561Sobrien  objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::object_klass(), 3, CHECK_NULL);
433389857Sobrien  objArrayHandle dest(THREAD, dest_o);
4334130561Sobrien  klassOop enc_k = ik_h->constants()->klass_at(encl_method_class_idx, CHECK_NULL);
4335130561Sobrien  dest->obj_at_put(0, Klass::cast(enc_k)->java_mirror());
4336130561Sobrien  int encl_method_method_idx = ik_h->enclosing_method_method_index();
433789857Sobrien  if (encl_method_method_idx != 0) {
4338130561Sobrien    symbolOop sym_o = ik_h->constants()->symbol_at(
4339104834Sobrien                        extract_low_short_from_int(
434089857Sobrien                          ik_h->constants()->name_and_type_at(encl_method_method_idx)));
434168765Sobrien    symbolHandle sym(THREAD, sym_o);
434268765Sobrien    Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
434368765Sobrien    dest->obj_at_put(1, str());
4344130561Sobrien    sym_o = ik_h->constants()->symbol_at(
434568765Sobrien              extract_high_short_from_int(
4346218822Sdim                ik_h->constants()->name_and_type_at(encl_method_method_idx)));
434768765Sobrien    sym = symbolHandle(THREAD, sym_o);
4348130561Sobrien    str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
4349130561Sobrien    dest->obj_at_put(2, str());
4350130561Sobrien  }
4351130561Sobrien  return (jobjectArray) JNIHandles::make_local(dest());
435268765Sobrien}
435368765SobrienJVM_END
435477298Sobrien
435577298SobrienJVM_ENTRY(jintArray, JVM_GetThreadStateValues(JNIEnv* env,
435668765Sobrien                                              jint javaThreadState))
435768765Sobrien{
435868765Sobrien  // If new thread states are added in future JDK and VM versions,
435968765Sobrien  // this should check if the JDK version is compatible with thread
436068765Sobrien  // states supported by the VM.  Return NULL if not compatible.
436168765Sobrien  //
436268765Sobrien  // This function must map the VM java_lang_Thread::ThreadStatus
4363218822Sdim  // to the Java thread state that the JDK supports.
436468765Sobrien  //
436568765Sobrien
436677298Sobrien  typeArrayHandle values_h;
436768765Sobrien  switch (javaThreadState) {
4368130561Sobrien    case JAVA_THREAD_STATE_NEW : {
436968765Sobrien      typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
437068765Sobrien      values_h = typeArrayHandle(THREAD, r);
437168765Sobrien      values_h->int_at_put(0, java_lang_Thread::NEW);
437268765Sobrien      break;
437368765Sobrien    }
437468765Sobrien    case JAVA_THREAD_STATE_RUNNABLE : {
437568765Sobrien      typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
437689857Sobrien      values_h = typeArrayHandle(THREAD, r);
437768765Sobrien      values_h->int_at_put(0, java_lang_Thread::RUNNABLE);
4378130561Sobrien      break;
4379130561Sobrien    }
4380130561Sobrien    case JAVA_THREAD_STATE_BLOCKED : {
4381130561Sobrien      typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
438268765Sobrien      values_h = typeArrayHandle(THREAD, r);
438368765Sobrien      values_h->int_at_put(0, java_lang_Thread::BLOCKED_ON_MONITOR_ENTER);
438468765Sobrien      break;
438568765Sobrien    }
438668765Sobrien    case JAVA_THREAD_STATE_WAITING : {
438768765Sobrien      typeArrayOop r = oopFactory::new_typeArray(T_INT, 2, CHECK_NULL);
438868765Sobrien      values_h = typeArrayHandle(THREAD, r);
438968765Sobrien      values_h->int_at_put(0, java_lang_Thread::IN_OBJECT_WAIT);
4390218822Sdim      values_h->int_at_put(1, java_lang_Thread::PARKED);
439168765Sobrien      break;
439268765Sobrien    }
439368765Sobrien    case JAVA_THREAD_STATE_TIMED_WAITING : {
4394130561Sobrien      typeArrayOop r = oopFactory::new_typeArray(T_INT, 3, CHECK_NULL);
439568765Sobrien      values_h = typeArrayHandle(THREAD, r);
439668765Sobrien      values_h->int_at_put(0, java_lang_Thread::SLEEPING);
439768765Sobrien      values_h->int_at_put(1, java_lang_Thread::IN_OBJECT_WAIT_TIMED);
439868765Sobrien      values_h->int_at_put(2, java_lang_Thread::PARKED_TIMED);
439968765Sobrien      break;
440068765Sobrien    }
440168765Sobrien    case JAVA_THREAD_STATE_TERMINATED : {
4402130561Sobrien      typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
440368765Sobrien      values_h = typeArrayHandle(THREAD, r);
440468765Sobrien      values_h->int_at_put(0, java_lang_Thread::TERMINATED);
440568765Sobrien      break;
440668765Sobrien    }
440768765Sobrien    default:
440868765Sobrien      // Unknown state - probably incompatible JDK version
440968765Sobrien      return NULL;
441068765Sobrien  }
441168765Sobrien
441268765Sobrien  return (jintArray) JNIHandles::make_local(env, values_h());
4413130561Sobrien}
4414130561SobrienJVM_END
441568765Sobrien
441668765Sobrien
441768765SobrienJVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env,
4418130561Sobrien                                                jint javaThreadState,
441968765Sobrien                                                jintArray values))
442068765Sobrien{
442168765Sobrien  // If new thread states are added in future JDK and VM versions,
442268765Sobrien  // this should check if the JDK version is compatible with thread
442368765Sobrien  // states supported by the VM.  Return NULL if not compatible.
442468765Sobrien  //
442568765Sobrien  // This function must map the VM java_lang_Thread::ThreadStatus
442668765Sobrien  // to the Java thread state that the JDK supports.
442768765Sobrien  //
4428130561Sobrien
442968765Sobrien  ResourceMark rm;
443068765Sobrien
443168765Sobrien  // Check if threads is null
443268765Sobrien  if (values == NULL) {
4433130561Sobrien    THROW_(vmSymbols::java_lang_NullPointerException(), 0);
443468765Sobrien  }
443568765Sobrien
443668765Sobrien  typeArrayOop v = typeArrayOop(JNIHandles::resolve_non_null(values));
443768765Sobrien  typeArrayHandle values_h(THREAD, v);
443868765Sobrien
443968765Sobrien  objArrayHandle names_h;
444068765Sobrien  switch (javaThreadState) {
444168765Sobrien    case JAVA_THREAD_STATE_NEW : {
444268765Sobrien      assert(values_h->length() == 1 &&
444368765Sobrien               values_h->int_at(0) == java_lang_Thread::NEW,
444468765Sobrien             "Invalid threadStatus value");
444568765Sobrien
4446130561Sobrien      objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
4447130561Sobrien                                               1, /* only 1 substate */
4448218822Sdim                                               CHECK_NULL);
4449218822Sdim      names_h = objArrayHandle(THREAD, r);
4450218822Sdim      Handle name = java_lang_String::create_from_str("NEW", CHECK_NULL);
4451130561Sobrien      names_h->obj_at_put(0, name());
4452218822Sdim      break;
445368765Sobrien    }
4454130561Sobrien    case JAVA_THREAD_STATE_RUNNABLE : {
4455130561Sobrien      assert(values_h->length() == 1 &&
4456130561Sobrien               values_h->int_at(0) == java_lang_Thread::RUNNABLE,
4457130561Sobrien             "Invalid threadStatus value");
4458130561Sobrien
4459130561Sobrien      objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
4460130561Sobrien                                               1, /* only 1 substate */
4461130561Sobrien                                               CHECK_NULL);
4462130561Sobrien      names_h = objArrayHandle(THREAD, r);
4463130561Sobrien      Handle name = java_lang_String::create_from_str("RUNNABLE", CHECK_NULL);
4464130561Sobrien      names_h->obj_at_put(0, name());
4465130561Sobrien      break;
4466130561Sobrien    }
446768765Sobrien    case JAVA_THREAD_STATE_BLOCKED : {
446868765Sobrien      assert(values_h->length() == 1 &&
446968765Sobrien               values_h->int_at(0) == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER,
447068765Sobrien             "Invalid threadStatus value");
447168765Sobrien
447268765Sobrien      objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
447368765Sobrien                                               1, /* only 1 substate */
447468765Sobrien                                               CHECK_NULL);
447568765Sobrien      names_h = objArrayHandle(THREAD, r);
447668765Sobrien      Handle name = java_lang_String::create_from_str("BLOCKED", CHECK_NULL);
447768765Sobrien      names_h->obj_at_put(0, name());
447868765Sobrien      break;
447968765Sobrien    }
448068765Sobrien    case JAVA_THREAD_STATE_WAITING : {
448168765Sobrien      assert(values_h->length() == 2 &&
448268765Sobrien               values_h->int_at(0) == java_lang_Thread::IN_OBJECT_WAIT &&
4483130561Sobrien               values_h->int_at(1) == java_lang_Thread::PARKED,
4484218822Sdim             "Invalid threadStatus value");
4485218822Sdim      objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
4486218822Sdim                                               2, /* number of substates */
4487130561Sobrien                                               CHECK_NULL);
448868765Sobrien      names_h = objArrayHandle(THREAD, r);
4489218822Sdim      Handle name0 = java_lang_String::create_from_str("WAITING.OBJECT_WAIT",
4490218822Sdim                                                       CHECK_NULL);
4491218822Sdim      Handle name1 = java_lang_String::create_from_str("WAITING.PARKED",
4492130561Sobrien                                                       CHECK_NULL);
4493218822Sdim      names_h->obj_at_put(0, name0());
449468765Sobrien      names_h->obj_at_put(1, name1());
449568765Sobrien      break;
4496130561Sobrien    }
449768765Sobrien    case JAVA_THREAD_STATE_TIMED_WAITING : {
4498130561Sobrien      assert(values_h->length() == 3 &&
4499130561Sobrien               values_h->int_at(0) == java_lang_Thread::SLEEPING &&
450068765Sobrien               values_h->int_at(1) == java_lang_Thread::IN_OBJECT_WAIT_TIMED &&
4501130561Sobrien               values_h->int_at(2) == java_lang_Thread::PARKED_TIMED,
4502218822Sdim             "Invalid threadStatus value");
4503218822Sdim      objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
4504218822Sdim                                               3, /* number of substates */
4505218822Sdim                                               CHECK_NULL);
4506218822Sdim      names_h = objArrayHandle(THREAD, r);
4507218822Sdim      Handle name0 = java_lang_String::create_from_str("TIMED_WAITING.SLEEPING",
4508218822Sdim                                                       CHECK_NULL);
450968765Sobrien      Handle name1 = java_lang_String::create_from_str("TIMED_WAITING.OBJECT_WAIT",
451068765Sobrien                                                       CHECK_NULL);
451168765Sobrien      Handle name2 = java_lang_String::create_from_str("TIMED_WAITING.PARKED",
451268765Sobrien                                                       CHECK_NULL);
451368765Sobrien      names_h->obj_at_put(0, name0());
451468765Sobrien      names_h->obj_at_put(1, name1());
451568765Sobrien      names_h->obj_at_put(2, name2());
4516      break;
4517    }
4518    case JAVA_THREAD_STATE_TERMINATED : {
4519      assert(values_h->length() == 1 &&
4520               values_h->int_at(0) == java_lang_Thread::TERMINATED,
4521             "Invalid threadStatus value");
4522      objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
4523                                               1, /* only 1 substate */
4524                                               CHECK_NULL);
4525      names_h = objArrayHandle(THREAD, r);
4526      Handle name = java_lang_String::create_from_str("TERMINATED", CHECK_NULL);
4527      names_h->obj_at_put(0, name());
4528      break;
4529    }
4530    default:
4531      // Unknown state - probably incompatible JDK version
4532      return NULL;
4533  }
4534  return (jobjectArray) JNIHandles::make_local(env, names_h());
4535}
4536JVM_END
4537
4538JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size))
4539{
4540  memset(info, 0, sizeof(info_size));
4541
4542  info->jvm_version = Abstract_VM_Version::jvm_version();
4543  info->update_version = 0;          /* 0 in HotSpot Express VM */
4544  info->special_update_version = 0;  /* 0 in HotSpot Express VM */
4545
4546  // when we add a new capability in the jvm_version_info struct, we should also
4547  // consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
4548  // counter defined in runtimeService.cpp.
4549  info->is_attachable = AttachListener::is_attach_supported();
4550#ifdef KERNEL
4551  info->is_kernel_jvm = 1; // true;
4552#else  // KERNEL
4553  info->is_kernel_jvm = 0; // false;
4554#endif // KERNEL
4555}
4556JVM_END
4557
4558