| OLD | NEW |
| 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 class SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
| 8 | 8 |
| 9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
| 10 | 10 |
| (...skipping 2445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2456 js.Binary notObjectOrIndexingTest = | 2456 js.Binary notObjectOrIndexingTest = |
| 2457 new js.Binary('||', objectTest, notIndexingTest); | 2457 new js.Binary('||', objectTest, notIndexingTest); |
| 2458 test = new js.Binary('&&', stringTest, notObjectOrIndexingTest); | 2458 test = new js.Binary('&&', stringTest, notObjectOrIndexingTest); |
| 2459 } else { | 2459 } else { |
| 2460 compiler.internalError('Unexpected type guard', instruction: input); | 2460 compiler.internalError('Unexpected type guard', instruction: input); |
| 2461 } | 2461 } |
| 2462 return test; | 2462 return test; |
| 2463 } | 2463 } |
| 2464 | 2464 |
| 2465 void visitTypeConversion(HTypeConversion node) { | 2465 void visitTypeConversion(HTypeConversion node) { |
| 2466 if (node.isChecked) { | 2466 if (!node.isChecked) { |
| 2467 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { | 2467 use(node.checkedInput); |
| 2468 js.Expression test = generateTest(node); | 2468 return; |
| 2469 js.Block oldContainer = currentContainer; | 2469 } |
| 2470 js.Statement body = new js.Block.empty(); | 2470 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { |
| 2471 currentContainer = body; | 2471 js.Expression test = generateTest(node); |
| 2472 if (node.isArgumentTypeCheck) { | 2472 js.Block oldContainer = currentContainer; |
| 2473 generateThrowWithHelper('iae', node.checkedInput); | 2473 js.Statement body = new js.Block.empty(); |
| 2474 } else if (node.isReceiverTypeCheck) { | 2474 currentContainer = body; |
| 2475 use(node.checkedInput); | 2475 if (node.isArgumentTypeCheck) { |
| 2476 String methodName = | 2476 generateThrowWithHelper('iae', node.checkedInput); |
| 2477 backend.namer.invocationName(node.receiverTypeCheckSelector); | 2477 } else if (node.isReceiverTypeCheck) { |
| 2478 js.Expression call = jsPropertyCall(pop(), methodName, []); | 2478 use(node.checkedInput); |
| 2479 pushStatement(new js.Throw(call)); | 2479 String methodName = |
| 2480 } | 2480 backend.namer.invocationName(node.receiverTypeCheckSelector); |
| 2481 currentContainer = oldContainer; | 2481 js.Expression call = jsPropertyCall(pop(), methodName, []); |
| 2482 body = unwrapStatement(body); | 2482 pushStatement(new js.Throw(call)); |
| 2483 pushStatement(new js.If.noElse(test, body), node); | |
| 2484 return; | |
| 2485 } | 2483 } |
| 2484 currentContainer = oldContainer; |
| 2485 body = unwrapStatement(body); |
| 2486 pushStatement(new js.If.noElse(test, body), node); |
| 2487 return; |
| 2488 } |
| 2486 | 2489 |
| 2487 assert(node.isCheckedModeCheck || node.isCastTypeCheck); | 2490 assert(node.isCheckedModeCheck || node.isCastTypeCheck); |
| 2488 DartType type = node.typeExpression; | 2491 DartType type = node.typeExpression; |
| 2489 if (type.kind == TypeKind.FUNCTION) { | 2492 if (type.kind == TypeKind.FUNCTION) { |
| 2490 // TODO(5022): We currently generate $isFunction checks for | 2493 // TODO(5022): We currently generate $isFunction checks for |
| 2491 // function types. | 2494 // function types. |
| 2492 world.registerIsCheck( | 2495 world.registerIsCheck( |
| 2493 compiler.functionClass.computeType(compiler), work.resolutionTree); | 2496 compiler.functionClass.computeType(compiler), work.resolutionTree); |
| 2494 } | 2497 } |
| 2495 world.registerIsCheck(type, work.resolutionTree); | 2498 world.registerIsCheck(type, work.resolutionTree); |
| 2496 | 2499 |
| 2497 // TODO(kasperl): For now, we ignore type checks against type | 2500 FunctionElement helperElement; |
| 2498 // variables. This is clearly wrong. | 2501 if (node.isBooleanConversionCheck) { |
| 2499 if (type.kind == TypeKind.TYPE_VARIABLE) { | 2502 helperElement = |
| 2500 use(node.checkedInput); | 2503 compiler.findHelper(const SourceString('boolConversionCheck')); |
| 2501 return; | 2504 } else { |
| 2502 } | 2505 helperElement = backend.getCheckedModeHelper(type, |
| 2503 | 2506 typeCast: node.isCastTypeCheck); |
| 2504 FunctionElement helperElement; | 2507 } |
| 2505 if (node.isBooleanConversionCheck) { | 2508 world.registerStaticUse(helperElement); |
| 2506 helperElement = | 2509 List<js.Expression> arguments = <js.Expression>[]; |
| 2507 compiler.findHelper(const SourceString('boolConversionCheck')); | 2510 use(node.checkedInput); |
| 2508 } else { | 2511 arguments.add(pop()); |
| 2509 helperElement = backend.getCheckedModeHelper(type, | 2512 int parameterCount = |
| 2510 typeCast: node.isCastTypeCheck); | 2513 helperElement.computeSignature(compiler).parameterCount; |
| 2511 } | 2514 // TODO(johnniwinther): Refactor this to avoid using the parameter count |
| 2512 world.registerStaticUse(helperElement); | 2515 // to determine how the helper should be called. |
| 2513 List<js.Expression> arguments = <js.Expression>[]; | 2516 if (node.typeExpression.kind == TypeKind.TYPE_VARIABLE) { |
| 2514 use(node.checkedInput); | 2517 assert(parameterCount == 2); |
| 2518 use(node.typeRepresentation); |
| 2515 arguments.add(pop()); | 2519 arguments.add(pop()); |
| 2516 int parameterCount = | 2520 } else if (parameterCount == 2) { |
| 2517 helperElement.computeSignature(compiler).parameterCount; | 2521 // 2 arguments implies that the method is either [propertyTypeCheck], |
| 2518 // TODO(johnniwinther): Refactor this to avoid using the parameter count | 2522 // [propertyTypeCast] or [assertObjectIsSubtype]. |
| 2519 // to determine how the helper should be called. | 2523 assert(!type.isMalformed); |
| 2520 if (parameterCount == 2) { | 2524 String additionalArgument = backend.namer.operatorIs(type.element); |
| 2521 // 2 arguments implies that the method is either [propertyTypeCheck] | 2525 arguments.add(js.string(additionalArgument)); |
| 2522 // or [propertyTypeCast]. | 2526 } else if (parameterCount == 3) { |
| 2523 assert(!type.isMalformed); | 2527 // 3 arguments implies that the method is [malformedTypeCheck]. |
| 2524 String additionalArgument = backend.namer.operatorIs(type.element); | 2528 assert(type.isMalformed); |
| 2525 arguments.add(js.string(additionalArgument)); | 2529 String reasons = Types.fetchReasonsFromMalformedType(type); |
| 2526 } else if (parameterCount == 3) { | 2530 arguments.add(js.string('$type')); |
| 2527 // 3 arguments implies that the method is [malformedTypeCheck]. | 2531 // TODO(johnniwinther): Handle escaping correctly. |
| 2528 assert(type.isMalformed); | 2532 arguments.add(js.string(reasons)); |
| 2529 String reasons = Types.fetchReasonsFromMalformedType(type); | 2533 } else if (parameterCount == 4) { |
| 2530 arguments.add(js.string('$type')); | 2534 Element element = type.element; |
| 2531 // TODO(johnniwinther): Handle escaping correctly. | 2535 String isField = backend.namer.operatorIs(element); |
| 2532 arguments.add(js.string(reasons)); | 2536 arguments.add(js.string(isField)); |
| 2533 } else { | 2537 use(node.typeRepresentation); |
| 2534 assert(!type.isMalformed); | 2538 arguments.add(pop()); |
| 2535 } | 2539 String asField = backend.namer.substitutionName(element); |
| 2536 String helperName = backend.namer.isolateAccess(helperElement); | 2540 arguments.add(js.string(asField)); |
| 2537 push(new js.Call(new js.VariableUse(helperName), arguments)); | |
| 2538 } else { | 2541 } else { |
| 2539 use(node.checkedInput); | 2542 assert(!type.isMalformed); |
| 2543 // No additional arguments needed. |
| 2540 } | 2544 } |
| 2545 String helperName = backend.namer.isolateAccess(helperElement); |
| 2546 push(new js.Call(new js.VariableUse(helperName), arguments)); |
| 2541 } | 2547 } |
| 2542 } | 2548 } |
| 2543 | 2549 |
| 2544 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { | 2550 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
| 2545 SsaOptimizedCodeGenerator(backend, work) : super(backend, work); | 2551 SsaOptimizedCodeGenerator(backend, work) : super(backend, work); |
| 2546 | 2552 |
| 2547 HBasicBlock beginGraph(HGraph graph) { | 2553 HBasicBlock beginGraph(HGraph graph) { |
| 2548 return graph.entry; | 2554 return graph.entry; |
| 2549 } | 2555 } |
| 2550 | 2556 |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2978 if (leftType.canBeNull() && rightType.canBeNull()) { | 2984 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 2979 if (left.isConstantNull() || right.isConstantNull() || | 2985 if (left.isConstantNull() || right.isConstantNull() || |
| 2980 (leftType.isPrimitive() && leftType == rightType)) { | 2986 (leftType.isPrimitive() && leftType == rightType)) { |
| 2981 return '=='; | 2987 return '=='; |
| 2982 } | 2988 } |
| 2983 return null; | 2989 return null; |
| 2984 } else { | 2990 } else { |
| 2985 return '==='; | 2991 return '==='; |
| 2986 } | 2992 } |
| 2987 } | 2993 } |
| OLD | NEW |