hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
changeset 6453 970dc585ab63
parent 5702 201c5cde25bb
child 6460 6f5143b00f4c
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Sep 02 11:40:02 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Fri Sep 03 17:51:07 2010 -0700
@@ -1613,7 +1613,194 @@
   __ bind(*op->stub()->continuation());
 }
 
-
+void LIR_Assembler::type_profile_helper(Register mdo,
+                                        ciMethodData *md, ciProfileData *data,
+                                        Register recv, Label* update_done) {
+  uint i;
+  for (i = 0; i < ReceiverTypeData::row_limit(); i++) {
+    Label next_test;
+    // See if the receiver is receiver[n].
+    __ cmpptr(recv, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))));
+    __ jccb(Assembler::notEqual, next_test);
+    Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)));
+    __ addptr(data_addr, DataLayout::counter_increment);
+    __ jmpb(*update_done);
+    __ bind(next_test);
+  }
+
+  // Didn't find receiver; find next empty slot and fill it in
+  for (i = 0; i < ReceiverTypeData::row_limit(); i++) {
+    Label next_test;
+    Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)));
+    __ cmpptr(recv_addr, (intptr_t)NULL_WORD);
+    __ jccb(Assembler::notEqual, next_test);
+    __ movptr(recv_addr, recv);
+    __ movptr(Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))), DataLayout::counter_increment);
+    __ jmpb(*update_done);
+    __ bind(next_test);
+  }
+}
+
+void LIR_Assembler::emit_checkcast(LIR_OpTypeCheck *op) {
+  assert(op->code() == lir_checkcast, "Invalid operation");
+  // we always need a stub for the failure case.
+  CodeStub* stub = op->stub();
+  Register obj = op->object()->as_register();
+  Register k_RInfo = op->tmp1()->as_register();
+  Register klass_RInfo = op->tmp2()->as_register();
+  Register dst = op->result_opr()->as_register();
+  ciKlass* k = op->klass();
+  Register Rtmp1 = noreg;
+
+  // check if it needs to be profiled
+  ciMethodData* md;
+  ciProfileData* data;
+
+  if (op->should_profile()) {
+    ciMethod* method = op->profiled_method();
+    assert(method != NULL, "Should have method");
+    int bci = op->profiled_bci();
+    md = method->method_data();
+    if (md == NULL) {
+      bailout("out of memory building methodDataOop");
+      return;
+    }
+    data = md->bci_to_data(bci);
+    assert(data != NULL,                "need data for checkcast");
+    assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for checkcast");
+  }
+  Label profile_cast_failure;
+
+  Label done, done_null;
+  // Where to go in case of cast failure
+  Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry();
+
+  if (obj == k_RInfo) {
+    k_RInfo = dst;
+  } else if (obj == klass_RInfo) {
+    klass_RInfo = dst;
+  }
+  if (k->is_loaded()) {
+    select_different_registers(obj, dst, k_RInfo, klass_RInfo);
+  } else {
+    Rtmp1 = op->tmp3()->as_register();
+    select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1);
+  }
+
+  assert_different_registers(obj, k_RInfo, klass_RInfo);
+  if (!k->is_loaded()) {
+    jobject2reg_with_patching(k_RInfo, op->info_for_patch());
+  } else {
+#ifdef _LP64
+    __ movoop(k_RInfo, k->constant_encoding());
+#endif // _LP64
+  }
+  assert(obj != k_RInfo, "must be different");
+
+  __ cmpptr(obj, (int32_t)NULL_WORD);
+  if (op->should_profile()) {
+    Label profile_done;
+    __ jccb(Assembler::notEqual, profile_done);
+    // Object is null; update methodDataOop
+    Register mdo  = klass_RInfo;
+    __ movoop(mdo, md->constant_encoding());
+    Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset()));
+    int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant());
+    __ orl(data_addr, header_bits);
+    __ jmp(done_null);
+    __ bind(profile_done);
+  } else {
+    __ jcc(Assembler::equal, done_null);
+  }
+  __ verify_oop(obj);
+
+  if (op->fast_check()) {
+    // get object classo
+    // not a safepoint as obj null check happens earlier
+    if (k->is_loaded()) {
+#ifdef _LP64
+      __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
+#else
+      __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
+#endif // _LP64
+    } else {
+      __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
+    }
+    __ jcc(Assembler::notEqual, *failure_target);
+  } else {
+    // get object class
+    // not a safepoint as obj null check happens earlier
+    __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
+    if (k->is_loaded()) {
+      // See if we get an immediate positive hit
+#ifdef _LP64
+      __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset()));
+#else
+      __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding());
+#endif // _LP64
+      if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) {
+        __ jcc(Assembler::notEqual, *failure_target);
+      } else {
+        // See if we get an immediate positive hit
+        __ jcc(Assembler::equal, done);
+        // check for self
+#ifdef _LP64
+        __ cmpptr(klass_RInfo, k_RInfo);
+#else
+        __ cmpoop(klass_RInfo, k->constant_encoding());
+#endif // _LP64
+        __ jcc(Assembler::equal, done);
+
+        __ push(klass_RInfo);
+#ifdef _LP64
+        __ push(k_RInfo);
+#else
+        __ pushoop(k->constant_encoding());
+#endif // _LP64
+        __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
+        __ pop(klass_RInfo);
+        __ pop(klass_RInfo);
+        // result is a boolean
+        __ cmpl(klass_RInfo, 0);
+        __ jcc(Assembler::equal, *failure_target);
+      }
+    } else {
+      // perform the fast part of the checking logic
+      __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, failure_target, NULL);
+      // call out-of-line instance of __ check_klass_subtype_slow_path(...):
+      __ push(klass_RInfo);
+      __ push(k_RInfo);
+      __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
+      __ pop(klass_RInfo);
+      __ pop(k_RInfo);
+      // result is a boolean
+      __ cmpl(k_RInfo, 0);
+      __ jcc(Assembler::equal, *failure_target);
+    }
+  }
+  __ bind(done);
+
+  if (op->should_profile()) {
+    Register mdo  = klass_RInfo, recv = k_RInfo;
+    __ movoop(mdo, md->constant_encoding());
+    __ movptr(recv, Address(obj, oopDesc::klass_offset_in_bytes()));
+    Label update_done;
+    type_profile_helper(mdo, md, data, recv, &update_done);
+    __ jmpb(update_done);
+
+    __ bind(profile_cast_failure);
+    __ movoop(mdo, md->constant_encoding());
+    Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
+    __ subptr(counter_addr, DataLayout::counter_increment);
+    __ jmp(*stub->entry());
+
+    __ bind(update_done);
+  }
+  __ bind(done_null);
+  if (dst != obj) {
+    __ mov(dst, obj);
+  }
+}
 
 void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
   LIR_Code code = op->code();
@@ -1646,140 +1833,6 @@
     __ cmpl(k_RInfo, 0);
     __ jcc(Assembler::equal, *stub->entry());
     __ bind(done);
-  } else if (op->code() == lir_checkcast) {
-    // we always need a stub for the failure case.
-    CodeStub* stub = op->stub();
-    Register obj = op->object()->as_register();
-    Register k_RInfo = op->tmp1()->as_register();
-    Register klass_RInfo = op->tmp2()->as_register();
-    Register dst = op->result_opr()->as_register();
-    ciKlass* k = op->klass();
-    Register Rtmp1 = noreg;
-
-    Label done;
-    if (obj == k_RInfo) {
-      k_RInfo = dst;
-    } else if (obj == klass_RInfo) {
-      klass_RInfo = dst;
-    }
-    if (k->is_loaded()) {
-      select_different_registers(obj, dst, k_RInfo, klass_RInfo);
-    } else {
-      Rtmp1 = op->tmp3()->as_register();
-      select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1);
-    }
-
-    assert_different_registers(obj, k_RInfo, klass_RInfo);
-    if (!k->is_loaded()) {
-      jobject2reg_with_patching(k_RInfo, op->info_for_patch());
-    } else {
-#ifdef _LP64
-      __ movoop(k_RInfo, k->constant_encoding());
-#else
-      k_RInfo = noreg;
-#endif // _LP64
-    }
-    assert(obj != k_RInfo, "must be different");
-    __ cmpptr(obj, (int32_t)NULL_WORD);
-    if (op->profiled_method() != NULL) {
-      ciMethod* method = op->profiled_method();
-      int bci          = op->profiled_bci();
-
-      Label profile_done;
-      __ jcc(Assembler::notEqual, profile_done);
-      // Object is null; update methodDataOop
-      ciMethodData* md = method->method_data();
-      if (md == NULL) {
-        bailout("out of memory building methodDataOop");
-        return;
-      }
-      ciProfileData* data = md->bci_to_data(bci);
-      assert(data != NULL,       "need data for checkcast");
-      assert(data->is_BitData(), "need BitData for checkcast");
-      Register mdo  = klass_RInfo;
-      __ movoop(mdo, md->constant_encoding());
-      Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset()));
-      int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant());
-      __ orl(data_addr, header_bits);
-      __ jmp(done);
-      __ bind(profile_done);
-    } else {
-      __ jcc(Assembler::equal, done);
-    }
-    __ verify_oop(obj);
-
-    if (op->fast_check()) {
-      // get object classo
-      // not a safepoint as obj null check happens earlier
-      if (k->is_loaded()) {
-#ifdef _LP64
-        __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
-#else
-        __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
-#endif // _LP64
-      } else {
-        __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
-
-      }
-      __ jcc(Assembler::notEqual, *stub->entry());
-      __ bind(done);
-    } else {
-      // get object class
-      // not a safepoint as obj null check happens earlier
-      __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
-      if (k->is_loaded()) {
-        // See if we get an immediate positive hit
-#ifdef _LP64
-        __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset()));
-#else
-        __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding());
-#endif // _LP64
-        if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) {
-          __ jcc(Assembler::notEqual, *stub->entry());
-        } else {
-          // See if we get an immediate positive hit
-          __ jcc(Assembler::equal, done);
-          // check for self
-#ifdef _LP64
-          __ cmpptr(klass_RInfo, k_RInfo);
-#else
-          __ cmpoop(klass_RInfo, k->constant_encoding());
-#endif // _LP64
-          __ jcc(Assembler::equal, done);
-
-          __ push(klass_RInfo);
-#ifdef _LP64
-          __ push(k_RInfo);
-#else
-          __ pushoop(k->constant_encoding());
-#endif // _LP64
-          __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
-          __ pop(klass_RInfo);
-          __ pop(klass_RInfo);
-          // result is a boolean
-          __ cmpl(klass_RInfo, 0);
-          __ jcc(Assembler::equal, *stub->entry());
-        }
-        __ bind(done);
-      } else {
-        // perform the fast part of the checking logic
-        __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, stub->entry(), NULL);
-        // call out-of-line instance of __ check_klass_subtype_slow_path(...):
-        __ push(klass_RInfo);
-        __ push(k_RInfo);
-        __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
-        __ pop(klass_RInfo);
-        __ pop(k_RInfo);
-        // result is a boolean
-        __ cmpl(k_RInfo, 0);
-        __ jcc(Assembler::equal, *stub->entry());
-        __ bind(done);
-      }
-
-    }
-    if (dst != obj) {
-      __ mov(dst, obj);
-    }
   } else if (code == lir_instanceof) {
     Register obj = op->object()->as_register();
     Register k_RInfo = op->tmp1()->as_register();
@@ -1922,7 +1975,6 @@
   }
 }
 
-
 void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) {
   Assembler::Condition acond, ncond;
   switch (condition) {
@@ -3253,13 +3305,13 @@
   // Perform additional virtual call profiling for invokevirtual and
   // invokeinterface bytecodes
   if ((bc == Bytecodes::_invokevirtual || bc == Bytecodes::_invokeinterface) &&
-      Tier1ProfileVirtualCalls) {
+      C1ProfileVirtualCalls) {
     assert(op->recv()->is_single_cpu(), "recv must be allocated");
     Register recv = op->recv()->as_register();
     assert_different_registers(mdo, recv);
     assert(data->is_VirtualCallData(), "need VirtualCallData for virtual calls");
     ciKlass* known_klass = op->known_holder();
-    if (Tier1OptimizeVirtualCallProfiling && known_klass != NULL) {
+    if (C1OptimizeVirtualCallProfiling && known_klass != NULL) {
       // We know the type that will be seen at this call site; we can
       // statically update the methodDataOop rather than needing to do
       // dynamic tests on the receiver type
@@ -3272,7 +3324,7 @@
         ciKlass* receiver = vc_data->receiver(i);
         if (known_klass->equals(receiver)) {
           Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
-          __ addl(data_addr, DataLayout::counter_increment);
+          __ addptr(data_addr, DataLayout::counter_increment);
           return;
         }
       }
@@ -3288,49 +3340,26 @@
           Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)));
           __ movoop(recv_addr, known_klass->constant_encoding());
           Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
-          __ addl(data_addr, DataLayout::counter_increment);
+          __ addptr(data_addr, DataLayout::counter_increment);
           return;
         }
       }
     } else {
       __ movptr(recv, Address(recv, oopDesc::klass_offset_in_bytes()));
       Label update_done;
-      uint i;
-      for (i = 0; i < VirtualCallData::row_limit(); i++) {
-        Label next_test;
-        // See if the receiver is receiver[n].
-        __ cmpptr(recv, Address(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))));
-        __ jcc(Assembler::notEqual, next_test);
-        Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
-        __ addl(data_addr, DataLayout::counter_increment);
-        __ jmp(update_done);
-        __ bind(next_test);
-      }
-
-      // Didn't find receiver; find next empty slot and fill it in
-      for (i = 0; i < VirtualCallData::row_limit(); i++) {
-        Label next_test;
-        Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)));
-        __ cmpptr(recv_addr, (int32_t)NULL_WORD);
-        __ jcc(Assembler::notEqual, next_test);
-        __ movptr(recv_addr, recv);
-        __ movl(Address(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))), DataLayout::counter_increment);
-        __ jmp(update_done);
-        __ bind(next_test);
-      }
+      type_profile_helper(mdo, md, data, recv, &update_done);
       // Receiver did not match any saved receiver and there is no empty row for it.
       // Increment total counter to indicate polymorphic case.
-      __ addl(counter_addr, DataLayout::counter_increment);
+      __ addptr(counter_addr, DataLayout::counter_increment);
 
       __ bind(update_done);
     }
   } else {
     // Static call
-    __ addl(counter_addr, DataLayout::counter_increment);
+    __ addptr(counter_addr, DataLayout::counter_increment);
   }
 }
 
-
 void LIR_Assembler::emit_delay(LIR_OpDelay*) {
   Unimplemented();
 }