Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.jjs.impl;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.AccessModifier;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JTypeOracle;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.impl.MakeCallsStatic.CreateStaticImplsVisitor;
import java.util.HashMap;
import java.util.Map;
/**
* All call sites that might result in virtual dispatch to a JSO must be
* rewritten to force static dispatch. This transform may NOT be run multiple
* times; it will create ever-expanding replacement expressions.
*/
public class JsoDevirtualizer {
/**
* Rewrite any virtual dispatches to Object or JavaScriptObject such that
* dispatch occurs statically for JSOs.
*/
private class RewriteVirtualDispatches extends JModVisitor {
/**
* A method call at this point can be one of 5 things:
*
*
a dual dispatch interface
*
a single dispatch trough single-jso interface
*
a java.lang.Object override from JavaScriptObject
*
a regular dispatch (no JSOs involved or static JSO call)
*
in draftMode, a 'static' virtual JSO call that hasn't been made
* static yet.
*
*/
@Override
public void endVisit(JMethodCall x, Context ctx) {
JMethod method = x.getTarget();
JMethod newMethod;
JDeclaredType targetType = method.getEnclosingType();
if (targetType == null) {
return;
}
if (!method.needsVtable()) {
return;
}
JType instanceType = x.getInstance().getType();
// if the instance can't possibly be a JSO, don't devirtualize
if (instanceType != program.getTypeJavaLangObject()
&& !program.typeOracle.canBeJavaScriptObject(instanceType)) {
return;
}
if (polyMethodToJsoMethod.containsKey(method)) {
// already did this one before
newMethod = polyMethodToJsoMethod.get(method);
} else if (program.typeOracle.isDualJsoInterface(targetType)) {
JMethod overridingMethod =
findOverridingMethod(method, program.typeOracle.getSingleJsoImpl(targetType));
assert overridingMethod != null;
JMethod jsoStaticImpl = getStaticImpl(overridingMethod);
newMethod = getOrCreateDevirtualMethod(x, jsoStaticImpl);
polyMethodToJsoMethod.put(method, newMethod);
} else if (program.isJavaScriptObject(targetType)) {
// It's a virtual JSO dispatch, usually occurs in draftCompile
newMethod = getStaticImpl(method);
polyMethodToJsoMethod.put(method, newMethod);
} else if (program.typeOracle.isSingleJsoImpl(targetType)) {
// interface dispatch with single implementing JSO concrete type
JMethod overridingMethod =
findOverridingMethod(method, program.typeOracle.getSingleJsoImpl(targetType));
assert overridingMethod != null;
newMethod = getStaticImpl(overridingMethod);
polyMethodToJsoMethod.put(method, newMethod);
} else if (targetType == program.getTypeJavaLangObject()) {
// it's a java.lang.Object overriden method in JSO
JMethod overridingMethod = findOverridingMethod(method, program.getJavaScriptObject());
if (overridingMethod != null) {
JMethod jsoStaticImpl = getStaticImpl(overridingMethod);
newMethod = getOrCreateDevirtualMethod(x, jsoStaticImpl);
polyMethodToJsoMethod.put(method, newMethod);
} else {
// else this method isn't overriden by JavaScriptObject
assert false : "Object method not overriden by JavaScriptObject";
return;
}
} else {
return;
}
assert (newMethod != null);
ctx.replaceMe(MakeCallsStatic.makeStaticCall(x, newMethod));
}
@Override
public boolean visit(JMethod x, Context ctx) {
// Don't rewrite the polymorphic call inside of the devirtualizing method!
if (polyMethodToDevirtualMethods.containsValue(x)) {
return false;
}
return true;
}
}
public static void exec(JProgram program) {
new JsoDevirtualizer(program).execImpl();
}
/**
* Maps each Object instance methods (ie, {@link Object#equals(Object)}) onto
* its corresponding devirtualizing method.
*/
protected Map polyMethodToJsoMethod = new HashMap();
/**
* Contains the Cast.isJavaObject method.
*/
private final JMethod isJavaObjectMethod;
/**
* Key is the method signature, value is the number of unique instances with
* the same signature.
*/
private Map jsoMethodInstances = new HashMap();
/**
* Contains the set of devirtualizing methods that replace polymorphic calls
* to Object methods.
*/
private final Map polyMethodToDevirtualMethods =
new HashMap();
private final JProgram program;
private final CreateStaticImplsVisitor staticImplCreator;
private JsoDevirtualizer(JProgram program) {
this.program = program;
this.isJavaObjectMethod = program.getIndexedMethod("Cast.isJavaObject");
staticImplCreator = new CreateStaticImplsVisitor(program);
}
private void execImpl() {
JClassType jsoType = program.getJavaScriptObject();
if (jsoType == null) {
return;
}
RewriteVirtualDispatches rewriter = new RewriteVirtualDispatches();
rewriter.accept(program);
assert (rewriter.didChange());
}
/**
* Finds the method that overrides this method, starting with the target
* class.
*/
private JMethod findOverridingMethod(JMethod method, JClassType target) {
if (target == null) {
return null;
}
for (JMethod overridingMethod : target.getMethods()) {
if (JTypeOracle.methodsDoMatch(method, overridingMethod)) {
return overridingMethod;
}
}
return findOverridingMethod(method, target.getSuperClass());
}
/**
* Create a conditional method to discriminate between static and virtual
* dispatch.
*
*