diff --git a/BUILD b/BUILD
index 7c01d6b0bbcc5ca882ff9deaa4bdfe2222fb05fe..262b2c6ec00da68a29a1349efbfed06ecc6330ea 100644
--- a/BUILD
+++ b/BUILD
@@ -44,6 +44,7 @@ package(default_visibility = ["//visibility:public"])
 cc_library(
   name = "gpr",
   srcs = [
+    "src/core/profiling/timers.h",
     "src/core/support/block_annotate.h",
     "src/core/support/env.h",
     "src/core/support/file.h",
@@ -53,6 +54,8 @@ cc_library(
     "src/core/support/string_win32.h",
     "src/core/support/thd_internal.h",
     "src/core/support/time_precise.h",
+    "src/core/profiling/basic_timers.c",
+    "src/core/profiling/stap_timers.c",
     "src/core/support/alloc.c",
     "src/core/support/cmdline.c",
     "src/core/support/cpu_iphone.c",
@@ -218,12 +221,12 @@ cc_library(
     "src/core/json/json_common.h",
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
-    "src/core/profiling/timers.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/api_trace.h",
     "src/core/surface/byte_buffer_queue.h",
     "src/core/surface/call.h",
+    "src/core/surface/call_test_only.h",
     "src/core/surface/channel.h",
     "src/core/surface/completion_queue.h",
     "src/core/surface/event_string.h",
@@ -356,8 +359,6 @@ cc_library(
     "src/core/json/json_reader.c",
     "src/core/json/json_string.c",
     "src/core/json/json_writer.c",
-    "src/core/profiling/basic_timers.c",
-    "src/core/profiling/stap_timers.c",
     "src/core/surface/api_trace.c",
     "src/core/surface/byte_buffer.c",
     "src/core/surface/byte_buffer_queue.c",
@@ -504,12 +505,12 @@ cc_library(
     "src/core/json/json_common.h",
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
-    "src/core/profiling/timers.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/api_trace.h",
     "src/core/surface/byte_buffer_queue.h",
     "src/core/surface/call.h",
+    "src/core/surface/call_test_only.h",
     "src/core/surface/channel.h",
     "src/core/surface/completion_queue.h",
     "src/core/surface/event_string.h",
@@ -622,8 +623,6 @@ cc_library(
     "src/core/json/json_reader.c",
     "src/core/json/json_string.c",
     "src/core/json/json_writer.c",
-    "src/core/profiling/basic_timers.c",
-    "src/core/profiling/stap_timers.c",
     "src/core/surface/api_trace.c",
     "src/core/surface/byte_buffer.c",
     "src/core/surface/byte_buffer_queue.c",
@@ -961,6 +960,8 @@ cc_library(
 objc_library(
   name = "gpr_objc",
   srcs = [
+    "src/core/profiling/basic_timers.c",
+    "src/core/profiling/stap_timers.c",
     "src/core/support/alloc.c",
     "src/core/support/cmdline.c",
     "src/core/support/cpu_iphone.c",
@@ -1028,6 +1029,7 @@ objc_library(
     "include/grpc/support/tls_msvc.h",
     "include/grpc/support/tls_pthread.h",
     "include/grpc/support/useful.h",
+    "src/core/profiling/timers.h",
     "src/core/support/block_annotate.h",
     "src/core/support/env.h",
     "src/core/support/file.h",
@@ -1147,8 +1149,6 @@ objc_library(
     "src/core/json/json_reader.c",
     "src/core/json/json_string.c",
     "src/core/json/json_writer.c",
-    "src/core/profiling/basic_timers.c",
-    "src/core/profiling/stap_timers.c",
     "src/core/surface/api_trace.c",
     "src/core/surface/byte_buffer.c",
     "src/core/surface/byte_buffer_queue.c",
@@ -1292,12 +1292,12 @@ objc_library(
     "src/core/json/json_common.h",
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
-    "src/core/profiling/timers.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/api_trace.h",
     "src/core/surface/byte_buffer_queue.h",
     "src/core/surface/call.h",
+    "src/core/surface/call_test_only.h",
     "src/core/surface/channel.h",
     "src/core/surface/completion_queue.h",
     "src/core/surface/event_string.h",
diff --git a/Makefile b/Makefile
index 6d6dc71accee69358abb3ce457311182287fb91d..788fdb52155e870fded2cb2d1b00304826584cfa 100644
--- a/Makefile
+++ b/Makefile
@@ -3893,6 +3893,8 @@ clean:
 
 
 LIBGPR_SRC = \
+    src/core/profiling/basic_timers.c \
+    src/core/profiling/stap_timers.c \
     src/core/support/alloc.c \
     src/core/support/cmdline.c \
     src/core/support/cpu_iphone.c \
@@ -4118,8 +4120,6 @@ LIBGRPC_SRC = \
     src/core/json/json_reader.c \
     src/core/json/json_string.c \
     src/core/json/json_writer.c \
-    src/core/profiling/basic_timers.c \
-    src/core/profiling/stap_timers.c \
     src/core/surface/api_trace.c \
     src/core/surface/byte_buffer.c \
     src/core/surface/byte_buffer_queue.c \
@@ -4400,8 +4400,6 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/json/json_reader.c \
     src/core/json/json_string.c \
     src/core/json/json_writer.c \
-    src/core/profiling/basic_timers.c \
-    src/core/profiling/stap_timers.c \
     src/core/surface/api_trace.c \
     src/core/surface/byte_buffer.c \
     src/core/surface/byte_buffer_queue.c \
diff --git a/binding.gyp b/binding.gyp
index 2a5cb1ced496d63722dd730c486c9e7919c9108f..392835c7721cc41b353d30ec512e2cd645741e97 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -1,3 +1,10 @@
+# GRPC Node gyp file
+# This currently builds the Node extension and dependencies
+# This file has been automatically generated from a template file.
+# Please look at the templates directory instead.
+# This file can be regenerated from the template by running
+# tools/buildgen/generate_projects.sh
+
 # Copyright 2015, Google Inc.
 # All rights reserved.
 #
@@ -26,11 +33,234 @@
 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Some of this file is built with the help of
+# https://n8.io/converting-a-c-library-to-gyp/
 {
-  "variables" : {
+  'variables': {
     'config': '<!(echo $CONFIG)'
   },
-  "targets" : [
+  # TODO: Finish windows support
+  'target_defaults': {
+      # Empirically, Node only exports ALPN symbols if its major version is >0.
+      # io.js always reports versions >0 and always exports ALPN symbols.
+      # Therefore, Node's major version will be truthy if and only if it
+      # supports ALPN. The output of "node -v" is v[major].[minor].[patch],
+      # like "v4.1.1" in a recent version. We use grep to extract just the
+      # major version. "4", would be the output for the example.
+    'defines': [
+      'TSI_OPENSSL_ALPN_SUPPORT=<!(node -v | grep -oP "(?<=v)(\d+)(?=\.\d+\.\d+)")'
+    ],
+    'include_dirs': [
+      '.',
+      'include'
+    ]
+  },
+  'targets': [
+    {
+      'target_name': 'gpr',
+      'product_prefix': 'lib',
+      'type': 'static_library',
+      'dependencies': [
+      ],
+      'sources': [
+        'src/core/support/alloc.c',
+        'src/core/support/cmdline.c',
+        'src/core/support/cpu_iphone.c',
+        'src/core/support/cpu_linux.c',
+        'src/core/support/cpu_posix.c',
+        'src/core/support/cpu_windows.c',
+        'src/core/support/env_linux.c',
+        'src/core/support/env_posix.c',
+        'src/core/support/env_win32.c',
+        'src/core/support/file.c',
+        'src/core/support/file_posix.c',
+        'src/core/support/file_win32.c',
+        'src/core/support/histogram.c',
+        'src/core/support/host_port.c',
+        'src/core/support/log.c',
+        'src/core/support/log_android.c',
+        'src/core/support/log_linux.c',
+        'src/core/support/log_posix.c',
+        'src/core/support/log_win32.c',
+        'src/core/support/murmur_hash.c',
+        'src/core/support/slice.c',
+        'src/core/support/slice_buffer.c',
+        'src/core/support/stack_lockfree.c',
+        'src/core/support/string.c',
+        'src/core/support/string_posix.c',
+        'src/core/support/string_win32.c',
+        'src/core/support/subprocess_posix.c',
+        'src/core/support/sync.c',
+        'src/core/support/sync_posix.c',
+        'src/core/support/sync_win32.c',
+        'src/core/support/thd.c',
+        'src/core/support/thd_posix.c',
+        'src/core/support/thd_win32.c',
+        'src/core/support/time.c',
+        'src/core/support/time_posix.c',
+        'src/core/support/time_win32.c',
+        'src/core/support/tls_pthread.c',
+      ],
+    },
+    {
+      'target_name': 'grpc',
+      'product_prefix': 'lib',
+      'type': 'static_library',
+      'dependencies': [
+        'gpr',
+      ],
+      'sources': [
+        'src/core/httpcli/httpcli_security_connector.c',
+        'src/core/security/base64.c',
+        'src/core/security/client_auth_filter.c',
+        'src/core/security/credentials.c',
+        'src/core/security/credentials_metadata.c',
+        'src/core/security/credentials_posix.c',
+        'src/core/security/credentials_win32.c',
+        'src/core/security/google_default_credentials.c',
+        'src/core/security/handshake.c',
+        'src/core/security/json_token.c',
+        'src/core/security/jwt_verifier.c',
+        'src/core/security/secure_endpoint.c',
+        'src/core/security/security_connector.c',
+        'src/core/security/security_context.c',
+        'src/core/security/server_auth_filter.c',
+        'src/core/security/server_secure_chttp2.c',
+        'src/core/surface/init_secure.c',
+        'src/core/surface/secure_channel_create.c',
+        'src/core/tsi/fake_transport_security.c',
+        'src/core/tsi/ssl_transport_security.c',
+        'src/core/tsi/transport_security.c',
+        'src/core/census/grpc_context.c',
+        'src/core/census/grpc_filter.c',
+        'src/core/channel/channel_args.c',
+        'src/core/channel/channel_stack.c',
+        'src/core/channel/client_channel.c',
+        'src/core/channel/compress_filter.c',
+        'src/core/channel/connected_channel.c',
+        'src/core/channel/http_client_filter.c',
+        'src/core/channel/http_server_filter.c',
+        'src/core/channel/noop_filter.c',
+        'src/core/client_config/client_config.c',
+        'src/core/client_config/connector.c',
+        'src/core/client_config/lb_policies/pick_first.c',
+        'src/core/client_config/lb_policies/round_robin.c',
+        'src/core/client_config/lb_policy.c',
+        'src/core/client_config/lb_policy_factory.c',
+        'src/core/client_config/lb_policy_registry.c',
+        'src/core/client_config/resolver.c',
+        'src/core/client_config/resolver_factory.c',
+        'src/core/client_config/resolver_registry.c',
+        'src/core/client_config/resolvers/dns_resolver.c',
+        'src/core/client_config/resolvers/sockaddr_resolver.c',
+        'src/core/client_config/subchannel.c',
+        'src/core/client_config/subchannel_factory.c',
+        'src/core/client_config/subchannel_factory_decorators/add_channel_arg.c',
+        'src/core/client_config/subchannel_factory_decorators/merge_channel_args.c',
+        'src/core/client_config/uri_parser.c',
+        'src/core/compression/algorithm.c',
+        'src/core/compression/message_compress.c',
+        'src/core/debug/trace.c',
+        'src/core/httpcli/format_request.c',
+        'src/core/httpcli/httpcli.c',
+        'src/core/httpcli/parser.c',
+        'src/core/iomgr/alarm.c',
+        'src/core/iomgr/alarm_heap.c',
+        'src/core/iomgr/closure.c',
+        'src/core/iomgr/endpoint.c',
+        'src/core/iomgr/endpoint_pair_posix.c',
+        'src/core/iomgr/endpoint_pair_windows.c',
+        'src/core/iomgr/exec_ctx.c',
+        'src/core/iomgr/fd_posix.c',
+        'src/core/iomgr/iocp_windows.c',
+        'src/core/iomgr/iomgr.c',
+        'src/core/iomgr/iomgr_posix.c',
+        'src/core/iomgr/iomgr_windows.c',
+        'src/core/iomgr/pollset_multipoller_with_epoll.c',
+        'src/core/iomgr/pollset_multipoller_with_poll_posix.c',
+        'src/core/iomgr/pollset_posix.c',
+        'src/core/iomgr/pollset_set_posix.c',
+        'src/core/iomgr/pollset_set_windows.c',
+        'src/core/iomgr/pollset_windows.c',
+        'src/core/iomgr/resolve_address_posix.c',
+        'src/core/iomgr/resolve_address_windows.c',
+        'src/core/iomgr/sockaddr_utils.c',
+        'src/core/iomgr/socket_utils_common_posix.c',
+        'src/core/iomgr/socket_utils_linux.c',
+        'src/core/iomgr/socket_utils_posix.c',
+        'src/core/iomgr/socket_windows.c',
+        'src/core/iomgr/tcp_client_posix.c',
+        'src/core/iomgr/tcp_client_windows.c',
+        'src/core/iomgr/tcp_posix.c',
+        'src/core/iomgr/tcp_server_posix.c',
+        'src/core/iomgr/tcp_server_windows.c',
+        'src/core/iomgr/tcp_windows.c',
+        'src/core/iomgr/time_averaged_stats.c',
+        'src/core/iomgr/udp_server.c',
+        'src/core/iomgr/wakeup_fd_eventfd.c',
+        'src/core/iomgr/wakeup_fd_nospecial.c',
+        'src/core/iomgr/wakeup_fd_pipe.c',
+        'src/core/iomgr/wakeup_fd_posix.c',
+        'src/core/iomgr/workqueue_posix.c',
+        'src/core/iomgr/workqueue_windows.c',
+        'src/core/json/json.c',
+        'src/core/json/json_reader.c',
+        'src/core/json/json_string.c',
+        'src/core/json/json_writer.c',
+        'src/core/profiling/basic_timers.c',
+        'src/core/profiling/stap_timers.c',
+        'src/core/surface/api_trace.c',
+        'src/core/surface/byte_buffer.c',
+        'src/core/surface/byte_buffer_queue.c',
+        'src/core/surface/byte_buffer_reader.c',
+        'src/core/surface/call.c',
+        'src/core/surface/call_details.c',
+        'src/core/surface/call_log_batch.c',
+        'src/core/surface/channel.c',
+        'src/core/surface/channel_connectivity.c',
+        'src/core/surface/channel_create.c',
+        'src/core/surface/completion_queue.c',
+        'src/core/surface/event_string.c',
+        'src/core/surface/init.c',
+        'src/core/surface/lame_client.c',
+        'src/core/surface/metadata_array.c',
+        'src/core/surface/server.c',
+        'src/core/surface/server_chttp2.c',
+        'src/core/surface/server_create.c',
+        'src/core/surface/version.c',
+        'src/core/transport/chttp2/alpn.c',
+        'src/core/transport/chttp2/bin_encoder.c',
+        'src/core/transport/chttp2/frame_data.c',
+        'src/core/transport/chttp2/frame_goaway.c',
+        'src/core/transport/chttp2/frame_ping.c',
+        'src/core/transport/chttp2/frame_rst_stream.c',
+        'src/core/transport/chttp2/frame_settings.c',
+        'src/core/transport/chttp2/frame_window_update.c',
+        'src/core/transport/chttp2/hpack_parser.c',
+        'src/core/transport/chttp2/hpack_table.c',
+        'src/core/transport/chttp2/huffsyms.c',
+        'src/core/transport/chttp2/incoming_metadata.c',
+        'src/core/transport/chttp2/parsing.c',
+        'src/core/transport/chttp2/status_conversion.c',
+        'src/core/transport/chttp2/stream_encoder.c',
+        'src/core/transport/chttp2/stream_lists.c',
+        'src/core/transport/chttp2/stream_map.c',
+        'src/core/transport/chttp2/timeout_encoding.c',
+        'src/core/transport/chttp2/varint.c',
+        'src/core/transport/chttp2/writing.c',
+        'src/core/transport/chttp2_transport.c',
+        'src/core/transport/connectivity_state.c',
+        'src/core/transport/metadata.c',
+        'src/core/transport/stream_op.c',
+        'src/core/transport/transport.c',
+        'src/core/transport/transport_op_string.c',
+        'src/core/census/context.c',
+        'src/core/census/initialize.c',
+        'src/core/census/operation.c',
+        'src/core/census/tracing.c',
+      ],
+    },
     {
       'include_dirs': [
         "<!(node -e \"require('nan')\")"
@@ -88,7 +318,7 @@
         "src/node/ext/timeval.cc"
       ],
       "dependencies": [
-        "grpc.gyp:grpc"
+        "grpc"
       ]
     }
   ]
diff --git a/build.yaml b/build.yaml
index 503d7a80c75590a9f2ef2ad1ab6acfb81fb10c85..9fd667df7f09119db79a307889ff7b2ba19ea00a 100644
--- a/build.yaml
+++ b/build.yaml
@@ -177,12 +177,12 @@ filegroups:
   - src/core/json/json_common.h
   - src/core/json/json_reader.h
   - src/core/json/json_writer.h
-  - src/core/profiling/timers.h
   - src/core/statistics/census_interface.h
   - src/core/statistics/census_rpc_stats.h
   - src/core/surface/api_trace.h
   - src/core/surface/byte_buffer_queue.h
   - src/core/surface/call.h
+  - src/core/surface/call_test_only.h
   - src/core/surface/channel.h
   - src/core/surface/completion_queue.h
   - src/core/surface/event_string.h
@@ -292,8 +292,6 @@ filegroups:
   - src/core/json/json_reader.c
   - src/core/json/json_string.c
   - src/core/json/json_writer.c
-  - src/core/profiling/basic_timers.c
-  - src/core/profiling/stap_timers.c
   - src/core/surface/api_trace.c
   - src/core/surface/byte_buffer.c
   - src/core/surface/byte_buffer_queue.c
@@ -392,6 +390,7 @@ libs:
   - include/grpc/support/tls_pthread.h
   - include/grpc/support/useful.h
   headers:
+  - src/core/profiling/timers.h
   - src/core/support/block_annotate.h
   - src/core/support/env.h
   - src/core/support/file.h
@@ -402,6 +401,8 @@ libs:
   - src/core/support/thd_internal.h
   - src/core/support/time_precise.h
   src:
+  - src/core/profiling/basic_timers.c
+  - src/core/profiling/stap_timers.c
   - src/core/support/alloc.c
   - src/core/support/cmdline.c
   - src/core/support/cpu_iphone.c
diff --git a/gRPC.podspec b/gRPC.podspec
index 5b93281b4179a04e75953e1c723f8105d801faf0..66b49a83fe0844a2f0311a9c3e7c6b121420de84 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -63,7 +63,8 @@ Pod::Spec.new do |s|
 
   # Core cross-platform gRPC library, written in C.
   s.subspec 'C-Core' do |ss|
-    ss.source_files = 'src/core/support/block_annotate.h',
+    ss.source_files = 'src/core/profiling/timers.h',
+                      'src/core/support/block_annotate.h',
                       'src/core/support/env.h',
                       'src/core/support/file.h',
                       'src/core/support/murmur_hash.h',
@@ -99,6 +100,8 @@ Pod::Spec.new do |s|
                       'grpc/support/tls_msvc.h',
                       'grpc/support/tls_pthread.h',
                       'grpc/support/useful.h',
+                      'src/core/profiling/basic_timers.c',
+                      'src/core/profiling/stap_timers.c',
                       'src/core/support/alloc.c',
                       'src/core/support/cmdline.c',
                       'src/core/support/cpu_iphone.c',
@@ -222,12 +225,12 @@ Pod::Spec.new do |s|
                       'src/core/json/json_common.h',
                       'src/core/json/json_reader.h',
                       'src/core/json/json_writer.h',
-                      'src/core/profiling/timers.h',
                       'src/core/statistics/census_interface.h',
                       'src/core/statistics/census_rpc_stats.h',
                       'src/core/surface/api_trace.h',
                       'src/core/surface/byte_buffer_queue.h',
                       'src/core/surface/call.h',
+                      'src/core/surface/call_test_only.h',
                       'src/core/surface/channel.h',
                       'src/core/surface/completion_queue.h',
                       'src/core/surface/event_string.h',
@@ -367,8 +370,6 @@ Pod::Spec.new do |s|
                       'src/core/json/json_reader.c',
                       'src/core/json/json_string.c',
                       'src/core/json/json_writer.c',
-                      'src/core/profiling/basic_timers.c',
-                      'src/core/profiling/stap_timers.c',
                       'src/core/surface/api_trace.c',
                       'src/core/surface/byte_buffer.c',
                       'src/core/surface/byte_buffer_queue.c',
@@ -419,7 +420,8 @@ Pod::Spec.new do |s|
                       'src/core/census/operation.c',
                       'src/core/census/tracing.c'
 
-    ss.private_header_files = 'src/core/support/block_annotate.h',
+    ss.private_header_files = 'src/core/profiling/timers.h',
+                              'src/core/support/block_annotate.h',
                               'src/core/support/env.h',
                               'src/core/support/file.h',
                               'src/core/support/murmur_hash.h',
@@ -513,12 +515,12 @@ Pod::Spec.new do |s|
                               'src/core/json/json_common.h',
                               'src/core/json/json_reader.h',
                               'src/core/json/json_writer.h',
-                              'src/core/profiling/timers.h',
                               'src/core/statistics/census_interface.h',
                               'src/core/statistics/census_rpc_stats.h',
                               'src/core/surface/api_trace.h',
                               'src/core/surface/byte_buffer_queue.h',
                               'src/core/surface/call.h',
+                              'src/core/surface/call_test_only.h',
                               'src/core/surface/channel.h',
                               'src/core/surface/completion_queue.h',
                               'src/core/surface/event_string.h',
diff --git a/grpc.gyp b/grpc.gyp
deleted file mode 100644
index 668a6e12f324ec6f280b2db5ad395f7f4b177094..0000000000000000000000000000000000000000
--- a/grpc.gyp
+++ /dev/null
@@ -1,296 +0,0 @@
-# GRPC gyp file
-# This currently builds C code.
-# This file has been automatically generated from a template file.
-# Please look at the templates directory instead.
-# This file can be regenerated from the template by running
-# tools/buildgen/generate_projects.sh
-
-# Copyright 2015, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Some of this file is built with the help of
-# https://n8.io/converting-a-c-library-to-gyp/
-{
-  # TODO: Finish windows support
-  'target_defaults': {
-    'default_configuration': 'Debug',
-    'configurations': {
-      'Debug': {
-        'defines': [ 'DEBUG', '_DEBUG' ],
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'RuntimeLibrary': 1, # static debug
-          },
-        },
-      },
-      'Release': {
-        'defines': [ 'NDEBUG' ],
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'RuntimeLibrary': 0, # static release
-          },
-        },
-      }
-    },
-    'msvs_settings': {
-      'VCLinkerTool': {
-        'GenerateDebugInformation': 'true',
-      },
-    },
-    # TODO: Add fallback for Windows, and if pkg-config is not available
-    'defines': [
-      'TSI_OPENSSL_ALPN_SUPPORT=<!(pkg-config --atleast-version=1.0.2 openssl >/dev/null 2>&1 && echo 1 || echo 0)'
-    ],
-    'include_dirs': [
-      '.',
-      'include'
-    ],
-    # TODO: Check for libraries with pkg-config
-    'libraries': [
-      '-lcrypto',
-      '-lssl',
-      '-ldl',
-      '-lpthread',
-      '-lz'
-    ],
-    'direct_dependent_settings': {
-      'include_dirs': [
-        '.',
-        'include'
-      ],
-    }
-  },
-  'targets': [
-    {
-      'target_name': 'gpr',
-      'product_prefix': 'lib',
-      'type': 'static_library',
-      'dependencies': [
-      ],
-      'sources': [
-        'src/core/support/alloc.c',
-        'src/core/support/cmdline.c',
-        'src/core/support/cpu_iphone.c',
-        'src/core/support/cpu_linux.c',
-        'src/core/support/cpu_posix.c',
-        'src/core/support/cpu_windows.c',
-        'src/core/support/env_linux.c',
-        'src/core/support/env_posix.c',
-        'src/core/support/env_win32.c',
-        'src/core/support/file.c',
-        'src/core/support/file_posix.c',
-        'src/core/support/file_win32.c',
-        'src/core/support/histogram.c',
-        'src/core/support/host_port.c',
-        'src/core/support/log.c',
-        'src/core/support/log_android.c',
-        'src/core/support/log_linux.c',
-        'src/core/support/log_posix.c',
-        'src/core/support/log_win32.c',
-        'src/core/support/murmur_hash.c',
-        'src/core/support/slice.c',
-        'src/core/support/slice_buffer.c',
-        'src/core/support/stack_lockfree.c',
-        'src/core/support/string.c',
-        'src/core/support/string_posix.c',
-        'src/core/support/string_win32.c',
-        'src/core/support/subprocess_posix.c',
-        'src/core/support/sync.c',
-        'src/core/support/sync_posix.c',
-        'src/core/support/sync_win32.c',
-        'src/core/support/thd.c',
-        'src/core/support/thd_posix.c',
-        'src/core/support/thd_win32.c',
-        'src/core/support/time.c',
-        'src/core/support/time_posix.c',
-        'src/core/support/time_precise.c',
-        'src/core/support/time_win32.c',
-        'src/core/support/tls_pthread.c',
-      ],
-    },
-    {
-      'target_name': 'grpc',
-      'product_prefix': 'lib',
-      'type': 'static_library',
-      'dependencies': [
-        'gpr',
-      ],
-      'sources': [
-        'src/core/httpcli/httpcli_security_connector.c',
-        'src/core/security/base64.c',
-        'src/core/security/client_auth_filter.c',
-        'src/core/security/credentials.c',
-        'src/core/security/credentials_metadata.c',
-        'src/core/security/credentials_posix.c',
-        'src/core/security/credentials_win32.c',
-        'src/core/security/google_default_credentials.c',
-        'src/core/security/handshake.c',
-        'src/core/security/json_token.c',
-        'src/core/security/jwt_verifier.c',
-        'src/core/security/secure_endpoint.c',
-        'src/core/security/security_connector.c',
-        'src/core/security/security_context.c',
-        'src/core/security/server_auth_filter.c',
-        'src/core/security/server_secure_chttp2.c',
-        'src/core/surface/init_secure.c',
-        'src/core/surface/secure_channel_create.c',
-        'src/core/tsi/fake_transport_security.c',
-        'src/core/tsi/ssl_transport_security.c',
-        'src/core/tsi/transport_security.c',
-        'src/core/census/grpc_context.c',
-        'src/core/census/grpc_filter.c',
-        'src/core/channel/channel_args.c',
-        'src/core/channel/channel_stack.c',
-        'src/core/channel/client_channel.c',
-        'src/core/channel/compress_filter.c',
-        'src/core/channel/connected_channel.c',
-        'src/core/channel/http_client_filter.c',
-        'src/core/channel/http_server_filter.c',
-        'src/core/channel/noop_filter.c',
-        'src/core/client_config/client_config.c',
-        'src/core/client_config/connector.c',
-        'src/core/client_config/lb_policies/pick_first.c',
-        'src/core/client_config/lb_policies/round_robin.c',
-        'src/core/client_config/lb_policy.c',
-        'src/core/client_config/lb_policy_factory.c',
-        'src/core/client_config/lb_policy_registry.c',
-        'src/core/client_config/resolver.c',
-        'src/core/client_config/resolver_factory.c',
-        'src/core/client_config/resolver_registry.c',
-        'src/core/client_config/resolvers/dns_resolver.c',
-        'src/core/client_config/resolvers/sockaddr_resolver.c',
-        'src/core/client_config/subchannel.c',
-        'src/core/client_config/subchannel_factory.c',
-        'src/core/client_config/subchannel_factory_decorators/add_channel_arg.c',
-        'src/core/client_config/subchannel_factory_decorators/merge_channel_args.c',
-        'src/core/client_config/uri_parser.c',
-        'src/core/compression/algorithm.c',
-        'src/core/compression/message_compress.c',
-        'src/core/debug/trace.c',
-        'src/core/httpcli/format_request.c',
-        'src/core/httpcli/httpcli.c',
-        'src/core/httpcli/parser.c',
-        'src/core/iomgr/alarm.c',
-        'src/core/iomgr/alarm_heap.c',
-        'src/core/iomgr/closure.c',
-        'src/core/iomgr/endpoint.c',
-        'src/core/iomgr/endpoint_pair_posix.c',
-        'src/core/iomgr/endpoint_pair_windows.c',
-        'src/core/iomgr/exec_ctx.c',
-        'src/core/iomgr/fd_posix.c',
-        'src/core/iomgr/iocp_windows.c',
-        'src/core/iomgr/iomgr.c',
-        'src/core/iomgr/iomgr_posix.c',
-        'src/core/iomgr/iomgr_windows.c',
-        'src/core/iomgr/pollset_multipoller_with_epoll.c',
-        'src/core/iomgr/pollset_multipoller_with_poll_posix.c',
-        'src/core/iomgr/pollset_posix.c',
-        'src/core/iomgr/pollset_set_posix.c',
-        'src/core/iomgr/pollset_set_windows.c',
-        'src/core/iomgr/pollset_windows.c',
-        'src/core/iomgr/resolve_address_posix.c',
-        'src/core/iomgr/resolve_address_windows.c',
-        'src/core/iomgr/sockaddr_utils.c',
-        'src/core/iomgr/socket_utils_common_posix.c',
-        'src/core/iomgr/socket_utils_linux.c',
-        'src/core/iomgr/socket_utils_posix.c',
-        'src/core/iomgr/socket_windows.c',
-        'src/core/iomgr/tcp_client_posix.c',
-        'src/core/iomgr/tcp_client_windows.c',
-        'src/core/iomgr/tcp_posix.c',
-        'src/core/iomgr/tcp_server_posix.c',
-        'src/core/iomgr/tcp_server_windows.c',
-        'src/core/iomgr/tcp_windows.c',
-        'src/core/iomgr/time_averaged_stats.c',
-        'src/core/iomgr/udp_server.c',
-        'src/core/iomgr/wakeup_fd_eventfd.c',
-        'src/core/iomgr/wakeup_fd_nospecial.c',
-        'src/core/iomgr/wakeup_fd_pipe.c',
-        'src/core/iomgr/wakeup_fd_posix.c',
-        'src/core/iomgr/workqueue_posix.c',
-        'src/core/iomgr/workqueue_windows.c',
-        'src/core/json/json.c',
-        'src/core/json/json_reader.c',
-        'src/core/json/json_string.c',
-        'src/core/json/json_writer.c',
-        'src/core/profiling/basic_timers.c',
-        'src/core/profiling/stap_timers.c',
-        'src/core/surface/api_trace.c',
-        'src/core/surface/byte_buffer.c',
-        'src/core/surface/byte_buffer_queue.c',
-        'src/core/surface/byte_buffer_reader.c',
-        'src/core/surface/call.c',
-        'src/core/surface/call_details.c',
-        'src/core/surface/call_log_batch.c',
-        'src/core/surface/channel.c',
-        'src/core/surface/channel_connectivity.c',
-        'src/core/surface/channel_create.c',
-        'src/core/surface/completion_queue.c',
-        'src/core/surface/event_string.c',
-        'src/core/surface/init.c',
-        'src/core/surface/lame_client.c',
-        'src/core/surface/metadata_array.c',
-        'src/core/surface/server.c',
-        'src/core/surface/server_chttp2.c',
-        'src/core/surface/server_create.c',
-        'src/core/surface/version.c',
-        'src/core/transport/chttp2/alpn.c',
-        'src/core/transport/chttp2/bin_encoder.c',
-        'src/core/transport/chttp2/frame_data.c',
-        'src/core/transport/chttp2/frame_goaway.c',
-        'src/core/transport/chttp2/frame_ping.c',
-        'src/core/transport/chttp2/frame_rst_stream.c',
-        'src/core/transport/chttp2/frame_settings.c',
-        'src/core/transport/chttp2/frame_window_update.c',
-        'src/core/transport/chttp2/hpack_parser.c',
-        'src/core/transport/chttp2/hpack_table.c',
-        'src/core/transport/chttp2/huffsyms.c',
-        'src/core/transport/chttp2/incoming_metadata.c',
-        'src/core/transport/chttp2/parsing.c',
-        'src/core/transport/chttp2/status_conversion.c',
-        'src/core/transport/chttp2/stream_encoder.c',
-        'src/core/transport/chttp2/stream_lists.c',
-        'src/core/transport/chttp2/stream_map.c',
-        'src/core/transport/chttp2/timeout_encoding.c',
-        'src/core/transport/chttp2/varint.c',
-        'src/core/transport/chttp2/writing.c',
-        'src/core/transport/chttp2_transport.c',
-        'src/core/transport/connectivity_state.c',
-        'src/core/transport/metadata.c',
-        'src/core/transport/stream_op.c',
-        'src/core/transport/transport.c',
-        'src/core/transport/transport_op_string.c',
-        'src/core/census/context.c',
-        'src/core/census/initialize.c',
-        'src/core/census/operation.c',
-        'src/core/census/tracing.c',
-      ],
-    },
-  ]
-}
diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h
index 434dd6de874e1988dabb7c8d576e4ec0e19c49ad..f98038da520ea7249fe002cf0d8e54f081ed196c 100644
--- a/include/grpc/support/port_platform.h
+++ b/include/grpc/support/port_platform.h
@@ -181,6 +181,7 @@
 #ifndef _BSD_SOURCE
 #define _BSD_SOURCE
 #endif
+#define GPR_FORBID_UNREACHABLE_CODE
 #define GPR_MSG_IOVLEN_TYPE int
 #if TARGET_OS_IPHONE
 #define GPR_PLATFORM_STRING "ios"
@@ -336,4 +337,15 @@ typedef uintptr_t gpr_uintptr;
 #endif
 #endif
 
+#ifdef GPR_FORBID_UNREACHABLE_CODE
+#define GPR_UNREACHABLE_CODE(STATEMENT)
+#else
+#define GPR_UNREACHABLE_CODE(STATEMENT)             \
+  do {                                              \
+    gpr_log(GPR_ERROR, "Should never reach here."); \
+    abort();                                        \
+    STATEMENT;                                      \
+  } while (0)
+#endif /* GPR_FORBID_UNREACHABLE_CODE */
+
 #endif /* GRPC_SUPPORT_PORT_PLATFORM_H */
diff --git a/package.json b/package.json
index 0eea3475a34b2b1e46ce7ca3ba3b506a2fc72e58..c624c45107edf5735a289c324d627a9de5f76c1e 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
     "lib": "src/node/src"
   },
   "scripts": {
-    "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/examples src/node/interop src/node/index.js",
+    "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js",
     "test": "./node_modules/.bin/mocha src/node/test && npm run-script lint",
     "gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json",
     "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test"
@@ -53,7 +53,6 @@
     "src/core",
     "test/proto",
     "include",
-    "grpc.gyp",
     "binding.gyp"
   ],
   "main": "src/node/index.js",
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index 79c56580843ed2567091988fa1c739e9d36d0a6f..dfa71c9af5ee344c9f81ba63bd1ed3b3a977426e 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -237,7 +237,7 @@ static void picked_target(grpc_exec_ctx *exec_ctx, void *arg,
   call_data *calld = arg;
   grpc_pollset *pollset;
 
-  GRPC_TIMER_BEGIN("picked_target", 0);
+  GPR_TIMER_BEGIN("picked_target", 0);
 
   if (calld->picked_channel == NULL) {
     /* treat this like a cancellation */
@@ -260,7 +260,7 @@ static void picked_target(grpc_exec_ctx *exec_ctx, void *arg,
     }
   }
 
-  GRPC_TIMER_END("picked_target", 0);
+  GPR_TIMER_END("picked_target", 0);
 }
 
 static grpc_closure *merge_into_waiting_op(grpc_call_element *elem,
@@ -321,7 +321,7 @@ static void perform_transport_stream_op(grpc_exec_ctx *exec_ctx,
   grpc_subchannel_call *subchannel_call;
   grpc_lb_policy *lb_policy;
   grpc_transport_stream_op op2;
-  GRPC_TIMER_BEGIN("perform_transport_stream_op", 0);
+  GPR_TIMER_BEGIN("perform_transport_stream_op", 0);
   GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
   GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
 
@@ -434,7 +434,7 @@ static void perform_transport_stream_op(grpc_exec_ctx *exec_ctx,
       break;
   }
 
-  GRPC_TIMER_END("perform_transport_stream_op", 0);
+  GPR_TIMER_END("perform_transport_stream_op", 0);
 }
 
 static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
@@ -654,9 +654,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
     case CALL_WAITING_FOR_CONFIG:
     case CALL_WAITING_FOR_CALL:
     case CALL_WAITING_FOR_SEND:
-      gpr_log(GPR_ERROR, "should never reach here");
-      abort();
-      break;
+      GPR_UNREACHABLE_CODE(return );
   }
 }
 
diff --git a/src/core/channel/compress_filter.c b/src/core/channel/compress_filter.c
index 6c1ed2931fb1a12204324bb513498cea7e144e06..20b5084044a5cb4cfd9f8be5798371d7550bb726 100644
--- a/src/core/channel/compress_filter.c
+++ b/src/core/channel/compress_filter.c
@@ -243,7 +243,7 @@ static void process_send_ops(grpc_call_element *elem,
         GPR_ASSERT(calld->remaining_slice_bytes > 0);
         /* Increase input ref count, gpr_slice_buffer_add takes ownership.  */
         gpr_slice_buffer_add(&calld->slices, gpr_slice_ref(sop->data.slice));
-        GPR_ASSERT(GPR_SLICE_LENGTH(sop->data.slice) >=
+        GPR_ASSERT(GPR_SLICE_LENGTH(sop->data.slice) <=
                    calld->remaining_slice_bytes);
         calld->remaining_slice_bytes -=
             (gpr_uint32)GPR_SLICE_LENGTH(sop->data.slice);
@@ -272,13 +272,13 @@ static void process_send_ops(grpc_call_element *elem,
 static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
                                                grpc_call_element *elem,
                                                grpc_transport_stream_op *op) {
-  GRPC_TIMER_BEGIN("compress_start_transport_stream_op", 0);
+  GPR_TIMER_BEGIN("compress_start_transport_stream_op", 0);
 
   if (op->send_ops && op->send_ops->nops > 0) {
     process_send_ops(elem, op->send_ops);
   }
 
-  GRPC_TIMER_END("compress_start_transport_stream_op", 0);
+  GPR_TIMER_END("compress_start_transport_stream_op", 0);
 
   /* pass control down the stack */
   grpc_call_next_op(exec_ctx, elem, op);
diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c
index 9a7f8c45be77516faaa909f746534a35b9e0c767..f78a5cc31595bf4d0a959d99d74a9f7ee6ed34b9 100644
--- a/src/core/channel/http_client_filter.c
+++ b/src/core/channel/http_client_filter.c
@@ -163,10 +163,10 @@ static void hc_mutate_op(grpc_call_element *elem,
 static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
                                   grpc_transport_stream_op *op) {
-  GRPC_TIMER_BEGIN("hc_start_transport_op", 0);
+  GPR_TIMER_BEGIN("hc_start_transport_op", 0);
   GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
   hc_mutate_op(elem, op);
-  GRPC_TIMER_END("hc_start_transport_op", 0);
+  GPR_TIMER_END("hc_start_transport_op", 0);
   grpc_call_next_op(exec_ctx, elem, op);
 }
 
diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c
index 16a0c1d3ac09c992069ac613d993d7b6f93fbbec..99e5066a4efe760a79fcaafe72125a333a98ca4a 100644
--- a/src/core/channel/http_server_filter.c
+++ b/src/core/channel/http_server_filter.c
@@ -231,10 +231,10 @@ static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
                                   grpc_transport_stream_op *op) {
   GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  GRPC_TIMER_BEGIN("hs_start_transport_op", 0);
+  GPR_TIMER_BEGIN("hs_start_transport_op", 0);
   hs_mutate_op(elem, op);
   grpc_call_next_op(exec_ctx, elem, op);
-  GRPC_TIMER_END("hs_start_transport_op", 0);
+  GPR_TIMER_END("hs_start_transport_op", 0);
 }
 
 /* Constructor for call_data */
diff --git a/src/core/client_config/uri_parser.c b/src/core/client_config/uri_parser.c
index df9f32d403cb6bf89bd8debdd5ae24aa7c7e476f..cbdfffcf8e88ebf5c32944ef5d80b3ddacd2e0d4 100644
--- a/src/core/client_config/uri_parser.c
+++ b/src/core/client_config/uri_parser.c
@@ -37,6 +37,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
 #include <grpc/support/string_util.h>
 
 /** a size_t default value... maps to all 1's */
@@ -120,8 +121,7 @@ static int parse_fragment_or_query(const char *uri_text, size_t *i) {
         } else {
           return 1;
         }
-        gpr_log(GPR_ERROR, "should never reach here");
-        abort();
+        GPR_UNREACHABLE_CODE(return 0);
       default:
         (*i) += advance;
         break;
diff --git a/src/core/httpcli/parser.c b/src/core/httpcli/parser.c
index 404906d5ae216054c176dec2f8e318399d88cee6..046770c094421f6e2a122115725a50ba0cfc9aeb 100644
--- a/src/core/httpcli/parser.c
+++ b/src/core/httpcli/parser.c
@@ -139,8 +139,7 @@ static int finish_line(grpc_httpcli_parser *parser) {
       }
       break;
     case GRPC_HTTPCLI_BODY:
-      gpr_log(GPR_ERROR, "should never reach here");
-      abort();
+      GPR_UNREACHABLE_CODE(return 0);
   }
 
   parser->cur_line_length = 0;
@@ -165,8 +164,7 @@ static int addbyte(grpc_httpcli_parser *parser, gpr_uint8 byte) {
       } else {
         return 1;
       }
-      gpr_log(GPR_ERROR, "should never reach here");
-      abort();
+      GPR_UNREACHABLE_CODE(return 0);
     case GRPC_HTTPCLI_BODY:
       if (parser->r.body_length == parser->body_capacity) {
         parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2);
@@ -177,10 +175,7 @@ static int addbyte(grpc_httpcli_parser *parser, gpr_uint8 byte) {
       parser->r.body_length++;
       return 1;
   }
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
-
-  return 0;
+  GPR_UNREACHABLE_CODE(return 0);
 }
 
 void grpc_httpcli_parser_init(grpc_httpcli_parser *parser) {
diff --git a/src/core/iomgr/exec_ctx.c b/src/core/iomgr/exec_ctx.c
index 1ad39885e43fb22bed2b69435fe23b85376bdb1a..410b34c521346a8e115cdb78636c45a054abfa03 100644
--- a/src/core/iomgr/exec_ctx.c
+++ b/src/core/iomgr/exec_ctx.c
@@ -39,20 +39,20 @@
 
 int grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
   int did_something = 0;
-  GRPC_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
+  GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
   while (!grpc_closure_list_empty(exec_ctx->closure_list)) {
     grpc_closure *c = exec_ctx->closure_list.head;
     exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
     while (c != NULL) {
       grpc_closure *next = c->next;
       did_something++;
-      GRPC_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
+      GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
       c->cb(exec_ctx, c->cb_arg, c->success);
-      GRPC_TIMER_END("grpc_exec_ctx_flush.cb", 0);
+      GPR_TIMER_END("grpc_exec_ctx_flush.cb", 0);
       c = next;
     }
   }
-  GRPC_TIMER_END("grpc_exec_ctx_flush", 0);
+  GPR_TIMER_END("grpc_exec_ctx_flush", 0);
   return did_something;
 }
 
diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c
index e8743918951aa8a06e02a61fee446146b9c35839..2aafd21dfb5d04d2e4fe2e045db24fe8c1e40adb 100644
--- a/src/core/iomgr/pollset_multipoller_with_epoll.c
+++ b/src/core/iomgr/pollset_multipoller_with_epoll.c
@@ -183,11 +183,11 @@ static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
 
   /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid
      even going into the blocking annotation if possible */
-  GRPC_TIMER_BEGIN("poll", 0);
+  GPR_TIMER_BEGIN("poll", 0);
   GRPC_SCHEDULING_START_BLOCKING_REGION;
   poll_rv = grpc_poll_function(pfds, 2, timeout_ms);
   GRPC_SCHEDULING_END_BLOCKING_REGION;
-  GRPC_TIMER_END("poll", 0);
+  GPR_TIMER_END("poll", 0);
 
   if (poll_rv < 0) {
     if (errno != EINTR) {
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
index 9fda8f8c0cc96b0332860e01455e122cb101b798..4d8bc5374f9703dced935c93e270932bc8e776ab 100644
--- a/src/core/iomgr/pollset_posix.c
+++ b/src/core/iomgr/pollset_posix.c
@@ -101,9 +101,12 @@ static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
 void grpc_pollset_kick_ext(grpc_pollset *p,
                            grpc_pollset_worker *specific_worker,
                            gpr_uint32 flags) {
+  GPR_TIMER_BEGIN("grpc_pollset_kick_ext", 0);
+
   /* pollset->mu already held */
   if (specific_worker != NULL) {
     if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
+      GPR_TIMER_BEGIN("grpc_pollset_kick_ext.broadcast", 0);
       GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
       for (specific_worker = p->root_worker.next;
            specific_worker != &p->root_worker;
@@ -111,44 +114,50 @@ void grpc_pollset_kick_ext(grpc_pollset *p,
         grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
       }
       p->kicked_without_pollers = 1;
-      return;
+      GPR_TIMER_END("grpc_pollset_kick_ext.broadcast", 0);
     } else if (gpr_tls_get(&g_current_thread_worker) !=
                (gpr_intptr)specific_worker) {
+      GPR_TIMER_MARK("different_thread_worker", 0);
       if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
         specific_worker->reevaluate_polling_on_wakeup = 1;
       }
       grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
-      return;
     } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) {
+      GPR_TIMER_MARK("kick_yoself", 0);
       if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
         specific_worker->reevaluate_polling_on_wakeup = 1;
       }
       grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
-      return;
     }
   } else if (gpr_tls_get(&g_current_thread_poller) != (gpr_intptr)p) {
     GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
+    GPR_TIMER_MARK("kick_anonymous", 0);
     specific_worker = pop_front_worker(p);
     if (specific_worker != NULL) {
       if (gpr_tls_get(&g_current_thread_worker) ==
           (gpr_intptr)specific_worker) {
+        GPR_TIMER_MARK("kick_anonymous_not_self", 0);
         push_back_worker(p, specific_worker);
         specific_worker = pop_front_worker(p);
         if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 &&
             gpr_tls_get(&g_current_thread_worker) ==
                 (gpr_intptr)specific_worker) {
           push_back_worker(p, specific_worker);
-          return;
+          specific_worker = NULL;
         }
       }
-      push_back_worker(p, specific_worker);
-      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
-      return;
+      if (specific_worker != NULL) {
+        GPR_TIMER_MARK("finally_kick", 0);
+        push_back_worker(p, specific_worker);
+        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd);
+      }
     } else {
+      GPR_TIMER_MARK("kicked_no_pollers", 0);
       p->kicked_without_pollers = 1;
-      return;
     }
   }
+
+  GPR_TIMER_END("grpc_pollset_kick_ext", 0);
 }
 
 void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
@@ -229,7 +238,7 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
   int locked = 1;
   int queued_work = 0;
   int keep_polling = 0;
-  GRPC_TIMER_BEGIN("grpc_pollset_work", 0);
+  GPR_TIMER_BEGIN("grpc_pollset_work", 0);
   /* this must happen before we (potentially) drop pollset->mu */
   worker->next = worker->prev = NULL;
   worker->reevaluate_polling_on_wakeup = 0;
@@ -274,10 +283,10 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
       }
       gpr_tls_set(&g_current_thread_poller, (gpr_intptr)pollset);
       gpr_tls_set(&g_current_thread_worker, (gpr_intptr)worker);
-      GRPC_TIMER_BEGIN("maybe_work_and_unlock", 0);
+      GPR_TIMER_BEGIN("maybe_work_and_unlock", 0);
       pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, worker,
                                              deadline, now);
-      GRPC_TIMER_END("maybe_work_and_unlock", 0);
+      GPR_TIMER_END("maybe_work_and_unlock", 0);
       locked = 0;
       gpr_tls_set(&g_current_thread_poller, 0);
       gpr_tls_set(&g_current_thread_worker, 0);
@@ -332,7 +341,7 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
       gpr_mu_lock(&pollset->mu);
     }
   }
-  GRPC_TIMER_END("grpc_pollset_work", 0);
+  GPR_TIMER_END("grpc_pollset_work", 0);
 }
 
 void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@@ -567,11 +576,11 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
      even going into the blocking annotation if possible */
   /* poll fd count (argument 2) is shortened by one if we have no events
      to poll on - such that it only includes the kicker */
-  GRPC_TIMER_BEGIN("poll", 0);
+  GPR_TIMER_BEGIN("poll", 0);
   GRPC_SCHEDULING_START_BLOCKING_REGION;
   r = grpc_poll_function(pfd, nfds, timeout);
   GRPC_SCHEDULING_END_BLOCKING_REGION;
-  GRPC_TIMER_END("poll", 0);
+  GPR_TIMER_END("poll", 0);
 
   if (r < 0) {
     gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c
index aca2691c416e64f29d9ea81db9e223fc82ace368..fe20039264121585feaeb058bba68535597f7429 100644
--- a/src/core/iomgr/tcp_client_posix.c
+++ b/src/core/iomgr/tcp_client_posix.c
@@ -191,7 +191,7 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, int success) {
     goto finish;
   }
 
-  abort();
+  GPR_UNREACHABLE_CODE(return );
 
 finish:
   if (fd != NULL) {
diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c
index 9e3773bcd449e79299368a8b1f174377665baea8..915553d50984b68bb289bbabc330898422095810 100644
--- a/src/core/iomgr/tcp_posix.c
+++ b/src/core/iomgr/tcp_posix.c
@@ -180,7 +180,7 @@ static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
   GPR_ASSERT(!tcp->finished_edge);
   GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC);
   GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC);
-  GRPC_TIMER_BEGIN("tcp_continue_read", 0);
+  GPR_TIMER_BEGIN("tcp_continue_read", 0);
 
   while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) {
     gpr_slice_buffer_add_indexed(tcp->incoming_buffer,
@@ -199,11 +199,11 @@ static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
   msg.msg_controllen = 0;
   msg.msg_flags = 0;
 
-  GRPC_TIMER_BEGIN("recvmsg", 1);
+  GPR_TIMER_BEGIN("recvmsg", 1);
   do {
     read_bytes = recvmsg(tcp->fd, &msg, 0);
   } while (read_bytes < 0 && errno == EINTR);
-  GRPC_TIMER_END("recvmsg", 0);
+  GPR_TIMER_END("recvmsg", 0);
 
   if (read_bytes < 0) {
     /* NB: After calling call_read_cb a parallel call of the read handler may
@@ -240,7 +240,7 @@ static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
     TCP_UNREF(exec_ctx, tcp, "read");
   }
 
-  GRPC_TIMER_END("tcp_continue_read", 0);
+  GPR_TIMER_END("tcp_continue_read", 0);
 }
 
 static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
@@ -316,12 +316,12 @@ static flush_result tcp_flush(grpc_tcp *tcp) {
     msg.msg_controllen = 0;
     msg.msg_flags = 0;
 
-    GRPC_TIMER_BEGIN("sendmsg", 1);
+    GPR_TIMER_BEGIN("sendmsg", 1);
     do {
       /* TODO(klempner): Cork if this is a partial write */
       sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS);
     } while (sent_length < 0 && errno == EINTR);
-    GRPC_TIMER_END("sendmsg", 0);
+    GPR_TIMER_END("sendmsg", 0);
 
     if (sent_length < 0) {
       if (errno == EAGAIN) {
@@ -376,9 +376,9 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
   } else {
     cb = tcp->write_cb;
     tcp->write_cb = NULL;
-    GRPC_TIMER_BEGIN("tcp_handle_write.cb", 0);
+    GPR_TIMER_BEGIN("tcp_handle_write.cb", 0);
     cb->cb(exec_ctx, cb->cb_arg, status == FLUSH_DONE);
-    GRPC_TIMER_END("tcp_handle_write.cb", 0);
+    GPR_TIMER_END("tcp_handle_write.cb", 0);
     TCP_UNREF(exec_ctx, tcp, "write");
   }
 }
@@ -399,11 +399,11 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
     }
   }
 
-  GRPC_TIMER_BEGIN("tcp_write", 0);
+  GPR_TIMER_BEGIN("tcp_write", 0);
   GPR_ASSERT(tcp->write_cb == NULL);
 
   if (buf->length == 0) {
-    GRPC_TIMER_END("tcp_write", 0);
+    GPR_TIMER_END("tcp_write", 0);
     grpc_exec_ctx_enqueue(exec_ctx, cb, 1);
     return;
   }
@@ -420,7 +420,7 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
     grpc_exec_ctx_enqueue(exec_ctx, cb, status == FLUSH_DONE);
   }
 
-  GRPC_TIMER_END("tcp_write", 0);
+  GPR_TIMER_END("tcp_write", 0);
 }
 
 static void tcp_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c
index 13bd67576f55d9adf90d36c64c69efcaed7f3c41..99c76dcbe9aeddfd7d303e994fba5526e9057bea 100644
--- a/src/core/iomgr/tcp_server_posix.c
+++ b/src/core/iomgr/tcp_server_posix.c
@@ -352,7 +352,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
     gpr_free(addr_str);
   }
 
-  abort();
+  GPR_UNREACHABLE_CODE(return );
 
 error:
   gpr_mu_lock(&sp->server->mu);
diff --git a/src/core/iomgr/wakeup_fd_eventfd.c b/src/core/iomgr/wakeup_fd_eventfd.c
index 48eb1afb3d8b4e15eb38afd2a723df0d446860d2..f67379e4fcfaf709bf9964e4eebd58b7e2481c13 100644
--- a/src/core/iomgr/wakeup_fd_eventfd.c
+++ b/src/core/iomgr/wakeup_fd_eventfd.c
@@ -39,9 +39,11 @@
 #include <sys/eventfd.h>
 #include <unistd.h>
 
-#include "src/core/iomgr/wakeup_fd_posix.h"
 #include <grpc/support/log.h>
 
+#include "src/core/iomgr/wakeup_fd_posix.h"
+#include "src/core/profiling/timers.h"
+
 static void eventfd_create(grpc_wakeup_fd* fd_info) {
   int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
   /* TODO(klempner): Handle failure more gracefully */
@@ -60,9 +62,11 @@ static void eventfd_consume(grpc_wakeup_fd* fd_info) {
 
 static void eventfd_wakeup(grpc_wakeup_fd* fd_info) {
   int err;
+  GPR_TIMER_BEGIN("eventfd_wakeup", 0);
   do {
     err = eventfd_write(fd_info->read_fd, 1);
   } while (err < 0 && errno == EINTR);
+  GPR_TIMER_END("eventfd_wakeup", 0);
 }
 
 static void eventfd_destroy(grpc_wakeup_fd* fd_info) {
diff --git a/src/core/profiling/basic_timers.c b/src/core/profiling/basic_timers.c
index 8a68277cca2e069fca2cf11f972f9ff46b76659f..b49cdd07b3e2f29bc5acf809b3c60a77e582e15e 100644
--- a/src/core/profiling/basic_timers.c
+++ b/src/core/profiling/basic_timers.c
@@ -46,18 +46,18 @@
 
 typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
 
-typedef struct grpc_timer_entry {
+typedef struct gpr_timer_entry {
   gpr_timespec tm;
   const char *tagstr;
   const char *file;
   int line;
   char type;
   gpr_uint8 important;
-} grpc_timer_entry;
+} gpr_timer_entry;
 
-#define MAX_COUNT (1024 * 1024 / sizeof(grpc_timer_entry))
+#define MAX_COUNT (1024 * 1024 / sizeof(gpr_timer_entry))
 
-static __thread grpc_timer_entry g_log[MAX_COUNT];
+static __thread gpr_timer_entry g_log[MAX_COUNT];
 static __thread int g_count;
 static gpr_once g_once_init = GPR_ONCE_INIT;
 static FILE *output_file;
@@ -74,7 +74,7 @@ static void log_report() {
   int i;
   gpr_once_init(&g_once_init, init_output);
   for (i = 0; i < g_count; i++) {
-    grpc_timer_entry *entry = &(g_log[i]);
+    gpr_timer_entry *entry = &(g_log[i]);
     fprintf(output_file,
             "{\"t\": %ld.%09d, \"thd\": \"%p\", \"type\": \"%c\", \"tag\": "
             "\"%s\", \"file\": \"%s\", \"line\": %d, \"imp\": %d}\n",
@@ -87,9 +87,9 @@ static void log_report() {
   g_count = 0;
 }
 
-static void grpc_timers_log_add(const char *tagstr, marker_type type,
-                                int important, const char *file, int line) {
-  grpc_timer_entry *entry;
+static void gpr_timers_log_add(const char *tagstr, marker_type type,
+                               int important, const char *file, int line) {
+  gpr_timer_entry *entry;
 
   /* TODO (vpai) : Improve concurrency */
   if (g_count == MAX_COUNT) {
@@ -107,28 +107,28 @@ static void grpc_timers_log_add(const char *tagstr, marker_type type,
 }
 
 /* Latency profiler API implementation. */
-void grpc_timer_add_mark(const char *tagstr, int important, const char *file,
-                         int line) {
-  grpc_timers_log_add(tagstr, MARK, important, file, line);
+void gpr_timer_add_mark(const char *tagstr, int important, const char *file,
+                        int line) {
+  gpr_timers_log_add(tagstr, MARK, important, file, line);
 }
 
-void grpc_timer_begin(const char *tagstr, int important, const char *file,
-                      int line) {
-  grpc_timers_log_add(tagstr, BEGIN, important, file, line);
+void gpr_timer_begin(const char *tagstr, int important, const char *file,
+                     int line) {
+  gpr_timers_log_add(tagstr, BEGIN, important, file, line);
 }
 
-void grpc_timer_end(const char *tagstr, int important, const char *file,
-                    int line) {
-  grpc_timers_log_add(tagstr, END, important, file, line);
+void gpr_timer_end(const char *tagstr, int important, const char *file,
+                   int line) {
+  gpr_timers_log_add(tagstr, END, important, file, line);
 }
 
 /* Basic profiler specific API functions. */
-void grpc_timers_global_init(void) {}
+void gpr_timers_global_init(void) {}
 
-void grpc_timers_global_destroy(void) {}
+void gpr_timers_global_destroy(void) {}
 
 #else  /* !GRPC_BASIC_PROFILER */
-void grpc_timers_global_init(void) {}
+void gpr_timers_global_init(void) {}
 
-void grpc_timers_global_destroy(void) {}
+void gpr_timers_global_destroy(void) {}
 #endif /* GRPC_BASIC_PROFILER */
diff --git a/src/core/profiling/stap_timers.c b/src/core/profiling/stap_timers.c
index 6868a674a986c8c1075f9d388070b9c0d1741225..efcd1af4a1c8a6599954ecf441b8dfa3e3ea8cd2 100644
--- a/src/core/profiling/stap_timers.c
+++ b/src/core/profiling/stap_timers.c
@@ -42,23 +42,23 @@
 #include "src/core/profiling/stap_probes.h"
 
 /* Latency profiler API implementation. */
-void grpc_timer_add_mark(int tag, const char *tagstr, void *id,
-                         const char *file, int line) {
+void gpr_timer_add_mark(int tag, const char *tagstr, void *id, const char *file,
+                        int line) {
   _STAP_ADD_MARK(tag);
 }
 
-void grpc_timer_add_important_mark(int tag, const char *tagstr, void *id,
-                                   const char *file, int line) {
+void gpr_timer_add_important_mark(int tag, const char *tagstr, void *id,
+                                  const char *file, int line) {
   _STAP_ADD_IMPORTANT_MARK(tag);
 }
 
-void grpc_timer_begin(int tag, const char *tagstr, void *id, const char *file,
-                      int line) {
+void gpr_timer_begin(int tag, const char *tagstr, void *id, const char *file,
+                     int line) {
   _STAP_TIMING_NS_BEGIN(tag);
 }
 
-void grpc_timer_end(int tag, const char *tagstr, void *id, const char *file,
-                    int line) {
+void gpr_timer_end(int tag, const char *tagstr, void *id, const char *file,
+                   int line) {
   _STAP_TIMING_NS_END(tag);
 }
 
diff --git a/src/core/profiling/timers.h b/src/core/profiling/timers.h
index 94251fbcf54e3a90227848bf3bea4681350c1f6b..0d112e7248551a2aa2e88b6b1f74ea5deb23c399 100644
--- a/src/core/profiling/timers.h
+++ b/src/core/profiling/timers.h
@@ -38,28 +38,28 @@
 extern "C" {
 #endif
 
-void grpc_timers_global_init(void);
-void grpc_timers_global_destroy(void);
+void gpr_timers_global_init(void);
+void gpr_timers_global_destroy(void);
 
-void grpc_timer_add_mark(const char *tagstr, int important, const char *file,
-                         int line);
-void grpc_timer_begin(const char *tagstr, int important, const char *file,
-                      int line);
-void grpc_timer_end(const char *tagstr, int important, const char *file,
-                    int line);
+void gpr_timer_add_mark(const char *tagstr, int important, const char *file,
+                        int line);
+void gpr_timer_begin(const char *tagstr, int important, const char *file,
+                     int line);
+void gpr_timer_end(const char *tagstr, int important, const char *file,
+                   int line);
 
 #if !(defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
 /* No profiling. No-op all the things. */
-#define GRPC_TIMER_MARK(tag, important) \
-  do {                                  \
+#define GPR_TIMER_MARK(tag, important) \
+  do {                                 \
   } while (0)
 
-#define GRPC_TIMER_BEGIN(tag, important) \
-  do {                                   \
+#define GPR_TIMER_BEGIN(tag, important) \
+  do {                                  \
   } while (0)
 
-#define GRPC_TIMER_END(tag, important) \
-  do {                                 \
+#define GPR_TIMER_END(tag, important) \
+  do {                                \
   } while (0)
 
 #else /* at least one profiler requested... */
@@ -69,14 +69,14 @@ void grpc_timer_end(const char *tagstr, int important, const char *file,
 #endif
 
 /* Generic profiling interface. */
-#define GRPC_TIMER_MARK(tag, important) \
-  grpc_timer_add_mark(tag, important, __FILE__, __LINE__);
+#define GPR_TIMER_MARK(tag, important) \
+  gpr_timer_add_mark(tag, important, __FILE__, __LINE__);
 
-#define GRPC_TIMER_BEGIN(tag, important) \
-  grpc_timer_begin(tag, important, __FILE__, __LINE__);
+#define GPR_TIMER_BEGIN(tag, important) \
+  gpr_timer_begin(tag, important, __FILE__, __LINE__);
 
-#define GRPC_TIMER_END(tag, important) \
-  grpc_timer_end(tag, important, __FILE__, __LINE__);
+#define GPR_TIMER_END(tag, important) \
+  gpr_timer_end(tag, important, __FILE__, __LINE__);
 
 #ifdef GRPC_STAP_PROFILER
 /* Empty placeholder for now. */
@@ -91,21 +91,27 @@ void grpc_timer_end(const char *tagstr, int important, const char *file,
 #ifdef __cplusplus
 }
 
+#if (defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
 namespace grpc {
 class ProfileScope {
  public:
   ProfileScope(const char *desc, bool important) : desc_(desc) {
-    GRPC_TIMER_BEGIN(desc_, important ? 1 : 0);
+    GPR_TIMER_BEGIN(desc_, important ? 1 : 0);
   }
-  ~ProfileScope() { GRPC_TIMER_END(desc_, 0); }
+  ~ProfileScope() { GPR_TIMER_END(desc_, 0); }
 
  private:
   const char *const desc_;
 };
 }
 
-#define GRPC_TIMER_SCOPE(tag, important) \
-  ProfileScope _profile_scope_##__LINE__((tag), (important))
+#define GPR_TIMER_SCOPE(tag, important) \
+  ::grpc::ProfileScope _profile_scope_##__LINE__((tag), (important))
+#else
+#define GPR_TIMER_SCOPE(tag, important) \
+  do {                                  \
+  } while (false)
+#endif
 #endif
 
 #endif /* GRPC_CORE_PROFILING_TIMERS_H */
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 398db20e8cf0ad817d30a1f5ffda0fed2076bd9b..5e155d83b9cf9ec6c7d7caf8ba6f02297a649231 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -181,6 +181,48 @@ void grpc_server_credentials_set_auth_metadata_processor(
   creds->processor = processor;
 }
 
+static void server_credentials_pointer_arg_destroy(void *p) {
+  grpc_server_credentials_unref(p);
+}
+
+static void *server_credentials_pointer_arg_copy(void *p) {
+  return grpc_server_credentials_ref(p);
+}
+
+grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
+  grpc_arg arg;
+  memset(&arg, 0, sizeof(grpc_arg));
+  arg.type = GRPC_ARG_POINTER;
+  arg.key = GRPC_SERVER_CREDENTIALS_ARG;
+  arg.value.pointer.p = p;
+  arg.value.pointer.copy = server_credentials_pointer_arg_copy;
+  arg.value.pointer.destroy = server_credentials_pointer_arg_destroy;
+  return arg;
+}
+
+grpc_server_credentials *grpc_server_credentials_from_arg(
+    const grpc_arg *arg) {
+  if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
+  if (arg->type != GRPC_ARG_POINTER) {
+    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
+            GRPC_SERVER_CREDENTIALS_ARG);
+    return NULL;
+  }
+  return arg->value.pointer.p;
+}
+
+grpc_server_credentials *grpc_find_server_credentials_in_args(
+    const grpc_channel_args *args) {
+  size_t i;
+  if (args == NULL) return NULL;
+  for (i = 0; i < args->num_args; i++) {
+    grpc_server_credentials *p =
+        grpc_server_credentials_from_arg(&args->args[i]);
+    if (p != NULL) return p;
+  }
+  return NULL;
+}
+
 /* -- Ssl credentials. -- */
 
 static void ssl_destruct(grpc_credentials *creds) {
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index b213e052d34c02d8c48ebecc968b57e05cd11a04..01203b08f1faf6dcc84a6553d1d4a87b0cec09c7 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -215,7 +215,6 @@ typedef struct {
       grpc_server_credentials *c, grpc_security_connector **sc);
 } grpc_server_credentials_vtable;
 
-/* TODO(jboeuf): Add a refcount. */
 struct grpc_server_credentials {
   const grpc_server_credentials_vtable *vtable;
   const char *type;
@@ -231,6 +230,13 @@ grpc_server_credentials *grpc_server_credentials_ref(
 
 void grpc_server_credentials_unref(grpc_server_credentials *creds);
 
+#define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials"
+
+grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *c);
+grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg);
+grpc_server_credentials *grpc_find_server_credentials_in_args(
+    const grpc_channel_args *args);
+
 /* -- Ssl credentials. -- */
 
 typedef struct {
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index fb905e0b228fa06a5b40ebe0599eacf307225b8c..f544c1d943d313d8b9ff21eaa12f85ee1038e0bd 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -305,33 +305,43 @@ void grpc_auth_property_reset(grpc_auth_property *property) {
   memset(property, 0, sizeof(grpc_auth_property));
 }
 
-grpc_arg grpc_auth_metadata_processor_to_arg(grpc_auth_metadata_processor *p) {
+static void auth_context_pointer_arg_destroy(void *p) {
+  GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg");
+}
+
+static void *auth_context_pointer_arg_copy(void *p) {
+  return GRPC_AUTH_CONTEXT_REF(p, "auth_context_pointer_arg");
+}
+
+grpc_arg grpc_auth_context_to_arg(grpc_auth_context *p) {
   grpc_arg arg;
   memset(&arg, 0, sizeof(grpc_arg));
   arg.type = GRPC_ARG_POINTER;
-  arg.key = GRPC_AUTH_METADATA_PROCESSOR_ARG;
+  arg.key = GRPC_AUTH_CONTEXT_ARG;
   arg.value.pointer.p = p;
+  arg.value.pointer.copy = auth_context_pointer_arg_copy;
+  arg.value.pointer.destroy = auth_context_pointer_arg_destroy;
   return arg;
 }
 
-grpc_auth_metadata_processor *grpc_auth_metadata_processor_from_arg(
+grpc_auth_context *grpc_auth_context_from_arg(
     const grpc_arg *arg) {
-  if (strcmp(arg->key, GRPC_AUTH_METADATA_PROCESSOR_ARG) != 0) return NULL;
+  if (strcmp(arg->key, GRPC_AUTH_CONTEXT_ARG) != 0) return NULL;
   if (arg->type != GRPC_ARG_POINTER) {
     gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
-            GRPC_AUTH_METADATA_PROCESSOR_ARG);
+            GRPC_AUTH_CONTEXT_ARG);
     return NULL;
   }
   return arg->value.pointer.p;
 }
 
-grpc_auth_metadata_processor *grpc_find_auth_metadata_processor_in_args(
+grpc_auth_context *grpc_find_auth_context_in_args(
     const grpc_channel_args *args) {
   size_t i;
   if (args == NULL) return NULL;
   for (i = 0; i < args->num_args; i++) {
-    grpc_auth_metadata_processor *p =
-        grpc_auth_metadata_processor_from_arg(&args->args[i]);
+    grpc_auth_context *p =
+        grpc_auth_context_from_arg(&args->args[i]);
     if (p != NULL) return p;
   }
   return NULL;
diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h
index a9a03064108a162c08efd4de9f33c0f0f654724e..2bbdc4be973e3f66237663b83ea59e6a10536fa0 100644
--- a/src/core/security/security_context.h
+++ b/src/core/security/security_context.h
@@ -103,13 +103,12 @@ typedef struct {
 grpc_server_security_context *grpc_server_security_context_create(void);
 void grpc_server_security_context_destroy(void *ctx);
 
-/* --- Auth metadata processing. --- */
-#define GRPC_AUTH_METADATA_PROCESSOR_ARG "grpc.auth_metadata_processor"
+/* --- Channel args for auth context --- */
+#define GRPC_AUTH_CONTEXT_ARG "grpc.auth_context"
 
-grpc_arg grpc_auth_metadata_processor_to_arg(grpc_auth_metadata_processor *p);
-grpc_auth_metadata_processor *grpc_auth_metadata_processor_from_arg(
-    const grpc_arg *arg);
-grpc_auth_metadata_processor *grpc_find_auth_metadata_processor_in_args(
+grpc_arg grpc_auth_context_to_arg(grpc_auth_context *c);
+grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg);
+grpc_auth_context *grpc_find_auth_context_in_args(
     const grpc_channel_args *args);
 
 #endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */
diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c
index 30ca9f57a25e2ae770afeba65c4070badf3ea436..2e18369fe8c0deb2c27c0d01236f279a3a2be034 100644
--- a/src/core/security/server_auth_filter.c
+++ b/src/core/security/server_auth_filter.c
@@ -34,7 +34,7 @@
 #include <string.h>
 
 #include "src/core/security/auth_filters.h"
-#include "src/core/security/security_connector.h"
+#include "src/core/security/credentials.h"
 #include "src/core/security/security_context.h"
 
 #include <grpc/support/alloc.h>
@@ -58,8 +58,8 @@ typedef struct call_data {
 } call_data;
 
 typedef struct channel_data {
-  grpc_security_connector *security_connector;
-  grpc_auth_metadata_processor processor;
+  grpc_auth_context *auth_context;
+  grpc_server_credentials *creds;
   grpc_mdctx *mdctx;
 } channel_data;
 
@@ -160,12 +160,12 @@ static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
       grpc_stream_op *op = &ops[i];
       if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue;
       calld->got_client_metadata = 1;
-      if (chand->processor.process == NULL) continue;
+      if (chand->creds->processor.process == NULL) continue;
       calld->md_op = op;
       calld->md = metadata_batch_to_md_array(&op->data.metadata);
-      chand->processor.process(chand->processor.state, calld->auth_context,
-                               calld->md.metadata, calld->md.count,
-                               on_md_processing_done, elem);
+      chand->creds->processor.process(
+          chand->creds->processor.state, calld->auth_context,
+          calld->md.metadata, calld->md.count, on_md_processing_done, elem);
       return;
     }
   }
@@ -221,7 +221,7 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
   }
   server_ctx = grpc_server_security_context_create();
   server_ctx->auth_context =
-      grpc_auth_context_create(chand->security_connector->auth_context);
+      grpc_auth_context_create(chand->auth_context);
   server_ctx->auth_context->pollset = initial_op->bind_pollset;
   initial_op->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
   initial_op->context[GRPC_CONTEXT_SECURITY].destroy =
@@ -241,9 +241,8 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
                               grpc_channel_element *elem, grpc_channel *master,
                               const grpc_channel_args *args, grpc_mdctx *mdctx,
                               int is_first, int is_last) {
-  grpc_security_connector *sc = grpc_find_security_connector_in_args(args);
-  grpc_auth_metadata_processor *processor =
-      grpc_find_auth_metadata_processor_in_args(args);
+  grpc_auth_context *auth_context = grpc_find_auth_context_in_args(args);
+  grpc_server_credentials *creds = grpc_find_server_credentials_in_args(args);
   /* grab pointers to our data from the channel element */
   channel_data *chand = elem->channel_data;
 
@@ -252,15 +251,14 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
      path */
   GPR_ASSERT(!is_first);
   GPR_ASSERT(!is_last);
-  GPR_ASSERT(sc != NULL);
-  GPR_ASSERT(processor != NULL);
+  GPR_ASSERT(auth_context != NULL);
+  GPR_ASSERT(creds != NULL);
 
   /* initialize members */
-  GPR_ASSERT(!sc->is_client_side);
-  chand->security_connector =
-      GRPC_SECURITY_CONNECTOR_REF(sc, "server_auth_filter");
+  chand->auth_context =
+      GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter");
+  chand->creds = grpc_server_credentials_ref(creds);
   chand->mdctx = mdctx;
-  chand->processor = *processor;
 }
 
 /* Destructor for channel data */
@@ -268,8 +266,8 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
                                  grpc_channel_element *elem) {
   /* grab pointers to our data from the channel element */
   channel_data *chand = elem->channel_data;
-  GRPC_SECURITY_CONNECTOR_UNREF(chand->security_connector,
-                                "server_auth_filter");
+  GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter");
+  grpc_server_credentials_unref(chand->creds);
 }
 
 const grpc_channel_filter grpc_server_auth_filter = {
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 881e44a3fedd012397298dad20ad5872ac07a419..82c639e8301debc2fd8f7a5a31d9bc5ef1dda4e8 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -93,9 +93,9 @@ static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep,
   grpc_server_secure_state *state = statep;
   grpc_channel_args *args_copy;
   grpc_arg args_to_add[2];
-  args_to_add[0] = grpc_security_connector_to_arg(state->sc);
+  args_to_add[0] = grpc_server_credentials_to_arg(state->creds);
   args_to_add[1] =
-      grpc_auth_metadata_processor_to_arg(&state->creds->processor);
+      grpc_auth_context_to_arg(state->sc->auth_context);
   args_copy = grpc_channel_args_copy_and_add(
       grpc_server_get_channel_args(state->server), args_to_add,
       GPR_ARRAY_SIZE(args_to_add));
diff --git a/src/core/support/alloc.c b/src/core/support/alloc.c
index beb0e780d0ca3bfdbcf9e14c730bf889e3cd1f36..bfcb77956b31fda7b9474139575bca073a1e8d85 100644
--- a/src/core/support/alloc.c
+++ b/src/core/support/alloc.c
@@ -39,28 +39,28 @@
 
 void *gpr_malloc(size_t size) {
   void *p;
-  GRPC_TIMER_BEGIN("gpr_malloc", 0);
+  GPR_TIMER_BEGIN("gpr_malloc", 0);
   p = malloc(size);
   if (!p) {
     abort();
   }
-  GRPC_TIMER_END("gpr_malloc", 0);
+  GPR_TIMER_END("gpr_malloc", 0);
   return p;
 }
 
 void gpr_free(void *p) {
-  GRPC_TIMER_BEGIN("gpr_free", 0);
+  GPR_TIMER_BEGIN("gpr_free", 0);
   free(p);
-  GRPC_TIMER_END("gpr_free", 0);
+  GPR_TIMER_END("gpr_free", 0);
 }
 
 void *gpr_realloc(void *p, size_t size) {
-  GRPC_TIMER_BEGIN("gpr_realloc", 0);
+  GPR_TIMER_BEGIN("gpr_realloc", 0);
   p = realloc(p, size);
   if (!p) {
     abort();
   }
-  GRPC_TIMER_END("gpr_realloc", 0);
+  GPR_TIMER_END("gpr_realloc", 0);
   return p;
 }
 
diff --git a/src/core/support/sync_posix.c b/src/core/support/sync_posix.c
index f356bec9846381d463011e9e53bfc9f7844ccbf2..39c96feb137c890eb2d5b35eeea704ffab9386e9 100644
--- a/src/core/support/sync_posix.c
+++ b/src/core/support/sync_posix.c
@@ -47,15 +47,15 @@ void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
 void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); }
 
 void gpr_mu_lock(gpr_mu* mu) {
-  GRPC_TIMER_BEGIN("gpr_mu_lock", 0);
+  GPR_TIMER_BEGIN("gpr_mu_lock", 0);
   GPR_ASSERT(pthread_mutex_lock(mu) == 0);
-  GRPC_TIMER_END("gpr_mu_lock", 0);
+  GPR_TIMER_END("gpr_mu_lock", 0);
 }
 
 void gpr_mu_unlock(gpr_mu* mu) {
-  GRPC_TIMER_BEGIN("gpr_mu_unlock", 0);
+  GPR_TIMER_BEGIN("gpr_mu_unlock", 0);
   GPR_ASSERT(pthread_mutex_unlock(mu) == 0);
-  GRPC_TIMER_END("gpr_mu_unlock", 0);
+  GPR_TIMER_END("gpr_mu_unlock", 0);
 }
 
 int gpr_mu_trylock(gpr_mu* mu) {
diff --git a/src/core/surface/byte_buffer.c b/src/core/surface/byte_buffer.c
index 295ef5ab0ee4faa3bcab596f31ad845234f0453e..fb39c4531d9acca2d2cd2bd21ec4de2098fb2e5d 100644
--- a/src/core/surface/byte_buffer.c
+++ b/src/core/surface/byte_buffer.c
@@ -75,9 +75,7 @@ grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb) {
       return grpc_raw_byte_buffer_create(bb->data.raw.slice_buffer.slices,
                                          bb->data.raw.slice_buffer.count);
   }
-  gpr_log(GPR_INFO, "should never get here");
-  abort();
-  return NULL;
+  GPR_UNREACHABLE_CODE(return NULL);
 }
 
 void grpc_byte_buffer_destroy(grpc_byte_buffer *bb) {
@@ -95,7 +93,5 @@ size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) {
     case GRPC_BB_RAW:
       return bb->data.raw.slice_buffer.length;
   }
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
-  return 0;
+  GPR_UNREACHABLE_CODE(return 0);
 }
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 030317708450e77398fc9d531a9c54fd449dee28..60380a599eb7cc2d5345f5af0b174d90ce6252b5 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -307,7 +307,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
   grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_call *call;
-  GRPC_TIMER_BEGIN("grpc_call_create", 0);
+  GPR_TIMER_BEGIN("grpc_call_create", 0);
   call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
   memset(call, 0, sizeof(grpc_call));
   gpr_mu_init(&call->mu);
@@ -402,7 +402,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
     set_deadline_alarm(&exec_ctx, call, send_deadline);
   }
   grpc_exec_ctx_finish(&exec_ctx);
-  GRPC_TIMER_END("grpc_call_create", 0);
+  GPR_TIMER_END("grpc_call_create", 0);
   return call;
 }
 
@@ -436,8 +436,7 @@ static grpc_cq_completion *allocate_completion(grpc_call *call) {
     gpr_mu_unlock(&call->completion_mu);
     return &call->completions[i];
   }
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
+  GPR_UNREACHABLE_CODE(return NULL);
   return NULL;
 }
 
@@ -464,7 +463,7 @@ void grpc_call_internal_ref(grpc_call *c) {
 static void destroy_call(grpc_exec_ctx *exec_ctx, grpc_call *call) {
   size_t i;
   grpc_call *c = call;
-  GRPC_TIMER_BEGIN("destroy_call", 0);
+  GPR_TIMER_BEGIN("destroy_call", 0);
   grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c));
   GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->channel, "call");
   gpr_mu_destroy(&c->mu);
@@ -497,7 +496,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, grpc_call *call) {
     GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
   }
   gpr_free(c);
-  GRPC_TIMER_END("destroy_call", 0);
+  GPR_TIMER_END("destroy_call", 0);
 }
 
 #ifdef GRPC_CALL_REF_COUNT_DEBUG
@@ -531,9 +530,13 @@ static void set_compression_algorithm(grpc_call *call,
   call->compression_algorithm = algo;
 }
 
-grpc_compression_algorithm grpc_call_get_compression_algorithm(
-    const grpc_call *call) {
-  return call->compression_algorithm;
+grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
+    grpc_call *call) {
+  grpc_compression_algorithm algorithm;
+  gpr_mu_lock(&call->mu);
+  algorithm = call->compression_algorithm;
+  gpr_mu_unlock(&call->mu);
+  return algorithm;
 }
 
 static void destroy_encodings_accepted_by_peer(void *p) { return; }
@@ -585,12 +588,20 @@ static void set_encodings_accepted_by_peer(grpc_call *call, grpc_mdelem *mdel) {
       (void *)(((gpr_uintptr)call->encodings_accepted_by_peer) + 1));
 }
 
-gpr_uint32 grpc_call_get_encodings_accepted_by_peer(grpc_call *call) {
-  return call->encodings_accepted_by_peer;
+gpr_uint32 grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
+  gpr_uint32 encodings_accepted_by_peer;
+  gpr_mu_lock(&call->mu);
+  encodings_accepted_by_peer = call->encodings_accepted_by_peer;
+  gpr_mu_unlock(&call->mu);
+  return encodings_accepted_by_peer;
 }
 
-gpr_uint32 grpc_call_get_message_flags(const grpc_call *call) {
-  return call->incoming_message_flags;
+gpr_uint32 grpc_call_test_only_get_message_flags(grpc_call *call) {
+  gpr_uint32 flags;
+  gpr_mu_lock(&call->mu);
+  flags = call->incoming_message_flags;
+  gpr_mu_unlock(&call->mu);
+  return flags;
 }
 
 static void set_status_details(grpc_call *call, status_source source,
@@ -635,7 +646,7 @@ static void unlock(grpc_exec_ctx *exec_ctx, grpc_call *call) {
   const size_t MAX_RECV_PEEK_AHEAD = 65536;
   size_t buffered_bytes;
 
-  GRPC_TIMER_BEGIN("unlock", 0);
+  GPR_TIMER_BEGIN("unlock", 0);
 
   memset(&op, 0, sizeof(op));
 
@@ -708,7 +719,7 @@ static void unlock(grpc_exec_ctx *exec_ctx, grpc_call *call) {
     GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completing");
   }
 
-  GRPC_TIMER_END("unlock", 0);
+  GPR_TIMER_END("unlock", 0);
 }
 
 static void get_final_status(grpc_call *call, grpc_ioreq_data out) {
@@ -858,7 +869,7 @@ static void early_out_write_ops(grpc_call *call) {
 
 static void call_on_done_send(grpc_exec_ctx *exec_ctx, void *pc, int success) {
   grpc_call *call = pc;
-  GRPC_TIMER_BEGIN("call_on_done_send", 0);
+  GPR_TIMER_BEGIN("call_on_done_send", 0);
   lock(call);
   if (call->last_send_contains & (1 << GRPC_IOREQ_SEND_INITIAL_METADATA)) {
     finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, success);
@@ -882,11 +893,11 @@ static void call_on_done_send(grpc_exec_ctx *exec_ctx, void *pc, int success) {
   call->sending = 0;
   unlock(exec_ctx, call);
   GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "sending");
-  GRPC_TIMER_END("call_on_done_send", 0);
+  GPR_TIMER_END("call_on_done_send", 0);
 }
 
 static void finish_message(grpc_call *call) {
-  GRPC_TIMER_BEGIN("finish_message", 0);
+  GPR_TIMER_BEGIN("finish_message", 0);
   if (call->error_status_set == 0) {
     /* TODO(ctiller): this could be a lot faster if coded directly */
     grpc_byte_buffer *byte_buffer;
@@ -906,7 +917,7 @@ static void finish_message(grpc_call *call) {
   gpr_slice_buffer_reset_and_unref(&call->incoming_message);
   GPR_ASSERT(call->incoming_message.count == 0);
   call->reading_message = 0;
-  GRPC_TIMER_END("finish_message", 0);
+  GPR_TIMER_END("finish_message", 0);
 }
 
 static int begin_message(grpc_call *call, grpc_begin_message msg) {
@@ -996,7 +1007,7 @@ static void call_on_done_recv(grpc_exec_ctx *exec_ctx, void *pc, int success) {
   grpc_call *child_call;
   grpc_call *next_child_call;
   size_t i;
-  GRPC_TIMER_BEGIN("call_on_done_recv", 0);
+  GPR_TIMER_BEGIN("call_on_done_recv", 0);
   lock(call);
   call->receiving = 0;
   if (success) {
@@ -1006,19 +1017,19 @@ static void call_on_done_recv(grpc_exec_ctx *exec_ctx, void *pc, int success) {
         case GRPC_NO_OP:
           break;
         case GRPC_OP_METADATA:
-          GRPC_TIMER_BEGIN("recv_metadata", 0);
+          GPR_TIMER_BEGIN("recv_metadata", 0);
           recv_metadata(exec_ctx, call, &op->data.metadata);
-          GRPC_TIMER_END("recv_metadata", 0);
+          GPR_TIMER_END("recv_metadata", 0);
           break;
         case GRPC_OP_BEGIN_MESSAGE:
-          GRPC_TIMER_BEGIN("begin_message", 0);
+          GPR_TIMER_BEGIN("begin_message", 0);
           success = begin_message(call, op->data.begin_message);
-          GRPC_TIMER_END("begin_message", 0);
+          GPR_TIMER_END("begin_message", 0);
           break;
         case GRPC_OP_SLICE:
-          GRPC_TIMER_BEGIN("add_slice_to_message", 0);
+          GPR_TIMER_BEGIN("add_slice_to_message", 0);
           success = add_slice_to_message(call, op->data.slice);
-          GRPC_TIMER_END("add_slice_to_message", 0);
+          GPR_TIMER_END("add_slice_to_message", 0);
           break;
       }
     }
@@ -1064,7 +1075,7 @@ static void call_on_done_recv(grpc_exec_ctx *exec_ctx, void *pc, int success) {
   unlock(exec_ctx, call);
 
   GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "receiving");
-  GRPC_TIMER_END("call_on_done_recv", 0);
+  GPR_TIMER_END("call_on_done_recv", 0);
 }
 
 static int prepare_application_metadata(grpc_call *call, size_t count,
@@ -1542,25 +1553,25 @@ static void recv_metadata(grpc_exec_ctx *exec_ctx, grpc_call *call,
     grpc_mdelem *mdel = l->md;
     grpc_mdstr *key = mdel->key;
     if (key == grpc_channel_get_status_string(call->channel)) {
-      GRPC_TIMER_BEGIN("status", 0);
+      GPR_TIMER_BEGIN("status", 0);
       set_status_code(call, STATUS_FROM_WIRE, decode_status(mdel));
-      GRPC_TIMER_END("status", 0);
+      GPR_TIMER_END("status", 0);
     } else if (key == grpc_channel_get_message_string(call->channel)) {
-      GRPC_TIMER_BEGIN("status-details", 0);
+      GPR_TIMER_BEGIN("status-details", 0);
       set_status_details(call, STATUS_FROM_WIRE, GRPC_MDSTR_REF(mdel->value));
-      GRPC_TIMER_END("status-details", 0);
+      GPR_TIMER_END("status-details", 0);
     } else if (key ==
                grpc_channel_get_compression_algorithm_string(call->channel)) {
-      GRPC_TIMER_BEGIN("compression_algorithm", 0);
+      GPR_TIMER_BEGIN("compression_algorithm", 0);
       set_compression_algorithm(call, decode_compression(mdel));
-      GRPC_TIMER_END("compression_algorithm", 0);
+      GPR_TIMER_END("compression_algorithm", 0);
     } else if (key == grpc_channel_get_encodings_accepted_by_peer_string(
                           call->channel)) {
-      GRPC_TIMER_BEGIN("encodings_accepted_by_peer", 0);
+      GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
       set_encodings_accepted_by_peer(call, mdel);
-      GRPC_TIMER_END("encodings_accepted_by_peer", 0);
+      GPR_TIMER_END("encodings_accepted_by_peer", 0);
     } else {
-      GRPC_TIMER_BEGIN("report_up", 0);
+      GPR_TIMER_BEGIN("report_up", 0);
       dest = &call->buffered_metadata[is_trailing];
       if (dest->count == dest->capacity) {
         dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2);
@@ -1581,15 +1592,15 @@ static void recv_metadata(grpc_exec_ctx *exec_ctx, grpc_call *call,
       }
       call->owned_metadata[call->owned_metadata_count++] = mdel;
       l->md = NULL;
-      GRPC_TIMER_END("report_up", 0);
+      GPR_TIMER_END("report_up", 0);
     }
   }
   if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
           0 &&
       !call->is_client) {
-    GRPC_TIMER_BEGIN("set_deadline_alarm", 0);
+    GPR_TIMER_BEGIN("set_deadline_alarm", 0);
     set_deadline_alarm(exec_ctx, call, md->deadline);
-    GRPC_TIMER_END("set_deadline_alarm", 0);
+    GPR_TIMER_END("set_deadline_alarm", 0);
   }
   if (!is_trailing) {
     call->read_state = READ_STATE_GOT_INITIAL_METADATA;
@@ -1652,7 +1663,7 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
   grpc_call_error error;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
-  GRPC_TIMER_BEGIN("grpc_call_start_batch", 0);
+  GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
 
   GRPC_API_TRACE(
       "grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, reserved=%p)",
@@ -1891,7 +1902,7 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
                                               finish_func, tag);
 done:
   grpc_exec_ctx_finish(&exec_ctx);
-  GRPC_TIMER_END("grpc_call_start_batch", 0);
+  GPR_TIMER_END("grpc_call_start_batch", 0);
   return error;
 }
 
diff --git a/src/core/surface/call.h b/src/core/surface/call.h
index f421a81619f7854c0f3024afea7721feadc5876c..9b7c6f9bfbed9e4bc174820fac8759bb5b449c9a 100644
--- a/src/core/surface/call.h
+++ b/src/core/surface/call.h
@@ -169,17 +169,6 @@ void *grpc_call_context_get(grpc_call *call, grpc_context_index elem);
 
 gpr_uint8 grpc_call_is_client(grpc_call *call);
 
-grpc_compression_algorithm grpc_call_get_compression_algorithm(
-    const grpc_call *call);
-
-gpr_uint32 grpc_call_get_message_flags(const grpc_call *call);
-
-/** Returns a bitset for the encodings (compression algorithms) supported by \a
- * call's peer.
- *
- * To be indexed by grpc_compression_algorithm enum values. */
-gpr_uint32 grpc_call_get_encodings_accepted_by_peer(grpc_call *call);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/core/surface/call_test_only.h b/src/core/surface/call_test_only.h
new file mode 100644
index 0000000000000000000000000000000000000000..df4be3248b2a0baa58f16fdfcea7c10f131f01bb
--- /dev/null
+++ b/src/core/surface/call_test_only.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CORE_SURFACE_CALL_TEST_ONLY_H
+#define GRPC_INTERNAL_CORE_SURFACE_CALL_TEST_ONLY_H
+
+#include <grpc/grpc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Return the compression algorithm from \a call.
+ *
+ * \warning This function should \b only be used in test code. */
+grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
+    grpc_call *call);
+
+/** Return the message flags from \a call.
+ *
+ * \warning This function should \b only be used in test code. */
+gpr_uint32 grpc_call_test_only_get_message_flags(grpc_call *call);
+
+/** Returns a bitset for the encodings (compression algorithms) supported by \a
+ * call's peer.
+ *
+ * To be indexed by grpc_compression_algorithm enum values. */
+gpr_uint32 grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_INTERNAL_CORE_SURFACE_CALL_TEST_ONLY_H */
diff --git a/src/core/surface/channel_connectivity.c b/src/core/surface/channel_connectivity.c
index f72fb0414261d3e63ca1dbc29dcec66c5666b317..ca3c02c536ab23e16c954848f51955b801bd745a 100644
--- a/src/core/surface/channel_connectivity.c
+++ b/src/core/surface/channel_connectivity.c
@@ -100,9 +100,7 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
   switch (w->phase) {
     case WAITING:
     case CALLED_BACK:
-      gpr_log(GPR_ERROR, "should never reach here");
-      abort();
-      break;
+      GPR_UNREACHABLE_CODE(return );
     case CALLING_BACK:
       w->phase = CALLED_BACK;
       break;
@@ -149,9 +147,7 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
       w->phase = CALLING_BACK_AND_FINISHED;
       break;
     case CALLING_BACK_AND_FINISHED:
-      gpr_log(GPR_ERROR, "should never reach here");
-      abort();
-      break;
+      GPR_UNREACHABLE_CODE(return );
     case CALLED_BACK:
       delete = 1;
       break;
diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c
index 695dfbd83b412100c44390f94e2aa27d4c9a7d7e..bcdb3638733c9f2d900cad97d7217435d4fd9094 100644
--- a/src/core/surface/completion_queue.c
+++ b/src/core/surface/completion_queue.c
@@ -144,6 +144,8 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
   int i;
   grpc_pollset_worker *pluck_worker;
 
+  GPR_TIMER_BEGIN("grpc_cq_end_op", 0);
+
   storage->tag = tag;
   storage->done = done;
   storage->done_arg = done_arg;
@@ -175,6 +177,8 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
     gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
     grpc_pollset_shutdown(exec_ctx, &cc->pollset, &cc->pollset_destroy_done);
   }
+
+  GPR_TIMER_END("grpc_cq_end_op", 0);
 }
 
 grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
@@ -185,7 +189,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
   gpr_timespec now;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
-  GRPC_TIMER_BEGIN("grpc_completion_queue_next", 0);
+  GPR_TIMER_BEGIN("grpc_completion_queue_next", 0);
 
   GRPC_API_TRACE(
       "grpc_completion_queue_next("
@@ -234,7 +238,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
   GRPC_CQ_INTERNAL_UNREF(cc, "next");
   grpc_exec_ctx_finish(&exec_ctx);
 
-  GRPC_TIMER_END("grpc_completion_queue_next", 0);
+  GPR_TIMER_END("grpc_completion_queue_next", 0);
 
   return ret;
 }
@@ -260,8 +264,7 @@ static void del_plucker(grpc_completion_queue *cc, void *tag,
       return;
     }
   }
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
+  GPR_UNREACHABLE_CODE(return );
 }
 
 grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
@@ -274,7 +277,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
   int first_loop = 1;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
-  GRPC_TIMER_BEGIN("grpc_completion_queue_pluck", 0);
+  GPR_TIMER_BEGIN("grpc_completion_queue_pluck", 0);
 
   GRPC_API_TRACE(
       "grpc_completion_queue_pluck("
@@ -342,7 +345,7 @@ done:
   GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
   grpc_exec_ctx_finish(&exec_ctx);
 
-  GRPC_TIMER_END("grpc_completion_queue_pluck", 0);
+  GPR_TIMER_END("grpc_completion_queue_pluck", 0);
 
   return ret;
 }
diff --git a/src/core/surface/init.c b/src/core/surface/init.c
index 95011cab178a3fe42d0d92b90216b96c3c319b09..715c90a5e1d46785a38c97dd9499e6fde835a506 100644
--- a/src/core/surface/init.c
+++ b/src/core/surface/init.c
@@ -115,7 +115,7 @@ void grpc_init(void) {
         gpr_log(GPR_ERROR, "Could not initialize census.");
       }
     }
-    grpc_timers_global_init();
+    gpr_timers_global_init();
     for (i = 0; i < g_number_of_plugins; i++) {
       if (g_all_of_the_plugins[i].init != NULL) {
         g_all_of_the_plugins[i].init();
@@ -133,7 +133,7 @@ void grpc_shutdown(void) {
   if (--g_initializations == 0) {
     grpc_iomgr_shutdown();
     census_shutdown();
-    grpc_timers_global_destroy();
+    gpr_timers_global_destroy();
     grpc_tracer_shutdown();
     grpc_resolver_registry_shutdown();
     for (i = 0; i < g_number_of_plugins; i++) {
diff --git a/src/core/transport/chttp2/frame_data.c b/src/core/transport/chttp2/frame_data.c
index acfa7c002ebac93f934fbb7ce43dff63d9c7a43e..07179a4571e9b139ba17d93c623a0841d6fa6d8d 100644
--- a/src/core/transport/chttp2/frame_data.c
+++ b/src/core/transport/chttp2/frame_data.c
@@ -168,7 +168,5 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
       }
   }
 
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
-  return GRPC_CHTTP2_CONNECTION_ERROR;
+  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
 }
diff --git a/src/core/transport/chttp2/frame_goaway.c b/src/core/transport/chttp2/frame_goaway.c
index 2ff1eda89b60d7c219f08db1698f9ecb21a05d02..c5758bcb7147b84623250d25ea47810dd736581b 100644
--- a/src/core/transport/chttp2/frame_goaway.c
+++ b/src/core/transport/chttp2/frame_goaway.c
@@ -152,9 +152,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
       }
       return GRPC_CHTTP2_PARSE_OK;
   }
-  gpr_log(GPR_ERROR, "Should never end up here");
-  abort();
-  return GRPC_CHTTP2_CONNECTION_ERROR;
+  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
 }
 
 void grpc_chttp2_goaway_append(gpr_uint32 last_stream_id, gpr_uint32 error_code,
diff --git a/src/core/transport/chttp2/hpack_parser.c b/src/core/transport/chttp2/hpack_parser.c
index 20ea51337517bd0fa65a18a8482981aee6bc11a9..20d8312d547bc72392b6c75667c520ad718e3fea 100644
--- a/src/core/transport/chttp2/hpack_parser.c
+++ b/src/core/transport/chttp2/hpack_parser.c
@@ -1166,9 +1166,7 @@ static int append_string(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
       append_bytes(str, decoded, 3);
       goto b64_byte0;
   }
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
-  return 1;
+  GPR_UNREACHABLE_CODE(return 1);
 }
 
 /* append a null terminator to a string */
@@ -1313,9 +1311,7 @@ static int parse_value_string(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
       return 0;
   }
   /* Add code to prevent return without value error */
-  gpr_log(GPR_ERROR, "Should never reach beyond switch in parse_value_string");
-  abort();
-  return 0;
+  GPR_UNREACHABLE_CODE(return 0);
 }
 
 static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c
index e71d4fc87aa21c9d12169f4bf785bbbf614170b2..5d4d8e70c4680dd892b20441384c719c82aa9d30 100644
--- a/src/core/transport/chttp2/parsing.c
+++ b/src/core/transport/chttp2/parsing.c
@@ -69,7 +69,7 @@ void grpc_chttp2_prepare_to_read(
   grpc_chttp2_stream_global *stream_global;
   grpc_chttp2_stream_parsing *stream_parsing;
 
-  GRPC_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
+  GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
 
   transport_parsing->next_stream_id = transport_global->next_stream_id;
 
@@ -93,7 +93,7 @@ void grpc_chttp2_prepare_to_read(
     }
   }
 
-  GRPC_TIMER_END("grpc_chttp2_prepare_to_read", 0);
+  GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0);
 }
 
 void grpc_chttp2_publish_reads(
@@ -422,14 +422,10 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
         transport_parsing->incoming_frame_size -= (gpr_uint32)(end - cur);
         return 1;
       }
-      gpr_log(GPR_ERROR, "should never reach here");
-      abort();
+      GPR_UNREACHABLE_CODE(return 0);
   }
 
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
-
-  return 0;
+  GPR_UNREACHABLE_CODE(return 0);
 }
 
 static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing) {
@@ -585,9 +581,7 @@ static int init_data_frame_parser(
     case GRPC_CHTTP2_CONNECTION_ERROR:
       return 0;
   }
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
-  return 0;
+  GPR_UNREACHABLE_CODE(return 0);
 }
 
 static void free_timeout(void *p) { gpr_free(p); }
@@ -825,7 +819,5 @@ static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
     case GRPC_CHTTP2_CONNECTION_ERROR:
       return 0;
   }
-  gpr_log(GPR_ERROR, "should never reach here");
-  abort();
-  return 0;
+  GPR_UNREACHABLE_CODE(return 0);
 }
diff --git a/src/core/transport/chttp2/stream_encoder.c b/src/core/transport/chttp2/stream_encoder.c
index 83227e677db07cacf633799bba2fc312034ad435..6c7f7a9ea7f068c4e24ea8c0de96278d1fb23936 100644
--- a/src/core/transport/chttp2/stream_encoder.c
+++ b/src/core/transport/chttp2/stream_encoder.c
@@ -428,7 +428,7 @@ static grpc_mdelem *hpack_enc(grpc_chttp2_hpack_compressor *c,
       emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
       return elem;
     }
-    abort();
+    GPR_UNREACHABLE_CODE(return NULL);
   }
 
   indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
@@ -442,7 +442,7 @@ static grpc_mdelem *hpack_enc(grpc_chttp2_hpack_compressor *c,
       emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
       return elem;
     }
-    abort();
+    GPR_UNREACHABLE_CODE(return NULL);
   }
 
   /* no elem, key in the table... fall back to literal emission */
@@ -454,7 +454,7 @@ static grpc_mdelem *hpack_enc(grpc_chttp2_hpack_compressor *c,
     emit_lithdr_noidx_v(c, elem, st);
     return elem;
   }
-  abort();
+  GPR_UNREACHABLE_CODE(return NULL);
 }
 
 #define STRLEN_LIT(x) (sizeof(x) - 1)
diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c
index 4abe00bb7cfccadbd86c955412ae5337fb9cf4b0..69ad8854ba66f6ceeebc7f1a6815178ee4a2f46d 100644
--- a/src/core/transport/chttp2/writing.c
+++ b/src/core/transport/chttp2/writing.c
@@ -181,7 +181,7 @@ void grpc_chttp2_perform_writes(
 static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) {
   grpc_chttp2_stream_writing *stream_writing;
 
-  GRPC_TIMER_BEGIN("finalize_outbuf", 0);
+  GPR_TIMER_BEGIN("finalize_outbuf", 0);
 
   while (
       grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) {
@@ -212,7 +212,7 @@ static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) {
     grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
   }
 
-  GRPC_TIMER_END("finalize_outbuf", 0);
+  GPR_TIMER_END("finalize_outbuf", 0);
 }
 
 void grpc_chttp2_cleanup_writing(
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index d39816b0117ce67d2eecc372625f522511fc7563..effc3c4b3becf8858aac8070c6d006db024e3e77 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -510,7 +510,7 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
 static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
 
 static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
-  GRPC_TIMER_BEGIN("unlock", 0);
+  GPR_TIMER_BEGIN("unlock", 0);
   unlock_check_read_write_state(exec_ctx, t);
   if (!t->writing_active && !t->closed &&
       grpc_chttp2_unlocking_check_writes(&t->global, &t->writing)) {
@@ -521,7 +521,7 @@ static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
   }
 
   gpr_mu_unlock(&t->mu);
-  GRPC_TIMER_END("unlock", 0);
+  GPR_TIMER_END("unlock", 0);
 }
 
 /*
@@ -548,7 +548,7 @@ void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
   grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr;
   grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
 
-  GRPC_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0);
+  GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0);
 
   lock(t);
 
@@ -572,15 +572,15 @@ void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
 
   UNREF_TRANSPORT(exec_ctx, t, "writing");
 
-  GRPC_TIMER_END("grpc_chttp2_terminate_writing", 0);
+  GPR_TIMER_END("grpc_chttp2_terminate_writing", 0);
 }
 
 static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
                            int iomgr_success_ignored) {
   grpc_chttp2_transport *t = gt;
-  GRPC_TIMER_BEGIN("writing_action", 0);
+  GPR_TIMER_BEGIN("writing_action", 0);
   grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
-  GRPC_TIMER_END("writing_action", 0);
+  GPR_TIMER_END("writing_action", 0);
 }
 
 void grpc_chttp2_add_incoming_goaway(
@@ -650,7 +650,7 @@ static void maybe_start_some_streams(
 static void perform_stream_op_locked(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) {
-  GRPC_TIMER_BEGIN("perform_stream_op_locked", 0);
+  GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
   if (op->cancel_with_status != GRPC_STATUS_OK) {
     cancel_from_api(transport_global, stream_global, op->cancel_with_status);
   }
@@ -722,7 +722,7 @@ static void perform_stream_op_locked(
   }
 
   grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
-  GRPC_TIMER_END("perform_stream_op_locked", 0);
+  GPR_TIMER_END("perform_stream_op_locked", 0);
 }
 
 static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
@@ -1113,7 +1113,7 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, int success) {
   int keep_reading = 0;
   grpc_chttp2_transport *t = tp;
 
-  GRPC_TIMER_BEGIN("recv_data", 0);
+  GPR_TIMER_BEGIN("recv_data", 0);
 
   lock(t);
   i = 0;
@@ -1125,13 +1125,13 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, int success) {
                                      &t->parsing_stream_map);
     grpc_chttp2_prepare_to_read(&t->global, &t->parsing);
     gpr_mu_unlock(&t->mu);
-    GRPC_TIMER_BEGIN("recv_data.parse", 0);
+    GPR_TIMER_BEGIN("recv_data.parse", 0);
     for (; i < t->read_buffer.count &&
                grpc_chttp2_perform_read(exec_ctx, &t->parsing,
                                         t->read_buffer.slices[i]);
          i++)
       ;
-    GRPC_TIMER_END("recv_data.parse", 0);
+    GPR_TIMER_END("recv_data.parse", 0);
     gpr_mu_lock(&t->mu);
     if (i != t->read_buffer.count) {
       drop_connection(exec_ctx, t);
@@ -1169,7 +1169,7 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, int success) {
     UNREF_TRANSPORT(exec_ctx, t, "recv_data");
   }
 
-  GRPC_TIMER_END("recv_data", 0);
+  GPR_TIMER_END("recv_data", 0);
 }
 
 /*
diff --git a/src/core/transport/stream_op.c b/src/core/transport/stream_op.c
index 5c3c90b054179bc7075787dcbfac1a534c12ec5b..6493e77bc516c186fcb13ac77f91427703e6a1d8 100644
--- a/src/core/transport/stream_op.c
+++ b/src/core/transport/stream_op.c
@@ -302,7 +302,7 @@ void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
   grpc_linked_mdelem *l;
   grpc_linked_mdelem *next;
 
-  GRPC_TIMER_BEGIN("grpc_metadata_batch_filter", 0);
+  GPR_TIMER_BEGIN("grpc_metadata_batch_filter", 0);
 
   assert_valid_list(&batch->list);
   assert_valid_list(&batch->garbage);
@@ -333,5 +333,5 @@ void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
   assert_valid_list(&batch->list);
   assert_valid_list(&batch->garbage);
 
-  GRPC_TIMER_END("grpc_metadata_batch_filter", 0);
+  GPR_TIMER_END("grpc_metadata_batch_filter", 0);
 }
diff --git a/src/cpp/proto/proto_utils.cc b/src/cpp/proto/proto_utils.cc
index a7b6fd241b5c7ed824dfeebce6dac9073f6d554d..b1330fde7f6541ddd55cfb9fac841228f3d45383 100644
--- a/src/cpp/proto/proto_utils.cc
+++ b/src/cpp/proto/proto_utils.cc
@@ -160,7 +160,7 @@ namespace grpc {
 
 Status SerializeProto(const grpc::protobuf::Message& msg,
                       grpc_byte_buffer** bp) {
-  GRPC_TIMER_SCOPE("SerializeProto", 0);
+  GPR_TIMER_SCOPE("SerializeProto", 0);
   int byte_size = msg.ByteSize();
   if (byte_size <= kMaxBufferLength) {
     gpr_slice slice = gpr_slice_malloc(byte_size);
@@ -179,7 +179,7 @@ Status SerializeProto(const grpc::protobuf::Message& msg,
 
 Status DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg,
                         int max_message_size) {
-  GRPC_TIMER_SCOPE("DeserializeProto", 0);
+  GPR_TIMER_SCOPE("DeserializeProto", 0);
   if (!buffer) {
     return Status(StatusCode::INTERNAL, "No payload");
   }
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index 2cd1905a97de2c191e08264790e5db9c21e70617..f5063a079e184097d745001df5bc009c1b610e52 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -153,8 +153,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
         GPR_ASSERT((*req)->in_flight_);
         return true;
     }
-    gpr_log(GPR_ERROR, "Should never reach here");
-    abort();
+    GPR_UNREACHABLE_CODE(return false);
   }
 
   void SetupRequest() { cq_ = grpc_completion_queue_create(nullptr); }
@@ -541,7 +540,7 @@ void Server::ScheduleCallback() {
 void Server::RunRpc() {
   // Wait for one more incoming rpc.
   bool ok;
-  GRPC_TIMER_SCOPE("Server::RunRpc", 0);
+  GPR_TIMER_SCOPE("Server::RunRpc", 0);
   auto* mrd = SyncRequest::Wait(&cq_, &ok);
   if (mrd) {
     ScheduleCallback();
@@ -557,7 +556,7 @@ void Server::RunRpc() {
           mrd->TeardownRequest();
         }
       }
-      GRPC_TIMER_SCOPE("cd.Run()", 0);
+      GPR_TIMER_SCOPE("cd.Run()", 0);
       cd.Run();
     }
   }
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index 14cc6c0efe10ea79da81674a33d36a8e7b84d2eb..cb55083d1ae188ded69cce3976d8bd79e5497234 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -44,12 +44,14 @@ var GoogleAuth = require('google-auth-library');
 
 var assert = require('assert');
 
-var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
-var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
-var AUTH_USER = ('155450119199-vefjjaekcc6cmsd5914v6lqufunmh9ue' +
-    '@developer.gserviceaccount.com');
-var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' +
-    '@developer.gserviceaccount.com');
+var SERVICE_ACCOUNT_EMAIL;
+try {
+  SERVICE_ACCOUNT_EMAIL = require(
+      process.env.GOOGLE_APPLICATION_CREDENTIALS).client_email;
+} catch (e) {
+  // This will cause the tests to fail if they need that string
+  SERVICE_ACCOUNT_EMAIL = null;
+}
 
 var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial';
 var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin';
@@ -345,6 +347,41 @@ function customMetadata(client, done) {
   stream.end();
 }
 
+function statusCodeAndMessage(client, done) {
+  done = multiDone(done, 2);
+  var arg = {
+    response_status: {
+      code: 2,
+      message: 'test status message'
+    }
+  };
+  client.unaryCall(arg, function(err, resp) {
+    assert(err);
+    assert.strictEqual(err.code, 2);
+    assert.strictEqual(err.message, 'test status message');
+    done();
+  });
+  var duplex = client.fullDuplexCall();
+  duplex.on('status', function(status) {
+    assert(status);
+    assert.strictEqual(status.code, 2);
+    assert.strictEqual(status.details, 'test status message');
+    done();
+  });
+  duplex.on('error', function(){});
+  duplex.write(arg);
+  duplex.end();
+}
+
+function unimplementedMethod(client, done) {
+  client.unimplementedCall({}, function(err, resp) {
+    assert(err);
+    assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED);
+    assert(!err.message);
+    done();
+  });
+}
+
 /**
  * Run one of the authentication tests.
  * @param {string} expected_user The expected username in the response
@@ -369,7 +406,7 @@ function authTest(expected_user, scope, client, done) {
     assert.strictEqual(resp.payload.body.length, 314159);
     assert.strictEqual(resp.username, expected_user);
     if (scope) {
-      assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
+      assert(scope.indexOf(resp.oauth_scope) > -1);
     }
     if (done) {
       done();
@@ -377,56 +414,49 @@ function authTest(expected_user, scope, client, done) {
   });
 }
 
-function oauth2Test(expected_user, scope, per_rpc, client, done) {
-  (new GoogleAuth()).getApplicationDefault(function(err, credential) {
+function computeEngineCreds(client, done, extra) {
+  authTest(extra.service_account, null, client, done);
+}
+
+function serviceAccountCreds(client, done, extra) {
+  authTest(SERVICE_ACCOUNT_EMAIL, extra.oauth_scope, client, done);
+}
+
+function jwtTokenCreds(client, done, extra) {
+  authTest(SERVICE_ACCOUNT_EMAIL, null, client, done);
+}
+
+function oauth2Test(client, done, extra) {
+  var arg = {
+    fill_username: true,
+    fill_oauth_scope: true
+  };
+  client.unaryCall(arg, function(err, resp) {
     assert.ifError(err);
-    var arg = {
-      fill_username: true,
-      fill_oauth_scope: true
-    };
-    credential = credential.createScoped(scope);
-    credential.getAccessToken(function(err, token) {
-      assert.ifError(err);
-      var updateMetadata = function(authURI, metadata, callback) {
-        metadata.add('authorization', 'Bearer ' + token);
-        callback(null, metadata);
-      };
-      var makeTestCall = function(error, client_metadata) {
-        assert.ifError(error);
-        client.unaryCall(arg, function(err, resp) {
-          assert.ifError(err);
-          assert.strictEqual(resp.username, expected_user);
-          assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
-          if (done) {
-            done();
-          }
-        }, client_metadata);
-      };
-      if (per_rpc) {
-        updateMetadata('', new grpc.Metadata(), makeTestCall);
-      } else {
-        client.$updateMetadata = updateMetadata;
-        makeTestCall(null, new grpc.Metadata());
-      }
-    });
+    assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL);
+    assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1);
+    if (done) {
+      done();
+    }
   });
 }
 
-function perRpcAuthTest(expected_user, scope, per_rpc, client, done) {
+function perRpcAuthTest(client, done, extra) {
   (new GoogleAuth()).getApplicationDefault(function(err, credential) {
     assert.ifError(err);
     var arg = {
       fill_username: true,
       fill_oauth_scope: true
     };
+    var scope = extra.oauth_scope;
     if (credential.createScopedRequired() && scope) {
       credential = credential.createScoped(scope);
     }
     var creds = grpc.credentials.createFromGoogleCredential(credential);
     client.unaryCall(arg, function(err, resp) {
       assert.ifError(err);
-      assert.strictEqual(resp.username, expected_user);
-      assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
+      assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL);
+      assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1);
       if (done) {
         done();
       }
@@ -473,25 +503,44 @@ function getOauth2Creds(scope, callback) {
  * Map from test case names to test functions
  */
 var test_cases = {
-  empty_unary: {run: emptyUnary},
-  large_unary: {run: largeUnary},
-  client_streaming: {run: clientStreaming},
-  server_streaming: {run: serverStreaming},
-  ping_pong: {run: pingPong},
-  empty_stream: {run: emptyStream},
-  cancel_after_begin: {run: cancelAfterBegin},
-  cancel_after_first_response: {run: cancelAfterFirstResponse},
-  timeout_on_sleeping_server: {run: timeoutOnSleepingServer},
-  custom_metadata: {run: customMetadata},
-  compute_engine_creds: {run: _.partial(authTest, COMPUTE_ENGINE_USER, null),
-                         getCreds: _.partial(getApplicationCreds, null)},
-  service_account_creds: {run: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
-                          getCreds: _.partial(getApplicationCreds, AUTH_SCOPE)},
-  jwt_token_creds: {run: _.partial(authTest, AUTH_USER, null),
-                    getCreds: _.partial(getApplicationCreds, null)},
-  oauth2_auth_token: {run: _.partial(oauth2Test, AUTH_USER, AUTH_SCOPE, false),
-                      getCreds: _.partial(getOauth2Creds, AUTH_SCOPE)},
-  per_rpc_creds: {run: _.partial(perRpcAuthTest, AUTH_USER, AUTH_SCOPE, true)}
+  empty_unary: {run: emptyUnary,
+                Client: testProto.TestService},
+  large_unary: {run: largeUnary,
+                Client: testProto.TestService},
+  client_streaming: {run: clientStreaming,
+                     Client: testProto.TestService},
+  server_streaming: {run: serverStreaming,
+                     Client: testProto.TestService},
+  ping_pong: {run: pingPong,
+              Client: testProto.TestService},
+  empty_stream: {run: emptyStream,
+                 Client: testProto.TestService},
+  cancel_after_begin: {run: cancelAfterBegin,
+                       Client: testProto.TestService},
+  cancel_after_first_response: {run: cancelAfterFirstResponse,
+                                Client: testProto.TestService},
+  timeout_on_sleeping_server: {run: timeoutOnSleepingServer,
+                               Client: testProto.TestService},
+  custom_metadata: {run: customMetadata,
+                    Client: testProto.TestService},
+  status_code_and_message: {run: statusCodeAndMessage,
+                            Client: testProto.TestService},
+  unimplemented_method: {run: unimplementedMethod,
+                         Client: testProto.UnimplementedService},
+  compute_engine_creds: {run: computeEngineCreds,
+                         Client: testProto.TestService,
+                         getCreds: getApplicationCreds},
+  service_account_creds: {run: serviceAccountCreds,
+                          Client: testProto.TestService,
+                          getCreds: getApplicationCreds},
+  jwt_token_creds: {run: jwtTokenCreds,
+                    Client: testProto.TestService,
+                    getCreds: getApplicationCreds},
+  oauth2_auth_token: {run: oauth2Test,
+                      Client: testProto.TestService,
+                      getCreds: getOauth2Creds},
+  per_rpc_creds: {run: perRpcAuthTest,
+                  Client: testProto.TestService}
 };
 
 /**
@@ -504,8 +553,9 @@ var test_cases = {
  * @param {bool} tls Indicates that a secure channel should be used
  * @param {function} done Callback to call when the test is completed. Included
  *     primarily for use with mocha
+ * @param {object=} extra Extra options for some tests
  */
-function runTest(address, host_override, test_case, tls, test_ca, done) {
+function runTest(address, host_override, test_case, tls, test_ca, done, extra) {
   // TODO(mlumish): enable TLS functionality
   var options = {};
   var creds;
@@ -529,12 +579,13 @@ function runTest(address, host_override, test_case, tls, test_ca, done) {
 
   var execute = function(err, creds) {
     assert.ifError(err);
-    var client = new testProto.TestService(address, creds, options);
-    test.run(client, done);
+    var client = new test.Client(address, creds, options);
+    test.run(client, done, extra);
   };
 
   if (test.getCreds) {
-    test.getCreds(function(err, new_creds) {
+    test.getCreds(extra.oauth_scope, function(err, new_creds) {
+      assert.ifError(err);
       execute(err, grpc.credentials.combineChannelCredentials(
           creds, new_creds));
     });
@@ -547,13 +598,18 @@ if (require.main === module) {
   var parseArgs = require('minimist');
   var argv = parseArgs(process.argv, {
     string: ['server_host', 'server_host_override', 'server_port', 'test_case',
-             'use_tls', 'use_test_ca']
+             'use_tls', 'use_test_ca', 'default_service_account', 'oauth_scope',
+             'service_account_key_file']
   });
+  var extra_args = {
+    service_account: argv.default_service_account,
+    oauth_scope: argv.oauth_scope
+  };
   runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
           argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
           function () {
             console.log('OK:', argv.test_case);
-          });
+          }, extra_args);
 }
 
 /**
diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js
index 3e83304faa39490dd0293c352dc14dbe79284cb8..5321005c863eda160f2d09e510f87bc6dde2ec62 100644
--- a/src/node/interop/interop_server.js
+++ b/src/node/interop/interop_server.js
@@ -44,6 +44,9 @@ var testProto = grpc.load({
 var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial';
 var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin';
 
+var incompressible_data = fs.readFileSync(
+    __dirname + '/../../../test/cpp/interop/rnd.dat');
+
 /**
  * Create a buffer filled with size zeroes
  * @param {number} size The length of the buffer
@@ -83,6 +86,19 @@ function getEchoTrailer(call) {
   return response_trailer;
 }
 
+function getPayload(payload_type, size) {
+  if (payload_type === 'RANDOM') {
+    payload_type = ['COMPRESSABLE',
+                    'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+  }
+  var body;
+  switch (payload_type) {
+    case 'COMPRESSABLE': body = zeroBuffer(size); break;
+    case 'UNCOMPRESSABLE': incompressible_data.slice(size); break;
+  }
+  return {type: payload_type, body: body};
+}
+
 /**
  * Respond to an empty parameter with an empty response.
  * NOTE: this currently does not work due to issue #137
@@ -104,13 +120,14 @@ function handleEmpty(call, callback) {
 function handleUnary(call, callback) {
   echoHeader(call);
   var req = call.request;
-  var zeros = zeroBuffer(req.response_size);
-  var payload_type = req.response_type;
-  if (payload_type === 'RANDOM') {
-    payload_type = ['COMPRESSABLE',
-                    'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+  if (req.response_status) {
+    var status = req.response_status;
+    status.metadata = getEchoTrailer(call);
+    callback(status);
+    return;
   }
-  callback(null, {payload: {type: payload_type, body: zeros}},
+  var payload = getPayload(req.response_type, req.response_size);
+  callback(null, {payload: payload},
            getEchoTrailer(call));
 }
 
@@ -139,18 +156,14 @@ function handleStreamingInput(call, callback) {
 function handleStreamingOutput(call) {
   echoHeader(call);
   var req = call.request;
-  var payload_type = req.response_type;
-  if (payload_type === 'RANDOM') {
-    payload_type = ['COMPRESSABLE',
-                    'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+  if (req.response_status) {
+    var status = req.response_status;
+    status.metadata = getEchoTrailer(call);
+    call.emit('error', status);
+    return;
   }
   _.each(req.response_parameters, function(resp_param) {
-    call.write({
-      payload: {
-        body: zeroBuffer(resp_param.size),
-        type: payload_type
-      }
-    });
+    call.write({payload: getPayload(req.response_type, resp_param.size)});
   });
   call.end(getEchoTrailer(call));
 }
@@ -163,18 +176,14 @@ function handleStreamingOutput(call) {
 function handleFullDuplex(call) {
   echoHeader(call);
   call.on('data', function(value) {
-    var payload_type = value.response_type;
-    if (payload_type === 'RANDOM') {
-      payload_type = ['COMPRESSABLE',
-                      'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+    if (value.response_status) {
+      var status = value.response_status;
+      status.metadata = getEchoTrailer(call);
+      call.emit('error', status);
+      return;
     }
     _.each(value.response_parameters, function(resp_param) {
-      call.write({
-        payload: {
-          body: zeroBuffer(resp_param.size),
-          type: payload_type
-        }
-      });
+      call.write({payload: getPayload(value.response_type, resp_param.size)});
     });
   });
   call.on('end', function() {
@@ -188,7 +197,7 @@ function handleFullDuplex(call) {
  * @param {Call} call Call to handle
  */
 function handleHalfDuplex(call) {
-  throw new Error('HalfDuplexCall not yet implemented');
+  call.emit('error', Error('HalfDuplexCall not yet implemented'));
 }
 
 /**
diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js
index 009ff633067ae3bebe28a51274ae7cbf704434c7..ddc094f89684de28988a9633efaca44f5d02f848 100644
--- a/src/node/src/credentials.js
+++ b/src/node/src/credentials.js
@@ -153,7 +153,7 @@ exports.combineCallCredentials = function() {
     current = current.compose(arguments[i]);
   }
   return current;
-}
+};
 
 /**
  * Create an insecure credentials object. This is used to create a channel that
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 87b5b7ad06ee739ea2ab6d21c765ea39cd70a37c..a974d593c95956e0e3a08f4d6fca5711d192d29b 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -629,7 +629,7 @@ function Server(options) {
             (new Metadata())._getCoreRepresentation();
         batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
           code: grpc.status.UNIMPLEMENTED,
-          details: 'This method is not available on this server.',
+          details: '',
           metadata: {}
         };
         batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
diff --git a/src/node/test/async_test.js b/src/node/test/async_test.js
index ce3ce50a2d6df113f8f4469b3920bf024ed94647..6d71ea24f54430160265b38d9ac0576d85b907a1 100644
--- a/src/node/test/async_test.js
+++ b/src/node/test/async_test.js
@@ -57,7 +57,7 @@ describe('Async functionality', function() {
                                grpc.ServerCredentials.createInsecure());
     server.start();
     math_client = new math.Math('localhost:' + port_num,
-                                grpc.Credentials.createInsecure());
+                                grpc.credentials.createInsecure());
     done();
   });
   after(function() {
diff --git a/src/node/test/channel_test.js b/src/node/test/channel_test.js
index b86f89b8a850ec8f6bf8292723f45b1129a94ffd..05269f7b6e4ef808d7d023e5baa9046af813fcb3 100644
--- a/src/node/test/channel_test.js
+++ b/src/node/test/channel_test.js
@@ -149,7 +149,7 @@ describe('channel', function() {
     afterEach(function() {
       channel.close();
     });
-    it.only('should time out if called alone', function(done) {
+    it('should time out if called alone', function(done) {
       var old_state = channel.getConnectivityState();
       var deadline = new Date();
       deadline.setSeconds(deadline.getSeconds() + 1);
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index 8eb91ee69e6a808442c9c65ea690eb368f5a09d0..7fc311a888dc0f139ecca1d7efb4e352c5f17536 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -130,8 +130,8 @@ describe('client credentials', function() {
       callback(null, metadata);
     };
     var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
-    var combined_creds = grpc.credentials.combineCredentials(client_ssl_creds,
-                                                             creds);
+    var combined_creds = grpc.credentials.combineChannelCredentials(
+        client_ssl_creds, creds);
     var client = new Client('localhost:' + port, combined_creds,
                             client_options);
     var call = client.unary({}, function(err, data) {
@@ -150,8 +150,8 @@ describe('client credentials', function() {
       callback(null, metadata);
     };
     var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
-    var combined_creds = grpc.credentials.combineCredentials(client_ssl_creds,
-                                                             creds);
+    var combined_creds = grpc.credentials.combineChannelCredentials(
+        client_ssl_creds, creds);
     var client = new Client('localhost:' + port, combined_creds,
                             client_options);
     var call = client.unary({}, function(err, data) {
@@ -231,7 +231,7 @@ describe('client credentials', function() {
           updater_creds, alt_updater_creds);
       var call = client.unary({}, function(err, data) {
         assert.ifError(err);
-      }, null, {credentials: updater_creds});
+      }, null, {credentials: combined_updater});
       call.on('metadata', function(metadata) {
         assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
         assert.deepEqual(metadata.get('other_plugin_key'),
diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js
index 804c1d45e4a8cafcb60fc6252b288e9c98d22ec8..f8c0b14137796063457096d34047452cd820018f 100644
--- a/src/node/test/interop_sanity_test.js
+++ b/src/node/test/interop_sanity_test.js
@@ -71,7 +71,7 @@ describe('Interop tests', function() {
     interop_client.runTest(port, name_override, 'server_streaming', true, true,
                            done);
   });
-  it('should pass ping_pong', function(done) {
+  it.only('should pass ping_pong', function(done) {
     interop_client.runTest(port, name_override, 'ping_pong', true, true, done);
   });
   it('should pass empty_stream', function(done) {
@@ -94,4 +94,12 @@ describe('Interop tests', function() {
     interop_client.runTest(port, name_override, 'custom_metadata',
                            true, true, done);
   });
+  it('should pass status_code_and_message', function(done) {
+    interop_client.runTest(port, name_override, 'status_code_and_message',
+                           true, true, done);
+  });
+  it('should pass unimplemented_method', function(done) {
+    interop_client.runTest(port, name_override, 'unimplemented_method',
+                           true, true, done);
+  });
 });
diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php
index d55d5629b74d15d231667ca965a1ac58ff978052..0590264ef80ba351f44a5535c46f7d798e80afda 100755
--- a/src/php/tests/interop/interop_client.php
+++ b/src/php/tests/interop/interop_client.php
@@ -250,6 +250,23 @@ function pingPong($stub) {
               'Call did not complete successfully');
 }
 
+/**
+ * Run the empty_stream test.
+ * Passes when run against the Node server as of 2015-10-09
+ * @param $stub Stub object that has service methods.
+ */
+function emptyStream($stub) {
+  // for the current PHP implementation, $call->read() will wait
+  // forever for a server response if the server is not sending any.
+  // so this test is imeplemented as a timeout to indicate the absence
+  // of receiving any response from the server
+  $call = $stub->FullDuplexCall(array('timeout' => 100000));
+  $call->writesDone();
+  hardAssert($call->read() === null, 'Server returned too many responses');
+  hardAssert($call->getStatus()->code === Grpc\STATUS_OK,
+              'Call did not complete successfully');
+}
+
 /**
  * Run the cancel_after_begin test.
  * Passes when run against the Node server as of 2015-08-28
@@ -370,6 +387,9 @@ switch ($args['test_case']) {
   case 'ping_pong':
     pingPong($stub);
     break;
+  case 'empty_stream':
+    emptyStream($stub);
+    break;
   case 'cancel_after_begin':
     cancelAfterBegin($stub);
     break;
diff --git a/templates/grpc.gyp.template b/templates/binding.gyp.template
similarity index 53%
rename from templates/grpc.gyp.template
rename to templates/binding.gyp.template
index 9a7637d8bf48a0e3aab979abaafcdb911043d57d..50d0823d1d4dfb9ae2954484891f5aa2b49b1b6d 100644
--- a/templates/grpc.gyp.template
+++ b/templates/binding.gyp.template
@@ -1,7 +1,7 @@
 %YAML 1.2
 --- |
-  # GRPC gyp file
-  # This currently builds C code.
+  # GRPC Node gyp file
+  # This currently builds the Node extension and dependencies
   # This file has been automatically generated from a template file.
   # Please look at the templates directory instead.
   # This file can be regenerated from the template by running
@@ -39,54 +39,24 @@
   # Some of this file is built with the help of
   # https://n8.io/converting-a-c-library-to-gyp/
   {
+    'variables': {
+      'config': '<!(echo $CONFIG)'
+    },
     # TODO: Finish windows support
     'target_defaults': {
-      'default_configuration': 'Debug',
-      'configurations': {
-        'Debug': {
-          'defines': [ 'DEBUG', '_DEBUG' ],
-          'msvs_settings': {
-            'VCCLCompilerTool': {
-              'RuntimeLibrary': 1, # static debug
-            },
-          },
-        },
-        'Release': {
-          'defines': [ 'NDEBUG' ],
-          'msvs_settings': {
-            'VCCLCompilerTool': {
-              'RuntimeLibrary': 0, # static release
-            },
-          },
-        }
-      },
-      'msvs_settings': {
-        'VCLinkerTool': {
-          'GenerateDebugInformation': 'true',
-        },
-      },
-      # TODO: Add fallback for Windows, and if pkg-config is not available
+        # Empirically, Node only exports ALPN symbols if its major version is >0.
+        # io.js always reports versions >0 and always exports ALPN symbols.
+        # Therefore, Node's major version will be truthy if and only if it
+        # supports ALPN. The output of "node -v" is v[major].[minor].[patch],
+        # like "v4.1.1" in a recent version. We use grep to extract just the
+        # major version. "4", would be the output for the example.
       'defines': [
-        'TSI_OPENSSL_ALPN_SUPPORT=<!(pkg-config --atleast-version=1.0.2 openssl >/dev/null 2>&1 && echo 1 || echo 0)'
+        'TSI_OPENSSL_ALPN_SUPPORT=<!(node -v | grep -oP "(?<=v)(\d+)(?=\.\d+\.\d+)")'
       ],
       'include_dirs': [
         '.',
         'include'
-      ],
-      # TODO: Check for libraries with pkg-config
-      'libraries': [
-        '-lcrypto',
-        '-lssl',
-        '-ldl',
-        '-lpthread',
-        '-lz'
-      ],
-      'direct_dependent_settings': {
-        'include_dirs': [
-          '.',
-          'include'
-        ],
-      }
+      ]
     },
     'targets': [
       % for lib in libs:
@@ -108,5 +78,65 @@
       },
       % endif
       % endfor
+      {
+        'include_dirs': [
+          "<!(node -e \"require('nan')\")"
+        ],
+        'cflags': [
+          '-std=c++0x',
+          '-Wall',
+          '-pthread',
+          '-g',
+          '-zdefs',
+          '-Werror',
+          '-Wno-error=deprecated-declarations'
+        ],
+        'ldflags': [
+          '-g'
+        ],
+        "conditions": [
+          ['OS != "win"', {
+            'conditions': [
+              ['config=="gcov"', {
+                'cflags': [
+                  '-ftest-coverage',
+                  '-fprofile-arcs',
+                  '-O0'
+                ],
+                'ldflags': [
+                  '-ftest-coverage',
+                  '-fprofile-arcs'
+                ]
+              }
+             ]
+            ]
+          }],
+          ['OS == "mac"', {
+            'xcode_settings': {
+              'MACOSX_DEPLOYMENT_TARGET': '10.9',
+              'OTHER_CFLAGS': [
+                '-std=c++11',
+                '-stdlib=libc++'
+              ]
+            }
+          }]
+        ],
+        "target_name": "grpc_node",
+        "sources": [
+          "src/node/ext/byte_buffer.cc",
+          "src/node/ext/call.cc",
+          "src/node/ext/call_credentials.cc",
+          "src/node/ext/channel.cc",
+          "src/node/ext/channel_credentials.cc",
+          "src/node/ext/completion_queue_async_worker.cc",
+          "src/node/ext/node_grpc.cc",
+          "src/node/ext/server.cc",
+          "src/node/ext/server_credentials.cc",
+          "src/node/ext/timeval.cc"
+        ],
+        "dependencies": [
+          "grpc"
+        ]
+      }
     ]
   }
diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c
index a4614a2aba4b15d7cbfe52fc79b6b2bcfde52d4e..f321fe1e7c7f8f09769e64dab29394912f336172 100644
--- a/test/core/end2end/tests/compressed_payload.c
+++ b/test/core/end2end/tests/compressed_payload.c
@@ -46,7 +46,7 @@
 #include "test/core/end2end/cq_verifier.h"
 #include "src/core/channel/channel_args.h"
 #include "src/core/channel/compress_filter.h"
-#include "src/core/surface/call.h"
+#include "src/core/surface/call_test_only.h"
 
 enum { TIMEOUT = 200000 };
 
@@ -196,12 +196,13 @@ static void request_with_payload_template(
   cq_expect_completion(cqv, tag(101), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(GPR_BITCOUNT(grpc_call_get_encodings_accepted_by_peer(s)) == 3);
-  GPR_ASSERT(GPR_BITGET(grpc_call_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(
+      GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer(s)) == 3);
+  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_NONE) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_DEFLATE) != 0);
-  GPR_ASSERT(GPR_BITGET(grpc_call_get_encodings_accepted_by_peer(s),
+  GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s),
                         GRPC_COMPRESS_GZIP) != 0);
 
   op = ops;
diff --git a/test/core/profiling/timers_test.c b/test/core/profiling/timers_test.c
index b79cde64bdb22076fcd6d663b75674c626ae1eee..7070fe465f17253729bde3cf3c7f599cf5cc6ae3 100644
--- a/test/core/profiling/timers_test.c
+++ b/test/core/profiling/timers_test.c
@@ -54,15 +54,15 @@ void test_log_events(size_t num_seqs) {
       for (j = 0; j < advance; j++) {
         switch (state[i]) {
           case 0:
-            GRPC_TIMER_MARK(STATE_0, i);
+            GPR_TIMER_MARK(STATE_0, i);
             state[i]++;
             break;
           case 1:
-            GRPC_TIMER_MARK(STATE_1, i);
+            GPR_TIMER_MARK(STATE_1, i);
             state[i]++;
             break;
           case 2:
-            GRPC_TIMER_MARK(STATE_2, i);
+            GPR_TIMER_MARK(STATE_2, i);
             state[i]++;
             break;
           case 3:
@@ -76,8 +76,8 @@ void test_log_events(size_t num_seqs) {
 
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
-  grpc_timers_global_init();
+  gpr_timers_global_init();
   test_log_events(1000000);
-  grpc_timers_global_destroy();
+  gpr_timers_global_destroy();
   return 0;
 }
diff --git a/test/cpp/interop/client_helper.h b/test/cpp/interop/client_helper.h
index 0221df93db5a715bd93781b2077297d1a64014b1..ace193042ee39b1ed88a4226773e4257a678e13d 100644
--- a/test/cpp/interop/client_helper.h
+++ b/test/cpp/interop/client_helper.h
@@ -38,7 +38,7 @@
 
 #include <grpc++/channel.h>
 
-#include "src/core/surface/call.h"
+#include "src/core/surface/call_test_only.h"
 
 namespace grpc {
 namespace testing {
@@ -57,11 +57,11 @@ class InteropClientContextInspector {
 
   // Inspector methods, able to peek inside ClientContext, follow.
   grpc_compression_algorithm GetCallCompressionAlgorithm() const {
-    return grpc_call_get_compression_algorithm(context_.call_);
+    return grpc_call_test_only_get_compression_algorithm(context_.call_);
   }
 
   gpr_uint32 GetMessageFlags() const {
-    return grpc_call_get_message_flags(context_.call_);
+    return grpc_call_test_only_get_message_flags(context_.call_);
   }
 
  private:
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index 4570750846674f276d0444f8ccbe782f0c8648f2..5138a38170a0797fcd2b77360a66afc45b4a8ca9 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -38,7 +38,7 @@
 #include <gflags/gflags.h>
 #include <grpc++/security/server_credentials.h>
 
-#include "src/core/surface/call.h"
+#include "src/core/surface/call_test_only.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 
 DECLARE_bool(use_tls);
@@ -65,11 +65,11 @@ InteropServerContextInspector::InteropServerContextInspector(
 
 grpc_compression_algorithm
 InteropServerContextInspector::GetCallCompressionAlgorithm() const {
-  return grpc_call_get_compression_algorithm(context_.call_);
+  return grpc_call_test_only_get_compression_algorithm(context_.call_);
 }
 
 gpr_uint32 InteropServerContextInspector::GetEncodingsAcceptedByClient() const {
-  return grpc_call_get_encodings_accepted_by_peer(context_.call_);
+  return grpc_call_test_only_get_encodings_accepted_by_peer(context_.call_);
 }
 
 std::shared_ptr<const AuthContext>
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index 6adf92a005c13558d3119b286670bf4247526aed..3c33a1c5de45b34786977d8466ca07e13eea90bb 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -101,7 +101,7 @@ class SynchronousUnaryClient GRPC_FINAL : public SynchronousClient {
     WaitToIssue(thread_idx);
     auto* stub = channels_[thread_idx % channels_.size()].get_stub();
     double start = Timer::Now();
-    GRPC_TIMER_SCOPE("SynchronousUnaryClient::ThreadFunc", 0);
+    GPR_TIMER_SCOPE("SynchronousUnaryClient::ThreadFunc", 0);
     grpc::ClientContext context;
     grpc::Status s =
         stub->UnaryCall(&context, request_, &responses_[thread_idx]);
@@ -138,7 +138,7 @@ class SynchronousStreamingClient GRPC_FINAL : public SynchronousClient {
 
   bool ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
     WaitToIssue(thread_idx);
-    GRPC_TIMER_SCOPE("SynchronousStreamingClient::ThreadFunc", 0);
+    GPR_TIMER_SCOPE("SynchronousStreamingClient::ThreadFunc", 0);
     double start = Timer::Now();
     if (stream_[thread_idx]->Write(request_) &&
         stream_[thread_idx]->Read(&responses_[thread_idx])) {
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index ac763e4b3c617755ea5ef2a250c2d0ee19e98b9f..dd5c4f4f73fe5083d0bc0c549213107b5930c1aa 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -82,9 +82,12 @@ static deque<string> get_hosts(const string& name) {
 namespace runsc {
 
 // ClientContext allocator
-static ClientContext* AllocContext(list<ClientContext>* contexts) {
+template <class T>
+static ClientContext* AllocContext(list<ClientContext>* contexts, T deadline) {
   contexts->emplace_back();
-  return &contexts->back();
+  auto context = &contexts->back();
+  context->set_deadline(deadline);
+  return context;
 }
 
 struct ServerData {
@@ -147,6 +150,11 @@ std::unique_ptr<ScenarioResult> RunScenario(
   // Trim to just what we need
   workers.resize(num_clients + num_servers);
 
+  gpr_timespec deadline =
+      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                   gpr_time_from_seconds(
+                       warmup_seconds + benchmark_seconds + 20, GPR_TIMESPAN));
+
   // Start servers
   using runsc::ServerData;
   // servers is array rather than std::vector to avoid gcc-4.4 issues
@@ -160,7 +168,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
     result_server_config.set_host(workers[i]);
     *args.mutable_setup() = server_config;
     servers[i].stream =
-        servers[i].stub->RunServer(runsc::AllocContext(&contexts));
+        servers[i].stub->RunServer(runsc::AllocContext(&contexts, deadline));
     GPR_ASSERT(servers[i].stream->Write(args));
     ServerStatus init_status;
     GPR_ASSERT(servers[i].stream->Read(&init_status));
@@ -188,7 +196,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
     result_client_config.set_host(workers[i + num_servers]);
     *args.mutable_setup() = client_config;
     clients[i].stream =
-        clients[i].stub->RunTest(runsc::AllocContext(&contexts));
+        clients[i].stub->RunTest(runsc::AllocContext(&contexts, deadline));
     GPR_ASSERT(clients[i].stream->Write(args));
     ClientStatus init_status;
     GPR_ASSERT(clients[i].stream->Read(&init_status));
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 98d56f21eeead9f248949e629204c54db71fd6e7..d3be97ecbc620df946b861b3e732e2d0625d01e6 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -852,12 +852,12 @@ src/core/json/json.h \
 src/core/json/json_common.h \
 src/core/json/json_reader.h \
 src/core/json/json_writer.h \
-src/core/profiling/timers.h \
 src/core/statistics/census_interface.h \
 src/core/statistics/census_rpc_stats.h \
 src/core/surface/api_trace.h \
 src/core/surface/byte_buffer_queue.h \
 src/core/surface/call.h \
+src/core/surface/call_test_only.h \
 src/core/surface/channel.h \
 src/core/surface/completion_queue.h \
 src/core/surface/event_string.h \
@@ -990,8 +990,6 @@ src/core/json/json.c \
 src/core/json/json_reader.c \
 src/core/json/json_string.c \
 src/core/json/json_writer.c \
-src/core/profiling/basic_timers.c \
-src/core/profiling/stap_timers.c \
 src/core/surface/api_trace.c \
 src/core/surface/byte_buffer.c \
 src/core/surface/byte_buffer_queue.c \
@@ -1068,6 +1066,7 @@ include/grpc/support/tls_gcc.h \
 include/grpc/support/tls_msvc.h \
 include/grpc/support/tls_pthread.h \
 include/grpc/support/useful.h \
+src/core/profiling/timers.h \
 src/core/support/block_annotate.h \
 src/core/support/env.h \
 src/core/support/file.h \
@@ -1077,6 +1076,8 @@ src/core/support/string.h \
 src/core/support/string_win32.h \
 src/core/support/thd_internal.h \
 src/core/support/time_precise.h \
+src/core/profiling/basic_timers.c \
+src/core/profiling/stap_timers.c \
 src/core/support/alloc.c \
 src/core/support/cmdline.c \
 src/core/support/cpu_iphone.c \
diff --git a/tools/jenkins/build_docker_and_run_tests.sh b/tools/jenkins/build_docker_and_run_tests.sh
index 8b7809f2e23d213493f2e8871c4c6b56ba65b77a..6e3166ce5799cece3cf8862c0787416d862b34ba 100755
--- a/tools/jenkins/build_docker_and_run_tests.sh
+++ b/tools/jenkins/build_docker_and_run_tests.sh
@@ -53,8 +53,8 @@ DOCKER_IMAGE_NAME=grpc_jenkins_slave${docker_suffix}_`sha1sum tools/jenkins/grpc
 # Make sure docker image has been built. Should be instantaneous if so.
 docker build -t $DOCKER_IMAGE_NAME tools/jenkins/grpc_jenkins_slave$docker_suffix
 
-# Make sure the CID file is gone.
-rm -f docker.cid
+# Choose random name for docker container
+CONTAINER_NAME="run_tests_$(uuidgen)"
 
 # Run tests inside docker
 docker run \
@@ -70,23 +70,21 @@ docker run \
   -v /var/run/docker.sock:/var/run/docker.sock \
   -v $(which docker):/bin/docker \
   -w /var/local/git/grpc \
-  --cidfile=docker.cid \
+  --name=$CONTAINER_NAME \
   $DOCKER_IMAGE_NAME \
   bash -l /var/local/jenkins/grpc/tools/jenkins/docker_run_tests.sh || DOCKER_FAILED="true"
 
-DOCKER_CID=`cat docker.cid`
-
 if [ "$XML_REPORT" != "" ]
 then
-  docker cp "$DOCKER_CID:/var/local/git/grpc/$XML_REPORT" $git_root
+  docker cp "$CONTAINER_NAME:/var/local/git/grpc/$XML_REPORT" $git_root
 fi
 
-docker cp "$DOCKER_CID:/var/local/git/grpc/reports.zip" $git_root || true
+docker cp "$CONTAINER_NAME:/var/local/git/grpc/reports.zip" $git_root || true
 unzip $git_root/reports.zip -d $git_root || true
 rm -f reports.zip
 
 # remove the container, possibly killing it first
-docker rm -f $DOCKER_CID || true
+docker rm -f $CONTAINER_NAME || true
 
 if [ "$DOCKER_FAILED" != "" ] && [ "$XML_REPORT" == "" ]
 then
diff --git a/tools/jenkins/build_interop_image.sh b/tools/jenkins/build_interop_image.sh
index 3664eed84d9b0567f1ae53c10f0453f3593789e3..166efbd9e2f0123048ac22910fc356bdf205fc37 100755
--- a/tools/jenkins/build_interop_image.sh
+++ b/tools/jenkins/build_interop_image.sh
@@ -77,7 +77,7 @@ docker build -t $BASE_IMAGE --force-rm=true tools/jenkins/$BASE_NAME || exit $?
 # Create a local branch so the child Docker script won't complain
 git branch -f jenkins-docker
 
-CIDFILE=`mktemp -u --suffix=.cid`
+CONTAINER_NAME="build_${BASE_NAME}_$(uuidgen)"
 
 # Prepare image for interop tests, commit it on success.
 (docker run \
@@ -85,17 +85,14 @@ CIDFILE=`mktemp -u --suffix=.cid`
   -i $TTY_FLAG \
   $MOUNT_ARGS \
   -v /tmp/ccache:/tmp/ccache \
-  --cidfile=$CIDFILE \
+  --name=$CONTAINER_NAME \
   $BASE_IMAGE \
   bash -l /var/local/jenkins/grpc/tools/jenkins/$BASE_NAME/build_interop.sh \
-  && docker commit `cat $CIDFILE` $INTEROP_IMAGE \
+  && docker commit $CONTAINER_NAME $INTEROP_IMAGE \
   && echo "Successfully built image $INTEROP_IMAGE")
 EXITCODE=$?
 
 # remove intermediate container, possibly killing it first
-docker rm -f `cat $CIDFILE`
-
-# remove the cidfile
-rm -rf `cat $CIDFILE`
+docker rm -f $CONTAINER_NAME
 
 exit $EXITCODE
diff --git a/tools/jenkins/grpc_interop_node/Dockerfile b/tools/jenkins/grpc_interop_node/Dockerfile
index 587227b94294daec0c98f3de898a6f949f0a8af4..db5aff844de1aa96584e56d7a3ee3b474c7cf345 100644
--- a/tools/jenkins/grpc_interop_node/Dockerfile
+++ b/tools/jenkins/grpc_interop_node/Dockerfile
@@ -48,6 +48,7 @@ RUN apt-get update && apt-get install -y \
   libc6-dbg \
   libc6-dev \
   libgtest-dev \
+  libssl-dev \
   libtool \
   make \
   strace \
diff --git a/tools/jenkins/grpc_interop_node/build_interop.sh b/tools/jenkins/grpc_interop_node/build_interop.sh
index 84e25e330886ab3c15cacea0af121a25e49bd3d3..3b69715c9af983effb7126e0312b1588483a0e5c 100755
--- a/tools/jenkins/grpc_interop_node/build_interop.sh
+++ b/tools/jenkins/grpc_interop_node/build_interop.sh
@@ -45,5 +45,4 @@ make install-certs
 
 # build Node interop client & server
 npm install -g node-gyp
-make install_c -C /var/local/git/grpc
-(cd src/node && npm install && node-gyp rebuild)
+(npm install && node-gyp rebuild)
diff --git a/tools/jenkins/grpc_jenkins_slave/Dockerfile b/tools/jenkins/grpc_jenkins_slave/Dockerfile
index 5f2b425c8c27e2ef171365c6e4126546c23c88a0..129a8db24fafd5f86fb99b5f5e2e71c4616b362f 100644
--- a/tools/jenkins/grpc_jenkins_slave/Dockerfile
+++ b/tools/jenkins/grpc_jenkins_slave/Dockerfile
@@ -157,6 +157,12 @@ RUN apt-get update && apt-get install -y \
 
 RUN apt-get install -y libzookeeper-mt-dev
 
+##################
+# Docker "inception".
+# Note this is quite the ugly hack.
+# This makes sure that the docker binary we inject has its dependencies.
+RUN curl https://get.docker.com/ | sh
+RUN apt-get remove --purge -y docker-engine
 
 RUN mkdir /var/local/jenkins
 
diff --git a/tools/run_tests/dockerjob.py b/tools/run_tests/dockerjob.py
index 11686d46b09ed8267a157d216ae1b671e28bcb47..1d67fe3033e2d0880fedb512cc96ff0dbeaaf80f 100755
--- a/tools/run_tests/dockerjob.py
+++ b/tools/run_tests/dockerjob.py
@@ -38,24 +38,32 @@ import subprocess
 
 _DEVNULL = open(os.devnull, 'w')
 
-def wait_for_file(filepath, timeout_seconds=15):
-  """Wait until given file exists and returns its content."""
-  started = time.time()
-  while time.time() - started < timeout_seconds:
-    if os.path.isfile(filepath):
-      with open(filepath, 'r') as f:
-        content = f.read()
-        # make sure we don't return empty content
-        if content:
-          return content
-    time.sleep(1)
-  raise Exception('Failed to read file %s.' % filepath)
+
+def random_name(base_name):
+  """Randomizes given base name."""
+  return '%s_%s' % (base_name, uuid.uuid4())
+
+
+def docker_kill(cid):
+  """Kills a docker container. Returns True if successful."""
+  return subprocess.call(['docker','kill', str(cid)],
+                         stdout=_DEVNULL,
+                         stderr=subprocess.STDOUT) == 0
 
 
-def docker_mapped_port(cid, port):
+def docker_mapped_port(cid, port, timeout_seconds=15):
   """Get port mapped to internal given internal port for given container."""
-  output = subprocess.check_output('docker port %s %s' % (cid, port), shell=True)
-  return int(output.split(':', 2)[1])
+  started = time.time()
+  while time.time() - started < timeout_seconds:
+    try:
+      output = subprocess.check_output('docker port %s %s' % (cid, port),
+                                       stderr=_DEVNULL,
+                                       shell=True)
+      return int(output.split(':', 2)[1])
+    except subprocess.CalledProcessError as e:
+      pass
+  raise Exception('Failed to get exposed port %s for container %s.' %
+                  (port, cid))
 
 
 def finish_jobs(jobs):
@@ -71,7 +79,7 @@ def image_exists(image):
   """Returns True if given docker image exists."""
   return subprocess.call(['docker','inspect', image],
                          stdout=_DEVNULL,
-                         stderr=_DEVNULL) == 0
+                         stderr=subprocess.STDOUT) == 0
 
 
 def remove_image(image, skip_nonexistent=False, max_retries=10):
@@ -79,7 +87,9 @@ def remove_image(image, skip_nonexistent=False, max_retries=10):
   if skip_nonexistent and not image_exists(image):
     return True
   for attempt in range(0, max_retries):
-    if subprocess.call(['docker','rmi', '-f', image]) == 0:
+    if subprocess.call(['docker','rmi', '-f', image],
+                       stdout=_DEVNULL,
+                       stderr=subprocess.STDOUT) == 0:
       return True
     time.sleep(2)
   print 'Failed to remove docker image %s' % image
@@ -92,23 +102,16 @@ class DockerJob:
   def __init__(self, spec):
     self._spec = spec
     self._job = jobset.Job(spec, bin_hash=None, newline_on_success=True, travis=True, add_env={}, xml_report=None)
-    self._cidfile = spec.cidfile
-    self._cid = None
-
-  def cid(self):
-    """Gets cid of this container"""
-    if not self._cid:
-      self._cid = wait_for_file(self._cidfile)
-    return self._cid
+    self._container_name = spec.container_name
 
   def mapped_port(self, port):
-    return docker_mapped_port(self.cid(), port)
+    return docker_mapped_port(self._container_name, port)
 
   def kill(self, suppress_failure=False):
     """Sends kill signal to the container."""
     if suppress_failure:
       self._job.suppress_failure_message()
-    return subprocess.call(['docker','kill', self.cid()]) == 0
+    return docker_kill(self._container_name)
 
   def is_running(self):
     """Polls a job and returns True if given job is still running."""
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index 87be703b4cdfa6d1a3b859db603801b32a461717..17a63c02e8413a2c2c04fcd6b959afb6cded0fd6 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -135,13 +135,14 @@ class JobSpec(object):
 
   def __init__(self, cmdline, shortname=None, environ=None, hash_targets=None,
                cwd=None, shell=False, timeout_seconds=5*60, flake_retries=0,
-               timeout_retries=0):
+               timeout_retries=0, kill_handler=None):
     """
     Arguments:
       cmdline: a list of arguments to pass as the command line
       environ: a dictionary of environment variables to set in the child process
       hash_targets: which files to include in the hash representing the jobs version
                     (or empty, indicating the job should not be hashed)
+      kill_handler: a handler that will be called whenever job.kill() is invoked
     """
     if environ is None:
       environ = {}
@@ -156,6 +157,7 @@ class JobSpec(object):
     self.timeout_seconds = timeout_seconds
     self.flake_retries = flake_retries
     self.timeout_retries = timeout_retries
+    self.kill_handler = kill_handler
 
   def identity(self):
     return '%r %r %r' % (self.cmdline, self.environ, self.hash_targets)
@@ -254,6 +256,8 @@ class Job(object):
   def kill(self):
     if self._state == _RUNNING:
       self._state = _KILLED
+      if self._spec.kill_handler:
+        self._spec.kill_handler(self)
       self._process.terminate()
 
   def suppress_failure_message(self):
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index f328f4642ee117260bc54fea566e1046f08c9f0b..6daa967bba488f01f0e8a589a205aa72a3c079ce 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -71,6 +71,7 @@ class CXXLanguage:
     self.client_cmdline_base = ['bins/opt/interop_client']
     self.client_cwd = None
     self.server_cwd = None
+    self.safename = 'cxx'
 
   def cloud_to_prod_args(self):
     return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@@ -96,6 +97,7 @@ class CSharpLanguage:
     self.client_cmdline_base = ['mono', 'Grpc.IntegrationTesting.Client.exe']
     self.client_cwd = 'src/csharp/Grpc.IntegrationTesting.Client/bin/Debug'
     self.server_cwd = 'src/csharp/Grpc.IntegrationTesting.Server/bin/Debug'
+    self.safename = str(self)
 
   def cloud_to_prod_args(self):
     return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@@ -121,6 +123,7 @@ class JavaLanguage:
     self.client_cmdline_base = ['./run-test-client.sh']
     self.client_cwd = '../grpc-java'
     self.server_cwd = '../grpc-java'
+    self.safename = str(self)
 
   def cloud_to_prod_args(self):
     return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@@ -147,6 +150,7 @@ class GoLanguage:
     # TODO: this relies on running inside docker
     self.client_cwd = '/go/src/google.golang.org/grpc/interop/client'
     self.server_cwd = '/go/src/google.golang.org/grpc/interop/server'
+    self.safename = str(self)
 
   def cloud_to_prod_args(self):
     return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@@ -172,6 +176,7 @@ class NodeLanguage:
     self.client_cmdline_base = ['node', 'src/node/interop/interop_client.js']
     self.client_cwd = None
     self.server_cwd = None
+    self.safename = str(self)
 
   def cloud_to_prod_args(self):
     return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@@ -196,6 +201,7 @@ class PHPLanguage:
   def __init__(self):
     self.client_cmdline_base = ['src/php/bin/interop_client.sh']
     self.client_cwd = None
+    self.safename = str(self)
 
   def cloud_to_prod_args(self):
     return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@@ -218,6 +224,7 @@ class RubyLanguage:
     self.client_cmdline_base = ['ruby', 'src/ruby/bin/interop/interop_client.rb']
     self.client_cwd = None
     self.server_cwd = None
+    self.safename = str(self)
 
   def cloud_to_prod_args(self):
     return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@@ -251,11 +258,9 @@ _LANGUAGES = {
 # languages supported as cloud_to_cloud servers
 _SERVERS = ['c++', 'node', 'csharp', 'java', 'go', 'ruby']
 
-# TODO(jtattermusch): add empty_stream once PHP starts supporting it.
 # TODO(jtattermusch): add timeout_on_sleeping_server once java starts supporting it.
-# TODO(jtattermusch): add support for auth tests.
 _TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong',
-               'client_streaming', 'server_streaming',
+               'empty_stream', 'client_streaming', 'server_streaming',
                'cancel_after_begin', 'cancel_after_first_response']
 
 _AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds',
@@ -321,17 +326,29 @@ def add_auth_options(language, test_case, cmdline, env):
   return (cmdline, env)
 
 
+def _job_kill_handler(job):
+  if job._spec.container_name:
+    dockerjob.docker_kill(job._spec.container_name)
+
+
 def cloud_to_prod_jobspec(language, test_case, docker_image=None, auth=False):
   """Creates jobspec for cloud-to-prod interop test"""
   cmdline = language.cloud_to_prod_args() + ['--test_case=%s' % test_case]
   cwd = language.client_cwd
   environ = language.cloud_to_prod_env()
+  container_name = None
   if auth:
     cmdline, environ = add_auth_options(language, test_case, cmdline, environ)
   cmdline = bash_login_cmdline(cmdline)
 
   if docker_image:
-    cmdline = docker_run_cmdline(cmdline, image=docker_image, cwd=cwd, environ=environ)
+    container_name = dockerjob.random_name('interop_client_%s' % language.safename)
+    cmdline = docker_run_cmdline(cmdline,
+                                 image=docker_image,
+                                 cwd=cwd,
+                                 environ=environ,
+                                 docker_args=['--net=host',
+                                              '--name', container_name])
     cwd = None
     environ = None
 
@@ -343,7 +360,9 @@ def cloud_to_prod_jobspec(language, test_case, docker_image=None, auth=False):
           shortname="%s:%s:%s" % (suite_name, language, test_case),
           timeout_seconds=2*60,
           flake_retries=5 if args.allow_flakes else 0,
-          timeout_retries=2 if args.allow_flakes else 0)
+          timeout_retries=2 if args.allow_flakes else 0,
+          kill_handler=_job_kill_handler)
+  test_job.container_name = container_name
   return test_job
 
 
@@ -356,11 +375,14 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
                                 '--server_port=%s' % server_port ])
   cwd = language.client_cwd
   if docker_image:
+    container_name = dockerjob.random_name('interop_client_%s' % language.safename)
     cmdline = docker_run_cmdline(cmdline,
                                  image=docker_image,
                                  cwd=cwd,
-                                 docker_args=['--net=host'])
+                                 docker_args=['--net=host',
+                                              '--name', container_name])
     cwd = None
+
   test_job = jobset.JobSpec(
           cmdline=cmdline,
           cwd=cwd,
@@ -368,34 +390,36 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
                                                  test_case),
           timeout_seconds=2*60,
           flake_retries=5 if args.allow_flakes else 0,
-          timeout_retries=2 if args.allow_flakes else 0)
+          timeout_retries=2 if args.allow_flakes else 0,
+          kill_handler=_job_kill_handler)
+  test_job.container_name = container_name
   return test_job
 
 
 def server_jobspec(language, docker_image):
   """Create jobspec for running a server"""
-  cidfile = tempfile.mktemp()
+  container_name = dockerjob.random_name('interop_server_%s' % language.safename)
   cmdline = bash_login_cmdline(language.server_args() +
                                ['--port=%s' % _DEFAULT_SERVER_PORT])
   docker_cmdline = docker_run_cmdline(cmdline,
                                       image=docker_image,
                                       cwd=language.server_cwd,
                                       docker_args=['-p', str(_DEFAULT_SERVER_PORT),
-                                                   '--cidfile', cidfile])
+                                                   '--name', container_name])
   server_job = jobset.JobSpec(
           cmdline=docker_cmdline,
-          shortname="interop_server:%s" % language,
+          shortname="interop_server_%s" % language,
           timeout_seconds=30*60)
-  server_job.cidfile = cidfile
+  server_job.container_name = container_name
   return server_job
 
 
 def build_interop_image_jobspec(language, tag=None):
   """Creates jobspec for building interop docker image for a language"""
-  safelang = str(language).replace("+", "x")
   if not tag:
-    tag = 'grpc_interop_%s:%s' % (safelang, uuid.uuid4())
-  env = {'INTEROP_IMAGE': tag, 'BASE_NAME': 'grpc_interop_%s' % safelang}
+    tag = 'grpc_interop_%s:%s' % (language.safename, uuid.uuid4())
+  env = {'INTEROP_IMAGE': tag,
+         'BASE_NAME': 'grpc_interop_%s' % language.safename}
   if not args.travis:
     env['TTY_FLAG'] = '-t'
   build_job = jobset.JobSpec(
diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh
index 780969089daec2bb8d3540ee95d9251fce14f72a..0a11e87c37a7cfd023ae93cf84f3c0a60a4abde9 100755
--- a/tools/run_tests/run_node.sh
+++ b/tools/run_tests/run_node.sh
@@ -46,6 +46,8 @@ then
   lcov --base-directory . --directory . -c -o coverage.info
   genhtml -o ../reports/node_ext_coverage --num-spaces 2 \
     -t 'Node gRPC test coverage' coverage.info
+  echo '<html><head><meta http-equiv="refresh" content="0;URL=lcov-report/index.html"></head></html>' > \
+    ../reports/node_coverage/index.html
 else
   ./node_modules/mocha/bin/mocha --timeout 8000 src/node/test
 fi
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index a3bed4ef8793d7ec9f59b7e4e2dbae536eb5fd89..ce1e0887f2d68fde84b0aa6d7d41f5d56229af0f 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -101,7 +101,8 @@ class SimpleConfig(object):
                           timeout_seconds=self.timeout_seconds,
                           hash_targets=hash_targets
                               if self.allow_hashing else None,
-                          flake_retries=5 if args.allow_flakes else 0)
+                          flake_retries=5 if args.allow_flakes else 0,
+                          timeout_retries=3 if args.allow_flakes else 0)
 
 
 # ValgrindConfig: compile with some CONFIG=config, but use valgrind to run
@@ -121,7 +122,7 @@ class ValgrindConfig(object):
                           shortname='valgrind %s' % cmdline[0],
                           hash_targets=None,
                           flake_retries=5 if args.allow_flakes else 0,
-                          timeout_retries=2 if args.allow_flakes else 0)
+                          timeout_retries=3 if args.allow_flakes else 0)
 
 
 def get_c_tests(travis, test_lang) :
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index f2237e0fef76491cd7e5015bf9f0531575ddd77b..32c490376d99d5043ed404552b93644ab07fe6a8 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -12161,6 +12161,7 @@
       "include/grpc/support/tls_msvc.h", 
       "include/grpc/support/tls_pthread.h", 
       "include/grpc/support/useful.h", 
+      "src/core/profiling/timers.h", 
       "src/core/support/block_annotate.h", 
       "src/core/support/env.h", 
       "src/core/support/file.h", 
@@ -12201,6 +12202,9 @@
       "include/grpc/support/tls_msvc.h", 
       "include/grpc/support/tls_pthread.h", 
       "include/grpc/support/useful.h", 
+      "src/core/profiling/basic_timers.c", 
+      "src/core/profiling/stap_timers.c", 
+      "src/core/profiling/timers.h", 
       "src/core/support/alloc.c", 
       "src/core/support/block_annotate.h", 
       "src/core/support/cmdline.c", 
@@ -12351,7 +12355,6 @@
       "src/core/json/json_common.h", 
       "src/core/json/json_reader.h", 
       "src/core/json/json_writer.h", 
-      "src/core/profiling/timers.h", 
       "src/core/security/auth_filters.h", 
       "src/core/security/base64.h", 
       "src/core/security/credentials.h", 
@@ -12366,6 +12369,7 @@
       "src/core/surface/api_trace.h", 
       "src/core/surface/byte_buffer_queue.h", 
       "src/core/surface/call.h", 
+      "src/core/surface/call_test_only.h", 
       "src/core/surface/channel.h", 
       "src/core/surface/completion_queue.h", 
       "src/core/surface/event_string.h", 
@@ -12569,9 +12573,6 @@
       "src/core/json/json_string.c", 
       "src/core/json/json_writer.c", 
       "src/core/json/json_writer.h", 
-      "src/core/profiling/basic_timers.c", 
-      "src/core/profiling/stap_timers.c", 
-      "src/core/profiling/timers.h", 
       "src/core/security/auth_filters.h", 
       "src/core/security/base64.c", 
       "src/core/security/base64.h", 
@@ -12608,6 +12609,7 @@
       "src/core/surface/call.h", 
       "src/core/surface/call_details.c", 
       "src/core/surface/call_log_batch.c", 
+      "src/core/surface/call_test_only.h", 
       "src/core/surface/channel.c", 
       "src/core/surface/channel.h", 
       "src/core/surface/channel_connectivity.c", 
@@ -12856,12 +12858,12 @@
       "src/core/json/json_common.h", 
       "src/core/json/json_reader.h", 
       "src/core/json/json_writer.h", 
-      "src/core/profiling/timers.h", 
       "src/core/statistics/census_interface.h", 
       "src/core/statistics/census_rpc_stats.h", 
       "src/core/surface/api_trace.h", 
       "src/core/surface/byte_buffer_queue.h", 
       "src/core/surface/call.h", 
+      "src/core/surface/call_test_only.h", 
       "src/core/surface/channel.h", 
       "src/core/surface/completion_queue.h", 
       "src/core/surface/event_string.h", 
@@ -13059,9 +13061,6 @@
       "src/core/json/json_string.c", 
       "src/core/json/json_writer.c", 
       "src/core/json/json_writer.h", 
-      "src/core/profiling/basic_timers.c", 
-      "src/core/profiling/stap_timers.c", 
-      "src/core/profiling/timers.h", 
       "src/core/statistics/census_interface.h", 
       "src/core/statistics/census_rpc_stats.h", 
       "src/core/surface/api_trace.c", 
@@ -13074,6 +13073,7 @@
       "src/core/surface/call.h", 
       "src/core/surface/call_details.c", 
       "src/core/surface/call_log_batch.c", 
+      "src/core/surface/call_test_only.h", 
       "src/core/surface/channel.c", 
       "src/core/surface/channel.h", 
       "src/core/surface/channel_connectivity.c", 
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj
index 4c3b36abdc8bfa46cb6cb6086c32d0d8e6ed5437..fa495db07b663308881fcc11d16d3c115428560f 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj
@@ -163,6 +163,7 @@
     <ClInclude Include="..\..\..\include\grpc\support\useful.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\..\src\core\profiling\timers.h" />
     <ClInclude Include="..\..\..\src\core\support\block_annotate.h" />
     <ClInclude Include="..\..\..\src\core\support\env.h" />
     <ClInclude Include="..\..\..\src\core\support\file.h" />
@@ -174,6 +175,10 @@
     <ClInclude Include="..\..\..\src\core\support\time_precise.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\..\src\core\profiling\basic_timers.c">
+    </ClCompile>
+    <ClCompile Include="..\..\..\src\core\profiling\stap_timers.c">
+    </ClCompile>
     <ClCompile Include="..\..\..\src\core\support\alloc.c">
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\support\cmdline.c">
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
index 69391b4f991ef412feecd6b99ad3414862b7f96c..ee03e454535d8fe67eb60377ded282de312b5bf3 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
+    <ClCompile Include="..\..\..\src\core\profiling\basic_timers.c">
+      <Filter>src\core\profiling</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\src\core\profiling\stap_timers.c">
+      <Filter>src\core\profiling</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\..\src\core\support\alloc.c">
       <Filter>src\core\support</Filter>
     </ClCompile>
@@ -200,6 +206,9 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\..\src\core\profiling\timers.h">
+      <Filter>src\core\profiling</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\..\src\core\support\block_annotate.h">
       <Filter>src\core\support</Filter>
     </ClInclude>
@@ -245,6 +254,9 @@
     <Filter Include="src\core">
       <UniqueIdentifier>{c5e1baa7-de77-beb1-9675-942261648f79}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\profiling">
+      <UniqueIdentifier>{93b7086c-8c8a-6bbf-fb14-1f166bf0146a}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\support">
       <UniqueIdentifier>{bb116f2a-ea2a-c233-82da-0c54e3cbfec1}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 183edbc05bf7cd124537104857d68049da4de391..23bcd0c4430cdc5c7d607f944ebdb9923f1b5eba 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -338,12 +338,12 @@
     <ClInclude Include="..\..\..\src\core\json\json_common.h" />
     <ClInclude Include="..\..\..\src\core\json\json_reader.h" />
     <ClInclude Include="..\..\..\src\core\json\json_writer.h" />
-    <ClInclude Include="..\..\..\src\core\profiling\timers.h" />
     <ClInclude Include="..\..\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="..\..\..\src\core\statistics\census_rpc_stats.h" />
     <ClInclude Include="..\..\..\src\core\surface\api_trace.h" />
     <ClInclude Include="..\..\..\src\core\surface\byte_buffer_queue.h" />
     <ClInclude Include="..\..\..\src\core\surface\call.h" />
+    <ClInclude Include="..\..\..\src\core\surface\call_test_only.h" />
     <ClInclude Include="..\..\..\src\core\surface\channel.h" />
     <ClInclude Include="..\..\..\src\core\surface\completion_queue.h" />
     <ClInclude Include="..\..\..\src\core\surface\event_string.h" />
@@ -575,10 +575,6 @@
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\json\json_writer.c">
     </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\basic_timers.c">
-    </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\stap_timers.c">
-    </ClCompile>
     <ClCompile Include="..\..\..\src\core\surface\api_trace.c">
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\surface\byte_buffer.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 66ce9ca05be6387db553db3a0be7571d201cf373..1cfccf0e197664f81c53cfb1a0cb9328de66dfc4 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -292,12 +292,6 @@
     <ClCompile Include="..\..\..\src\core\json\json_writer.c">
       <Filter>src\core\json</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\basic_timers.c">
-      <Filter>src\core\profiling</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\stap_timers.c">
-      <Filter>src\core\profiling</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\..\src\core\surface\api_trace.c">
       <Filter>src\core\surface</Filter>
     </ClCompile>
@@ -725,9 +719,6 @@
     <ClInclude Include="..\..\..\src\core\json\json_writer.h">
       <Filter>src\core\json</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\src\core\profiling\timers.h">
-      <Filter>src\core\profiling</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>
@@ -743,6 +734,9 @@
     <ClInclude Include="..\..\..\src\core\surface\call.h">
       <Filter>src\core\surface</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\core\surface\call_test_only.h">
+      <Filter>src\core\surface</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\..\src\core\surface\channel.h">
       <Filter>src\core\surface</Filter>
     </ClInclude>
@@ -896,9 +890,6 @@
     <Filter Include="src\core\json">
       <UniqueIdentifier>{e665cc0e-b994-d7c5-cc18-2007392019f0}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\profiling">
-      <UniqueIdentifier>{87674b72-0f05-0469-481a-bd8c7af9ad80}</UniqueIdentifier>
-    </Filter>
     <Filter Include="src\core\security">
       <UniqueIdentifier>{1d850ac6-e639-4eab-5338-4ba40272fcc9}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index b527179f9f314935c5bac6aade3c72617646481c..e308a03fdaa4f5647d728c31b8f32032313caaea 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -317,12 +317,12 @@
     <ClInclude Include="..\..\..\src\core\json\json_common.h" />
     <ClInclude Include="..\..\..\src\core\json\json_reader.h" />
     <ClInclude Include="..\..\..\src\core\json\json_writer.h" />
-    <ClInclude Include="..\..\..\src\core\profiling\timers.h" />
     <ClInclude Include="..\..\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="..\..\..\src\core\statistics\census_rpc_stats.h" />
     <ClInclude Include="..\..\..\src\core\surface\api_trace.h" />
     <ClInclude Include="..\..\..\src\core\surface\byte_buffer_queue.h" />
     <ClInclude Include="..\..\..\src\core\surface\call.h" />
+    <ClInclude Include="..\..\..\src\core\surface\call_test_only.h" />
     <ClInclude Include="..\..\..\src\core\surface\channel.h" />
     <ClInclude Include="..\..\..\src\core\surface\completion_queue.h" />
     <ClInclude Include="..\..\..\src\core\surface\event_string.h" />
@@ -514,10 +514,6 @@
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\json\json_writer.c">
     </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\basic_timers.c">
-    </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\stap_timers.c">
-    </ClCompile>
     <ClCompile Include="..\..\..\src\core\surface\api_trace.c">
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\surface\byte_buffer.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 7be3c9ec93b65d5cfd028d9f04de7f987e01d998..370d1f6fb2f5db2390008b2196edc34c3799c0bd 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -232,12 +232,6 @@
     <ClCompile Include="..\..\..\src\core\json\json_writer.c">
       <Filter>src\core\json</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\basic_timers.c">
-      <Filter>src\core\profiling</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\..\src\core\profiling\stap_timers.c">
-      <Filter>src\core\profiling</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\..\src\core\surface\api_trace.c">
       <Filter>src\core\surface</Filter>
     </ClCompile>
@@ -623,9 +617,6 @@
     <ClInclude Include="..\..\..\src\core\json\json_writer.h">
       <Filter>src\core\json</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\src\core\profiling\timers.h">
-      <Filter>src\core\profiling</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>
@@ -641,6 +632,9 @@
     <ClInclude Include="..\..\..\src\core\surface\call.h">
       <Filter>src\core\surface</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\core\surface\call_test_only.h">
+      <Filter>src\core\surface</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\..\src\core\surface\channel.h">
       <Filter>src\core\surface</Filter>
     </ClInclude>
@@ -794,9 +788,6 @@
     <Filter Include="src\core\json">
       <UniqueIdentifier>{443ffc61-1bea-2477-6e54-1ddf8c139264}</UniqueIdentifier>
     </Filter>
-    <Filter Include="src\core\profiling">
-      <UniqueIdentifier>{7f91d9bf-c9de-835a-d74d-b16f843b89a9}</UniqueIdentifier>
-    </Filter>
     <Filter Include="src\core\statistics">
       <UniqueIdentifier>{e084164c-a069-00e3-db35-4e0b1cd6f0b7}</UniqueIdentifier>
     </Filter>