Reviewers: scottb, jbrosenberg,
Description:
This patch substantially reduces the overhead of Java types in the
output by minimizing vtable setup and virtual class literal fetches.
Improvements are anywhere from 5% to 10% uncompressed obfuscated JS.
The patch includes the following changes:
1) A new Immortal CodeGenType. Immortal CodeGenTypes are CodeGenTypes
that cannot even be pruned by the final pruner pass. They exist in order
to conveniently define code in Java (as opposed to encoding JS in Java
strings) which must be injected into the Javascript AST during
construction. They must consist of only static methods and static
fields, and static field initializers are only permitted to be literals
and JSO.createObject()/createArray(). In addition, they are guaranteed
to be hoisted prior to the first non-Immortal type statement.
2) A new SeedUtil Immortal type which provides utility functions for
setting up vtables. It eliminates empty constructor seed functions by
using 2 helper functions to setup anonymous closure versions. Something
like this before the patch:
function fooSeed() {}
_ = fooSeed.prototype = FooConstructor.prototype = new superType();
_.castableTypeMap = { ... }
_.getClass = function() {
return classLiteral;
}
is replaced with
defineSeed(seedId, superSeedid, { castableTypeMap }, FooConstructor1,
FooConstructor2, ...)
This has two effects. First, it reduces both compressed and uncompressed
codesize by a non-trivial amount by eliminating empty globally named
seed functions which are only used as prototype placeholders. Secondly,
it frees up extra obfuscated identifiers (by using numeric ids to
identifer function seeds) in the global scope. Note: the seedId is not
necessarily the queryId. Third, prototypes can be
looked up by seedId.
3) Eliminate of All getClass() overrides. Two designs were tried, one
which removes the overrides during AST generation and the other which
leaves them in, but removes them later in the compilation. The latter
turned out to be simpler and produce some side benefits. This works as
follows:
First, java.lang.Object is given a new Class<?> clazz field and
Object.getClass() returns it.
Second, the ClassLiteralHolder fields, which are evaluated last, install
the appropriate Class instance into this field on the appropriate
prototype. That is, the Class.createForClass() method for example,
creates a new ClassLiteral, looks up the appropriate prototype, and
installs it into the Object.clazz field for that type.
Third, a final pass, just prior to generating the Javascript AST, prunes
all getClass() overrides. The overrides are left in during the
GenerateJavaAST phase, because it is advantageous to allow some of them
to be inlined when
method call tightening allows it, and because it minimizes the amount of
changes to ControlFlowAnalyzer. CFA did had
to be changed to rescue ClassLiterals for any instantiated type, if the
getClass() method is live.
deRPC had to be modified to deal with the new scheme of looking up the
prototype/seed function by number instead of name, as well as the new
naming scheme when -XdisableClassMetadata is active.
Please review this at http://gwt-code-reviews.appspot.com/1447821/
Affected files:
M dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
M dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
M dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java
M dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
M dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
A dev/core/src/com/google/gwt/dev/jjs/ast/JSeedIdOf.java
M dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
M dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
M dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java
M dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
M dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
M dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
M dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
M dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
M
dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
M dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java
M dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
A dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceGetClassOverrides.java
M dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
M
dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java
M dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
M dev/core/src/com/google/gwt/dev/js/JsToStringGenerationVisitor.java
A dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java
M dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
M
dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
A
dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/SeedUtil.java
M user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
M user/src/com/google/gwt/rpc/server/WebModeClientOracle.java
M user/src/com/google/gwt/rpc/server/WebModePayloadSink.java
M user/super/com/google/gwt/emul/java/lang/Class.java
M user/super/com/google/gwt/emul/java/lang/Object.java
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors