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, |