Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Side by Side Diff: dart/sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 50313007: Implement dynamic function checks. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r30897. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 2055 matching lines...) Expand 10 before | Expand all | Expand 10 after
2066 HInstruction representations = buildTypeArgumentRepresentations(type); 2066 HInstruction representations = buildTypeArgumentRepresentations(type);
2067 add(representations); 2067 add(representations);
2068 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, 2068 return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
2069 original, representations); 2069 original, representations);
2070 } else if (type.kind == TypeKind.TYPE_VARIABLE) { 2070 } else if (type.kind == TypeKind.TYPE_VARIABLE) {
2071 TypeMask subtype = original.instructionType; 2071 TypeMask subtype = original.instructionType;
2072 HInstruction typeVariable = addTypeVariableReference(type); 2072 HInstruction typeVariable = addTypeVariableReference(type);
2073 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, 2073 return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
2074 original, typeVariable); 2074 original, typeVariable);
2075 } else if (type.kind == TypeKind.FUNCTION) { 2075 } else if (type.kind == TypeKind.FUNCTION) {
2076 if (backend.rti.isSimpleFunctionType(type)) { 2076 String name = kind == HTypeConversion.CAST_TYPE_CHECK
2077 return original.convertType(compiler, type, kind); 2077 ? '_asCheck' : '_assertCheck';
2078 } 2078
2079 TypeMask subtype = original.instructionType; 2079 List arguments = [buildFunctionType(type), original];
2080 if (type.containsTypeVariables) { 2080 pushInvokeDynamic(
2081 bool contextIsTypeArguments = false; 2081 null,
2082 HInstruction context; 2082 new Selector.call(name, compiler.jsHelperLibrary, 1),
2083 if (!currentElement.enclosingElement.isClosure() 2083 arguments);
2084 && currentElement.isInstanceMember()) { 2084
2085 context = localsHandler.readThis(); 2085 return new HTypeConversion(type, kind, original.instructionType, pop());
2086 } else {
2087 ClassElement contextClass = Types.getClassContext(type);
2088 context = buildTypeVariableList(contextClass);
2089 add(context);
2090 contextIsTypeArguments = true;
2091 }
2092 return new HTypeConversion.withContext(type, kind, subtype,
2093 original, context, contextIsTypeArguments: contextIsTypeArguments);
2094 } else {
2095 return new HTypeConversion(type, kind, subtype, original);
2096 }
2097 } else { 2086 } else {
2098 return original.convertType(compiler, type, kind); 2087 return original.convertType(compiler, type, kind);
2099 } 2088 }
2100 } 2089 }
2101 2090
2102 HInstruction potentiallyCheckType(HInstruction original, DartType type, 2091 HInstruction potentiallyCheckType(HInstruction original, DartType type,
2103 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { 2092 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
2104 if (!compiler.enableTypeAssertions) return original; 2093 if (!compiler.enableTypeAssertions) return original;
2105 HInstruction other = buildTypeConversion(original, type, kind); 2094 HInstruction other = buildTypeConversion(original, type, kind);
2106 if (other != original) add(other); 2095 if (other != original) add(other);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2158 value, 2147 value,
2159 compiler.boolClass.computeType(compiler), 2148 compiler.boolClass.computeType(compiler),
2160 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 2149 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
2161 } 2150 }
2162 HInstruction result = new HBoolify(value, backend.boolType); 2151 HInstruction result = new HBoolify(value, backend.boolType);
2163 add(result); 2152 add(result);
2164 return result; 2153 return result;
2165 } 2154 }
2166 2155
2167 HInstruction attachPosition(HInstruction target, Node node) { 2156 HInstruction attachPosition(HInstruction target, Node node) {
2168 target.sourcePosition = sourceFileLocationForBeginToken(node); 2157 if (node != null) {
2158 target.sourcePosition = sourceFileLocationForBeginToken(node);
2159 }
2169 return target; 2160 return target;
2170 } 2161 }
2171 2162
2172 SourceFileLocation sourceFileLocationForBeginToken(Node node) => 2163 SourceFileLocation sourceFileLocationForBeginToken(Node node) =>
2173 sourceFileLocationForToken(node, node.getBeginToken()); 2164 sourceFileLocationForToken(node, node.getBeginToken());
2174 2165
2175 SourceFileLocation sourceFileLocationForEndToken(Node node) => 2166 SourceFileLocation sourceFileLocationForEndToken(Node node) =>
2176 sourceFileLocationForToken(node, node.getEndToken()); 2167 sourceFileLocationForToken(node, node.getEndToken());
2177 2168
2178 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { 2169 SourceFileLocation sourceFileLocationForToken(Node node, Token token) {
(...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after
3051 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); 3042 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
3052 type = type.unalias(compiler); 3043 type = type.unalias(compiler);
3053 HInstruction instruction = buildIsNode(node, type, expression); 3044 HInstruction instruction = buildIsNode(node, type, expression);
3054 if (isNot) { 3045 if (isNot) {
3055 add(instruction); 3046 add(instruction);
3056 instruction = new HNot(instruction, backend.boolType); 3047 instruction = new HNot(instruction, backend.boolType);
3057 } 3048 }
3058 push(instruction); 3049 push(instruction);
3059 } 3050 }
3060 3051
3061 HLiteralList buildTypeVariableList(ClassElement contextClass) {
3062 List<HInstruction> inputs = <HInstruction>[];
3063 for (Link<DartType> link = contextClass.typeVariables;
3064 !link.isEmpty;
3065 link = link.tail) {
3066 inputs.add(addTypeVariableReference(link.head));
3067 }
3068 return buildLiteralList(inputs);
3069 }
3070
3071 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { 3052 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) {
3072 type = type.unalias(compiler); 3053 type = type.unalias(compiler);
3073 if (type.kind == TypeKind.FUNCTION) { 3054 if (type.kind == TypeKind.FUNCTION) {
3074 if (backend.rti.isSimpleFunctionType(type)) { 3055 List arguments = [buildFunctionType(type), expression];
3075 // TODO(johnniwinther): Avoid interceptor if unneeded. 3056 pushInvokeDynamic(
3076 return new HIs.raw( 3057 node, new Selector.call('_isTest', compiler.jsHelperLibrary, 1),
3077 type, expression, invokeInterceptor(expression), backend.boolType); 3058 arguments);
3078 } 3059 return new HIs.compound(type, expression, pop(), backend.boolType);
3079 Element checkFunctionSubtype = backend.getCheckFunctionSubtype();
3080
3081 HInstruction signatureName = graph.addConstantString(
3082 new DartString.literal(backend.namer.getFunctionTypeName(type)),
3083 compiler);
3084
3085 HInstruction contextName;
3086 HInstruction context;
3087 HInstruction typeArguments;
3088 if (type.containsTypeVariables) {
3089 ClassElement contextClass = Types.getClassContext(type);
3090 contextName = graph.addConstantString(
3091 new DartString.literal(backend.namer.getNameOfClass(contextClass)),
3092 compiler);
3093 if (!currentElement.enclosingElement.isClosure()
3094 && currentElement.isInstanceMember()) {
3095 context = localsHandler.readThis();
3096 typeArguments = graph.addConstantNull(compiler);
3097 } else {
3098 context = graph.addConstantNull(compiler);
3099 typeArguments = buildTypeVariableList(contextClass);
3100 add(typeArguments);
3101 }
3102 } else {
3103 contextName = graph.addConstantNull(compiler);
3104 context = graph.addConstantNull(compiler);
3105 typeArguments = graph.addConstantNull(compiler);
3106 }
3107
3108 List<HInstruction> inputs = <HInstruction>[expression,
3109 signatureName,
3110 contextName,
3111 context,
3112 typeArguments];
3113 pushInvokeStatic(node, checkFunctionSubtype, inputs, backend.boolType);
3114 HInstruction call = pop();
3115 return new HIs.compound(type, expression, call, backend.boolType);
3116 } else if (type.kind == TypeKind.TYPE_VARIABLE) { 3060 } else if (type.kind == TypeKind.TYPE_VARIABLE) {
3117 HInstruction runtimeType = addTypeVariableReference(type); 3061 HInstruction runtimeType = addTypeVariableReference(type);
3118 Element helper = backend.getCheckSubtypeOfRuntimeType(); 3062 Element helper = backend.getCheckSubtypeOfRuntimeType();
3119 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; 3063 List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
3120 pushInvokeStatic(null, helper, inputs, backend.boolType); 3064 pushInvokeStatic(null, helper, inputs, backend.boolType);
3121 HInstruction call = pop(); 3065 HInstruction call = pop();
3122 return new HIs.variable(type, expression, call, backend.boolType); 3066 return new HIs.variable(type, expression, call, backend.boolType);
3123 } else if (RuntimeTypes.hasTypeArguments(type)) { 3067 } else if (RuntimeTypes.hasTypeArguments(type)) {
3124 ClassElement element = type.element; 3068 ClassElement element = type.element;
3125 Element helper = backend.getCheckSubtype(); 3069 Element helper = backend.getCheckSubtype();
(...skipping 21 matching lines...) Expand all
3147 } else { 3091 } else {
3148 if (backend.hasDirectCheckFor(type)) { 3092 if (backend.hasDirectCheckFor(type)) {
3149 return new HIs.direct(type, expression, backend.boolType); 3093 return new HIs.direct(type, expression, backend.boolType);
3150 } 3094 }
3151 // TODO(johnniwinther): Avoid interceptor if unneeded. 3095 // TODO(johnniwinther): Avoid interceptor if unneeded.
3152 return new HIs.raw( 3096 return new HIs.raw(
3153 type, expression, invokeInterceptor(expression), backend.boolType); 3097 type, expression, invokeInterceptor(expression), backend.boolType);
3154 } 3098 }
3155 } 3099 }
3156 3100
3101 HInstruction buildFunctionType(FunctionType type) {
3102 type.accept(new TypeBuilder(), this);
3103 return pop();
3104 }
3105
3157 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { 3106 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) {
3158 Selector selector = elements.getSelector(node); 3107 Selector selector = elements.getSelector(node);
3159 if (selector.namedArgumentCount == 0) { 3108 if (selector.namedArgumentCount == 0) {
3160 addGenericSendArgumentsToList(node.arguments, list); 3109 addGenericSendArgumentsToList(node.arguments, list);
3161 } else { 3110 } else {
3162 // Visit positional arguments and add them to the list. 3111 // Visit positional arguments and add them to the list.
3163 Link<Node> arguments = node.arguments; 3112 Link<Node> arguments = node.arguments;
3164 int positionalArgumentCount = selector.positionalArgumentCount; 3113 int positionalArgumentCount = selector.positionalArgumentCount;
3165 for (int i = 0; 3114 for (int i = 0;
3166 i < positionalArgumentCount; 3115 i < positionalArgumentCount;
(...skipping 2780 matching lines...) Expand 10 before | Expand all | Expand 10 after
5947 new HSubGraphBlockInformation(elseBranch.graph)); 5896 new HSubGraphBlockInformation(elseBranch.graph));
5948 5897
5949 HBasicBlock conditionStartBlock = conditionBranch.block; 5898 HBasicBlock conditionStartBlock = conditionBranch.block;
5950 conditionStartBlock.setBlockFlow(info, joinBlock); 5899 conditionStartBlock.setBlockFlow(info, joinBlock);
5951 SubGraph conditionGraph = conditionBranch.graph; 5900 SubGraph conditionGraph = conditionBranch.graph;
5952 HIf branch = conditionGraph.end.last; 5901 HIf branch = conditionGraph.end.last;
5953 assert(branch is HIf); 5902 assert(branch is HIf);
5954 branch.blockInformation = conditionStartBlock.blockFlow; 5903 branch.blockInformation = conditionStartBlock.blockFlow;
5955 } 5904 }
5956 } 5905 }
5906
5907 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
5908 void visitType(DartType type, _) {
5909 throw 'Internal error $type';
5910 }
5911
5912 void visitVoidType(VoidType type, SsaBuilder builder) {
5913 ClassElement cls = builder.compiler.findHelper('VoidRuntimeType');
5914 builder.push(new HVoidType(type, new TypeMask.exact(cls)));
5915 }
5916
5917 void visitTypeVariableType(TypeVariableType type,
5918 SsaBuilder builder) {
5919 ClassElement cls = builder.compiler.findHelper('RuntimeType');
5920 TypeMask instructionType = new TypeMask.subclass(cls);
5921 if (!builder.currentElement.enclosingElement.isClosure() &&
5922 builder.currentElement.isInstanceMember()) {
5923 HInstruction receiver = builder.localsHandler.readThis();
5924 builder.push(new HReadTypeVariable(type, receiver, instructionType));
5925 } else {
5926 builder.push(
5927 new HReadTypeVariable.noReceiver(
5928 type, builder.addTypeVariableReference(type), instructionType));
5929 }
5930 }
5931
5932 void visitFunctionType(FunctionType type, SsaBuilder builder) {
5933 type.returnType.accept(this, builder);
5934 HInstruction returnType = builder.pop();
5935 List<HInstruction> inputs = <HInstruction>[returnType];
5936
5937 for (DartType parameter in type.parameterTypes) {
5938 parameter.accept(this, builder);
5939 inputs.add(builder.pop());
5940 }
5941
5942 for (DartType parameter in type.optionalParameterTypes) {
5943 parameter.accept(this, builder);
5944 inputs.add(builder.pop());
5945 }
5946
5947 Link<DartType> namedParameterTypes = type.namedParameterTypes;
5948 for (String name in type.namedParameters) {
5949 DartString dartString = new DartString.literal(name);
5950 inputs.add(
5951 builder.graph.addConstantString(dartString, builder.compiler));
5952 namedParameterTypes.head.accept(this, builder);
5953 inputs.add(builder.pop());
5954 namedParameterTypes = namedParameterTypes.tail;
5955 }
5956
5957 ClassElement cls = builder.compiler.findHelper('RuntimeFunctionType');
5958 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls)));
5959 }
5960
5961 void visitMalformedType(MalformedType type, SsaBuilder builder) {
5962 visitDynamicType(builder.compiler.types.dynamicType, builder);
5963 }
5964
5965 void visitStatementType(StatementType type, SsaBuilder builder) {
5966 throw 'not implemented visitStatementType($type)';
5967 }
5968
5969 void visitGenericType(GenericType type, SsaBuilder builder) {
5970 throw 'not implemented visitGenericType($type)';
5971 }
5972
5973 void visitInterfaceType(InterfaceType type, SsaBuilder builder) {
5974 List<HInstruction> inputs = <HInstruction>[];
5975 for (DartType typeArgument in type.typeArguments) {
5976 typeArgument.accept(this, builder);
5977 inputs.add(builder.pop());
5978 }
5979 ClassElement cls;
5980 if (type.typeArguments.isEmpty) {
5981 cls = builder.compiler.findHelper('RuntimeTypePlain');
5982 } else {
5983 cls = builder.compiler.findHelper('RuntimeTypeGeneric');
5984 }
5985 builder.push(new HInterfaceType(inputs, type, new TypeMask.exact(cls)));
5986 }
5987
5988 void visitTypedefType(TypedefType type, SsaBuilder builder) {
5989 DartType unaliased = type.unalias(builder.compiler);
5990 if (unaliased is TypedefType) throw 'unable to unalias $type';
5991 unaliased.accept(this, builder);
5992 }
5993
5994 void visitDynamicType(DynamicType type, SsaBuilder builder) {
5995 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType');
5996 builder.push(new HDynamicType(type, new TypeMask.exact(cls)));
5997 }
5998 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698