[vm] Propagate more UTF8 conversion errors

Change-Id: I8d4f3a892a51bed8b922961bd74bcad727f66508
Reviewed-on: https://dart-review.googlesource.com/73280
Commit-Queue: Zach Anderson <zra@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 9270003..86685dc 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -52,6 +52,8 @@
 const char* const DartUtils::kHttpScheme = "http:";
 const char* const DartUtils::kVMServiceLibURL = "dart:vmservice";
 
+dart::SimpleHashMap* DartUtils::environment_ = NULL;
+
 MagicNumberData appjit_magic_number = {8, {0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0}};
 MagicNumberData snapshot_magic_number = {4, {0xf5, 0xf5, 0xdc, 0xdc}};
 MagicNumberData kernel_magic_number = {4, {0x90, 0xab, 0xcd, 0xef}};
@@ -803,6 +805,43 @@
   return Dart_NewStringFromCString(new_str);
 }
 
+void DartUtils::SetEnvironment(dart::SimpleHashMap* environment) {
+  environment_ = environment;
+}
+
+Dart_Handle DartUtils::EnvironmentCallback(Dart_Handle name) {
+  uint8_t* utf8_array;
+  intptr_t utf8_len;
+  Dart_Handle result = Dart_Null();
+  Dart_Handle handle = Dart_StringToUTF8(name, &utf8_array, &utf8_len);
+  if (Dart_IsError(handle)) {
+    handle = Dart_ThrowException(
+        DartUtils::NewDartArgumentError(Dart_GetError(handle)));
+  } else {
+    char* name_chars = reinterpret_cast<char*>(malloc(utf8_len + 1));
+    memmove(name_chars, utf8_array, utf8_len);
+    name_chars[utf8_len] = '\0';
+    const char* value = NULL;
+    if (environment_ != NULL) {
+      SimpleHashMap::Entry* entry =
+          environment_->Lookup(GetHashmapKeyFromString(name_chars),
+                               SimpleHashMap::StringHash(name_chars), false);
+      if (entry != NULL) {
+        value = reinterpret_cast<char*>(entry->value);
+      }
+    }
+    if (value != NULL) {
+      result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(value),
+                                      strlen(value));
+      if (Dart_IsError(result)) {
+        result = Dart_Null();
+      }
+    }
+    free(name_chars);
+  }
+  return result;
+}
+
 // Statically allocated Dart_CObject instances for immutable
 // objects. As these will be used by different threads the use of
 // these depends on the fact that the marking internally in the
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index c6a9b23..5bfaf6d 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -10,6 +10,7 @@
 #include "include/dart_native_api.h"
 #include "platform/assert.h"
 #include "platform/globals.h"
+#include "platform/hashmap.h"
 
 namespace dart {
 namespace bin {
@@ -33,6 +34,10 @@
   return handle;
 }
 
+static inline void* GetHashmapKeyFromString(char* key) {
+  return reinterpret_cast<void*>(key);
+}
+
 class CommandLineOptions {
  public:
   explicit CommandLineOptions(int max_count)
@@ -256,6 +261,9 @@
 
   static Dart_Handle LibraryFilePath(Dart_Handle library_uri);
 
+  static void SetEnvironment(dart::SimpleHashMap* environment);
+  static Dart_Handle EnvironmentCallback(Dart_Handle name);
+
  private:
   static Dart_Handle SetWorkingDirectory();
   static Dart_Handle PrepareBuiltinLibrary(Dart_Handle builtin_lib,
@@ -271,6 +279,8 @@
   static Dart_Handle PrepareIsolateLibrary(Dart_Handle isolate_lib);
   static Dart_Handle PrepareCLILibrary(Dart_Handle cli_lib);
 
+  static dart::SimpleHashMap* environment_;
+
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(DartUtils);
 };
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index de20ad9..362a955 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -25,7 +25,8 @@
   Namespace* namespc = Namespace::GetNamespace(args, 0);
   const char* current = Directory::Current(namespc);
   if (current != NULL) {
-    Dart_SetReturnValue(args, DartUtils::NewString(current));
+    Dart_Handle str = ThrowIfError(DartUtils::NewString(current));
+    Dart_SetReturnValue(args, str);
   } else {
     Dart_SetReturnValue(args, DartUtils::NewDartOSError());
   }
@@ -106,7 +107,8 @@
 void FUNCTION_NAME(Directory_SystemTemp)(Dart_NativeArguments args) {
   Namespace* namespc = Namespace::GetNamespace(args, 0);
   const char* result = Directory::SystemTemp(namespc);
-  Dart_SetReturnValue(args, DartUtils::NewString(result));
+  Dart_Handle str = ThrowIfError(DartUtils::NewString(result));
+  Dart_SetReturnValue(args, str);
 }
 
 void FUNCTION_NAME(Directory_CreateTemp)(Dart_NativeArguments args) {
@@ -125,7 +127,8 @@
     }
   }
   if (result != NULL) {
-    Dart_SetReturnValue(args, DartUtils::NewString(result));
+    Dart_Handle str = ThrowIfError(DartUtils::NewString(result));
+    Dart_SetReturnValue(args, str);
   } else {
     Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
   }
@@ -248,10 +251,7 @@
                                sizeof(*listing), ReleaseListing);
   Dart_Handle result = Dart_SetNativeInstanceField(
       dart_this, kAsyncDirectoryListerFieldIndex, listing_pointer);
-  if (Dart_IsError(result)) {
-    Log::PrintErr("SetAsyncDirectoryListerPointer failed\n");
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
 }
 
 void Directory::SetSystemTemp(const char* path) {
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index bfd5c0e..8132cde 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -413,7 +413,7 @@
   virtual bool IsListeningSocket() const { return true; }
 
   virtual void SetPortAndMask(Dart_Port port, intptr_t mask) {
-    HashMap::Entry* entry = tokens_map_.Lookup(
+    SimpleHashMap::Entry* entry = tokens_map_.Lookup(
         GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), true);
     PortEntry* pentry;
     if (entry->value == NULL) {
@@ -454,7 +454,7 @@
       } while (current != root);
     }
 
-    for (HashMap::Entry* entry = tokens_map_.Start(); entry != NULL;
+    for (SimpleHashMap::Entry* entry = tokens_map_.Start(); entry != NULL;
          entry = tokens_map_.Next(entry)) {
       PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
       if (pentry->IsReady()) {
@@ -467,7 +467,7 @@
   }
 
   virtual void RemovePort(Dart_Port port) {
-    HashMap::Entry* entry = tokens_map_.Lookup(
+    SimpleHashMap::Entry* entry = tokens_map_.Lookup(
         GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false);
     if (entry != NULL) {
       PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
@@ -491,7 +491,7 @@
   }
 
   virtual void RemoveAllPorts() {
-    for (HashMap::Entry* entry = tokens_map_.Start(); entry != NULL;
+    for (SimpleHashMap::Entry* entry = tokens_map_.Start(); entry != NULL;
          entry = tokens_map_.Next(entry)) {
       PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
       entry->value = NULL;
@@ -532,7 +532,7 @@
     ASSERT(IS_EVENT(events, kCloseEvent) || IS_EVENT(events, kErrorEvent) ||
            IS_EVENT(events, kDestroyedEvent));
 
-    for (HashMap::Entry* entry = tokens_map_.Start(); entry != NULL;
+    for (SimpleHashMap::Entry* entry = tokens_map_.Start(); entry != NULL;
          entry = tokens_map_.Next(entry)) {
       PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
       DartUtils::PostInt32(pentry->dart_port, events);
@@ -550,7 +550,7 @@
   }
 
   virtual void ReturnTokens(Dart_Port port, int count) {
-    HashMap::Entry* entry = tokens_map_.Lookup(
+    SimpleHashMap::Entry* entry = tokens_map_.Lookup(
         GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false);
     ASSERT(entry != NULL);
 
@@ -588,7 +588,7 @@
 
   // A convenience mapping:
   //   Dart_Port -> struct PortEntry { dart_port, mask, token_count }
-  HashMap tokens_map_;
+  SimpleHashMap tokens_map_;
 
   bool disable_tokens_;
 
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 07e6c04..a6bd764 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -75,7 +75,7 @@
 }
 
 EventHandlerImplementation::EventHandlerImplementation()
-    : socket_map_(&HashMap::SamePointerValue, 16) {
+    : socket_map_(&SimpleHashMap::SamePointerValue, 16) {
   intptr_t result;
   result = NO_RETRY_EXPECTED(pipe(interrupt_fds_));
   if (result != 0) {
@@ -143,8 +143,8 @@
     intptr_t fd,
     bool is_listening) {
   ASSERT(fd >= 0);
-  HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd),
-                                             GetHashmapHashFromFd(fd), true);
+  SimpleHashMap::Entry* entry = socket_map_.Lookup(
+      GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
   ASSERT(entry != NULL);
   DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value);
   if (di == NULL) {
diff --git a/runtime/bin/eventhandler_android.h b/runtime/bin/eventhandler_android.h
index c934549..0cfd543 100644
--- a/runtime/bin/eventhandler_android.h
+++ b/runtime/bin/eventhandler_android.h
@@ -85,7 +85,7 @@
   static void* GetHashmapKeyFromFd(intptr_t fd);
   static uint32_t GetHashmapHashFromFd(intptr_t fd);
 
-  HashMap socket_map_;
+  SimpleHashMap socket_map_;
   TimeoutQueue timeout_queue_;
   bool shutdown_;
   int interrupt_fds_[2];
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 6a7ae35..0f16c8e 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -266,7 +266,7 @@
 }
 
 EventHandlerImplementation::EventHandlerImplementation()
-    : socket_map_(&HashMap::SamePointerValue, 16) {
+    : socket_map_(&SimpleHashMap::SamePointerValue, 16) {
   shutdown_ = false;
   // Create the port.
   port_handle_ = ZX_HANDLE_INVALID;
@@ -311,7 +311,7 @@
     bool is_listening) {
   IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
   ASSERT(handle->fd() >= 0);
-  HashMap::Entry* entry =
+  SimpleHashMap::Entry* entry =
       socket_map_.Lookup(GetHashmapKeyFromFd(handle->fd()),
                          GetHashmapHashFromFd(handle->fd()), true);
   ASSERT(entry != NULL);
diff --git a/runtime/bin/eventhandler_fuchsia.h b/runtime/bin/eventhandler_fuchsia.h
index 170f7bd..5a9f1ab 100644
--- a/runtime/bin/eventhandler_fuchsia.h
+++ b/runtime/bin/eventhandler_fuchsia.h
@@ -158,7 +158,7 @@
   intptr_t GetPollEvents(intptr_t events);
   void HandleInterrupt(InterruptMessage* msg);
 
-  HashMap socket_map_;
+  SimpleHashMap socket_map_;
   TimeoutQueue timeout_queue_;
   bool shutdown_;
   zx_handle_t port_handle_;
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 2b20572..d02a49e 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -69,7 +69,7 @@
 }
 
 EventHandlerImplementation::EventHandlerImplementation()
-    : socket_map_(&HashMap::SamePointerValue, 16) {
+    : socket_map_(&SimpleHashMap::SamePointerValue, 16) {
   intptr_t result;
   result = NO_RETRY_EXPECTED(pipe(interrupt_fds_));
   if (result != 0) {
@@ -151,8 +151,8 @@
     intptr_t fd,
     bool is_listening) {
   ASSERT(fd >= 0);
-  HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd),
-                                             GetHashmapHashFromFd(fd), true);
+  SimpleHashMap::Entry* entry = socket_map_.Lookup(
+      GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
   ASSERT(entry != NULL);
   DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value);
   if (di == NULL) {
diff --git a/runtime/bin/eventhandler_linux.h b/runtime/bin/eventhandler_linux.h
index d817bd5..ac468dc 100644
--- a/runtime/bin/eventhandler_linux.h
+++ b/runtime/bin/eventhandler_linux.h
@@ -83,7 +83,7 @@
   static void* GetHashmapKeyFromFd(intptr_t fd);
   static uint32_t GetHashmapHashFromFd(intptr_t fd);
 
-  HashMap socket_map_;
+  SimpleHashMap socket_map_;
   TimeoutQueue timeout_queue_;
   bool shutdown_;
   int interrupt_fds_[2];
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index 974ab8a..04abaac 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -93,7 +93,7 @@
 }
 
 EventHandlerImplementation::EventHandlerImplementation()
-    : socket_map_(&HashMap::SamePointerValue, 16) {
+    : socket_map_(&SimpleHashMap::SamePointerValue, 16) {
   intptr_t result;
   result = NO_RETRY_EXPECTED(pipe(interrupt_fds_));
   if (result != 0) {
@@ -160,8 +160,8 @@
     intptr_t fd,
     bool is_listening) {
   ASSERT(fd >= 0);
-  HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd),
-                                             GetHashmapHashFromFd(fd), true);
+  SimpleHashMap::Entry* entry = socket_map_.Lookup(
+      GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
   ASSERT(entry != NULL);
   DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value);
   if (di == NULL) {
diff --git a/runtime/bin/eventhandler_macos.h b/runtime/bin/eventhandler_macos.h
index c8ed3ba..7550fce 100644
--- a/runtime/bin/eventhandler_macos.h
+++ b/runtime/bin/eventhandler_macos.h
@@ -96,7 +96,7 @@
   static void* GetHashmapKeyFromFd(intptr_t fd);
   static uint32_t GetHashmapHashFromFd(intptr_t fd);
 
-  HashMap socket_map_;
+  SimpleHashMap socket_map_;
   TimeoutQueue timeout_queue_;
   bool shutdown_;
   int interrupt_fds_[2];
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 56cf4c9..45e5b91 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -49,10 +49,7 @@
   DEBUG_ASSERT(IsFile(dart_this));
   Dart_Handle result = Dart_SetNativeInstanceField(
       dart_this, kFileNativeFieldIndex, file_pointer);
-  if (Dart_IsError(result)) {
-    Log::PrintErr("SetNativeInstanceField in SetFile() failed\n");
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
 }
 
 void FUNCTION_NAME(File_GetPointer)(Dart_NativeArguments args) {
@@ -213,9 +210,7 @@
     dart_args[2] = Dart_NewInteger(bytes_read);
     // TODO(sgjesse): Cache the _makeUint8ListView function somewhere.
     Dart_Handle io_lib = Dart_LookupLibrary(DartUtils::NewString("dart:io"));
-    if (Dart_IsError(io_lib)) {
-      Dart_PropagateError(io_lib);
-    }
+    ThrowIfError(io_lib);
     Dart_Handle array_view =
         Dart_Invoke(io_lib, DartUtils::NewString("_makeUint8ListView"),
                     kNumArgs, dart_args);
@@ -239,9 +234,7 @@
   intptr_t length = end - start;
   intptr_t array_len = 0;
   Dart_Handle result = Dart_ListLength(buffer_obj, &array_len);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
   ASSERT(end <= array_len);
   uint8_t* buffer = Dart_ScopeAllocate(length);
   int64_t bytes_read = file->Read(reinterpret_cast<void*>(buffer), length);
@@ -278,9 +271,7 @@
   void* buffer = NULL;
   Dart_Handle result =
       Dart_TypedDataAcquireData(buffer_obj, &type, &buffer, &buffer_len);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
 
   ASSERT(type == Dart_TypedData_kUint8 || type == Dart_TypedData_kInt8);
   ASSERT(end <= buffer_len);
@@ -291,11 +282,7 @@
   bool success = file->WriteFully(byte_buffer + start, length);
 
   // Release the direct pointer acquired above.
-  result = Dart_TypedDataReleaseData(buffer_obj);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-
+  ThrowIfError(Dart_TypedDataReleaseData(buffer_obj));
   if (!success) {
     Dart_SetReturnValue(args, DartUtils::NewDartOSError());
   } else {
@@ -567,7 +554,8 @@
   if (target == NULL) {
     Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
   } else {
-    Dart_SetReturnValue(args, DartUtils::NewString(target));
+    Dart_Handle str = ThrowIfError(DartUtils::NewString(target));
+    Dart_SetReturnValue(args, str);
   }
 }
 
@@ -700,7 +688,8 @@
     }
   }
   if (path != NULL) {
-    Dart_SetReturnValue(args, DartUtils::NewString(path));
+    Dart_Handle str = ThrowIfError(DartUtils::NewString(path));
+    Dart_SetReturnValue(args, str);
   } else {
     Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
   }
@@ -743,22 +732,16 @@
   }
   Dart_Handle returned_data =
       Dart_NewTypedData(Dart_TypedData_kInt64, File::kStatSize);
-  if (Dart_IsError(returned_data)) {
-    Dart_PropagateError(returned_data);
-  }
+  ThrowIfError(returned_data);
   Dart_TypedData_Type data_type_unused;
   void* data_location;
   intptr_t data_length_unused;
   Dart_Handle status = Dart_TypedDataAcquireData(
       returned_data, &data_type_unused, &data_location, &data_length_unused);
-  if (Dart_IsError(status)) {
-    Dart_PropagateError(status);
-  }
+  ThrowIfError(status);
   memmove(data_location, stat_data, File::kStatSize * sizeof(int64_t));
   status = Dart_TypedDataReleaseData(returned_data);
-  if (Dart_IsError(status)) {
-    Dart_PropagateError(status);
-  }
+  ThrowIfError(status);
   Dart_SetReturnValue(args, returned_data);
 }
 
diff --git a/runtime/bin/file_system_watcher_android.cc b/runtime/bin/file_system_watcher_android.cc
index b138d435..0bef08c 100644
--- a/runtime/bin/file_system_watcher_android.cc
+++ b/runtime/bin/file_system_watcher_android.cc
@@ -123,10 +123,12 @@
       Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
       Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
       if (e->len > 0) {
-        Dart_ListSetAt(
-            event, 2,
-            Dart_NewStringFromUTF8(reinterpret_cast<uint8_t*>(e->name),
-                                   strlen(e->name)));
+        Dart_Handle name = Dart_NewStringFromUTF8(
+            reinterpret_cast<uint8_t*>(e->name), strlen(e->name));
+        if (Dart_IsError(name)) {
+          return name;
+        }
+        Dart_ListSetAt(event, 2, name);
       } else {
         Dart_ListSetAt(event, 2, Dart_Null());
       }
diff --git a/runtime/bin/file_system_watcher_linux.cc b/runtime/bin/file_system_watcher_linux.cc
index a0387c0..c23c133 100644
--- a/runtime/bin/file_system_watcher_linux.cc
+++ b/runtime/bin/file_system_watcher_linux.cc
@@ -123,10 +123,12 @@
       Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
       Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
       if (e->len > 0) {
-        Dart_ListSetAt(
-            event, 2,
-            Dart_NewStringFromUTF8(reinterpret_cast<uint8_t*>(e->name),
-                                   strlen(e->name)));
+        Dart_Handle name = Dart_NewStringFromUTF8(
+            reinterpret_cast<uint8_t*>(e->name), strlen(e->name));
+        if (Dart_IsError(name)) {
+          return name;
+        }
+        Dart_ListSetAt(event, 2, name);
       } else {
         Dart_ListSetAt(event, 2, Dart_Null());
       }
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 9a4f87a..53ca879 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -376,9 +376,12 @@
     }
     Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
     Dart_ListSetAt(event, 1, Dart_NewInteger(1));
-    Dart_ListSetAt(event, 2,
-                   Dart_NewStringFromUTF8(
-                       reinterpret_cast<uint8_t*>(e.data.path), path_len));
+    Dart_Handle name = Dart_NewStringFromUTF8(
+        reinterpret_cast<uint8_t*>(e.data.path), path_len);
+    if (Dart_IsError(name)) {
+      return name;
+    }
+    Dart_ListSetAt(event, 2, name);
     Dart_ListSetAt(event, 3, Dart_NewBoolean(true));
     Dart_ListSetAt(event, 4, Dart_NewInteger(path_id));
     Dart_ListSetAt(events, i, event);
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 32c310e..e75b1fa 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -86,11 +86,7 @@
 static CommandLineOptions* entry_points_files = NULL;
 
 // The environment provided through the command line using -D options.
-static dart::HashMap* environment = NULL;
-
-static void* GetHashmapKeyFromString(char* key) {
-  return reinterpret_cast<void*>(key);
-}
+static dart::SimpleHashMap* environment = NULL;
 
 static bool ProcessEnvironmentOption(const char* arg,
                                      CommandLineOptions* vm_options) {
@@ -98,36 +94,6 @@
                                                    &environment);
 }
 
-static Dart_Handle EnvironmentCallback(Dart_Handle name) {
-  uint8_t* utf8_array;
-  intptr_t utf8_len;
-  Dart_Handle result = Dart_Null();
-  Dart_Handle handle = Dart_StringToUTF8(name, &utf8_array, &utf8_len);
-  if (Dart_IsError(handle)) {
-    handle = Dart_ThrowException(
-        DartUtils::NewDartArgumentError(Dart_GetError(handle)));
-  } else {
-    char* name_chars = reinterpret_cast<char*>(malloc(utf8_len + 1));
-    memmove(name_chars, utf8_array, utf8_len);
-    name_chars[utf8_len] = '\0';
-    const char* value = NULL;
-    if (environment != NULL) {
-      HashMap::Entry* entry =
-          environment->Lookup(GetHashmapKeyFromString(name_chars),
-                              HashMap::StringHash(name_chars), false);
-      if (entry != NULL) {
-        value = reinterpret_cast<char*>(entry->value);
-      }
-    }
-    if (value != NULL) {
-      result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(value),
-                                      strlen(value));
-    }
-    free(name_chars);
-  }
-  return result;
-}
-
 static const char* kSnapshotKindNames[] = {
     "core",
     "core-jit",
@@ -1423,7 +1389,8 @@
   }
 
   Dart_EnterScope();
-  Dart_Handle result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+  Dart_Handle result =
+      Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
   CHECK_RESULT(result);
 
   // The root library has to be set to generate AOT snapshots, and sometimes we
@@ -1510,6 +1477,7 @@
     PrintUsage();
     return kErrorExitCode;
   }
+  DartUtils::SetEnvironment(environment);
 
   // Sniff the script to check if it is actually a dill file.
   uint8_t* kernel_buffer = NULL;
@@ -1656,7 +1624,7 @@
     return 0;
   }
 
-  result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+  result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
   CHECK_RESULT(result);
 
   // Load up the script before a snapshot is created.
@@ -1709,7 +1677,7 @@
       exit(kErrorExitCode);
     }
     Dart_EnterScope();
-    result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+    result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
     CHECK_RESULT(result);
 
     // Set up the library tag handler in such a manner that it will use the
diff --git a/runtime/bin/hashmap_test.cc b/runtime/bin/hashmap_test.cc
index 7234f41..307d21f 100644
--- a/runtime/bin/hashmap_test.cc
+++ b/runtime/bin/hashmap_test.cc
@@ -17,11 +17,12 @@
 class IntSet {
  public:
   explicit IntSet(IntKeyHash hash)
-      : hash_(hash), map_(HashMap::SamePointerValue, kInitialSize) {}
+      : hash_(hash), map_(SimpleHashMap::SamePointerValue, kInitialSize) {}
 
   void Insert(int x) {
     EXPECT_NE(0, x);  // 0 corresponds to (void*)NULL - illegal key value
-    HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), hash_(x), true);
+    SimpleHashMap::Entry* p =
+        map_.Lookup(reinterpret_cast<void*>(x), hash_(x), true);
     EXPECT(p != NULL);  // insert is set!
     EXPECT_EQ(reinterpret_cast<void*>(x), p->key);
     // We don't care about p->value.
@@ -33,7 +34,7 @@
   }
 
   bool Present(int x) {
-    HashMap::Entry* p =
+    SimpleHashMap::Entry* p =
         map_.Lookup(reinterpret_cast<void*>(x), hash_(x), false);
     if (p != NULL) {
       EXPECT_EQ(reinterpret_cast<void*>(x), p->key);
@@ -45,7 +46,7 @@
 
   uint32_t occupancy() const {
     uint32_t count = 0;
-    for (HashMap::Entry* p = map_.Start(); p != NULL; p = map_.Next(p)) {
+    for (SimpleHashMap::Entry* p = map_.Start(); p != NULL; p = map_.Next(p)) {
       count++;
     }
     EXPECT_EQ(map_.occupancy_, count);
@@ -54,7 +55,7 @@
 
  private:
   IntKeyHash hash_;
-  HashMap map_;
+  SimpleHashMap map_;
 };
 
 static uint32_t WordHash(uint32_t key) {
@@ -166,7 +167,7 @@
   EXPECT_EQ(0u, set.occupancy());
 }
 
-VM_UNIT_TEST_CASE(HashMap_Basic) {
+VM_UNIT_TEST_CASE(SimpleHashMap_Basic) {
   TestSet(WordHash, 100);
   TestSet(Hash, 100);
   TestSet(CollisionHash1, 50);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 5531dd5..2c18c3b 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -114,40 +114,6 @@
   return dart_arguments;
 }
 
-static void* GetHashmapKeyFromString(char* key) {
-  return reinterpret_cast<void*>(key);
-}
-
-static Dart_Handle EnvironmentCallback(Dart_Handle name) {
-  uint8_t* utf8_array;
-  intptr_t utf8_len;
-  Dart_Handle result = Dart_Null();
-  Dart_Handle handle = Dart_StringToUTF8(name, &utf8_array, &utf8_len);
-  if (Dart_IsError(handle)) {
-    handle = Dart_ThrowException(
-        DartUtils::NewDartArgumentError(Dart_GetError(handle)));
-  } else {
-    char* name_chars = reinterpret_cast<char*>(malloc(utf8_len + 1));
-    memmove(name_chars, utf8_array, utf8_len);
-    name_chars[utf8_len] = '\0';
-    const char* value = NULL;
-    if (Options::environment() != NULL) {
-      HashMap::Entry* entry = Options::environment()->Lookup(
-          GetHashmapKeyFromString(name_chars), HashMap::StringHash(name_chars),
-          false);
-      if (entry != NULL) {
-        value = reinterpret_cast<char*>(entry->value);
-      }
-    }
-    if (value != NULL) {
-      result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(value),
-                                      strlen(value));
-    }
-    free(name_chars);
-  }
-  return result;
-}
-
 #define SAVE_ERROR_AND_EXIT(result)                                            \
   *error = strdup(Dart_GetError(result));                                      \
   if (Dart_IsCompilationError(result)) {                                       \
@@ -330,7 +296,7 @@
 #endif
   }
 
-  result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+  result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
   CHECK_RESULT(result);
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -626,7 +592,7 @@
     result = Dart_CompileAll();
     CHECK_RESULT(result);
   }
-  result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+  result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
   CHECK_RESULT(result);
   Dart_ExitScope();
   Dart_ExitIsolate();
@@ -1182,6 +1148,7 @@
       Platform::Exit(kErrorExitCode);
     }
   }
+  DartUtils::SetEnvironment(Options::environment());
 
   Loader::InitOnce();
 
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index f2e1e1f..9e7a323 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -227,7 +227,7 @@
 }
 // clang-format on
 
-dart::HashMap* Options::environment_ = NULL;
+dart::SimpleHashMap* Options::environment_ = NULL;
 bool Options::ProcessEnvironmentOption(const char* arg,
                                        CommandLineOptions* vm_options) {
   return OptionProcessor::ProcessEnvironmentOption(arg, vm_options,
@@ -236,7 +236,7 @@
 
 void Options::DestroyEnvironment() {
   if (environment_ != NULL) {
-    for (HashMap::Entry* p = environment_->Start(); p != NULL;
+    for (SimpleHashMap::Entry* p = environment_->Start(); p != NULL;
          p = environment_->Next(p)) {
       free(p->key);
       free(p->value);
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index a90fffd..53184a4 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -115,7 +115,7 @@
   static void SetDart2Options(CommandLineOptions* vm_options);
   static void SetDart1Options(CommandLineOptions* vm_options);
 
-  static dart::HashMap* environment() { return environment_; }
+  static dart::SimpleHashMap* environment() { return environment_; }
 
   static const char* vm_service_server_ip() { return vm_service_server_ip_; }
   static int vm_service_server_port() { return vm_service_server_port_; }
@@ -148,7 +148,7 @@
   ENUM_OPTIONS_LIST(ENUM_OPTION_DECL)
 #undef ENUM_OPTION_DECL
 
-  static dart::HashMap* environment_;
+  static dart::SimpleHashMap* environment_;
 
 // Frontend argument processing.
 #if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/bin/options.cc b/runtime/bin/options.cc
index 5fc416d..f9652c6 100644
--- a/runtime/bin/options.cc
+++ b/runtime/bin/options.cc
@@ -41,13 +41,10 @@
   return false;
 }
 
-static void* GetHashmapKeyFromString(char* key) {
-  return reinterpret_cast<void*>(key);
-}
-
-bool OptionProcessor::ProcessEnvironmentOption(const char* arg,
-                                               CommandLineOptions* vm_options,
-                                               dart::HashMap** environment) {
+bool OptionProcessor::ProcessEnvironmentOption(
+    const char* arg,
+    CommandLineOptions* vm_options,
+    dart::SimpleHashMap** environment) {
   ASSERT(arg != NULL);
   ASSERT(environment != NULL);
   if (*arg == '\0') {
@@ -64,7 +61,7 @@
     return true;
   }
   if (*environment == NULL) {
-    *environment = new HashMap(&HashMap::SameStringValue, 4);
+    *environment = new SimpleHashMap(&SimpleHashMap::SameStringValue, 4);
   }
   // Split the name=value part of the -Dname=value argument.
   char* name;
@@ -85,9 +82,10 @@
   strncpy(name, arg, name_len);
   name[name_len] = '\0';
   value = strdup(equals_pos + 1);
-  HashMap::Entry* entry = (*environment)
-                              ->Lookup(GetHashmapKeyFromString(name),
-                                       HashMap::StringHash(name), true);
+  SimpleHashMap::Entry* entry =
+      (*environment)
+          ->Lookup(GetHashmapKeyFromString(name),
+                   SimpleHashMap::StringHash(name), true);
   ASSERT(entry != NULL);  // Lookup adds an entry if key not found.
   if (entry->value != NULL) {
     free(name);
diff --git a/runtime/bin/options.h b/runtime/bin/options.h
index d1d6088..e4edbcf 100644
--- a/runtime/bin/options.h
+++ b/runtime/bin/options.h
@@ -34,7 +34,7 @@
 
   static bool ProcessEnvironmentOption(const char* arg,
                                        CommandLineOptions* vm_options,
-                                       dart::HashMap** environment);
+                                       dart::SimpleHashMap** environment);
 
  private:
   static OptionProcessor* first_;
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index eff6dfb..20003a0 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -4,6 +4,7 @@
 
 #include "bin/platform.h"
 
+#include "bin/dartutils.h"
 #include "bin/file.h"
 #include "bin/utils.h"
 #include "include/dart_api.h"
@@ -16,7 +17,9 @@
 }
 
 void FUNCTION_NAME(Platform_OperatingSystem)(Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, DartUtils::NewString(Platform::OperatingSystem()));
+  Dart_Handle str = DartUtils::NewString(Platform::OperatingSystem());
+  ThrowIfError(str);
+  Dart_SetReturnValue(args, str);
 }
 
 void FUNCTION_NAME(Platform_OperatingSystemVersion)(Dart_NativeArguments args) {
@@ -24,19 +27,25 @@
   if (version == NULL) {
     Dart_SetReturnValue(args, DartUtils::NewDartOSError());
   } else {
-    Dart_SetReturnValue(args, DartUtils::NewString(version));
+    Dart_Handle str = DartUtils::NewString(version);
+    ThrowIfError(str);
+    Dart_SetReturnValue(args, str);
   }
 }
 
 void FUNCTION_NAME(Platform_PathSeparator)(Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, DartUtils::NewString(File::PathSeparator()));
+  Dart_Handle str = DartUtils::NewString(File::PathSeparator());
+  ThrowIfError(str);
+  Dart_SetReturnValue(args, str);
 }
 
 void FUNCTION_NAME(Platform_LocalHostname)(Dart_NativeArguments args) {
   const intptr_t HOSTNAME_LENGTH = 256;
   char hostname[HOSTNAME_LENGTH];
   if (Platform::LocalHostname(hostname, HOSTNAME_LENGTH)) {
-    Dart_SetReturnValue(args, DartUtils::NewString(hostname));
+    Dart_Handle str = DartUtils::NewString(hostname);
+    ThrowIfError(str);
+    Dart_SetReturnValue(args, str);
   } else {
     Dart_SetReturnValue(args, DartUtils::NewDartOSError());
   }
@@ -66,10 +75,8 @@
   Dart_Handle result = Dart_NewListOf(Dart_CoreType_String, end - 1);
   for (intptr_t i = 1; i < end; i++) {
     Dart_Handle str = DartUtils::NewString(argv[i]);
-    Dart_Handle error = Dart_ListSetAt(result, i - 1, str);
-    if (Dart_IsError(error)) {
-      Dart_PropagateError(error);
-    }
+    ThrowIfError(str);
+    ThrowIfError(Dart_ListSetAt(result, i - 1, str));
   }
   Dart_SetReturnValue(args, result);
 }
@@ -83,9 +90,7 @@
     Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
   } else {
     Dart_Handle result = Dart_NewList(count);
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     intptr_t result_idx = 0;
     for (intptr_t env_idx = 0; env_idx < count; env_idx++) {
       Dart_Handle str = DartUtils::NewString(env[env_idx]);
@@ -95,9 +100,7 @@
         continue;
       }
       Dart_Handle error = Dart_ListSetAt(result, result_idx, str);
-      if (Dart_IsError(error)) {
-        Dart_PropagateError(error);
-      }
+      ThrowIfError(error);
       result_idx++;
     }
     Dart_SetReturnValue(args, result);
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index 1c1191a..065b477 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -28,21 +28,15 @@
   ASSERT(Dart_IsList(strings));
   intptr_t len = 0;
   Dart_Handle result = Dart_ListLength(strings, &len);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
   // Protect against user-defined list implementations that can have
   // arbitrary length.
   if ((len < 0) || (len > kMaxArgumentListLength)) {
     result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     result = DartUtils::SetStringField(status_handle, "_errorMessage",
                                        "Max argument list length exceeded");
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     return NULL;
   }
   *length = len;
@@ -51,19 +45,13 @@
       reinterpret_cast<char**>(Dart_ScopeAllocate(len * sizeof(*string_args)));
   for (int i = 0; i < len; i++) {
     Dart_Handle arg = Dart_ListGetAt(strings, i);
-    if (Dart_IsError(arg)) {
-      Dart_PropagateError(arg);
-    }
+    ThrowIfError(arg);
     if (!Dart_IsString(arg)) {
       result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
-      if (Dart_IsError(result)) {
-        Dart_PropagateError(result);
-      }
+      ThrowIfError(result);
       result =
           DartUtils::SetStringField(status_handle, "_errorMessage", error_msg);
-      if (Dart_IsError(result)) {
-        Dart_PropagateError(result);
-      }
+      ThrowIfError(result);
       return NULL;
     }
     string_args[i] = const_cast<char*>(DartUtils::GetStringValue(arg));
@@ -100,14 +88,10 @@
   Dart_Handle result;
   if (!Dart_IsString(path_handle)) {
     result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     result = DartUtils::SetStringField(status_handle, "_errorMessage",
                                        "Path must be a builtin string");
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     Dart_SetBooleanReturnValue(args, false);
     return;
   }
@@ -128,15 +112,11 @@
     working_directory = DartUtils::GetStringValue(working_directory_handle);
   } else if (!Dart_IsNull(working_directory_handle)) {
     result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     result =
         DartUtils::SetStringField(status_handle, "_errorMessage",
                                   "WorkingDirectory must be a builtin string");
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     Dart_SetBooleanReturnValue(args, false);
     return;
   }
@@ -183,16 +163,12 @@
   } else {
     result =
         DartUtils::SetIntegerField(status_handle, "_errorCode", error_code);
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
     result = DartUtils::SetStringField(status_handle, "_errorMessage",
                                        os_error_message != NULL
                                            ? os_error_message
                                            : "Cannot get error message");
-    if (Dart_IsError(result)) {
-      Dart_PropagateError(result);
-    }
+    ThrowIfError(result);
   }
   Dart_SetBooleanReturnValue(args, error_code == 0);
 }
@@ -220,13 +196,9 @@
   exit_event->SetClosedFd();
   if (success) {
     Dart_Handle out = result.stdout_data();
-    if (Dart_IsError(out)) {
-      Dart_PropagateError(out);
-    }
+    ThrowIfError(out);
     Dart_Handle err = result.stderr_data();
-    if (Dart_IsError(err)) {
-      Dart_PropagateError(err);
-    }
+    ThrowIfError(err);
     Dart_Handle list = Dart_NewList(4);
     Dart_ListSetAt(list, 0, Dart_NewInteger(pid));
     Dart_ListSetAt(list, 1, Dart_NewInteger(result.exit_code()));
@@ -316,15 +288,11 @@
   Dart_Handle bytes = Dart_GetNativeArgument(args, 0);
   intptr_t bytes_length = 0;
   Dart_Handle result = Dart_ListLength(bytes, &bytes_length);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
   uint8_t* buffer = Dart_ScopeAllocate(bytes_length + 1);
   result = Dart_ListGetAsBytes(bytes, 0, buffer, bytes_length);
   buffer[bytes_length] = '\0';
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
   intptr_t len;
   char* str = StringUtils::ConsoleStringToUtf8(reinterpret_cast<char*>(buffer),
                                                bytes_length, &len);
@@ -333,6 +301,7 @@
         DartUtils::NewInternalError("SystemEncodingToString failed"));
   }
   result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(str), len);
+  ThrowIfError(result);
   Dart_SetReturnValue(args, result);
 }
 
@@ -342,9 +311,7 @@
   intptr_t utf8_len;
   Dart_Handle result =
       Dart_StringToUTF8(str, reinterpret_cast<uint8_t**>(&utf8), &utf8_len);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
+  ThrowIfError(result);
   intptr_t system_len;
   const char* system_string =
       StringUtils::Utf8ToConsoleString(utf8, utf8_len, &system_len);
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index c22ee52..d8ee1bc 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -44,7 +44,7 @@
 
 ListeningSocketRegistry::OSSocket* ListeningSocketRegistry::LookupByPort(
     intptr_t port) {
-  HashMap::Entry* entry = sockets_by_port_.Lookup(
+  SimpleHashMap::Entry* entry = sockets_by_port_.Lookup(
       GetHashmapKeyFromIntptr(port), GetHashmapHashFromIntptr(port), false);
   if (entry == NULL) {
     return NULL;
@@ -53,7 +53,7 @@
 }
 
 void ListeningSocketRegistry::InsertByPort(intptr_t port, OSSocket* socket) {
-  HashMap::Entry* entry = sockets_by_port_.Lookup(
+  SimpleHashMap::Entry* entry = sockets_by_port_.Lookup(
       GetHashmapKeyFromIntptr(port), GetHashmapHashFromIntptr(port), true);
   ASSERT(entry != NULL);
   entry->value = reinterpret_cast<void*>(socket);
@@ -66,7 +66,7 @@
 
 ListeningSocketRegistry::OSSocket* ListeningSocketRegistry::LookupByFd(
     Socket* fd) {
-  HashMap::Entry* entry = sockets_by_fd_.Lookup(
+  SimpleHashMap::Entry* entry = sockets_by_fd_.Lookup(
       GetHashmapKeyFromIntptr(reinterpret_cast<intptr_t>(fd)),
       GetHashmapHashFromIntptr(reinterpret_cast<intptr_t>(fd)), false);
   if (entry == NULL) {
@@ -76,7 +76,7 @@
 }
 
 void ListeningSocketRegistry::InsertByFd(Socket* fd, OSSocket* socket) {
-  HashMap::Entry* entry = sockets_by_fd_.Lookup(
+  SimpleHashMap::Entry* entry = sockets_by_fd_.Lookup(
       GetHashmapKeyFromIntptr(reinterpret_cast<intptr_t>(fd)),
       GetHashmapHashFromIntptr(reinterpret_cast<intptr_t>(fd)), true);
   ASSERT(entry != NULL);
@@ -234,7 +234,7 @@
 void ListeningSocketRegistry::CloseAllSafe() {
   MutexLocker ml(mutex_);
 
-  for (HashMap::Entry* cursor = sockets_by_fd_.Start(); cursor != NULL;
+  for (SimpleHashMap::Entry* cursor = sockets_by_fd_.Start(); cursor != NULL;
        cursor = sockets_by_fd_.Next(cursor)) {
     CloseOneSafe(reinterpret_cast<OSSocket*>(cursor->value), false);
   }
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index a521e53..05a25121 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -248,8 +248,8 @@
   bool CloseOneSafe(OSSocket* os_socket, bool update_hash_maps);
   void CloseAllSafe();
 
-  HashMap sockets_by_port_;
-  HashMap sockets_by_fd_;
+  SimpleHashMap sockets_by_port_;
+  SimpleHashMap sockets_by_fd_;
 
   Mutex* mutex_;
 
diff --git a/runtime/platform/hashmap.cc b/runtime/platform/hashmap.cc
index d5dfba9..88c521e 100644
--- a/runtime/platform/hashmap.cc
+++ b/runtime/platform/hashmap.cc
@@ -8,16 +8,18 @@
 
 namespace dart {
 
-HashMap::HashMap(MatchFun match, uint32_t initial_capacity) {
+SimpleHashMap::SimpleHashMap(MatchFun match, uint32_t initial_capacity) {
   match_ = match;
   Initialize(initial_capacity);
 }
 
-HashMap::~HashMap() {
+SimpleHashMap::~SimpleHashMap() {
   delete[] map_;
 }
 
-HashMap::Entry* HashMap::Lookup(void* key, uint32_t hash, bool insert) {
+SimpleHashMap::Entry* SimpleHashMap::Lookup(void* key,
+                                            uint32_t hash,
+                                            bool insert) {
   // Find a matching entry.
   Entry* p = Probe(key, hash);
   if (p->key != NULL) {
@@ -44,7 +46,7 @@
   return NULL;
 }
 
-void HashMap::Remove(void* key, uint32_t hash) {
+void SimpleHashMap::Remove(void* key, uint32_t hash) {
   // Lookup the entry for the key to remove.
   Entry* candidate = Probe(key, hash);
   if (candidate->key == NULL) {
@@ -106,7 +108,7 @@
   occupancy_--;
 }
 
-void HashMap::Clear(ClearFun clear) {
+void SimpleHashMap::Clear(ClearFun clear) {
   // Mark all entries as empty.
   const Entry* end = map_end();
   for (Entry* p = map_; p < end; p++) {
@@ -118,11 +120,11 @@
   occupancy_ = 0;
 }
 
-HashMap::Entry* HashMap::Start() const {
+SimpleHashMap::Entry* SimpleHashMap::Start() const {
   return Next(map_ - 1);
 }
 
-HashMap::Entry* HashMap::Next(Entry* p) const {
+SimpleHashMap::Entry* SimpleHashMap::Next(Entry* p) const {
   const Entry* end = map_end();
   ASSERT(map_ - 1 <= p && p < end);
   for (p++; p < end; p++) {
@@ -133,7 +135,7 @@
   return NULL;
 }
 
-HashMap::Entry* HashMap::Probe(void* key, uint32_t hash) {
+SimpleHashMap::Entry* SimpleHashMap::Probe(void* key, uint32_t hash) {
   ASSERT(key != NULL);
 
   ASSERT(dart::Utils::IsPowerOfTwo(capacity_));
@@ -152,7 +154,7 @@
   return p;
 }
 
-void HashMap::Initialize(uint32_t capacity) {
+void SimpleHashMap::Initialize(uint32_t capacity) {
   ASSERT(dart::Utils::IsPowerOfTwo(capacity));
   map_ = new Entry[capacity];
   if (map_ == NULL) {
@@ -162,7 +164,7 @@
   occupancy_ = 0;
 }
 
-void HashMap::Resize() {
+void SimpleHashMap::Resize() {
   Entry* map = map_;
   uint32_t n = occupancy_;
 
diff --git a/runtime/platform/hashmap.h b/runtime/platform/hashmap.h
index be8278e..e3e9c5a 100644
--- a/runtime/platform/hashmap.h
+++ b/runtime/platform/hashmap.h
@@ -9,7 +9,7 @@
 
 namespace dart {
 
-class HashMap {
+class SimpleHashMap {
  public:
   typedef bool (*MatchFun)(void* key1, void* key2);
 
@@ -17,9 +17,9 @@
 
   // initial_capacity is the size of the initial hash map;
   // it must be a power of 2 (and thus must not be 0).
-  HashMap(MatchFun match, uint32_t initial_capacity);
+  SimpleHashMap(MatchFun match, uint32_t initial_capacity);
 
-  ~HashMap();
+  ~SimpleHashMap();
 
   static bool SamePointerValue(void* key1, void* key2) { return key1 == key2; }
 
@@ -43,7 +43,7 @@
                   reinterpret_cast<char*>(key2)) == 0;
   }
 
-  // HashMap entries are (key, value, hash) triplets.
+  // SimpleHashMap entries are (key, value, hash) triplets.
   // Some clients may not need to use the value slot
   // (e.g. implementers of sets, where the key is the value).
   struct Entry {
@@ -62,7 +62,7 @@
 
   // Removes the entry with matching key.
   //
-  // WARNING: This method cannot be called while iterating a `HashMap`
+  // WARNING: This method cannot be called while iterating a `SimpleHashMap`
   // otherwise the iteration might step over elements!
   void Remove(void* key, uint32_t hash);
 
@@ -101,7 +101,7 @@
   void Resize();
 
   friend class IntSet;  // From hashmap_test.cc
-  DISALLOW_COPY_AND_ASSIGN(HashMap);
+  DISALLOW_COPY_AND_ASSIGN(SimpleHashMap);
 };
 
 }  // namespace dart