Version 1.5.0-dev.4.3

svn merge -c 37076 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 37077 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 37097 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 37101 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 37107 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

Merge 37105, 37104, 37095, 37042, 37022, 37016 by applying
https://codereview.chromium.org/321583008/

git-svn-id: http://dart.googlecode.com/svn/trunk@37110 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 72706ac..417a905 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -633,10 +633,12 @@
     caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
   }
   if (FLAG_trace_patching) {
-    OS::PrintErr("PatchStaticCall: patching from %#" Px " to '%s' %#" Px "\n",
+    OS::PrintErr("PatchStaticCall: patching caller pc %#" Px ""
+        " to '%s' new entry point %#" Px " (%s)\n",
         caller_frame->pc(),
         target_function.ToFullyQualifiedCString(),
-        target_code.EntryPoint());
+        target_code.EntryPoint(),
+        target_code.is_optimized() ? "optimized" : "unoptimized");
   }
   arguments.SetReturn(target_code);
 }
@@ -1293,9 +1295,11 @@
     caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
   }
   if (FLAG_trace_patching) {
-    OS::PrintErr("FixCallersTarget: patching from %#" Px " to '%s' %#" Px "\n",
+    OS::PrintErr("FixCallersTarget: caller %#" Px " "
+        "target '%s' %#" Px " -> %#" Px "\n",
         frame->pc(),
         target_function.ToFullyQualifiedCString(),
+        target_code.EntryPoint(),
         current_target_code.EntryPoint());
   }
   arguments.SetReturn(current_target_code);
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index da3feb1..b8805f8 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -59,6 +59,7 @@
     "Enable compiler verification assertions");
 
 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
+DECLARE_FLAG(bool, trace_patching);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 DECLARE_FLAG(bool, warning_as_error);
 
@@ -556,8 +557,12 @@
         if (optimized) {
           if (osr_id == Isolate::kNoDeoptId) {
             CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
-            if (FLAG_trace_compiler) {
-              OS::Print("--> patching entry %#" Px "\n",
+            if (FLAG_trace_compiler || FLAG_trace_patching) {
+              if (FLAG_trace_compiler) {
+                OS::Print("  ");
+              }
+              OS::Print("Patch unoptimized '%s' entry point %#" Px "\n",
+                  function.ToFullyQualifiedCString(),
                   Code::Handle(function.unoptimized_code()).EntryPoint());
             }
           }
@@ -575,11 +580,10 @@
           ASSERT(CodePatcher::CodeIsPatchable(code));
         }
         if (parsed_function->HasDeferredPrefixes()) {
-          GrowableObjectArray* prefixes = parsed_function->DeferredPrefixes();
-          LibraryPrefix& prefix = LibraryPrefix::Handle();
-          for (intptr_t i = 0; i < prefixes->Length(); i++) {
-            prefix ^= prefixes->At(i);
-            prefix.RegisterDependentCode(code);
+          ZoneGrowableArray<const LibraryPrefix*>* prefixes =
+              parsed_function->deferred_prefixes();
+          for (intptr_t i = 0; i < prefixes->length(); i++) {
+            (*prefixes)[i]->RegisterDependentCode(code);
           }
         }
       }
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index afaffa1..c0c74a6 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -42,7 +42,8 @@
     use_far_branches_(false),
     loop_headers_(NULL),
     loop_invariant_loads_(NULL),
-    guarded_fields_(builder.guarded_fields()) {
+    guarded_fields_(builder.guarded_fields()),
+    deferred_prefixes_(builder.deferred_prefixes()) {
   DiscoverBlocks();
 }
 
@@ -63,6 +64,21 @@
 }
 
 
+void FlowGraph::AddToDeferredPrefixes(
+    ZoneGrowableArray<const LibraryPrefix*>* from) {
+  ZoneGrowableArray<const LibraryPrefix*>* to = deferred_prefixes();
+  for (intptr_t i = 0; i < from->length(); i++) {
+    const  LibraryPrefix* prefix = (*from)[i];
+    for (intptr_t j = 0; j < to->length(); j++) {
+      if ((*to)[j]->raw() == prefix->raw()) {
+        return;
+      }
+    }
+    to->Add(prefix);
+  }
+}
+
+
 bool FlowGraph::ShouldReorderBlocks(const Function& function,
                                     bool is_optimized) {
   return is_optimized && FLAG_reorder_basic_blocks && !function.is_intrinsic();
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 9d2d42e..1868d0a 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -216,11 +216,16 @@
 
   static void AddToGuardedFields(ZoneGrowableArray<const Field*>* array,
                                  const Field* field);
+  void AddToDeferredPrefixes(ZoneGrowableArray<const LibraryPrefix*>* from);
 
   ZoneGrowableArray<const Field*>* guarded_fields() const {
     return guarded_fields_;
   }
 
+  ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const {
+    return deferred_prefixes_;
+  }
+
  private:
   friend class IfConverter;
   friend class BranchSimplifier;
@@ -300,6 +305,7 @@
   ZoneGrowableArray<BlockEntryInstr*>* loop_headers_;
   ZoneGrowableArray<BitVector*>* loop_invariant_loads_;
   ZoneGrowableArray<const Field*>* guarded_fields_;
+  ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes_;
 };
 
 
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 7632971..8467cb5 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -199,6 +199,10 @@
     return guarded_fields_;
   }
 
+  ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const {
+    return parsed_function_->deferred_prefixes();
+  }
+
   intptr_t temp_count() const { return temp_count_; }
   intptr_t AllocateTemp() { return temp_count_++; }
   void DeallocateTemps(intptr_t count) {
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index b07c635..11fedc1 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -802,6 +802,9 @@
         FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(),
                                       (*callee_graph->guarded_fields())[i]);
       }
+      // When inlined, we add the deferred prefixes of the callee to the
+      // caller's list of deferred prefixes.
+      caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes());
 
       // We allocate a ZoneHandle for the unoptimized code so that it cannot be
       // disconnected from its function during the rest of compilation.
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2f9559b..cc02d9a 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2523,6 +2523,13 @@
         if (!CodePatcher::IsEntryPatched(code)) {
           CodePatcher::PatchEntry(code);
         }
+      } else if (!function.HasCode() && (code.GetEntryPatchPc() != 0)) {
+        // The code has already been disconnected, make it invalid. Do not
+        // bother with OSR compiled code that has no valid entry-patch.
+        ReportSwitchingCode(code);
+        if (!CodePatcher::IsEntryPatched(code)) {
+          CodePatcher::PatchEntry(code);
+        }
       }
     }
   }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 8667c20..c41e5c1 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -135,16 +135,12 @@
 void ParsedFunction::AddDeferredPrefix(const LibraryPrefix& prefix) {
   ASSERT(prefix.is_deferred_load());
   ASSERT(!prefix.is_loaded());
-  if (deferred_prefixes_ == NULL) {
-    deferred_prefixes_ =
-        &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New());
-  }
-  for (intptr_t i = 0; i < deferred_prefixes_->Length(); i++) {
-    if (deferred_prefixes_->At(i) == prefix.raw()) {
+  for (intptr_t i = 0; i < deferred_prefixes_->length(); i++) {
+    if ((*deferred_prefixes_)[i]->raw() == prefix.raw()) {
       return;
     }
   }
-  deferred_prefixes_->Add(prefix);
+  deferred_prefixes_->Add(&LibraryPrefix::ZoneHandle(I, prefix.raw()));
 }
 
 
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index f187032..15de41f 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -47,7 +47,7 @@
         saved_current_context_var_(NULL),
         saved_entry_context_var_(NULL),
         expression_temp_var_(NULL),
-        deferred_prefixes_(NULL),
+        deferred_prefixes_(new ZoneGrowableArray<const LibraryPrefix*>()),
         first_parameter_index_(0),
         first_stack_local_index_(0),
         num_copied_params_(0),
@@ -110,8 +110,10 @@
   static LocalVariable* CreateExpressionTempVar(intptr_t token_pos);
   LocalVariable* EnsureExpressionTemp();
 
-  bool HasDeferredPrefixes() const { return deferred_prefixes_ != NULL; }
-  GrowableObjectArray* DeferredPrefixes() const { return deferred_prefixes_; }
+  bool HasDeferredPrefixes() const { return deferred_prefixes_->length() != 0; }
+  ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const {
+    return deferred_prefixes_;
+  }
   void AddDeferredPrefix(const LibraryPrefix& prefix);
 
   int first_parameter_index() const { return first_parameter_index_; }
@@ -132,7 +134,7 @@
   LocalVariable* saved_current_context_var_;
   LocalVariable* saved_entry_context_var_;
   LocalVariable* expression_temp_var_;
-  GrowableObjectArray* deferred_prefixes_;
+  ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes_;
 
   int first_parameter_index_;
   int first_stack_local_index_;
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart
index e067fe3..79106ff 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart
@@ -292,6 +292,12 @@
       bailout('Used as key in Map');
     }
 
+    if (info.targetsIncludeNoSuchMethod &&
+        info.arguments != null &&
+        info.arguments.contains(currentUser)) {
+      bailout('Passed to noSuchMethod');
+    }
+
     Iterable<Element> inferredTargetTypes = info.targets.map((element) {
       return inferrer.types.getInferredTypeOf(element);
     });
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
index 355ca78..f8d4594 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -248,6 +248,19 @@
     });
   }
 
+  String getInferredSignatureOf(FunctionElement function) {
+    ElementTypeInformation info = getInferredTypeOf(function);
+    FunctionElement impl = function.implementation;
+    FunctionSignature signature = impl.functionSignature;
+    var res = "";
+    signature.forEachParameter((Element parameter) {
+      TypeInformation type = getInferredTypeOf(parameter);
+      res += "${res.isEmpty ? '(' : ', '}${type.type} ${parameter.name}";
+    });
+    res += ") -> ${info.type}";
+    return res;
+  }
+
   TypeInformation nonNullSubtype(ClassElement type) {
     return getConcreteTypeFor(new TypeMask.nonNullSubtype(type.declaration));
   }
@@ -640,6 +653,25 @@
               'at ${(info.type as MapTypeMask).allocationElement} '
               'after ${info.refineCount}');
       });
+      types.allocatedClosures.forEach((TypeInformation info) {
+        if (info is ElementTypeInformation) {
+          print('${types.getInferredSignatureOf(info.element)} for '
+                '${info.element}');
+        } else if (info is ClosureTypeInformation) {
+          print('${types.getInferredSignatureOf(info.element)} for '
+                '${info.element}');
+        } else if (info is DynamicCallSiteTypeInformation) {
+          for (Element target in info.targets) {
+            if (target is FunctionElement) {
+              print('${types.getInferredSignatureOf(target)} for ${target}');
+            } else {
+              print('${types.getInferredTypeOf(target).type} for ${target}');
+            }
+          }
+        } else {
+          print('${info.type} for some unknown kind of closure');
+        }
+      });
       analyzedElements.forEach((Element elem) {
         TypeInformation type = types.getInferredTypeOf(elem);
         print('${elem} :: ${type} from ${type.assignments} ');
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index 26dd4d1..ead1c4a 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -562,6 +562,14 @@
     }
   }
 
+  bool get targetsIncludeNoSuchMethod {
+    return targets.any((Element e) {
+      return e is FunctionElement &&
+             e.isInstanceMember &&
+             e.name == Compiler.NO_SUCH_METHOD;
+    });
+  }
+
   /**
    * We optimize certain operations on the [int] class because we know
    * more about their return type than the actual Dart code. For
diff --git a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
index 16697e9..b486a1c 100644
--- a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
@@ -183,15 +183,15 @@
     encodeVLQ(output, sourceUrlIndex - previousSourceUrlIndex);
     encodeVLQ(output, sourceLine - previousSourceLine);
     encodeVLQ(output, sourceColumn - previousSourceColumn);
-    updatePreviousSourceLocation(entry.sourceLocation);
 
-    if (sourceName == null) {
-      return;
+    if (sourceName != null) {
+      int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap);
+      encodeVLQ(output, sourceNameIndex - previousSourceNameIndex);
     }
 
-    int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap);
-    encodeVLQ(output, sourceNameIndex - previousSourceNameIndex);
-
+    // Update previous source location to ensure the next indices are relative
+    // to those if [entry.sourceLocation].
+    updatePreviousSourceLocation(entry.sourceLocation);
   }
 
   int indexOf(List<String> list, String value, Map<String, int> map) {
@@ -254,14 +254,14 @@
 
 class TokenSourceFileLocation extends SourceFileLocation {
   final Token token;
+  final String name;
 
-  TokenSourceFileLocation(SourceFile sourceFile, this.token)
+  TokenSourceFileLocation(SourceFile sourceFile, this.token, this.name)
     : super(sourceFile);
 
   int get offset => token.charOffset;
 
   String getSourceName() {
-    if (token.isIdentifier()) return token.value;
-    return null;
+    return name;
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 2b87a74..6f004fe 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -1052,14 +1052,7 @@
   }
 
   SourceFile currentSourceFile() {
-    Element element = sourceElement;
-    // TODO(johnniwinther): remove the 'element.patch' hack.
-    if (element is FunctionElement) {
-      FunctionElement functionElement = element;
-      if (functionElement.patch != null) element = functionElement.patch;
-    }
-    Script script = element.compilationUnit.script;
-    return script.file;
+    return sourceElement.implementation.compilationUnit.script.file;
   }
 
   void checkValidSourceFileLocation(
@@ -2307,7 +2300,7 @@
   SourceFileLocation sourceFileLocationForToken(ast.Node node, Token token) {
     SourceFile sourceFile = currentSourceFile();
     SourceFileLocation location =
-        new TokenSourceFileLocation(sourceFile, token);
+        new TokenSourceFileLocation(sourceFile, token, sourceElement.name);
     checkValidSourceFileLocation(location, sourceFile, token.charOffset);
     return location;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 8a9fd0f..30a0d9a9 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -19,6 +19,7 @@
     // TODO(sra): Attaching positions might be cleaner if the source position
     // was on a wrapping node.
     SourceFile sourceFile = sourceFileOfElement(element);
+    String name = element.name;
     AstElement implementation = element.implementation;
     ast.Node expression = implementation.node;
     Token beginToken;
@@ -34,21 +35,18 @@
     // checks below.
     var sourcePosition, endSourcePosition;
     if (beginToken.charOffset < sourceFile.length) {
-      sourcePosition = new TokenSourceFileLocation(sourceFile, beginToken);
+      sourcePosition =
+          new TokenSourceFileLocation(sourceFile, beginToken, name);
     }
     if (endToken.charOffset < sourceFile.length) {
-      endSourcePosition = new TokenSourceFileLocation(sourceFile, endToken);
+      endSourcePosition =
+          new TokenSourceFileLocation(sourceFile, endToken, name);
     }
     return node.withPosition(sourcePosition, endSourcePosition);
   }
 
   SourceFile sourceFileOfElement(Element element) {
-    // TODO(johnniwinther): remove the 'element.patch' hack.
-    FunctionElement functionElement = element.asFunctionElement();
-    if (functionElement != null && functionElement.patch != null) {
-      element = functionElement.patch;
-    }
-    return element.compilationUnit.script.file;
+    return element.implementation.compilationUnit.script.file;
   }
 
   js.Fun buildJavaScriptFunction(FunctionElement element,
diff --git a/tests/compiler/dart2js_extra/19191_test.dart b/tests/compiler/dart2js_extra/19191_test.dart
new file mode 100644
index 0000000..a5c4b56
--- /dev/null
+++ b/tests/compiler/dart2js_extra/19191_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2014, 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.
+
+// Regression test for http://dartbug.com/19191
+
+class A {
+  var method;
+  
+  noSuchMethod(Invocation invocation) {
+    if (invocation.isGetter) {
+      return method;
+    } else if (invocation.isSetter) {
+      method = invocation.positionalArguments[0];
+      return null;
+    } else if (invocation.isMethod) {
+      return Function.apply(method, invocation.positionalArguments,
+          invocation.namedArguments);
+    } else {
+      throw new NoSuchMethodError(this, invocation.memberName,
+          invocation.positionalArguments, invocation.namedArguments);
+    }
+  }
+  
+  init() {
+    closure_fails = (String str) {
+      return str.toUpperCase();
+    };
+  }
+  
+  run() {
+    print(closure_fails("Hello World"));
+  }
+}
+
+void main() {
+  var a = new A();
+  a.init();
+  a.run();
+}
+
diff --git a/tests/language/deferred_inlined_test.dart b/tests/language/deferred_inlined_test.dart
new file mode 100644
index 0000000..4808a3f
--- /dev/null
+++ b/tests/language/deferred_inlined_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2014, 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=--optimization-counter-threshold=10
+
+// Declares foo that returns 42.
+import "deferred_constraints_lib2.dart" deferred as lib;
+
+import 'package:expect/expect.dart';
+
+bool libLoaded = false;
+
+main() {
+  Expect.equals(88, heyhey());
+
+  // Trigger optimization of 'hehey' which inlines 'barbar'.
+  for (int i = 0; i < 30000; i++) {
+    heyhey();
+  }
+
+  lib.loadLibrary().then((_) {
+    libLoaded = true;
+    Expect.equals(42, heyhey());
+  });
+}
+
+
+// Inline bar in optimized code.
+heyhey() => barbar();
+
+
+barbar() {
+  if (libLoaded) {
+    // Returns 42.
+    return lib.foo();
+  }
+  return 88;
+}
\ No newline at end of file
diff --git a/tests/language/deferred_optimized_test.dart b/tests/language/deferred_optimized_test.dart
new file mode 100644
index 0000000..ef3c2a0
--- /dev/null
+++ b/tests/language/deferred_optimized_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2014, 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=--optimization-counter-threshold=10 --no-use-inlining
+
+// Declares foo that returns 42.
+import "deferred_constraints_lib2.dart" deferred as lib;
+
+import 'package:expect/expect.dart';
+
+bool libLoaded = false;
+
+main() {
+  Expect.equals(88, heyhey());
+
+  for (int i = 0; i < 30; i++) {
+    heyhey();
+  }
+
+  lib.loadLibrary().then((_) {
+    libLoaded = true;
+    Expect.equals(42, heyhey());
+  });
+}
+
+
+heyhey() => barbar();
+
+
+barbar() {
+  if (libLoaded) {
+    // Returns 42.
+    return lib.foo();
+  }
+  return 88;
+}
\ No newline at end of file
diff --git a/tools/VERSION b/tools/VERSION
index bbd311b..dbc0a4a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 5
 PATCH 0
 PRERELEASE 4
-PRERELEASE_PATCH 2
+PRERELEASE_PATCH 3