Version 0.6.8.0 .

svn merge -r 25191:25219  https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@25221 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/http/test/safe_http_server.dart b/pkg/http/test/safe_http_server.dart
index 0f3b9f1..e55834c 100644
--- a/pkg/http/test/safe_http_server.dart
+++ b/pkg/http/test/safe_http_server.dart
@@ -30,7 +30,7 @@
       : super(server),
         _inner = server;
 
-  void close() => _inner.close();
+  Future close() => _inner.close();
 
   int get port => _inner.port;
 
diff --git a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
index 0f3b9f1..e55834c 100644
--- a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
+++ b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
@@ -30,7 +30,7 @@
       : super(server),
         _inner = server;
 
-  void close() => _inner.close();
+  Future close() => _inner.close();
 
   int get port => _inner.port;
 
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index e75250f..8a26043 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -20,6 +20,7 @@
   kOutEvent = 1,
   kErrorEvent = 2,
   kCloseEvent = 3,
+  kDestroyedEvent = 4,
   kCloseCommand = 8,
   kShutdownReadCommand = 9,
   kShutdownWriteCommand = 10,
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 594a6db..258a96b 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -224,6 +224,7 @@
         }
         socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
         delete sd;
+        DartUtils::PostInt32(msg.dart_port, 1 << kDestroyedEvent);
       } else {
         // Setup events to wait for.
         sd->SetPortAndMask(msg.dart_port, msg.data);
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 2b62391..cae7403 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -233,6 +233,7 @@
         }
         socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
         delete sd;
+        DartUtils::PostInt32(msg.dart_port, 1 << kDestroyedEvent);
       } else {
         if ((msg.data & (1 << kInEvent)) != 0 && sd->IsClosedRead()) {
           DartUtils::PostInt32(msg.dart_port, 1 << kCloseEvent);
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index 9a60d6f..1570015 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -244,6 +244,7 @@
         }
         socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
         delete sd;
+        DartUtils::PostInt32(msg.dart_port, 1 << kDestroyedEvent);
       } else {
         if ((msg.data & (1 << kInEvent)) != 0 && sd->IsClosedRead()) {
           DartUtils::PostInt32(msg.dart_port, 1 << kCloseEvent);
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 332f80f..3ced5d0 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -324,7 +324,7 @@
 
 
 bool FileHandle::IsClosed() {
-  return false;
+  return IsClosing();
 }
 
 
@@ -573,7 +573,7 @@
 
 
 void ClientSocket::DoClose() {
-  // Always do a suhtdown before initiating a disconnect.
+  // Always do a shutdown before initiating a disconnect.
   shutdown(socket(), SD_BOTH);
   IssueDisconnect();
 }
@@ -630,12 +630,14 @@
 
 
 void ClientSocket::IssueDisconnect() {
+  Dart_Port p = port();
   IOBuffer* buffer = IOBuffer::AllocateDisconnectBuffer();
   BOOL ok = DisconnectEx_(
     socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0);
   if (!ok && WSAGetLastError() != WSA_IO_PENDING) {
     DisconnectComplete(buffer);
   }
+  if (p != ILLEGAL_PORT) DartUtils::PostInt32(p, 1 << kDestroyedEvent);
 }
 
 
@@ -666,6 +668,15 @@
 }
 
 
+static void DeleteIfClosed(Handle* handle) {
+  if (handle->IsClosed()) {
+    Dart_Port port = handle->port();
+    delete handle;
+    DartUtils::PostInt32(port, 1 << kDestroyedEvent);
+  }
+}
+
+
 void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) {
   if (msg->id == kTimeoutId) {
     // Change of timeout request. Just set the new timeout and port as the
@@ -674,7 +685,6 @@
   } else if (msg->id == kShutdownId) {
     shutdown_ = true;
   } else {
-    bool delete_handle = false;
     Handle* handle = reinterpret_cast<Handle*>(msg->id);
     ASSERT(handle != NULL);
     if (handle->is_listen_socket()) {
@@ -701,9 +711,6 @@
 
       if ((msg->data & (1 << kCloseCommand)) != 0) {
         listen_socket->Close();
-        if (listen_socket->IsClosed()) {
-          delete_handle = true;
-        }
       }
     } else {
       handle->EnsureInitialized(this);
@@ -756,15 +763,11 @@
       }
 
       if ((msg->data & (1 << kCloseCommand)) != 0) {
+        handle->SetPortAndMask(msg->dart_port, msg->data);
         handle->Close();
-        if (handle->IsClosed()) {
-          delete_handle = true;
-        }
       }
     }
-    if (delete_handle) {
-      delete handle;
-    }
+    DeleteIfClosed(handle);
   }
 }
 
@@ -780,9 +783,7 @@
     }
   }
 
-  if (listen_socket->IsClosed()) {
-    delete listen_socket;
-  }
+  DeleteIfClosed(listen_socket);
 }
 
 
@@ -825,9 +826,7 @@
     }
   }
 
-  if (handle->IsClosed()) {
-    delete handle;
-  }
+  DeleteIfClosed(handle);
 }
 
 
@@ -849,9 +848,7 @@
     HandleError(handle);
   }
 
-  if (handle->IsClosed()) {
-    delete handle;
-  }
+  DeleteIfClosed(handle);
 }
 
 
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 4cd6745..a3cc62b 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -172,8 +172,9 @@
   static const int WRITE_EVENT = 1;
   static const int ERROR_EVENT = 2;
   static const int CLOSED_EVENT = 3;
+  static const int DESTROYED_EVENT = 4;
   static const int FIRST_EVENT = READ_EVENT;
-  static const int LAST_EVENT = CLOSED_EVENT;
+  static const int LAST_EVENT = DESTROYED_EVENT;
   static const int EVENT_COUNT = LAST_EVENT - FIRST_EVENT + 1;
 
   static const int CLOSE_COMMAND = 8;
@@ -197,6 +198,7 @@
 
   // Socket close state
   bool isClosed = false;
+  bool isClosing = false;
   bool isClosedRead = false;
   bool isClosedWrite = false;
   Completer closeCompleter = new Completer();
@@ -370,7 +372,7 @@
   }
 
   int available() {
-    if (isClosed) return 0;
+    if (isClosing || isClosed) return 0;
     var result = nativeAvailable();
     if (result is OSError) {
       reportError(result, "Available failed");
@@ -384,7 +386,7 @@
     if (len != null && len <= 0) {
       throw new ArgumentError("Illegal length $len");
     }
-    if (isClosed) return null;
+    if (isClosing || isClosed) return null;
     var result = nativeRead(len == null ? -1 : len);
     if (result is OSError) {
       reportError(result, "Read failed");
@@ -410,7 +412,7 @@
     if (offset is! int || bytes is! int) {
       throw new ArgumentError("Invalid arguments to write on Socket");
     }
-    if (isClosed) return 0;
+    if (isClosing || isClosed) return 0;
     if (bytes == 0) return 0;
     _BufferAndStart bufferAndStart =
         _ensureFastAndSerializableByteData(buffer, offset, offset + bytes);
@@ -451,11 +453,20 @@
       if (((events & (1 << i)) != 0)) {
         if (i == CLOSED_EVENT &&
             typeFlags != TYPE_LISTENING_SOCKET &&
+            !isClosing &&
             !isClosed) {
           isClosedRead = true;
         }
 
         var handler = eventHandlers[i];
+        if (i == DESTROYED_EVENT) {
+          assert(!isClosed);
+          isClosed = true;
+          closeCompleter.complete(this);
+          disconnectFromEventHandler();
+          if (handler != null) handler();
+          continue;
+        }
         assert(handler != null);
         if (i == WRITE_EVENT) {
           // If the event was disabled before we had a chance to fire the event,
@@ -486,11 +497,12 @@
     activateHandlers();
   }
 
-  void setHandlers({read: null, write: null, error: null, closed: null}) {
+  void setHandlers({read, write, error, closed, destroyed}) {
     eventHandlers[READ_EVENT] = read;
     eventHandlers[WRITE_EVENT] = write;
     eventHandlers[ERROR_EVENT] = error;
     eventHandlers[CLOSED_EVENT] = closed;
+    eventHandlers[DESTROYED_EVENT] = destroyed;
   }
 
   void setListening({read: true, write: true}) {
@@ -500,37 +512,34 @@
     activateHandlers();
   }
 
-  Future get closeFuture => closeCompleter.future;
+  Future<_NativeSocket> get closeFuture => closeCompleter.future;
 
   void activateHandlers() {
-    if (canActivateEvents && !isClosed) {
-      // If we don't listen for either read or write, disconnect as we won't
-      // get close and error events anyway.
+    if (canActivateEvents && !isClosing && !isClosed) {
       if ((eventMask & ((1 << READ_EVENT) | (1 << WRITE_EVENT))) == 0) {
+        // If we don't listen for either read or write, disconnect as we won't
+        // get close and error events anyway.
         if (eventPort != null) disconnectFromEventHandler();
       } else {
         int data = eventMask;
-        data |= typeFlags;
         if (isClosedRead) data &= ~(1 << READ_EVENT);
         if (isClosedWrite) data &= ~(1 << WRITE_EVENT);
+        data |= typeFlags;
         sendToEventHandler(data);
       }
     }
   }
 
-  void close() {
-    if (!isClosed) {
+  Future<_NativeSocket> close() {
+    if (!isClosing && !isClosed) {
       sendToEventHandler(1 << CLOSE_COMMAND);
-      isClosed = true;
-      closeCompleter.complete(this);
+      isClosing = true;
     }
-    // Outside the if support closing sockets created but never
-    // assigned any actual socket.
-    disconnectFromEventHandler();
+    return closeFuture;
   }
 
   void shutdown(SocketDirection direction) {
-    if (!isClosed) {
+    if (!isClosing && !isClosed) {
       switch (direction) {
         case SocketDirection.RECEIVE:
           shutdownRead();
@@ -548,7 +557,7 @@
   }
 
   void shutdownWrite() {
-    if (!isClosed) {
+    if (!isClosing && !isClosed) {
       if (isClosedRead) {
         close();
       } else {
@@ -559,7 +568,7 @@
   }
 
   void shutdownRead() {
-    if (!isClosed) {
+    if (!isClosing && !isClosed) {
       if (isClosedWrite) {
         close();
       } else {
@@ -709,7 +718,7 @@
 
   int get port => _socket.port;
 
-  void close() => _socket.close();
+  Future close() => _socket.close().then((_) => this);
 
   void _pause() {
     _socket.setListening(read: false, write: false);
@@ -768,6 +777,7 @@
         _controller.add(RawSocketEvent.WRITE);
       },
       closed: () => _controller.add(RawSocketEvent.READ_CLOSED),
+      destroyed: () => _controller.add(RawSocketEvent.CLOSED),
       error: (e) {
         _controller.addError(e);
         close();
@@ -825,7 +835,7 @@
   int write(List<int> buffer, [int offset, int count]) =>
       _socket.write(buffer, offset, count);
 
-  void close() => _socket.close();
+  Future close() => _socket.close().then((_) => this);
 
   void shutdown(SocketDirection direction) => _socket.shutdown(direction);
 
@@ -918,7 +928,7 @@
 
   int get port => _socket.port;
 
-  void close() => _socket.close();
+  Future close() => _socket.close().then((_) => this);
 }
 
 
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index b8b3546..149ec50 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -422,7 +422,6 @@
 
 static Dart_Handle CreateTypedefMirror(Dart_Handle cls,
                                        Dart_Handle cls_name,
-                                       Dart_Handle owner,
                                        Dart_Handle owner_mirror) {
   Dart_Handle mirror_cls_name = NewString("_LocalTypedefMirrorImpl");
   Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL);
@@ -451,16 +450,14 @@
 static Dart_Handle CreateConstructorMap(Dart_Handle owner,
                                         Dart_Handle owner_mirror);
 
-
 static Dart_Handle CreateClassMirrorUsingApi(Dart_Handle intf,
                                              Dart_Handle intf_name,
-                                             Dart_Handle lib,
                                              Dart_Handle lib_mirror) {
   ASSERT(Dart_IsClass(intf));
   if (Dart_ClassIsTypedef(intf)) {
     // This class is actually a typedef.  Represent it specially in
     // reflection.
-    return CreateTypedefMirror(intf, intf_name, lib, lib_mirror);
+    return CreateTypedefMirror(intf, intf_name, lib_mirror);
   }
 
   Dart_Handle cls_name = NewString("_LocalClassMirrorImpl");
@@ -613,7 +610,7 @@
       return intf;
     }
     Dart_Handle intf_mirror =
-        CreateClassMirrorUsingApi(intf, intf_name, owner, owner_mirror);
+        CreateClassMirrorUsingApi(intf, intf_name, owner_mirror);
     if (Dart_IsError(intf_mirror)) {
       return intf_mirror;
     }
@@ -972,6 +969,7 @@
 
 static RawInstance* CreateClassMirror(const Class& cls,
                                       const Instance& owner_mirror) {
+  Instance& retvalue = Instance::Handle();
   Dart_EnterScope();
   Isolate* isolate = Isolate::Current();
   Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw());
@@ -982,30 +980,23 @@
   if (Dart_IsError(name_handle)) {
     Dart_PropagateError(name_handle);
   }
-  Dart_Handle lib_handle = Api::NewHandle(isolate, cls.library());
-  if (Dart_IsError(lib_handle)) {
-    Dart_PropagateError(lib_handle);
-  }
-  Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
-  if (Dart_IsError(lib_mirror)) {
-    Dart_PropagateError(lib_mirror);
-  }
+  Dart_Handle lib_mirror = Api::NewHandle(isolate, owner_mirror.raw());
   // TODO(11742): At some point the handle calls will be replaced by inlined
   // functionality.
   Dart_Handle result =  CreateClassMirrorUsingApi(cls_handle,
                                                   name_handle,
-                                                  lib_handle,
                                                   lib_mirror);
   if (Dart_IsError(result)) {
     Dart_PropagateError(result);
   }
-  const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+  retvalue ^= Api::UnwrapHandle(result);
   Dart_ExitScope();
   return retvalue.raw();
 }
 
 
 static RawInstance* CreateLibraryMirror(const Library& lib) {
+  Instance& retvalue = Instance::Handle();
   Dart_EnterScope();
   Isolate* isolate = Isolate::Current();
   Dart_Handle lib_handle = Api::NewHandle(isolate, lib.raw());
@@ -1015,7 +1006,7 @@
   if (Dart_IsError(result)) {
     Dart_PropagateError(result);
   }
-  const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+  retvalue ^= Api::UnwrapHandle(result);
   Dart_ExitScope();
   return retvalue.raw();
 }
@@ -1023,6 +1014,7 @@
 
 static RawInstance* CreateMethodMirror(const Function& func,
                                        const Instance& owner_mirror) {
+  Instance& retvalue = Instance::Handle();
   Dart_EnterScope();
   Isolate* isolate = Isolate::Current();
   Dart_Handle func_handle = Api::NewHandle(isolate, func.raw());
@@ -1033,7 +1025,7 @@
   if (Dart_IsError(result)) {
     Dart_PropagateError(result);
   }
-  const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+  retvalue ^= Api::UnwrapHandle(result);
   Dart_ExitScope();
   return retvalue.raw();
 }
@@ -1082,17 +1074,9 @@
   if (Dart_IsError(name_handle)) {
     Dart_PropagateError(name_handle);
   }
-  Dart_Handle lib_handle = Api::NewHandle(isolate, cls.library());
-  if (Dart_IsError(lib_handle)) {
-    Dart_PropagateError(lib_handle);
-  }
-  Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
-  if (Dart_IsError(lib_mirror)) {
-    Dart_PropagateError(lib_mirror);
-  }
+  Dart_Handle lib_mirror = Dart_Null();
   Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
                                                  name_handle,
-                                                 lib_handle,
                                                  lib_mirror);
   if (Dart_IsError(result)) {
     Dart_PropagateError(result);
@@ -1263,6 +1247,16 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(ClassMirror_library, 1) {
+  const MirrorReference& klass_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
+  Class& klass = Class::Handle();
+  klass ^= klass_ref.referent();
+
+  return CreateLibraryMirror(Library::Handle(klass.library()));
+}
+
+
 // Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
 // exceptions. Wrap and propagate any compilation errors.
 static RawObject* ReflectivelyInvokeDynamicFunction(const Instance& receiver,
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 542e6e8..450aa2d 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -422,7 +422,10 @@
 
   var _owner;
   DeclarationMirror get owner {
-    if (_owner != null && _owner is! Mirror) {
+    if (_owner == null) {
+      _owner = _library(_reflectee);
+    }
+    if (_owner is! Mirror) {
       _owner = _owner.resolve(mirrors);
     }
     return _owner;
@@ -573,6 +576,9 @@
   static _name(reflectee)
       native "ClassMirror_name";
 
+  static _library(reflectee)
+      native "ClassMirror_library";
+
   _invoke(reflectee, memberName, positionalArguments)
       native 'ClassMirror_invoke';
 
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index d7912dc..5bf8ad1 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -244,6 +244,7 @@
   V(InstanceMirror_invokeSetter, 4)                                            \
   V(ClosureMirror_apply, 2)                                                    \
   V(ClassMirror_name, 1)                                                       \
+  V(ClassMirror_library, 1)                                                    \
   V(ClassMirror_invoke, 4)                                                     \
   V(ClassMirror_invokeGetter, 3)                                               \
   V(ClassMirror_invokeSetter, 4)                                               \
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 6665626..746ca35 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3094,22 +3094,30 @@
     Value* allocated_context =
         Bind(new AllocateContextInstr(node->token_pos(),
                                       num_context_variables));
-
-    // If this node_sequence is the body of the function being compiled, and if
-    // this function allocates context variables, but none of its enclosing
-    // functions do, the context on entry is not linked as parent of the
-    // allocated context but saved on entry and restored on exit as to prevent
-    // memory leaks.
-    // In this case, the parser pre-allocates a variable to save the context.
-    if (MustSaveRestoreContext(node)) {
+    { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
+      // If this node_sequence is the body of the function being compiled, and
+      // if this function allocates context variables, but none of its enclosing
+      // functions do, the context on entry is not linked as parent of the
+      // allocated context but saved on entry and restored on exit as to prevent
+      // memory leaks.
+      // In this case, the parser pre-allocates a variable to save the context.
+      if (MustSaveRestoreContext(node)) {
+        Value* current_context = Bind(new CurrentContextInstr());
+        Do(BuildStoreTemp(
+            *owner()->parsed_function()->saved_entry_context_var(),
+            current_context));
+        Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
+        AddInstruction(new StoreContextInstr(null_context));
+      }
       Value* current_context = Bind(new CurrentContextInstr());
-      Do(BuildStoreTemp(*owner()->parsed_function()->saved_entry_context_var(),
-                        current_context));
-      Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
-      AddInstruction(new StoreContextInstr(null_context));
+      Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var));
+      Do(new StoreVMFieldInstr(tmp_val,
+                               Context::parent_offset(),
+                               current_context,
+                               Type::ZoneHandle()));
+      AddInstruction(
+          new StoreContextInstr(Bind(ExitTempLocalScope(tmp_var))));
     }
-
-    AddInstruction(new ChainContextInstr(allocated_context));
     owner()->set_context_level(scope->context_level());
 
     // If this node_sequence is the body of the function being compiled, copy
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index a350e07..e3a1f82 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -3793,7 +3793,6 @@
         *is_load = true;
         break;
 
-      case Instruction::kChainContext:
       case Instruction::kStoreContext:
         kind_ = kContext;
         break;
@@ -4019,7 +4018,7 @@
       return Alias::VMField(store_vm_field->offset_in_bytes());
     }
 
-    if (instr->IsStoreContext() || instr->IsChainContext()) {
+    if (instr->IsStoreContext()) {
       return Alias::CurrentContext();
     }
 
@@ -4261,7 +4260,7 @@
     return store_static_field->value()->definition();
   }
 
-  if (instr->IsStoreContext() || instr->IsChainContext()) {
+  if (instr->IsStoreContext()) {
     return instr->InputAt(0)->definition();
   }
 
@@ -5512,9 +5511,6 @@
 void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) { }
 
 
-void ConstantPropagator::VisitChainContext(ChainContextInstr* instr) { }
-
-
 void ConstantPropagator::VisitCatchEntry(CatchEntryInstr* instr) { }
 
 
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 49d2a54..bc01952 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -565,7 +565,6 @@
   M(ExtractConstructorTypeArguments)                                           \
   M(ExtractConstructorInstantiator)                                            \
   M(AllocateContext)                                                           \
-  M(ChainContext)                                                              \
   M(CloneContext)                                                              \
   M(CatchEntry)                                                                \
   M(BinarySmiOp)                                                               \
@@ -4248,29 +4247,6 @@
 };
 
 
-class ChainContextInstr : public TemplateInstruction<1> {
- public:
-  explicit ChainContextInstr(Value* context_value) {
-    SetInputAt(0, context_value);
-  }
-
-  DECLARE_INSTRUCTION(ChainContext)
-
-  virtual intptr_t ArgumentCount() const { return 0; }
-
-  Value* context_value() const { return inputs_[0]; }
-
-  virtual bool CanDeoptimize() const { return false; }
-
-  virtual EffectSet Effects() const { return EffectSet::None(); }
-
-  virtual bool MayThrow() const { return false; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChainContextInstr);
-};
-
-
 class CloneContextInstr : public TemplateDefinition<1> {
  public:
   CloneContextInstr(intptr_t token_pos, Value* context_value)
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 87fba15..8d95969 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -3071,13 +3071,47 @@
 
 
 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister left = locs()->in(0).fpu_reg();
+  QRegister right = locs()->in(1).fpu_reg();
+  QRegister result = locs()->out().fpu_reg();
+
+  switch (op_kind()) {
+    case MethodRecognizer::kFloat32x4Equal:
+      __ vceqqs(result, left, right);
+      break;
+    case MethodRecognizer::kFloat32x4NotEqual:
+      __ vceqqs(result, left, right);
+      // Invert the result.
+      __ veorq(QTMP, QTMP, QTMP);  // QTMP <- 0.
+      __ vornq(result, QTMP, result);  // result <- ~result.
+      break;
+    case MethodRecognizer::kFloat32x4GreaterThan:
+      __ vcgtqs(result, left, right);
+      break;
+    case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
+      __ vcgeqs(result, left, right);
+      break;
+    case MethodRecognizer::kFloat32x4LessThan:
+      __ vcgtqs(result, right, left);
+      break;
+    case MethodRecognizer::kFloat32x4LessThanOrEqual:
+      __ vcgeqs(result, right, left);
+      break;
+
+    default: UNREACHABLE();
+  }
 }
 
 
@@ -3137,13 +3171,49 @@
 
 
 LocationSummary* Float32x4WithInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister replacement = locs()->in(0).fpu_reg();
+  QRegister value = locs()->in(1).fpu_reg();
+  QRegister result = locs()->out().fpu_reg();
+
+  DRegister dresult0 = EvenDRegisterOf(result);
+  DRegister dresult1 = OddDRegisterOf(result);
+  SRegister sresult0 = EvenSRegisterOf(dresult0);
+  SRegister sresult1 = OddSRegisterOf(dresult0);
+  SRegister sresult2 = EvenSRegisterOf(dresult1);
+  SRegister sresult3 = OddSRegisterOf(dresult1);
+
+  __ vcvtsd(STMP, EvenDRegisterOf(replacement));
+  if (result != value) {
+    __ vmovq(result, value);
+  }
+
+  switch (op_kind()) {
+    case MethodRecognizer::kFloat32x4WithX:
+      __ vmovs(sresult0, STMP);
+      break;
+    case MethodRecognizer::kFloat32x4WithY:
+      __ vmovs(sresult1, STMP);
+      break;
+    case MethodRecognizer::kFloat32x4WithZ:
+      __ vmovs(sresult2, STMP);
+      break;
+    case MethodRecognizer::kFloat32x4WithW:
+      __ vmovs(sresult3, STMP);
+      break;
+    default: UNREACHABLE();
+  }
 }
 
 
@@ -3170,15 +3240,49 @@
 
 
 LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
 void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister value = locs()->in(0).fpu_reg();
+  Register result = locs()->out().reg();
+
+  DRegister dvalue0 = EvenDRegisterOf(value);
+  DRegister dvalue1 = OddDRegisterOf(value);
+  SRegister svalue0 = EvenSRegisterOf(dvalue0);
+  SRegister svalue1 = OddSRegisterOf(dvalue0);
+  SRegister svalue2 = EvenSRegisterOf(dvalue1);
+  SRegister svalue3 = OddSRegisterOf(dvalue1);
+
+  switch (op_kind()) {
+    case MethodRecognizer::kUint32x4GetFlagX:
+      __ vmovrs(result, svalue0);
+      break;
+    case MethodRecognizer::kUint32x4GetFlagY:
+      __ vmovrs(result, svalue1);
+      break;
+    case MethodRecognizer::kUint32x4GetFlagZ:
+      __ vmovrs(result, svalue2);
+      break;
+    case MethodRecognizer::kUint32x4GetFlagW:
+      __ vmovrs(result, svalue3);
+      break;
+    default: UNREACHABLE();
+  }
+
+  __ tst(result, ShifterOperand(result));
+  __ LoadObject(result, Bool::True(), NE);
+  __ LoadObject(result, Bool::False(), EQ);
 }
 
+
 LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const {
   UNIMPLEMENTED();
   return NULL;
@@ -3875,25 +3979,6 @@
 }
 
 
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::NoLocation(),
-                               LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register context_value = locs()->in(0).reg();
-
-  // Chain the new context in context_value to its parent in CTX.
-  __ StoreIntoObject(context_value,
-                     FieldAddress(context_value, Context::parent_offset()),
-                     CTX);
-  // Set new context as current context.
-  __ mov(CTX, ShifterOperand(context_value));
-}
-
-
 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 532be75..0f4e24b 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -4700,25 +4700,6 @@
 }
 
 
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::NoLocation(),
-                               LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register context_value = locs()->in(0).reg();
-
-  // Chain the new context in context_value to its parent in CTX.
-  __ StoreIntoObject(context_value,
-                     FieldAddress(context_value, Context::parent_offset()),
-                     CTX);
-  // Set new context as current context.
-  __ MoveRegister(CTX, context_value);
-}
-
-
 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 6b8b215..7015a13 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -3713,25 +3713,6 @@
 }
 
 
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::NoLocation(),
-                               LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register context_value = locs()->in(0).reg();
-
-  // Chain the new context in context_value to its parent in CTX.
-  __ StoreIntoObject(context_value,
-                     FieldAddress(context_value, Context::parent_offset()),
-                     CTX);
-  // Set new context as current context.
-  __ mov(CTX, context_value);
-}
-
-
 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 79ab510..a320b95 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -4370,25 +4370,6 @@
 }
 
 
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::NoLocation(),
-                               LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register context_value = locs()->in(0).reg();
-
-  // Chain the new context in context_value to its parent in CTX.
-  __ StoreIntoObject(context_value,
-                     FieldAddress(context_value, Context::parent_offset()),
-                     CTX);
-  // Set new context as current context.
-  __ MoveRegister(CTX, context_value);
-}
-
-
 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 3a9154a..0104ffb 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1679,11 +1679,13 @@
                        String superName,
                        { bool classIsNative: false,
                          bool emitStatics: false }) {
-    assert(superName != null);
-    String separator = '';
-    String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement);
     StringBuffer buffer = new StringBuffer();
-    if (!emitStatics) {
+    if (emitStatics) {
+      assert(invariant(classElement, superName == null, message: superName));
+    } else {
+      assert(invariant(classElement, superName != null));
+      String nativeName =
+          namer.getPrimitiveInterceptorRuntimeName(classElement);
       if (nativeName != null) {
         buffer.write('$nativeName/');
       }
@@ -1691,6 +1693,8 @@
     }
     int bufferClassLength = buffer.length;
 
+    String separator = '';
+
     var fieldMetadata = [];
     bool hasMetadata = false;
 
@@ -1833,16 +1837,25 @@
     emitSuper(superName, builder);
     emitRuntimeName(runtimeName, builder);
     emitClassFields(classElement, builder, superName);
-    var metadata = buildMetadataFunction(classElement);
-    if (metadata != null) {
-      builder.addProperty("@", metadata);
-    }
     emitClassGettersSetters(classElement, builder);
     if (!classElement.isMixinApplication) {
       emitInstanceMembers(classElement, builder);
     }
     emitIsTests(classElement, builder);
 
+    emitClassBuilderWithReflectionData(
+        className, classElement, builder, buffer);
+  }
+
+  void emitClassBuilderWithReflectionData(String className,
+                                          ClassElement classElement,
+                                          ClassBuilder builder,
+                                          CodeBuffer buffer) {
+    var metadata = buildMetadataFunction(classElement);
+    if (metadata != null) {
+      builder.addProperty("@", metadata);
+    }
+
     List<CodeBuffer> classBuffers = elementBuffers[classElement];
     if (classBuffers == null) {
       classBuffers = [];
@@ -1854,7 +1867,7 @@
     bool hasStatics = false;
     ClassBuilder staticsBuilder = new ClassBuilder();
     if (emitClassFields(
-            classElement, staticsBuilder, superName, emitStatics: true)) {
+            classElement, staticsBuilder, null, emitStatics: true)) {
       hasStatics = true;
       statics.write('"":$_');
       statics.write(
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index 6538cf2..4440c06 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -232,14 +232,11 @@
     // Emit the native class interceptors that were actually used.
     for (ClassElement classElement in classes) {
       if (neededClasses.contains(classElement)) {
-        ClassBuilder builder = builders[classElement];
         // Define interceptor class for [classElement].
-        String className = backend.namer.getName(classElement);
-        jsAst.Expression init =
-            js(emitter.classesCollector)[className].assign(
-                builder.toObjectInitializer());
-        mainBuffer.write(jsAst.prettyPrint(init, compiler));
-        mainBuffer.write('$N$n');
+        emitter.emitClassBuilderWithReflectionData(
+            backend.namer.getName(classElement),
+            classElement, builders[classElement],
+            emitter.bufferForElement(classElement, mainBuffer));
         emitter.needsDefineClass = true;
       }
     }
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 12f9cae..3ae9aa1 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -1087,7 +1087,8 @@
 
     final bool isImplicitSuperCall = false;
     final SourceString className = lookupTarget.name;
-    verifyThatConstructorMatchesCall(calledConstructor,
+    verifyThatConstructorMatchesCall(constructor,
+                                     calledConstructor,
                                      selector,
                                      isImplicitSuperCall,
                                      call,
@@ -1124,7 +1125,8 @@
 
       final SourceString className = lookupTarget.name;
       final bool isImplicitSuperCall = true;
-      verifyThatConstructorMatchesCall(calledConstructor,
+      verifyThatConstructorMatchesCall(constructor,
+                                       calledConstructor,
                                        callToMatch,
                                        isImplicitSuperCall,
                                        functionNode,
@@ -1136,6 +1138,7 @@
   }
 
   void verifyThatConstructorMatchesCall(
+      FunctionElement caller,
       FunctionElement lookedupConstructor,
       Selector call,
       bool isImplicitSuperCall,
@@ -1159,6 +1162,10 @@
                            ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
                            : MessageKind.NO_MATCHING_CONSTRUCTOR;
         visitor.compiler.reportErrorCode(diagnosticNode, kind);
+      } else if (caller.modifiers.isConst()
+                 && !lookedupConstructor.modifiers.isConst()) {
+        visitor.compiler.reportErrorCode(
+            diagnosticNode, MessageKind.CONST_CALLS_NON_CONST);
       }
     }
   }
@@ -3252,7 +3259,7 @@
         DartType supertype = resolveSupertype(element, superMixin.superclass);
         Link<Node> link = superMixin.mixins.nodes;
         while (!link.isEmpty) {
-          supertype = applyMixin(supertype, resolveType(link.head));
+          supertype = applyMixin(supertype, resolveType(link.head), node);
           link = link.tail;
         }
         element.supertype = supertype;
@@ -3314,21 +3321,21 @@
     DartType supertype = resolveSupertype(element, node.superclass);
     Link<Node> link = node.mixins.nodes;
     while (!link.tail.isEmpty) {
-      supertype = applyMixin(supertype, resolveType(link.head));
+      supertype = applyMixin(supertype, resolveType(link.head), link.head);
       link = link.tail;
     }
     doApplyMixinTo(element, supertype, resolveType(link.head));
     return element.computeType(compiler);
   }
 
-  DartType applyMixin(DartType supertype, DartType mixinType) {
+  DartType applyMixin(DartType supertype, DartType mixinType, Node node) {
     String superName = supertype.name.slowToString();
     String mixinName = mixinType.name.slowToString();
     ClassElement mixinApplication = new MixinApplicationElementX(
         new SourceString("${superName}_${mixinName}"),
         element.getCompilationUnit(),
         compiler.getNextFreeClassId(),
-        element.parseNode(compiler),
+        node,
         Modifiers.EMPTY);  // TODO(kasperl): Should this be abstract?
     doApplyMixinTo(mixinApplication, supertype, mixinType);
     mixinApplication.resolutionState = STATE_DONE;
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 7b016b8..1c05b77 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -591,17 +591,41 @@
 
   /**
    * Constant representing [:ConcreteList#[]:] where [:ConcreteList:] is the
-   * concrete implmentation of lists for the selected backend.
+   * concrete implementation of lists for the selected backend.
    */
   FunctionElement listIndex;
 
   /**
    * Constant representing [:ConcreteList#[]=:] where [:ConcreteList:] is the
-   * concrete implmentation of lists for the selected backend.
+   * concrete implementation of lists for the selected backend.
    */
   FunctionElement listIndexSet;
 
   /**
+   * Constant representing [:ConcreteList#add:] where [:ConcreteList:] is the
+   * concrete implementation of lists for the selected backend.
+   */
+  FunctionElement listAdd;
+
+  /**
+   * Constant representing [:ConcreteList#removeAt:] where [:ConcreteList:] is
+   * the concrete implementation of lists for the selected backend.
+   */
+  FunctionElement listRemoveAt;
+
+  /**
+   * Constant representing [:ConcreteList#insert:] where [:ConcreteList:] is
+   * the concrete implementation of lists for the selected backend.
+   */
+  FunctionElement listInsert;
+
+  /**
+   * Constant representing [:ConcreteList#removeLast:] where [:ConcreteList:] is
+   * the concrete implementation of lists for the selected backend.
+   */
+  FunctionElement listRemoveLast;
+
+  /**
    * Constant representing [:List():].
    */
   FunctionElement listConstructor;
@@ -1273,16 +1297,15 @@
       }
     }
 
-    if (function == listIndex) {
-      ConcreteType indexType = environment.lookupType(
-          listIndex.functionSignature.requiredParameters.head);
+    if (function == listIndex || function == listRemoveAt) {
+      Link<Element> parameters = function.functionSignature.requiredParameters;
+      ConcreteType indexType = environment.lookupType(parameters.head);
       if (!indexType.baseTypes.contains(baseTypes.intBaseType)) {
         return emptyConcreteType;
       }
       return listElementType;
-    } else if (function == listIndexSet) {
-      Link<Element> parameters =
-          listIndexSet.functionSignature.requiredParameters;
+    } else if (function == listIndexSet || function == listInsert) {
+      Link<Element> parameters = function.functionSignature.requiredParameters;
       ConcreteType indexType = environment.lookupType(parameters.head);
       if (!indexType.baseTypes.contains(baseTypes.intBaseType)) {
         return emptyConcreteType;
@@ -1290,6 +1313,13 @@
       ConcreteType elementType = environment.lookupType(parameters.tail.head);
       augmentListElementType(elementType);
       return emptyConcreteType;
+    } else if (function == listAdd) {
+      Link<Element> parameters = function.functionSignature.requiredParameters;
+      ConcreteType elementType = environment.lookupType(parameters.head);
+      augmentListElementType(elementType);
+      return emptyConcreteType;
+    } else if (function == listRemoveLast) {
+      return listElementType;
     }
     return null;
   }
@@ -1446,6 +1476,11 @@
     ClassElement jsArrayClass = baseTypes.listBaseType.element;
     listIndex = jsArrayClass.lookupMember(const SourceString('[]'));
     listIndexSet = jsArrayClass.lookupMember(const SourceString('[]='));
+    listAdd = jsArrayClass.lookupMember(const SourceString('add'));
+    listRemoveAt = jsArrayClass.lookupMember(const SourceString('removeAt'));
+    listInsert = jsArrayClass.lookupMember(const SourceString('insert'));
+    listRemoveLast =
+        jsArrayClass.lookupMember(const SourceString('removeLast'));
     List<SourceString> typePreservingOps = const [const SourceString('+'),
                                                   const SourceString('-'),
                                                   const SourceString('*')];
@@ -1543,6 +1578,8 @@
     inferredFieldTypes.forEach((k,v) {
       print("  $k: $v");
     });
+    print("listElementType:");
+    print("  $listElementType");
     print("inferredParameterTypes:");
     inferredParameterTypes.forEach((k,v) {
       print("  $k: $v");
@@ -1677,7 +1714,16 @@
   }
 
   ConcreteType visitDoWhile(DoWhile node) {
-    inferrer.fail(node, 'not yet implemented');
+    analyze(node.body);
+    analyze(node.condition);
+    ConcreteTypesEnvironment oldEnvironment;
+    do {
+      oldEnvironment = environment;
+      analyze(node.body);
+      analyze(node.condition);
+      environment = oldEnvironment.join(environment);
+    } while (oldEnvironment != environment);
+    return inferrer.emptyConcreteType;
   }
 
   ConcreteType visitExpressionStatement(ExpressionStatement node) {
@@ -1690,7 +1736,6 @@
       analyze(node.initializer);
     }
     analyze(node.conditionStatement);
-    ConcreteType result = inferrer.emptyConcreteType;
     ConcreteTypesEnvironment oldEnvironment;
     do {
       oldEnvironment = environment;
@@ -1702,7 +1747,7 @@
     // value indicating whether something changed to avoid performing this
     // comparison twice.
     } while (oldEnvironment != environment);
-    return result;
+    return inferrer.emptyConcreteType;
   }
 
   void analyzeClosure(FunctionExpression node) {
@@ -2001,7 +2046,6 @@
 
   ConcreteType visitWhile(While node) {
     analyze(node.condition);
-    ConcreteType result = inferrer.emptyConcreteType;
     ConcreteTypesEnvironment oldEnvironment;
     do {
       oldEnvironment = environment;
@@ -2009,7 +2053,7 @@
       analyze(node.body);
       environment = oldEnvironment.join(environment);
     } while (oldEnvironment != environment);
-    return result;
+    return inferrer.emptyConcreteType;
   }
 
   ConcreteType visitParenthesizedExpression(ParenthesizedExpression node) {
@@ -2288,8 +2332,8 @@
         : environment.lookupTypeOfThis();
     SourceString name =
         canonicalizeMethodName(node.selector.asIdentifier().source);
-    ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
     if (name.stringValue == '!=') {
+      ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
       ConcreteType returnType = analyzeDynamicSend(elements.getSelector(node),
                                                    receiverType,
                                                    const SourceString('=='),
@@ -2298,8 +2342,12 @@
           ? returnType
           : inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
     } else if (name.stringValue == '&&' || name.stringValue == '||'){
+      ConcreteTypesEnvironment oldEnvironment = environment;
+      analyze(node.arguments.head);
+      environment = oldEnvironment.join(environment);
       return inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
     } else {
+      ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
       return analyzeDynamicSend(elements.getSelector(node),
                                 receiverType, name, argumentsTypes);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
index 156042e..dc3f3dd 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
@@ -337,17 +337,19 @@
   }
 }
 
-class ContainerTracerVisitor extends InferrerVisitor {
+class ContainerTracerVisitor extends InferrerVisitor<TypeMask> {
   final Element analyzedElement;
   final TracerForConcreteContainer tracer;
   final bool visitingClosure;
 
   ContainerTracerVisitor(element, tracer, [LocalsHandler locals])
-      : super(element, tracer.inferrer, tracer.compiler, locals),
+      : super(element, tracer.inferrer.types, tracer.compiler, locals),
         this.analyzedElement = element,
         this.tracer = tracer,
         visitingClosure = locals != null;
 
+  SimpleTypesInferrer get inferrer => tracer.inferrer;
+
   bool escaping = false;
   bool visitingInitializers = false;
 
@@ -437,7 +439,7 @@
       visitingInitializers = false;
       visit(node.body);
     }
-    return compiler.typesTask.functionType;
+    return types.functionType;
   }
 
   TypeMask visitLiteralList(LiteralList node) {
@@ -455,7 +457,7 @@
     } else {
       node.visitChildren(this);
     }
-    return compiler.typesTask.growableListType;
+    return types.growableListType;
   }
 
   // TODO(ngeoffray): Try to move the following two methods in
@@ -503,7 +505,7 @@
     bool isIndexEscaping = false;
     bool isValueEscaping = false;
     if (isIncrementOrDecrement) {
-      rhsType = compiler.typesTask.intType;
+      rhsType = types.intType;
       if (node.isIndex) {
         isIndexEscaping = visitAndCatchEscaping(() {
           indexType = visit(node.arguments.head);
@@ -606,7 +608,7 @@
     } else if (element.isFunction()) {
       return inferrer.getReturnTypeOfElement(element);
     } else {
-      return compiler.typesTask.dynamicType;
+      return types.dynamicType;
     }
   }
 
@@ -622,7 +624,7 @@
     } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
       visitArguments(node.arguments, element);
       if (tracer.couldBeTheList(node)) {
-        tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
+        tracer.unionPotentialTypeWith(types.nullType);
         escaping = true;
         LiteralInt length = node.arguments.head.asLiteralInt();
         if (length != null) {
@@ -660,7 +662,7 @@
       return inferrer.getReturnTypeOfElement(element);
     } else {
       // Closure call or unresolved.
-      return compiler.typesTask.dynamicType;
+      return types.dynamicType;
     }
   }
 
@@ -675,9 +677,9 @@
     } else if (Elements.isInstanceSend(node, elements)) {
       return visitDynamicSend(node);
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
-      return compiler.typesTask.functionType;
+      return types.functionType;
     } else if (Elements.isErroneousElement(element)) {
-      return compiler.typesTask.dynamicType;
+      return types.dynamicType;
     } else if (Elements.isLocal(element)) {
       if (tracer.couldBeTheList(element)) {
         escaping = true;
@@ -685,7 +687,7 @@
       return locals.use(element);
     } else {
       node.visitChildren(this);
-      return compiler.typesTask.dynamicType;
+      return types.dynamicType;
     }
   }
 
@@ -696,7 +698,7 @@
         visitArguments(node.arguments, elements.getSelector(node));
 
     if (isEscaping) return tracer.bailout('Passed to a closure');
-    return compiler.typesTask.dynamicType;
+    return types.dynamicType;
   }
 
   TypeMask visitDynamicSend(Send node) {
@@ -744,7 +746,7 @@
 
   TypeMask visitReturn(Return node) {
     if (node.expression == null) {
-      return compiler.typesTask.nullType;
+      return types.nullType;
     }
     
     TypeMask type;
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
index d357a35..12d0ba0 100644
--- a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -4,50 +4,116 @@
 
 part of simple_types_inferrer;
 
-TypeMask narrowType(TypeMask type,
-                    DartType annotation,
-                    Compiler compiler,
-                    {bool isNullable: true}) {
-  if (annotation.isDynamic) return type;
-  if (annotation.isMalformed) return type;
-  if (annotation.isVoid) return compiler.typesTask.nullType;
-  if (annotation.element == compiler.objectClass) return type;
-  TypeMask otherType;
-  if (annotation.kind == TypeKind.TYPEDEF
-      || annotation.kind == TypeKind.FUNCTION) {
-    otherType = compiler.typesTask.functionType;
-  } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
-    return type;
-  } else {
-    assert(annotation.kind == TypeKind.INTERFACE);
-    otherType = new TypeMask.nonNullSubtype(annotation);
-  }
-  if (isNullable) otherType = otherType.nullable();
-  if (type == null) return otherType;
-  return type.intersection(otherType, compiler);
+/**
+ * The interface [InferrerVisitor] will use when working on types.
+ */
+abstract class TypeSystem<T> {
+  T get dynamicType;
+  T get nullType;
+  T get intType;
+  T get doubleType;
+  T get numType;
+  T get boolType;
+  T get functionType;
+  T get listType;
+  T get constListType;
+  T get fixedListType;
+  T get growableListType;
+  T get mapType;
+  T get constMapType;
+  T get stringType;
+  T get typeType;
+
+  T nonNullSubtype(DartType type);
+  T nonNullSubclass(DartType type);
+  T nonNullExact(DartType type);
+
+  /**
+   * Returns the intersection between [T] and [annotation].
+   * [isNullable] indicates whether the annotation implies a null
+   * type.
+   */
+  T narrowType(T type, DartType annotation, {bool isNullable: true});
+
+  /**
+   * Returns the least upper bound between [firstType] and
+   * [secondType].
+   */
+  T computeLUB(T firstType, T secondType);
+
+  /**
+   * Returns the type inferred by the inferrer for [element].
+   */
+  T getTypeOfCapturedAndBoxedVariable(Element element);
 }
 
 /**
- * Returns the least upper bound between [firstType] and
- * [secondType].
+ * An implementation of [TypeSystem] for [TypeMask].
  */
-TypeMask computeLUB(TypeMask firstType,
-                    TypeMask secondType,
-                    Compiler compiler) {
-  TypeMask dynamicType = compiler.typesTask.dynamicType;
-  if (firstType == null) {
-    return secondType;
-  } else if (secondType == dynamicType) {
-    return secondType;
-  } else if (firstType == dynamicType) {
-    return firstType;
-  } else if (firstType == secondType) {
-    return firstType;
-  } else {
-    TypeMask union = firstType.union(secondType, compiler);
-    // TODO(kasperl): If the union isn't nullable it seems wasteful
-    // to use dynamic. Fix that.
-    return union.containsAll(compiler) ? dynamicType : union;
+class TypeMaskSystem implements TypeSystem<TypeMask> {
+  final Compiler compiler;
+  TypeMaskSystem(this.compiler);
+
+  TypeMask narrowType(TypeMask type,
+                      DartType annotation,
+                      {bool isNullable: true}) {
+    if (annotation.isDynamic) return type;
+    if (annotation.isMalformed) return type;
+    if (annotation.isVoid) return nullType;
+    if (annotation.element == compiler.objectClass) return type;
+    TypeMask otherType;
+    if (annotation.kind == TypeKind.TYPEDEF
+        || annotation.kind == TypeKind.FUNCTION) {
+      otherType = functionType;
+    } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
+      // TODO(ngeoffray): Narrow to bound.
+      return type;
+    } else {
+      assert(annotation.kind == TypeKind.INTERFACE);
+      otherType = new TypeMask.nonNullSubtype(annotation);
+    }
+    if (isNullable) otherType = otherType.nullable();
+    if (type == null) return otherType;
+    return type.intersection(otherType, compiler);
+  }
+
+  TypeMask computeLUB(TypeMask firstType, TypeMask secondType) {
+    if (firstType == null) {
+      return secondType;
+    } else if (secondType == dynamicType || firstType == dynamicType) {
+      return dynamicType;
+    } else if (firstType == secondType) {
+      return firstType;
+    } else {
+      TypeMask union = firstType.union(secondType, compiler);
+      // TODO(kasperl): If the union isn't nullable it seems wasteful
+      // to use dynamic. Fix that.
+      return union.containsAll(compiler) ? dynamicType : union;
+    }
+  }
+
+  TypeMask get dynamicType => compiler.typesTask.dynamicType;
+  TypeMask get nullType => compiler.typesTask.nullType;
+  TypeMask get intType => compiler.typesTask.intType;
+  TypeMask get doubleType => compiler.typesTask.doubleType;
+  TypeMask get numType => compiler.typesTask.numType;
+  TypeMask get boolType => compiler.typesTask.boolType;
+  TypeMask get functionType => compiler.typesTask.functionType;
+  TypeMask get listType => compiler.typesTask.listType;
+  TypeMask get constListType => compiler.typesTask.constListType;
+  TypeMask get fixedListType => compiler.typesTask.fixedListType;
+  TypeMask get growableListType => compiler.typesTask.growableListType;
+  TypeMask get mapType => compiler.typesTask.mapType;
+  TypeMask get constMapType => compiler.typesTask.constMapType;
+  TypeMask get stringType => compiler.typesTask.stringType;
+  TypeMask get typeType => compiler.typesTask.typeType;
+
+  TypeMask nonNullSubtype(DartType type) => new TypeMask.nonNullSubtype(type);
+  TypeMask nonNullSubclass(DartType type) => new TypeMask.nonNullSubclass(type);
+  TypeMask nonNullExact(DartType type) => new TypeMask.nonNullExact(type);
+
+  TypeMask getTypeOfCapturedAndBoxedVariable(Element element) {
+    return compiler.typesTask.typesInferrer.getTypeOfElement(element);
   }
 }
 
@@ -58,11 +124,11 @@
  * The inferrer makes sure updates get merged into the parent scope,
  * once the control flow block has been visited.
  */
-class VariableScope {
-  Map<Element, TypeMask> variables;
+class VariableScope<T> {
+  Map<Element, T> variables;
 
   /// The parent of this scope. Null for the root scope.
-  final VariableScope parent;
+  final VariableScope<T> parent;
 
   /// The block level of this scope. Starts at 0 for the root scope.
   final int blockLevel;
@@ -72,32 +138,32 @@
         this.parent = parent,
         this.blockLevel = parent == null ? 0 : parent.blockLevel + 1;
 
-  VariableScope.deepCopyOf(VariableScope other)
+  VariableScope.deepCopyOf(VariableScope<T> other)
       : variables = other.variables == null
             ? null
-            : new Map<Element, TypeMask>.from(other.variables),
+            : new Map<Element, T>.from(other.variables),
         blockLevel = other.blockLevel,
         parent = other.parent == null
             ? null
-            : new VariableScope.deepCopyOf(other.parent);
+            : new VariableScope<T>.deepCopyOf(other.parent);
 
-  TypeMask operator [](Element variable) {
-    TypeMask result;
+  T operator [](Element variable) {
+    T result;
     if (variables == null || (result = variables[variable]) == null) {
       return parent == null ? null : parent[variable];
     }
     return result;
   }
 
-  void operator []=(Element variable, TypeMask mask) {
+  void operator []=(Element variable, T mask) {
     assert(mask != null);
     if (variables == null) {
-      variables = new Map<Element, TypeMask>();
+      variables = new Map<Element, T>();
     }
     variables[variable] = mask;
   }
 
-  void forEachOwnLocal(void f(Element element, TypeMask mask)) {
+  void forEachOwnLocal(void f(Element element, T type)) {
     if (variables == null) return;
     variables.forEach(f);
   }
@@ -115,12 +181,12 @@
 /**
  * Placeholder for inferred types of local variables.
  */
-class LocalsHandler {
+class LocalsHandler<T> {
   final Compiler compiler;
-  final TypesInferrer inferrer;
-  final VariableScope locals;
+  final TypeSystem<T> types;
+  final VariableScope<T> locals;
   final Map<Element, Element> capturedAndBoxed;
-  final Map<Element, TypeMask> fieldsInitializedInConstructor;
+  final Map<Element, T> fieldsInitializedInConstructor;
   final bool inTryBlock;
   bool isThisExposed;
   bool seenReturnOrThrow = false;
@@ -130,46 +196,46 @@
     return seenReturnOrThrow || seenBreakOrContinue;
   }
 
-  LocalsHandler(this.inferrer, this.compiler)
-      : locals = new VariableScope(),
+  LocalsHandler(this.types, this.compiler)
+      : locals = new VariableScope<T>(),
         capturedAndBoxed = new Map<Element, Element>(),
-        fieldsInitializedInConstructor = new Map<Element, TypeMask>(),
+        fieldsInitializedInConstructor = new Map<Element, T>(),
         inTryBlock = false,
         isThisExposed = true;
 
-  LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
-      : locals = new VariableScope(other.locals),
+  LocalsHandler.from(LocalsHandler<T> other, {bool inTryBlock: false})
+      : locals = new VariableScope<T>(other.locals),
         capturedAndBoxed = new Map<Element, Element>.from(
             other.capturedAndBoxed),
-        fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
+        fieldsInitializedInConstructor = new Map<Element, T>.from(
             other.fieldsInitializedInConstructor),
         inTryBlock = other.inTryBlock || inTryBlock,
-        inferrer = other.inferrer,
+        types = other.types,
         compiler = other.compiler,
         isThisExposed = other.isThisExposed;
 
-  LocalsHandler.deepCopyOf(LocalsHandler other)
-      : locals = new VariableScope.deepCopyOf(other.locals),
+  LocalsHandler.deepCopyOf(LocalsHandler<T> other)
+      : locals = new VariableScope<T>.deepCopyOf(other.locals),
         capturedAndBoxed = new Map<Element, Element>.from(
             other.capturedAndBoxed),
-        fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
+        fieldsInitializedInConstructor = new Map<Element, T>.from(
             other.fieldsInitializedInConstructor),
         inTryBlock = other.inTryBlock,
-        inferrer = other.inferrer,
+        types = other.types,
         compiler = other.compiler,
         isThisExposed = other.isThisExposed;
 
-  TypeMask use(Element local) {
+  T use(Element local) {
     if (capturedAndBoxed.containsKey(local)) {
-      return inferrer.getTypeOfElement(capturedAndBoxed[local]);
+      return types.getTypeOfCapturedAndBoxedVariable(capturedAndBoxed[local]);
     }
     return locals[local];
   }
 
-  void update(Element local, TypeMask type) {
+  void update(Element local, T type) {
     assert(type != null);
     if (compiler.trustTypeAnnotations || compiler.enableTypeAssertions) {
-      type = narrowType(type, local.computeType(compiler), compiler);
+      type = types.narrowType(type, local.computeType(compiler));
     }
     if (capturedAndBoxed.containsKey(local) || inTryBlock) {
       // If a local is captured and boxed, or is set in a try block,
@@ -178,7 +244,7 @@
       // We don't know if an assignment in a try block
       // will be executed, so all assigments in that block are
       // potential types after we have left it.
-      type = computeLUB(locals[local], type, compiler);
+      type = types.computeLUB(locals[local], type);
     }
     locals[local] = type;
   }
@@ -191,16 +257,16 @@
    * Merge handlers [first] and [second] into [:this:] and returns
    * whether the merge changed one of the variables types in [first].
    */
-  bool merge(LocalsHandler other, {bool discardIfAborts: true}) {
-    VariableScope currentOther = other.locals;
+  bool merge(LocalsHandler<T> other, {bool discardIfAborts: true}) {
+    VariableScope<T> currentOther = other.locals;
     assert(currentOther != locals);
     bool changed = false;
     // Iterate over all updates in the other handler until we reach
     // the block level of this handler. We know that [VariableScope]s
     // that are lower in block level, are the same.
     do {
-      currentOther.forEachOwnLocal((Element local, TypeMask otherType) {
-        TypeMask myType = locals[local];
+      currentOther.forEachOwnLocal((Element local, T otherType) {
+        T myType = locals[local];
         if (myType == null) return;
         bool isCaptured = capturedAndBoxed.containsKey(local);
         if (!isCaptured && aborts && discardIfAborts) {
@@ -208,7 +274,7 @@
         } else if (!isCaptured && other.aborts && discardIfAborts) {
           // Don't do anything.
         } else {
-          TypeMask type = computeLUB(myType, otherType, compiler);
+          T type = types.computeLUB(myType, otherType);
           if (type != myType) {
             changed = true;
           }
@@ -256,13 +322,13 @@
     // contain different fields, but if this map does not contain it,
     // then we know the field can be null and we don't need to track
     // it.
-    fieldsInitializedInConstructor.forEach((Element element, TypeMask type) {
-      TypeMask otherType = other.fieldsInitializedInConstructor[element];
+    fieldsInitializedInConstructor.forEach((Element element, T type) {
+      T otherType = other.fieldsInitializedInConstructor[element];
       if (otherType == null) {
         toRemove.add(element);
       } else {
         fieldsInitializedInConstructor[element] =
-            computeLUB(type, otherType, compiler);
+            types.computeLUB(type, otherType);
       }
     });
     // Remove fields that were not initialized in [other].
@@ -276,23 +342,23 @@
     return changed;
   }
 
-  void updateField(Element element, TypeMask type) {
+  void updateField(Element element, T type) {
     if (isThisExposed) return;
     fieldsInitializedInConstructor[element] = type;
   }
 }
 
-abstract class InferrerVisitor extends ResolvedVisitor<TypeMask> {
+abstract class InferrerVisitor<T> extends ResolvedVisitor<T> {
   final Element analyzedElement;
   // Subclasses know more about this field. Typing it dynamic to avoid
   // warnings.
-  final /* TypesInferrer */ inferrer;
+  final TypeSystem<T> types;
   final Compiler compiler;
-  final Map<TargetElement, List<LocalsHandler>> breaksFor =
-      new Map<TargetElement, List<LocalsHandler>>();
+  final Map<TargetElement, List<LocalsHandler<T>>> breaksFor =
+      new Map<TargetElement, List<LocalsHandler<T>>>();
   final Map<TargetElement, List<LocalsHandler>> continuesFor =
-      new Map<TargetElement, List<LocalsHandler>>();
-  LocalsHandler locals;
+      new Map<TargetElement, List<LocalsHandler<T>>>();
+  LocalsHandler<T> locals;
 
   bool accumulateIsChecks = false;
   bool conditionIsSimple = false;
@@ -304,108 +370,103 @@
   void set isThisExposed(value) { locals.isThisExposed = value; }
 
   InferrerVisitor(Element analyzedElement,
-                  this.inferrer,
+                  this.types,
                   Compiler compiler,
-                  [LocalsHandler handler])
+                  [LocalsHandler<T> handler])
     : this.compiler = compiler,
       this.analyzedElement = analyzedElement,
       super(compiler.enqueuer.resolution.getCachedElements(analyzedElement)) {
     locals = (handler == null)
-        ? new LocalsHandler(inferrer, compiler)
+        ? new LocalsHandler<T>(types, compiler)
         : handler;
   }
 
-  TypeMask visitSendSet(SendSet node);
+  T visitSendSet(SendSet node);
 
-  TypeMask visitSuperSend(Send node);
+  T visitSuperSend(Send node);
 
-  TypeMask visitStaticSend(Send node);
+  T visitStaticSend(Send node);
 
-  TypeMask visitGetterSend(Send node);
+  T visitGetterSend(Send node);
 
-  TypeMask visitClosureSend(Send node);
+  T visitClosureSend(Send node);
 
-  TypeMask visitDynamicSend(Send node);
+  T visitDynamicSend(Send node);
 
-  TypeMask visitForIn(ForIn node);
+  T visitForIn(ForIn node);
 
-  TypeMask visitReturn(Return node);
+  T visitReturn(Return node);
 
-  TypeMask visitNode(Node node) {
+  T visitNode(Node node) {
     node.visitChildren(this);
-    return compiler.typesTask.dynamicType;
   }
 
-  TypeMask visitNewExpression(NewExpression node) {
+  T visitNewExpression(NewExpression node) {
     return node.send.accept(this);
   }
 
-  TypeMask visit(Node node) {
-    return node == null ? compiler.typesTask.dynamicType : node.accept(this);
+  T visit(Node node) {
+    return node == null ? null : node.accept(this);
   }
 
-  TypeMask visitFunctionExpression(FunctionExpression node) {
+  T visitFunctionExpression(FunctionExpression node) {
     node.visitChildren(this);
-    return compiler.typesTask.functionType;
+    return types.functionType;
   }
 
-  TypeMask visitFunctionDeclaration(FunctionDeclaration node) {
-    locals.update(elements[node], compiler.typesTask.functionType);
+  T visitFunctionDeclaration(FunctionDeclaration node) {
+    locals.update(elements[node], types.functionType);
     return visit(node.function);
   }
 
-  TypeMask visitLiteralString(LiteralString node) {
-    return compiler.typesTask.stringType;
+  T visitLiteralString(LiteralString node) {
+    return types.stringType;
   }
 
-  TypeMask visitStringInterpolation(StringInterpolation node) {
+  T visitStringInterpolation(StringInterpolation node) {
     node.visitChildren(this);
-    return compiler.typesTask.stringType;
+    return types.stringType;
   }
 
-  TypeMask visitStringJuxtaposition(StringJuxtaposition node) {
+  T visitStringJuxtaposition(StringJuxtaposition node) {
     node.visitChildren(this);
-    return compiler.typesTask.stringType;
+    return types.stringType;
   }
 
-  TypeMask visitLiteralBool(LiteralBool node) {
-    return compiler.typesTask.boolType;
+  T visitLiteralBool(LiteralBool node) {
+    return types.boolType;
   }
 
-  TypeMask visitLiteralDouble(LiteralDouble node) {
-    return compiler.typesTask.doubleType;
+  T visitLiteralDouble(LiteralDouble node) {
+    return types.doubleType;
   }
 
-  TypeMask visitLiteralInt(LiteralInt node) {
+  T visitLiteralInt(LiteralInt node) {
     ConstantSystem constantSystem = compiler.backend.constantSystem;
     Constant constant = constantSystem.createInt(node.value);
     // The JavaScript backend may turn this literal into a double at
     // runtime.
     return constantSystem.isDouble(constant)
-        ? compiler.typesTask.doubleType
-        : compiler.typesTask.intType;
+        ? types.doubleType
+        : types.intType;
   }
 
-  TypeMask visitLiteralList(LiteralList node) {
+  T visitLiteralList(LiteralList node) {
     node.visitChildren(this);
-    return node.isConst()
-        ? compiler.typesTask.constListType
-        : compiler.typesTask.growableListType;
+    return node.isConst() ? types.constListType : types.growableListType;
   }
 
-  TypeMask visitLiteralMap(LiteralMap node) {
+  T visitLiteralMap(LiteralMap node) {
     node.visitChildren(this);
-    return node.isConst()
-        ? compiler.typesTask.constMapType
-        : compiler.typesTask.mapType;
+    return node.isConst() ? types.constMapType : types.mapType;
   }
 
-  TypeMask visitLiteralNull(LiteralNull node) {
-    return compiler.typesTask.nullType;
+  T visitLiteralNull(LiteralNull node) {
+    return types.nullType;
   }
 
-  TypeMask visitTypeReferenceSend(Send node) {
-    return compiler.typesTask.typeType;
+  T visitTypeReferenceSend(Send node) {
+    return types.typeType;
   }
 
   bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
@@ -415,33 +476,32 @@
         analyzedElement.getOutermostEnclosingMemberOrTopLevel().implementation;
   }
 
-  TypeMask _thisType;
-  TypeMask get thisType {
+  T _thisType;
+  T get thisType {
     if (_thisType != null) return _thisType;
     ClassElement cls = outermostElement.getEnclosingClass();
     if (compiler.world.isUsedAsMixin(cls)) {
-      return _thisType = new TypeMask.nonNullSubtype(cls.rawType);
+      return _thisType = types.nonNullSubtype(cls.rawType);
     } else if (compiler.world.hasAnySubclass(cls)) {
-      return _thisType = new TypeMask.nonNullSubclass(cls.rawType);
+      return _thisType = types.nonNullSubclass(cls.rawType);
     } else {
-      return _thisType = new TypeMask.nonNullExact(cls.rawType);
+      return _thisType = types.nonNullExact(cls.rawType);
     }
   }
 
-  TypeMask _superType;
-  TypeMask get superType {
+  T _superType;
+  T get superType {
     if (_superType != null) return _superType;
-    return _superType = new TypeMask.nonNullExact(
+    return _superType = types.nonNullExact(
         outermostElement.getEnclosingClass().superclass.rawType);
   }
 
-  TypeMask visitIdentifier(Identifier node) {
+  T visitIdentifier(Identifier node) {
     if (node.isThis()) {
       return thisType;
     } else if (node.isSuper()) {
       return superType;
     }
-    return compiler.typesTask.dynamicType;
   }
 
   void potentiallyAddIsCheck(Send node) {
@@ -460,14 +520,13 @@
       }
       DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
       Element element = elements[node.receiver];
-      TypeMask existing = locals.use(element);
-      TypeMask newType = narrowType(
-          existing, type, compiler, isNullable: false);
+      T existing = locals.use(element);
+      T newType = types.narrowType(existing, type, isNullable: false);
       locals.update(element, newType);
     }
   }
 
-  TypeMask visitOperatorSend(Send node) {
+  T visitOperatorSend(Send node) {
     Operator op = node.selector;
     if (const SourceString("[]") == op.source) {
       return visitDynamicSend(node);
@@ -479,18 +538,18 @@
       visit(node.receiver);
       accumulateIsChecks = oldAccumulateIsChecks;
       if (!accumulateIsChecks) isChecks = null;
-      LocalsHandler saved = locals;
-      locals = new LocalsHandler.from(locals);
+      LocalsHandler<T> saved = locals;
+      locals = new LocalsHandler<T>.from(locals);
       updateIsChecks(isChecks, usePositive: true);
       visit(node.arguments.head);
       saved.merge(locals);
       locals = saved;
-      return compiler.typesTask.boolType;
+      return types.boolType;
     } else if (const SourceString("||") == op.source) {
       conditionIsSimple = false;
       visit(node.receiver);
-      LocalsHandler saved = locals;
-      locals = new LocalsHandler.from(locals);
+      LocalsHandler<T> saved = locals;
+      locals = new LocalsHandler<T>.from(locals);
       updateIsChecks(isChecks, usePositive: false);
       bool oldAccumulateIsChecks = accumulateIsChecks;
       accumulateIsChecks = false;
@@ -498,28 +557,28 @@
       accumulateIsChecks = oldAccumulateIsChecks;
       saved.merge(locals);
       locals = saved;
-      return compiler.typesTask.boolType;
+      return types.boolType;
     } else if (const SourceString("!") == op.source) {
       bool oldAccumulateIsChecks = accumulateIsChecks;
       accumulateIsChecks = false;
       node.visitChildren(this);
       accumulateIsChecks = oldAccumulateIsChecks;
-      return compiler.typesTask.boolType;
+      return types.boolType;
     } else if (const SourceString("is") == op.source) {
       potentiallyAddIsCheck(node);
       node.visitChildren(this);
-      return compiler.typesTask.boolType;
+      return types.boolType;
     } else if (const SourceString("as") == op.source) {
-      TypeMask receiverType = visit(node.receiver);
+      T receiverType = visit(node.receiver);
       DartType type = elements.getType(node.arguments.head);
-      return narrowType(receiverType, type, compiler);
+      return types.narrowType(receiverType, type);
     } else if (node.argumentsNode is Prefix) {
       // Unary operator.
       return visitDynamicSend(node);
     } else if (const SourceString('===') == op.source
                || const SourceString('!==') == op.source) {
       node.visitChildren(this);
-      return compiler.typesTask.boolType;
+      return types.boolType;
     } else {
       // Binary operator.
       return visitDynamicSend(node);
@@ -532,35 +591,34 @@
   // to avoid confusing the [ResolvedVisitor].
   visitTypeAnnotation(TypeAnnotation node) {}
 
-  TypeMask visitConditional(Conditional node) {
+  T visitConditional(Conditional node) {
     List<Send> tests = <Send>[];
     bool simpleCondition = handleCondition(node.condition, tests);
-    LocalsHandler saved = locals;
-    locals = new LocalsHandler.from(locals);
+    LocalsHandler<T> saved = locals;
+    locals = new LocalsHandler<T>.from(locals);
     updateIsChecks(tests, usePositive: true);
-    TypeMask firstType = visit(node.thenExpression);
-    LocalsHandler thenLocals = locals;
+    T firstType = visit(node.thenExpression);
+    LocalsHandler<T> thenLocals = locals;
     locals = saved;
     if (simpleCondition) updateIsChecks(tests, usePositive: false);
-    TypeMask secondType = visit(node.elseExpression);
+    T secondType = visit(node.elseExpression);
     locals.merge(thenLocals);
-    TypeMask type = computeLUB(firstType, secondType, compiler);
+    T type = types.computeLUB(firstType, secondType);
     return type;
   }
 
-  TypeMask visitVariableDefinitions(VariableDefinitions node) {
+  T visitVariableDefinitions(VariableDefinitions node) {
     for (Link<Node> link = node.definitions.nodes;
          !link.isEmpty;
          link = link.tail) {
       Node definition = link.head;
       if (definition is Identifier) {
-        locals.update(elements[definition], compiler.typesTask.nullType);
+        locals.update(elements[definition], types.nullType);
       } else {
         assert(definition.asSendSet() != null);
         visit(definition);
       }
     }
-    return compiler.typesTask.dynamicType;
   }
 
   bool handleCondition(Node node, List<Send> tests) {
@@ -578,19 +636,18 @@
     return simpleCondition;
   }
 
-  TypeMask visitIf(If node) {
+  T visitIf(If node) {
     List<Send> tests = <Send>[];
     bool simpleCondition = handleCondition(node.condition, tests);
-    LocalsHandler saved = locals;
-    locals = new LocalsHandler.from(locals);
+    LocalsHandler<T> saved = locals;
+    locals = new LocalsHandler<T>.from(locals);
     updateIsChecks(tests, usePositive: true);
     visit(node.thenPart);
-    LocalsHandler thenLocals = locals;
+    LocalsHandler<T> thenLocals = locals;
     locals = saved;
     if (simpleCondition) updateIsChecks(tests, usePositive: false);
     visit(node.elsePart);
     locals.merge(thenLocals);
-    return compiler.typesTask.dynamicType;
   }
 
   void setupBreaksAndContinues(TargetElement element) {
@@ -607,7 +664,7 @@
   void mergeBreaks(TargetElement element) {
     if (element == null) return;
     if (!element.isBreakTarget) return;
-    for (LocalsHandler handler in breaksFor[element]) {
+    for (LocalsHandler<T> handler in breaksFor[element]) {
       locals.merge(handler, discardIfAborts: false);
     }
   }
@@ -616,20 +673,20 @@
     if (element == null) return false;
     if (!element.isContinueTarget) return false;
     bool changed = false;
-    for (LocalsHandler handler in continuesFor[element]) {
+    for (LocalsHandler<T> handler in continuesFor[element]) {
       changed = locals.merge(handler, discardIfAborts: false) || changed;
     }
     return changed;
   }
 
-  TypeMask handleLoop(Node node, void logic()) {
+  T handleLoop(Node node, void logic()) {
     loopLevel++;
     bool changed = false;
     TargetElement target = elements[node];
     setupBreaksAndContinues(target);
     do {
-      LocalsHandler saved = locals;
-      locals = new LocalsHandler.from(locals);
+      LocalsHandler<T> saved = locals;
+      locals = new LocalsHandler<T>.from(locals);
       logic();
       changed = saved.merge(locals);
       locals = saved;
@@ -638,10 +695,9 @@
     loopLevel--;
     mergeBreaks(target);
     clearBreaksAndContinues(target);
-    return compiler.typesTask.dynamicType;
   }
 
-  TypeMask visitWhile(While node) {
+  T visitWhile(While node) {
     return handleLoop(node, () {
       List<Send> tests = <Send>[];
       handleCondition(node.condition, tests);
@@ -650,7 +706,7 @@
     });
   }
 
-  TypeMask visitDoWhile(DoWhile node) {
+  T visitDoWhile(DoWhile node) {
     return handleLoop(node, () {
       visit(node.body);
       List<Send> tests = <Send>[];
@@ -659,7 +715,7 @@
     });
   }
 
-  TypeMask visitFor(For node) {
+  T visitFor(For node) {
     visit(node.initializer);
     return handleLoop(node, () {
       List<Send> tests = <Send>[];
@@ -670,101 +726,94 @@
     });
   }
 
-  TypeMask visitTryStatement(TryStatement node) {
-    LocalsHandler saved = locals;
-    locals = new LocalsHandler.from(locals, inTryBlock: true);
+  T visitTryStatement(TryStatement node) {
+    LocalsHandler<T> saved = locals;
+    locals = new LocalsHandler<T>.from(locals, inTryBlock: true);
     visit(node.tryBlock);
     saved.merge(locals);
     locals = saved;
     for (Node catchBlock in node.catchBlocks) {
       saved = locals;
-      locals = new LocalsHandler.from(locals);
+      locals = new LocalsHandler<T>.from(locals);
       visit(catchBlock);
       saved.merge(locals);
       locals = saved;
     }
     visit(node.finallyBlock);
-    return compiler.typesTask.dynamicType;
   }
 
-  TypeMask visitThrow(Throw node) {
+  T visitThrow(Throw node) {
     node.visitChildren(this);
     locals.seenReturnOrThrow = true;
-    return compiler.typesTask.dynamicType;
+    return types.dynamicType;
   }
 
-  TypeMask visitCatchBlock(CatchBlock node) {
+  T visitCatchBlock(CatchBlock node) {
     Node exception = node.exception;
     if (exception != null) {
       DartType type = elements.getType(node.type);
-      TypeMask mask = type == null
-          ? compiler.typesTask.dynamicType
-          : new TypeMask.nonNullSubtype(type.asRaw());
+      T mask = type == null
+          ? types.dynamicType
+          : types.nonNullSubtype(type.asRaw());
       locals.update(elements[exception], mask);
     }
     Node trace = node.trace;
     if (trace != null) {
-      locals.update(elements[trace], compiler.typesTask.dynamicType);
+      locals.update(elements[trace], types.dynamicType);
     }
     visit(node.block);
-    return compiler.typesTask.dynamicType;
   }
 
-  TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
+  T visitParenthesizedExpression(ParenthesizedExpression node) {
     return visit(node.expression);
   }
 
-  TypeMask visitBlock(Block node) {
+  T visitBlock(Block node) {
     if (node.statements != null) {
       for (Node statement in node.statements) {
         visit(statement);
         if (locals.aborts) break;
       }
     }
-    return compiler.typesTask.dynamicType;
   }
 
-  TypeMask visitLabeledStatement(LabeledStatement node) {
+  T visitLabeledStatement(LabeledStatement node) {
     Statement body = node.statement;
     if (body is Loop
         || body is SwitchStatement
         || Elements.isUnusedLabel(node, elements)) {
       // Loops and switches handle their own labels.
       visit(body);
-      return compiler.typesTask.dynamicType;
+    } else {
+      TargetElement targetElement = elements[body];
+      setupBreaksAndContinues(targetElement);
+      visit(body);
+      mergeBreaks(targetElement);
+      clearBreaksAndContinues(targetElement);
     }
-
-    TargetElement targetElement = elements[body];
-    setupBreaksAndContinues(targetElement);
-    visit(body);
-    mergeBreaks(targetElement);
-    clearBreaksAndContinues(targetElement);
-    return compiler.typesTask.dynamicType;
   }
 
-  TypeMask visitBreakStatement(BreakStatement node) {
+  T visitBreakStatement(BreakStatement node) {
     TargetElement target = elements[node];
     locals.seenBreakOrContinue = true;
     // Do a deep-copy of the locals, because the code following the
     // break will change them.
-    breaksFor[target].add(new LocalsHandler.deepCopyOf(locals));
-    return compiler.typesTask.dynamicType;
+    breaksFor[target].add(new LocalsHandler<T>.deepCopyOf(locals));
   }
 
-  TypeMask visitContinueStatement(ContinueStatement node) {
+  T visitContinueStatement(ContinueStatement node) {
     TargetElement target = elements[node];
     locals.seenBreakOrContinue = true;
     // Do a deep-copy of the locals, because the code following the
     // continue will change them.
-    continuesFor[target].add(new LocalsHandler.deepCopyOf(locals));
-    return compiler.typesTask.dynamicType;
+    continuesFor[target].add(new LocalsHandler<T>.deepCopyOf(locals));
   }
 
   void internalError(String reason, {Node node}) {
     compiler.internalError(reason, node: node);
   }
 
-  TypeMask visitSwitchStatement(SwitchStatement node) {
+  T visitSwitchStatement(SwitchStatement node) {
     visit(node.parenthesizedExpression);
 
     setupBreaksAndContinues(elements[node]);
@@ -792,8 +841,8 @@
       do {
         changed = false;
         for (Node switchCase in node.cases) {
-          LocalsHandler saved = locals;
-          locals = new LocalsHandler.from(locals);
+          LocalsHandler<T> saved = locals;
+          locals = new LocalsHandler<T>.from(locals);
           visit(switchCase);
           changed = saved.merge(locals, discardIfAborts: false) || changed;
           locals = saved;
@@ -804,8 +853,8 @@
         clearBreaksAndContinues(target);
       });
     } else {
-      LocalsHandler saved = locals;
-      List<LocalsHandler> localsToMerge = <LocalsHandler>[];
+      LocalsHandler<T> saved = locals;
+      List<LocalsHandler<T>> localsToMerge = <LocalsHandler>[];
 
       for (SwitchCase switchCase in node.cases) {
         if (switchCase.isDefaultCase) {
@@ -815,12 +864,12 @@
           locals = saved;
           visit(switchCase);
         } else {
-          locals = new LocalsHandler.from(saved);
+          locals = new LocalsHandler<T>.from(saved);
           visit(switchCase);
           localsToMerge.add(locals);
         }
       }
-      for (LocalsHandler handler in localsToMerge) {
+      for (LocalsHandler<T> handler in localsToMerge) {
         saved.merge(handler, discardIfAborts: false);
       }
       locals = saved;
@@ -835,6 +884,17 @@
     // that the [visitBlock] method does not assume the code after the
     // switch is dead code.
     locals.seenBreakOrContinue = false;
-    return compiler.typesTask.dynamicType;
+  }
+
+  T visitCascadeReceiver(CascadeReceiver node) {
+    // TODO(ngeoffray): Implement.
+    node.visitChildren(this);
+    return types.dynamicType;
+  }
+
+  T visitCascade(Cascade node) {
+    // TODO(ngeoffray): Implement.
+    node.visitChildren(this);
+    return types.dynamicType;
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 2a0c230..df69132 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -172,11 +172,14 @@
 
 class SimpleTypesInferrer extends TypesInferrer {
   InternalSimpleTypesInferrer internal;
-  Compiler compiler;
+  final Compiler compiler;
+  final TypeMaskSystem types;
 
   SimpleTypesInferrer(Compiler compiler) :
       compiler = compiler,
-      internal = new InternalSimpleTypesInferrer(compiler, OPTIMISTIC);
+      types = new TypeMaskSystem(compiler) {
+    internal = new InternalSimpleTypesInferrer(this, OPTIMISTIC);
+  }
 
   TypeMask getReturnTypeOfElement(Element element) {
     if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
@@ -206,7 +209,7 @@
     assert(internal.optimismState == RETRY);
 
     // Discard the inferrer and start again with a pessimistic one.
-    internal = new InternalSimpleTypesInferrer(compiler, PESSIMISTIC);
+    internal = new InternalSimpleTypesInferrer(this, PESSIMISTIC);
     return internal.analyzeMain(element);
   }
 
@@ -264,22 +267,7 @@
 
   int optimismState;
 
-  bool isDynamicType(TypeMask type) => identical(type, dynamicType);
-  TypeMask get dynamicType => compiler.typesTask.dynamicType;
-  TypeMask get nullType => compiler.typesTask.nullType;
-  TypeMask get intType => compiler.typesTask.intType;
-  TypeMask get doubleType => compiler.typesTask.doubleType;
-  TypeMask get numType => compiler.typesTask.numType;
-  TypeMask get boolType => compiler.typesTask.boolType;
-  TypeMask get functionType => compiler.typesTask.functionType;
-  TypeMask get listType => compiler.typesTask.listType;
-  TypeMask get constListType => compiler.typesTask.constListType;
-  TypeMask get fixedListType => compiler.typesTask.fixedListType;
-  TypeMask get growableListType => compiler.typesTask.growableListType;
-  TypeMask get mapType => compiler.typesTask.mapType;
-  TypeMask get constMapType => compiler.typesTask.constMapType;
-  TypeMask get stringType => compiler.typesTask.stringType;
-  TypeMask get typeType => compiler.typesTask.typeType;
+  bool isDynamicType(TypeMask type) => identical(type, types.dynamicType);
 
   /**
    * These are methods that are expected to return only bool.  We optimistically
@@ -328,7 +316,11 @@
    */
   int analyzed = 0;
 
-  InternalSimpleTypesInferrer(this.compiler, this.optimismState);
+  final TypeMaskSystem types;
+
+  InternalSimpleTypesInferrer(SimpleTypesInferrer inferrer, this.optimismState)
+      : this.compiler = inferrer.compiler,
+        this.types = inferrer.types;
 
   /**
    * Main entry point of the inferrer.  Analyzes all elements that the resolver
@@ -406,7 +398,7 @@
   }
 
   TypeMask getNonNullType(TypeMask returnType) {
-    return returnType != null ? returnType : dynamicType;
+    return returnType != null ? returnType : types.dynamicType;
   }
 
   Iterable<Element> getCallersOf(Element element) {
@@ -490,7 +482,7 @@
           if (optimismState == OPTIMISTIC) {
             FunctionTypeInformation info =
                 typeInformationOf(element.implementation);
-            info.returnType = boolType;
+            info.returnType = types.boolType;
           }
         } else {
           // Put the other operators in buckets by length, later to be added in
@@ -544,11 +536,11 @@
     typeInfo.forEach((element, TypeInformation info) {
       TypeMask type = info.type;
       TypeMask returnType = info.returnType;
-      if (type != null && type != nullType && !isDynamicType(type)) {
+      if (type != null && type != types.nullType && !isDynamicType(type)) {
         interestingTypes++;
       }
       if (returnType != null
-          && returnType != nullType
+          && returnType != types.nullType
           && !isDynamicType(returnType)) {
         interestingTypes++;
       }
@@ -617,7 +609,7 @@
     // If the type is useful, say it has changed.
     return existing != newType
         && !isDynamicType(newType)
-        && newType != nullType;
+        && newType != types.nullType;
   }
 
   /**
@@ -642,7 +634,7 @@
     // If the return type is useful, say it has changed.
     return existing != newType
         && !isDynamicType(newType)
-        && newType != nullType;
+        && newType != types.nullType;
   }
 
   bool isNativeElement(Element element) {
@@ -667,19 +659,19 @@
         assert(annotation is FunctionType);
         annotation = annotation.returnType;
       }
-      newType = narrowType(newType, annotation, compiler);
+      newType = types.narrowType(newType, annotation);
     }
     return newType;
   }
 
   TypeMask fetchReturnType(Element element) {
     TypeMask returnType = typeInformationOf(element).returnType;
-    return returnType is ElementTypeMask ? dynamicType : returnType;
+    return returnType is ElementTypeMask ? types.dynamicType : returnType;
   }
 
   TypeMask fetchType(Element element) {
     TypeMask type = typeInformationOf(element).type;
-    return type is ElementTypeMask ? dynamicType : type;
+    return type is ElementTypeMask ? types.dynamicType : type;
   }
 
   /**
@@ -698,7 +690,7 @@
       if (info.returnType == null) {
         var elementType = element.computeType(compiler);
         if (elementType.kind != TypeKind.FUNCTION) {
-          info.returnType = dynamicType;
+          info.returnType = types.dynamicType;
         } else {
           info.returnType = typeOfNativeBehavior(
             native.NativeBehavior.ofMethod(element, compiler));
@@ -713,7 +705,8 @@
               || element.isGetter()
               || element.isFactoryConstructor())) {
         FunctionType functionType = element.computeType(compiler);
-        returnType = narrowType(dynamicType, functionType.returnType, compiler);
+        returnType = types.narrowType(
+            types.dynamicType, functionType.returnType);
       } else {
         returnType = info.returnType =
             new ElementTypeMask(fetchReturnType, element);
@@ -723,30 +716,30 @@
   }
 
   TypeMask typeOfNativeBehavior(native.NativeBehavior nativeBehavior) {
-    if (nativeBehavior == null) return dynamicType;
+    if (nativeBehavior == null) return types.dynamicType;
     List typesReturned = nativeBehavior.typesReturned;
-    if (typesReturned.isEmpty) return dynamicType;
+    if (typesReturned.isEmpty) return types.dynamicType;
     TypeMask returnType;
     for (var type in typesReturned) {
       TypeMask mappedType;
       if (type == native.SpecialType.JsObject) {
         mappedType = new TypeMask.nonNullExact(rawTypeOf(compiler.objectClass));
       } else if (type.element == compiler.stringClass) {
-        mappedType = stringType;
+        mappedType = types.stringType;
       } else if (type.element == compiler.intClass) {
-        mappedType = intType;
+        mappedType = types.intType;
       } else if (type.element == compiler.doubleClass) {
-        mappedType = doubleType;
+        mappedType = types.doubleType;
       } else if (type.element == compiler.numClass) {
-        mappedType = numType;
+        mappedType = types.numType;
       } else if (type.element == compiler.boolClass) {
-        mappedType = boolType;
+        mappedType = types.boolType;
       } else if (type.element == compiler.nullClass) {
-        mappedType = nullType;
+        mappedType = types.nullType;
       } else if (type.isVoid) {
-        mappedType = nullType;
+        mappedType = types.nullType;
       } else if (type.isDynamic) {
-        return dynamicType;
+        return types.dynamicType;
       } else if (!compiler.world.hasAnySubtype(type.element)) {
         mappedType = new TypeMask.nonNullExact(rawTypeOf(type.element));
       } else {
@@ -759,9 +752,9 @@
           mappedType = new TypeMask.nonNullSubtype(rawTypeOf(element));
         }
       }
-      returnType = computeLUB(returnType, mappedType, compiler);
+      returnType = types.computeLUB(returnType, mappedType);
       if (!isTypeValuable(returnType)) {
-        returnType = dynamicType;
+        returnType = types.dynamicType;
         break;
       }
     }
@@ -781,7 +774,7 @@
       if (type == null) {
         InterfaceType rawType = element.computeType(compiler).asRaw();
         info.type = type = rawType.isDynamic
-            ? dynamicType
+            ? types.dynamicType
             : new TypeMask.subtype(rawType);
       }
       assert(type != null);
@@ -796,7 +789,8 @@
           // therefore only trust their type after the checks.
           || (compiler.enableTypeAssertions
               && (element.isField() || element.isVariable()))) {
-        type = narrowType(dynamicType, element.computeType(compiler), compiler);
+        type = types.narrowType(
+            types.dynamicType, element.computeType(compiler));
       } else {
         type = info.type = new ElementTypeMask(fetchType, element);
       }
@@ -811,14 +805,14 @@
   TypeMask typeOfSelector(Selector selector) {
     // Bailout for closure calls. We're not tracking types of
     // closures.
-    if (selector.isClosureCall()) return dynamicType;
-    if (selector.isSetter() || selector.isIndexSet()) return dynamicType;
+    if (selector.isClosureCall()) return types.dynamicType;
+    if (selector.isSetter() || selector.isIndexSet()) return types.dynamicType;
 
     TypeMask result;
     iterateOverElements(selector, (Element element) {
       assert(element.isImplementation);
       TypeMask type = typeOfElementWithSelector(element, selector);
-      result = computeLUB(result, type, compiler);
+      result = types.computeLUB(result, type);
       return isTypeValuable(result);
     });
     if (result == null) {
@@ -836,11 +830,13 @@
     } else if (selector.isGetter()) {
       if (element.isFunction()) {
         // [functionType] is null if the inferrer did not run.
-        return functionType == null ? dynamicType : functionType;
+        return types.functionType == null
+            ? types.dynamicType
+            : types.functionType;
       } else if (element.isField()) {
         return typeOfElement(element);
       } else if (Elements.isUnresolved(element)) {
-        return dynamicType;
+        return types.dynamicType;
       } else {
         assert(element.isGetter());
         return returnTypeOfElement(element);
@@ -850,10 +846,10 @@
                && selector.mask.isContainer) {
       ContainerTypeMask mask = selector.mask;
       TypeMask elementType = mask.elementType;
-      return elementType == null ? dynamicType : elementType;
+      return elementType == null ? types.dynamicType : elementType;
     } else if (element.isGetter() || element.isField()) {
       assert(selector.isCall() || selector.isSetter());
-      return dynamicType;
+      return types.dynamicType;
     } else {
       return returnTypeOfElement(element);
     }
@@ -928,7 +924,7 @@
       elementType = computeLubFor(elementType, mask, parameter);
     });
     if (elementType == null) {
-      elementType = dynamicType;
+      elementType = types.dynamicType;
     }
     return recordType(parameter, elementType);
   }
@@ -1075,11 +1071,12 @@
         return firstType;
       }
     }
-    return computeLUB(firstType, secondType, compiler);
+    return types.computeLUB(firstType, secondType);
   }
 
   TypeMask handleIntrisifiedSelector(Selector selector,
                                      ArgumentsTypes arguments) {
+    TypeMask intType = types.intType;
     if (selector.mask != intType) return null;
     if (!selector.isCall() && !selector.isOperator()) return null;
     if (!arguments.named.isEmpty) return null;
@@ -1132,13 +1129,13 @@
         if (!selector.isSetter()) {
           TypeMask type = handleIntrisifiedSelector(selector, arguments);
           if (type == null) type = typeOfElementWithSelector(element, selector);
-          result = computeLUB(result, type, compiler);
+          result = types.computeLUB(result, type);
         }
       }
     }
 
     if (result == null) {
-      result = dynamicType;
+      result = types.dynamicType;
     }
     return result;
   }
@@ -1177,10 +1174,10 @@
   }
 
   TypeMask computeTypeWithConstraints(Element element,
-                                      Map<Node, TypeMask> types) {
+                                      Map<Node, TypeMask> assignments) {
     List<CallSite> constraints = <CallSite>[];
     TypeMask elementType;
-    types.forEach((Node node, TypeMask mask) {
+    assignments.forEach((Node node, TypeMask mask) {
       CallSite constraint = setterConstraints[node];
       if (constraint != null) {
         // If this update has a constraint, we collect it and don't
@@ -1216,7 +1213,7 @@
           assert(selector.isGetter());
           type = typeOfSelector(selector);
         }
-        elementType = computeLUB(elementType, type, compiler);
+        elementType = types.computeLUB(elementType, type);
       }
       info.type = existing;
     }
@@ -1343,19 +1340,21 @@
   }
 }
 
-class SimpleTypeInferrerVisitor extends InferrerVisitor {
+class SimpleTypeInferrerVisitor extends InferrerVisitor<TypeMask> {
   TypeMask returnType;
   bool visitingInitializers = false;
   bool isConstructorRedirect = false;
   SideEffects sideEffects = new SideEffects.empty();
   final Element outermostElement;
+  final InternalSimpleTypesInferrer inferrer;
 
   SimpleTypeInferrerVisitor.internal(analyzedElement,
                                      this.outermostElement,
                                      inferrer,
                                      compiler,
                                      locals)
-    : super(analyzedElement, inferrer, compiler, locals);
+    : super(analyzedElement, inferrer.types, compiler, locals),
+      this.inferrer = inferrer;
 
   factory SimpleTypeInferrerVisitor(Element element,
                                     Compiler compiler,
@@ -1373,7 +1372,7 @@
     if (analyzedElement.isField() && node.asSendSet() == null) {
       // Eagerly bailout, because computing the closure data only
       // works for functions and field assignments.
-      return inferrer.nullType;
+      return types.nullType;
     }
     // Update the locals that are boxed in [locals]. These locals will
     // be handled specially, in that we are computing their LUB at
@@ -1402,14 +1401,14 @@
       Send send = node.asSendSet();
       ParameterTypeInformation info = inferrer.typeInformationOf(element);
       info.defaultType = (send == null)
-          ? inferrer.nullType
+          ? types.nullType
           : visit(send.arguments.head);
     });
 
     if (analyzedElement.isNative()) {
       // Native methods do not have a body, and we currently just say
       // they return dynamic.
-      return inferrer.dynamicType;
+      return types.dynamicType;
     }
 
     if (analyzedElement.isGenerativeConstructor()) {
@@ -1455,7 +1454,7 @@
           TypeMask type = locals.fieldsInitializedInConstructor[field];
           if (type == null && field.parseNode(compiler).asSendSet() == null) {
             inferrer.recordNonFinalFieldElementType(
-                node, field, inferrer.nullType, null);
+                node, field, types.nullType, null);
           }
         });
       }
@@ -1470,7 +1469,7 @@
         // No return in the body.
         returnType = locals.seenReturnOrThrow
             ? new TypeMask.nonNullEmpty()  // Body always throws.
-            : inferrer.nullType;
+            : types.nullType;
       } else if (!locals.seenReturnOrThrow &&
                  !inferrer.isDynamicType(returnType)) {
         // We haven't seen returns on all branches. So the method may
@@ -1484,7 +1483,7 @@
         // bool.
         signature.forEachParameter((Element parameter) {
           if (inferrer.typeOfElement(parameter).isNullable){
-            returnType = computeLUB(returnType, inferrer.boolType, compiler);
+            returnType = types.computeLUB(returnType, types.boolType);
           }
         });
       }
@@ -1532,7 +1531,7 @@
       inferrer.recordType(field, locals.locals[variable]);
     });
 
-    return inferrer.functionType;
+    return types.functionType;
   }
 
   TypeMask visitLiteralList(LiteralList node) {
@@ -1541,12 +1540,12 @@
       // when re-analyzing the node.
       return inferrer.concreteTypes.putIfAbsent(node, () {
         ContainerTypeMask container = new ContainerTypeMask(
-            inferrer.constListType, node, outermostElement);
+            types.constListType, node, outermostElement);
         TypeMask elementType = new TypeMask.nonNullEmpty();
         int length = 0;
         for (Node element in node.elements.nodes) {
           length++;
-          elementType = computeLUB(elementType, visit(element), compiler);
+          elementType = types.computeLUB(elementType, visit(element));
         }
         container.elementType = elementType;
         container.length = length;
@@ -1556,7 +1555,7 @@
       node.visitChildren(this);
       return inferrer.concreteTypes.putIfAbsent(
         node, () => new ContainerTypeMask(
-            inferrer.growableListType, node, outermostElement));
+            types.growableListType, node, outermostElement));
     }
   }
 
@@ -1577,7 +1576,7 @@
           // null.
           inferrer.recordNonFinalFieldElementType(
               analyzedElement.parseNode(compiler), element,
-              inferrer.nullType, null);
+              types.nullType, null);
         }
         // Accessing a field does not expose [:this:].
         return true;
@@ -1593,7 +1592,7 @@
     Element element = elements[node];
     if (!Elements.isUnresolved(element) && element.impliesType()) {
       node.visitChildren(this);
-      return inferrer.dynamicType;
+      return types.dynamicType;
     }
 
     Selector getterSelector =
@@ -1621,7 +1620,7 @@
     TypeMask indexType;
 
     if (isIncrementOrDecrement) {
-      rhsType = inferrer.intType;
+      rhsType = types.intType;
       if (node.isIndex) indexType = visit(node.arguments.head);
     } else if (node.isIndex) {
       indexType = visit(node.arguments.head);
@@ -1716,7 +1715,7 @@
         locals.update(element, newType);
       } else {
         // Bogus SendSet, for example [: myMethod += 42 :].
-        getterType = inferrer.dynamicType;
+        getterType = types.dynamicType;
         newType = handleDynamicSend(
             node, operatorSelector, getterType, operatorArguments);
       }
@@ -1780,7 +1779,7 @@
   TypeMask visitSuperSend(Send node) {
     Element element = elements[node];
     if (Elements.isUnresolved(element)) {
-      return inferrer.dynamicType;
+      return types.dynamicType;
     }
     Selector selector = elements.getSelector(node);
     // TODO(ngeoffray): We could do better here if we knew what we
@@ -1790,7 +1789,7 @@
       handleStaticSend(node, selector, element, null);
       return inferrer.typeOfElementWithSelector(element, selector);
     } else if (element.isFunction()) {
-      if (!selector.applies(element, compiler)) return inferrer.dynamicType;
+      if (!selector.applies(element, compiler)) return types.dynamicType;
       ArgumentsTypes arguments = analyzeArguments(node.arguments);
       handleStaticSend(node, selector, element, arguments);
       return inferrer.returnTypeOfElement(element);
@@ -1798,7 +1797,7 @@
       analyzeArguments(node.arguments);
       // Closure call on a getter. We don't have function types yet,
       // so we just return [:dynamic:].
-      return inferrer.dynamicType;
+      return types.dynamicType;
     }
   }
 
@@ -1812,24 +1811,24 @@
     }
     Selector selector = elements.getSelector(node);
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
-    if (!selector.applies(element, compiler)) return inferrer.dynamicType;
+    if (!selector.applies(element, compiler)) return types.dynamicType;
 
     handleStaticSend(node, selector, element, arguments);
     if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
       return inferrer.concreteTypes.putIfAbsent(
           node, () => new ContainerTypeMask(
-              inferrer.growableListType, node, outermostElement));
+              types.growableListType, node, outermostElement));
     } else if (Elements.isFixedListConstructorCall(element, node, compiler)
         || Elements.isFilledListConstructorCall(element, node, compiler)) {
       return inferrer.concreteTypes.putIfAbsent(
           node, () => new ContainerTypeMask(
-              inferrer.fixedListType, node, outermostElement));
+              types.fixedListType, node, outermostElement));
     } else if (element.isFunction() || element.isConstructor()) {
       return inferrer.returnTypeOfElement(element);
     } else {
       assert(element.isField() || element.isGetter());
       // Closure call.
-      return inferrer.dynamicType;
+      return types.dynamicType;
     }
   }
 
@@ -1845,10 +1844,10 @@
     } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')
                || name == const SourceString('JS_OPERATOR_AS_PREFIX')
                || name == const SourceString('JS_OBJECT_CLASS_NAME')) {
-      return inferrer.stringType;
+      return types.stringType;
     } else {
       sideEffects.setAllSideEffects();
-      return inferrer.dynamicType;
+      return types.dynamicType;
     }
   }
 
@@ -1880,15 +1879,15 @@
       return visitDynamicSend(node);
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
       handleStaticSend(node, selector, element, null);
-      return inferrer.functionType;
+      return types.functionType;
     } else if (Elements.isErroneousElement(element)) {
-      return inferrer.dynamicType;
+      return types.dynamicType;
     } else if (Elements.isLocal(element)) {
       assert(locals.use(element) != null);
       return locals.use(element);
     } else {
       node.visitChildren(this);
-      return inferrer.dynamicType;
+      return types.dynamicType;
     }
   }
 
@@ -1906,7 +1905,7 @@
     }
     sideEffects.setDependsOnSomething();
     sideEffects.setAllSideEffects();
-    return inferrer.dynamicType;
+    return types.dynamicType;
   }
 
   void handleStaticSend(Node node,
@@ -1992,7 +1991,7 @@
     if (node.isRedirectingFactoryBody) {
       Element element = elements[node.expression];
       if (Elements.isErroneousElement(element)) {
-        recordReturnType(inferrer.dynamicType);
+        recordReturnType(types.dynamicType);
       } else {
         element = element.implementation;
         // We don't create a selector for redirecting factories, and
@@ -2021,11 +2020,10 @@
     } else {
       Node expression = node.expression;
       recordReturnType(expression == null
-          ? inferrer.nullType
+          ? types.nullType
           : expression.accept(this));
     }
     locals.seenReturnOrThrow = true;
-    return inferrer.dynamicType;
   }
 
   TypeMask visitForIn(ForIn node) {
@@ -2059,7 +2057,7 @@
     if (element != null && element.isInstanceMember()) {
       receiverType = thisType;
     } else {
-      receiverType = inferrer.dynamicType;
+      receiverType = types.dynamicType;
     }
 
     handlePlainAssignment(identifier, element, selector,
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index ee30a60..b7442dd 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -120,6 +120,8 @@
       "super call arguments and constructor parameters don't match");
   static const NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT = const MessageKind(
       "implicit super call arguments and constructor parameters don't match");
+  static const CONST_CALLS_NON_CONST = const MessageKind(
+      "const constructor cannot call a non-const constructor");
   static const INITIALIZING_FORMAL_NOT_ALLOWED = const MessageKind(
       'an initializing formal parameter is only allowed in '
       'non-redirecting generative constructors');
diff --git a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
index aeb24ac..634a76f 100644
--- a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
+++ b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
@@ -30,7 +30,7 @@
       : super(server),
         _inner = server;
 
-  void close() => _inner.close();
+  Future close() => _inner.close();
 
   int get port => _inner.port;
 
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 66a769d..fcfc43b 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -4,19 +4,10 @@
 
 part of dart.async;
 
-class _BroadcastStream<T> extends _StreamImpl<T> {
-  _BroadcastStreamController _controller;
-
-  _BroadcastStream(this._controller);
+class _BroadcastStream<T> extends _ControllerStream<T> {
+  _BroadcastStream(_StreamControllerLifecycle controller) : super(controller);
 
   bool get isBroadcast => true;
-
-  StreamSubscription<T> _createSubscription(
-      void onData(T data),
-      void onError(Object error),
-      void onDone(),
-      bool cancelOnError) =>
-    _controller._subscribe(onData, onError, onDone, cancelOnError);
 }
 
 abstract class _BroadcastSubscriptionLink {
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index e0ba58a..5b3d760 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -602,9 +602,10 @@
   int get hashCode => _controller.hashCode ^ 0x35323532;
 
   bool operator==(Object other) {
+    if (identical(this, other)) return true;
     if (other is! _ControllerStream) return false;
     _ControllerStream otherStream = other;
-    return identical(otherStream._controller, this);
+    return identical(otherStream._controller, this._controller);
   }
 }
 
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 452dbe7..5d316eb 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -168,10 +168,13 @@
       => new _HttpServer.listenOn(serverSocket);
 
   /**
-   * Permanently stops this [HttpServer] from listening for new connections.
-   * This closes this [Stream] of [HttpRequest]s with a done event.
+   * Permanently stops this [HttpServer] from listening for new
+   * connections.  This closes this [Stream] of [HttpRequest]s with a
+   * done event. The returned future completes when the server is
+   * stopped. For a server started using [bind] or [bindSecure] this
+   * means that the port listened on no longer in use.
    */
-  void close();
+  Future close();
 
   /**
    * Returns the port that the server is listening on. This can be
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 4931831..98a3cf9 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -1926,10 +1926,13 @@
                                      cancelOnError: cancelOnError);
   }
 
-  void close() {
+  Future close() {
     closed = true;
+    Future result;
     if (_serverSocket != null && _closeServer) {
-      _serverSocket.close();
+      result = _serverSocket.close();
+    } else {
+      result = new Future.value();
     }
     if (_sessionManagerInstance != null) {
       _sessionManagerInstance.close();
@@ -1939,6 +1942,7 @@
       connection.destroy();
     }
     _connections.clear();
+    return result;
   }
 
   int get port {
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 957440e..e82adc7 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -257,9 +257,10 @@
   int get port;
 
   /**
-   * Closes the socket.
+   * Closes the socket. The returned future completes when the socket
+   * is fully closed and is no longer bound.
    */
-  void close();
+  Future close();
 }
 
 /**
@@ -300,12 +301,14 @@
   static const RawSocketEvent READ = const RawSocketEvent._(0);
   static const RawSocketEvent WRITE = const RawSocketEvent._(1);
   static const RawSocketEvent READ_CLOSED = const RawSocketEvent._(2);
+  static const RawSocketEvent CLOSED = const RawSocketEvent._(3);
   const RawSocketEvent._(this._value);
   final int _value;
   String toString() {
     return ['RawSocketEvent:READ',
             'RawSocketEvent:WRITE',
-            'RawSocketEvent:READ_CLOSED'][_value];
+            'RawSocketEvent:READ_CLOSED',
+            'RawSocketEvent:CLOSED'][_value];
   }
 }
 
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 16e1222..932743a 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -172,7 +172,6 @@
 Language/07_Classes/6_Constructors/2_Factories_A01_t05: Fail # Inherited from dartjs
 Language/07_Classes/6_Constructors/2_Factories_A07_t01: Fail # inherited from VM
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t01: Fail # http://dartbug.com/5519
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t02: Fail # http://dartbug.com/5519
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: Fail # inherited from VM
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: Fail # inherited from VM
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: Fail # inherited from VM
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 33ec9d5..554472b 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -691,7 +691,6 @@
 Language/07_Classes/4_Abstract_Instance_Members_A04_t06: Fail # Checks that a compile-time error is produced when the overriding non-abstract  instance method has almost the same set of named parameters as the abstract method being overriden,  except for one that has a different name.
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: Fail # Checks that error is produced if a final variable is not initialized in one  of the specified ways.
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t01: Fail # Checks that a compile-time error is produced when a class with constant  constructor also declares a non-final instance variable.
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t02: Fail # Checks that compile-time error is produced when a class with constant constructor inherits a non-final instance variable.
 Language/07_Classes/6_Constructors_A02_t01: Fail # Checks that a compile-error is produced when a named constructor definition does not begin with the name of its class.
 Language/11_Expressions/01_Constants_A16_t01: Fail # Checks that an IntegerDivisionByZeroException raised during evaluation  of a compile-time constant causes a compile-time error.
 Language/11_Expressions/01_Constants_A16_t02: Fail # Checks that an OutOfMemoryException raised during evaluation of a compile-time constant causes a compile-time error.
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index d6e1a83..abb669a 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -292,6 +292,28 @@
   result.checkNodeHasType('bar', [result.int]);
 }
 
+testDoWhile() {
+  final String source = r"""
+      class A { f() => new B(); }
+      class B { f() => new C(); }
+      class C { f() => new A(); }
+      main() {
+        var bar = null;
+        var foo = new A();
+        do {
+          foo = foo.f();
+        } while (bar = 42);
+        foo; bar;
+      }
+      """;
+  AnalysisResult result = analyze(source);
+  result.checkNodeHasType(
+      'foo',
+      [result.base('A'), result.base('B'), result.base('C')]);
+  // Check that the condition is evaluated.
+  result.checkNodeHasType('bar', [result.int]);
+}
+
 testFor1() {
   final String source = r"""
       class A { f() => new B(); }
@@ -887,6 +909,21 @@
   }
 }
 
+testBooleanOperatorsShortCirtcuit() {
+  String source(op) {
+    return """
+        main() {
+          var x = null;
+          "foo" $op (x = 42);
+          x;
+        }""";
+  }
+  for (String op in ['&&', '||']) {
+    AnalysisResult result = analyze(source(op));
+    result.checkNodeHasType('x', [result.nullType, result.int]);
+  }
+}
+
 testOperators() {
   final String source = r"""
       class A {
@@ -1071,21 +1108,43 @@
 
 testLists() {
   final String source = r"""
+    class A {}
+    class B {}
+    class C {}
+    class D {}
+    class E {}
+    class F {}
+    class G {}
+
     main() {
-      var l1 = [1.2];
+      var l1 = [new A()];
       var l2 = [];
-      l1['a'] = 42;  // raises an error, so int should not be recorded
-      l1[1] = 'abc';
-      "__dynamic_for_test"[1] = true;
-      var x = l1[1];
-      var y = l2[1];
-      var z = l1['foo'];
-      x; y; z;
+      l1['a'] = new B();  // raises an error, so B should not be recorded
+      l1[1] = new C();
+      l1.add(new D());
+      l1.insert('a', new E());  // raises an error, so E should not be recorded
+      l1.insert(1, new F());
+      "__dynamic_for_test"[1] = new G();
+      var x1 = l1[1];
+      var x2 = l2[1];
+      var x3 = l1['foo'];  // raises an error, should return empty
+      var x4 = l1.removeAt(1);
+      var x5 = l2.removeAt(1);
+      var x6 = l1.removeAt('a');  // raises an error, should return empty
+      var x7 = l1.removeLast();
+      var x8 = l2.removeLast();
+      x1; x2; x3; x4; x5; x6; x7; x8;
     }""";
   AnalysisResult result = analyze(source);
-  result.checkNodeHasType('x', [result.double, result.string, result.bool]);
-  result.checkNodeHasType('y', [result.double, result.string, result.bool]);
-  result.checkNodeHasType('z', []);
+  final expectedTypes = ['A', 'C', 'D', 'F', 'G'].map(result.base).toList();
+  result.checkNodeHasType('x1', expectedTypes);
+  result.checkNodeHasType('x2', expectedTypes);
+  result.checkNodeHasType('x3', []);
+  result.checkNodeHasType('x4', expectedTypes);
+  result.checkNodeHasType('x5', expectedTypes);
+  result.checkNodeHasType('x6', []);
+  result.checkNodeHasType('x7', expectedTypes);
+  result.checkNodeHasType('x8', expectedTypes);
 }
 
 testListWithCapacity() {
@@ -1529,6 +1588,7 @@
   testIfThenElse();
   testTernaryIf();
   testWhile();
+  testDoWhile();
   testFor1();
   testFor2();
   testFor3();
@@ -1553,6 +1613,7 @@
   // testNoReturn(); // right now we infer the empty type instead of null
   testArithmeticOperators();
   testBooleanOperators();
+  testBooleanOperatorsShortCirtcuit();
   testOperators();
   testCompoundOperators1();
   testCompoundOperators2();
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index cf84f928..750dc2e 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -107,7 +107,10 @@
     var length;
     operator[](index) => this[index];
     operator[]=(index, value) {}
-    var add;
+    add(value) {}
+    removeAt(index) {}
+    insert(index, value) {}
+    removeLast() {}
   }
   class JSMutableArray extends JSArray implements JSMutableIndexable {}
   class JSFixedArray extends JSMutableArray {}
@@ -177,7 +180,7 @@
   class bool {}
   class String implements Pattern {}
   class Object {
-    Object();
+    const Object();
     operator ==(other) { return true; }
     get hashCode => throw "Object.hashCode not implemented.";
     String toString() { return null; }
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index ab28e12..c260b67 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -123,11 +123,8 @@
 mandel_isolate_test: Pass, Fail, Timeout # Issue 7952
 mandel_isolate_stream_test: Pass, Fail, Timeout # Issue 7952
 
-[ $compiler == dart2js && ( $runtime == ff || $runtime == safari ) ]
-isolate_stress_test: Pass, Timeout # http://dartbug.com/10697
-
-[ $compiler == dart2js && ( $runtime == drt || $runtime == chrome ) ]
-isolate_stress_test: Pass, Crash, Timeout # issue 11648
+[ $compiler == dart2js && ( $runtime == ff || $runtime == safari || $runtime == drt || $runtime == chrome ) ]
+isolate_stress_test: Pass, Slow # http://dartbug.com/10697
 
 [ $arch == arm || $arch == simarm ]
 *: Skip
diff --git a/tests/isolate/isolate_stress_test.dart b/tests/isolate/isolate_stress_test.dart
index 685ea59..84a3447 100644
--- a/tests/isolate/isolate_stress_test.dart
+++ b/tests/isolate/isolate_stress_test.dart
@@ -7,14 +7,10 @@
 // in dart2js).
 
 import 'dart:async';
-import 'dart:html';
 import 'dart:isolate';
 
-// TODO(ahe): Remove dependency on unittest when tests are wrapperless.
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-const bool IS_UNITTEST = true;
+// TODO(ahe): Remove this import when we have wrapper-less testing.
+import 'dart:html';
 
 worker() {
   port.receive((String uri, SendPort replyTo) {
@@ -24,7 +20,6 @@
 }
 
 main() {
-  useHtmlConfiguration();
   try {
     // Create a Worker to confuse broken isolate implementation in dart2js.
     new Worker('data:application/javascript,').terminate();
@@ -38,25 +33,14 @@
       throw new Exception('Unexpected reply from worker: $reply');
     }
     if (++isolateCount > 200) {
-      if (IS_UNITTEST) {
-        doneClosure();
-      } else {
-        port.close();
-        window.postMessage('unittest-suite-done', '*');
-      }
+      port.close();
+      window.postMessage('unittest-suite-success', '*');
       return;
     }
     spawnFunction(worker).call('').then(spawnMany);
     print('isolateCount = $isolateCount');
   }
 
-  if (IS_UNITTEST) {
-    test('stress test', () {
-      spawnMany('Hello from Worker');
-      doneClosure = expectAsync0(() {});
-    });
-  } else {
-    spawnMany('Hello from Worker');
-    window.postMessage('unittest-suite-wait-for-done', '*');
-  }
+  spawnMany('Hello from Worker');
+  window.postMessage('unittest-suite-wait-for-done', '*');
 }
diff --git a/tests/language/const_constructor_mixin2_test.dart b/tests/language/const_constructor_mixin2_test.dart
new file mode 100644
index 0000000..7fc27c6
--- /dev/null
+++ b/tests/language/const_constructor_mixin2_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Mixin {
+  var nonFinalField;
+}
+
+class A {
+  const A(foo);
+}
+
+class B extends A 
+    with Mixin  /// 01: compile-time error
+    {
+  const B(foo) : super(foo);
+}
+
+main() {
+  var a = const B(42);
+  a.nonFinalField = 54; /// 01: continued
+}
diff --git a/tests/language/const_constructor_mixin3_test.dart b/tests/language/const_constructor_mixin3_test.dart
new file mode 100644
index 0000000..c81b7d3
--- /dev/null
+++ b/tests/language/const_constructor_mixin3_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Mixin {
+}
+
+class A {
+  const A();
+}
+
+class B extends A
+    with Mixin /// 01: compile-time error
+    {
+  const B();
+}
+
+main() {
+  var a = const B();
+}
diff --git a/tests/language/const_constructor_mixin_test.dart b/tests/language/const_constructor_mixin_test.dart
index 832be8c..83ad156 100644
--- a/tests/language/const_constructor_mixin_test.dart
+++ b/tests/language/const_constructor_mixin_test.dart
@@ -9,7 +9,9 @@
   const A(foo);
 }
 
-class B extends A with Mixin {
+class B extends A
+    with Mixin  /// 01: compile-time error
+    {
   const B(foo) : super(foo);
 }
 
diff --git a/tests/language/language.status b/tests/language/language.status
index a04ad53..04b54c3 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -18,7 +18,6 @@
 [ $compiler == dart2dart ]
 mixin_super_constructor_named_test: Fail
 mixin_super_constructor_positionals_test: Fail
-const_constructor_super_test/01: fail
 
 [ $compiler == none ]
 mixin_super_constructor_named_test: Fail
@@ -73,6 +72,11 @@
 
 mixin_forwarding_constructor2_test: Fail # Issue 11888
 mixin_typedef_constructor_test: Fail # Issue 11888
+mixin_type_parameter2_test: Fail # Issue 11888
+
+const_constructor_mixin_test/01: Fail # Issue 11917
+const_constructor_mixin2_test/01: Fail # Issue 11917
+const_constructor_mixin3_test/01: Fail # Issue 11917
 
 [ $compiler == none && $unchecked ]
 
@@ -144,6 +148,7 @@
 mixin_issue10216_2_test: Fail               # VM issue
 mixin_forwarding_constructor2_test: Fail # Issue 11888
 mixin_typedef_constructor_test: Fail # Issue 11888
+mixin_type_parameter2_test: Fail # Issue 11888
 
 mixin_with_two_implicit_constructors_test: Fail # Issue 11889
 
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 8e01e1e..85880b7 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -272,6 +272,10 @@
 # test issue 11579, assignment, no setter
 getter_no_setter_test/none: fail
 
+# test issue 11918: mixin and const constructor
+const_constructor_mixin_test/01: fail
+const_constructor_mixin3_test/01: fail
+
 [ $compiler == dartanalyzer && $checked ]
 factory1_test/00: fail
 factory1_test/01: fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 26d084f..293c051 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -90,7 +90,6 @@
 compile_time_constant_checked3_test/06: Fail, OK
 
 [ $compiler == dart2js ]
-const_constructor_super_test/01: Fail # Const ctor calls non-const super ctor
 function_type_alias6_test: Crash # dartbug.com/9792
 branch_canonicalization_test: Fail # Issue 638.
 div_with_power_of_two_test: Fail # Issue 8301.
diff --git a/tests/language/mixin_type_parameter1_test.dart b/tests/language/mixin_type_parameter1_test.dart
new file mode 100644
index 0000000..d591abd
--- /dev/null
+++ b/tests/language/mixin_type_parameter1_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class Mixin1<T> {
+}
+
+abstract class Mixin2<T> {
+}
+
+class A {
+}
+
+typedef MyTypedef<K, V> = A with Mixin1<K>, Mixin2<V>;
+
+class B<K, V> extends MyTypedef<K, V> {
+}
+
+main() {
+  var b = new B<num, String>();
+  Expect.isTrue(b is Mixin1<num>);
+  Expect.isTrue(b is! Mixin1<String>);
+  Expect.isTrue(b is Mixin2<String>);
+  Expect.isTrue(b is! Mixin2<num>);
+}
diff --git a/tests/language/mixin_type_parameter2_test.dart b/tests/language/mixin_type_parameter2_test.dart
new file mode 100644
index 0000000..27fe245
--- /dev/null
+++ b/tests/language/mixin_type_parameter2_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class Mixin1<T> {
+}
+
+abstract class Mixin2<T> {
+}
+
+class A {
+  A(foo);
+}
+
+typedef MyTypedef<K, V> = A with Mixin1<K>, Mixin2<V>;
+
+class B<K, V> extends MyTypedef<K, V> {
+  B(foo) : super(foo);
+}
+
+main() {
+  var b = new B<num, String>(null);
+  Expect.isTrue(b is Mixin1<num>);
+  Expect.isTrue(b is! Mixin1<String>);
+  Expect.isTrue(b is Mixin2<String>);
+  Expect.isTrue(b is! Mixin2<num>);
+}
diff --git a/tests/language/mixin_type_parameter3_test.dart b/tests/language/mixin_type_parameter3_test.dart
new file mode 100644
index 0000000..17da813
--- /dev/null
+++ b/tests/language/mixin_type_parameter3_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class Mixin1<T> {
+}
+
+abstract class Mixin2<T> {
+}
+
+class A {
+  A(foo);
+}
+
+class B<K, V> extends A with Mixin1<K>, Mixin2<V> {
+  B(foo) : super(foo);
+}
+
+main() {
+  var b = new B<num, String>(null);
+  Expect.isTrue(b is Mixin1<num>);
+  Expect.isTrue(b is! Mixin1<String>);
+  Expect.isTrue(b is Mixin2<String>);
+  Expect.isTrue(b is! Mixin2<num>);
+}
diff --git a/tests/lib/async/stream_controller_test.dart b/tests/lib/async/stream_controller_test.dart
index 3f2a48b..8f1d26a 100644
--- a/tests/lib/async/stream_controller_test.dart
+++ b/tests/lib/async/stream_controller_test.dart
@@ -416,9 +416,30 @@
   Expect.isTrue(c.isClosed);
 }
 
+void testStreamEquals() {
+  StreamController c;
+  c = new StreamController(sync: false);
+  Expect.equals(c.stream, c.stream);
+  c = new StreamController(sync: true);
+  Expect.equals(c.stream, c.stream);
+  c = new StreamController(sync: false, onListen:(){});
+  Expect.equals(c.stream, c.stream);
+  c = new StreamController(sync: true, onListen:(){});
+  Expect.equals(c.stream, c.stream);
+  c = new StreamController.broadcast(sync: false);
+  Expect.equals(c.stream, c.stream);
+  c = new StreamController.broadcast(sync: true);
+  Expect.equals(c.stream, c.stream);
+  c = new StreamController.broadcast(sync: false, onListen:(){});
+  Expect.equals(c.stream, c.stream);
+  c = new StreamController.broadcast(sync: true, onListen:(){});
+  Expect.equals(c.stream, c.stream);
+}
+
 main() {
   testMultiController();
   testSingleController();
   testExtraMethods();
   testClosed();
+  testStreamEquals();
 }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 0e75568..9b5952c 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -85,6 +85,7 @@
 async/timer_not_available_test: Fail, OK # only meant to test when there is no way to
                                          # implement timer (currently only in d8)
 async/timer_isolate_test: Skip # See Issue 4997
+mirrors/native_class_test: Fail, OK # This test is meant to run in a browser.
 
 [ $runtime == vm || ($compiler == none && $runtime == drt) ]
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9001.
@@ -107,8 +108,6 @@
 
 
 [ $arch == arm || $arch == simarm ]
-typed_data/float32x4_unbox_regress_test: Crash # Unimplemented
-typed_data/float32x4_list_test: Crash # Unimplemented
 typed_data/float32x4_test: Crash # Unimplemented
 
 [ $arch == mips ]
diff --git a/tests/lib/mirrors/native_class_test.dart b/tests/lib/mirrors/native_class_test.dart
new file mode 100644
index 0000000..b6171d0
--- /dev/null
+++ b/tests/lib/mirrors/native_class_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.native_class_test;
+
+import 'dart:html';
+
+@MirrorsUsed(targets: 'dart.dom.html.Element')
+import 'dart:mirrors';
+
+import 'stringify.dart';
+
+main() {
+  expect('s(dart.dom.html.Element)', reflectClass(Element).qualifiedName);
+  expect(
+      's(dart.dom.html.Node)', reflectClass(Element).superclass.qualifiedName);
+  window.postMessage('unittest-suite-success', '*');
+}
diff --git a/tests/lib/typed_data/float32x4_list_test.dart b/tests/lib/typed_data/float32x4_list_test.dart
index 79ffdbc..0de9492 100644
--- a/tests/lib/typed_data/float32x4_list_test.dart
+++ b/tests/lib/typed_data/float32x4_list_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// VMOptions=--deoptimization_counter_threshold=1000
+// VMOptions=--deoptimization_counter_threshold=1000 --optimization-counter-threshold=10
 
 // Library tag to be able to run in html test framework.
 library float32x4_list_test;
@@ -40,49 +40,49 @@
 testLoadStoreDeoptDriver() {
   Float32x4List list = new Float32x4List(4);
   Float32x4 value = new Float32x4(1.0, 2.0, 3.0, 4.0);
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStoreDeopt(list, 0, value);
   }
   try {
     // Invalid index.
     testLoadStoreDeopt(list, 5, value);
   } catch (_) {}
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStoreDeopt(list, 0, value);
   }
   try {
     // null list.
     testLoadStoreDeopt(null, 0, value);
   } catch (_) {}
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStoreDeopt(list, 0, value);
   }
   try {
     // null value.
     testLoadStoreDeopt(list, 0, null);
   } catch (_) {}
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStoreDeopt(list, 0, value);
   }
   try {
     // non-smi index.
     testLoadStoreDeopt(list, 3.14159, value);
   } catch (_) {}
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStoreDeopt(list, 0, value);
   }
   try {
     // non-Float32x4 value.
     testLoadStoreDeopt(list, 0, 4.toDouble());
   } catch (_) {}
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStoreDeopt(list, 0, value);
   }
   try {
     // non-Float32x4List list.
     testLoadStoreDeopt([new Float32x4(2.0, 3.0, 4.0, 5.0)], 0, value);
   } catch (_) {}
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStoreDeopt(list, 0, value);
   }
 }
@@ -112,7 +112,7 @@
   var list;
 
   list = new Float32x4List(8);
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStore(list);
   }
 
@@ -121,13 +121,13 @@
     floatList[i] = i.toDouble();
   }
   list = new Float32x4List.view(floatList);
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testView(list);
   }
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testLoadStore(list);
   }
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testListZero();
   }
   testLoadStoreDeoptDriver();
diff --git a/tests/lib/typed_data/float32x4_unbox_regress_test.dart b/tests/lib/typed_data/float32x4_unbox_regress_test.dart
index c20a6ea..e179f95 100644
--- a/tests/lib/typed_data/float32x4_unbox_regress_test.dart
+++ b/tests/lib/typed_data/float32x4_unbox_regress_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// VMOptions=--deoptimization_counter_threshold=1000
+// VMOptions=--deoptimization_counter_threshold=1000 --optimization-counter-threshold=10
 
 // Library tag to be able to run in html test framework.
 library float32x4_unbox_regress_test;
@@ -18,7 +18,7 @@
   var value = new Float32x4(1.0, 2.0, 3.0, 4.0);
   var smi = 12;
   list = new Float32x4List(8);
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testListStore(list, 0, value);
   }
 
@@ -41,7 +41,7 @@
   var a = new Float32x4(1.0, 2.0, 3.0, 4.0);
   var b = new Float32x4(2.0, 3.0, 4.0, 5.0);
   var smi = 12;
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testAdd(a, b);
   }
 
@@ -59,7 +59,7 @@
 void testGetDeopt() {
   var a = new Float32x4(1.0, 2.0, 3.0, 4.0);
   var smi = 12;
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testGet(a);
   }
 
@@ -68,7 +68,7 @@
   } catch (_) {
   }
 
-  for (int i = 0; i < 3000; i++) {
+  for (int i = 0; i < 20; i++) {
     testGet(a);
   }
 }
@@ -86,7 +86,7 @@
   var b = new Float32x4(1.0, 2.1, 3.1, 4.0);
   var smi = 12;
 
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < 20; i++) {
     testComparison(a, b);
   }
 
@@ -95,7 +95,7 @@
   } catch (_) {
   }
 
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < 20; i++) {
     testComparison(a, b);
   }
 
@@ -104,7 +104,7 @@
   } catch (_) {
   }
 
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < 20; i++) {
     testComparison(a, b);
   }
 }
diff --git a/tests/standalone/io/raw_socket_test.dart b/tests/standalone/io/raw_socket_test.dart
index 1b1b23f..a61bccf 100644
--- a/tests/standalone/io/raw_socket_test.dart
+++ b/tests/standalone/io/raw_socket_test.dart
@@ -150,6 +150,7 @@
     server.listen((client) {
       int bytesRead = 0;
       int bytesWritten = 0;
+      bool closedEventReceived = false;
       List<int> data = new List<int>(messageSize);
 
       client.writeEventsEnabled = false;
@@ -188,14 +189,20 @@
           case RawSocketEvent.READ_CLOSED:
             server.close();
             break;
+          case RawSocketEvent.CLOSED:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
           default: throw "Unexpected event $event";
         }
-      });
+      },
+      onDone: () => Expect.isTrue(closedEventReceived));
     });
 
     RawSocket.connect("127.0.0.1", server.port).then((socket) {
       int bytesRead = 0;
       int bytesWritten = 0;
+      bool closedEventReceived = false;
       List<int> data = createTestData();
 
       socket.listen((event) {
@@ -229,10 +236,17 @@
             verifyTestData(data);
             socket.close();
             break;
+          case RawSocketEvent.CLOSED:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
           default: throw "Unexpected event $event";
         }
       },
-      onDone: () => port.close());
+      onDone: () {
+        Expect.isTrue(closedEventReceived);
+        port.close();
+      });
     });
   });
 }
@@ -288,6 +302,7 @@
   RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) {
     Expect.isTrue(server.port > 0);
     server.listen((client) {
+      bool closedEventReceived = false;
       List<int> data = new List<int>.filled(messageSize, 0);
       writeSubscription = client.listen((event) {
         switch (event) {
@@ -312,12 +327,18 @@
             client.close();
             server.close();
             break;
+          case RawSocketEvent.CLOSED:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
           default: throw "Unexpected event $event";
         }
-      });
+      },
+      onDone: () => Expect.isTrue(closedEventReceived));
     });
 
     RawSocket.connect("127.0.0.1", server.port).then((socket) {
+      bool closedEventReceived = false;
       socket.writeEventsEnabled = false;
       readSubscription = socket.listen((event) {
         switch (event) {
@@ -343,10 +364,15 @@
           case RawSocketEvent.WRITE:
             throw "Unexpected write event";
           case RawSocketEvent.READ_CLOSED:
-            throw "Unexpected close event";
+            throw "Unexpected read closed event";
+          case RawSocketEvent.CLOSED:
+          Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
           default: throw "Unexpected event $event";
         }
-      });
+      },
+      onDone: () => Expect.isTrue(closedEventReceived));
       readSubscription.pause();
       connected.complete(true);
     });
diff --git a/tests/standalone/io/raw_socket_typed_data_test.dart b/tests/standalone/io/raw_socket_typed_data_test.dart
index 61f9281..e843aba 100644
--- a/tests/standalone/io/raw_socket_typed_data_test.dart
+++ b/tests/standalone/io/raw_socket_typed_data_test.dart
@@ -28,6 +28,8 @@
             client.close();
             server.close();
             break;
+          case RawSocketEvent.CLOSED:
+            break;
           default: throw "Unexpected event $event";
         }
       });
@@ -71,6 +73,8 @@
             break;
           case RawSocketEvent.READ_CLOSED:
             break;
+          case RawSocketEvent.CLOSED:
+            break;
           default: throw "Unexpected event $event";
         }
       },
@@ -155,6 +159,8 @@
           case RawSocketEvent.READ_CLOSED:
             server.close();
             break;
+          case RawSocketEvent.CLOSED:
+            break;
           default: throw "Unexpected event $event";
         }
       });
@@ -194,6 +200,8 @@
             verifyTestData(received);
             socket.close();
             break;
+          case RawSocketEvent.CLOSED:
+            break;
           default: throw "Unexpected event $event";
         }
       },
diff --git a/tests/standalone/io/socket_exception_test.dart b/tests/standalone/io/socket_exception_test.dart
index 41290d6..f882b3e 100644
--- a/tests/standalone/io/socket_exception_test.dart
+++ b/tests/standalone/io/socket_exception_test.dart
@@ -118,7 +118,7 @@
   static void clientSocketAddDestroyNoErrorTest() {
     ServerSocket.bind("127.0.0.1", 0).then((server) {
       server.listen((socket) {
-        // Passive block data by not sobscribing to socket.
+        // Passive block data by not subscribing to socket.
       });
       Socket.connect("127.0.0.1", server.port).then((client) {
         client.listen((data) {}, onDone: server.close);
diff --git a/tools/VERSION b/tools/VERSION
index 9a50ffe..de9958b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 6
-BUILD 7
+BUILD 8
 PATCH 0
diff --git a/tools/publish_all_pkgs.py b/tools/publish_all_pkgs.py
index 2e3d181..6c302e2 100644
--- a/tools/publish_all_pkgs.py
+++ b/tools/publish_all_pkgs.py
@@ -21,13 +21,9 @@
   pkgs_to_publish = []
   for name in os.listdir('pkg'):
     if os.path.isdir(os.path.join('pkg', name)):
-      if (name != '.svn' and name != 'fixnum' and name != 'expect'):
+      if (name != '.svn' and name != 'expect'):
         pkgs_to_publish.append(os.path.join('pkg', name))
 
-  # Publish dart2js as an "unsupported" package.
-  pkgs_to_publish.append(
-    os.path.join('sdk', 'lib', '_internal', 'compiler'))
-
   for pkg in pkgs_to_publish:
     print "\n\nPublishing %s:\n-------------------------------" % pkg
     subprocess.call(['python', 'tools/publish_pkg.py', pkg])