< prev index next >

src/hotspot/share/c1/c1_LIRGenerator.cpp

Print this page

@@ -32,10 +32,12 @@
 #include "c1/c1_ValueStack.hpp"
 #include "ci/ciArrayKlass.hpp"
 #include "ci/ciInstance.hpp"
 #include "ci/ciObjArray.hpp"
 #include "ci/ciUtilities.hpp"
+#include "ci/ciValueArrayKlass.hpp"
+#include "ci/ciValueKlass.hpp"
 #include "gc/shared/barrierSet.hpp"
 #include "gc/shared/c1/barrierSetC1.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"

@@ -1546,16 +1548,89 @@
 
   access_store_at(decorators, field_type, object, LIR_OprFact::intConst(x->offset()),
                   value.result(), info != NULL ? new CodeEmitInfo(info) : NULL, info);
 }
 
+// FIXME -- I can't find any other way to pass an address to access_load_at().
+class TempResolvedAddress: public Instruction {
+ public:
+  TempResolvedAddress(ValueType* type, LIR_Opr addr) : Instruction(type) {
+    set_operand(addr);
+  }
+  virtual void input_values_do(ValueVisitor*) {}
+  virtual void visit(InstructionVisitor* v)   {}
+  virtual const char* name() const  { return "TempResolvedAddress"; }
+};
+
+void LIRGenerator::access_flattened_array(bool is_load, LIRItem& array, LIRItem& index, LIRItem& obj_item) {
+  // Find the starting address of the source (inside the array)
+  ciType* array_type = array.value()->declared_type();
+  ciValueArrayKlass* value_array_klass = array_type->as_value_array_klass();
+  ciValueKlass* elem_klass = value_array_klass->element_klass()->as_value_klass();
+  int array_header_size = value_array_klass->array_header_in_bytes();
+
+#ifndef _LP64
+  LIR_Opr index_op = index.result();
+#else
+  LIR_Opr index_op = new_register(T_LONG);
+  __ convert(Bytecodes::_i2l, index.result(), index_op);
+#endif
+  // Need to shift manually, as LIR_Address can scale only up to 3.
+  __ shift_left(index_op, value_array_klass->log2_element_size(), index_op);
+
+  LIR_Opr elm_op = new_pointer_register();
+  LIR_Address* elm_address = new LIR_Address(array.result(), index_op, array_header_size, T_ADDRESS);
+  __ leal(LIR_OprFact::address(elm_address), elm_op);
+
+  for (int i = 0; i < elem_klass->nof_nonstatic_fields(); i++) {
+    ciField* inner_field = elem_klass->nonstatic_field_at(i);
+    int obj_offset = inner_field->offset();
+    int elm_offset = obj_offset - elem_klass->first_field_offset(); // object header is not stored in array.
+
+    BasicType field_type = inner_field->type()->basic_type();
+    switch (field_type) {
+    case T_BYTE:
+    case T_BOOLEAN:
+    case T_SHORT:
+    case T_CHAR:
+     field_type = T_INT;
+      break;
+    default:
+      break;
+    }
+
+    LIR_Opr temp = new_register(field_type);
+    TempResolvedAddress* elm_resolved_addr = new TempResolvedAddress(as_ValueType(field_type), elm_op);
+    LIRItem elm_item(elm_resolved_addr, this);
+
+    DecoratorSet decorators = IN_HEAP;
+    if (is_load) {
+      access_load_at(decorators, field_type,
+                     elm_item, LIR_OprFact::intConst(elm_offset), temp,
+                     NULL, NULL);
+      access_store_at(decorators, field_type,
+                      obj_item, LIR_OprFact::intConst(obj_offset), temp,
+                      NULL, NULL);
+    } else {
+    access_load_at(decorators, field_type,
+                   obj_item, LIR_OprFact::intConst(obj_offset), temp,
+                   NULL, NULL);
+    access_store_at(decorators, field_type,
+                    elm_item, LIR_OprFact::intConst(elm_offset), temp,
+                    NULL, NULL);
+    }
+  }
+}
+
 void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
   assert(x->is_pinned(),"");
+  bool is_flattened = x->array()->is_flattened_array();
   bool needs_range_check = x->compute_needs_range_check();
   bool use_length = x->length() != NULL;
   bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
-  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
+  bool needs_store_check = obj_store && !is_flattened &&
+                                        (x->value()->as_Constant() == NULL ||
                                          !get_jobject_constant(x->value())->is_null_object() ||
                                          x->should_profile());
 
   LIRItem array(x->array(), this);
   LIRItem index(x->index(), this);

@@ -1568,11 +1643,12 @@
   if (use_length && needs_range_check) {
     length.set_instruction(x->length());
     length.load_item();
 
   }
-  if (needs_store_check || x->check_boolean()) {
+  
+  if (needs_store_check || x->check_boolean() || is_flattened) {
     value.load_item();
   } else {
     value.load_for_store(x->elt_type());
   }
 

@@ -1601,17 +1677,22 @@
   if (GenerateArrayStoreCheck && needs_store_check) {
     CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
     array_store_check(value.result(), array.result(), store_check_info, x->profiled_method(), x->profiled_bci());
   }
 
+  if (is_flattened) {
+    index.load_item();
+    access_flattened_array(false, array, index, value); 
+  } else {
   DecoratorSet decorators = IN_HEAP | IS_ARRAY;
   if (x->check_boolean()) {
     decorators |= C1_MASK_BOOLEAN;
   }
 
   access_store_at(decorators, x->elt_type(), array, index.result(), value.result(),
                   NULL, null_check_info);
+  }
 }
 
 void LIRGenerator::access_load_at(DecoratorSet decorators, BasicType type,
                                   LIRItem& base, LIR_Opr offset, LIR_Opr result,
                                   CodeEmitInfo* patch_info, CodeEmitInfo* load_emit_info) {

@@ -1868,16 +1949,24 @@
       // The range check performs the null check, so clear it out for the load
       null_check_info = NULL;
     }
   }
 
-  DecoratorSet decorators = IN_HEAP | IS_ARRAY;
+  if (x->array()->is_flattened_array()) {
+    // Find the destination address (of the NewValueTypeInstance)
+    LIR_Opr obj = x->vt()->operand();
+    LIRItem obj_item(x->vt(), this);
 
+    access_flattened_array(true, array, index, obj_item);
+    set_no_result(x);
+  } else {
+    DecoratorSet decorators = IN_HEAP | IS_ARRAY;
   LIR_Opr result = rlock_result(x, x->elt_type());
   access_load_at(decorators, x->elt_type(),
                  array, index.result(), result,
                  NULL, null_check_info);
+  }
 }
 
 
 void LIRGenerator::do_NullCheck(NullCheck* x) {
   if (x->can_trap()) {

@@ -2733,10 +2822,11 @@
     if (loc->is_register()) {
       param->load_item_force(loc);
     } else {
       LIR_Address* addr = loc->as_address_ptr();
       param->load_for_store(addr->type());
+      assert(addr->type() != T_VALUETYPE, "not supported yet");
       if (addr->type() == T_OBJECT) {
         __ move_wide(param->result(), addr);
       } else
         if (addr->type() == T_LONG || addr->type() == T_DOUBLE) {
           __ unaligned_move(param->result(), addr);
< prev index next >