gwt /
gwt /
941b3b16bb50c60fc6879ef35f4ace293cd6e4e7 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.
Review at http://gwt-code-reviews.appspot.com/1447821
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10435 8db76d5a-ed1c-0410-87a9-c151d255dfc7
33 files changed