| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 // [readLocal] uses the [boxElement] to find its box. By replacing it | 241 // [readLocal] uses the [boxElement] to find its box. By replacing it |
| 242 // behind its back we can still get to the old values. | 242 // behind its back we can still get to the old values. |
| 243 updateLocal(boxElement, oldBox); | 243 updateLocal(boxElement, oldBox); |
| 244 HInstruction oldValue = readLocal(boxedVariable); | 244 HInstruction oldValue = readLocal(boxedVariable); |
| 245 updateLocal(boxElement, newBox); | 245 updateLocal(boxElement, newBox); |
| 246 updateLocal(boxedVariable, oldValue); | 246 updateLocal(boxedVariable, oldValue); |
| 247 } | 247 } |
| 248 updateLocal(boxElement, newBox); | 248 updateLocal(boxElement, newBox); |
| 249 } | 249 } |
| 250 | 250 |
| 251 HType cachedTypeOfThis; |
| 252 |
| 253 HType computeTypeOfThis() { |
| 254 Element element = closureData.thisElement; |
| 255 ClassElement cls = element.enclosingElement.getEnclosingClass(); |
| 256 Compiler compiler = builder.compiler; |
| 257 DartType type = cls.computeType(compiler); |
| 258 if (compiler.world.isUsedAsMixin(cls)) { |
| 259 // If the enclosing class is used as a mixin, [:this:] can be |
| 260 // of the class that mixins the enclosing class. These two |
| 261 // classes do not have a subclass relationship, so, for |
| 262 // simplicity, we mark the type as an interface type. |
| 263 cachedTypeOfThis = new HType.nonNullSubtype(type, compiler); |
| 264 } else { |
| 265 cachedTypeOfThis = new HType.nonNullSubclass(type, compiler); |
| 266 } |
| 267 return cachedTypeOfThis; |
| 268 } |
| 269 |
| 251 /** | 270 /** |
| 252 * Documentation wanted -- johnniwinther | 271 * Documentation wanted -- johnniwinther |
| 253 * | 272 * |
| 254 * Invariant: [function] must be an implementation element. | 273 * Invariant: [function] must be an implementation element. |
| 255 */ | 274 */ |
| 256 void startFunction(Element element, Expression node) { | 275 void startFunction(Element element, Expression node) { |
| 257 assert(invariant(node, element.isImplementation)); | 276 assert(invariant(node, element.isImplementation)); |
| 258 Compiler compiler = builder.compiler; | 277 Compiler compiler = builder.compiler; |
| 259 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( | 278 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 260 element, node, builder.elements); | 279 element, node, builder.elements); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 // Inside closure redirect references to itself to [:this:]. | 313 // Inside closure redirect references to itself to [:this:]. |
| 295 HThis thisInstruction = new HThis(closureData.thisElement); | 314 HThis thisInstruction = new HThis(closureData.thisElement); |
| 296 builder.graph.thisInstruction = thisInstruction; | 315 builder.graph.thisInstruction = thisInstruction; |
| 297 builder.graph.entry.addAtEntry(thisInstruction); | 316 builder.graph.entry.addAtEntry(thisInstruction); |
| 298 updateLocal(closureData.closureElement, thisInstruction); | 317 updateLocal(closureData.closureElement, thisInstruction); |
| 299 } else if (element.isInstanceMember() | 318 } else if (element.isInstanceMember() |
| 300 || element.isGenerativeConstructor()) { | 319 || element.isGenerativeConstructor()) { |
| 301 // Once closures have been mapped to classes their instance members might | 320 // Once closures have been mapped to classes their instance members might |
| 302 // not have any thisElement if the closure was created inside a static | 321 // not have any thisElement if the closure was created inside a static |
| 303 // context. | 322 // context. |
| 304 ClassElement cls = element.getEnclosingClass(); | 323 HThis thisInstruction = new HThis( |
| 305 DartType type = cls.computeType(builder.compiler); | 324 closureData.thisElement, computeTypeOfThis()); |
| 306 HThis thisInstruction = new HThis(closureData.thisElement, | |
| 307 new HBoundedType.nonNull(type)); | |
| 308 builder.graph.thisInstruction = thisInstruction; | 325 builder.graph.thisInstruction = thisInstruction; |
| 309 builder.graph.entry.addAtEntry(thisInstruction); | 326 builder.graph.entry.addAtEntry(thisInstruction); |
| 310 directLocals[closureData.thisElement] = thisInstruction; | 327 directLocals[closureData.thisElement] = thisInstruction; |
| 311 } | 328 } |
| 312 | 329 |
| 313 // If this method is an intercepted method, add the extra | 330 // If this method is an intercepted method, add the extra |
| 314 // parameter to it, that is the actual receiver. | 331 // parameter to it, that is the actual receiver. |
| 315 ClassElement cls = element.getEnclosingClass(); | 332 ClassElement cls = element.getEnclosingClass(); |
| 316 if (builder.backend.isInterceptorClass(cls)) { | 333 if (builder.backend.isInterceptorClass(cls)) { |
| 317 HType type = HType.UNKNOWN; | 334 HType type = HType.UNKNOWN; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 return lookup; | 426 return lookup; |
| 410 } else { | 427 } else { |
| 411 assert(isUsedInTry(element)); | 428 assert(isUsedInTry(element)); |
| 412 HLocalValue local = getLocal(element); | 429 HLocalValue local = getLocal(element); |
| 413 HInstruction variable = new HLocalGet(element, local); | 430 HInstruction variable = new HLocalGet(element, local); |
| 414 builder.add(variable); | 431 builder.add(variable); |
| 415 return variable; | 432 return variable; |
| 416 } | 433 } |
| 417 } | 434 } |
| 418 | 435 |
| 419 HType cachedTypeOfThis; | |
| 420 | |
| 421 HInstruction readThis() { | 436 HInstruction readThis() { |
| 422 HInstruction res = readLocal(closureData.thisElement); | 437 HInstruction res = readLocal(closureData.thisElement); |
| 423 if (res.guaranteedType == null) { | 438 if (res.guaranteedType == null) { |
| 424 if (cachedTypeOfThis == null) { | 439 if (cachedTypeOfThis == null) { |
| 425 assert(closureData.isClosure()); | 440 computeTypeOfThis(); |
| 426 Element element = closureData.thisElement; | |
| 427 ClassElement cls = element.enclosingElement.getEnclosingClass(); | |
| 428 DartType type = cls.computeType(builder.compiler); | |
| 429 cachedTypeOfThis = new HBoundedType.nonNull(type); | |
| 430 } | 441 } |
| 431 res.guaranteedType = cachedTypeOfThis; | 442 res.guaranteedType = cachedTypeOfThis; |
| 432 } | 443 } |
| 433 return res; | 444 return res; |
| 434 } | 445 } |
| 435 | 446 |
| 436 HLocalValue getLocal(Element element) { | 447 HLocalValue getLocal(Element element) { |
| 437 // If the element is a parameter, we already have a | 448 // If the element is a parameter, we already have a |
| 438 // HParameterValue for it. We cannot create another one because | 449 // HParameterValue for it. We cannot create another one because |
| 439 // it could then have another name than the real parameter. And | 450 // it could then have another name than the real parameter. And |
| (...skipping 3573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4013 List<HInstruction> inputs = <HInstruction>[]; | 4024 List<HInstruction> inputs = <HInstruction>[]; |
| 4014 for (Link<Node> link = node.entries.nodes; | 4025 for (Link<Node> link = node.entries.nodes; |
| 4015 !link.isEmpty; | 4026 !link.isEmpty; |
| 4016 link = link.tail) { | 4027 link = link.tail) { |
| 4017 visit(link.head); | 4028 visit(link.head); |
| 4018 inputs.addLast(pop()); | 4029 inputs.addLast(pop()); |
| 4019 inputs.addLast(pop()); | 4030 inputs.addLast(pop()); |
| 4020 } | 4031 } |
| 4021 HLiteralList keyValuePairs = new HLiteralList(inputs); | 4032 HLiteralList keyValuePairs = new HLiteralList(inputs); |
| 4022 add(keyValuePairs); | 4033 add(keyValuePairs); |
| 4034 DartType mapType = compiler.mapLiteralClass.computeType(compiler); |
| 4035 // TODO(ngeoffray): Use the actual implementation type of a map |
| 4036 // literal. |
| 4023 pushInvokeHelper1(backend.getMapMaker(), keyValuePairs, | 4037 pushInvokeHelper1(backend.getMapMaker(), keyValuePairs, |
| 4024 new HType.fromBoundedType(compiler.mapClass.computeType(compiler), | 4038 new HType.nonNullSubtype(mapType, compiler)); |
| 4025 compiler, | |
| 4026 false)); | |
| 4027 } | 4039 } |
| 4028 | 4040 |
| 4029 visitLiteralMapEntry(LiteralMapEntry node) { | 4041 visitLiteralMapEntry(LiteralMapEntry node) { |
| 4030 visit(node.value); | 4042 visit(node.value); |
| 4031 visit(node.key); | 4043 visit(node.key); |
| 4032 } | 4044 } |
| 4033 | 4045 |
| 4034 visitNamedArgument(NamedArgument node) { | 4046 visitNamedArgument(NamedArgument node) { |
| 4035 visit(node.expression); | 4047 visit(node.expression); |
| 4036 } | 4048 } |
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4604 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 4616 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 4605 } | 4617 } |
| 4606 | 4618 |
| 4607 visitTypeVariable(TypeVariable node) { | 4619 visitTypeVariable(TypeVariable node) { |
| 4608 compiler.internalError('SsaBuilder.visitTypeVariable'); | 4620 compiler.internalError('SsaBuilder.visitTypeVariable'); |
| 4609 } | 4621 } |
| 4610 | 4622 |
| 4611 HType mapBaseType(BaseType baseType) { | 4623 HType mapBaseType(BaseType baseType) { |
| 4612 if (!baseType.isClass()) return HType.UNKNOWN; | 4624 if (!baseType.isClass()) return HType.UNKNOWN; |
| 4613 ClassBaseType classBaseType = baseType; | 4625 ClassBaseType classBaseType = baseType; |
| 4614 return new HType.fromBoundedType( | 4626 ClassElement cls = classBaseType.element; |
| 4615 classBaseType.element.computeType(compiler), compiler, false); | 4627 // Special case the list and map classes that are used as types |
| 4628 // for literals in the type inferrer. |
| 4629 if (cls == compiler.listClass) { |
| 4630 return HType.READABLE_ARRAY; |
| 4631 } else if (cls == compiler.mapClass) { |
| 4632 // TODO(ngeoffray): get the actual implementation of a map |
| 4633 // literal. |
| 4634 return new HType.nonNullSubtype( |
| 4635 compiler.mapLiteralClass.computeType(compiler), compiler); |
| 4636 } else { |
| 4637 return new HType.nonNullExactClass( |
| 4638 cls.computeType(compiler), compiler); |
| 4639 } |
| 4616 } | 4640 } |
| 4617 | 4641 |
| 4618 HType mapInferredType(ConcreteType concreteType) { | 4642 HType mapInferredType(ConcreteType concreteType) { |
| 4619 if (concreteType == null) return HType.UNKNOWN; | 4643 if (concreteType == null) return HType.UNKNOWN; |
| 4620 HType ssaType = HType.CONFLICTING; | 4644 HType ssaType = HType.CONFLICTING; |
| 4621 for (BaseType baseType in concreteType.baseTypes) { | 4645 for (BaseType baseType in concreteType.baseTypes) { |
| 4622 ssaType = ssaType.union(mapBaseType(baseType), compiler); | 4646 ssaType = ssaType.union(mapBaseType(baseType), compiler); |
| 4623 } | 4647 } |
| 4624 assert(!ssaType.isConflicting()); | 4648 assert(!ssaType.isConflicting()); |
| 4625 return ssaType; | 4649 return ssaType; |
| 4626 } | 4650 } |
| 4627 | 4651 |
| 4652 // [type] is either an instance of [DartType] or special objects |
| 4653 // like [native.SpecialType.JsObject], or [native.SpecialType.JsArray]. |
| 4628 HType mapNativeType(type) { | 4654 HType mapNativeType(type) { |
| 4629 if (type == native.SpecialType.JsObject) { | 4655 if (type == native.SpecialType.JsObject) { |
| 4630 return new HBoundedType.exact( | 4656 return new HType.nonNullExactClass( |
| 4631 compiler.objectClass.computeType(compiler)); | 4657 compiler.objectClass.computeType(compiler), compiler); |
| 4632 } else if (type == native.SpecialType.JsArray) { | 4658 } else if (type == native.SpecialType.JsArray) { |
| 4633 return HType.READABLE_ARRAY; | 4659 return HType.READABLE_ARRAY; |
| 4634 } else { | 4660 } else { |
| 4635 return new HType.fromBoundedType(type, compiler, false); | 4661 return new HType.nonNullSubclass(type, compiler); |
| 4636 } | 4662 } |
| 4637 } | 4663 } |
| 4638 | 4664 |
| 4639 HType mapNativeBehaviorType(native.NativeBehavior nativeBehavior) { | 4665 HType mapNativeBehaviorType(native.NativeBehavior nativeBehavior) { |
| 4640 if (nativeBehavior.typesInstantiated.isEmpty) return HType.UNKNOWN; | 4666 if (nativeBehavior.typesInstantiated.isEmpty) return HType.UNKNOWN; |
| 4641 | 4667 |
| 4642 HType ssaType = HType.CONFLICTING; | 4668 HType ssaType = HType.CONFLICTING; |
| 4643 for (final type in nativeBehavior.typesInstantiated) { | 4669 for (final type in nativeBehavior.typesInstantiated) { |
| 4644 ssaType = ssaType.union(mapNativeType(type), compiler); | 4670 ssaType = ssaType.union(mapNativeType(type), compiler); |
| 4645 } | 4671 } |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5025 new HSubGraphBlockInformation(elseBranch.graph)); | 5051 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5026 | 5052 |
| 5027 HBasicBlock conditionStartBlock = conditionBranch.block; | 5053 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5028 conditionStartBlock.setBlockFlow(info, joinBlock); | 5054 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5029 SubGraph conditionGraph = conditionBranch.graph; | 5055 SubGraph conditionGraph = conditionBranch.graph; |
| 5030 HIf branch = conditionGraph.end.last; | 5056 HIf branch = conditionGraph.end.last; |
| 5031 assert(branch is HIf); | 5057 assert(branch is HIf); |
| 5032 branch.blockInformation = conditionStartBlock.blockFlow; | 5058 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5033 } | 5059 } |
| 5034 } | 5060 } |
| OLD | NEW |