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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2984183002: dart2js-kernel: Recognize some List constructors. (Closed)
Patch Set: Created 3 years, 5 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
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/graph_builder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
6 6
7 import '../closure.dart'; 7 import '../closure.dart';
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common/codegen.dart' show CodegenRegistry; 9 import '../common/codegen.dart' show CodegenRegistry;
10 import '../common/names.dart'; 10 import '../common/names.dart';
(...skipping 1998 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 HInstruction listInstruction; 2009 HInstruction listInstruction;
2010 if (listLiteral.isConst) { 2010 if (listLiteral.isConst) {
2011 listInstruction = graph.addConstant( 2011 listInstruction = graph.addConstant(
2012 _elementMap.getConstantValue(listLiteral), closedWorld); 2012 _elementMap.getConstantValue(listLiteral), closedWorld);
2013 } else { 2013 } else {
2014 List<HInstruction> elements = <HInstruction>[]; 2014 List<HInstruction> elements = <HInstruction>[];
2015 for (ir.Expression element in listLiteral.expressions) { 2015 for (ir.Expression element in listLiteral.expressions) {
2016 element.accept(this); 2016 element.accept(this);
2017 elements.add(pop()); 2017 elements.add(pop());
2018 } 2018 }
2019 listInstruction = 2019 listInstruction = buildLiteralList(elements);
2020 new HLiteralList(elements, commonMasks.extendableArrayType);
2021 add(listInstruction); 2020 add(listInstruction);
2022 InterfaceType type = localsHandler.substInContext(_commonElements 2021 InterfaceType type = localsHandler.substInContext(_commonElements
2023 .listType(_elementMap.getDartType(listLiteral.typeArgument))); 2022 .listType(_elementMap.getDartType(listLiteral.typeArgument)));
2024 listInstruction = _setListRuntimeTypeInfoIfNeeded(listInstruction, type); 2023 listInstruction = _setListRuntimeTypeInfoIfNeeded(listInstruction, type);
2025 } 2024 }
2026 2025
2027 TypeMask type = _typeInferenceMap.typeOfListLiteral( 2026 TypeMask type = _typeInferenceMap.typeOfListLiteral(
2028 targetElement, listLiteral, closedWorld); 2027 targetElement, listLiteral, closedWorld);
2029 if (!type.containsAll(closedWorld)) { 2028 if (!type.containsAll(closedWorld)) {
2030 listInstruction.instructionType = type; 2029 listInstruction.instructionType = type;
(...skipping 17 matching lines...) Expand all
2048 constructorArgs.add(pop()); 2047 constructorArgs.add(pop());
2049 } 2048 }
2050 2049
2051 // The constructor is a procedure because it's a factory. 2050 // The constructor is a procedure because it's a factory.
2052 FunctionEntity constructor; 2051 FunctionEntity constructor;
2053 List<HInstruction> inputs = <HInstruction>[]; 2052 List<HInstruction> inputs = <HInstruction>[];
2054 if (constructorArgs.isEmpty) { 2053 if (constructorArgs.isEmpty) {
2055 constructor = _commonElements.mapLiteralConstructorEmpty; 2054 constructor = _commonElements.mapLiteralConstructorEmpty;
2056 } else { 2055 } else {
2057 constructor = _commonElements.mapLiteralConstructor; 2056 constructor = _commonElements.mapLiteralConstructor;
2058 HLiteralList argList = 2057 HLiteralList argList = buildLiteralList(constructorArgs);
2059 new HLiteralList(constructorArgs, commonMasks.extendableArrayType);
2060 add(argList); 2058 add(argList);
2061 inputs.add(argList); 2059 inputs.add(argList);
2062 } 2060 }
2063 2061
2064 assert( 2062 assert(
2065 constructor is ConstructorEntity && constructor.isFactoryConstructor); 2063 constructor is ConstructorEntity && constructor.isFactoryConstructor);
2066 2064
2067 InterfaceType type = localsHandler.substInContext(_commonElements.mapType( 2065 InterfaceType type = localsHandler.substInContext(_commonElements.mapType(
2068 _elementMap.getDartType(mapLiteral.keyType), 2066 _elementMap.getDartType(mapLiteral.keyType),
2069 _elementMap.getDartType(mapLiteral.valueType))); 2067 _elementMap.getDartType(mapLiteral.valueType)));
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
2397 return; 2395 return;
2398 } 2396 }
2399 FunctionEntity function = _elementMap.getMember(target); 2397 FunctionEntity function = _elementMap.getMember(target);
2400 TypeMask typeMask = _typeInferenceMap.getReturnTypeOf(function); 2398 TypeMask typeMask = _typeInferenceMap.getReturnTypeOf(function);
2401 2399
2402 // TODO(sra): For JS interop external functions, use a different function to 2400 // TODO(sra): For JS interop external functions, use a different function to
2403 // build arguments. 2401 // build arguments.
2404 List<HInstruction> arguments = 2402 List<HInstruction> arguments =
2405 _visitArgumentsForStaticTarget(target.function, invocation.arguments); 2403 _visitArgumentsForStaticTarget(target.function, invocation.arguments);
2406 2404
2407 // TODO(johnniwinther): Move factory calls to a helper function?
2408 if (function is ConstructorEntity && function.isFactoryConstructor) { 2405 if (function is ConstructorEntity && function.isFactoryConstructor) {
2409 if (function.isExternal && function.isFromEnvironmentConstructor) { 2406 if (function.isExternal && function.isFromEnvironmentConstructor) {
Siggi Cherem (dart-lang) 2017/07/25 16:54:45 nit: consider moving this at the beginning of hand
sra1 2017/07/25 20:08:15 Done.
2410 if (invocation.isConst) { 2407 if (invocation.isConst) {
2411 // Just like all const constructors (see visitConstructorInvocation). 2408 // Just like all const constructors (see visitConstructorInvocation).
2412 stack.add(graph.addConstant( 2409 stack.add(graph.addConstant(
2413 _elementMap.getConstantValue(invocation), closedWorld)); 2410 _elementMap.getConstantValue(invocation), closedWorld));
2414 } else { 2411 } else {
2415 generateUnsupportedError( 2412 generateUnsupportedError(
2416 invocation, 2413 invocation,
2417 '${function.enclosingClass.name}.${function.name} ' 2414 '${function.enclosingClass.name}.${function.name} '
2418 'can only be used as a const constructor'); 2415 'can only be used as a const constructor');
2419 } 2416 }
2420 return; 2417 return;
2421 } 2418 }
2422 2419
2423 // Factory constructors take type parameters; other static methods ignore 2420 handleInvokeFactoryConstructor(invocation, function, typeMask, arguments);
2424 // them. 2421 return;
2422 }
2425 2423
2424 // Static methods currently ignore the type parameters.
2425 _pushStaticInvocation(function, arguments, typeMask);
2426 }
2427
2428 void handleInvokeFactoryConstructor(
2429 ir.StaticInvocation invocation,
2430 FunctionEntity function,
2431 TypeMask typeMask,
2432 List<HInstruction> arguments) {
2433 bool isFixedList = false; // Any fixed list, e.g. new List(10), UInt8List.
2434
2435 // Recognize `new List()` and `new List(n)`.
2436 bool isFixedListConstructorCall = false;
2437 bool isGrowableListConstructorCall = false;
2438 if (commonElements.isUnnamedListConstructor(function) &&
2439 invocation.arguments.named.isEmpty) {
2440 int argumentCount = invocation.arguments.positional.length;
2441 isFixedListConstructorCall = argumentCount == 1;
2442 isGrowableListConstructorCall = argumentCount == 0;
2443 isFixedList = isFixedListConstructorCall;
2444 }
2445
2446 TypeMask resultType = typeMask;
2447
2448 bool isJSArrayTypedConstructor =
2449 function == commonElements.jsArrayTypedConstructor;
2450
2451 if (isFixedListConstructorCall) {
2452 assert(arguments.length == 1);
2453 HInstruction lengthInput = arguments.first;
2454 if (!lengthInput.isNumber(closedWorld)) {
2455 HTypeConversion conversion = new HTypeConversion(
2456 null,
2457 HTypeConversion.ARGUMENT_TYPE_CHECK,
2458 commonMasks.numType,
2459 lengthInput);
2460 add(conversion);
2461 lengthInput = conversion;
2462 }
2463 js.Template code = js.js.parseForeignJS('new Array(#)');
2464 var behavior = new native.NativeBehavior();
2465 // TODO(sra): Find the full type being created here, e.g. JSArray<Set<T>>.
2466 var expectedType = commonElements.listType();
2467 behavior.typesInstantiated.add(expectedType);
2468 behavior.typesReturned.add(expectedType);
2469
2470 // The allocation can throw only if the given length is a double or
2471 // outside the unsigned 32 bit range.
2472 // TODO(sra): Array allocation should be an instruction so that canThrow
2473 // can depend on a length type discovered in optimization.
2474 bool canThrow = true;
2475 if (lengthInput.isUInt32(closedWorld)) {
2476 canThrow = false;
2477 }
2478
2479 // TODO(sra): Pick up type inference type, which might be more precise,
2480 // e.g. a container type.
2481 resultType = commonMasks.fixedListType;
2482 HForeignCode foreign = new HForeignCode(code, resultType, arguments,
2483 nativeBehavior: behavior,
2484 throwBehavior: canThrow
2485 ? native.NativeThrowBehavior.MAY
2486 : native.NativeThrowBehavior.NEVER);
2487 push(foreign);
2488 // TODO(sra): Global type analysis tracing may have determined that the
2489 // fixed-length property is never checked. If so, we can avoid marking the
2490 // array.
2491 if (true) {
Siggi Cherem (dart-lang) 2017/07/25 16:54:45 (no action required) In case you were considering
sra1 2017/07/25 20:08:15 Done.
2492 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array');
2493 // We set the instruction as [canThrow] to avoid it being dead code.
2494 // We need a finer grained side effect.
2495 add(new HForeignCode(code, commonMasks.nullType, [stack.last],
2496 throwBehavior: native.NativeThrowBehavior.MAY));
2497 }
2498 } else if (isGrowableListConstructorCall) {
2499 push(buildLiteralList(<HInstruction>[]));
2500 // TODO(sra): Pick up type inference type, which might be more precise,
Siggi Cherem (dart-lang) 2017/07/25 16:54:45 consider using "TODO(redemption)" (so we can grep
sra1 2017/07/25 20:08:16 Done.
2501 // e.g. a container type.
2502 resultType = commonMasks.growableListType;
2503 stack.last.instructionType = resultType;
2504 } else if (isJSArrayTypedConstructor) {
2505 // TODO(sra): Instead of calling the identity-like factory constructor,
2506 // simply select the single argument.
2507 // Factory constructors take type parameters.
2426 if (closedWorld.rtiNeed.classNeedsRti(function.enclosingClass)) { 2508 if (closedWorld.rtiNeed.classNeedsRti(function.enclosingClass)) {
2427 _addTypeArguments(arguments, invocation.arguments); 2509 _addTypeArguments(arguments, invocation.arguments);
2428 } 2510 }
2429
2430 _pushStaticInvocation(function, arguments, typeMask); 2511 _pushStaticInvocation(function, arguments, typeMask);
2431 2512 } else {
2432 bool isFixedListConstructorCall = false; 2513 // Factory constructors take type parameters.
2433 bool isGrowableListConstructorCall = false; 2514 if (closedWorld.rtiNeed.classNeedsRti(function.enclosingClass)) {
2434 if (commonElements.isUnnamedListConstructor(function) && 2515 _addTypeArguments(arguments, invocation.arguments);
2435 invocation.arguments.named.isEmpty) {
2436 isFixedListConstructorCall =
2437 invocation.arguments.positional.length == 1;
2438 isGrowableListConstructorCall = invocation.arguments.positional.isEmpty;
2439 } 2516 }
2440 bool isJSArrayTypedConstructor =
2441 function == commonElements.jsArrayTypedConstructor;
2442 if (rtiNeed.classNeedsRti(commonElements.listClass) &&
2443 (isFixedListConstructorCall ||
2444 isGrowableListConstructorCall ||
2445 isJSArrayTypedConstructor)) {
2446 InterfaceType type = _elementMap.createInterfaceType(
2447 target.enclosingClass, invocation.arguments.types);
2448 stack.add(_setListRuntimeTypeInfoIfNeeded(pop(), type));
2449 }
2450 } else {
2451 _pushStaticInvocation(function, arguments, typeMask); 2517 _pushStaticInvocation(function, arguments, typeMask);
2452 } 2518 }
2519
2520 HInstruction newInstance = stack.last;
2521
2522 if (isFixedList) {
2523 // If we inlined a constructor the call-site-specific type from type
2524 // inference (e.g. a container type) will not be on the node. Store the
2525 // more specialized type on the allocation.
2526 newInstance.instructionType = resultType;
2527 graph.allocatedFixedLists.add(newInstance);
2528 }
2529
2530 if (rtiNeed.classNeedsRti(commonElements.listClass) &&
2531 (isFixedListConstructorCall ||
2532 isGrowableListConstructorCall ||
2533 isJSArrayTypedConstructor)) {
2534 InterfaceType type = _elementMap.createInterfaceType(
2535 invocation.target.enclosingClass, invocation.arguments.types);
2536 stack.add(_setListRuntimeTypeInfoIfNeeded(pop(), type));
2537 }
2538
2539 // TODO(sra): For redirecting factory constructors, check or trust the type.
2453 } 2540 }
2454 2541
2455 void handleInvokeStaticForeign( 2542 void handleInvokeStaticForeign(
2456 ir.StaticInvocation invocation, ir.Procedure target) { 2543 ir.StaticInvocation invocation, ir.Procedure target) {
2457 String name = target.name.name; 2544 String name = target.name.name;
2458 if (name == 'JS') { 2545 if (name == 'JS') {
2459 handleForeignJs(invocation); 2546 handleForeignJs(invocation);
2460 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { 2547 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
2461 handleForeignJsCurrentIsolateContext(invocation); 2548 handleForeignJsCurrentIsolateContext(invocation);
2462 } else if (name == 'JS_CALL_IN_ISOLATE') { 2549 } else if (name == 'JS_CALL_IN_ISOLATE') {
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
3017 // arguments), in case the [noSuchMethod] implementation calls 3104 // arguments), in case the [noSuchMethod] implementation calls
3018 // [JSInvocationMirror._invokeOn]. 3105 // [JSInvocationMirror._invokeOn].
3019 // TODO(johnniwinther): Register this more precisely. 3106 // TODO(johnniwinther): Register this more precisely.
3020 registry?.registerDynamicUse(new DynamicUse(selector, null)); 3107 registry?.registerDynamicUse(new DynamicUse(selector, null));
3021 } 3108 }
3022 3109
3023 ConstantValue nameConstant = constantSystem.createString(publicName); 3110 ConstantValue nameConstant = constantSystem.createString(publicName);
3024 3111
3025 js.Name internalName = namer.invocationName(selector); 3112 js.Name internalName = namer.invocationName(selector);
3026 3113
3027 var argumentsInstruction = 3114 var argumentsInstruction = buildLiteralList(arguments);
3028 new HLiteralList(arguments, commonMasks.extendableArrayType);
3029 add(argumentsInstruction); 3115 add(argumentsInstruction);
3030 3116
3031 var argumentNames = new List<HInstruction>(); 3117 var argumentNames = new List<HInstruction>();
3032 for (String argumentName in selector.namedArguments) { 3118 for (String argumentName in selector.namedArguments) {
3033 ConstantValue argumentNameConstant = 3119 ConstantValue argumentNameConstant =
3034 constantSystem.createString(argumentName); 3120 constantSystem.createString(argumentName);
3035 argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld)); 3121 argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld));
3036 } 3122 }
3037 var argumentNamesInstruction = 3123 var argumentNamesInstruction = buildLiteralList(argumentNames);
3038 new HLiteralList(argumentNames, commonMasks.extendableArrayType);
3039 add(argumentNamesInstruction); 3124 add(argumentNamesInstruction);
3040 3125
3041 ConstantValue kindConstant = 3126 ConstantValue kindConstant =
3042 constantSystem.createInt(selector.invocationMirrorKind); 3127 constantSystem.createInt(selector.invocationMirrorKind);
3043 3128
3044 _pushStaticInvocation( 3129 _pushStaticInvocation(
3045 _commonElements.createInvocationMirror, 3130 _commonElements.createInvocationMirror,
3046 [ 3131 [
3047 graph.addConstant(nameConstant, closedWorld), 3132 graph.addConstant(nameConstant, closedWorld),
3048 graph.addConstantStringFromName(internalName, closedWorld), 3133 graph.addConstantStringFromName(internalName, closedWorld),
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
3563 enterBlock.setBlockFlow( 3648 enterBlock.setBlockFlow(
3564 new HTryBlockInformation( 3649 new HTryBlockInformation(
3565 kernelBuilder.wrapStatementGraph(bodyGraph), 3650 kernelBuilder.wrapStatementGraph(bodyGraph),
3566 exception, 3651 exception,
3567 kernelBuilder.wrapStatementGraph(catchGraph), 3652 kernelBuilder.wrapStatementGraph(catchGraph),
3568 kernelBuilder.wrapStatementGraph(finallyGraph)), 3653 kernelBuilder.wrapStatementGraph(finallyGraph)),
3569 exitBlock); 3654 exitBlock);
3570 kernelBuilder.inTryStatement = previouslyInTryStatement; 3655 kernelBuilder.inTryStatement = previouslyInTryStatement;
3571 } 3656 }
3572 } 3657 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/graph_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698