Merge "Add null check in artQuickResolutionTrampoline"
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 77dc367..8f840cc 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -21,7 +21,6 @@
 LIBART_COMPILER_SRC_FILES := \
 	compiled_method.cc \
 	dex/local_value_numbering.cc \
-	dex/arena_bit_vector.cc \
 	dex/quick/arm/assemble_arm.cc \
 	dex/quick/arm/call_arm.cc \
 	dex/quick/arm/fp_arm.cc \
@@ -54,6 +53,7 @@
 	dex/mir_optimization.cc \
 	dex/pass_driver.cc \
 	dex/bb_optimizations.cc \
+	dex/bit_vector_block_iterator.cc \
 	dex/frontend.cc \
 	dex/mir_graph.cc \
 	dex/mir_analysis.cc \
@@ -72,6 +72,7 @@
 	optimizing/nodes.cc \
 	trampolines/trampoline_compiler.cc \
 	utils/arena_allocator.cc \
+	utils/arena_bit_vector.cc \
 	utils/arm/assembler_arm.cc \
 	utils/arm/managed_register_arm.cc \
 	utils/assembler.cc \
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index f935095..0999d09 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -285,7 +285,7 @@
 #elif defined(__x86_64__)
       instruction_set = kX86_64;
       // TODO: x86_64 compilation support.
-      compiler_options_->SetCompilerFilter(Runtime::kInterpretOnly);
+      compiler_options_->SetCompilerFilter(CompilerOptions::kInterpretOnly);
 #endif
 
       for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
diff --git a/compiler/dex/arena_bit_vector.h b/compiler/dex/arena_bit_vector.h
deleted file mode 100644
index cdd5c68..0000000
--- a/compiler/dex/arena_bit_vector.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_DEX_ARENA_BIT_VECTOR_H_
-#define ART_COMPILER_DEX_ARENA_BIT_VECTOR_H_
-
-#include "base/bit_vector.h"
-#include "compiler_enums.h"
-#include "utils/arena_allocator.h"
-#include "compiler_ir.h"
-
-namespace art {
-
-// Forward declaration
-class MIRGraph;
-
-/*
- * A BitVector implementation that uses Arena allocation.
- */
-class ArenaBitVector : public BitVector {
-  public:
-    /**
-     * @class BasicBlockIterator
-     * @brief Helper class to get the BasicBlocks when iterating through the ArenaBitVector.
-     */
-    class BasicBlockIterator {
-      public:
-        explicit BasicBlockIterator(ArenaBitVector* bv, MIRGraph* mir_graph)
-          : mir_graph_(mir_graph),
-            internal_iterator_(bv) {}
-
-        explicit BasicBlockIterator(ArenaBitVector* bv, CompilationUnit* c_unit)
-          : mir_graph_(c_unit->mir_graph.get()),
-            internal_iterator_(bv) {}
-
-        BasicBlock* Next();
-
-        static void* operator new(size_t size, ArenaAllocator* arena) {
-          return arena->Alloc(sizeof(ArenaBitVector::BasicBlockIterator),
-                              ArenaAllocator::kAllocGrowableArray);
-        };
-        static void operator delete(void* p) {}  // Nop.
-
-      private:
-        MIRGraph* const mir_graph_;
-        Iterator internal_iterator_;
-    };
-
-    ArenaBitVector(ArenaAllocator* arena, uint32_t start_bits, bool expandable,
-                   OatBitMapKind kind = kBitMapMisc);
-    ~ArenaBitVector() {}
-
-  static void* operator new(size_t size, ArenaAllocator* arena) {
-     return arena->Alloc(sizeof(ArenaBitVector), ArenaAllocator::kAllocGrowableBitMap);
-  }
-  static void operator delete(void* p) {}  // Nop.
-
-  private:
-    const OatBitMapKind kind_;      // for memory use tuning. TODO: currently unused.
-};
-
-
-}  // namespace art
-
-#endif  // ART_COMPILER_DEX_ARENA_BIT_VECTOR_H_
diff --git a/compiler/dex/bit_vector_block_iterator.cc b/compiler/dex/bit_vector_block_iterator.cc
new file mode 100644
index 0000000..32d7d71
--- /dev/null
+++ b/compiler/dex/bit_vector_block_iterator.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bit_vector_block_iterator.h"
+#include "mir_graph.h"
+
+namespace art {
+
+BasicBlock* BitVectorBlockIterator::Next() {
+  int idx = internal_iterator_.Next();
+
+  if (idx == -1) {
+    return nullptr;
+  }
+
+  return mir_graph_->GetBasicBlock(idx);
+}
+
+}  // namespace art
diff --git a/compiler/dex/bit_vector_block_iterator.h b/compiler/dex/bit_vector_block_iterator.h
new file mode 100644
index 0000000..0821e9e
--- /dev/null
+++ b/compiler/dex/bit_vector_block_iterator.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DEX_BIT_VECTOR_BLOCK_ITERATOR_H_
+#define ART_COMPILER_DEX_BIT_VECTOR_BLOCK_ITERATOR_H_
+
+#include "base/bit_vector.h"
+#include "compiler_enums.h"
+#include "utils/arena_bit_vector.h"
+#include "utils/arena_allocator.h"
+#include "compiler_ir.h"
+
+namespace art {
+
+class MIRGraph;
+
+/**
+ * @class BasicBlockIterator
+ * @brief Helper class to get the BasicBlocks when iterating through the ArenaBitVector.
+ */
+class BitVectorBlockIterator {
+  public:
+    explicit BitVectorBlockIterator(BitVector* bv, MIRGraph* mir_graph)
+      : mir_graph_(mir_graph),
+        internal_iterator_(bv) {}
+
+    explicit BitVectorBlockIterator(BitVector* bv, CompilationUnit* c_unit)
+      : mir_graph_(c_unit->mir_graph.get()),
+        internal_iterator_(bv) {}
+
+    BasicBlock* Next();
+
+    void* operator new(size_t size, ArenaAllocator* arena) {
+      return arena->Alloc(size, ArenaAllocator::kAllocGrowableArray);
+    };
+    void operator delete(void* p) {}  // Nop.
+
+  private:
+    MIRGraph* const mir_graph_;
+    BitVector::Iterator internal_iterator_;
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_BIT_VECTOR_BLOCK_ITERATOR_H_
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index 2bc36a5..0cd9ba3 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -402,29 +402,6 @@
 
 std::ostream& operator<<(std::ostream& os, const SelectInstructionKind& kind);
 
-// Type of growable bitmap for memory tuning.
-enum OatBitMapKind {
-  kBitMapMisc = 0,
-  kBitMapUse,
-  kBitMapDef,
-  kBitMapLiveIn,
-  kBitMapBMatrix,
-  kBitMapDominators,
-  kBitMapIDominated,
-  kBitMapDomFrontier,
-  kBitMapPhi,
-  kBitMapTmpBlocks,
-  kBitMapInputBlocks,
-  kBitMapRegisterV,
-  kBitMapTempSSARegisterV,
-  kBitMapNullCheck,
-  kBitMapTmpBlockV,
-  kBitMapPredecessors,
-  kNumBitMapKinds
-};
-
-std::ostream& operator<<(std::ostream& os, const OatBitMapKind& kind);
-
 // LIR fixup kinds for Arm
 enum FixupKind {
   kFixupNone,
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 2174f67..d344055 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -20,7 +20,7 @@
 #include "dex_file.h"
 #include "dex_instruction.h"
 #include "compiler_ir.h"
-#include "arena_bit_vector.h"
+#include "utils/arena_bit_vector.h"
 #include "utils/growable_array.h"
 
 namespace art {
diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc
index 0f79f41..4e258ef 100644
--- a/compiler/dex/ssa_transformation.cc
+++ b/compiler/dex/ssa_transformation.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "bit_vector_block_iterator.h"
 #include "compiler_internals.h"
 #include "dataflow_iterator-inl.h"
 
@@ -248,9 +249,9 @@
   }
 
   /* Calculate DF_up */
-  ArenaBitVector::BasicBlockIterator it(bb->i_dominated, cu_);
+  BitVectorBlockIterator it(bb->i_dominated, cu_);
   for (BasicBlock *dominated_bb = it.Next(); dominated_bb != nullptr; dominated_bb = it.Next()) {
-    ArenaBitVector::BasicBlockIterator inner_it(dominated_bb->dom_frontier, cu_);
+    BitVectorBlockIterator inner_it(dominated_bb->dom_frontier, cu_);
     for (BasicBlock *df_up_block = inner_it.Next(); df_up_block != nullptr;
          df_up_block = inner_it.Next()) {
       CheckForDominanceFrontier(bb, df_up_block);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 8f6a26c..3d5d531 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -18,8 +18,8 @@
 #define ART_COMPILER_OPTIMIZING_NODES_H_
 
 #include "utils/allocation.h"
+#include "utils/arena_bit_vector.h"
 #include "utils/growable_array.h"
-#include "dex/arena_bit_vector.h"
 
 namespace art {
 
diff --git a/compiler/utils/arena_allocator_test.cc b/compiler/utils/arena_allocator_test.cc
index b76fe74..7156540 100644
--- a/compiler/utils/arena_allocator_test.cc
+++ b/compiler/utils/arena_allocator_test.cc
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#include "dex/arena_bit_vector.h"
 #include "gtest/gtest.h"
 #include "utils/arena_allocator.h"
+#include "utils/arena_bit_vector.h"
 
 namespace art {
 
diff --git a/compiler/dex/arena_bit_vector.cc b/compiler/utils/arena_bit_vector.cc
similarity index 85%
rename from compiler/dex/arena_bit_vector.cc
rename to compiler/utils/arena_bit_vector.cc
index 1b37b71..6f03524 100644
--- a/compiler/dex/arena_bit_vector.cc
+++ b/compiler/utils/arena_bit_vector.cc
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "compiler_internals.h"
-#include "dex_file-inl.h"
+#include "arena_allocator.h"
+#include "arena_bit_vector.h"
 
 namespace art {
 
@@ -44,14 +44,4 @@
                                bool expandable, OatBitMapKind kind)
   :  BitVector(start_bits, expandable, new (arena) ArenaBitVectorAllocator(arena)), kind_(kind) {}
 
-BasicBlock* ArenaBitVector::BasicBlockIterator::Next() {
-    int idx = internal_iterator_.Next();
-
-    if (idx == -1) {
-      return nullptr;
-    }
-
-    return mir_graph_->GetBasicBlock(idx);
-}
-
 }  // namespace art
diff --git a/compiler/utils/arena_bit_vector.h b/compiler/utils/arena_bit_vector.h
new file mode 100644
index 0000000..6c14617
--- /dev/null
+++ b/compiler/utils/arena_bit_vector.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_UTILS_ARENA_BIT_VECTOR_H_
+#define ART_COMPILER_UTILS_ARENA_BIT_VECTOR_H_
+
+#include "base/bit_vector.h"
+#include "utils/arena_allocator.h"
+
+namespace art {
+
+// Type of growable bitmap for memory tuning.
+enum OatBitMapKind {
+  kBitMapMisc = 0,
+  kBitMapUse,
+  kBitMapDef,
+  kBitMapLiveIn,
+  kBitMapBMatrix,
+  kBitMapDominators,
+  kBitMapIDominated,
+  kBitMapDomFrontier,
+  kBitMapPhi,
+  kBitMapTmpBlocks,
+  kBitMapInputBlocks,
+  kBitMapRegisterV,
+  kBitMapTempSSARegisterV,
+  kBitMapNullCheck,
+  kBitMapTmpBlockV,
+  kBitMapPredecessors,
+  kNumBitMapKinds
+};
+
+std::ostream& operator<<(std::ostream& os, const OatBitMapKind& kind);
+
+/*
+ * A BitVector implementation that uses Arena allocation.
+ */
+class ArenaBitVector : public BitVector {
+  public:
+    ArenaBitVector(ArenaAllocator* arena, uint32_t start_bits, bool expandable,
+                   OatBitMapKind kind = kBitMapMisc);
+    ~ArenaBitVector() {}
+
+  static void* operator new(size_t size, ArenaAllocator* arena) {
+     return arena->Alloc(sizeof(ArenaBitVector), ArenaAllocator::kAllocGrowableBitMap);
+  }
+  static void operator delete(void* p) {}  // Nop.
+
+  private:
+    const OatBitMapKind kind_;      // for memory use tuning. TODO: currently unused.
+};
+
+
+}  // namespace art
+
+#endif  // ART_COMPILER_UTILS_ARENA_BIT_VECTOR_H_
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 1e5a681..d6d2b42 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -332,7 +332,7 @@
   ifeq ($$(art_target_or_host),target)
     LOCAL_SRC_FILES := $(LIBART_TARGET_SRC_FILES)
     $(foreach arch,$(ART_SUPPORTED_ARCH),
-      LOCAL_SRC_FILES_$(arch) := $$(LIBART_TARGET_SRC_FILES_$(arch))))
+      LOCAL_SRC_FILES_$(arch) := $$(LIBART_TARGET_SRC_FILES_$(arch)))
   else # host
     LOCAL_SRC_FILES := $(LIBART_HOST_SRC_FILES)
     LOCAL_IS_HOST_MODULE := true
@@ -352,7 +352,7 @@
   LOCAL_CFLAGS := $(LIBART_CFLAGS)
   LOCAL_LDFLAGS := $(LIBART_LDFLAGS)
   $(foreach arch,$(ART_SUPPORTED_ARCH),
-    LOCAL_LDFLAGS_$(arch) := $$(LIBART_TARGET_LDFLAGS_$(arch))))
+    LOCAL_LDFLAGS_$(arch) := $$(LIBART_TARGET_LDFLAGS_$(arch)))
 
   ifeq ($$(art_target_or_host),target)
     LOCAL_CLANG := $(ART_TARGET_CLANG)
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index b1f2275..8683a56 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -1307,8 +1307,10 @@
      *   esi: pointer to this string data
      *   edi: pointer to comp string data
      */
+    jecxz .Lkeep_length
     repe cmpsw                    // find nonmatching chars in [%esi] and [%edi], up to length %ecx
     jne .Lnot_equal
+.Lkeep_length:
     POP edi                       // pop callee save reg
     POP esi                       // pop callee save reg
     ret
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 6ef0082..3da7409 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -40,7 +40,7 @@
 
 inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class* element_class) {
   for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
-    // Read the cached the array class once to avoid races with other threads setting it.
+    // Read the cached array class once to avoid races with other threads setting it.
     mirror::Class* array_class = find_array_class_cache_[i];
     if (array_class != nullptr && array_class->GetComponentType() == element_class) {
       return array_class;
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index f16db8b..3a17e41 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -290,14 +290,14 @@
 
   if (!program_header_only_) {
     if (header_->e_phoff >= Size()) {
-      *error_msg = StringPrintf("Failed to find e_phoff value %d less than %d in %s",
+      *error_msg = StringPrintf("Failed to find e_phoff value %d less than %zd in %s",
                                 header_->e_phoff,
                                 Size(),
                                 file_->GetPath().c_str());
       return false;
     }
     if (header_->e_shoff >= Size()) {
-      *error_msg = StringPrintf("Failed to find e_shoff value %d less than %d in %s",
+      *error_msg = StringPrintf("Failed to find e_shoff value %d less than %zd in %s",
                                 header_->e_shoff,
                                 Size(),
                                 file_->GetPath().c_str());
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index ce9dcea..e089ef2 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -74,7 +74,7 @@
     obj->AssertSelfBrooksPointer();
   }
   pre_fence_visitor(obj, usable_size);
-  if (kIsDebugBuild && klass != nullptr && Runtime::Current()->IsStarted()) {
+  if (kIsDebugBuild && Runtime::Current()->IsStarted()) {
     CHECK_LE(obj->SizeOf(), usable_size);
   }
   const size_t new_num_bytes_allocated =
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 567ec99..fe8421d 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -45,9 +45,9 @@
 }
 
 RosAllocSpace* RosAllocSpace::CreateFromMemMap(MemMap* mem_map, const std::string& name,
-                                            size_t starting_size, size_t initial_size,
-                                            size_t growth_limit, size_t capacity,
-                                            bool low_memory_mode) {
+                                               size_t starting_size, size_t initial_size,
+                                               size_t growth_limit, size_t capacity,
+                                               bool low_memory_mode) {
   DCHECK(mem_map != nullptr);
   allocator::RosAlloc* rosalloc = CreateRosAlloc(mem_map->Begin(), starting_size, initial_size,
                                                  low_memory_mode);
@@ -73,8 +73,8 @@
 }
 
 RosAllocSpace* RosAllocSpace::Create(const std::string& name, size_t initial_size,
-                                  size_t growth_limit, size_t capacity, byte* requested_begin,
-                                  bool low_memory_mode) {
+                                     size_t growth_limit, size_t capacity, byte* requested_begin,
+                                     bool low_memory_mode) {
   uint64_t start_time = 0;
   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     start_time = NanoTime();
diff --git a/runtime/mapping_table.h b/runtime/mapping_table.h
index a82bc1c..79e6e94 100644
--- a/runtime/mapping_table.h
+++ b/runtime/mapping_table.h
@@ -56,8 +56,8 @@
       // We must have dex to pc entries or else the loop will go beyond the end of the table.
       DCHECK_GT(total_size, pc_to_dex_size);
       for (uint32_t i = 0; i < pc_to_dex_size; ++i) {
-        DecodeUnsignedLeb128(&table);  // Move ptr past native PC.
-        DecodeUnsignedLeb128(&table);  // Move ptr past dex PC.
+        DecodeUnsignedLeb128(&table);  // Move ptr past native PC delta.
+        DecodeSignedLeb128(&table);  // Move ptr past dex PC delta.
       }
     }
     return table;
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index d44f75f..8158bc5 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -91,20 +91,26 @@
 // array.
 class SetLengthToUsableSizeVisitor {
  public:
-  SetLengthToUsableSizeVisitor(size_t header_size, size_t component_size) :
-      header_size_(header_size), component_size_(component_size) {
+  SetLengthToUsableSizeVisitor(int32_t min_length, size_t header_size, size_t component_size) :
+      minimum_length_(min_length), header_size_(header_size), component_size_(component_size) {
   }
 
   void operator()(Object* obj, size_t usable_size) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // Avoid AsArray as object is not yet in live bitmap or allocation stack.
     Array* array = down_cast<Array*>(obj);
-    uint32_t length = (usable_size - header_size_) / component_size_;
     // DCHECK(array->IsArrayInstance());
+    int32_t length = (usable_size - header_size_) / component_size_;
+    DCHECK_GE(length, minimum_length_);
+    byte* old_end = reinterpret_cast<byte*>(array->GetRawData(component_size_, minimum_length_));
+    byte* new_end = reinterpret_cast<byte*>(array->GetRawData(component_size_, length));
+    // Ensure space beyond original allocation is zeroed.
+    memset(old_end, 0, new_end - old_end);
     array->SetLength(length);
   }
 
  private:
+  const int32_t minimum_length_;
   const size_t header_size_;
   const size_t component_size_;
 
@@ -128,12 +134,14 @@
         heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
                                                               allocator_type, visitor));
   } else {
-    SetLengthToUsableSizeVisitor visitor(HeaderSize(component_size), component_size);
+    SetLengthToUsableSizeVisitor visitor(component_count, HeaderSize(component_size),
+                                         component_size);
     result = down_cast<Array*>(
         heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
                                                               allocator_type, visitor));
   }
   if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) {
+    CHECK_EQ(array_class->GetComponentSize(), component_size);
     if (!fill_usable) {
       CHECK_EQ(result->SizeOf(), size);
     } else {
diff --git a/test/021-string2/src/Main.java b/test/021-string2/src/Main.java
index 87e4baf..0239a3c 100644
--- a/test/021-string2/src/Main.java
+++ b/test/021-string2/src/Main.java
@@ -36,6 +36,10 @@
         Assert.assertTrue(test1.compareTo(test2) > 0);
         Assert.assertTrue(test2.compareTo(test1) < 0);
 
+        Assert.assertEquals("".compareTo(""), 0);
+        Assert.assertTrue(test.compareTo("") > 0);
+        Assert.assertTrue("".compareTo(test) < 0);
+
         /* compare string with a nonzero offset, in left/right side */
         Assert.assertEquals(test.compareTo(sub), 0);
         Assert.assertEquals(sub.compareTo(test), 0);