Exemple #1
0
		private int RewriteForNumberVariables(Node n, int desired)
		{
			switch (n.GetType())
			{
				case Token.EXPR_VOID:
				{
					Node child = n.GetFirstChild();
					int type = RewriteForNumberVariables(child, NumberType);
					if (type == NumberType)
					{
						n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
					}
					return NoType;
				}

				case Token.NUMBER:
				{
					n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
					return NumberType;
				}

				case Token.GETVAR:
				{
					int varIndex = theFunction.GetVarIndex(n);
					if (inDirectCallFunction && theFunction.IsParameter(varIndex) && desired == NumberType)
					{
						n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
						return NumberType;
					}
					else
					{
						if (theFunction.IsNumberVar(varIndex))
						{
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							return NumberType;
						}
					}
					return NoType;
				}

				case Token.INC:
				case Token.DEC:
				{
					Node child = n.GetFirstChild();
					int type = RewriteForNumberVariables(child, NumberType);
					if (child.GetType() == Token.GETVAR)
					{
						if (type == NumberType && !ConvertParameter(child))
						{
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							MarkDCPNumberContext(child);
							return NumberType;
						}
						return NoType;
					}
					else
					{
						if (child.GetType() == Token.GETELEM || child.GetType() == Token.GETPROP)
						{
							return type;
						}
					}
					return NoType;
				}

				case Token.SETVAR:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int rType = RewriteForNumberVariables(rChild, NumberType);
					int varIndex = theFunction.GetVarIndex(n);
					if (inDirectCallFunction && theFunction.IsParameter(varIndex))
					{
						if (rType == NumberType)
						{
							if (!ConvertParameter(rChild))
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
								return NumberType;
							}
							MarkDCPNumberContext(rChild);
							return NoType;
						}
						else
						{
							return rType;
						}
					}
					else
					{
						if (theFunction.IsNumberVar(varIndex))
						{
							if (rType != NumberType)
							{
								n.RemoveChild(rChild);
								n.AddChildToBack(new Node(Token.TO_DOUBLE, rChild));
							}
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							MarkDCPNumberContext(rChild);
							return NumberType;
						}
						else
						{
							if (rType == NumberType)
							{
								if (!ConvertParameter(rChild))
								{
									n.RemoveChild(rChild);
									n.AddChildToBack(new Node(Token.TO_OBJECT, rChild));
								}
							}
							return NoType;
						}
					}
					goto case Token.LE;
				}

				case Token.LE:
				case Token.LT:
				case Token.GE:
				case Token.GT:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int lType = RewriteForNumberVariables(lChild, NumberType);
					int rType = RewriteForNumberVariables(rChild, NumberType);
					MarkDCPNumberContext(lChild);
					MarkDCPNumberContext(rChild);
					if (ConvertParameter(lChild))
					{
						if (ConvertParameter(rChild))
						{
							return NoType;
						}
						else
						{
							if (rType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
							}
						}
					}
					else
					{
						if (ConvertParameter(rChild))
						{
							if (lType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
							}
						}
						else
						{
							if (lType == NumberType)
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
								}
								else
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
								}
							}
							else
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
								}
							}
						}
					}
					// we actually build a boolean value
					return NoType;
				}

				case Token.ADD:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int lType = RewriteForNumberVariables(lChild, NumberType);
					int rType = RewriteForNumberVariables(rChild, NumberType);
					if (ConvertParameter(lChild))
					{
						if (ConvertParameter(rChild))
						{
							return NoType;
						}
						else
						{
							if (rType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
							}
						}
					}
					else
					{
						if (ConvertParameter(rChild))
						{
							if (lType == NumberType)
							{
								n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
							}
						}
						else
						{
							if (lType == NumberType)
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
									return NumberType;
								}
								else
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
								}
							}
							else
							{
								if (rType == NumberType)
								{
									n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
								}
							}
						}
					}
					return NoType;
				}

				case Token.BITXOR:
				case Token.BITOR:
				case Token.BITAND:
				case Token.RSH:
				case Token.LSH:
				case Token.SUB:
				case Token.MUL:
				case Token.DIV:
				case Token.MOD:
				{
					Node lChild = n.GetFirstChild();
					Node rChild = lChild.GetNext();
					int lType = RewriteForNumberVariables(lChild, NumberType);
					int rType = RewriteForNumberVariables(rChild, NumberType);
					MarkDCPNumberContext(lChild);
					MarkDCPNumberContext(rChild);
					if (lType == NumberType)
					{
						if (rType == NumberType)
						{
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							return NumberType;
						}
						else
						{
							if (!ConvertParameter(rChild))
							{
								n.RemoveChild(rChild);
								n.AddChildToBack(new Node(Token.TO_DOUBLE, rChild));
								n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							}
							return NumberType;
						}
					}
					else
					{
						if (rType == NumberType)
						{
							if (!ConvertParameter(lChild))
							{
								n.RemoveChild(lChild);
								n.AddChildToFront(new Node(Token.TO_DOUBLE, lChild));
								n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							}
							return NumberType;
						}
						else
						{
							if (!ConvertParameter(lChild))
							{
								n.RemoveChild(lChild);
								n.AddChildToFront(new Node(Token.TO_DOUBLE, lChild));
							}
							if (!ConvertParameter(rChild))
							{
								n.RemoveChild(rChild);
								n.AddChildToBack(new Node(Token.TO_DOUBLE, rChild));
							}
							n.PutIntProp(Node.ISNUMBER_PROP, Node.BOTH);
							return NumberType;
						}
					}
					goto case Token.SETELEM;
				}

				case Token.SETELEM:
				case Token.SETELEM_OP:
				{
					Node arrayBase = n.GetFirstChild();
					Node arrayIndex = arrayBase.GetNext();
					Node rValue = arrayIndex.GetNext();
					int baseType = RewriteForNumberVariables(arrayBase, NumberType);
					if (baseType == NumberType)
					{
						if (!ConvertParameter(arrayBase))
						{
							n.RemoveChild(arrayBase);
							n.AddChildToFront(new Node(Token.TO_OBJECT, arrayBase));
						}
					}
					int indexType = RewriteForNumberVariables(arrayIndex, NumberType);
					if (indexType == NumberType)
					{
						if (!ConvertParameter(arrayIndex))
						{
							// setting the ISNUMBER_PROP signals the codegen
							// to use the OptRuntime.setObjectIndex that takes
							// a double index
							n.PutIntProp(Node.ISNUMBER_PROP, Node.LEFT);
						}
					}
					int rValueType = RewriteForNumberVariables(rValue, NumberType);
					if (rValueType == NumberType)
					{
						if (!ConvertParameter(rValue))
						{
							n.RemoveChild(rValue);
							n.AddChildToBack(new Node(Token.TO_OBJECT, rValue));
						}
					}
					return NoType;
				}

				case Token.GETELEM:
				{
					Node arrayBase = n.GetFirstChild();
					Node arrayIndex = arrayBase.GetNext();
					int baseType = RewriteForNumberVariables(arrayBase, NumberType);
					if (baseType == NumberType)
					{
						if (!ConvertParameter(arrayBase))
						{
							n.RemoveChild(arrayBase);
							n.AddChildToFront(new Node(Token.TO_OBJECT, arrayBase));
						}
					}
					int indexType = RewriteForNumberVariables(arrayIndex, NumberType);
					if (indexType == NumberType)
					{
						if (!ConvertParameter(arrayIndex))
						{
							// setting the ISNUMBER_PROP signals the codegen
							// to use the OptRuntime.getObjectIndex that takes
							// a double index
							n.PutIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
						}
					}
					return NoType;
				}

				case Token.CALL:
				{
					Node child = n.GetFirstChild();
					// the function node
					// must be an object
					RewriteAsObjectChildren(child, child.GetFirstChild());
					child = child.GetNext();
					// the first arg
					OptFunctionNode target = (OptFunctionNode)n.GetProp(Node.DIRECTCALL_PROP);
					if (target != null)
					{
						while (child != null)
						{
							int type = RewriteForNumberVariables(child, NumberType);
							if (type == NumberType)
							{
								MarkDCPNumberContext(child);
							}
							child = child.GetNext();
						}
					}
					else
					{
						RewriteAsObjectChildren(n, child);
					}
					return NoType;
				}

				default:
				{
					RewriteAsObjectChildren(n, n.GetFirstChild());
					return NoType;
				}
			}
		}
Exemple #2
0
		private void VisitObjectLiteral(Node node, Node child, bool topLevel)
		{
			object[] properties = (object[])node.GetProp(Node.OBJECT_IDS_PROP);
			int count = properties.Length;
			// If code budget is tight swap out literals into separate method
			if (!topLevel && (count > 10 || cfw.GetCurrentCodeOffset() > 30000) && !hasVarsInRegs && !isGenerator && !inLocalBlock)
			{
				if (literals == null)
				{
					literals = new List<Node>();
				}
				literals.Add(node);
				string methodName = codegen.GetBodyMethodName(scriptOrFn) + "_literal" + literals.Count;
				cfw.AddALoad(funObjLocal);
				cfw.AddALoad(contextLocal);
				cfw.AddALoad(variableObjectLocal);
				cfw.AddALoad(thisObjLocal);
				cfw.AddALoad(argsLocal);
				cfw.AddInvoke(ByteCode.INVOKEVIRTUAL, codegen.mainClassName, methodName, "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;" + ")Lorg/mozilla/javascript/Scriptable;");
				return;
			}
			// load array with property ids
			AddNewObjectArray(count);
			for (int i = 0; i != count; ++i)
			{
				cfw.Add(ByteCode.DUP);
				cfw.AddPush(i);
				object id = properties[i];
				if (id is string)
				{
					cfw.AddPush((string)id);
				}
				else
				{
					cfw.AddPush(System.Convert.ToInt32(((int)id)));
					AddScriptRuntimeInvoke("wrapInt", "(I)Ljava/lang/Integer;");
				}
				cfw.Add(ByteCode.AASTORE);
			}
			// load array with property values
			AddNewObjectArray(count);
			Node child2 = child;
			for (int i_1 = 0; i_1 != count; ++i_1)
			{
				cfw.Add(ByteCode.DUP);
				cfw.AddPush(i_1);
				int childType = child2.GetType();
				if (childType == Token.GET || childType == Token.SET)
				{
					GenerateExpression(child2.GetFirstChild(), node);
				}
				else
				{
					GenerateExpression(child2, node);
				}
				cfw.Add(ByteCode.AASTORE);
				child2 = child2.GetNext();
			}
			// check if object literal actually has any getters or setters
			bool hasGetterSetters = false;
			child2 = child;
			for (int i_2 = 0; i_2 != count; ++i_2)
			{
				int childType = child2.GetType();
				if (childType == Token.GET || childType == Token.SET)
				{
					hasGetterSetters = true;
					break;
				}
				child2 = child2.GetNext();
			}
			// create getter/setter flag array
			if (hasGetterSetters)
			{
				cfw.AddPush(count);
				cfw.Add(ByteCode.NEWARRAY, ByteCode.T_INT);
				child2 = child;
				for (int i_3 = 0; i_3 != count; ++i_3)
				{
					cfw.Add(ByteCode.DUP);
					cfw.AddPush(i_3);
					int childType = child2.GetType();
					if (childType == Token.GET)
					{
						cfw.Add(ByteCode.ICONST_M1);
					}
					else
					{
						if (childType == Token.SET)
						{
							cfw.Add(ByteCode.ICONST_1);
						}
						else
						{
							cfw.Add(ByteCode.ICONST_0);
						}
					}
					cfw.Add(ByteCode.IASTORE);
					child2 = child2.GetNext();
				}
			}
			else
			{
				cfw.Add(ByteCode.ACONST_NULL);
			}
			cfw.AddALoad(contextLocal);
			cfw.AddALoad(variableObjectLocal);
			AddScriptRuntimeInvoke("newObjectLiteral", "([Ljava/lang/Object;" + "[Ljava/lang/Object;" + "[I" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Scriptable;");
		}
Exemple #3
0
		private int GetLocalBlockRegister(Node node)
		{
			Node localBlock = (Node)node.GetProp(Node.LOCAL_BLOCK_PROP);
			int localSlot = localBlock.GetExistingIntProp(Node.LOCAL_PROP);
			return localSlot;
		}
Exemple #4
0
		private void VisitArrayLiteral(Node node, Node child, bool topLevel)
		{
			int count = 0;
			for (Node cursor = child; cursor != null; cursor = cursor.GetNext())
			{
				++count;
			}
			// If code budget is tight swap out literals into separate method
			if (!topLevel && (count > 10 || cfw.GetCurrentCodeOffset() > 30000) && !hasVarsInRegs && !isGenerator && !inLocalBlock)
			{
				if (literals == null)
				{
					literals = new List<Node>();
				}
				literals.Add(node);
				string methodName = codegen.GetBodyMethodName(scriptOrFn) + "_literal" + literals.Count;
				cfw.AddALoad(funObjLocal);
				cfw.AddALoad(contextLocal);
				cfw.AddALoad(variableObjectLocal);
				cfw.AddALoad(thisObjLocal);
				cfw.AddALoad(argsLocal);
				cfw.AddInvoke(ByteCode.INVOKEVIRTUAL, codegen.mainClassName, methodName, "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;" + ")Lorg/mozilla/javascript/Scriptable;");
				return;
			}
			// load array to store array literal objects
			AddNewObjectArray(count);
			for (int i = 0; i != count; ++i)
			{
				cfw.Add(ByteCode.DUP);
				cfw.AddPush(i);
				GenerateExpression(child, node);
				cfw.Add(ByteCode.AASTORE);
				child = child.GetNext();
			}
			int[] skipIndexes = (int[])node.GetProp(Node.SKIP_INDEXES_PROP);
			if (skipIndexes == null)
			{
				cfw.Add(ByteCode.ACONST_NULL);
				cfw.Add(ByteCode.ICONST_0);
			}
			else
			{
				cfw.AddPush(OptRuntime.EncodeIntArray(skipIndexes));
				cfw.AddPush(skipIndexes.Length);
			}
			cfw.AddALoad(contextLocal);
			cfw.AddALoad(variableObjectLocal);
			AddOptRuntimeInvoke("newArrayLiteral", "([Ljava/lang/Object;" + "Ljava/lang/String;" + "I" + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Scriptable;");
		}
Exemple #5
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);
				}
			}
		}
Exemple #6
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();
			}
		}
Exemple #7
0
		private int GetLocalBlockRef(Node node)
		{
			Node localBlock = (Node)node.GetProp(Node.LOCAL_BLOCK_PROP);
			return localBlock.GetExistingIntProp(Node.LOCAL_PROP);
		}
Exemple #8
0
		private void VisitLiteral(Node node, Node child)
		{
			int type = node.GetType();
			int count;
			object[] propertyIds = null;
			if (type == Token.ARRAYLIT)
			{
				count = 0;
				for (Node n = child; n != null; n = n.GetNext())
				{
					++count;
				}
			}
			else
			{
				if (type == Token.OBJECTLIT)
				{
					propertyIds = (object[])node.GetProp(Node.OBJECT_IDS_PROP);
					count = propertyIds.Length;
				}
				else
				{
					throw BadTree(node);
				}
			}
			AddIndexOp(Icode_LITERAL_NEW, count);
			StackChange(2);
			while (child != null)
			{
				int childType = child.GetType();
				if (childType == Token.GET)
				{
					VisitExpression(child.GetFirstChild(), 0);
					AddIcode(Icode_LITERAL_GETTER);
				}
				else
				{
					if (childType == Token.SET)
					{
						VisitExpression(child.GetFirstChild(), 0);
						AddIcode(Icode_LITERAL_SETTER);
					}
					else
					{
						VisitExpression(child, 0);
						AddIcode(Icode_LITERAL_SET);
					}
				}
				StackChange(-1);
				child = child.GetNext();
			}
			if (type == Token.ARRAYLIT)
			{
				int[] skipIndexes = (int[])node.GetProp(Node.SKIP_INDEXES_PROP);
				if (skipIndexes == null)
				{
					AddToken(Token.ARRAYLIT);
				}
				else
				{
					int index = literalIds.Size();
					literalIds.Add(skipIndexes);
					AddIndexOp(Icode_SPARE_ARRAYLIT, index);
				}
			}
			else
			{
				int index = literalIds.Size();
				literalIds.Add(propertyIds);
				AddIndexOp(Token.OBJECTLIT, index);
			}
			StackChange(-1);
		}