source: webkit/trunk/Source/JavaScriptCore/jsc.cpp@ 236362

Last change on this file since 236362 was 236362, checked in by [email protected], 7 years ago

Add functions to measure memory footprint to JSC
https://bugs.webkit.org/show_bug.cgi?id=189768

Reviewed by Saam Barati.

Rolling this back in again.

Provide system memory metrics for the current process to aid in memory reduction measurement and
tuning using native JS tests.

  • jsc.cpp:

(MemoryFootprint::now):
(MemoryFootprint::resetPeak):
(GlobalObject::finishCreation):
(JSCMemoryFootprint::JSCMemoryFootprint):
(JSCMemoryFootprint::createStructure):
(JSCMemoryFootprint::create):
(JSCMemoryFootprint::finishCreation):
(JSCMemoryFootprint::addProperty):
(functionResetMemoryPeak):

  • Property svn:eol-style set to native
File size: 100.6 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004-2018 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include "ArrayBuffer.h"
26#include "ArrayPrototype.h"
27#include "BuiltinNames.h"
28#include "ButterflyInlines.h"
29#include "CatchScope.h"
30#include "CodeBlock.h"
31#include "Completion.h"
32#include "ConfigFile.h"
33#include "Disassembler.h"
34#include "Exception.h"
35#include "ExceptionHelpers.h"
36#include "HeapProfiler.h"
37#include "HeapSnapshotBuilder.h"
38#include "InitializeThreading.h"
39#include "Interpreter.h"
40#include "JIT.h"
41#include "JSArray.h"
42#include "JSArrayBuffer.h"
43#include "JSBigInt.h"
44#include "JSCInlines.h"
45#include "JSFunction.h"
46#include "JSInternalPromise.h"
47#include "JSInternalPromiseDeferred.h"
48#include "JSLock.h"
49#include "JSModuleLoader.h"
50#include "JSNativeStdFunction.h"
51#include "JSONObject.h"
52#include "JSSourceCode.h"
53#include "JSString.h"
54#include "JSTypedArrays.h"
55#include "JSWebAssemblyInstance.h"
56#include "JSWebAssemblyMemory.h"
57#include "LLIntThunks.h"
58#include "ObjectConstructor.h"
59#include "ParserError.h"
60#include "ProfilerDatabase.h"
61#include "PromiseDeferredTimer.h"
62#include "ProtoCallFrame.h"
63#include "ReleaseHeapAccessScope.h"
64#include "SamplingProfiler.h"
65#include "StackVisitor.h"
66#include "StructureInlines.h"
67#include "StructureRareDataInlines.h"
68#include "SuperSampler.h"
69#include "TestRunnerUtils.h"
70#include "TypedArrayInlines.h"
71#include "WasmContext.h"
72#include "WasmFaultSignalHandler.h"
73#include "WasmMemory.h"
74#include <locale.h>
75#include <math.h>
76#include <stdio.h>
77#include <stdlib.h>
78#include <string.h>
79#include <sys/stat.h>
80#include <sys/types.h>
81#include <thread>
82#include <type_traits>
83#include <wtf/CommaPrinter.h>
84#include <wtf/MainThread.h>
85#include <wtf/MonotonicTime.h>
86#include <wtf/NeverDestroyed.h>
87#include <wtf/StringPrintStream.h>
88#include <wtf/WallTime.h>
89#include <wtf/text/StringBuilder.h>
90
91#if OS(WINDOWS)
92#include <direct.h>
93#include <wtf/text/win/WCharStringExtras.h>
94#else
95#include <unistd.h>
96#endif
97
98#if PLATFORM(COCOA)
99#include <crt_externs.h>
100#endif
101
102#if HAVE(READLINE)
103// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
104// We #define it to something else to avoid this conflict.
105#define Function ReadlineFunction
106#include <readline/history.h>
107#include <readline/readline.h>
108#undef Function
109#endif
110
111#if HAVE(SYS_TIME_H)
112#include <sys/time.h>
113#endif
114
115#if HAVE(SIGNAL_H)
116#include <signal.h>
117#endif
118
119#if COMPILER(MSVC)
120#include <crtdbg.h>
121#include <mmsystem.h>
122#include <windows.h>
123#endif
124
125#if PLATFORM(IOS) && CPU(ARM_THUMB2)
126#include <fenv.h>
127#include <arm/arch.h>
128#endif
129
130#if __has_include(<WebKitAdditions/MemoryFootprint.h>)
131#include <WebKitAdditions/MemoryFootprint.h>
132#else
133struct MemoryFootprint {
134 uint64_t current;
135 uint64_t peak;
136
137 static MemoryFootprint now()
138 {
139 return { 0L, 0L };
140 }
141
142 static void resetPeak()
143 {
144 }
145};
146#endif
147
148#if !defined(PATH_MAX)
149#define PATH_MAX 4096
150#endif
151
152using namespace JSC;
153using namespace WTF;
154
155namespace {
156
157NO_RETURN_WITH_VALUE static void jscExit(int status)
158{
159 waitForAsynchronousDisassembly();
160
161#if ENABLE(DFG_JIT)
162 if (DFG::isCrashing()) {
163 for (;;) {
164#if OS(WINDOWS)
165 Sleep(1000);
166#else
167 pause();
168#endif
169 }
170 }
171#endif // ENABLE(DFG_JIT)
172 exit(status);
173}
174
175class Masquerader : public JSNonFinalObject {
176public:
177 Masquerader(VM& vm, Structure* structure)
178 : Base(vm, structure)
179 {
180 }
181
182 typedef JSNonFinalObject Base;
183 static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
184
185 static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
186 {
187 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(vm, "Masquerading object allocated");
188 Structure* structure = createStructure(vm, globalObject, jsNull());
189 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
190 result->finishCreation(vm);
191 return result;
192 }
193
194 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
195 {
196 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
197 }
198
199 DECLARE_INFO;
200};
201
202const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Masquerader) };
203static unsigned asyncTestPasses { 0 };
204static unsigned asyncTestExpectedPasses { 0 };
205
206}
207
208template<typename Vector>
209static bool fillBufferWithContentsOfFile(const String& fileName, Vector& buffer);
210static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName);
211
212class CommandLine;
213class GlobalObject;
214class Workers;
215
216template<typename Func>
217int runJSC(CommandLine, bool isWorker, const Func&);
218static void checkException(ExecState*, GlobalObject*, bool isLastFile, bool hasException, JSValue, CommandLine&, bool& success);
219
220class Message : public ThreadSafeRefCounted<Message> {
221public:
222 Message(ArrayBufferContents&&, int32_t);
223 ~Message();
224
225 ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
226 int32_t index() const { return m_index; }
227
228private:
229 ArrayBufferContents m_contents;
230 int32_t m_index { 0 };
231};
232
233class Worker : public BasicRawSentinelNode<Worker> {
234public:
235 Worker(Workers&);
236 ~Worker();
237
238 void enqueue(const AbstractLocker&, RefPtr<Message>);
239 RefPtr<Message> dequeue();
240
241 static Worker& current();
242
243private:
244 static ThreadSpecific<Worker*>& currentWorker();
245
246 Workers& m_workers;
247 Deque<RefPtr<Message>> m_messages;
248};
249
250class Workers {
251public:
252 Workers();
253 ~Workers();
254
255 template<typename Func>
256 void broadcast(const Func&);
257
258 void report(String);
259 String tryGetReport();
260 String getReport();
261
262 static Workers& singleton();
263
264private:
265 friend class Worker;
266
267 Lock m_lock;
268 Condition m_condition;
269 SentinelLinkedList<Worker, BasicRawSentinelNode<Worker>> m_workers;
270 Deque<String> m_reports;
271};
272
273
274static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
275
276static EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState*);
277static EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState*);
278static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
279static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
280static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
281static EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState*);
282static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
283static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
284static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
285static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
286static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
287static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
288static EncodedJSValue JSC_HOST_CALL functionCreateMemoryFootprint(ExecState*);
289static EncodedJSValue JSC_HOST_CALL functionResetMemoryPeak(ExecState*);
290static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
291static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
292static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
293static EncodedJSValue JSC_HOST_CALL functionRunString(ExecState*);
294static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
295static EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState*);
296static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
297static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
298static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
299static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
300static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
301static EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState*);
302static EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState*);
303static EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState*);
304static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
305static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
306static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*);
307static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
308static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
309static EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*);
310static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
311static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*);
312static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
313static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
314static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
315static EncodedJSValue JSC_HOST_CALL functionIsPureNaN(ExecState*);
316static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
317static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
318static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
319static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
320static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
321static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*);
322static EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*);
323static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
324static EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*);
325static EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState*);
326static EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*);
327static EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState*);
328#if ENABLE(SAMPLING_PROFILER)
329static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*);
330static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*);
331#endif
332
333static EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*);
334static EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState*);
335static EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*);
336
337#if ENABLE(WEBASSEMBLY)
338static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState*);
339#endif
340
341#if ENABLE(SAMPLING_FLAGS)
342static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
343static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
344#endif
345
346static EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState*);
347static EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState*);
348static EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState*);
349static EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState*);
350static EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState*);
351static EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState*);
352static EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState*);
353static EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState*);
354static EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState*);
355static EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState*);
356static EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState*);
357static EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState*);
358static EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState*);
359static EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*);
360static EncodedJSValue JSC_HOST_CALL functionDollarAgentMonotonicNow(ExecState*);
361static EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState*);
362static EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState*);
363static EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState*);
364static EncodedJSValue JSC_HOST_CALL functionDisableRichSourceInfo(ExecState*);
365static EncodedJSValue JSC_HOST_CALL functionMallocInALoop(ExecState*);
366static EncodedJSValue JSC_HOST_CALL functionTotalCompileTime(ExecState*);
367
368struct Script {
369 enum class StrictMode {
370 Strict,
371 Sloppy
372 };
373
374 enum class ScriptType {
375 Script,
376 Module
377 };
378
379 enum class CodeSource {
380 File,
381 CommandLine
382 };
383
384 StrictMode strictMode;
385 CodeSource codeSource;
386 ScriptType scriptType;
387 char* argument;
388
389 Script(StrictMode strictMode, CodeSource codeSource, ScriptType scriptType, char *argument)
390 : strictMode(strictMode)
391 , codeSource(codeSource)
392 , scriptType(scriptType)
393 , argument(argument)
394 {
395 if (strictMode == StrictMode::Strict)
396 ASSERT(codeSource == CodeSource::File);
397 }
398};
399
400class CommandLine {
401public:
402 CommandLine(int argc, char** argv)
403 {
404 parseArguments(argc, argv);
405 }
406
407 bool m_interactive { false };
408 bool m_dump { false };
409 bool m_module { false };
410 bool m_exitCode { false };
411 Vector<Script> m_scripts;
412 Vector<String> m_arguments;
413 bool m_profile { false };
414 String m_profilerOutput;
415 String m_uncaughtExceptionName;
416 bool m_treatWatchdogExceptionAsSuccess { false };
417 bool m_alwaysDumpUncaughtException { false };
418 bool m_dumpSamplingProfilerData { false };
419 bool m_enableRemoteDebugging { false };
420
421 void parseArguments(int, char**);
422};
423
424static const char interactivePrompt[] = ">>> ";
425
426class StopWatch {
427public:
428 void start();
429 void stop();
430 long getElapsedMS(); // call stop() first
431
432private:
433 MonotonicTime m_startTime;
434 MonotonicTime m_stopTime;
435};
436
437void StopWatch::start()
438{
439 m_startTime = MonotonicTime::now();
440}
441
442void StopWatch::stop()
443{
444 m_stopTime = MonotonicTime::now();
445}
446
447long StopWatch::getElapsedMS()
448{
449 return (m_stopTime - m_startTime).millisecondsAs<long>();
450}
451
452template<typename Vector>
453static inline String stringFromUTF(const Vector& utf8)
454{
455 return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
456}
457
458template<typename Vector>
459static inline SourceCode jscSource(const Vector& utf8, const SourceOrigin& sourceOrigin, const String& filename)
460{
461 String str = stringFromUTF(utf8);
462 return makeSource(str, sourceOrigin, filename);
463}
464
465class GlobalObject : public JSGlobalObject {
466private:
467 GlobalObject(VM&, Structure*);
468
469public:
470 typedef JSGlobalObject Base;
471
472 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
473 {
474 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
475 object->finishCreation(vm, arguments);
476 return object;
477 }
478
479 static const bool needsDestruction = false;
480
481 DECLARE_INFO;
482 static const GlobalObjectMethodTable s_globalObjectMethodTable;
483
484 static Structure* createStructure(VM& vm, JSValue prototype)
485 {
486 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
487 }
488
489 static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
490
491protected:
492 void finishCreation(VM& vm, const Vector<String>& arguments)
493 {
494 Base::finishCreation(vm);
495
496 addFunction(vm, "debug", functionDebug, 1);
497 addFunction(vm, "describe", functionDescribe, 1);
498 addFunction(vm, "describeArray", functionDescribeArray, 1);
499 addFunction(vm, "print", functionPrintStdOut, 1);
500 addFunction(vm, "printErr", functionPrintStdErr, 1);
501 addFunction(vm, "quit", functionQuit, 0);
502 addFunction(vm, "gc", functionGCAndSweep, 0);
503 addFunction(vm, "fullGC", functionFullGC, 0);
504 addFunction(vm, "edenGC", functionEdenGC, 0);
505 addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
506 addFunction(vm, "gcHeapSize", functionHeapSize, 0);
507 addFunction(vm, "MemoryFootprint", functionCreateMemoryFootprint, 0);
508 addFunction(vm, "resetMemoryPeak", functionResetMemoryPeak, 0);
509 addFunction(vm, "addressOf", functionAddressOf, 1);
510 addFunction(vm, "version", functionVersion, 1);
511 addFunction(vm, "run", functionRun, 1);
512 addFunction(vm, "runString", functionRunString, 1);
513 addFunction(vm, "load", functionLoad, 1);
514 addFunction(vm, "loadString", functionLoadString, 1);
515 addFunction(vm, "readFile", functionReadFile, 2);
516 addFunction(vm, "read", functionReadFile, 2);
517 addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
518 addFunction(vm, "sleepSeconds", functionSleepSeconds, 1);
519 addFunction(vm, "jscStack", functionJSCStack, 1);
520 addFunction(vm, "readline", functionReadline, 0);
521 addFunction(vm, "preciseTime", functionPreciseTime, 0);
522 addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
523 addFunction(vm, "noInline", functionNeverInlineFunction, 1);
524 addFunction(vm, "noDFG", functionNoDFG, 1);
525 addFunction(vm, "noFTL", functionNoFTL, 1);
526 addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
527 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
528 addFunction(vm, "jscOptions", functionJSCOptions, 0);
529 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
530 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
531 addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
532 addFunction(vm, "failNextNewCodeBlock", functionFailNextNewCodeBlock, 1);
533#if ENABLE(SAMPLING_FLAGS)
534 addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
535 addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
536#endif
537
538 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
539 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse, IsFinalTierIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
540 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
541 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
542 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isPureNaN"), 0, functionIsPureNaN, CheckInt32Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
543 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
544
545 addFunction(vm, "effectful42", functionEffectful42, 0);
546 addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
547 addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
548
549 addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
550
551 addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
552
553 addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
554
555 addFunction(vm, "getRandomSeed", functionGetRandomSeed, 0);
556 addFunction(vm, "setRandomSeed", functionSetRandomSeed, 1);
557 addFunction(vm, "isRope", functionIsRope, 1);
558 addFunction(vm, "callerSourceOrigin", functionCallerSourceOrigin, 0);
559
560 addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
561
562 addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
563
564 addFunction(vm, "platformSupportsSamplingProfiler", functionPlatformSupportsSamplingProfiler, 0);
565 addFunction(vm, "generateHeapSnapshot", functionGenerateHeapSnapshot, 0);
566 addFunction(vm, "resetSuperSamplerState", functionResetSuperSamplerState, 0);
567 addFunction(vm, "ensureArrayStorage", functionEnsureArrayStorage, 0);
568#if ENABLE(SAMPLING_PROFILER)
569 addFunction(vm, "startSamplingProfiler", functionStartSamplingProfiler, 0);
570 addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
571#endif
572
573 addFunction(vm, "maxArguments", functionMaxArguments, 0);
574
575 addFunction(vm, "asyncTestStart", functionAsyncTestStart, 1);
576 addFunction(vm, "asyncTestPassed", functionAsyncTestPassed, 1);
577
578#if ENABLE(WEBASSEMBLY)
579 addFunction(vm, "WebAssemblyMemoryMode", functionWebAssemblyMemoryMode, 1);
580#endif
581
582 if (!arguments.isEmpty()) {
583 JSArray* array = constructEmptyArray(globalExec(), 0);
584 for (size_t i = 0; i < arguments.size(); ++i)
585 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
586 putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
587 }
588
589 putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
590
591 Structure* plainObjectStructure = JSFinalObject::createStructure(vm, this, objectPrototype(), 0);
592
593 JSObject* dollar = JSFinalObject::create(vm, plainObjectStructure);
594 putDirect(vm, Identifier::fromString(globalExec(), "$"), dollar);
595 putDirect(vm, Identifier::fromString(globalExec(), "$262"), dollar);
596
597 addFunction(vm, dollar, "createRealm", functionDollarCreateRealm, 0);
598 addFunction(vm, dollar, "detachArrayBuffer", functionDollarDetachArrayBuffer, 1);
599 addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1);
600
601 dollar->putDirect(vm, Identifier::fromString(globalExec(), "global"), this);
602
603 JSObject* agent = JSFinalObject::create(vm, plainObjectStructure);
604 dollar->putDirect(vm, Identifier::fromString(globalExec(), "agent"), agent);
605
606 // The test262 INTERPRETING.md document says that some of these functions are just in the main
607 // thread and some are in the other threads. We just put them in all threads.
608 addFunction(vm, agent, "start", functionDollarAgentStart, 1);
609 addFunction(vm, agent, "receiveBroadcast", functionDollarAgentReceiveBroadcast, 1);
610 addFunction(vm, agent, "report", functionDollarAgentReport, 1);
611 addFunction(vm, agent, "sleep", functionDollarAgentSleep, 1);
612 addFunction(vm, agent, "broadcast", functionDollarAgentBroadcast, 1);
613 addFunction(vm, agent, "getReport", functionDollarAgentGetReport, 0);
614 addFunction(vm, agent, "leaving", functionDollarAgentLeaving, 0);
615 addFunction(vm, agent, "monotonicNow", functionDollarAgentMonotonicNow, 0);
616
617 addFunction(vm, "waitForReport", functionWaitForReport, 0);
618
619 addFunction(vm, "heapCapacity", functionHeapCapacity, 0);
620 addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
621
622 addFunction(vm, "disableRichSourceInfo", functionDisableRichSourceInfo, 0);
623 addFunction(vm, "mallocInALoop", functionMallocInALoop, 0);
624 addFunction(vm, "totalCompileTime", functionTotalCompileTime, 0);
625 }
626
627 void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
628 {
629 Identifier identifier = Identifier::fromString(&vm, name);
630 object->putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
631 }
632
633 void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
634 {
635 addFunction(vm, this, name, function, arguments);
636 }
637
638 static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, JSValue, const SourceOrigin&);
639 static Identifier moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
640 static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
641 static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue);
642};
643
644static bool supportsRichSourceInfo = true;
645static bool shellSupportsRichSourceInfo(const JSGlobalObject*)
646{
647 return supportsRichSourceInfo;
648}
649
650const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
651const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
652 &shellSupportsRichSourceInfo,
653 &shouldInterruptScript,
654 &javaScriptRuntimeFlags,
655 nullptr, // queueTaskToEventLoop
656 &shouldInterruptScriptBeforeTimeout,
657 &moduleLoaderImportModule,
658 &moduleLoaderResolve,
659 &moduleLoaderFetch,
660 &moduleLoaderCreateImportMetaProperties,
661 nullptr, // moduleLoaderEvaluate
662 nullptr, // promiseRejectionTracker
663 nullptr, // defaultLanguage
664 nullptr, // compileStreaming
665 nullptr, // instantinateStreaming
666};
667
668GlobalObject::GlobalObject(VM& vm, Structure* structure)
669 : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
670{
671}
672
673static UChar pathSeparator()
674{
675#if OS(WINDOWS)
676 return '\\';
677#else
678 return '/';
679#endif
680}
681
682struct DirectoryName {
683 // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
684 String rootName;
685
686 // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
687 String queryName;
688};
689
690struct ModuleName {
691 ModuleName(const String& moduleName);
692
693 bool startsWithRoot() const
694 {
695 return !queries.isEmpty() && queries[0].isEmpty();
696 }
697
698 Vector<String> queries;
699};
700
701ModuleName::ModuleName(const String& moduleName)
702{
703 // A module name given from code is represented as the UNIX style path. Like, `./A/B.js`.
704 queries = moduleName.splitAllowingEmptyEntries('/');
705}
706
707static std::optional<DirectoryName> extractDirectoryName(const String& absolutePathToFile)
708{
709 size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
710 if (firstSeparatorPosition == notFound)
711 return std::nullopt;
712 DirectoryName directoryName;
713 directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
714 size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
715 ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
716 if (firstSeparatorPosition == lastSeparatorPosition)
717 directoryName.queryName = StringImpl::empty();
718 else {
719 size_t queryStartPosition = firstSeparatorPosition + 1;
720 size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
721 directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
722 }
723 return directoryName;
724}
725
726static std::optional<DirectoryName> currentWorkingDirectory()
727{
728#if OS(WINDOWS)
729 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
730 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
731 // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
732 // And other I/O functions taking a path name also truncate it. To avoid this situation,
733 //
734 // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
735 // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
736 //
737 // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
738 DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
739 if (!bufferLength)
740 return std::nullopt;
741 // In Windows, wchar_t is the UTF-16LE.
742 // https://msdn.microsoft.com/en-us/library/dd374081.aspx
743 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
744 Vector<wchar_t> buffer(bufferLength);
745 DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.data());
746 String directoryString = wcharToString(buffer.data(), lengthNotIncludingNull);
747 // We don't support network path like \\host\share\<path name>.
748 if (directoryString.startsWith("\\\\"))
749 return std::nullopt;
750#else
751 Vector<char> buffer(PATH_MAX);
752 if (!getcwd(buffer.data(), PATH_MAX))
753 return std::nullopt;
754 String directoryString = String::fromUTF8(buffer.data());
755#endif
756 if (directoryString.isEmpty())
757 return std::nullopt;
758
759 if (directoryString[directoryString.length() - 1] == pathSeparator())
760 return extractDirectoryName(directoryString);
761 // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
762 return extractDirectoryName(makeString(directoryString, pathSeparator()));
763}
764
765static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
766{
767 Vector<String> directoryPieces = directoryName.queryName.split(pathSeparator());
768
769 // Only first '/' is recognized as the path from the root.
770 if (moduleName.startsWithRoot())
771 directoryPieces.clear();
772
773 for (const auto& query : moduleName.queries) {
774 if (query == String(".."_s)) {
775 if (!directoryPieces.isEmpty())
776 directoryPieces.removeLast();
777 } else if (!query.isEmpty() && query != String("."_s))
778 directoryPieces.append(query);
779 }
780
781 StringBuilder builder;
782 builder.append(directoryName.rootName);
783 for (size_t i = 0; i < directoryPieces.size(); ++i) {
784 builder.append(directoryPieces[i]);
785 if (i + 1 != directoryPieces.size())
786 builder.append(pathSeparator());
787 }
788 return builder.toString();
789}
790
791static String absolutePath(const String& fileName)
792{
793 auto directoryName = currentWorkingDirectory();
794 if (!directoryName)
795 return fileName;
796 return resolvePath(directoryName.value(), ModuleName(fileName.impl()));
797}
798
799JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin& sourceOrigin)
800{
801 VM& vm = globalObject->vm();
802 auto scope = DECLARE_CATCH_SCOPE(vm);
803
804 auto rejectPromise = [&] (JSValue error) {
805 return JSInternalPromiseDeferred::create(exec, globalObject)->reject(exec, error);
806 };
807
808 if (sourceOrigin.isNull())
809 return rejectPromise(createError(exec, "Could not resolve the module specifier."_s));
810
811 auto referrer = sourceOrigin.string();
812 auto moduleName = moduleNameValue->value(exec);
813 if (UNLIKELY(scope.exception())) {
814 JSValue exception = scope.exception();
815 scope.clearException();
816 return rejectPromise(exception);
817 }
818
819 auto directoryName = extractDirectoryName(referrer.impl());
820 if (!directoryName)
821 return rejectPromise(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
822
823 auto result = JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), parameters, jsUndefined());
824 scope.releaseAssertNoException();
825 return result;
826}
827
828Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
829{
830 VM& vm = globalObject->vm();
831 auto scope = DECLARE_THROW_SCOPE(vm);
832
833 scope.releaseAssertNoException();
834 const Identifier key = keyValue.toPropertyKey(exec);
835 RETURN_IF_EXCEPTION(scope, { });
836
837 if (key.isSymbol())
838 return key;
839
840 if (referrerValue.isUndefined()) {
841 auto directoryName = currentWorkingDirectory();
842 if (!directoryName) {
843 throwException(exec, scope, createError(exec, "Could not resolve the current working directory."_s));
844 return { };
845 }
846 return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
847 }
848
849 const Identifier referrer = referrerValue.toPropertyKey(exec);
850 RETURN_IF_EXCEPTION(scope, { });
851
852 if (referrer.isSymbol()) {
853 auto directoryName = currentWorkingDirectory();
854 if (!directoryName) {
855 throwException(exec, scope, createError(exec, "Could not resolve the current working directory."_s));
856 return { };
857 }
858 return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
859 }
860
861 // If the referrer exists, we assume that the referrer is the correct absolute path.
862 auto directoryName = extractDirectoryName(referrer.impl());
863 if (!directoryName) {
864 throwException(exec, scope, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
865 return { };
866 }
867 return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
868}
869
870template<typename Vector>
871static void convertShebangToJSComment(Vector& buffer)
872{
873 if (buffer.size() >= 2) {
874 if (buffer[0] == '#' && buffer[1] == '!')
875 buffer[0] = buffer[1] = '/';
876 }
877}
878
879static RefPtr<Uint8Array> fillBufferWithContentsOfFile(FILE* file)
880{
881 if (fseek(file, 0, SEEK_END) == -1)
882 return nullptr;
883 long bufferCapacity = ftell(file);
884 if (bufferCapacity == -1)
885 return nullptr;
886 if (fseek(file, 0, SEEK_SET) == -1)
887 return nullptr;
888 RefPtr<Uint8Array> result = Uint8Array::create(bufferCapacity);
889 size_t readSize = fread(result->data(), 1, bufferCapacity, file);
890 if (readSize != static_cast<size_t>(bufferCapacity))
891 return nullptr;
892 return result;
893}
894
895static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName)
896{
897 FILE* f = fopen(fileName.utf8().data(), "rb");
898 if (!f) {
899 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
900 return nullptr;
901 }
902
903 RefPtr<Uint8Array> result = fillBufferWithContentsOfFile(f);
904 fclose(f);
905
906 return result;
907}
908
909template<typename Vector>
910static bool fillBufferWithContentsOfFile(FILE* file, Vector& buffer)
911{
912 // We might have injected "use strict"; at the top.
913 size_t initialSize = buffer.size();
914 if (fseek(file, 0, SEEK_END) == -1)
915 return false;
916 long bufferCapacity = ftell(file);
917 if (bufferCapacity == -1)
918 return false;
919 if (fseek(file, 0, SEEK_SET) == -1)
920 return false;
921 buffer.resize(bufferCapacity + initialSize);
922 size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
923 return readSize == buffer.size() - initialSize;
924}
925
926static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
927{
928 FILE* f = fopen(fileName.utf8().data(), "rb");
929 if (!f) {
930 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
931 return false;
932 }
933
934 bool result = fillBufferWithContentsOfFile(f, buffer);
935 fclose(f);
936
937 return result;
938}
939
940static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
941{
942 if (!fillBufferWithContentsOfFile(fileName, buffer))
943 return false;
944 convertShebangToJSComment(buffer);
945 return true;
946}
947
948template<typename Vector>
949static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector& buffer)
950{
951 // We assume that fileName is always an absolute path.
952#if OS(WINDOWS)
953 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
954 // Use long UNC to pass the long path name to the Windows APIs.
955 String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
956 auto pathName = stringToNullTerminatedWChar(longUNCPathName);
957 struct _stat status { };
958 if (_wstat(pathName.data(), &status))
959 return false;
960 if ((status.st_mode & S_IFMT) != S_IFREG)
961 return false;
962
963 FILE* f = _wfopen(pathName.data(), L"rb");
964#else
965 auto pathName = fileName.utf8();
966 struct stat status { };
967 if (stat(pathName.data(), &status))
968 return false;
969 if ((status.st_mode & S_IFMT) != S_IFREG)
970 return false;
971
972 FILE* f = fopen(pathName.data(), "r");
973#endif
974 if (!f) {
975 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
976 return false;
977 }
978
979 bool result = fillBufferWithContentsOfFile(f, buffer);
980 if (result)
981 convertShebangToJSComment(buffer);
982 fclose(f);
983
984 return result;
985}
986
987JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue, JSValue)
988{
989 VM& vm = globalObject->vm();
990 auto scope = DECLARE_CATCH_SCOPE(vm);
991 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
992 String moduleKey = key.toWTFString(exec);
993 if (UNLIKELY(scope.exception())) {
994 JSValue exception = scope.exception();
995 scope.clearException();
996 return deferred->reject(exec, exception);
997 }
998
999 // Here, now we consider moduleKey as the fileName.
1000 Vector<uint8_t> buffer;
1001 if (!fetchModuleFromLocalFileSystem(moduleKey, buffer)) {
1002 auto result = deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
1003 scope.releaseAssertNoException();
1004 return result;
1005 }
1006
1007#if ENABLE(WEBASSEMBLY)
1008 // FileSystem does not have mime-type header. The JSC shell recognizes WebAssembly's magic header.
1009 if (buffer.size() >= 4) {
1010 if (buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' && buffer[3] == 'm') {
1011 auto result = deferred->resolve(exec, JSSourceCode::create(vm, SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleKey }, moduleKey))));
1012 scope.releaseAssertNoException();
1013 return result;
1014 }
1015 }
1016#endif
1017
1018 auto result = deferred->resolve(exec, JSSourceCode::create(vm, makeSource(stringFromUTF(buffer), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
1019 scope.releaseAssertNoException();
1020 return result;
1021}
1022
1023JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSModuleRecord*, JSValue)
1024{
1025 VM& vm = exec->vm();
1026 auto scope = DECLARE_THROW_SCOPE(vm);
1027
1028 JSObject* metaProperties = constructEmptyObject(exec, globalObject->nullPrototypeObjectStructure());
1029 RETURN_IF_EXCEPTION(scope, nullptr);
1030
1031 metaProperties->putDirect(vm, Identifier::fromString(&vm, "filename"), key);
1032 RETURN_IF_EXCEPTION(scope, nullptr);
1033
1034 return metaProperties;
1035}
1036
1037static CString cStringFromViewWithString(ExecState* exec, ThrowScope& scope, StringViewWithUnderlyingString& viewWithString)
1038{
1039 Expected<CString, UTF8ConversionError> expectedString = viewWithString.view.tryGetUtf8();
1040 if (expectedString)
1041 return expectedString.value();
1042 switch (expectedString.error()) {
1043 case UTF8ConversionError::OutOfMemory:
1044 throwOutOfMemoryError(exec, scope);
1045 break;
1046 case UTF8ConversionError::IllegalSource:
1047 scope.throwException(exec, createError(exec, "Illegal source encountered during UTF8 conversion"));
1048 break;
1049 case UTF8ConversionError::SourceExhausted:
1050 scope.throwException(exec, createError(exec, "Source exhausted during UTF8 conversion"));
1051 break;
1052 default:
1053 RELEASE_ASSERT_NOT_REACHED();
1054 }
1055 return { };
1056}
1057
1058static EncodedJSValue printInternal(ExecState* exec, FILE* out)
1059{
1060 VM& vm = exec->vm();
1061 auto scope = DECLARE_THROW_SCOPE(vm);
1062
1063 if (asyncTestExpectedPasses) {
1064 JSValue value = exec->argument(0);
1065 if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete")) {
1066 asyncTestPasses++;
1067 return JSValue::encode(jsUndefined());
1068 }
1069 }
1070
1071 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1072 if (i)
1073 if (EOF == fputc(' ', out))
1074 goto fail;
1075
1076 auto viewWithString = exec->uncheckedArgument(i).toString(exec)->viewWithUnderlyingString(exec);
1077 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1078 auto string = cStringFromViewWithString(exec, scope, viewWithString);
1079 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1080 if (fprintf(out, "%s", string.data()) < 0)
1081 goto fail;
1082 }
1083
1084 fputc('\n', out);
1085fail:
1086 fflush(out);
1087 return JSValue::encode(jsUndefined());
1088}
1089
1090EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState* exec) { return printInternal(exec, stdout); }
1091EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState* exec) { return printInternal(exec, stderr); }
1092
1093EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
1094{
1095 VM& vm = exec->vm();
1096 auto scope = DECLARE_THROW_SCOPE(vm);
1097 auto viewWithString = exec->argument(0).toString(exec)->viewWithUnderlyingString(exec);
1098 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1099 auto string = cStringFromViewWithString(exec, scope, viewWithString);
1100 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1101 fprintf(stderr, "--> %s\n", string.data());
1102 return JSValue::encode(jsUndefined());
1103}
1104
1105EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
1106{
1107 if (exec->argumentCount() < 1)
1108 return JSValue::encode(jsUndefined());
1109 return JSValue::encode(jsString(exec, toString(exec->argument(0))));
1110}
1111
1112EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
1113{
1114 if (exec->argumentCount() < 1)
1115 return JSValue::encode(jsUndefined());
1116 VM& vm = exec->vm();
1117 JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0));
1118 if (!object)
1119 return JSValue::encode(jsNontrivialString(exec, "<not object>"_s));
1120 return JSValue::encode(jsNontrivialString(exec, toString("<Butterfly: ", RawPointer(object->butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1121}
1122
1123EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState* exec)
1124{
1125 VM& vm = exec->vm();
1126 auto scope = DECLARE_THROW_SCOPE(vm);
1127
1128 if (exec->argumentCount() >= 1) {
1129 Seconds seconds = Seconds(exec->argument(0).toNumber(exec));
1130 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1131 sleep(seconds);
1132 }
1133
1134 return JSValue::encode(jsUndefined());
1135}
1136
1137class FunctionJSCStackFunctor {
1138public:
1139 FunctionJSCStackFunctor(StringBuilder& trace)
1140 : m_trace(trace)
1141 {
1142 }
1143
1144 StackVisitor::Status operator()(StackVisitor& visitor) const
1145 {
1146 m_trace.append(String::format(" %zu %s\n", visitor->index(), visitor->toString().utf8().data()));
1147 return StackVisitor::Continue;
1148 }
1149
1150private:
1151 StringBuilder& m_trace;
1152};
1153
1154EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
1155{
1156 StringBuilder trace;
1157 trace.appendLiteral("--> Stack trace:\n");
1158
1159 FunctionJSCStackFunctor functor(trace);
1160 exec->iterate(functor);
1161 fprintf(stderr, "%s", trace.toString().utf8().data());
1162 return JSValue::encode(jsUndefined());
1163}
1164
1165EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
1166{
1167 VM& vm = exec->vm();
1168 JSLockHolder lock(vm);
1169 vm.heap.collectNow(Sync, CollectionScope::Full);
1170 return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
1171}
1172
1173EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
1174{
1175 VM& vm = exec->vm();
1176 JSLockHolder lock(vm);
1177 vm.heap.collectSync(CollectionScope::Full);
1178 return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
1179}
1180
1181EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1182{
1183 VM& vm = exec->vm();
1184 JSLockHolder lock(vm);
1185 vm.heap.collectSync(CollectionScope::Eden);
1186 return JSValue::encode(jsNumber(vm.heap.sizeAfterLastEdenCollection()));
1187}
1188
1189EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*)
1190{
1191 // It's best for this to be the first thing called in the
1192 // JS program so the option is set to true before we JIT.
1193 Options::forceGCSlowPaths() = true;
1194 return JSValue::encode(jsUndefined());
1195}
1196
1197EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
1198{
1199 VM& vm = exec->vm();
1200 JSLockHolder lock(vm);
1201 return JSValue::encode(jsNumber(vm.heap.size()));
1202}
1203
1204class JSCMemoryFootprint : public JSDestructibleObject {
1205 using Base = JSDestructibleObject;
1206public:
1207 JSCMemoryFootprint(VM& vm, Structure* structure)
1208 : Base(vm, structure)
1209 { }
1210
1211 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
1212 {
1213 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
1214 }
1215
1216 static JSCMemoryFootprint* create(VM& vm, JSGlobalObject* globalObject)
1217 {
1218 Structure* structure = createStructure(vm, globalObject, jsNull());
1219 JSCMemoryFootprint* footprint = new (NotNull, allocateCell<JSCMemoryFootprint>(vm.heap, sizeof(JSCMemoryFootprint))) JSCMemoryFootprint(vm, structure);
1220 footprint->finishCreation(vm);
1221 return footprint;
1222 }
1223
1224 void finishCreation(VM& vm)
1225 {
1226 Base::finishCreation(vm);
1227
1228 auto addProperty = [&] (VM& vm, const char* name, JSValue value) {
1229 JSCMemoryFootprint::addProperty(vm, name, value);
1230 };
1231
1232 MemoryFootprint footprint = MemoryFootprint::now();
1233
1234 // Report sizes in KBytes so that values up to GB are still integers.
1235 addProperty(vm, "current", jsNumber(footprint.current / 1024));
1236 addProperty(vm, "peak", jsNumber(footprint.peak / 1024));
1237 }
1238
1239 DECLARE_INFO;
1240
1241private:
1242 void addProperty(VM& vm, const char* name, JSValue value)
1243 {
1244 Identifier identifier = Identifier::fromString(&vm, name);
1245 putDirect(vm, identifier, value);
1246 }
1247};
1248
1249const ClassInfo JSCMemoryFootprint::s_info = { "MemoryFootprint", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCMemoryFootprint) };
1250
1251EncodedJSValue JSC_HOST_CALL functionCreateMemoryFootprint(ExecState* exec)
1252{
1253 VM& vm = exec->vm();
1254 JSLockHolder lock(vm);
1255 return JSValue::encode(JSCMemoryFootprint::create(vm, exec->lexicalGlobalObject()));
1256}
1257
1258EncodedJSValue JSC_HOST_CALL functionResetMemoryPeak(ExecState*)
1259{
1260 MemoryFootprint::resetPeak();
1261 return JSValue::encode(jsUndefined());
1262}
1263
1264// This function is not generally very helpful in 64-bit code as the tag and payload
1265// share a register. But in 32-bit JITed code the tag may not be checked if an
1266// optimization removes type checking requirements, such as in ===.
1267EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
1268{
1269 JSValue value = exec->argument(0);
1270 if (!value.isCell())
1271 return JSValue::encode(jsUndefined());
1272 // Need to cast to uint64_t so bitwise_cast will play along.
1273 uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
1274 EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
1275 return returnValue;
1276}
1277
1278EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
1279{
1280 // We need this function for compatibility with the Mozilla JS tests but for now
1281 // we don't actually do any version-specific handling
1282 return JSValue::encode(jsUndefined());
1283}
1284
1285EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
1286{
1287 VM& vm = exec->vm();
1288 auto scope = DECLARE_THROW_SCOPE(vm);
1289
1290 String fileName = exec->argument(0).toWTFString(exec);
1291 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1292 Vector<char> script;
1293 if (!fetchScriptFromLocalFileSystem(fileName, script))
1294 return JSValue::encode(throwException(exec, scope, createError(exec, "Could not open file."_s)));
1295
1296 GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1297
1298 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1299 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1300 for (unsigned i = 1; i < exec->argumentCount(); ++i) {
1301 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1302 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1303 }
1304 globalObject->putDirect(
1305 vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1306
1307 NakedPtr<Exception> exception;
1308 StopWatch stopWatch;
1309 stopWatch.start();
1310 evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), exception);
1311 stopWatch.stop();
1312
1313 if (exception) {
1314 throwException(globalObject->globalExec(), scope, exception);
1315 return JSValue::encode(jsUndefined());
1316 }
1317
1318 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1319}
1320
1321EncodedJSValue JSC_HOST_CALL functionRunString(ExecState* exec)
1322{
1323 VM& vm = exec->vm();
1324 auto scope = DECLARE_THROW_SCOPE(vm);
1325
1326 String source = exec->argument(0).toWTFString(exec);
1327 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1328
1329 GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1330
1331 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1332 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1333 for (unsigned i = 1; i < exec->argumentCount(); ++i) {
1334 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1335 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1336 }
1337 globalObject->putDirect(
1338 vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1339
1340 NakedPtr<Exception> exception;
1341 evaluate(globalObject->globalExec(), makeSource(source, exec->callerSourceOrigin()), JSValue(), exception);
1342
1343 if (exception) {
1344 scope.throwException(globalObject->globalExec(), exception);
1345 return JSValue::encode(jsUndefined());
1346 }
1347
1348 return JSValue::encode(globalObject);
1349}
1350
1351EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
1352{
1353 VM& vm = exec->vm();
1354 auto scope = DECLARE_THROW_SCOPE(vm);
1355
1356 String fileName = exec->argument(0).toWTFString(exec);
1357 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1358 Vector<char> script;
1359 if (!fetchScriptFromLocalFileSystem(fileName, script))
1360 return JSValue::encode(throwException(exec, scope, createError(exec, "Could not open file."_s)));
1361
1362 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1363
1364 NakedPtr<Exception> evaluationException;
1365 JSValue result = evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
1366 if (evaluationException)
1367 throwException(exec, scope, evaluationException);
1368 return JSValue::encode(result);
1369}
1370
1371EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
1372{
1373 VM& vm = exec->vm();
1374 auto scope = DECLARE_THROW_SCOPE(vm);
1375
1376 String sourceCode = exec->argument(0).toWTFString(exec);
1377 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1378 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1379
1380 NakedPtr<Exception> evaluationException;
1381 JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
1382 if (evaluationException)
1383 throwException(exec, scope, evaluationException);
1384 return JSValue::encode(result);
1385}
1386
1387EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
1388{
1389 VM& vm = exec->vm();
1390 auto scope = DECLARE_THROW_SCOPE(vm);
1391
1392 String fileName = exec->argument(0).toWTFString(exec);
1393 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1394
1395 bool isBinary = false;
1396 if (exec->argumentCount() > 1) {
1397 String type = exec->argument(1).toWTFString(exec);
1398 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1399 if (type != "binary")
1400 return throwVMError(exec, scope, "Expected 'binary' as second argument.");
1401 isBinary = true;
1402 }
1403
1404 RefPtr<Uint8Array> content = fillBufferWithContentsOfFile(fileName);
1405 if (!content)
1406 return throwVMError(exec, scope, "Could not open file.");
1407
1408 if (!isBinary)
1409 return JSValue::encode(jsString(exec, String::fromUTF8WithLatin1Fallback(content->data(), content->length())));
1410
1411 Structure* structure = exec->lexicalGlobalObject()->typedArrayStructure(TypeUint8);
1412 JSObject* result = JSUint8Array::create(vm, structure, WTFMove(content));
1413 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1414
1415 return JSValue::encode(result);
1416}
1417
1418EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
1419{
1420 VM& vm = exec->vm();
1421 auto scope = DECLARE_THROW_SCOPE(vm);
1422
1423 String fileName = exec->argument(0).toWTFString(exec);
1424 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1425 Vector<char> script;
1426 if (!fetchScriptFromLocalFileSystem(fileName, script))
1427 return JSValue::encode(throwException(exec, scope, createError(exec, "Could not open file."_s)));
1428
1429 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1430
1431 StopWatch stopWatch;
1432 stopWatch.start();
1433
1434 JSValue syntaxException;
1435 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), &syntaxException);
1436 stopWatch.stop();
1437
1438 if (!validSyntax)
1439 throwException(exec, scope, syntaxException);
1440 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1441}
1442
1443#if ENABLE(SAMPLING_FLAGS)
1444EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
1445{
1446 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1447 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1448 if ((flag >= 1) && (flag <= 32))
1449 SamplingFlags::setFlag(flag);
1450 }
1451 return JSValue::encode(jsNull());
1452}
1453
1454EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
1455{
1456 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1457 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1458 if ((flag >= 1) && (flag <= 32))
1459 SamplingFlags::clearFlag(flag);
1460 }
1461 return JSValue::encode(jsNull());
1462}
1463#endif
1464
1465EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState* exec)
1466{
1467 return JSValue::encode(jsNumber(exec->lexicalGlobalObject()->weakRandom().seed()));
1468}
1469
1470EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState* exec)
1471{
1472 VM& vm = exec->vm();
1473 auto scope = DECLARE_THROW_SCOPE(vm);
1474
1475 unsigned seed = exec->argument(0).toUInt32(exec);
1476 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1477 exec->lexicalGlobalObject()->weakRandom().setSeed(seed);
1478 return JSValue::encode(jsUndefined());
1479}
1480
1481EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState* exec)
1482{
1483 JSValue argument = exec->argument(0);
1484 if (!argument.isString())
1485 return JSValue::encode(jsBoolean(false));
1486 const StringImpl* impl = asString(argument)->tryGetValueImpl();
1487 return JSValue::encode(jsBoolean(!impl));
1488}
1489
1490EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState* state)
1491{
1492 SourceOrigin sourceOrigin = state->callerSourceOrigin();
1493 if (sourceOrigin.isNull())
1494 return JSValue::encode(jsNull());
1495 return JSValue::encode(jsString(state, sourceOrigin.string()));
1496}
1497
1498EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
1499{
1500 Vector<char, 256> line;
1501 int c;
1502 while ((c = getchar()) != EOF) {
1503 // FIXME: Should we also break on \r?
1504 if (c == '\n')
1505 break;
1506 line.append(c);
1507 }
1508 line.append('\0');
1509 return JSValue::encode(jsString(exec, line.data()));
1510}
1511
1512EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
1513{
1514 return JSValue::encode(jsNumber(WallTime::now().secondsSinceEpoch().value()));
1515}
1516
1517EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
1518{
1519 return JSValue::encode(setNeverInline(exec));
1520}
1521
1522EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
1523{
1524 return JSValue::encode(setNeverOptimize(exec));
1525}
1526
1527EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState* exec)
1528{
1529 if (exec->argumentCount()) {
1530 FunctionExecutable* executable = getExecutableForFunction(exec->argument(0));
1531 if (executable)
1532 executable->setNeverFTLOptimize(true);
1533 }
1534 return JSValue::encode(jsUndefined());
1535}
1536
1537EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState* exec)
1538{
1539 return JSValue::encode(setCannotUseOSRExitFuzzing(exec));
1540}
1541
1542EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
1543{
1544 return JSValue::encode(optimizeNextInvocation(exec));
1545}
1546
1547EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1548{
1549 return JSValue::encode(numberOfDFGCompiles(exec));
1550}
1551
1552Message::Message(ArrayBufferContents&& contents, int32_t index)
1553 : m_contents(WTFMove(contents))
1554 , m_index(index)
1555{
1556}
1557
1558Message::~Message()
1559{
1560}
1561
1562Worker::Worker(Workers& workers)
1563 : m_workers(workers)
1564{
1565 auto locker = holdLock(m_workers.m_lock);
1566 m_workers.m_workers.append(this);
1567
1568 *currentWorker() = this;
1569}
1570
1571Worker::~Worker()
1572{
1573 auto locker = holdLock(m_workers.m_lock);
1574 RELEASE_ASSERT(isOnList());
1575 remove();
1576}
1577
1578void Worker::enqueue(const AbstractLocker&, RefPtr<Message> message)
1579{
1580 m_messages.append(message);
1581}
1582
1583RefPtr<Message> Worker::dequeue()
1584{
1585 auto locker = holdLock(m_workers.m_lock);
1586 while (m_messages.isEmpty())
1587 m_workers.m_condition.wait(m_workers.m_lock);
1588 return m_messages.takeFirst();
1589}
1590
1591Worker& Worker::current()
1592{
1593 return **currentWorker();
1594}
1595
1596ThreadSpecific<Worker*>& Worker::currentWorker()
1597{
1598 static ThreadSpecific<Worker*>* result;
1599 static std::once_flag flag;
1600 std::call_once(
1601 flag,
1602 [] () {
1603 result = new ThreadSpecific<Worker*>();
1604 });
1605 return *result;
1606}
1607
1608Workers::Workers()
1609{
1610}
1611
1612Workers::~Workers()
1613{
1614 UNREACHABLE_FOR_PLATFORM();
1615}
1616
1617template<typename Func>
1618void Workers::broadcast(const Func& func)
1619{
1620 auto locker = holdLock(m_lock);
1621 for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
1622 if (worker != &Worker::current())
1623 func(locker, *worker);
1624 }
1625 m_condition.notifyAll();
1626}
1627
1628void Workers::report(String string)
1629{
1630 auto locker = holdLock(m_lock);
1631 m_reports.append(string.isolatedCopy());
1632 m_condition.notifyAll();
1633}
1634
1635String Workers::tryGetReport()
1636{
1637 auto locker = holdLock(m_lock);
1638 if (m_reports.isEmpty())
1639 return String();
1640 return m_reports.takeFirst();
1641}
1642
1643String Workers::getReport()
1644{
1645 auto locker = holdLock(m_lock);
1646 while (m_reports.isEmpty())
1647 m_condition.wait(m_lock);
1648 return m_reports.takeFirst();
1649}
1650
1651Workers& Workers::singleton()
1652{
1653 static Workers* result;
1654 static std::once_flag flag;
1655 std::call_once(
1656 flag,
1657 [] {
1658 result = new Workers();
1659 });
1660 return *result;
1661}
1662
1663EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState* exec)
1664{
1665 VM& vm = exec->vm();
1666 GlobalObject* result = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1667 return JSValue::encode(result->getDirect(vm, Identifier::fromString(exec, "$")));
1668}
1669
1670EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState* exec)
1671{
1672 return functionTransferArrayBuffer(exec);
1673}
1674
1675EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState* exec)
1676{
1677 VM& vm = exec->vm();
1678 auto scope = DECLARE_THROW_SCOPE(vm);
1679
1680 String sourceCode = exec->argument(0).toWTFString(exec);
1681 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1682
1683 GlobalObject* globalObject = jsDynamicCast<GlobalObject*>(vm,
1684 exec->thisValue().get(exec, Identifier::fromString(exec, "global")));
1685 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1686 if (!globalObject)
1687 return JSValue::encode(throwException(exec, scope, createError(exec, "Expected global to point to a global object"_s)));
1688
1689 NakedPtr<Exception> evaluationException;
1690 JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
1691 if (evaluationException)
1692 throwException(exec, scope, evaluationException);
1693 return JSValue::encode(result);
1694}
1695
1696EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState* exec)
1697{
1698 VM& vm = exec->vm();
1699 auto scope = DECLARE_THROW_SCOPE(vm);
1700
1701 String sourceCode = exec->argument(0).toWTFString(exec).isolatedCopy();
1702 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1703
1704 Lock didStartLock;
1705 Condition didStartCondition;
1706 bool didStart = false;
1707
1708 Thread::create(
1709 "JSC Agent",
1710 [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
1711 CommandLine commandLine(0, nullptr);
1712 commandLine.m_interactive = false;
1713 runJSC(
1714 commandLine, true,
1715 [&] (VM&, GlobalObject* globalObject, bool& success) {
1716 // Notify the thread that started us that we have registered a worker.
1717 {
1718 auto locker = holdLock(didStartLock);
1719 didStart = true;
1720 didStartCondition.notifyOne();
1721 }
1722
1723 NakedPtr<Exception> evaluationException;
1724 JSValue result;
1725 result = evaluate(globalObject->globalExec(), makeSource(sourceCode, SourceOrigin("worker"_s)), JSValue(), evaluationException);
1726 if (evaluationException)
1727 result = evaluationException->value();
1728 checkException(globalObject->globalExec(), globalObject, true, evaluationException, result, commandLine, success);
1729 if (!success)
1730 exit(1);
1731 });
1732 })->detach();
1733
1734 {
1735 auto locker = holdLock(didStartLock);
1736 while (!didStart)
1737 didStartCondition.wait(didStartLock);
1738 }
1739
1740 return JSValue::encode(jsUndefined());
1741}
1742
1743EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec)
1744{
1745 VM& vm = exec->vm();
1746 auto scope = DECLARE_THROW_SCOPE(vm);
1747
1748 JSValue callback = exec->argument(0);
1749 CallData callData;
1750 CallType callType = getCallData(vm, callback, callData);
1751 if (callType == CallType::None)
1752 return JSValue::encode(throwException(exec, scope, createError(exec, "Expected callback"_s)));
1753
1754 RefPtr<Message> message;
1755 {
1756 ReleaseHeapAccessScope releaseAccess(vm.heap);
1757 message = Worker::current().dequeue();
1758 }
1759
1760 RefPtr<ArrayBuffer> nativeBuffer = ArrayBuffer::create(message->releaseContents());
1761 ArrayBufferSharingMode sharingMode = nativeBuffer->sharingMode();
1762 JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(sharingMode), WTFMove(nativeBuffer));
1763
1764 MarkedArgumentBuffer args;
1765 args.append(jsBuffer);
1766 args.append(jsNumber(message->index()));
1767 if (UNLIKELY(args.hasOverflowed()))
1768 return JSValue::encode(throwOutOfMemoryError(exec, scope));
1769 scope.release();
1770 return JSValue::encode(call(exec, callback, callType, callData, jsNull(), args));
1771}
1772
1773EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState* exec)
1774{
1775 VM& vm = exec->vm();
1776 auto scope = DECLARE_THROW_SCOPE(vm);
1777
1778 String report = exec->argument(0).toWTFString(exec);
1779 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1780
1781 Workers::singleton().report(report);
1782
1783 return JSValue::encode(jsUndefined());
1784}
1785
1786EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState* exec)
1787{
1788 VM& vm = exec->vm();
1789 auto scope = DECLARE_THROW_SCOPE(vm);
1790
1791 if (exec->argumentCount() >= 1) {
1792 Seconds seconds = Seconds::fromMilliseconds(exec->argument(0).toNumber(exec));
1793 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1794 sleep(seconds);
1795 }
1796 return JSValue::encode(jsUndefined());
1797}
1798
1799EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState* exec)
1800{
1801 VM& vm = exec->vm();
1802 auto scope = DECLARE_THROW_SCOPE(vm);
1803
1804 JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
1805 if (!jsBuffer || !jsBuffer->isShared())
1806 return JSValue::encode(throwException(exec, scope, createError(exec, "Expected SharedArrayBuffer"_s)));
1807
1808 int32_t index = exec->argument(1).toInt32(exec);
1809 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1810
1811 Workers::singleton().broadcast(
1812 [&] (const AbstractLocker& locker, Worker& worker) {
1813 ArrayBuffer* nativeBuffer = jsBuffer->impl();
1814 ArrayBufferContents contents;
1815 nativeBuffer->transferTo(vm, contents); // "transferTo" means "share" if the buffer is shared.
1816 RefPtr<Message> message = adoptRef(new Message(WTFMove(contents), index));
1817 worker.enqueue(locker, message);
1818 });
1819
1820 return JSValue::encode(jsUndefined());
1821}
1822
1823EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState* exec)
1824{
1825 VM& vm = exec->vm();
1826
1827 String string = Workers::singleton().tryGetReport();
1828 if (!string)
1829 return JSValue::encode(jsNull());
1830
1831 return JSValue::encode(jsString(&vm, string));
1832}
1833
1834EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*)
1835{
1836 return JSValue::encode(jsUndefined());
1837}
1838
1839EncodedJSValue JSC_HOST_CALL functionDollarAgentMonotonicNow(ExecState*)
1840{
1841 return JSValue::encode(jsNumber(MonotonicTime::now().secondsSinceEpoch().milliseconds()));
1842}
1843
1844EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState* exec)
1845{
1846 VM& vm = exec->vm();
1847
1848 String string;
1849 {
1850 ReleaseHeapAccessScope releaseAccess(vm.heap);
1851 string = Workers::singleton().getReport();
1852 }
1853 if (!string)
1854 return JSValue::encode(jsNull());
1855
1856 return JSValue::encode(jsString(&vm, string));
1857}
1858
1859EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState* exec)
1860{
1861 VM& vm = exec->vm();
1862 return JSValue::encode(jsNumber(vm.heap.capacity()));
1863}
1864
1865EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState* exec)
1866{
1867 VM& vm = exec->vm();
1868 auto scope = DECLARE_THROW_SCOPE(vm);
1869
1870 double sleepTimeMs = 0;
1871 if (exec->argumentCount() >= 1) {
1872 sleepTimeMs = exec->argument(0).toNumber(exec);
1873 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1874 }
1875
1876 vm.heap.releaseAccess();
1877 if (sleepTimeMs)
1878 sleep(Seconds::fromMilliseconds(sleepTimeMs));
1879 vm.heap.acquireAccess();
1880 return JSValue::encode(jsUndefined());
1881}
1882
1883EncodedJSValue JSC_HOST_CALL functionDisableRichSourceInfo(ExecState*)
1884{
1885 supportsRichSourceInfo = false;
1886 return JSValue::encode(jsUndefined());
1887}
1888
1889EncodedJSValue JSC_HOST_CALL functionMallocInALoop(ExecState*)
1890{
1891 Vector<void*> ptrs;
1892 for (unsigned i = 0; i < 5000; ++i)
1893 ptrs.append(fastMalloc(1024 * 2));
1894 for (void* ptr : ptrs)
1895 fastFree(ptr);
1896 return JSValue::encode(jsUndefined());
1897}
1898
1899EncodedJSValue JSC_HOST_CALL functionTotalCompileTime(ExecState*)
1900{
1901#if ENABLE(JIT)
1902 return JSValue::encode(jsNumber(JIT::totalCompileTime().milliseconds()));
1903#else
1904 return JSValue::encode(jsNumber(0));
1905#endif
1906}
1907
1908template<typename ValueType>
1909typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
1910
1911template<typename ValueType>
1912typename std::enable_if<std::is_fundamental<ValueType>::value>::type addOption(VM& vm, JSObject* optionsObject, Identifier identifier, ValueType value)
1913{
1914 optionsObject->putDirect(vm, identifier, JSValue(value));
1915}
1916
1917EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState* exec)
1918{
1919 VM& vm = exec->vm();
1920 JSObject* optionsObject = constructEmptyObject(exec);
1921#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
1922 addOption(vm, optionsObject, Identifier::fromString(exec, #name_), Options::name_());
1923 JSC_OPTIONS(FOR_EACH_OPTION)
1924#undef FOR_EACH_OPTION
1925 return JSValue::encode(optionsObject);
1926}
1927
1928EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1929{
1930 if (exec->argumentCount() < 1)
1931 return JSValue::encode(jsUndefined());
1932
1933 CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1934 if (!block)
1935 return JSValue::encode(jsNumber(0));
1936
1937 return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1938}
1939
1940EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1941{
1942 VM& vm = exec->vm();
1943 auto scope = DECLARE_THROW_SCOPE(vm);
1944
1945 if (exec->argumentCount() < 1)
1946 return JSValue::encode(throwException(exec, scope, createError(exec, "Not enough arguments"_s)));
1947
1948 JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
1949 if (!buffer)
1950 return JSValue::encode(throwException(exec, scope, createError(exec, "Expected an array buffer"_s)));
1951
1952 ArrayBufferContents dummyContents;
1953 buffer->impl()->transferTo(vm, dummyContents);
1954
1955 return JSValue::encode(jsUndefined());
1956}
1957
1958EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState* exec)
1959{
1960 VM& vm = exec->vm();
1961 vm.setFailNextNewCodeBlock();
1962 return JSValue::encode(jsUndefined());
1963}
1964
1965EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1966{
1967 jscExit(EXIT_SUCCESS);
1968
1969#if COMPILER(MSVC)
1970 // Without this, Visual Studio will complain that this method does not return a value.
1971 return JSValue::encode(jsUndefined());
1972#endif
1973}
1974
1975EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1976
1977EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1978EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1979EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
1980{
1981 for (size_t i = 0; i < exec->argumentCount(); ++i) {
1982 if (!exec->argument(i).isInt32())
1983 return JSValue::encode(jsBoolean(false));
1984 }
1985 return JSValue::encode(jsBoolean(true));
1986}
1987
1988EncodedJSValue JSC_HOST_CALL functionIsPureNaN(ExecState* exec)
1989{
1990 for (size_t i = 0; i < exec->argumentCount(); ++i) {
1991 JSValue value = exec->argument(i);
1992 if (!value.isNumber())
1993 return JSValue::encode(jsBoolean(false));
1994 double number = value.asNumber();
1995 if (!std::isnan(number))
1996 return JSValue::encode(jsBoolean(false));
1997 if (isImpureNaN(number))
1998 return JSValue::encode(jsBoolean(false));
1999 }
2000 return JSValue::encode(jsBoolean(true));
2001}
2002
2003EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
2004
2005EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
2006{
2007 return JSValue::encode(jsNumber(42));
2008}
2009
2010EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
2011{
2012 VM& vm = exec->vm();
2013 return JSValue::encode(Masquerader::create(vm, exec->lexicalGlobalObject()));
2014}
2015
2016EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
2017{
2018 JSValue value = exec->argument(0);
2019 if (value.isObject())
2020 return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties(exec->vm())));
2021 return JSValue::encode(jsBoolean(false));
2022}
2023
2024EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
2025{
2026 VM& vm = exec->vm();
2027 vm.dumpTypeProfilerData();
2028 return JSValue::encode(jsUndefined());
2029}
2030
2031EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
2032{
2033 VM& vm = exec->vm();
2034 vm.drainMicrotasks();
2035 return JSValue::encode(jsUndefined());
2036}
2037
2038EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*)
2039{
2040#if USE(JSVALUE64)
2041 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
2042#else
2043 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
2044#endif
2045}
2046
2047EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState* exec)
2048{
2049 VM& vm = exec->vm();
2050 return JSValue::encode(GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>()));
2051}
2052
2053EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
2054{
2055 VM& vm = exec->vm();
2056 auto scope = DECLARE_THROW_SCOPE(vm);
2057
2058 String source = exec->argument(0).toWTFString(exec);
2059 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2060
2061 StopWatch stopWatch;
2062 stopWatch.start();
2063
2064 ParserError error;
2065 bool validSyntax = checkModuleSyntax(exec, makeSource(source, { }, String(), TextPosition(), SourceProviderSourceType::Module), error);
2066 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2067 stopWatch.stop();
2068
2069 if (!validSyntax)
2070 throwException(exec, scope, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
2071 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2072}
2073
2074EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*)
2075{
2076#if ENABLE(SAMPLING_PROFILER)
2077 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
2078#else
2079 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
2080#endif
2081}
2082
2083EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
2084{
2085 VM& vm = exec->vm();
2086 JSLockHolder lock(vm);
2087 auto scope = DECLARE_THROW_SCOPE(vm);
2088
2089 HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler());
2090 snapshotBuilder.buildSnapshot();
2091
2092 String jsonString = snapshotBuilder.json();
2093 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
2094 scope.releaseAssertNoException();
2095 return result;
2096}
2097
2098EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*)
2099{
2100 resetSuperSamplerState();
2101 return JSValue::encode(jsUndefined());
2102}
2103
2104EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState* exec)
2105{
2106 VM& vm = exec->vm();
2107 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
2108 if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(i)))
2109 object->ensureArrayStorage(vm);
2110 }
2111 return JSValue::encode(jsUndefined());
2112}
2113
2114#if ENABLE(SAMPLING_PROFILER)
2115EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState* exec)
2116{
2117 VM& vm = exec->vm();
2118 SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
2119 samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
2120 samplingProfiler.start();
2121 return JSValue::encode(jsUndefined());
2122}
2123
2124EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec)
2125{
2126 VM& vm = exec->vm();
2127 auto scope = DECLARE_THROW_SCOPE(vm);
2128
2129 if (!vm.samplingProfiler())
2130 return JSValue::encode(throwException(exec, scope, createError(exec, "Sampling profiler was never started"_s)));
2131
2132 String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
2133 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
2134 scope.releaseAssertNoException();
2135 return result;
2136}
2137#endif // ENABLE(SAMPLING_PROFILER)
2138
2139EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*)
2140{
2141 return JSValue::encode(jsNumber(JSC::maxArguments));
2142}
2143
2144EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState* exec)
2145{
2146 VM& vm = exec->vm();
2147 auto scope = DECLARE_THROW_SCOPE(vm);
2148
2149 JSValue numberOfAsyncPasses = exec->argument(0);
2150 if (!numberOfAsyncPasses.isUInt32())
2151 return throwVMError(exec, scope, "Expected first argument to a uint32"_s);
2152
2153 asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32();
2154 return encodedJSUndefined();
2155}
2156
2157EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*)
2158{
2159 asyncTestPasses++;
2160 return encodedJSUndefined();
2161}
2162
2163#if ENABLE(WEBASSEMBLY)
2164
2165static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState* exec)
2166{
2167 VM& vm = exec->vm();
2168 auto scope = DECLARE_THROW_SCOPE(vm);
2169
2170 if (!Options::useWebAssembly())
2171 return throwVMTypeError(exec, scope, "WebAssemblyMemoryMode should only be called if the useWebAssembly option is set"_s);
2172
2173 if (JSObject* object = exec->argument(0).getObject()) {
2174 if (auto* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, object))
2175 return JSValue::encode(jsString(&vm, makeString(memory->memory().mode())));
2176 if (auto* instance = jsDynamicCast<JSWebAssemblyInstance*>(vm, object))
2177 return JSValue::encode(jsString(&vm, makeString(instance->memoryMode())));
2178 }
2179
2180 return throwVMTypeError(exec, scope, "WebAssemblyMemoryMode expects either a WebAssembly.Memory or WebAssembly.Instance"_s);
2181}
2182
2183#endif // ENABLE(WEBASSEBLY)
2184
2185// Use SEH for Release builds only to get rid of the crash report dialog
2186// (luckily the same tests fail in Release and Debug builds so far). Need to
2187// be in a separate main function because the jscmain function requires object
2188// unwinding.
2189
2190#if COMPILER(MSVC) && !defined(_DEBUG)
2191#define TRY __try {
2192#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
2193#else
2194#define TRY
2195#define EXCEPT(x)
2196#endif
2197
2198int jscmain(int argc, char** argv);
2199
2200static double s_desiredTimeout;
2201static double s_timeoutMultiplier = 1.0;
2202
2203static void startTimeoutThreadIfNeeded()
2204{
2205 if (char* timeoutString = getenv("JSCTEST_timeout")) {
2206 if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
2207 dataLog("WARNING: timeout string is malformed, got ", timeoutString,
2208 " but expected a number. Not using a timeout.\n");
2209 } else {
2210 Thread::create("jsc Timeout Thread", [] () {
2211 Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier);
2212 sleep(timeoutDuration);
2213 dataLog("Timed out after ", timeoutDuration, " seconds!\n");
2214 CRASH();
2215 });
2216 }
2217 }
2218}
2219
2220int main(int argc, char** argv)
2221{
2222#if PLATFORM(IOS) && CPU(ARM_THUMB2)
2223 // Enabled IEEE754 denormal support.
2224 fenv_t env;
2225 fegetenv( &env );
2226 env.__fpscr &= ~0x01000000u;
2227 fesetenv( &env );
2228#endif
2229
2230#if OS(WINDOWS)
2231 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
2232 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
2233 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
2234 ::SetErrorMode(0);
2235
2236#if defined(_DEBUG)
2237 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
2238 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2239 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
2240 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
2241 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
2242 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
2243#endif
2244
2245 timeBeginPeriod(1);
2246#endif
2247
2248#if PLATFORM(GTK)
2249 if (!setlocale(LC_ALL, ""))
2250 WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
2251#endif
2252
2253 // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
2254 // threading yet, since that would do somethings that we'd like to defer until after we
2255 // have a chance to parse options.
2256 WTF::initializeThreading();
2257
2258#if PLATFORM(IOS)
2259 Options::crashIfCantAllocateJITMemory() = true;
2260#endif
2261
2262 // We can't use destructors in the following code because it uses Windows
2263 // Structured Exception Handling
2264 int res = 0;
2265 TRY
2266 res = jscmain(argc, argv);
2267 EXCEPT(res = 3)
2268 finalizeStatsAtEndOfTesting();
2269
2270 jscExit(res);
2271}
2272
2273static void dumpException(GlobalObject* globalObject, JSValue exception)
2274{
2275 VM& vm = globalObject->vm();
2276 auto scope = DECLARE_CATCH_SCOPE(vm);
2277
2278#define CHECK_EXCEPTION() do { \
2279 if (scope.exception()) { \
2280 scope.clearException(); \
2281 return; \
2282 } \
2283 } while (false)
2284
2285 printf("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data());
2286
2287 Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
2288 CHECK_EXCEPTION();
2289 Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
2290 CHECK_EXCEPTION();
2291 Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
2292 CHECK_EXCEPTION();
2293 Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
2294 CHECK_EXCEPTION();
2295
2296 JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
2297 CHECK_EXCEPTION();
2298 JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
2299 CHECK_EXCEPTION();
2300 JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
2301 CHECK_EXCEPTION();
2302 JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
2303 CHECK_EXCEPTION();
2304
2305 if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
2306 && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
2307 printf(
2308 "at %s:%s\n",
2309 fileNameValue.toWTFString(globalObject->globalExec()).utf8().data(),
2310 lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
2311 }
2312
2313 if (!stackValue.isUndefinedOrNull()) {
2314 auto stackString = stackValue.toWTFString(globalObject->globalExec());
2315 if (stackString.length())
2316 printf("%s\n", stackString.utf8().data());
2317 }
2318
2319#undef CHECK_EXCEPTION
2320}
2321
2322static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, CommandLine& options)
2323{
2324 const String& expectedExceptionName = options.m_uncaughtExceptionName;
2325 auto scope = DECLARE_CATCH_SCOPE(vm);
2326 scope.clearException();
2327 if (!exception) {
2328 printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
2329 return false;
2330 }
2331
2332 ExecState* exec = globalObject->globalExec();
2333 JSValue exceptionClass = globalObject->get(exec, Identifier::fromString(exec, expectedExceptionName));
2334 if (!exceptionClass.isObject() || scope.exception()) {
2335 printf("Expected uncaught exception with name '%s' but given exception class is not defined\n", expectedExceptionName.utf8().data());
2336 return false;
2337 }
2338
2339 bool isInstanceOfExpectedException = jsCast<JSObject*>(exceptionClass)->hasInstance(exec, exception);
2340 if (scope.exception()) {
2341 printf("Expected uncaught exception with name '%s' but given exception class fails performing hasInstance\n", expectedExceptionName.utf8().data());
2342 return false;
2343 }
2344 if (isInstanceOfExpectedException) {
2345 if (options.m_alwaysDumpUncaughtException)
2346 dumpException(globalObject, exception);
2347 return true;
2348 }
2349
2350 printf("Expected uncaught exception with name '%s' but exception value is not instance of this exception class\n", expectedExceptionName.utf8().data());
2351 dumpException(globalObject, exception);
2352 return false;
2353}
2354
2355static void checkException(ExecState* exec, GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, CommandLine& options, bool& success)
2356{
2357 VM& vm = globalObject->vm();
2358
2359 if (options.m_treatWatchdogExceptionAsSuccess && value.inherits<TerminatedExecutionError>(vm)) {
2360 ASSERT(hasException);
2361 return;
2362 }
2363
2364 if (!options.m_uncaughtExceptionName || !isLastFile) {
2365 success = success && !hasException;
2366 if (options.m_dump && !hasException)
2367 printf("End: %s\n", value.toWTFString(exec).utf8().data());
2368 if (hasException)
2369 dumpException(globalObject, value);
2370 } else
2371 success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), options);
2372}
2373
2374static void runWithOptions(GlobalObject* globalObject, CommandLine& options, bool& success)
2375{
2376 Vector<Script>& scripts = options.m_scripts;
2377 String fileName;
2378 Vector<char> scriptBuffer;
2379
2380 if (options.m_dump)
2381 JSC::Options::dumpGeneratedBytecodes() = true;
2382
2383 VM& vm = globalObject->vm();
2384 auto scope = DECLARE_CATCH_SCOPE(vm);
2385
2386#if ENABLE(SAMPLING_FLAGS)
2387 SamplingFlags::start();
2388#endif
2389
2390 for (size_t i = 0; i < scripts.size(); i++) {
2391 JSInternalPromise* promise = nullptr;
2392 bool isModule = options.m_module || scripts[i].scriptType == Script::ScriptType::Module;
2393 if (scripts[i].codeSource == Script::CodeSource::File) {
2394 fileName = scripts[i].argument;
2395 if (scripts[i].strictMode == Script::StrictMode::Strict)
2396 scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
2397
2398 if (isModule) {
2399 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName, jsUndefined(), jsUndefined());
2400 scope.releaseAssertNoException();
2401 } else {
2402 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer)) {
2403 success = false; // fail early so we can catch missing files
2404 return;
2405 }
2406 }
2407 } else {
2408 size_t commandLineLength = strlen(scripts[i].argument);
2409 scriptBuffer.resize(commandLineLength);
2410 std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
2411 fileName = "[Command Line]"_s;
2412 }
2413
2414 bool isLastFile = i == scripts.size() - 1;
2415 if (isModule) {
2416 if (!promise)
2417 promise = loadAndEvaluateModule(globalObject->globalExec(), makeSource(stringFromUTF(scriptBuffer), SourceOrigin { absolutePath(fileName) }, fileName, TextPosition(), SourceProviderSourceType::Module), jsUndefined());
2418 scope.clearException();
2419
2420 JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&success, &options, isLastFile](ExecState* exec) {
2421 checkException(exec, jsCast<GlobalObject*>(exec->lexicalGlobalObject()), isLastFile, false, exec->argument(0), options, success);
2422 return JSValue::encode(jsUndefined());
2423 });
2424
2425 JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&success, &options, isLastFile](ExecState* exec) {
2426 checkException(exec, jsCast<GlobalObject*>(exec->lexicalGlobalObject()), isLastFile, true, exec->argument(0), options, success);
2427 return JSValue::encode(jsUndefined());
2428 });
2429
2430 promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
2431 scope.releaseAssertNoException();
2432 vm.drainMicrotasks();
2433 } else {
2434 NakedPtr<Exception> evaluationException;
2435 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
2436 scope.assertNoException();
2437 if (evaluationException)
2438 returnValue = evaluationException->value();
2439 checkException(globalObject->globalExec(), globalObject, isLastFile, evaluationException, returnValue, options, success);
2440 }
2441
2442 scriptBuffer.clear();
2443 scope.clearException();
2444 }
2445
2446#if ENABLE(REGEXP_TRACING)
2447 vm.dumpRegExpTrace();
2448#endif
2449}
2450
2451#define RUNNING_FROM_XCODE 0
2452
2453static void runInteractive(GlobalObject* globalObject)
2454{
2455 VM& vm = globalObject->vm();
2456 auto scope = DECLARE_CATCH_SCOPE(vm);
2457
2458 std::optional<DirectoryName> directoryName = currentWorkingDirectory();
2459 if (!directoryName)
2460 return;
2461 SourceOrigin sourceOrigin(resolvePath(directoryName.value(), ModuleName("interpreter")));
2462
2463 bool shouldQuit = false;
2464 while (!shouldQuit) {
2465#if HAVE(READLINE) && !RUNNING_FROM_XCODE
2466 ParserError error;
2467 String source;
2468 do {
2469 error = ParserError();
2470 char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
2471 shouldQuit = !line;
2472 if (!line)
2473 break;
2474 source = source + String::fromUTF8(line);
2475 source = source + '\n';
2476 checkSyntax(vm, makeSource(source, sourceOrigin), error);
2477 if (!line[0]) {
2478 free(line);
2479 break;
2480 }
2481 add_history(line);
2482 free(line);
2483 } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
2484
2485 if (error.isValid()) {
2486 printf("%s:%d\n", error.message().utf8().data(), error.line());
2487 continue;
2488 }
2489
2490
2491 NakedPtr<Exception> evaluationException;
2492 JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, sourceOrigin), JSValue(), evaluationException);
2493#else
2494 printf("%s", interactivePrompt);
2495 Vector<char, 256> line;
2496 int c;
2497 while ((c = getchar()) != EOF) {
2498 // FIXME: Should we also break on \r?
2499 if (c == '\n')
2500 break;
2501 line.append(c);
2502 }
2503 if (line.isEmpty())
2504 break;
2505
2506 NakedPtr<Exception> evaluationException;
2507 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, sourceOrigin, sourceOrigin.string()), JSValue(), evaluationException);
2508#endif
2509 if (evaluationException)
2510 printf("Exception: %s\n", evaluationException->value().toWTFString(globalObject->globalExec()).utf8().data());
2511 else
2512 printf("%s\n", returnValue.toWTFString(globalObject->globalExec()).utf8().data());
2513
2514 scope.clearException();
2515 vm.drainMicrotasks();
2516 }
2517 printf("\n");
2518}
2519
2520static NO_RETURN void printUsageStatement(bool help = false)
2521{
2522 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
2523 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
2524 fprintf(stderr, " -e Evaluate argument as script code\n");
2525 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
2526 fprintf(stderr, " -h|--help Prints this help message\n");
2527 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
2528 fprintf(stderr, " -m Execute as a module\n");
2529#if HAVE(SIGNAL_H)
2530 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
2531#endif
2532 fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
2533 fprintf(stderr, " -x Output exit code before terminating\n");
2534 fprintf(stderr, "\n");
2535 fprintf(stderr, " --sample Collects and outputs sampling profiler data\n");
2536 fprintf(stderr, " --test262-async Check that some script calls the print function with the string 'Test262:AsyncTestComplete'\n");
2537 fprintf(stderr, " --strict-file=<file> Parse the given file as if it were in strict mode (this option may be passed more than once)\n");
2538 fprintf(stderr, " --module-file=<file> Parse and evaluate the given file as module (this option may be passed more than once)\n");
2539 fprintf(stderr, " --exception=<name> Check the last script exits with an uncaught exception with the specified name\n");
2540 fprintf(stderr, " --watchdog-exception-ok Uncaught watchdog exceptions exit with success\n");
2541 fprintf(stderr, " --dumpException Dump uncaught exception text\n");
2542 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
2543 fprintf(stderr, " --dumpOptions Dumps all non-default JSC VM options before continuing\n");
2544 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
2545 fprintf(stderr, "\n");
2546
2547 jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
2548}
2549
2550void CommandLine::parseArguments(int argc, char** argv)
2551{
2552 Options::initialize();
2553
2554 if (Options::dumpOptions()) {
2555 printf("Command line:");
2556#if PLATFORM(COCOA)
2557 for (char** envp = *_NSGetEnviron(); *envp; envp++) {
2558 const char* env = *envp;
2559 if (!strncmp("JSC_", env, 4))
2560 printf(" %s", env);
2561 }
2562#endif // PLATFORM(COCOA)
2563 for (int i = 0; i < argc; ++i)
2564 printf(" %s", argv[i]);
2565 printf("\n");
2566 }
2567
2568 int i = 1;
2569 JSC::Options::DumpLevel dumpOptionsLevel = JSC::Options::DumpLevel::None;
2570 bool needToExit = false;
2571
2572 bool hasBadJSCOptions = false;
2573 for (; i < argc; ++i) {
2574 const char* arg = argv[i];
2575 if (!strcmp(arg, "-f")) {
2576 if (++i == argc)
2577 printUsageStatement();
2578 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
2579 continue;
2580 }
2581 if (!strcmp(arg, "-e")) {
2582 if (++i == argc)
2583 printUsageStatement();
2584 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::CommandLine, Script::ScriptType::Script, argv[i]));
2585 continue;
2586 }
2587 if (!strcmp(arg, "-i")) {
2588 m_interactive = true;
2589 continue;
2590 }
2591 if (!strcmp(arg, "-d")) {
2592 m_dump = true;
2593 continue;
2594 }
2595 if (!strcmp(arg, "-p")) {
2596 if (++i == argc)
2597 printUsageStatement();
2598 m_profile = true;
2599 m_profilerOutput = argv[i];
2600 continue;
2601 }
2602 if (!strcmp(arg, "-m")) {
2603 m_module = true;
2604 continue;
2605 }
2606 if (!strcmp(arg, "-s")) {
2607#if HAVE(SIGNAL_H)
2608 signal(SIGILL, _exit);
2609 signal(SIGFPE, _exit);
2610 signal(SIGBUS, _exit);
2611 signal(SIGSEGV, _exit);
2612#endif
2613 continue;
2614 }
2615 if (!strcmp(arg, "-x")) {
2616 m_exitCode = true;
2617 continue;
2618 }
2619 if (!strcmp(arg, "--")) {
2620 ++i;
2621 break;
2622 }
2623 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
2624 printUsageStatement(true);
2625
2626 if (!strcmp(arg, "--options")) {
2627 dumpOptionsLevel = JSC::Options::DumpLevel::Verbose;
2628 needToExit = true;
2629 continue;
2630 }
2631 if (!strcmp(arg, "--dumpOptions")) {
2632 dumpOptionsLevel = JSC::Options::DumpLevel::Overridden;
2633 continue;
2634 }
2635 if (!strcmp(arg, "--sample")) {
2636 JSC::Options::useSamplingProfiler() = true;
2637 JSC::Options::collectSamplingProfilerDataForJSCShell() = true;
2638 m_dumpSamplingProfilerData = true;
2639 continue;
2640 }
2641
2642 static const char* timeoutMultiplierOptStr = "--timeoutMultiplier=";
2643 static const unsigned timeoutMultiplierOptStrLength = strlen(timeoutMultiplierOptStr);
2644 if (!strncmp(arg, timeoutMultiplierOptStr, timeoutMultiplierOptStrLength)) {
2645 const char* valueStr = &arg[timeoutMultiplierOptStrLength];
2646 if (sscanf(valueStr, "%lf", &s_timeoutMultiplier) != 1)
2647 dataLog("WARNING: --timeoutMultiplier=", valueStr, " is invalid. Expects a numeric ratio.\n");
2648 continue;
2649 }
2650
2651 if (!strcmp(arg, "--test262-async")) {
2652 asyncTestExpectedPasses++;
2653 continue;
2654 }
2655
2656 if (!strcmp(arg, "--remote-debug")) {
2657 m_enableRemoteDebugging = true;
2658 continue;
2659 }
2660
2661 static const unsigned strictFileStrLength = strlen("--strict-file=");
2662 if (!strncmp(arg, "--strict-file=", strictFileStrLength)) {
2663 m_scripts.append(Script(Script::StrictMode::Strict, Script::CodeSource::File, Script::ScriptType::Script, argv[i] + strictFileStrLength));
2664 continue;
2665 }
2666
2667 static const unsigned moduleFileStrLength = strlen("--module-file=");
2668 if (!strncmp(arg, "--module-file=", moduleFileStrLength)) {
2669 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Module, argv[i] + moduleFileStrLength));
2670 continue;
2671 }
2672
2673 if (!strcmp(arg, "--dumpException")) {
2674 m_alwaysDumpUncaughtException = true;
2675 continue;
2676 }
2677
2678 static const unsigned exceptionStrLength = strlen("--exception=");
2679 if (!strncmp(arg, "--exception=", exceptionStrLength)) {
2680 m_uncaughtExceptionName = String(arg + exceptionStrLength);
2681 continue;
2682 }
2683
2684 if (!strcmp(arg, "--watchdog-exception-ok")) {
2685 m_treatWatchdogExceptionAsSuccess = true;
2686 continue;
2687 }
2688
2689 // See if the -- option is a JSC VM option.
2690 if (strstr(arg, "--") == arg) {
2691 if (!JSC::Options::setOption(&arg[2])) {
2692 hasBadJSCOptions = true;
2693 dataLog("ERROR: invalid option: ", arg, "\n");
2694 }
2695 continue;
2696 }
2697
2698 // This arg is not recognized by the VM nor by jsc. Pass it on to the
2699 // script.
2700 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
2701 }
2702
2703 if (hasBadJSCOptions && JSC::Options::validateOptions())
2704 CRASH();
2705
2706 if (m_scripts.isEmpty())
2707 m_interactive = true;
2708
2709 for (; i < argc; ++i)
2710 m_arguments.append(argv[i]);
2711
2712 if (dumpOptionsLevel != JSC::Options::DumpLevel::None) {
2713 const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
2714 ? "Modified JSC runtime options:"
2715 : "All JSC runtime options:";
2716 JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
2717 }
2718 JSC::Options::ensureOptionsAreCoherent();
2719 if (needToExit)
2720 jscExit(EXIT_SUCCESS);
2721}
2722
2723template<typename Func>
2724int runJSC(CommandLine options, bool isWorker, const Func& func)
2725{
2726 Worker worker(Workers::singleton());
2727
2728 VM& vm = VM::create(LargeHeap).leakRef();
2729 int result;
2730 bool success = true;
2731 GlobalObject* globalObject = nullptr;
2732 {
2733 JSLockHolder locker(vm);
2734
2735 if (options.m_profile && !vm.m_perBytecodeProfiler)
2736 vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm);
2737
2738 globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
2739 globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
2740 func(vm, globalObject, success);
2741 vm.drainMicrotasks();
2742 }
2743 vm.promiseDeferredTimer->runRunLoop();
2744 {
2745 JSLockHolder locker(vm);
2746 if (options.m_interactive && success)
2747 runInteractive(globalObject);
2748 }
2749
2750 result = success && (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3;
2751
2752 if (options.m_exitCode) {
2753 printf("jsc exiting %d", result);
2754 if (asyncTestExpectedPasses != asyncTestPasses)
2755 printf(" because expected: %d async test passes but got: %d async test passes", asyncTestExpectedPasses, asyncTestPasses);
2756 printf("\n");
2757 }
2758
2759 if (options.m_profile) {
2760 JSLockHolder locker(vm);
2761 if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
2762 fprintf(stderr, "could not save profiler output.\n");
2763 }
2764
2765#if ENABLE(JIT)
2766 {
2767 JSLockHolder locker(vm);
2768 if (Options::useExceptionFuzz())
2769 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
2770 bool fireAtEnabled =
2771 Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
2772 if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
2773 printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
2774 if (Options::useOSRExitFuzz()) {
2775 printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
2776 printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
2777 }
2778
2779
2780 auto compileTimeStats = JIT::compileTimeStats();
2781 Vector<CString> compileTimeKeys;
2782 for (auto& entry : compileTimeStats)
2783 compileTimeKeys.append(entry.key);
2784 std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
2785 for (CString key : compileTimeKeys)
2786 printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key).milliseconds());
2787 }
2788#endif
2789
2790 if (Options::gcAtEnd()) {
2791 // We need to hold the API lock to do a GC.
2792 JSLockHolder locker(&vm);
2793 vm.heap.collectNow(Sync, CollectionScope::Full);
2794 }
2795
2796 if (options.m_dumpSamplingProfilerData) {
2797#if ENABLE(SAMPLING_PROFILER)
2798 JSLockHolder locker(&vm);
2799 vm.samplingProfiler()->reportTopFunctions();
2800 vm.samplingProfiler()->reportTopBytecodes();
2801#else
2802 dataLog("Sampling profiler is not enabled on this platform\n");
2803#endif
2804 }
2805
2806 if (isWorker) {
2807 JSLockHolder locker(vm);
2808 // This is needed because we don't want the worker's main
2809 // thread to die before its compilation threads finish.
2810 vm.deref();
2811 }
2812
2813 return result;
2814}
2815
2816int jscmain(int argc, char** argv)
2817{
2818 // Need to override and enable restricted options before we start parsing options below.
2819 Options::enableRestrictedOptions(true);
2820
2821 // Note that the options parsing can affect VM creation, and thus
2822 // comes first.
2823 CommandLine options(argc, argv);
2824
2825 processConfigFile(Options::configFile(), "jsc");
2826
2827 // Initialize JSC before getting VM.
2828 WTF::initializeMainThread();
2829 JSC::initializeThreading();
2830 startTimeoutThreadIfNeeded();
2831#if ENABLE(WEBASSEMBLY)
2832 JSC::Wasm::enableFastMemory();
2833#endif
2834 Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled();
2835
2836 int result = runJSC(
2837 options, false,
2838 [&] (VM&, GlobalObject* globalObject, bool& success) {
2839 runWithOptions(globalObject, options, success);
2840 });
2841
2842 printSuperSamplerState();
2843
2844 return result;
2845}
2846
2847#if OS(WINDOWS)
2848extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
2849{
2850 return main(argc, const_cast<char**>(argv));
2851}
2852#endif
Note: See TracBrowser for help on using the repository browser.