Esempio n. 1
0
		private void VisitSetConstVar(Node node, Node child, bool needValue)
		{
			if (!hasVarsInRegs)
			{
				Kit.CodeBug();
			}
			int varIndex = fnCurrent.GetVarIndex(node);
			GenerateExpression(child.GetNext(), node);
			bool isNumber = (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1);
			short reg = varRegisters[varIndex];
			int beyond = cfw.AcquireLabel();
			int noAssign = cfw.AcquireLabel();
			if (isNumber)
			{
				cfw.AddILoad(reg + 2);
				cfw.Add(ByteCode.IFNE, noAssign);
				short stack = cfw.GetStackTop();
				cfw.AddPush(1);
				cfw.AddIStore(reg + 2);
				cfw.AddDStore(reg);
				if (needValue)
				{
					cfw.AddDLoad(reg);
					cfw.MarkLabel(noAssign, stack);
				}
				else
				{
					cfw.Add(ByteCode.GOTO, beyond);
					cfw.MarkLabel(noAssign, stack);
					cfw.Add(ByteCode.POP2);
				}
			}
			else
			{
				cfw.AddILoad(reg + 1);
				cfw.Add(ByteCode.IFNE, noAssign);
				short stack = cfw.GetStackTop();
				cfw.AddPush(1);
				cfw.AddIStore(reg + 1);
				cfw.AddAStore(reg);
				if (needValue)
				{
					cfw.AddALoad(reg);
					cfw.MarkLabel(noAssign, stack);
				}
				else
				{
					cfw.Add(ByteCode.GOTO, beyond);
					cfw.MarkLabel(noAssign, stack);
					cfw.Add(ByteCode.POP);
				}
			}
			cfw.MarkLabel(beyond);
		}
Esempio n. 2
0
		private void VisitSetElem(int type, Node node, Node child)
		{
			GenerateExpression(child, node);
			child = child.GetNext();
			if (type == Token.SETELEM_OP)
			{
				cfw.Add(ByteCode.DUP);
			}
			GenerateExpression(child, node);
			child = child.GetNext();
			bool indexIsNumber = (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1);
			if (type == Token.SETELEM_OP)
			{
				if (indexIsNumber)
				{
					// stack: ... object object number
					//        -> ... object number object number
					cfw.Add(ByteCode.DUP2_X1);
					cfw.AddALoad(contextLocal);
					AddOptRuntimeInvoke("getObjectIndex", "(Ljava/lang/Object;D" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
				}
				else
				{
					// stack: ... object object indexObject
					//        -> ... object indexObject object indexObject
					cfw.Add(ByteCode.DUP_X1);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("getObjectElem", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
				}
			}
			GenerateExpression(child, node);
			cfw.AddALoad(contextLocal);
			if (indexIsNumber)
			{
				AddScriptRuntimeInvoke("setObjectIndex", "(Ljava/lang/Object;" + "D" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
			}
			else
			{
				AddScriptRuntimeInvoke("setObjectElem", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
			}
		}
Esempio n. 3
0
		private void VisitGetVar(Node node)
		{
			if (!hasVarsInRegs)
			{
				Kit.CodeBug();
			}
			int varIndex = fnCurrent.GetVarIndex(node);
			short reg = varRegisters[varIndex];
			if (VarIsDirectCallParameter(varIndex))
			{
				// Remember that here the isNumber flag means that we
				// want to use the incoming parameter in a Number
				// context, so test the object type and convert the
				//  value as necessary.
				if (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1)
				{
					DcpLoadAsNumber(reg);
				}
				else
				{
					DcpLoadAsObject(reg);
				}
			}
			else
			{
				if (fnCurrent.IsNumberVar(varIndex))
				{
					cfw.AddDLoad(reg);
				}
				else
				{
					cfw.AddALoad(reg);
				}
			}
		}
Esempio n. 4
0
		private void VisitSetVar(Node node, Node child, bool needValue)
		{
			if (!hasVarsInRegs)
			{
				Kit.CodeBug();
			}
			int varIndex = fnCurrent.GetVarIndex(node);
			GenerateExpression(child.GetNext(), node);
			bool isNumber = (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1);
			short reg = varRegisters[varIndex];
			bool[] constDeclarations = fnCurrent.fnode.GetParamAndVarConst();
			if (constDeclarations[varIndex])
			{
				if (!needValue)
				{
					if (isNumber)
					{
						cfw.Add(ByteCode.POP2);
					}
					else
					{
						cfw.Add(ByteCode.POP);
					}
				}
			}
			else
			{
				if (VarIsDirectCallParameter(varIndex))
				{
					if (isNumber)
					{
						if (needValue)
						{
							cfw.Add(ByteCode.DUP2);
						}
						cfw.AddALoad(reg);
						cfw.Add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
						int isNumberLabel = cfw.AcquireLabel();
						int beyond = cfw.AcquireLabel();
						cfw.Add(ByteCode.IF_ACMPEQ, isNumberLabel);
						short stack = cfw.GetStackTop();
						AddDoubleWrap();
						cfw.AddAStore(reg);
						cfw.Add(ByteCode.GOTO, beyond);
						cfw.MarkLabel(isNumberLabel, stack);
						cfw.AddDStore(reg + 1);
						cfw.MarkLabel(beyond);
					}
					else
					{
						if (needValue)
						{
							cfw.Add(ByteCode.DUP);
						}
						cfw.AddAStore(reg);
					}
				}
				else
				{
					bool isNumberVar = fnCurrent.IsNumberVar(varIndex);
					if (isNumber)
					{
						if (isNumberVar)
						{
							cfw.AddDStore(reg);
							if (needValue)
							{
								cfw.AddDLoad(reg);
							}
						}
						else
						{
							if (needValue)
							{
								cfw.Add(ByteCode.DUP2);
							}
							// Cannot save number in variable since !isNumberVar,
							// so convert to object
							AddDoubleWrap();
							cfw.AddAStore(reg);
						}
					}
					else
					{
						if (isNumberVar)
						{
							Kit.CodeBug();
						}
						cfw.AddAStore(reg);
						if (needValue)
						{
							cfw.AddALoad(reg);
						}
					}
				}
			}
		}
Esempio n. 5
0
		private void VisitBitOp(Node node, int type, Node child)
		{
			int childNumberFlag = node.GetIntProp(Node.ISNUMBER_PROP, -1);
			GenerateExpression(child, node);
			// special-case URSH; work with the target arg as a long, so
			// that we can return a 32-bit unsigned value, and call
			// toUint32 instead of toInt32.
			if (type == Token.URSH)
			{
				AddScriptRuntimeInvoke("toUint32", "(Ljava/lang/Object;)J");
				GenerateExpression(child.GetNext(), node);
				AddScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I");
				// Looks like we need to explicitly mask the shift to 5 bits -
				// LUSHR takes 6 bits.
				cfw.AddPush(31);
				cfw.Add(ByteCode.IAND);
				cfw.Add(ByteCode.LUSHR);
				cfw.Add(ByteCode.L2D);
				AddDoubleWrap();
				return;
			}
			if (childNumberFlag == -1)
			{
				AddScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I");
				GenerateExpression(child.GetNext(), node);
				AddScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I");
			}
			else
			{
				AddScriptRuntimeInvoke("toInt32", "(D)I");
				GenerateExpression(child.GetNext(), node);
				AddScriptRuntimeInvoke("toInt32", "(D)I");
			}
			switch (type)
			{
				case Token.BITOR:
				{
					cfw.Add(ByteCode.IOR);
					break;
				}

				case Token.BITXOR:
				{
					cfw.Add(ByteCode.IXOR);
					break;
				}

				case Token.BITAND:
				{
					cfw.Add(ByteCode.IAND);
					break;
				}

				case Token.RSH:
				{
					cfw.Add(ByteCode.ISHR);
					break;
				}

				case Token.LSH:
				{
					cfw.Add(ByteCode.ISHL);
					break;
				}

				default:
				{
					throw Codegen.BadTree();
				}
			}
			cfw.Add(ByteCode.I2D);
			if (childNumberFlag == -1)
			{
				AddDoubleWrap();
			}
		}
Esempio n. 6
0
		private void VisitIfJumpRelOp(Node node, Node child, int trueGOTO, int falseGOTO)
		{
			if (trueGOTO == -1 || falseGOTO == -1)
			{
				throw Codegen.BadTree();
			}
			int type = node.GetType();
			Node rChild = child.GetNext();
			if (type == Token.INSTANCEOF || type == Token.IN)
			{
				GenerateExpression(child, node);
				GenerateExpression(rChild, node);
				cfw.AddALoad(contextLocal);
				AddScriptRuntimeInvoke((type == Token.INSTANCEOF) ? "instanceOf" : "in", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Z");
				cfw.Add(ByteCode.IFNE, trueGOTO);
				cfw.Add(ByteCode.GOTO, falseGOTO);
				return;
			}
			int childNumberFlag = node.GetIntProp(Node.ISNUMBER_PROP, -1);
			int left_dcp_register = NodeIsDirectCallParameter(child);
			int right_dcp_register = NodeIsDirectCallParameter(rChild);
			if (childNumberFlag != -1)
			{
				// Force numeric context on both parameters and optimize
				// direct call case as Optimizer currently does not handle it
				if (childNumberFlag != Node.RIGHT)
				{
					// Left already has number content
					GenerateExpression(child, node);
				}
				else
				{
					if (left_dcp_register != -1)
					{
						DcpLoadAsNumber(left_dcp_register);
					}
					else
					{
						GenerateExpression(child, node);
						AddObjectToDouble();
					}
				}
				if (childNumberFlag != Node.LEFT)
				{
					// Right already has number content
					GenerateExpression(rChild, node);
				}
				else
				{
					if (right_dcp_register != -1)
					{
						DcpLoadAsNumber(right_dcp_register);
					}
					else
					{
						GenerateExpression(rChild, node);
						AddObjectToDouble();
					}
				}
				GenSimpleCompare(type, trueGOTO, falseGOTO);
			}
			else
			{
				if (left_dcp_register != -1 && right_dcp_register != -1)
				{
					// Generate code to dynamically check for number content
					// if both operands are dcp
					short stack = cfw.GetStackTop();
					int leftIsNotNumber = cfw.AcquireLabel();
					cfw.AddALoad(left_dcp_register);
					cfw.Add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
					cfw.Add(ByteCode.IF_ACMPNE, leftIsNotNumber);
					cfw.AddDLoad(left_dcp_register + 1);
					DcpLoadAsNumber(right_dcp_register);
					GenSimpleCompare(type, trueGOTO, falseGOTO);
					if (stack != cfw.GetStackTop())
					{
						throw Codegen.BadTree();
					}
					cfw.MarkLabel(leftIsNotNumber);
					int rightIsNotNumber = cfw.AcquireLabel();
					cfw.AddALoad(right_dcp_register);
					cfw.Add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
					cfw.Add(ByteCode.IF_ACMPNE, rightIsNotNumber);
					cfw.AddALoad(left_dcp_register);
					AddObjectToDouble();
					cfw.AddDLoad(right_dcp_register + 1);
					GenSimpleCompare(type, trueGOTO, falseGOTO);
					if (stack != cfw.GetStackTop())
					{
						throw Codegen.BadTree();
					}
					cfw.MarkLabel(rightIsNotNumber);
					// Load both register as objects to call generic cmp_*
					cfw.AddALoad(left_dcp_register);
					cfw.AddALoad(right_dcp_register);
				}
				else
				{
					GenerateExpression(child, node);
					GenerateExpression(rChild, node);
				}
				if (type == Token.GE || type == Token.GT)
				{
					cfw.Add(ByteCode.SWAP);
				}
				string routine = ((type == Token.LT) || (type == Token.GT)) ? "cmp_LT" : "cmp_LE";
				AddScriptRuntimeInvoke(routine, "(Ljava/lang/Object;" + "Ljava/lang/Object;" + ")Z");
				cfw.Add(ByteCode.IFNE, trueGOTO);
				cfw.Add(ByteCode.GOTO, falseGOTO);
			}
		}
Esempio n. 7
0
		private void VisitIncDec(Node node)
		{
			int incrDecrMask = node.GetExistingIntProp(Node.INCRDECR_PROP);
			Node child = node.GetFirstChild();
			switch (child.GetType())
			{
				case Token.GETVAR:
				{
					if (!hasVarsInRegs)
					{
						Kit.CodeBug();
					}
					bool post = ((incrDecrMask & Node.POST_FLAG) != 0);
					int varIndex = fnCurrent.GetVarIndex(child);
					short reg = varRegisters[varIndex];
					if (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1)
					{
						int offset = VarIsDirectCallParameter(varIndex) ? 1 : 0;
						cfw.AddDLoad(reg + offset);
						if (post)
						{
							cfw.Add(ByteCode.DUP2);
						}
						cfw.AddPush(1.0);
						if ((incrDecrMask & Node.DECR_FLAG) == 0)
						{
							cfw.Add(ByteCode.DADD);
						}
						else
						{
							cfw.Add(ByteCode.DSUB);
						}
						if (!post)
						{
							cfw.Add(ByteCode.DUP2);
						}
						cfw.AddDStore(reg + offset);
					}
					else
					{
						if (VarIsDirectCallParameter(varIndex))
						{
							DcpLoadAsObject(reg);
						}
						else
						{
							cfw.AddALoad(reg);
						}
						if (post)
						{
							cfw.Add(ByteCode.DUP);
						}
						AddObjectToDouble();
						cfw.AddPush(1.0);
						if ((incrDecrMask & Node.DECR_FLAG) == 0)
						{
							cfw.Add(ByteCode.DADD);
						}
						else
						{
							cfw.Add(ByteCode.DSUB);
						}
						AddDoubleWrap();
						if (!post)
						{
							cfw.Add(ByteCode.DUP);
						}
						cfw.AddAStore(reg);
						break;
					}
					break;
				}

				case Token.NAME:
				{
					cfw.AddALoad(variableObjectLocal);
					cfw.AddPush(child.GetString());
					// push name
					cfw.AddALoad(contextLocal);
					cfw.AddPush(incrDecrMask);
					AddScriptRuntimeInvoke("nameIncrDecr", "(Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/String;" + "Lorg/mozilla/javascript/Context;" + "I)Ljava/lang/Object;");
					break;
				}

				case Token.GETPROPNOWARN:
				{
					throw Kit.CodeBug();
				}

				case Token.GETPROP:
				{
					Node getPropChild = child.GetFirstChild();
					GenerateExpression(getPropChild, node);
					GenerateExpression(getPropChild.GetNext(), node);
					cfw.AddALoad(contextLocal);
					cfw.AddPush(incrDecrMask);
					AddScriptRuntimeInvoke("propIncrDecr", "(Ljava/lang/Object;" + "Ljava/lang/String;" + "Lorg/mozilla/javascript/Context;" + "I)Ljava/lang/Object;");
					break;
				}

				case Token.GETELEM:
				{
					Node elemChild = child.GetFirstChild();
					GenerateExpression(elemChild, node);
					GenerateExpression(elemChild.GetNext(), node);
					cfw.AddALoad(contextLocal);
					cfw.AddPush(incrDecrMask);
					if (elemChild.GetNext().GetIntProp(Node.ISNUMBER_PROP, -1) != -1)
					{
						AddOptRuntimeInvoke("elemIncrDecr", "(Ljava/lang/Object;" + "D" + "Lorg/mozilla/javascript/Context;" + "I" + ")Ljava/lang/Object;");
					}
					else
					{
						AddScriptRuntimeInvoke("elemIncrDecr", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "I" + ")Ljava/lang/Object;");
					}
					break;
				}

				case Token.GET_REF:
				{
					Node refChild = child.GetFirstChild();
					GenerateExpression(refChild, node);
					cfw.AddALoad(contextLocal);
					cfw.AddPush(incrDecrMask);
					AddScriptRuntimeInvoke("refIncrDecr", "(Lorg/mozilla/javascript/Ref;" + "Lorg/mozilla/javascript/Context;" + "I)Ljava/lang/Object;");
					break;
				}

				default:
				{
					Codegen.BadTree();
					break;
				}
			}
		}
Esempio n. 8
0
		private void VisitArithmetic(Node node, int opCode, Node child, Node parent)
		{
			int childNumberFlag = node.GetIntProp(Node.ISNUMBER_PROP, -1);
			if (childNumberFlag != -1)
			{
				GenerateExpression(child, node);
				GenerateExpression(child.GetNext(), node);
				cfw.Add(opCode);
			}
			else
			{
				bool childOfArithmetic = IsArithmeticNode(parent);
				GenerateExpression(child, node);
				if (!IsArithmeticNode(child))
				{
					AddObjectToDouble();
				}
				GenerateExpression(child.GetNext(), node);
				if (!IsArithmeticNode(child.GetNext()))
				{
					AddObjectToDouble();
				}
				cfw.Add(opCode);
				if (!childOfArithmetic)
				{
					AddDoubleWrap();
				}
			}
		}
Esempio n. 9
0
		private void GenerateCallArgArray(Node node, Node argChild, bool directCall)
		{
			int argCount = 0;
			for (Node child = argChild; child != null; child = child.GetNext())
			{
				++argCount;
			}
			// load array object to set arguments
			if (argCount == 1 && itsOneArgArray >= 0)
			{
				cfw.AddALoad(itsOneArgArray);
			}
			else
			{
				AddNewObjectArray(argCount);
			}
			// Copy arguments into it
			for (int i = 0; i != argCount; ++i)
			{
				// If we are compiling a generator an argument could be the result
				// of a yield. In that case we will have an immediate on the stack
				// which we need to avoid
				if (!isGenerator)
				{
					cfw.Add(ByteCode.DUP);
					cfw.AddPush(i);
				}
				if (!directCall)
				{
					GenerateExpression(argChild, node);
				}
				else
				{
					// If this has also been a directCall sequence, the Number
					// flag will have remained set for any parameter so that
					// the values could be copied directly into the outgoing
					// args. Here we want to force it to be treated as not in
					// a Number context, so we set the flag off.
					int dcp_register = NodeIsDirectCallParameter(argChild);
					if (dcp_register >= 0)
					{
						DcpLoadAsObject(dcp_register);
					}
					else
					{
						GenerateExpression(argChild, node);
						int childNumberFlag = argChild.GetIntProp(Node.ISNUMBER_PROP, -1);
						if (childNumberFlag == Node.BOTH)
						{
							AddDoubleWrap();
						}
					}
				}
				// When compiling generators, any argument to a method may be a
				// yield expression. Hence we compile the argument first and then
				// load the argument index and assign the value to the args array.
				if (isGenerator)
				{
					short tempLocal = GetNewWordLocal();
					cfw.AddAStore(tempLocal);
					cfw.Add(ByteCode.CHECKCAST, "[Ljava/lang/Object;");
					cfw.Add(ByteCode.DUP);
					cfw.AddPush(i);
					cfw.AddALoad(tempLocal);
					ReleaseWordLocal(tempLocal);
				}
				cfw.Add(ByteCode.AASTORE);
				argChild = argChild.GetNext();
			}
		}
Esempio n. 10
0
		private void GenerateFunctionAndThisObj(Node node, Node parent)
		{
			// Place on stack (function object, function this) pair
			int type = node.GetType();
			switch (node.GetType())
			{
				case Token.GETPROPNOWARN:
				{
					throw Kit.CodeBug();
				}

				case Token.GETPROP:
				case Token.GETELEM:
				{
					Node target = node.GetFirstChild();
					GenerateExpression(target, node);
					Node id = target.GetNext();
					if (type == Token.GETPROP)
					{
						string property = id.GetString();
						cfw.AddPush(property);
						cfw.AddALoad(contextLocal);
						cfw.AddALoad(variableObjectLocal);
						AddScriptRuntimeInvoke("getPropFunctionAndThis", "(Ljava/lang/Object;" + "Ljava/lang/String;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Callable;");
					}
					else
					{
						GenerateExpression(id, node);
						// id
						if (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1)
						{
							AddDoubleWrap();
						}
						cfw.AddALoad(contextLocal);
						AddScriptRuntimeInvoke("getElemFunctionAndThis", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/Callable;");
					}
					break;
				}

				case Token.NAME:
				{
					string name = node.GetString();
					cfw.AddPush(name);
					cfw.AddALoad(contextLocal);
					cfw.AddALoad(variableObjectLocal);
					AddScriptRuntimeInvoke("getNameFunctionAndThis", "(Ljava/lang/String;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Callable;");
					break;
				}

				default:
				{
					// including GETVAR
					GenerateExpression(node, parent);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("getValueFunctionAndThis", "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/Callable;");
					break;
				}
			}
			// Get thisObj prepared by get(Name|Prop|Elem|Value)FunctionAndThis
			cfw.AddALoad(contextLocal);
			AddScriptRuntimeInvoke("lastStoredScriptable", "(Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/Scriptable;");
		}
Esempio n. 11
0
		private void GenerateExpression(Node node, Node parent)
		{
			int type = node.GetType();
			Node child = node.GetFirstChild();
			switch (type)
			{
				case Token.USE_STACK:
				{
					break;
				}

				case Token.FUNCTION:
				{
					if (fnCurrent != null || parent.GetType() != Token.SCRIPT)
					{
						int fnIndex = node.GetExistingIntProp(Node.FUNCTION_PROP);
						OptFunctionNode ofn = OptFunctionNode.Get(scriptOrFn, fnIndex);
						int t = ofn.fnode.GetFunctionType();
						if (t != FunctionNode.FUNCTION_EXPRESSION)
						{
							throw Codegen.BadTree();
						}
						VisitFunction(ofn, t);
					}
					break;
				}

				case Token.NAME:
				{
					cfw.AddALoad(contextLocal);
					cfw.AddALoad(variableObjectLocal);
					cfw.AddPush(node.GetString());
					AddScriptRuntimeInvoke("name", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/String;" + ")Ljava/lang/Object;");
					break;
				}

				case Token.CALL:
				case Token.NEW:
				{
					int specialType = node.GetIntProp(Node.SPECIALCALL_PROP, Node.NON_SPECIALCALL);
					if (specialType == Node.NON_SPECIALCALL)
					{
						OptFunctionNode target;
						target = (OptFunctionNode)node.GetProp(Node.DIRECTCALL_PROP);
						if (target != null)
						{
							VisitOptimizedCall(node, target, type, child);
						}
						else
						{
							if (type == Token.CALL)
							{
								VisitStandardCall(node, child);
							}
							else
							{
								VisitStandardNew(node, child);
							}
						}
					}
					else
					{
						VisitSpecialCall(node, type, specialType, child);
					}
					break;
				}

				case Token.REF_CALL:
				{
					GenerateFunctionAndThisObj(child, node);
					// stack: ... functionObj thisObj
					child = child.GetNext();
					GenerateCallArgArray(node, child, false);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("callRef", "(Lorg/mozilla/javascript/Callable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/Ref;");
					break;
				}

				case Token.NUMBER:
				{
					double num = node.GetDouble();
					if (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1)
					{
						cfw.AddPush(num);
					}
					else
					{
						codegen.PushNumberAsObject(cfw, num);
					}
					break;
				}

				case Token.STRING:
				{
					cfw.AddPush(node.GetString());
					break;
				}

				case Token.THIS:
				{
					cfw.AddALoad(thisObjLocal);
					break;
				}

				case Token.THISFN:
				{
					cfw.Add(ByteCode.ALOAD_0);
					break;
				}

				case Token.NULL:
				{
					cfw.Add(ByteCode.ACONST_NULL);
					break;
				}

				case Token.TRUE:
				{
					cfw.Add(ByteCode.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;");
					break;
				}

				case Token.FALSE:
				{
					cfw.Add(ByteCode.GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;");
					break;
				}

				case Token.REGEXP:
				{
					// Create a new wrapper around precompiled regexp
					cfw.AddALoad(contextLocal);
					cfw.AddALoad(variableObjectLocal);
					int i = node.GetExistingIntProp(Node.REGEXP_PROP);
					cfw.Add(ByteCode.GETSTATIC, codegen.mainClassName, codegen.GetCompiledRegexpName(scriptOrFn, i), "Ljava/lang/Object;");
					cfw.AddInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "wrapRegExp", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/Object;" + ")Lorg/mozilla/javascript/Scriptable;");
					break;
				}

				case Token.COMMA:
				{
					Node next = child.GetNext();
					while (next != null)
					{
						GenerateExpression(child, node);
						cfw.Add(ByteCode.POP);
						child = next;
						next = next.GetNext();
					}
					GenerateExpression(child, node);
					break;
				}

				case Token.ENUM_NEXT:
				case Token.ENUM_ID:
				{
					int local = GetLocalBlockRegister(node);
					cfw.AddALoad(local);
					if (type == Token.ENUM_NEXT)
					{
						AddScriptRuntimeInvoke("enumNext", "(Ljava/lang/Object;)Ljava/lang/Boolean;");
					}
					else
					{
						cfw.AddALoad(contextLocal);
						AddScriptRuntimeInvoke("enumId", "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
					}
					break;
				}

				case Token.ARRAYLIT:
				{
					VisitArrayLiteral(node, child, false);
					break;
				}

				case Token.OBJECTLIT:
				{
					VisitObjectLiteral(node, child, false);
					break;
				}

				case Token.NOT:
				{
					int trueTarget = cfw.AcquireLabel();
					int falseTarget = cfw.AcquireLabel();
					int beyond = cfw.AcquireLabel();
					GenerateIfJump(child, node, trueTarget, falseTarget);
					cfw.MarkLabel(trueTarget);
					cfw.Add(ByteCode.GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;");
					cfw.Add(ByteCode.GOTO, beyond);
					cfw.MarkLabel(falseTarget);
					cfw.Add(ByteCode.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;");
					cfw.MarkLabel(beyond);
					cfw.AdjustStackTop(-1);
					break;
				}

				case Token.BITNOT:
				{
					GenerateExpression(child, node);
					AddScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I");
					cfw.AddPush(-1);
					// implement ~a as (a ^ -1)
					cfw.Add(ByteCode.IXOR);
					cfw.Add(ByteCode.I2D);
					AddDoubleWrap();
					break;
				}

				case Token.VOID:
				{
					GenerateExpression(child, node);
					cfw.Add(ByteCode.POP);
					Codegen.PushUndefined(cfw);
					break;
				}

				case Token.TYPEOF:
				{
					GenerateExpression(child, node);
					AddScriptRuntimeInvoke("typeof", "(Ljava/lang/Object;" + ")Ljava/lang/String;");
					break;
				}

				case Token.TYPEOFNAME:
				{
					VisitTypeofname(node);
					break;
				}

				case Token.INC:
				case Token.DEC:
				{
					VisitIncDec(node);
					break;
				}

				case Token.OR:
				case Token.AND:
				{
					GenerateExpression(child, node);
					cfw.Add(ByteCode.DUP);
					AddScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z");
					int falseTarget = cfw.AcquireLabel();
					if (type == Token.AND)
					{
						cfw.Add(ByteCode.IFEQ, falseTarget);
					}
					else
					{
						cfw.Add(ByteCode.IFNE, falseTarget);
					}
					cfw.Add(ByteCode.POP);
					GenerateExpression(child.GetNext(), node);
					cfw.MarkLabel(falseTarget);
					break;
				}

				case Token.HOOK:
				{
					Node ifThen = child.GetNext();
					Node ifElse = ifThen.GetNext();
					GenerateExpression(child, node);
					AddScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z");
					int elseTarget = cfw.AcquireLabel();
					cfw.Add(ByteCode.IFEQ, elseTarget);
					short stack = cfw.GetStackTop();
					GenerateExpression(ifThen, node);
					int afterHook = cfw.AcquireLabel();
					cfw.Add(ByteCode.GOTO, afterHook);
					cfw.MarkLabel(elseTarget, stack);
					GenerateExpression(ifElse, node);
					cfw.MarkLabel(afterHook);
					break;
				}

				case Token.ADD:
				{
					GenerateExpression(child, node);
					GenerateExpression(child.GetNext(), node);
					switch (node.GetIntProp(Node.ISNUMBER_PROP, -1))
					{
						case Node.BOTH:
						{
							cfw.Add(ByteCode.DADD);
							break;
						}

						case Node.LEFT:
						{
							AddOptRuntimeInvoke("add", "(DLjava/lang/Object;)Ljava/lang/Object;");
							break;
						}

						case Node.RIGHT:
						{
							AddOptRuntimeInvoke("add", "(Ljava/lang/Object;D)Ljava/lang/Object;");
							break;
						}

						default:
						{
							if (child.GetType() == Token.STRING)
							{
								AddScriptRuntimeInvoke("add", "(Ljava/lang/CharSequence;" + "Ljava/lang/Object;" + ")Ljava/lang/CharSequence;");
							}
							else
							{
								if (child.GetNext().GetType() == Token.STRING)
								{
									AddScriptRuntimeInvoke("add", "(Ljava/lang/Object;" + "Ljava/lang/CharSequence;" + ")Ljava/lang/CharSequence;");
								}
								else
								{
									cfw.AddALoad(contextLocal);
									AddScriptRuntimeInvoke("add", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
								}
							}
							break;
						}
					}
					break;
				}

				case Token.MUL:
				{
					VisitArithmetic(node, ByteCode.DMUL, child, parent);
					break;
				}

				case Token.SUB:
				{
					VisitArithmetic(node, ByteCode.DSUB, child, parent);
					break;
				}

				case Token.DIV:
				case Token.MOD:
				{
					VisitArithmetic(node, type == Token.DIV ? ByteCode.DDIV : ByteCode.DREM, child, parent);
					break;
				}

				case Token.BITOR:
				case Token.BITXOR:
				case Token.BITAND:
				case Token.LSH:
				case Token.RSH:
				case Token.URSH:
				{
					VisitBitOp(node, type, child);
					break;
				}

				case Token.POS:
				case Token.NEG:
				{
					GenerateExpression(child, node);
					AddObjectToDouble();
					if (type == Token.NEG)
					{
						cfw.Add(ByteCode.DNEG);
					}
					AddDoubleWrap();
					break;
				}

				case Token.TO_DOUBLE:
				{
					// cnvt to double (not Double)
					GenerateExpression(child, node);
					AddObjectToDouble();
					break;
				}

				case Token.TO_OBJECT:
				{
					// convert from double
					int prop = -1;
					if (child.GetType() == Token.NUMBER)
					{
						prop = child.GetIntProp(Node.ISNUMBER_PROP, -1);
					}
					if (prop != -1)
					{
						child.RemoveProp(Node.ISNUMBER_PROP);
						GenerateExpression(child, node);
						child.PutIntProp(Node.ISNUMBER_PROP, prop);
					}
					else
					{
						GenerateExpression(child, node);
						AddDoubleWrap();
					}
					break;
				}

				case Token.IN:
				case Token.INSTANCEOF:
				case Token.LE:
				case Token.LT:
				case Token.GE:
				case Token.GT:
				{
					int trueGOTO = cfw.AcquireLabel();
					int falseGOTO = cfw.AcquireLabel();
					VisitIfJumpRelOp(node, child, trueGOTO, falseGOTO);
					AddJumpedBooleanWrap(trueGOTO, falseGOTO);
					break;
				}

				case Token.EQ:
				case Token.NE:
				case Token.SHEQ:
				case Token.SHNE:
				{
					int trueGOTO = cfw.AcquireLabel();
					int falseGOTO = cfw.AcquireLabel();
					VisitIfJumpEqOp(node, child, trueGOTO, falseGOTO);
					AddJumpedBooleanWrap(trueGOTO, falseGOTO);
					break;
				}

				case Token.GETPROP:
				case Token.GETPROPNOWARN:
				{
					VisitGetProp(node, child);
					break;
				}

				case Token.GETELEM:
				{
					GenerateExpression(child, node);
					// object
					GenerateExpression(child.GetNext(), node);
					// id
					cfw.AddALoad(contextLocal);
					if (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1)
					{
						AddScriptRuntimeInvoke("getObjectIndex", "(Ljava/lang/Object;D" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
					}
					else
					{
						cfw.AddALoad(variableObjectLocal);
						AddScriptRuntimeInvoke("getObjectElem", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Ljava/lang/Object;");
					}
					break;
				}

				case Token.GET_REF:
				{
					GenerateExpression(child, node);
					// reference
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("refGet", "(Lorg/mozilla/javascript/Ref;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
					break;
				}

				case Token.GETVAR:
				{
					VisitGetVar(node);
					break;
				}

				case Token.SETVAR:
				{
					VisitSetVar(node, child, true);
					break;
				}

				case Token.SETNAME:
				{
					VisitSetName(node, child);
					break;
				}

				case Token.STRICT_SETNAME:
				{
					VisitStrictSetName(node, child);
					break;
				}

				case Token.SETCONST:
				{
					VisitSetConst(node, child);
					break;
				}

				case Token.SETCONSTVAR:
				{
					VisitSetConstVar(node, child, true);
					break;
				}

				case Token.SETPROP:
				case Token.SETPROP_OP:
				{
					VisitSetProp(type, node, child);
					break;
				}

				case Token.SETELEM:
				case Token.SETELEM_OP:
				{
					VisitSetElem(type, node, child);
					break;
				}

				case Token.SET_REF:
				case Token.SET_REF_OP:
				{
					GenerateExpression(child, node);
					child = child.GetNext();
					if (type == Token.SET_REF_OP)
					{
						cfw.Add(ByteCode.DUP);
						cfw.AddALoad(contextLocal);
						AddScriptRuntimeInvoke("refGet", "(Lorg/mozilla/javascript/Ref;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
					}
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("refSet", "(Lorg/mozilla/javascript/Ref;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
					break;
				}

				case Token.DEL_REF:
				{
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("refDel", "(Lorg/mozilla/javascript/Ref;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
					break;
				}

				case Token.DELPROP:
				{
					bool isName = child.GetType() == Token.BINDNAME;
					GenerateExpression(child, node);
					child = child.GetNext();
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					cfw.AddPush(isName);
					AddScriptRuntimeInvoke("delete", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "Z)Ljava/lang/Object;");
					break;
				}

				case Token.BINDNAME:
				{
					while (child != null)
					{
						GenerateExpression(child, node);
						child = child.GetNext();
					}
					// Generate code for "ScriptRuntime.bind(varObj, "s")"
					cfw.AddALoad(contextLocal);
					cfw.AddALoad(variableObjectLocal);
					cfw.AddPush(node.GetString());
					AddScriptRuntimeInvoke("bind", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/String;" + ")Lorg/mozilla/javascript/Scriptable;");
					break;
				}

				case Token.LOCAL_LOAD:
				{
					cfw.AddALoad(GetLocalBlockRegister(node));
					break;
				}

				case Token.REF_SPECIAL:
				{
					string special = (string)node.GetProp(Node.NAME_PROP);
					GenerateExpression(child, node);
					cfw.AddPush(special);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("specialRef", "(Ljava/lang/Object;" + "Ljava/lang/String;" + "Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/Ref;");
					break;
				}

				case Token.REF_MEMBER:
				case Token.REF_NS_MEMBER:
				case Token.REF_NAME:
				case Token.REF_NS_NAME:
				{
					int memberTypeFlags = node.GetIntProp(Node.MEMBER_TYPE_PROP, 0);
					do
					{
						// generate possible target, possible namespace and member
						GenerateExpression(child, node);
						child = child.GetNext();
					}
					while (child != null);
					cfw.AddALoad(contextLocal);
					string methodName;
					string signature;
					switch (type)
					{
						case Token.REF_MEMBER:
						{
							methodName = "memberRef";
							signature = "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "I" + ")Lorg/mozilla/javascript/Ref;";
							break;
						}

						case Token.REF_NS_MEMBER:
						{
							methodName = "memberRef";
							signature = "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "I" + ")Lorg/mozilla/javascript/Ref;";
							break;
						}

						case Token.REF_NAME:
						{
							methodName = "nameRef";
							signature = "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "I" + ")Lorg/mozilla/javascript/Ref;";
							cfw.AddALoad(variableObjectLocal);
							break;
						}

						case Token.REF_NS_NAME:
						{
							methodName = "nameRef";
							signature = "(Ljava/lang/Object;" + "Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "I" + ")Lorg/mozilla/javascript/Ref;";
							cfw.AddALoad(variableObjectLocal);
							break;
						}

						default:
						{
							throw Kit.CodeBug();
						}
					}
					cfw.AddPush(memberTypeFlags);
					AddScriptRuntimeInvoke(methodName, signature);
					break;
				}

				case Token.DOTQUERY:
				{
					VisitDotQuery(node, child);
					break;
				}

				case Token.ESCXMLATTR:
				{
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("escapeAttributeValue", "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/String;");
					break;
				}

				case Token.ESCXMLTEXT:
				{
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("escapeTextValue", "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/String;");
					break;
				}

				case Token.DEFAULTNAMESPACE:
				{
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					AddScriptRuntimeInvoke("setDefaultNamespace", "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;");
					break;
				}

				case Token.YIELD:
				{
					GenerateYieldPoint(node, true);
					break;
				}

				case Token.WITHEXPR:
				{
					Node enterWith = child;
					Node with = enterWith.GetNext();
					Node leaveWith = with.GetNext();
					GenerateStatement(enterWith);
					GenerateExpression(with.GetFirstChild(), with);
					GenerateStatement(leaveWith);
					break;
				}

				case Token.ARRAYCOMP:
				{
					Node initStmt = child;
					Node expr = child.GetNext();
					GenerateStatement(initStmt);
					GenerateExpression(expr, node);
					break;
				}

				default:
				{
					throw new Exception("Unexpected node type " + type);
				}
			}
		}
Esempio n. 12
0
		private void GenerateStatement(Node node)
		{
			UpdateLineNumber(node);
			int type = node.GetType();
			Node child = node.GetFirstChild();
			switch (type)
			{
				case Token.LOOP:
				case Token.LABEL:
				case Token.WITH:
				case Token.SCRIPT:
				case Token.BLOCK:
				case Token.EMPTY:
				{
					// no-ops.
					if (compilerEnv.IsGenerateObserverCount())
					{
						// Need to add instruction count even for no-ops to catch
						// cases like while (1) {}
						AddInstructionCount(1);
					}
					while (child != null)
					{
						GenerateStatement(child);
						child = child.GetNext();
					}
					break;
				}

				case Token.LOCAL_BLOCK:
				{
					bool prevLocal = inLocalBlock;
					inLocalBlock = true;
					int local = GetNewWordLocal();
					if (isGenerator)
					{
						cfw.Add(ByteCode.ACONST_NULL);
						cfw.AddAStore(local);
					}
					node.PutIntProp(Node.LOCAL_PROP, local);
					while (child != null)
					{
						GenerateStatement(child);
						child = child.GetNext();
					}
					ReleaseWordLocal((short)local);
					node.RemoveProp(Node.LOCAL_PROP);
					inLocalBlock = prevLocal;
					break;
				}

				case Token.FUNCTION:
				{
					int fnIndex = node.GetExistingIntProp(Node.FUNCTION_PROP);
					OptFunctionNode ofn = OptFunctionNode.Get(scriptOrFn, fnIndex);
					int t = ofn.fnode.GetFunctionType();
					if (t == FunctionNode.FUNCTION_EXPRESSION_STATEMENT)
					{
						VisitFunction(ofn, t);
					}
					else
					{
						if (t != FunctionNode.FUNCTION_STATEMENT)
						{
							throw Codegen.BadTree();
						}
					}
					break;
				}

				case Token.TRY:
				{
					VisitTryCatchFinally((Jump)node, child);
					break;
				}

				case Token.CATCH_SCOPE:
				{
					// nothing stays on the stack on entry into a catch scope
					cfw.SetStackTop((short)0);
					int local = GetLocalBlockRegister(node);
					int scopeIndex = node.GetExistingIntProp(Node.CATCH_SCOPE_PROP);
					string name = child.GetString();
					// name of exception
					child = child.GetNext();
					GenerateExpression(child, node);
					// load expression object
					if (scopeIndex == 0)
					{
						cfw.Add(ByteCode.ACONST_NULL);
					}
					else
					{
						// Load previous catch scope object
						cfw.AddALoad(local);
					}
					cfw.AddPush(name);
					cfw.AddALoad(contextLocal);
					cfw.AddALoad(variableObjectLocal);
					AddScriptRuntimeInvoke("newCatchScope", "(Ljava/lang/Throwable;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/String;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Scriptable;");
					cfw.AddAStore(local);
					break;
				}

				case Token.THROW:
				{
					GenerateExpression(child, node);
					if (compilerEnv.IsGenerateObserverCount())
					{
						AddInstructionCount();
					}
					GenerateThrowJavaScriptException();
					break;
				}

				case Token.RETHROW:
				{
					if (compilerEnv.IsGenerateObserverCount())
					{
						AddInstructionCount();
					}
					cfw.AddALoad(GetLocalBlockRegister(node));
					cfw.Add(ByteCode.ATHROW);
					break;
				}

				case Token.RETURN_RESULT:
				case Token.RETURN:
				{
					if (!isGenerator)
					{
						if (child != null)
						{
							GenerateExpression(child, node);
						}
						else
						{
							if (type == Token.RETURN)
							{
								Codegen.PushUndefined(cfw);
							}
							else
							{
								if (popvLocal < 0)
								{
									throw Codegen.BadTree();
								}
								cfw.AddALoad(popvLocal);
							}
						}
					}
					if (compilerEnv.IsGenerateObserverCount())
					{
						AddInstructionCount();
					}
					if (epilogueLabel == -1)
					{
						if (!hasVarsInRegs)
						{
							throw Codegen.BadTree();
						}
						epilogueLabel = cfw.AcquireLabel();
					}
					cfw.Add(ByteCode.GOTO, epilogueLabel);
					break;
				}

				case Token.SWITCH:
				{
					if (compilerEnv.IsGenerateObserverCount())
					{
						AddInstructionCount();
					}
					VisitSwitch((Jump)node, child);
					break;
				}

				case Token.ENTERWITH:
				{
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					cfw.AddALoad(variableObjectLocal);
					AddScriptRuntimeInvoke("enterWith", "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Scriptable;");
					cfw.AddAStore(variableObjectLocal);
					IncReferenceWordLocal(variableObjectLocal);
					break;
				}

				case Token.LEAVEWITH:
				{
					cfw.AddALoad(variableObjectLocal);
					AddScriptRuntimeInvoke("leaveWith", "(Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Scriptable;");
					cfw.AddAStore(variableObjectLocal);
					DecReferenceWordLocal(variableObjectLocal);
					break;
				}

				case Token.ENUM_INIT_KEYS:
				case Token.ENUM_INIT_VALUES:
				case Token.ENUM_INIT_ARRAY:
				{
					GenerateExpression(child, node);
					cfw.AddALoad(contextLocal);
					int enumType = type == Token.ENUM_INIT_KEYS ? ScriptRuntime.ENUMERATE_KEYS : type == Token.ENUM_INIT_VALUES ? ScriptRuntime.ENUMERATE_VALUES : ScriptRuntime.ENUMERATE_ARRAY;
					cfw.AddPush(enumType);
					AddScriptRuntimeInvoke("enumInit", "(Ljava/lang/Object;" + "Lorg/mozilla/javascript/Context;" + "I" + ")Ljava/lang/Object;");
					cfw.AddAStore(GetLocalBlockRegister(node));
					break;
				}

				case Token.EXPR_VOID:
				{
					if (child.GetType() == Token.SETVAR)
					{
						VisitSetVar(child, child.GetFirstChild(), false);
					}
					else
					{
						if (child.GetType() == Token.SETCONSTVAR)
						{
							VisitSetConstVar(child, child.GetFirstChild(), false);
						}
						else
						{
							if (child.GetType() == Token.YIELD)
							{
								GenerateYieldPoint(child, false);
							}
							else
							{
								GenerateExpression(child, node);
								if (node.GetIntProp(Node.ISNUMBER_PROP, -1) != -1)
								{
									cfw.Add(ByteCode.POP2);
								}
								else
								{
									cfw.Add(ByteCode.POP);
								}
							}
						}
					}
					break;
				}

				case Token.EXPR_RESULT:
				{
					GenerateExpression(child, node);
					if (popvLocal < 0)
					{
						popvLocal = GetNewWordLocal();
					}
					cfw.AddAStore(popvLocal);
					break;
				}

				case Token.TARGET:
				{
					if (compilerEnv.IsGenerateObserverCount())
					{
						AddInstructionCount();
					}
					int label = GetTargetLabel(node);
					cfw.MarkLabel(label);
					if (compilerEnv.IsGenerateObserverCount())
					{
						SaveCurrentCodeOffset();
					}
					break;
				}

				case Token.JSR:
				case Token.GOTO:
				case Token.IFEQ:
				case Token.IFNE:
				{
					if (compilerEnv.IsGenerateObserverCount())
					{
						AddInstructionCount();
					}
					VisitGoto((Jump)node, type, child);
					break;
				}

				case Token.FINALLY:
				{
					// This is the non-exception case for a finally block. In
					// other words, since we inline finally blocks wherever
					// jsr was previously used, and jsr is only used when the
					// function is not a generator, we don't need to generate
					// this case if the function isn't a generator.
					if (!isGenerator)
					{
						break;
					}
					if (compilerEnv.IsGenerateObserverCount())
					{
						SaveCurrentCodeOffset();
					}
					// there is exactly one value on the stack when enterring
					// finally blocks: the return address (or its int encoding)
					cfw.SetStackTop((short)1);
					// Save return address in a new local
					int finallyRegister = GetNewWordLocal();
					int finallyStart = cfw.AcquireLabel();
					int finallyEnd = cfw.AcquireLabel();
					cfw.MarkLabel(finallyStart);
					GenerateIntegerWrap();
					cfw.AddAStore(finallyRegister);
					while (child != null)
					{
						GenerateStatement(child);
						child = child.GetNext();
					}
					cfw.AddALoad(finallyRegister);
					cfw.Add(ByteCode.CHECKCAST, "java/lang/Integer");
					GenerateIntegerUnwrap();
					BodyCodegen.FinallyReturnPoint ret = finallys.Get(node);
					ret.tableLabel = cfw.AcquireLabel();
					cfw.Add(ByteCode.GOTO, ret.tableLabel);
					ReleaseWordLocal((short)finallyRegister);
					cfw.MarkLabel(finallyEnd);
					break;
				}

				case Token.DEBUGGER:
				{
					break;
				}

				default:
				{
					throw Codegen.BadTree();
				}
			}
		}
Esempio n. 13
0
		private void VisitExpression(Node node, int contextFlags)
		{
			int type = node.GetType();
			Node child = node.GetFirstChild();
			int savedStackDepth = stackDepth;
			switch (type)
			{
				case Token.FUNCTION:
				{
					int fnIndex = node.GetExistingIntProp(Node.FUNCTION_PROP);
					FunctionNode fn = scriptOrFn.GetFunctionNode(fnIndex);
					// See comments in visitStatement for Token.FUNCTION case
					if (fn.GetFunctionType() != FunctionNode.FUNCTION_EXPRESSION)
					{
						throw Kit.CodeBug();
					}
					AddIndexOp(Icode_CLOSURE_EXPR, fnIndex);
					StackChange(1);
					break;
				}

				case Token.LOCAL_LOAD:
				{
					int localIndex = GetLocalBlockRef(node);
					AddIndexOp(Token.LOCAL_LOAD, localIndex);
					StackChange(1);
					break;
				}

				case Token.COMMA:
				{
					Node lastChild = node.GetLastChild();
					while (child != lastChild)
					{
						VisitExpression(child, 0);
						AddIcode(Icode_POP);
						StackChange(-1);
						child = child.GetNext();
					}
					// Preserve tail context flag if any
					VisitExpression(child, contextFlags & ECF_TAIL);
					break;
				}

				case Token.USE_STACK:
				{
					// Indicates that stack was modified externally,
					// like placed catch object
					StackChange(1);
					break;
				}

				case Token.REF_CALL:
				case Token.CALL:
				case Token.NEW:
				{
					if (type == Token.NEW)
					{
						VisitExpression(child, 0);
					}
					else
					{
						GenerateCallFunAndThis(child);
					}
					int argCount = 0;
					while ((child = child.GetNext()) != null)
					{
						VisitExpression(child, 0);
						++argCount;
					}
					int callType = node.GetIntProp(Node.SPECIALCALL_PROP, Node.NON_SPECIALCALL);
					if (type != Token.REF_CALL && callType != Node.NON_SPECIALCALL)
					{
						// embed line number and source filename
						AddIndexOp(Icode_CALLSPECIAL, argCount);
						AddUint8(callType);
						AddUint8(type == Token.NEW ? 1 : 0);
						AddUint16(lineNumber & unchecked((int)(0xFFFF)));
					}
					else
					{
						// Only use the tail call optimization if we're not in a try
						// or we're not generating debug info (since the
						// optimization will confuse the debugger)
						if (type == Token.CALL && (contextFlags & ECF_TAIL) != 0 && !compilerEnv.IsGenerateDebugInfo() && !itsInTryFlag)
						{
							type = Icode_TAIL_CALL;
						}
						AddIndexOp(type, argCount);
					}
					// adjust stack
					if (type == Token.NEW)
					{
						// new: f, args -> result
						StackChange(-argCount);
					}
					else
					{
						// call: f, thisObj, args -> result
						// ref_call: f, thisObj, args -> ref
						StackChange(-1 - argCount);
					}
					if (argCount > itsData.itsMaxCalleeArgs)
					{
						itsData.itsMaxCalleeArgs = argCount;
					}
					break;
				}

				case Token.AND:
				case Token.OR:
				{
					VisitExpression(child, 0);
					AddIcode(Icode_DUP);
					StackChange(1);
					int afterSecondJumpStart = iCodeTop;
					int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ;
					AddGotoOp(jump);
					StackChange(-1);
					AddIcode(Icode_POP);
					StackChange(-1);
					child = child.GetNext();
					// Preserve tail context flag if any
					VisitExpression(child, contextFlags & ECF_TAIL);
					ResolveForwardGoto(afterSecondJumpStart);
					break;
				}

				case Token.HOOK:
				{
					Node ifThen = child.GetNext();
					Node ifElse = ifThen.GetNext();
					VisitExpression(child, 0);
					int elseJumpStart = iCodeTop;
					AddGotoOp(Token.IFNE);
					StackChange(-1);
					// Preserve tail context flag if any
					VisitExpression(ifThen, contextFlags & ECF_TAIL);
					int afterElseJumpStart = iCodeTop;
					AddGotoOp(Token.GOTO);
					ResolveForwardGoto(elseJumpStart);
					stackDepth = savedStackDepth;
					// Preserve tail context flag if any
					VisitExpression(ifElse, contextFlags & ECF_TAIL);
					ResolveForwardGoto(afterElseJumpStart);
					break;
				}

				case Token.GETPROP:
				case Token.GETPROPNOWARN:
				{
					VisitExpression(child, 0);
					child = child.GetNext();
					AddStringOp(type, child.GetString());
					break;
				}

				case Token.DELPROP:
				{
					bool isName = child.GetType() == Token.BINDNAME;
					VisitExpression(child, 0);
					child = child.GetNext();
					VisitExpression(child, 0);
					if (isName)
					{
						// special handling for delete name
						AddIcode(Icode_DELNAME);
					}
					else
					{
						AddToken(Token.DELPROP);
					}
					StackChange(-1);
					break;
				}

				case Token.GETELEM:
				case Token.BITAND:
				case Token.BITOR:
				case Token.BITXOR:
				case Token.LSH:
				case Token.RSH:
				case Token.URSH:
				case Token.ADD:
				case Token.SUB:
				case Token.MOD:
				case Token.DIV:
				case Token.MUL:
				case Token.EQ:
				case Token.NE:
				case Token.SHEQ:
				case Token.SHNE:
				case Token.IN:
				case Token.INSTANCEOF:
				case Token.LE:
				case Token.LT:
				case Token.GE:
				case Token.GT:
				{
					VisitExpression(child, 0);
					child = child.GetNext();
					VisitExpression(child, 0);
					AddToken(type);
					StackChange(-1);
					break;
				}

				case Token.POS:
				case Token.NEG:
				case Token.NOT:
				case Token.BITNOT:
				case Token.TYPEOF:
				case Token.VOID:
				{
					VisitExpression(child, 0);
					if (type == Token.VOID)
					{
						AddIcode(Icode_POP);
						AddIcode(Icode_UNDEF);
					}
					else
					{
						AddToken(type);
					}
					break;
				}

				case Token.GET_REF:
				case Token.DEL_REF:
				{
					VisitExpression(child, 0);
					AddToken(type);
					break;
				}

				case Token.SETPROP:
				case Token.SETPROP_OP:
				{
					VisitExpression(child, 0);
					child = child.GetNext();
					string property = child.GetString();
					child = child.GetNext();
					if (type == Token.SETPROP_OP)
					{
						AddIcode(Icode_DUP);
						StackChange(1);
						AddStringOp(Token.GETPROP, property);
						// Compensate for the following USE_STACK
						StackChange(-1);
					}
					VisitExpression(child, 0);
					AddStringOp(Token.SETPROP, property);
					StackChange(-1);
					break;
				}

				case Token.SETELEM:
				case Token.SETELEM_OP:
				{
					VisitExpression(child, 0);
					child = child.GetNext();
					VisitExpression(child, 0);
					child = child.GetNext();
					if (type == Token.SETELEM_OP)
					{
						AddIcode(Icode_DUP2);
						StackChange(2);
						AddToken(Token.GETELEM);
						StackChange(-1);
						// Compensate for the following USE_STACK
						StackChange(-1);
					}
					VisitExpression(child, 0);
					AddToken(Token.SETELEM);
					StackChange(-2);
					break;
				}

				case Token.SET_REF:
				case Token.SET_REF_OP:
				{
					VisitExpression(child, 0);
					child = child.GetNext();
					if (type == Token.SET_REF_OP)
					{
						AddIcode(Icode_DUP);
						StackChange(1);
						AddToken(Token.GET_REF);
						// Compensate for the following USE_STACK
						StackChange(-1);
					}
					VisitExpression(child, 0);
					AddToken(Token.SET_REF);
					StackChange(-1);
					break;
				}

				case Token.STRICT_SETNAME:
				case Token.SETNAME:
				{
					string name = child.GetString();
					VisitExpression(child, 0);
					child = child.GetNext();
					VisitExpression(child, 0);
					AddStringOp(type, name);
					StackChange(-1);
					break;
				}

				case Token.SETCONST:
				{
					string name = child.GetString();
					VisitExpression(child, 0);
					child = child.GetNext();
					VisitExpression(child, 0);
					AddStringOp(Icode_SETCONST, name);
					StackChange(-1);
					break;
				}

				case Token.TYPEOFNAME:
				{
					int index = -1;
					// use typeofname if an activation frame exists
					// since the vars all exist there instead of in jregs
					if (itsInFunctionFlag && !itsData.itsNeedsActivation)
					{
						index = scriptOrFn.GetIndexForNameNode(node);
					}
					if (index == -1)
					{
						AddStringOp(Icode_TYPEOFNAME, node.GetString());
						StackChange(1);
					}
					else
					{
						AddVarOp(Token.GETVAR, index);
						StackChange(1);
						AddToken(Token.TYPEOF);
					}
					break;
				}

				case Token.BINDNAME:
				case Token.NAME:
				case Token.STRING:
				{
					AddStringOp(type, node.GetString());
					StackChange(1);
					break;
				}

				case Token.INC:
				case Token.DEC:
				{
					VisitIncDec(node, child);
					break;
				}

				case Token.NUMBER:
				{
					double num = node.GetDouble();
					int inum = (int)num;
					if (inum == num)
					{
						if (inum == 0)
						{
							AddIcode(Icode_ZERO);
							// Check for negative zero
							if (1.0 / num < 0.0)
							{
								AddToken(Token.NEG);
							}
						}
						else
						{
							if (inum == 1)
							{
								AddIcode(Icode_ONE);
							}
							else
							{
								if ((short)inum == inum)
								{
									AddIcode(Icode_SHORTNUMBER);
									// write short as uin16 bit pattern
									AddUint16(inum & unchecked((int)(0xFFFF)));
								}
								else
								{
									AddIcode(Icode_INTNUMBER);
									AddInt(inum);
								}
							}
						}
					}
					else
					{
						int index = GetDoubleIndex(num);
						AddIndexOp(Token.NUMBER, index);
					}
					StackChange(1);
					break;
				}

				case Token.GETVAR:
				{
					if (itsData.itsNeedsActivation)
					{
						Kit.CodeBug();
					}
					int index = scriptOrFn.GetIndexForNameNode(node);
					AddVarOp(Token.GETVAR, index);
					StackChange(1);
					break;
				}

				case Token.SETVAR:
				{
					if (itsData.itsNeedsActivation)
					{
						Kit.CodeBug();
					}
					int index = scriptOrFn.GetIndexForNameNode(child);
					child = child.GetNext();
					VisitExpression(child, 0);
					AddVarOp(Token.SETVAR, index);
					break;
				}

				case Token.SETCONSTVAR:
				{
					if (itsData.itsNeedsActivation)
					{
						Kit.CodeBug();
					}
					int index = scriptOrFn.GetIndexForNameNode(child);
					child = child.GetNext();
					VisitExpression(child, 0);
					AddVarOp(Token.SETCONSTVAR, index);
					break;
				}

				case Token.NULL:
				case Token.THIS:
				case Token.THISFN:
				case Token.FALSE:
				case Token.TRUE:
				{
					AddToken(type);
					StackChange(1);
					break;
				}

				case Token.ENUM_NEXT:
				case Token.ENUM_ID:
				{
					AddIndexOp(type, GetLocalBlockRef(node));
					StackChange(1);
					break;
				}

				case Token.REGEXP:
				{
					int index = node.GetExistingIntProp(Node.REGEXP_PROP);
					AddIndexOp(Token.REGEXP, index);
					StackChange(1);
					break;
				}

				case Token.ARRAYLIT:
				case Token.OBJECTLIT:
				{
					VisitLiteral(node, child);
					break;
				}

				case Token.ARRAYCOMP:
				{
					VisitArrayComprehension(node, child, child.GetNext());
					break;
				}

				case Token.REF_SPECIAL:
				{
					VisitExpression(child, 0);
					AddStringOp(type, (string)node.GetProp(Node.NAME_PROP));
					break;
				}

				case Token.REF_MEMBER:
				case Token.REF_NS_MEMBER:
				case Token.REF_NAME:
				case Token.REF_NS_NAME:
				{
					int memberTypeFlags = node.GetIntProp(Node.MEMBER_TYPE_PROP, 0);
					// generate possible target, possible namespace and member
					int childCount = 0;
					do
					{
						VisitExpression(child, 0);
						++childCount;
						child = child.GetNext();
					}
					while (child != null);
					AddIndexOp(type, memberTypeFlags);
					StackChange(1 - childCount);
					break;
				}

				case Token.DOTQUERY:
				{
					int queryPC;
					UpdateLineNumber(node);
					VisitExpression(child, 0);
					AddIcode(Icode_ENTERDQ);
					StackChange(-1);
					queryPC = iCodeTop;
					VisitExpression(child.GetNext(), 0);
					AddBackwardGoto(Icode_LEAVEDQ, queryPC);
					break;
				}

				case Token.DEFAULTNAMESPACE:
				case Token.ESCXMLATTR:
				case Token.ESCXMLTEXT:
				{
					VisitExpression(child, 0);
					AddToken(type);
					break;
				}

				case Token.YIELD:
				{
					if (child != null)
					{
						VisitExpression(child, 0);
					}
					else
					{
						AddIcode(Icode_UNDEF);
						StackChange(1);
					}
					AddToken(Token.YIELD);
					AddUint16(node.GetLineno() & unchecked((int)(0xFFFF)));
					break;
				}

				case Token.WITHEXPR:
				{
					Node enterWith = node.GetFirstChild();
					Node with = enterWith.GetNext();
					VisitExpression(enterWith.GetFirstChild(), 0);
					AddToken(Token.ENTERWITH);
					StackChange(-1);
					VisitExpression(with.GetFirstChild(), 0);
					AddToken(Token.LEAVEWITH);
					break;
				}

				default:
				{
					throw BadTree(node);
				}
			}
			if (savedStackDepth + 1 != stackDepth)
			{
				Kit.CodeBug();
			}
		}
Esempio n. 14
0
		private void VisitStatement(Node node, int initialStackDepth)
		{
			int type = node.GetType();
			Node child = node.GetFirstChild();
			switch (type)
			{
				case Token.FUNCTION:
				{
					int fnIndex = node.GetExistingIntProp(Node.FUNCTION_PROP);
					int fnType = scriptOrFn.GetFunctionNode(fnIndex).GetFunctionType();
					// Only function expressions or function expression
					// statements need closure code creating new function
					// object on stack as function statements are initialized
					// at script/function start.
					// In addition, function expressions can not be present here
					// at statement level, they must only be present as expressions.
					if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT)
					{
						AddIndexOp(Icode_CLOSURE_STMT, fnIndex);
					}
					else
					{
						if (fnType != FunctionNode.FUNCTION_STATEMENT)
						{
							throw Kit.CodeBug();
						}
					}
					// For function statements or function expression statements
					// in scripts, we need to ensure that the result of the script
					// is the function if it is the last statement in the script.
					// For example, eval("function () {}") should return a
					// function, not undefined.
					if (!itsInFunctionFlag)
					{
						AddIndexOp(Icode_CLOSURE_EXPR, fnIndex);
						StackChange(1);
						AddIcode(Icode_POP_RESULT);
						StackChange(-1);
					}
					break;
				}

				case Token.LABEL:
				case Token.LOOP:
				case Token.BLOCK:
				case Token.EMPTY:
				case Token.WITH:
				{
					UpdateLineNumber(node);
					goto case Token.SCRIPT;
				}

				case Token.SCRIPT:
				{
					// fall through
					while (child != null)
					{
						VisitStatement(child, initialStackDepth);
						child = child.GetNext();
					}
					break;
				}

				case Token.ENTERWITH:
				{
					VisitExpression(child, 0);
					AddToken(Token.ENTERWITH);
					StackChange(-1);
					break;
				}

				case Token.LEAVEWITH:
				{
					AddToken(Token.LEAVEWITH);
					break;
				}

				case Token.LOCAL_BLOCK:
				{
					int local = AllocLocal();
					node.PutIntProp(Node.LOCAL_PROP, local);
					UpdateLineNumber(node);
					while (child != null)
					{
						VisitStatement(child, initialStackDepth);
						child = child.GetNext();
					}
					AddIndexOp(Icode_LOCAL_CLEAR, local);
					ReleaseLocal(local);
					break;
				}

				case Token.DEBUGGER:
				{
					AddIcode(Icode_DEBUGGER);
					break;
				}

				case Token.SWITCH:
				{
					UpdateLineNumber(node);
					// See comments in IRFactory.createSwitch() for description
					// of SWITCH node
					VisitExpression(child, 0);
					for (Jump caseNode = (Jump)child.GetNext(); caseNode != null; caseNode = (Jump)caseNode.GetNext())
					{
						if (caseNode.GetType() != Token.CASE)
						{
							throw BadTree(caseNode);
						}
						Node test = caseNode.GetFirstChild();
						AddIcode(Icode_DUP);
						StackChange(1);
						VisitExpression(test, 0);
						AddToken(Token.SHEQ);
						StackChange(-1);
						// If true, Icode_IFEQ_POP will jump and remove case
						// value from stack
						AddGoto(caseNode.target, Icode_IFEQ_POP);
						StackChange(-1);
					}
					AddIcode(Icode_POP);
					StackChange(-1);
					break;
				}

				case Token.TARGET:
				{
					MarkTargetLabel(node);
					break;
				}

				case Token.IFEQ:
				case Token.IFNE:
				{
					Node target = ((Jump)node).target;
					VisitExpression(child, 0);
					AddGoto(target, type);
					StackChange(-1);
					break;
				}

				case Token.GOTO:
				{
					Node target = ((Jump)node).target;
					AddGoto(target, type);
					break;
				}

				case Token.JSR:
				{
					Node target = ((Jump)node).target;
					AddGoto(target, Icode_GOSUB);
					break;
				}

				case Token.FINALLY:
				{
					// Account for incomming GOTOSUB address
					StackChange(1);
					int finallyRegister = GetLocalBlockRef(node);
					AddIndexOp(Icode_STARTSUB, finallyRegister);
					StackChange(-1);
					while (child != null)
					{
						VisitStatement(child, initialStackDepth);
						child = child.GetNext();
					}
					AddIndexOp(Icode_RETSUB, finallyRegister);
					break;
				}

				case Token.EXPR_VOID:
				case Token.EXPR_RESULT:
				{
					UpdateLineNumber(node);
					VisitExpression(child, 0);
					AddIcode((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT);
					StackChange(-1);
					break;
				}

				case Token.TRY:
				{
					Jump tryNode = (Jump)node;
					int exceptionObjectLocal = GetLocalBlockRef(tryNode);
					int scopeLocal = AllocLocal();
					AddIndexOp(Icode_SCOPE_SAVE, scopeLocal);
					int tryStart = iCodeTop;
					bool savedFlag = itsInTryFlag;
					itsInTryFlag = true;
					while (child != null)
					{
						VisitStatement(child, initialStackDepth);
						child = child.GetNext();
					}
					itsInTryFlag = savedFlag;
					Node catchTarget = tryNode.target;
					if (catchTarget != null)
					{
						int catchStartPC = labelTable[GetTargetLabel(catchTarget)];
						AddExceptionHandler(tryStart, catchStartPC, catchStartPC, false, exceptionObjectLocal, scopeLocal);
					}
					Node finallyTarget = tryNode.GetFinally();
					if (finallyTarget != null)
					{
						int finallyStartPC = labelTable[GetTargetLabel(finallyTarget)];
						AddExceptionHandler(tryStart, finallyStartPC, finallyStartPC, true, exceptionObjectLocal, scopeLocal);
					}
					AddIndexOp(Icode_LOCAL_CLEAR, scopeLocal);
					ReleaseLocal(scopeLocal);
					break;
				}

				case Token.CATCH_SCOPE:
				{
					int localIndex = GetLocalBlockRef(node);
					int scopeIndex = node.GetExistingIntProp(Node.CATCH_SCOPE_PROP);
					string name = child.GetString();
					child = child.GetNext();
					VisitExpression(child, 0);
					// load expression object
					AddStringPrefix(name);
					AddIndexPrefix(localIndex);
					AddToken(Token.CATCH_SCOPE);
					AddUint8(scopeIndex != 0 ? 1 : 0);
					StackChange(-1);
					break;
				}

				case Token.THROW:
				{
					UpdateLineNumber(node);
					VisitExpression(child, 0);
					AddToken(Token.THROW);
					AddUint16(lineNumber & unchecked((int)(0xFFFF)));
					StackChange(-1);
					break;
				}

				case Token.RETHROW:
				{
					UpdateLineNumber(node);
					AddIndexOp(Token.RETHROW, GetLocalBlockRef(node));
					break;
				}

				case Token.RETURN:
				{
					UpdateLineNumber(node);
					if (node.GetIntProp(Node.GENERATOR_END_PROP, 0) != 0)
					{
						// We're in a generator, so change RETURN to GENERATOR_END
						AddIcode(Icode_GENERATOR_END);
						AddUint16(lineNumber & unchecked((int)(0xFFFF)));
					}
					else
					{
						if (child != null)
						{
							VisitExpression(child, ECF_TAIL);
							AddToken(Token.RETURN);
							StackChange(-1);
						}
						else
						{
							AddIcode(Icode_RETUNDEF);
						}
					}
					break;
				}

				case Token.RETURN_RESULT:
				{
					UpdateLineNumber(node);
					AddToken(Token.RETURN_RESULT);
					break;
				}

				case Token.ENUM_INIT_KEYS:
				case Token.ENUM_INIT_VALUES:
				case Token.ENUM_INIT_ARRAY:
				{
					VisitExpression(child, 0);
					AddIndexOp(type, GetLocalBlockRef(node));
					StackChange(-1);
					break;
				}

				case Icode_GENERATOR:
				{
					break;
				}

				default:
				{
					throw BadTree(node);
				}
			}
			if (stackDepth != initialStackDepth)
			{
				throw Kit.CodeBug();
			}
		}
Esempio n. 15
0
		public int GetVarIndex(Node n)
		{
			int index = n.GetIntProp(Node.VARIABLE_PROP, -1);
			if (index == -1)
			{
				Node node;
				int type = n.GetType();
				if (type == Token.GETVAR)
				{
					node = n;
				}
				else
				{
					if (type == Token.SETVAR || type == Token.SETCONSTVAR)
					{
						node = n.GetFirstChild();
					}
					else
					{
						throw Kit.CodeBug();
					}
				}
				index = fnode.GetIndexForNameNode(node);
				if (index < 0)
				{
					throw Kit.CodeBug();
				}
				n.PutIntProp(Node.VARIABLE_PROP, index);
			}
			return index;
		}