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

Side by Side Diff: pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart

Issue 2688413003: Extract BackendUsage, MirrorsData, and CheckedModeHelpers from Backend. (Closed)
Patch Set: Cleanup Created 3 years, 10 months 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 import '../compiler.dart' show Compiler; 5 import '../common.dart';
6 import '../elements/resolution_types.dart'; 6 import '../core_types.dart';
7 import '../elements/elements.dart'; 7 import '../elements/elements.dart' show ErroneousElement;
8 import '../elements/entities.dart';
9 import '../elements/resolution_types.dart' show MalformedType;
10 import '../elements/types.dart';
8 import '../js/js.dart' as jsAst; 11 import '../js/js.dart' as jsAst;
9 import '../js/js.dart' show js; 12 import '../js/js.dart' show js;
10 import '../ssa/codegen.dart' show SsaCodeGenerator; 13 import '../ssa/codegen.dart' show SsaCodeGenerator;
11 import '../ssa/nodes.dart' show HTypeConversion; 14 import '../ssa/nodes.dart' show HTypeConversion;
12 import '../universe/call_structure.dart' show CallStructure; 15 import '../universe/call_structure.dart' show CallStructure;
13 import '../universe/use.dart' show StaticUse; 16 import '../universe/use.dart' show StaticUse;
14 import 'backend.dart'; 17 import 'backend_helpers.dart';
15 18
16 class CheckedModeHelper { 19 class CheckedModeHelper {
17 final String name; 20 final String name;
18 21
19 const CheckedModeHelper(String this.name); 22 const CheckedModeHelper(String this.name);
20 23
21 StaticUse getStaticUse(Compiler compiler) { 24 StaticUse getStaticUse(BackendHelpers helpers) {
22 JavaScriptBackend backend = compiler.backend;
23 // TODO(johnniwinther): Refactor this to avoid looking up directly in the 25 // TODO(johnniwinther): Refactor this to avoid looking up directly in the
24 // js helper library but instead access helpers directly on backend helpers. 26 // js helper library but instead access helpers directly on backend helpers.
25 LibraryElement jsHelperLibrary = backend.helpers.jsHelperLibrary; 27 return new StaticUse.staticInvoke(
26 MethodElement method = jsHelperLibrary.find(name); 28 helpers.findHelperFunction(name), callStructure);
27 return new StaticUse.staticInvoke(method, callStructure);
28 } 29 }
29 30
30 CallStructure get callStructure => CallStructure.ONE_ARG; 31 CallStructure get callStructure => CallStructure.ONE_ARG;
31 32
32 jsAst.Expression generateCall( 33 jsAst.Expression generateCall(
33 SsaCodeGenerator codegen, HTypeConversion node) { 34 SsaCodeGenerator codegen, HTypeConversion node) {
34 StaticUse staticUse = getStaticUse(codegen.compiler); 35 StaticUse staticUse = getStaticUse(codegen.backend.helpers);
35 codegen.registry.registerStaticUse(staticUse); 36 codegen.registry.registerStaticUse(staticUse);
36 List<jsAst.Expression> arguments = <jsAst.Expression>[]; 37 List<jsAst.Expression> arguments = <jsAst.Expression>[];
37 codegen.use(node.checkedInput); 38 codegen.use(node.checkedInput);
38 arguments.add(codegen.pop()); 39 arguments.add(codegen.pop());
39 generateAdditionalArguments(codegen, node, arguments); 40 generateAdditionalArguments(codegen, node, arguments);
40 jsAst.Expression helper = 41 jsAst.Expression helper =
41 codegen.backend.emitter.staticFunctionAccess(staticUse.element); 42 codegen.backend.emitter.staticFunctionAccess(staticUse.element);
42 return new jsAst.Call(helper, arguments); 43 return new jsAst.Call(helper, arguments);
43 } 44 }
44 45
45 void generateAdditionalArguments(SsaCodeGenerator codegen, 46 void generateAdditionalArguments(SsaCodeGenerator codegen,
46 HTypeConversion node, List<jsAst.Expression> arguments) { 47 HTypeConversion node, List<jsAst.Expression> arguments) {
47 // No additional arguments needed. 48 // No additional arguments needed.
48 } 49 }
49
50 static const List<CheckedModeHelper> helpers = const <CheckedModeHelper>[
51 const MalformedCheckedModeHelper('checkMalformedType'),
52 const CheckedModeHelper('voidTypeCheck'),
53 const CheckedModeHelper('stringTypeCast'),
54 const CheckedModeHelper('stringTypeCheck'),
55 const CheckedModeHelper('doubleTypeCast'),
56 const CheckedModeHelper('doubleTypeCheck'),
57 const CheckedModeHelper('numTypeCast'),
58 const CheckedModeHelper('numTypeCheck'),
59 const CheckedModeHelper('boolTypeCast'),
60 const CheckedModeHelper('boolTypeCheck'),
61 const CheckedModeHelper('intTypeCast'),
62 const CheckedModeHelper('intTypeCheck'),
63 const PropertyCheckedModeHelper('numberOrStringSuperNativeTypeCast'),
64 const PropertyCheckedModeHelper('numberOrStringSuperNativeTypeCheck'),
65 const PropertyCheckedModeHelper('numberOrStringSuperTypeCast'),
66 const PropertyCheckedModeHelper('numberOrStringSuperTypeCheck'),
67 const PropertyCheckedModeHelper('stringSuperNativeTypeCast'),
68 const PropertyCheckedModeHelper('stringSuperNativeTypeCheck'),
69 const PropertyCheckedModeHelper('stringSuperTypeCast'),
70 const PropertyCheckedModeHelper('stringSuperTypeCheck'),
71 const CheckedModeHelper('listTypeCast'),
72 const CheckedModeHelper('listTypeCheck'),
73 const PropertyCheckedModeHelper('listSuperNativeTypeCast'),
74 const PropertyCheckedModeHelper('listSuperNativeTypeCheck'),
75 const PropertyCheckedModeHelper('listSuperTypeCast'),
76 const PropertyCheckedModeHelper('listSuperTypeCheck'),
77 const PropertyCheckedModeHelper('interceptedTypeCast'),
78 const PropertyCheckedModeHelper('interceptedTypeCheck'),
79 const SubtypeCheckedModeHelper('subtypeCast'),
80 const SubtypeCheckedModeHelper('assertSubtype'),
81 const TypeVariableCheckedModeHelper('subtypeOfRuntimeTypeCast'),
82 const TypeVariableCheckedModeHelper('assertSubtypeOfRuntimeType'),
83 const PropertyCheckedModeHelper('propertyTypeCast'),
84 const PropertyCheckedModeHelper('propertyTypeCheck')
85 ];
86 } 50 }
87 51
88 class MalformedCheckedModeHelper extends CheckedModeHelper { 52 class MalformedCheckedModeHelper extends CheckedModeHelper {
89 const MalformedCheckedModeHelper(String name) : super(name); 53 const MalformedCheckedModeHelper(String name) : super(name);
90 54
91 CallStructure get callStructure => CallStructure.TWO_ARGS; 55 CallStructure get callStructure => CallStructure.TWO_ARGS;
92 56
93 void generateAdditionalArguments(SsaCodeGenerator codegen, 57 void generateAdditionalArguments(SsaCodeGenerator codegen,
94 HTypeConversion node, List<jsAst.Expression> arguments) { 58 HTypeConversion node, List<jsAst.Expression> arguments) {
59 // TODO(johnniwinther): Support malformed types in [types.dart].
95 MalformedType type = node.typeExpression; 60 MalformedType type = node.typeExpression;
96 ErroneousElement element = type.element; 61 ErroneousElement element = type.element;
97 arguments.add(js.escapedString(element.message)); 62 arguments.add(js.escapedString(element.message));
98 } 63 }
99 } 64 }
100 65
101 class PropertyCheckedModeHelper extends CheckedModeHelper { 66 class PropertyCheckedModeHelper extends CheckedModeHelper {
102 const PropertyCheckedModeHelper(String name) : super(name); 67 const PropertyCheckedModeHelper(String name) : super(name);
103 68
104 CallStructure get callStructure => CallStructure.TWO_ARGS; 69 CallStructure get callStructure => CallStructure.TWO_ARGS;
105 70
106 void generateAdditionalArguments(SsaCodeGenerator codegen, 71 void generateAdditionalArguments(SsaCodeGenerator codegen,
107 HTypeConversion node, List<jsAst.Expression> arguments) { 72 HTypeConversion node, List<jsAst.Expression> arguments) {
108 ResolutionDartType type = node.typeExpression; 73 DartType type = node.typeExpression;
109 jsAst.Name additionalArgument = codegen.backend.namer.operatorIsType(type); 74 jsAst.Name additionalArgument = codegen.backend.namer.operatorIsType(type);
110 arguments.add(js.quoteName(additionalArgument)); 75 arguments.add(js.quoteName(additionalArgument));
111 } 76 }
112 } 77 }
113 78
114 class TypeVariableCheckedModeHelper extends CheckedModeHelper { 79 class TypeVariableCheckedModeHelper extends CheckedModeHelper {
115 const TypeVariableCheckedModeHelper(String name) : super(name); 80 const TypeVariableCheckedModeHelper(String name) : super(name);
116 81
117 CallStructure get callStructure => CallStructure.TWO_ARGS; 82 CallStructure get callStructure => CallStructure.TWO_ARGS;
118 83
119 void generateAdditionalArguments(SsaCodeGenerator codegen, 84 void generateAdditionalArguments(SsaCodeGenerator codegen,
120 HTypeConversion node, List<jsAst.Expression> arguments) { 85 HTypeConversion node, List<jsAst.Expression> arguments) {
121 assert(node.typeExpression.isTypeVariable); 86 assert(node.typeExpression.isTypeVariable);
122 codegen.use(node.typeRepresentation); 87 codegen.use(node.typeRepresentation);
123 arguments.add(codegen.pop()); 88 arguments.add(codegen.pop());
124 } 89 }
125 } 90 }
126 91
127 class SubtypeCheckedModeHelper extends CheckedModeHelper { 92 class SubtypeCheckedModeHelper extends CheckedModeHelper {
128 const SubtypeCheckedModeHelper(String name) : super(name); 93 const SubtypeCheckedModeHelper(String name) : super(name);
129 94
130 CallStructure get callStructure => const CallStructure.unnamed(4); 95 CallStructure get callStructure => const CallStructure.unnamed(4);
131 96
132 void generateAdditionalArguments(SsaCodeGenerator codegen, 97 void generateAdditionalArguments(SsaCodeGenerator codegen,
133 HTypeConversion node, List<jsAst.Expression> arguments) { 98 HTypeConversion node, List<jsAst.Expression> arguments) {
134 ResolutionDartType type = node.typeExpression; 99 InterfaceType type = node.typeExpression;
135 Element element = type.element; 100 ClassEntity element = type.element;
136 jsAst.Name isField = codegen.backend.namer.operatorIs(element); 101 jsAst.Name isField = codegen.backend.namer.operatorIs(element);
137 arguments.add(js.quoteName(isField)); 102 arguments.add(js.quoteName(isField));
138 codegen.use(node.typeRepresentation); 103 codegen.use(node.typeRepresentation);
139 arguments.add(codegen.pop()); 104 arguments.add(codegen.pop());
140 jsAst.Name asField = codegen.backend.namer.substitutionName(element); 105 jsAst.Name asField = codegen.backend.namer.substitutionName(element);
141 arguments.add(js.quoteName(asField)); 106 arguments.add(js.quoteName(asField));
142 } 107 }
143 } 108 }
109
110 class CheckedModeHelpers {
111 final CommonElements _commonElements;
112 final BackendHelpers _helpers;
113
114 CheckedModeHelpers(this._commonElements, this._helpers);
115
116 /// All the checked mode helpers.
117 static const List<CheckedModeHelper> helpers = const <CheckedModeHelper>[
118 const MalformedCheckedModeHelper('checkMalformedType'),
119 const CheckedModeHelper('voidTypeCheck'),
120 const CheckedModeHelper('stringTypeCast'),
121 const CheckedModeHelper('stringTypeCheck'),
122 const CheckedModeHelper('doubleTypeCast'),
123 const CheckedModeHelper('doubleTypeCheck'),
124 const CheckedModeHelper('numTypeCast'),
125 const CheckedModeHelper('numTypeCheck'),
126 const CheckedModeHelper('boolTypeCast'),
127 const CheckedModeHelper('boolTypeCheck'),
128 const CheckedModeHelper('intTypeCast'),
129 const CheckedModeHelper('intTypeCheck'),
130 const PropertyCheckedModeHelper('numberOrStringSuperNativeTypeCast'),
131 const PropertyCheckedModeHelper('numberOrStringSuperNativeTypeCheck'),
132 const PropertyCheckedModeHelper('numberOrStringSuperTypeCast'),
133 const PropertyCheckedModeHelper('numberOrStringSuperTypeCheck'),
134 const PropertyCheckedModeHelper('stringSuperNativeTypeCast'),
135 const PropertyCheckedModeHelper('stringSuperNativeTypeCheck'),
136 const PropertyCheckedModeHelper('stringSuperTypeCast'),
137 const PropertyCheckedModeHelper('stringSuperTypeCheck'),
138 const CheckedModeHelper('listTypeCast'),
139 const CheckedModeHelper('listTypeCheck'),
140 const PropertyCheckedModeHelper('listSuperNativeTypeCast'),
141 const PropertyCheckedModeHelper('listSuperNativeTypeCheck'),
142 const PropertyCheckedModeHelper('listSuperTypeCast'),
143 const PropertyCheckedModeHelper('listSuperTypeCheck'),
144 const PropertyCheckedModeHelper('interceptedTypeCast'),
145 const PropertyCheckedModeHelper('interceptedTypeCheck'),
146 const SubtypeCheckedModeHelper('subtypeCast'),
147 const SubtypeCheckedModeHelper('assertSubtype'),
148 const TypeVariableCheckedModeHelper('subtypeOfRuntimeTypeCast'),
149 const TypeVariableCheckedModeHelper('assertSubtypeOfRuntimeType'),
150 const PropertyCheckedModeHelper('propertyTypeCast'),
151 const PropertyCheckedModeHelper('propertyTypeCheck'),
152 ];
153
154 // Checked mode helpers indexed by name.
155 static final Map<String, CheckedModeHelper> checkedModeHelperByName =
156 new Map<String, CheckedModeHelper>.fromIterable(helpers,
157 key: (helper) => helper.name);
158
159 /**
160 * Returns the checked mode helper that will be needed to do a type check/type
161 * cast on [type] at runtime. Note that this method is being called both by
162 * the resolver with interface types (int, String, ...), and by the SSA
163 * backend with implementation types (JSInt, JSString, ...).
164 */
165 CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) {
166 return getCheckedModeHelperInternal(type,
167 typeCast: typeCast, nativeCheckOnly: false);
168 }
169
170 /**
171 * Returns the native checked mode helper that will be needed to do a type
172 * check/type cast on [type] at runtime. If no native helper exists for
173 * [type], [:null:] is returned.
174 */
175 CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) {
176 return getCheckedModeHelperInternal(type,
177 typeCast: typeCast, nativeCheckOnly: true);
178 }
179
180 /**
181 * Returns the checked mode helper for the type check/type cast for [type]. If
182 * [nativeCheckOnly] is [:true:], only names for native helpers are returned.
183 */
184 CheckedModeHelper getCheckedModeHelperInternal(DartType type,
185 {bool typeCast, bool nativeCheckOnly}) {
186 String name = getCheckedModeHelperNameInternal(type,
187 typeCast: typeCast, nativeCheckOnly: nativeCheckOnly);
188 if (name == null) return null;
189 CheckedModeHelper helper = checkedModeHelperByName[name];
190 assert(helper != null);
191 return helper;
192 }
193
194 String getCheckedModeHelperNameInternal(DartType type,
195 {bool typeCast, bool nativeCheckOnly}) {
196 assert(!type.isTypedef);
197 if (type.isMalformed) {
198 // The same error is thrown for type test and type cast of a malformed
199 // type so we only need one check method.
200 return 'checkMalformedType';
201 }
202
203 if (type.isVoid) {
204 assert(!typeCast); // Cannot cast to void.
205 if (nativeCheckOnly) return null;
206 return 'voidTypeCheck';
207 }
208
209 if (type.isTypeVariable) {
210 return typeCast
211 ? 'subtypeOfRuntimeTypeCast'
212 : 'assertSubtypeOfRuntimeType';
213 }
214
215 if (type.isFunctionType) return null;
216
217 assert(invariant(NO_LOCATION_SPANNABLE, type.isInterfaceType,
218 message: "Unexpected type: $type"));
219 InterfaceType interfaceType = type;
220 ClassEntity element = interfaceType.element;
221 bool nativeCheck = true;
222 // TODO(13955), TODO(9731). The test for non-primitive types should use an
223 // interceptor. The interceptor should be an argument to HTypeConversion so
224 // that it can be optimized by standard interceptor optimizations.
225 // nativeCheckOnly || emitter.nativeEmitter.requiresNativeIsCheck(element);
226
227 var suffix = typeCast ? 'TypeCast' : 'TypeCheck';
228 if (element == _helpers.jsStringClass ||
229 element == _commonElements.stringClass) {
230 if (nativeCheckOnly) return null;
231 return 'string$suffix';
232 }
233
234 if (element == _helpers.jsDoubleClass ||
235 element == _commonElements.doubleClass) {
236 if (nativeCheckOnly) return null;
237 return 'double$suffix';
238 }
239
240 if (element == _helpers.jsNumberClass ||
241 element == _commonElements.numClass) {
242 if (nativeCheckOnly) return null;
243 return 'num$suffix';
244 }
245
246 if (element == _helpers.jsBoolClass ||
247 element == _commonElements.boolClass) {
248 if (nativeCheckOnly) return null;
249 return 'bool$suffix';
250 }
251
252 if (element == _helpers.jsIntClass ||
253 element == _commonElements.intClass ||
254 element == _helpers.jsUInt32Class ||
255 element == _helpers.jsUInt31Class ||
256 element == _helpers.jsPositiveIntClass) {
257 if (nativeCheckOnly) return null;
258 return 'int$suffix';
259 }
260
261 if (_commonElements.isNumberOrStringSupertype(element)) {
262 return nativeCheck
263 ? 'numberOrStringSuperNative$suffix'
264 : 'numberOrStringSuper$suffix';
265 }
266
267 if (_commonElements.isStringOnlySupertype(element)) {
268 return nativeCheck ? 'stringSuperNative$suffix' : 'stringSuper$suffix';
269 }
270
271 if ((element == _commonElements.listClass ||
272 element == _helpers.jsArrayClass) &&
273 type.treatAsRaw) {
274 if (nativeCheckOnly) return null;
275 return 'list$suffix';
276 }
277
278 if (_commonElements.isListSupertype(element)) {
279 return nativeCheck ? 'listSuperNative$suffix' : 'listSuper$suffix';
280 }
281
282 if (type.isInterfaceType && !type.treatAsRaw) {
283 return typeCast ? 'subtypeCast' : 'assertSubtype';
284 }
285
286 if (nativeCheck) {
287 // TODO(karlklose): can we get rid of this branch when we use
288 // interceptors?
289 return 'intercepted$suffix';
290 } else {
291 return 'property$suffix';
292 }
293 }
294 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend_usage.dart ('k') | pkg/compiler/lib/src/js_backend/mirrors_analysis.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698