< prev index next >

hotspot/src/share/vm/classfile/javaClasses.cpp

Print this page

        

@@ -1516,47 +1516,15 @@
 }
 
 // After this many redefines, the stack trace is unreliable.
 const int MAX_VERSION = USHRT_MAX;
 
-// Helper backtrace functions to store bci|version together.
-static inline int merge_bci_and_version(int bci, int version) {
-  // only store u2 for version, checking for overflow.
-  if (version > USHRT_MAX || version < 0) version = MAX_VERSION;
-  assert((jushort)bci == bci, "bci should be short");
-  return build_int_from_shorts(version, bci);
-}
-
-static inline int bci_at(unsigned int merged) {
-  return extract_high_short_from_int(merged);
-}
-static inline int version_at(unsigned int merged) {
-  return extract_low_short_from_int(merged);
-}
-
 static inline bool version_matches(Method* method, int version) {
   assert(version < MAX_VERSION, "version is too big");
   return method != NULL && (method->constants()->version() == version);
 }
 
-static inline int get_line_number(Method* method, int bci) {
-  int line_number = 0;
-  if (method->is_native()) {
-    // Negative value different from -1 below, enabling Java code in
-    // class java.lang.StackTraceElement to distinguish "native" from
-    // "no LineNumberTable".  JDK tests for -2.
-    line_number = -2;
-  } else {
-    // Returns -1 if no LineNumberTable, and otherwise actual line number
-    line_number = method->line_number_from_bci(bci);
-    if (line_number == -1 && ShowHiddenFrames) {
-      line_number = bci + 1000000;
-    }
-  }
-  return line_number;
-}
-
 // This class provides a simple wrapper over the internal structure of
 // exception backtrace to insulate users of the backtrace from needing
 // to know what it looks like.
 class BacktraceBuilder: public StackObj {
  private:

@@ -1674,11 +1642,11 @@
       expand(CHECK);
       method = mhandle();
     }
 
     _methods->short_at_put(_index, method->orig_method_idnum());
-    _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version()));
+    _bcis->int_at_put(_index, Backtrace::merge_bci_and_version(bci, method->constants()->version()));
     _cprefs->short_at_put(_index, method->name_index());
 
     // We need to save the mirrors in the backtrace to keep the class
     // from being unloaded while we still have this stack trace.
     assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror");

@@ -1686,23 +1654,10 @@
     _index++;
   }
 
 };
 
-Symbol* get_source_file_name(InstanceKlass* holder, int version) {
-  // Find the specific ik version that contains this source_file_name_index
-  // via the previous versions list, but use the current version's
-  // constant pool to look it up.  The previous version's index has been
-  // merged for the current constant pool.
-  InstanceKlass* ik = holder->get_klass_version(version);
-  // This version has been cleaned up.
-  if (ik == NULL) return NULL;
-  int source_file_name_index = ik->source_file_name_index();
-  return (source_file_name_index == 0) ?
-      (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index);
-}
-
 // Print stack trace element to resource allocated buffer
 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
                                   int method_id, int version, int bci, int cpref) {
 
   // Get strings and string lengths

@@ -1716,11 +1671,11 @@
   Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
   char* method_name = sym->as_C_string();
   buf_len += (int)strlen(method_name);
 
   char* source_file_name = NULL;
-  Symbol* source = get_source_file_name(holder, version);
+  Symbol* source = Backtrace::get_source_file_name(holder, version);
   if (source != NULL) {
     source_file_name = source->as_C_string();
     buf_len += (int)strlen(source_file_name);
   }
 

@@ -1731,11 +1686,11 @@
   sprintf(buf, "\tat %s.%s", klass_name, method_name);
 
   if (!version_matches(method, version)) {
     strcat(buf, "(Redefined)");
   } else {
-    int line_number = get_line_number(method, bci);
+    int line_number = Backtrace::get_line_number(method, bci);
     if (line_number == -2) {
       strcat(buf, "(Native Method)");
     } else {
       if (source_file_name != NULL && (line_number != -1)) {
         // Sourcename and linenumber

@@ -1800,12 +1755,12 @@
       for (int index = 0; index < length; index++) {
         Handle mirror(THREAD, mirrors->obj_at(index));
         // NULL mirror means end of stack trace
         if (mirror.is_null()) goto handle_cause;
         int method = methods->short_at(index);
-        int version = version_at(bcis->int_at(index));
-        int bci = bci_at(bcis->int_at(index));
+        int version = Backtrace::version_at(bcis->int_at(index));
+        int bci = Backtrace::bci_at(bcis->int_at(index));
         int cpref = cprefs->short_at(index);
         print_stack_element(st, mirror, method, version, bci, cpref);
       }
       result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset)));
     }

@@ -2088,12 +2043,12 @@
   typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk);
 
   assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check");
 
   int method = methods->short_at(chunk_index);
-  int version = version_at(bcis->int_at(chunk_index));
-  int bci = bci_at(bcis->int_at(chunk_index));
+  int version = Backtrace::version_at(bcis->int_at(chunk_index));
+  int bci = Backtrace::bci_at(bcis->int_at(chunk_index));
   int cpref = cprefs->short_at(chunk_index);
   Handle mirror(THREAD, mirrors->obj_at(chunk_index));
 
   // Chunk can be partial full
   if (mirror.is_null()) {

@@ -2112,10 +2067,11 @@
   if (ik->should_be_initialized()) {
     ik->initialize(CHECK_0);
   }
 
   Handle element = ik->allocate_instance_handle(CHECK_0);
+
   // Fill in class name
   ResourceMark rm(THREAD);
   InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
   const char* str = holder->external_name();
   oop classname = StringTable::intern((char*) str, CHECK_0);

@@ -2134,17 +2090,17 @@
     // The method was redefined, accurate line number information isn't available
     java_lang_StackTraceElement::set_fileName(element(), NULL);
     java_lang_StackTraceElement::set_lineNumber(element(), -1);
   } else {
     // Fill in source file name and line number.
-    Symbol* source = get_source_file_name(holder, version);
+    Symbol* source = Backtrace::get_source_file_name(holder, version);
     if (ShowHiddenFrames && source == NULL)
       source = vmSymbols::unknown_class_name();
     oop filename = StringTable::intern(source, CHECK_0);
     java_lang_StackTraceElement::set_fileName(element(), filename);
 
-    int line_number = get_line_number(method, bci);
+    int line_number = Backtrace::get_line_number(method, bci);
     java_lang_StackTraceElement::set_lineNumber(element(), line_number);
   }
   return element();
 }
 

@@ -2153,10 +2109,112 @@
   int method_id = method->orig_method_idnum();
   int cpref = method->name_index();
   return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD);
 }
 
+Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) {
+  if (MemberNameInStackFrame) {
+    Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
+    Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname());
+    // we should expand MemberName::name when Throwable uses StackTrace
+    // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL);
+    return method;
+  } else {
+    short mid       = stackFrame->short_field(_mid_offset);
+    short version   = stackFrame->short_field(_version_offset);
+    return holder->method_with_orig_idnum(mid, version);
+  }
+}
+
+Symbol* java_lang_StackFrameInfo::get_file_name(Handle stackFrame, InstanceKlass* holder) {
+  if (MemberNameInStackFrame) {
+    return holder->source_file_name();
+  } else {
+    short version = stackFrame->short_field(_version_offset);
+    return Backtrace::get_source_file_name(holder, version);
+  }
+}
+
+void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) {
+  // set Method* or mid/cpref
+  if (MemberNameInStackFrame) {
+    oop mname = stackFrame->obj_field(_memberName_offset);
+    InstanceKlass* ik = method->method_holder();
+    CallInfo info(method(), ik);
+    MethodHandles::init_method_MemberName(mname, info);
+  } else {
+    int mid = method->orig_method_idnum();
+    int cpref = method->name_index();
+    assert((jushort)mid == mid,        "mid should be short");
+    assert((jushort)cpref == cpref,    "cpref should be short");
+    java_lang_StackFrameInfo::set_mid(stackFrame(),     (short)mid);
+    java_lang_StackFrameInfo::set_cpref(stackFrame(),   (short)cpref);
+  }
+  // set bci
+  java_lang_StackFrameInfo::set_bci(stackFrame(), bci);
+  // method may be redefined; store the version
+  int version = method->constants()->version();
+  assert((jushort)version == version, "version should be short");
+  java_lang_StackFrameInfo::set_version(stackFrame(), (short)version);
+}
+
+void java_lang_StackFrameInfo::fill_methodInfo(Handle stackFrame, TRAPS) {
+  ResourceMark rm(THREAD);
+  oop k = stackFrame->obj_field(_declaringClass_offset);
+  InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k));
+  Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK);
+  int bci = stackFrame->int_field(_bci_offset);
+
+  // The method can be NULL if the requested class version is gone
+  Symbol* sym = (method != NULL) ? method->name() : NULL;
+  if (MemberNameInStackFrame) {
+    assert(sym != NULL, "MemberName must have method name");
+  } else {
+      // The method can be NULL if the requested class version is gone
+    if (sym == NULL) {
+      short cpref   = stackFrame->short_field(_cpref_offset);
+      sym = holder->constants()->symbol_at(cpref);
+    }
+  }
+
+  // set method name
+  oop methodname = StringTable::intern(sym, CHECK);
+  java_lang_StackFrameInfo::set_methodName(stackFrame(), methodname);
+
+  // set file name and line number
+  Symbol* source = get_file_name(stackFrame, holder);
+  if (source != NULL) {
+    oop filename = StringTable::intern(source, CHECK);
+    java_lang_StackFrameInfo::set_fileName(stackFrame(), filename);
+  }
+  
+  // if the method has been redefined, the bci is no longer applicable
+  short version = stackFrame->short_field(_version_offset);
+  if (version_matches(method, version)) {
+    int line_number = Backtrace::get_line_number(method, bci);
+    java_lang_StackFrameInfo::set_lineNumber(stackFrame(), line_number);
+  }
+}
+
+void java_lang_StackFrameInfo::compute_offsets() {
+  Klass* k = SystemDictionary::StackFrameInfo_klass();
+  compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(),  vmSymbols::class_signature());
+  compute_offset(_memberName_offset,     k, vmSymbols::memberName_name(),  vmSymbols::object_signature());
+  compute_offset(_bci_offset,            k, vmSymbols::bci_name(),         vmSymbols::int_signature());
+  compute_offset(_methodName_offset,     k, vmSymbols::methodName_name(),  vmSymbols::string_signature());
+  compute_offset(_fileName_offset,       k, vmSymbols::fileName_name(),    vmSymbols::string_signature());
+  compute_offset(_lineNumber_offset,     k, vmSymbols::lineNumber_name(),  vmSymbols::int_signature());
+  STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
+}
+
+void java_lang_LiveStackFrameInfo::compute_offsets() {
+  Klass* k = SystemDictionary::LiveStackFrameInfo_klass();
+  compute_offset(_monitors_offset,   k, vmSymbols::monitors_name(),    vmSymbols::object_array_signature());
+  compute_offset(_locals_offset,     k, vmSymbols::locals_name(),      vmSymbols::object_array_signature());
+  compute_offset(_operands_offset,   k, vmSymbols::operands_name(),    vmSymbols::object_array_signature());
+}
+
 void java_lang_reflect_AccessibleObject::compute_offsets() {
   Klass* k = SystemDictionary::reflect_AccessibleObject_klass();
   compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
 }
 

@@ -3469,10 +3527,22 @@
 int java_lang_System::static_security_offset;
 int java_lang_StackTraceElement::declaringClass_offset;
 int java_lang_StackTraceElement::methodName_offset;
 int java_lang_StackTraceElement::fileName_offset;
 int java_lang_StackTraceElement::lineNumber_offset;
+int java_lang_StackFrameInfo::_declaringClass_offset;
+int java_lang_StackFrameInfo::_memberName_offset;
+int java_lang_StackFrameInfo::_bci_offset;
+int java_lang_StackFrameInfo::_methodName_offset;
+int java_lang_StackFrameInfo::_fileName_offset;
+int java_lang_StackFrameInfo::_lineNumber_offset;
+int java_lang_StackFrameInfo::_mid_offset;
+int java_lang_StackFrameInfo::_version_offset;
+int java_lang_StackFrameInfo::_cpref_offset;
+int java_lang_LiveStackFrameInfo::_monitors_offset;
+int java_lang_LiveStackFrameInfo::_locals_offset;
+int java_lang_LiveStackFrameInfo::_operands_offset;
 int java_lang_AssertionStatusDirectives::classes_offset;
 int java_lang_AssertionStatusDirectives::classEnabled_offset;
 int java_lang_AssertionStatusDirectives::packages_offset;
 int java_lang_AssertionStatusDirectives::packageEnabled_offset;
 int java_lang_AssertionStatusDirectives::deflt_offset;

@@ -3498,10 +3568,54 @@
 
 void java_lang_StackTraceElement::set_lineNumber(oop element, int value) {
   element->int_field_put(lineNumber_offset, value);
 }
 
+// Support for java_lang_StackFrameInfo
+void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
+  element->obj_field_put(_declaringClass_offset, value);
+}
+
+void java_lang_StackFrameInfo::set_mid(oop element, short value) {
+  element->short_field_put(_mid_offset, value);
+}
+
+void java_lang_StackFrameInfo::set_version(oop element, short value) {
+  element->short_field_put(_version_offset, value);
+}
+
+void java_lang_StackFrameInfo::set_cpref(oop element, short value) {
+  element->short_field_put(_cpref_offset, value);
+}
+
+void java_lang_StackFrameInfo::set_bci(oop element, int value) {
+  element->int_field_put(_bci_offset, value);
+}
+
+void java_lang_StackFrameInfo::set_fileName(oop element, oop value) {
+  element->obj_field_put(_fileName_offset, value);
+}
+
+void java_lang_StackFrameInfo::set_methodName(oop element, oop value) {
+  element->obj_field_put(_methodName_offset, value);
+}
+
+void java_lang_StackFrameInfo::set_lineNumber(oop element, int value) {
+  element->int_field_put(_lineNumber_offset, value);
+}
+
+void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) {
+  element->obj_field_put(_monitors_offset, value);
+}
+
+void java_lang_LiveStackFrameInfo::set_locals(oop element, oop value) {
+  element->obj_field_put(_locals_offset, value);
+}
+
+void java_lang_LiveStackFrameInfo::set_operands(oop element, oop value) {
+  element->obj_field_put(_operands_offset, value);
+}
 
 // Support for java Assertions - java_lang_AssertionStatusDirectives.
 
 void java_lang_AssertionStatusDirectives::set_classes(oop o, oop val) {
   o->obj_field_put(classes_offset, val);

@@ -3631,10 +3745,12 @@
   java_lang_reflect_Field::compute_offsets();
   java_nio_Buffer::compute_offsets();
   sun_reflect_ConstantPool::compute_offsets();
   sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
   java_lang_reflect_Parameter::compute_offsets();
+  java_lang_StackFrameInfo::compute_offsets();
+  java_lang_LiveStackFrameInfo::compute_offsets();
 
   // generated interpreter code wants to know about the offsets we just computed:
   AbstractAssembler::update_delayed_values();
 }
 
< prev index next >