Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |