312 lines
11 KiB
Java
312 lines
11 KiB
Java
|
/* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1/GPL 2.0
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (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.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is Rhino code, released
|
||
|
* May 6, 1999.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* Netscape Communications Corporation.
|
||
|
* Portions created by the Initial Developer are Copyright (C) 1997-2000
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
* Norris Boyd
|
||
|
* Roger Lawrence
|
||
|
* Hannes Wallnoefer
|
||
|
*
|
||
|
* Alternatively, the contents of this file may be used under the terms of
|
||
|
* the GNU General Public License Version 2 or later (the "GPL"), in which
|
||
|
* case the provisions of the GPL are applicable instead of those above. If
|
||
|
* you wish to allow use of your version of this file only under the terms of
|
||
|
* the GPL and not to allow others to use your version of this file under the
|
||
|
* MPL, indicate your decision by deleting the provisions above and replacing
|
||
|
* them with the notice and other provisions required by the GPL. If you do
|
||
|
* not delete the provisions above, a recipient may use your version of this
|
||
|
* file under either the MPL or the GPL.
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** */
|
||
|
|
||
|
|
||
|
package org.mozilla.javascript.optimizer;
|
||
|
|
||
|
import org.mozilla.javascript.*;
|
||
|
|
||
|
public final class OptRuntime extends ScriptRuntime
|
||
|
{
|
||
|
|
||
|
public static final Double zeroObj = new Double(0.0);
|
||
|
public static final Double oneObj = new Double(1.0);
|
||
|
public static final Double minusOneObj = new Double(-1.0);
|
||
|
|
||
|
/**
|
||
|
* Implement ....() call shrinking optimizer code.
|
||
|
*/
|
||
|
public static Object call0(Callable fun, Scriptable thisObj,
|
||
|
Context cx, Scriptable scope)
|
||
|
{
|
||
|
return fun.call(cx, scope, thisObj, ScriptRuntime.emptyArgs);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement ....(arg) call shrinking optimizer code.
|
||
|
*/
|
||
|
public static Object call1(Callable fun, Scriptable thisObj, Object arg0,
|
||
|
Context cx, Scriptable scope)
|
||
|
{
|
||
|
return fun.call(cx, scope, thisObj, new Object[] { arg0 } );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement ....(arg0, arg1) call shrinking optimizer code.
|
||
|
*/
|
||
|
public static Object call2(Callable fun, Scriptable thisObj,
|
||
|
Object arg0, Object arg1,
|
||
|
Context cx, Scriptable scope)
|
||
|
{
|
||
|
return fun.call(cx, scope, thisObj, new Object[] { arg0, arg1 });
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement ....(arg0, arg1, ...) call shrinking optimizer code.
|
||
|
*/
|
||
|
public static Object callN(Callable fun, Scriptable thisObj,
|
||
|
Object[] args,
|
||
|
Context cx, Scriptable scope)
|
||
|
{
|
||
|
return fun.call(cx, scope, thisObj, args);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement name(args) call shrinking optimizer code.
|
||
|
*/
|
||
|
public static Object callName(Object[] args, String name,
|
||
|
Context cx, Scriptable scope)
|
||
|
{
|
||
|
Callable f = getNameFunctionAndThis(name, cx, scope);
|
||
|
Scriptable thisObj = lastStoredScriptable(cx);
|
||
|
return f.call(cx, scope, thisObj, args);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement name() call shrinking optimizer code.
|
||
|
*/
|
||
|
public static Object callName0(String name,
|
||
|
Context cx, Scriptable scope)
|
||
|
{
|
||
|
Callable f = getNameFunctionAndThis(name, cx, scope);
|
||
|
Scriptable thisObj = lastStoredScriptable(cx);
|
||
|
return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement x.property() call shrinking optimizer code.
|
||
|
*/
|
||
|
public static Object callProp0(Object value, String property,
|
||
|
Context cx, Scriptable scope)
|
||
|
{
|
||
|
Callable f = getPropFunctionAndThis(value, property, cx, scope);
|
||
|
Scriptable thisObj = lastStoredScriptable(cx);
|
||
|
return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs);
|
||
|
}
|
||
|
|
||
|
public static Object add(Object val1, double val2)
|
||
|
{
|
||
|
if (val1 instanceof Scriptable)
|
||
|
val1 = ((Scriptable) val1).getDefaultValue(null);
|
||
|
if (!(val1 instanceof String))
|
||
|
return wrapDouble(toNumber(val1) + val2);
|
||
|
return ((String)val1).concat(toString(val2));
|
||
|
}
|
||
|
|
||
|
public static Object add(double val1, Object val2)
|
||
|
{
|
||
|
if (val2 instanceof Scriptable)
|
||
|
val2 = ((Scriptable) val2).getDefaultValue(null);
|
||
|
if (!(val2 instanceof String))
|
||
|
return wrapDouble(toNumber(val2) + val1);
|
||
|
return toString(val1).concat((String)val2);
|
||
|
}
|
||
|
|
||
|
public static Object elemIncrDecr(Object obj, double index,
|
||
|
Context cx, int incrDecrMask)
|
||
|
{
|
||
|
return ScriptRuntime.elemIncrDecr(obj, new Double(index), cx,
|
||
|
incrDecrMask);
|
||
|
}
|
||
|
|
||
|
public static Object[] padStart(Object[] currentArgs, int count) {
|
||
|
Object[] result = new Object[currentArgs.length + count];
|
||
|
System.arraycopy(currentArgs, 0, result, count, currentArgs.length);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
public static void initFunction(NativeFunction fn, int functionType,
|
||
|
Scriptable scope, Context cx)
|
||
|
{
|
||
|
ScriptRuntime.initFunction(cx, scope, fn, functionType, false);
|
||
|
}
|
||
|
|
||
|
public static Object callSpecial(Context cx, Callable fun,
|
||
|
Scriptable thisObj, Object[] args,
|
||
|
Scriptable scope,
|
||
|
Scriptable callerThis, int callType,
|
||
|
String fileName, int lineNumber)
|
||
|
{
|
||
|
return ScriptRuntime.callSpecial(cx, fun, thisObj, args, scope,
|
||
|
callerThis, callType,
|
||
|
fileName, lineNumber);
|
||
|
}
|
||
|
|
||
|
public static Object newObjectSpecial(Context cx, Object fun,
|
||
|
Object[] args, Scriptable scope,
|
||
|
Scriptable callerThis, int callType)
|
||
|
{
|
||
|
return ScriptRuntime.newSpecial(cx, fun, args, scope, callType);
|
||
|
}
|
||
|
|
||
|
public static Double wrapDouble(double num)
|
||
|
{
|
||
|
if (num == 0.0) {
|
||
|
if (1 / num > 0) {
|
||
|
// +0.0
|
||
|
return zeroObj;
|
||
|
}
|
||
|
} else if (num == 1.0) {
|
||
|
return oneObj;
|
||
|
} else if (num == -1.0) {
|
||
|
return minusOneObj;
|
||
|
} else if (num != num) {
|
||
|
return NaNobj;
|
||
|
}
|
||
|
return new Double(num);
|
||
|
}
|
||
|
|
||
|
static String encodeIntArray(int[] array)
|
||
|
{
|
||
|
// XXX: this extremely inefficient for small integers
|
||
|
if (array == null) { return null; }
|
||
|
int n = array.length;
|
||
|
char[] buffer = new char[1 + n * 2];
|
||
|
buffer[0] = 1;
|
||
|
for (int i = 0; i != n; ++i) {
|
||
|
int value = array[i];
|
||
|
int shift = 1 + i * 2;
|
||
|
buffer[shift] = (char)(value >>> 16);
|
||
|
buffer[shift + 1] = (char)value;
|
||
|
}
|
||
|
return new String(buffer);
|
||
|
}
|
||
|
|
||
|
private static int[] decodeIntArray(String str, int arraySize)
|
||
|
{
|
||
|
// XXX: this extremely inefficient for small integers
|
||
|
if (arraySize == 0) {
|
||
|
if (str != null) throw new IllegalArgumentException();
|
||
|
return null;
|
||
|
}
|
||
|
if (str.length() != 1 + arraySize * 2 && str.charAt(0) != 1) {
|
||
|
throw new IllegalArgumentException();
|
||
|
}
|
||
|
int[] array = new int[arraySize];
|
||
|
for (int i = 0; i != arraySize; ++i) {
|
||
|
int shift = 1 + i * 2;
|
||
|
array[i] = (str.charAt(shift) << 16) | str.charAt(shift + 1);
|
||
|
}
|
||
|
return array;
|
||
|
}
|
||
|
|
||
|
public static Scriptable newArrayLiteral(Object[] objects,
|
||
|
String encodedInts,
|
||
|
int skipCount,
|
||
|
Context cx,
|
||
|
Scriptable scope)
|
||
|
{
|
||
|
int[] skipIndexces = decodeIntArray(encodedInts, skipCount);
|
||
|
return newArrayLiteral(objects, skipIndexces, cx, scope);
|
||
|
}
|
||
|
|
||
|
public static void main(final Script script, final String[] args)
|
||
|
{
|
||
|
ContextFactory.getGlobal().call(new ContextAction() {
|
||
|
public Object run(Context cx)
|
||
|
{
|
||
|
ScriptableObject global = getGlobal(cx);
|
||
|
|
||
|
// get the command line arguments and define "arguments"
|
||
|
// array in the top-level object
|
||
|
Object[] argsCopy = new Object[args.length];
|
||
|
System.arraycopy(args, 0, argsCopy, 0, args.length);
|
||
|
Scriptable argsObj = cx.newArray(global, argsCopy);
|
||
|
global.defineProperty("arguments", argsObj,
|
||
|
ScriptableObject.DONTENUM);
|
||
|
script.exec(cx, global);
|
||
|
return null;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static void throwStopIteration(Object obj) {
|
||
|
throw new JavaScriptException(
|
||
|
NativeIterator.getStopIterationObject((Scriptable)obj), "", 0);
|
||
|
}
|
||
|
|
||
|
public static Scriptable createNativeGenerator(NativeFunction funObj,
|
||
|
Scriptable scope,
|
||
|
Scriptable thisObj,
|
||
|
int maxLocals,
|
||
|
int maxStack)
|
||
|
{
|
||
|
return new NativeGenerator(scope, funObj,
|
||
|
new GeneratorState(thisObj, maxLocals, maxStack));
|
||
|
}
|
||
|
|
||
|
public static Object[] getGeneratorStackState(Object obj) {
|
||
|
GeneratorState rgs = (GeneratorState) obj;
|
||
|
if (rgs.stackState == null)
|
||
|
rgs.stackState = new Object[rgs.maxStack];
|
||
|
return rgs.stackState;
|
||
|
}
|
||
|
|
||
|
public static Object[] getGeneratorLocalsState(Object obj) {
|
||
|
GeneratorState rgs = (GeneratorState) obj;
|
||
|
if (rgs.localsState == null)
|
||
|
rgs.localsState = new Object[rgs.maxLocals];
|
||
|
return rgs.localsState;
|
||
|
}
|
||
|
|
||
|
public static class GeneratorState {
|
||
|
static final String CLASS_NAME =
|
||
|
"org/mozilla/javascript/optimizer/OptRuntime$GeneratorState";
|
||
|
|
||
|
public int resumptionPoint;
|
||
|
static final String resumptionPoint_NAME = "resumptionPoint";
|
||
|
static final String resumptionPoint_TYPE = "I";
|
||
|
|
||
|
public Scriptable thisObj;
|
||
|
static final String thisObj_NAME = "thisObj";
|
||
|
static final String thisObj_TYPE =
|
||
|
"Lorg/mozilla/javascript/Scriptable;";
|
||
|
|
||
|
Object[] stackState;
|
||
|
Object[] localsState;
|
||
|
int maxLocals;
|
||
|
int maxStack;
|
||
|
|
||
|
GeneratorState(Scriptable thisObj, int maxLocals, int maxStack) {
|
||
|
this.thisObj = thisObj;
|
||
|
this.maxLocals = maxLocals;
|
||
|
this.maxStack = maxStack;
|
||
|
}
|
||
|
}
|
||
|
}
|