AddALoad() public method

Load object from the given local into stack.
Load object from the given local into stack.
public AddALoad ( int local ) : void
local int number of local register
return void
Example #1
0
		private void GenerateFunctionInit(ClassFileWriter cfw, OptFunctionNode ofn)
		{
			int CONTEXT_ARG = 1;
			int SCOPE_ARG = 2;
			cfw.StartMethod(GetFunctionInitMethodName(ofn), FUNCTION_INIT_SIGNATURE, (short)(ClassFileWriter.ACC_PRIVATE | ClassFileWriter.ACC_FINAL));
			// Call NativeFunction.initScriptFunction
			cfw.AddLoadThis();
			cfw.AddALoad(CONTEXT_ARG);
			cfw.AddALoad(SCOPE_ARG);
			cfw.AddInvoke(ByteCode.INVOKEVIRTUAL, "org/mozilla/javascript/NativeFunction", "initScriptFunction", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")V");
			// precompile all regexp literals
			if (ofn.fnode.GetRegexpCount() != 0)
			{
				cfw.AddALoad(CONTEXT_ARG);
				cfw.AddInvoke(ByteCode.INVOKESTATIC, mainClassName, REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE);
			}
			cfw.Add(ByteCode.RETURN);
			// 3 = (scriptThis/functionRef) + scope + context
			cfw.StopMethod((short)3);
		}
Example #2
0
		private void EmitRegExpInit(ClassFileWriter cfw)
		{
			// precompile all regexp literals
			int totalRegCount = 0;
			for (int i = 0; i != scriptOrFnNodes.Length; ++i)
			{
				totalRegCount += scriptOrFnNodes[i].GetRegexpCount();
			}
			if (totalRegCount == 0)
			{
				return;
			}
			cfw.StartMethod(REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE));
			cfw.AddField("_reInitDone", "Z", (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE | ClassFileWriter.ACC_VOLATILE));
			cfw.Add(ByteCode.GETSTATIC, mainClassName, "_reInitDone", "Z");
			int doInit = cfw.AcquireLabel();
			cfw.Add(ByteCode.IFEQ, doInit);
			cfw.Add(ByteCode.RETURN);
			cfw.MarkLabel(doInit);
			// get regexp proxy and store it in local slot 1
			cfw.AddALoad(0);
			// context
			cfw.AddInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "checkRegExpProxy", "(Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/RegExpProxy;");
			cfw.AddAStore(1);
			// proxy
			// We could apply double-checked locking here but concurrency
			// shouldn't be a problem in practice
			for (int i_1 = 0; i_1 != scriptOrFnNodes.Length; ++i_1)
			{
				ScriptNode n = scriptOrFnNodes[i_1];
				int regCount = n.GetRegexpCount();
				for (int j = 0; j != regCount; ++j)
				{
					string reFieldName = GetCompiledRegexpName(n, j);
					string reFieldType = "Ljava/lang/Object;";
					string reString = n.GetRegexpString(j);
					string reFlags = n.GetRegexpFlags(j);
					cfw.AddField(reFieldName, reFieldType, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE));
					cfw.AddALoad(1);
					// proxy
					cfw.AddALoad(0);
					// context
					cfw.AddPush(reString);
					if (reFlags == null)
					{
						cfw.Add(ByteCode.ACONST_NULL);
					}
					else
					{
						cfw.AddPush(reFlags);
					}
					cfw.AddInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/RegExpProxy", "compileRegExp", "(Lorg/mozilla/javascript/Context;" + "Ljava/lang/String;Ljava/lang/String;" + ")Ljava/lang/Object;");
					cfw.Add(ByteCode.PUTSTATIC, mainClassName, reFieldName, reFieldType);
				}
			}
			cfw.AddPush(1);
			cfw.Add(ByteCode.PUTSTATIC, mainClassName, "_reInitDone", "Z");
			cfw.Add(ByteCode.RETURN);
			cfw.StopMethod((short)2);
		}
Example #3
0
		private void GenerateFunctionConstructor(ClassFileWriter cfw)
		{
			int SCOPE_ARG = 1;
			int CONTEXT_ARG = 2;
			int ID_ARG = 3;
			cfw.StartMethod("<init>", FUNCTION_CONSTRUCTOR_SIGNATURE, ClassFileWriter.ACC_PUBLIC);
			cfw.AddALoad(0);
			cfw.AddInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME, "<init>", "()V");
			cfw.AddLoadThis();
			cfw.AddILoad(ID_ARG);
			cfw.Add(ByteCode.PUTFIELD, cfw.GetClassName(), ID_FIELD_NAME, "I");
			cfw.AddLoadThis();
			cfw.AddALoad(CONTEXT_ARG);
			cfw.AddALoad(SCOPE_ARG);
			int start = (scriptOrFnNodes[0].GetType() == Token.SCRIPT) ? 1 : 0;
			int end = scriptOrFnNodes.Length;
			if (start == end)
			{
				throw BadTree();
			}
			bool generateSwitch = (2 <= end - start);
			int switchStart = 0;
			int switchStackTop = 0;
			if (generateSwitch)
			{
				cfw.AddILoad(ID_ARG);
				// do switch from (start + 1,  end - 1) mapping start to
				// the default case
				switchStart = cfw.AddTableSwitch(start + 1, end - 1);
			}
			for (int i = start; i != end; ++i)
			{
				if (generateSwitch)
				{
					if (i == start)
					{
						cfw.MarkTableSwitchDefault(switchStart);
						switchStackTop = cfw.GetStackTop();
					}
					else
					{
						cfw.MarkTableSwitchCase(switchStart, i - 1 - start, switchStackTop);
					}
				}
				OptFunctionNode ofn = OptFunctionNode.Get(scriptOrFnNodes[i]);
				cfw.AddInvoke(ByteCode.INVOKESPECIAL, mainClassName, GetFunctionInitMethodName(ofn), FUNCTION_INIT_SIGNATURE);
				cfw.Add(ByteCode.RETURN);
			}
			// 4 = this + scope + context + id
			cfw.StopMethod((short)4);
		}
Example #4
0
		private void GenerateExecute(ClassFileWriter cfw)
		{
			cfw.StartMethod("exec", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Ljava/lang/Object;", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL));
			int CONTEXT_ARG = 1;
			int SCOPE_ARG = 2;
			cfw.AddLoadThis();
			cfw.AddALoad(CONTEXT_ARG);
			cfw.AddALoad(SCOPE_ARG);
			cfw.Add(ByteCode.DUP);
			cfw.Add(ByteCode.ACONST_NULL);
			cfw.AddInvoke(ByteCode.INVOKEVIRTUAL, cfw.GetClassName(), "call", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;" + ")Ljava/lang/Object;");
			cfw.Add(ByteCode.ARETURN);
			// 3 = this + context + scope
			cfw.StopMethod((short)3);
		}
Example #5
0
		private void GenerateCallMethod(ClassFileWriter cfw)
		{
			cfw.StartMethod("call", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;)Ljava/lang/Object;", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL));
			// Generate code for:
			// if (!ScriptRuntime.hasTopCall(cx)) {
			//     return ScriptRuntime.doTopCall(this, cx, scope, thisObj, args);
			// }
			int nonTopCallLabel = cfw.AcquireLabel();
			cfw.AddALoad(1);
			//cx
			cfw.AddInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "hasTopCall", "(Lorg/mozilla/javascript/Context;" + ")Z");
			cfw.Add(ByteCode.IFNE, nonTopCallLabel);
			cfw.AddALoad(0);
			cfw.AddALoad(1);
			cfw.AddALoad(2);
			cfw.AddALoad(3);
			cfw.AddALoad(4);
			cfw.AddInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "doTopCall", "(Lorg/mozilla/javascript/Callable;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;" + ")Ljava/lang/Object;");
			cfw.Add(ByteCode.ARETURN);
			cfw.MarkLabel(nonTopCallLabel);
			// Now generate switch to call the real methods
			cfw.AddALoad(0);
			cfw.AddALoad(1);
			cfw.AddALoad(2);
			cfw.AddALoad(3);
			cfw.AddALoad(4);
			int end = scriptOrFnNodes.Length;
			bool generateSwitch = (2 <= end);
			int switchStart = 0;
			int switchStackTop = 0;
			if (generateSwitch)
			{
				cfw.AddLoadThis();
				cfw.Add(ByteCode.GETFIELD, cfw.GetClassName(), ID_FIELD_NAME, "I");
				// do switch from (1,  end - 1) mapping 0 to
				// the default case
				switchStart = cfw.AddTableSwitch(1, end - 1);
			}
			for (int i = 0; i != end; ++i)
			{
				ScriptNode n = scriptOrFnNodes[i];
				if (generateSwitch)
				{
					if (i == 0)
					{
						cfw.MarkTableSwitchDefault(switchStart);
						switchStackTop = cfw.GetStackTop();
					}
					else
					{
						cfw.MarkTableSwitchCase(switchStart, i - 1, switchStackTop);
					}
				}
				if (n.GetType() == Token.FUNCTION)
				{
					OptFunctionNode ofn = OptFunctionNode.Get(n);
					if (ofn.IsTargetOfDirectCall())
					{
						int pcount = ofn.fnode.GetParamCount();
						if (pcount != 0)
						{
							// loop invariant:
							// stack top == arguments array from addALoad4()
							for (int p = 0; p != pcount; ++p)
							{
								cfw.Add(ByteCode.ARRAYLENGTH);
								cfw.AddPush(p);
								int undefArg = cfw.AcquireLabel();
								int beyond = cfw.AcquireLabel();
								cfw.Add(ByteCode.IF_ICMPLE, undefArg);
								// get array[p]
								cfw.AddALoad(4);
								cfw.AddPush(p);
								cfw.Add(ByteCode.AALOAD);
								cfw.Add(ByteCode.GOTO, beyond);
								cfw.MarkLabel(undefArg);
								PushUndefined(cfw);
								cfw.MarkLabel(beyond);
								// Only one push
								cfw.AdjustStackTop(-1);
								cfw.AddPush(0.0);
								// restore invariant
								cfw.AddALoad(4);
							}
						}
					}
				}
				cfw.AddInvoke(ByteCode.INVOKESTATIC, mainClassName, GetBodyMethodName(n), GetBodyMethodSignature(n));
				cfw.Add(ByteCode.ARETURN);
			}
			cfw.StopMethod((short)5);
		}
Example #6
0
		// How dispatch to generators works:
		// Two methods are generated corresponding to a user-written generator.
		// One of these creates a generator object (NativeGenerator), which is
		// returned to the user. The other method contains all of the body code
		// of the generator.
		// When a user calls a generator, the call() method dispatches control to
		// to the method that creates the NativeGenerator object. Subsequently when
		// the user invokes .next(), .send() or any such method on the generator
		// object, the resumeGenerator() below dispatches the call to the
		// method corresponding to the generator body. As a matter of convention
		// the generator body is given the name of the generator activation function
		// appended by "_gen".
		private void GenerateResumeGenerator(ClassFileWriter cfw)
		{
			bool hasGenerators = false;
			for (int i = 0; i < scriptOrFnNodes.Length; i++)
			{
				if (IsGenerator(scriptOrFnNodes[i]))
				{
					hasGenerators = true;
				}
			}
			// if there are no generators defined, we don't implement a
			// resumeGenerator(). The base class provides a default implementation.
			if (!hasGenerators)
			{
				return;
			}
			cfw.StartMethod("resumeGenerator", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "ILjava/lang/Object;" + "Ljava/lang/Object;)Ljava/lang/Object;", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL));
			// load arguments for dispatch to the corresponding *_gen method
			cfw.AddALoad(0);
			cfw.AddALoad(1);
			cfw.AddALoad(2);
			cfw.AddALoad(4);
			cfw.AddALoad(5);
			cfw.AddILoad(3);
			cfw.AddLoadThis();
			cfw.Add(ByteCode.GETFIELD, cfw.GetClassName(), ID_FIELD_NAME, "I");
			int startSwitch = cfw.AddTableSwitch(0, scriptOrFnNodes.Length - 1);
			cfw.MarkTableSwitchDefault(startSwitch);
			int endlabel = cfw.AcquireLabel();
			for (int i_1 = 0; i_1 < scriptOrFnNodes.Length; i_1++)
			{
				ScriptNode n = scriptOrFnNodes[i_1];
				cfw.MarkTableSwitchCase(startSwitch, i_1, (short)6);
				if (IsGenerator(n))
				{
					string type = "(" + mainClassSignature + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/Object;" + "Ljava/lang/Object;I)Ljava/lang/Object;";
					cfw.AddInvoke(ByteCode.INVOKESTATIC, mainClassName, GetBodyMethodName(n) + "_gen", type);
					cfw.Add(ByteCode.ARETURN);
				}
				else
				{
					cfw.Add(ByteCode.GOTO, endlabel);
				}
			}
			cfw.MarkLabel(endlabel);
			PushUndefined(cfw);
			cfw.Add(ByteCode.ARETURN);
			// this method uses as many locals as there are arguments (hence 6)
			cfw.StopMethod((short)6);
		}
Example #7
0
		private void EmitDirectConstructor(ClassFileWriter cfw, OptFunctionNode ofn)
		{
			cfw.StartMethod(GetDirectCtorName(ofn.fnode), GetBodyMethodSignature(ofn.fnode), (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE));
			int argCount = ofn.fnode.GetParamCount();
			int firstLocal = (4 + argCount * 3) + 1;
			cfw.AddALoad(0);
			// this
			cfw.AddALoad(1);
			// cx
			cfw.AddALoad(2);
			// scope
			cfw.AddInvoke(ByteCode.INVOKEVIRTUAL, "org/mozilla/javascript/BaseFunction", "createObject", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Scriptable;");
			cfw.AddAStore(firstLocal);
			cfw.AddALoad(0);
			cfw.AddALoad(1);
			cfw.AddALoad(2);
			cfw.AddALoad(firstLocal);
			for (int i = 0; i < argCount; i++)
			{
				cfw.AddALoad(4 + (i * 3));
				cfw.AddDLoad(5 + (i * 3));
			}
			cfw.AddALoad(4 + argCount * 3);
			cfw.AddInvoke(ByteCode.INVOKESTATIC, mainClassName, GetBodyMethodName(ofn.fnode), GetBodyMethodSignature(ofn.fnode));
			int exitLabel = cfw.AcquireLabel();
			cfw.Add(ByteCode.DUP);
			// make a copy of direct call result
			cfw.Add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Scriptable");
			cfw.Add(ByteCode.IFEQ, exitLabel);
			// cast direct call result
			cfw.Add(ByteCode.CHECKCAST, "org/mozilla/javascript/Scriptable");
			cfw.Add(ByteCode.ARETURN);
			cfw.MarkLabel(exitLabel);
			cfw.AddALoad(firstLocal);
			cfw.Add(ByteCode.ARETURN);
			cfw.StopMethod((short)(firstLocal + 1));
		}