SymbolTable* SymbolTable::clone(VM& vm) { SymbolTable* result = SymbolTable::create(vm); result->m_parameterCountIncludingThis = m_parameterCountIncludingThis; result->m_usesNonStrictEval = m_usesNonStrictEval; result->m_captureStart = m_captureStart; result->m_captureEnd = m_captureEnd; Map::iterator iter = m_map.begin(); Map::iterator end = m_map.end(); for (; iter != end; ++iter) { result->m_map.add( iter->key, SymbolTableEntry(iter->value.getIndex(), iter->value.getAttributes())); } if (m_slowArguments) { result->m_slowArguments = std::make_unique<SlowArgument[]>(parameterCount()); for (unsigned i = parameterCount(); i--;) result->m_slowArguments[i] = m_slowArguments[i]; } return result; }
Storage storageForGeneratorLocal(unsigned index) { // We assign a symbol to a register. There is one-on-one corresponding between a register and a symbol. // By doing so, we allocate the specific storage to save the given register. // This allow us not to save all the live registers even if the registers are not overwritten from the previous resuming time. // It means that, the register can be retrieved even if the immediate previous op_save does not save it. if (m_storages.size() <= index) m_storages.resize(index + 1); if (Optional<Storage> storage = m_storages[index]) return *storage; Identifier identifier = Identifier::fromUid(PrivateName()); unsigned identifierIndex = m_codeBlock->numberOfIdentifiers(); m_codeBlock->addIdentifier(identifier); ScopeOffset scopeOffset = m_generatorFrameSymbolTable->takeNextScopeOffset(NoLockingNecessary); m_generatorFrameSymbolTable->set(NoLockingNecessary, identifier.impl(), SymbolTableEntry(VarOffset(scopeOffset))); Storage storage = { identifier, identifierIndex, scopeOffset }; m_storages[index] = storage; return storage; }
SymbolTable* SymbolTable::cloneCapturedNames(VM& vm) { SymbolTable* result = SymbolTable::create(vm); result->m_parameterCountIncludingThis = m_parameterCountIncludingThis; result->m_usesNonStrictEval = m_usesNonStrictEval; result->m_captureStart = m_captureStart; result->m_captureEnd = m_captureEnd; for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { if (!isCaptured(iter->value.getIndex())) continue; result->m_map.add( iter->key, SymbolTableEntry(iter->value.getIndex(), iter->value.getAttributes())); } if (m_slowArguments) { result->m_slowArguments = std::make_unique<SlowArgument[]>(parameterCount()); for (unsigned i = parameterCount(); i--;) result->m_slowArguments[i] = m_slowArguments[i]; } if (m_uniqueIDMap && result->m_uniqueIDMap) { { auto iter = m_uniqueIDMap->begin(); auto end = m_uniqueIDMap->end(); for (; iter != end; ++iter) result->m_uniqueIDMap->set(iter->key, iter->value); } { auto iter = m_registerToVariableMap->begin(); auto end = m_registerToVariableMap->end(); for (; iter != end; ++iter) result->m_registerToVariableMap->set(iter->key, iter->value); } { auto iter = m_uniqueTypeSetMap->begin(); auto end = m_uniqueTypeSetMap->end(); for (; iter != end; ++iter) result->m_uniqueTypeSetMap->set(iter->key, iter->value); } } return result; }
SymbolTable* SymbolTable::cloneScopePart(VM& vm) { SymbolTable* result = SymbolTable::create(vm); result->m_usesNonStrictEval = m_usesNonStrictEval; result->m_nestedLexicalScope = m_nestedLexicalScope; result->m_scopeType = m_scopeType; for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { if (!iter->value.varOffset().isScope()) continue; result->m_map.add( iter->key, SymbolTableEntry(iter->value.varOffset(), iter->value.getAttributes())); } result->m_maxScopeOffset = m_maxScopeOffset; if (ScopedArgumentsTable* arguments = this->arguments()) result->m_arguments.set(vm, result, arguments); if (m_typeProfilingRareData) { result->m_typeProfilingRareData = std::make_unique<TypeProfilingRareData>(); { auto iter = m_typeProfilingRareData->m_uniqueIDMap.begin(); auto end = m_typeProfilingRareData->m_uniqueIDMap.end(); for (; iter != end; ++iter) result->m_typeProfilingRareData->m_uniqueIDMap.set(iter->key, iter->value); } { auto iter = m_typeProfilingRareData->m_offsetToVariableMap.begin(); auto end = m_typeProfilingRareData->m_offsetToVariableMap.end(); for (; iter != end; ++iter) result->m_typeProfilingRareData->m_offsetToVariableMap.set(iter->key, iter->value); } { auto iter = m_typeProfilingRareData->m_uniqueTypeSetMap.begin(); auto end = m_typeProfilingRareData->m_uniqueTypeSetMap.end(); for (; iter != end; ++iter) result->m_typeProfilingRareData->m_uniqueTypeSetMap.set(iter->key, iter->value); } } return result; }
static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyModule(ExecState* state) { VM& vm = state->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSValue val = state->argument(0); // If the given bytes argument is not a BufferSource, a TypeError exception is thrown. JSArrayBuffer* arrayBuffer = val.getObject() ? jsDynamicCast<JSArrayBuffer*>(val.getObject()) : nullptr; JSArrayBufferView* arrayBufferView = val.getObject() ? jsDynamicCast<JSArrayBufferView*>(val.getObject()) : nullptr; if (!(arrayBuffer || arrayBufferView)) return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("first argument to WebAssembly.Module must be an ArrayBufferView or an ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(val)))); if (arrayBufferView ? arrayBufferView->isNeutered() : arrayBuffer->impl()->isNeutered()) return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("underlying TypedArray has been detatched from the ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(val)))); size_t byteOffset = arrayBufferView ? arrayBufferView->byteOffset() : 0; size_t byteSize = arrayBufferView ? arrayBufferView->length() : arrayBuffer->impl()->byteLength(); const auto* base = arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data()); Wasm::Plan plan(&vm, base + byteOffset, byteSize); // On failure, a new WebAssembly.CompileError is thrown. plan.run(); if (plan.failed()) return JSValue::encode(throwException(state, scope, createWebAssemblyCompileError(state, plan.errorMessage()))); // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), asInternalFunction(state->jsCallee())->globalObject()->WebAssemblyModuleStructure()); RETURN_IF_EXCEPTION(scope, { }); // The export symbol table is the same for all Instances of a Module. SymbolTable* exportSymbolTable = SymbolTable::create(vm); for (auto& exp : plan.exports()) { auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); } // Only wasm-internal functions have a callee, stubs to JS do not. unsigned calleeCount = plan.internalFunctionCount(); JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmToJSStubs(), plan.takeFunctionIndexSpace(), exportSymbolTable, calleeCount); plan.initializeCallees(state->jsCallee()->globalObject(), [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { result->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); result->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); }); return JSValue::encode(result); }
JSValue WebAssemblyModuleConstructor::createModule(ExecState* state, Structure* structure) { VM& vm = state->vm(); auto scope = DECLARE_THROW_SCOPE(vm); size_t byteOffset; size_t byteSize; uint8_t* base = getWasmBufferFromValue(state, state->argument(0), byteOffset, byteSize); RETURN_IF_EXCEPTION(scope, { }); Wasm::Plan plan(&vm, base + byteOffset, byteSize); // On failure, a new WebAssembly.CompileError is thrown. plan.run(); if (plan.failed()) return throwException(state, scope, createJSWebAssemblyCompileError(state, vm, plan.errorMessage())); // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. // The export symbol table is the same for all Instances of a Module. SymbolTable* exportSymbolTable = SymbolTable::create(vm); for (auto& exp : plan.exports()) { auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); } // Only wasm-internal functions have a callee, stubs to JS do not. unsigned calleeCount = plan.internalFunctionCount(); JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), exportSymbolTable, calleeCount); plan.initializeCallees(state->jsCallee()->globalObject(), [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { result->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); result->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); }); return result; }