Bug 1311466 - Part 3: Core changes for WebAssembly module serialization including a test; r=asuth

This commit is contained in:
Jan Varga 2016-10-25 21:18:48 +02:00
Родитель 51534c010e
Коммит 00707ba46a
10 изменённых файлов: 261 добавлений и 2 удалений

Просмотреть файл

@ -27,6 +27,10 @@ enum StructuredCloneTags {
SCTAG_DOM_MUTABLEFILE, SCTAG_DOM_MUTABLEFILE,
SCTAG_DOM_FILE, SCTAG_DOM_FILE,
SCTAG_DOM_WASM,
// New IDB tags go here!
// These tags are used for both main thread and workers. // These tags are used for both main thread and workers.
SCTAG_DOM_IMAGEDATA, SCTAG_DOM_IMAGEDATA,
SCTAG_DOM_MAP_MESSAGEPORT, SCTAG_DOM_MAP_MESSAGEPORT,
@ -56,6 +60,12 @@ enum StructuredCloneTags {
// This tag is used by both main thread and workers. // This tag is used by both main thread and workers.
SCTAG_DOM_URLSEARCHPARAMS, SCTAG_DOM_URLSEARCHPARAMS,
// When adding a new tag for IDB, please don't add it to the end of the list!
// Tags that are supported by IDB must not ever change. See the static assert
// in IDBObjectStore.cpp, method CommonStructuredCloneReadCallback.
// Adding to the end of the list would make removing of other tags harder in
// future.
SCTAG_DOM_MAX SCTAG_DOM_MAX
}; };

Просмотреть файл

@ -8237,6 +8237,16 @@ struct ObjectStoreAddOrPutRequestOp::StoredFileInfo final
aText.AppendInt(id); aText.AppendInt(id);
break; break;
case StructuredCloneFile::eWasmBytecode:
aText.Append('/');
aText.AppendInt(id);
break;
case StructuredCloneFile::eWasmCompiled:
aText.Append('\\');
aText.AppendInt(id);
break;
default: default:
MOZ_CRASH("Should never get here!"); MOZ_CRASH("Should never get here!");
} }
@ -15097,6 +15107,22 @@ TransactionBase::VerifyRequestParams(const ObjectStoreAddPutParams& aParams)
} }
case StructuredCloneFile::eStructuredClone: case StructuredCloneFile::eStructuredClone:
ASSERT_UNLESS_FUZZING();
return false;
case StructuredCloneFile::eWasmBytecode:
case StructuredCloneFile::eWasmCompiled:
if (NS_WARN_IF(file.type() !=
DatabaseOrMutableFile::TPBackgroundIDBDatabaseFileParent)) {
ASSERT_UNLESS_FUZZING();
return false;
}
if (NS_WARN_IF(!file.get_PBackgroundIDBDatabaseFileParent())) {
ASSERT_UNLESS_FUZZING();
return false;
}
break;
case StructuredCloneFile::eEndGuard: case StructuredCloneFile::eEndGuard:
ASSERT_UNLESS_FUZZING(); ASSERT_UNLESS_FUZZING();
return false; return false;
@ -25545,7 +25571,9 @@ ObjectStoreAddOrPutRequestOp::Init(TransactionBase* aTransaction)
const FileAddInfo& fileAddInfo = fileAddInfos[index]; const FileAddInfo& fileAddInfo = fileAddInfos[index];
MOZ_ASSERT(fileAddInfo.type() == StructuredCloneFile::eBlob || MOZ_ASSERT(fileAddInfo.type() == StructuredCloneFile::eBlob ||
fileAddInfo.type() == StructuredCloneFile::eMutableFile); fileAddInfo.type() == StructuredCloneFile::eMutableFile ||
fileAddInfo.type() == StructuredCloneFile::eWasmBytecode ||
fileAddInfo.type() == StructuredCloneFile::eWasmCompiled);
const DatabaseOrMutableFile& file = fileAddInfo.file(); const DatabaseOrMutableFile& file = fileAddInfo.file();
@ -25591,6 +25619,29 @@ ObjectStoreAddOrPutRequestOp::Init(TransactionBase* aTransaction)
break; break;
} }
case StructuredCloneFile::eWasmBytecode:
case StructuredCloneFile::eWasmCompiled: {
MOZ_ASSERT(file.type() ==
DatabaseOrMutableFile::TPBackgroundIDBDatabaseFileParent);
storedFileInfo->mFileActor =
static_cast<DatabaseFile*>(
file.get_PBackgroundIDBDatabaseFileParent());
MOZ_ASSERT(storedFileInfo->mFileActor);
storedFileInfo->mFileInfo = storedFileInfo->mFileActor->GetFileInfo();
MOZ_ASSERT(storedFileInfo->mFileInfo);
storedFileInfo->mInputStream =
storedFileInfo->mFileActor->GetInputStream();
if (storedFileInfo->mInputStream && !mFileManager) {
mFileManager = fileManager;
}
storedFileInfo->mType = fileAddInfo.type();
break;
}
default: default:
MOZ_CRASH("Should never get here!"); MOZ_CRASH("Should never get here!");
} }

Просмотреть файл

@ -323,6 +323,56 @@ StructuredCloneWriteCallback(JSContext* aCx,
} }
} }
if (JS::IsWasmModuleObject(aObj)) {
RefPtr<JS::WasmModule> module = JS::GetWasmModule(aObj);
MOZ_ASSERT(module);
size_t bytecodeSize;
size_t compiledSize;
module->serializedSize(&bytecodeSize, &compiledSize);
UniquePtr<uint8_t[]> bytecode(new uint8_t[bytecodeSize]);
MOZ_ASSERT(bytecode);
UniquePtr<uint8_t[]> compiled(new uint8_t[compiledSize]);
MOZ_ASSERT(compiled);
module->serialize(bytecode.get(),
bytecodeSize,
compiled.get(),
compiledSize);
RefPtr<BlobImpl> blobImpl =
new BlobImplMemory(bytecode.release(), bytecodeSize, EmptyString());
RefPtr<Blob> bytecodeBlob = Blob::Create(nullptr, blobImpl);
blobImpl =
new BlobImplMemory(compiled.release(), compiledSize, EmptyString());
RefPtr<Blob> compiledBlob = Blob::Create(nullptr, blobImpl);
if (cloneWriteInfo->mFiles.Length() + 1 > size_t(UINT32_MAX)) {
MOZ_ASSERT(false, "Fix the structured clone data to use a bigger type!");
return false;
}
const uint32_t index = cloneWriteInfo->mFiles.Length();
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_WASM, /* flags */ 0) ||
!JS_WriteUint32Pair(aWriter, index, index + 1)) {
return false;
}
StructuredCloneFile* newFile = cloneWriteInfo->mFiles.AppendElement();
newFile->mBlob = bytecodeBlob;
newFile->mType = StructuredCloneFile::eWasmBytecode;
newFile = cloneWriteInfo->mFiles.AppendElement();
newFile->mBlob = compiledBlob;
newFile->mType = StructuredCloneFile::eWasmCompiled;
return true;
}
return StructuredCloneHolder::WriteFullySerializableObjects(aCx, aWriter, aObj); return StructuredCloneHolder::WriteFullySerializableObjects(aCx, aWriter, aObj);
} }
@ -797,7 +847,8 @@ CommonStructuredCloneReadCallback(JSContext* aCx,
static_assert(SCTAG_DOM_BLOB == 0xffff8001 && static_assert(SCTAG_DOM_BLOB == 0xffff8001 &&
SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE == 0xffff8002 && SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE == 0xffff8002 &&
SCTAG_DOM_MUTABLEFILE == 0xffff8004 && SCTAG_DOM_MUTABLEFILE == 0xffff8004 &&
SCTAG_DOM_FILE == 0xffff8005, SCTAG_DOM_FILE == 0xffff8005 &&
SCTAG_DOM_WASM == 0xffff8006,
"You changed our structured clone tag values and just ate " "You changed our structured clone tag values and just ate "
"everyone's IndexedDB data. I hope you are happy."); "everyone's IndexedDB data. I hope you are happy.");
@ -1320,6 +1371,25 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
break; break;
} }
case StructuredCloneFile::eWasmBytecode:
case StructuredCloneFile::eWasmCompiled: {
MOZ_ASSERT(file.mBlob);
MOZ_ASSERT(!file.mMutableFile);
PBackgroundIDBDatabaseFileChild* fileActor =
database->GetOrCreateFileActorForBlob(file.mBlob);
if (NS_WARN_IF(!fileActor)) {
IDB_REPORT_INTERNAL_ERR();
aRv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
return nullptr;
}
fileAddInfo->file() = fileActor;
fileAddInfo->type() = file.mType;
break;
}
default: default:
MOZ_CRASH("Should never get here!"); MOZ_CRASH("Should never get here!");
} }

Просмотреть файл

@ -29,6 +29,8 @@ struct StructuredCloneFile
eBlob, eBlob,
eMutableFile, eMutableFile,
eStructuredClone, eStructuredClone,
eWasmBytecode,
eWasmCompiled,
eEndGuard eEndGuard
}; };

Просмотреть файл

@ -85,6 +85,21 @@ function getNullFile(name, size)
return getFile(name, "binary/null", getView(size)); return getFile(name, "binary/null", getView(size));
} }
function isWasmSupported()
{
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
return testingFunctions.wasmIsSupported();
}
function getWasmModule(text)
{
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
let wasmTextToBinary = SpecialPowers.unwrap(testingFunctions.wasmTextToBinary);
let binary = wasmTextToBinary(text);
let module = new WebAssembly.Module(binary);
return module;
}
function verifyBuffers(buffer1, buffer2) function verifyBuffers(buffer1, buffer2)
{ {
ok(compareBuffers(buffer1, buffer2), "Correct buffer data"); ok(compareBuffers(buffer1, buffer2), "Correct buffer data");

Просмотреть файл

@ -113,6 +113,7 @@ support-files =
unit/test_transaction_ordering.js unit/test_transaction_ordering.js
unit/test_unique_index_update.js unit/test_unique_index_update.js
unit/test_view_put_get_values.js unit/test_view_put_get_values.js
unit/test_wasm_put_get_values.js
unit/test_writer_starvation.js unit/test_writer_starvation.js
[test_abort_deleted_index.html] [test_abort_deleted_index.html]
@ -390,5 +391,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_view_put_get_values.html] [test_view_put_get_values.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_wasm_put_get_values.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_serviceworker.html] [test_serviceworker.html]
skip-if = buildapp == 'b2g' skip-if = buildapp == 'b2g'

Просмотреть файл

@ -0,0 +1,20 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_wasm_put_get_values.js"></script>
<script type="text/javascript;version=1.7" src="file.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

Просмотреть файл

@ -0,0 +1,68 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var disableWorkerTest = "Need a way to set temporary prefs from a worker";
var testGenerator = testSteps();
function testSteps()
{
const name =
this.window ? window.location.pathname : "test_wasm_put_get_values.js";
const objectStoreName = "Wasm";
const wasmData = { key: 1, wasm: null };
if (this.window) {
SpecialPowers.pushPrefEnv({ "set": [["javascript.options.wasm", true]] },
continueToNextStep);
yield undefined;
} else {
enableWasm();
}
if (!isWasmSupported()) {
finishTest();
yield undefined;
}
info("Opening database");
let request = indexedDB.open(name);
request.onerror = errorHandler;
request.onupgradeneeded = continueToNextStepSync;
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
// upgradeneeded
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = continueToNextStepSync;
info("Creating objectStore");
request.result.createObjectStore(objectStoreName);
yield undefined;
// success
let db = request.result;
db.onerror = errorHandler;
info("Storing wasm");
wasmData.wasm = getWasmModule('(module (func (nop)))');
let objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
request = objectStore.add(wasmData.wasm, wasmData.key);
request.onsuccess = continueToNextStepSync;
yield undefined;
is(request.result, wasmData.key, "Got correct key");
finishTest();
yield undefined;
}

Просмотреть файл

@ -209,6 +209,11 @@ function resetTesting()
SpecialPowers.clearUserPref("dom.indexedDB.testing"); SpecialPowers.clearUserPref("dom.indexedDB.testing");
} }
function enableWasm()
{
SpecialPowers.setBoolPref("javascript.options.wasm", true);
}
function gc() function gc()
{ {
Cu.forceGC(); Cu.forceGC();
@ -363,6 +368,20 @@ function getFile(name, type, str)
return new File([str], name, {type: type}); return new File([str], name, {type: type});
} }
function isWasmSupported()
{
let testingFunctions = Cu.getJSTestingFunctions();
return testingFunctions.wasmIsSupported();
}
function getWasmModule(text)
{
let testingFunctions = Cu.getJSTestingFunctions();
let binary = testingFunctions.wasmTextToBinary(text);
let module = new WebAssembly.Module(binary);
return module;
}
function compareBuffers(buffer1, buffer2) function compareBuffers(buffer1, buffer2)
{ {
if (buffer1.byteLength != buffer2.byteLength) { if (buffer1.byteLength != buffer2.byteLength) {

Просмотреть файл

@ -59,3 +59,4 @@ skip-if = true
# bug 951017: intermittent failure on Android x86 emulator # bug 951017: intermittent failure on Android x86 emulator
skip-if = os == "android" && processor == "x86" skip-if = os == "android" && processor == "x86"
[test_view_put_get_values.js] [test_view_put_get_values.js]
[test_wasm_put_get_values.js]