diff --git a/bench/snippets/error-capturestack.mjs b/bench/snippets/error-capturestack.mjs new file mode 100644 index 00000000000000..0c59ff9c84aa58 --- /dev/null +++ b/bench/snippets/error-capturestack.mjs @@ -0,0 +1,12 @@ +import { bench, run } from "./runner.mjs"; + +var err = new Error(); +bench("Error.captureStackTrace(err)", () => { + Error.captureStackTrace(err); +}); + +bench("Error.prototype.stack", () => { + new Error().stack; +}); + +await run(); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 91d365af6c2813..61444668fe6ecf 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -390,6 +390,7 @@ static String computeErrorInfoWithoutPrepareStackTrace(JSC::VM& vm, Vector(lexicalGlobalObject); JSC::Structure* callSiteStructure = globalObject->callSiteStructure(); - JSC::IndexingType callSitesIndexingType = callSites->indexingType(); size_t framesCount = stackTrace.size(); for (size_t i = 0; i < framesCount; i++) { - /* Note that we're using initializeIndex and not callSites->butterfly()->contiguous().data() - * directly, since if we're "having a bad time" (globalObject->isHavingABadTime()), - * the array won't be contiguous, but a "slow put" array. - * See https://github.com/WebKit/webkit/commit/1c4a32c94c1f6c6aa35cf04a2b40c8fe29754b8e for more info - * about what's a "bad time". */ CallSite* callSite = CallSite::create(lexicalGlobalObject, callSiteStructure, stackTrace.at(i), encounteredStrictFrame); - callSites->initializeIndex(objectScope, i, callSite, callSitesIndexingType); + callSites->putDirectIndex(lexicalGlobalObject, i, callSite); if (!encounteredStrictFrame) { encounteredStrictFrame = callSite->isStrict(); @@ -2815,10 +2812,6 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb JSC::JSObject* errorObject = objectArg.asCell()->getObject(); JSC::JSValue caller = callFrame->argument(1); - // We cannot use our ErrorInstance::captureStackTrace() fast path here unfortunately. - // We need to return these CallSite array objects which means we need to create them - JSValue errorValue = lexicalGlobalObject->get(lexicalGlobalObject, vm.propertyNames->Error); - auto* errorConstructor = jsDynamicCast(errorValue); size_t stackTraceLimit = globalObject->stackTraceLimit().value(); if (stackTraceLimit == 0) { stackTraceLimit = DEFAULT_ERROR_STACK_TRACE_LIMIT; @@ -2826,17 +2819,13 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb JSCStackTrace stackTrace = JSCStackTrace::captureCurrentJSStackTrace(globalObject, callFrame, stackTraceLimit, caller); - // Create an (uninitialized) array for our "call sites" - JSC::GCDeferralContext deferralContext(vm); - JSC::ObjectInitializationScope objectScope(vm); - JSC::JSArray* callSites = JSC::JSArray::tryCreateUninitializedRestricted(objectScope, - &deferralContext, + // Note: we cannot use tryCreateUninitializedRestricted here because we cannot allocate memory inside initializeIndex() + JSC::JSArray* callSites = JSC::JSArray::create(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous), stackTrace.size()); - RELEASE_ASSERT(callSites); // Create the call sites (one per frame) - GlobalObject::createCallSitesFromFrames(lexicalGlobalObject, objectScope, stackTrace, callSites); + GlobalObject::createCallSitesFromFrames(lexicalGlobalObject, stackTrace, callSites); /* Foramt the stack trace. * Note that v8 won't actually format the stack trace here, but will create a "stack" accessor @@ -2847,6 +2836,7 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb size_t framesCount = stackTrace.size(); ZigStackFrame remappedFrames[framesCount]; for (int i = 0; i < framesCount; i++) { + memset(remappedFrames + i, 0, sizeof(ZigStackFrame)); remappedFrames[i].source_url = Bun::toString(lexicalGlobalObject, stackTrace.at(i).sourceURL()); if (JSCStackFrame::SourcePositions* sourcePositions = stackTrace.at(i).getSourcePositions()) { remappedFrames[i].position.line = sourcePositions->line.zeroBasedInt(); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index f44212da1dbdb3..0b5c882f5c0421 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -166,7 +166,7 @@ class GlobalObject : public JSC::JSGlobalObject { void clearDOMGuardedObjects(); - static void createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ObjectInitializationScope& objectScope, JSCStackTrace& stackTrace, JSC::JSArray* callSites); + static void createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites); JSC::JSValue formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites); static void reportUncaughtExceptionAtEventLoop(JSGlobalObject*, JSC::Exception*);