MCompare::CompareType
BaselineInspector::expectedCompareType(jsbytecode *pc)
{
    ICStub *first = monomorphicStub(pc), *second = NULL;
    if (!first && !dimorphicStub(pc, &first, &second))
        return MCompare::Compare_Unknown;

    if (CanUseInt32Compare(first->kind()) && (!second || CanUseInt32Compare(second->kind())))
        return MCompare::Compare_Int32;

    if (CanUseDoubleCompare(first->kind()) && (!second || CanUseDoubleCompare(second->kind()))) {
        ICCompare_NumberWithUndefined *coerce =
            first->isCompare_NumberWithUndefined()
            ? first->toCompare_NumberWithUndefined()
            : (second && second->isCompare_NumberWithUndefined())
              ? second->toCompare_NumberWithUndefined()
              : NULL;
        if (coerce) {
            return coerce->lhsIsUndefined()
                   ? MCompare::Compare_DoubleMaybeCoerceLHS
                   : MCompare::Compare_DoubleMaybeCoerceRHS;
        }
        return MCompare::Compare_Double;
    }

    return MCompare::Compare_Unknown;
}
MIRType
BaselineInspector::expectedResultType(jsbytecode *pc)
{
    // Look at the IC entries for this op to guess what type it will produce,
    // returning MIRType_None otherwise.

    ICStub *stub = monomorphicStub(pc);
    if (!stub)
        return MIRType_None;

    switch (stub->kind()) {
      case ICStub::BinaryArith_Int32:
        if (stub->toBinaryArith_Int32()->allowDouble())
            return MIRType_Double;
        return MIRType_Int32;
      case ICStub::BinaryArith_BooleanWithInt32:
      case ICStub::UnaryArith_Int32:
      case ICStub::BinaryArith_DoubleWithInt32:
        return MIRType_Int32;
      case ICStub::BinaryArith_Double:
      case ICStub::UnaryArith_Double:
        return MIRType_Double;
      case ICStub::BinaryArith_StringConcat:
      case ICStub::BinaryArith_StringObjectConcat:
        return MIRType_String;
      default:
        return MIRType_None;
    }
}
示例#3
0
bool BaselineInspector::isOptimizableConstStringSplit(jsbytecode* pc,
                                                      JSString** strOut,
                                                      JSString** sepOut,
                                                      ArrayObject** objOut) {
  if (!hasICScript()) {
    return false;
  }

  const ICEntry& entry = icEntryFromPC(pc);

  // If ConstStringSplit stub is attached, must have only one stub attached.
  if (entry.fallbackStub()->numOptimizedStubs() != 1) {
    return false;
  }

  ICStub* stub = entry.firstStub();
  if (stub->kind() != ICStub::Call_ConstStringSplit) {
    return false;
  }

  *strOut = stub->toCall_ConstStringSplit()->expectedStr();
  *sepOut = stub->toCall_ConstStringSplit()->expectedSep();
  *objOut = stub->toCall_ConstStringSplit()->templateObject();
  return true;
}
JSObject *
BaselineInspector::getTemplateObject(jsbytecode *pc)
{
    if (!hasBaselineScript())
        return nullptr;

    const ICEntry &entry = icEntryFromPC(pc);
    for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
        switch (stub->kind()) {
          case ICStub::NewArray_Fallback:
            return stub->toNewArray_Fallback()->templateObject();
          case ICStub::NewObject_Fallback:
            return stub->toNewObject_Fallback()->templateObject();
          case ICStub::Rest_Fallback:
            return stub->toRest_Fallback()->templateObject();
          case ICStub::Call_Scripted:
            if (JSObject *obj = stub->toCall_Scripted()->templateObject())
                return obj;
            break;
          default:
            break;
        }
    }

    return nullptr;
}
示例#5
0
MIRType
BaselineInspector::expectedResultType(jsbytecode* pc)
{
    // Look at the IC entries for this op to guess what type it will produce,
    // returning MIRType::None otherwise. Note that IonBuilder may call this
    // for bytecode ops that are unreachable and don't have a Baseline IC, see
    // comment in monomorphicStub.

    ICStub* stub = monomorphicStub(pc);
    if (!stub)
        return MIRType::None;

    switch (stub->kind()) {
      case ICStub::BinaryArith_Int32:
        if (stub->toBinaryArith_Int32()->allowDouble())
            return MIRType::Double;
        return MIRType::Int32;
      case ICStub::BinaryArith_BooleanWithInt32:
      case ICStub::UnaryArith_Int32:
      case ICStub::BinaryArith_DoubleWithInt32:
        return MIRType::Int32;
      case ICStub::BinaryArith_Double:
      case ICStub::UnaryArith_Double:
        return MIRType::Double;
      case ICStub::BinaryArith_StringConcat:
      case ICStub::BinaryArith_StringObjectConcat:
        return MIRType::String;
      default:
        return MIRType::None;
    }
}
示例#6
0
MCompare::CompareType
BaselineInspector::expectedCompareType(jsbytecode* pc)
{
    ICStub* first = monomorphicStub(pc);
    ICStub* second = nullptr;
    if (!first && !dimorphicStub(pc, &first, &second))
        return MCompare::Compare_Unknown;

    if (ICStub* fallback = second ? second->next() : first->next()) {
        MOZ_ASSERT(fallback->isFallback());
        if (fallback->toCompare_Fallback()->hadUnoptimizableAccess())
            return MCompare::Compare_Unknown;
    }

    if (CanUseInt32Compare(first->kind()) && (!second || CanUseInt32Compare(second->kind()))) {
        ICCompare_Int32WithBoolean* coerce =
            first->isCompare_Int32WithBoolean()
            ? first->toCompare_Int32WithBoolean()
            : ((second && second->isCompare_Int32WithBoolean())
               ? second->toCompare_Int32WithBoolean()
               : nullptr);
        if (coerce) {
            return coerce->lhsIsInt32()
                   ? MCompare::Compare_Int32MaybeCoerceRHS
                   : MCompare::Compare_Int32MaybeCoerceLHS;
        }
        return MCompare::Compare_Int32;
    }

    if (CanUseDoubleCompare(first->kind()) && (!second || CanUseDoubleCompare(second->kind()))) {
        ICCompare_NumberWithUndefined* coerce =
            first->isCompare_NumberWithUndefined()
            ? first->toCompare_NumberWithUndefined()
            : (second && second->isCompare_NumberWithUndefined())
              ? second->toCompare_NumberWithUndefined()
              : nullptr;
        if (coerce) {
            return coerce->lhsIsUndefined()
                   ? MCompare::Compare_DoubleMaybeCoerceLHS
                   : MCompare::Compare_DoubleMaybeCoerceRHS;
        }
        return MCompare::Compare_Double;
    }

    return MCompare::Compare_Unknown;
}
示例#7
0
ObjectGroup* BaselineInspector::getTemplateObjectGroup(jsbytecode* pc) {
  if (!hasICScript()) {
    return nullptr;
  }

  const ICEntry& entry = icEntryFromPC(pc);
  for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
    switch (stub->kind()) {
      case ICStub::NewArray_Fallback:
        return stub->toNewArray_Fallback()->templateGroup();
      default:
        break;
    }
  }

  return nullptr;
}
示例#8
0
MIRType BaselineInspector::expectedResultType(jsbytecode* pc) {
  // Look at the IC entries for this op to guess what type it will produce,
  // returning MIRType::None otherwise. Note that IonBuilder may call this
  // for bytecode ops that are unreachable and don't have a Baseline IC, see
  // comment in monomorphicStub.

  ICStub* stub = monomorphicStub(pc);
  if (!stub) {
    return MIRType::None;
  }

  switch (stub->kind()) {
    case ICStub::CacheIR_Regular:
      return ParseCacheIRStub(stub);
    default:
      return MIRType::None;
  }
}
示例#9
0
MIRType
BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
{
    if (!hasBaselineScript())
        return MIRType::Value;

    const ICEntry& entry = icEntryFromPC(pc);
    MIRType type = MIRType::None;

    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        MIRType stubType;
        switch (stub->kind()) {
          case ICStub::GetProp_Fallback:
            if (stub->toGetProp_Fallback()->hadUnoptimizableAccess())
                return MIRType::Value;
            continue;

          case ICStub::GetElem_Fallback:
            if (stub->toGetElem_Fallback()->hadUnoptimizableAccess())
                return MIRType::Value;
            continue;

          case ICStub::CacheIR_Monitored:
            stubType = GetCacheIRExpectedInputType(stub->toCacheIR_Monitored());
            if (stubType == MIRType::Value)
                return MIRType::Value;
            break;

          default:
            MOZ_CRASH("Unexpected stub");
        }

        if (type != MIRType::None) {
            if (type != stubType)
                return MIRType::Value;
        } else {
            type = stubType;
        }
    }

    return (type == MIRType::None) ? MIRType::Value : type;
}
示例#10
0
bool
BaselineInspector::isOptimizableCallStringSplit(jsbytecode* pc, JSString** stringOut, JSString** stringArg,
                                                JSObject** objOut)
{
    if (!hasBaselineScript())
        return false;

    const ICEntry& entry = icEntryFromPC(pc);

    // If StringSplit stub is attached, must have only one stub attached.
    if (entry.fallbackStub()->numOptimizedStubs() != 1)
        return false;

    ICStub* stub = entry.firstStub();
    if (stub->kind() != ICStub::Call_StringSplit)
        return false;

    *stringOut = stub->toCall_StringSplit()->expectedThis();
    *stringArg = stub->toCall_StringSplit()->expectedArg();
    *objOut = stub->toCall_StringSplit()->templateObject();
    return true;
}
示例#11
0
MIRType
BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
{
    if (!hasBaselineScript())
        return MIRType_Value;

    const ICEntry& entry = icEntryFromPC(pc);
    MIRType type = MIRType_None;

    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        MIRType stubType;
        switch (stub->kind()) {
          case ICStub::GetProp_Fallback:
            if (stub->toGetProp_Fallback()->hadUnoptimizableAccess())
                return MIRType_Value;
            continue;

          case ICStub::GetElem_Fallback:
            if (stub->toGetElem_Fallback()->hadUnoptimizableAccess())
                return MIRType_Value;
            continue;

          case ICStub::GetProp_Generic:
            return MIRType_Value;

          case ICStub::GetProp_ArgumentsLength:
          case ICStub::GetElem_Arguments:
            // Either an object or magic arguments.
            return MIRType_Value;

          case ICStub::GetProp_ArrayLength:
          case ICStub::GetProp_UnboxedArrayLength:
          case ICStub::GetProp_Native:
          case ICStub::GetProp_NativeDoesNotExist:
          case ICStub::GetProp_NativePrototype:
          case ICStub::GetProp_Unboxed:
          case ICStub::GetProp_TypedObject:
          case ICStub::GetProp_CallScripted:
          case ICStub::GetProp_CallNative:
          case ICStub::GetProp_CallDOMProxyNative:
          case ICStub::GetProp_CallDOMProxyWithGenerationNative:
          case ICStub::GetProp_DOMProxyShadowed:
          case ICStub::GetElem_NativeSlot:
          case ICStub::GetElem_NativePrototypeSlot:
          case ICStub::GetElem_NativePrototypeCallNative:
          case ICStub::GetElem_NativePrototypeCallScripted:
          case ICStub::GetElem_String:
          case ICStub::GetElem_Dense:
          case ICStub::GetElem_TypedArray:
          case ICStub::GetElem_UnboxedArray:
            stubType = MIRType_Object;
            break;

          case ICStub::GetProp_Primitive:
            stubType = MIRTypeFromValueType(stub->toGetProp_Primitive()->primitiveType());
            break;

          case ICStub::GetProp_StringLength:
            stubType = MIRType_String;
            break;

          default:
            MOZ_CRASH("Unexpected stub");
        }

        if (type != MIRType_None) {
            if (type != stubType)
                return MIRType_Value;
        } else {
            type = stubType;
        }
    }

    return (type == MIRType_None) ? MIRType_Value : type;
}