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

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

Issue 1525163002: dart2js cps: Use oneshot interceptors and 'instanceof' expressions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Merge Created 5 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library code_generator; 5 library code_generator;
6 6
7 import 'glue.dart'; 7 import 'glue.dart';
8 8
9 import '../../closure.dart' show 9 import '../../closure.dart' show
10 ClosureClassElement; 10 ClosureClassElement;
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 274
275 registry.registerInstantiation(node.type); 275 registry.registerInstantiation(node.type);
276 FunctionElement target = node.target; 276 FunctionElement target = node.target;
277 List<js.Expression> arguments = visitExpressionList(node.arguments); 277 List<js.Expression> arguments = visitExpressionList(node.arguments);
278 return buildStaticInvoke( 278 return buildStaticInvoke(
279 target, 279 target,
280 arguments, 280 arguments,
281 sourceInformation: node.sourceInformation); 281 sourceInformation: node.sourceInformation);
282 } 282 }
283 283
284 void registerMethodInvoke(tree_ir.InvokeMethod node) { 284 void registerMethodInvoke(Selector selector, TypeMask receiverType) {
285 Selector selector = node.selector; 285 registry.registerDynamicUse(new DynamicUse(selector, receiverType));
286 TypeMask mask = node.mask; 286 if (!selector.isGetter && !selector.isSetter) {
287 mask = glue.extendMaskIfReachesAll(selector, mask);
288 if (selector.isGetter) {
289 registry.registerDynamicUse(new DynamicUse(selector, mask));
290 } else if (selector.isSetter) {
291 registry.registerDynamicUse(new DynamicUse(selector, mask));
292 } else {
293 assert(invariant(CURRENT_ELEMENT_SPANNABLE,
294 selector.isCall || selector.isOperator ||
295 selector.isIndex || selector.isIndexSet,
296 message: 'unexpected kind ${selector.kind}'));
297 // TODO(sigurdm): We should find a better place to register the call. 287 // TODO(sigurdm): We should find a better place to register the call.
298 Selector call = new Selector.callClosureFrom(selector); 288 Selector call = new Selector.callClosureFrom(selector);
299 registry.registerDynamicUse(new DynamicUse(call, null)); 289 registry.registerDynamicUse(new DynamicUse(call, null));
300 registry.registerDynamicUse(new DynamicUse(selector, mask));
301 } 290 }
302 } 291 }
303 292
304 @override 293 @override
305 js.Expression visitInvokeMethod(tree_ir.InvokeMethod node) { 294 js.Expression visitInvokeMethod(tree_ir.InvokeMethod node) {
306 registerMethodInvoke(node); 295 TypeMask mask = glue.extendMaskIfReachesAll(node.selector, node.mask);
296 registerMethodInvoke(node.selector, mask);
307 return js.propertyCall(visitExpression(node.receiver), 297 return js.propertyCall(visitExpression(node.receiver),
308 glue.invocationName(node.selector), 298 glue.invocationName(node.selector),
309 visitExpressionList(node.arguments)) 299 visitExpressionList(node.arguments))
310 .withSourceInformation(node.sourceInformation); 300 .withSourceInformation(node.sourceInformation);
311 } 301 }
312 302
313 @override 303 @override
314 js.Expression visitInvokeStatic(tree_ir.InvokeStatic node) { 304 js.Expression visitInvokeStatic(tree_ir.InvokeStatic node) {
315 FunctionElement target = node.target; 305 FunctionElement target = node.target;
316 List<js.Expression> arguments = visitExpressionList(node.arguments); 306 List<js.Expression> arguments = visitExpressionList(node.arguments);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 new CallStructure.unnamed(node.arguments.length))); 338 new CallStructure.unnamed(node.arguments.length)));
349 return js.js('#.#.call(#, #)', 339 return js.js('#.#.call(#, #)',
350 [glue.prototypeAccess(node.target.enclosingClass), 340 [glue.prototypeAccess(node.target.enclosingClass),
351 glue.invocationName(node.selector), 341 glue.invocationName(node.selector),
352 visitExpression(node.receiver), 342 visitExpression(node.receiver),
353 visitExpressionList(node.arguments)]) 343 visitExpressionList(node.arguments)])
354 .withSourceInformation(node.sourceInformation); 344 .withSourceInformation(node.sourceInformation);
355 } 345 }
356 346
357 @override 347 @override
348 js.Expression visitOneShotInterceptor(tree_ir.OneShotInterceptor node) {
349 registerMethodInvoke(node.selector, node.mask);
350 registry.registerUseInterceptor();
351 return js.js('#.#(#)',
352 [glue.getInterceptorLibrary(),
353 glue.registerOneShotInterceptor(node.selector),
354 visitExpressionList(node.arguments)])
355 .withSourceInformation(node.sourceInformation);
356 }
357
358 @override
358 js.Expression visitLiteralList(tree_ir.LiteralList node) { 359 js.Expression visitLiteralList(tree_ir.LiteralList node) {
359 registry.registerInstantiatedClass(glue.listClass); 360 registry.registerInstantiatedClass(glue.listClass);
360 List<js.Expression> entries = visitExpressionList(node.values); 361 List<js.Expression> entries = visitExpressionList(node.values);
361 return new js.ArrayInitializer(entries); 362 return new js.ArrayInitializer(entries);
362 } 363 }
363 364
364 @override 365 @override
365 js.Expression visitLiteralMap(tree_ir.LiteralMap node) { 366 js.Expression visitLiteralMap(tree_ir.LiteralMap node) {
366 ConstructorElement constructor; 367 ConstructorElement constructor;
367 if (node.entries.isEmpty) { 368 if (node.entries.isEmpty) {
(...skipping 24 matching lines...) Expand all
392 @override 393 @override
393 js.Expression visitNot(tree_ir.Not node) { 394 js.Expression visitNot(tree_ir.Not node) {
394 return new js.Prefix("!", visitExpression(node.operand)); 395 return new js.Prefix("!", visitExpression(node.operand));
395 } 396 }
396 397
397 @override 398 @override
398 js.Expression visitThis(tree_ir.This node) { 399 js.Expression visitThis(tree_ir.This node) {
399 return new js.This(); 400 return new js.This();
400 } 401 }
401 402
403 /// Ensure that 'instanceof' checks may be performed against [class_].
404 ///
405 /// Even if the class is never instantiated, a JS constructor must be emitted
406 /// so the 'instanceof' expression does not throw an exception at runtime.
407 ///
408 /// It does not help to ask the class world if the class is instantiated,
409 /// because it could still get tree-shaken if it is unused after optimization.
410 void registerInstanceofCheck(ClassElement class_) {
411 // TODO(asgerf): This is the only hook we have to ensure the JS constructor
412 // gets emitted, but it is very imprecise. We should do better.
413 registry.registerInstantiatedClass(class_);
414 }
415
402 @override 416 @override
403 js.Expression visitTypeOperator(tree_ir.TypeOperator node) { 417 js.Expression visitTypeOperator(tree_ir.TypeOperator node) {
404 js.Expression value = visitExpression(node.value); 418 js.Expression value = visitExpression(node.value);
405 List<js.Expression> typeArguments = visitExpressionList(node.typeArguments); 419 List<js.Expression> typeArguments = visitExpressionList(node.typeArguments);
406 DartType type = node.type; 420 DartType type = node.type;
407 if (type is InterfaceType) { 421 if (type is InterfaceType) {
408 registry.registerTypeUse(new TypeUse.isCheck(type)); 422 registry.registerTypeUse(new TypeUse.isCheck(type));
409 //glue.registerIsCheck(type, registry);
410 ClassElement clazz = type.element; 423 ClassElement clazz = type.element;
411 424
412 if (glue.isStringClass(clazz)) { 425 if (glue.isStringClass(clazz)) {
413 if (node.isTypeTest) { 426 if (node.isTypeTest) {
414 return js.js(r'typeof # === "string"', <js.Expression>[value]); 427 return js.js(r'typeof # === "string"', <js.Expression>[value]);
415 } 428 }
416 // TODO(sra): Implement fast cast via calling 'stringTypeCast'. 429 // TODO(sra): Implement fast cast via calling 'stringTypeCast'.
417 } else if (glue.isBoolClass(clazz)) { 430 } else if (glue.isBoolClass(clazz)) {
418 if (node.isTypeTest) { 431 if (node.isTypeTest) {
419 return js.js(r'typeof # === "boolean"', <js.Expression>[value]); 432 return js.js(r'typeof # === "boolean"', <js.Expression>[value]);
420 } 433 }
421 // TODO(sra): Implement fast cast via calling 'boolTypeCast'. 434 // TODO(sra): Implement fast cast via calling 'boolTypeCast'.
435 } else if (node.isTypeTest &&
436 node.typeArguments.isEmpty &&
437 glue.mayGenerateInstanceofCheck(type)) {
438 registerInstanceofCheck(clazz);
439 return js.js('# instanceof #', [value, glue.constructorAccess(clazz)]);
422 } 440 }
423 441
424 // The helper we use needs the JSArray class to exist, but for some 442 // The helper we use needs the JSArray class to exist, but for some
425 // reason the helper does not cause this dependency to be registered. 443 // reason the helper does not cause this dependency to be registered.
426 // TODO(asgerf): Most programs need List anyway, but we should fix this. 444 // TODO(asgerf): Most programs need List anyway, but we should fix this.
427 registry.registerInstantiatedClass(glue.listClass); 445 registry.registerInstantiatedClass(glue.listClass);
428 446
429 // We use one of the two helpers: 447 // We use one of the two helpers:
430 // 448 //
431 // checkSubtype(value, $isT, typeArgs, $asT) 449 // checkSubtype(value, $isT, typeArgs, $asT)
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 void registerDefaultParameterValues(ExecutableElement element) { 1158 void registerDefaultParameterValues(ExecutableElement element) {
1141 if (element is! FunctionElement) return; 1159 if (element is! FunctionElement) return;
1142 FunctionElement function = element; 1160 FunctionElement function = element;
1143 if (function.isStatic) return; // Defaults are inlined at call sites. 1161 if (function.isStatic) return; // Defaults are inlined at call sites.
1144 function.functionSignature.forEachOptionalParameter((param) { 1162 function.functionSignature.forEachOptionalParameter((param) {
1145 ConstantValue constant = glue.getDefaultParameterValue(param); 1163 ConstantValue constant = glue.getDefaultParameterValue(param);
1146 registry.registerCompileTimeConstant(constant); 1164 registry.registerCompileTimeConstant(constant);
1147 }); 1165 });
1148 } 1166 }
1149 } 1167 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/glue.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698