Replace String CharArray with internal uint16_t array.

Summary of high level changes:
  - Adds compiler inliner support to identify string init methods
  - Adds compiler support (quick & optimizing) with new invoke code path
    that calls method off the thread pointer
  - Adds thread entrypoints for all string init methods
  - Adds map to verifier to log when receiver of string init has been
    copied to other registers. used by compiler and interpreter

Change-Id: I797b992a8feb566f9ad73060011ab6f51eb7ce01
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index b367cff..8f5a7d4 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -19,6 +19,7 @@
 
 #include "array.h"
 #include "class.h"
+#include "gc/heap-inl.h"
 #include "intern_table.h"
 #include "runtime.h"
 #include "string.h"
@@ -29,41 +30,147 @@
 namespace mirror {
 
 inline uint32_t String::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength + 51;
+  uint32_t vtable_entries = Object::kVTableLength + 52;
   return Class::ComputeClassSize(true, vtable_entries, 0, 1, 0, 1, 2);
 }
 
-inline uint16_t String::UncheckedCharAt(int32_t index) {
-  return GetCharArray()->Get(index + GetOffset());
-}
+// Sets string count in the allocation code path to ensure it is guarded by a CAS.
+class SetStringCountVisitor {
+ public:
+  explicit SetStringCountVisitor(int32_t count) : count_(count) {
+  }
 
-inline CharArray* String::GetCharArray() {
-  return GetFieldObject<CharArray>(ValueOffset());
-}
+  void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    // Avoid AsString as object is not yet in live bitmap or allocation stack.
+    String* string = down_cast<String*>(obj);
+    string->SetCount(count_);
+  }
 
-inline int32_t String::GetLength() {
-  int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_));
-  DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
-  return result;
-}
+ private:
+  const int32_t count_;
+};
 
-inline void String::SetArray(CharArray* new_array) {
-  // Array is invariant so use non-transactional mode. Also disable check as we may run inside
-  // a transaction.
-  DCHECK(new_array != nullptr);
-  SetFieldObject<false, false>(OFFSET_OF_OBJECT_MEMBER(String, array_), new_array);
-}
+// Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
+class SetStringCountAndBytesVisitor {
+ public:
+  SetStringCountAndBytesVisitor(int32_t count, uint8_t* src, int32_t high_byte)
+      : count_(count), src_(src), high_byte_(high_byte) {
+  }
+
+  void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    // Avoid AsString as object is not yet in live bitmap or allocation stack.
+    String* string = down_cast<String*>(obj);
+    string->SetCount(count_);
+    uint16_t* value = string->GetValue();
+    for (int i = 0; i < count_; i++) {
+      value[i] = high_byte_ + (src_[i] & 0xFF);
+    }
+  }
+
+ private:
+  const int32_t count_;
+  const uint8_t* const src_;
+  const int32_t high_byte_;
+};
+
+// Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
+class SetStringCountAndValueVisitor {
+ public:
+  SetStringCountAndValueVisitor(int32_t count, uint16_t* src) : count_(count), src_(src) {
+  }
+
+  void operator()(Object* obj, size_t usable_size) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    UNUSED(usable_size);
+    // Avoid AsString as object is not yet in live bitmap or allocation stack.
+    String* string = down_cast<String*>(obj);
+    string->SetCount(count_);
+    memcpy(string->GetValue(), src_, count_ * sizeof(uint16_t));
+  }
+
+ private:
+  const int32_t count_;
+  const uint16_t* const src_;
+};
 
 inline String* String::Intern() {
   return Runtime::Current()->GetInternTable()->InternWeak(this);
 }
 
+inline uint16_t String::CharAt(int32_t index) {
+  int32_t count = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_));
+  if (UNLIKELY((index < 0) || (index >= count))) {
+    Thread* self = Thread::Current();
+    self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
+                             "length=%i; index=%i", count, index);
+    return 0;
+  }
+  return GetValue()[index];
+}
+
+template<VerifyObjectFlags kVerifyFlags>
+inline size_t String::SizeOf() {
+  return sizeof(String) + (sizeof(uint16_t) * GetLength<kVerifyFlags>());
+}
+
+template <bool kIsInstrumented, typename PreFenceVisitor>
+inline String* String::Alloc(Thread* self, int32_t utf16_length, gc::AllocatorType allocator_type,
+                             const PreFenceVisitor& pre_fence_visitor) {
+  size_t header_size = sizeof(String);
+  size_t data_size = sizeof(uint16_t) * utf16_length;
+  size_t size = header_size + data_size;
+  Class* string_class = GetJavaLangString();
+
+  // Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
+  if (UNLIKELY(size < data_size)) {
+    self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow",
+                                             PrettyDescriptor(string_class).c_str(),
+                                             utf16_length).c_str());
+    return nullptr;
+  }
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  return down_cast<String*>(
+      heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, string_class, size,
+                                                             allocator_type, pre_fence_visitor));
+}
+
+template <bool kIsInstrumented>
+inline String* String::AllocFromByteArray(Thread* self, int32_t byte_length,
+                                          Handle<ByteArray> array, int32_t offset,
+                                          int32_t high_byte, gc::AllocatorType allocator_type) {
+  uint8_t* data = reinterpret_cast<uint8_t*>(array->GetData()) + offset;
+  SetStringCountAndBytesVisitor visitor(byte_length, data, high_byte << 8);
+  String* string = Alloc<kIsInstrumented>(self, byte_length, allocator_type, visitor);
+  return string;
+}
+
+template <bool kIsInstrumented>
+inline String* String::AllocFromCharArray(Thread* self, int32_t array_length,
+                                          Handle<CharArray> array, int32_t offset,
+                                          gc::AllocatorType allocator_type) {
+  uint16_t* data = array->GetData() + offset;
+  SetStringCountAndValueVisitor visitor(array_length, data);
+  String* new_string = Alloc<kIsInstrumented>(self, array_length, allocator_type, visitor);
+  return new_string;
+}
+
+template <bool kIsInstrumented>
+inline String* String::AllocFromString(Thread* self, int32_t string_length, Handle<String> string,
+                                       int32_t offset, gc::AllocatorType allocator_type) {
+  uint16_t* data = string->GetValue() + offset;
+  SetStringCountAndValueVisitor visitor(string_length, data);
+  String* new_string = Alloc<kIsInstrumented>(self, string_length, allocator_type, visitor);
+  return new_string;
+}
+
 inline int32_t String::GetHashCode() {
   int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_));
   if (UNLIKELY(result == 0)) {
     result = ComputeHashCode();
   }
-  DCHECK(result != 0 || ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0)
+  DCHECK(result != 0 || ComputeUtf16Hash(GetValue(), GetLength()) == 0)
       << ToModifiedUtf8() << " " << result;
   return result;
 }