Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart | 
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart | 
| index 054170945afacdfc5180699b48f3b581c57e2bfa..60bb2adbed4f60cf0403efa1466817b36b487f8e 100644 | 
| --- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart | 
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart | 
| @@ -275,6 +275,8 @@ class LocalsHandler { | 
| // classes, or the same as [:this:] for non-intercepted classes. | 
| ClassElement cls = element.getEnclosingClass(); | 
| JavaScriptBackend backend = compiler.backend; | 
| + bool isNativeUpgradeFactory = element.isGenerativeConstructor() | 
| 
 
ngeoffray
2013/10/17 09:08:59
What is a native upgrade factory?
 
sra1
2013/10/18 04:09:32
Added comment
 
 | 
| + && Elements.isNativeOrExtendsNative(cls); | 
| if (backend.isInterceptedMethod(element)) { | 
| bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); | 
| SourceString name = isInterceptorClass | 
| @@ -291,6 +293,14 @@ class LocalsHandler { | 
| directLocals[closureData.thisElement] = value; | 
| } | 
| value.instructionType = builder.getTypeOfThis(); | 
| + } else if (isNativeUpgradeFactory) { | 
| + bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); | 
| + Element parameter = new InterceptedElement( | 
| + cls.computeType(compiler), const SourceString('receiver'), element); | 
| + HParameterValue value = new HParameterValue(parameter); | 
| + builder.graph.explicitReceiverParameter = value; | 
| + builder.graph.entry.addAtEntry(value); | 
| + value.instructionType = builder.getTypeOfThis(); | 
| 
 
ngeoffray
2013/10/17 09:08:59
This seems very similar to the code line 281 to 29
 
sra1
2013/10/18 04:09:32
In the fixed version there are more differences, e
 
 | 
| } | 
| } | 
| @@ -1267,6 +1277,13 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| } | 
| } | 
| + // Generative constructors of native classes should not be called directly | 
| + // and have an extra argument that causes problems with inlining. | 
| + if (element.isGenerativeConstructor() | 
| + && Elements.isNativeOrExtendsNative(element.getEnclosingClass())) { | 
| + return false; | 
| + } | 
| + | 
| // A generative constructor body is not seen by global analysis, | 
| // so we should not query for its type. | 
| if (!element.isGenerativeConstructorBody()) { | 
| @@ -1586,9 +1603,13 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| TreeElements definitions = compiler.analyzeElement(member); | 
| Node node = member.parseNode(compiler); | 
| SendSet assignment = node.asSendSet(); | 
| - HInstruction value; | 
| if (assignment == null) { | 
| - value = graph.addConstantNull(compiler); | 
| + // Unassigned fields of native classes are not initialized to | 
| + // prevent overwriting pre-initialized native properties. | 
| + if (!Elements.isNativeOrExtendsNative(classElement)) { | 
| + HInstruction value = graph.addConstantNull(compiler); | 
| 
 
ngeoffray
2013/10/17 09:08:59
Avoid the temporary?
 
sra1
2013/10/18 04:09:32
Done.
 
 | 
| + fieldValues[member] = value; | 
| + } | 
| } else { | 
| Node right = assignment.arguments.head; | 
| TreeElements savedElements = elements; | 
| @@ -1599,9 +1620,9 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| member, node, elements); | 
| inlinedFrom(member, () => right.accept(this)); | 
| elements = savedElements; | 
| - value = pop(); | 
| + HInstruction value = pop(); | 
| + fieldValues[member] = value; | 
| 
 
ngeoffray
2013/10/17 09:08:59
Avoid the temporary?
 
sra1
2013/10/18 04:09:32
Done.
 
 | 
| } | 
| - fieldValues[member] = value; | 
| }); | 
| }); | 
| } | 
| @@ -1619,6 +1640,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| functionElement = functionElement.implementation; | 
| ClassElement classElement = | 
| functionElement.getEnclosingClass().implementation; | 
| + bool isNativeUpgradeFactory = | 
| + Elements.isNativeOrExtendsNative(classElement); | 
| FunctionExpression function = functionElement.parseNode(compiler); | 
| // Note that constructors (like any other static function) do not need | 
| // to deal with optional arguments. It is the callers job to provide all | 
| @@ -1654,10 +1677,20 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| // Call the JavaScript constructor with the fields as argument. | 
| List<HInstruction> constructorArguments = <HInstruction>[]; | 
| + List<Element> fields = <Element>[]; | 
| + | 
| classElement.forEachInstanceField( | 
| (ClassElement enclosingClass, Element member) { | 
| - constructorArguments.add(potentiallyCheckType( | 
| - fieldValues[member], member.computeType(compiler))); | 
| + HInstruction value = fieldValues[member]; | 
| + if (value == null) { | 
| + // Uninitialized native fields are pre-initialized by the native | 
| + // implementation. | 
| + assert(isNativeUpgradeFactory); | 
| + } else { | 
| + fields.add(member); | 
| + constructorArguments.add( | 
| + potentiallyCheckType(value, member.computeType(compiler))); | 
| + } | 
| }, | 
| includeSuperAndInjectedMembers: true); | 
| @@ -1668,11 +1701,25 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| if (!currentInlinedInstantiations.isEmpty) { | 
| instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); | 
| } | 
| - HForeignNew newObject = new HForeignNew(classElement, | 
| - ssaType, | 
| - constructorArguments, | 
| - instantiatedTypes); | 
| - add(newObject); | 
| + | 
| + HInstruction newObject; | 
| + if (!isNativeUpgradeFactory) { | 
| + newObject = new HForeignNew(classElement, | 
| + ssaType, | 
| + constructorArguments, | 
| + instantiatedTypes); | 
| + add(newObject); | 
| + } else { | 
| + // Bulk assign to the initialized fields. | 
| + newObject = graph.explicitReceiverParameter; | 
| + // Null guard ensures an error if we are being called from an explicit | 
| + // 'new' of the constructor instead of via an upgrade. It is optimized out | 
| + // if there are field initializers. | 
| + add(new HFieldGet(null, newObject, isAssignable: false)); | 
| + for (int i = 0; i < fields.length; i++) { | 
| + add(new HFieldSet(fields[i], newObject, constructorArguments[i])); | 
| + } | 
| + } | 
| removeInlinedInstantiation(type); | 
| // Create the runtime type information, if needed. | 
| if (backend.classNeedsRti(classElement)) { | 
| @@ -1684,12 +1731,22 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| } | 
| // Generate calls to the constructor bodies. | 
| + HInstruction interceptor = null; | 
| for (int index = constructors.length - 1; index >= 0; index--) { | 
| FunctionElement constructor = constructors[index]; | 
| assert(invariant(functionElement, constructor.isImplementation)); | 
| ConstructorBodyElement body = getConstructorBody(constructor); | 
| if (body == null) continue; | 
| + | 
| List bodyCallInputs = <HInstruction>[]; | 
| + if (isNativeUpgradeFactory) { | 
| + if (interceptor == null) { | 
| + Constant constant = new InterceptorConstant( | 
| + classElement.computeType(compiler)); | 
| + interceptor = graph.addConstant(constant, compiler); | 
| + } | 
| + bodyCallInputs.add(interceptor); | 
| + } | 
| bodyCallInputs.add(newObject); | 
| TreeElements elements = | 
| compiler.enqueuer.resolution.getCachedElements(constructor); | 
| @@ -1697,7 +1754,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| ClosureClassMap parameterClosureData = | 
| compiler.closureToClassMapper.getMappingForNestedFunction(node); | 
| - | 
| FunctionSignature functionSignature = body.computeSignature(compiler); | 
| // Provide the parameters to the generative constructor body. | 
| functionSignature.orderedForEachParameter((parameter) { | 
| @@ -1724,7 +1780,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); | 
| } | 
| - if (tryInlineMethod(body, null, bodyCallInputs, function)) { | 
| + if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. | 
| + tryInlineMethod(body, null, bodyCallInputs, function)) { | 
| pop(); | 
| } else { | 
| HInvokeConstructorBody invoke = | 
| @@ -3565,6 +3622,11 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { | 
| } | 
| var inputs = <HInstruction>[]; | 
| + if (constructor.isGenerativeConstructor() && | 
| + Elements.isNativeOrExtendsNative(constructor.getEnclosingClass())) { | 
| + // Native class generative constructors take a pre-constructed object. | 
| + inputs.add(graph.addConstantNull(compiler)); | 
| + } | 
| // TODO(5347): Try to avoid the need for calling [implementation] before | 
| // calling [addStaticSendArgumentsToList]. | 
| bool succeeded = addStaticSendArgumentsToList(selector, send.arguments, |