[google-web-toolkit commit] r3255 - in changes/spoon/runAsync: dev/core/src/com/google/gwt/dev/jjs/impl dev/core/src/com/goog...

1 view
Skip to first unread message

codesite...@google.com

unread,
Jul 18, 2008, 2:11:05 PM7/18/08
to gwt...@gmail.com
Author: sp...@google.com
Date: Fri Jul 18 11:09:48 2008
New Revision: 3255

Modified:
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/MethodAdaptor.java
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/GeckoDispatchAdapter.java
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/JsValueMoz.java
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/JsValueSaf.java
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/LowLevelSaf.java
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/WebKitDispatchAdapter.java
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/IDispatchProxy.java
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/JsValueIE6.java
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/MethodDispatch.java
changes/spoon/runAsync/eclipse/dev/linux/.classpath
changes/spoon/runAsync/eclipse/dev/mac/.classpath
changes/spoon/runAsync/eclipse/dev/windows/.classpath
changes/spoon/runAsync/jni/linux/JsValueMoz.cpp
changes/spoon/runAsync/jni/linux/NativeWrapper.cpp
changes/spoon/runAsync/jni/linux/prebuilt/libgwt-ll.so
changes/spoon/runAsync/jni/mac/gwt-webkit.cpp
changes/spoon/runAsync/jni/mac/java-dispatch.cpp
changes/spoon/runAsync/jni/mac/java-dispatch.h
changes/spoon/runAsync/jni/mac/prebuilt/libgwt-ll.jnilib
changes/spoon/runAsync/user/test/com/google/gwt/dev/jjs/test/HostedTest.java

Log:
Merged from trunk, revisions 2276:2284.

svn merge -r2276:2284 https://google-web-toolkit.googlecode.com/svn/trunk .

Modified: changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
==============================================================================
---
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java (original)
+++
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
Fri Jul 18 11:09:48 2008
@@ -893,6 +893,11 @@
}

@Override
+ public boolean visit(JClassType x, Context ctx) {
+ return rescuer.instantiatedTypes.contains(x);
+ }
+
+ @Override
public boolean visit(JProgram x, Context ctx) {
didRescue = false;
return true;

Modified: changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
==============================================================================
---
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java (original)
+++
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
Fri Jul 18 11:09:48 2008
@@ -37,6 +37,7 @@
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JContinueStatement;
+import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JDoStatement;
import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
import com.google.gwt.dev.jjs.ast.JExpression;
@@ -52,11 +53,9 @@
import com.google.gwt.dev.jjs.ast.JLabel;
import com.google.gwt.dev.jjs.ast.JLabeledStatement;
import com.google.gwt.dev.jjs.ast.JLocal;
-import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JLongLiteral;
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.JNewArray;
import com.google.gwt.dev.jjs.ast.JNewInstance;
@@ -81,7 +80,6 @@
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
-import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import com.google.gwt.dev.jjs.ast.js.JsonArray;
import com.google.gwt.dev.jjs.ast.js.JsonObject;
@@ -585,35 +583,21 @@
if (x.isStatic()) {
print(CHARS_STATIC);
}
- if (shouldPrintMethodBody()) {
- accept(x.getBody());
- } else {
- print("{ ... }");
- newlineOpt();
+ if (!shouldPrintMethodBody()) {
+ print("{...}");
}
} else {
printMethodHeader(x);
- if (shouldPrintMethodBody() && !x.isAbstract()) {
- space();
- accept(x.getBody());
- } else {
- semi();
- newlineOpt();
- }
}

- return false;
- }
-
- @Override
- public boolean visit(JMethodBody x, Context ctx) {
- if (shouldPrintMethodBody()) {
- accept(x.getBlock());
- return false;
+ if (x.isAbstract() || !shouldPrintMethodBody()) {
+ semi();
+ newlineOpt();
} else {
- visitCollectionWithCommas(x.locals.iterator());
- return false;
+ accept(x.getBody());
}
+
+ return false;
}

@Override
@@ -748,16 +732,6 @@
@Override
public boolean visit(JsniFieldRef x, Context ctx) {
return visit(x.getField(), ctx);
- }
-
- @Override
- public boolean visit(JsniMethodBody x, Context ctx) {
- print("/*-{");
- // don't visit my block
- newline();
- print("}-*/");
- semi();
- return false;
}

@Override

Modified: changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
==============================================================================
---
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java (original)
+++
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
Fri Jul 18 11:09:48 2008
@@ -28,6 +28,8 @@
import com.google.gwt.dev.util.JsniRef;
import com.google.gwt.util.tools.Utility;

+import org.apache.commons.collections.map.AbstractReferenceMap;
+import org.apache.commons.collections.map.ReferenceIdentityMap;
import org.apache.commons.collections.map.ReferenceMap;

import java.io.IOException;
@@ -327,13 +329,15 @@

private final TreeLogger logger;

- private final Map<MethodAdaptor, Object> methodToDispatch = new
HashMap<MethodAdaptor, Object>();
-
private final TypeOracle typeOracle;

@SuppressWarnings("unchecked")
+ private final Map<Object, Object> weakJavaWrapperCache = new ReferenceIdentityMap(
+ AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK);
+
+ @SuppressWarnings("unchecked")
private final Map<Integer, Object> weakJsoCache = new ReferenceMap(
- ReferenceMap.HARD, ReferenceMap.WEAK);
+ AbstractReferenceMap.HARD, AbstractReferenceMap.WEAK);

public CompilingClassLoader(TreeLogger logger, ByteCodeCompiler compiler,
TypeOracle typeOracle) throws UnableToCompleteException {
@@ -434,10 +438,16 @@
return dispClassInfoOracle.getDispId(jsniMemberRef);
}

- public Object getMethodDispatch(MethodAdaptor method) {
- synchronized (methodToDispatch) {
- return methodToDispatch.get(method);
- }
+ /**
+ * Retrieves the mapped wrapper for a given Java Object, provided
the wrapper
+ * was previously cached and has not been garbage collected.
+ *
+ * @param javaObject the Object being wrapped
+ * @return the mapped wrapper, or <code>null</code> if the Java object
+ * mapped or if the wrapper has been garbage collected
+ */
+ public Object getWrapperForObject(Object javaObject) {
+ return weakJavaWrapperCache.get(javaObject);
}

/**
@@ -451,10 +461,14 @@
weakJsoCache.put(uniqueId, jso);
}

- public void putMethodDispatch(MethodAdaptor method, Object
methodDispatch) {
- synchronized (methodToDispatch) {
- methodToDispatch.put(method, methodDispatch);
- }
+ /**
+ * Weakly caches a wrapper for a given Java Object.
+ *
+ * @param javaObject the Object being wrapped
+ * @param wrapper the mapped wrapper
+ */
+ public void putWrapperForObject(Object javaObject, Object wrapper) {
+ weakJavaWrapperCache.put(javaObject, wrapper);
}

@Override
@@ -499,11 +513,8 @@

void clear() {
weakJsoCache.clear();
+ weakJavaWrapperCache.clear();
dispClassInfoOracle.clear();
-
- synchronized (methodToDispatch) {
- methodToDispatch.clear();
- }
}

private String getBinaryName(JClassType type) {

Modified: changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/MethodAdaptor.java
==============================================================================
---
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/MethodAdaptor.java (original)
+++
changes/spoon/runAsync/dev/core/src/com/google/gwt/dev/shell/MethodAdaptor.java
Fri Jul 18 11:09:48 2008
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.shell;

+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -84,6 +85,10 @@

public Class<?> getReturnType() {
return returnType;
+ }
+
+ public AccessibleObject getUnderlyingObject() {
+ return (method != null) ? method : constructor;
}

@Override

Modified: changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/GeckoDispatchAdapter.java
==============================================================================
---
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/GeckoDispatchAdapter.java (original)
+++
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/GeckoDispatchAdapter.java
Fri Jul 18 11:09:48 2008
@@ -24,6 +24,7 @@
import com.google.gwt.dev.shell.moz.LowLevelMoz.DispatchMethod;
import com.google.gwt.dev.shell.moz.LowLevelMoz.DispatchObject;

+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;

/**
@@ -85,10 +86,11 @@
return;
} else {
MethodAdaptor method = javaDispatch.getMethod(dispId);
- DispatchMethod dispMethod = (DispatchMethod) classLoader.getMethodDispatch(method);
+ AccessibleObject obj = method.getUnderlyingObject();
+ DispatchMethod dispMethod = (DispatchMethod) classLoader.getWrapperForObject(obj);
if (dispMethod == null) {
dispMethod = new MethodDispatch(classLoader, method);
- classLoader.putMethodDispatch(method, dispMethod);
+ classLoader.putWrapperForObject(obj, dispMethod);
}
jsValue.setWrappedFunction(method.toString(), dispMethod);
}

Modified: changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/JsValueMoz.java
==============================================================================
---
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/JsValueMoz.java (original)
+++
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/JsValueMoz.java
Fri Jul 18 11:09:48 2008
@@ -154,9 +154,9 @@

protected static native int _getInt(int jsRootedValue);

- protected static native double _getNumber(int jsRootedValue);
+ protected static native int _getJsval(int jsRootedValue);

- protected static native int _getObjectPointer(int jsRootedValue);
+ protected static native double _getNumber(int jsRootedValue);

protected static native String _getString(int jsRootedValue);

@@ -191,6 +191,8 @@
protected static native void _setJsRootedValue(int jsRootedValue,
int jsOtherRootedValue);

+ protected static native void _setJsval(int jsRootedValue, int jsval);
+
protected static native void _setNull(int jsRootedValue);

protected static native void _setString(int jsRootedValue, String val);
@@ -294,7 +296,8 @@

@Override
public int getJavaScriptObjectPointer() {
- return _getObjectPointer(jsRootedValue);
+ assert isJavaScriptObject();
+ return _getJsval(jsRootedValue);
}

/**
@@ -534,7 +537,13 @@
*/
public void setWrappedFunction(String methodName,
DispatchMethod dispatchMethod) {
- _setWrappedFunction(jsRootedValue, methodName, dispatchMethod);
+ Integer jsval = LowLevelMoz.sObjectToJsval.get(dispatchMethod);
+ if (jsval != null) {
+ _setJsval(jsRootedValue, jsval);
+ } else {
+ _setWrappedFunction(jsRootedValue, methodName, dispatchMethod);
+ LowLevelMoz.sObjectToJsval.put(dispatchMethod, _getJsval(jsRootedValue));
+ }
}

/*
@@ -553,9 +562,19 @@
if (val instanceof DispatchObject) {
dispObj = (DispatchObject) val;
} else {
- dispObj = new GeckoDispatchAdapter(cl, val);
+ dispObj = (DispatchObject) cl.getWrapperForObject(val);
+ if (dispObj == null) {
+ dispObj = new GeckoDispatchAdapter(cl, val);
+ cl.putWrapperForObject(val, dispObj);
+ }
+ }
+ Integer cached = LowLevelMoz.sObjectToJsval.get(dispObj);
+ if (cached != null) {
+ _setJsval(jsRootedValue, cached);
+ } else {
+ _setWrappedJavaObject(jsRootedValue, dispObj);
+ LowLevelMoz.sObjectToJsval.put(dispObj, _getJsval(jsRootedValue));
}
- _setWrappedJavaObject(jsRootedValue, dispObj);
}

/**

Modified: changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java
==============================================================================
---
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java (original)
+++
changes/spoon/runAsync/dev/linux/src/com/google/gwt/dev/shell/moz/LowLevelMoz.java
Fri Jul 18 11:09:48 2008
@@ -17,6 +17,8 @@

import com.google.gwt.dev.shell.LowLevel;

+import java.util.IdentityHashMap;
+import java.util.Map;
import java.util.Vector;

/**
@@ -76,6 +78,13 @@
boolean gwtOnLoad(int scriptGlobalObject, String moduleName);
}

+ /**
+ * Stores a map from DispatchObject/DispatchMethod to the live underlying
+ * jsval. This is used to both preserve identity for the same Java
Object and
+ * also prevent GC.
+ */
+ static Map<Object, Integer> sObjectToJsval = new
IdentityHashMap<Object, Integer>();
+
private static Vector<ExternalFactory> sExternalFactories = new Vector<ExternalFactory>();
private static boolean sInitialized = false;

@@ -186,6 +195,13 @@
System.out.flush();
}

+ /**
+ * Native code accessor to remove the mapping upon GC.
+ */
+ static void removeJsvalForObject(Object o) {
+ sObjectToJsval.remove(o);
+ }
+
// CHECKSTYLE_NAMING_OFF: Non JSNI native code may have leading '_'s.

private static native boolean _executeScriptWithInfo(int scriptObject,
@@ -220,7 +236,8 @@
* @param jsthis the JS object with the named method
* @param jsargs an array of arguments to the method
*/
- @SuppressWarnings("unused") // kept for future debugging purposes
+ @SuppressWarnings("unused")
+ // kept for future debugging purposes
private static void printInvocationParams(String methodName,
JsValueMoz jsthis, JsValueMoz[] jsargs) {
System.out.println("LowLevelMoz.invoke:");

Modified: changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/JsValueSaf.java
==============================================================================
---
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/JsValueSaf.java (original)
+++
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/JsValueSaf.java
Fri Jul 18 11:09:48 2008
@@ -92,11 +92,8 @@

@Override
public int getJavaScriptObjectPointer() {
- if (isJavaScriptObject()) {
- return jsval;
- } else {
- return 0;
- }
+ assert isJavaScriptObject();
+ return jsval;
}

public int getJsValue() {
@@ -196,17 +193,6 @@
setJsVal(LowLevelSaf.toJsNumber(LowLevelSaf.getCurrentJsContext(), val));
}

- /**
- * Set a new value. Unlock the previous value, but do *not* lock the
new value
- * (see class comment).
- *
- * @param jsval the new value to set
- */
- public void setJsVal(int jsval) {
- LowLevelSaf.gcUnprotect(LowLevelSaf.getCurrentJsContext(), this.jsval);
- init(jsval);
- }
-
@Override
public void setNull() {
setJsVal(LowLevelSaf.getJsNull(LowLevelSaf.getCurrentJsContext()));
@@ -247,7 +233,11 @@
} else if (val instanceof DispatchObject) {
dispObj = (DispatchObject) val;
} else {
- dispObj = new WebKitDispatchAdapter(cl, val);
+ dispObj = (DispatchObject) cl.getWrapperForObject(val);
+ if (dispObj == null) {
+ dispObj = new WebKitDispatchAdapter(cl, val);
+ cl.putWrapperForObject(val, dispObj);
+ }
}
setJsVal(LowLevelSaf.wrapDispatchObject(LowLevelSaf.getCurrentJsContext(),
dispObj));
@@ -275,6 +265,17 @@
+
LowLevelSaf.getTypeString(LowLevelSaf.getCurrentJsContext(), jsval)
+ ")");
}
+ }
+
+ /**
+ * Set a new value. Unlock the previous value, but do *not* lock the
new value
+ * (see class comment).
+ *
+ * @param jsval the new value to set
+ */
+ private void setJsVal(int jsval) {
+ LowLevelSaf.gcUnprotect(LowLevelSaf.getCurrentJsContext(), this.jsval);
+ init(jsval);
}

}

Modified: changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/LowLevelSaf.java
==============================================================================
---
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/LowLevelSaf.java (original)
+++
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/LowLevelSaf.java
Fri Jul 18 11:09:48 2008
@@ -17,6 +17,8 @@

import com.google.gwt.dev.shell.LowLevel;

+import java.util.IdentityHashMap;
+import java.util.Map;
import java.util.Stack;

/**
@@ -50,12 +52,19 @@
void setField(int jsContext, String name, int value);
}

- private static boolean jsValueProtectionCheckingEnabled;
+ /**
+ * Stores a map from DispatchObject/DispatchMethod to the live underlying
+ * jsval. This is used to both preserve identity for the same Java
Object and
+ * also prevent GC.
+ */
+ static Map<Object, Integer> sObjectToJsval = new
IdentityHashMap<Object, Integer>();

private static boolean initialized = false;

private static final ThreadLocal<Stack<Integer>> jsContextStack =
new ThreadLocal<Stack<Integer>>();

+ private static boolean jsValueProtectionCheckingEnabled;
+
public static int executeScript(int jsContext, String script) {
final int[] rval = new int[1];
if (!executeScriptWithInfoImpl(jsContext, script, null, 0, rval)) {
@@ -119,7 +128,7 @@
}

LowLevel.init();
- if (!initImpl(DispatchObject.class, DispatchMethod.class)) {
+ if (!initImpl(DispatchObject.class, DispatchMethod.class,
LowLevelSaf.class)) {
throw new RuntimeException("Unable to initialize LowLevelSaf");
}

@@ -271,19 +280,39 @@

public static int wrapDispatchMethod(int jsContext, String name,
DispatchMethod dispatch) {
- final int[] rval = new int[1];
- if (!wrapDispatchMethodImpl(jsContext, name, dispatch, rval)) {
- throw new RuntimeException("Failed to wrap DispatchMethod.");
+ Integer cached = LowLevelSaf.sObjectToJsval.get(dispatch);
+ if (cached != null) {
+ /*
+ * Add another lock to the cached jsval, since it will not have any.
+ */
+ LowLevelSaf.gcProtect(LowLevelSaf.getCurrentJsContext(), cached);
+ return cached;
+ } else {
+ final int[] rval = new int[1];
+ if (!wrapDispatchMethodImpl(jsContext, name, dispatch, rval)) {
+ throw new RuntimeException("Failed to wrap DispatchMethod.");
+ }
+ LowLevelSaf.sObjectToJsval.put(dispatch, rval[0]);
+ return rval[0];
}
- return rval[0];
}

public static int wrapDispatchObject(int jsContext, DispatchObject
dispatcher) {
- final int[] rval = new int[1];
- if (!wrapDispatchObjectImpl(jsContext, dispatcher, rval)) {
- throw new RuntimeException("Failed to wrap DispatchObject.");
+ Integer cached = LowLevelSaf.sObjectToJsval.get(dispatcher);
+ if (cached != null) {
+ /*
+ * Add another lock to the cached jsval, since it will not have any.
+ */
+ LowLevelSaf.gcProtect(LowLevelSaf.getCurrentJsContext(), cached);
+ return cached;
+ } else {
+ final int[] rval = new int[1];
+ if (!wrapDispatchObjectImpl(jsContext, dispatcher, rval)) {
+ throw new RuntimeException("Failed to wrap DispatchObject.");
+ }
+ LowLevelSaf.sObjectToJsval.put(dispatcher, rval[0]);
+ return rval[0];
}
- return rval[0];
}

static native boolean isGcProtected(int jsValue);
@@ -299,6 +328,13 @@
return jsValueProtectionCheckingEnabled;
}

+ /**
+ * Native code accessor to remove the mapping upon GC.
+ */
+ static void releaseObject(Object o) {
+ sObjectToJsval.remove(o);
+ }
+
private static native boolean executeScriptWithInfoImpl(int jsContext,
String script, String url, int line, int[] rval);

@@ -306,7 +342,8 @@

private static native boolean initImpl(
Class<DispatchObject> dispatchObjectClass,
- Class<DispatchMethod> dispatchMethodClass);
+ Class<DispatchMethod> dispatchMethodClass,
+ Class<LowLevelSaf> lowLevelSafClass);

private static native boolean invokeImpl(int jsContext, int jsScriptObject,
String methodName, int thisObj, int[] args, int argsLength,
int[] rval);

Modified: changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java
==============================================================================
---
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java (original)
+++
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java
Fri Jul 18 11:09:48 2008
@@ -20,7 +20,6 @@
import com.google.gwt.dev.shell.JsValueGlue;
import com.google.gwt.dev.shell.ModuleSpace;
import com.google.gwt.dev.shell.ModuleSpaceHost;
-import com.google.gwt.dev.shell.mac.LowLevelSaf.DispatchObject;

/**
* An implementation of {@link com.google.gwt.dev.shell.ModuleSpace}
for Safari.
@@ -104,20 +103,5 @@
@Override
protected Object getStaticDispatcher() {
return new WebKitDispatchAdapter(getIsolatedClassLoader());
- }
-
- protected int wrapObjectAsJSObject(Object o) {
- if (o == null) {
- return LowLevelSaf.getJsNull(LowLevelSaf.getCurrentJsContext());
- }
-
- DispatchObject dispObj;
- if (o instanceof DispatchObject) {
- dispObj = (DispatchObject) o;
- } else {
- dispObj = new WebKitDispatchAdapter(getIsolatedClassLoader(), o);
- }
- return LowLevelSaf.wrapDispatchObject(LowLevelSaf.getCurrentJsContext(),
- dispObj);
}
}

Modified: changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/WebKitDispatchAdapter.java
==============================================================================
---
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/WebKitDispatchAdapter.java (original)
+++
changes/spoon/runAsync/dev/mac/src/com/google/gwt/dev/shell/mac/WebKitDispatchAdapter.java
Fri Jul 18 11:09:48 2008
@@ -24,6 +24,7 @@
import com.google.gwt.dev.shell.mac.LowLevelSaf.DispatchMethod;
import com.google.gwt.dev.shell.mac.LowLevelSaf.DispatchObject;

+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;

/**
@@ -79,10 +80,11 @@
return jsval;
} else {
MethodAdaptor method = javaDispatch.getMethod(dispId);
- DispatchMethod dispMethod = (DispatchMethod) classLoader.getMethodDispatch(method);
+ AccessibleObject obj = method.getUnderlyingObject();
+ DispatchMethod dispMethod = (DispatchMethod) classLoader.getWrapperForObject(obj);
if (dispMethod == null) {
dispMethod = new MethodDispatch(classLoader, method);
- classLoader.putMethodDispatch(method, dispMethod);
+ classLoader.putWrapperForObject(obj, dispMethod);
}
// Native code eats the same ref it gave us.
return LowLevelSaf.wrapDispatchMethod(jsContext, method.toString(),

Modified: changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/IDispatchProxy.java
==============================================================================
---
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/IDispatchProxy.java (original)
+++
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/IDispatchProxy.java
Fri Jul 18 11:09:48 2008
@@ -26,6 +26,7 @@
import org.eclipse.swt.internal.ole.win32.IDispatch;
import org.eclipse.swt.ole.win32.Variant;

+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

@@ -154,10 +155,11 @@
return callMethod(classLoader, getTarget(), params, method);
} else if (flags == COM.DISPATCH_PROPERTYGET) {
// The function is being accessed as a property.
- IDispatchImpl dispMethod = (IDispatchImpl) classLoader.getMethodDispatch(method);
+ AccessibleObject obj = method.getUnderlyingObject();
+ IDispatchImpl dispMethod = (IDispatchImpl) classLoader.getWrapperForObject(obj);
if (dispMethod == null || dispMethod.refCount < 1) {
dispMethod = new MethodDispatch(classLoader, method);
- classLoader.putMethodDispatch(method, dispMethod);
+ classLoader.putWrapperForObject(obj, dispMethod);
}
IDispatch disp = new IDispatch(dispMethod.getAddress());
disp.AddRef();

Modified: changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/JsValueIE6.java
==============================================================================
---
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/JsValueIE6.java (original)
+++
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/JsValueIE6.java
Fri Jul 18 11:09:48 2008
@@ -496,7 +496,11 @@
} else if (val instanceof IDispatchImpl) {
dispObj = (IDispatchImpl) val;
} else {
- dispObj = new IDispatchProxy(cl, val);
+ dispObj = (IDispatchImpl) cl.getWrapperForObject(val);
+ if (dispObj == null || dispObj.refCount < 1) {
+ dispObj = new IDispatchProxy(cl, val);
+ cl.putWrapperForObject(val, dispObj);
+ }
}
IDispatch disp = new IDispatch(dispObj.getAddress());
disp.AddRef();

Modified: changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/MethodDispatch.java
==============================================================================
---
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/MethodDispatch.java (original)
+++
changes/spoon/runAsync/dev/windows/src/com/google/gwt/dev/shell/ie/MethodDispatch.java
Fri Jul 18 11:09:48 2008
@@ -23,6 +23,7 @@
import org.eclipse.swt.internal.ole.win32.IDispatch;
import org.eclipse.swt.ole.win32.Variant;

+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException;

/**
@@ -114,10 +115,11 @@
throw new RuntimeException(
"Failed to get Object.toString() method", e);
}
- IDispatchImpl dispMethod = (IDispatchImpl) classLoader.getMethodDispatch(toStringMethod);
- if (dispMethod == null) {
+ AccessibleObject obj = toStringMethod.getUnderlyingObject();
+ IDispatchImpl dispMethod = (IDispatchImpl) classLoader.getWrapperForObject(obj);
+ if (dispMethod == null || dispMethod.refCount < 1) {
dispMethod = new MethodDispatch(classLoader, toStringMethod);
- classLoader.putMethodDispatch(toStringMethod, dispMethod);
+ classLoader.putWrapperForObject(obj, dispMethod);
}
IDispatch disp = new IDispatch(dispMethod.getAddress());
disp.AddRef();

Modified: changes/spoon/runAsync/eclipse/dev/linux/.classpath
==============================================================================
--- changes/spoon/runAsync/eclipse/dev/linux/.classpath (original)
+++ changes/spoon/runAsync/eclipse/dev/linux/.classpath Fri Jul 18
11:09:48 2008
@@ -14,7 +14,7 @@
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-optional-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-beanutils-1.6.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-collections-3.1.jar"/>
+ <classpathentry kind="var"
path="GWT_TOOLS/lib/tomcat/commons-collections-3.1.jar" sourcepath="/GWT_TOOLS/lib/tomcat/commons-collections-3.1-src.zip"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-digester-1.5.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-el-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-logging-1.0.jar"/>

Modified: changes/spoon/runAsync/eclipse/dev/mac/.classpath
==============================================================================
--- changes/spoon/runAsync/eclipse/dev/mac/.classpath (original)
+++ changes/spoon/runAsync/eclipse/dev/mac/.classpath Fri Jul 18
11:09:48 2008
@@ -14,7 +14,7 @@
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-optional-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-beanutils-1.6.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-collections-3.1.jar"/>
+ <classpathentry kind="var"
path="GWT_TOOLS/lib/tomcat/commons-collections-3.1.jar" sourcepath="/GWT_TOOLS/lib/tomcat/commons-collections-3.1-src.zip"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-digester-1.5.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-el-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-logging-1.0.jar"/>

Modified: changes/spoon/runAsync/eclipse/dev/windows/.classpath
==============================================================================
--- changes/spoon/runAsync/eclipse/dev/windows/.classpath (original)
+++ changes/spoon/runAsync/eclipse/dev/windows/.classpath Fri Jul 18
11:09:48 2008
@@ -14,7 +14,7 @@
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-optional-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-beanutils-1.6.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-collections-3.1.jar"/>
+ <classpathentry kind="var"
path="GWT_TOOLS/lib/tomcat/commons-collections-3.1.jar" sourcepath="/GWT_TOOLS/lib/tomcat/commons-collections-3.1-src.zip"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-digester-1.5.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-el-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-logging-1.0.jar"/>

Modified: changes/spoon/runAsync/jni/linux/JsValueMoz.cpp
==============================================================================
--- changes/spoon/runAsync/jni/linux/JsValueMoz.cpp (original)
+++ changes/spoon/runAsync/jni/linux/JsValueMoz.cpp Fri Jul 18 11:09:48 2008
@@ -382,18 +382,17 @@

/**
* Class: com_google_gwt_dev_shell_moz_JsValueMoz
- * Method: _getObjectPointer()
+ * Method: _getJsval()
* Signature: (I)I
*/
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_gwt_dev_shell_moz_JsValueMoz__1getObjectPointer
+Java_com_google_gwt_dev_shell_moz_JsValueMoz__1getJsval
(JNIEnv* jniEnv, jclass, jint jsRootedValueInt)
{
JsRootedValue* jsRootedValue = reinterpret_cast<JsRootedValue*>
(jsRootedValueInt);
Tracer tracer("JsValueMoz._getObjectPointer", jsRootedValue);
- JSObject* ptr = jsRootedValue->getObject();
- int val = reinterpret_cast<int>(ptr);
+ int val = jsRootedValue->getValue();
tracer.log("value=%d", val);
return val;
}
@@ -733,6 +732,23 @@
}

/*
+ * Set the Javascript value to a specific jsval.
+ *
+ * Class: com_google_gwt_dev_shell_moz_JsValueMoz
+ * Method: _setJsval()
+ * Signature: (II)V
+ */
+extern "C" JNIEXPORT void JNICALL
+Java_com_google_gwt_dev_shell_moz_JsValueMoz__1setJsval
+ (JNIEnv* jniEnv, jclass, jint jsRootedValueInt, jint jsval)
+{
+ JsRootedValue* jsRootedValue = reinterpret_cast<JsRootedValue*>
+ (jsRootedValueInt);
+ Tracer tracer("JsValueMoz._setJsval", jsRootedValue);
+ jsRootedValue->setValue(jsval);
+}
+
+/*
* Set the JavaScript value to be null.
*
* Class: com_google_gwt_dev_shell_moz_JsValueMoz
@@ -821,7 +837,7 @@
jsRootedValue->setObject(newObj);
tracer.log("jsobject=%08x", unsigned(newObj));

- // TODO(jat): how does this globalref get freed?
+ // This is collected when the gwt_nativewrapper_class destructor runs.
jobject dispObjRef = jniEnv->NewGlobalRef(obj);
if (!dispObjRef || jniEnv->ExceptionCheck()) {
tracer.throwHostedModeException(jniEnv,

Modified: changes/spoon/runAsync/jni/linux/NativeWrapper.cpp
==============================================================================
--- changes/spoon/runAsync/jni/linux/NativeWrapper.cpp (original)
+++ changes/spoon/runAsync/jni/linux/NativeWrapper.cpp Fri Jul 18
11:09:48 2008
@@ -158,9 +158,23 @@
static void JS_DLL_CALLBACK gwt_nativewrapper_finalize(JSContext *cx,
JSObject *obj)
{
+ Tracer tracer("gwt_nativewrapper_finalize");
jobject dispObj = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
- if (dispObj)
+ if (dispObj) {
+ // Remove this pairing from the global map.
+ jmethodID removeMethod = savedJNIEnv->GetStaticMethodID(lowLevelMozClass, "removeJsvalForObject",
+ "(Ljava/lang/Object;)V");
+ if (!removeMethod || savedJNIEnv->ExceptionCheck()) {
+ tracer.setFail("Cannot GetMethodID for removeJsvalForObject");
+ return;
+ }
+ savedJNIEnv->CallStaticVoidMethod(lowLevelMozClass, removeMethod, dispObj);
+ if (savedJNIEnv->ExceptionCheck()) {
+ tracer.setFail("Exception calling removeJsvalForObject");
+ return;
+ }
savedJNIEnv->DeleteGlobalRef(dispObj);
+ }
}

static JSBool JS_DLL_CALLBACK gwt_nativewrapper_setProperty(JSContext
*cx, JSObject *obj, jsval id, jsval *vp)

Modified: changes/spoon/runAsync/jni/linux/prebuilt/libgwt-ll.so
==============================================================================
Binary files. No diff available.

Modified: changes/spoon/runAsync/jni/mac/gwt-webkit.cpp
==============================================================================
--- changes/spoon/runAsync/jni/mac/gwt-webkit.cpp (original)
+++ changes/spoon/runAsync/jni/mac/gwt-webkit.cpp Fri Jul 18 11:09:48 2008
@@ -677,10 +677,10 @@
*/
JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_initImpl
(JNIEnv *env, jclass klass, jclass dispatchObjectClass,
- jclass dispatchMethodClass) {
+ jclass dispatchMethodClass, jclass lowLevelSafClass) {
TR_ENTER();
TR_LEAVE();
- return static_cast<jboolean>(gwt::Initialize(env,
dispatchObjectClass, dispatchMethodClass));
+ return static_cast<jboolean>(gwt::Initialize(env,
dispatchObjectClass, dispatchMethodClass, lowLevelSafClass));
}

/*

Modified: changes/spoon/runAsync/jni/mac/java-dispatch.cpp
==============================================================================
--- changes/spoon/runAsync/jni/mac/java-dispatch.cpp (original)
+++ changes/spoon/runAsync/jni/mac/java-dispatch.cpp Fri Jul 18
11:09:48 2008
@@ -54,6 +54,12 @@
void DispatchMethodFinalize(JSObjectRef);

/*
+ * Call this when an underlying Java Object should be freed.
+ */
+ void ReleaseJavaObject(jobject jObject);
+
+
+ /*
* The class definition stuct for DispatchObjects.
*/
static JSClassDefinition _dispatchObjectClassDef = { 0,
@@ -85,10 +91,12 @@
static JNIEnv* _javaEnv;
static jclass _javaDispatchObjectClass;
static jclass _javaDispatchMethodClass;
+ static jclass _lowLevelSafClass;
static jmethodID _javaDispatchObjectSetFieldMethod;
static jmethodID _javaDispatchObjectGetFieldMethod;
static jmethodID _javaDispatchMethodInvokeMethod;
static jmethodID _javaDispatchObjectToStringMethod;
+ static jmethodID _lowLevelSafReleaseObject;

/*
* Structure to hold DispatchMethod private data.
@@ -100,7 +108,7 @@
DispatchMethodData(jobject jObject, std::string& utf8Name)
: _jObject(jObject), _utf8Name(utf8Name) { }
~DispatchMethodData() {
- _javaEnv->DeleteGlobalRef(_jObject);
+ ReleaseJavaObject(_jObject);
}
jobject _jObject;
std::string _utf8Name;
@@ -293,7 +301,7 @@
void DispatchObjectFinalize(JSObjectRef jsObject) {
TR_ENTER();
jobject jObject = reinterpret_cast<jobject>(JSObjectGetPrivate(jsObject));
- _javaEnv->DeleteGlobalRef(jObject);
+ ReleaseJavaObject(jObject);
TR_LEAVE();
}

@@ -445,9 +453,10 @@
*
*/
bool Initialize(JNIEnv* javaEnv, jclass javaDispatchObjectClass,
- jclass javaDispatchMethodClass) {
+ jclass javaDispatchMethodClass, jclass lowLevelSafClass) {
TR_ENTER();
- if (!javaEnv || !javaDispatchObjectClass ||
!javaDispatchMethodClass) {
+ if (!javaEnv || !javaDispatchObjectClass || !javaDispatchMethodClass
+ || !lowLevelSafClass) {
return false;
}

@@ -456,6 +465,8 @@
javaEnv->NewGlobalRef(javaDispatchObjectClass));
_javaDispatchMethodClass = static_cast<jclass>(
javaEnv->NewGlobalRef(javaDispatchMethodClass));
+ _lowLevelSafClass = static_cast<jclass>(
+ javaEnv->NewGlobalRef(lowLevelSafClass));
_javaDispatchObjectSetFieldMethod = javaEnv->GetMethodID(
javaDispatchObjectClass, "setField", "(ILjava/lang/String;I)V");
_javaDispatchObjectGetFieldMethod = javaEnv->GetMethodID(
@@ -464,15 +475,28 @@
javaDispatchMethodClass, "invoke", "(II[I[I)I");
_javaDispatchObjectToStringMethod = javaEnv->GetMethodID(
javaDispatchObjectClass, "toString", "()Ljava/lang/String;");
+ _lowLevelSafReleaseObject = javaEnv->GetStaticMethodID(
+ lowLevelSafClass, "releaseObject", "(Ljava/lang/Object;)V");

if (!_javaDispatchObjectSetFieldMethod || !_javaDispatchObjectGetFieldMethod
|| !_javaDispatchMethodInvokeMethod || !_javaDispatchObjectToStringMethod
- || javaEnv->ExceptionCheck()) {
+ || !_lowLevelSafReleaseObject || javaEnv->ExceptionCheck()) {
return false;
}

TR_LEAVE();
return true;
+}
+
+void ReleaseJavaObject(jobject jObject) {
+ // Tell the Java code we're done with this object.
+ _javaEnv->CallStaticVoidMethod(_lowLevelSafClass, _lowLevelSafReleaseObject,
+ jObject);
+ if (_javaEnv->ExceptionCheck()) {
+ TR_FAIL();
+ return;
+ }
+ _javaEnv->DeleteGlobalRef(jObject);
}

} // namespace gwt

Modified: changes/spoon/runAsync/jni/mac/java-dispatch.h
==============================================================================
--- changes/spoon/runAsync/jni/mac/java-dispatch.h (original)
+++ changes/spoon/runAsync/jni/mac/java-dispatch.h Fri Jul 18 11:09:48 2008
@@ -23,11 +23,11 @@
namespace gwt {

/*
- * Initializes static members needed by DispatchObjects and DispatchMethods.
- * This should be called before before calling either
DispatchMethodCreate or
- * DispatchObjectCreate.
+ * Initializes static members needed by DispatchObject, DispatchMethod,
+ * and LowLevelSaf. This should be called before before calling anything
+ * else.
*/
-bool Initialize(JNIEnv*, jclass, jclass);
+bool Initialize(JNIEnv*, jclass, jclass, jclass);

/*
* Returns a shared reference to the DispatchObject class

Modified: changes/spoon/runAsync/jni/mac/prebuilt/libgwt-ll.jnilib
==============================================================================
Binary files. No diff available.

Modified: changes/spoon/runAsync/user/test/com/google/gwt/dev/jjs/test/HostedTest.java
==============================================================================
---
changes/spoon/runAsync/user/test/com/google/gwt/dev/jjs/test/HostedTest.java (original)
+++
changes/spoon/runAsync/user/test/com/google/gwt/dev/jjs/test/HostedTest.java
Fri Jul 18 11:09:48 2008
@@ -144,6 +144,18 @@
return s.length;
}-*/;

+ private static native boolean jsIdentical(Object o1, Object o2) /*-{
+ return o1 === o2;
+ }-*/;
+
+ private static native boolean jsniInstanceFunctionsIdentical(Object
o) /*-{
+ return o.@java.lang.Object::toString() === o.@java.lang.Object::toString();
+ }-*/;
+
+ private static native boolean jsniStaticFunctionsIdentical() /*-{
+ return
@com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;) === @com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;);
+ }-*/;
+
private static native int passThroughInt(int val) /*-{
return val;
}-*/;
@@ -200,7 +212,7 @@
assertTrue(HostedTest.class.desiredAssertionStatus());
}
}
-
+
/*
* Test that returning JavaScript boxed primitives works as
expected. Note
* that Boolean and Number cannot be supported properly in web mode,
so we do
@@ -320,6 +332,13 @@
A.B b = new A.B();
assertEquals(1, b.getUsingSourceRef());
assertEquals(1, b.getUsingBinaryRef());
+ }
+
+ public void testJavaObjectIdentityInJS() {
+ Object o = new Object();
+ assertTrue(jsIdentical(o, o));
+ assertTrue(jsniInstanceFunctionsIdentical(o));
+ assertTrue(jsniStaticFunctionsIdentical());
}

public void testJsniFormats() {

Reply all
Reply to author
Forward
0 new messages