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