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

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

[Win] jsc.exe sometimes never exits.
https://bugs.webkit.org/show_bug.cgi?id=158073

Reviewed by Mark Lam.

Make sure the VM is deleted after the test has finished. This will gracefully stop the sampling profiler thread,
and give the thread the opportunity to release the machine thread lock aquired in SamplingProfiler::takeSample.
If the sampling profiler thread was terminated while holding the machine thread lock, the machine thread will
not be able to grab the lock afterwards.

  • jsc.cpp:

(jscmain):

  • Property svn:eol-style set to native
File size: 89.9 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004-2008, 2012-2013, 2015-2016 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 "ArrayPrototype.h"
26#include "BuiltinExecutableCreator.h"
27#include "ButterflyInlines.h"
28#include "CodeBlock.h"
29#include "Completion.h"
30#include "CopiedSpaceInlines.h"
31#include "Disassembler.h"
32#include "Exception.h"
33#include "ExceptionHelpers.h"
34#include "GetterSetter.h"
35#include "HeapProfiler.h"
36#include "HeapSnapshotBuilder.h"
37#include "HeapStatistics.h"
38#include "InitializeThreading.h"
39#include "Interpreter.h"
40#include "JIT.h"
41#include "JSArray.h"
42#include "JSArrayBuffer.h"
43#include "JSCInlines.h"
44#include "JSFunction.h"
45#include "JSInternalPromise.h"
46#include "JSInternalPromiseDeferred.h"
47#include "JSLock.h"
48#include "JSNativeStdFunction.h"
49#include "JSONObject.h"
50#include "JSProxy.h"
51#include "JSString.h"
52#include "JSWASMModule.h"
53#include "LLIntData.h"
54#include "ParserError.h"
55#include "ProfilerDatabase.h"
56#include "SamplingProfiler.h"
57#include "ShadowChicken.h"
58#include "StackVisitor.h"
59#include "StructureInlines.h"
60#include "StructureRareDataInlines.h"
61#include "SuperSampler.h"
62#include "TestRunnerUtils.h"
63#include "TypeProfilerLog.h"
64#include "WASMModuleParser.h"
65#include <locale.h>
66#include <math.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <thread>
71#include <wtf/CurrentTime.h>
72#include <wtf/MainThread.h>
73#include <wtf/StringPrintStream.h>
74#include <wtf/text/StringBuilder.h>
75
76#if OS(WINDOWS)
77#include <direct.h>
78#else
79#include <unistd.h>
80#endif
81
82#if HAVE(READLINE)
83// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
84// We #define it to something else to avoid this conflict.
85#define Function ReadlineFunction
86#include <readline/history.h>
87#include <readline/readline.h>
88#undef Function
89#endif
90
91#if HAVE(SYS_TIME_H)
92#include <sys/time.h>
93#endif
94
95#if HAVE(SIGNAL_H)
96#include <signal.h>
97#endif
98
99#if COMPILER(MSVC)
100#include <crtdbg.h>
101#include <mmsystem.h>
102#include <windows.h>
103#endif
104
105#if PLATFORM(IOS) && CPU(ARM_THUMB2)
106#include <fenv.h>
107#include <arm/arch.h>
108#endif
109
110#if PLATFORM(EFL)
111#include <Ecore.h>
112#endif
113
114#if !defined(PATH_MAX)
115#define PATH_MAX 4096
116#endif
117
118using namespace JSC;
119using namespace WTF;
120
121namespace {
122
123NO_RETURN_WITH_VALUE static void jscExit(int status)
124{
125 waitForAsynchronousDisassembly();
126
127#if ENABLE(DFG_JIT)
128 if (DFG::isCrashing()) {
129 for (;;) {
130#if OS(WINDOWS)
131 Sleep(1000);
132#else
133 pause();
134#endif
135 }
136 }
137#endif // ENABLE(DFG_JIT)
138 exit(status);
139}
140
141class Element;
142class ElementHandleOwner;
143class Masuqerader;
144class Root;
145class RuntimeArray;
146
147class Element : public JSNonFinalObject {
148public:
149 Element(VM& vm, Structure* structure)
150 : Base(vm, structure)
151 {
152 }
153
154 typedef JSNonFinalObject Base;
155 static const bool needsDestruction = false;
156
157 Root* root() const { return m_root.get(); }
158 void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
159
160 static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
161 {
162 Structure* structure = createStructure(vm, globalObject, jsNull());
163 Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
164 element->finishCreation(vm, root);
165 return element;
166 }
167
168 void finishCreation(VM&, Root*);
169
170 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
171 {
172 Element* thisObject = jsCast<Element*>(cell);
173 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
174 Base::visitChildren(thisObject, visitor);
175 visitor.append(&thisObject->m_root);
176 }
177
178 static ElementHandleOwner* handleOwner();
179
180 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
181 {
182 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
183 }
184
185 DECLARE_INFO;
186
187private:
188 WriteBarrier<Root> m_root;
189};
190
191class ElementHandleOwner : public WeakHandleOwner {
192public:
193 virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
194 {
195 Element* element = jsCast<Element*>(handle.slot()->asCell());
196 return visitor.containsOpaqueRoot(element->root());
197 }
198};
199
200class Masquerader : public JSNonFinalObject {
201public:
202 Masquerader(VM& vm, Structure* structure)
203 : Base(vm, structure)
204 {
205 }
206
207 typedef JSNonFinalObject Base;
208 static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
209
210 static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
211 {
212 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(vm, "Masquerading object allocated");
213 Structure* structure = createStructure(vm, globalObject, jsNull());
214 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
215 result->finishCreation(vm);
216 return result;
217 }
218
219 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
220 {
221 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
222 }
223
224 DECLARE_INFO;
225};
226
227class Root : public JSDestructibleObject {
228public:
229 Root(VM& vm, Structure* structure)
230 : Base(vm, structure)
231 {
232 }
233
234 Element* element()
235 {
236 return m_element.get();
237 }
238
239 void setElement(Element* element)
240 {
241 Weak<Element> newElement(element, Element::handleOwner());
242 m_element.swap(newElement);
243 }
244
245 static Root* create(VM& vm, JSGlobalObject* globalObject)
246 {
247 Structure* structure = createStructure(vm, globalObject, jsNull());
248 Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
249 root->finishCreation(vm);
250 return root;
251 }
252
253 typedef JSDestructibleObject Base;
254
255 DECLARE_INFO;
256 static const bool needsDestruction = true;
257
258 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
259 {
260 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
261 }
262
263 static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
264 {
265 Base::visitChildren(thisObject, visitor);
266 visitor.addOpaqueRoot(thisObject);
267 }
268
269private:
270 Weak<Element> m_element;
271};
272
273class ImpureGetter : public JSNonFinalObject {
274public:
275 ImpureGetter(VM& vm, Structure* structure)
276 : Base(vm, structure)
277 {
278 }
279
280 DECLARE_INFO;
281 typedef JSNonFinalObject Base;
282 static const unsigned StructureFlags = Base::StructureFlags | JSC::GetOwnPropertySlotIsImpure | JSC::OverridesGetOwnPropertySlot;
283
284 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
285 {
286 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
287 }
288
289 static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
290 {
291 ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
292 getter->finishCreation(vm, delegate);
293 return getter;
294 }
295
296 void finishCreation(VM& vm, JSObject* delegate)
297 {
298 Base::finishCreation(vm);
299 if (delegate)
300 m_delegate.set(vm, this, delegate);
301 }
302
303 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
304 {
305 ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
306
307 if (thisObject->m_delegate) {
308 if (thisObject->m_delegate->getPropertySlot(exec, name, slot))
309 return true;
310 if (exec->hadException())
311 return false;
312 }
313
314 return Base::getOwnPropertySlot(object, exec, name, slot);
315 }
316
317 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
318 {
319 Base::visitChildren(cell, visitor);
320 ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
321 visitor.append(&thisObject->m_delegate);
322 }
323
324 void setDelegate(VM& vm, JSObject* delegate)
325 {
326 m_delegate.set(vm, this, delegate);
327 }
328
329private:
330 WriteBarrier<JSObject> m_delegate;
331};
332
333class CustomGetter : public JSNonFinalObject {
334public:
335 CustomGetter(VM& vm, Structure* structure)
336 : Base(vm, structure)
337 {
338 }
339
340 DECLARE_INFO;
341 typedef JSNonFinalObject Base;
342 static const unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot;
343
344 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
345 {
346 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
347 }
348
349 static CustomGetter* create(VM& vm, Structure* structure)
350 {
351 CustomGetter* getter = new (NotNull, allocateCell<CustomGetter>(vm.heap, sizeof(CustomGetter))) CustomGetter(vm, structure);
352 getter->finishCreation(vm);
353 return getter;
354 }
355
356 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
357 {
358 CustomGetter* thisObject = jsCast<CustomGetter*>(object);
359 if (propertyName == PropertyName(Identifier::fromString(exec, "customGetter"))) {
360 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->customGetter);
361 return true;
362 }
363 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
364 }
365
366private:
367 static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
368 {
369 CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(JSValue::decode(thisValue));
370 if (!thisObject)
371 return throwVMTypeError(exec);
372 bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
373 if (shouldThrow)
374 return throwVMTypeError(exec);
375 return JSValue::encode(jsNumber(100));
376 }
377};
378
379class RuntimeArray : public JSArray {
380public:
381 typedef JSArray Base;
382 static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
383
384 static RuntimeArray* create(ExecState* exec)
385 {
386 VM& vm = exec->vm();
387 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
388 Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
389 RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
390 runtimeArray->finishCreation(exec);
391 vm.heap.addFinalizer(runtimeArray, destroy);
392 return runtimeArray;
393 }
394
395 ~RuntimeArray() { }
396
397 static void destroy(JSCell* cell)
398 {
399 static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
400 }
401
402 static const bool needsDestruction = false;
403
404 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
405 {
406 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
407 if (propertyName == exec->propertyNames().length) {
408 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
409 return true;
410 }
411
412 Optional<uint32_t> index = parseIndex(propertyName);
413 if (index && index.value() < thisObject->getLength()) {
414 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()]));
415 return true;
416 }
417
418 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
419 }
420
421 static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
422 {
423 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
424 if (index < thisObject->getLength()) {
425 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
426 return true;
427 }
428
429 return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
430 }
431
432 static NO_RETURN_DUE_TO_CRASH bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
433 {
434 RELEASE_ASSERT_NOT_REACHED();
435 }
436
437 static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
438 {
439 RELEASE_ASSERT_NOT_REACHED();
440 }
441
442 unsigned getLength() const { return m_vector.size(); }
443
444 DECLARE_INFO;
445
446 static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
447 {
448 return globalObject->arrayPrototype();
449 }
450
451 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
452 {
453 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
454 }
455
456protected:
457 void finishCreation(ExecState* exec)
458 {
459 Base::finishCreation(exec->vm());
460 ASSERT(inherits(info()));
461
462 for (size_t i = 0; i < exec->argumentCount(); i++)
463 m_vector.append(exec->argument(i).toInt32(exec));
464 }
465
466private:
467 RuntimeArray(ExecState* exec, Structure* structure)
468 : JSArray(exec->vm(), structure, 0)
469 {
470 }
471
472 static EncodedJSValue lengthGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
473 {
474 RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
475 if (!thisObject)
476 return throwVMTypeError(exec);
477 return JSValue::encode(jsNumber(thisObject->getLength()));
478 }
479
480 Vector<int> m_vector;
481};
482
483class SimpleObject : public JSNonFinalObject {
484public:
485 SimpleObject(VM& vm, Structure* structure)
486 : Base(vm, structure)
487 {
488 }
489
490 typedef JSNonFinalObject Base;
491 static const bool needsDestruction = false;
492
493 static SimpleObject* create(VM& vm, JSGlobalObject* globalObject)
494 {
495 Structure* structure = createStructure(vm, globalObject, jsNull());
496 SimpleObject* simpleObject = new (NotNull, allocateCell<SimpleObject>(vm.heap, sizeof(SimpleObject))) SimpleObject(vm, structure);
497 simpleObject->finishCreation(vm);
498 return simpleObject;
499 }
500
501 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
502 {
503 SimpleObject* thisObject = jsCast<SimpleObject*>(cell);
504 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
505 Base::visitChildren(thisObject, visitor);
506 visitor.append(&thisObject->m_hiddenValue);
507 }
508
509 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
510 {
511 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
512 }
513
514 JSValue hiddenValue()
515 {
516 return m_hiddenValue.get();
517 }
518
519 void setHiddenValue(VM& vm, JSValue value)
520 {
521 ASSERT(value.isCell());
522 m_hiddenValue.set(vm, this, value);
523 }
524
525 DECLARE_INFO;
526
527private:
528 WriteBarrier<JSC::Unknown> m_hiddenValue;
529};
530
531
532const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, CREATE_METHOD_TABLE(Element) };
533const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, CREATE_METHOD_TABLE(Masquerader) };
534const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, CREATE_METHOD_TABLE(Root) };
535const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(ImpureGetter) };
536const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(CustomGetter) };
537const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) };
538const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, 0, CREATE_METHOD_TABLE(SimpleObject) };
539static bool test262AsyncPassed { false };
540static bool test262AsyncTest { false };
541
542ElementHandleOwner* Element::handleOwner()
543{
544 static ElementHandleOwner* owner = 0;
545 if (!owner)
546 owner = new ElementHandleOwner();
547 return owner;
548}
549
550void Element::finishCreation(VM& vm, Root* root)
551{
552 Base::finishCreation(vm);
553 setRoot(vm, root);
554 m_root->setElement(this);
555}
556
557}
558
559static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
560
561static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
562static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
563static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
564static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
565static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
566static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
567static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
568
569static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
570static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
571static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
572static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
573static EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState*);
574static EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState*);
575static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState*);
576static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
577static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
578static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
579static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
580static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
581static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
582static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
583static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
584static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
585static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
586static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
587static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState*);
588#ifndef NDEBUG
589static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
590#endif
591static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
592static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
593static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
594static EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState*);
595static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
596static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
597static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
598static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
599static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
600static EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState*);
601static EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState*);
602static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
603static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
604static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
605static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
606static EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*);
607static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
608static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*);
609static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
610static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
611static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
612static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
613static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
614static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
615static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
616static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
617static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
618static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
619static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState*);
620static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*);
621static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
622static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
623static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState*);
624static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
625static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*);
626static EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*);
627#if ENABLE(WEBASSEMBLY)
628static EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState*);
629#endif
630static EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState*);
631static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
632static EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*);
633static EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState*);
634#if ENABLE(SAMPLING_PROFILER)
635static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*);
636static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*);
637#endif
638
639#if ENABLE(SAMPLING_FLAGS)
640static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
641static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
642#endif
643
644static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState*);
645static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState*);
646
647struct Script {
648 enum class StrictMode {
649 Strict,
650 Sloppy
651 };
652
653 enum class ScriptType {
654 Script,
655 Module
656 };
657
658 enum class CodeSource {
659 File,
660 CommandLine
661 };
662
663 StrictMode strictMode;
664 CodeSource codeSource;
665 ScriptType scriptType;
666 char* argument;
667
668 Script(StrictMode strictMode, CodeSource codeSource, ScriptType scriptType, char *argument)
669 : strictMode(strictMode)
670 , codeSource(codeSource)
671 , scriptType(scriptType)
672 , argument(argument)
673 {
674 if (strictMode == StrictMode::Strict)
675 ASSERT(codeSource == CodeSource::File);
676 }
677};
678
679class CommandLine {
680public:
681 CommandLine(int argc, char** argv)
682 {
683 parseArguments(argc, argv);
684 }
685
686 bool m_interactive { false };
687 bool m_dump { false };
688 bool m_module { false };
689 bool m_exitCode { false };
690 Vector<Script> m_scripts;
691 Vector<String> m_arguments;
692 bool m_profile { false };
693 String m_profilerOutput;
694 String m_uncaughtExceptionName;
695 bool m_dumpSamplingProfilerData { false };
696
697 void parseArguments(int, char**);
698};
699
700static const char interactivePrompt[] = ">>> ";
701
702class StopWatch {
703public:
704 void start();
705 void stop();
706 long getElapsedMS(); // call stop() first
707
708private:
709 double m_startTime;
710 double m_stopTime;
711};
712
713void StopWatch::start()
714{
715 m_startTime = monotonicallyIncreasingTime();
716}
717
718void StopWatch::stop()
719{
720 m_stopTime = monotonicallyIncreasingTime();
721}
722
723long StopWatch::getElapsedMS()
724{
725 return static_cast<long>((m_stopTime - m_startTime) * 1000);
726}
727
728template<typename Vector>
729static inline String stringFromUTF(const Vector& utf8)
730{
731 return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
732}
733
734template<typename Vector>
735static inline SourceCode jscSource(const Vector& utf8, const String& filename)
736{
737 String str = stringFromUTF(utf8);
738 return makeSource(str, filename);
739}
740
741class GlobalObject : public JSGlobalObject {
742private:
743 GlobalObject(VM&, Structure*);
744
745public:
746 typedef JSGlobalObject Base;
747
748 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
749 {
750 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
751 object->finishCreation(vm, arguments);
752 vm.heap.addFinalizer(object, destroy);
753 return object;
754 }
755
756 static const bool needsDestruction = false;
757
758 DECLARE_INFO;
759 static const GlobalObjectMethodTable s_globalObjectMethodTable;
760
761 static Structure* createStructure(VM& vm, JSValue prototype)
762 {
763 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
764 }
765
766 static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
767
768protected:
769 void finishCreation(VM& vm, const Vector<String>& arguments)
770 {
771 Base::finishCreation(vm);
772
773 addFunction(vm, "debug", functionDebug, 1);
774 addFunction(vm, "describe", functionDescribe, 1);
775 addFunction(vm, "describeArray", functionDescribeArray, 1);
776 addFunction(vm, "print", functionPrint, 1);
777 addFunction(vm, "quit", functionQuit, 0);
778 addFunction(vm, "abort", functionAbort, 0);
779 addFunction(vm, "gc", functionGCAndSweep, 0);
780 addFunction(vm, "fullGC", functionFullGC, 0);
781 addFunction(vm, "edenGC", functionEdenGC, 0);
782 addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
783 addFunction(vm, "gcHeapSize", functionHeapSize, 0);
784 addFunction(vm, "addressOf", functionAddressOf, 1);
785 addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
786#ifndef NDEBUG
787 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
788#endif
789 addFunction(vm, "version", functionVersion, 1);
790 addFunction(vm, "run", functionRun, 1);
791 addFunction(vm, "load", functionLoad, 1);
792 addFunction(vm, "loadString", functionLoadString, 1);
793 addFunction(vm, "readFile", functionReadFile, 1);
794 addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
795 addFunction(vm, "jscStack", functionJSCStack, 1);
796 addFunction(vm, "readline", functionReadline, 0);
797 addFunction(vm, "preciseTime", functionPreciseTime, 0);
798 addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
799 addFunction(vm, "noInline", functionNeverInlineFunction, 1);
800 addFunction(vm, "noDFG", functionNoDFG, 1);
801 addFunction(vm, "noFTL", functionNoFTL, 1);
802 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
803 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
804 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
805 addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
806 addFunction(vm, "failNextNewCodeBlock", functionFailNextNewCodeBlock, 1);
807#if ENABLE(SAMPLING_FLAGS)
808 addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
809 addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
810#endif
811 addFunction(vm, "shadowChickenFunctionsOnStack", functionShadowChickenFunctionsOnStack, 0);
812 addFunction(vm, "setGlobalConstRedeclarationShouldNotThrow", functionSetGlobalConstRedeclarationShouldNotThrow, 0);
813 addConstructableFunction(vm, "Root", functionCreateRoot, 0);
814 addConstructableFunction(vm, "Element", functionCreateElement, 1);
815 addFunction(vm, "getElement", functionGetElement, 1);
816 addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
817
818 addConstructableFunction(vm, "SimpleObject", functionCreateSimpleObject, 0);
819 addFunction(vm, "getHiddenValue", functionGetHiddenValue, 1);
820 addFunction(vm, "setHiddenValue", functionSetHiddenValue, 2);
821
822 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum);
823 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum);
824 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum);
825 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum);
826 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum);
827 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum);
828
829 addFunction(vm, "effectful42", functionEffectful42, 0);
830 addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
831 addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
832
833 addFunction(vm, "createProxy", functionCreateProxy, 1);
834 addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
835
836 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
837 addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
838 addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
839 addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
840 addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
841
842 addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
843 addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
844 addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
845
846 addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
847 addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
848 addFunction(vm, "basicBlockExecutionCount", functionBasicBlockExecutionCount, 2);
849
850 addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
851
852 addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
853
854 addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
855
856#if ENABLE(WEBASSEMBLY)
857 addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 3);
858#endif
859 addFunction(vm, "loadModule", functionLoadModule, 1);
860 addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
861
862 addFunction(vm, "platformSupportsSamplingProfiler", functionPlatformSupportsSamplingProfiler, 0);
863 addFunction(vm, "generateHeapSnapshot", functionGenerateHeapSnapshot, 0);
864#if ENABLE(SAMPLING_PROFILER)
865 addFunction(vm, "startSamplingProfiler", functionStartSamplingProfiler, 0);
866 addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
867#endif
868
869 if (!arguments.isEmpty()) {
870 JSArray* array = constructEmptyArray(globalExec(), 0);
871 for (size_t i = 0; i < arguments.size(); ++i)
872 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
873 putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
874 }
875
876 putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
877 }
878
879 void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
880 {
881 Identifier identifier = Identifier::fromString(&vm, name);
882 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
883 }
884
885 void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
886 {
887 Identifier identifier = Identifier::fromString(&vm, name);
888 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
889 }
890
891 static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSValue, JSValue);
892 static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSValue);
893};
894
895const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
896const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr, nullptr };
897
898
899GlobalObject::GlobalObject(VM& vm, Structure* structure)
900 : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
901{
902}
903
904static UChar pathSeparator()
905{
906#if OS(WINDOWS)
907 return '\\';
908#else
909 return '/';
910#endif
911}
912
913struct DirectoryName {
914 // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
915 String rootName;
916
917 // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
918 String queryName;
919};
920
921struct ModuleName {
922 ModuleName(const String& moduleName);
923
924 bool startsWithRoot() const
925 {
926 return !queries.isEmpty() && queries[0].isEmpty();
927 }
928
929 Vector<String> queries;
930};
931
932ModuleName::ModuleName(const String& moduleName)
933{
934 // A module name given from code is represented as the UNIX style path. Like, `./A/B.js`.
935 moduleName.split('/', true, queries);
936}
937
938static bool extractDirectoryName(const String& absolutePathToFile, DirectoryName& directoryName)
939{
940 size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
941 if (firstSeparatorPosition == notFound)
942 return false;
943 directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
944 size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
945 ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
946 if (firstSeparatorPosition == lastSeparatorPosition)
947 directoryName.queryName = StringImpl::empty();
948 else {
949 size_t queryStartPosition = firstSeparatorPosition + 1;
950 size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
951 directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
952 }
953 return true;
954}
955
956static bool currentWorkingDirectory(DirectoryName& directoryName)
957{
958#if OS(WINDOWS)
959 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
960 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
961 // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
962 // And other I/O functions taking a path name also truncate it. To avoid this situation,
963 //
964 // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
965 // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
966 //
967 // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
968 DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
969 if (!bufferLength)
970 return false;
971 // In Windows, wchar_t is the UTF-16LE.
972 // https://msdn.microsoft.com/en-us/library/dd374081.aspx
973 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
974 auto buffer = std::make_unique<wchar_t[]>(bufferLength);
975 DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.get());
976 static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
977 String directoryString = String(reinterpret_cast<UChar*>(buffer.get()));
978 // We don't support network path like \\host\share\<path name>.
979 if (directoryString.startsWith("\\\\"))
980 return false;
981#else
982 auto buffer = std::make_unique<char[]>(PATH_MAX);
983 if (!getcwd(buffer.get(), PATH_MAX))
984 return false;
985 String directoryString = String::fromUTF8(buffer.get());
986#endif
987 if (directoryString.isEmpty())
988 return false;
989
990 if (directoryString[directoryString.length() - 1] == pathSeparator())
991 return extractDirectoryName(directoryString, directoryName);
992 // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
993 return extractDirectoryName(makeString(directoryString, pathSeparator()), directoryName);
994}
995
996static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
997{
998 Vector<String> directoryPieces;
999 directoryName.queryName.split(pathSeparator(), false, directoryPieces);
1000
1001 // Only first '/' is recognized as the path from the root.
1002 if (moduleName.startsWithRoot())
1003 directoryPieces.clear();
1004
1005 for (const auto& query : moduleName.queries) {
1006 if (query == String(ASCIILiteral(".."))) {
1007 if (!directoryPieces.isEmpty())
1008 directoryPieces.removeLast();
1009 } else if (!query.isEmpty() && query != String(ASCIILiteral(".")))
1010 directoryPieces.append(query);
1011 }
1012
1013 StringBuilder builder;
1014 builder.append(directoryName.rootName);
1015 for (size_t i = 0; i < directoryPieces.size(); ++i) {
1016 builder.append(directoryPieces[i]);
1017 if (i + 1 != directoryPieces.size())
1018 builder.append(pathSeparator());
1019 }
1020 return builder.toString();
1021}
1022
1023JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSValue keyValue, JSValue referrerValue)
1024{
1025 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1026 const Identifier key = keyValue.toPropertyKey(exec);
1027 if (exec->hadException()) {
1028 JSValue exception = exec->exception();
1029 exec->clearException();
1030 return deferred->reject(exec, exception);
1031 }
1032
1033 if (key.isSymbol())
1034 return deferred->resolve(exec, keyValue);
1035
1036 DirectoryName directoryName;
1037 if (referrerValue.isUndefined()) {
1038 if (!currentWorkingDirectory(directoryName))
1039 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1040 } else {
1041 const Identifier referrer = referrerValue.toPropertyKey(exec);
1042 if (exec->hadException()) {
1043 JSValue exception = exec->exception();
1044 exec->clearException();
1045 return deferred->reject(exec, exception);
1046 }
1047 if (referrer.isSymbol()) {
1048 if (!currentWorkingDirectory(directoryName))
1049 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1050 } else {
1051 // If the referrer exists, we assume that the referrer is the correct absolute path.
1052 if (!extractDirectoryName(referrer.impl(), directoryName))
1053 return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
1054 }
1055 }
1056
1057 return deferred->resolve(exec, jsString(exec, resolvePath(directoryName, ModuleName(key.impl()))));
1058}
1059
1060static void convertShebangToJSComment(Vector<char>& buffer)
1061{
1062 if (buffer.size() >= 2) {
1063 if (buffer[0] == '#' && buffer[1] == '!')
1064 buffer[0] = buffer[1] = '/';
1065 }
1066}
1067
1068static bool fillBufferWithContentsOfFile(FILE* file, Vector<char>& buffer)
1069{
1070 // We might have injected "use strict"; at the top.
1071 size_t initialSize = buffer.size();
1072 fseek(file, 0, SEEK_END);
1073 size_t bufferCapacity = ftell(file);
1074 fseek(file, 0, SEEK_SET);
1075 buffer.resize(bufferCapacity + initialSize);
1076 size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
1077 return readSize == buffer.size() - initialSize;
1078}
1079
1080static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1081{
1082 FILE* f = fopen(fileName.utf8().data(), "rb");
1083 if (!f) {
1084 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1085 return false;
1086 }
1087
1088 bool result = fillBufferWithContentsOfFile(f, buffer);
1089 fclose(f);
1090
1091 return result;
1092}
1093
1094static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1095{
1096 if (!fillBufferWithContentsOfFile(fileName, buffer))
1097 return false;
1098 convertShebangToJSComment(buffer);
1099 return true;
1100}
1101
1102static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1103{
1104 // We assume that fileName is always an absolute path.
1105#if OS(WINDOWS)
1106 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
1107 // Use long UNC to pass the long path name to the Windows APIs.
1108 String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
1109 static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
1110 auto utf16Vector = longUNCPathName.charactersWithNullTermination();
1111 FILE* f = _wfopen(reinterpret_cast<wchar_t*>(utf16Vector.data()), L"rb");
1112#else
1113 FILE* f = fopen(fileName.utf8().data(), "r");
1114#endif
1115 if (!f) {
1116 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1117 return false;
1118 }
1119
1120 bool result = fillBufferWithContentsOfFile(f, buffer);
1121 if (result)
1122 convertShebangToJSComment(buffer);
1123 fclose(f);
1124
1125 return result;
1126}
1127
1128JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSValue key)
1129{
1130 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1131 String moduleKey = key.toWTFString(exec);
1132 if (exec->hadException()) {
1133 JSValue exception = exec->exception();
1134 exec->clearException();
1135 return deferred->reject(exec, exception);
1136 }
1137
1138 // Here, now we consider moduleKey as the fileName.
1139 Vector<char> utf8;
1140 if (!fetchModuleFromLocalFileSystem(moduleKey, utf8))
1141 return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
1142
1143 return deferred->resolve(exec, jsString(exec, stringFromUTF(utf8)));
1144}
1145
1146
1147EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
1148{
1149 if (test262AsyncTest) {
1150 JSValue value = exec->argument(0);
1151 if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete"))
1152 test262AsyncPassed = true;
1153 return JSValue::encode(jsUndefined());
1154 }
1155
1156 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1157 if (i)
1158 putchar(' ');
1159
1160 printf("%s", exec->uncheckedArgument(i).toString(exec)->view(exec).get().utf8().data());
1161 }
1162
1163 putchar('\n');
1164 fflush(stdout);
1165 return JSValue::encode(jsUndefined());
1166}
1167
1168#ifndef NDEBUG
1169EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
1170{
1171 VMEntryFrame* topVMEntryFrame = exec->vm().topVMEntryFrame;
1172 ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
1173 if (callerFrame)
1174 exec->vm().interpreter->dumpCallFrame(callerFrame);
1175 return JSValue::encode(jsUndefined());
1176}
1177#endif
1178
1179EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
1180{
1181 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->view(exec).get().utf8().data());
1182 return JSValue::encode(jsUndefined());
1183}
1184
1185EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
1186{
1187 if (exec->argumentCount() < 1)
1188 return JSValue::encode(jsUndefined());
1189 return JSValue::encode(jsString(exec, toString(exec->argument(0))));
1190}
1191
1192EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
1193{
1194 if (exec->argumentCount() < 1)
1195 return JSValue::encode(jsUndefined());
1196 JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
1197 if (!object)
1198 return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
1199 return JSValue::encode(jsNontrivialString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1200}
1201
1202class FunctionJSCStackFunctor {
1203public:
1204 FunctionJSCStackFunctor(StringBuilder& trace)
1205 : m_trace(trace)
1206 {
1207 }
1208
1209 StackVisitor::Status operator()(StackVisitor& visitor) const
1210 {
1211 m_trace.append(String::format(" %zu %s\n", visitor->index(), visitor->toString().utf8().data()));
1212 return StackVisitor::Continue;
1213 }
1214
1215private:
1216 StringBuilder& m_trace;
1217};
1218
1219EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
1220{
1221 StringBuilder trace;
1222 trace.appendLiteral("--> Stack trace:\n");
1223
1224 FunctionJSCStackFunctor functor(trace);
1225 exec->iterate(functor);
1226 fprintf(stderr, "%s", trace.toString().utf8().data());
1227 return JSValue::encode(jsUndefined());
1228}
1229
1230EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
1231{
1232 JSLockHolder lock(exec);
1233 return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
1234}
1235
1236EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
1237{
1238 JSLockHolder lock(exec);
1239 Root* root = jsDynamicCast<Root*>(exec->argument(0));
1240 if (!root)
1241 return JSValue::encode(jsUndefined());
1242 return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), root));
1243}
1244
1245EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
1246{
1247 JSLockHolder lock(exec);
1248 Root* root = jsDynamicCast<Root*>(exec->argument(0));
1249 if (!root)
1250 return JSValue::encode(jsUndefined());
1251 Element* result = root->element();
1252 return JSValue::encode(result ? result : jsUndefined());
1253}
1254
1255EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
1256{
1257 JSLockHolder lock(exec);
1258 Element* element = jsDynamicCast<Element*>(exec->argument(0));
1259 Root* root = jsDynamicCast<Root*>(exec->argument(1));
1260 if (element && root)
1261 element->setRoot(exec->vm(), root);
1262 return JSValue::encode(jsUndefined());
1263}
1264
1265EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState* exec)
1266{
1267 JSLockHolder lock(exec);
1268 return JSValue::encode(SimpleObject::create(exec->vm(), exec->lexicalGlobalObject()));
1269}
1270
1271EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState* exec)
1272{
1273 JSLockHolder lock(exec);
1274 SimpleObject* simpleObject = jsCast<SimpleObject*>(exec->argument(0).asCell());
1275 return JSValue::encode(simpleObject->hiddenValue());
1276}
1277
1278EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState* exec)
1279{
1280 JSLockHolder lock(exec);
1281 SimpleObject* simpleObject = jsCast<SimpleObject*>(exec->argument(0).asCell());
1282 JSValue value = exec->argument(1);
1283 simpleObject->setHiddenValue(exec->vm(), value);
1284 return JSValue::encode(jsUndefined());
1285}
1286
1287EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
1288{
1289 JSLockHolder lock(exec);
1290 JSValue target = exec->argument(0);
1291 if (!target.isObject())
1292 return JSValue::encode(jsUndefined());
1293 JSObject* jsTarget = asObject(target.asCell());
1294 Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->getPrototypeDirect(), ImpureProxyType);
1295 JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
1296 return JSValue::encode(proxy);
1297}
1298
1299EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
1300{
1301 JSLockHolder lock(exec);
1302 RuntimeArray* array = RuntimeArray::create(exec);
1303 return JSValue::encode(array);
1304}
1305
1306EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
1307{
1308 JSLockHolder lock(exec);
1309 JSValue target = exec->argument(0);
1310 JSObject* delegate = nullptr;
1311 if (target.isObject())
1312 delegate = asObject(target.asCell());
1313 Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1314 ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
1315 return JSValue::encode(result);
1316}
1317
1318EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState* exec)
1319{
1320 JSLockHolder lock(exec);
1321 Structure* structure = CustomGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1322 CustomGetter* result = CustomGetter::create(exec->vm(), structure);
1323 return JSValue::encode(result);
1324}
1325
1326EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
1327{
1328 JSLockHolder lock(exec);
1329 JSValue base = exec->argument(0);
1330 if (!base.isObject())
1331 return JSValue::encode(jsUndefined());
1332 JSValue delegate = exec->argument(1);
1333 if (!delegate.isObject())
1334 return JSValue::encode(jsUndefined());
1335 ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
1336 impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
1337 return JSValue::encode(jsUndefined());
1338}
1339
1340EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
1341{
1342 JSLockHolder lock(exec);
1343 exec->heap()->collectAllGarbage();
1344 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1345}
1346
1347EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
1348{
1349 JSLockHolder lock(exec);
1350 exec->heap()->collect(FullCollection);
1351 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1352}
1353
1354EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1355{
1356 JSLockHolder lock(exec);
1357 exec->heap()->collect(EdenCollection);
1358 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
1359}
1360
1361EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*)
1362{
1363 // It's best for this to be the first thing called in the
1364 // JS program so the option is set to true before we JIT.
1365 Options::forceGCSlowPaths() = true;
1366 return JSValue::encode(jsUndefined());
1367}
1368
1369EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
1370{
1371 JSLockHolder lock(exec);
1372 return JSValue::encode(jsNumber(exec->heap()->size()));
1373}
1374
1375// This function is not generally very helpful in 64-bit code as the tag and payload
1376// share a register. But in 32-bit JITed code the tag may not be checked if an
1377// optimization removes type checking requirements, such as in ===.
1378EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
1379{
1380 JSValue value = exec->argument(0);
1381 if (!value.isCell())
1382 return JSValue::encode(jsUndefined());
1383 // Need to cast to uint64_t so bitwise_cast will play along.
1384 uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
1385 EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
1386 return returnValue;
1387}
1388
1389static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
1390{
1391 JSValue value = exec->argument(0);
1392 if (!value.isObject())
1393 return JSValue::encode(jsUndefined());
1394
1395 JSValue property = exec->argument(1);
1396 if (!property.isString())
1397 return JSValue::encode(jsUndefined());
1398
1399 Identifier ident = Identifier::fromString(&exec->vm(), property.toWTFString(exec));
1400
1401 PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
1402 value.getPropertySlot(exec, ident, slot);
1403
1404 JSValue result;
1405 if (slot.isCacheableGetter())
1406 result = slot.getterSetter();
1407 else
1408 result = jsNull();
1409
1410 return JSValue::encode(result);
1411}
1412
1413EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
1414{
1415 // We need this function for compatibility with the Mozilla JS tests but for now
1416 // we don't actually do any version-specific handling
1417 return JSValue::encode(jsUndefined());
1418}
1419
1420EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
1421{
1422 String fileName = exec->argument(0).toWTFString(exec);
1423 if (exec->hadException())
1424 return JSValue::encode(jsUndefined());
1425 Vector<char> script;
1426 if (!fetchScriptFromLocalFileSystem(fileName, script))
1427 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1428
1429 GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
1430
1431 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1432 for (unsigned i = 1; i < exec->argumentCount(); ++i)
1433 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1434 globalObject->putDirect(
1435 exec->vm(), Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1436
1437 NakedPtr<Exception> exception;
1438 StopWatch stopWatch;
1439 stopWatch.start();
1440 evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), exception);
1441 stopWatch.stop();
1442
1443 if (exception) {
1444 exec->vm().throwException(globalObject->globalExec(), exception);
1445 return JSValue::encode(jsUndefined());
1446 }
1447
1448 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1449}
1450
1451EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
1452{
1453 String fileName = exec->argument(0).toWTFString(exec);
1454 if (exec->hadException())
1455 return JSValue::encode(jsUndefined());
1456 Vector<char> script;
1457 if (!fetchScriptFromLocalFileSystem(fileName, script))
1458 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1459
1460 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1461
1462 NakedPtr<Exception> evaluationException;
1463 JSValue result = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
1464 if (evaluationException)
1465 exec->vm().throwException(exec, evaluationException);
1466 return JSValue::encode(result);
1467}
1468
1469EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
1470{
1471 String sourceCode = exec->argument(0).toWTFString(exec);
1472 if (exec->hadException())
1473 return JSValue::encode(jsUndefined());
1474 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1475
1476 NakedPtr<Exception> evaluationException;
1477 JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode), JSValue(), evaluationException);
1478 if (evaluationException)
1479 exec->vm().throwException(exec, evaluationException);
1480 return JSValue::encode(result);
1481}
1482
1483EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
1484{
1485 String fileName = exec->argument(0).toWTFString(exec);
1486 if (exec->hadException())
1487 return JSValue::encode(jsUndefined());
1488 Vector<char> script;
1489 if (!fillBufferWithContentsOfFile(fileName, script))
1490 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1491
1492 return JSValue::encode(jsString(exec, stringFromUTF(script)));
1493}
1494
1495EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
1496{
1497 String fileName = exec->argument(0).toWTFString(exec);
1498 if (exec->hadException())
1499 return JSValue::encode(jsUndefined());
1500 Vector<char> script;
1501 if (!fetchScriptFromLocalFileSystem(fileName, script))
1502 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1503
1504 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1505
1506 StopWatch stopWatch;
1507 stopWatch.start();
1508
1509 JSValue syntaxException;
1510 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, fileName), &syntaxException);
1511 stopWatch.stop();
1512
1513 if (!validSyntax)
1514 exec->vm().throwException(exec, syntaxException);
1515 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1516}
1517
1518#if ENABLE(SAMPLING_FLAGS)
1519EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
1520{
1521 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1522 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1523 if ((flag >= 1) && (flag <= 32))
1524 SamplingFlags::setFlag(flag);
1525 }
1526 return JSValue::encode(jsNull());
1527}
1528
1529EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
1530{
1531 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1532 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1533 if ((flag >= 1) && (flag <= 32))
1534 SamplingFlags::clearFlag(flag);
1535 }
1536 return JSValue::encode(jsNull());
1537}
1538#endif
1539
1540EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState* exec)
1541{
1542 return JSValue::encode(exec->vm().shadowChicken().functionsOnStack(exec));
1543}
1544
1545EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState* exec)
1546{
1547 exec->vm().setGlobalConstRedeclarationShouldThrow(false);
1548 return JSValue::encode(jsUndefined());
1549}
1550
1551EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
1552{
1553 Vector<char, 256> line;
1554 int c;
1555 while ((c = getchar()) != EOF) {
1556 // FIXME: Should we also break on \r?
1557 if (c == '\n')
1558 break;
1559 line.append(c);
1560 }
1561 line.append('\0');
1562 return JSValue::encode(jsString(exec, line.data()));
1563}
1564
1565EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
1566{
1567 return JSValue::encode(jsNumber(currentTime()));
1568}
1569
1570EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
1571{
1572 return JSValue::encode(setNeverInline(exec));
1573}
1574
1575EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
1576{
1577 return JSValue::encode(setNeverOptimize(exec));
1578}
1579
1580EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState* exec)
1581{
1582 if (JSFunction* function = jsDynamicCast<JSFunction*>(exec->argument(0))) {
1583 FunctionExecutable* executable = function->jsExecutable();
1584 executable->setNeverFTLOptimize(true);
1585 }
1586
1587 return JSValue::encode(jsUndefined());
1588}
1589
1590EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
1591{
1592 return JSValue::encode(optimizeNextInvocation(exec));
1593}
1594
1595EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1596{
1597 return JSValue::encode(numberOfDFGCompiles(exec));
1598}
1599
1600EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1601{
1602 if (exec->argumentCount() < 1)
1603 return JSValue::encode(jsUndefined());
1604
1605 CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1606 if (!block)
1607 return JSValue::encode(jsNumber(0));
1608
1609 return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1610}
1611
1612EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1613{
1614 if (exec->argumentCount() < 1)
1615 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Not enough arguments"))));
1616
1617 JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
1618 if (!buffer)
1619 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Expected an array buffer"))));
1620
1621 ArrayBufferContents dummyContents;
1622 buffer->impl()->transfer(dummyContents);
1623
1624 return JSValue::encode(jsUndefined());
1625}
1626
1627EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState* exec)
1628{
1629 exec->vm().setFailNextNewCodeBlock();
1630 return JSValue::encode(jsUndefined());
1631}
1632
1633EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1634{
1635 jscExit(EXIT_SUCCESS);
1636
1637#if COMPILER(MSVC)
1638 // Without this, Visual Studio will complain that this method does not return a value.
1639 return JSValue::encode(jsUndefined());
1640#endif
1641}
1642
1643EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*)
1644{
1645 CRASH();
1646}
1647
1648EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1649EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1650
1651EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1652EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1653EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
1654{
1655 for (size_t i = 0; i < exec->argumentCount(); ++i) {
1656 if (!exec->argument(i).isInt32())
1657 return JSValue::encode(jsBoolean(false));
1658 }
1659 return JSValue::encode(jsBoolean(true));
1660}
1661
1662EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
1663
1664EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
1665{
1666 return JSValue::encode(jsNumber(42));
1667}
1668
1669EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
1670{
1671 return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
1672}
1673
1674EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
1675{
1676 JSValue value = exec->argument(0);
1677 if (value.isObject())
1678 return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
1679 return JSValue::encode(jsBoolean(false));
1680}
1681
1682EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
1683{
1684 exec->vm().dumpTypeProfilerData();
1685 return JSValue::encode(jsUndefined());
1686}
1687
1688EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
1689{
1690 RELEASE_ASSERT(exec->vm().typeProfiler());
1691 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
1692
1693 JSValue functionValue = exec->argument(0);
1694 RELEASE_ASSERT(functionValue.isFunction());
1695 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1696
1697 RELEASE_ASSERT(exec->argument(1).isString());
1698 String substring = exec->argument(1).getString(exec);
1699 String sourceCodeText = executable->source().view().toString();
1700 unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
1701
1702 String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), exec->vm());
1703 return JSValue::encode(JSONParse(exec, jsonString));
1704}
1705
1706EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
1707{
1708 RELEASE_ASSERT(exec->vm().typeProfiler());
1709 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
1710
1711 JSValue functionValue = exec->argument(0);
1712 RELEASE_ASSERT(functionValue.isFunction());
1713 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1714
1715 unsigned offset = executable->typeProfilingStartOffset();
1716 String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), exec->vm());
1717 return JSValue::encode(JSONParse(exec, jsonString));
1718}
1719
1720EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
1721{
1722 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1723 exec->vm().controlFlowProfiler()->dumpData();
1724 return JSValue::encode(jsUndefined());
1725}
1726
1727EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
1728{
1729 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1730
1731 JSValue functionValue = exec->argument(0);
1732 RELEASE_ASSERT(functionValue.isFunction());
1733 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1734
1735 RELEASE_ASSERT(exec->argument(1).isString());
1736 String substring = exec->argument(1).getString(exec);
1737 String sourceCodeText = executable->source().view().toString();
1738 RELEASE_ASSERT(sourceCodeText.contains(substring));
1739 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1740
1741 bool hasExecuted = exec->vm().controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), exec->vm());
1742 return JSValue::encode(jsBoolean(hasExecuted));
1743}
1744
1745EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState* exec)
1746{
1747 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1748
1749 JSValue functionValue = exec->argument(0);
1750 RELEASE_ASSERT(functionValue.isFunction());
1751 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1752
1753 RELEASE_ASSERT(exec->argument(1).isString());
1754 String substring = exec->argument(1).getString(exec);
1755 String sourceCodeText = executable->source().view().toString();
1756 RELEASE_ASSERT(sourceCodeText.contains(substring));
1757 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1758
1759 size_t executionCount = exec->vm().controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), exec->vm());
1760 return JSValue::encode(JSValue(executionCount));
1761}
1762
1763EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
1764{
1765 Options::useExceptionFuzz() = true;
1766 return JSValue::encode(jsUndefined());
1767}
1768
1769EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
1770{
1771 exec->vm().drainMicrotasks();
1772 return JSValue::encode(jsUndefined());
1773}
1774
1775EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*)
1776{
1777#if USE(JSVALUE64)
1778 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
1779#else
1780 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
1781#endif
1782}
1783
1784#if ENABLE(WEBASSEMBLY)
1785EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState* exec)
1786{
1787 String fileName = exec->argument(0).toWTFString(exec);
1788 if (exec->hadException())
1789 return JSValue::encode(jsUndefined());
1790 Vector<char> buffer;
1791 if (!fillBufferWithContentsOfFile(fileName, buffer))
1792 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1793 RefPtr<WebAssemblySourceProvider> sourceProvider = WebAssemblySourceProvider::create(reinterpret_cast<Vector<uint8_t>&>(buffer), fileName);
1794 SourceCode source(sourceProvider);
1795 JSObject* imports = exec->argument(1).getObject();
1796 JSArrayBuffer* arrayBuffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(2));
1797
1798 String errorMessage;
1799 JSWASMModule* module = parseWebAssembly(exec, source, imports, arrayBuffer, errorMessage);
1800 if (!module)
1801 return JSValue::encode(exec->vm().throwException(exec, createSyntaxError(exec, errorMessage)));
1802 return JSValue::encode(module);
1803}
1804#endif
1805
1806EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
1807{
1808 String fileName = exec->argument(0).toWTFString(exec);
1809 if (exec->hadException())
1810 return JSValue::encode(jsUndefined());
1811 Vector<char> script;
1812 if (!fetchScriptFromLocalFileSystem(fileName, script))
1813 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1814
1815 JSInternalPromise* promise = loadAndEvaluateModule(exec, fileName);
1816 if (exec->hadException())
1817 return JSValue::encode(jsUndefined());
1818
1819 JSValue error;
1820 JSFunction* errorHandler = JSNativeStdFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, String(), [&](ExecState* exec) {
1821 error = exec->argument(0);
1822 return JSValue::encode(jsUndefined());
1823 });
1824
1825 promise->then(exec, nullptr, errorHandler);
1826 exec->vm().drainMicrotasks();
1827 if (error)
1828 return JSValue::encode(exec->vm().throwException(exec, error));
1829 return JSValue::encode(jsUndefined());
1830}
1831
1832EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
1833{
1834 if (exec->argumentCount() < 1 || !exec->argument(0).isString())
1835 return JSValue::encode(jsUndefined());
1836
1837 String functionText = exec->argument(0).toWTFString(exec);
1838 if (exec->hadException())
1839 return JSValue::encode(JSValue());
1840
1841 VM& vm = exec->vm();
1842 const SourceCode& source = makeSource(functionText);
1843 JSFunction* func = JSFunction::createBuiltinFunction(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
1844
1845 return JSValue::encode(func);
1846}
1847
1848EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState* exec)
1849{
1850 VM& vm = exec->vm();
1851 return JSValue::encode(GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>()));
1852}
1853
1854EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
1855{
1856 String source = exec->argument(0).toWTFString(exec);
1857 if (exec->hadException())
1858 return JSValue::encode(jsUndefined());
1859
1860 StopWatch stopWatch;
1861 stopWatch.start();
1862
1863 ParserError error;
1864 bool validSyntax = checkModuleSyntax(exec, makeSource(source), error);
1865 stopWatch.stop();
1866
1867 if (!validSyntax)
1868 exec->vm().throwException(exec, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
1869 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1870}
1871
1872EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*)
1873{
1874#if ENABLE(SAMPLING_PROFILER)
1875 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
1876#else
1877 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
1878#endif
1879}
1880
1881EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
1882{
1883 JSLockHolder lock(exec);
1884
1885 HeapSnapshotBuilder snapshotBuilder(exec->vm().ensureHeapProfiler());
1886 snapshotBuilder.buildSnapshot();
1887
1888 String jsonString = snapshotBuilder.json();
1889 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
1890 RELEASE_ASSERT(!exec->hadException());
1891 return result;
1892}
1893
1894#if ENABLE(SAMPLING_PROFILER)
1895EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState* exec)
1896{
1897 SamplingProfiler& samplingProfiler = exec->vm().ensureSamplingProfiler(WTF::Stopwatch::create());
1898 samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
1899 samplingProfiler.start();
1900 return JSValue::encode(jsUndefined());
1901}
1902
1903EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec)
1904{
1905 if (!exec->vm().samplingProfiler())
1906 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Sampling profiler was never started"))));
1907
1908 String jsonString = exec->vm().samplingProfiler()->stackTracesAsJSON();
1909 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
1910 RELEASE_ASSERT(!exec->hadException());
1911 return result;
1912}
1913#endif // ENABLE(SAMPLING_PROFILER)
1914
1915// Use SEH for Release builds only to get rid of the crash report dialog
1916// (luckily the same tests fail in Release and Debug builds so far). Need to
1917// be in a separate main function because the jscmain function requires object
1918// unwinding.
1919
1920#if COMPILER(MSVC) && !defined(_DEBUG)
1921#define TRY __try {
1922#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1923#else
1924#define TRY
1925#define EXCEPT(x)
1926#endif
1927
1928int jscmain(int argc, char** argv);
1929
1930static double s_desiredTimeout;
1931
1932static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
1933{
1934 auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
1935 std::this_thread::sleep_for(timeout);
1936
1937 dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
1938 CRASH();
1939}
1940
1941int main(int argc, char** argv)
1942{
1943#if PLATFORM(IOS) && CPU(ARM_THUMB2)
1944 // Enabled IEEE754 denormal support.
1945 fenv_t env;
1946 fegetenv( &env );
1947 env.__fpscr &= ~0x01000000u;
1948 fesetenv( &env );
1949#endif
1950
1951#if OS(WINDOWS)
1952 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1953 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1954 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1955 ::SetErrorMode(0);
1956
1957#if defined(_DEBUG)
1958 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1959 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1960 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1961 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1962 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1963 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1964#endif
1965
1966 timeBeginPeriod(1);
1967#endif
1968
1969#if PLATFORM(EFL)
1970 ecore_init();
1971#endif
1972
1973#if PLATFORM(GTK)
1974 if (!setlocale(LC_ALL, ""))
1975 WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
1976#endif
1977
1978 // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
1979 // threading yet, since that would do somethings that we'd like to defer until after we
1980 // have a chance to parse options.
1981 WTF::initializeThreading();
1982
1983 if (char* timeoutString = getenv("JSCTEST_timeout")) {
1984 if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1985 dataLog(
1986 "WARNING: timeout string is malformed, got ", timeoutString,
1987 " but expected a number. Not using a timeout.\n");
1988 } else
1989 createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1990 }
1991
1992#if PLATFORM(IOS)
1993 Options::crashIfCantAllocateJITMemory() = true;
1994#endif
1995
1996 // We can't use destructors in the following code because it uses Windows
1997 // Structured Exception Handling
1998 int res = 0;
1999 TRY
2000 res = jscmain(argc, argv);
2001 EXCEPT(res = 3)
2002 if (Options::logHeapStatisticsAtExit())
2003 HeapStatistics::reportSuccess();
2004 if (Options::reportLLIntStats())
2005 LLInt::Data::finalizeStats();
2006
2007#if PLATFORM(EFL)
2008 ecore_shutdown();
2009#endif
2010
2011 jscExit(res);
2012}
2013
2014static void dumpException(GlobalObject* globalObject, JSValue exception)
2015{
2016 printf("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data());
2017
2018 Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
2019 Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
2020 Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
2021 Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
2022
2023 JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
2024 JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
2025 JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
2026 JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
2027
2028 if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
2029 && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
2030 printf(
2031 "at %s:%s\n",
2032 fileNameValue.toWTFString(globalObject->globalExec()).utf8().data(),
2033 lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
2034 }
2035
2036 if (!stackValue.isUndefinedOrNull())
2037 printf("%s\n", stackValue.toWTFString(globalObject->globalExec()).utf8().data());
2038}
2039
2040static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, const String& expectedExceptionName)
2041{
2042 if (!exception) {
2043 printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
2044 return false;
2045 }
2046
2047 JSValue exceptionName = exception.get(globalObject->globalExec(), vm.propertyNames->name);
2048
2049 if (JSString* exceptionNameStr = jsDynamicCast<JSString*>(exceptionName)) {
2050 const String& name = exceptionNameStr->value(globalObject->globalExec());
2051 if (name == expectedExceptionName)
2052 return true;
2053 printf("Expected uncaught exception with name '%s' but got one with name '%s'\n", expectedExceptionName.utf8().data(), name.utf8().data());
2054 dumpException(globalObject, exception);
2055 return false;
2056 }
2057 printf("Expected uncaught exception with name '%s' but exception value did not have a name property\n", expectedExceptionName.utf8().data());
2058 dumpException(globalObject, exception);
2059 return false;
2060}
2061
2062static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, const String& uncaughtExceptionName, bool dump, bool module)
2063{
2064 String fileName;
2065 Vector<char> scriptBuffer;
2066
2067 if (dump)
2068 JSC::Options::dumpGeneratedBytecodes() = true;
2069
2070 VM& vm = globalObject->vm();
2071 bool success = true;
2072
2073 auto checkException = [&] (bool isLastFile, bool hasException, JSValue value) {
2074 if (!uncaughtExceptionName || !isLastFile) {
2075 success = success && !hasException;
2076 if (dump && !hasException)
2077 printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
2078 if (hasException)
2079 dumpException(globalObject, value);
2080 } else
2081 success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), uncaughtExceptionName);
2082 };
2083
2084#if ENABLE(SAMPLING_FLAGS)
2085 SamplingFlags::start();
2086#endif
2087
2088 for (size_t i = 0; i < scripts.size(); i++) {
2089 JSInternalPromise* promise = nullptr;
2090 bool isModule = module || scripts[i].scriptType == Script::ScriptType::Module;
2091 if (scripts[i].codeSource == Script::CodeSource::File) {
2092 fileName = scripts[i].argument;
2093 if (scripts[i].strictMode == Script::StrictMode::Strict)
2094 scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
2095
2096 if (isModule)
2097 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName);
2098 else {
2099 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer))
2100 return false; // fail early so we can catch missing files
2101 }
2102 } else {
2103 size_t commandLineLength = strlen(scripts[i].argument);
2104 scriptBuffer.resize(commandLineLength);
2105 std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
2106 fileName = ASCIILiteral("[Command Line]");
2107 }
2108
2109 bool isLastFile = i == scripts.size() - 1;
2110 if (isModule) {
2111 if (!promise)
2112 promise = loadAndEvaluateModule(globalObject->globalExec(), jscSource(scriptBuffer, fileName));
2113 vm.clearException();
2114
2115 JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
2116 checkException(isLastFile, false, exec->argument(0));
2117 return JSValue::encode(jsUndefined());
2118 });
2119
2120 JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
2121 checkException(isLastFile, true, exec->argument(0));
2122 return JSValue::encode(jsUndefined());
2123 });
2124
2125 promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
2126 vm.drainMicrotasks();
2127 } else {
2128 NakedPtr<Exception> evaluationException;
2129 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, fileName), JSValue(), evaluationException);
2130 if (evaluationException)
2131 returnValue = evaluationException->value();
2132 checkException(isLastFile, evaluationException, returnValue);
2133 }
2134
2135 scriptBuffer.clear();
2136 vm.clearException();
2137 }
2138
2139#if ENABLE(REGEXP_TRACING)
2140 vm.dumpRegExpTrace();
2141#endif
2142 return success;
2143}
2144
2145#define RUNNING_FROM_XCODE 0
2146
2147static void runInteractive(GlobalObject* globalObject)
2148{
2149 String interpreterName(ASCIILiteral("Interpreter"));
2150
2151 bool shouldQuit = false;
2152 while (!shouldQuit) {
2153#if HAVE(READLINE) && !RUNNING_FROM_XCODE
2154 ParserError error;
2155 String source;
2156 do {
2157 error = ParserError();
2158 char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
2159 shouldQuit = !line;
2160 if (!line)
2161 break;
2162 source = source + line;
2163 source = source + '\n';
2164 checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
2165 if (!line[0])
2166 break;
2167 add_history(line);
2168 } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
2169
2170 if (error.isValid()) {
2171 printf("%s:%d\n", error.message().utf8().data(), error.line());
2172 continue;
2173 }
2174
2175
2176 NakedPtr<Exception> evaluationException;
2177 JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), evaluationException);
2178#else
2179 printf("%s", interactivePrompt);
2180 Vector<char, 256> line;
2181 int c;
2182 while ((c = getchar()) != EOF) {
2183 // FIXME: Should we also break on \r?
2184 if (c == '\n')
2185 break;
2186 line.append(c);
2187 }
2188 if (line.isEmpty())
2189 break;
2190
2191 NakedPtr<Exception> evaluationException;
2192 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, interpreterName), JSValue(), evaluationException);
2193#endif
2194 if (evaluationException)
2195 printf("Exception: %s\n", evaluationException->value().toWTFString(globalObject->globalExec()).utf8().data());
2196 else
2197 printf("%s\n", returnValue.toWTFString(globalObject->globalExec()).utf8().data());
2198
2199 globalObject->globalExec()->clearException();
2200 globalObject->vm().drainMicrotasks();
2201 }
2202 printf("\n");
2203}
2204
2205static NO_RETURN void printUsageStatement(bool help = false)
2206{
2207 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
2208 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
2209 fprintf(stderr, " -e Evaluate argument as script code\n");
2210 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
2211 fprintf(stderr, " -h|--help Prints this help message\n");
2212 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
2213 fprintf(stderr, " -m Execute as a module\n");
2214#if HAVE(SIGNAL_H)
2215 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
2216#endif
2217 fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
2218 fprintf(stderr, " -x Output exit code before terminating\n");
2219 fprintf(stderr, "\n");
2220 fprintf(stderr, " --sample Collects and outputs sampling profiler data\n");
2221 fprintf(stderr, " --test262-async Check that some script calls the print function with the string 'Test262:AsyncTestComplete'\n");
2222 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");
2223 fprintf(stderr, " --module-file=<file> Parse and evaluate the given file as module (this option may be passed more than once)\n");
2224 fprintf(stderr, " --exception=<name> Check the last script exits with an uncaught exception with the specified name\n");
2225 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
2226 fprintf(stderr, " --dumpOptions Dumps all non-default JSC VM options before continuing\n");
2227 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
2228 fprintf(stderr, "\n");
2229
2230 jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
2231}
2232
2233void CommandLine::parseArguments(int argc, char** argv)
2234{
2235 Options::initialize();
2236
2237 int i = 1;
2238 JSC::Options::DumpLevel dumpOptionsLevel = JSC::Options::DumpLevel::None;
2239 bool needToExit = false;
2240
2241 bool hasBadJSCOptions = false;
2242 for (; i < argc; ++i) {
2243 const char* arg = argv[i];
2244 if (!strcmp(arg, "-f")) {
2245 if (++i == argc)
2246 printUsageStatement();
2247 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
2248 continue;
2249 }
2250 if (!strcmp(arg, "-e")) {
2251 if (++i == argc)
2252 printUsageStatement();
2253 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::CommandLine, Script::ScriptType::Script, argv[i]));
2254 continue;
2255 }
2256 if (!strcmp(arg, "-i")) {
2257 m_interactive = true;
2258 continue;
2259 }
2260 if (!strcmp(arg, "-d")) {
2261 m_dump = true;
2262 continue;
2263 }
2264 if (!strcmp(arg, "-p")) {
2265 if (++i == argc)
2266 printUsageStatement();
2267 m_profile = true;
2268 m_profilerOutput = argv[i];
2269 continue;
2270 }
2271 if (!strcmp(arg, "-m")) {
2272 m_module = true;
2273 continue;
2274 }
2275 if (!strcmp(arg, "-s")) {
2276#if HAVE(SIGNAL_H)
2277 signal(SIGILL, _exit);
2278 signal(SIGFPE, _exit);
2279 signal(SIGBUS, _exit);
2280 signal(SIGSEGV, _exit);
2281#endif
2282 continue;
2283 }
2284 if (!strcmp(arg, "-x")) {
2285 m_exitCode = true;
2286 continue;
2287 }
2288 if (!strcmp(arg, "--")) {
2289 ++i;
2290 break;
2291 }
2292 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
2293 printUsageStatement(true);
2294
2295 if (!strcmp(arg, "--options")) {
2296 dumpOptionsLevel = JSC::Options::DumpLevel::Verbose;
2297 needToExit = true;
2298 continue;
2299 }
2300 if (!strcmp(arg, "--dumpOptions")) {
2301 dumpOptionsLevel = JSC::Options::DumpLevel::Overridden;
2302 continue;
2303 }
2304 if (!strcmp(arg, "--sample")) {
2305 JSC::Options::useSamplingProfiler() = true;
2306 JSC::Options::collectSamplingProfilerDataForJSCShell() = true;
2307 m_dumpSamplingProfilerData = true;
2308 continue;
2309 }
2310
2311 if (!strcmp(arg, "--test262-async")) {
2312 test262AsyncTest = true;
2313 continue;
2314 }
2315
2316 static const unsigned strictFileStrLength = strlen("--strict-file=");
2317 if (!strncmp(arg, "--strict-file=", strictFileStrLength)) {
2318 m_scripts.append(Script(Script::StrictMode::Strict, Script::CodeSource::File, Script::ScriptType::Script, argv[i] + strictFileStrLength));
2319 continue;
2320 }
2321
2322 static const unsigned moduleFileStrLength = strlen("--module-file=");
2323 if (!strncmp(arg, "--module-file=", moduleFileStrLength)) {
2324 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Module, argv[i] + moduleFileStrLength));
2325 continue;
2326 }
2327
2328 static const unsigned exceptionStrLength = strlen("--exception=");
2329 if (!strncmp(arg, "--exception=", exceptionStrLength)) {
2330 m_uncaughtExceptionName = String(arg + exceptionStrLength);
2331 continue;
2332 }
2333
2334 // See if the -- option is a JSC VM option.
2335 if (strstr(arg, "--") == arg) {
2336 if (!JSC::Options::setOption(&arg[2])) {
2337 hasBadJSCOptions = true;
2338 dataLog("ERROR: invalid option: ", arg, "\n");
2339 }
2340 continue;
2341 }
2342
2343 // This arg is not recognized by the VM nor by jsc. Pass it on to the
2344 // script.
2345 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
2346 }
2347
2348 if (hasBadJSCOptions && JSC::Options::validateOptions())
2349 CRASH();
2350
2351 if (m_scripts.isEmpty())
2352 m_interactive = true;
2353
2354 for (; i < argc; ++i)
2355 m_arguments.append(argv[i]);
2356
2357 if (dumpOptionsLevel != JSC::Options::DumpLevel::None) {
2358 const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
2359 ? "Modified JSC runtime options:"
2360 : "All JSC runtime options:";
2361 JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
2362 }
2363 JSC::Options::ensureOptionsAreCoherent();
2364 if (needToExit)
2365 jscExit(EXIT_SUCCESS);
2366}
2367
2368// We make this function no inline so that globalObject won't be on the stack if we do a GC in jscmain.
2369static int NEVER_INLINE runJSC(VM* vm, CommandLine options)
2370{
2371 JSLockHolder locker(vm);
2372
2373 int result;
2374 if (options.m_profile && !vm->m_perBytecodeProfiler)
2375 vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*vm);
2376
2377 GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
2378 bool success = runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_dump, options.m_module);
2379 if (options.m_interactive && success)
2380 runInteractive(globalObject);
2381
2382 vm->drainMicrotasks();
2383 result = success && (test262AsyncTest == test262AsyncPassed) ? 0 : 3;
2384
2385 if (options.m_exitCode)
2386 printf("jsc exiting %d\n", result);
2387
2388 if (options.m_profile) {
2389 if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
2390 fprintf(stderr, "could not save profiler output.\n");
2391 }
2392
2393#if ENABLE(JIT)
2394 if (Options::useExceptionFuzz())
2395 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
2396 bool fireAtEnabled =
2397 Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
2398 if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
2399 printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
2400 if (Options::useOSRExitFuzz()) {
2401 printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
2402 printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
2403 }
2404
2405 auto compileTimeStats = JIT::compileTimeStats();
2406 Vector<CString> compileTimeKeys;
2407 for (auto& entry : compileTimeStats)
2408 compileTimeKeys.append(entry.key);
2409 std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
2410 for (CString key : compileTimeKeys)
2411 printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
2412#endif
2413
2414 return result;
2415}
2416
2417int jscmain(int argc, char** argv)
2418{
2419 // Note that the options parsing can affect VM creation, and thus
2420 // comes first.
2421 CommandLine options(argc, argv);
2422
2423 // Initialize JSC before getting VM.
2424#if ENABLE(SAMPLING_REGIONS)
2425 WTF::initializeMainThread();
2426#endif
2427 JSC::initializeThreading();
2428
2429 Ref<VM> vm = VM::create(LargeHeap);
2430 int result = runJSC(vm.ptr(), options);
2431
2432 if (Options::gcAtEnd()) {
2433 // We need to hold the API lock to do a GC.
2434 JSLockHolder locker(vm);
2435 vm->heap.collectAllGarbage();
2436 }
2437
2438 if (options.m_dumpSamplingProfilerData) {
2439#if ENABLE(SAMPLING_PROFILER)
2440 JSLockHolder locker(vm);
2441 vm->samplingProfiler()->reportTopFunctions();
2442 vm->samplingProfiler()->reportTopBytecodes();
2443#else
2444 dataLog("Sampling profiler is not enabled on this platform\n");
2445#endif
2446 }
2447
2448 printSuperSamplerState();
2449
2450 return result;
2451}
2452
2453#if OS(WINDOWS)
2454extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
2455{
2456 return main(argc, const_cast<char**>(argv));
2457}
2458#endif
Note: See TracBrowser for help on using the repository browser.