// print how long each step took #define VERBOSE // // This loads up a JavaScriptCore global object which only has a "write" // global function and then calls eval // // // Usage: // ./cold-jsc-start // ./cold-jsc-start -e "write('hey')" // #include "root.h" #include #include #include #include #include #include #include #include using namespace JSC; JSC_DEFINE_HOST_FUNCTION(jsFunctionWrite, (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callframe)) { if (callframe->argumentCount() < 1) return JSValue::encode(jsUndefined()); JSValue arg1 = callframe->argument(0); JSValue toWriteArg = callframe->argument(1); auto &vm = globalObject->vm(); auto scope = DECLARE_CATCH_SCOPE(vm); int32_t fd = STDOUT_FILENO; if (callframe->argumentCount() > 1) { fd = arg1.toInt32(globalObject); RETURN_IF_EXCEPTION(scope, encodedJSValue()); } else { toWriteArg = arg1; } if (auto *buffer = jsDynamicCast(toWriteArg)) { auto *data = buffer->vector(); auto length = buffer->byteLength(); auto written = write(fd, data, length); return JSValue::encode(jsNumber(written)); } auto string = toWriteArg.toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, encodedJSValue()); auto utf8 = string.utf8(); auto length = utf8.length(); auto written = write(fd, utf8.data(), length); return JSValue::encode(jsNumber(written)); } int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } #ifdef VERBOSE auto stopwatch = Stopwatch::create(); stopwatch->start(); #endif { WTF::initializeMainThread(); JSC::initialize(); { JSC::Options::AllowUnfinalizedAccessScope scope; JSC::Options::useConcurrentJIT() = true; // JSC::Options::useSigillCrashAnalyzer() = true; JSC::Options::useWebAssembly() = true; JSC::Options::useSourceProviderCache() = true; // JSC::Options::useUnlinkedCodeBlockJettisoning() = false; JSC::Options::exposeInternalModuleLoader() = true; JSC::Options::useSharedArrayBuffer() = true; JSC::Options::useJIT() = true; JSC::Options::useBBQJIT() = true; JSC::Options::useJITCage() = false; JSC::Options::useShadowRealm() = true; JSC::Options::useResizableArrayBuffer() = true; JSC::Options::showPrivateScriptsInStackTraces() = true; JSC::Options::useSetMethods() = true; JSC::Options::assertOptionsAreCoherent(); } } #ifdef VERBOSE fprintf(stderr, "JSC::Initialize took %f ms\n", stopwatch->elapsedTime().milliseconds()); stopwatch->reset(); stopwatch->start(); #endif auto &vm = JSC::VM::create(JSC::HeapType::Large).leakRef(); vm.heap.acquireAccess(); #ifdef VERBOSE fprintf(stderr, "JSC::VM::create took %f ms\n", stopwatch->elapsedTime().milliseconds()); stopwatch->reset(); stopwatch->start(); #endif JSC::JSLockHolder locker(vm); auto *globalObject = JSC::JSGlobalObject::create( vm, JSC::JSGlobalObject::createStructure(vm, JSC::jsNull())); #ifdef VERBOSE fprintf(stderr, "JSC::JSGlobalObject::create took %f ms\n", stopwatch->elapsedTime().milliseconds()); stopwatch->reset(); stopwatch->start(); #endif JSC::gcProtect(globalObject); globalObject->putDirectNativeFunction( vm, globalObject, PropertyName(JSC::Identifier::fromString(vm, "write"_s)), 0, jsFunctionWrite, ImplementationVisibility::Public, JSC::NoIntrinsic, JSC::PropertyAttribute::ReadOnly | 0); vm.ref(); if (argc > 2) { auto source = JSC::makeSource(WTF::String::fromUTF8(argv[argc - 1]), SourceOrigin(WTF::URL("file://eval.js"_s)), JSC::SourceTaintedOrigin::Untainted, "eval.js"_s); NakedPtr evaluationException; JSValue returnValue = JSC::profiledEvaluate(globalObject, ProfilingReason::API, source, globalObject, evaluationException); #ifdef VERBOSE fprintf(stderr, "\neval took %f ms\n", stopwatch->elapsedTime().milliseconds()); stopwatch->reset(); #endif if (evaluationException) { fprintf( stderr, "Exception: %s\n", evaluationException->value().toWTFString(globalObject).utf8().data()); return 1; } else { return 0; } } WTF::String fileURLString = WTF::String::fromUTF8(argv[argc - 1]); if (auto contents = WTF::FileSystemImpl::readEntireFile(fileURLString)) { auto source = JSC::makeSource(WTF::String::fromUTF8(contents.value()), SourceOrigin(WTF::URL(fileURLString)), JSC::SourceTaintedOrigin::Untainted, fileURLString); NakedPtr evaluationException; JSValue returnValue = JSC::profiledEvaluate(globalObject, ProfilingReason::API, source, globalObject, evaluationException); #ifdef VERBOSE fprintf(stderr, "eval took %f ms\n", stopwatch->elapsedTime().milliseconds()); stopwatch->reset(); #endif if (evaluationException) { fprintf( stderr, "Exception: %s\n", evaluationException->value().toWTFString(globalObject).utf8().data()); return 1; } else { return 0; } } else { fprintf(stderr, "Could not read file %s\n", argv[argc - 1]); return 1; } }