Merge "Avoid duplicated code for FILLED_NEW_ARRAY." into dalvik-dev
diff --git a/src/gc/collector/garbage_collector.cc b/src/gc/collector/garbage_collector.cc
index 7412835..378a971 100644
--- a/src/gc/collector/garbage_collector.cc
+++ b/src/gc/collector/garbage_collector.cc
@@ -14,6 +14,11 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+
+#include <stdio.h>
+#include <cutils/trace.h>
+
 #include "garbage_collector.h"
 
 #include "base/logging.h"
@@ -68,10 +73,12 @@
   if (!IsConcurrent()) {
     // Pause is the entire length of the GC.
     uint64_t pause_start = NanoTime();
+    ATRACE_BEGIN("Application threads suspended");
     thread_list->SuspendAll();
     MarkingPhase();
     ReclaimPhase();
     thread_list->ResumeAll();
+    ATRACE_END();
     uint64_t pause_end = NanoTime();
     pause_times_.push_back(pause_end - pause_start);
   } else {
@@ -82,9 +89,11 @@
     bool done = false;
     while (!done) {
       uint64_t pause_start = NanoTime();
+      ATRACE_BEGIN("Application threads suspended");
       thread_list->SuspendAll();
       done = HandleDirtyObjectsPhase();
       thread_list->ResumeAll();
+      ATRACE_END();
       uint64_t pause_end = NanoTime();
       pause_times_.push_back(pause_end - pause_start);
     }
diff --git a/src/gc/heap.cc b/src/gc/heap.cc
index 34c0b5c..9ec1f21 100644
--- a/src/gc/heap.cc
+++ b/src/gc/heap.cc
@@ -16,6 +16,8 @@
 
 #include "heap.h"
 
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include <cutils/trace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -1121,6 +1123,19 @@
 collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type, GcCause gc_cause,
                                                bool clear_soft_references) {
   Thread* self = Thread::Current();
+
+  switch (gc_cause) {
+    case kGcCauseForAlloc:
+      ATRACE_BEGIN("GC (alloc)");
+      break;
+    case kGcCauseBackground:
+      ATRACE_BEGIN("GC (background)");
+      break;
+    case kGcCauseExplicit:
+      ATRACE_BEGIN("GC (explicit)");
+      break;
+  }
+
   ScopedThreadStateChange tsc(self, kWaitingPerformingGc);
   Locks::mutator_lock_->AssertNotHeld(self);
 
@@ -1234,6 +1249,7 @@
     gc_complete_cond_->Broadcast(self);
   }
   // Inform DDMS that a GC completed.
+  ATRACE_END();
   Dbg::GcDidFinish();
   return gc_type;
 }
@@ -1632,6 +1648,7 @@
 collector::GcType Heap::WaitForConcurrentGcToComplete(Thread* self) {
   collector::GcType last_gc_type = collector::kGcTypeNone;
   if (concurrent_gc_) {
+    ATRACE_BEGIN("GC: Wait For Concurrent");
     bool do_wait;
     uint64_t wait_start = NanoTime();
     {
@@ -1656,6 +1673,7 @@
         LOG(INFO) << "WaitForConcurrentGcToComplete blocked for " << PrettyDuration(wait_time);
       }
     }
+    ATRACE_END();
   }
   return last_gc_type;
 }
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 121e514..39c8f0e 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -1145,7 +1145,7 @@
       case Instruction::CONST_4: {
         PREAMBLE();
         uint32_t dst = inst->VRegA_11n();
-        int32_t val = static_cast<int32_t>(inst->VRegB_11n() << 28) >> 28;
+        int32_t val = inst->VRegB_11n();
         shadow_frame.SetVReg(dst, val);
         if (val == 0) {
           shadow_frame.SetVRegReference(dst, NULL);
@@ -1156,7 +1156,7 @@
       case Instruction::CONST_16: {
         PREAMBLE();
         uint32_t dst = inst->VRegA_21s();
-        int32_t val = static_cast<int16_t>(inst->VRegB_21s());
+        int32_t val = inst->VRegB_21s();
         shadow_frame.SetVReg(dst, val);
         if (val == 0) {
           shadow_frame.SetVRegReference(dst, NULL);
@@ -1178,7 +1178,7 @@
       case Instruction::CONST_HIGH16: {
         PREAMBLE();
         uint32_t dst = inst->VRegA_21h();
-        int32_t val = inst->VRegB_21h() << 16;
+        int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
         shadow_frame.SetVReg(dst, val);
         if (val == 0) {
           shadow_frame.SetVRegReference(dst, NULL);
@@ -1188,14 +1188,12 @@
       }
       case Instruction::CONST_WIDE_16:
         PREAMBLE();
-        shadow_frame.SetVRegLong(inst->VRegA_21s(),
-                                 static_cast<int16_t>(inst->VRegB_21s()));
+        shadow_frame.SetVRegLong(inst->VRegA_21s(), inst->VRegB_21s());
         inst = inst->Next_2xx();
         break;
       case Instruction::CONST_WIDE_32:
         PREAMBLE();
-        shadow_frame.SetVRegLong(inst->VRegA_31i(),
-                                 static_cast<int32_t>(inst->VRegB_31i()));
+        shadow_frame.SetVRegLong(inst->VRegA_31i(), inst->VRegB_31i());
         inst = inst->Next_3xx();
         break;
       case Instruction::CONST_WIDE:
@@ -1302,10 +1300,10 @@
         if (UNLIKELY(array == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           HANDLE_PENDING_EXCEPTION();
-          break;
+        } else {
+          shadow_frame.SetVReg(inst->VRegA_12x(), array->AsArray()->GetLength());
+          inst = inst->Next_1xx();
         }
-        shadow_frame.SetVReg(inst->VRegA_12x(), array->AsArray()->GetLength());
-        inst = inst->Next_1xx();
         break;
       }
       case Instruction::NEW_INSTANCE: {
@@ -1365,8 +1363,9 @@
         }
         Array* array = obj->AsArray();
         DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
+        const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
         const Instruction::ArrayDataPayload* payload =
-            reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + inst->GetDexPc(insns) + inst->VRegB_31t());
+            reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
         if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
           self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
                                    "Ljava/lang/ArrayIndexOutOfBoundsException;",
@@ -2195,33 +2194,35 @@
         break;
       case Instruction::FLOAT_TO_INT: {
         PREAMBLE();
-        uint32_t dst = inst->VRegA_12x();
         float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
+        int32_t result;
         if (val != val) {
-          shadow_frame.SetVReg(dst, 0);
+          result = 0;
         } else if (val > static_cast<float>(kMaxInt)) {
-          shadow_frame.SetVReg(dst, kMaxInt);
+          result = kMaxInt;
         } else if (val < static_cast<float>(kMinInt)) {
-          shadow_frame.SetVReg(dst, kMinInt);
+          result = kMinInt;
         } else {
-          shadow_frame.SetVReg(dst, val);
+          result = val;
         }
+        shadow_frame.SetVReg(inst->VRegA_12x(), result);
         inst = inst->Next_1xx();
         break;
       }
       case Instruction::FLOAT_TO_LONG: {
         PREAMBLE();
-        uint32_t dst = inst->VRegA_12x();
         float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
+        int64_t result;
         if (val != val) {
-          shadow_frame.SetVRegLong(dst, 0);
+          result = 0;
         } else if (val > static_cast<float>(kMaxLong)) {
-          shadow_frame.SetVRegLong(dst, kMaxLong);
+          result = kMaxLong;
         } else if (val < static_cast<float>(kMinLong)) {
-          shadow_frame.SetVRegLong(dst, kMinLong);
+          result = kMinLong;
         } else {
-          shadow_frame.SetVRegLong(dst, val);
+          result = val;
         }
+        shadow_frame.SetVRegLong(inst->VRegA_12x(), result);
         inst = inst->Next_1xx();
         break;
       }
@@ -2232,33 +2233,35 @@
         break;
       case Instruction::DOUBLE_TO_INT: {
         PREAMBLE();
-        uint32_t dst = inst->VRegA_12x();
         double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
+        int32_t result;
         if (val != val) {
-          shadow_frame.SetVReg(dst, 0);
+          result = 0;
         } else if (val > static_cast<double>(kMaxInt)) {
-          shadow_frame.SetVReg(dst, kMaxInt);
+          result = kMaxInt;
         } else if (val < static_cast<double>(kMinInt)) {
-          shadow_frame.SetVReg(dst, kMinInt);
+          result = kMinInt;
         } else {
-          shadow_frame.SetVReg(dst, val);
+          result = val;
         }
+        shadow_frame.SetVReg(inst->VRegA_12x(), result);
         inst = inst->Next_1xx();
         break;
       }
       case Instruction::DOUBLE_TO_LONG: {
         PREAMBLE();
-        uint32_t dst = inst->VRegA_12x();
         double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
+        int64_t result;
         if (val != val) {
-          shadow_frame.SetVRegLong(dst, 0);
+          result = 0;
         } else if (val > static_cast<double>(kMaxLong)) {
-          shadow_frame.SetVRegLong(dst, kMaxLong);
+          result = kMaxLong;
         } else if (val < static_cast<double>(kMinLong)) {
-          shadow_frame.SetVRegLong(dst, kMinLong);
+          result = kMinLong;
         } else {
-          shadow_frame.SetVRegLong(dst, val);
+          result = val;
         }
+        shadow_frame.SetVRegLong(inst->VRegA_12x(), result);
         inst = inst->Next_1xx();
         break;
       }
diff --git a/src/mirror/array.cc b/src/mirror/array.cc
index e2e63a6..88cd309 100644
--- a/src/mirror/array.cc
+++ b/src/mirror/array.cc
@@ -134,14 +134,12 @@
   return new_array;
 }
 
-bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
+void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
   art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
-  return false;
 }
 
-bool Array::ThrowArrayStoreException(Object* object) const {
+void Array::ThrowArrayStoreException(Object* object) const {
   art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
-  return false;
 }
 
 template<typename T>
diff --git a/src/mirror/array.h b/src/mirror/array.h
index 33c0aeb..98b8ea0 100644
--- a/src/mirror/array.h
+++ b/src/mirror/array.h
@@ -73,15 +73,16 @@
   bool IsValidIndex(int32_t index) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(index < 0 || index >= GetLength())) {
-      return ThrowArrayIndexOutOfBoundsException(index);
+      ThrowArrayIndexOutOfBoundsException(index);
+      return false;
     }
     return true;
   }
 
  protected:
-  bool ThrowArrayIndexOutOfBoundsException(int32_t index) const
+  void ThrowArrayIndexOutOfBoundsException(int32_t index) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool ThrowArrayStoreException(Object* object) const
+  void ThrowArrayStoreException(Object* object) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
diff --git a/src/thread.cc b/src/thread.cc
index 2deb7a5..d6bd8a4 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+
 #include "thread.h"
 
+#include <cutils/trace.h>
 #include <pthread.h>
 #include <signal.h>
 #include <sys/resource.h>
@@ -574,6 +577,13 @@
   }
 }
 
+void Thread::RunCheckpointFunction() {
+  CHECK(checkpoint_function_ != NULL);
+  ATRACE_BEGIN("Checkpoint function");
+  checkpoint_function_->Run(this);
+  ATRACE_END();
+}
+
 bool Thread::RequestCheckpoint(Closure* function) {
   CHECK(!ReadFlag(kCheckpointRequest)) << "Already have a pending checkpoint request";
   checkpoint_function_ = function;
@@ -589,10 +599,12 @@
 
 void Thread::FullSuspendCheck() {
   VLOG(threads) << this << " self-suspending";
+  ATRACE_BEGIN("Full suspend check");
   // Make thread appear suspended to other threads, release mutator_lock_.
   TransitionFromRunnableToSuspended(kSuspended);
   // Transition back to runnable noting requests to suspend, re-acquire share on mutator_lock_.
   TransitionFromSuspendedToRunnable();
+  ATRACE_END();
   VLOG(threads) << this << " self-reviving";
 }
 
diff --git a/src/thread.h b/src/thread.h
index 24987cd..0daf763 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -554,10 +554,7 @@
     held_mutexes_[level] = mutex;
   }
 
-  void RunCheckpointFunction() {
-    CHECK(checkpoint_function_ != NULL);
-    checkpoint_function_->Run(this);
-  }
+  void RunCheckpointFunction();
 
   bool ReadFlag(ThreadFlag flag) const {
     return (state_and_flags_.as_struct.flags & flag) != 0;