Example #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;
}
Example #2
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->toFallbackStub()->state().hasFailures()) {
      return MCompare::Compare_Unknown;
    }
  }

  MCompare::CompareType first_type =
      ParseCacheIRStubForCompareType(first->toCacheIR_Regular());
  if (!second) {
    return first_type;
  }

  MCompare::CompareType second_type =
      ParseCacheIRStubForCompareType(second->toCacheIR_Regular());

  if (first_type == MCompare::Compare_Unknown ||
      second_type == MCompare::Compare_Unknown) {
    return MCompare::Compare_Unknown;
  }

  if (first_type == second_type) {
    return first_type;
  }

  return CompatibleType(first_type, second_type);
}
Example #3
0
bool
BaselineInspector::instanceOfData(jsbytecode* pc, Shape** shape, uint32_t* slot,
                                  JSObject** prototypeObject)
{
    MOZ_ASSERT(*pc == JSOP_INSTANCEOF);

    if (!hasBaselineScript())
        return false;

    const ICEntry& entry = icEntryFromPC(pc);

    ICStub* stub = entry.firstStub();
    if (!stub->isInstanceOf_Function() ||
        !stub->next()->isInstanceOf_Fallback() ||
        stub->next()->toInstanceOf_Fallback()->hadUnoptimizableAccess())
    {
        return false;
    }

    ICInstanceOf_Function* optStub = stub->toInstanceOf_Function();
    *shape = optStub->shape();
    *prototypeObject = optStub->prototypeObject();
    *slot = optStub->slot();

    if (IsInsideNursery(*prototypeObject))
        return false;

    return true;
}
Example #4
0
bool BaselineInspector::instanceOfData(jsbytecode* pc, Shape** shape,
                                       uint32_t* slot,
                                       JSObject** prototypeObject) {
  MOZ_ASSERT(*pc == JSOP_INSTANCEOF);
  if (!hasICScript()) {
    return false;
  }

  const ICEntry& entry = icEntryFromPC(pc);
  ICStub* firstStub = entry.firstStub();

  // Ensure singleton instanceof stub
  if (!firstStub->next() || !firstStub->isCacheIR_Regular() ||
      !firstStub->next()->isInstanceOf_Fallback() ||
      firstStub->next()->toInstanceOf_Fallback()->state().hasFailures()) {
    return false;
  }

  ICCacheIR_Regular* stub = entry.firstStub()->toCacheIR_Regular();
  CacheIRReader reader(stub->stubInfo());

  ObjOperandId rhsId = ObjOperandId(1);
  ObjOperandId resId = ObjOperandId(2);

  if (!reader.matchOp(CacheOp::GuardIsObject, rhsId)) {
    return false;
  }

  if (!reader.matchOp(CacheOp::GuardShape, rhsId)) {
    return false;
  }

  *shape = stub->stubInfo()->getStubField<Shape*>(stub, reader.stubOffset());

  if (!reader.matchOp(CacheOp::LoadObject, resId)) {
    return false;
  }

  *prototypeObject = stub->stubInfo()
                         ->getStubField<JSObject*>(stub, reader.stubOffset())
                         .get();

  if (IsInsideNursery(*prototypeObject)) {
    return false;
  }

  if (!reader.matchOp(CacheOp::GuardFunctionPrototype, rhsId)) {
    return false;
  }

  reader.skip();  // Skip over the protoID;

  *slot = stub->stubInfo()->getStubRawWord(stub, reader.stubOffset());

  return true;
}
bool
BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, Vector<Shape *> &shapes)
{
    // Return a list of shapes seen by the baseline IC for the current op.
    // An empty list indicates no shapes are known, or there was an uncacheable
    // access.
    JS_ASSERT(shapes.empty());

    if (!hasBaselineScript())
        return true;

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

    ICStub *stub = entry.firstStub();
    while (stub->next()) {
        Shape *shape;
        if (stub->isGetProp_Native()) {
            shape = stub->toGetProp_Native()->shape();
        } else if (stub->isSetProp_Native()) {
            shape = stub->toSetProp_Native()->shape();
        } else {
            shapes.clear();
            return true;
        }

        // Don't add the same shape twice (this can happen if there are multiple
        // SetProp_Native stubs with different TypeObject's).
        bool found = false;
        for (size_t i = 0; i < shapes.length(); i++) {
            if (shapes[i] == shape) {
                found = true;
                break;
            }
        }

        if (!found && !shapes.append(shape))
            return false;

        stub = stub->next();
    }

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

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

    return true;
}
Example #6
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;
}
Example #7
0
RawShape
BaselineInspector::maybeMonomorphicShapeForPropertyOp(jsbytecode *pc)
{
    if (!hasBaselineScript())
        return NULL;

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

    ICStub *stub = entry.firstStub();
    ICStub *next = stub->next();

    if (!next || !next->isFallback())
        return NULL;

    if (stub->isGetProp_Native()) {
        JS_ASSERT(next->isGetProp_Fallback());
        if (next->toGetProp_Fallback()->hadUnoptimizableAccess())
            return NULL;
        return stub->toGetProp_Native()->shape();
    }

    if (stub->isSetProp_Native()) {
        JS_ASSERT(next->isSetProp_Fallback());
        if (next->toSetProp_Fallback()->hadUnoptimizableAccess())
            return NULL;
        return stub->toSetProp_Native()->shape();
    }

    return NULL;
}
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;
}
Example #9
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;
}
Example #10
0
bool BaselineInspector::commonSetPropFunction(
    jsbytecode* pc, JSObject** holder, Shape** holderShape,
    JSFunction** commonSetter, bool* isOwnProperty, ReceiverVector& receivers,
    ObjectGroupVector& convertUnboxedGroups) {
  if (!hasICScript()) {
    return false;
  }

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

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

  for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
    if (stub->isCacheIR_Updated()) {
      if (!AddCacheIRSetPropFunction(stub->toCacheIR_Updated(), holder,
                                     holderShape, commonSetter, isOwnProperty,
                                     receivers, convertUnboxedGroups)) {
        return false;
      }
    } else if (!stub->isFallback() ||
               stub->toFallbackStub()->state().hasFailures()) {
      // We have an unoptimizable access, so don't try to optimize.
      return false;
    }
  }

  if (!*commonSetter) {
    return false;
  }

  MOZ_ASSERT(*isOwnProperty == !*holder);
  return true;
}
Example #11
0
JSObject *
BaselineInspector::commonSetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonSetter)
{
    if (!hasBaselineScript())
        return nullptr;

    const ICEntry &entry = icEntryFromPC(pc);
    JSObject *holder = nullptr;
    Shape *holderShape = nullptr;
    JSFunction *setter = nullptr;
    for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
            ICSetPropCallSetter *nstub = static_cast<ICSetPropCallSetter *>(stub);
            if (!holder) {
                holder = nstub->holder();
                holderShape = nstub->holderShape();
                setter = nstub->setter();
            } else if (nstub->holderShape() != holderShape) {
                return nullptr;
            } else {
                MOZ_ASSERT(setter == nstub->setter());
            }
        } else if (stub->isSetProp_Fallback() &&
                   stub->toSetProp_Fallback()->hadUnoptimizableAccess())
        {
            // We have an unoptimizable access, so don't try to optimize.
            return nullptr;
        }
    }
    *lastProperty = holderShape;
    *commonSetter = setter;
    return holder;
}
Example #12
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;
}
Example #13
0
bool
BaselineInspector::commonGetPropFunction(jsbytecode* pc, 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());

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

    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isGetProp_CallScripted() ||
                stub->isGetProp_CallNative() ||
                stub->isGetProp_CallNativeGlobal())
        {
            ICGetPropCallGetter* nstub = static_cast<ICGetPropCallGetter*>(stub);
            bool isOwn = nstub->isOwnGetter();
            if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers, convertUnboxedGroups))
                return false;

            if (!*holder) {
                *holder = nstub->holder();
                *holderShape = nstub->holderShape();
                *commonGetter = nstub->getter();
                *globalShape = GlobalShapeForGetPropFunction(nstub);
                *isOwnProperty = isOwn;
            } else if (nstub->holderShape() != *holderShape ||
                       GlobalShapeForGetPropFunction(nstub) != *globalShape ||
                       isOwn != *isOwnProperty)
            {
                return false;
            } else {
                MOZ_ASSERT(*commonGetter == nstub->getter());
            }
        } 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 (!*holder)
        return false;

    MOZ_ASSERT(*isOwnProperty == (receivers.empty() && convertUnboxedGroups.empty()));
    return true;
}
Example #14
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;
}
bool
BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **psecond)
{
    if (!hasBaselineScript())
        return false;

    const ICEntry &entry = icEntryFromPC(pc);

    ICStub *stub = entry.firstStub();
    ICStub *next = stub->next();
    ICStub *after = next ? next->next() : NULL;

    if (!after || !after->isFallback())
        return false;

    *pfirst = stub;
    *psecond = next;
    return true;
}
bool
SetElemICInspector::sawTypedArrayWrite() const
{
    if (!icEntry_)
        return false;

    // Check for a SetElem_TypedArray stub.
    for (ICStub *stub = icEntry_->firstStub(); stub; stub = stub->next()) {
        if (stub->isSetElem_TypedArray())
            return true;
    }
    return false;
}
bool
SetElemICInspector::sawDenseWrite() const
{
    if (!icEntry_)
        return false;

    // Check for a SetElem_DenseAdd or SetElem_Dense stub.
    for (ICStub *stub = icEntry_->firstStub(); stub; stub = stub->next()) {
        if (stub->isSetElem_DenseAdd() || stub->isSetElem_Dense())
            return true;
    }
    return false;
}
JSObject *
BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native)
{
    if (!hasBaselineScript())
        return nullptr;

    const ICEntry &entry = icEntryFromPC(pc);
    for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isCall_Native() && stub->toCall_Native()->callee()->native() == native)
            return stub->toCall_Native()->templateObject();
    }

    return nullptr;
}
Example #19
0
JSObject*
BaselineInspector::getTemplateObjectForClassHook(jsbytecode* pc, const Class* clasp)
{
    if (!hasBaselineScript())
        return nullptr;

    const ICEntry& entry = icEntryFromPC(pc);
    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isCall_ClassHook() && stub->toCall_ClassHook()->clasp() == clasp)
            return stub->toCall_ClassHook()->templateObject();
    }

    return nullptr;
}
JSObject *
BaselineInspector::commonSetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonSetter)
{
    const ICEntry &entry = icEntryFromPC(pc);
    for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
            ICSetPropCallSetter *nstub = static_cast<ICSetPropCallSetter *>(stub);
            *lastProperty = nstub->holderShape();
            *commonSetter = nstub->setter();
            return nstub->holder();
        }
    }
    return nullptr;
}
bool
SetElemICInspector::sawOOBTypedArrayWrite() const
{
    if (!icEntry_)
        return false;

    // Check for SetElem_TypedArray stubs with expectOutOfBounds set.
    for (ICStub *stub = icEntry_->firstStub(); stub; stub = stub->next()) {
        if (!stub->isSetElem_TypedArray())
            continue;
        if (stub->toSetElem_TypedArray()->expectOutOfBounds())
            return true;
    }
    return false;
}
ICStub *
BaselineInspector::monomorphicStub(jsbytecode *pc)
{
    if (!hasBaselineScript())
        return NULL;

    const ICEntry &entry = icEntryFromPC(pc);

    ICStub *stub = entry.firstStub();
    ICStub *next = stub->next();

    if (!next || !next->isFallback())
        return NULL;

    return stub;
}
Example #23
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;
}
Example #24
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;
}
Example #25
0
JSObject*
BaselineInspector::getTemplateObjectForSimdCtor(jsbytecode* pc, SimdType simdType)
{
    if (!hasBaselineScript())
        return nullptr;

    const ICEntry& entry = icEntryFromPC(pc);
    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isCall_ClassHook() && stub->toCall_ClassHook()->clasp() == &SimdTypeDescr::class_) {
            JSObject* templateObj = stub->toCall_ClassHook()->templateObject();
            InlineTypedObject& typedObj = templateObj->as<InlineTypedObject>();
            if (typedObj.typeDescr().as<SimdTypeDescr>().type() == simdType)
                return templateObj;
        }
    }

    return nullptr;
}
Example #26
0
bool
BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
                                         JSFunction** commonSetter, bool* isOwnProperty,
                                         ReceiverVector& receivers,
                                         ObjectGroupVector& convertUnboxedGroups)
{
    if (!hasBaselineScript())
        return false;

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

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

    for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
        if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
            ICSetPropCallSetter* nstub = static_cast<ICSetPropCallSetter*>(stub);
            if (!AddReceiver(nstub->guard(), receivers, convertUnboxedGroups))
                return false;

            if (!*holder) {
                *holder = nstub->holder();
                *holderShape = nstub->holderShape();
                *commonSetter = nstub->setter();
                *isOwnProperty = false;
            } else if (nstub->holderShape() != *holderShape) {
                return false;
            } else {
                MOZ_ASSERT(*commonSetter == nstub->setter());
            }
        } else if (!stub->isSetProp_Fallback() ||
                   stub->toSetProp_Fallback()->hadUnoptimizableAccess())
        {
            // We have an unoptimizable access, so don't try to optimize.
            return false;
        }
    }

    if (!*holder)
        return false;

    return true;
}
Example #27
0
JSFunction*
BaselineInspector::getSingleCallee(jsbytecode* pc)
{
    MOZ_ASSERT(*pc == JSOP_NEW);

    if (!hasBaselineScript())
        return nullptr;

    const ICEntry& entry = icEntryFromPC(pc);
    ICStub* stub = entry.firstStub();

    if (entry.fallbackStub()->toCall_Fallback()->hadUnoptimizableCall())
        return nullptr;

    if (!stub->isCall_Scripted() || stub->next() != entry.fallbackStub())
        return nullptr;

    return stub->toCall_Scripted()->callee();
}
bool
SetElemICInspector::sawOOBDenseWrite() const
{
    if (!icEntry_)
        return false;

    // Check for a SetElem_DenseAdd stub.
    for (ICStub *stub = icEntry_->firstStub(); stub; stub = stub->next()) {
        if (stub->isSetElem_DenseAdd())
            return true;
    }

    // Check for a write hole bit on the SetElem_Fallback stub.
    ICStub *stub = icEntry_->fallbackStub();
    if (stub->isSetElem_Fallback())
        return stub->toSetElem_Fallback()->hasArrayWriteHole();

    return false;
}
Example #29
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;
}
Example #30
0
JSFunction* BaselineInspector::getSingleCallee(jsbytecode* pc) {
  MOZ_ASSERT(*pc == JSOP_NEW);

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

  const ICEntry& entry = icEntryFromPC(pc);
  ICStub* stub = entry.firstStub();

  if (entry.fallbackStub()->state().hasFailures()) {
    return nullptr;
  }

  if (!stub->isCall_Scripted() || stub->next() != entry.fallbackStub()) {
    return nullptr;
  }

  return stub->toCall_Scripted()->callee();
}