Skip to content

Commit

Permalink
[JSC] Use MarkedArgumentBuffer::ensureCapacity
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=267194
rdar://120598941

Reviewed by Justin Michaud.

Use ensureCapacity for MarkedArgumentBuffer to avoid repeated allocations.

* Source/JavaScriptCore/API/JSObjectRef.cpp:
(JSObjectMakeFunction):
(JSObjectMakeArray):
(JSObjectMakeDate):
(JSObjectMakeRegExp):
(JSObjectCallAsFunction):
(JSObjectCallAsConstructor):
* Source/JavaScriptCore/runtime/ArgList.h:
(JSC::MarkedVector::fill):
(JSC::MarkedVector::isUsingInlineBuffer const):
* Source/JavaScriptCore/tools/JSDollarVM.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/wasm/WasmOperations.cpp:
(JSC::Wasm::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/wasm/js/WebAssemblyExceptionConstructor.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/wasm/js/WebAssemblyTagPrototype.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/WebCore/bindings/js/JSDOMConvertSequences.h:
(WebCore::JSConverter<IDLSequence<T>>::convert):
(WebCore::JSConverter<IDLFrozenArray<T>>::convert):
* Source/WebCore/bindings/js/JSDOMConvertWebGL.cpp:
(WebCore::convertToJSValue):
* Source/WebCore/bindings/js/JSDOMMapLike.cpp:
(WebCore::forwardFunctionCallToBackingMap):
(WebCore::forwardForEachCallToBackingMap):
* Source/WebCore/bindings/js/JSDOMSetLike.cpp:
(WebCore::forwardFunctionCallToBackingSet):
(WebCore::forwardForEachCallToBackingSet):
* Source/WebCore/bindings/js/JSIDBRequestCustom.cpp:
(WebCore::JSIDBRequest::result const):
* Source/WebCore/bindings/js/JSNavigatorCustom.cpp:
(WebCore::JSNavigator::getUserMedia):
* Source/WebCore/bindings/js/JSPluginElementFunctions.cpp:
(WebCore::JSC_DEFINE_HOST_FUNCTION):
* Source/WebCore/bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::executeFunctionInContext):
* Source/WebCore/bindings/scripts/CodeGeneratorJS.pm:
(GenerateCallbackImplementationContent):

Canonical link: https://commits.webkit.org/272785@main
  • Loading branch information
Constellation committed Jan 8, 2024
1 parent 1314723 commit e96e2b5
Show file tree
Hide file tree
Showing 14 changed files with 45 additions and 7 deletions.
6 changes: 6 additions & 0 deletions Source/JavaScriptCore/API/JSObjectRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa
Identifier nameID = name ? name->identifier(&vm) : Identifier::fromString(vm, "anonymous"_s);

MarkedArgumentBuffer args;
args.ensureCapacity(parameterCount + 1);
for (unsigned i = 0; i < parameterCount; i++)
args.append(jsString(vm, parameterNames[i]->string()));
args.append(jsString(vm, body->string()));
Expand Down Expand Up @@ -173,6 +174,7 @@ JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSVa
JSObject* result;
if (argumentCount) {
MarkedArgumentBuffer argList;
argList.ensureCapacity(argumentCount);
for (size_t i = 0; i < argumentCount; ++i)
argList.append(toJS(globalObject, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
Expand Down Expand Up @@ -204,6 +206,7 @@ JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSVal
auto scope = DECLARE_CATCH_SCOPE(vm);

MarkedArgumentBuffer argList;
argList.ensureCapacity(argumentCount);
for (size_t i = 0; i < argumentCount; ++i)
argList.append(toJS(globalObject, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
Expand Down Expand Up @@ -254,6 +257,7 @@ JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSV
auto scope = DECLARE_CATCH_SCOPE(vm);

MarkedArgumentBuffer argList;
argList.ensureCapacity(argumentCount);
for (size_t i = 0; i < argumentCount; ++i)
argList.append(toJS(globalObject, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
Expand Down Expand Up @@ -717,6 +721,7 @@ JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObject
jsThisObject = globalObject->globalThis();

MarkedArgumentBuffer argList;
argList.ensureCapacity(argumentCount);
for (size_t i = 0; i < argumentCount; i++)
argList.append(toJS(globalObject, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
Expand Down Expand Up @@ -763,6 +768,7 @@ JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size
return nullptr;

MarkedArgumentBuffer argList;
argList.ensureCapacity(argumentCount);
for (size_t i = 0; i < argumentCount; i++)
argList.append(toJS(globalObject, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
Expand Down
21 changes: 17 additions & 4 deletions Source/JavaScriptCore/runtime/ArgList.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class alignas(alignof(EncodedJSValue)) MarkedVectorBase {

Status expandCapacity();
Status expandCapacity(int newCapacity);
Status slowEnsureCapacity(size_t requestedCapacity);
JS_EXPORT_PRIVATE Status slowEnsureCapacity(size_t requestedCapacity);

void addMarkSet(JSValue);

Expand Down Expand Up @@ -215,18 +215,31 @@ class MarkedVector : public OverflowHandler, public MarkedVectorBase {
ensureCapacity(count);
if (OverflowHandler::hasOverflowed())
return;
if (LIKELY(!m_markSet)) {
m_markSet = &vm.heap.markListSet();
m_markSet->add(this);
if (!isUsingInlineBuffer()) {
if (LIKELY(!m_markSet)) {
m_markSet = &vm.heap.markListSet();
m_markSet->add(this);
}
}
m_size = count;
auto* buffer = reinterpret_cast<JSValue*>(&slotFor(0));

// This clearing does not need to consider about concurrent marking from GC since MarkedVector
// gets marked only while mutator is stopping. So, while clearing in the mutator, concurrent
// marker will not see the buffer.
#if USE(JSVALUE64)
memset(bitwise_cast<void*>(buffer), 0, sizeof(JSValue) * count);
#else
for (unsigned i = 0; i < count; ++i)
buffer[i] = JSValue();
#endif

func(buffer);
}

private:
bool isUsingInlineBuffer() const { return m_buffer == m_inlineBuffer; }

EncodedJSValue m_inlineBuffer[inlineCapacity] { };
};

Expand Down
7 changes: 5 additions & 2 deletions Source/JavaScriptCore/tools/JSDollarVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4072,8 +4072,11 @@ JSC_DEFINE_HOST_FUNCTION(functionCallFromCPP, (JSGlobalObject* globalObject, Cal
return JSValue::encode(jsUndefined());

MarkedArgumentBuffer arguments;
for (unsigned i = 2; i < callFrame->argumentCount(); ++i)
arguments.append(callFrame->argument(i));
if (callFrame->argumentCount() > 2) {
arguments.ensureCapacity(callFrame->argumentCount() - 2);
for (unsigned i = 2; i < callFrame->argumentCount(); ++i)
arguments.append(callFrame->argument(i));
}
ASSERT(!arguments.hasOverflowed());
RETURN_IF_EXCEPTION(scope, { });

Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/wasm/WasmOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ JSC_DEFINE_JIT_OPERATION(operationIterateResults, void, (Instance* instance, con

unsigned iterationCount = 0;
MarkedArgumentBuffer buffer;
buffer.ensureCapacity(signature->returnCount());
JSValue result = JSValue::decode(encResult);
forEachInIterable(globalObject, result, [&] (VM&, JSGlobalObject*, JSValue value) -> void {
if (buffer.size() < signature->returnCount()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ JSC_DEFINE_HOST_FUNCTION(constructJSWebAssemblyException, (JSGlobalObject* globa
if (!tag)
return throwVMTypeError(globalObject, scope, "WebAssembly.Exception constructor expects the first argument to be a WebAssembly.Tag"_s);

const auto& tagFunctionType = tag->type();
MarkedArgumentBuffer values;
values.ensureCapacity(tagFunctionType.argumentCount());
forEachInIterable(globalObject, tagParameters, [&] (VM&, JSGlobalObject*, JSValue nextValue) {
values.append(nextValue);
if (UNLIKELY(values.hasOverflowed()))
throwOutOfMemoryError(globalObject, scope);
});
RETURN_IF_EXCEPTION(scope, { });

const auto& tagFunctionType = tag->type();
if (values.size() != tagFunctionType.argumentCount())
return throwVMTypeError(globalObject, scope, "WebAssembly.Exception constructor expects the number of paremeters in WebAssembly.Tag to match the tags parameter count."_s);

Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/wasm/js/WebAssemblyTagPrototype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ JSC_DEFINE_HOST_FUNCTION(webAssemblyTagProtoFuncType, (JSGlobalObject* globalObj
const Wasm::Tag& tag = jsTag->tag();

MarkedArgumentBuffer argList;
argList.ensureCapacity(tag.parameterCount());
for (size_t i = 0; i < tag.parameterCount(); ++i)
argList.append(Wasm::typeToString(vm, tag.parameter(i).kind));

Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/bindings/js/JSDOMConvertSequences.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ template<typename T> struct JSConverter<IDLSequence<T>> {
JSC::VM& vm = JSC::getVM(&lexicalGlobalObject);
auto scope = DECLARE_THROW_SCOPE(vm);
JSC::MarkedArgumentBuffer list;
list.ensureCapacity(vector.size());
for (auto& element : vector) {
auto jsValue = toJS<T>(lexicalGlobalObject, globalObject, element);
RETURN_IF_EXCEPTION(scope, { });
Expand Down Expand Up @@ -418,6 +419,7 @@ template<typename T> struct JSConverter<IDLFrozenArray<T>> {
JSC::VM& vm = JSC::getVM(&lexicalGlobalObject);
auto scope = DECLARE_THROW_SCOPE(vm);
JSC::MarkedArgumentBuffer list;
list.ensureCapacity(vector.size());
for (auto& element : vector) {
auto jsValue = toJS<T>(lexicalGlobalObject, globalObject, element);
RETURN_IF_EXCEPTION(scope, { });
Expand Down
3 changes: 3 additions & 0 deletions Source/WebCore/bindings/js/JSDOMConvertWebGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,21 @@ JSValue convertToJSValue(JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject&
return jsStringWithCache(lexicalGlobalObject.vm(), value);
}, [&] (const Vector<bool>& values) -> JSValue {
MarkedArgumentBuffer list;
list.ensureCapacity(values.size());
for (auto& value : values)
list.append(jsBoolean(value));
RELEASE_ASSERT(!list.hasOverflowed());
return constructArray(&globalObject, static_cast<JSC::ArrayAllocationProfile*>(nullptr), list);
}, [&] (const Vector<int>& values) -> JSValue {
MarkedArgumentBuffer list;
list.ensureCapacity(values.size());
for (auto& value : values)
list.append(jsNumber(value));
RELEASE_ASSERT(!list.hasOverflowed());
return constructArray(&globalObject, static_cast<JSC::ArrayAllocationProfile*>(nullptr), list);
}, [&] (const Vector<unsigned>& values) -> JSValue {
MarkedArgumentBuffer list;
list.ensureCapacity(values.size());
for (auto& value : values)
list.append(jsNumber(value));
RELEASE_ASSERT(!list.hasOverflowed());
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/bindings/js/JSDOMMapLike.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ JSC::JSValue forwardFunctionCallToBackingMap(JSC::JSGlobalObject& lexicalGlobalO
ASSERT(callData.type != JSC::CallData::Type::None);

JSC::MarkedArgumentBuffer arguments;
arguments.ensureCapacity(callFrame.argumentCount());
for (size_t cptr = 0; cptr < callFrame.argumentCount(); ++cptr)
arguments.append(callFrame.uncheckedArgument(cptr));
ASSERT(!arguments.hasOverflowed());
Expand All @@ -109,6 +110,7 @@ JSC::JSValue forwardForEachCallToBackingMap(JSDOMGlobalObject& globalObject, JSC
ASSERT(callData.type != JSC::CallData::Type::None);

JSC::MarkedArgumentBuffer arguments;
arguments.ensureCapacity(callFrame.argumentCount() + 1);
arguments.append(&result.second.get());
for (size_t cptr = 0; cptr < callFrame.argumentCount(); ++cptr)
arguments.append(callFrame.uncheckedArgument(cptr));
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/bindings/js/JSDOMSetLike.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ JSC::JSValue forwardFunctionCallToBackingSet(JSC::JSGlobalObject& lexicalGlobalO
auto callData = JSC::getCallData(function);
ASSERT(callData.type != JSC::CallData::Type::None);
JSC::MarkedArgumentBuffer arguments;
arguments.ensureCapacity(callFrame.argumentCount());
for (size_t cptr = 0; cptr < callFrame.argumentCount(); ++cptr)
arguments.append(callFrame.uncheckedArgument(cptr));
ASSERT(!arguments.hasOverflowed());
Expand All @@ -111,6 +112,7 @@ JSC::JSValue forwardForEachCallToBackingSet(JSDOMGlobalObject& globalObject, JSC
ASSERT(callData.type != JSC::CallData::Type::None);

JSC::MarkedArgumentBuffer arguments;
arguments.ensureCapacity(callFrame.argumentCount() + 1);
arguments.append(&result.second.get());
for (size_t cptr = 0; cptr < callFrame.argumentCount(); ++cptr)
arguments.append(callFrame.uncheckedArgument(cptr));
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/bindings/js/JSIDBRequestCustom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ JSC::JSValue JSIDBRequest::result(JSC::JSGlobalObject& lexicalGlobalObject) cons
auto& values = getAllResult.values();
auto& keyPath = getAllResult.keyPath();
JSC::MarkedArgumentBuffer list;
list.ensureCapacity(values.size());
for (unsigned i = 0; i < values.size(); i ++) {
auto result = deserializeIDBValueWithKeyInjection(lexicalGlobalObject, values[i], keys[i], keyPath);
if (!result)
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/bindings/js/JSNavigatorCustom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ JSC::JSValue JSNavigator::getUserMedia(JSC::JSGlobalObject& lexicalGlobalObject,
auto callData = JSC::getCallData(function);
ASSERT(callData.type != JSC::CallData::Type::None);
JSC::MarkedArgumentBuffer arguments;
arguments.ensureCapacity(callFrame.argumentCount());
for (size_t cptr = 0; cptr < callFrame.argumentCount(); ++cptr)
arguments.append(callFrame.uncheckedArgument(cptr));
ASSERT(!arguments.hasOverflowed());
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/bindings/js/JSPluginElementFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ JSC_DEFINE_HOST_FUNCTION(callPlugin, (JSGlobalObject* lexicalGlobalObject, CallF

size_t argumentCount = callFrame->argumentCount();
MarkedArgumentBuffer argumentList;
argumentList.ensureCapacity(argumentCount);
for (size_t i = 0; i < argumentCount; i++)
argumentList.append(callFrame->argument(i));
ASSERT(!argumentList.hasOverflowed());
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/bindings/js/ScheduledAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV
JSGlobalObject* lexicalGlobalObject = globalObject;

MarkedArgumentBuffer arguments;
arguments.ensureCapacity(m_arguments.size());
for (auto& argument : m_arguments)
arguments.append(argument.get());
if (UNLIKELY(arguments.hasOverflowed())) {
Expand Down

0 comments on commit e96e2b5

Please sign in to comment.