Version 1.1.0-dev.5.1

svn merge -c 31331 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31389 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31390 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31403 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31431 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31460 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31461 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31462 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31470 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31473 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 31474 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

R=kasperl@google.com

Review URL: https://codereview.chromium.org//125033003

git-svn-id: http://dart.googlecode.com/svn/trunk@31475 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 2567cbe..5d17d04 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -696,6 +696,10 @@
     struct sigaction act;
     bzero(&act, sizeof(act));
     act.sa_handler = SignalHandler;
+    sigemptyset(&act.sa_mask);
+    for (int i = 0; i < kSignalsCount; i++) {
+      sigaddset(&act.sa_mask, kSignals[i]);
+    }
     int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         sigaction(signal, &act, NULL));
     if (status < 0) {
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 7479064..175e36d 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -695,6 +695,10 @@
     struct sigaction act;
     bzero(&act, sizeof(act));
     act.sa_handler = SignalHandler;
+    sigemptyset(&act.sa_mask);
+    for (int i = 0; i < kSignalsCount; i++) {
+      sigaddset(&act.sa_mask, kSignals[i]);
+    }
     int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         sigaction(signal, &act, NULL));
     if (status < 0) {
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index ae0f37e..e369b21 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -739,6 +739,10 @@
     struct sigaction act;
     bzero(&act, sizeof(act));
     act.sa_handler = SignalHandler;
+    sigemptyset(&act.sa_mask);
+    for (int i = 0; i < kSignalsCount; i++) {
+      sigaddset(&act.sa_mask, kSignals[i]);
+    }
     int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         sigaction(signal, &act, NULL));
     if (status < 0) {
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index c6e88b6..f467d52 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -544,6 +544,7 @@
                                          callee_graph)) {
           function.set_is_inlinable(false);
           TRACE_INLINING(OS::Print("     Bailout: optional arg mismatch\n"));
+          isolate->set_long_jump_base(base);
           return false;
         }
       }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 72f93d8..9e74db6 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -743,7 +743,8 @@
                                              *(param[i].default_value));
       const Object* metadata = param[i].metadata;
       if ((metadata != NULL) && (*metadata).IsError()) {
-        return (*metadata).raw();  // Error evaluating the metadata.
+        isolate->set_long_jump_base(base);
+        return metadata->raw();  // Error evaluating the metadata.
       }
       param_descriptor.SetAt(j + kParameterMetadataOffset,
           (param[i].metadata == NULL) ? Object::null_instance() :
@@ -864,7 +865,10 @@
     Parser parser(script, lib, token_pos);
     parser.set_current_class(cls);
     parser.set_parsing_metadata(true);
-    return parser.EvaluateMetadata();
+
+    RawObject* metadata = parser.EvaluateMetadata();
+    isolate->set_long_jump_base(base);
+    return metadata;
   } else {
     Error& error = Error::Handle();
     error = isolate->object_store()->sticky_error();
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
index f55026a..c3a33a5 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
@@ -391,6 +391,8 @@
     // P.   Unmangled name (if reflectable).
     // P+1. First metadata (if reflectable).
     // ...
+    // TODO(ahe): Consider one of the parameter counts can be replaced by the
+    // length property of the JavaScript function object.
 
     List expressions = [];
 
@@ -421,14 +423,14 @@
         if (member.isInstanceMember()) {
           Set invokedSelectors =
               compiler.codegenWorld.invokedNames[member.name];
-          if (invokedSelectors != null && invokedSelectors.contains(selector)) {
+          //if (invokedSelectors != null && invokedSelectors.contains(selector)) {
             expressions.add(js.string(namer.invocationName(selector)));
-          } else {
-            // Don't add a stub for calling this as a regular instance method,
-            // we only need the "call" stub for implicit closures of this
-            // method.
-            expressions.add("null");
-          }
+          //} else {
+          //  // Don't add a stub for calling this as a regular instance method,
+          //  // we only need the "call" stub for implicit closures of this
+          //  // method.
+          //  expressions.add("null");
+          //}
         } else {
           // Static methods don't need "named" stubs as the default arguments
           // are inlined at call sites. But static methods might need "call"
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
index 1076afe..92b95c9 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
@@ -18,12 +18,21 @@
   Namer namer = backend.namer;
   Compiler compiler = backend.compiler;
   Element closureFromTearOff = compiler.findHelper('closureFromTearOff');
-  String tearOffAccess =
-      // Default value for mocked-up test libraries.
-      'function () { throw "Helper \'closureFromTearOff\' missing." }';
+  String tearOffAccess;
+  String tearOffGlobalObjectName;
+  String tearOffGlobalObject;
   if (closureFromTearOff != null) {
     tearOffAccess = namer.isolateAccess(closureFromTearOff);
+    tearOffGlobalObjectName = tearOffGlobalObject =
+        namer.globalObjectFor(closureFromTearOff);
+  } else {
+    // Default values for mocked-up test libraries.
+    tearOffAccess =
+        'function() { throw "Helper \'closureFromTearOff\' missing." }';
+    tearOffGlobalObjectName = 'MissingHelperFunction';
+    tearOffGlobalObject = '($tearOffAccess())';
   }
+
   String metadataField = '"${namer.metadataField}"';
   String reflectableField = namer.reflectableField;
 
@@ -83,11 +92,13 @@
     var optionalParameterInfo = ${readInt("array", "1")};
     var optionalParameterCount = optionalParameterInfo >> 1;
     var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
+    var isIntercepted =''' // Break long line.
+       ''' requiredParameterCount + optionalParameterCount != funcs[0].length;
     var functionTypeIndex = ${readFunctionType("array", "2")};
     var isReflectable =''' // Break long line.
     ''' array.length > requiredParameterCount + optionalParameterCount + 3;
     if (getterStubName) {
-      f = tearOff(funcs, array, isStatic, name);
+      f = tearOff(funcs, array, isStatic, name, isIntercepted);
 '''
       /* Used to create an isolate using spawnFunction.*/
 '''
@@ -129,15 +140,56 @@
 ''';
 
   String tearOff = '''
-  function tearOff(funcs, reflectionInfo, isStatic, name) {
-    return function() {
-      return $tearOffAccess(''' // Break long line.
-       '''this, funcs, reflectionInfo, isStatic, arguments, name);
-    }
+  function tearOffGetterNoCsp(funcs, reflectionInfo, name, isIntercepted) {
+    return isIntercepted
+        ? new Function("funcs", "reflectionInfo", "name",''' // Break long line.
+                   ''' "$tearOffGlobalObjectName", "c",
+            "return function tearOff_" + name + (functionCounter++)+ "(x) {" +
+              "if (c === null) c = $tearOffAccess(" +
+                  "this, funcs, reflectionInfo, false, [x], name);" +
+              "return new c(this, funcs[0], x, name);" +
+            "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null)
+        : new Function("funcs", "reflectionInfo", "name",''' // Break long line.
+                   ''' "$tearOffGlobalObjectName", "c",
+            "return function tearOff_" + name + (functionCounter++)+ "() {" +
+              "if (c === null) c = $tearOffAccess(" +
+                  "this, funcs, reflectionInfo, false, [], name);" +
+              "return new c(this, funcs[0], null, name);" +
+            "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null)
+  }
+  function tearOffGetterCsp(funcs, reflectionInfo, name, isIntercepted) {
+    var cache = null;
+    return isIntercepted
+        ? function(x) {
+            if (cache === null) cache = $tearOffAccess(''' // Break long line.
+             '''this, funcs, reflectionInfo, false, [x], name);
+            return new cache(this, funcs[0], x, name)
+          }
+        : function() {
+            if (cache === null) cache = $tearOffAccess(''' // Break long line.
+             '''this, funcs, reflectionInfo, false, [], name);
+            return new cache(this, funcs[0], null, name)
+          }
+  }
+  function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) {
+    var cache;
+    return isStatic
+        ? function() {
+            if (cache === void 0) cache = $tearOffAccess(''' // Break long line.
+             '''this, funcs, reflectionInfo, true, [], name).prototype;
+            return cache;
+          }
+        : tearOffGetter(funcs, reflectionInfo, name, isIntercepted);
   }
 ''';
 
+
+
+
   String init = '''
+  var functionCounter = 0;
+  var tearOffGetter = (typeof dart_precompiled == "function")
+      ? tearOffGetterCsp : tearOffGetterNoCsp;
   if (!init.libraries) init.libraries = [];
   if (!init.mangledNames) init.mangledNames = map();
   if (!init.mangledGlobalNames) init.mangledGlobalNames = map();
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 77d6903..6d233b5 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -3615,18 +3615,19 @@
           '"$name" does not handle closure with optional parameters',
           node: closure);
     }
-    visit(closure);
+
+    compiler.enqueuer.codegen.registerStaticUse(element);
+    push(new HForeign(backend.namer.elementAccess(element),
+                      backend.dynamicType,
+                      <HInstruction>[]));
     return params;
   }
 
   void handleForeignDartClosureToJs(Send node, String name) {
-    FunctionSignature params = handleForeignRawFunctionRef(node, name);
-    List<HInstruction> inputs = <HInstruction>[pop()];
-    String invocationName = backend.namer.invocationName(
-        new Selector.callClosure(params.requiredParameterCount));
-    push(new HForeign(js.js('#.$invocationName'),
-                      backend.dynamicType,
-                      inputs));
+    // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take
+    // care to wrap the closure in another closure that saves the current
+    // isolate.
+    handleForeignRawFunctionRef(node, name);
   }
 
   void handleForeignSetCurrentIsolate(Send node) {
diff --git a/sdk/lib/_internal/lib/foreign_helper.dart b/sdk/lib/_internal/lib/foreign_helper.dart
index 95b5907..5c2d64a 100644
--- a/sdk/lib/_internal/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/lib/foreign_helper.dart
@@ -128,6 +128,9 @@
 
 /**
  * Converts the Dart closure [function] into a JavaScript closure.
+ *
+ * Warning: This is no different from [RAW_DART_FUNCTION_REF] which means care
+ * must be taken to store the current isolate.
  */
 DART_CLOSURE_TO_JS(Function function) {}
 
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index ba5cf5b..bc490dd 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -5,29 +5,33 @@
 library _js_helper;
 
 import 'dart:collection';
-import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS,
-                                   JS,
-                                   JS_CALL_IN_ISOLATE,
-                                   JS_CONST,
-                                   JS_CURRENT_ISOLATE,
-                                   JS_CURRENT_ISOLATE_CONTEXT,
-                                   JS_DART_OBJECT_CONSTRUCTOR,
-                                   JS_FUNCTION_CLASS_NAME,
-                                   JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG,
-                                   JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
-                                   JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
-                                   JS_FUNCTION_TYPE_RETURN_TYPE_TAG,
-                                   JS_FUNCTION_TYPE_TAG,
-                                   JS_FUNCTION_TYPE_VOID_RETURN_TAG,
-                                   JS_GET_NAME,
-                                   JS_HAS_EQUALS,
-                                   JS_IS_INDEXABLE_FIELD_NAME,
-                                   JS_OBJECT_CLASS_NAME,
-                                   JS_NULL_CLASS_NAME,
-                                   JS_OPERATOR_AS_PREFIX,
-                                   JS_OPERATOR_IS_PREFIX,
-                                   JS_SIGNATURE_NAME,
-                                   RAW_DART_FUNCTION_REF;
+
+import 'dart:_foreign_helper' show
+    DART_CLOSURE_TO_JS,
+    JS,
+    JS_CALL_IN_ISOLATE,
+    JS_CONST,
+    JS_CURRENT_ISOLATE,
+    JS_CURRENT_ISOLATE_CONTEXT,
+    JS_DART_OBJECT_CONSTRUCTOR,
+    JS_EFFECT,
+    JS_FUNCTION_CLASS_NAME,
+    JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG,
+    JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
+    JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
+    JS_FUNCTION_TYPE_RETURN_TYPE_TAG,
+    JS_FUNCTION_TYPE_TAG,
+    JS_FUNCTION_TYPE_VOID_RETURN_TAG,
+    JS_GET_NAME,
+    JS_HAS_EQUALS,
+    JS_IS_INDEXABLE_FIELD_NAME,
+    JS_NULL_CLASS_NAME,
+    JS_OBJECT_CLASS_NAME,
+    JS_OPERATOR_AS_PREFIX,
+    JS_OPERATOR_IS_PREFIX,
+    JS_SIGNATURE_NAME,
+    RAW_DART_FUNCTION_REF;
+
 import 'dart:_interceptors';
 import 'dart:_collection-dev' as _symbol_dev;
 import 'dart:_collection-dev' show MappedIterable;
@@ -1741,10 +1745,21 @@
   static const OPTIONAL_PARAMETER_INDEX = 4;
   static const DEFAULT_ARGUMENTS_INDEX = 5;
 
+  /**
+   * Global counter to prevent reusing function code objects.
+   *
+   * V8 will share the underlying function code objects when the same string is
+   * passed to "new Function".  Shared function code objects can lead to
+   * sub-optimal performance due to polymorhism, and can be prevented by
+   * ensuring the strings are different.
+   */
+  static int functionCounter = 0;
+
   Closure();
 
   /**
-   * Creates a closure for use by implicit getters associated with a method.
+   * Creates a new closure class for use by implicit getters associated with a
+   * method.
    *
    * In other words, creates a tear-off closure.
    *
@@ -1762,46 +1777,83 @@
    * Caution: this function may be called when building constants.
    * TODO(ahe): Don't call this function when building constants.
    */
-  factory Closure.fromTearOff(receiver,
-                              List functions,
-                              List reflectionInfo,
-                              bool isStatic,
-                              jsArguments,
-                              String propertyName) {
+  static fromTearOff(receiver,
+                     List functions,
+                     List reflectionInfo,
+                     bool isStatic,
+                     jsArguments,
+                     String propertyName) {
+    JS_EFFECT(() {
+      BoundClosure.receiverOf(JS('BoundClosure', 'void 0'));
+      BoundClosure.selfOf(JS('BoundClosure', 'void 0'));
+    });
     // TODO(ahe): All the place below using \$ should be rewritten to go
     // through the namer.
     var function = JS('', '#[#]', functions, 0);
-    // TODO(ahe): Try fetching the property directly instead of using "in".
-    if (isStatic && JS('bool', '"\$tearOff" in #', function)) {
-      // The implicit closure of a static function is always the same.
-      return JS('Closure', '#.\$tearOff', function);
-    }
-
     String name = JS('String|Null', '#.\$stubName', function);
     String callName = JS('String|Null', '#.\$callName', function);
 
-    JS('', r'#.$reflectionInfo = #', function, reflectionInfo);
+    JS('', '#.\$reflectionInfo = #', function, reflectionInfo);
     ReflectionInfo info = new ReflectionInfo(function);
 
     var functionType = info.functionType;
 
+    // function tmp() {};
+    // tmp.prototype = BC.prototype;
+    // var proto = new tmp;
+    // for each computed prototype property:
+    //   proto[property] = ...;
+    // proto._init = BC;
+    // var dynClosureConstructor =
+    //     new Function('self', 'target', 'receiver', 'name',
+    //                  'this._init(self, target, receiver, name)');
+    // proto.constructor = dynClosureConstructor; // Necessary?
+    // dynClosureConstructor.prototype = proto;
+    // return dynClosureConstructor;
+
+    // We need to create a new subclass of either TearOffClosure or
+    // BoundClosure.  For this, we need to create an object whose prototype is
+    // the prototype is either TearOffClosure.prototype or
+    // BoundClosure.prototype, respectively in pseudo JavaScript code. The
+    // simplest way to access the JavaScript construction function of a Dart
+    // class is to create an instance and access its constructor property.  The
+    // newly created instance could in theory be used directly as the
+    // prototype, but it might include additional fields that we don't need.
+    // So we only use the new instance to access the constructor property and
+    // use Object.create to create the desired prototype.
+    var prototype = isStatic
+        // TODO(ahe): Safe to use Object.create?
+        ? JS('TearOffClosure', 'Object.create(#.constructor.prototype)',
+             new TearOffClosure())
+        : JS('BoundClosure', 'Object.create(#.constructor.prototype)',
+             new BoundClosure(null, null, null, null));
+
+    JS('', '#.\$initialize = #', prototype, JS('', '#.constructor', prototype));
+    var constructor = isStatic
+        ? JS('', 'function(){this.\$initialize()}')
+        : isCsp
+            ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}')
+            : JS('',
+                 'new Function("a","b","c","d",'
+                     '"this.\$initialize(a,b,c,d);"+#)',
+                 functionCounter++);
+
+    // TODO(ahe): Is it necessary to set the constructor property?
+    JS('', '#.constructor = #', prototype, constructor);
+
+    JS('', '#.prototype = #', constructor, prototype);
+
     // Create a closure and "monkey" patch it with call stubs.
-    Closure closure;
     var trampoline = function;
+    var isIntercepted = false;
     if (!isStatic) {
       if (JS('bool', '#.length == 1', jsArguments)) {
         // Intercepted call.
-        var argument = JS('', '#[0]', jsArguments);
-        trampoline = forwardInterceptedCallTo(argument, receiver, function);
-        closure = new BoundClosure(receiver, function, argument, name);
-      } else {
-        trampoline = forwardTo(receiver, function);
-        closure = new BoundClosure(receiver, function, null, name);
+        isIntercepted = true;
       }
+      trampoline = forwardCallTo(function, isIntercepted);
     } else {
-      closure = new TearOffClosure();
-      JS('', '#.\$tearOff = #', function, closure);
-      JS('', r'#.$name = #', closure, propertyName);
+      JS('', '#.\$name = #', prototype, propertyName);
     }
 
     var signatureFunction;
@@ -1811,54 +1863,241 @@
              functionType);
     } else if (!isStatic
                && JS('bool', 'typeof # == "function"', functionType)) {
-      signatureFunction = functionType;
-      JS('', r'#.$receiver = #', closure, receiver);
+      var getReceiver = isIntercepted
+          ? RAW_DART_FUNCTION_REF(BoundClosure.receiverOf)
+          : RAW_DART_FUNCTION_REF(BoundClosure.selfOf);
+      signatureFunction = JS(
+        '',
+        'function(f,r){'
+          'return function(){'
+            'return f.apply({\$receiver:r(this)},arguments)'
+          '}'
+        '}(#,#)', functionType, getReceiver);
     } else {
       throw 'Error in reflectionInfo.';
     }
 
-    JS('', '#.\$signature = #', closure, signatureFunction);
+    JS('', '#.\$signature = #', prototype, signatureFunction);
 
-    JS('', '#[#] = #', closure, callName, trampoline);
+    JS('', '#[#] = #', prototype, callName, trampoline);
     for (int i = 1; i < functions.length; i++) {
       var stub = functions[i];
       var stubCallName = JS('String|Null', '#.\$callName', stub);
-      // TODO(ahe): Support interceptors here.
-      JS('', '#[#] = #', closure, stubCallName,
-         isStatic ? stub : forwardTo(receiver, stub));
+      if (stubCallName != null) {
+        JS('', '#[#] = #', prototype, stubCallName,
+           isStatic ? stub : forwardCallTo(stub, isIntercepted));
+      }
     }
 
-    JS('', '#["call*"] = #', closure, function);
+    JS('', '#["call*"] = #', prototype, function);
 
-    return closure;
+    return constructor;
   }
 
-  static forwardTo(receiver, function) {
-    return JS(
-        '',
-        'function(r,f){return function(){return f.apply(r,arguments)}}(#,#)',
-        receiver, function);
+  static cspForwardCall(int arity, function) {
+    var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf);
+    switch (arity) {
+    case 0:
+      return JS(
+          '',
+          'function(F,S){'
+            'return function(){'
+              'return F.call(S(this))'
+            '}'
+          '}(#,#)', function, getSelf);
+    case 1:
+      return JS(
+          '',
+          'function(F,S){'
+            'return function(a){'
+              'return F.call(S(this),a)'
+            '}'
+          '}(#,#)', function, getSelf);
+    case 2:
+      return JS(
+          '',
+          'function(F,S){'
+            'return function(a,b){'
+              'return F.call(S(this),a,b)'
+            '}'
+          '}(#,#)', function, getSelf);
+    case 3:
+      return JS(
+          '',
+          'function(F,S){'
+            'return function(a,b,c){'
+              'return F.call(S(this),a,b,c)'
+            '}'
+          '}(#,#)', function, getSelf);
+    case 4:
+      return JS(
+          '',
+          'function(F,S){'
+            'return function(a,b,c,d){'
+              'return F.call(S(this),a,b,c,d)'
+            '}'
+          '}(#,#)', function, getSelf);
+    case 5:
+      return JS(
+          '',
+          'function(F,S){'
+            'return function(a,b,c,d,e){'
+              'return F.call(S(this),a,b,c,d,e)'
+            '}'
+          '}(#,#)', function, getSelf);
+    default:
+      return JS(
+          '',
+          'function(f,s){'
+            'return function(){'
+              'return f.apply(s(this),arguments)'
+            '}'
+          '}(#,#)', function, getSelf);
+    }
   }
 
-  static forwardInterceptedCallTo(self, interceptor, function) {
-    return JS(
-        '',
-        'function(i,s,f){return function(){'
-        'return f.call.bind(f,i,s).apply(i,arguments)}}(#,#,#)',
-        interceptor, self, function);
+  static bool get isCsp => JS('bool', 'typeof dart_precompiled == "function"');
+
+  static forwardCallTo(function, bool isIntercepted) {
+    if (isIntercepted) return forwardInterceptedCallTo(function);
+    int arity = JS('int', '#.length', function);
+    if (isCsp) {
+      return cspForwardCall(arity, function);
+    } else if (arity == 0) {
+      return JS(
+          '',
+          '(new Function("F",#))(#)',
+          'return function(){'
+            'return F.call(this.${BoundClosure.selfFieldName()});${functionCounter++}'
+          '}',
+          function);
+    } else if (1 <= arity && arity < 27) {
+      String arguments = JS(
+          'String',
+          '"abcdefghijklmnopqrstuvwxyz".split("").splice(0,#).join(",")',
+          arity);
+      return JS(
+          '',
+          '(new Function("F",#))(#)',
+          'return function($arguments){'
+            'return F.call(this.${BoundClosure.selfFieldName()},$arguments);'
+            '${functionCounter++}'
+          '}',
+          function);
+    } else {
+      return cspForwardCall(arity, function);
+    }
+  }
+
+  static cspForwardInterceptedCall(int arity, String name, function) {
+    var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf);
+    var getReceiver = RAW_DART_FUNCTION_REF(BoundClosure.receiverOf);
+    switch (arity) {
+    case 0:
+      // Intercepted functions always takes at least one argument (the
+      // receiver).
+      throw new RuntimeError('Intercepted function with no arguments.');
+    case 1:
+      return JS(
+          '',
+          'function(n,s,r){'
+            'return function(){'
+              'return s(this)[n](r(this))'
+            '}'
+          '}(#,#,#)', name, getSelf, getReceiver);
+    case 2:
+      return JS(
+          '',
+          'function(n,s,r){'
+            'return function(a){'
+              'return s(this)[n](r(this),a)'
+            '}'
+          '}(#,#,#)', name, getSelf, getReceiver);
+    case 3:
+      return JS(
+          '',
+          'function(n,s,r){'
+            'return function(a,b){'
+              'return s(this)[n](r(this),a,b)'
+            '}'
+          '}(#,#,#)', name, getSelf, getReceiver);
+    case 4:
+      return JS(
+          '',
+          'function(n,s,r){'
+            'return function(a,b,c){'
+              'return s(this)[n](r(this),a,b,c)'
+            '}'
+          '}(#,#,#)', name, getSelf, getReceiver);
+    case 5:
+      return JS(
+          '',
+          'function(n,s,r){'
+            'return function(a,b,c,d){'
+              'return s(this)[n](r(this),a,b,c,d)'
+            '}'
+          '}(#,#,#)', name, getSelf, getReceiver);
+    case 6:
+      return JS(
+          '',
+          'function(n,s,r){'
+            'return function(a,b,c,d,e){'
+              'return s(this)[n](r(this),a,b,c,d,e)'
+            '}'
+          '}(#,#,#)', name, getSelf, getReceiver);
+    default:
+      return JS(
+          '',
+          'function(f,s,r,a){'
+            'return function(){'
+              'a=[r(this)];'
+              'Array.prototype.push.apply(a,arguments);'
+              'return f.apply(s(this),a)'
+            '}'
+          '}(#,#,#)', function, getSelf, getReceiver);
+    }
+  }
+
+  static forwardInterceptedCallTo(function) {
+    String stubName = JS('String|Null', '#.\$stubName', function);
+    int arity = JS('int', '#.length', function);
+    bool isCsp = JS('bool', 'typeof dart_precompiled == "function"');
+    if (isCsp) {
+      return cspForwardInterceptedCall(arity, stubName, function);
+    } else if (arity == 1) {
+      return JS('', 'new Function(#)',
+                'return this.${BoundClosure.selfFieldName()}.$stubName('
+                    'this.${BoundClosure.receiverFieldName()});'
+                '${functionCounter++}');
+    } else if (1 < arity && arity < 28) {
+      String arguments = JS(
+          'String',
+          '"abcdefghijklmnopqrstuvwxyz".split("").splice(0,#).join(",")',
+          arity - 1);
+      return JS(
+          '',
+          '(new Function(#))()',
+          'return function($arguments){'
+            'return this.${BoundClosure.selfFieldName()}.$stubName('
+                'this.${BoundClosure.receiverFieldName()},$arguments);'
+            '${functionCounter++}'
+          '}');
+    } else {
+      return cspForwardInterceptedCall(arity, stubName, function);
+    }
   }
 
   String toString() => "Closure";
 }
 
 /// Called from implicit method getter (aka tear-off).
-Closure closureFromTearOff(receiver,
-                           functions,
-                           reflectionInfo,
-                           isStatic,
-                           jsArguments,
-                           name) {
-  return new Closure.fromTearOff(
+closureFromTearOff(receiver,
+                   functions,
+                   reflectionInfo,
+                   isStatic,
+                   jsArguments,
+                   name) {
+  return Closure.fromTearOff(
       receiver,
       JSArray.markFixedList(functions),
       JSArray.markFixedList(reflectionInfo),
@@ -1917,13 +2156,46 @@
     return receiverHashCode ^ Primitives.objectHashCode(_target);
   }
 
+  @NoInline
   static selfOf(BoundClosure closure) => closure._self;
 
   static targetOf(BoundClosure closure) => closure._target;
 
+  @NoInline
   static receiverOf(BoundClosure closure) => closure._receiver;
 
   static nameOf(BoundClosure closure) => closure._name;
+
+  static String selfFieldNameCache;
+
+  static String selfFieldName() {
+    if (selfFieldNameCache == null) {
+      selfFieldNameCache = computeFieldNamed('self');
+    }
+    return selfFieldNameCache;
+  }
+
+  static String receiverFieldNameCache;
+
+  static String receiverFieldName() {
+    if (receiverFieldNameCache == null) {
+      receiverFieldNameCache = computeFieldNamed('receiver');
+    }
+    return receiverFieldNameCache;
+  }
+
+  @NoInline() @NoSideEffects()
+  static String computeFieldNamed(String fieldName) {
+    var template = new BoundClosure('self', 'target', 'receiver', 'name');
+    var names = JSArray.markFixedList(
+        JS('', 'Object.getOwnPropertyNames(#)', template));
+    for (int i = 0; i < names.length; i++) {
+      var name = names[i];
+      if (JS('bool', '#[#] === #', template, name, fieldName)) {
+        return JS('String', '#', name);
+      }
+    }
+  }
 }
 
 bool jsHasOwnProperty(var jsObject, String property) {
diff --git a/sdk/lib/_internal/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
index ca1d2d1..f389abb 100644
--- a/sdk/lib/_internal/lib/js_rti.dart
+++ b/sdk/lib/_internal/lib/js_rti.dart
@@ -523,21 +523,18 @@
   assert(isJsObject(s));
   assert(isJsObject(t));
 
-  return JS('bool', r'''
-     function (t, s, isAssignable) {
-       for (var $name in t) {
-         if (!s.hasOwnProperty($name)) {
-           return false;
-         }
-         var tType = t[$name];
-         var sType = s[$name];
-         if (!isAssignable.call$2(sType, tType)) {
-          return false;
-         }
-       }
-       return true;
-     }(#, #, #)
-  ''', t, s, RAW_DART_FUNCTION_REF(isAssignable));
+  List names =
+      JSArray.markFixedList(JS('', 'Object.getOwnPropertyNames(#)', t));
+  for (int i = 0; i < names.length; i++) {
+    var name = names[i];
+    if (JS('bool', '!Object.hasOwnProperty.call(#, #)', s, name)) {
+      return false;
+    }
+    var tType = JS('', '#[#]', t, name);
+    var sType = JS('', '#[#]', s, name);
+    if (!isAssignable(tType, sType)) return false;
+  }
+  return true;
 }
 
 bool isFunctionSubtype(var s, var t) {
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 536de09..b1003d9 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -544,7 +544,14 @@
 
 Object _getDartProxy(o, String propertyName, createProxy(o)) {
   var dartProxy = JS('', '#[#]', o, propertyName);
-  if (dartProxy == null) {
+  // Temporary fix for dartbug.com/15193
+  // In some cases it's possible to see a JavaScript object that
+  // came from a different context and was previously proxied to
+  // Dart in that context. The JS object will have a cached proxy
+  // but it won't be a valid Dart object in this context.
+  // For now we throw away the cached proxy, but we should be able
+  // to cache proxies from multiple JS contexts and Dart isolates.
+  if (dartProxy == null || !_isLocalObject(o)) {
     dartProxy = createProxy(o);
     _defineProperty(o, propertyName, dartProxy);
   }
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 9415463..e0193c3 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -58,7 +58,7 @@
     // 2. Some code was refactored, and there are more methods.
     // Either situation could be problematic, but in situation 2, it is often
     // acceptable to increase [expectedMethodCount] a little.
-    int expectedMethodCount = 352;
+    int expectedMethodCount = 363;
     Expect.isTrue(
         generatedCode.length <= expectedMethodCount,
         'Too many compiled methods: '
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 499d474..c8bc459d 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -6,7 +6,6 @@
 *: Skip
 
 [ $compiler == dart2js ]
-bound_closure_test: Fail
 call_on_native_class_test: CompileTimeError # Issue 14813
 native_no_such_method_exception4_frog_test: Fail  # Issue 9631
 native_no_such_method_exception5_frog_test: Fail  # Issue 9631
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 1762ceb..7679ca1 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -89,6 +89,7 @@
 [ $runtime == safari ]
 typed_data/setRange_2_test: Fail # Safari doesn't fully implement spec for TypedArray.set
 typed_data/setRange_3_test: Fail # Safari doesn't fully implement spec for TypedArray.set
+mirrors/to_string_test: Fail # Safari bug TODO(ahe): Add bug number if able to submit bug.
 
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
 typed_data/setRange_2_test: RuntimeError # TODO(dart2js-team): Please triage this failure.
@@ -141,6 +142,7 @@
 
 [ $compiler == dart2js && $checked ]
 convert/utf85_test: Pass, Slow # Issue 12029.
+async/stream_transform_test: Fail # https://code.google.com/p/v8/issues/detail?id=3084
 
 [ $compiler == dart2js ]
 convert/chunked_conversion_utf88_test: Slow, Pass
@@ -199,6 +201,7 @@
 typed_data/setRange_1_test: Fail # Issue 15413
 typed_data/setRange_2_test: Fail # Issue 15413
 typed_data/setRange_3_test: Fail # Issue 15413
+mirrors/syntax_error_test/01: Fail # Issue 15886
 
 [ $compiler == none  ]
 mirrors/hierarchy_test: Fail # TODO(ahe): This test is slightly broken. http://dartbug.com/12464
diff --git a/tests/lib/mirrors/syntax_error_test.dart b/tests/lib/mirrors/syntax_error_test.dart
new file mode 100644
index 0000000..8888ce5
--- /dev/null
+++ b/tests/lib/mirrors/syntax_error_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+// Regression test for Issue 15744
+// Also, tests that syntax errors in reflected classes are reported correctly.
+
+import 'dart:mirrors';
+
+class MD {
+  final String name;
+  const MD({this.name});
+}
+
+@MD(name:'A')
+class A {}
+
+@MD(name:'B')
+class B {
+  static x = { 0: 0; };  /// 01: compile-time error
+}
+
+main() {
+  reflectClass(A).metadata;
+  reflectClass(B).newInstance(const Symbol(''), []);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 64ffd99..d775a81 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 1
 PATCH 0
 PRERELEASE 5
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1