예제 #1
0
bool BaselineInspector::megamorphicGetterSetterFunction(
    jsbytecode* pc, bool isGetter, JSFunction** getterOrSetter) {
  if (!hasICScript()) {
    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->isFallback()) {
      if (stub->toFallbackStub()->state().hasFailures()) {
        return false;
      }
      if (stub->toFallbackStub()->state().mode() !=
          ICState::Mode::Megamorphic) {
        return false;
      }
      continue;
    }

    return false;
  }

  if (!*getterOrSetter) {
    return false;
  }

  return true;
}
예제 #2
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 (!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 (!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->toFallbackStub()->state().hasFailures()) {
    receivers.clear();
  }

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

  return true;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
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;
}