Ignore:
Timestamp:
Jan 25, 2017, 6:34:30 PM (8 years ago)
Author:
[email protected]
Message:

jsc.cpp should have the $.agent stuff for testing SAB
https://bugs.webkit.org/show_bug.cgi?id=167431

Reviewed by Saam Barati.

JSTests:

Add a very basic test of Atomics using $.agent. This is based on
LayoutTests/workers/sab/simple.html.

  • stress/lars-sab-workers.js: Added.

(startWorker):
(resources):
(wake):
(else):

Source/JavaScriptCore:

This adds some stuff that the SAB branch of test262 needs. None of this is exposed except for our
own tests and the SAB branch of test262. We now pass all of the Atomics tests in the SAB branch
of test262.

  • jsc.cpp:

(Message::releaseContents):
(Message::index):
(GlobalObject::finishCreation):
(GlobalObject::addFunction):
(Message::Message):
(Message::~Message):
(Worker::Worker):
(Worker::~Worker):
(Worker::send):
(Worker::receive):
(Worker::current):
(Worker::currentWorker):
(Workers::Workers):
(Workers::~Workers):
(Workers::broadcast):
(Workers::report):
(Workers::tryGetReport):
(Workers::getReport):
(Workers::singleton):
(functionDollarCreateRealm):
(functionDollarDetachArrayBuffer):
(functionDollarEvalScript):
(functionDollarAgentStart):
(functionDollarAgentReceiveBroadcast):
(functionDollarAgentReport):
(functionDollarAgentSleep):
(functionDollarAgentBroadcast):
(functionDollarAgentGetReport):
(functionWaitForReport):
(checkException):
(runWithScripts):
(runJSC):
(jscmain):

  • runtime/JSArrayBuffer.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jsc.cpp

    r211070 r211194  
    6464#include "ProfilerDatabase.h"
    6565#include "ProtoCallFrame.h"
     66#include "ReleaseHeapAccessScope.h"
    6667#include "SamplingProfiler.h"
    6768#include "ShadowChicken.h"
     
    908909
    909910static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
     911
     912class CommandLine;
     913class GlobalObject;
     914class Workers;
     915
     916template<typename Func>
     917int runJSC(CommandLine, const Func&);
     918static void checkException(GlobalObject*, bool isLastFile, bool hasException, JSValue, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool& success);
     919
     920class Message : public ThreadSafeRefCounted<Message> {
     921public:
     922    Message(ArrayBufferContents&&, int32_t);
     923    ~Message();
     924   
     925    ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
     926    int32_t index() const { return m_index; }
     927
     928private:
     929    ArrayBufferContents m_contents;
     930    int32_t m_index { 0 };
     931};
     932
     933class Worker : public BasicRawSentinelNode<Worker> {
     934public:
     935    Worker(Workers&);
     936    ~Worker();
     937   
     938    void enqueue(const AbstractLocker&, RefPtr<Message>);
     939    RefPtr<Message> dequeue();
     940   
     941    static Worker& current();
     942
     943private:
     944    static ThreadSpecific<Worker*>& currentWorker();
     945
     946    Workers& m_workers;
     947    Deque<RefPtr<Message>> m_messages;
     948};
     949
     950class Workers {
     951public:
     952    Workers();
     953    ~Workers();
     954   
     955    template<typename Func>
     956    void broadcast(const Func&);
     957   
     958    void report(String);
     959    String tryGetReport();
     960    String getReport();
     961   
     962    static Workers& singleton();
     963   
     964private:
     965    friend class Worker;
     966   
     967    Lock m_lock;
     968    Condition m_condition;
     969    SentinelLinkedList<Worker, BasicRawSentinelNode<Worker>> m_workers;
     970    Deque<String> m_reports;
     971};
    910972
    911973static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
     
    10131075static EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState*);
    10141076static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState*);
     1077static EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState*);
     1078static EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState*);
     1079static EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState*);
     1080static EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState*);
     1081static EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState*);
     1082static EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState*);
     1083static EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState*);
     1084static EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState*);
     1085static EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState*);
     1086static EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*);
     1087static EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState*);
    10151088
    10161089struct Script {
     
    12671340
    12681341        putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
     1342       
     1343        Structure* plainObjectStructure = JSFinalObject::createStructure(vm, this, objectPrototype(), 0);
     1344       
     1345        JSObject* dollar = JSFinalObject::create(vm, plainObjectStructure);
     1346        putDirect(vm, Identifier::fromString(globalExec(), "$"), dollar);
     1347       
     1348        addFunction(vm, dollar, "createRealm", functionDollarCreateRealm, 0);
     1349        addFunction(vm, dollar, "detachArrayBuffer", functionDollarDetachArrayBuffer, 1);
     1350        addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1);
     1351       
     1352        dollar->putDirect(vm, Identifier::fromString(globalExec(), "global"), this);
     1353       
     1354        JSObject* agent = JSFinalObject::create(vm, plainObjectStructure);
     1355        dollar->putDirect(vm, Identifier::fromString(globalExec(), "agent"), agent);
     1356       
     1357        // The test262 INTERPRETING.md document says that some of these functions are just in the main
     1358        // thread and some are in the other threads. We just put them in all threads.
     1359        addFunction(vm, agent, "start", functionDollarAgentStart, 1);
     1360        addFunction(vm, agent, "receiveBroadcast", functionDollarAgentReceiveBroadcast, 1);
     1361        addFunction(vm, agent, "report", functionDollarAgentReport, 1);
     1362        addFunction(vm, agent, "sleep", functionDollarAgentSleep, 1);
     1363        addFunction(vm, agent, "broadcast", functionDollarAgentBroadcast, 1);
     1364        addFunction(vm, agent, "getReport", functionDollarAgentGetReport, 0);
     1365        addFunction(vm, agent, "leaving", functionDollarAgentLeaving, 0);
     1366       
     1367        addFunction(vm, "waitForReport", functionWaitForReport, 0);
     1368    }
     1369   
     1370    void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
     1371    {
     1372        Identifier identifier = Identifier::fromString(&vm, name);
     1373        object->putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
    12691374    }
    12701375
    12711376    void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
    12721377    {
    1273         Identifier identifier = Identifier::fromString(&vm, name);
    1274         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
     1378        addFunction(vm, this, name, function, arguments);
    12751379    }
    12761380   
     
    16631767EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState* exec)
    16641768{
    1665     if (exec->argumentCount() >= 1)
    1666         sleep(exec->argument(0).toNumber(exec));
     1769    VM& vm = exec->vm();
     1770    auto scope = DECLARE_THROW_SCOPE(vm);
     1771
     1772    if (exec->argumentCount() >= 1) {
     1773        Seconds seconds = Seconds(exec->argument(0).toNumber(exec));
     1774        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     1775        sleep(seconds);
     1776    }
     1777   
    16671778    return JSValue::encode(jsUndefined());
    16681779}
     
    22202331{
    22212332    return JSValue::encode(numberOfDFGCompiles(exec));
     2333}
     2334
     2335Message::Message(ArrayBufferContents&& contents, int32_t index)
     2336    : m_contents(WTFMove(contents))
     2337    , m_index(index)
     2338{
     2339}
     2340
     2341Message::~Message()
     2342{
     2343}
     2344
     2345Worker::Worker(Workers& workers)
     2346    : m_workers(workers)
     2347{
     2348    auto locker = holdLock(m_workers.m_lock);
     2349    m_workers.m_workers.append(this);
     2350   
     2351    *currentWorker() = this;
     2352}
     2353
     2354Worker::~Worker()
     2355{
     2356    auto locker = holdLock(m_workers.m_lock);
     2357    RELEASE_ASSERT(isOnList());
     2358    remove();
     2359}
     2360
     2361void Worker::enqueue(const AbstractLocker&, RefPtr<Message> message)
     2362{
     2363    m_messages.append(message);
     2364}
     2365
     2366RefPtr<Message> Worker::dequeue()
     2367{
     2368    auto locker = holdLock(m_workers.m_lock);
     2369    while (m_messages.isEmpty())
     2370        m_workers.m_condition.wait(m_workers.m_lock);
     2371    return m_messages.takeFirst();
     2372}
     2373
     2374Worker& Worker::current()
     2375{
     2376    return **currentWorker();
     2377}
     2378
     2379ThreadSpecific<Worker*>& Worker::currentWorker()
     2380{
     2381    static ThreadSpecific<Worker*>* result;
     2382    static std::once_flag flag;
     2383    std::call_once(
     2384        flag,
     2385        [] () {
     2386            result = new ThreadSpecific<Worker*>();
     2387        });
     2388    return *result;
     2389}
     2390
     2391Workers::Workers()
     2392{
     2393}
     2394
     2395Workers::~Workers()
     2396{
     2397    UNREACHABLE_FOR_PLATFORM();
     2398}
     2399
     2400template<typename Func>
     2401void Workers::broadcast(const Func& func)
     2402{
     2403    auto locker = holdLock(m_lock);
     2404    for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
     2405        if (worker != &Worker::current())
     2406            func(locker, *worker);
     2407    }
     2408    m_condition.notifyAll();
     2409}
     2410
     2411void Workers::report(String string)
     2412{
     2413    auto locker = holdLock(m_lock);
     2414    m_reports.append(string.isolatedCopy());
     2415    m_condition.notifyAll();
     2416}
     2417
     2418String Workers::tryGetReport()
     2419{
     2420    auto locker = holdLock(m_lock);
     2421    if (m_reports.isEmpty())
     2422        return String();
     2423    return m_reports.takeFirst();
     2424}
     2425
     2426String Workers::getReport()
     2427{
     2428    auto locker = holdLock(m_lock);
     2429    while (m_reports.isEmpty())
     2430        m_condition.wait(m_lock);
     2431    return m_reports.takeFirst();
     2432}
     2433
     2434Workers& Workers::singleton()
     2435{
     2436    static Workers* result;
     2437    static std::once_flag flag;
     2438    std::call_once(
     2439        flag,
     2440        [] {
     2441            result = new Workers();
     2442        });
     2443    return *result;
     2444}
     2445
     2446EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState* exec)
     2447{
     2448    VM& vm = exec->vm();
     2449    GlobalObject* result = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
     2450    return JSValue::encode(result->getDirect(vm, Identifier::fromString(exec, "$")));
     2451}
     2452
     2453EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState* exec)
     2454{
     2455    return functionTransferArrayBuffer(exec);
     2456}
     2457
     2458EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState* exec)
     2459{
     2460    VM& vm = exec->vm();
     2461    auto scope = DECLARE_THROW_SCOPE(vm);
     2462
     2463    String sourceCode = exec->argument(0).toWTFString(exec);
     2464    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2465   
     2466    GlobalObject* globalObject = jsDynamicCast<GlobalObject*>(
     2467        exec->thisValue().get(exec, Identifier::fromString(exec, "global")));
     2468    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2469    if (!globalObject)
     2470        return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected global to point to a global object"))));
     2471   
     2472    NakedPtr<Exception> evaluationException;
     2473    JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
     2474    if (evaluationException)
     2475        throwException(exec, scope, evaluationException);
     2476    return JSValue::encode(result);
     2477}
     2478
     2479EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState* exec)
     2480{
     2481    VM& vm = exec->vm();
     2482    auto scope = DECLARE_THROW_SCOPE(vm);
     2483
     2484    String sourceCode = exec->argument(0).toWTFString(exec).isolatedCopy();
     2485    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2486   
     2487    Lock didStartLock;
     2488    Condition didStartCondition;
     2489    bool didStart = false;
     2490   
     2491    ThreadIdentifier thread = createThread(
     2492        "JSC Agent",
     2493        [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
     2494            CommandLine commandLine(0, nullptr);
     2495            commandLine.m_interactive = false;
     2496            runJSC(
     2497                commandLine,
     2498                [&] (VM&, GlobalObject* globalObject) {
     2499                    // Notify the thread that started us that we have registered a worker.
     2500                    {
     2501                        auto locker = holdLock(didStartLock);
     2502                        didStart = true;
     2503                        didStartCondition.notifyOne();
     2504                    }
     2505                   
     2506                    NakedPtr<Exception> evaluationException;
     2507                    bool success = true;
     2508                    JSValue result;
     2509                    result = evaluate(globalObject->globalExec(), makeSource(sourceCode, SourceOrigin(ASCIILiteral("worker"))), JSValue(), evaluationException);
     2510                    if (evaluationException)
     2511                        result = evaluationException->value();
     2512                    checkException(globalObject, true, evaluationException, result, String(), false, false, success);
     2513                    if (!success)
     2514                        exit(1);
     2515                    return success;
     2516                });
     2517        });
     2518    detachThread(thread);
     2519   
     2520    {
     2521        auto locker = holdLock(didStartLock);
     2522        while (!didStart)
     2523            didStartCondition.wait(didStartLock);
     2524    }
     2525   
     2526    return JSValue::encode(jsUndefined());
     2527}
     2528
     2529EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec)
     2530{
     2531    VM& vm = exec->vm();
     2532    auto scope = DECLARE_THROW_SCOPE(vm);
     2533
     2534    JSValue callback = exec->argument(0);
     2535    CallData callData;
     2536    CallType callType = getCallData(callback, callData);
     2537    if (callType == CallType::None)
     2538        return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected callback"))));
     2539   
     2540    RefPtr<Message> message;
     2541    {
     2542        ReleaseHeapAccessScope releaseAccess(vm.heap);
     2543        message = Worker::current().dequeue();
     2544    }
     2545   
     2546    RefPtr<ArrayBuffer> nativeBuffer = ArrayBuffer::create(message->releaseContents());
     2547    JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(nativeBuffer->sharingMode()), nativeBuffer);
     2548   
     2549    MarkedArgumentBuffer args;
     2550    args.append(jsBuffer);
     2551    args.append(jsNumber(message->index()));
     2552    return JSValue::encode(call(exec, callback, callType, callData, jsNull(), args));
     2553}
     2554
     2555EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState* exec)
     2556{
     2557    VM& vm = exec->vm();
     2558    auto scope = DECLARE_THROW_SCOPE(vm);
     2559
     2560    String report = exec->argument(0).toWTFString(exec);
     2561    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2562   
     2563    Workers::singleton().report(report);
     2564   
     2565    return JSValue::encode(jsUndefined());
     2566}
     2567
     2568EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState* exec)
     2569{
     2570    VM& vm = exec->vm();
     2571    auto scope = DECLARE_THROW_SCOPE(vm);
     2572
     2573    if (exec->argumentCount() >= 1) {
     2574        Seconds seconds = Seconds::fromMilliseconds(exec->argument(0).toNumber(exec));
     2575        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2576        sleep(seconds);
     2577    }
     2578    return JSValue::encode(jsUndefined());
     2579}
     2580
     2581EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState* exec)
     2582{
     2583    VM& vm = exec->vm();
     2584    auto scope = DECLARE_THROW_SCOPE(vm);
     2585
     2586    JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
     2587    if (!jsBuffer || !jsBuffer->isShared())
     2588        return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected SharedArrayBuffer"))));
     2589   
     2590    int32_t index = exec->argument(1).toInt32(exec);
     2591    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2592   
     2593    Workers::singleton().broadcast(
     2594        [&] (const AbstractLocker& locker, Worker& worker) {
     2595            ArrayBuffer* nativeBuffer = jsBuffer->impl();
     2596            ArrayBufferContents contents;
     2597            nativeBuffer->transferTo(contents); // "transferTo" means "share" if the buffer is shared.
     2598            RefPtr<Message> message = adoptRef(new Message(WTFMove(contents), index));
     2599            worker.enqueue(locker, message);
     2600        });
     2601   
     2602    return JSValue::encode(jsUndefined());
     2603}
     2604
     2605EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState* exec)
     2606{
     2607    VM& vm = exec->vm();
     2608
     2609    String string = Workers::singleton().tryGetReport();
     2610    if (!string)
     2611        return JSValue::encode(jsNull());
     2612   
     2613    return JSValue::encode(jsString(&vm, string));
     2614}
     2615
     2616EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*)
     2617{
     2618    return JSValue::encode(jsUndefined());
     2619}
     2620
     2621EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState* exec)
     2622{
     2623    VM& vm = exec->vm();
     2624
     2625    String string;
     2626    {
     2627        ReleaseHeapAccessScope releaseAccess(vm.heap);
     2628        string = Workers::singleton().getReport();
     2629    }
     2630    if (!string)
     2631        return JSValue::encode(jsNull());
     2632   
     2633    return JSValue::encode(jsString(&vm, string));
    22222634}
    22232635
     
    29053317}
    29063318
     3319static void checkException(GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool& success)
     3320{
     3321    VM& vm = globalObject->vm();
     3322    if (!uncaughtExceptionName || !isLastFile) {
     3323        success = success && !hasException;
     3324        if (dump && !hasException)
     3325            printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
     3326        if (hasException)
     3327            dumpException(globalObject, value);
     3328    } else
     3329        success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), uncaughtExceptionName, alwaysDumpUncaughtException);
     3330}
     3331
    29073332static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool module)
    29083333{
     
    29163341    auto scope = DECLARE_CATCH_SCOPE(vm);
    29173342    bool success = true;
    2918 
    2919     auto checkException = [&] (bool isLastFile, bool hasException, JSValue value) {
    2920         if (!uncaughtExceptionName || !isLastFile) {
    2921             success = success && !hasException;
    2922             if (dump && !hasException)
    2923                 printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
    2924             if (hasException)
    2925                 dumpException(globalObject, value);
    2926         } else
    2927             success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), uncaughtExceptionName, alwaysDumpUncaughtException);
    2928     };
    29293343
    29303344#if ENABLE(SAMPLING_FLAGS)
     
    29603374
    29613375            JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
    2962                 checkException(isLastFile, false, exec->argument(0));
     3376                checkException(globalObject, isLastFile, false, exec->argument(0), uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
    29633377                return JSValue::encode(jsUndefined());
    29643378            });
    29653379
    29663380            JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
    2967                 checkException(isLastFile, true, exec->argument(0));
     3381                checkException(globalObject, isLastFile, true, exec->argument(0), uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
    29683382                return JSValue::encode(jsUndefined());
    29693383            });
     
    29773391            if (evaluationException)
    29783392                returnValue = evaluationException->value();
    2979             checkException(isLastFile, evaluationException, returnValue);
     3393            checkException(globalObject, isLastFile, evaluationException, returnValue, uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
    29803394        }
    29813395
     
    32423656}
    32433657
    3244 // We make this function no inline so that globalObject won't be on the stack if we do a GC in jscmain.
    3245 static int NEVER_INLINE runJSC(VM* vm, CommandLine options)
    3246 {
    3247     JSLockHolder locker(vm);
     3658template<typename Func>
     3659int runJSC(CommandLine options, const Func& func)
     3660{
     3661    Worker worker(Workers::singleton());
     3662   
     3663    VM& vm = VM::create(LargeHeap).leakRef();
     3664    JSLockHolder locker(&vm);
    32483665
    32493666    int result;
    3250     if (options.m_profile && !vm->m_perBytecodeProfiler)
    3251         vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*vm);
    3252 
    3253     GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
     3667    if (options.m_profile && !vm.m_perBytecodeProfiler)
     3668        vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm);
     3669
     3670    GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
    32543671    globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
    3255     bool success = runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_alwaysDumpUncaughtException, options.m_dump, options.m_module);
     3672    bool success = func(vm, globalObject);
    32563673    if (options.m_interactive && success)
    32573674        runInteractive(globalObject);
    32583675
    3259     vm->drainMicrotasks();
     3676    vm.drainMicrotasks();
    32603677    result = success && (test262AsyncTest == test262AsyncPassed) ? 0 : 3;
    32613678
     
    32643681
    32653682    if (options.m_profile) {
    3266         if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
     3683        if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
    32673684            fprintf(stderr, "could not save profiler output.\n");
    32683685    }
     
    32893706#endif
    32903707
     3708    if (Options::gcAtEnd()) {
     3709        // We need to hold the API lock to do a GC.
     3710        JSLockHolder locker(&vm);
     3711        vm.heap.collectAllGarbage();
     3712    }
     3713
     3714    if (options.m_dumpSamplingProfilerData) {
     3715#if ENABLE(SAMPLING_PROFILER)
     3716        JSLockHolder locker(&vm);
     3717        vm.samplingProfiler()->reportTopFunctions();
     3718        vm.samplingProfiler()->reportTopBytecodes();
     3719#else
     3720        dataLog("Sampling profiler is not enabled on this platform\n");
     3721#endif
     3722    }
     3723
    32913724    return result;
    32923725}
     
    33063739    startTimeoutThreadIfNeeded();
    33073740
    3308     VM* vm = &VM::create(LargeHeap).leakRef();
    33093741    int result;
    3310     result = runJSC(vm, options);
    3311 
    3312     if (Options::gcAtEnd()) {
    3313         // We need to hold the API lock to do a GC.
    3314         JSLockHolder locker(vm);
    3315         vm->heap.collectAllGarbage();
    3316     }
    3317 
    3318     if (options.m_dumpSamplingProfilerData) {
    3319 #if ENABLE(SAMPLING_PROFILER)
    3320         JSLockHolder locker(vm);
    3321         vm->samplingProfiler()->reportTopFunctions();
    3322         vm->samplingProfiler()->reportTopBytecodes();
    3323 #else
    3324         dataLog("Sampling profiler is not enabled on this platform\n");
    3325 #endif
    3326     }
     3742    result = runJSC(
     3743        options,
     3744        [&] (VM&, GlobalObject* globalObject) {
     3745            return runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_alwaysDumpUncaughtException, options.m_dump, options.m_module);
     3746        });
    33273747
    33283748    printSuperSamplerState();
Note: See TracChangeset for help on using the changeset viewer.