Chromium Code Reviews| Index: dart/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/dart/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
| index a6386a38711f43c8fc311178e9856bda3257c085..889ecbe2ad1adb08ccbf3c2a247913611fe1c274 100644 |
| --- a/dart/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
| +++ b/dart/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
| @@ -18,6 +18,12 @@ class CodeEmitterTask extends CompilerTask { |
| final InterceptorEmitter interceptorEmitter = new InterceptorEmitter(); |
| final MetadataEmitter metadataEmitter = new MetadataEmitter(); |
| + final Set<Constant> cachedEmittedConstants = new Set<Constant>.identity(); |
|
Johnni Winther
2014/06/19 09:22:32
We canonicalize these so why use identity?
ahe
2014/06/19 09:36:19
Think of it this way: the way we implement canonic
|
| + final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); |
| + final Map<Element, ClassBuilder> cachedClassBuilders = |
| + new HashMap<Element, ClassBuilder>.identity(); |
| + final Set<Element> cachedElements = new HashSet<Element>.identity(); |
| + |
| bool needsDefineClass = false; |
| bool needsMixinSupport = false; |
| bool needsLazyInitializer = false; |
| @@ -766,8 +772,23 @@ class CodeEmitterTask extends CompilerTask { |
| void generateClass(ClassElement classElement, ClassBuilder properties) { |
| compiler.withCurrentElement(classElement, () { |
| - classEmitter.generateClass( |
| - classElement, properties, additionalProperties[classElement]); |
| + if (compiler.hasIncrementalSupport) { |
| + ClassBuilder builder = |
| + cachedClassBuilders.putIfAbsent(classElement, () { |
| + ClassBuilder builder = new ClassBuilder(namer); |
| + classEmitter.generateClass( |
| + classElement, builder, additionalProperties[classElement]); |
| + return builder; |
| + }); |
| + invariant(classElement, builder.fields.isEmpty); |
| + invariant(classElement, builder.superName == null); |
| + invariant(classElement, builder.functionType == null); |
| + invariant(classElement, builder.fieldMetadata == null); |
| + properties.properties.addAll(builder.properties); |
| + } else { |
| + classEmitter.generateClass( |
| + classElement, properties, additionalProperties[classElement]); |
| + } |
| }); |
| } |
| @@ -901,7 +922,15 @@ class CodeEmitterTask extends CompilerTask { |
| void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) { |
| List<Constant> constants = outputConstantLists[outputUnit]; |
| if (constants == null) return; |
| + bool isMainBuffer = buffer == mainBuffer; |
| + if (compiler.hasIncrementalSupport && isMainBuffer) { |
| + buffer = cachedEmittedConstantsBuffer; |
| + } |
| for (Constant constant in constants) { |
| + if (compiler.hasIncrementalSupport && isMainBuffer) { |
| + if (cachedEmittedConstants.contains(constant)) continue; |
| + cachedEmittedConstants.add(constant); |
| + } |
| String name = namer.constantName(constant); |
| if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); |
| jsAst.Expression init = js('#.# = #', |
| @@ -910,6 +939,9 @@ class CodeEmitterTask extends CompilerTask { |
| buffer.write(jsAst.prettyPrint(init, compiler)); |
| buffer.write('$N'); |
| } |
| + if (compiler.hasIncrementalSupport && isMainBuffer) { |
| + mainBuffer.add(cachedEmittedConstantsBuffer); |
| + } |
| } |
| bool isConstantInlinedOrAlreadyEmitted(Constant constant) { |
| @@ -1094,7 +1126,7 @@ class CodeEmitterTask extends CompilerTask { |
| void computeNeededConstants() { |
| JavaScriptConstantCompiler handler = backend.constants; |
| List<Constant> constants = handler.getConstantsForEmission( |
| - compareConstants); |
| + compiler.hasIncrementalSupport ? null : compareConstants); |
| for (Constant constant in constants) { |
| if (isConstantInlinedOrAlreadyEmitted(constant)) continue; |
| OutputUnit constantUnit = |
| @@ -1302,6 +1334,8 @@ class CodeEmitterTask extends CompilerTask { |
| String assembleProgram() { |
| measure(() { |
| + invalidateCaches(); |
| + |
| // Compute the required type checks to know which classes need a |
| // 'is$' method. |
| typeTestEmitter.computeRequiredTypeChecks(); |
| @@ -1445,22 +1479,24 @@ class CodeEmitterTask extends CompilerTask { |
| List<Element> sortedElements = |
| Elements.sortedByPosition(elementDescriptors.keys); |
| - Iterable<Element> pendingStatics = sortedElements.where((element) { |
| - return !element.isLibrary && |
| - elementDescriptors[element].values.any((descriptor) => |
| - descriptor != null); |
| - }); |
| - |
| - pendingStatics.forEach((element) => |
| - compiler.reportInfo( |
| - element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
| - |
| + Iterable<Element> pendingStatics; |
| + if (!compiler.hasIncrementalSupport) { |
| + pendingStatics = sortedElements.where((element) { |
| + return !element.isLibrary && |
| + elementDescriptors[element].values.any((descriptor) => |
| + descriptor != null); |
| + }); |
| + |
| + pendingStatics.forEach((element) => |
| + compiler.reportInfo( |
| + element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
| + } |
| for (LibraryElement library in sortedElements.where((element) => |
| element.isLibrary)) { |
| writeLibraryDescriptors(library); |
| elementDescriptors[library] = const {}; |
| } |
| - if (!pendingStatics.isEmpty) { |
| + if (pendingStatics != null && !pendingStatics.isEmpty) { |
| compiler.internalError(pendingStatics.first, |
| 'Pending statics (see above).'); |
| } |
| @@ -1755,4 +1791,18 @@ class CodeEmitterTask extends CompilerTask { |
| void registerReadTypeVariable(TypeVariableElement element) { |
| readTypeVariables.add(element); |
| } |
| + |
| + void invalidateCaches() { |
| + if (!compiler.hasIncrementalSupport) return; |
| + if (cachedElements.isEmpty) return; |
| + for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| + if (element.isInstanceMember) { |
| + // print('Invalidating ${element.enclosingClass} due to ${element}'); |
|
Johnni Winther
2014/06/19 09:22:32
Remove debug line.
ahe
2014/06/19 13:50:10
Done.
|
| + cachedClassBuilders.remove(element.enclosingClass); |
| + |
| + nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| + |
| + } |
| + } |
| + } |
| } |