StopMethod() public method

Complete generation of the method.
Complete generation of the method. After this method is called, no more code can be added to the method begun with startMethod.
public StopMethod ( short maxLocals ) : void
maxLocals short /// the maximum number of local variable slots /// (a.k.a. Java registers) used by the method ///
return void
Example #1
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 #2
0
		private void EmitConstantDudeInitializers(ClassFileWriter cfw)
		{
			int N = itsConstantListSize;
			if (N == 0)
			{
				return;
			}
			cfw.StartMethod("<clinit>", "()V", (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_FINAL));
			double[] array = itsConstantList;
			for (int i = 0; i != N; ++i)
			{
				double num = array[i];
				string constantName = "_k" + i;
				string constantType = GetStaticConstantWrapperType(num);
				cfw.AddField(constantName, constantType, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE));
				int inum = (int)num;
				if (inum == num)
				{
					cfw.AddPush(inum);
					cfw.AddInvoke(ByteCode.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
				}
				else
				{
					cfw.AddPush(num);
					AddDoubleWrap(cfw);
				}
				cfw.Add(ByteCode.PUTSTATIC, mainClassName, constantName, constantType);
			}
			cfw.Add(ByteCode.RETURN);
			cfw.StopMethod((short)0);
		}
Example #3
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 #4
0
		private void GenerateNativeFunctionOverrides(ClassFileWriter cfw, string encodedSource)
		{
			// Override NativeFunction.getLanguageVersion() with
			// public int getLanguageVersion() { return <version-constant>; }
			cfw.StartMethod("getLanguageVersion", "()I", ClassFileWriter.ACC_PUBLIC);
			cfw.AddPush(compilerEnv.GetLanguageVersion());
			cfw.Add(ByteCode.IRETURN);
			// 1: this and no argument or locals
			cfw.StopMethod((short)1);
			// The rest of NativeFunction overrides require specific code for each
			// script/function id
			int Do_getFunctionName = 0;
			int Do_getParamCount = 1;
			int Do_getParamAndVarCount = 2;
			int Do_getParamOrVarName = 3;
			int Do_getEncodedSource = 4;
			int Do_getParamOrVarConst = 5;
			int SWITCH_COUNT = 6;
			for (int methodIndex = 0; methodIndex != SWITCH_COUNT; ++methodIndex)
			{
				if (methodIndex == Do_getEncodedSource && encodedSource == null)
				{
					continue;
				}
				// Generate:
				//   prologue;
				//   switch over function id to implement function-specific action
				//   epilogue
				short methodLocals;
				switch (methodIndex)
				{
					case Do_getFunctionName:
					{
						methodLocals = 1;
						// Only this
						cfw.StartMethod("getFunctionName", "()Ljava/lang/String;", ClassFileWriter.ACC_PUBLIC);
						break;
					}

					case Do_getParamCount:
					{
						methodLocals = 1;
						// Only this
						cfw.StartMethod("getParamCount", "()I", ClassFileWriter.ACC_PUBLIC);
						break;
					}

					case Do_getParamAndVarCount:
					{
						methodLocals = 1;
						// Only this
						cfw.StartMethod("getParamAndVarCount", "()I", ClassFileWriter.ACC_PUBLIC);
						break;
					}

					case Do_getParamOrVarName:
					{
						methodLocals = 1 + 1;
						// this + paramOrVarIndex
						cfw.StartMethod("getParamOrVarName", "(I)Ljava/lang/String;", ClassFileWriter.ACC_PUBLIC);
						break;
					}

					case Do_getParamOrVarConst:
					{
						methodLocals = 1 + 1 + 1;
						// this + paramOrVarName
						cfw.StartMethod("getParamOrVarConst", "(I)Z", ClassFileWriter.ACC_PUBLIC);
						break;
					}

					case Do_getEncodedSource:
					{
						methodLocals = 1;
						// Only this
						cfw.StartMethod("getEncodedSource", "()Ljava/lang/String;", ClassFileWriter.ACC_PUBLIC);
						cfw.AddPush(encodedSource);
						break;
					}

					default:
					{
						throw Kit.CodeBug();
					}
				}
				int count = scriptOrFnNodes.Length;
				int switchStart = 0;
				int switchStackTop = 0;
				if (count > 1)
				{
					// Generate switch but only if there is more then one
					// script/function
					cfw.AddLoadThis();
					cfw.Add(ByteCode.GETFIELD, cfw.GetClassName(), ID_FIELD_NAME, "I");
					// do switch from 1 .. count - 1 mapping 0 to the default case
					switchStart = cfw.AddTableSwitch(1, count - 1);
				}
				for (int i = 0; i != count; ++i)
				{
					ScriptNode n = scriptOrFnNodes[i];
					if (i == 0)
					{
						if (count > 1)
						{
							cfw.MarkTableSwitchDefault(switchStart);
							switchStackTop = cfw.GetStackTop();
						}
					}
					else
					{
						cfw.MarkTableSwitchCase(switchStart, i - 1, switchStackTop);
					}
					switch (methodIndex)
					{
						case Do_getFunctionName:
						{
							// Impelemnet method-specific switch code
							// Push function name
							if (n.GetType() == Token.SCRIPT)
							{
								cfw.AddPush(string.Empty);
							}
							else
							{
								string name = ((FunctionNode)n).GetName();
								cfw.AddPush(name);
							}
							cfw.Add(ByteCode.ARETURN);
							break;
						}

						case Do_getParamCount:
						{
							// Push number of defined parameters
							cfw.AddPush(n.GetParamCount());
							cfw.Add(ByteCode.IRETURN);
							break;
						}

						case Do_getParamAndVarCount:
						{
							// Push number of defined parameters and declared variables
							cfw.AddPush(n.GetParamAndVarCount());
							cfw.Add(ByteCode.IRETURN);
							break;
						}

						case Do_getParamOrVarName:
						{
							// Push name of parameter using another switch
							// over paramAndVarCount
							int paramAndVarCount = n.GetParamAndVarCount();
							if (paramAndVarCount == 0)
							{
								// The runtime should never call the method in this
								// case but to make bytecode verifier happy return null
								// as throwing execption takes more code
								cfw.Add(ByteCode.ACONST_NULL);
								cfw.Add(ByteCode.ARETURN);
							}
							else
							{
								if (paramAndVarCount == 1)
								{
									// As above do not check for valid index but always
									// return the name of the first param
									cfw.AddPush(n.GetParamOrVarName(0));
									cfw.Add(ByteCode.ARETURN);
								}
								else
								{
									// Do switch over getParamOrVarName
									cfw.AddILoad(1);
									// param or var index
									// do switch from 1 .. paramAndVarCount - 1 mapping 0
									// to the default case
									int paramSwitchStart = cfw.AddTableSwitch(1, paramAndVarCount - 1);
									for (int j = 0; j != paramAndVarCount; ++j)
									{
										if (cfw.GetStackTop() != 0)
										{
											Kit.CodeBug();
										}
										string s = n.GetParamOrVarName(j);
										if (j == 0)
										{
											cfw.MarkTableSwitchDefault(paramSwitchStart);
										}
										else
										{
											cfw.MarkTableSwitchCase(paramSwitchStart, j - 1, 0);
										}
										cfw.AddPush(s);
										cfw.Add(ByteCode.ARETURN);
									}
								}
							}
							break;
						}

						case Do_getParamOrVarConst:
						{
							// Push name of parameter using another switch
							// over paramAndVarCount
							paramAndVarCount = n.GetParamAndVarCount();
							bool[] constness = n.GetParamAndVarConst();
							if (paramAndVarCount == 0)
							{
								// The runtime should never call the method in this
								// case but to make bytecode verifier happy return null
								// as throwing execption takes more code
								cfw.Add(ByteCode.ICONST_0);
								cfw.Add(ByteCode.IRETURN);
							}
							else
							{
								if (paramAndVarCount == 1)
								{
									// As above do not check for valid index but always
									// return the name of the first param
									cfw.AddPush(constness[0]);
									cfw.Add(ByteCode.IRETURN);
								}
								else
								{
									// Do switch over getParamOrVarName
									cfw.AddILoad(1);
									// param or var index
									// do switch from 1 .. paramAndVarCount - 1 mapping 0
									// to the default case
									int paramSwitchStart = cfw.AddTableSwitch(1, paramAndVarCount - 1);
									for (int j = 0; j != paramAndVarCount; ++j)
									{
										if (cfw.GetStackTop() != 0)
										{
											Kit.CodeBug();
										}
										if (j == 0)
										{
											cfw.MarkTableSwitchDefault(paramSwitchStart);
										}
										else
										{
											cfw.MarkTableSwitchCase(paramSwitchStart, j - 1, 0);
										}
										cfw.AddPush(constness[j]);
										cfw.Add(ByteCode.IRETURN);
									}
								}
							}
							break;
						}

						case Do_getEncodedSource:
						{
							// Push number encoded source start and end
							// to prepare for encodedSource.substring(start, end)
							cfw.AddPush(n.GetEncodedSourceStart());
							cfw.AddPush(n.GetEncodedSourceEnd());
							cfw.AddInvoke(ByteCode.INVOKEVIRTUAL, "java/lang/String", "substring", "(II)Ljava/lang/String;");
							cfw.Add(ByteCode.ARETURN);
							break;
						}

						default:
						{
							throw Kit.CodeBug();
						}
					}
				}
				cfw.StopMethod(methodLocals);
			}
		}
Example #5
0
		private void GenerateScriptCtor(ClassFileWriter cfw)
		{
			cfw.StartMethod("<init>", "()V", ClassFileWriter.ACC_PUBLIC);
			cfw.AddLoadThis();
			cfw.AddInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME, "<init>", "()V");
			// set id to 0
			cfw.AddLoadThis();
			cfw.AddPush(0);
			cfw.Add(ByteCode.PUTFIELD, cfw.GetClassName(), ID_FIELD_NAME, "I");
			cfw.Add(ByteCode.RETURN);
			// 1 parameter = this
			cfw.StopMethod((short)1);
		}
Example #6
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 #7
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 #8
0
		// 5: this, cx, scope, js this, args[]
		private void GenerateMain(ClassFileWriter cfw)
		{
			cfw.StartMethod("main", "([Ljava/lang/String;)V", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_STATIC));
			// load new ScriptImpl()
			cfw.Add(ByteCode.NEW, cfw.GetClassName());
			cfw.Add(ByteCode.DUP);
			cfw.AddInvoke(ByteCode.INVOKESPECIAL, cfw.GetClassName(), "<init>", "()V");
			// load 'args'
			cfw.Add(ByteCode.ALOAD_0);
			// Call mainMethodClass.main(Script script, String[] args)
			cfw.AddInvoke(ByteCode.INVOKESTATIC, mainMethodClass, "main", "(Lorg/mozilla/javascript/Script;[Ljava/lang/String;)V");
			cfw.Add(ByteCode.RETURN);
			// 1 = String[] args
			cfw.StopMethod((short)1);
		}
Example #9
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 #10
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 #11
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));
		}