diff options
-rw-r--r-- | bench/snippets/buffer-create.mjs | 18 | ||||
-rw-r--r-- | src/bun.js/bindings/JSBuffer.cpp | 67 |
2 files changed, 64 insertions, 21 deletions
diff --git a/bench/snippets/buffer-create.mjs b/bench/snippets/buffer-create.mjs index 28eb4ce0f..0af800431 100644 --- a/bench/snippets/buffer-create.mjs +++ b/bench/snippets/buffer-create.mjs @@ -1,6 +1,22 @@ import { bench, run } from "mitata"; const N = parseInt(process.argv.slice(2).at(0) || "10", 10); +var isBuffer = new Buffer(0); +var isNOtBuffer = "not a buffer"; + +bench("Buffer.isBuffer(buffer)", () => { + return Buffer.isBuffer(isBuffer); +}); + +{ + var j = 0; + j += 1; + j += eval("'ok'"); + + bench("Buffer.isBuffer(string)", () => { + return Buffer.isBuffer(j); + }); +} bench("Buffer.from('short string')", () => { return Buffer.from("short string"); @@ -45,4 +61,4 @@ bench("Buffer.alloc(24_000)", () => { return Buffer.alloc(24_000); }); -await run(); +await run({}); diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index bd2975e14..5830f731e 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -115,18 +115,6 @@ static JSUint8Array* allocBufferUnsafe(JSC::JSGlobalObject* lexicalGlobalObject, return uint8Array; } -bool JSBuffer__isBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value) -{ - JSC::VM& vm = lexicalGlobalObject->vm(); - auto clientData = WebCore::clientData(vm); - - auto* jsBuffer = JSC::jsDynamicCast<JSC::JSUint8Array*>(JSC::JSValue::decode(value)); - if (!jsBuffer) - return false; - - return jsBuffer->hasProperty(lexicalGlobalObject, clientData->builtinNames().dataViewPrivateName()); -} - // Normalize val to be an integer in the range of [1, -1] since // implementations of memcmp() can vary by platform. static int normalizeCompareVal(int val, size_t a_length, size_t b_length) @@ -378,8 +366,8 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG auto* subclassStructure = globalObject->JSBufferSubclassStructure(); // fill argument - if (callFrame->argumentCount() > 1) { - auto uint8Array = JSC::JSUint8Array::createUninitialized(lexicalGlobalObject, subclassStructure, length); + if (UNLIKELY(callFrame->argumentCount() > 1)) { + auto* uint8Array = JSC::JSUint8Array::createUninitialized(lexicalGlobalObject, subclassStructure, length); auto value = callFrame->argument(1); @@ -422,12 +410,12 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); } } else { - auto arrayBuffer = JSC::ArrayBuffer::tryCreate(length, 1); - if (!arrayBuffer) { + auto* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, length); + if (UNLIKELY(!uint8Array)) { throwOutOfMemoryError(lexicalGlobalObject, throwScope); - return JSValue::encode(jsUndefined()); + return JSC::JSValue::encode(jsUndefined()); } - auto uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(arrayBuffer), 0, length); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); } } @@ -1559,6 +1547,24 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_concat, (JSGlobalObject * l extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsBufferConstructorAllocWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int size)); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsBufferConstructorAllocUnsafeWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int size)); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsBufferConstructorAllocUnsafeSlowWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int size)); +extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsBufferConstructorIsBufferWithoutTypeChecks, JSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void*, JSUint8Array* value)); + +static bool isBufferWithCell(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSUint8Array* cell) +{ + auto& vm = lexicalGlobalObject->vm(); + JSValue prototype = cell->getPrototype(vm, lexicalGlobalObject); + return prototype.inherits<JSBufferPrototype>(); +} + +JSC_DEFINE_JIT_OPERATION(jsBufferConstructorIsBufferWithoutTypeChecks, JSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* ctx, JSUint8Array* thisValue)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + IGNORE_WARNINGS_BEGIN("frame-address") + CallFrame* callFrame = DECLARE_CALL_FRAME(vm); + IGNORE_WARNINGS_END + JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); + return jsBoolean(isBufferWithCell(lexicalGlobalObject, thisValue)); +} JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int byteLength)) { @@ -1763,7 +1769,6 @@ void JSBufferPrototype::finishCreation(VM& vm, JSC::JSGlobalObject* globalThis) Base::finishCreation(vm); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); auto clientData = WebCore::clientData(vm); - this->putDirect(vm, clientData->builtinNames().dataViewPrivateName(), JSC::jsUndefined(), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); reifyStaticProperties(vm, JSBuffer::info(), JSBufferPrototypeTableValues, *this); } @@ -1781,6 +1786,11 @@ static const JSC::DOMJIT::Signature DOMJITSignaturejsBufferConstructorAlloc(jsBu JSC::DOMJIT::Effect::forWriteKinds(JSC::DFG::AbstractHeapKind::Heap), JSC::SpecUint8Array, JSC::SpecInt32Only); +static const JSC::DOMJIT::Signature DOMJITSignaturejsBufferConstructorIsBuffer(jsBufferConstructorIsBufferWithoutTypeChecks, + JSBufferConstructor::info(), + JSC::DOMJIT::Effect::forPure(), + JSC::SpecOther, JSC::SpecUint8Array); + static const JSC::DOMJIT::Signature DOMJITSignaturejsBufferConstructorAllocUnsafe(jsBufferConstructorAllocUnsafeWithoutTypeChecks, JSBufferConstructor::info(), JSC::DOMJIT::Effect::forWriteKinds(JSC::DFG::AbstractHeapKind::Heap), @@ -1802,7 +1812,7 @@ static const HashTableValue JSBufferConstructorTableValues[] = { { "compare"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_compare, 2 } }, { "concat"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_concat, 2 } }, { "from"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferConstructorFromCodeGenerator, 1 } }, - { "isBuffer"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_isBuffer, 1 } }, + { "isBuffer"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsBufferConstructorFunction_isBuffer, &DOMJITSignaturejsBufferConstructorIsBuffer } }, { "toBuffer"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_toBuffer, 1 } }, { "isEncoding"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_isEncoding, 1 } }, }; @@ -1976,3 +1986,20 @@ JSC_DEFINE_HOST_FUNCTION(constructJSBuffer, (JSC::JSGlobalObject * lexicalGlobal RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(object)); } + +bool JSBuffer__isBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value) +{ + JSC::VM& vm = lexicalGlobalObject->vm(); + auto clientData = WebCore::clientData(vm); + + JSC::JSValue jsValue = JSC::JSValue::decode(value); + if (!jsValue || !jsValue.isCell()) + return false; + + JSC::JSUint8Array* cell = jsDynamicCast<JSC::JSUint8Array*>(jsValue.asCell()); + if (!cell) + return false; + + JSValue prototype = cell->getPrototype(vm, lexicalGlobalObject); + return prototype.inherits<JSBufferPrototype>(); +}
\ No newline at end of file |