private void visitIfJumpEqOp(Node node, Node child,
                                 int trueGOTO, int falseGOTO)
    {
        if (trueGOTO == -1 || falseGOTO == -1) throw Codegen.badTree();

        short stackInitial = cfw.getStackTop();
        int type = node.getType();
        Node rChild = child.getNext();

        // Optimize if one of operands is null
        if (child.getType() == Token.NULL || rChild.getType() == Token.NULL) {
            // eq is symmetric in this case
            if (child.getType() == Token.NULL) {
                child = rChild;
            }
            generateExpression(child, node);
            if (type == Token.SHEQ || type == Token.SHNE) {
                int testCode = (type == Token.SHEQ)
                                ? ByteCode.IFNULL : ByteCode.IFNONNULL;
                cfw.add(testCode, trueGOTO);
            } else {
                if (type != Token.EQ) {
                    // swap false/true targets for !=
                    if (type != Token.NE) throw Codegen.badTree();
                    int tmp = trueGOTO;
                    trueGOTO = falseGOTO;
                    falseGOTO = tmp;
                }
                cfw.add(ByteCode.DUP);
                int undefCheckLabel = cfw.acquireLabel();
                cfw.add(ByteCode.IFNONNULL, undefCheckLabel);
                short stack = cfw.getStackTop();
                cfw.add(ByteCode.POP);
                cfw.add(ByteCode.GOTO, trueGOTO);
                cfw.markLabel(undefCheckLabel, stack);
                Codegen.pushUndefined(cfw);
                cfw.add(ByteCode.IF_ACMPEQ, trueGOTO);
            }
            cfw.add(ByteCode.GOTO, falseGOTO);
        } else {
            int child_dcp_register = nodeIsDirectCallParameter(child);
            if (child_dcp_register != -1
                && rChild.getType() == Token.TO_OBJECT)
            {
                Node convertChild = rChild.getFirstChild();
                if (convertChild.getType() == Token.NUMBER) {
                    cfw.addALoad(child_dcp_register);
                    cfw.add(ByteCode.GETSTATIC,
                            "java/lang/Void",
                            "TYPE",
                            "Ljava/lang/Class;");
                    int notNumbersLabel = cfw.acquireLabel();
                    cfw.add(ByteCode.IF_ACMPNE, notNumbersLabel);
                    cfw.addDLoad(child_dcp_register + 1);
                    cfw.addPush(convertChild.getDouble());
                    cfw.add(ByteCode.DCMPL);
                    if (type == Token.EQ)
                        cfw.add(ByteCode.IFEQ, trueGOTO);
                    else
                        cfw.add(ByteCode.IFNE, trueGOTO);
                    cfw.add(ByteCode.GOTO, falseGOTO);
                    cfw.markLabel(notNumbersLabel);
                    // fall thru into generic handling
                }
            }

            generateExpression(child, node);
            generateExpression(rChild, node);

            String name;
            int testCode;
            switch (type) {
              case Token.EQ:
                name = "eq";
                testCode = ByteCode.IFNE;
                break;
              case Token.NE:
                name = "eq";
                testCode = ByteCode.IFEQ;
                break;
              case Token.SHEQ:
                name = "shallowEq";
                testCode = ByteCode.IFNE;
                break;
              case Token.SHNE:
                name = "shallowEq";
                testCode = ByteCode.IFEQ;
                break;
              default:
                throw Codegen.badTree();
            }
            addScriptRuntimeInvoke(name,
                                   "(Ljava/lang/Object;"
                                   +"Ljava/lang/Object;"
                                   +")Z");
            cfw.add(testCode, trueGOTO);
            cfw.add(ByteCode.GOTO, falseGOTO);
        }
        if (stackInitial != cfw.getStackTop()) throw Codegen.badTree();
    }