Exemple #1
0
bool
BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers,
                                          ObjectGroupVector& convertUnboxedGroups)
{
    // Return a list of the receivers seen by the baseline IC for the current
    // op. Empty lists indicate no receivers are known, or there was an
    // uncacheable access. convertUnboxedGroups is used for unboxed object
    // groups which have been seen, but have had instances converted to native
    // objects and should be eagerly converted by Ion.
    MOZ_ASSERT(receivers.empty());
    MOZ_ASSERT(convertUnboxedGroups.empty());

    if (!hasBaselineScript())
        return true;

    MOZ_ASSERT(isValidPC(pc));
    const ICEntry& entry = icEntryFromPC(pc);

    ICStub* stub = entry.firstStub();
    while (stub->next()) {
        ReceiverGuard receiver;
        if (stub->isCacheIR_Monitored()) {
            if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(), &receiver) &&
                !GetCacheIRReceiverForUnboxedProperty(stub->toCacheIR_Monitored(), &receiver))
            {
                receivers.clear();
                return true;
            }
        } else if (stub->isCacheIR_Updated()) {
            if (!GetCacheIRReceiverForNativeSetSlot(stub->toCacheIR_Updated(), &receiver) &&
                !GetCacheIRReceiverForUnboxedProperty(stub->toCacheIR_Updated(), &receiver))
            {
                receivers.clear();
                return true;
            }
        } else {
            receivers.clear();
            return true;
        }

        if (!AddReceiver(receiver, receivers, convertUnboxedGroups))
            return false;

        stub = stub->next();
    }

    if (stub->isGetProp_Fallback()) {
        if (stub->toGetProp_Fallback()->hadUnoptimizableAccess())
            receivers.clear();
    } else {
        if (stub->toSetProp_Fallback()->hadUnoptimizableAccess())
            receivers.clear();
    }

    // Don't inline if there are more than 5 receivers.
    if (receivers.length() > 5)
        receivers.clear();

    return true;
}
Exemple #2
0
MIRType BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc) {
  if (!hasICScript()) {
    return MIRType::Value;
  }

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

  for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
    MIRType stubType = MIRType::None;
    if (stub->isCacheIR_Monitored()) {
      stubType = GetCacheIRExpectedInputType(stub->toCacheIR_Monitored());
      if (stubType == MIRType::Value) {
        return MIRType::Value;
      }
    } else if (stub->isGetElem_Fallback() || stub->isGetProp_Fallback()) {
      // If we have an unoptimizable access, don't try to optimize.
      if (stub->toFallbackStub()->state().hasFailures()) {
        return MIRType::Value;
      }
    } else {
      MOZ_CRASH("Unexpected stub");
    }

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

  return (type == MIRType::None) ? MIRType::Value : type;
}
Exemple #3
0
bool
BaselineInspector::megamorphicGetterSetterFunction(jsbytecode* pc, bool isGetter,
                                                   JSFunction** getterOrSetter)
{
    if (!hasBaselineScript())
        return false;

    *getterOrSetter = nullptr;
    const ICEntry& entry = icEntryFromPC(pc);

    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isCacheIR_Monitored()) {
            MOZ_ASSERT(isGetter);
            JSFunction* getter =
                GetMegamorphicGetterSetterFunction(stub,
                                                   stub->toCacheIR_Monitored()->stubInfo(),
                                                   isGetter);
            if (!getter || (*getterOrSetter && *getterOrSetter != getter))
                return false;
            *getterOrSetter = getter;
            continue;
        }
        if (stub->isCacheIR_Updated()) {
            MOZ_ASSERT(!isGetter);
            JSFunction* setter =
                GetMegamorphicGetterSetterFunction(stub,
                                                   stub->toCacheIR_Updated()->stubInfo(),
                                                   isGetter);
            if (!setter || (*getterOrSetter && *getterOrSetter != setter))
                return false;
            *getterOrSetter = setter;
            continue;
        }
        if (stub->isGetProp_Fallback()) {
            if (stub->toGetProp_Fallback()->hadUnoptimizableAccess())
                return false;
            if (stub->toGetProp_Fallback()->state().mode() != ICState::Mode::Megamorphic)
                return false;
            continue;
        }
        if (stub->isSetProp_Fallback()) {
            if (stub->toSetProp_Fallback()->hadUnoptimizableAccess())
                return false;
            if (stub->toSetProp_Fallback()->state().mode() != ICState::Mode::Megamorphic)
                return false;
            continue;
        }

        return false;
    }

    if (!*getterOrSetter)
        return false;

    return true;
}
Exemple #4
0
bool BaselineInspector::maybeInfoForProtoReadSlot(
    jsbytecode* pc, ReceiverVector& receivers,
    ObjectGroupVector& convertUnboxedGroups, JSObject** holder) {
  // This is like maybeInfoForPropertyOp, but for when the property exists on
  // the prototype.

  MOZ_ASSERT(receivers.empty());
  MOZ_ASSERT(convertUnboxedGroups.empty());
  MOZ_ASSERT(!*holder);

  if (!hasICScript()) {
    return true;
  }

  MOZ_ASSERT(isValidPC(pc));
  const ICEntry& entry = icEntryFromPC(pc);

  ICStub* stub = entry.firstStub();
  while (stub->next()) {
    ReceiverGuard receiver;
    if (stub->isCacheIR_Monitored()) {
      if (!GetCacheIRReceiverForProtoReadSlot(stub->toCacheIR_Monitored(),
                                              &receiver, holder)) {
        receivers.clear();
        return true;
      }
    } else {
      receivers.clear();
      return true;
    }

    if (!AddReceiver(receiver, receivers, convertUnboxedGroups)) {
      return false;
    }

    stub = stub->next();
  }

  if (stub->toFallbackStub()->state().hasFailures()) {
    receivers.clear();
  }

  // Don't inline if there are more than 5 receivers.
  if (receivers.length() > 5) {
    receivers.clear();
  }

  MOZ_ASSERT_IF(!receivers.empty(), *holder);
  return true;
}
Exemple #5
0
bool
BaselineInspector::commonGetPropFunction(jsbytecode* pc, bool innerized,
                                         JSObject** holder, Shape** holderShape,
                                         JSFunction** commonGetter, Shape** globalShape,
                                         bool* isOwnProperty,
                                         ReceiverVector& receivers,
                                         ObjectGroupVector& convertUnboxedGroups)
{
    if (!hasBaselineScript())
        return false;

    MOZ_ASSERT(receivers.empty());
    MOZ_ASSERT(convertUnboxedGroups.empty());

    *globalShape = nullptr;
    *commonGetter = nullptr;
    const ICEntry& entry = icEntryFromPC(pc);

    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isCacheIR_Monitored()) {
            if (!AddCacheIRGetPropFunction(stub->toCacheIR_Monitored(), innerized,
                                           holder, holderShape,
                                           commonGetter, globalShape, isOwnProperty, receivers,
                                           convertUnboxedGroups, script))
            {
                return false;
            }
        } else if (stub->isGetProp_Fallback()) {
            // If we have an unoptimizable access, don't try to optimize.
            if (stub->toGetProp_Fallback()->hadUnoptimizableAccess())
                return false;
        } else if (stub->isGetName_Fallback()) {
            if (stub->toGetName_Fallback()->hadUnoptimizableAccess())
                return false;
        } else {
            return false;
        }
    }

    if (!*commonGetter)
        return false;

    MOZ_ASSERT(*isOwnProperty == !*holder);
    MOZ_ASSERT(*isOwnProperty == (receivers.empty() && convertUnboxedGroups.empty()));
    return true;
}
Exemple #6
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;
}
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_CallScripted:
        case ICStub::GetProp_CallNative:
        case ICStub::GetProp_CallDOMProxyNative:
        case ICStub::GetProp_CallDOMProxyWithGenerationNative:
        case ICStub::GetProp_DOMProxyShadowed:
        case ICStub::GetElem_NativeSlotName:
        case ICStub::GetElem_NativeSlotSymbol:
        case ICStub::GetElem_NativePrototypeSlotName:
        case ICStub::GetElem_NativePrototypeSlotSymbol:
        case ICStub::GetElem_NativePrototypeCallNativeName:
        case ICStub::GetElem_NativePrototypeCallNativeSymbol:
        case ICStub::GetElem_NativePrototypeCallScriptedName:
        case ICStub::GetElem_NativePrototypeCallScriptedSymbol:
        case ICStub::GetElem_UnboxedPropertyName:
        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;

        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;
}