Move Method shorty to managed heap

Change-Id: Iafd05502b498c823063d0603915a92db8c95f060
diff --git a/src/check_jni.cc b/src/check_jni.cc
index 0486284..38f47dc 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -446,7 +446,7 @@
   void checkSig(jmethodID mid, const char* expectedType, bool isStatic) {
     ScopedJniThreadState ts(mEnv);
     const Method* m = DecodeMethod(ts, mid);
-    if (*expectedType != m->GetShorty()[0]) {
+    if (*expectedType != m->GetShorty()->CharAt(0)) {
       LOG(ERROR) << "JNI ERROR: expected return type '" << *expectedType << "' calling " << PrettyMethod(m);
       JniAbort();
     } else if (isStatic && !m->IsStatic()) {
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 6d5c643..c81df8d 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -886,7 +886,7 @@
   dst->SetProtoIdx(method_id.proto_idx_);
   dst->SetCodeItemOffset(src.code_off_);
   const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
-  dst->SetShorty(shorty);
+  dst->SetShorty(String::AllocFromModifiedUtf8(shorty));
   dst->SetAccessFlags(src.access_flags_);
   dst->SetReturnTypeIdx(dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_);
 
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index cb1cd8d..c3bb4c3 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -512,6 +512,7 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_strings_),                    "shadow$_dex_cache_strings_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, invoke_stub_array_),                    "shadow$_invoke_stub_array_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, mapping_table_),                        "shadow$_mapping_table_"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, shorty_),                               "shadow$_shorty_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, signature_),                            "shadow$_signature_"));
 
     // alphabetical 32-bit
@@ -531,7 +532,6 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, num_registers_),                        "shadow$_num_registers_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, proto_idx_),                            "shadow$_proto_idx_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, return_pc_offset_in_bytes_),            "shadow$_return_pc_offset_in_bytes_"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, shorty_),                               "shadow$_shorty_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_slot_),                            "slot"));
   };
 };
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index 8bbf659..aaec17b 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -106,9 +106,9 @@
             // Skip past "this"
             sReg++;
         }
-        const art::StringPiece& shorty = cUnit->method->GetShorty();
-        for (int i = 1; i < shorty.size(); i++) {
-            char arg = shorty[i];
+        String* shorty = cUnit->method->GetShorty();
+        for (int i = 1; i < shorty->GetLength(); i++) {
+            char arg = shorty->CharAt(i);
             // Is it wide?
             if ((arg == 'D') || (arg == 'J')) {
                 cUnit->regLocation[sReg].wide = true;
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 2ea6f76..c60dc24 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -123,9 +123,9 @@
 byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, va_list ap) {
   size_t num_bytes = method->NumArgArrayBytes();
   UniquePtr<byte[]> arg_array(new byte[num_bytes]);
-  const StringPiece& shorty = method->GetShorty();
-  for (int i = 1, offset = 0; i < shorty.size(); ++i) {
-    switch (shorty[i]) {
+  String* shorty = method->GetShorty();
+  for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
+    switch (shorty->CharAt(i)) {
       case 'Z':
       case 'B':
       case 'C':
@@ -160,9 +160,9 @@
 byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, jvalue* args) {
   size_t num_bytes = method->NumArgArrayBytes();
   UniquePtr<byte[]> arg_array(new byte[num_bytes]);
-  const StringPiece& shorty = method->GetShorty();
-  for (int i = 1, offset = 0; i < shorty.size(); ++i) {
-    switch (shorty[i]) {
+  String* shorty = method->GetShorty();
+  for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
+    switch (shorty->CharAt(i)) {
       case 'Z':
       case 'B':
       case 'C':
diff --git a/src/jni_internal_arm.cc b/src/jni_internal_arm.cc
index ed42c12..65dc380 100644
--- a/src/jni_internal_arm.cc
+++ b/src/jni_internal_arm.cc
@@ -101,7 +101,7 @@
   __ blx(IP);
 
   // If the method returns a value, store it to the result pointer.
-  char ch = method->GetShorty()[0];
+  char ch = method->GetShorty()->CharAt(0);
   if (ch != 'V') {
     // Load the result JValue pointer of the stub caller's out args.
     __ LoadFromOffset(kLoadWord, IP, SP, frame_size);
diff --git a/src/jni_internal_x86.cc b/src/jni_internal_x86.cc
index a6917d4..a096da0 100644
--- a/src/jni_internal_x86.cc
+++ b/src/jni_internal_x86.cc
@@ -57,7 +57,7 @@
 
   // pop arguments and padding up to saved EDI
   __ addl(ESP, Immediate(frame_size + pad_size - kPointerSize));
-  char ch = method->GetShorty()[0];
+  char ch = method->GetShorty()->CharAt(0);
   if (ch != 'V') {
     // Load the result JValue pointer.
     __ movl(EDI, Address(ESP, 24));
diff --git a/src/object.cc b/src/object.cc
index c66791b..6cb6d98 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -359,10 +359,10 @@
 }
 
 size_t Method::NumArgArrayBytes() const {
-  const StringPiece& shorty = GetShorty();
+  String* shorty = GetShorty();
   size_t num_bytes = 0;
-  for (int i = 1; i < shorty.length(); ++i) {
-    char ch = shorty[i];
+  for (int i = 1; i < shorty->GetLength(); ++i) {
+    char ch = shorty->CharAt(i);
     if (ch == 'D' || ch == 'J') {
       num_bytes += 8;
     } else if (ch == 'L') {
@@ -376,13 +376,20 @@
   return num_bytes;
 }
 
+size_t Method::NumArgs() const {
+  // "1 +" because the first in Args is the receiver.
+  // "- 1" because we don't count the return type.
+  return (IsStatic() ? 0 : 1) + GetShorty()->GetLength() - 1;
+}
+
 // The number of reference arguments to this method including implicit this
 // pointer
 size_t Method::NumReferenceArgs() const {
-  const StringPiece& shorty = GetShorty();
+  String* shorty = GetShorty();
   size_t result = IsStatic() ? 0 : 1;  // The implicit this pointer.
-  for (int i = 1; i < shorty.length(); i++) {
-    if ((shorty[i] == 'L') || (shorty[i] == '[')) {
+  for (int i = 1; i < shorty->GetLength(); i++) {
+    char ch = shorty->CharAt(i);
+    if ((ch == 'L') || (ch == '[')) {
       result++;
     }
   }
@@ -391,10 +398,11 @@
 
 // The number of long or double arguments
 size_t Method::NumLongOrDoubleArgs() const {
-  const StringPiece& shorty = GetShorty();
+  String* shorty = GetShorty();
   size_t result = 0;
-  for (int i = 1; i < shorty.length(); i++) {
-    if ((shorty[i] == 'D') || (shorty[i] == 'J')) {
+  for (int i = 1; i < shorty->GetLength(); i++) {
+    char ch = shorty->CharAt(i);
+    if ((ch == 'D') || (ch == 'J')) {
       result++;
     }
   }
@@ -409,7 +417,7 @@
   } else if (param == 0) {
     return true;  // this argument
   }
-  return GetShorty()[param] == 'L';
+  return GetShorty()->CharAt(param) == 'L';
 }
 
 // Is the given method parameter a long or double?
@@ -420,7 +428,8 @@
   } else if (param == 0) {
     return false;  // this argument
   }
-  return (GetShorty()[param] == 'J') || (GetShorty()[param] == 'D');
+  char ch = GetShorty()->CharAt(param);
+  return (ch == 'J' || ch == 'D');
 }
 
 static size_t ShortyCharToSize(char x) {
@@ -441,11 +450,11 @@
   } else if (param == 0) {
     return kPointerSize;  // this argument
   }
-  return ShortyCharToSize(GetShorty()[param]);
+  return ShortyCharToSize(GetShorty()->CharAt(param));
 }
 
 size_t Method::ReturnSize() const {
-  return ShortyCharToSize(GetShorty()[0]);
+  return ShortyCharToSize(GetShorty()->CharAt(0));
 }
 
 bool Method::HasSameNameAndDescriptor(const Method* that) const {
diff --git a/src/object.h b/src/object.h
index bc9ec7e..01ed500 100644
--- a/src/object.h
+++ b/src/object.h
@@ -643,14 +643,9 @@
 
   void SetName(String* new_name);
 
-  const char* GetShorty() const;
+  String* GetShorty() const;
 
-  void SetShorty(const char* new_shorty) {
-    DCHECK(NULL == GetFieldPtr<const char*>(
-        OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false));
-    DCHECK_LE(1u, strlen(new_shorty));
-    SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Method, shorty_), new_shorty, false);
-  }
+  void SetShorty(String* new_shorty);
 
   const String* GetSignature() const;
 
@@ -838,11 +833,7 @@
   //       need to deal with it.
   //
   // The number of Args that should be supplied to this method
-  size_t NumArgs() const {
-    // "1 +" because the first in Args is the receiver.
-    // "- 1" because we don't count the return type.
-    return (IsStatic() ? 0 : 1) + strlen(GetShorty()) - 1;
-  }
+  size_t NumArgs() const;
 
   // The number of reference arguments to this method including implicit this
   // pointer.
@@ -1039,6 +1030,9 @@
   // Storage for mapping_table_
   const ByteArray* mapping_table_;
 
+  // The short-form method descriptor string.
+  String* shorty_;
+
   // The method descriptor.  This represents the parameters a method
   // takes and value it returns.  This string is a list of the type
   // descriptors for the parameters enclosed in parenthesis followed
@@ -1102,9 +1096,6 @@
   // Offset of return PC within frame for compiled code (in bytes)
   size_t return_pc_offset_in_bytes_;
 
-  // The short-form method descriptor string. TODO: make String*
-  const char* shorty_;
-
   uint32_t java_slot_;
 
   static Class* java_lang_reflect_Method_;
@@ -2594,12 +2585,19 @@
 
 }
 
-inline const char* Method::GetShorty() const {
+inline String* Method::GetShorty() const {
   DCHECK(GetDeclaringClass()->IsLoaded());
-  return GetFieldPtr<const char*>(
+  return GetFieldObject<String*>(
       OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false);
 }
 
+inline void Method::SetShorty(String* new_shorty) {
+  DCHECK(NULL == GetFieldObject<String*>(
+      OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false));
+  DCHECK_LE(1, new_shorty->GetLength());
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, shorty_), new_shorty, false);
+}
+
 inline const String* Method::GetSignature() const {
   DCHECK(GetDeclaringClass()->IsLoaded());
   const String* result =