Chromium Code Reviews| Index: lib/compiler/implementation/ssa/builder.dart |
| diff --git a/lib/compiler/implementation/ssa/builder.dart b/lib/compiler/implementation/ssa/builder.dart |
| index 75c7877de8d50ca3b1f5d008465d0361af8e9761..8fcda31c6bef30d3c0fd03a334ecf85b067a2370 100644 |
| --- a/lib/compiler/implementation/ssa/builder.dart |
| +++ b/lib/compiler/implementation/ssa/builder.dart |
| @@ -1242,14 +1242,13 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| HForeignNew newObject = new HForeignNew(classElement, constructorArguments); |
| add(newObject); |
| - // If the class has type variables, create the runtime type |
| - // information with the type parameters provided. |
| - if (!classElement.typeVariables.isEmpty()) { |
| - List<HInstruction> rtiInputs = <HInstruction>[]; |
| + // Create the runtime type information, if needed. |
| + if (needsRuntimeTypeInfo(classElement)) { |
| + List<HInstruction> inputs = <HInstruction>[]; |
| classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
| - rtiInputs.add(localsHandler.directLocals[typeVariable.element]); |
| + inputs.add(localsHandler.directLocals[typeVariable.element]); |
| }); |
| - callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); |
| + callSetRuntimeTypeInfo(classElement, inputs, newObject); |
| } |
| // Generate calls to the constructor bodies. |
| @@ -2638,7 +2637,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| void handleListConstructor(InterfaceType type, |
| Node currentNode, |
| HInstruction newObject) { |
| - if (type.arguments.isEmpty()) return; |
| + if (!needsRuntimeTypeInfo(type.element)) return; |
| List<HInstruction> inputs = <HInstruction>[]; |
| type.arguments.forEach((DartType argument) { |
| inputs.add(analyzeTypeArgument(argument, currentNode)); |
| @@ -2646,23 +2645,64 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| } |
| + // Runtime type information is required if the type has type |
| + // variables or if the program calls [runtimeType]. |
| + // TODO(karlklose): it is unnecessary for type variables that |
| + // can never match an is-Check. |
| + bool needsRuntimeTypeInfo(ClassElement element) { |
| + bool classHasTypeVariables = !element.typeVariables.isEmpty(); |
| + bool runtimeTypeIsUsed = compiler.enabledRuntimeType; |
| + return (classHasTypeVariables || runtimeTypeIsUsed); |
| + } |
| + |
| void callSetRuntimeTypeInfo(ClassElement element, |
| - List<HInstruction> inputs, |
| + List<HInstruction> rtiInputs, |
| HInstruction newObject) { |
| - List<String> typeVariables = <String>[]; |
| - element.typeVariables.forEach((TypeVariableType typeVariable) { |
| - typeVariables.add("'$typeVariable': #"); |
| - }); |
| - |
| - String jsCode = '{ ${Strings.join(typeVariables, ', ')} }'; |
| - HInstruction typeInfo = new HForeign(new LiteralDartString(jsCode), |
| - new LiteralDartString('Object'), |
| - inputs); |
| - add(typeInfo); |
| + bool classHasTypeVariables = !element.typeVariables.isEmpty(); |
| + bool runtimeTypeIsUsed = compiler.enabledRuntimeType; |
| + |
| + // Construct the runtime type information. |
| + HInstruction runtimeType; |
| + HInstruction typeInfo; |
|
kasperl
2012/09/14 12:35:37
Isn't this typeInfo variable unused (shadowed)?
karlklose
2012/09/17 14:50:37
Done, removed.
|
| + StringBuffer runtimeCode = new StringBuffer(); |
| + List<HInstruction> runtimeCodeInputs = <HInstruction>[]; |
| + if (runtimeTypeIsUsed) { |
| + String runtimeTypeString = |
| + RuntimeTypeInformation.generateRuntimeTypeString(element, |
| + rtiInputs.length); |
| + runtimeType = |
|
kasperl
2012/09/14 12:35:37
Can't you declare runtimeType here?
karlklose
2012/09/17 14:50:37
Done.
|
| + new HForeign(new LiteralDartString(runtimeTypeString), |
| + new LiteralDartString('String'), |
| + rtiInputs); |
| + add(runtimeType); |
| + runtimeCodeInputs.add(runtimeType); |
| + runtimeCode.add('runtimeType: #'); |
| + } |
| + if (classHasTypeVariables) { |
| + if (runtimeTypeIsUsed) runtimeCode.add(', '); |
| + String typeVariablesString = |
| + RuntimeTypeInformation.generateTypeVariableString(element, |
| + rtiInputs.length); |
| + HInstruction typeInfo = |
|
kasperl
2012/09/14 12:35:37
Add a helper for this creation of a new foreign st
karlklose
2012/09/17 14:50:37
Done.
|
| + new HForeign(new LiteralDartString(typeVariablesString), |
| + new LiteralDartString('String'), |
| + rtiInputs); |
| + add(typeInfo); |
| + runtimeCodeInputs.add(typeInfo); |
| + runtimeCode.add('#'); |
| + } |
| + HInstruction runtimeInfo = |
| + new HForeign(new LiteralDartString("{$runtimeCode}"), |
| + new LiteralDartString('Object'), |
| + runtimeCodeInputs); |
| + add(runtimeInfo); |
| + |
| + // Set the runtime type information on the object. |
| Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo(); |
| HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement); |
| add(typeInfoSetter); |
| - add(new HInvokeStatic(<HInstruction>[typeInfoSetter, newObject, typeInfo])); |
| + add(new HInvokeStatic( |
| + <HInstruction>[typeInfoSetter, newObject, runtimeInfo])); |
| } |
| visitNewSend(Send node) { |