changeset 18133:5c1bd485c54b

Truffle: fix deoptimization of int[] with double/long values
author Andreas Woess <andreas.woess@jku.at>
date Tue, 21 Oct 2014 02:31:32 +0200
parents b00fc4dc6dc2
children 6a2f814224b1
files src/share/vm/runtime/deoptimization.cpp
diffstat 1 files changed, 35 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/runtime/deoptimization.cpp	Mon Oct 20 16:22:18 2014 -0700
+++ b/src/share/vm/runtime/deoptimization.cpp	Tue Oct 21 02:31:32 2014 +0200
@@ -832,11 +832,43 @@
     }
 
     // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
-    case T_INT: case T_FLOAT: // 4 bytes.
+    case T_INT: case T_FLOAT: { // 4 bytes.
       assert(value->type() == T_INT, "Agreement.");
-      val = value->get_int();
-      obj->int_at_put(index, (jint)*((jint*)&val));
+      bool big_value = false;
+      if (i + 1 < sv->field_size() && type == T_INT) {
+        if (sv->field_at(i)->is_location()) {
+          Location::Type type = ((LocationValue*) sv->field_at(i))->location().type();
+          if (type == Location::dbl || type == Location::lng) {
+            big_value = true;
+          }
+        } else if (sv->field_at(i)->is_constant_int()) {
+          ScopeValue* next_scope_field = sv->field_at(i + 1);
+          if (next_scope_field->is_constant_long() || next_scope_field->is_constant_double()) {
+            big_value = true;
+          }
+        }
+      }
+
+      if (big_value) {
+        StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++i));
+  #ifdef _LP64
+        jlong res = (jlong)low->get_int();
+  #else
+  #ifdef SPARC
+        // For SPARC we have to swap high and low words.
+        jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
+  #else
+        jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
+  #endif //SPARC
+  #endif
+        obj->int_at_put(index, (jint)*((jint*)&res));
+        obj->int_at_put(++index, (jint)*(((jint*)&res) + 1));
+      } else {
+        val = value->get_int();
+        obj->int_at_put(index, (jint)*((jint*)&val));
+      }
       break;
+    }
 
     case T_SHORT: case T_CHAR: // 2 bytes
       assert(value->type() == T_INT, "Agreement.");