Esempio n. 1
0
bool
ArrayPushDense(JSContext *cx, HandleArrayObject obj, HandleValue v, uint32_t *length)
{
    if (MOZ_LIKELY(obj->lengthIsWritable())) {
        uint32_t idx = obj->length();
        NativeObject::EnsureDenseResult result = obj->ensureDenseElements(cx, idx, 1);
        if (result == NativeObject::ED_FAILED)
            return false;

        if (result == NativeObject::ED_OK) {
            obj->setDenseElement(idx, v);
            MOZ_ASSERT(idx < INT32_MAX);
            *length = idx + 1;
            obj->setLengthInt32(*length);
            return true;
        }
    }

    JS::AutoValueArray<3> argv(cx);
    argv[0].setUndefined();
    argv[1].setObject(*obj);
    argv[2].set(v);
    if (!js::array_push(cx, 1, argv.begin()))
        return false;

    *length = argv[0].toInt32();
    return true;
}
Esempio n. 2
0
bool
MapIteratorObject::next(JSContext* cx, Handle<MapIteratorObject*> mapIterator,
                        HandleArrayObject resultPairObj)
{
    MOZ_ASSERT(resultPairObj->getDenseInitializedLength() == 2);

    ValueMap::Range* range = MapIteratorObjectRange(mapIterator);
    if (!range || range->empty()) {
        js_delete(range);
        mapIterator->setReservedSlot(RangeSlot, PrivateValue(nullptr));
        return true;
    }
    switch (mapIterator->kind()) {
      case MapObject::Keys:
        resultPairObj->setDenseElementWithType(cx, 0, range->front().key.get());
        break;

      case MapObject::Values:
        resultPairObj->setDenseElementWithType(cx, 1, range->front().value);
        break;

      case MapObject::Entries: {
        resultPairObj->setDenseElementWithType(cx, 0, range->front().key.get());
        resultPairObj->setDenseElementWithType(cx, 1, range->front().value);
        break;
      }
    }
    range->popFront();
    return false;
}
Esempio n. 3
0
bool
SetIteratorObject::next(Handle<SetIteratorObject*> setIterator, HandleArrayObject resultObj,
                        JSContext* cx)
{
    // Check invariants for inlined _GetNextSetEntryForIterator.

    // The array should be tenured, so that post-barrier can be done simply.
    MOZ_ASSERT(resultObj->isTenured());

    // The array elements should be fixed.
    MOZ_ASSERT(resultObj->hasFixedElements());
    MOZ_ASSERT(resultObj->getDenseInitializedLength() == 1);
    MOZ_ASSERT(resultObj->getDenseCapacity() >= 1);

    ValueSet::Range* range = SetIteratorObjectRange(setIterator);
    if (!range || range->empty()) {
        js_delete(range);
        setIterator->setReservedSlot(RangeSlot, PrivateValue(nullptr));
        return true;
    }
    resultObj->setDenseElementWithType(cx, 0, range->front().get());
    range->popFront();
    return false;
}
Esempio n. 4
0
bool
MapIteratorObject::next(JSContext* cx, Handle<MapIteratorObject*> mapIterator,
                        HandleArrayObject resultPairObj)
{
    // Check invariants for inlined _GetNextMapEntryForIterator.

    // The array should be tenured, so that post-barrier can be done simply.
    MOZ_ASSERT(resultPairObj->isTenured());

    // The array elements should be fixed.
    MOZ_ASSERT(resultPairObj->hasFixedElements());
    MOZ_ASSERT(resultPairObj->getDenseInitializedLength() == 2);
    MOZ_ASSERT(resultPairObj->getDenseCapacity() >= 2);

    ValueMap::Range* range = MapIteratorObjectRange(mapIterator);
    if (!range || range->empty()) {
        js_delete(range);
        mapIterator->setReservedSlot(RangeSlot, PrivateValue(nullptr));
        return true;
    }
    switch (mapIterator->kind()) {
      case MapObject::Keys:
        resultPairObj->setDenseElementWithType(cx, 0, range->front().key.get());
        break;

      case MapObject::Values:
        resultPairObj->setDenseElementWithType(cx, 1, range->front().value);
        break;

      case MapObject::Entries: {
        resultPairObj->setDenseElementWithType(cx, 0, range->front().key.get());
        resultPairObj->setDenseElementWithType(cx, 1, range->front().value);
        break;
      }
    }
    range->popFront();
    return false;
}
Esempio n. 5
0
bool
js::ForOfPIC::Chain::tryOptimizeArray(JSContext *cx, HandleArrayObject array, bool *optimized)
{
    MOZ_ASSERT(optimized);

    *optimized = false;

    if (!initialized_) {
        // If PIC is not initialized, initialize it.
        if (!initialize(cx))
            return false;

    } else if (!disabled_ && !isArrayStateStillSane()) {
        // Otherwise, if array state is no longer sane, reinitialize.
        reset(cx);

        if (!initialize(cx))
            return false;
    }
    MOZ_ASSERT(initialized_);

    // If PIC is disabled, don't bother trying to optimize.
    if (disabled_)
        return true;

    // By the time we get here, we should have a sane array state to work with.
    MOZ_ASSERT(isArrayStateStillSane());

    // Check if stub already exists.
    ForOfPIC::Stub *stub = isArrayOptimized(&array->as<ArrayObject>());
    if (stub) {
        *optimized = true;
        return true;
    }

    // If the number of stubs is about to exceed the limit, throw away entire
    // existing cache before adding new stubs.  We shouldn't really have heavy
    // churn on these.
    if (numStubs() >= MAX_STUBS)
        eraseChain();

    // Ensure array's prototype is the actual Array.prototype
    if (!isOptimizableArray(array))
        return true;

    // Ensure array doesn't define '@@iterator' directly.
    if (array->lookup(cx, cx->names().std_iterator))
        return true;

    // Good to optimize now, create stub to add.
    RootedShape shape(cx, array->lastProperty());
    stub = cx->new_<Stub>(shape);
    if (!stub)
        return false;

    // Add the stub.
    addStub(stub);

    *optimized = true;
    return true;
}