aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-08-12 01:17:02 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-08-12 01:18:31 -0700
commit5c1ca0cc479526967397247a874ea7792787f249 (patch)
treee907b58d9bd79b53b61f9f683fe7906ecdd209a7 /src
parent2ac8c83be0fce4f56af3621d637d34f3fc1c39f5 (diff)
downloadbun-5c1ca0cc479526967397247a874ea7792787f249.tar.gz
bun-5c1ca0cc479526967397247a874ea7792787f249.tar.zst
bun-5c1ca0cc479526967397247a874ea7792787f249.zip
[bun.js] up to 60% faster TextEncoder.encodeInto and ~3% faster TextEncoder.encode
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/bindings/headers-cpp.h2
-rw-r--r--src/bun.js/bindings/headers.h2
-rw-r--r--src/bun.js/bindings/webcore/DOMJITCheckDOM.h98
-rw-r--r--src/bun.js/bindings/webcore/DOMJITHelpers.cpp57
-rw-r--r--src/bun.js/bindings/webcore/DOMJITHelpers.h216
-rw-r--r--src/bun.js/bindings/webcore/DOMJITIDLConvert.h59
-rw-r--r--src/bun.js/bindings/webcore/DOMJITIDLType.h50
-rw-r--r--src/bun.js/bindings/webcore/DOMJITIDLTypeFilter.h80
-rw-r--r--src/bun.js/bindings/webcore/JSEventDOMJIT.cpp44
-rw-r--r--src/bun.js/bindings/webcore/JSTextEncoder.cpp153
-rw-r--r--src/bun.js/builtins/BunBuiltinNames.h1
-rw-r--r--src/bun.js/webcore/encoding.zig144
12 files changed, 822 insertions, 84 deletions
diff --git a/src/bun.js/bindings/headers-cpp.h b/src/bun.js/bindings/headers-cpp.h
index 4cb7a80e0..0f1772882 100644
--- a/src/bun.js/bindings/headers-cpp.h
+++ b/src/bun.js/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1660175100
+//-- AUTOGENERATED FILE -- 1660283220
// clang-format off
#pragma once
diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h
index 9fd86fb2e..0afc722bf 100644
--- a/src/bun.js/bindings/headers.h
+++ b/src/bun.js/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format off
-//-- AUTOGENERATED FILE -- 1660175100
+//-- AUTOGENERATED FILE -- 1660283220
#pragma once
#include <stddef.h>
diff --git a/src/bun.js/bindings/webcore/DOMJITCheckDOM.h b/src/bun.js/bindings/webcore/DOMJITCheckDOM.h
new file mode 100644
index 000000000..98554085a
--- /dev/null
+++ b/src/bun.js/bindings/webcore/DOMJITCheckDOM.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "DOMJITHelpers.h"
+
+#if ENABLE(JIT)
+
+// #include "Document.h"
+// #include "Element.h"
+#include "Event.h"
+#include "Node.h"
+
+namespace WebCore {
+namespace DOMJIT {
+
+template<typename DOMInterface>
+struct TypeChecker {
+};
+
+template<>
+struct TypeChecker<Node> {
+ static CCallHelpers::Jump branchIfFail(CCallHelpers& jit, GPRReg dom)
+ {
+ return DOMJIT::branchIfNotNode(jit, dom);
+ }
+};
+
+// template<>
+// struct TypeChecker<Document> {
+// static CCallHelpers::Jump branchIfFail(CCallHelpers& jit, GPRReg dom)
+// {
+// return DOMJIT::branchIfNotDocumentWrapper(jit, dom);
+// }
+// };
+
+// template<>
+// struct TypeChecker<DocumentFragment> {
+// static CCallHelpers::Jump branchIfFail(CCallHelpers& jit, GPRReg dom)
+// {
+// return DOMJIT::branchIfNotDocumentFragment(jit, dom);
+// }
+// };
+
+template<>
+struct TypeChecker<Event> {
+ static CCallHelpers::Jump branchIfFail(CCallHelpers& jit, GPRReg dom)
+ {
+ return DOMJIT::branchIfNotEvent(jit, dom);
+ }
+};
+
+// template<>
+// struct TypeChecker<Element> {
+// static CCallHelpers::Jump branchIfFail(CCallHelpers& jit, GPRReg dom)
+// {
+// return DOMJIT::branchIfNotElement(jit, dom);
+// }
+// };
+
+template<typename DOMInterface>
+Ref<JSC::Snippet> checkDOM()
+{
+ Ref<JSC::Snippet> snippet = JSC::Snippet::create();
+ snippet->setGenerator([=](CCallHelpers& jit, JSC::SnippetParams& params) {
+ return TypeChecker<DOMInterface>::branchIfFail(jit, params[0].gpr());
+ });
+ return snippet;
+}
+
+}
+}
+
+#endif
diff --git a/src/bun.js/bindings/webcore/DOMJITHelpers.cpp b/src/bun.js/bindings/webcore/DOMJITHelpers.cpp
new file mode 100644
index 000000000..4666ea358
--- /dev/null
+++ b/src/bun.js/bindings/webcore/DOMJITHelpers.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DOMJITHelpers.h"
+
+#if ENABLE(JIT)
+
+// #include "Document.h"
+#include "JSDOMBinding.h"
+#include "Node.h"
+
+namespace WebCore {
+namespace DOMJIT {
+
+using JSC::CCallHelpers;
+using JSC::GPRReg;
+using JSC::JSValueRegs;
+using JSC::MacroAssembler;
+
+// void loadDocument(MacroAssembler& jit, GPRReg node, GPRReg output)
+// {
+// jit.loadPtr(CCallHelpers::Address(node, Node::treeScopeMemoryOffset()), output);
+// jit.loadPtr(CCallHelpers::Address(output, TreeScope::documentScopeMemoryOffset()), output);
+// }
+
+// void loadDocumentElement(MacroAssembler& jit, GPRReg document, GPRReg output)
+// {
+// jit.loadPtr(CCallHelpers::Address(document, Document::documentElementMemoryOffset()), output);
+// }
+
+}
+}
+
+#endif
diff --git a/src/bun.js/bindings/webcore/DOMJITHelpers.h b/src/bun.js/bindings/webcore/DOMJITHelpers.h
new file mode 100644
index 000000000..73bfc7430
--- /dev/null
+++ b/src/bun.js/bindings/webcore/DOMJITHelpers.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2016-2019 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "JSDOMWrapper.h"
+#include "Node.h"
+#include <JavaScriptCore/FrameTracers.h>
+#include <JavaScriptCore/SnippetParams.h>
+
+#if ENABLE(JIT)
+
+IGNORE_WARNINGS_BEGIN("frame-address")
+
+namespace WebCore {
+namespace DOMJIT {
+
+using JSC::CCallHelpers;
+using JSC::GPRReg;
+using JSC::JSValueRegs;
+using JSC::MacroAssembler;
+
+static_assert(std::is_same<GPRReg, MacroAssembler::RegisterID>::value, "GPRReg is the alias to the MacroAssembler::RegisterID");
+
+inline CCallHelpers::Jump branchIfNotWorldIsNormal(CCallHelpers& jit, GPRReg globalObject)
+{
+ return jit.branchTest8(CCallHelpers::Zero, CCallHelpers::Address(globalObject, JSDOMGlobalObject::offsetOfWorldIsNormal()));
+}
+
+inline CCallHelpers::Jump branchIfNotWeakIsLive(CCallHelpers& jit, GPRReg weakImpl)
+{
+ return jit.branchTestPtr(CCallHelpers::NonZero, CCallHelpers::Address(weakImpl, JSC::WeakImpl::offsetOfWeakHandleOwner()), CCallHelpers::TrustedImm32(JSC::WeakImpl::StateMask));
+}
+
+template<typename WrappedNode>
+JSC::EncodedJSValue toWrapperSlowImpl(JSC::JSGlobalObject* globalObject, void* result)
+{
+ return JSC::JSValue::encode(toJS(globalObject, static_cast<JSDOMGlobalObject*>(globalObject), *static_cast<WrappedNode*>(result)));
+}
+
+template<typename WrappedType>
+void tryLookUpWrapperCache(CCallHelpers& jit, CCallHelpers::JumpList& failureCases, GPRReg wrapped, GPRReg resultGPR)
+{
+ jit.loadPtr(CCallHelpers::Address(wrapped, ScriptWrappable::offsetOfWrapper<WrappedType>()), resultGPR);
+ failureCases.append(jit.branchTestPtr(CCallHelpers::Zero, resultGPR));
+ failureCases.append(branchIfNotWeakIsLive(jit, resultGPR));
+ jit.loadPtr(CCallHelpers::Address(resultGPR, JSC::WeakImpl::offsetOfJSValue() + JSC::JSValue::offsetOfPayload()), resultGPR);
+}
+
+template<typename WrappedType, typename ToJSFunction>
+void toWrapper(CCallHelpers& jit, JSC::SnippetParams& params, GPRReg wrapped, GPRReg globalObject, JSValueRegs result, ToJSFunction function, JSC::JSValue globalObjectConstant)
+{
+ ASSERT(wrapped != result.payloadGPR());
+ ASSERT(globalObject != result.payloadGPR());
+ GPRReg payloadGPR = result.payloadGPR();
+ CCallHelpers::JumpList slowCases;
+
+ if (globalObjectConstant) {
+ if (!JSC::jsCast<JSDOMGlobalObject*>(globalObjectConstant)->worldIsNormal()) {
+ slowCases.append(jit.jump());
+ params.addSlowPathCall(slowCases, jit, function, result, globalObject, wrapped);
+ return;
+ }
+ } else
+ slowCases.append(branchIfNotWorldIsNormal(jit, globalObject));
+
+ tryLookUpWrapperCache<WrappedType>(jit, slowCases, wrapped, payloadGPR);
+ jit.boxCell(payloadGPR, result);
+ params.addSlowPathCall(slowCases, jit, function, result, globalObject, wrapped);
+}
+
+inline CCallHelpers::Jump branchIfDOMWrapper(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::AboveOrEqual,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSDOMWrapperType)));
+}
+
+inline CCallHelpers::Jump branchIfUint8Array(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::Equal,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(Uint8ArrayType)));
+}
+
+inline CCallHelpers::Jump branchIfNotDOMWrapper(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::Below,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSDOMWrapperType)));
+}
+
+inline CCallHelpers::Jump branchIfEvent(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branchIfType(target, JSC::JSType(JSEventType));
+}
+
+inline CCallHelpers::Jump branchIfNotEvent(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branchIfNotType(target, JSC::JSType(JSEventType));
+}
+
+inline CCallHelpers::Jump branchIfNode(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::AboveOrEqual,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSNodeType)));
+}
+
+inline CCallHelpers::Jump branchIfNotNode(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::Below,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSNodeType)));
+}
+
+// inline CCallHelpers::Jump branchIfElement(CCallHelpers& jit, GPRReg target)
+// {
+// return jit.branch8(
+// CCallHelpers::Equal,
+// CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+// CCallHelpers::TrustedImm32(JSC::JSType(JSElementType)));
+// }
+
+// inline CCallHelpers::Jump branchIfNotElement(CCallHelpers& jit, GPRReg target)
+// {
+// return jit.branch8(
+// CCallHelpers::NotEqual,
+// CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+// CCallHelpers::TrustedImm32(JSC::JSType(JSElementType)));
+// }
+
+// inline CCallHelpers::Jump branchIfDocumentFragment(CCallHelpers& jit, GPRReg target)
+// {
+// return jit.branchIfType(target, JSC::JSType(JSDocumentFragmentNodeType));
+// }
+
+// inline CCallHelpers::Jump branchIfNotDocumentFragment(CCallHelpers& jit, GPRReg target)
+// {
+// return jit.branchIfNotType(target, JSC::JSType(JSDocumentFragmentNodeType));
+// }
+
+// inline CCallHelpers::Jump branchIfDocumentWrapper(CCallHelpers& jit, GPRReg target)
+// {
+// return jit.branchIfType(target, JSC::JSType(JSDocumentWrapperType));
+// }
+
+// inline CCallHelpers::Jump branchIfNotDocumentWrapper(CCallHelpers& jit, GPRReg target)
+// {
+// return jit.branchIfNotType(target, JSC::JSType(JSDocumentWrapperType));
+// }
+
+// void loadDocument(MacroAssembler&, GPRReg node, GPRReg output);
+// void loadDocumentElement(MacroAssembler&, GPRReg document, GPRReg output);
+
+// inline CCallHelpers::Jump branchTestIsElementFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
+// {
+// return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsElement()));
+// }
+
+// inline CCallHelpers::Jump branchTestIsShadowRootFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
+// {
+// return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsShadowRoot()));
+// }
+
+// inline CCallHelpers::Jump branchTestIsElementOrShadowRootFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
+// {
+// return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()),
+// CCallHelpers::TrustedImm32(Node::flagIsShadowRoot() | Node::flagIsElement()));
+// }
+
+// inline CCallHelpers::Jump branchTestIsHTMLFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
+// {
+// return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsHTML()));
+// }
+
+JSC_DECLARE_JIT_OPERATION(operationToJSNode, JSC::EncodedJSValue, (JSC::JSGlobalObject*, void*));
+JSC_DECLARE_JIT_OPERATION(operationToJSContainerNode, JSC::EncodedJSValue, (JSC::JSGlobalObject*, void*));
+// JSC_DECLARE_JIT_OPERATION(operationToJSElement, JSC::EncodedJSValue, (JSC::JSGlobalObject*, void*));
+// JSC_DECLARE_JIT_OPERATION(operationToJSHTMLElement, JSC::EncodedJSValue, (JSC::JSGlobalObject*, void*));
+// JSC_DECLARE_JIT_OPERATION(operationToJSDocument, JSC::EncodedJSValue, (JSC::JSGlobalObject*, void*));
+
+}
+}
+
+IGNORE_WARNINGS_END
+
+#endif
diff --git a/src/bun.js/bindings/webcore/DOMJITIDLConvert.h b/src/bun.js/bindings/webcore/DOMJITIDLConvert.h
new file mode 100644
index 000000000..81395e125
--- /dev/null
+++ b/src/bun.js/bindings/webcore/DOMJITIDLConvert.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+
+namespace WebCore { namespace DOMJIT {
+
+template<typename IDLType>
+struct DirectConverter;
+
+template<>
+struct DirectConverter<IDLDOMString> {
+ static String directConvert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSString* string)
+ {
+ return string->value(&lexicalGlobalObject);
+ }
+};
+
+template<>
+struct DirectConverter<IDLAtomStringAdaptor<IDLDOMString>> {
+ static AtomString directConvert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSString* string)
+ {
+ return string->toAtomString(&lexicalGlobalObject);
+ }
+};
+
+template<>
+struct DirectConverter<IDLRequiresExistingAtomStringAdaptor<IDLDOMString>> {
+ static AtomString directConvert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSString* string)
+ {
+ return string->toExistingAtomString(&lexicalGlobalObject);
+ }
+};
+
+} }
diff --git a/src/bun.js/bindings/webcore/DOMJITIDLType.h b/src/bun.js/bindings/webcore/DOMJITIDLType.h
new file mode 100644
index 000000000..219468875
--- /dev/null
+++ b/src/bun.js/bindings/webcore/DOMJITIDLType.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+
+namespace WebCore { namespace DOMJIT {
+
+template<typename IDLType>
+struct IDLJSArgumentTypeSelect;
+
+template<> struct IDLJSArgumentTypeSelect<IDLBoolean> { typedef bool type; };
+template<> struct IDLJSArgumentTypeSelect<IDLByte> { typedef int32_t type; };
+template<> struct IDLJSArgumentTypeSelect<IDLOctet> { typedef int32_t type; };
+template<> struct IDLJSArgumentTypeSelect<IDLShort> { typedef int32_t type; };
+template<> struct IDLJSArgumentTypeSelect<IDLUnsignedShort> { typedef int32_t type; };
+template<> struct IDLJSArgumentTypeSelect<IDLLong> { typedef int32_t type; };
+template<> struct IDLJSArgumentTypeSelect<IDLDOMString> { typedef JSC::JSString* type; };
+template<> struct IDLJSArgumentTypeSelect<IDLUint8Array> { typedef JSC::JSUint8Array* type; };
+template<> struct IDLJSArgumentTypeSelect<IDLObject> { typedef JSC::JSObject* type; };
+template<> struct IDLJSArgumentTypeSelect<IDLAtomStringAdaptor<IDLDOMString>> { typedef JSC::JSString* type; };
+template<> struct IDLJSArgumentTypeSelect<IDLRequiresExistingAtomStringAdaptor<IDLDOMString>> { typedef JSC::JSString* type; };
+
+template<typename IDLType>
+using IDLJSArgumentType = typename IDLJSArgumentTypeSelect<IDLType>::type;
+
+} }
diff --git a/src/bun.js/bindings/webcore/DOMJITIDLTypeFilter.h b/src/bun.js/bindings/webcore/DOMJITIDLTypeFilter.h
new file mode 100644
index 000000000..7728db7d2
--- /dev/null
+++ b/src/bun.js/bindings/webcore/DOMJITIDLTypeFilter.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include <JavaScriptCore/SpeculatedType.h>
+
+namespace WebCore { namespace DOMJIT {
+
+template<typename IDLType>
+struct IDLArgumentTypeFilter;
+
+template<> struct IDLArgumentTypeFilter<IDLBoolean> { static const constexpr JSC::SpeculatedType value = JSC::SpecBoolean; };
+template<> struct IDLArgumentTypeFilter<IDLByte> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLArgumentTypeFilter<IDLOctet> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLArgumentTypeFilter<IDLShort> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLArgumentTypeFilter<IDLUnsignedShort> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLArgumentTypeFilter<IDLLong> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLArgumentTypeFilter<IDLDOMString> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLArgumentTypeFilter<IDLAtomStringAdaptor<IDLDOMString>> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLArgumentTypeFilter<IDLRequiresExistingAtomStringAdaptor<IDLDOMString>> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLArgumentTypeFilter<IDLUint8Array> { static const constexpr JSC::SpeculatedType value = JSC::SpecUint8Array; };
+
+template<typename IDLType>
+struct IDLResultTypeFilter {
+ static const constexpr JSC::SpeculatedType value = JSC::SpecFullTop;
+};
+
+template<> struct IDLResultTypeFilter<IDLAny> { static const constexpr JSC::SpeculatedType value = JSC::SpecHeapTop; };
+template<> struct IDLResultTypeFilter<IDLBoolean> { static const constexpr JSC::SpeculatedType value = JSC::SpecBoolean; };
+template<> struct IDLResultTypeFilter<IDLByte> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLResultTypeFilter<IDLOctet> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLResultTypeFilter<IDLShort> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLResultTypeFilter<IDLUnsignedShort> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLResultTypeFilter<IDLLong> { static const constexpr JSC::SpeculatedType value = JSC::SpecInt32Only; };
+template<> struct IDLResultTypeFilter<IDLUnsignedLong> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeNumber; };
+template<> struct IDLResultTypeFilter<IDLLongLong> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeNumber; };
+template<> struct IDLResultTypeFilter<IDLUnsignedLongLong> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeNumber; };
+template<> struct IDLResultTypeFilter<IDLFloat> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeNumber; };
+template<> struct IDLResultTypeFilter<IDLUnrestrictedFloat> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeNumber; };
+template<> struct IDLResultTypeFilter<IDLDouble> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeNumber; };
+template<> struct IDLResultTypeFilter<IDLUnrestrictedDouble> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeNumber; };
+template<> struct IDLResultTypeFilter<IDLDOMString> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLResultTypeFilter<IDLByteString> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLResultTypeFilter<IDLUSVString> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLResultTypeFilter<IDLAtomStringAdaptor<IDLDOMString>> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLResultTypeFilter<IDLRequiresExistingAtomStringAdaptor<IDLDOMString>> { static const constexpr JSC::SpeculatedType value = JSC::SpecString; };
+template<> struct IDLResultTypeFilter<IDLUint8Array> { static const constexpr JSC::SpeculatedType value = JSC::SpecUint8Array; };
+template<> struct IDLResultTypeFilter<IDLObject> { static const constexpr JSC::SpeculatedType value = JSC::SpecBytecodeTop; };
+
+
+template<typename T>
+struct IDLResultTypeFilter<IDLNullable<T>> {
+ static const constexpr JSC::SpeculatedType value = JSC::SpecOther | IDLResultTypeFilter<T>::value;
+};
+
+} }
diff --git a/src/bun.js/bindings/webcore/JSEventDOMJIT.cpp b/src/bun.js/bindings/webcore/JSEventDOMJIT.cpp
new file mode 100644
index 000000000..f6c6b77d8
--- /dev/null
+++ b/src/bun.js/bindings/webcore/JSEventDOMJIT.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSEvent.h"
+
+#if ENABLE(JIT)
+
+#include "DOMJITCheckDOM.h"
+
+
+namespace WebCore {
+using namespace JSC;
+
+Ref<JSC::Snippet> checkSubClassSnippetForJSEvent()
+{
+ return DOMJIT::checkDOM<Event>();
+}
+
+}
+
+#endif
diff --git a/src/bun.js/bindings/webcore/JSTextEncoder.cpp b/src/bun.js/bindings/webcore/JSTextEncoder.cpp
index c12c94d56..85157758e 100644
--- a/src/bun.js/bindings/webcore/JSTextEncoder.cpp
+++ b/src/bun.js/bindings/webcore/JSTextEncoder.cpp
@@ -43,7 +43,7 @@
#include "JSDOMAttribute.h"
// #include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
-// #include "JSDOMConvertBufferSource.h"
+#include "JSDOMConvertBufferSource.h"
#include "JSDOMConvertInterface.h"
#include "JSDOMConvertNumbers.h"
#include "JSDOMConvertStrings.h"
@@ -55,8 +55,27 @@
// #include "ScriptExecutionContext.h"
// #include "WebCoreJSClientData.h"
+#include <JavaScriptCore/DOMJITAbstractHeap.h>
+#include "DOMJITIDLConvert.h"
+#include "DOMJITIDLType.h"
+#include "DOMJITIDLTypeFilter.h"
+#include "DOMJITHelpers.h"
+#include <JavaScriptCore/DFGAbstractHeap.h>
+
namespace WebCore {
using namespace JSC;
+using namespace JSC::DOMJIT;
+
+extern "C" JSC::EncodedJSValue TextEncoder__encode8(JSC::JSGlobalObject* global, const LChar* stringPtr, size_t stringLen);
+extern "C" JSC::EncodedJSValue TextEncoder__encode16(JSC::JSGlobalObject* global, const UChar* stringPtr, size_t stringLen);
+extern "C" size_t TextEncoder__encodeInto8(const LChar* stringPtr, size_t stringLen, void* ptr, size_t len);
+extern "C" size_t TextEncoder__encodeInto16(const UChar* stringPtr, size_t stringLen, void* ptr, size_t len);
+extern "C" JSC::EncodedJSValue TextEncoder__encodeRopeString(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSString* str);
+
+extern "C" {
+static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsTextEncoderEncodeWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject*, JSTextEncoder*, DOMJIT::IDLJSArgumentType<IDLDOMString>));
+static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSTextEncoder* castedThis, DOMJIT::IDLJSArgumentType<IDLDOMString> source, DOMJIT::IDLJSArgumentType<IDLUint8Array> destination));
+}
template<> TextEncoder::EncodeIntoResult convertDictionary<TextEncoder::EncodeIntoResult>(JSGlobalObject& lexicalGlobalObject, JSValue value)
{
@@ -194,15 +213,97 @@ template<> void JSTextEncoderDOMConstructor::initializeProperties(VM& vm, JSDOMG
putDirect(vm, vm.propertyNames->prototype, JSTextEncoder::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete);
}
+constexpr JSC::DFG::AbstractHeapKind heapKinds[] = { JSC::DFG::HeapObjectCount };
+
+// This is the equivalent of DataView.set
+constexpr JSC::DFG::AbstractHeapKind encodeIntoRead[] = { JSC::DFG::MiscFields, JSC::DFG::TypedArrayProperties };
+constexpr JSC::DFG::AbstractHeapKind encodeIntoWrite[] = { JSC::DFG::TypedArrayProperties };
+
+static const JSC::DOMJIT::Signature DOMJITSignatureForJSTextEncoderEncodeWithoutTypeCheck(
+ jsTextEncoderEncodeWithoutTypeCheck,
+ JSTextEncoder::info(),
+ JSC::DOMJIT::Effect::forReadWriteDFG<1, 1>(heapKinds, heapKinds),
+ DOMJIT::IDLResultTypeFilter<IDLUint8Array>::value,
+ DOMJIT::IDLArgumentTypeFilter<IDLDOMString>::value);
+
+static const JSC::DOMJIT::Signature DOMJITSignatureForJSTextEncoderEncodeIntoWithoutTypeCheck(
+ jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeCheck,
+ JSTextEncoder::info(),
+ // this is slightly incorrect
+ // there could be cases where the object returned by encodeInto will appear to be reused
+ // it impacts HeapObjectCount
+ JSC::DOMJIT::Effect::forReadWriteDFG<2, 1>(encodeIntoRead, encodeIntoWrite),
+ DOMJIT::IDLResultTypeFilter<IDLObject>::value,
+ DOMJIT::IDLArgumentTypeFilter<IDLDOMString>::value,
+ DOMJIT::IDLArgumentTypeFilter<IDLUint8Array>::value);
+
/* Hash table for prototype */
static const HashTableValue JSTextEncoderPrototypeTableValues[] = {
{ "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsTextEncoderConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
{ "encoding"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsTextEncoder_encoding), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
- { "encode"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsTextEncoderPrototypeFunction_encode), (intptr_t)(0) } },
- { "encodeInto"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsTextEncoderPrototypeFunction_encodeInto), (intptr_t)(2) } },
+ { "encode"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsTextEncoderPrototypeFunction_encode), (intptr_t) static_cast<const JSC::DOMJIT::Signature*>(&DOMJITSignatureForJSTextEncoderEncodeWithoutTypeCheck) } },
+ { "encodeInto"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsTextEncoderPrototypeFunction_encodeInto), (intptr_t) static_cast<const JSC::DOMJIT::Signature*>(&DOMJITSignatureForJSTextEncoderEncodeIntoWithoutTypeCheck) } },
};
+JSC_DEFINE_JIT_OPERATION(jsTextEncoderEncodeWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSTextEncoder* castedThis, DOMJIT::IDLJSArgumentType<IDLDOMString> input))
+{
+ VM& vm = JSC::getVM(lexicalGlobalObject);
+ IGNORE_WARNINGS_BEGIN("frame-address")
+ CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+ IGNORE_WARNINGS_END
+ JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ EncodedJSValue res;
+ String str;
+ if (input->is8Bit()) {
+ if (input->isRope()) {
+ auto encodedValue = TextEncoder__encodeRopeString(lexicalGlobalObject, input);
+ if (!JSC::JSValue::decode(encodedValue).isUndefined()) {
+ RELEASE_AND_RETURN(throwScope, encodedValue);
+ }
+ }
+
+ str = input->value(lexicalGlobalObject);
+ res = TextEncoder__encode8(lexicalGlobalObject, str.characters8(), str.length());
+ } else {
+ str = input->value(lexicalGlobalObject);
+ res = TextEncoder__encode16(lexicalGlobalObject, str.characters16(), str.length());
+ }
+
+ if (UNLIKELY(JSC::JSValue::decode(res).isObject() && JSC::JSValue::decode(res).getObject()->isErrorInstance())) {
+ throwScope.throwException(lexicalGlobalObject, JSC::JSValue::decode(res));
+ return encodedJSValue();
+ }
+
+ RELEASE_AND_RETURN(throwScope, res);
+}
+
+JSC_DEFINE_JIT_OPERATION(jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSTextEncoder* castedThis, DOMJIT::IDLJSArgumentType<IDLDOMString> sourceStr, DOMJIT::IDLJSArgumentType<IDLUint8Array> destination))
+{
+ VM& vm = JSC::getVM(lexicalGlobalObject);
+ IGNORE_WARNINGS_BEGIN("frame-address")
+ CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+ IGNORE_WARNINGS_END
+ JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+ auto source = sourceStr->value(lexicalGlobalObject);
+ size_t res = 0;
+ if (!source.is8Bit()) {
+ res = TextEncoder__encodeInto16(source.characters16(), source.length(), destination->vector(), destination->length());
+ } else {
+ res = TextEncoder__encodeInto8(source.characters8(), source.length(), destination->vector(), destination->length());
+ }
+
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto clientData = WebCore::clientData(vm);
+
+ auto* result = JSC::constructEmptyObject(globalObject, globalObject->encodeIntoObjectPrototype(), 2);
+ result->putDirect(vm, clientData->builtinNames().readPublicName(), JSC::jsNumber(static_cast<uint32_t>(res)), 0);
+ result->putDirect(vm, clientData->builtinNames().writtenPublicName(), JSC::jsNumber(static_cast<uint32_t>(res >> 32)), 0);
+
+ return JSValue::encode(result);
+}
+
const ClassInfo JSTextEncoderPrototype::s_info = { "TextEncoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTextEncoderPrototype) };
void JSTextEncoderPrototype::finishCreation(VM& vm)
@@ -271,10 +372,6 @@ JSC_DEFINE_CUSTOM_GETTER(jsTextEncoder_encoding, (JSGlobalObject * lexicalGlobal
return IDLAttribute<JSTextEncoder>::get<jsTextEncoder_encodingGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName);
}
-extern "C" JSC::EncodedJSValue TextEncoder__encode(JSC::JSGlobalObject* lexicalGlobalObject, const ZigString*);
-extern "C" JSC::EncodedJSValue TextEncoder__encodeInto(JSC::JSGlobalObject* lexicalGlobalObject, const ZigString*, void* ptr, size_t len);
-extern "C" JSC::EncodedJSValue TextEncoder__encodeRopeString(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSString* str);
-
static inline JSC::EncodedJSValue jsTextEncoderPrototypeFunction_encodeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSTextEncoder>::ClassParameter castedThis)
{
auto& vm = JSC::getVM(lexicalGlobalObject);
@@ -283,19 +380,28 @@ static inline JSC::EncodedJSValue jsTextEncoderPrototypeFunction_encodeBody(JSC:
UNUSED_PARAM(callFrame);
EnsureStillAliveScope argument0 = callFrame->argument(0);
JSC::JSString* input = argument0.value().toStringOrNull(lexicalGlobalObject);
- if (input && input->is8Bit() && input->isRope()) {
- auto encodedValue = TextEncoder__encodeRopeString(lexicalGlobalObject, input);
- if (!JSC::JSValue::decode(encodedValue).isUndefined()) {
- RELEASE_AND_RETURN(throwScope, encodedValue);
+ EncodedJSValue res;
+ String str;
+ if (input->is8Bit()) {
+ if (input->isRope()) {
+ auto encodedValue = TextEncoder__encodeRopeString(lexicalGlobalObject, input);
+ if (!JSC::JSValue::decode(encodedValue).isUndefined()) {
+ RELEASE_AND_RETURN(throwScope, encodedValue);
+ }
}
+
+ str = input->value(lexicalGlobalObject);
+ res = TextEncoder__encode8(lexicalGlobalObject, str.characters8(), str.length());
+ } else {
+ str = input->value(lexicalGlobalObject);
+ res = TextEncoder__encode16(lexicalGlobalObject, str.characters16(), str.length());
}
- auto str = Zig::toZigString(input->tryGetValue(lexicalGlobalObject));
- auto res = TextEncoder__encode(lexicalGlobalObject, &str);
if (UNLIKELY(JSC::JSValue::decode(res).isObject() && JSC::JSValue::decode(res).getObject()->isErrorInstance())) {
throwScope.throwException(lexicalGlobalObject, JSC::JSValue::decode(res));
return encodedJSValue();
}
+
RELEASE_AND_RETURN(throwScope, res);
}
@@ -323,15 +429,21 @@ static inline JSC::EncodedJSValue jsTextEncoderPrototypeFunction_encodeIntoBody(
return encodedJSValue();
}
- RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- auto str = Zig::toZigString(WTFMove(source));
- auto res = TextEncoder__encodeInto(lexicalGlobalObject, &str, destination->vector(), destination->length());
- if (UNLIKELY(JSC::JSValue::decode(res).isObject() && JSC::JSValue::decode(res).getObject()->isErrorInstance())) {
- throwScope.throwException(lexicalGlobalObject, JSC::JSValue::decode(res));
- return encodedJSValue();
+ size_t res = 0;
+ if (!source.is8Bit()) {
+ res = TextEncoder__encodeInto16(source.characters16(), source.length(), destination->vector(), destination->length());
+ } else {
+ res = TextEncoder__encodeInto8(source.characters8(), source.length(), destination->vector(), destination->length());
}
- RELEASE_AND_RETURN(throwScope, res);
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto clientData = WebCore::clientData(vm);
+
+ auto* result = JSC::constructEmptyObject(globalObject, globalObject->encodeIntoObjectPrototype(), 2);
+ result->putDirect(vm, clientData->builtinNames().readPublicName(), JSC::jsNumber(static_cast<uint32_t>(res)), 0);
+ result->putDirect(vm, clientData->builtinNames().writtenPublicName(), JSC::jsNumber(static_cast<uint32_t>(res >> 32)), 0);
+
+ return JSValue::encode(result);
}
JSC_DEFINE_HOST_FUNCTION(jsTextEncoderPrototypeFunction_encodeInto, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
@@ -419,5 +531,4 @@ TextEncoder* JSTextEncoder::toWrapped(JSC::VM&, JSC::JSValue value)
return &wrapper->wrapped();
return nullptr;
}
-
}
diff --git a/src/bun.js/builtins/BunBuiltinNames.h b/src/bun.js/builtins/BunBuiltinNames.h
index cd350f999..b646211eb 100644
--- a/src/bun.js/builtins/BunBuiltinNames.h
+++ b/src/bun.js/builtins/BunBuiltinNames.h
@@ -237,6 +237,7 @@ using namespace JSC;
macro(writeRequests) \
macro(writer) \
macro(writing) \
+ macro(written) \
BUN_ADDITIONAL_PRIVATE_IDENTIFIERS(macro) \
class BunBuiltinNames {
diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig
index b3bea11e5..6e06a06f4 100644
--- a/src/bun.js/webcore/encoding.zig
+++ b/src/bun.js/webcore/encoding.zig
@@ -45,9 +45,10 @@ pub const TextEncoder = struct {
const utf8_string: string = "utf-8";
- pub export fn TextEncoder__encode(
+ pub export fn TextEncoder__encode8(
globalThis: *JSGlobalObject,
- zig_str: *const ZigString,
+ ptr: [*]const u8,
+ len: usize,
) JSValue {
// as much as possible, rely on JSC to own the memory
// their code is more battle-tested than bun's code
@@ -58,52 +59,63 @@ pub const TextEncoder = struct {
// so it's extra good for that case
// this also means there won't be reallocations for small strings
var buf: [2048]u8 = undefined;
-
- var ctx = globalThis.ref();
- if (zig_str.is16Bit()) {
- const slice = zig_str.utf16Slice();
- // max utf16 -> utf8 length
- if (slice.len <= buf.len / 4) {
- const result = strings.copyUTF16IntoUTF8(&buf, @TypeOf(slice), slice);
- const uint8array = JSC.JSValue.createUninitializedUint8Array(globalThis, result.written);
- std.debug.assert(result.written <= buf.len);
- std.debug.assert(result.read == slice.len);
- const array_buffer = uint8array.asArrayBuffer(globalThis).?;
- std.debug.assert(result.written == array_buffer.len);
- @memcpy(array_buffer.slice().ptr, &buf, result.written);
- return uint8array;
- } else {
- var bytes = strings.toUTF8AllocWithType(
- default_allocator,
- @TypeOf(slice),
- slice,
- ) catch {
- return JSC.toInvalidArguments("Out of memory", .{}, ctx);
- };
- return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(ctx, null);
- }
+ const slice = ptr[0..len];
+
+ if (slice.len <= buf.len / 2) {
+ const result = strings.copyLatin1IntoUTF8(&buf, []const u8, slice);
+ const uint8array = JSC.JSValue.createUninitializedUint8Array(globalThis, result.written);
+ std.debug.assert(result.written <= buf.len);
+ std.debug.assert(result.read == slice.len);
+ const array_buffer = uint8array.asArrayBuffer(globalThis).?;
+ std.debug.assert(result.written == array_buffer.len);
+ @memcpy(array_buffer.slice().ptr, &buf, result.written);
+ return uint8array;
} else {
- const slice = zig_str.slice();
-
- if (slice.len <= buf.len / 2) {
- const result = strings.copyLatin1IntoUTF8(&buf, []const u8, slice);
- const uint8array = JSC.JSValue.createUninitializedUint8Array(globalThis, result.written);
- std.debug.assert(result.written <= buf.len);
- std.debug.assert(result.read == slice.len);
- const array_buffer = uint8array.asArrayBuffer(globalThis).?;
- std.debug.assert(result.written == array_buffer.len);
- @memcpy(array_buffer.slice().ptr, &buf, result.written);
- return uint8array;
- } else {
- const bytes = strings.allocateLatin1IntoUTF8(globalThis.bunVM().allocator, []const u8, slice) catch {
- return JSC.toInvalidArguments("Out of memory", .{}, ctx);
- };
- std.debug.assert(bytes.len >= slice.len);
- return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(ctx, null);
- }
+ const bytes = strings.allocateLatin1IntoUTF8(globalThis.bunVM().allocator, []const u8, slice) catch {
+ return JSC.toInvalidArguments("Out of memory", .{}, globalThis);
+ };
+ std.debug.assert(bytes.len >= slice.len);
+ return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis, null);
}
+ }
+
+ pub export fn TextEncoder__encode16(
+ globalThis: *JSGlobalObject,
+ ptr: [*]const u16,
+ len: usize,
+ ) JSValue {
+ // as much as possible, rely on JSC to own the memory
+ // their code is more battle-tested than bun's code
+ // so we do a stack allocation here
+ // and then copy into JSC memory
+ // unless it's huge
+ // JSC will GC Uint8Array that occupy less than 512 bytes
+ // so it's extra good for that case
+ // this also means there won't be reallocations for small strings
+ var buf: [2048]u8 = undefined;
- unreachable;
+ const slice = ptr[0..len];
+
+ // max utf16 -> utf8 length
+ if (slice.len <= buf.len / 4) {
+ const result = strings.copyUTF16IntoUTF8(&buf, @TypeOf(slice), slice);
+ const uint8array = JSC.JSValue.createUninitializedUint8Array(globalThis, result.written);
+ std.debug.assert(result.written <= buf.len);
+ std.debug.assert(result.read == slice.len);
+ const array_buffer = uint8array.asArrayBuffer(globalThis).?;
+ std.debug.assert(result.written == array_buffer.len);
+ @memcpy(array_buffer.slice().ptr, &buf, result.written);
+ return uint8array;
+ } else {
+ var bytes = strings.toUTF8AllocWithType(
+ default_allocator,
+ @TypeOf(slice),
+ slice,
+ ) catch {
+ return JSC.toInvalidArguments("Out of memory", .{}, globalThis);
+ };
+ return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis, null);
+ }
}
// This is a fast path for copying a Rope string into a Uint8Array.
@@ -194,31 +206,41 @@ pub const TextEncoder = struct {
return array;
}
- const read_key = ZigString.init("read");
- const written_key = ZigString.init("written");
+ pub export fn TextEncoder__encodeInto16(
+ input_ptr: [*]const u16,
+ input_len: usize,
+ buf_ptr: [*]u8,
+ buf_len: usize,
+ ) u64 {
+ var output = buf_ptr[0..buf_len];
+ const input = input_ptr[0..input_len];
+ const result: strings.EncodeIntoResult =
+ strings.copyUTF16IntoUTF8(output, []const u16, input);
+ const sized: [2]u32 = .{ result.read, result.written };
+ return @bitCast(u64, sized);
+ }
- pub export fn TextEncoder__encodeInto(
- globalThis: *JSC.JSGlobalObject,
- input: *const ZigString,
+ pub export fn TextEncoder__encodeInto8(
+ input_ptr: [*]const u8,
+ input_len: usize,
buf_ptr: [*]u8,
buf_len: usize,
- ) JSC.JSValue {
+ ) u64 {
var output = buf_ptr[0..buf_len];
- var result: strings.EncodeIntoResult = strings.EncodeIntoResult{ .read = 0, .written = 0 };
- if (input.is16Bit()) {
- const utf16_slice = input.utf16Slice();
- result = strings.copyUTF16IntoUTF8(output, @TypeOf(utf16_slice), utf16_slice);
- } else {
- result = strings.copyLatin1IntoUTF8(output, @TypeOf(input.slice()), input.slice());
- }
- return JSC.JSValue.createObject2(globalThis, &read_key, &written_key, JSValue.jsNumber(result.read), JSValue.jsNumber(result.written));
+ const input = input_ptr[0..input_len];
+ const result: strings.EncodeIntoResult =
+ strings.copyLatin1IntoUTF8(output, []const u8, input);
+ const sized: [2]u32 = .{ result.read, result.written };
+ return @bitCast(u64, sized);
}
};
comptime {
if (!JSC.is_bindgen) {
- _ = TextEncoder.TextEncoder__encode;
- _ = TextEncoder.TextEncoder__encodeInto;
+ _ = TextEncoder.TextEncoder__encode8;
+ _ = TextEncoder.TextEncoder__encode16;
+ _ = TextEncoder.TextEncoder__encodeInto8;
+ _ = TextEncoder.TextEncoder__encodeInto16;
_ = TextEncoder.TextEncoder__encodeRopeString;
}
}