Complete compiler portion of exception handling

Will still need much testing once the runtime portions are in place.

Change-Id: I90fc7c1fd89bfae89dfd19a6e422024b6b5454ec
diff --git a/src/thread.cc b/src/thread.cc
index 45ff6dd..d5174ab 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -142,6 +142,110 @@
     UNIMPLEMENTED(FATAL) << "Stack overflow: " << PrettyMethod(method);
 }
 
+// TODO: placeholder
+static void ThrowNullPointerFromCode() {
+    //NOTE: to save code space, this handler must look up caller's Method*
+    UNIMPLEMENTED(FATAL) << "Null pointer exception";
+}
+
+// TODO: placeholder
+static void ThrowDivZeroFromCode() {
+    UNIMPLEMENTED(FATAL) << "Divide by zero";
+}
+
+// TODO: placeholder
+static void ThrowArrayBoundsFromCode(int32_t index, int32_t limit) {
+    UNIMPLEMENTED(FATAL) << "Bound check exception, idx: " << index <<
+        ", limit: " << limit;
+}
+
+// TODO: placeholder
+static void ThrowVerificationErrorFromCode(int32_t src1, int32_t ref) {
+    UNIMPLEMENTED(FATAL) << "Verification error, src1: " << src1 <<
+        " ref: " << ref;
+}
+
+// TODO: placeholder
+static void ThrowNegArraySizeFromCode(int32_t index) {
+    UNIMPLEMENTED(FATAL) << "Negative array size: " << index;
+}
+
+// TODO: placeholder
+static void ThrowInternalErrorFromCode(int32_t errnum) {
+    UNIMPLEMENTED(FATAL) << "Internal error: " << errnum;
+}
+
+// TODO: placeholder
+static void ThrowRuntimeExceptionFromCode(int32_t errnum) {
+    UNIMPLEMENTED(FATAL) << "Internal error: " << errnum;
+}
+
+// TODO: placeholder
+static void ThrowNoSuchMethodFromCode(int32_t method_idx) {
+    UNIMPLEMENTED(FATAL) << "No such method, idx: " << method_idx;
+}
+
+/*
+ * Temporary placeholder.  Should include run-time checks for size
+ * of fill data <= size of array.  If not, throw arrayOutOfBoundsException.
+ * As with other new "FromCode" routines, this should return to the caller
+ * only if no exception has been thrown.
+ *
+ * NOTE: When dealing with a raw dex file, the data to be copied uses
+ * little-endian ordering.  Require that oat2dex do any required swapping
+ * so this routine can get by with a memcpy().
+ *
+ * Format of the data:
+ *  ushort ident = 0x0300   magic value
+ *  ushort width            width of each element in the table
+ *  uint   size             number of elements in the table
+ *  ubyte  data[size*width] table of data values (may contain a single-byte
+ *                          padding at the end)
+ */
+static void HandleFillArrayDataFromCode(Array* array, const uint16_t* table)
+{
+    uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16);
+    uint32_t size_in_bytes = size * table[1];
+    if (static_cast<int32_t>(size) > array->GetLength()) {
+      ThrowArrayBoundsFromCode(array->GetLength(), size);
+    }
+    memcpy((char*)array + art::Array::DataOffset().Int32Value(),
+           (char*)&table[4], size_in_bytes);
+}
+
+// TODO: move to more appropriate location
+/*
+ * Float/double conversion requires clamping to min and max of integer form.  If
+ * target doesn't support this normally, use these.
+ */
+static int64_t D2L(double d)
+{
+    static const double kMaxLong = (double)(int64_t)0x7fffffffffffffffULL;
+    static const double kMinLong = (double)(int64_t)0x8000000000000000ULL;
+    if (d >= kMaxLong)
+        return (int64_t)0x7fffffffffffffffULL;
+    else if (d <= kMinLong)
+        return (int64_t)0x8000000000000000ULL;
+    else if (d != d) // NaN case
+        return 0;
+    else
+        return (int64_t)d;
+}
+
+static int64_t F2L(float f)
+{
+    static const float kMaxLong = (float)(int64_t)0x7fffffffffffffffULL;
+    static const float kMinLong = (float)(int64_t)0x8000000000000000ULL;
+    if (f >= kMaxLong)
+        return (int64_t)0x7fffffffffffffffULL;
+    else if (f <= kMinLong)
+        return (int64_t)0x8000000000000000ULL;
+    else if (f != f) // NaN case
+        return 0;
+    else
+        return (int64_t)f;
+}
+
 void Thread::InitFunctionPointers() {
 #if defined(__arm__)
   pShlLong = art_shl_long;
@@ -195,6 +299,14 @@
   pFindFieldFromCode = Field::FindFieldFromCode;
   pCheckSuspendFromCode = CheckSuspendFromCode;
   pStackOverflowFromCode = StackOverflowFromCode;
+  pThrowNullPointerFromCode = ThrowNullPointerFromCode;
+  pThrowArrayBoundsFromCode = ThrowArrayBoundsFromCode;
+  pThrowDivZeroFromCode = ThrowDivZeroFromCode;
+  pThrowVerificationErrorFromCode = ThrowVerificationErrorFromCode;
+  pThrowNegArraySizeFromCode = ThrowNegArraySizeFromCode;
+  pThrowRuntimeExceptionFromCode = ThrowRuntimeExceptionFromCode;
+  pThrowInternalErrorFromCode = ThrowInternalErrorFromCode;
+  pThrowNoSuchMethodFromCode = ThrowNoSuchMethodFromCode;
   pDebugMe = DebugMe;
 }