changeset 21982:861108f5408e

Support derived references in HotSpotReferenceMap.
author Roland Schatz <roland.schatz@oracle.com>
date Tue, 16 Jun 2015 16:30:34 +0200
parents 007e88ccbba9
children 964677af4a3c
files jvmci/com.oracle.jvmci.code/src/com/oracle/jvmci/code/Location.java jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotReferenceMap.java jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/LIRKind.java src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/jvmci/jvmciCodeInstaller.cpp src/share/vm/jvmci/jvmciJavaAccess.hpp
diffstat 7 files changed, 188 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/com.oracle.jvmci.code/src/com/oracle/jvmci/code/Location.java	Tue Jun 16 16:30:34 2015 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.jvmci.code;
+
+/**
+ * Represents a location where a value can be stored. This can be either a {@link Register} or a
+ * stack slot.
+ */
+public final class Location {
+
+    public final Register reg;
+    public final int offset;
+    public final boolean addFrameSize;
+
+    private Location(Register reg, int offset, boolean addFrameSize) {
+        this.reg = reg;
+        this.offset = offset;
+        this.addFrameSize = addFrameSize;
+    }
+
+    /**
+     * Create a {@link Location} for a register.
+     */
+    public static Location register(Register reg) {
+        return new Location(reg, 0, false);
+    }
+
+    /**
+     * Create a {@link Location} for a vector subregister.
+     *
+     * @param reg the {@link Register vector register}
+     * @param offset the offset in bytes into the vector register
+     */
+    public static Location subregister(Register reg, int offset) {
+        return new Location(reg, offset, false);
+    }
+
+    /**
+     * Create a {@link Location} for a stack slot.
+     */
+    public static Location stack(int offset, boolean addFrameSize) {
+        return new Location(null, offset, addFrameSize);
+    }
+
+    public boolean isRegister() {
+        return reg != null;
+    }
+
+    public boolean isStack() {
+        return reg == null;
+    }
+}
--- a/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotReferenceMap.java	Tue Jun 16 12:19:53 2015 +0200
+++ b/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotReferenceMap.java	Tue Jun 16 16:30:34 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, 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
@@ -27,28 +27,35 @@
 import java.util.*;
 
 import com.oracle.jvmci.code.*;
+import com.oracle.jvmci.common.*;
 import com.oracle.jvmci.meta.*;
 
 public final class HotSpotReferenceMap extends ReferenceMap {
 
-    private Value[] objects;
-    private int[] bytesPerElement;
+    private Location[] objects;
+    private Location[] derivedBase;
+    private int[] sizeInBytes;
     private int maxRegisterSize;
+
     private ArrayList<Value> objectValues;
+    private int objectCount;
 
     private final TargetDescription target;
 
     public HotSpotReferenceMap(TargetDescription target) {
         this.target = target;
-        this.objects = Value.NO_VALUES;
+        this.objectCount = 0;
     }
 
     @Override
     public void reset() {
+        objects = null;
+        derivedBase = null;
+        sizeInBytes = null;
+        maxRegisterSize = 0;
+
         objectValues = new ArrayList<>();
-        objects = Value.NO_VALUES;
-        bytesPerElement = null;
-        maxRegisterSize = 0;
+        objectCount = 0;
     }
 
     @Override
@@ -59,6 +66,11 @@
         LIRKind lirKind = v.getLIRKind();
         if (!lirKind.isValue()) {
             objectValues.add(v);
+            if (lirKind.isDerivedReference()) {
+                objectCount++;
+            } else {
+                objectCount += lirKind.getReferenceCount();
+            }
         }
         if (isRegister(v)) {
             int size = target.getSizeInBytes(lirKind.getPlatformKind());
@@ -70,12 +82,31 @@
 
     @Override
     public void finish() {
-        objects = objectValues.toArray(new Value[objectValues.size()]);
-        this.bytesPerElement = new int[objects.length];
-        for (int i = 0; i < objects.length; i++) {
-            bytesPerElement[i] = bytesPerElement(objects[i].getLIRKind());
+        objects = new Location[objectCount];
+        derivedBase = new Location[objectCount];
+        sizeInBytes = new int[objectCount];
+
+        int idx = 0;
+        for (Value obj : objectValues) {
+            LIRKind kind = obj.getLIRKind();
+            int bytes = bytesPerElement(kind);
+            if (kind.isDerivedReference()) {
+                throw JVMCIError.unimplemented("derived references not yet implemented");
+            } else {
+                for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) {
+                    if (kind.isReference(i)) {
+                        objects[idx] = toLocation(obj, i * bytes);
+                        derivedBase[idx] = null;
+                        sizeInBytes[idx] = bytes;
+                        idx++;
+                    }
+                }
+            }
         }
+
+        assert idx == objectCount;
         objectValues = null;
+        objectCount = 0;
     }
 
     private int bytesPerElement(LIRKind kind) {
@@ -83,6 +114,15 @@
         return target.getSizeInBytes(platformKind) / platformKind.getVectorLength();
     }
 
+    private static Location toLocation(Value v, int offset) {
+        if (isRegister(v)) {
+            return Location.subregister(asRegister(v), offset);
+        } else {
+            StackSlot s = asStackSlot(v);
+            return Location.stack(s.getRawOffset() + offset, s.getRawAddFrameSize());
+        }
+    }
+
     @Override
     public int hashCode() {
         throw new UnsupportedOperationException();
--- a/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/LIRKind.java	Tue Jun 16 12:19:53 2015 +0200
+++ b/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/LIRKind.java	Tue Jun 16 16:30:34 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -262,6 +262,11 @@
         return referenceMask == DERIVED_REFERENCE;
     }
 
+    public int getReferenceCount() {
+        assert !isDerivedReference();
+        return Integer.bitCount(referenceMask);
+    }
+
     /**
      * Check whether the {@code idx}th part of this value is a reference that must be tracked at
      * safepoints.
--- a/src/share/vm/classfile/systemDictionary.hpp	Tue Jun 16 12:19:53 2015 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Tue Jun 16 16:30:34 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -232,6 +232,7 @@
   JVMCI_ONLY(do_klass(CompilationResult_Site_klass,          com_oracle_jvmci_code_CompilationResult_Site,                 Jvmci)) \
   JVMCI_ONLY(do_klass(InfopointReason_klass,                 com_oracle_jvmci_code_InfopointReason,                        Jvmci)) \
   JVMCI_ONLY(do_klass(InstalledCode_klass,                   com_oracle_jvmci_code_InstalledCode,                          Jvmci)) \
+  JVMCI_ONLY(do_klass(code_Location_klass,                   com_oracle_jvmci_code_Location,                               Jvmci)) \
   JVMCI_ONLY(do_klass(code_Register_klass,                   com_oracle_jvmci_code_Register,                               Jvmci)) \
   JVMCI_ONLY(do_klass(RegisterValue_klass,                   com_oracle_jvmci_code_RegisterValue,                          Jvmci)) \
   JVMCI_ONLY(do_klass(RegisterCategory_klass,                com_oracle_jvmci_code_Register_RegisterCategory,              Jvmci)) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 16 12:19:53 2015 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 16 16:30:34 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -344,6 +344,7 @@
   JVMCI_ONLY(template(com_oracle_jvmci_code_BytecodeFrame,                      "com/oracle/jvmci/code/BytecodeFrame"))                           \
   JVMCI_ONLY(template(com_oracle_jvmci_code_BytecodePosition,                   "com/oracle/jvmci/code/BytecodePosition"))                        \
   JVMCI_ONLY(template(com_oracle_jvmci_code_DebugInfo,                          "com/oracle/jvmci/code/DebugInfo"))                               \
+  JVMCI_ONLY(template(com_oracle_jvmci_code_Location,                           "com/oracle/jvmci/code/Location"))                                \
   JVMCI_ONLY(template(com_oracle_jvmci_code_Register,                           "com/oracle/jvmci/code/Register"))                                \
   JVMCI_ONLY(template(com_oracle_jvmci_code_RegisterValue,                      "com/oracle/jvmci/code/RegisterValue"))                           \
   JVMCI_ONLY(template(com_oracle_jvmci_code_Register_RegisterCategory,          "com/oracle/jvmci/code/Register$RegisterCategory"))               \
--- a/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Tue Jun 16 12:19:53 2015 +0200
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Tue Jun 16 16:30:34 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, 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
@@ -69,6 +69,31 @@
   return asMethod(HotSpotResolvedJavaMethodImpl::metaspaceMethod(hotspot_method));
 }
 
+VMReg getVMRegFromLocation(oop location, int total_frame_size) {
+  oop reg = code_Location::reg(location);
+  jint offset = code_Location::offset(location);
+
+  if (reg != NULL) {
+    // register
+    jint number = code_Register::number(reg);
+    VMReg vmReg = CodeInstaller::get_hotspot_reg(number);
+    assert(offset % 4 == 0, "must be aligned");
+    return vmReg->next(offset / 4);
+  } else {
+    // stack slot
+#ifdef TARGET_ARCH_sparc
+    if(offset >= 0) {
+      offset += 128;
+    }
+#endif
+    if (code_Location::addFrameSize(location)) {
+      offset += total_frame_size;
+    }
+    assert(offset % 4 == 0, "must be aligned");
+    return VMRegImpl::stack2reg(offset / 4);
+  }
+}
+
 // creates a HotSpot oop map out of the byte arrays provided by DebugInfo
 OopMap* CodeInstaller::create_oop_map(oop debug_info) {
   oop reference_map = DebugInfo::referenceMap(debug_info);
@@ -77,53 +102,29 @@
   }
   OopMap* map = new OopMap(_total_frame_size, _parameter_count);
   objArrayOop objects = HotSpotReferenceMap::objects(reference_map);
-  typeArrayOop bytesPerArray = HotSpotReferenceMap::bytesPerElement(reference_map);
+  objArrayOop derivedBase = HotSpotReferenceMap::derivedBase(reference_map);
+  typeArrayOop sizeInBytes = HotSpotReferenceMap::sizeInBytes(reference_map);
   for (int i = 0; i < objects->length(); i++) {
-    oop value = objects->obj_at(i);
-    oop lirKind = AbstractValue::lirKind(value);
-    oop platformKind = LIRKind::platformKind(lirKind);
-    int bytesPerElement = bytesPerArray->int_at(i);
-    assert(bytesPerElement == 4 || bytesPerElement == 8, "wrong sizes");
-    jint referenceMask = LIRKind::referenceMask(lirKind);
-    assert(referenceMask != 0, "must be a reference type");
-    assert(referenceMask != -1, "must not be a derived reference type");
-    
-    VMReg vmReg;
-    if (value->is_a(RegisterValue::klass())) {
-      oop reg = RegisterValue::reg(value);
-      jint number = code_Register::number(reg);
-      vmReg = CodeInstaller::get_hotspot_reg(number);
-    } else if (value->is_a(StackSlot::klass())) {
-      jint offset = StackSlot::offset(value);
-#ifdef TARGET_ARCH_sparc
-      if(offset >= 0) {
-        offset += 128;
-      }
-#endif
-      if (StackSlot::addFrameSize(value)) {
-        offset += _total_frame_size;
-      }
-      assert(offset % 4 == 0, "must be aligned");
-      vmReg = VMRegImpl::stack2reg(offset / 4);
-    }
-      
-    int bit = 1;
-    while (referenceMask != 0) {
-      if (referenceMask & bit) {
-        if (bytesPerElement == 8) {
-          map->set_oop(vmReg);
-        } else {
-          map->set_narrowoop(vmReg);
-        }
-        referenceMask &= ~bit;
-      }
-      vmReg = vmReg->next();
-      if (bytesPerElement == 8) {
-        vmReg = vmReg->next();
-      }
-      bit <<= 1;
+    oop location = objects->obj_at(i);
+    oop baseLocation = derivedBase->obj_at(i);
+    int bytes = sizeInBytes->int_at(i);
+
+    VMReg vmReg = getVMRegFromLocation(location, _total_frame_size);
+    if (baseLocation != NULL) {
+      // derived oop
+      assert(bytes == 8, "derived oop can't be compressed");
+      VMReg baseReg = getVMRegFromLocation(baseLocation, _total_frame_size);
+      map->set_derived_oop(vmReg, baseReg);
+    } else if (bytes == 8) {
+      // wide oop
+      map->set_oop(vmReg);
+    } else {
+      // narrow oop
+      assert(bytes == 4, "wrong size");
+      map->set_narrowoop(vmReg);
     }
   }
+
   oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
   if (callee_save_info != NULL) {
     objArrayOop registers = RegisterSaveLayout::registers(callee_save_info);
--- a/src/share/vm/jvmci/jvmciJavaAccess.hpp	Tue Jun 16 12:19:53 2015 +0200
+++ b/src/share/vm/jvmci/jvmciJavaAccess.hpp	Tue Jun 16 16:30:34 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, 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
@@ -157,8 +157,9 @@
     objArrayOop_field(DebugInfo, virtualObjectMapping, "[Lcom/oracle/jvmci/meta/Value;")                                                                       \
   end_class                                                                                                                                                    \
   start_class(HotSpotReferenceMap)                                                                                                                             \
-    objArrayOop_field(HotSpotReferenceMap, objects, "[Lcom/oracle/jvmci/meta/Value;")                                                                          \
-    typeArrayOop_field(HotSpotReferenceMap, bytesPerElement, "[I")                                                                                             \
+    objArrayOop_field(HotSpotReferenceMap, objects, "[Lcom/oracle/jvmci/code/Location;")                                                                       \
+    objArrayOop_field(HotSpotReferenceMap, derivedBase, "[Lcom/oracle/jvmci/code/Location;")                                                                   \
+    typeArrayOop_field(HotSpotReferenceMap, sizeInBytes, "[I")                                                                                                 \
     int_field(HotSpotReferenceMap, maxRegisterSize)                                                                                                            \
   end_class                                                                                                                                                    \
   start_class(RegisterSaveLayout)                                                                                                                              \
@@ -221,6 +222,11 @@
   start_class(RegisterValue)                                                                                                                                   \
     oop_field(RegisterValue, reg, "Lcom/oracle/jvmci/code/Register;")                                                                                          \
   end_class                                                                                                                                                    \
+  start_class(code_Location)                                                                                                                                   \
+    oop_field(code_Location, reg, "Lcom/oracle/jvmci/code/Register;")                                                                                          \
+    int_field(code_Location, offset)                                                                                                                           \
+    boolean_field(code_Location, addFrameSize)                                                                                                                 \
+  end_class                                                                                                                                                    \
   start_class(code_Register)                                                                                                                                   \
     int_field(code_Register, number)                                                                                                                           \
     int_field(code_Register, encoding)                                                                                                                         \