[metal] Improve order in device creation

Change it to follow device struct allocation, initialization, and
subresource creation. This way we can handle destruction on failures
better.
diff --git a/experimental/metal/metal_device.m b/experimental/metal/metal_device.m
index 191bd25..5e697cd 100644
--- a/experimental/metal/metal_device.m
+++ b/experimental/metal/metal_device.m
@@ -94,7 +94,23 @@
   iree_host_size_t total_size = iree_sizeof_struct(*device) + identifier.size;
   IREE_RETURN_IF_ERROR(iree_allocator_malloc(host_allocator, total_size, (void**)&device));
 
+  iree_hal_resource_initialize(&iree_hal_metal_device_vtable, &device->resource);
+  iree_string_view_append_to_buffer(identifier, &device->identifier,
+                                    (char*)device + iree_sizeof_struct(*device));
+  iree_arena_block_pool_initialize(params->arena_block_size, host_allocator, &device->block_pool);
+  device->params = *params;
+  device->host_allocator = host_allocator;
+
+  device->device = [metal_device retain];                            // +1
   id<MTLCommandQueue> metal_queue = [metal_device newCommandQueue];  // +1
+  device->queue = metal_queue;
+  device->command_buffer_resource_reference_mode = params->command_buffer_resource_reference_mode;
+  dispatch_queue_attr_t queue_attr = dispatch_queue_attr_make_with_qos_class(
+      DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, /*relative_priority=*/0);
+  device->semaphore_notification_queue = dispatch_queue_create("dev.iree.queue.metal", queue_attr);
+  device->event_listener = [[MTLSharedEventListener alloc]
+      initWithDispatchQueue:device->semaphore_notification_queue];  // +1
+  device->capture_manager = NULL;
 
   iree_status_t status = iree_hal_metal_allocator_create(metal_device,
 #if defined(IREE_PLATFORM_MACOS)
@@ -103,40 +119,20 @@
                                                          params->resource_hazard_tracking_mode,
                                                          host_allocator, &device->device_allocator);
 
-  iree_hal_metal_builtin_executable_t* builtin_executable = NULL;
   if (iree_status_is_ok(status)) {
-    status =
-        iree_hal_metal_builtin_executable_create(metal_device, host_allocator, &builtin_executable);
-  } else {
-    iree_hal_device_release((iree_hal_device_t*)device);
+    status = iree_hal_metal_builtin_executable_create(metal_device, host_allocator,
+                                                      &device->builtin_executable);
   }
 
   if (iree_status_is_ok(status)) {
     status = iree_hal_metal_staging_buffer_initialize(
         metal_device, params->queue_uniform_buffer_size, &device->staging_buffer);
-  } else {
-    iree_hal_device_release((iree_hal_device_t*)device);
   }
 
   if (iree_status_is_ok(status)) {
-    iree_hal_resource_initialize(&iree_hal_metal_device_vtable, &device->resource);
-    iree_string_view_append_to_buffer(identifier, &device->identifier,
-                                      (char*)device + iree_sizeof_struct(*device));
-    iree_arena_block_pool_initialize(params->arena_block_size, host_allocator, &device->block_pool);
-    device->params = *params;
-    device->host_allocator = host_allocator;
-    device->device = [metal_device retain];  // +1
-    device->queue = metal_queue;
-    device->command_buffer_resource_reference_mode = params->command_buffer_resource_reference_mode;
-    device->builtin_executable = builtin_executable;
-    dispatch_queue_attr_t queue_attr = dispatch_queue_attr_make_with_qos_class(
-        DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, /*relative_priority=*/0);
-    device->semaphore_notification_queue =
-        dispatch_queue_create("dev.iree.queue.metal", queue_attr);
-    device->event_listener = [[MTLSharedEventListener alloc]
-        initWithDispatchQueue:device->semaphore_notification_queue];  // +1
-    device->capture_manager = NULL;
     *out_device = (iree_hal_device_t*)device;
+  } else {
+    iree_hal_device_release((iree_hal_device_t*)device);
   }
   return status;
 }