Merge "Fix the behavior of java.lang.String.fastIndexOf when start > length()." into ics-mr1-plus-art
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 3166b75..ea5502a 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -67,6 +67,7 @@
 .PHONY: test-art-host-oat-$(1)
 test-art-host-oat-$(1): $(ART_TEST_OUT)/oat-test-dex-$(1).jar $(HOST_CORE_IMG_OUT)
 	mkdir -p /tmp/android-data/test-art-host-oat-$(1)
+	$(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(HOST_CORE_IMG_OUT) --dex-file=$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar --oat-file=$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar.oat --instruction-set=X86 --host-prefix=""
 	ANDROID_DATA=/tmp/android-data/test-art-host-oat-$(1) \
 	  ANDROID_ROOT=$(HOST_OUT) \
 	  LD_LIBRARY_PATH=$(HOST_OUT_SHARED_LIBRARIES) \
diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc
index 2639057..bad7142 100644
--- a/src/compiler/codegen/x86/Assemble.cc
+++ b/src/compiler/codegen/x86/Assemble.cc
@@ -1079,7 +1079,7 @@
   LIR *lir;
   AssemblerStatus res = kSuccess;  // Assume success
 
-  const bool kVerbosePcFixup = cUnit->method_idx == 9703;
+  const bool kVerbosePcFixup = false;
   for (lir = (LIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
     if (lir->opcode < 0) {
       continue;
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index b85ba7c..d18080f 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -135,8 +135,9 @@
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; RTTI
+; Type Checking, in the nature of casting
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 declare i32 @art_is_assignable_from_code(%JavaObject*, %JavaObject*)
 declare void @art_check_cast_from_code(%JavaObject*, %JavaObject*)
+declare void @art_check_put_array_element_from_code(%JavaObject*, %JavaObject*)
diff --git a/src/compiler_llvm/compiler_runtime_func_list.h b/src/compiler_llvm/compiler_runtime_func_list.h
index 5cf5bb5..189939b 100644
--- a/src/compiler_llvm/compiler_runtime_func_list.h
+++ b/src/compiler_llvm/compiler_runtime_func_list.h
@@ -171,7 +171,11 @@
   V(__aeabi_uidiv) \
   V(__aeabi_ul2d) \
   V(__aeabi_ul2f) \
-  V(__aeabi_uldivmod)
+  V(__aeabi_uldivmod) \
+  V(__moddi3) \
+  V(__modsi3) \
+  V(__umoddi3) \
+  V(__umodsi3)
 
 #else
 
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 973ef06..07fc6a3 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -773,6 +773,17 @@
 AttrListPtr func_art_check_cast_from_code_PAL;
 func_art_check_cast_from_code->setAttributes(func_art_check_cast_from_code_PAL);
 
+Function* func_art_check_put_array_element_from_code = mod->getFunction("art_check_put_array_element_from_code");
+if (!func_art_check_put_array_element_from_code) {
+func_art_check_put_array_element_from_code = Function::Create(
+ /*Type=*/FuncTy_27,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_check_put_array_element_from_code", mod); // (external, no body)
+func_art_check_put_array_element_from_code->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_check_put_array_element_from_code_PAL;
+func_art_check_put_array_element_from_code->setAttributes(func_art_check_put_array_element_from_code_PAL);
+
 // Global Variable Declarations
 
 
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index bcd40de..8b1cef6 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2328,6 +2328,14 @@
 
   llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kArray);
 
+  if (elem_jty == kObject) { // If put an object, check the type.
+    llvm::Function* runtime_func = irb_.GetRuntime(CheckPutArrayElement);
+
+    irb_.CreateCall2(runtime_func, new_value, array_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+  }
+
   irb_.CreateStore(new_value, array_elem_addr);
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 1c21d48..518a175 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -31,6 +31,7 @@
   V(InitializeType, art_initialize_type_from_code) \
   V(IsAssignable, art_is_assignable_from_code) \
   V(CheckCast, art_check_cast_from_code) \
+  V(CheckPutArrayElement, art_check_put_array_element_from_code) \
   V(AllocObject, art_alloc_object_from_code) \
   V(AllocObjectWithAccessCheck, art_alloc_object_from_code_with_access_check) \
   V(AllocArray, art_alloc_array_from_code) \
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 6ad80f8..ff31825 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -39,7 +39,7 @@
 
 void art_set_current_thread_from_code(void* thread_object_addr) {
   // TODO: LLVM IR generating something like "r9 = thread_object_addr"
-  UNIMPLEMENTED(WARNING);
+  // UNIMPLEMENTED(WARNING);
 }
 
 void art_lock_object_from_code(Object* obj) {
@@ -438,7 +438,7 @@
 }
 
 void art_check_cast_from_code(const Class* dest_type, const Class* src_type) {
-DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
+  DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
   DCHECK(src_type->IsClass()) << PrettyClass(src_type);
   if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
@@ -448,6 +448,24 @@
   }
 }
 
+void art_check_put_array_element_from_code(const Object* element, const Object* array) {
+  if (element == NULL) {
+    return;
+  }
+  DCHECK(array != NULL);
+  Class* array_class = array->GetClass();
+  DCHECK(array_class != NULL);
+  Class* component_type = array_class->GetComponentType();
+  Class* element_class = element->GetClass();
+  if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+        "%s cannot be stored in an array of type %s",
+        PrettyDescriptor(element_class).c_str(),
+        PrettyDescriptor(array_class).c_str());
+  }
+  return;
+}
+
 //----------------------------------------------------------------------------
 // Runtime Support Function Lookup Callback
 //----------------------------------------------------------------------------
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 747b613..6017ddb 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -200,7 +200,7 @@
   }
 
   const Compiler* CreateOatFile(const std::string& boot_image_option,
-                                const std::string& host_prefix,
+                                const std::string* host_prefix,
                                 const std::vector<const DexFile*>& dex_files,
                                 File* oat_file,
 #if defined(ART_USE_LLVM_COMPILER)
@@ -248,8 +248,8 @@
       ImageSpace* image_space = heap->GetImageSpace();
       image_file_location_checksum = image_space->GetImageHeader().GetOatChecksum();
       image_file_location = image_space->GetImageFilename();
-      if (!host_prefix.empty() && StartsWith(image_file_location, host_prefix.c_str())) {
-        image_file_location = image_file_location.substr(host_prefix.size());
+      if (host_prefix != NULL && StartsWith(image_file_location, host_prefix->c_str())) {
+        image_file_location = image_file_location.substr(host_prefix->size());
       }
     }
 
@@ -470,7 +470,7 @@
   std::string image_filename;
   std::string boot_image_filename;
   uintptr_t image_base = 0;
-  std::string host_prefix;
+  UniquePtr<std::string> host_prefix;
   std::vector<const char*> runtime_args;
   int thread_count = 2;
   bool support_debugging = false;
@@ -529,7 +529,7 @@
     } else if (option.starts_with("--boot-image=")) {
       boot_image_filename = option.substr(strlen("--boot-image=")).data();
     } else if (option.starts_with("--host-prefix=")) {
-      host_prefix = option.substr(strlen("--host-prefix=")).data();
+      host_prefix.reset(new std::string(option.substr(strlen("--host-prefix=")).data()));
     } else if (option.starts_with("--instruction-set=")) {
       StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
       if (instruction_set_str == "Thumb2" || instruction_set_str == "ARM") {
@@ -574,19 +574,19 @@
     Usage("--oat-fd should not be used with --image");
   }
 
-  if (host_prefix.empty()) {
+  if (host_prefix.get() == NULL) {
     const char* android_product_out = getenv("ANDROID_PRODUCT_OUT");
     if (android_product_out != NULL) {
-        host_prefix = android_product_out;
+        host_prefix.reset(new std::string(android_product_out));
     }
   }
 
   bool image = (!image_filename.empty());
   if (!image && boot_image_filename.empty()) {
-    if (host_prefix.empty()) {
+    if (host_prefix.get() == NULL) {
       boot_image_filename += GetAndroidRoot();
     } else {
-      boot_image_filename += host_prefix;
+      boot_image_filename += *host_prefix.get();
       boot_image_filename += "/system";
     }
     boot_image_filename += "/framework/boot.art";
@@ -661,8 +661,8 @@
   } else {
     options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
   }
-  if (!host_prefix.empty()) {
-    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
+  if (host_prefix.get() != NULL) {
+    options.push_back(std::make_pair("host-prefix", host_prefix->c_str()));
   }
   for (size_t i = 0; i < runtime_args.size(); i++) {
     options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
@@ -703,7 +703,7 @@
   }
 
   UniquePtr<const Compiler> compiler(dex2oat->CreateOatFile(boot_image_option,
-                                                            host_prefix,
+                                                            host_prefix.get(),
                                                             dex_files,
                                                             oat_file.get(),
 #if defined(ART_USE_LLVM_COMPILER)
diff --git a/src/heap.cc b/src/heap.cc
index d2aada4..8a7ab3d 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -313,6 +313,7 @@
 #if VERIFY_OBJECT_ENABLED
 void Heap::VerifyObject(const Object* obj) {
   if (this == NULL || !verify_objects_ || Runtime::Current()->IsShuttingDown() ||
+      Thread::Current() == NULL ||
       Runtime::Current()->GetThreadList()->GetLockOwner() == Thread::Current()->GetTid()) {
     return;
   }
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
index 69e9c98..f8a071f 100644
--- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -218,14 +218,9 @@
   points->pIdivmod = __aeabi_idivmod;
   points->pD2l = D2L;
   points->pF2l = F2L;
-  points->pLadd = NULL;
-  points->pLand = NULL;
   points->pLdiv = __aeabi_ldivmod;
   points->pLdivmod = __aeabi_ldivmod;  // result returned in r2:r3
   points->pLmul = __aeabi_lmul;
-  points->pLor = NULL;
-  points->pLsub = NULL;
-  points->pLxor = NULL;
   points->pShlLong = art_shl_long;
   points->pShrLong = art_shr_long;
   points->pUshrLong = art_ushr_long;
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 62b20f2..a5cdc33 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -216,14 +216,9 @@
   points->pIdivmod = NULL;
   points->pD2l = D2L;
   points->pF2l = F2L;
-  points->pLadd = NULL;
-  points->pLand = NULL;
   points->pLdiv = NULL;
   points->pLdivmod = NULL;
   points->pLmul = NULL;
-  points->pLor = NULL;
-  points->pLsub = NULL;
-  points->pLxor = NULL;
   points->pShlLong = art_shl_long;
   points->pShrLong = art_shr_long;
   points->pUshrLong = art_ushr_long;
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
index 1a8e675..af7fee3 100644
--- a/src/oat/runtime/oat_support_entrypoints.h
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -105,14 +105,9 @@
   int32_t (*pIdivmod)(int32_t, int32_t);
   int64_t (*pD2l)(double);
   int64_t (*pF2l)(float);
-  int64_t (*pLadd)(int64_t, int64_t);
-  int64_t (*pLand)(int64_t, int64_t);
   int64_t (*pLdiv)(int64_t, int64_t);
   int64_t (*pLdivmod)(int64_t, int64_t);
   int64_t (*pLmul)(int64_t, int64_t);
-  int64_t (*pLor)(int64_t, int64_t);
-  int64_t (*pLsub)(int64_t, int64_t);
-  int64_t (*pLxor)(int64_t, int64_t);
   uint64_t (*pShlLong)(uint64_t, uint32_t);
   uint64_t (*pShrLong)(uint64_t, uint32_t);
   uint64_t (*pUshrLong)(uint64_t, uint32_t);
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index dd139ee..735c231 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -76,6 +76,9 @@
 extern "C" int32_t art_idivmod_from_code(int32_t, int32_t);
 extern "C" int64_t art_ldiv_from_code(int64_t, int64_t);
 extern "C" int64_t art_ldivmod_from_code(int64_t, int64_t);
+extern "C" uint64_t art_lshl_from_code(uint64_t, uint32_t);
+extern "C" uint64_t art_lshr_from_code(uint64_t, uint32_t);
+extern "C" uint64_t art_lushr_from_code(uint64_t, uint32_t);
 
 // Intrinsic entrypoints.
 extern "C" int32_t art_memcmp16(void*, void*, int32_t);
@@ -183,17 +186,12 @@
   points->pIdivmod = art_idivmod_from_code;
   points->pD2l = D2L;
   points->pF2l = F2L;
-  points->pLadd = NULL;
-  points->pLand = NULL;
   points->pLdiv = art_ldiv_from_code;
   points->pLdivmod = art_ldivmod_from_code;
   points->pLmul = NULL;
-  points->pLor = NULL;
-  points->pLsub = NULL;
-  points->pLxor = NULL;
-  points->pShlLong = NULL;
-  points->pShrLong = NULL;
-  points->pUshrLong = NULL;
+  points->pShlLong = art_lshl_from_code;
+  points->pShrLong = art_lshr_from_code;
+  points->pUshrLong = art_lushr_from_code;
 
   // Intrinsics
   points->pIndexOf = art_indexof;
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
index 0797da6..4f3d334 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -414,7 +414,7 @@
     ret
 
 DEFINE_FUNCTION art_ldiv_from_code
-    addl LITERAL(12), %esp        // alignment padding
+    subl LITERAL(12), %esp        // alignment padding
     pushl %ebx                    // pass arg4
     pushl %edx                    // pass arg3
     pushl %ecx                    // pass arg2
@@ -424,7 +424,7 @@
     ret
 
 DEFINE_FUNCTION art_ldivmod_from_code
-    addl LITERAL(12), %esp        // alignment padding
+    subl LITERAL(12), %esp        // alignment padding
     pushl %ebx                    // pass arg4
     pushl %edx                    // pass arg3
     pushl %ecx                    // pass arg2
@@ -433,6 +433,42 @@
     addl LITERAL(28), %esp        // pop arguments
     ret
 
+DEFINE_FUNCTION art_lshl_from_code
+    // eax:ecx << edx
+    xchg %edx, %ecx
+    shld %cl,%eax,%edx
+    shl  %cl,%eax
+    test LITERAL(32), %cl
+    jz  1f
+    mov %eax, %edx
+    xor %eax, %eax
+1:
+    ret
+
+DEFINE_FUNCTION art_lshr_from_code
+    // eax:ecx >> edx
+    xchg %edx, %ecx
+    shrd %cl,%eax,%edx
+    sar  %cl,%eax
+    test LITERAL(32),%cl
+    jz  1f
+    mov %edx, %eax
+    sar LITERAL(31), %edx
+1:
+    ret
+
+DEFINE_FUNCTION art_lushr_from_code
+    // eax:ecx >>> edx
+    xchg %edx, %ecx
+    shrd %cl,%eax,%edx
+    shr  %cl,%eax
+    test   $0x20,%cl
+    jz  1f
+    mov %edx, %eax
+    xor %edx, %edx
+1:
+    ret
+
 DEFINE_FUNCTION art_can_put_array_element_from_code
     test %eax, %eax               // Null is trivially storable
     jz   1f
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 555e1be..aa63ef5 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -205,14 +205,9 @@
     DUMP_ENTRY_POINT(pIdivmod);
     DUMP_ENTRY_POINT(pD2l);
     DUMP_ENTRY_POINT(pF2l);
-    DUMP_ENTRY_POINT(pLadd);
-    DUMP_ENTRY_POINT(pLand);
     DUMP_ENTRY_POINT(pLdiv);
     DUMP_ENTRY_POINT(pLdivmod);
     DUMP_ENTRY_POINT(pLmul);
-    DUMP_ENTRY_POINT(pLor);
-    DUMP_ENTRY_POINT(pLsub);
-    DUMP_ENTRY_POINT(pLxor);
     DUMP_ENTRY_POINT(pShlLong);
     DUMP_ENTRY_POINT(pShrLong);
     DUMP_ENTRY_POINT(pUshrLong);
diff --git a/src/runtime.cc b/src/runtime.cc
index c4a9bd7..c013726 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -634,7 +634,6 @@
                    options->heap_growth_limit_,
                    options->heap_maximum_size_,
                    options->image_);
-  heap_->EnableObjectValidation();
 
   BlockSignals();
 
@@ -649,6 +648,9 @@
   // Set us to runnable so tools using a runtime can allocate and GC by default
   Thread::Current()->SetState(Thread::kRunnable);
 
+  // Now we're attached, we can take the heap lock and validate the heap.
+  GetHeap()->EnableObjectValidation();
+
   CHECK_GE(GetHeap()->GetSpaces().size(), 1U);
   if (GetHeap()->GetSpaces()[0]->IsImageSpace()) {
     class_linker_ = ClassLinker::CreateFromImage(intern_table_);