1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "ci/ciField.hpp"
  26 #include "ci/ciValueKlass.hpp"
  27 #include "oops/fieldStreams.hpp"
  28 #include "oops/valueKlass.hpp"
  29 
  30 int ciValueKlass::compute_field_index_map() {
  31   assert(is_loaded(), "value class must be loaded to compute mapping of field indeces");
  32 
  33   if (_field_index_map != NULL) {
  34     return _field_index_map->length();
  35   }
  36 
  37   Arena* arena = CURRENT_ENV->arena();
  38   guarantee(has_nonstatic_fields(), "value types without fields currently not supported");
  39 
  40   // FIXME: Once it is possible to construct class hierarchies with value types.
  41   assert(!super()->has_nonstatic_fields(), "a value type must not inherit fields from its superclass");
  42 
  43   _field_index_map = new (arena) GrowableArray<int>(arena, nof_declared_nonstatic_fields(), 0, 0);
  44   GUARDED_VM_ENTRY(
  45     valueKlassHandle vklass_h(ValueKlass::cast(get_Klass()));
  46     methodHandle factory_h(vklass_h->factory_method());
  47     if (factory_h.is_null()) { // Value parameter mapping not defined
  48       for (JavaFieldStream fs(vklass_h); !fs.done(); fs.next()) {
  49         if (fs.access_flags().is_static()) {
  50           continue;
  51         }
  52         _field_index_map->append(fs.field_descriptor().index());
  53       }
  54     } else {
  55       int valuefactory_length = factory_h->constMethod()->valuefactory_parameter_mapping_length();
  56       assert(valuefactory_length == nof_declared_nonstatic_fields(),
  57              "value factory length must be the same as the number of nonstatic declared for the value type");
  58       for (int i = 0; i < nof_declared_nonstatic_fields(); i++) {
  59         _field_index_map->append(factory_h->constMethod()->valuefactory_parameter_mapping_start()[i].data.field_index);
  60       }
  61     }
  62   )
  63   return _field_index_map->length();
  64 }
  65 
  66 // Number of value type fields
  67 int ciValueKlass::field_count() {
  68   if (_field_index_map == NULL) {
  69     return compute_field_index_map();
  70   } else {
  71     return _field_index_map->length();
  72   }
  73 }
  74 
  75 // Size of value type fields in words
  76 int ciValueKlass::field_size() {
  77   int size = 0;
  78   for (int i = 0; i < field_count(); ++i) {
  79     size += field_type_by_index(i)->size();
  80   }
  81   return size;
  82 }
  83 
  84 // Returns the index of the field with the given offset. If the field at 'offset'
  85 // belongs to a flattened value type field, return the index of the field
  86 // in the flattened value type.
  87 int ciValueKlass::field_index_by_offset(int offset) {
  88   assert(contains_field_offset(offset), "invalid field offset");
  89   int best_offset = 0;
  90   int best_index = -1;
  91   // Search the field with the given offset
  92   for (int i = 0; i < field_count(); ++i) {
  93     int field_offset = field_offset_by_index(i);
  94     if (field_offset == offset) {
  95       // Exact match
  96       return i;
  97     } else if (field_offset < offset && field_offset > best_offset) {
  98       // No exact match. Save the index of the field with the closest offset that
  99       // is smaller than the given field offset. This index corresponds to the
 100       // flattened value type field that holds the field we are looking for.
 101       best_offset = field_offset;
 102       best_index = i;
 103     }
 104   }
 105   assert(best_index >= 0, "field not found");
 106   assert(best_offset == offset || field_type_by_index(best_index)->is_valuetype(), "offset should match for non-VTs");
 107   return best_index;
 108 }
 109 
 110 // Returns the field offset of the field with the given index
 111 int ciValueKlass::field_offset_by_index(int index) {
 112   if (_field_index_map == NULL) {
 113     compute_field_index_map();
 114   }
 115   GUARDED_VM_ENTRY(
 116     valueKlassHandle vklass_h(ValueKlass::cast(get_Klass()));
 117     return vklass_h->field_offset(_field_index_map->at(index));
 118   )
 119 }
 120 
 121 // Returns the field type of the field with the given index
 122 ciType* ciValueKlass::field_type_by_index(int index) {
 123   int offset = field_offset_by_index(index);
 124   VM_ENTRY_MARK;
 125   return get_field_type_by_offset(offset);
 126 }
 127 
 128 // Offset of the first field in the value type
 129 int ciValueKlass::first_field_offset() const {
 130   GUARDED_VM_ENTRY(
 131     valueKlassHandle vklass_h(ValueKlass::cast(get_Klass()));
 132     return vklass_h()->first_field_offset();
 133   )
 134 }
 135 
 136 // When passing field's fields as arguments, count the number of extra
 137 // argument slots that are needed
 138 int ciValueKlass::extra_value_args() {
 139   // -1 because we count the number of extra args
 140   int vt_extra = nof_nonstatic_fields() - 1;
 141   for (int j = 0; j < nof_nonstatic_fields(); j++) {
 142     ciField* f = nonstatic_field_at(j);
 143     BasicType bt = f->type()->basic_type();
 144     assert(bt != T_VALUETYPE, "embedded");
 145     if (bt == T_LONG || bt == T_DOUBLE) {
 146       vt_extra++;
 147     }
 148   }
 149   return vt_extra;
 150 }