AddPush() public method

public AddPush ( bool k ) : void
k bool
return void
Example #1
0
		internal virtual void PushNumberAsObject(ClassFileWriter cfw, double num)
		{
			if (num == 0.0)
			{
				if (1 / num > 0)
				{
					// +0.0
					cfw.Add(ByteCode.GETSTATIC, "org/mozilla/javascript/optimizer/OptRuntime", "zeroObj", "Ljava/lang/Double;");
				}
				else
				{
					cfw.AddPush(num);
					AddDoubleWrap(cfw);
				}
			}
			else
			{
				if (num == 1.0)
				{
					cfw.Add(ByteCode.GETSTATIC, "org/mozilla/javascript/optimizer/OptRuntime", "oneObj", "Ljava/lang/Double;");
					return;
				}
				else
				{
					if (num == -1.0)
					{
						cfw.Add(ByteCode.GETSTATIC, "org/mozilla/javascript/optimizer/OptRuntime", "minusOneObj", "Ljava/lang/Double;");
					}
					else
					{
						if (num != num)
						{
							cfw.Add(ByteCode.GETSTATIC, "org/mozilla/javascript/ScriptRuntime", "NaNobj", "Ljava/lang/Double;");
						}
						else
						{
							if (itsConstantListSize >= 2000)
							{
								// There appears to be a limit in the JVM on either the number
								// of static fields in a class or the size of the class
								// initializer. Either way, we can't have any more than 2000
								// statically init'd constants.
								cfw.AddPush(num);
								AddDoubleWrap(cfw);
							}
							else
							{
								int N = itsConstantListSize;
								int index = 0;
								if (N == 0)
								{
									itsConstantList = new double[64];
								}
								else
								{
									double[] array = itsConstantList;
									while (index != N && array[index] != num)
									{
										++index;
									}
									if (N == array.Length)
									{
										array = new double[N * 2];
										System.Array.Copy(itsConstantList, 0, array, 0, N);
										itsConstantList = array;
									}
								}
								if (index == N)
								{
									itsConstantList[N] = num;
									itsConstantListSize = N + 1;
								}
								string constantName = "_k" + index;
								string constantType = GetStaticConstantWrapperType(num);
								cfw.Add(ByteCode.GETSTATIC, mainClassName, constantName, constantType);
							}
						}
					}
				}
			}
		}
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 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 #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 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);
		}