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

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

InPlaceAbstractState::beginBasicBlock shouldn't have to clear any abstract values
https://bugs.webkit.org/show_bug.cgi?id=185365

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch does three things to improve compile times:

  • Fixes some inlining goofs.


  • Adds the ability to measure compile times with run-jsc-benchmarks.


  • Dramatically improves the performance of InPlaceAbstractState::beginBasicBlock by removing the code that clears abstract values. It turns out that on constant folding "needed" this, in the sense that this was the only thing protecting it from loading the abstract value of a no-result node and then concluding that because it had a non-empty m_value, it could be constant-folded. Any node that produces a result will explicitly set its abstract value, so this problem can also be guarded by just having constant folding check if the node it wants to fold returns any result.


Solid 0.96% compile time speed-up across SunSpider-CompileTime and V8Spider-CompileTime.

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGAbstractValue.cpp:

(JSC::DFG::AbstractValue::set):

  • dfg/DFGAbstractValue.h:

(JSC::DFG::AbstractValue::merge):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::doToChildrenWithNode):
(JSC::DFG::Graph::doToChildren):

  • dfg/DFGInPlaceAbstractState.cpp:

(JSC::DFG::InPlaceAbstractState::beginBasicBlock):

  • jit/JIT.cpp:

(JSC::JIT::totalCompileTime):

  • jit/JIT.h:
  • jsc.cpp:

(GlobalObject::finishCreation):
(functionTotalCompileTime):

Source/WTF:

Fix some inlining goof-ups.

  • wtf/TinyPtrSet.h:

(WTF::TinyPtrSet::add):
(WTF::TinyPtrSet::merge):
(WTF::TinyPtrSet::addOutOfLine):
(WTF::TinyPtrSet::mergeOtherOutOfLine):

Tools:

Make it possible to measure compile times.

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