Improved Job performance by using reference equality on state, added deferred & channel tests for bad class with exceptions on equals
diff --git a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
index 5040d34..ccbb56a 100644
--- a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
+++ b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt
@@ -250,7 +250,7 @@
 
             }
             // otherwise -- do nothing (Empty)
-            else -> check(expect == Empty)
+            else -> check(expect === Empty)
         }
         // #4. Do other (overridable) processing after completion handlers
         completionException?.let { handleCompletionException(it) }
@@ -291,7 +291,7 @@
                 // LIST -- a list of completion handlers
                 state is NodeList -> {
                     val node = nodeCache ?: makeNode(handler).also { nodeCache = it }
-                    if (state.addLastIf(node) { this.state == state }) return node
+                    if (state.addLastIf(node) { this.state === state }) return node
                 }
                 // is not active anymore
                 else -> {
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/DeferTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/DeferTest.kt
index 2131a25..a98b6f0 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/DeferTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/DeferTest.kt
@@ -2,6 +2,7 @@
 
 import org.junit.Test
 import java.io.IOException
+import kotlin.test.assertTrue
 
 class DeferTest : TestBase() {
     @Test
@@ -73,4 +74,21 @@
         yield() // yield to both waiters
         finish(13)
     }
+
+    class BadClass {
+        override fun equals(other: Any?): Boolean = error("equals")
+        override fun hashCode(): Int = error("hashCode")
+        override fun toString(): String = error("toString")
+    }
+
+    @Test
+    fun testDeferBadClass() = runBlocking {
+        val bad = BadClass()
+        val d = defer(context) {
+            expect(1)
+            bad
+        }
+        assertTrue(d.await() === bad)
+        finish(2)
+    }
 }
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt
index 741f5a9..a0ef4d1 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/RendezvousChannelTest.kt
@@ -229,4 +229,21 @@
         }
         finish(10)
     }
+
+    class BadClass {
+        override fun equals(other: Any?): Boolean = error("equals")
+        override fun hashCode(): Int = error("hashCode")
+        override fun toString(): String = error("toString")
+    }
+
+    @Test
+    fun testDeferBadClass() = runBlocking {
+        val bad = BadClass()
+        val c = buildChannel(context) {
+            expect(1)
+            send(bad)
+        }
+        assertTrue(c.receive() === bad)
+        finish(2)
+    }
 }
\ No newline at end of file