diff src/share/vm/interpreter/bytecodeInterpreter.cpp @ 6725:da91efe96a93

6964458: Reimplement class meta-data storage to use native memory Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author coleenp
date Sat, 01 Sep 2012 13:25:18 -0400
parents 1d7922586cf6
children d8ce2825b193
line wrap: on
line diff
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp	Fri Aug 31 16:39:35 2012 -0700
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Sat Sep 01 13:25:18 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -490,7 +490,7 @@
   register address          pc = istate->bcp();
   register jubyte opcode;
   register intptr_t*        locals = istate->locals();
-  register constantPoolCacheOop  cp = istate->constants(); // method()->constants()->cache()
+  register ConstantPoolCache*    cp = istate->constants(); // method()->constants()->cache()
 #ifdef LOTS_OF_REGS
   register JavaThread*      THREAD = istate->thread();
   register volatile jbyte*  BYTE_MAP_BASE = _byte_map_base;
@@ -679,7 +679,7 @@
               // The bias pattern is present in the object's header. Need to check
               // whether the bias owner and the epoch are both still current.
               intptr_t xx = ((intptr_t) THREAD) ^ (intptr_t) mark;
-              xx = (intptr_t) rcvr->klass()->klass_part()->prototype_header() ^ xx;
+              xx = (intptr_t) rcvr->klass()->prototype_header() ^ xx;
               intptr_t yy = (xx & ~((int) markOopDesc::age_mask_in_place));
               if (yy != 0 ) {
                 // At this point we know that the header has the bias pattern and
@@ -723,8 +723,8 @@
                     // value as the comparison value when doing the cas to acquire the
                     // bias in the current epoch. In other words, we allow transfer of
                     // the bias from one thread to another directly in this situation.
-                    xx = (intptr_t) rcvr->klass()->klass_part()->prototype_header() | (intptr_t) THREAD;
-                    if (Atomic::cmpxchg_ptr((intptr_t)THREAD | (intptr_t) rcvr->klass()->klass_part()->prototype_header(),
+                    xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD;
+                    if (Atomic::cmpxchg_ptr((intptr_t)THREAD | (intptr_t) rcvr->klass()->prototype_header(),
                                             (intptr_t*) rcvr->mark_addr(),
                                             (intptr_t) mark) != (intptr_t) mark) {
                       CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception);
@@ -741,8 +741,8 @@
                   // bias of this particular object, so it's okay to continue in the
                   // normal locking code.
                   //
-                  xx = (intptr_t) rcvr->klass()->klass_part()->prototype_header() | (intptr_t) THREAD;
-                  if (Atomic::cmpxchg_ptr(rcvr->klass()->klass_part()->prototype_header(),
+                  xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD;
+                  if (Atomic::cmpxchg_ptr(rcvr->klass()->prototype_header(),
                                           (intptr_t*) rcvr->mark_addr(),
                                           mark) == mark) {
                     // (*counters->revoked_lock_entry_count_addr())++;
@@ -1530,7 +1530,7 @@
 
           oop rcvr = LOCALS_OBJECT(0);
           VERIFY_OOP(rcvr);
-          if (rcvr->klass()->klass_part()->has_finalizer()) {
+          if (rcvr->klass()->has_finalizer()) {
             CALL_VM(InterpreterRuntime::register_finalizer(THREAD, rcvr), handle_exception);
           }
           goto handle_return;
@@ -1625,14 +1625,13 @@
           // arrObj, index are set
           if (rhsObject != NULL) {
             /* Check assignability of rhsObject into arrObj */
-            klassOop rhsKlassOop = rhsObject->klass(); // EBX (subclass)
-            assert(arrObj->klass()->klass()->klass_part()->oop_is_objArrayKlass(), "Ack not an objArrayKlass");
-            klassOop elemKlassOop = ((objArrayKlass*) arrObj->klass()->klass_part())->element_klass(); // superklass EAX
+            Klass* rhsKlassOop = rhsObject->klass(); // EBX (subclass)
+            Klass* elemKlassOop = objArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX
             //
             // Check for compatibilty. This check must not GC!!
             // Seems way more expensive now that we must dispatch
             //
-            if (rhsKlassOop != elemKlassOop && !rhsKlassOop->klass_part()->is_subtype_of(elemKlassOop)) { // ebx->is...
+            if (rhsKlassOop != elemKlassOop && !rhsKlassOop->is_subtype_of(elemKlassOop)) { // ebx->is...
               VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), "");
             }
           }
@@ -1774,7 +1773,8 @@
 
           oop obj;
           if ((Bytecodes::Code)opcode == Bytecodes::_getstatic) {
-            obj = (oop) cache->f1_as_instance();
+            Klass* k = (Klass*) cache->f1();
+            obj = k->java_mirror();
             MORE_STACK(1);  // Assume single slot push
           } else {
             obj = (oop) STACK_OBJECT(-1);
@@ -1885,7 +1885,8 @@
             --count;
           }
           if ((Bytecodes::Code)opcode == Bytecodes::_putstatic) {
-            obj = (oop) cache->f1_as_instance();
+            Klass* k = (Klass*) cache->f1();
+            obj = k->java_mirror();
           } else {
             --count;
             obj = (oop) STACK_OBJECT(count);
@@ -1944,14 +1945,14 @@
 
       CASE(_new): {
         u2 index = Bytes::get_Java_u2(pc+1);
-        constantPoolOop constants = istate->method()->constants();
+        ConstantPool* constants = istate->method()->constants();
         if (!constants->tag_at(index).is_unresolved_klass()) {
           // Make sure klass is initialized and doesn't have a finalizer
-          oop entry = constants->slot_at(index).get_oop();
+          Klass* entry = constants->slot_at(index).get_klass();
           assert(entry->is_klass(), "Should be resolved klass");
-          klassOop k_entry = (klassOop) entry;
-          assert(k_entry->klass_part()->oop_is_instance(), "Should be instanceKlass");
-          instanceKlass* ik = (instanceKlass*) k_entry->klass_part();
+          Klass* k_entry = (Klass*) entry;
+          assert(k_entry->oop_is_instance(), "Should be InstanceKlass");
+          InstanceKlass* ik = (InstanceKlass*) k_entry;
           if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
             size_t obj_size = ik->size_helper();
             oop result = NULL;
@@ -2037,14 +2038,14 @@
             if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
               CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
             }
-            klassOop klassOf = (klassOop) METHOD->constants()->slot_at(index).get_oop();
-            klassOop objKlassOop = STACK_OBJECT(-1)->klass(); //ebx
+            Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
+            Klass* objKlassOop = STACK_OBJECT(-1)->klass(); //ebx
             //
             // Check for compatibilty. This check must not GC!!
             // Seems way more expensive now that we must dispatch
             //
             if (objKlassOop != klassOf &&
-                !objKlassOop->klass_part()->is_subtype_of(klassOf)) {
+                !objKlassOop->is_subtype_of(klassOf)) {
               ResourceMark rm(THREAD);
               const char* objName = Klass::cast(objKlassOop)->external_name();
               const char* klassName = Klass::cast(klassOf)->external_name();
@@ -2072,13 +2073,13 @@
             if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
               CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
             }
-            klassOop klassOf = (klassOop) METHOD->constants()->slot_at(index).get_oop();
-            klassOop objKlassOop = STACK_OBJECT(-1)->klass();
+            Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
+            Klass* objKlassOop = STACK_OBJECT(-1)->klass();
             //
             // Check for compatibilty. This check must not GC!!
             // Seems way more expensive now that we must dispatch
             //
-            if ( objKlassOop == klassOf || objKlassOop->klass_part()->is_subtype_of(klassOf)) {
+            if ( objKlassOop == klassOf || objKlassOop->is_subtype_of(klassOf)) {
               SET_STACK_INT(1, -1);
             } else {
               SET_STACK_INT(0, -1);
@@ -2100,7 +2101,7 @@
             wide = true;
           }
 
-          constantPoolOop constants = METHOD->constants();
+          ConstantPool* constants = METHOD->constants();
           switch (constants->tag_at(index).value()) {
           case JVM_CONSTANT_Integer:
             SET_STACK_INT(constants->int_at(index), 0);
@@ -2111,16 +2112,24 @@
             break;
 
           case JVM_CONSTANT_String:
-            VERIFY_OOP(constants->resolved_string_at(index));
-            SET_STACK_OBJECT(constants->resolved_string_at(index), 0);
+            {
+              oop result = constants->resolved_references()->obj_at(index);
+              if (result == NULL) {
+                CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception);
+                SET_STACK_OBJECT(THREAD->vm_result(), 0);
+                THREAD->set_vm_result(NULL);
+              } else {
+                VERIFY_OOP(result);
+                SET_STACK_OBJECT(result, 0);
+              }
             break;
+            }
 
           case JVM_CONSTANT_Class:
             VERIFY_OOP(constants->resolved_klass_at(index)->java_mirror());
             SET_STACK_OBJECT(constants->resolved_klass_at(index)->java_mirror(), 0);
             break;
 
-          case JVM_CONSTANT_UnresolvedString:
           case JVM_CONSTANT_UnresolvedClass:
           case JVM_CONSTANT_UnresolvedClassInError:
             CALL_VM(InterpreterRuntime::ldc(THREAD, wide), handle_exception);
@@ -2137,7 +2146,7 @@
         {
           u2 index = Bytes::get_Java_u2(pc+1);
 
-          constantPoolOop constants = METHOD->constants();
+          ConstantPool* constants = METHOD->constants();
           switch (constants->tag_at(index).value()) {
 
           case JVM_CONSTANT_Long:
@@ -2154,15 +2163,6 @@
 
       CASE(_fast_aldc_w):
       CASE(_fast_aldc): {
-        if (!EnableInvokeDynamic) {
-          // We should not encounter this bytecode if !EnableInvokeDynamic.
-          // The verifier will stop it.  However, if we get past the verifier,
-          // this will stop the thread in a reasonable way, without crashing the JVM.
-          CALL_VM(InterpreterRuntime::throw_IncompatibleClassChangeError(THREAD),
-                  handle_exception);
-          ShouldNotReachHere();
-        }
-
         u2 index;
         int incr;
         if (opcode == Bytecodes::_fast_aldc) {
@@ -2176,12 +2176,12 @@
         // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
         // This kind of CP cache entry does not need to match the flags byte, because
         // there is a 1-1 relation between bytecode type and CP entry type.
-        ConstantPoolCacheEntry* cache = cp->entry_at(index);
-        oop result = cache->f1_as_instance();
+        ConstantPool* constants = METHOD->constants();
+        oop result = constants->resolved_references()->obj_at(index);
         if (result == NULL) {
           CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode),
                   handle_exception);
-          result = cache->f1_as_instance();
+          result = THREAD->vm_result();
         }
 
         VERIFY_OOP(result);
@@ -2201,16 +2201,15 @@
 
         int index = Bytes::get_native_u4(pc+1);
 
-        // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
+        // We are resolved if the resolved_references field contains a non-null object (CallSite, etc.)
         // This kind of CP cache entry does not need to match the flags byte, because
         // there is a 1-1 relation between bytecode type and CP entry type.
-        assert(constantPoolCacheOopDesc::is_secondary_index(index), "incorrect format");
-        ConstantPoolCacheEntry* cache = cp->secondary_entry_at(index);
-        oop result = cache->f1_as_instance();
+        ConstantPool* constants = METHOD->constants();
+        oop result = constants->resolved_references()->obj_at(index);
         if (result == NULL) {
           CALL_VM(InterpreterRuntime::resolve_invokedynamic(THREAD),
                   handle_exception);
-          result = cache->f1_as_instance();
+          result = THREAD->vm_result();
         }
 
         VERIFY_OOP(result);
@@ -2218,7 +2217,7 @@
         CHECK_NULL(method_handle);
 
         istate->set_msg(call_method_handle);
-        istate->set_callee((methodOop) method_handle);
+        istate->set_callee((Method*) method_handle);
         istate->set_bcp_advance(5);
 
         UPDATE_PC_AND_RETURN(0); // I'll be back...
@@ -2244,7 +2243,7 @@
         // This code isn't produced by javac, but could be produced by
         // another compliant java compiler.
         if (cache->is_forced_virtual()) {
-          methodOop callee;
+          Method* callee;
           CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
           if (cache->is_vfinal()) {
             callee = cache->f2_as_vfinal_method();
@@ -2253,9 +2252,9 @@
             int parms = cache->parameter_size();
             // Same comments as invokevirtual apply here
             VERIFY_OOP(STACK_OBJECT(-parms));
-            instanceKlass* rcvrKlass = (instanceKlass*)
-                                 STACK_OBJECT(-parms)->klass()->klass_part();
-            callee = (methodOop) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
+            InstanceKlass* rcvrKlass = (InstanceKlass*)
+                                 STACK_OBJECT(-parms)->klass();
+            callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
           }
           istate->set_callee(callee);
           istate->set_callee_entry_point(callee->from_interpreted_entry());
@@ -2269,14 +2268,14 @@
         }
 
         // this could definitely be cleaned up QQQ
-        methodOop callee;
-        klassOop iclass = cache->f1_as_klass();
-        // instanceKlass* interface = (instanceKlass*) iclass->klass_part();
+        Method* callee;
+        Klass* iclass = cache->f1_as_klass();
+        // InstanceKlass* interface = (InstanceKlass*) iclass;
         // get receiver
         int parms = cache->parameter_size();
         oop rcvr = STACK_OBJECT(-parms);
         CHECK_NULL(rcvr);
-        instanceKlass* int2 = (instanceKlass*) rcvr->klass()->klass_part();
+        InstanceKlass* int2 = (InstanceKlass*) rcvr->klass();
         itableOffsetEntry* ki = (itableOffsetEntry*) int2->start_of_itable();
         int i;
         for ( i = 0 ; i < int2->itable_length() ; i++, ki++ ) {
@@ -2323,7 +2322,7 @@
 
         istate->set_msg(call_method);
         {
-          methodOop callee;
+          Method* callee;
           if ((Bytecodes::Code)opcode == Bytecodes::_invokevirtual) {
             CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
             if (cache->is_vfinal()) callee = cache->f2_as_vfinal_method();
@@ -2331,13 +2330,13 @@
               // get receiver
               int parms = cache->parameter_size();
               // this works but needs a resourcemark and seems to create a vtable on every call:
-              // methodOop callee = rcvr->klass()->klass_part()->vtable()->method_at(cache->f2_as_index());
+              // Method* callee = rcvr->klass()->vtable()->method_at(cache->f2_as_index());
               //
               // this fails with an assert
-              // instanceKlass* rcvrKlass = instanceKlass::cast(STACK_OBJECT(-parms)->klass());
+              // InstanceKlass* rcvrKlass = InstanceKlass::cast(STACK_OBJECT(-parms)->klass());
               // but this works
               VERIFY_OOP(STACK_OBJECT(-parms));
-              instanceKlass* rcvrKlass = (instanceKlass*) STACK_OBJECT(-parms)->klass()->klass_part();
+              InstanceKlass* rcvrKlass = (InstanceKlass*) STACK_OBJECT(-parms)->klass();
               /*
                 Executing this code in java.lang.String:
                     public String(char value[]) {
@@ -2345,16 +2344,16 @@
                           this.value = (char[])value.clone();
                      }
 
-                 a find on rcvr->klass()->klass_part() reports:
+                 a find on rcvr->klass() reports:
                  {type array char}{type array class}
                   - klass: {other class}
 
-                  but using instanceKlass::cast(STACK_OBJECT(-parms)->klass()) causes in assertion failure
-                  because rcvr->klass()->klass_part()->oop_is_instance() == 0
+                  but using InstanceKlass::cast(STACK_OBJECT(-parms)->klass()) causes in assertion failure
+                  because rcvr->klass()->oop_is_instance() == 0
                   However it seems to have a vtable in the right location. Huh?
 
               */
-              callee = (methodOop) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
+              callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
             }
           } else {
             if ((Bytecodes::Code)opcode == Bytecodes::_invokespecial) {
@@ -2500,7 +2499,7 @@
     CALL_VM(continuation_bci = (intptr_t)InterpreterRuntime::exception_handler_for_exception(THREAD, except_oop()),
             handle_exception);
 
-    except_oop = (oop) THREAD->vm_result();
+    except_oop = THREAD->vm_result();
     THREAD->set_vm_result(NULL);
     if (continuation_bci >= 0) {
       // Place exception on top of stack