| Index: pkg/compiler/lib/src/ssa/codegen.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
|
| index ea200c3cb337ce2af6834488c480f7351e302bed..16b093681ef285a7cfba119a3ae62760512f64d9 100644
|
| --- a/pkg/compiler/lib/src/ssa/codegen.dart
|
| +++ b/pkg/compiler/lib/src/ssa/codegen.dart
|
| @@ -1624,16 +1624,42 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| Element element = node.element;
|
| List<DartType> instantiatedTypes = node.instantiatedTypes;
|
|
|
| - registry.registerStaticInvocation(element);
|
| -
|
| if (instantiatedTypes != null && !instantiatedTypes.isEmpty) {
|
| instantiatedTypes.forEach((type) {
|
| registry.registerInstantiatedType(type);
|
| });
|
| }
|
|
|
| - push(backend.emitter.staticFunctionAccess(node.element));
|
| - push(new js.Call(pop(), visitArguments(node.inputs, start: 0)), node);
|
| + List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
|
| +
|
| + if (element == backend.getCheckConcurrentModificationError()) {
|
| + // Manually inline the [checkConcurrentModificationError] function. This
|
| + // function is only called from a for-loop update. Ideally we would just
|
| + // generate the conditionalcontrol flow in the builder but it adds basic
|
| + // blocks in the loop update that interfere with other optimizations and
|
| + // confuses loop recognition.
|
| +
|
| + assert(arguments.length == 2);
|
| + Element throwFunction = backend.getThrowConcurrentModificationError();
|
| + registry.registerStaticInvocation(throwFunction);
|
| +
|
| + // Calling using `(0, #)(#)` instead of `#(#)` separates the property load
|
| + // of the static function access from the call. For some reason this
|
| + // helps V8 see that the call never happens so V8 makes the call a
|
| + // deoptimization. This removes the call from the optimized loop, making
|
| + // more optimizations available to the loop. This form is 50% faster on
|
| + // some small loop, almost as fast as loops with no concurrent
|
| + // modification check.
|
| + push(js.js('# || (0, #)(#)',[
|
| + arguments[0],
|
| + backend.emitter.staticFunctionAccess(throwFunction),
|
| + arguments[1]]));
|
| + } else {
|
| + registry.registerStaticInvocation(element);
|
| + push(backend.emitter.staticFunctionAccess(element));
|
| + push(new js.Call(pop(), arguments), node);
|
| + }
|
| +
|
| }
|
|
|
| visitInvokeSuper(HInvokeSuper node) {
|
|
|