mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 22:01:47 +00:00
1012 lines
40 KiB
Objective-C
1012 lines
40 KiB
Objective-C
#include "root.h"
|
|
#include "_NativeModule.h"
|
|
|
|
#include "ExceptionOr.h"
|
|
#include "JavaScriptCore/CallData.h"
|
|
#include "JavaScriptCore/ArgList.h"
|
|
#include "JavaScriptCore/ExceptionScope.h"
|
|
#include "JavaScriptCore/JSCJSValue.h"
|
|
#include "JavaScriptCore/JSGlobalObject.h"
|
|
#include "JavaScriptCore/JSNativeStdFunction.h"
|
|
#include "MessagePort.h"
|
|
#include "SerializedScriptValue.h"
|
|
#include <JavaScriptCore/APICast.h>
|
|
#include <JavaScriptCore/AggregateError.h>
|
|
#include <JavaScriptCore/BytecodeIndex.h>
|
|
#include <JavaScriptCore/CallFrameInlines.h>
|
|
#include <JavaScriptCore/ClassInfo.h>
|
|
#include <JavaScriptCore/CodeBlock.h>
|
|
#include <JavaScriptCore/Completion.h>
|
|
#include <JavaScriptCore/DeferTermination.h>
|
|
#include <JavaScriptCore/Error.h>
|
|
#include <JavaScriptCore/ErrorInstance.h>
|
|
#include <JavaScriptCore/HeapSnapshotBuilder.h>
|
|
#include <JavaScriptCore/JIT.h>
|
|
#include <JavaScriptCore/JSBasePrivate.h>
|
|
#include <JavaScriptCore/JSCInlines.h>
|
|
#include <JavaScriptCore/JSONObject.h>
|
|
#include <JavaScriptCore/JSPromise.h>
|
|
#include <JavaScriptCore/JavaScript.h>
|
|
#include <JavaScriptCore/ObjectConstructor.h>
|
|
#include <JavaScriptCore/SamplingProfiler.h>
|
|
#include <JavaScriptCore/TestRunnerUtils.h>
|
|
#include <JavaScriptCore/VMTrapsInlines.h>
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <wtf/FileSystem.h>
|
|
#include <wtf/MemoryFootprint.h>
|
|
#include <wtf/text/WTFString.h>
|
|
|
|
#include "BunProcess.h"
|
|
#include <JavaScriptCore/SourceProviderCache.h>
|
|
#if ENABLE(REMOTE_INSPECTOR)
|
|
#include <JavaScriptCore/RemoteInspectorServer.h>
|
|
#endif
|
|
|
|
#include "JSDOMConvertBase.h"
|
|
#include "ZigSourceProvider.h"
|
|
#include "mimalloc.h"
|
|
|
|
#include <JavaScriptCore/ControlFlowProfiler.h>
|
|
|
|
#if OS(DARWIN)
|
|
#if ASSERT_ENABLED
|
|
#if !__has_feature(address_sanitizer)
|
|
#include <malloc/malloc.h>
|
|
#define IS_MALLOC_DEBUGGING_ENABLED 1
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
using namespace JSC;
|
|
using namespace WTF;
|
|
using namespace WebCore;
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionStartRemoteDebugger);
|
|
JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
#if ENABLE(REMOTE_INSPECTOR)
|
|
static const char* defaultHost = "127.0.0.1\0";
|
|
static uint16_t defaultPort = 9230; // node + 1
|
|
|
|
auto& vm = JSC::getVM(globalObject);
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
JSC::JSValue hostValue = callFrame->argument(0);
|
|
JSC::JSValue portValue = callFrame->argument(1);
|
|
const char* host = defaultHost;
|
|
if (hostValue.isString()) {
|
|
|
|
auto str = hostValue.toWTFString(globalObject);
|
|
if (!str.isEmpty())
|
|
host = toCString(str).span().data();
|
|
} else if (!hostValue.isUndefined()) {
|
|
throwVMError(globalObject, scope,
|
|
createTypeError(globalObject, "host must be a string"_s));
|
|
return JSC::JSValue::encode(JSC::jsUndefined());
|
|
}
|
|
|
|
uint16_t port = defaultPort;
|
|
if (portValue.isNumber()) {
|
|
auto port_int = portValue.toUInt32(globalObject);
|
|
if (!(port_int > 0 && port_int < 65536)) {
|
|
throwVMError(
|
|
globalObject, scope,
|
|
createRangeError(globalObject, "port must be between 0 and 65535"_s));
|
|
return JSC::JSValue::encode(JSC::jsUndefined());
|
|
}
|
|
port = port_int;
|
|
} else if (!portValue.isUndefined()) {
|
|
throwVMError(
|
|
globalObject, scope,
|
|
createTypeError(globalObject,
|
|
"port must be a number between 0 and 65535"_s));
|
|
return JSC::JSValue::encode(JSC::jsUndefined());
|
|
}
|
|
|
|
globalObject->setInspectable(true);
|
|
auto& server = Inspector::RemoteInspectorServer::singleton();
|
|
if (!server.start(reinterpret_cast<const char*>(host), port)) {
|
|
throwVMError(
|
|
globalObject, scope,
|
|
createError(globalObject,
|
|
makeString("Failed to start server \""_s,
|
|
reinterpret_cast<const unsigned char*>(host),
|
|
":"_s, port, "\". Is port already in use?"_s)));
|
|
return JSC::JSValue::encode(JSC::jsUndefined());
|
|
}
|
|
|
|
RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::jsUndefined()));
|
|
#else
|
|
auto& vm = JSC::getVM(globalObject);
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
throwVMError(globalObject, scope,
|
|
createTypeError(
|
|
globalObject,
|
|
"Remote inspector is not enabled in this build of Bun"_s));
|
|
return JSC::JSValue::encode(JSC::jsUndefined());
|
|
#endif
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionDescribe);
|
|
JSC_DEFINE_HOST_FUNCTION(functionDescribe, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
if (callFrame->argumentCount() < 1)
|
|
return JSValue::encode(jsUndefined());
|
|
return JSValue::encode(jsString(vm, toString(callFrame->argument(0))));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionDescribeArray);
|
|
JSC_DEFINE_HOST_FUNCTION(functionDescribeArray, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
if (callFrame->argumentCount() < 1)
|
|
return JSValue::encode(jsUndefined());
|
|
VM& vm = globalObject->vm();
|
|
JSObject* object = jsDynamicCast<JSObject*>(callFrame->argument(0));
|
|
if (!object)
|
|
return JSValue::encode(jsNontrivialString(vm, "<not object>"_s));
|
|
return JSValue::encode(jsNontrivialString(
|
|
vm, toString("<Butterfly: ", RawPointer(object->butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionGCAndSweep);
|
|
JSC_DEFINE_HOST_FUNCTION(functionGCAndSweep,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
JSLockHolder lock(vm);
|
|
vm.heap.collectNow(Sync, CollectionScope::Full);
|
|
return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionFullGC);
|
|
JSC_DEFINE_HOST_FUNCTION(functionFullGC,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
JSLockHolder lock(vm);
|
|
vm.heap.collectSync(CollectionScope::Full);
|
|
return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionEdenGC);
|
|
JSC_DEFINE_HOST_FUNCTION(functionEdenGC,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
JSLockHolder lock(vm);
|
|
vm.heap.collectSync(CollectionScope::Eden);
|
|
return JSValue::encode(jsNumber(vm.heap.sizeAfterLastEdenCollection()));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionHeapSize);
|
|
JSC_DEFINE_HOST_FUNCTION(functionHeapSize,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
JSLockHolder lock(vm);
|
|
return JSValue::encode(jsNumber(vm.heap.size()));
|
|
}
|
|
|
|
JSC::Structure*
|
|
createMemoryFootprintStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
|
|
{
|
|
|
|
JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(
|
|
globalObject, globalObject->objectPrototype(), 5);
|
|
JSC::PropertyOffset offset;
|
|
|
|
structure = structure->addPropertyTransition(
|
|
vm, structure, Identifier::fromString(vm, "current"_s), 0, offset);
|
|
structure = structure->addPropertyTransition(
|
|
vm, structure, Identifier::fromString(vm, "peak"_s), 0, offset);
|
|
structure = structure->addPropertyTransition(
|
|
vm, structure, Identifier::fromString(vm, "currentCommit"_s), 0, offset);
|
|
structure = structure->addPropertyTransition(
|
|
vm, structure, Identifier::fromString(vm, "peakCommit"_s), 0, offset);
|
|
structure = structure->addPropertyTransition(
|
|
vm, structure, Identifier::fromString(vm, "pageFaults"_s), 0, offset);
|
|
|
|
return structure;
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionMemoryUsageStatistics);
|
|
JSC_DEFINE_HOST_FUNCTION(functionMemoryUsageStatistics,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
|
|
auto& vm = JSC::getVM(globalObject);
|
|
|
|
if (vm.heap.size() == 0) {
|
|
vm.heap.collectNow(Sync, CollectionScope::Full);
|
|
}
|
|
|
|
const auto createdSortedTypeCounts =
|
|
[&](JSC::TypeCountSet* typeCounts) -> JSC::JSValue {
|
|
WTF::Vector<std::pair<Identifier, unsigned>> counts;
|
|
counts.reserveInitialCapacity(typeCounts->size());
|
|
for (auto& it : *typeCounts) {
|
|
if (it.value > 0)
|
|
counts.append(
|
|
std::make_pair(Identifier::fromString(vm, it.key), it.value));
|
|
}
|
|
|
|
// Sort by count first, then by name.
|
|
std::sort(counts.begin(), counts.end(),
|
|
[](const std::pair<Identifier, unsigned>& a,
|
|
const std::pair<Identifier, unsigned>& b) {
|
|
if (a.second == b.second) {
|
|
WTF::StringView left = a.first.string();
|
|
WTF::StringView right = b.first.string();
|
|
unsigned originalLeftLength = left.length();
|
|
unsigned originalRightLength = right.length();
|
|
unsigned size = std::min(left.length(), right.length());
|
|
left = left.substring(0, size);
|
|
right = right.substring(0, size);
|
|
std::strong_ordering result = WTF::codePointCompare(right, left);
|
|
if (result == std::strong_ordering::equal) {
|
|
return originalLeftLength > originalRightLength;
|
|
}
|
|
|
|
return result == std::strong_ordering::greater;
|
|
}
|
|
|
|
return a.second > b.second;
|
|
});
|
|
|
|
auto* objectTypeCounts = constructEmptyObject(globalObject);
|
|
for (auto& it : counts) {
|
|
objectTypeCounts->putDirect(vm, it.first, jsNumber(it.second));
|
|
}
|
|
return objectTypeCounts;
|
|
};
|
|
|
|
JSValue objectTypeCounts = createdSortedTypeCounts(vm.heap.objectTypeCounts().get());
|
|
JSValue protectedCounts = createdSortedTypeCounts(vm.heap.protectedObjectTypeCounts().get());
|
|
|
|
JSObject* object = constructEmptyObject(globalObject);
|
|
object->putDirect(vm, Identifier::fromString(vm, "objectTypeCounts"_s),
|
|
objectTypeCounts);
|
|
|
|
object->putDirect(vm,
|
|
Identifier::fromString(vm, "protectedObjectTypeCounts"_s),
|
|
protectedCounts);
|
|
object->putDirect(vm, Identifier::fromString(vm, "heapSize"_s),
|
|
jsNumber(vm.heap.size()));
|
|
object->putDirect(vm, Identifier::fromString(vm, "heapCapacity"_s),
|
|
jsNumber(vm.heap.capacity()));
|
|
object->putDirect(vm, Identifier::fromString(vm, "extraMemorySize"_s),
|
|
jsNumber(vm.heap.extraMemorySize()));
|
|
object->putDirect(vm, Identifier::fromString(vm, "objectCount"_s),
|
|
jsNumber(vm.heap.objectCount()));
|
|
object->putDirect(vm, Identifier::fromString(vm, "protectedObjectCount"_s),
|
|
jsNumber(vm.heap.protectedObjectCount()));
|
|
object->putDirect(vm, Identifier::fromString(vm, "globalObjectCount"_s),
|
|
jsNumber(vm.heap.globalObjectCount()));
|
|
object->putDirect(vm,
|
|
Identifier::fromString(vm, "protectedGlobalObjectCount"_s),
|
|
jsNumber(vm.heap.protectedGlobalObjectCount()));
|
|
|
|
#if IS_MALLOC_DEBUGGING_ENABLED
|
|
#if OS(DARWIN)
|
|
{
|
|
vm_address_t* zones;
|
|
unsigned count;
|
|
|
|
// Zero out the structures in case a zone is missing
|
|
malloc_statistics_t zone_stats;
|
|
zone_stats.blocks_in_use = 0;
|
|
zone_stats.size_in_use = 0;
|
|
zone_stats.max_size_in_use = 0;
|
|
zone_stats.size_allocated = 0;
|
|
|
|
malloc_zone_pressure_relief(nullptr, 0);
|
|
malloc_get_all_zones(mach_task_self(), 0, &zones, &count);
|
|
Vector<std::pair<Identifier, size_t>> zoneSizes;
|
|
zoneSizes.reserveInitialCapacity(count);
|
|
for (unsigned i = 0; i < count; i++) {
|
|
auto zone = reinterpret_cast<malloc_zone_t*>(zones[i]);
|
|
if (const char* name = malloc_get_zone_name(zone)) {
|
|
malloc_zone_statistics(reinterpret_cast<malloc_zone_t*>(zones[i]),
|
|
&zone_stats);
|
|
zoneSizes.append(
|
|
std::make_pair(Identifier::fromString(vm, String::fromUTF8(name)),
|
|
zone_stats.size_in_use));
|
|
}
|
|
}
|
|
|
|
std::sort(zoneSizes.begin(), zoneSizes.end(),
|
|
[](const std::pair<Identifier, size_t>& a,
|
|
const std::pair<Identifier, size_t>& b) {
|
|
// Sort by name if the sizes are the same.
|
|
if (a.second == b.second) {
|
|
WTF::StringView left = a.first.string();
|
|
WTF::StringView right = b.first.string();
|
|
unsigned originalLeftLength = left.length();
|
|
unsigned originalRightLength = right.length();
|
|
unsigned size = std::min(left.length(), right.length());
|
|
left = left.substring(0, size);
|
|
right = right.substring(0, size);
|
|
std::strong_ordering result = WTF::codePointCompare(right, left);
|
|
if (result == std::strong_ordering::equal) {
|
|
return originalLeftLength > originalRightLength;
|
|
}
|
|
|
|
return result == std::strong_ordering::greater;
|
|
}
|
|
|
|
return a.second > b.second;
|
|
});
|
|
|
|
auto* zoneSizesObject = constructEmptyObject(globalObject);
|
|
for (auto& it : zoneSizes) {
|
|
zoneSizesObject->putDirect(vm, it.first, jsDoubleNumber(it.second));
|
|
}
|
|
|
|
object->putDirect(vm, Identifier::fromString(vm, "zones"_s),
|
|
zoneSizesObject);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
return JSValue::encode(object);
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionCreateMemoryFootprint);
|
|
JSC_DEFINE_HOST_FUNCTION(functionCreateMemoryFootprint,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
|
|
size_t elapsed_msecs = 0;
|
|
size_t user_msecs = 0;
|
|
size_t system_msecs = 0;
|
|
size_t current_rss = 0;
|
|
size_t peak_rss = 0;
|
|
size_t current_commit = 0;
|
|
size_t peak_commit = 0;
|
|
size_t page_faults = 0;
|
|
|
|
mi_process_info(&elapsed_msecs, &user_msecs, &system_msecs, ¤t_rss,
|
|
&peak_rss, ¤t_commit, &peak_commit, &page_faults);
|
|
|
|
// mi_process_info produces incorrect rss size on linux.
|
|
Bun::getRSS(¤t_rss);
|
|
|
|
VM& vm = globalObject->vm();
|
|
JSC::JSObject* object = JSC::constructEmptyObject(
|
|
vm, JSC::jsCast<Zig::GlobalObject*>(globalObject)->memoryFootprintStructure());
|
|
|
|
object->putDirectOffset(vm, 0, jsNumber(current_rss));
|
|
object->putDirectOffset(vm, 1, jsNumber(peak_rss));
|
|
object->putDirectOffset(vm, 2, jsNumber(current_commit));
|
|
object->putDirectOffset(vm, 3, jsNumber(peak_commit));
|
|
object->putDirectOffset(vm, 4, jsNumber(page_faults));
|
|
|
|
return JSValue::encode(object);
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionNeverInlineFunction);
|
|
JSC_DEFINE_HOST_FUNCTION(functionNeverInlineFunction,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
return JSValue::encode(setNeverInline(globalObject, callFrame));
|
|
}
|
|
|
|
extern "C" bool Bun__mkdirp(JSC::JSGlobalObject*, const char*);
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionStartSamplingProfiler);
|
|
JSC_DEFINE_HOST_FUNCTION(functionStartSamplingProfiler,
|
|
(JSC::JSGlobalObject * globalObject,
|
|
JSC::CallFrame* callFrame))
|
|
{
|
|
auto& vm = JSC::getVM(globalObject);
|
|
JSC::SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
|
|
|
|
JSC::JSValue directoryValue = callFrame->argument(0);
|
|
JSC::JSValue sampleValue = callFrame->argument(1);
|
|
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
if (directoryValue.isString()) {
|
|
auto path = directoryValue.toWTFString(globalObject);
|
|
if (!path.isEmpty()) {
|
|
StringPrintStream pathOut;
|
|
auto pathCString = toCString(String(path));
|
|
if (!Bun__mkdirp(globalObject, pathCString.span().data())) {
|
|
throwVMError(
|
|
globalObject, scope,
|
|
createTypeError(globalObject, "directory couldn't be created"_s));
|
|
return {};
|
|
}
|
|
|
|
Options::samplingProfilerPath() = pathCString.span().data();
|
|
samplingProfiler.registerForReportAtExit();
|
|
}
|
|
}
|
|
if (sampleValue.isNumber()) {
|
|
unsigned sampleInterval = sampleValue.toUInt32(globalObject);
|
|
samplingProfiler.setTimingInterval(
|
|
Seconds::fromMicroseconds(sampleInterval));
|
|
}
|
|
|
|
samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
|
|
samplingProfiler.start();
|
|
return JSC::JSValue::encode(jsUndefined());
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionSamplingProfilerStackTraces);
|
|
JSC_DEFINE_HOST_FUNCTION(functionSamplingProfilerStackTraces,
|
|
(JSC::JSGlobalObject * globalObject,
|
|
JSC::CallFrame*))
|
|
{
|
|
auto& vm = JSC::getVM(globalObject);
|
|
JSC::DeferTermination deferScope(vm);
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
if (!vm.samplingProfiler())
|
|
return JSC::JSValue::encode(throwException(
|
|
globalObject, scope,
|
|
createError(globalObject, "Sampling profiler was never started"_s)));
|
|
|
|
WTF::String jsonString = vm.samplingProfiler()->stackTracesAsJSON()->toJSONString();
|
|
JSC::EncodedJSValue result = JSC::JSValue::encode(JSONParse(globalObject, jsonString));
|
|
scope.releaseAssertNoException();
|
|
return result;
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionGetRandomSeed);
|
|
JSC_DEFINE_HOST_FUNCTION(functionGetRandomSeed,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
return JSValue::encode(jsNumber(globalObject->weakRandom().seed()));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionSetRandomSeed);
|
|
JSC_DEFINE_HOST_FUNCTION(functionSetRandomSeed, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
unsigned seed = callFrame->argument(0).toUInt32(globalObject);
|
|
RETURN_IF_EXCEPTION(scope, {});
|
|
globalObject->weakRandom().setSeed(seed);
|
|
return JSValue::encode(jsUndefined());
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionIsRope);
|
|
JSC_DEFINE_HOST_FUNCTION(functionIsRope,
|
|
(JSGlobalObject*, CallFrame* callFrame))
|
|
{
|
|
JSValue argument = callFrame->argument(0);
|
|
if (!argument.isString())
|
|
return JSValue::encode(jsBoolean(false));
|
|
const StringImpl* impl = asString(argument)->tryGetValueImpl();
|
|
return JSValue::encode(jsBoolean(!impl));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionCallerSourceOrigin);
|
|
JSC_DEFINE_HOST_FUNCTION(functionCallerSourceOrigin,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
|
|
if (sourceOrigin.url().isNull())
|
|
return JSValue::encode(jsNull());
|
|
return JSValue::encode(jsString(vm, sourceOrigin.string()));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionNoFTL);
|
|
JSC_DEFINE_HOST_FUNCTION(functionNoFTL,
|
|
(JSGlobalObject*, CallFrame* callFrame))
|
|
{
|
|
if (callFrame->argumentCount()) {
|
|
FunctionExecutable* executable = getExecutableForFunction(callFrame->argument(0));
|
|
if (executable)
|
|
executable->setNeverFTLOptimize(true);
|
|
}
|
|
return JSValue::encode(jsUndefined());
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionNoOSRExitFuzzing);
|
|
JSC_DEFINE_HOST_FUNCTION(functionNoOSRExitFuzzing,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
return JSValue::encode(setCannotUseOSRExitFuzzing(globalObject, callFrame));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionOptimizeNextInvocation);
|
|
JSC_DEFINE_HOST_FUNCTION(functionOptimizeNextInvocation,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
return JSValue::encode(optimizeNextInvocation(globalObject, callFrame));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionNumberOfDFGCompiles);
|
|
JSC_DEFINE_HOST_FUNCTION(functionNumberOfDFGCompiles,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
return JSValue::encode(numberOfDFGCompiles(globalObject, callFrame));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionReleaseWeakRefs);
|
|
JSC_DEFINE_HOST_FUNCTION(functionReleaseWeakRefs,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
globalObject->vm().finalizeSynchronousJSExecution();
|
|
return JSValue::encode(jsUndefined());
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionTotalCompileTime);
|
|
JSC_DEFINE_HOST_FUNCTION(functionTotalCompileTime,
|
|
(JSGlobalObject*, CallFrame*))
|
|
{
|
|
return JSValue::encode(jsNumber(JIT::totalCompileTime().milliseconds()));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionGetProtectedObjects);
|
|
JSC_DEFINE_HOST_FUNCTION(functionGetProtectedObjects,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
MarkedArgumentBuffer list;
|
|
globalObject->vm().heap.forEachProtectedCell(
|
|
[&](JSCell* cell) { list.append(cell); });
|
|
RELEASE_ASSERT(!list.hasOverflowed());
|
|
return JSC::JSValue::encode(constructArray(
|
|
globalObject, static_cast<JSC::ArrayAllocationProfile*>(nullptr), list));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionReoptimizationRetryCount);
|
|
JSC_DEFINE_HOST_FUNCTION(functionReoptimizationRetryCount,
|
|
(JSGlobalObject*, CallFrame* callFrame))
|
|
{
|
|
if (callFrame->argumentCount() < 1)
|
|
return JSValue::encode(jsUndefined());
|
|
|
|
CodeBlock* block = getSomeBaselineCodeBlockForFunction(callFrame->argument(0));
|
|
if (!block)
|
|
return JSValue::encode(jsNumber(0));
|
|
|
|
return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
|
|
}
|
|
|
|
extern "C" void Bun__drainMicrotasks();
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionDrainMicrotasks);
|
|
JSC_DEFINE_HOST_FUNCTION(functionDrainMicrotasks,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
vm.drainMicrotasks();
|
|
RETURN_IF_EXCEPTION(scope, {});
|
|
Bun__drainMicrotasks();
|
|
RETURN_IF_EXCEPTION(scope, {});
|
|
return JSValue::encode(jsUndefined());
|
|
}
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(functionSetTimeZone, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
if (callFrame->argumentCount() < 1) {
|
|
throwTypeError(globalObject, scope,
|
|
"setTimeZone requires a timezone string"_s);
|
|
return {};
|
|
}
|
|
|
|
if (!callFrame->argument(0).isString()) {
|
|
throwTypeError(globalObject, scope,
|
|
"setTimeZone requires a timezone string"_s);
|
|
return {};
|
|
}
|
|
|
|
String timeZoneName = callFrame->argument(0).toWTFString(globalObject);
|
|
RETURN_IF_EXCEPTION(scope, {});
|
|
|
|
if (!WTF::setTimeZoneOverride(timeZoneName)) {
|
|
throwTypeError(globalObject, scope,
|
|
makeString("Invalid timezone: \""_s, timeZoneName, "\""_s));
|
|
return {};
|
|
}
|
|
vm.dateCache.resetIfNecessarySlow();
|
|
WTF::Vector<char16_t, 32> buffer;
|
|
WTF::getTimeZoneOverride(buffer);
|
|
WTF::String timeZoneString(buffer.span());
|
|
return JSValue::encode(jsString(vm, timeZoneString));
|
|
}
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
auto& vm = JSC::getVM(globalObject);
|
|
JSC::SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
|
|
|
|
JSC::JSValue callbackValue = callFrame->argument(0);
|
|
JSC::JSValue sampleValue = callFrame->argument(1);
|
|
|
|
MarkedArgumentBuffer args;
|
|
|
|
if (callFrame->argumentCount() > 2) {
|
|
size_t count = callFrame->argumentCount();
|
|
args.ensureCapacity(count - 2);
|
|
for (size_t i = 2; i < count; i++) {
|
|
args.append(callFrame->argument(i));
|
|
}
|
|
}
|
|
|
|
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
|
if (callbackValue.isUndefinedOrNull() || !callbackValue.isCallable()) {
|
|
throwException(
|
|
globalObject, throwScope,
|
|
createTypeError(globalObject, "First argument must be a function."_s));
|
|
return JSValue::encode(JSValue {});
|
|
}
|
|
|
|
JSC::JSFunction* function = jsCast<JSC::JSFunction*>(callbackValue);
|
|
|
|
if (sampleValue.isNumber()) {
|
|
unsigned sampleInterval = sampleValue.toUInt32(globalObject);
|
|
samplingProfiler.setTimingInterval(
|
|
Seconds::fromMicroseconds(sampleInterval));
|
|
}
|
|
|
|
const auto report = [](JSC::VM& vm,
|
|
JSC::JSGlobalObject* globalObject) -> JSC::JSValue {
|
|
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
auto& samplingProfiler = *vm.samplingProfiler();
|
|
StringPrintStream topFunctions;
|
|
samplingProfiler.reportTopFunctions(topFunctions);
|
|
|
|
StringPrintStream byteCodes;
|
|
samplingProfiler.reportTopBytecodes(byteCodes);
|
|
|
|
JSValue stackTraces = JSONParse(
|
|
globalObject, samplingProfiler.stackTracesAsJSON()->toJSONString());
|
|
|
|
samplingProfiler.shutdown();
|
|
RETURN_IF_EXCEPTION(throwScope, {});
|
|
|
|
JSObject* result = constructEmptyObject(globalObject, globalObject->objectPrototype(), 3);
|
|
result->putDirect(vm, Identifier::fromString(vm, "functions"_s),
|
|
jsString(vm, topFunctions.toString()));
|
|
result->putDirect(vm, Identifier::fromString(vm, "bytecodes"_s),
|
|
jsString(vm, byteCodes.toString()));
|
|
result->putDirect(vm, Identifier::fromString(vm, "stackTraces"_s),
|
|
stackTraces);
|
|
|
|
return result;
|
|
};
|
|
const auto reportFailure = [](JSC::VM& vm) -> JSC::JSValue {
|
|
if (auto* samplingProfiler = vm.samplingProfiler()) {
|
|
samplingProfiler->pause();
|
|
samplingProfiler->shutdown();
|
|
samplingProfiler->clearData();
|
|
}
|
|
|
|
return {};
|
|
};
|
|
|
|
JSC::CallData callData = JSC::getCallData(function);
|
|
|
|
samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
|
|
samplingProfiler.start();
|
|
JSValue returnValue = JSC::profiledCall(globalObject, ProfilingReason::API, function, callData, JSC::jsUndefined(), args);
|
|
|
|
if (returnValue.isEmpty() || throwScope.exception()) {
|
|
return JSValue::encode(reportFailure(vm));
|
|
}
|
|
|
|
if (auto* promise = jsDynamicCast<JSPromise*>(returnValue)) {
|
|
auto afterOngoingPromiseCapability = JSC::JSPromise::create(vm, globalObject->promiseStructure());
|
|
RETURN_IF_EXCEPTION(throwScope, {});
|
|
|
|
JSNativeStdFunction* resolve = JSNativeStdFunction::create(
|
|
vm, globalObject, 0, "resolve"_s,
|
|
[report](JSGlobalObject* globalObject, CallFrame* callFrame) {
|
|
return JSValue::encode(JSPromise::resolvedPromise(
|
|
globalObject, report(globalObject->vm(), globalObject)));
|
|
});
|
|
JSNativeStdFunction* reject = JSNativeStdFunction::create(
|
|
vm, globalObject, 0, "reject"_s,
|
|
[reportFailure](JSGlobalObject* globalObject, CallFrame* callFrame) {
|
|
EnsureStillAliveScope error = callFrame->argument(0);
|
|
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
|
|
reportFailure(globalObject->vm());
|
|
throwException(globalObject, scope, error.value());
|
|
return JSValue::encode({});
|
|
});
|
|
promise->performPromiseThen(globalObject, resolve, reject,
|
|
afterOngoingPromiseCapability);
|
|
return JSValue::encode(afterOngoingPromiseCapability);
|
|
}
|
|
|
|
return JSValue::encode(report(vm, globalObject));
|
|
}
|
|
|
|
JSC_DECLARE_HOST_FUNCTION(functionGenerateHeapSnapshotForDebugging);
|
|
JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshotForDebugging,
|
|
(JSGlobalObject * globalObject, CallFrame*))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
JSLockHolder lock(vm);
|
|
DeferTermination deferScope(vm);
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
String jsonString;
|
|
{
|
|
DeferGCForAWhile deferGC(vm); // Prevent concurrent GC from interfering with
|
|
// the full GC that the snapshot does.
|
|
|
|
HeapSnapshotBuilder snapshotBuilder(
|
|
vm.ensureHeapProfiler(),
|
|
HeapSnapshotBuilder::SnapshotType::GCDebuggingSnapshot);
|
|
snapshotBuilder.buildSnapshot();
|
|
|
|
jsonString = snapshotBuilder.json();
|
|
}
|
|
scope.releaseAssertNoException();
|
|
|
|
return JSValue::encode(JSONParse(globalObject, WTFMove(jsonString)));
|
|
}
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(functionSerialize,
|
|
(JSGlobalObject * lexicalGlobalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
auto* globalObject = jsCast<JSDOMGlobalObject*>(lexicalGlobalObject);
|
|
auto& vm = JSC::getVM(globalObject);
|
|
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
JSValue value = callFrame->argument(0);
|
|
JSValue optionsObject = callFrame->argument(1);
|
|
bool asNodeBuffer = false;
|
|
if (optionsObject.isObject()) {
|
|
JSC::JSObject* options = optionsObject.getObject();
|
|
auto binaryTypeValue = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "binaryType"_s));
|
|
RETURN_IF_EXCEPTION(throwScope, {});
|
|
if (binaryTypeValue) {
|
|
if (!binaryTypeValue.isString()) {
|
|
throwTypeError(globalObject, throwScope, "binaryType must be a string"_s);
|
|
return {};
|
|
}
|
|
|
|
asNodeBuffer = binaryTypeValue.toWTFString(globalObject) == "nodebuffer"_s;
|
|
RETURN_IF_EXCEPTION(throwScope, {});
|
|
}
|
|
}
|
|
|
|
Vector<JSC::Strong<JSC::JSObject>> transferList;
|
|
Vector<RefPtr<MessagePort>> dummyPorts;
|
|
ExceptionOr<Ref<SerializedScriptValue>> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList), dummyPorts);
|
|
|
|
if (serialized.hasException()) {
|
|
WebCore::propagateException(*globalObject, throwScope, serialized.releaseException());
|
|
RELEASE_AND_RETURN(throwScope, {});
|
|
}
|
|
|
|
auto serializedValue = serialized.releaseReturnValue();
|
|
auto arrayBuffer = serializedValue->toArrayBuffer();
|
|
|
|
if (asNodeBuffer) {
|
|
size_t byteLength = arrayBuffer->byteLength();
|
|
auto* subclassStructure = globalObject->JSBufferSubclassStructure();
|
|
JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(arrayBuffer), 0, byteLength);
|
|
return JSValue::encode(uint8Array);
|
|
}
|
|
|
|
if (arrayBuffer->isShared()) {
|
|
return JSValue::encode(
|
|
JSArrayBuffer::create(vm,
|
|
globalObject->arrayBufferStructureWithSharingMode<
|
|
ArrayBufferSharingMode::Shared>(),
|
|
WTFMove(arrayBuffer)));
|
|
}
|
|
|
|
return JSValue::encode(JSArrayBuffer::create(
|
|
vm, globalObject->arrayBufferStructure(), WTFMove(arrayBuffer)));
|
|
}
|
|
JSC_DEFINE_HOST_FUNCTION(functionDeserialize, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
auto& vm = JSC::getVM(globalObject);
|
|
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
|
JSValue value = callFrame->argument(0);
|
|
|
|
JSValue result;
|
|
|
|
if (auto* jsArrayBuffer = jsDynamicCast<JSArrayBuffer*>(value)) {
|
|
result = SerializedScriptValue::fromArrayBuffer(
|
|
*globalObject, globalObject, jsArrayBuffer->impl(), 0,
|
|
jsArrayBuffer->impl()->byteLength());
|
|
} else if (auto* view = jsDynamicCast<JSArrayBufferView*>(value)) {
|
|
auto arrayBuffer = view->possiblySharedImpl()->possiblySharedBuffer();
|
|
result = SerializedScriptValue::fromArrayBuffer(
|
|
*globalObject, globalObject, arrayBuffer.get(), view->byteOffset(),
|
|
view->byteLength());
|
|
} else {
|
|
throwTypeError(globalObject, throwScope,
|
|
"First argument must be an ArrayBuffer"_s);
|
|
return {};
|
|
}
|
|
|
|
RETURN_IF_EXCEPTION(throwScope, {});
|
|
RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
|
|
}
|
|
|
|
extern "C" JSC::EncodedJSValue ByteRangeMapping__findExecutedLines(
|
|
JSC::JSGlobalObject*, BunString sourceURL, BasicBlockRange* ranges,
|
|
size_t len, size_t functionOffset, bool ignoreSourceMap);
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(functionCodeCoverageForFile,
|
|
(JSGlobalObject * globalObject,
|
|
CallFrame* callFrame))
|
|
{
|
|
VM& vm = globalObject->vm();
|
|
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
String fileName = callFrame->argument(0).toWTFString(globalObject);
|
|
RETURN_IF_EXCEPTION(throwScope, {});
|
|
bool ignoreSourceMap = callFrame->argument(1).toBoolean(globalObject);
|
|
|
|
auto sourceID = Zig::sourceIDForSourceURL(fileName);
|
|
if (!sourceID) {
|
|
throwException(globalObject, throwScope,
|
|
createError(globalObject, "No source for file"_s));
|
|
return {};
|
|
}
|
|
|
|
auto basicBlocks = vm.controlFlowProfiler()->getBasicBlocksForSourceIDWithoutFunctionRange(
|
|
sourceID, vm);
|
|
|
|
if (basicBlocks.isEmpty()) {
|
|
return JSC::JSValue::encode(
|
|
JSC::constructEmptyArray(globalObject, nullptr, 0));
|
|
}
|
|
|
|
size_t functionStartOffset = basicBlocks.size();
|
|
|
|
const Vector<std::tuple<bool, unsigned, unsigned>>& functionRanges = vm.functionHasExecutedCache()->getFunctionRanges(sourceID);
|
|
|
|
basicBlocks.reserveCapacity(functionRanges.size() + basicBlocks.size());
|
|
|
|
for (const auto& functionRange : functionRanges) {
|
|
BasicBlockRange range;
|
|
range.m_hasExecuted = std::get<0>(functionRange);
|
|
range.m_startOffset = static_cast<int>(std::get<1>(functionRange));
|
|
range.m_endOffset = static_cast<int>(std::get<2>(functionRange));
|
|
range.m_executionCount = range.m_hasExecuted
|
|
? 1
|
|
: 0; // This is a hack. We don't actually count this.
|
|
basicBlocks.append(range);
|
|
}
|
|
|
|
return ByteRangeMapping__findExecutedLines(
|
|
globalObject, Bun::toString(fileName), basicBlocks.begin(),
|
|
basicBlocks.size(), functionStartOffset, ignoreSourceMap);
|
|
}
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(functionEstimateDirectMemoryUsageOf, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
|
|
JSValue value = callFrame->argument(0);
|
|
if (value.isCell()) {
|
|
auto& vm = JSC::getVM(globalObject);
|
|
EnsureStillAliveScope alive = value;
|
|
return JSValue::encode(jsDoubleNumber(alive.value().asCell()->estimatedSizeInBytes(vm)));
|
|
}
|
|
|
|
return JSValue::encode(jsNumber(0));
|
|
}
|
|
|
|
#if USE(BMALLOC_MEMORY_FOOTPRINT_API)
|
|
|
|
#include <bmalloc/bmalloc.h>
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(functionPercentAvailableMemoryInUse, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
return JSValue::encode(jsDoubleNumber(bmalloc::api::percentAvailableMemoryInUse()));
|
|
}
|
|
|
|
#else
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(functionPercentAvailableMemoryInUse, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
|
{
|
|
return JSValue::encode(jsNull());
|
|
}
|
|
|
|
#endif
|
|
|
|
// clang-format off
|
|
/* Source for BunJSCModuleTable.lut.h
|
|
@begin BunJSCModuleTable
|
|
callerSourceOrigin functionCallerSourceOrigin Function 0
|
|
jscDescribe functionDescribe Function 0
|
|
jscDescribeArray functionDescribeArray Function 0
|
|
drainMicrotasks functionDrainMicrotasks Function 0
|
|
edenGC functionEdenGC Function 0
|
|
fullGC functionFullGC Function 0
|
|
gcAndSweep functionGCAndSweep Function 0
|
|
getRandomSeed functionGetRandomSeed Function 0
|
|
heapSize functionHeapSize Function 0
|
|
heapStats functionMemoryUsageStatistics Function 0
|
|
startSamplingProfiler functionStartSamplingProfiler Function 0
|
|
samplingProfilerStackTraces functionSamplingProfilerStackTraces Function 0
|
|
noInline functionNeverInlineFunction Function 0
|
|
isRope functionIsRope Function 0
|
|
memoryUsage functionCreateMemoryFootprint Function 0
|
|
noFTL functionNoFTL Function 0
|
|
noOSRExitFuzzing functionNoOSRExitFuzzing Function 0
|
|
numberOfDFGCompiles functionNumberOfDFGCompiles Function 0
|
|
optimizeNextInvocation functionOptimizeNextInvocation Function 0
|
|
releaseWeakRefs functionReleaseWeakRefs Function 0
|
|
reoptimizationRetryCount functionReoptimizationRetryCount Function 0
|
|
setRandomSeed functionSetRandomSeed Function 0
|
|
startRemoteDebugger functionStartRemoteDebugger Function 0
|
|
totalCompileTime functionTotalCompileTime Function 0
|
|
getProtectedObjects functionGetProtectedObjects Function 0
|
|
generateHeapSnapshotForDebugging functionGenerateHeapSnapshotForDebugging Function 0
|
|
profile functionRunProfiler Function 0
|
|
setTimeZone functionSetTimeZone Function 0
|
|
serialize functionSerialize Function 0
|
|
deserialize functionDeserialize Function 0
|
|
estimateShallowMemoryUsageOf functionEstimateDirectMemoryUsageOf Function 1
|
|
percentAvailableMemoryInUse functionPercentAvailableMemoryInUse Function 0
|
|
@end
|
|
*/
|
|
|
|
namespace Zig {
|
|
DEFINE_NATIVE_MODULE(BunJSC)
|
|
{
|
|
INIT_NATIVE_MODULE(36);
|
|
|
|
putNativeFn(Identifier::fromString(vm, "callerSourceOrigin"_s), functionCallerSourceOrigin);
|
|
putNativeFn(Identifier::fromString(vm, "jscDescribe"_s), functionDescribe);
|
|
putNativeFn(Identifier::fromString(vm, "jscDescribeArray"_s), functionDescribeArray);
|
|
putNativeFn(Identifier::fromString(vm, "drainMicrotasks"_s), functionDrainMicrotasks);
|
|
putNativeFn(Identifier::fromString(vm, "edenGC"_s), functionEdenGC);
|
|
putNativeFn(Identifier::fromString(vm, "fullGC"_s), functionFullGC);
|
|
putNativeFn(Identifier::fromString(vm, "gcAndSweep"_s), functionGCAndSweep);
|
|
putNativeFn(Identifier::fromString(vm, "getRandomSeed"_s), functionGetRandomSeed);
|
|
putNativeFn(Identifier::fromString(vm, "heapSize"_s), functionHeapSize);
|
|
putNativeFn(Identifier::fromString(vm, "heapStats"_s), functionMemoryUsageStatistics);
|
|
putNativeFn(Identifier::fromString(vm, "startSamplingProfiler"_s), functionStartSamplingProfiler);
|
|
putNativeFn(Identifier::fromString(vm, "samplingProfilerStackTraces"_s), functionSamplingProfilerStackTraces);
|
|
putNativeFn(Identifier::fromString(vm, "noInline"_s), functionNeverInlineFunction);
|
|
putNativeFn(Identifier::fromString(vm, "isRope"_s), functionIsRope);
|
|
putNativeFn(Identifier::fromString(vm, "memoryUsage"_s), functionCreateMemoryFootprint);
|
|
putNativeFn(Identifier::fromString(vm, "noFTL"_s), functionNoFTL);
|
|
putNativeFn(Identifier::fromString(vm, "noOSRExitFuzzing"_s), functionNoOSRExitFuzzing);
|
|
putNativeFn(Identifier::fromString(vm, "numberOfDFGCompiles"_s), functionNumberOfDFGCompiles);
|
|
putNativeFn(Identifier::fromString(vm, "optimizeNextInvocation"_s), functionOptimizeNextInvocation);
|
|
putNativeFn(Identifier::fromString(vm, "releaseWeakRefs"_s), functionReleaseWeakRefs);
|
|
putNativeFn(Identifier::fromString(vm, "reoptimizationRetryCount"_s), functionReoptimizationRetryCount);
|
|
putNativeFn(Identifier::fromString(vm, "setRandomSeed"_s), functionSetRandomSeed);
|
|
putNativeFn(Identifier::fromString(vm, "startRemoteDebugger"_s), functionStartRemoteDebugger);
|
|
putNativeFn(Identifier::fromString(vm, "totalCompileTime"_s), functionTotalCompileTime);
|
|
putNativeFn(Identifier::fromString(vm, "getProtectedObjects"_s), functionGetProtectedObjects);
|
|
putNativeFn(Identifier::fromString(vm, "generateHeapSnapshotForDebugging"_s), functionGenerateHeapSnapshotForDebugging);
|
|
putNativeFn(Identifier::fromString(vm, "profile"_s), functionRunProfiler);
|
|
putNativeFn(Identifier::fromString(vm, "codeCoverageForFile"_s), functionCodeCoverageForFile);
|
|
putNativeFn(Identifier::fromString(vm, "setTimeZone"_s), functionSetTimeZone);
|
|
putNativeFn(Identifier::fromString(vm, "serialize"_s), functionSerialize);
|
|
putNativeFn(Identifier::fromString(vm, "deserialize"_s), functionDeserialize);
|
|
putNativeFn(Identifier::fromString(vm, "estimateShallowMemoryUsageOf"_s), functionEstimateDirectMemoryUsageOf);
|
|
putNativeFn(Identifier::fromString(vm, "percentAvailableMemoryInUse"_s), functionPercentAvailableMemoryInUse);
|
|
|
|
// Deprecated
|
|
putNativeFn(Identifier::fromString(vm, "describe"_s), functionDescribe);
|
|
putNativeFn(Identifier::fromString(vm, "describeArray"_s), functionDescribeArray);
|
|
putNativeFn(Identifier::fromString(vm, "setTimezone"_s), functionSetTimeZone);
|
|
|
|
RETURN_NATIVE_MODULE();
|
|
}
|
|
|
|
} // namespace Zig
|