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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart

Issue 14986002: Make static tear-off closures a class, like instance tear-off closures. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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 | Annotate | Revision Log
OLDNEW
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 509 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 } else if (sequenceElements.length == 1) { 520 } else if (sequenceElements.length == 1) {
521 return sequenceElements[0]; 521 return sequenceElements[0];
522 } else { 522 } else {
523 return new js.Sequence(sequenceElements); 523 return new js.Sequence(sequenceElements);
524 } 524 }
525 } 525 }
526 526
527 /** 527 /**
528 * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET]. 528 * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET].
529 */ 529 */
530 List<js.Expression> visitArguments(List<HInstruction> inputs) { 530 List<js.Expression> visitArguments(List<HInstruction> inputs,
531 assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET); 531 {int start: HInvoke.ARGUMENTS_OFFSET}) {
532 assert(inputs.length >= start);
532 List<js.Expression> result = <js.Expression>[]; 533 List<js.Expression> result = <js.Expression>[];
533 for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) { 534 for (int i = start; i < inputs.length; i++) {
534 use(inputs[i]); 535 use(inputs[i]);
535 result.add(pop()); 536 result.add(pop());
536 } 537 }
537 return result; 538 return result;
538 } 539 }
539 540
540 bool isVariableDeclared(String variableName) { 541 bool isVariableDeclared(String variableName) {
541 return declaredLocals.contains(variableName) || 542 return declaredLocals.contains(variableName) ||
542 collectedVariableDeclarations.contains(variableName); 543 collectedVariableDeclarations.contains(variableName);
543 } 544 }
(...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after
1605 visitArguments(node.inputs)), 1606 visitArguments(node.inputs)),
1606 node); 1607 node);
1607 world.registerDynamicInvocation(call.name, call); 1608 world.registerDynamicInvocation(call.name, call);
1608 } 1609 }
1609 1610
1610 visitInvokeStatic(HInvokeStatic node) { 1611 visitInvokeStatic(HInvokeStatic node) {
1611 if (node.typeCode() == HInstruction.INVOKE_STATIC_TYPECODE) { 1612 if (node.typeCode() == HInstruction.INVOKE_STATIC_TYPECODE) {
1612 // Register this invocation to collect the types used at all call sites. 1613 // Register this invocation to collect the types used at all call sites.
1613 backend.registerStaticInvocation(node); 1614 backend.registerStaticInvocation(node);
1614 } 1615 }
1615 use(node.target); 1616 Element element = node.element;
1616 push(new js.Call(pop(), visitArguments(node.inputs)), node); 1617 world.registerStaticUse(element);
1618 ClassElement cls = element.getEnclosingClass();
1619 if (element.isGenerativeConstructor()
1620 || (element.isFactoryConstructor() && cls == compiler.listClass)) {
1621 world.registerInstantiatedClass(cls, work.resolutionTree);
1622 }
1623 push(new js.VariableUse(backend.namer.isolateAccess(node.element)));
1624 push(new js.Call(pop(), visitArguments(node.inputs, start: 0)), node);
1617 } 1625 }
1618 1626
1619 visitInvokeSuper(HInvokeSuper node) { 1627 visitInvokeSuper(HInvokeSuper node) {
1620 Element superMethod = node.element; 1628 Element superMethod = node.element;
1629 world.registerStaticUse(superMethod);
1621 Element superClass = superMethod.getEnclosingClass(); 1630 Element superClass = superMethod.getEnclosingClass();
1622 if (superMethod.kind == ElementKind.FIELD) { 1631 if (superMethod.kind == ElementKind.FIELD) {
1623 String fieldName = node.caller.isShadowedByField(superMethod) 1632 String fieldName = node.caller.isShadowedByField(superMethod)
1624 ? backend.namer.shadowedFieldName(superMethod) 1633 ? backend.namer.shadowedFieldName(superMethod)
1625 : backend.namer.instanceFieldName(superMethod); 1634 : backend.namer.instanceFieldName(superMethod);
1626 use(node.inputs[1]); 1635 use(node.inputs[0]);
1627 js.PropertyAccess access = 1636 js.PropertyAccess access =
1628 new js.PropertyAccess.field(pop(), fieldName); 1637 new js.PropertyAccess.field(pop(), fieldName);
1629 if (node.isSetter) { 1638 if (node.isSetter) {
1630 use(node.value); 1639 use(node.value);
1631 push(new js.Assignment(access, pop()), node); 1640 push(new js.Assignment(access, pop()), node);
1632 } else { 1641 } else {
1633 push(access, node); 1642 push(access, node);
1634 } 1643 }
1635 } else { 1644 } else {
1636 String methodName = backend.namer.getName(superMethod); 1645 String methodName = backend.namer.getName(superMethod);
1637 String className = backend.namer.isolateAccess(superClass); 1646 String className = backend.namer.isolateAccess(superClass);
1638 js.VariableUse classReference = new js.VariableUse(className); 1647 js.VariableUse classReference = new js.VariableUse(className);
1639 js.PropertyAccess prototype = 1648 js.PropertyAccess prototype =
1640 new js.PropertyAccess.field(classReference, "prototype"); 1649 new js.PropertyAccess.field(classReference, "prototype");
1641 js.PropertyAccess method = 1650 js.PropertyAccess method =
1642 new js.PropertyAccess.field(prototype, methodName); 1651 new js.PropertyAccess.field(prototype, methodName);
1643 push(jsPropertyCall(method, "call", visitArguments(node.inputs)), node); 1652 push(jsPropertyCall(
1653 method, "call", visitArguments(node.inputs, start: 0)), node);
1644 } 1654 }
1645 world.registerStaticUse(superMethod); 1655 world.registerStaticUse(superMethod);
1646 } 1656 }
1647 1657
1648 visitFieldGet(HFieldGet node) { 1658 visitFieldGet(HFieldGet node) {
1649 use(node.receiver); 1659 use(node.receiver);
1650 Element element = node.element; 1660 Element element = node.element;
1651 if (element == backend.jsIndexableLength) { 1661 if (element == backend.jsIndexableLength) {
1652 // We're accessing a native JavaScript property called 'length' 1662 // We're accessing a native JavaScript property called 'length'
1653 // on a JS String or a JS array. Therefore, the name of that 1663 // on a JS String or a JS array. Therefore, the name of that
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
1981 js.Call value = new js.Call(jsHelper, [pop()]); 1991 js.Call value = new js.Call(jsHelper, [pop()]);
1982 attachLocation(value, argument); 1992 attachLocation(value, argument);
1983 push(value, node); 1993 push(value, node);
1984 } 1994 }
1985 1995
1986 void visitSwitch(HSwitch node) { 1996 void visitSwitch(HSwitch node) {
1987 // Switches are handled using [visitSwitchInfo]. 1997 // Switches are handled using [visitSwitchInfo].
1988 } 1998 }
1989 1999
1990 void visitStatic(HStatic node) { 2000 void visitStatic(HStatic node) {
1991 // Check whether this static is used for anything else than as a target in
1992 // a static call.
1993 node.usedBy.forEach((HInstruction instr) {
1994 if (instr is !HInvokeStatic) {
1995 backend.registerNonCallStaticUse(node);
1996 if (node.element.isFunction()) {
1997 world.registerInstantiatedClass(
1998 compiler.functionClass, work.resolutionTree);
1999 }
2000 } else if (instr.target != node) {
2001 backend.registerNonCallStaticUse(node);
2002 }
2003 });
2004 Element element = node.element; 2001 Element element = node.element;
2002 if (element.isFunction()) {
2003 backend.registerNonCallStaticUse(node);
2004 world.registerInstantiatedClass(
2005 compiler.functionClass, work.resolutionTree);
2006 push(new js.VariableUse(
2007 backend.namer.isolateStaticClosureAccess(node.element)));
2008 } else {
2009 push(new js.VariableUse(backend.namer.isolateAccess(node.element)));
2010 }
2005 world.registerStaticUse(element); 2011 world.registerStaticUse(element);
2006 ClassElement cls = element.getEnclosingClass();
2007 if (element.isGenerativeConstructor()
2008 || (element.isFactoryConstructor() && cls == compiler.listClass)) {
2009 world.registerInstantiatedClass(cls, work.resolutionTree);
2010 }
2011 push(new js.VariableUse(backend.namer.isolateAccess(node.element)));
2012 } 2012 }
2013 2013
2014 void visitLazyStatic(HLazyStatic node) { 2014 void visitLazyStatic(HLazyStatic node) {
2015 Element element = node.element; 2015 Element element = node.element;
2016 world.registerStaticUse(element); 2016 world.registerStaticUse(element);
2017 String lazyGetter = backend.namer.isolateLazyInitializerAccess(element); 2017 String lazyGetter = backend.namer.isolateLazyInitializerAccess(element);
2018 js.VariableUse target = new js.VariableUse(lazyGetter); 2018 js.VariableUse target = new js.VariableUse(lazyGetter);
2019 js.Call call = new js.Call(target, <js.Expression>[]); 2019 js.Call call = new js.Call(target, <js.Expression>[]);
2020 push(call, node); 2020 push(call, node);
2021 } 2021 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
2175 void checkNull(HInstruction input) { 2175 void checkNull(HInstruction input) {
2176 use(input); 2176 use(input);
2177 push(new js.Binary('==', pop(), new js.LiteralNull())); 2177 push(new js.Binary('==', pop(), new js.LiteralNull()));
2178 } 2178 }
2179 2179
2180 void checkNonNull(HInstruction input) { 2180 void checkNonNull(HInstruction input) {
2181 use(input); 2181 use(input);
2182 push(new js.Binary('!=', pop(), new js.LiteralNull())); 2182 push(new js.Binary('!=', pop(), new js.LiteralNull()));
2183 } 2183 }
2184 2184
2185 void checkFunction(HInstruction input,
2186 DartType type,
2187 { bool negative: false}) {
2188 String relation = negative ? '!==' : '===';
2189 checkTypeOf(input, relation, 'function');
2190 js.Expression functionTest = pop();
2191 checkObject(input, relation);
2192 js.Expression objectTest = pop();
2193 checkType(input, type, negative: negative);
2194 String combiner = negative ? '||' : '&&';
2195 push(new js.Binary(negative ? '&&' : '||',
2196 functionTest,
2197 new js.Binary(combiner, objectTest, pop())));
2198 }
2199
2200 void checkType(HInstruction input, DartType type, {bool negative: false}) { 2185 void checkType(HInstruction input, DartType type, {bool negative: false}) {
2201 assert(invariant(input, !type.isMalformed, 2186 assert(invariant(input, !type.isMalformed,
2202 message: 'Attempt to check malformed type $type')); 2187 message: 'Attempt to check malformed type $type'));
2203 world.registerIsCheck(type, work.resolutionTree); 2188 world.registerIsCheck(type, work.resolutionTree);
2204 Element element = type.element; 2189 Element element = type.element;
2205 use(input); 2190 use(input);
2206 2191
2207 // Hack in interceptor. Ideally the interceptor would occur at the 2192 // Hack in interceptor. Ideally the interceptor would occur at the
2208 // instruction level to allow optimizations, and checks would be broken into 2193 // instruction level to allow optimizations, and checks would be broken into
2209 // several smaller tests. 2194 // several smaller tests.
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2331 attachLocationToLast(node); 2316 attachLocationToLast(node);
2332 } else if (element == compiler.doubleClass) { 2317 } else if (element == compiler.doubleClass) {
2333 checkDouble(input, relation); 2318 checkDouble(input, relation);
2334 attachLocationToLast(node); 2319 attachLocationToLast(node);
2335 } else if (element == compiler.numClass) { 2320 } else if (element == compiler.numClass) {
2336 checkNum(input, relation); 2321 checkNum(input, relation);
2337 attachLocationToLast(node); 2322 attachLocationToLast(node);
2338 } else if (element == compiler.boolClass) { 2323 } else if (element == compiler.boolClass) {
2339 checkBool(input, relation); 2324 checkBool(input, relation);
2340 attachLocationToLast(node); 2325 attachLocationToLast(node);
2341 } else if (element == compiler.functionClass) {
2342 checkFunction(input, type, negative: negative);
2343 attachLocationToLast(node);
2344 } else if (element == compiler.intClass) { 2326 } else if (element == compiler.intClass) {
2345 // The is check in the code tells us that it might not be an 2327 // The is check in the code tells us that it might not be an
2346 // int. So we do a typeof first to avoid possible 2328 // int. So we do a typeof first to avoid possible
2347 // deoptimizations on the JS engine due to the Math.floor check. 2329 // deoptimizations on the JS engine due to the Math.floor check.
2348 checkNum(input, relation); 2330 checkNum(input, relation);
2349 js.Expression numTest = pop(); 2331 js.Expression numTest = pop();
2350 checkBigInt(input, relation); 2332 checkBigInt(input, relation);
2351 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node); 2333 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node);
2352 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { 2334 } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
2353 handleNumberOrStringSupertypeCheck(input, type, negative: negative); 2335 handleNumberOrStringSupertypeCheck(input, type, negative: negative);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 pushStatement(new js.Throw(call)); 2463 pushStatement(new js.Throw(call));
2482 } 2464 }
2483 currentContainer = oldContainer; 2465 currentContainer = oldContainer;
2484 body = unwrapStatement(body); 2466 body = unwrapStatement(body);
2485 pushStatement(new js.If.noElse(test, body), node); 2467 pushStatement(new js.If.noElse(test, body), node);
2486 return; 2468 return;
2487 } 2469 }
2488 2470
2489 assert(node.isCheckedModeCheck || node.isCastTypeCheck); 2471 assert(node.isCheckedModeCheck || node.isCastTypeCheck);
2490 DartType type = node.typeExpression; 2472 DartType type = node.typeExpression;
2473 if (type.kind == TypeKind.FUNCTION) {
2474 // TODO(5022): We currently generate $isFunction checks for
2475 // function types.
2476 world.registerIsCheck(
2477 compiler.functionClass.computeType(compiler), work.resolutionTree);
2478 }
2491 world.registerIsCheck(type, work.resolutionTree); 2479 world.registerIsCheck(type, work.resolutionTree);
2492 2480
2493 // TODO(kasperl): For now, we ignore type checks against type 2481 // TODO(kasperl): For now, we ignore type checks against type
2494 // variables. This is clearly wrong. 2482 // variables. This is clearly wrong.
2495 if (type.kind == TypeKind.TYPE_VARIABLE) { 2483 if (type.kind == TypeKind.TYPE_VARIABLE) {
2496 use(node.checkedInput); 2484 use(node.checkedInput);
2497 return; 2485 return;
2498 } 2486 }
2499 2487
2500 FunctionElement helperElement; 2488 FunctionElement helperElement;
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
2974 if (leftType.canBeNull() && rightType.canBeNull()) { 2962 if (leftType.canBeNull() && rightType.canBeNull()) {
2975 if (left.isConstantNull() || right.isConstantNull() || 2963 if (left.isConstantNull() || right.isConstantNull() ||
2976 (leftType.isPrimitive() && leftType == rightType)) { 2964 (leftType.isPrimitive() && leftType == rightType)) {
2977 return '=='; 2965 return '==';
2978 } 2966 }
2979 return null; 2967 return null;
2980 } else { 2968 } else {
2981 return '==='; 2969 return '===';
2982 } 2970 }
2983 } 2971 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698