Пример #1
1
  /**
   * Converts the given value to the given NativeObject (optionally following the prototype chains).
   *
   * @param nativeObject target NativeObject
   * @param value Value to convert
   * @param prototype use the prototype chain?
   */
  public static Value toNativeObject(
      HostObject nativeObject,
      Value value,
      boolean prototype,
      Solver.SolverInterface solverInterface) {
    State state = solverInterface.getState();
    boolean bad = false;
    Set<ObjectLabel> matches = Collections.newSet();

    if (prototype) {
      // Make lookup using prototype chains
      Set<ObjectLabel> objectLabels = Collections.newSet(value.getObjectLabels());
      Set<ObjectLabel> visited = Collections.newSet();

      while (!objectLabels.isEmpty()) {
        Set<ObjectLabel> temp = Collections.newSet();
        for (ObjectLabel objectLabel : objectLabels) {
          if (!visited.contains(objectLabel)) {
            visited.add(objectLabel);
            Value prototypeValue =
                state.readInternalPrototype(java.util.Collections.singleton(objectLabel));
            prototypeValue = UnknownValueResolver.getRealValue(prototypeValue, state);

            // FIXME: Needs code review. Looks fishy to compare objects with toString().
            String nativeObjectPrototype = nativeObject.toString();
            String objectLabelPrototype = "";
            if (objectLabel.getHostObject() != null) {
              objectLabelPrototype = objectLabel.getHostObject().toString();
            }

            if (nativeObject == objectLabel.getHostObject()
                || nativeObjectPrototype.equals(objectLabelPrototype)) {
              matches.add(objectLabel);
            } else if (prototypeValue.getObjectLabels().isEmpty()) {
              bad = true;
            } else {
              temp.addAll(prototypeValue.getObjectLabels());
            }
          }
        }
        objectLabels = temp;
      }
    } else {
      // Make lookup ignoring prototype chains

      // TODO: Verify this
      for (ObjectLabel objectLabel : value.getObjectLabels()) {
        if (objectLabel.getHostObject() == nativeObject
            || (objectLabel.getHostObject() != null
                && objectLabel.getHostObject().toString().equals(nativeObject + ".prototype"))) {
          matches.add(objectLabel);
        } else {
          bad = true;
        }
      }
    }

    //        Message.Status status;
    //        if (good && bad) {
    //            status = Message.Status.MAYBE;
    //        } else if (!good && bad) {
    //            status = Message.Status.CERTAIN;
    //        } else if (good && !bad) {
    //            status = Message.Status.NONE;
    //        } else if (!good && !bad) { // equivalent to Value of Undef / a null argument
    //            // Considered a certain type error.
    //            status = Message.Status.CERTAIN;
    //        } else {
    //            throw new AnalysisException("toNativeObject: fell through cases - should not
    // happen.");
    //        }
    if (bad) {
      String message = "TypeError, argument is not of expected type: " + nativeObject;
      solverInterface
          .getMonitoring()
          .addMessage(solverInterface.getNode(), Message.Severity.HIGH, message);
    }

    return Value.makeObject(matches);
  }
Пример #2
0
  /** Assumption. */
  @Override
  public void visit(AssumeNode n, State state) {
    if (Options.get().isControlSensitivityDisabled()) return;
    switch (n.getKind()) {
      case VARIABLE_NON_NULL_UNDEF:
        {
          Value v = state.readVariable(n.getVariableName(), null);
          v =
              UnknownValueResolver.getRealValue(
                  v, state); // TODO: limits use of polymorphic values?
          v = v.restrictToNotNullNotUndef().restrictToNotAbsent();
          if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) state.setToNone();
          else state.writeVariable(n.getVariableName(), v, false);
          break;
        }

      case PROPERTY_NON_NULL_UNDEF:
        {
          String propname;
          if (n.isPropertyFixed()) propname = n.getPropertyString();
          else {
            Value propval = state.readRegister(n.getPropertyRegister());
            propval =
                UnknownValueResolver.getRealValue(
                    propval, state); // TODO: limits use of polymorphic values?
            if (!propval.isMaybeSingleStr() || propval.isMaybeOtherThanStr())
              break; // safe to do nothing here if it gets complicated
            propname = propval.getStr();
          }
          Set<ObjectLabel> baseobjs =
              Conversion.toObjectLabels(
                  state,
                  n,
                  state.readRegister(n.getBaseRegister()),
                  null); // TODO: omitting side-effects here
          Value v = state.readPropertyWithAttributes(baseobjs, propname);
          if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) state.setToNone();
          else if (baseobjs.size() == 1 && baseobjs.iterator().next().isSingleton()) {
            v =
                UnknownValueResolver.getRealValue(
                    v, state); // TODO: limits use of polymorphic values?
            v = v.restrictToNotNullNotUndef().restrictToNotAbsent();
            state.writePropertyWithAttributes(baseobjs, propname, v, false);
          }
          break;
        }

      case UNREACHABLE:
        {
          if (Options.get().isIgnoreUnreachableEnabled()) {
            state.setToNone();
          }
          break;
        }

      default:
        throw new AnalysisException("Unhandled AssumeNode kind: " + n.getKind());
    }
  }
Пример #3
0
 /** 11.2.1 assignment with left-hand-side property accessor. */
 @Override
 public void visit(WritePropertyNode n, State state) {
   // get the base value, coerce with ToObject
   Value baseval = state.readRegister(n.getBaseRegister());
   baseval = UnknownValueResolver.getRealValue(baseval, state);
   m.visitPropertyAccess(n, baseval);
   Set<ObjectLabel> objlabels = Conversion.toObjectLabels(state, n, baseval, c);
   if (objlabels.isEmpty() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   state.writeRegister(
       n.getBaseRegister(),
       Value.makeObject(objlabels)); // if null/undefined, an exception would have been thrown via
   // toObjectLabels
   // get the property name value, separate the undefined/null/NaN components, coerce with ToString
   Value propertyval;
   int propertyreg;
   if (n.isPropertyFixed()) {
     propertyreg = AbstractNode.NO_VALUE;
     propertyval = Value.makeStr(n.getPropertyString());
   } else {
     propertyreg = n.getPropertyRegister();
     propertyval = state.readRegister(propertyreg);
     propertyval = UnknownValueResolver.getRealValue(propertyval, state);
   }
   boolean maybe_undef = propertyval.isMaybeUndef();
   boolean maybe_null = propertyval.isMaybeNull();
   boolean maybe_nan = propertyval.isMaybeNaN();
   propertyval = propertyval.restrictToNotNullNotUndef().restrictToNotNaN();
   Str propertystr = Conversion.toString(propertyval, propertyreg, c);
   // get the value to be written
   Value v = state.readRegister(n.getValueRegister());
   NativeFunctions.updateArrayLength(n, state, objlabels, propertystr, v, n.getValueRegister(), c);
   // write the object property value, as fixed property name or unknown property name, and
   // separately for "undefined"/"null"/"NaN"
   state.writeProperty(objlabels, propertystr, v, true, maybe_undef || maybe_null || maybe_nan);
   if (maybe_undef && !propertystr.isMaybeStr("undefined"))
     state.writeProperty(
         objlabels, Value.makeTemporaryStr("undefined"), v, true, !propertystr.isNotStr());
   if (maybe_null && !propertystr.isMaybeStr("null"))
     state.writeProperty(
         objlabels, Value.makeTemporaryStr("null"), v, true, !propertystr.isNotStr());
   if (maybe_nan && !propertystr.isMaybeStr("NaN"))
     state.writeProperty(
         objlabels, Value.makeTemporaryStr("NaN"), v, true, !propertystr.isNotStr());
   m.visitPropertyWrite(n, objlabels, propertystr); // TODO: more monitoring around here?
   if (Options.get().isEvalStatistics()
       && propertystr.getStr() != null
       && propertystr.getStr().equals("innerHTML")) {
     m.visitInnerHTMLWrite(n, v);
   }
   m.visitVariableOrProperty(
       n.getPropertyString(), n.getSourceLocation(), v, state.getContext(), state);
 }
Пример #4
0
 /** 12.5 and 12.6 'if'/iteration statement. */
 @Override
 public void visit(IfNode n, State state) {
   // do nothing (but see EdgeTransfer)
   Value val = state.readRegister(n.getConditionRegister());
   val = UnknownValueResolver.getRealValue(val, state);
   m.visitIf(n, Conversion.toBoolean(val));
 }
Пример #5
0
 /** 11.13 and 11.4 assignment with unary operator. */
 @Override
 public void visit(UnaryOperatorNode n, State state) {
   Value arg = state.readRegister(n.getArgRegister());
   arg = UnknownValueResolver.getRealValue(arg, state);
   Value v;
   switch (n.getOperator()) {
     case COMPLEMENT:
       v = Operators.complement(arg, n.getArgRegister(), c);
       break;
     case MINUS:
       v = Operators.uminus(arg, n.getArgRegister(), c);
       break;
     case NOT:
       v = Operators.not(arg, c);
       break;
     case PLUS:
       v = Operators.uplus(arg, n.getArgRegister(), c);
       break;
     default:
       throw new AnalysisException();
   }
   if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   if (n.getResultRegister() != AbstractNode.NO_VALUE)
     state.writeRegister(n.getResultRegister(), v);
 }
Пример #6
0
 /** 12.10 enter 'with' statement. */
 @Override
 public void visit(BeginWithNode n, State state) {
   Value v = state.readRegister(n.getObjectRegister());
   v = UnknownValueResolver.getRealValue(v, state);
   Set<ObjectLabel> objs = Conversion.toObjectLabels(state, n, v, c);
   if (objs.isEmpty() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   state.pushScopeChain(objs);
 }
Пример #7
0
 /** 12.6.4 check for more properties of 'for-in' statement. */
 @Override
 public void visit(HasNextPropertyNode n, State state) {
   Value v =
       UnknownValueResolver.getRealValue(state.readRegister(n.getPropertyListRegister()), state);
   Value res =
       !v.isNotStr()
           ? Value.makeBool(true)
           : Value.makeNone(); // string values represent property names
   if (v.isMaybeNull()) // null marks end-of-list
   res = res.joinBool(false);
   state.writeRegister(n.getResultRegister(), res);
 }
Пример #8
0
 /** 11.13 and 11.4.3 assignment with 'typeof' operator. */
 @Override
 public void visit(TypeofNode n, State state) {
   Value v;
   if (n.isVariable()) {
     Value val =
         state.readVariable(
             n.getVariableName(),
             null); // TODO: should also count as a variable read in Monitoring?
     val = UnknownValueResolver.getRealValue(val, state);
     v = Operators.typeof(val, val.isMaybeAbsent());
     m.visitVariableOrProperty(
         n.getVariableName(), n.getOperandSourceLocation(), val, state.getContext(), state);
   } else {
     Value val = state.readRegister(n.getArgRegister());
     val = UnknownValueResolver.getRealValue(val, state);
     v = Operators.typeof(val, false);
   }
   if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   if (n.getResultRegister() != AbstractNode.NO_VALUE)
     state.writeRegister(n.getResultRegister(), v);
 }
Пример #9
0
  /** Beginning of loop. */
  @Override
  public void visit(BeginLoopNode n, State state) {
    // TODO: do nothing if loop unrolling is disabled or in scanning mode

    Value v = state.readRegister(n.getIfNode().getConditionRegister());
    v = Conversion.toBoolean(UnknownValueResolver.getRealValue(v, state));
    if (v.isMaybeTrueButNotFalse() || v.isMaybeFalseButNotTrue()) {
      // branch condition is determinate, switch context and propagate only to specialized successor
      Context specializedContext =
          c.getAnalysis()
              .getContextSensitivityStrategy()
              .makeNextLoopUnrollingContext(state.getContext(), n);
      BasicBlock successor = state.getBasicBlock().getSingleSuccessor();
      State specializedState = state.clone();
      specializedState.setContext(specializedContext);
      specializedState.setBasicBlock(successor);
      c.propagateToBasicBlock(specializedState, successor, specializedContext);
      state.setToNone();
    } // otherwise, just ordinary propagation like no-op
  }
Пример #10
0
 /** 11.13 and 11.4.1 assignment with 'delete' operator. */
 @Override
 public void visit(DeletePropertyNode n, State state) {
   Value v;
   if (n.isVariable()) {
     v = state.deleteVariable(n.getVariableName());
     m.visitVariableOrProperty(
         n.getVariableName(), n.getSourceLocation(), v, state.getContext(), state);
   } else {
     Value baseval = state.readRegister(n.getBaseRegister());
     baseval = UnknownValueResolver.getRealValue(baseval, state);
     m.visitPropertyAccess(n, baseval);
     if (baseval.isMaybeNull() || baseval.isMaybeUndef()) {
       Exceptions.throwTypeError(state, c);
       if (baseval.isNullOrUndef() && !Options.get().isPropagateDeadFlow()) {
         state.setToNone();
         return;
       }
     }
     baseval = baseval.restrictToNotNullNotUndef();
     state.writeRegister(n.getBaseRegister(), baseval);
     Set<ObjectLabel> objlabels = Conversion.toObjectLabels(state, n, baseval, c);
     if (objlabels.isEmpty() && !Options.get().isPropagateDeadFlow()) {
       state.setToNone();
       return;
     }
     Str propertystr;
     if (n.isPropertyFixed()) {
       propertystr = Value.makeStr(n.getPropertyString());
     } else {
       Value propertyval = state.readRegister(n.getPropertyRegister());
       propertystr = Conversion.toString(propertyval, n.getPropertyRegister(), c);
     }
     v = state.deleteProperty(objlabels, propertystr, false);
   }
   if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   if (n.getResultRegister() != AbstractNode.NO_VALUE)
     state.writeRegister(n.getResultRegister(), v);
 }
Пример #11
0
  /** 12.6.4 begin 'for-in' statement. */
  @Override
  public void visit(BeginForInNode n, State state) {
    if (!Options.get().isForInSpecializationDisabled()) {
      // 1. Find properties to iterate through
      Value v1 = state.readRegister(n.getObjectRegister());
      state.writeRegister(
          n.getObjectRegister(), v1.makeExtendedScope()); // preserve the register value
      v1 = UnknownValueResolver.getRealValue(v1, state);
      Set<ObjectLabel> objs = Conversion.toObjectLabels(state, n, v1, c);
      State.Properties p = state.getEnumProperties(objs);
      Collection<Value> propertyNameValues = newList(p.toValues());

      // Add the no-iteration case
      propertyNameValues.add(Value.makeNull().makeExtendedScope());

      // 2. Make specialized context for each iteration
      int it = n.getPropertyListRegister();
      //            List<Context> specialized_contexts = newList();
      BasicBlock successor = n.getBlock().getSingleSuccessor();
      for (Value k : propertyNameValues) {
        m.visitPropertyRead(n, objs, k, state, true);
        if (!c.isScanning()) {
          // 2.1 Make specialized context
          State specialized_state = state.clone();
          specialized_state.writeRegister(it, k);
          Context specialized_context =
              c.getAnalysis()
                  .getContextSensitivityStrategy()
                  .makeForInEntryContext(state.getContext(), n, k);
          //                    specialized_contexts.add(specialized_context);
          specialized_state.setContext(specialized_context);
          specialized_state.setBasicBlock(successor);
          // 2.2  Propagate specialized context
          c.propagateToFunctionEntry(
              n, state.getContext(), specialized_state, specialized_context, successor);
        }
      }
      if (!c.isScanning()) {
        // TODO: could kill flow to specializations if covered by other context
        // List<Context> previousSpecializations = c.getAnalysis().getForInSpecializations(n,
        // s.getContext());
        // if (previousSpecializations != null && (p.isArray() || p.isNonArray())) {
        //    previousSpecializations.forEach(c -> {
        //        // covered.setToNone();
        //    });
        //  }

        // TODO: could kill null flow unless all iterations has reached at least one EndForInNode
      }
      state.setToNone();
    } else { // fall back to simple mode without context specialization
      Value v1 = state.readRegister(n.getObjectRegister());
      state.writeRegister(
          n.getObjectRegister(), v1.makeExtendedScope()); // preserve the register value
      v1 = UnknownValueResolver.getRealValue(v1, state);
      Set<ObjectLabel> objs = Conversion.toObjectLabels(state, n, v1, c);
      Properties p = state.getEnumProperties(objs);
      Value proplist = p.toValue().joinNull();
      m.visitPropertyRead(n, objs, proplist, state, true);
      state.writeRegister(n.getPropertyListRegister(), proplist);
    }
  }
Пример #12
0
  /** 11.2.2, 11.2.3, 13.2.1, and 13.2.2 'new' / function call. */
  @Override
  public void visit(CallNode n, State state) {
    if (n.getFunctionRegister()
        != AbstractNode.NO_VALUE) // old style call (where the function is given as a variable read)
    FunctionCalls.callFunction(
          new OrdinaryCallInfo(n, state) {

            @Override
            public Value getFunctionValue() {
              Value functionValue = state.readRegister(n.getFunctionRegister());
              if (n.getLiteralConstructorKind() != null) {
                // these literal invocations can not be spurious in ES5
                switch (n.getLiteralConstructorKind()) {
                  case ARRAY:
                    functionValue =
                        Value.makeObject(new ObjectLabel(ECMAScriptObjects.ARRAY, Kind.FUNCTION));
                    break;
                  case REGEXP:
                    functionValue =
                        Value.makeObject(new ObjectLabel(ECMAScriptObjects.REGEXP, Kind.FUNCTION));
                    break;
                  default:
                    throw new AnalysisException(
                        "Unhandled literal constructor type: " + n.getLiteralConstructorKind());
                }
              }
              return functionValue;
            }

            @Override
            public Set<ObjectLabel> prepareThis(State caller_state, State callee_state) {
              return UserFunctionCalls.determineThis(
                  n, caller_state, callee_state, c, n.getBaseRegister());
            }
          },
          state,
          c);
    else { // getPropertyString / getPropertyRegister - like ReadPropertyNode
      Value baseval = state.readRegister(n.getBaseRegister());
      baseval = UnknownValueResolver.getRealValue(baseval, state);
      Set<ObjectLabel> objlabels =
          baseval.getObjectLabels(); // the ReadPropertyNode has updated baseval to account for
      // ToObject
      Value propertyval;
      int propertyreg;
      if (n.isPropertyFixed()) {
        propertyreg = AbstractNode.NO_VALUE;
        propertyval = Value.makeStr(n.getPropertyString());
      } else {
        propertyreg = n.getPropertyRegister();
        propertyval = state.readRegister(propertyreg);
        propertyval = UnknownValueResolver.getRealValue(propertyval, state);
      }
      boolean maybe_undef = propertyval.isMaybeUndef();
      boolean maybe_null = propertyval.isMaybeNull();
      boolean maybe_nan = propertyval.isMaybeNaN();
      propertyval = propertyval.restrictToNotNullNotUndef().restrictToNotNaN();
      Str propertystr = Conversion.toString(propertyval, propertyreg, c);
      // read the object property value, as fixed property name or unknown property name, and
      // separately for "undefined"/"null"/"NaN"
      Map<ObjectLabel, Set<ObjectLabel>> target2this = newMap();
      List<Value> nonfunctions = newList();
      for (ObjectLabel objlabel :
          objlabels) { // find possible targets for each possible base object
        Set<ObjectLabel> singleton = singleton(objlabel);
        Value v;
        boolean read_undefined = false;
        boolean read_null = false;
        boolean read_nan = false;
        if (propertystr.isMaybeSingleStr()) {
          String propertyname = propertystr.getStr();
          v = state.readPropertyValue(singleton, propertyname);
        } else if (!propertystr.isNotStr()) {
          v = state.readPropertyValue(singleton, propertystr);
          read_undefined = propertystr.isMaybeStr("undefined");
          read_null = propertystr.isMaybeStr("null");
          read_nan = propertystr.isMaybeStr("NaN");
        } else v = Value.makeNone();
        if (maybe_undef && !read_undefined) {
          v = UnknownValueResolver.join(v, state.readPropertyValue(singleton, "undefined"), state);
        }
        if (maybe_null && !read_null) {
          v = UnknownValueResolver.join(v, state.readPropertyValue(singleton, "null"), state);
        }
        if (maybe_nan && !read_nan) {
          v = UnknownValueResolver.join(v, state.readPropertyValue(singleton, "NaN"), state);
        }
        v = UnknownValueResolver.getRealValue(v, state);

        // finally, remove all the TAJS hooks, which are spurious if accessed through a dynamic
        // property
        if (!n.isPropertyFixed()) {
          v = JSGlobal.removeTAJSSpecificFunctions(v);
        }

        for (ObjectLabel target : v.getObjectLabels()) {
          if (target.getKind() == Kind.FUNCTION) {
            addToMapSet(target2this, target, objlabel);
          } else {
            nonfunctions.add(Value.makeObject(target));
          }
        }
        if (v.isMaybePrimitive()) {
          nonfunctions.add(v.restrictToNotObject());
        }
      }
      // do calls to each target with the corresponding values of this
      for (Entry<ObjectLabel, Set<ObjectLabel>> me : target2this.entrySet()) {
        ObjectLabel target = me.getKey();
        Set<ObjectLabel> this_objs = me.getValue();
        FunctionCalls.callFunction(
            new OrdinaryCallInfo(n, state) {

              @Override
              public Value getFunctionValue() {
                return Value.makeObject(target);
              }

              @Override
              public Set<ObjectLabel> prepareThis(State caller_state, State callee_state) {
                return this_objs;
              }
            },
            state,
            c);
      }
      // also model calls to non-function values
      FunctionCalls.callFunction(
          new OrdinaryCallInfo(n, state) {

            @Override
            public Value getFunctionValue() {
              return Value.join(nonfunctions);
            }

            @Override
            public Set<ObjectLabel> prepareThis(State caller_state, State callee_state) {
              return Collections.emptySet();
            }
          },
          state,
          c);
    }
  }
Пример #13
0
 /** 11.2.1 assignment with right-hand-side property accessor. */
 @Override
 public void visit(ReadPropertyNode n, State state) {
   // get the base value, coerce with ToObject
   Value baseval = state.readRegister(n.getBaseRegister());
   baseval = UnknownValueResolver.getRealValue(baseval, state);
   m.visitPropertyAccess(n, baseval);
   Set<ObjectLabel> objlabels = Conversion.toObjectLabels(state, n, baseval, c);
   if (objlabels.isEmpty() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   state.writeRegister(
       n.getBaseRegister(),
       Value.makeObject(objlabels)); // if null/undefined, an exception would have been thrown via
   // toObjectLabels
   // get the property name value, separate the undefined/null/NaN components, coerce with ToString
   Value propertyval;
   int propertyreg;
   if (n.isPropertyFixed()) {
     propertyreg = AbstractNode.NO_VALUE;
     propertyval = Value.makeStr(n.getPropertyString());
   } else {
     propertyreg = n.getPropertyRegister();
     propertyval = state.readRegister(propertyreg);
     propertyval = UnknownValueResolver.getRealValue(propertyval, state);
   }
   boolean maybe_undef = propertyval.isMaybeUndef();
   boolean maybe_null = propertyval.isMaybeNull();
   boolean maybe_nan = propertyval.isMaybeNaN();
   propertyval = propertyval.restrictToNotNullNotUndef().restrictToNotNaN();
   Str propertystr = Conversion.toString(propertyval, propertyreg, c);
   // read the object property value, as fixed property name or unknown property name, and
   // separately for "undefined"/"null"/"NaN"
   Value v;
   boolean read_undefined = false;
   boolean read_null = false;
   boolean read_nan = false;
   if (propertystr.isMaybeSingleStr()) {
     String propertyname = propertystr.getStr();
     m.visitReadProperty(n, objlabels, propertystr, maybe_undef || maybe_null || maybe_nan, state);
     v = state.readPropertyValue(objlabels, propertyname);
     m.visitPropertyRead(n, objlabels, propertystr, state, true);
   } else if (!propertystr.isNotStr()) {
     m.visitReadProperty(n, objlabels, propertystr, true, state);
     m.visitPropertyRead(n, objlabels, propertystr, state, true);
     v = state.readPropertyValue(objlabels, propertystr);
     read_undefined = propertystr.isMaybeStr("undefined");
     read_null = propertystr.isMaybeStr("null");
     read_nan = propertystr.isMaybeStr("NaN");
   } else v = Value.makeNone();
   if (maybe_undef && !read_undefined) {
     m.visitReadProperty(n, objlabels, Value.makeTemporaryStr("undefined"), true, state);
     v = UnknownValueResolver.join(v, state.readPropertyValue(objlabels, "undefined"), state);
   }
   if (maybe_null && !read_null) {
     m.visitReadProperty(n, objlabels, Value.makeTemporaryStr("null"), true, state);
     v = UnknownValueResolver.join(v, state.readPropertyValue(objlabels, "null"), state);
   }
   if (maybe_nan && !read_nan) {
     m.visitReadProperty(n, objlabels, Value.makeTemporaryStr("NaN"), true, state);
     v = UnknownValueResolver.join(v, state.readPropertyValue(objlabels, "NaN"), state);
   }
   // remove all the TAJS hooks, which are spurious if accessed through a dynamic property
   if (!n.isPropertyFixed()) {
     v = JSGlobal.removeTAJSSpecificFunctions(v);
   }
   m.visitVariableOrProperty(
       n.getPropertyString(), n.getSourceLocation(), v, state.getContext(), state);
   m.visitRead(n, v, state);
   if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   // store the resulting value
   if (n.getResultRegister() != AbstractNode.NO_VALUE)
     state.writeRegister(n.getResultRegister(), v);
 }
Пример #14
0
 /** 11.13 and 11.5/6/7/8 assignment with binary operator. */
 @Override
 public void visit(BinaryOperatorNode n, State state) {
   Value arg1 = state.readRegister(n.getArg1Register());
   Value arg2 = state.readRegister(n.getArg2Register());
   arg1 = UnknownValueResolver.getRealValue(arg1, state);
   arg2 = UnknownValueResolver.getRealValue(arg2, state);
   Value v;
   switch (n.getOperator()) {
     case ADD:
       v =
           Operators.add(
               arg1,
               n.getArg1Register(),
               arg2,
               n.getArg2Register(),
               c); // TODO: test07.js could improve messages if keeping conversions of the two args
       // separate
       break;
     case AND:
       v = Operators.and(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case DIV:
       v = Operators.div(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case EQ:
       v = Operators.eq(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case GE:
       v = Operators.ge(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case GT:
       v = Operators.gt(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case IN:
       v = Operators.in(state, arg1, n.getArg1Register(), arg2, c);
       break;
     case INSTANCEOF:
       v = Operators.instof(state, arg1, arg2, c);
       break;
     case LE:
       v = Operators.le(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case LT:
       v = Operators.lt(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case MUL:
       v = Operators.mul(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case NE:
       v = Operators.neq(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case OR:
       v = Operators.or(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case REM:
       v = Operators.rem(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case SEQ:
       v = Operators.stricteq(arg1, arg2, c);
       break;
     case SHL:
       v = Operators.shl(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case SHR:
       v = Operators.shr(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case SNE:
       v = Operators.strictneq(arg1, arg2, c);
       break;
     case SUB:
       v = Operators.sub(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case USHR:
       v = Operators.ushr(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     case XOR:
       v = Operators.xor(arg1, n.getArg1Register(), arg2, n.getArg2Register(), c);
       break;
     default:
       throw new AnalysisException();
   }
   if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) {
     state.setToNone();
     return;
   }
   if (n.getResultRegister() != AbstractNode.NO_VALUE)
     state.writeRegister(n.getResultRegister(), v);
 }