Chromium Code Reviews| 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 computeTypeOfThis() { | |
| 252 Element element = closureData.thisElement; | |
| 253 ClassElement cls = element.enclosingElement.getEnclosingClass(); | |
| 254 DartType type = cls.computeType(builder.compiler); | |
| 255 Compiler compiler = builder.compiler; | |
| 256 if (compiler.world.isUsedAsMixin(cls)) { | |
|
kasperl
2013/02/11 14:30:34
Add comment to explain why this is done?
ngeoffray
2013/02/11 14:53:29
Done.
| |
| 257 return new HType.nonNullSubtype(type, compiler); | |
| 258 } else { | |
| 259 return new HType.nonNullSubclass(type, compiler); | |
| 260 } | |
| 261 } | |
| 262 | |
| 251 /** | 263 /** |
| 252 * Documentation wanted -- johnniwinther | 264 * Documentation wanted -- johnniwinther |
| 253 * | 265 * |
| 254 * Invariant: [function] must be an implementation element. | 266 * Invariant: [function] must be an implementation element. |
| 255 */ | 267 */ |
| 256 void startFunction(Element element, Expression node) { | 268 void startFunction(Element element, Expression node) { |
| 257 assert(invariant(node, element.isImplementation)); | 269 assert(invariant(node, element.isImplementation)); |
| 258 Compiler compiler = builder.compiler; | 270 Compiler compiler = builder.compiler; |
| 259 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( | 271 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 260 element, node, builder.elements); | 272 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:]. | 306 // Inside closure redirect references to itself to [:this:]. |
| 295 HThis thisInstruction = new HThis(closureData.thisElement); | 307 HThis thisInstruction = new HThis(closureData.thisElement); |
| 296 builder.graph.thisInstruction = thisInstruction; | 308 builder.graph.thisInstruction = thisInstruction; |
| 297 builder.graph.entry.addAtEntry(thisInstruction); | 309 builder.graph.entry.addAtEntry(thisInstruction); |
| 298 updateLocal(closureData.closureElement, thisInstruction); | 310 updateLocal(closureData.closureElement, thisInstruction); |
| 299 } else if (element.isInstanceMember() | 311 } else if (element.isInstanceMember() |
| 300 || element.isGenerativeConstructor()) { | 312 || element.isGenerativeConstructor()) { |
| 301 // Once closures have been mapped to classes their instance members might | 313 // Once closures have been mapped to classes their instance members might |
| 302 // not have any thisElement if the closure was created inside a static | 314 // not have any thisElement if the closure was created inside a static |
| 303 // context. | 315 // context. |
| 304 ClassElement cls = element.getEnclosingClass(); | 316 HThis thisInstruction = new HThis( |
| 305 DartType type = cls.computeType(builder.compiler); | 317 closureData.thisElement, computeTypeOfThis()); |
| 306 HThis thisInstruction = new HThis(closureData.thisElement, | |
| 307 new HBoundedType.nonNull(type)); | |
| 308 builder.graph.thisInstruction = thisInstruction; | 318 builder.graph.thisInstruction = thisInstruction; |
| 309 builder.graph.entry.addAtEntry(thisInstruction); | 319 builder.graph.entry.addAtEntry(thisInstruction); |
| 310 directLocals[closureData.thisElement] = thisInstruction; | 320 directLocals[closureData.thisElement] = thisInstruction; |
| 311 } | 321 } |
| 312 | 322 |
| 313 // If this method is an intercepted method, add the extra | 323 // If this method is an intercepted method, add the extra |
| 314 // parameter to it, that is the actual receiver. | 324 // parameter to it, that is the actual receiver. |
| 315 ClassElement cls = element.getEnclosingClass(); | 325 ClassElement cls = element.getEnclosingClass(); |
| 316 if (builder.backend.isInterceptorClass(cls)) { | 326 if (builder.backend.isInterceptorClass(cls)) { |
| 317 HType type = HType.UNKNOWN; | 327 HType type = HType.UNKNOWN; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 409 return lookup; | 419 return lookup; |
| 410 } else { | 420 } else { |
| 411 assert(isUsedInTry(element)); | 421 assert(isUsedInTry(element)); |
| 412 HLocalValue local = getLocal(element); | 422 HLocalValue local = getLocal(element); |
| 413 HInstruction variable = new HLocalGet(element, local); | 423 HInstruction variable = new HLocalGet(element, local); |
| 414 builder.add(variable); | 424 builder.add(variable); |
| 415 return variable; | 425 return variable; |
| 416 } | 426 } |
| 417 } | 427 } |
| 418 | 428 |
| 419 HType cachedTypeOfThis; | 429 HType cachedTypeOfThis; |
|
kasperl
2013/02/11 14:30:34
Could the cachedTypeOfThis reading/writing be move
ngeoffray
2013/02/11 14:53:29
Done.
| |
| 420 | 430 |
| 421 HInstruction readThis() { | 431 HInstruction readThis() { |
| 422 HInstruction res = readLocal(closureData.thisElement); | 432 HInstruction res = readLocal(closureData.thisElement); |
| 423 if (res.guaranteedType == null) { | 433 if (res.guaranteedType == null) { |
| 424 if (cachedTypeOfThis == null) { | 434 if (cachedTypeOfThis == null) { |
| 425 assert(closureData.isClosure()); | 435 assert(closureData.isClosure()); |
| 426 Element element = closureData.thisElement; | 436 cachedTypeOfThis = computeTypeOfThis(); |
| 427 ClassElement cls = element.enclosingElement.getEnclosingClass(); | |
| 428 DartType type = cls.computeType(builder.compiler); | |
| 429 cachedTypeOfThis = new HBoundedType.nonNull(type); | |
| 430 } | 437 } |
| 431 res.guaranteedType = cachedTypeOfThis; | 438 res.guaranteedType = cachedTypeOfThis; |
| 432 } | 439 } |
| 433 return res; | 440 return res; |
| 434 } | 441 } |
| 435 | 442 |
| 436 HLocalValue getLocal(Element element) { | 443 HLocalValue getLocal(Element element) { |
| 437 // If the element is a parameter, we already have a | 444 // If the element is a parameter, we already have a |
| 438 // HParameterValue for it. We cannot create another one because | 445 // HParameterValue for it. We cannot create another one because |
| 439 // it could then have another name than the real parameter. And | 446 // 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>[]; | 4020 List<HInstruction> inputs = <HInstruction>[]; |
| 4014 for (Link<Node> link = node.entries.nodes; | 4021 for (Link<Node> link = node.entries.nodes; |
| 4015 !link.isEmpty; | 4022 !link.isEmpty; |
| 4016 link = link.tail) { | 4023 link = link.tail) { |
| 4017 visit(link.head); | 4024 visit(link.head); |
| 4018 inputs.addLast(pop()); | 4025 inputs.addLast(pop()); |
| 4019 inputs.addLast(pop()); | 4026 inputs.addLast(pop()); |
| 4020 } | 4027 } |
| 4021 HLiteralList keyValuePairs = new HLiteralList(inputs); | 4028 HLiteralList keyValuePairs = new HLiteralList(inputs); |
| 4022 add(keyValuePairs); | 4029 add(keyValuePairs); |
| 4030 DartType mapType = compiler.mapLiteralClass.computeType(compiler); | |
| 4031 // TODO(ngeoffray): Use the actual implementation type of a map | |
| 4032 // literal. | |
| 4023 pushInvokeHelper1(backend.getMapMaker(), keyValuePairs, | 4033 pushInvokeHelper1(backend.getMapMaker(), keyValuePairs, |
| 4024 new HType.fromBoundedType(compiler.mapClass.computeType(compiler), | 4034 new HType.nonNullSubtype(mapType, compiler)); |
| 4025 compiler, | |
| 4026 false)); | |
| 4027 } | 4035 } |
| 4028 | 4036 |
| 4029 visitLiteralMapEntry(LiteralMapEntry node) { | 4037 visitLiteralMapEntry(LiteralMapEntry node) { |
| 4030 visit(node.value); | 4038 visit(node.value); |
| 4031 visit(node.key); | 4039 visit(node.key); |
| 4032 } | 4040 } |
| 4033 | 4041 |
| 4034 visitNamedArgument(NamedArgument node) { | 4042 visitNamedArgument(NamedArgument node) { |
| 4035 visit(node.expression); | 4043 visit(node.expression); |
| 4036 } | 4044 } |
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4604 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 4612 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 4605 } | 4613 } |
| 4606 | 4614 |
| 4607 visitTypeVariable(TypeVariable node) { | 4615 visitTypeVariable(TypeVariable node) { |
| 4608 compiler.internalError('SsaBuilder.visitTypeVariable'); | 4616 compiler.internalError('SsaBuilder.visitTypeVariable'); |
| 4609 } | 4617 } |
| 4610 | 4618 |
| 4611 HType mapBaseType(BaseType baseType) { | 4619 HType mapBaseType(BaseType baseType) { |
| 4612 if (!baseType.isClass()) return HType.UNKNOWN; | 4620 if (!baseType.isClass()) return HType.UNKNOWN; |
| 4613 ClassBaseType classBaseType = baseType; | 4621 ClassBaseType classBaseType = baseType; |
| 4614 return new HType.fromBoundedType( | 4622 ClassElement cls = classBaseType.element; |
| 4615 classBaseType.element.computeType(compiler), compiler, false); | 4623 // Special case the list and map classes that are used as types |
| 4624 // for literals in the type inferrer. | |
| 4625 if (cls == compiler.listClass) { | |
| 4626 return HType.READABLE_ARRAY; | |
| 4627 } else if (cls == compiler.mapClass) { | |
| 4628 // TODO(ngeoffray): get the actual implementation of a map | |
| 4629 // literal. | |
| 4630 return new HType.nonNullSubtype( | |
| 4631 compiler.mapLiteralClass.computeType(compiler), compiler); | |
|
kasperl
2013/02/11 14:30:34
It's very common that you call computeType as part
ngeoffray
2013/02/11 14:53:29
Sometimes, you do have the DartType available and
| |
| 4632 } else { | |
| 4633 return new HType.nonNullExactClass( | |
| 4634 cls.computeType(compiler), compiler); | |
| 4635 } | |
| 4616 } | 4636 } |
| 4617 | 4637 |
| 4618 HType mapInferredType(ConcreteType concreteType) { | 4638 HType mapInferredType(ConcreteType concreteType) { |
| 4619 if (concreteType == null) return HType.UNKNOWN; | 4639 if (concreteType == null) return HType.UNKNOWN; |
| 4620 HType ssaType = HType.CONFLICTING; | 4640 HType ssaType = HType.CONFLICTING; |
| 4621 for (BaseType baseType in concreteType.baseTypes) { | 4641 for (BaseType baseType in concreteType.baseTypes) { |
| 4622 ssaType = ssaType.union(mapBaseType(baseType), compiler); | 4642 ssaType = ssaType.union(mapBaseType(baseType), compiler); |
| 4623 } | 4643 } |
| 4624 assert(!ssaType.isConflicting()); | 4644 assert(!ssaType.isConflicting()); |
| 4625 return ssaType; | 4645 return ssaType; |
| 4626 } | 4646 } |
| 4627 | 4647 |
| 4628 HType mapNativeType(type) { | 4648 HType mapNativeType(type) { |
|
kasperl
2013/02/11 14:30:34
What is the type of type?
ngeoffray
2013/02/11 14:53:29
It can be of different classes (DartType or ad-hoc
| |
| 4629 if (type == native.SpecialType.JsObject) { | 4649 if (type == native.SpecialType.JsObject) { |
| 4630 return new HBoundedType.exact( | 4650 return new HType.nonNullExactClass( |
| 4631 compiler.objectClass.computeType(compiler)); | 4651 compiler.objectClass.computeType(compiler), compiler); |
| 4632 } else if (type == native.SpecialType.JsArray) { | 4652 } else if (type == native.SpecialType.JsArray) { |
| 4633 return HType.READABLE_ARRAY; | 4653 return HType.READABLE_ARRAY; |
| 4634 } else { | 4654 } else { |
| 4635 return new HType.fromBoundedType(type, compiler, false); | 4655 return new HType.nonNullSubclass(type, compiler); |
| 4636 } | 4656 } |
| 4637 } | 4657 } |
| 4638 | 4658 |
| 4639 HType mapNativeBehaviorType(native.NativeBehavior nativeBehavior) { | 4659 HType mapNativeBehaviorType(native.NativeBehavior nativeBehavior) { |
| 4640 if (nativeBehavior.typesInstantiated.isEmpty) return HType.UNKNOWN; | 4660 if (nativeBehavior.typesInstantiated.isEmpty) return HType.UNKNOWN; |
| 4641 | 4661 |
| 4642 HType ssaType = HType.CONFLICTING; | 4662 HType ssaType = HType.CONFLICTING; |
| 4643 for (final type in nativeBehavior.typesInstantiated) { | 4663 for (final type in nativeBehavior.typesInstantiated) { |
| 4644 ssaType = ssaType.union(mapNativeType(type), compiler); | 4664 ssaType = ssaType.union(mapNativeType(type), compiler); |
| 4645 } | 4665 } |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5025 new HSubGraphBlockInformation(elseBranch.graph)); | 5045 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5026 | 5046 |
| 5027 HBasicBlock conditionStartBlock = conditionBranch.block; | 5047 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5028 conditionStartBlock.setBlockFlow(info, joinBlock); | 5048 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5029 SubGraph conditionGraph = conditionBranch.graph; | 5049 SubGraph conditionGraph = conditionBranch.graph; |
| 5030 HIf branch = conditionGraph.end.last; | 5050 HIf branch = conditionGraph.end.last; |
| 5031 assert(branch is HIf); | 5051 assert(branch is HIf); |
| 5032 branch.blockInformation = conditionStartBlock.blockFlow; | 5052 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5033 } | 5053 } |
| 5034 } | 5054 } |
| OLD | NEW |