Example #1
0
void Worklist::runThread(ThreadData* data)
{
    CompilationScope compilationScope;

    if (Options::verboseCompilationQueue())
        dataLog(*this, ": Thread started\n");

    LongLivedState longLivedState;

    for (;;) {
        RefPtr<Plan> plan;
        {
            MutexLocker locker(m_lock);
            while (m_queue.isEmpty())
                m_planEnqueued.wait(m_lock);

            plan = m_queue.takeFirst();
            if (plan)
                m_numberOfActiveThreads++;
        }

        if (!plan) {
            if (Options::verboseCompilationQueue())
                dataLog(*this, ": Thread shutting down\n");
            return;
        }

        {
            MutexLocker locker(data->m_rightToRun);

            if (Options::verboseCompilationQueue())
                dataLog(*this, ": Compiling ", plan->key(), " asynchronously\n");

            plan->compileInThread(longLivedState, data);
        }

        {
            MutexLocker locker(m_lock);
            plan->notifyReady();

            if (Options::verboseCompilationQueue()) {
                dump(locker, WTF::dataFile());
                dataLog(": Compiled ", plan->key(), " asynchronously\n");
            }

            m_readyPlans.append(plan);

            m_planCompiled.broadcast();
            m_numberOfActiveThreads--;
        }
    }
}
Example #2
0
void Worklist::enqueue(PassRefPtr<Plan> passedPlan)
{
    RefPtr<Plan> plan = passedPlan;
    MutexLocker locker(m_lock);
    if (Options::verboseCompilationQueue()) {
        dump(locker, WTF::dataFile());
        dataLog(": Enqueueing plan to optimize ", plan->key(), "\n");
    }
    ASSERT(m_plans.find(plan->key()) == m_plans.end());
    m_plans.add(plan->key(), plan);
    m_queue.append(plan);
    m_planEnqueued.signal();
}
Example #3
0
void IDBIndexBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks)
{
    IDB_TRACE("IDBIndexBackendImpl::getInternal");

    RefPtr<IDBKey> key;

    if (keyRange->isOnlyKey())
        key = keyRange->lower();
    else {
        RefPtr<IDBBackingStore::Cursor> backingStoreCursor = index->backingStore()->openIndexCursor(index->databaseId(), index->m_objectStoreBackend->id(), index->id(), keyRange.get(), IDBCursor::NEXT);

        if (!backingStoreCursor) {
            callbacks->onSuccess(SerializedScriptValue::undefinedValue());
            return;
        }
        key = backingStoreCursor->key();
        backingStoreCursor->close();
    }

    String value = index->backingStore()->getObjectViaIndex(index->databaseId(), index->m_objectStoreBackend->id(), index->id(), *key);
    if (value.isNull()) {
        callbacks->onSuccess(SerializedScriptValue::undefinedValue());
        return;
    }
    callbacks->onSuccess(SerializedScriptValue::createFromWire(value));
}
Example #4
0
Worklist::State Worklist::completeAllReadyPlansForVM(VM& vm, CompilationKey requestedKey)
{
    DeferGC deferGC(vm.heap);
    Vector<RefPtr<Plan>, 8> myReadyPlans;

    removeAllReadyPlansForVM(vm, myReadyPlans);

    State resultingState = NotKnown;

    while (!myReadyPlans.isEmpty()) {
        RefPtr<Plan> plan = myReadyPlans.takeLast();
        CompilationKey currentKey = plan->key();

        if (Options::verboseCompilationQueue())
            dataLog(*this, ": Completing ", currentKey, "\n");

        RELEASE_ASSERT(plan->isCompiled);

        plan->finalizeAndNotifyCallback();

        if (currentKey == requestedKey)
            resultingState = Compiled;
    }

    if (!!requestedKey && resultingState == NotKnown) {
        MutexLocker locker(m_lock);
        if (m_plans.contains(requestedKey))
            resultingState = Compiling;
    }

    return resultingState;
}
Example #5
0
void IDBIndexBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
{
    IDB_TRACE("IDBIndexBackendImpl::getInternal");

    RefPtr<IDBKey> key;

    if (keyRange->isOnlyKey())
        key = keyRange->lower();
    else {
        RefPtr<IDBBackingStore::Cursor> backingStoreCursor = index->backingStore()->openIndexCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), keyRange.get(), IDBCursor::NEXT);

        if (!backingStoreCursor) {
            callbacks->onSuccess();
            return;
        }
        key = backingStoreCursor->key();
    }

    RefPtr<IDBKey> primaryKey = index->backingStore()->getPrimaryKeyViaIndex(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), *key);

    String value = index->backingStore()->getRecord(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), *primaryKey);

    if (value.isNull()) {
        callbacks->onSuccess();
        return;
    }
    if (index->m_objectStoreBackend->autoIncrement() && !index->m_objectStoreBackend->keyPath().isNull()) {
        callbacks->onSuccess(SerializedScriptValue::createFromWire(value),
                             primaryKey, index->m_objectStoreBackend->keyPath());
        return;
    }
    callbacks->onSuccess(SerializedScriptValue::createFromWire(value));
}
Example #6
0
void IDBIndexBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> range, unsigned short untypedDirection, IDBCursorBackendInterface::CursorType cursorType, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
{
    IDB_TRACE("IDBIndexBackendImpl::openCursorInternal");
    IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(untypedDirection);

    RefPtr<IDBBackingStore::Cursor> backingStoreCursor;

    switch (cursorType) {
    case IDBCursorBackendInterface::IndexKeyCursor:
        backingStoreCursor = index->backingStore()->openIndexKeyCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), range.get(), direction);
        break;
    case IDBCursorBackendInterface::IndexCursor:
        backingStoreCursor = index->backingStore()->openIndexCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), range.get(), direction);
        break;
    case IDBCursorBackendInterface::ObjectStoreCursor:
    case IDBCursorBackendInterface::InvalidCursorType:
        ASSERT_NOT_REACHED();
        break;
    }

    if (!backingStoreCursor) {
        callbacks->onSuccess(static_cast<SerializedScriptValue*>(0));
        return;
    }

    RefPtr<IDBCursorBackendImpl> cursor = IDBCursorBackendImpl::create(backingStoreCursor.get(), cursorType, transaction.get(), index->m_objectStoreBackend);
    callbacks->onSuccess(cursor, cursor->key(), cursor->primaryKey(), cursor->value());
}
Example #7
0
void IDBRequest::onSuccess(PassRefPtr<IDBCursorBackend> prpBackend)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(IDBCursor)");
    if (!shouldEnqueueEvent())
        return;

    DOMRequestState::Scope scope(m_requestState);

    RefPtr<IDBCursorBackend> backend = prpBackend;
    RefPtr<IDBKey> key = backend->key();
    RefPtr<IDBKey> primaryKey = backend->primaryKey();

    Deprecated::ScriptValue value = deserializeIDBValueBuffer(requestState(), backend->valueBuffer(), !!key);

    ASSERT(!m_pendingCursor);
    RefPtr<IDBCursor> cursor;
    switch (m_cursorType) {
    case IndexedDB::CursorType::KeyOnly:
        cursor = IDBCursor::create(backend.release(), m_cursorDirection, this, m_source.get(), m_transaction.get());
        break;
    case IndexedDB::CursorType::KeyAndValue:
        cursor = IDBCursorWithValue::create(backend.release(), m_cursorDirection, this, m_source.get(), m_transaction.get());
        break;
    default:
        ASSERT_NOT_REACHED();
    }
    setResultCursor(cursor, key.release(), primaryKey.release(), value);

    enqueueEvent(createSuccessEvent());
}
Example #8
0
static bool migrateObjectStores(PassRefPtr<IDBBackingStore> fromBackingStore, int64_t fromDatabaseId, PassRefPtr<IDBBackingStore> toBackingStore, int64_t toDatabaseId)
{
    Vector<int64_t> fromObjStoreIds, toObjStoreIds;
    Vector<String> fromObjStoreNames, toObjStoreNames;
    Vector<String> fromKeyPaths, toKeyPaths;
    Vector<bool> fromAutoIncrement, toAutoIncrement;

    // Migrate objectStores. Check to see if the object store already exists in the target.
    fromBackingStore->getObjectStores(fromDatabaseId, fromObjStoreIds, fromObjStoreNames, fromKeyPaths, fromAutoIncrement);

    toBackingStore->getObjectStores(toDatabaseId, toObjStoreIds, toObjStoreNames, toKeyPaths, toAutoIncrement);

    for (unsigned i = 0; i < fromObjStoreIds.size(); i++) {
        if (toObjStoreNames.contains(fromObjStoreNames[i]))
            continue;

        int64_t assignedObjectStoreId = -1;

        RefPtr<IDBBackingStore::Transaction> trans = toBackingStore->createTransaction();
        trans->begin();

        if (!toBackingStore->createObjectStore(toDatabaseId, fromObjStoreNames[i], fromKeyPaths[i], fromAutoIncrement[i], assignedObjectStoreId))
            return false;

        RefPtr<IDBBackingStore::Cursor> cursor = fromBackingStore->openObjectStoreCursor(fromDatabaseId, fromObjStoreIds[i], 0, IDBCursor::NEXT);
        if (cursor) {
            do {
                RefPtr<IDBKey> key = cursor->key();
                RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = toBackingStore->createInvalidRecordIdentifier();

                if (!toBackingStore->putObjectStoreRecord(toDatabaseId, assignedObjectStoreId, *(key.get()), cursor->value(), recordIdentifier.get()))
                    return false;

            } while (cursor->continueFunction());
        }

        // Populate any/all indexes for this objectstore.
        Vector<int64_t> idxIds;
        Vector<String> idxNames;
        Vector<String> idxKeyPaths;
        Vector<bool> idxUnique;
        fromBackingStore->getIndexes(fromDatabaseId, fromObjStoreIds[i], idxIds, idxNames, idxKeyPaths, idxUnique);
        for (unsigned j = 0; j < idxIds.size(); j++) {
            int64_t indexId = -1;

            if (!toBackingStore->createIndex(toDatabaseId, assignedObjectStoreId, idxNames[j], idxKeyPaths[j], idxUnique[j], indexId))
                return false;

            if (!IDBObjectStoreBackendImpl::populateIndex(*toBackingStore, toDatabaseId, assignedObjectStoreId, indexId, fromKeyPaths[i]))
                return false;
        }

        trans->commit();
    }

    return true;
}
void Worklist::enqueue(PassRefPtr<Plan> passedPlan)
{
    RefPtr<Plan> plan = passedPlan;
    MutexLocker locker(m_lock);
    /*
    if (Options::verboseCompilationQueue()) {
        dump(locker, WTF::dataFile());
        dataLog(": Enqueueing plan to optimize ", plan->key(), "\n");
    }
    */
    if (m_plans.find(plan->key()) != m_plans.end()) {
        printf("enqueue equal parsing plan\n");
        return;
    }

    m_plans.add(plan->key(), plan);
    m_queue.append(plan);
    m_planEnqueued.signal();
}
Example #10
0
void Worklist::removeAllReadyPlansForVM(VM& vm, Vector<RefPtr<Plan>, 8>& myReadyPlans)
{
    DeferGC deferGC(vm.heap);
    MutexLocker locker(m_lock);
    for (size_t i = 0; i < m_readyPlans.size(); ++i) {
        RefPtr<Plan> plan = m_readyPlans[i];
        if (&plan->vm != &vm)
            continue;
        if (!plan->isCompiled)
            continue;
        myReadyPlans.append(plan);
        m_readyPlans[i--] = m_readyPlans.last();
        m_readyPlans.removeLast();
        m_plans.remove(plan->key());
    }
}
Example #11
0
void InspectorDOMStorageAgent::getDOMStorageItems(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > >& items)
{
    Frame* frame;
    RefPtr<StorageArea> storageArea = findStorageArea(errorString, storageId, frame);
    if (!storageArea)
        return;

    RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > > storageItems = TypeBuilder::Array<TypeBuilder::Array<String> >::create();

    ExceptionCode ec = 0;
    for (unsigned i = 0; i < storageArea->length(ec, frame); ++i) {
        String name(storageArea->key(i, ec, frame));
        if (hadException(ec, errorString))
            return;
        String value(storageArea->getItem(name, ec, frame));
        if (hadException(ec, errorString))
            return;
        RefPtr<TypeBuilder::Array<String> > entry = TypeBuilder::Array<String>::create();
        entry->addItem(name);
        entry->addItem(value);
        storageItems->addItem(entry);
    }
    items = storageItems.release();
}
void InspectorDOMStorageAgent::getDOMStorageItems(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Array<String>>>& items)
{
    Frame* frame;
    RefPtr<StorageArea> storageArea = findStorageArea(errorString, storageId, frame);
    if (!storageArea) {
        if (errorString)
            *errorString = "No StorageArea for given storageId";
        return;
    }

    RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Array<String>>> storageItems = Inspector::Protocol::Array<Inspector::Protocol::Array<String>>::create();

    for (unsigned i = 0; i < storageArea->length(); ++i) {
        String key = storageArea->key(i);
        String value = storageArea->item(key);

        RefPtr<Inspector::Protocol::Array<String>> entry = Inspector::Protocol::Array<String>::create();
        entry->addItem(key);
        entry->addItem(value);
        storageItems->addItem(entry.release());
    }

    items = storageItems.release();
}
Example #13
0
void IDBIndexBackendImpl::getKeyInternal(ScriptExecutionContext* context, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks)
{
    IDB_TRACE("IDBIndexBackendImpl::getInternal");

    RefPtr<IDBBackingStore::Cursor> backingStoreCursor =
            index->backingStore()->openIndexKeyCursor(index->databaseId(), index->m_objectStoreBackend->id(), index->id(), keyRange.get(), IDBCursor::NEXT);

    if (!backingStoreCursor) {
        callbacks->onSuccess(static_cast<IDBKey*>(0));
        return;
    }

    RefPtr<IDBKey> keyResult = index->backingStore()->getPrimaryKeyViaIndex(index->databaseId(), index->m_objectStoreBackend->id(), index->id(), *backingStoreCursor->key());
    if (!keyResult) {
        callbacks->onSuccess(static_cast<IDBKey*>(0));
        backingStoreCursor->close();
        return;
    }
    callbacks->onSuccess(keyResult.get());
    backingStoreCursor->close();
}
Example #14
0
void Worklist::runThread(ThreadData* data)
{
    CompilationScope compilationScope;
    
    if (Options::verboseCompilationQueue())
        dataLog(*this, ": Thread started\n");
    
    LongLivedState longLivedState;
    
    for (;;) {
        RefPtr<Plan> plan;
        {
            LockHolder locker(m_lock);
            while (m_queue.isEmpty())
                m_planEnqueued.wait(m_lock);
            
            plan = m_queue.takeFirst();
            if (plan)
                m_numberOfActiveThreads++;
        }
        
        if (!plan) {
            if (Options::verboseCompilationQueue())
                dataLog(*this, ": Thread shutting down\n");
            return;
        }
        
        {
            LockHolder locker(data->m_rightToRun);
            {
                LockHolder locker(m_lock);
                if (plan->stage == Plan::Cancelled) {
                    m_numberOfActiveThreads--;
                    continue;
                }
                plan->notifyCompiling();
            }
        
            if (Options::verboseCompilationQueue())
                dataLog(*this, ": Compiling ", plan->key(), " asynchronously\n");
        
            RELEASE_ASSERT(!plan->vm.heap.isCollecting());
            plan->compileInThread(longLivedState, data);
            RELEASE_ASSERT(!plan->vm.heap.isCollecting());
            
            {
                LockHolder locker(m_lock);
                if (plan->stage == Plan::Cancelled) {
                    m_numberOfActiveThreads--;
                    continue;
                }
                plan->notifyCompiled();
            }
            RELEASE_ASSERT(!plan->vm.heap.isCollecting());
        }

        {
            LockHolder locker(m_lock);
            
            // We could have been cancelled between releasing rightToRun and acquiring m_lock.
            // This would mean that we might be in the middle of GC right now.
            if (plan->stage == Plan::Cancelled) {
                m_numberOfActiveThreads--;
                continue;
            }
            
            plan->notifyReady();
            
            if (Options::verboseCompilationQueue()) {
                dump(locker, WTF::dataFile());
                dataLog(": Compiled ", plan->key(), " asynchronously\n");
            }
            
            m_readyPlans.append(plan);
            
            m_planCompiled.notifyAll();
            m_numberOfActiveThreads--;
        }
    }
}