Chromium Code Reviews| Index: pkg/compiler/lib/src/js_emitter/program_builder.dart |
| diff --git a/pkg/compiler/lib/src/js_emitter/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder.dart |
| index 4e2f55577e1f5162fdeb4978ad9e506d378751da..50ab505001fb58178cce29584ec31777a5abd03e 100644 |
| --- a/pkg/compiler/lib/src/js_emitter/program_builder.dart |
| +++ b/pkg/compiler/lib/src/js_emitter/program_builder.dart |
| @@ -266,6 +266,7 @@ class ProgramBuilder { |
| /// |
| /// Returns a class that contains the fields of a class. |
| Class buildClassWithFieldsForTry(ClassElement element) { |
| + assert(_compiler.hasIncrementalSupport); |
| bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element); |
| List<Field> instanceFields = |
| @@ -374,10 +375,73 @@ class ProgramBuilder { |
| return result; |
| } |
| - Method _buildMethod(FunctionElement element, js.Expression code) { |
| + bool _methodNeedsStubs(FunctionElement method) { |
| + return !method.functionSignature.optionalParameters.isEmpty; |
| + } |
| + |
| + bool _methodCanBeReflected(FunctionElement method) { |
| + return backend.isAccessibleByReflection(method) || |
| + // During incremental compilation, we have to assume that reflection |
| + // *might* get enabled. |
| + _compiler.hasIncrementalSupport; |
| + } |
| + |
| + bool _methodCanBeApplied(FunctionElement method) { |
| + return _compiler.enabledFunctionApply && |
| + _compiler.world.getMightBePassedToApply(method); |
| + } |
| + |
| + // Hack for Try! |
| + Method buildMethodForTry(FunctionElement element) { |
|
floitsch
2015/01/28 16:10:39
As discussed: change name.
herhut
2015/01/29 10:24:21
now buildMethodHackForIncrementalCompilation
|
| + assert(_compiler.hasIncrementalSupport); |
| + if (element.isInstanceMember) { |
| + js.Expression code = backend.generatedCode[element]; |
| + return _buildMethod(element, code); |
| + } else { |
| + return _buildStaticMethod(element); |
| + } |
| + } |
| + |
| + // TODO(herhut): Why does this get code passed in and statics don't? |
|
floitsch
2015/01/28 16:10:39
Probably just an oversight.
herhut
2015/01/29 10:24:21
Changed.
|
| + DartMethod _buildMethod(FunctionElement element, js.Expression code) { |
| String name = namer.getNameOfInstanceMember(element); |
| - // TODO(floitsch): compute `needsTearOff`. |
| - return new Method(element, name, code, needsTearOff: false); |
| + |
| + bool canTearOff = false; |
| + String tearOffName; |
| + bool isClosure = false; |
| + bool isNotApplyTarget = !element.isFunction || element.isAccessor; |
| + |
| + final bool needsStubs = _methodNeedsStubs(element); |
| + final bool canBeReflected = _methodCanBeReflected(element); |
| + final bool canBeApplied = _methodCanBeApplied(element); |
| + final bool hasSuperAlias = backend.isAliasedSuperMember(element); |
| + |
| + if (isNotApplyTarget) { |
| + canTearOff = false; |
| + } else { |
| + if (element.enclosingClass.isClosure) { |
| + canTearOff = false; |
| + isClosure = true; |
| + } else { |
| + // Careful with operators. |
| + canTearOff = universe.hasInvokedGetter(element, _compiler.world) || |
| + (canBeReflected && !element.isOperator); |
| + assert(canTearOff || |
| + !universe.methodsNeedingSuperGetter.contains(element)); |
| + tearOffName = namer.getterName(element); |
| + } |
| + } |
| + |
| + if (canTearOff) { |
| + assert(invariant(element, !element.isGenerativeConstructor)); |
| + assert(invariant(element, !element.isGenerativeConstructorBody)); |
| + assert(invariant(element, !element.isConstructor)); |
| + } |
| + |
| + return new InstanceMethod(element, name, code, needsTearOff: canTearOff, |
| + tearOffName: tearOffName, isClosure: isClosure, |
| + hasSuperAlias: hasSuperAlias, canBeApplied: canBeApplied, |
| + canBeReflected: canBeReflected, needsStubs: needsStubs); |
| } |
| /// Builds a stub method. |
| @@ -386,8 +450,7 @@ class ProgramBuilder { |
| /// attribution. |
| Method _buildStubMethod(String name, js.Expression code, |
| {Element element}) { |
| - // TODO(floitsch): compute `needsTearOff`. |
| - return new StubMethod(name, code, needsTearOff: false, element: element); |
| + return new StubMethod(name, code, element: element); |
| } |
| // The getInterceptor methods directly access the prototype of classes. |
| @@ -418,6 +481,7 @@ class ProgramBuilder { |
| Set<ClassElement> classes = specializedGetInterceptors[name]; |
| js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
| // TODO(floitsch): compute `needsTearOff`. |
| + // TODO(herhut): Can these actually ever be torn off? |
|
floitsch
2015/01/28 16:10:39
Until we find a case where it can be, let's just r
herhut
2015/01/29 10:24:21
Done.
|
| return new StaticStubMethod(name, holder, code, needsTearOff: false); |
| }); |
| } |
| @@ -486,12 +550,25 @@ class ProgramBuilder { |
| String name = namer.getNameOfMember(element); |
| String holder = namer.globalObjectFor(element); |
| js.Expression code = backend.generatedCode[element]; |
| - bool needsTearOff = |
| - universe.staticFunctionsNeedingGetter.contains(element); |
| - // TODO(floitsch): add tear-off name: namer.getStaticClosureName(element). |
| + |
| + final bool isNotApplyTarget = !element.isConstructor && !element.isAccessor; |
| + final bool needsStubs = _methodNeedsStubs(element); |
| + final bool canBeApplied = _methodCanBeApplied(element); |
| + final bool canBeReflected = _methodCanBeReflected(element); |
| + |
| + final bool needsTearOff = isNotApplyTarget && (canBeReflected || |
| + universe.staticFunctionsNeedingGetter.contains(element)); |
| + |
| + final String tearOffName = |
| + needsTearOff ? namer.getStaticClosureName(element) : null; |
| + |
| return new StaticMethod(element, |
| name, _registry.registerHolder(holder), code, |
| - needsTearOff: needsTearOff); |
| + needsTearOff: needsTearOff, |
| + tearOffName: tearOffName, |
| + canBeApplied: canBeApplied, |
| + canBeReflected: canBeReflected, |
| + needsStubs: needsStubs); |
| } |
| void _registerConstants(OutputUnit outputUnit, |