Ejemplo n.º 1
0
 int getLocalBlockRef (Node node)
 {
     Node localBlock = (Node)node.getProp (Node.LOCAL_BLOCK_PROP);
     return localBlock.getExistingIntProp (Node.LOCAL_PROP);
 }
Ejemplo n.º 2
0
        void VisitExpression (Node node, int contextFlags)
        {
            if (VisitExpressionOptimized (node, contextFlags))
                return;

            int type = node.Type;
            Node child = node.FirstChild;
            int savedStackDepth = itsStackDepth;
            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					
                        switch (fn.FunctionType) {
                            case FunctionNode.FUNCTION_EXPRESSION:
                                addIndexOp (Icode_CLOSURE_EXPR, fnIndex);
                                break;
                            default:
                                throw Context.CodeBug ();
                        }

                        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.LastChild;
                        while (child != lastChild) {
                            VisitExpression (child, 0);
                            addIcode (Icode_POP);
                            stackChange (-1);
                            child = child.Next;
                        }
                        // 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.Next) != null) {
                            VisitExpression (child, 0);
                            ++argCount;
                        }
                        int callType = node.getIntProp (Node.SPECIALCALL_PROP, Node.NON_SPECIALCALL);
                        if (callType != Node.NON_SPECIALCALL) {
                            // embed line number and source filename
                            addIndexOp (Icode_CALLSPECIAL, argCount);
                            addUint8 (callType);
                            addUint8 (type == Token.NEW ? 1 : 0);
                            addUint16 (itsLineNumber & 0xFFFF);
                        }
                        else {
                            if (type == Token.CALL) {
                                if ((contextFlags & ECF_TAIL) != 0) {
                                    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 = itsICodeTop;
                        int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ;
                        addGotoOp (jump);
                        stackChange (-1);
                        addIcode (Icode_POP);
                        stackChange (-1);
                        child = child.Next;
                        // Preserve tail context flag if any
                        VisitExpression (child, contextFlags & ECF_TAIL);
                        resolveForwardGoto (afterSecondJumpStart);
                    }
                    break;


                case Token.HOOK: {
                        Node ifThen = child.Next;
                        Node ifElse = ifThen.Next;
                        VisitExpression (child, 0);
                        int elseJumpStart = itsICodeTop;
                        addGotoOp (Token.IFNE);
                        ;
                        stackChange (-1);
                        // Preserve tail context flag if any
                        VisitExpression (ifThen, contextFlags & ECF_TAIL);
                        int afterElseJumpStart = itsICodeTop;
                        addGotoOp (Token.GOTO);
                        resolveForwardGoto (elseJumpStart);
                        itsStackDepth = savedStackDepth;
                        // Preserve tail context flag if any
                        VisitExpression (ifElse, contextFlags & ECF_TAIL);
                        resolveForwardGoto (afterElseJumpStart);
                    }
                    break;


                case Token.GETPROP:
                    VisitExpression (child, 0);
                    child = child.Next;
                    addStringOp (Token.GETPROP, child.String);
                    break;


                case Token.ADD:
                case Token.GETELEM:
                case Token.DELPROP:
                case Token.BITAND:
                case Token.BITOR:
                case Token.BITXOR:
                case Token.LSH:
                case Token.RSH:
                case Token.URSH:
                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);
                    VisitExpression (child.Next, 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:
                case Token.SETPROP_GETTER:
                case Token.SETPROP_SETTER: 
                    {
                        VisitExpression (child, 0);
                        child = child.Next;
                        string property = child.String;
                        child = child.Next;
                        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 ((type == Token.SETPROP_OP) ? Token.SETPROP : type, property);
                        stackChange (-1);
                    }
                    break;


                case Token.SETELEM:
                case Token.SETELEM_OP:
                    VisitExpression (child, 0);
                    child = child.Next;
                    VisitExpression (child, 0);
                    child = child.Next;
                    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.Next;
                    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.SETNAME: {
                        string name = child.String;
                        VisitExpression (child, 0);
                        child = child.Next;
                        VisitExpression (child, 0);
                        addStringOp (Token.SETNAME, name);
                        stackChange (-1);
                    }
                    break;


                case Token.TYPEOFNAME: {
                        string name = node.String;
                        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.getParamOrVarIndex (name);
                        if (index == -1) {
                            addStringOp (Icode_TYPEOFNAME, name);
                            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.String);
                    stackChange (1);
                    break;


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


                case Token.NUMBER: {
                        double num = node.Double;
                        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 & 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)
                            Context.CodeBug ();
                        string name = node.String;
                        int index = scriptOrFn.getParamOrVarIndex (name);
                        addVarOp (Token.GETVAR, index);
                        stackChange (1);
                    }
                    break;


                case Token.SETVAR: {
                        if (itsData.itsNeedsActivation)
                            Context.CodeBug ();
                        string name = child.String;
                        child = child.Next;
                        VisitExpression (child, 0);
                        int index = scriptOrFn.getParamOrVarIndex (name);
                        addVarOp (Token.SETVAR, 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.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.Next;
                        }
                        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 = itsICodeTop;
                        VisitExpression (child.Next, 0);
                        addBackwardGoto (Icode_LEAVEDQ, queryPC);
                    }
                    break;


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

                default:
                    throw badTree (node);

            }
            //if (savedStackDepth + 1 != itsStackDepth) {
            //    EcmaScriptHelper.CodeBug();
            //}
        }
Ejemplo n.º 3
0
 void VisitLiteral (Node node, Node child)
 {
     int type = node.Type;
     int count;
     object [] propertyIds = null;
     if (type == Token.ARRAYLIT) {
         count = 0;
         for (Node n = child; n != null; n = n.Next) {
             ++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 (1);
     while (child != null) {
         VisitExpression (child, 0);
         addIcode (Icode_LITERAL_SET);
         stackChange (-1);
         child = child.Next;
     }
     if (type == Token.ARRAYLIT) {
         int [] skipIndexes = (int [])node.getProp (Node.SKIP_INDEXES_PROP);
         if (skipIndexes == null) {
             addToken (Token.ARRAYLIT);
         }
         else {
             int index = itsLiteralIds.size ();
             itsLiteralIds.add (skipIndexes);
             addIndexOp (Icode_SPARE_ARRAYLIT, index);
         }
     }
     else {
         int index = itsLiteralIds.size ();
         itsLiteralIds.add (propertyIds);
         addIndexOp (Token.OBJECTLIT, index);
     }
 }