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

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

test262: $.agent became $262.agent in test262 update
https://bugs.webkit.org/show_bug.cgi?id=177407

Patch by Joseph Pecoraro <Joseph Pecoraro> on 2017-09-23
Reviewed by Yusuke Suzuki.

JSTests:

  • test262.yaml:

~320 tests pass now that we correctly make $262 available.

Source/JavaScriptCore:

  • jsc.cpp:

(GlobalObject::finishCreation):
Alias $ and $262 for now.

  • Property svn:eol-style set to native
File size: 140.9 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include "ArrayBuffer.h"
26#include "ArrayPrototype.h"
27#include "BuiltinExecutableCreator.h"
28#include "BuiltinNames.h"
29#include "ButterflyInlines.h"
30#include "CatchScope.h"
31#include "CodeBlock.h"
32#include "Completion.h"
33#include "ConfigFile.h"
34#include "DOMAttributeGetterSetter.h"
35#include "DOMJITGetterSetter.h"
36#include "Disassembler.h"
37#include "Exception.h"
38#include "ExceptionHelpers.h"
39#include "FrameTracers.h"
40#include "GetterSetter.h"
41#include "HeapProfiler.h"
42#include "HeapSnapshotBuilder.h"
43#include "InitializeThreading.h"
44#include "Interpreter.h"
45#include "JIT.h"
46#include "JSArray.h"
47#include "JSArrayBuffer.h"
48#include "JSCInlines.h"
49#include "JSFunction.h"
50#include "JSInternalPromise.h"
51#include "JSInternalPromiseDeferred.h"
52#include "JSLock.h"
53#include "JSModuleLoader.h"
54#include "JSNativeStdFunction.h"
55#include "JSONObject.h"
56#include "JSProxy.h"
57#include "JSSourceCode.h"
58#include "JSString.h"
59#include "JSTypedArrays.h"
60#include "JSWebAssemblyInstance.h"
61#include "JSWebAssemblyMemory.h"
62#include "LLIntData.h"
63#include "LLIntThunks.h"
64#include "ObjectConstructor.h"
65#include "ParserError.h"
66#include "ProfilerDatabase.h"
67#include "PromiseDeferredTimer.h"
68#include "ProtoCallFrame.h"
69#include "ReleaseHeapAccessScope.h"
70#include "SamplingProfiler.h"
71#include "ShadowChicken.h"
72#include "Snippet.h"
73#include "SnippetParams.h"
74#include "StackVisitor.h"
75#include "StructureInlines.h"
76#include "StructureRareDataInlines.h"
77#include "SuperSampler.h"
78#include "TestRunnerUtils.h"
79#include "TypeProfiler.h"
80#include "TypeProfilerLog.h"
81#include "TypedArrayInlines.h"
82#include "WasmContext.h"
83#include "WasmFaultSignalHandler.h"
84#include "WasmMemory.h"
85#include <locale.h>
86#include <math.h>
87#include <stdio.h>
88#include <stdlib.h>
89#include <string.h>
90#include <thread>
91#include <type_traits>
92#include <wtf/CommaPrinter.h>
93#include <wtf/CurrentTime.h>
94#include <wtf/MainThread.h>
95#include <wtf/NeverDestroyed.h>
96#include <wtf/StringPrintStream.h>
97#include <wtf/text/StringBuilder.h>
98
99#if OS(WINDOWS)
100#include <direct.h>
101#include <wtf/text/win/WCharStringExtras.h>
102#else
103#include <unistd.h>
104#endif
105
106#if PLATFORM(COCOA)
107#include <crt_externs.h>
108#endif
109
110#if HAVE(READLINE)
111// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
112// We #define it to something else to avoid this conflict.
113#define Function ReadlineFunction
114#include <readline/history.h>
115#include <readline/readline.h>
116#undef Function
117#endif
118
119#if HAVE(SYS_TIME_H)
120#include <sys/time.h>
121#endif
122
123#if HAVE(SIGNAL_H)
124#include <signal.h>
125#endif
126
127#if COMPILER(MSVC)
128#include <crtdbg.h>
129#include <mmsystem.h>
130#include <windows.h>
131#endif
132
133#if PLATFORM(IOS) && CPU(ARM_THUMB2)
134#include <fenv.h>
135#include <arm/arch.h>
136#endif
137
138#if !defined(PATH_MAX)
139#define PATH_MAX 4096
140#endif
141
142using namespace JSC;
143using namespace WTF;
144
145namespace {
146
147NO_RETURN_WITH_VALUE static void jscExit(int status)
148{
149 waitForAsynchronousDisassembly();
150
151#if ENABLE(DFG_JIT)
152 if (DFG::isCrashing()) {
153 for (;;) {
154#if OS(WINDOWS)
155 Sleep(1000);
156#else
157 pause();
158#endif
159 }
160 }
161#endif // ENABLE(DFG_JIT)
162 exit(status);
163}
164
165class Element;
166class ElementHandleOwner;
167class Masuqerader;
168class Root;
169class RuntimeArray;
170
171class Element : public JSNonFinalObject {
172public:
173 Element(VM& vm, Structure* structure)
174 : Base(vm, structure)
175 {
176 }
177
178 typedef JSNonFinalObject Base;
179
180 Root* root() const { return m_root.get(); }
181 void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
182
183 static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
184 {
185 Structure* structure = createStructure(vm, globalObject, jsNull());
186 Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
187 element->finishCreation(vm, root);
188 return element;
189 }
190
191 void finishCreation(VM&, Root*);
192
193 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
194 {
195 Element* thisObject = jsCast<Element*>(cell);
196 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
197 Base::visitChildren(thisObject, visitor);
198 visitor.append(thisObject->m_root);
199 }
200
201 static ElementHandleOwner* handleOwner();
202
203 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
204 {
205 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
206 }
207
208 DECLARE_INFO;
209
210private:
211 WriteBarrier<Root> m_root;
212};
213
214class ElementHandleOwner : public WeakHandleOwner {
215public:
216 bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) override
217 {
218 Element* element = jsCast<Element*>(handle.slot()->asCell());
219 return visitor.containsOpaqueRoot(element->root());
220 }
221};
222
223class Masquerader : public JSNonFinalObject {
224public:
225 Masquerader(VM& vm, Structure* structure)
226 : Base(vm, structure)
227 {
228 }
229
230 typedef JSNonFinalObject Base;
231 static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
232
233 static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
234 {
235 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(vm, "Masquerading object allocated");
236 Structure* structure = createStructure(vm, globalObject, jsNull());
237 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
238 result->finishCreation(vm);
239 return result;
240 }
241
242 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
243 {
244 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
245 }
246
247 DECLARE_INFO;
248};
249
250class Root : public JSDestructibleObject {
251public:
252 Root(VM& vm, Structure* structure)
253 : Base(vm, structure)
254 {
255 }
256
257 Element* element()
258 {
259 return m_element.get();
260 }
261
262 void setElement(Element* element)
263 {
264 Weak<Element> newElement(element, Element::handleOwner());
265 m_element.swap(newElement);
266 }
267
268 static Root* create(VM& vm, JSGlobalObject* globalObject)
269 {
270 Structure* structure = createStructure(vm, globalObject, jsNull());
271 Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
272 root->finishCreation(vm);
273 return root;
274 }
275
276 typedef JSDestructibleObject Base;
277
278 DECLARE_INFO;
279
280 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
281 {
282 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
283 }
284
285 static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
286 {
287 Base::visitChildren(thisObject, visitor);
288 visitor.addOpaqueRoot(thisObject);
289 }
290
291private:
292 Weak<Element> m_element;
293};
294
295class ImpureGetter : public JSNonFinalObject {
296public:
297 ImpureGetter(VM& vm, Structure* structure)
298 : Base(vm, structure)
299 {
300 }
301
302 DECLARE_INFO;
303 typedef JSNonFinalObject Base;
304 static const unsigned StructureFlags = Base::StructureFlags | JSC::GetOwnPropertySlotIsImpure | JSC::OverridesGetOwnPropertySlot;
305
306 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
307 {
308 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
309 }
310
311 static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
312 {
313 ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
314 getter->finishCreation(vm, delegate);
315 return getter;
316 }
317
318 void finishCreation(VM& vm, JSObject* delegate)
319 {
320 Base::finishCreation(vm);
321 if (delegate)
322 m_delegate.set(vm, this, delegate);
323 }
324
325 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
326 {
327 VM& vm = exec->vm();
328 auto scope = DECLARE_THROW_SCOPE(vm);
329 ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
330
331 if (thisObject->m_delegate) {
332 if (thisObject->m_delegate->getPropertySlot(exec, name, slot))
333 return true;
334 RETURN_IF_EXCEPTION(scope, false);
335 }
336
337 return Base::getOwnPropertySlot(object, exec, name, slot);
338 }
339
340 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
341 {
342 Base::visitChildren(cell, visitor);
343 ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
344 visitor.append(thisObject->m_delegate);
345 }
346
347 void setDelegate(VM& vm, JSObject* delegate)
348 {
349 m_delegate.set(vm, this, delegate);
350 }
351
352private:
353 WriteBarrier<JSObject> m_delegate;
354};
355
356class CustomGetter : public JSNonFinalObject {
357public:
358 CustomGetter(VM& vm, Structure* structure)
359 : Base(vm, structure)
360 {
361 }
362
363 DECLARE_INFO;
364 typedef JSNonFinalObject Base;
365 static const unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot;
366
367 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
368 {
369 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
370 }
371
372 static CustomGetter* create(VM& vm, Structure* structure)
373 {
374 CustomGetter* getter = new (NotNull, allocateCell<CustomGetter>(vm.heap, sizeof(CustomGetter))) CustomGetter(vm, structure);
375 getter->finishCreation(vm);
376 return getter;
377 }
378
379 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
380 {
381 CustomGetter* thisObject = jsCast<CustomGetter*>(object);
382 if (propertyName == PropertyName(Identifier::fromString(exec, "customGetter"))) {
383 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->customGetter);
384 return true;
385 }
386
387 if (propertyName == PropertyName(Identifier::fromString(exec, "customGetterAccessor"))) {
388 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum | CustomAccessor, thisObject->customGetterAcessor);
389 return true;
390 }
391
392 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
393 }
394
395private:
396 static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
397 {
398 VM& vm = exec->vm();
399 auto scope = DECLARE_THROW_SCOPE(vm);
400
401 CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(vm, JSValue::decode(thisValue));
402 if (!thisObject)
403 return throwVMTypeError(exec, scope);
404 bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
405 RETURN_IF_EXCEPTION(scope, encodedJSValue());
406 if (shouldThrow)
407 return throwVMTypeError(exec, scope);
408 return JSValue::encode(jsNumber(100));
409 }
410
411 static EncodedJSValue customGetterAcessor(ExecState* exec, EncodedJSValue thisValue, PropertyName)
412 {
413 VM& vm = exec->vm();
414 auto scope = DECLARE_THROW_SCOPE(vm);
415
416 JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
417 if (!thisObject)
418 return throwVMTypeError(exec, scope);
419 bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
420 RETURN_IF_EXCEPTION(scope, encodedJSValue());
421 if (shouldThrow)
422 return throwVMTypeError(exec, scope);
423 return JSValue::encode(jsNumber(100));
424 }
425};
426
427class RuntimeArray : public JSArray {
428public:
429 typedef JSArray Base;
430 static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
431
432 static RuntimeArray* create(ExecState* exec)
433 {
434 VM& vm = exec->vm();
435 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
436 Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
437 RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(vm.heap)) RuntimeArray(exec, structure);
438 runtimeArray->finishCreation(exec);
439 vm.heap.addFinalizer(runtimeArray, destroy);
440 return runtimeArray;
441 }
442
443 ~RuntimeArray() { }
444
445 static void destroy(JSCell* cell)
446 {
447 static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
448 }
449
450 static const bool needsDestruction = false;
451
452 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
453 {
454 VM& vm = exec->vm();
455 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
456 if (propertyName == vm.propertyNames->length) {
457 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
458 return true;
459 }
460
461 std::optional<uint32_t> index = parseIndex(propertyName);
462 if (index && index.value() < thisObject->getLength()) {
463 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()]));
464 return true;
465 }
466
467 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
468 }
469
470 static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
471 {
472 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
473 if (index < thisObject->getLength()) {
474 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
475 return true;
476 }
477
478 return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
479 }
480
481 static NO_RETURN_DUE_TO_CRASH bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
482 {
483 RELEASE_ASSERT_NOT_REACHED();
484 }
485
486 static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
487 {
488 RELEASE_ASSERT_NOT_REACHED();
489 }
490
491 unsigned getLength() const { return m_vector.size(); }
492
493 DECLARE_INFO;
494
495 static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
496 {
497 return globalObject->arrayPrototype();
498 }
499
500 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
501 {
502 return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
503 }
504
505protected:
506 void finishCreation(ExecState* exec)
507 {
508 VM& vm = exec->vm();
509 Base::finishCreation(vm);
510 ASSERT(inherits(vm, info()));
511
512 for (size_t i = 0; i < exec->argumentCount(); i++)
513 m_vector.append(exec->argument(i).toInt32(exec));
514 }
515
516private:
517 RuntimeArray(ExecState* exec, Structure* structure)
518 : JSArray(exec->vm(), structure, 0)
519 {
520 }
521
522 static EncodedJSValue lengthGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
523 {
524 VM& vm = exec->vm();
525 auto scope = DECLARE_THROW_SCOPE(vm);
526
527 RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(vm, JSValue::decode(thisValue));
528 if (!thisObject)
529 return throwVMTypeError(exec, scope);
530 return JSValue::encode(jsNumber(thisObject->getLength()));
531 }
532
533 Vector<int> m_vector;
534};
535
536class SimpleObject : public JSNonFinalObject {
537public:
538 SimpleObject(VM& vm, Structure* structure)
539 : Base(vm, structure)
540 {
541 }
542
543 typedef JSNonFinalObject Base;
544 static const bool needsDestruction = false;
545
546 static SimpleObject* create(VM& vm, JSGlobalObject* globalObject)
547 {
548 Structure* structure = createStructure(vm, globalObject, jsNull());
549 SimpleObject* simpleObject = new (NotNull, allocateCell<SimpleObject>(vm.heap, sizeof(SimpleObject))) SimpleObject(vm, structure);
550 simpleObject->finishCreation(vm);
551 return simpleObject;
552 }
553
554 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
555 {
556 SimpleObject* thisObject = jsCast<SimpleObject*>(cell);
557 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
558 Base::visitChildren(thisObject, visitor);
559 visitor.append(thisObject->m_hiddenValue);
560 }
561
562 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
563 {
564 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
565 }
566
567 JSValue hiddenValue()
568 {
569 return m_hiddenValue.get();
570 }
571
572 void setHiddenValue(VM& vm, JSValue value)
573 {
574 ASSERT(value.isCell());
575 m_hiddenValue.set(vm, this, value);
576 }
577
578 DECLARE_INFO;
579
580private:
581 WriteBarrier<JSC::Unknown> m_hiddenValue;
582};
583
584class DOMJITNode : public JSNonFinalObject {
585public:
586 DOMJITNode(VM& vm, Structure* structure)
587 : Base(vm, structure)
588 {
589 }
590
591 DECLARE_INFO;
592 typedef JSNonFinalObject Base;
593 static const unsigned StructureFlags = Base::StructureFlags;
594
595 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
596 {
597 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
598 }
599
600#if ENABLE(JIT)
601 static Ref<Snippet> checkSubClassSnippet()
602 {
603 Ref<Snippet> snippet = Snippet::create();
604 snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
605 CCallHelpers::JumpList failureCases;
606 failureCases.append(jit.branch8(
607 CCallHelpers::NotEqual,
608 CCallHelpers::Address(params[0].gpr(), JSCell::typeInfoTypeOffset()),
609 CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
610 return failureCases;
611 });
612 return snippet;
613 }
614#endif
615
616 static DOMJITNode* create(VM& vm, Structure* structure)
617 {
618 DOMJITNode* getter = new (NotNull, allocateCell<DOMJITNode>(vm.heap, sizeof(DOMJITNode))) DOMJITNode(vm, structure);
619 getter->finishCreation(vm);
620 return getter;
621 }
622
623 int32_t value() const
624 {
625 return m_value;
626 }
627
628 static ptrdiff_t offsetOfValue() { return OBJECT_OFFSETOF(DOMJITNode, m_value); }
629
630private:
631 int32_t m_value { 42 };
632};
633
634class DOMJITGetter : public DOMJITNode {
635public:
636 DOMJITGetter(VM& vm, Structure* structure)
637 : Base(vm, structure)
638 {
639 }
640
641 DECLARE_INFO;
642 typedef DOMJITNode Base;
643 static const unsigned StructureFlags = Base::StructureFlags;
644
645 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
646 {
647 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
648 }
649
650 static DOMJITGetter* create(VM& vm, Structure* structure)
651 {
652 DOMJITGetter* getter = new (NotNull, allocateCell<DOMJITGetter>(vm.heap, sizeof(DOMJITGetter))) DOMJITGetter(vm, structure);
653 getter->finishCreation(vm);
654 return getter;
655 }
656
657 class DOMJITAttribute : public DOMJIT::GetterSetter {
658 public:
659 constexpr DOMJITAttribute()
660 : DOMJIT::GetterSetter(
661 DOMJITGetter::customGetter,
662#if ENABLE(JIT)
663 &callDOMGetter,
664#else
665 nullptr,
666#endif
667 SpecInt32Only)
668 {
669 }
670
671#if ENABLE(JIT)
672 static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
673 {
674 VM& vm = exec->vm();
675 NativeCallFrameTracer tracer(&vm, exec);
676 return JSValue::encode(jsNumber(static_cast<DOMJITGetter*>(pointer)->value()));
677 }
678
679 static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
680 {
681 Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
682 snippet->requireGlobalObject = false;
683 snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
684 JSValueRegs results = params[0].jsValueRegs();
685 GPRReg dom = params[1].gpr();
686 params.addSlowPathCall(jit.jump(), jit, slowCall, results, dom);
687 return CCallHelpers::JumpList();
688
689 });
690 return snippet;
691 }
692#endif
693 };
694
695private:
696 void finishCreation(VM&);
697
698 static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
699 {
700 VM& vm = exec->vm();
701 DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, JSValue::decode(thisValue));
702 ASSERT(thisObject);
703 return JSValue::encode(jsNumber(thisObject->value()));
704 }
705};
706
707static const DOMJITGetter::DOMJITAttribute DOMJITGetterDOMJIT;
708
709void DOMJITGetter::finishCreation(VM& vm)
710{
711 Base::finishCreation(vm);
712 const DOMJIT::GetterSetter* domJIT = &DOMJITGetterDOMJIT;
713 auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { DOMJITNode::info(), domJIT });
714 putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, ReadOnly | CustomAccessor);
715}
716
717class DOMJITGetterComplex : public DOMJITNode {
718public:
719 DOMJITGetterComplex(VM& vm, Structure* structure)
720 : Base(vm, structure)
721 {
722 }
723
724 DECLARE_INFO;
725 typedef DOMJITNode Base;
726 static const unsigned StructureFlags = Base::StructureFlags;
727
728 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
729 {
730 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
731 }
732
733 static DOMJITGetterComplex* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
734 {
735 DOMJITGetterComplex* getter = new (NotNull, allocateCell<DOMJITGetterComplex>(vm.heap, sizeof(DOMJITGetterComplex))) DOMJITGetterComplex(vm, structure);
736 getter->finishCreation(vm, globalObject);
737 return getter;
738 }
739
740 class DOMJITAttribute : public DOMJIT::GetterSetter {
741 public:
742 constexpr DOMJITAttribute()
743 : DOMJIT::GetterSetter(
744 DOMJITGetterComplex::customGetter,
745#if ENABLE(JIT)
746 &callDOMGetter,
747#else
748 nullptr,
749#endif
750 SpecInt32Only)
751 {
752 }
753
754#if ENABLE(JIT)
755 static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
756 {
757 VM& vm = exec->vm();
758 NativeCallFrameTracer tracer(&vm, exec);
759 auto scope = DECLARE_THROW_SCOPE(vm);
760 auto* object = static_cast<DOMJITNode*>(pointer);
761 auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(vm, object);
762 if (domjitGetterComplex) {
763 if (domjitGetterComplex->m_enableException)
764 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
765 }
766 return JSValue::encode(jsNumber(object->value()));
767 }
768
769 static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
770 {
771 Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
772 static_assert(GPRInfo::numberOfRegisters >= 4, "Number of registers should be larger or equal to 4.");
773 unsigned numGPScratchRegisters = GPRInfo::numberOfRegisters - 4;
774 snippet->numGPScratchRegisters = numGPScratchRegisters;
775 snippet->numFPScratchRegisters = 3;
776 snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
777 JSValueRegs results = params[0].jsValueRegs();
778 GPRReg domGPR = params[1].gpr();
779 for (unsigned i = 0; i < numGPScratchRegisters; ++i)
780 jit.move(CCallHelpers::TrustedImm32(42), params.gpScratch(i));
781
782 params.addSlowPathCall(jit.jump(), jit, slowCall, results, domGPR);
783 return CCallHelpers::JumpList();
784 });
785 return snippet;
786 }
787#endif
788 };
789
790private:
791 void finishCreation(VM&, JSGlobalObject*);
792
793 static EncodedJSValue JSC_HOST_CALL functionEnableException(ExecState* exec)
794 {
795 VM& vm = exec->vm();
796 auto* object = jsDynamicCast<DOMJITGetterComplex*>(vm, exec->thisValue());
797 if (object)
798 object->m_enableException = true;
799 return JSValue::encode(jsUndefined());
800 }
801
802 static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
803 {
804 VM& vm = exec->vm();
805 auto scope = DECLARE_THROW_SCOPE(vm);
806
807 auto* thisObject = jsDynamicCast<DOMJITGetterComplex*>(vm, JSValue::decode(thisValue));
808 ASSERT(thisObject);
809 if (thisObject->m_enableException)
810 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
811 return JSValue::encode(jsNumber(thisObject->value()));
812 }
813
814 bool m_enableException { false };
815};
816
817static const DOMJITGetterComplex::DOMJITAttribute DOMJITGetterComplexDOMJIT;
818
819void DOMJITGetterComplex::finishCreation(VM& vm, JSGlobalObject* globalObject)
820{
821 Base::finishCreation(vm);
822 const DOMJIT::GetterSetter* domJIT = &DOMJITGetterComplexDOMJIT;
823 auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { DOMJITGetterComplex::info(), domJIT });
824 putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, ReadOnly | CustomAccessor);
825 putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "enableException"), 0, functionEnableException, NoIntrinsic, 0);
826}
827
828class DOMJITFunctionObject : public DOMJITNode {
829public:
830 DOMJITFunctionObject(VM& vm, Structure* structure)
831 : Base(vm, structure)
832 {
833 }
834
835 DECLARE_INFO;
836 typedef DOMJITNode Base;
837 static const unsigned StructureFlags = Base::StructureFlags;
838
839
840 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
841 {
842 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
843 }
844
845 static DOMJITFunctionObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
846 {
847 DOMJITFunctionObject* object = new (NotNull, allocateCell<DOMJITFunctionObject>(vm.heap, sizeof(DOMJITFunctionObject))) DOMJITFunctionObject(vm, structure);
848 object->finishCreation(vm, globalObject);
849 return object;
850 }
851
852 static EncodedJSValue JSC_HOST_CALL safeFunction(ExecState* exec)
853 {
854 VM& vm = exec->vm();
855 auto scope = DECLARE_THROW_SCOPE(vm);
856
857 DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, exec->thisValue());
858 if (!thisObject)
859 return throwVMTypeError(exec, scope);
860 return JSValue::encode(jsNumber(thisObject->value()));
861 }
862
863 static EncodedJSValue JIT_OPERATION unsafeFunction(ExecState* exec, DOMJITNode* node)
864 {
865 VM& vm = exec->vm();
866 NativeCallFrameTracer tracer(&vm, exec);
867 return JSValue::encode(jsNumber(node->value()));
868 }
869
870#if ENABLE(JIT)
871 static Ref<Snippet> checkSubClassSnippet()
872 {
873 Ref<Snippet> snippet = Snippet::create();
874 snippet->numFPScratchRegisters = 1;
875 snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
876 static const double value = 42.0;
877 CCallHelpers::JumpList failureCases;
878 // May use scratch registers.
879 jit.loadDouble(CCallHelpers::TrustedImmPtr(&value), params.fpScratch(0));
880 failureCases.append(jit.branch8(
881 CCallHelpers::NotEqual,
882 CCallHelpers::Address(params[0].gpr(), JSCell::typeInfoTypeOffset()),
883 CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
884 return failureCases;
885 });
886 return snippet;
887 }
888#endif
889
890private:
891 void finishCreation(VM&, JSGlobalObject*);
892};
893
894static const DOMJIT::Signature DOMJITFunctionObjectSignature((uintptr_t)DOMJITFunctionObject::unsafeFunction, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
895
896void DOMJITFunctionObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
897{
898 Base::finishCreation(vm);
899 putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, &DOMJITFunctionObjectSignature, ReadOnly);
900}
901
902class DOMJITCheckSubClassObject : public DOMJITNode {
903public:
904 DOMJITCheckSubClassObject(VM& vm, Structure* structure)
905 : Base(vm, structure)
906 {
907 }
908
909 DECLARE_INFO;
910 typedef DOMJITNode Base;
911 static const unsigned StructureFlags = Base::StructureFlags;
912
913
914 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
915 {
916 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
917 }
918
919 static DOMJITCheckSubClassObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
920 {
921 DOMJITCheckSubClassObject* object = new (NotNull, allocateCell<DOMJITCheckSubClassObject>(vm.heap, sizeof(DOMJITCheckSubClassObject))) DOMJITCheckSubClassObject(vm, structure);
922 object->finishCreation(vm, globalObject);
923 return object;
924 }
925
926 static EncodedJSValue JSC_HOST_CALL safeFunction(ExecState* exec)
927 {
928 VM& vm = exec->vm();
929 auto scope = DECLARE_THROW_SCOPE(vm);
930
931 auto* thisObject = jsDynamicCast<DOMJITCheckSubClassObject*>(vm, exec->thisValue());
932 if (!thisObject)
933 return throwVMTypeError(exec, scope);
934 return JSValue::encode(jsNumber(thisObject->value()));
935 }
936
937 static EncodedJSValue JIT_OPERATION unsafeFunction(ExecState* exec, DOMJITNode* node)
938 {
939 VM& vm = exec->vm();
940 NativeCallFrameTracer tracer(&vm, exec);
941 return JSValue::encode(jsNumber(node->value()));
942 }
943
944private:
945 void finishCreation(VM&, JSGlobalObject*);
946};
947
948static const DOMJIT::Signature DOMJITCheckSubClassObjectSignature((uintptr_t)DOMJITCheckSubClassObject::unsafeFunction, DOMJITCheckSubClassObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
949
950void DOMJITCheckSubClassObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
951{
952 Base::finishCreation(vm);
953 putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, &DOMJITCheckSubClassObjectSignature, ReadOnly);
954}
955
956const ClassInfo Element::s_info = { "Element", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Element) };
957const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Masquerader) };
958const ClassInfo Root::s_info = { "Root", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Root) };
959const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ImpureGetter) };
960const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(CustomGetter) };
961#if ENABLE(JIT)
962const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, &DOMJITNode::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITNode) };
963#else
964const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITNode) };
965#endif
966const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetter) };
967const ClassInfo DOMJITGetterComplex::s_info = { "DOMJITGetterComplex", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetterComplex) };
968#if ENABLE(JIT)
969const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, &DOMJITFunctionObject::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
970#else
971const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
972#endif
973const ClassInfo DOMJITCheckSubClassObject::s_info = { "DOMJITCheckSubClassObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITCheckSubClassObject) };
974const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RuntimeArray) };
975const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(SimpleObject) };
976static unsigned asyncTestPasses { 0 };
977static unsigned asyncTestExpectedPasses { 0 };
978
979ElementHandleOwner* Element::handleOwner()
980{
981 static ElementHandleOwner* owner = 0;
982 if (!owner)
983 owner = new ElementHandleOwner();
984 return owner;
985}
986
987void Element::finishCreation(VM& vm, Root* root)
988{
989 Base::finishCreation(vm);
990 setRoot(vm, root);
991 m_root->setElement(this);
992}
993
994}
995
996static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
997static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName);
998
999class CommandLine;
1000class GlobalObject;
1001class Workers;
1002
1003template<typename Func>
1004int runJSC(CommandLine, bool isWorker, const Func&);
1005static void checkException(GlobalObject*, bool isLastFile, bool hasException, JSValue, CommandLine&, bool& success);
1006
1007class Message : public ThreadSafeRefCounted<Message> {
1008public:
1009 Message(ArrayBufferContents&&, int32_t);
1010 ~Message();
1011
1012 ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
1013 int32_t index() const { return m_index; }
1014
1015private:
1016 ArrayBufferContents m_contents;
1017 int32_t m_index { 0 };
1018};
1019
1020class Worker : public BasicRawSentinelNode<Worker> {
1021public:
1022 Worker(Workers&);
1023 ~Worker();
1024
1025 void enqueue(const AbstractLocker&, RefPtr<Message>);
1026 RefPtr<Message> dequeue();
1027
1028 static Worker& current();
1029
1030private:
1031 static ThreadSpecific<Worker*>& currentWorker();
1032
1033 Workers& m_workers;
1034 Deque<RefPtr<Message>> m_messages;
1035};
1036
1037class Workers {
1038public:
1039 Workers();
1040 ~Workers();
1041
1042 template<typename Func>
1043 void broadcast(const Func&);
1044
1045 void report(String);
1046 String tryGetReport();
1047 String getReport();
1048
1049 static Workers& singleton();
1050
1051private:
1052 friend class Worker;
1053
1054 Lock m_lock;
1055 Condition m_condition;
1056 SentinelLinkedList<Worker, BasicRawSentinelNode<Worker>> m_workers;
1057 Deque<String> m_reports;
1058};
1059
1060static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
1061static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
1062static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
1063static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
1064static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState*);
1065static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState*);
1066static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState*);
1067static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState*);
1068static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITCheckSubClassObject(ExecState*);
1069static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
1070static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
1071static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
1072
1073static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
1074static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
1075static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
1076static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
1077static EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState*);
1078static EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState*);
1079static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState*);
1080static EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState*);
1081static EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState*);
1082static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
1083static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
1084static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
1085static EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState*);
1086static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
1087static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
1088static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
1089static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
1090static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
1091static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
1092static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
1093static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState*);
1094#ifndef NDEBUG
1095static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
1096#endif
1097static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
1098static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
1099static EncodedJSValue JSC_HOST_CALL functionRunString(ExecState*);
1100static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
1101static EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState*);
1102static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
1103static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
1104static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
1105static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
1106static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
1107static EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState*);
1108static EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState*);
1109static EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState*);
1110static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
1111static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
1112static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*);
1113static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
1114static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
1115static EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*);
1116static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
1117static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*);
1118static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
1119static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
1120static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
1121static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
1122static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
1123static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
1124static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
1125static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
1126static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
1127static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
1128static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState*);
1129static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*);
1130static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
1131static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
1132static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState*);
1133static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
1134static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*);
1135static EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*);
1136static EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState*);
1137static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
1138static EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*);
1139static EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState*);
1140static EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*);
1141static EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState*);
1142#if ENABLE(SAMPLING_PROFILER)
1143static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*);
1144static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*);
1145#endif
1146
1147static EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*);
1148static EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState*);
1149static EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*);
1150
1151#if ENABLE(WEBASSEMBLY)
1152static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState*);
1153#endif
1154
1155#if ENABLE(SAMPLING_FLAGS)
1156static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
1157static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
1158#endif
1159
1160static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState*);
1161static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState*);
1162static EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState*);
1163static EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState*);
1164static EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState*);
1165static EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState*);
1166static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState*);
1167static EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState*);
1168static EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState*);
1169static EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState*);
1170static EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState*);
1171static EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState*);
1172static EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState*);
1173static EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState*);
1174static EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState*);
1175static EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState*);
1176static EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*);
1177static EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState*);
1178static EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState*);
1179static EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState*);
1180
1181struct Script {
1182 enum class StrictMode {
1183 Strict,
1184 Sloppy
1185 };
1186
1187 enum class ScriptType {
1188 Script,
1189 Module
1190 };
1191
1192 enum class CodeSource {
1193 File,
1194 CommandLine
1195 };
1196
1197 StrictMode strictMode;
1198 CodeSource codeSource;
1199 ScriptType scriptType;
1200 char* argument;
1201
1202 Script(StrictMode strictMode, CodeSource codeSource, ScriptType scriptType, char *argument)
1203 : strictMode(strictMode)
1204 , codeSource(codeSource)
1205 , scriptType(scriptType)
1206 , argument(argument)
1207 {
1208 if (strictMode == StrictMode::Strict)
1209 ASSERT(codeSource == CodeSource::File);
1210 }
1211};
1212
1213class CommandLine {
1214public:
1215 CommandLine(int argc, char** argv)
1216 {
1217 parseArguments(argc, argv);
1218 }
1219
1220 bool m_interactive { false };
1221 bool m_dump { false };
1222 bool m_module { false };
1223 bool m_exitCode { false };
1224 Vector<Script> m_scripts;
1225 Vector<String> m_arguments;
1226 bool m_profile { false };
1227 String m_profilerOutput;
1228 String m_uncaughtExceptionName;
1229 bool m_treatWatchdogExceptionAsSuccess { false };
1230 bool m_alwaysDumpUncaughtException { false };
1231 bool m_dumpSamplingProfilerData { false };
1232 bool m_enableRemoteDebugging { false };
1233
1234 void parseArguments(int, char**);
1235};
1236
1237static const char interactivePrompt[] = ">>> ";
1238
1239class StopWatch {
1240public:
1241 void start();
1242 void stop();
1243 long getElapsedMS(); // call stop() first
1244
1245private:
1246 double m_startTime;
1247 double m_stopTime;
1248};
1249
1250void StopWatch::start()
1251{
1252 m_startTime = monotonicallyIncreasingTime();
1253}
1254
1255void StopWatch::stop()
1256{
1257 m_stopTime = monotonicallyIncreasingTime();
1258}
1259
1260long StopWatch::getElapsedMS()
1261{
1262 return static_cast<long>((m_stopTime - m_startTime) * 1000);
1263}
1264
1265template<typename Vector>
1266static inline String stringFromUTF(const Vector& utf8)
1267{
1268 return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
1269}
1270
1271template<typename Vector>
1272static inline SourceCode jscSource(const Vector& utf8, const SourceOrigin& sourceOrigin, const String& filename)
1273{
1274 String str = stringFromUTF(utf8);
1275 return makeSource(str, sourceOrigin, filename);
1276}
1277
1278class GlobalObject : public JSGlobalObject {
1279private:
1280 GlobalObject(VM&, Structure*);
1281
1282public:
1283 typedef JSGlobalObject Base;
1284
1285 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
1286 {
1287 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
1288 object->finishCreation(vm, arguments);
1289 return object;
1290 }
1291
1292 static const bool needsDestruction = false;
1293
1294 DECLARE_INFO;
1295 static const GlobalObjectMethodTable s_globalObjectMethodTable;
1296
1297 static Structure* createStructure(VM& vm, JSValue prototype)
1298 {
1299 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
1300 }
1301
1302 static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
1303
1304protected:
1305 void finishCreation(VM& vm, const Vector<String>& arguments)
1306 {
1307 Base::finishCreation(vm);
1308
1309 addFunction(vm, "debug", functionDebug, 1);
1310 addFunction(vm, "describe", functionDescribe, 1);
1311 addFunction(vm, "describeArray", functionDescribeArray, 1);
1312 addFunction(vm, "print", functionPrintStdOut, 1);
1313 addFunction(vm, "printErr", functionPrintStdErr, 1);
1314 addFunction(vm, "quit", functionQuit, 0);
1315 addFunction(vm, "abort", functionAbort, 0);
1316 addFunction(vm, "gc", functionGCAndSweep, 0);
1317 addFunction(vm, "fullGC", functionFullGC, 0);
1318 addFunction(vm, "edenGC", functionEdenGC, 0);
1319 addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
1320 addFunction(vm, "gcHeapSize", functionHeapSize, 0);
1321 addFunction(vm, "addressOf", functionAddressOf, 1);
1322 addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
1323#ifndef NDEBUG
1324 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
1325#endif
1326 addFunction(vm, "version", functionVersion, 1);
1327 addFunction(vm, "run", functionRun, 1);
1328 addFunction(vm, "runString", functionRunString, 1);
1329 addFunction(vm, "load", functionLoad, 1);
1330 addFunction(vm, "loadString", functionLoadString, 1);
1331 addFunction(vm, "readFile", functionReadFile, 2);
1332 addFunction(vm, "read", functionReadFile, 2);
1333 addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
1334 addFunction(vm, "sleepSeconds", functionSleepSeconds, 1);
1335 addFunction(vm, "jscStack", functionJSCStack, 1);
1336 addFunction(vm, "readline", functionReadline, 0);
1337 addFunction(vm, "preciseTime", functionPreciseTime, 0);
1338 addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
1339 addFunction(vm, "noInline", functionNeverInlineFunction, 1);
1340 addFunction(vm, "noDFG", functionNoDFG, 1);
1341 addFunction(vm, "noFTL", functionNoFTL, 1);
1342 addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
1343 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
1344 addFunction(vm, "jscOptions", functionJSCOptions, 0);
1345 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
1346 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
1347 addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
1348 addFunction(vm, "failNextNewCodeBlock", functionFailNextNewCodeBlock, 1);
1349#if ENABLE(SAMPLING_FLAGS)
1350 addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
1351 addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
1352#endif
1353 addFunction(vm, "shadowChickenFunctionsOnStack", functionShadowChickenFunctionsOnStack, 0);
1354 addFunction(vm, "setGlobalConstRedeclarationShouldNotThrow", functionSetGlobalConstRedeclarationShouldNotThrow, 0);
1355 addConstructableFunction(vm, "Root", functionCreateRoot, 0);
1356 addConstructableFunction(vm, "Element", functionCreateElement, 1);
1357 addFunction(vm, "getElement", functionGetElement, 1);
1358 addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
1359
1360 addConstructableFunction(vm, "SimpleObject", functionCreateSimpleObject, 0);
1361 addFunction(vm, "getHiddenValue", functionGetHiddenValue, 1);
1362 addFunction(vm, "setHiddenValue", functionSetHiddenValue, 2);
1363
1364 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum);
1365 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum);
1366 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum);
1367 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum);
1368 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum);
1369 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum);
1370
1371 addFunction(vm, "effectful42", functionEffectful42, 0);
1372 addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
1373 addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
1374
1375 addFunction(vm, "createProxy", functionCreateProxy, 1);
1376 addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
1377
1378 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
1379 addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
1380 addFunction(vm, "createDOMJITNodeObject", functionCreateDOMJITNodeObject, 0);
1381 addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0);
1382 addFunction(vm, "createDOMJITGetterComplexObject", functionCreateDOMJITGetterComplexObject, 0);
1383 addFunction(vm, "createDOMJITFunctionObject", functionCreateDOMJITFunctionObject, 0);
1384 addFunction(vm, "createDOMJITCheckSubClassObject", functionCreateDOMJITCheckSubClassObject, 0);
1385 addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
1386 addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
1387 addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
1388
1389 addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
1390 addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
1391 addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
1392
1393 addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
1394 addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
1395 addFunction(vm, "basicBlockExecutionCount", functionBasicBlockExecutionCount, 2);
1396
1397 addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
1398
1399 addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
1400
1401 addFunction(vm, "getRandomSeed", functionGetRandomSeed, 0);
1402 addFunction(vm, "setRandomSeed", functionSetRandomSeed, 1);
1403 addFunction(vm, "isRope", functionIsRope, 1);
1404 addFunction(vm, "callerSourceOrigin", functionCallerSourceOrigin, 0);
1405
1406 addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1);
1407
1408 addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
1409
1410 addFunction(vm, "loadModule", functionLoadModule, 1);
1411 addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
1412
1413 addFunction(vm, "platformSupportsSamplingProfiler", functionPlatformSupportsSamplingProfiler, 0);
1414 addFunction(vm, "generateHeapSnapshot", functionGenerateHeapSnapshot, 0);
1415 addFunction(vm, "resetSuperSamplerState", functionResetSuperSamplerState, 0);
1416 addFunction(vm, "ensureArrayStorage", functionEnsureArrayStorage, 0);
1417#if ENABLE(SAMPLING_PROFILER)
1418 addFunction(vm, "startSamplingProfiler", functionStartSamplingProfiler, 0);
1419 addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
1420#endif
1421
1422 addFunction(vm, "maxArguments", functionMaxArguments, 0);
1423
1424 addFunction(vm, "asyncTestStart", functionAsyncTestStart, 1);
1425 addFunction(vm, "asyncTestPassed", functionAsyncTestPassed, 1);
1426
1427#if ENABLE(WEBASSEMBLY)
1428 addFunction(vm, "WebAssemblyMemoryMode", functionWebAssemblyMemoryMode, 1);
1429#endif
1430
1431 if (!arguments.isEmpty()) {
1432 JSArray* array = constructEmptyArray(globalExec(), 0);
1433 for (size_t i = 0; i < arguments.size(); ++i)
1434 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
1435 putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
1436 }
1437
1438 putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
1439
1440 Structure* plainObjectStructure = JSFinalObject::createStructure(vm, this, objectPrototype(), 0);
1441
1442 JSObject* dollar = JSFinalObject::create(vm, plainObjectStructure);
1443 putDirect(vm, Identifier::fromString(globalExec(), "$"), dollar);
1444 putDirect(vm, Identifier::fromString(globalExec(), "$262"), dollar);
1445
1446 addFunction(vm, dollar, "createRealm", functionDollarCreateRealm, 0);
1447 addFunction(vm, dollar, "detachArrayBuffer", functionDollarDetachArrayBuffer, 1);
1448 addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1);
1449
1450 dollar->putDirect(vm, Identifier::fromString(globalExec(), "global"), this);
1451
1452 JSObject* agent = JSFinalObject::create(vm, plainObjectStructure);
1453 dollar->putDirect(vm, Identifier::fromString(globalExec(), "agent"), agent);
1454
1455 // The test262 INTERPRETING.md document says that some of these functions are just in the main
1456 // thread and some are in the other threads. We just put them in all threads.
1457 addFunction(vm, agent, "start", functionDollarAgentStart, 1);
1458 addFunction(vm, agent, "receiveBroadcast", functionDollarAgentReceiveBroadcast, 1);
1459 addFunction(vm, agent, "report", functionDollarAgentReport, 1);
1460 addFunction(vm, agent, "sleep", functionDollarAgentSleep, 1);
1461 addFunction(vm, agent, "broadcast", functionDollarAgentBroadcast, 1);
1462 addFunction(vm, agent, "getReport", functionDollarAgentGetReport, 0);
1463 addFunction(vm, agent, "leaving", functionDollarAgentLeaving, 0);
1464
1465 addFunction(vm, "waitForReport", functionWaitForReport, 0);
1466
1467 addFunction(vm, "heapCapacity", functionHeapCapacity, 0);
1468 addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
1469 }
1470
1471 void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
1472 {
1473 Identifier identifier = Identifier::fromString(&vm, name);
1474 object->putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
1475 }
1476
1477 void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
1478 {
1479 addFunction(vm, this, name, function, arguments);
1480 }
1481
1482 void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
1483 {
1484 Identifier identifier = Identifier::fromString(&vm, name);
1485 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
1486 }
1487
1488 static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, const SourceOrigin&);
1489 static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
1490 static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue);
1491};
1492
1493const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
1494const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
1495 &supportsRichSourceInfo,
1496 &shouldInterruptScript,
1497 &javaScriptRuntimeFlags,
1498 nullptr, // queueTaskToEventLoop
1499 &shouldInterruptScriptBeforeTimeout,
1500 &moduleLoaderImportModule,
1501 &moduleLoaderResolve,
1502 &moduleLoaderFetch,
1503 nullptr, // moduleLoaderInstantiate
1504 nullptr, // moduleLoaderEvaluate
1505 nullptr, // promiseRejectionTracker
1506 nullptr, // defaultLanguage
1507};
1508
1509GlobalObject::GlobalObject(VM& vm, Structure* structure)
1510 : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
1511{
1512}
1513
1514static UChar pathSeparator()
1515{
1516#if OS(WINDOWS)
1517 return '\\';
1518#else
1519 return '/';
1520#endif
1521}
1522
1523struct DirectoryName {
1524 // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
1525 String rootName;
1526
1527 // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
1528 String queryName;
1529};
1530
1531struct ModuleName {
1532 ModuleName(const String& moduleName);
1533
1534 bool startsWithRoot() const
1535 {
1536 return !queries.isEmpty() && queries[0].isEmpty();
1537 }
1538
1539 Vector<String> queries;
1540};
1541
1542ModuleName::ModuleName(const String& moduleName)
1543{
1544 // A module name given from code is represented as the UNIX style path. Like, `./A/B.js`.
1545 moduleName.split('/', true, queries);
1546}
1547
1548static std::optional<DirectoryName> extractDirectoryName(const String& absolutePathToFile)
1549{
1550 size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
1551 if (firstSeparatorPosition == notFound)
1552 return std::nullopt;
1553 DirectoryName directoryName;
1554 directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
1555 size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
1556 ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
1557 if (firstSeparatorPosition == lastSeparatorPosition)
1558 directoryName.queryName = StringImpl::empty();
1559 else {
1560 size_t queryStartPosition = firstSeparatorPosition + 1;
1561 size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
1562 directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
1563 }
1564 return directoryName;
1565}
1566
1567static std::optional<DirectoryName> currentWorkingDirectory()
1568{
1569#if OS(WINDOWS)
1570 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
1571 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
1572 // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
1573 // And other I/O functions taking a path name also truncate it. To avoid this situation,
1574 //
1575 // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
1576 // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
1577 //
1578 // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
1579 DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
1580 if (!bufferLength)
1581 return std::nullopt;
1582 // In Windows, wchar_t is the UTF-16LE.
1583 // https://msdn.microsoft.com/en-us/library/dd374081.aspx
1584 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
1585 auto buffer = std::make_unique<wchar_t[]>(bufferLength);
1586 DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.get());
1587 String directoryString = wcharToString(buffer.get(), lengthNotIncludingNull);
1588 // We don't support network path like \\host\share\<path name>.
1589 if (directoryString.startsWith("\\\\"))
1590 return std::nullopt;
1591#else
1592 auto buffer = std::make_unique<char[]>(PATH_MAX);
1593 if (!getcwd(buffer.get(), PATH_MAX))
1594 return std::nullopt;
1595 String directoryString = String::fromUTF8(buffer.get());
1596#endif
1597 if (directoryString.isEmpty())
1598 return std::nullopt;
1599
1600 if (directoryString[directoryString.length() - 1] == pathSeparator())
1601 return extractDirectoryName(directoryString);
1602 // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
1603 return extractDirectoryName(makeString(directoryString, pathSeparator()));
1604}
1605
1606static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
1607{
1608 Vector<String> directoryPieces;
1609 directoryName.queryName.split(pathSeparator(), false, directoryPieces);
1610
1611 // Only first '/' is recognized as the path from the root.
1612 if (moduleName.startsWithRoot())
1613 directoryPieces.clear();
1614
1615 for (const auto& query : moduleName.queries) {
1616 if (query == String(ASCIILiteral(".."))) {
1617 if (!directoryPieces.isEmpty())
1618 directoryPieces.removeLast();
1619 } else if (!query.isEmpty() && query != String(ASCIILiteral(".")))
1620 directoryPieces.append(query);
1621 }
1622
1623 StringBuilder builder;
1624 builder.append(directoryName.rootName);
1625 for (size_t i = 0; i < directoryPieces.size(); ++i) {
1626 builder.append(directoryPieces[i]);
1627 if (i + 1 != directoryPieces.size())
1628 builder.append(pathSeparator());
1629 }
1630 return builder.toString();
1631}
1632
1633static String absolutePath(const String& fileName)
1634{
1635 auto directoryName = currentWorkingDirectory();
1636 if (!directoryName)
1637 return fileName;
1638 return resolvePath(directoryName.value(), ModuleName(fileName.impl()));
1639}
1640
1641JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSString* moduleNameValue, const SourceOrigin& sourceOrigin)
1642{
1643 VM& vm = globalObject->vm();
1644 auto scope = DECLARE_CATCH_SCOPE(vm);
1645
1646 auto rejectPromise = [&] (JSValue error) {
1647 return JSInternalPromiseDeferred::create(exec, globalObject)->reject(exec, error);
1648 };
1649
1650 if (sourceOrigin.isNull())
1651 return rejectPromise(createError(exec, ASCIILiteral("Could not resolve the module specifier.")));
1652
1653 auto referrer = sourceOrigin.string();
1654 auto moduleName = moduleNameValue->value(exec);
1655 if (UNLIKELY(scope.exception())) {
1656 JSValue exception = scope.exception();
1657 scope.clearException();
1658 return rejectPromise(exception);
1659 }
1660
1661 auto directoryName = extractDirectoryName(referrer.impl());
1662 if (!directoryName)
1663 return rejectPromise(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
1664
1665 auto result = JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), jsUndefined());
1666 scope.releaseAssertNoException();
1667 return result;
1668}
1669
1670JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
1671{
1672 VM& vm = globalObject->vm();
1673 auto scope = DECLARE_CATCH_SCOPE(vm);
1674
1675 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1676 scope.releaseAssertNoException();
1677 const Identifier key = keyValue.toPropertyKey(exec);
1678 if (UNLIKELY(scope.exception())) {
1679 JSValue exception = scope.exception();
1680 scope.clearException();
1681 return deferred->reject(exec, exception);
1682 }
1683
1684 if (key.isSymbol()) {
1685 auto result = deferred->resolve(exec, keyValue);
1686 scope.releaseAssertNoException();
1687 return result;
1688 }
1689 if (referrerValue.isUndefined()) {
1690 auto directoryName = currentWorkingDirectory();
1691 if (!directoryName)
1692 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1693 auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
1694 scope.releaseAssertNoException();
1695 return result;
1696 }
1697
1698 const Identifier referrer = referrerValue.toPropertyKey(exec);
1699 if (UNLIKELY(scope.exception())) {
1700 JSValue exception = scope.exception();
1701 scope.clearException();
1702 return deferred->reject(exec, exception);
1703 }
1704
1705 if (referrer.isSymbol()) {
1706 auto directoryName = currentWorkingDirectory();
1707 if (!directoryName)
1708 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1709 auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
1710 scope.releaseAssertNoException();
1711 return result;
1712 }
1713
1714 // If the referrer exists, we assume that the referrer is the correct absolute path.
1715 auto directoryName = extractDirectoryName(referrer.impl());
1716 if (!directoryName)
1717 return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
1718 auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
1719 scope.releaseAssertNoException();
1720 return result;
1721}
1722
1723static void convertShebangToJSComment(Vector<char>& buffer)
1724{
1725 if (buffer.size() >= 2) {
1726 if (buffer[0] == '#' && buffer[1] == '!')
1727 buffer[0] = buffer[1] = '/';
1728 }
1729}
1730
1731static RefPtr<Uint8Array> fillBufferWithContentsOfFile(FILE* file)
1732{
1733 fseek(file, 0, SEEK_END);
1734 size_t bufferCapacity = ftell(file);
1735 fseek(file, 0, SEEK_SET);
1736 RefPtr<Uint8Array> result = Uint8Array::create(bufferCapacity);
1737 size_t readSize = fread(result->data(), 1, bufferCapacity, file);
1738 if (readSize != bufferCapacity)
1739 return nullptr;
1740 return result;
1741}
1742
1743static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName)
1744{
1745 FILE* f = fopen(fileName.utf8().data(), "rb");
1746 if (!f) {
1747 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1748 return nullptr;
1749 }
1750
1751 RefPtr<Uint8Array> result = fillBufferWithContentsOfFile(f);
1752 fclose(f);
1753
1754 return result;
1755}
1756
1757static bool fillBufferWithContentsOfFile(FILE* file, Vector<char>& buffer)
1758{
1759 // We might have injected "use strict"; at the top.
1760 size_t initialSize = buffer.size();
1761 fseek(file, 0, SEEK_END);
1762 size_t bufferCapacity = ftell(file);
1763 fseek(file, 0, SEEK_SET);
1764 buffer.resize(bufferCapacity + initialSize);
1765 size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
1766 return readSize == buffer.size() - initialSize;
1767}
1768
1769static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1770{
1771 FILE* f = fopen(fileName.utf8().data(), "rb");
1772 if (!f) {
1773 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1774 return false;
1775 }
1776
1777 bool result = fillBufferWithContentsOfFile(f, buffer);
1778 fclose(f);
1779
1780 return result;
1781}
1782
1783static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1784{
1785 if (!fillBufferWithContentsOfFile(fileName, buffer))
1786 return false;
1787 convertShebangToJSComment(buffer);
1788 return true;
1789}
1790
1791static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1792{
1793 // We assume that fileName is always an absolute path.
1794#if OS(WINDOWS)
1795 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
1796 // Use long UNC to pass the long path name to the Windows APIs.
1797 String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
1798 FILE* f = _wfopen(stringToNullTerminatedWChar(longUNCPathName).data(), L"rb");
1799#else
1800 FILE* f = fopen(fileName.utf8().data(), "r");
1801#endif
1802 if (!f) {
1803 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1804 return false;
1805 }
1806
1807 bool result = fillBufferWithContentsOfFile(f, buffer);
1808 if (result)
1809 convertShebangToJSComment(buffer);
1810 fclose(f);
1811
1812 return result;
1813}
1814
1815JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue)
1816{
1817 VM& vm = globalObject->vm();
1818 auto scope = DECLARE_CATCH_SCOPE(vm);
1819 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1820 String moduleKey = key.toWTFString(exec);
1821 if (UNLIKELY(scope.exception())) {
1822 JSValue exception = scope.exception();
1823 scope.clearException();
1824 return deferred->reject(exec, exception);
1825 }
1826
1827 // Here, now we consider moduleKey as the fileName.
1828 Vector<char> utf8;
1829 if (!fetchModuleFromLocalFileSystem(moduleKey, utf8))
1830 return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
1831
1832 auto result = deferred->resolve(exec, JSSourceCode::create(vm, makeSource(stringFromUTF(utf8), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
1833 scope.releaseAssertNoException();
1834 return result;
1835}
1836
1837
1838static EncodedJSValue printInternal(ExecState* exec, FILE* out)
1839{
1840 VM& vm = exec->vm();
1841 auto scope = DECLARE_THROW_SCOPE(vm);
1842
1843 if (asyncTestExpectedPasses) {
1844 JSValue value = exec->argument(0);
1845 if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete")) {
1846 asyncTestPasses++;
1847 return JSValue::encode(jsUndefined());
1848 }
1849 }
1850
1851 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1852 if (i)
1853 if (EOF == fputc(' ', out))
1854 goto fail;
1855
1856 auto viewWithString = exec->uncheckedArgument(i).toString(exec)->viewWithUnderlyingString(exec);
1857 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1858 if (fprintf(out, "%s", viewWithString.view.utf8().data()) < 0)
1859 goto fail;
1860 }
1861
1862 fputc('\n', out);
1863fail:
1864 fflush(out);
1865 return JSValue::encode(jsUndefined());
1866}
1867
1868EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState* exec) { return printInternal(exec, stdout); }
1869EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState* exec) { return printInternal(exec, stderr); }
1870
1871#ifndef NDEBUG
1872EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
1873{
1874 VM& vm = exec->vm();
1875 VMEntryFrame* topVMEntryFrame = vm.topVMEntryFrame;
1876 ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
1877 if (callerFrame)
1878 vm.interpreter->dumpCallFrame(callerFrame);
1879 return JSValue::encode(jsUndefined());
1880}
1881#endif
1882
1883EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
1884{
1885 VM& vm = exec->vm();
1886 auto scope = DECLARE_THROW_SCOPE(vm);
1887 auto viewWithString = exec->argument(0).toString(exec)->viewWithUnderlyingString(exec);
1888 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1889 fprintf(stderr, "--> %s\n", viewWithString.view.utf8().data());
1890 return JSValue::encode(jsUndefined());
1891}
1892
1893EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
1894{
1895 if (exec->argumentCount() < 1)
1896 return JSValue::encode(jsUndefined());
1897 return JSValue::encode(jsString(exec, toString(exec->argument(0))));
1898}
1899
1900EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
1901{
1902 if (exec->argumentCount() < 1)
1903 return JSValue::encode(jsUndefined());
1904 VM& vm = exec->vm();
1905 JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0));
1906 if (!object)
1907 return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
1908 return JSValue::encode(jsNontrivialString(exec, toString("<Butterfly: ", RawPointer(object->butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1909}
1910
1911EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState* exec)
1912{
1913 VM& vm = exec->vm();
1914 auto scope = DECLARE_THROW_SCOPE(vm);
1915
1916 if (exec->argumentCount() >= 1) {
1917 Seconds seconds = Seconds(exec->argument(0).toNumber(exec));
1918 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1919 sleep(seconds);
1920 }
1921
1922 return JSValue::encode(jsUndefined());
1923}
1924
1925class FunctionJSCStackFunctor {
1926public:
1927 FunctionJSCStackFunctor(StringBuilder& trace)
1928 : m_trace(trace)
1929 {
1930 }
1931
1932 StackVisitor::Status operator()(StackVisitor& visitor) const
1933 {
1934 m_trace.append(String::format(" %zu %s\n", visitor->index(), visitor->toString().utf8().data()));
1935 return StackVisitor::Continue;
1936 }
1937
1938private:
1939 StringBuilder& m_trace;
1940};
1941
1942EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
1943{
1944 StringBuilder trace;
1945 trace.appendLiteral("--> Stack trace:\n");
1946
1947 FunctionJSCStackFunctor functor(trace);
1948 exec->iterate(functor);
1949 fprintf(stderr, "%s", trace.toString().utf8().data());
1950 return JSValue::encode(jsUndefined());
1951}
1952
1953EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
1954{
1955 VM& vm = exec->vm();
1956 JSLockHolder lock(vm);
1957 return JSValue::encode(Root::create(vm, exec->lexicalGlobalObject()));
1958}
1959
1960EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
1961{
1962 VM& vm = exec->vm();
1963 JSLockHolder lock(vm);
1964 auto scope = DECLARE_THROW_SCOPE(vm);
1965
1966 Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1967 if (!root)
1968 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Cannot create Element without a Root."))));
1969 return JSValue::encode(Element::create(vm, exec->lexicalGlobalObject(), root));
1970}
1971
1972EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
1973{
1974 VM& vm = exec->vm();
1975 JSLockHolder lock(vm);
1976 Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1977 if (!root)
1978 return JSValue::encode(jsUndefined());
1979 Element* result = root->element();
1980 return JSValue::encode(result ? result : jsUndefined());
1981}
1982
1983EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
1984{
1985 VM& vm = exec->vm();
1986 JSLockHolder lock(vm);
1987 Element* element = jsDynamicCast<Element*>(vm, exec->argument(0));
1988 Root* root = jsDynamicCast<Root*>(vm, exec->argument(1));
1989 if (element && root)
1990 element->setRoot(vm, root);
1991 return JSValue::encode(jsUndefined());
1992}
1993
1994EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState* exec)
1995{
1996 VM& vm = exec->vm();
1997 JSLockHolder lock(vm);
1998 return JSValue::encode(SimpleObject::create(vm, exec->lexicalGlobalObject()));
1999}
2000
2001EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState* exec)
2002{
2003 VM& vm = exec->vm();
2004 JSLockHolder lock(vm);
2005 auto scope = DECLARE_THROW_SCOPE(vm);
2006
2007 SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
2008 if (UNLIKELY(!simpleObject)) {
2009 throwTypeError(exec, scope, ASCIILiteral("Invalid use of getHiddenValue test function"));
2010 return encodedJSValue();
2011 }
2012 return JSValue::encode(simpleObject->hiddenValue());
2013}
2014
2015EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState* exec)
2016{
2017 VM& vm = exec->vm();
2018 JSLockHolder lock(vm);
2019 auto scope = DECLARE_THROW_SCOPE(vm);
2020
2021 SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
2022 if (UNLIKELY(!simpleObject)) {
2023 throwTypeError(exec, scope, ASCIILiteral("Invalid use of setHiddenValue test function"));
2024 return encodedJSValue();
2025 }
2026 JSValue value = exec->argument(1);
2027 simpleObject->setHiddenValue(vm, value);
2028 return JSValue::encode(jsUndefined());
2029}
2030
2031EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
2032{
2033 VM& vm = exec->vm();
2034 JSLockHolder lock(vm);
2035 JSValue target = exec->argument(0);
2036 if (!target.isObject())
2037 return JSValue::encode(jsUndefined());
2038 JSObject* jsTarget = asObject(target.asCell());
2039 Structure* structure = JSProxy::createStructure(vm, exec->lexicalGlobalObject(), jsTarget->getPrototypeDirect(), ImpureProxyType);
2040 JSProxy* proxy = JSProxy::create(vm, structure, jsTarget);
2041 return JSValue::encode(proxy);
2042}
2043
2044EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
2045{
2046 JSLockHolder lock(exec);
2047 RuntimeArray* array = RuntimeArray::create(exec);
2048 return JSValue::encode(array);
2049}
2050
2051EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
2052{
2053 VM& vm = exec->vm();
2054 JSLockHolder lock(vm);
2055 JSValue target = exec->argument(0);
2056 JSObject* delegate = nullptr;
2057 if (target.isObject())
2058 delegate = asObject(target.asCell());
2059 Structure* structure = ImpureGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
2060 ImpureGetter* result = ImpureGetter::create(vm, structure, delegate);
2061 return JSValue::encode(result);
2062}
2063
2064EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState* exec)
2065{
2066 VM& vm = exec->vm();
2067 JSLockHolder lock(vm);
2068 Structure* structure = CustomGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
2069 CustomGetter* result = CustomGetter::create(vm, structure);
2070 return JSValue::encode(result);
2071}
2072
2073EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState* exec)
2074{
2075 VM& vm = exec->vm();
2076 JSLockHolder lock(vm);
2077 Structure* structure = DOMJITNode::createStructure(vm, exec->lexicalGlobalObject(), DOMJITGetter::create(vm, DOMJITGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull())));
2078 DOMJITNode* result = DOMJITNode::create(vm, structure);
2079 return JSValue::encode(result);
2080}
2081
2082EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState* exec)
2083{
2084 VM& vm = exec->vm();
2085 JSLockHolder lock(vm);
2086 Structure* structure = DOMJITGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
2087 DOMJITGetter* result = DOMJITGetter::create(vm, structure);
2088 return JSValue::encode(result);
2089}
2090
2091EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState* exec)
2092{
2093 VM& vm = exec->vm();
2094 JSLockHolder lock(vm);
2095 Structure* structure = DOMJITGetterComplex::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
2096 DOMJITGetterComplex* result = DOMJITGetterComplex::create(vm, exec->lexicalGlobalObject(), structure);
2097 return JSValue::encode(result);
2098}
2099
2100EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState* exec)
2101{
2102 VM& vm = exec->vm();
2103 JSLockHolder lock(vm);
2104 Structure* structure = DOMJITFunctionObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
2105 DOMJITFunctionObject* result = DOMJITFunctionObject::create(vm, exec->lexicalGlobalObject(), structure);
2106 return JSValue::encode(result);
2107}
2108
2109EncodedJSValue JSC_HOST_CALL functionCreateDOMJITCheckSubClassObject(ExecState* exec)
2110{
2111 VM& vm = exec->vm();
2112 JSLockHolder lock(vm);
2113 Structure* structure = DOMJITCheckSubClassObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
2114 DOMJITCheckSubClassObject* result = DOMJITCheckSubClassObject::create(vm, exec->lexicalGlobalObject(), structure);
2115 return JSValue::encode(result);
2116}
2117
2118EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
2119{
2120 VM& vm = exec->vm();
2121 JSLockHolder lock(vm);
2122 auto scope = DECLARE_THROW_SCOPE(vm);
2123
2124 JSValue base = exec->argument(0);
2125 if (!base.isObject())
2126 return JSValue::encode(jsUndefined());
2127 JSValue delegate = exec->argument(1);
2128 if (!delegate.isObject())
2129 return JSValue::encode(jsUndefined());
2130 ImpureGetter* impureGetter = jsDynamicCast<ImpureGetter*>(vm, asObject(base.asCell()));
2131 if (UNLIKELY(!impureGetter)) {
2132 throwTypeError(exec, scope, ASCIILiteral("argument is not an ImpureGetter"));
2133 return encodedJSValue();
2134 }
2135 impureGetter->setDelegate(vm, asObject(delegate.asCell()));
2136 return JSValue::encode(jsUndefined());
2137}
2138
2139EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
2140{
2141 VM& vm = exec->vm();
2142 JSLockHolder lock(vm);
2143 vm.heap.collectNow(Sync, CollectionScope::Full);
2144 return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
2145}
2146
2147EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
2148{
2149 VM& vm = exec->vm();
2150 JSLockHolder lock(vm);
2151 vm.heap.collectSync(CollectionScope::Full);
2152 return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
2153}
2154
2155EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
2156{
2157 VM& vm = exec->vm();
2158 JSLockHolder lock(vm);
2159 vm.heap.collectSync(CollectionScope::Eden);
2160 return JSValue::encode(jsNumber(vm.heap.sizeAfterLastEdenCollection()));
2161}
2162
2163EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*)
2164{
2165 // It's best for this to be the first thing called in the
2166 // JS program so the option is set to true before we JIT.
2167 Options::forceGCSlowPaths() = true;
2168 return JSValue::encode(jsUndefined());
2169}
2170
2171EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
2172{
2173 VM& vm = exec->vm();
2174 JSLockHolder lock(vm);
2175 return JSValue::encode(jsNumber(vm.heap.size()));
2176}
2177
2178// This function is not generally very helpful in 64-bit code as the tag and payload
2179// share a register. But in 32-bit JITed code the tag may not be checked if an
2180// optimization removes type checking requirements, such as in ===.
2181EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
2182{
2183 JSValue value = exec->argument(0);
2184 if (!value.isCell())
2185 return JSValue::encode(jsUndefined());
2186 // Need to cast to uint64_t so bitwise_cast will play along.
2187 uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
2188 EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
2189 return returnValue;
2190}
2191
2192static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
2193{
2194 JSValue value = exec->argument(0);
2195 if (!value.isObject())
2196 return JSValue::encode(jsUndefined());
2197
2198 JSValue property = exec->argument(1);
2199 if (!property.isString())
2200 return JSValue::encode(jsUndefined());
2201
2202 PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
2203 value.getPropertySlot(exec, asString(property)->toIdentifier(exec), slot);
2204
2205 JSValue result;
2206 if (slot.isCacheableGetter())
2207 result = slot.getterSetter();
2208 else
2209 result = jsNull();
2210
2211 return JSValue::encode(result);
2212}
2213
2214EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
2215{
2216 // We need this function for compatibility with the Mozilla JS tests but for now
2217 // we don't actually do any version-specific handling
2218 return JSValue::encode(jsUndefined());
2219}
2220
2221EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
2222{
2223 VM& vm = exec->vm();
2224 auto scope = DECLARE_THROW_SCOPE(vm);
2225
2226 String fileName = exec->argument(0).toWTFString(exec);
2227 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2228 Vector<char> script;
2229 if (!fetchScriptFromLocalFileSystem(fileName, script))
2230 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
2231
2232 GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
2233
2234 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
2235 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2236 for (unsigned i = 1; i < exec->argumentCount(); ++i) {
2237 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
2238 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2239 }
2240 globalObject->putDirect(
2241 vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
2242
2243 NakedPtr<Exception> exception;
2244 StopWatch stopWatch;
2245 stopWatch.start();
2246 evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), exception);
2247 stopWatch.stop();
2248
2249 if (exception) {
2250 throwException(globalObject->globalExec(), scope, exception);
2251 return JSValue::encode(jsUndefined());
2252 }
2253
2254 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2255}
2256
2257EncodedJSValue JSC_HOST_CALL functionRunString(ExecState* exec)
2258{
2259 VM& vm = exec->vm();
2260 auto scope = DECLARE_THROW_SCOPE(vm);
2261
2262 String source = exec->argument(0).toWTFString(exec);
2263 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2264
2265 GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
2266
2267 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
2268 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2269 for (unsigned i = 1; i < exec->argumentCount(); ++i) {
2270 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
2271 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2272 }
2273 globalObject->putDirect(
2274 vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
2275
2276 NakedPtr<Exception> exception;
2277 evaluate(globalObject->globalExec(), makeSource(source, exec->callerSourceOrigin()), JSValue(), exception);
2278
2279 if (exception) {
2280 scope.throwException(globalObject->globalExec(), exception);
2281 return JSValue::encode(jsUndefined());
2282 }
2283
2284 return JSValue::encode(globalObject);
2285}
2286
2287EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
2288{
2289 VM& vm = exec->vm();
2290 auto scope = DECLARE_THROW_SCOPE(vm);
2291
2292 String fileName = exec->argument(0).toWTFString(exec);
2293 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2294 Vector<char> script;
2295 if (!fetchScriptFromLocalFileSystem(fileName, script))
2296 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
2297
2298 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2299
2300 NakedPtr<Exception> evaluationException;
2301 JSValue result = evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
2302 if (evaluationException)
2303 throwException(exec, scope, evaluationException);
2304 return JSValue::encode(result);
2305}
2306
2307EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
2308{
2309 VM& vm = exec->vm();
2310 auto scope = DECLARE_THROW_SCOPE(vm);
2311
2312 String sourceCode = exec->argument(0).toWTFString(exec);
2313 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2314 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2315
2316 NakedPtr<Exception> evaluationException;
2317 JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
2318 if (evaluationException)
2319 throwException(exec, scope, evaluationException);
2320 return JSValue::encode(result);
2321}
2322
2323EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
2324{
2325 VM& vm = exec->vm();
2326 auto scope = DECLARE_THROW_SCOPE(vm);
2327
2328 String fileName = exec->argument(0).toWTFString(exec);
2329 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2330
2331 bool isBinary = false;
2332 if (exec->argumentCount() > 1) {
2333 String type = exec->argument(1).toWTFString(exec);
2334 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2335 if (type != "binary")
2336 return throwVMError(exec, scope, "Expected 'binary' as second argument.");
2337 isBinary = true;
2338 }
2339
2340 RefPtr<Uint8Array> content = fillBufferWithContentsOfFile(fileName);
2341 if (!content)
2342 return throwVMError(exec, scope, "Could not open file.");
2343
2344 if (!isBinary)
2345 return JSValue::encode(jsString(exec, String::fromUTF8WithLatin1Fallback(content->data(), content->length())));
2346
2347 Structure* structure = exec->lexicalGlobalObject()->typedArrayStructure(TypeUint8);
2348 JSObject* result = JSUint8Array::create(vm, structure, WTFMove(content));
2349 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2350
2351 return JSValue::encode(result);
2352}
2353
2354EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
2355{
2356 VM& vm = exec->vm();
2357 auto scope = DECLARE_THROW_SCOPE(vm);
2358
2359 String fileName = exec->argument(0).toWTFString(exec);
2360 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2361 Vector<char> script;
2362 if (!fetchScriptFromLocalFileSystem(fileName, script))
2363 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
2364
2365 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2366
2367 StopWatch stopWatch;
2368 stopWatch.start();
2369
2370 JSValue syntaxException;
2371 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), &syntaxException);
2372 stopWatch.stop();
2373
2374 if (!validSyntax)
2375 throwException(exec, scope, syntaxException);
2376 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2377}
2378
2379#if ENABLE(SAMPLING_FLAGS)
2380EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
2381{
2382 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
2383 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
2384 if ((flag >= 1) && (flag <= 32))
2385 SamplingFlags::setFlag(flag);
2386 }
2387 return JSValue::encode(jsNull());
2388}
2389
2390EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
2391{
2392 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
2393 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
2394 if ((flag >= 1) && (flag <= 32))
2395 SamplingFlags::clearFlag(flag);
2396 }
2397 return JSValue::encode(jsNull());
2398}
2399#endif
2400
2401EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState* exec)
2402{
2403 VM& vm = exec->vm();
2404 return JSValue::encode(vm.shadowChicken().functionsOnStack(exec));
2405}
2406
2407EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState* exec)
2408{
2409 VM& vm = exec->vm();
2410 vm.setGlobalConstRedeclarationShouldThrow(false);
2411 return JSValue::encode(jsUndefined());
2412}
2413
2414EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState* exec)
2415{
2416 return JSValue::encode(jsNumber(exec->lexicalGlobalObject()->weakRandom().seed()));
2417}
2418
2419EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState* exec)
2420{
2421 VM& vm = exec->vm();
2422 auto scope = DECLARE_THROW_SCOPE(vm);
2423
2424 unsigned seed = exec->argument(0).toUInt32(exec);
2425 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2426 exec->lexicalGlobalObject()->weakRandom().setSeed(seed);
2427 return JSValue::encode(jsUndefined());
2428}
2429
2430EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState* exec)
2431{
2432 JSValue argument = exec->argument(0);
2433 if (!argument.isString())
2434 return JSValue::encode(jsBoolean(false));
2435 const StringImpl* impl = asString(argument)->tryGetValueImpl();
2436 return JSValue::encode(jsBoolean(!impl));
2437}
2438
2439EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState* state)
2440{
2441 SourceOrigin sourceOrigin = state->callerSourceOrigin();
2442 if (sourceOrigin.isNull())
2443 return JSValue::encode(jsNull());
2444 return JSValue::encode(jsString(state, sourceOrigin.string()));
2445}
2446
2447EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState* exec)
2448{
2449 JSValue value = exec->argument(0);
2450 RELEASE_ASSERT(value.isObject());
2451 JSGlobalObject* globalObject = jsCast<JSObject*>(value)->globalObject();
2452 RELEASE_ASSERT(globalObject);
2453 return JSValue::encode(globalObject);
2454}
2455
2456EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
2457{
2458 Vector<char, 256> line;
2459 int c;
2460 while ((c = getchar()) != EOF) {
2461 // FIXME: Should we also break on \r?
2462 if (c == '\n')
2463 break;
2464 line.append(c);
2465 }
2466 line.append('\0');
2467 return JSValue::encode(jsString(exec, line.data()));
2468}
2469
2470EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
2471{
2472 return JSValue::encode(jsNumber(currentTime()));
2473}
2474
2475EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
2476{
2477 return JSValue::encode(setNeverInline(exec));
2478}
2479
2480EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
2481{
2482 return JSValue::encode(setNeverOptimize(exec));
2483}
2484
2485EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState* exec)
2486{
2487 VM& vm = exec->vm();
2488 if (JSFunction* function = jsDynamicCast<JSFunction*>(vm, exec->argument(0))) {
2489 FunctionExecutable* executable = function->jsExecutable();
2490 executable->setNeverFTLOptimize(true);
2491 }
2492
2493 return JSValue::encode(jsUndefined());
2494}
2495
2496EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState* exec)
2497{
2498 return JSValue::encode(setCannotUseOSRExitFuzzing(exec));
2499}
2500
2501EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
2502{
2503 return JSValue::encode(optimizeNextInvocation(exec));
2504}
2505
2506EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
2507{
2508 return JSValue::encode(numberOfDFGCompiles(exec));
2509}
2510
2511Message::Message(ArrayBufferContents&& contents, int32_t index)
2512 : m_contents(WTFMove(contents))
2513 , m_index(index)
2514{
2515}
2516
2517Message::~Message()
2518{
2519}
2520
2521Worker::Worker(Workers& workers)
2522 : m_workers(workers)
2523{
2524 auto locker = holdLock(m_workers.m_lock);
2525 m_workers.m_workers.append(this);
2526
2527 *currentWorker() = this;
2528}
2529
2530Worker::~Worker()
2531{
2532 auto locker = holdLock(m_workers.m_lock);
2533 RELEASE_ASSERT(isOnList());
2534 remove();
2535}
2536
2537void Worker::enqueue(const AbstractLocker&, RefPtr<Message> message)
2538{
2539 m_messages.append(message);
2540}
2541
2542RefPtr<Message> Worker::dequeue()
2543{
2544 auto locker = holdLock(m_workers.m_lock);
2545 while (m_messages.isEmpty())
2546 m_workers.m_condition.wait(m_workers.m_lock);
2547 return m_messages.takeFirst();
2548}
2549
2550Worker& Worker::current()
2551{
2552 return **currentWorker();
2553}
2554
2555ThreadSpecific<Worker*>& Worker::currentWorker()
2556{
2557 static ThreadSpecific<Worker*>* result;
2558 static std::once_flag flag;
2559 std::call_once(
2560 flag,
2561 [] () {
2562 result = new ThreadSpecific<Worker*>();
2563 });
2564 return *result;
2565}
2566
2567Workers::Workers()
2568{
2569}
2570
2571Workers::~Workers()
2572{
2573 UNREACHABLE_FOR_PLATFORM();
2574}
2575
2576template<typename Func>
2577void Workers::broadcast(const Func& func)
2578{
2579 auto locker = holdLock(m_lock);
2580 for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
2581 if (worker != &Worker::current())
2582 func(locker, *worker);
2583 }
2584 m_condition.notifyAll();
2585}
2586
2587void Workers::report(String string)
2588{
2589 auto locker = holdLock(m_lock);
2590 m_reports.append(string.isolatedCopy());
2591 m_condition.notifyAll();
2592}
2593
2594String Workers::tryGetReport()
2595{
2596 auto locker = holdLock(m_lock);
2597 if (m_reports.isEmpty())
2598 return String();
2599 return m_reports.takeFirst();
2600}
2601
2602String Workers::getReport()
2603{
2604 auto locker = holdLock(m_lock);
2605 while (m_reports.isEmpty())
2606 m_condition.wait(m_lock);
2607 return m_reports.takeFirst();
2608}
2609
2610Workers& Workers::singleton()
2611{
2612 static Workers* result;
2613 static std::once_flag flag;
2614 std::call_once(
2615 flag,
2616 [] {
2617 result = new Workers();
2618 });
2619 return *result;
2620}
2621
2622EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState* exec)
2623{
2624 VM& vm = exec->vm();
2625 GlobalObject* result = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
2626 return JSValue::encode(result->getDirect(vm, Identifier::fromString(exec, "$")));
2627}
2628
2629EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState* exec)
2630{
2631 return functionTransferArrayBuffer(exec);
2632}
2633
2634EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState* exec)
2635{
2636 VM& vm = exec->vm();
2637 auto scope = DECLARE_THROW_SCOPE(vm);
2638
2639 String sourceCode = exec->argument(0).toWTFString(exec);
2640 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2641
2642 GlobalObject* globalObject = jsDynamicCast<GlobalObject*>(vm,
2643 exec->thisValue().get(exec, Identifier::fromString(exec, "global")));
2644 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2645 if (!globalObject)
2646 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected global to point to a global object"))));
2647
2648 NakedPtr<Exception> evaluationException;
2649 JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
2650 if (evaluationException)
2651 throwException(exec, scope, evaluationException);
2652 return JSValue::encode(result);
2653}
2654
2655EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState* exec)
2656{
2657 VM& vm = exec->vm();
2658 auto scope = DECLARE_THROW_SCOPE(vm);
2659
2660 String sourceCode = exec->argument(0).toWTFString(exec).isolatedCopy();
2661 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2662
2663 Lock didStartLock;
2664 Condition didStartCondition;
2665 bool didStart = false;
2666
2667 RefPtr<Thread> thread = Thread::create(
2668 "JSC Agent",
2669 [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
2670 CommandLine commandLine(0, nullptr);
2671 commandLine.m_interactive = false;
2672 runJSC(
2673 commandLine, true,
2674 [&] (VM&, GlobalObject* globalObject) {
2675 // Notify the thread that started us that we have registered a worker.
2676 {
2677 auto locker = holdLock(didStartLock);
2678 didStart = true;
2679 didStartCondition.notifyOne();
2680 }
2681
2682 NakedPtr<Exception> evaluationException;
2683 bool success = true;
2684 JSValue result;
2685 result = evaluate(globalObject->globalExec(), makeSource(sourceCode, SourceOrigin(ASCIILiteral("worker"))), JSValue(), evaluationException);
2686 if (evaluationException)
2687 result = evaluationException->value();
2688 checkException(globalObject, true, evaluationException, result, commandLine, success);
2689 if (!success)
2690 exit(1);
2691 return success;
2692 });
2693 });
2694 thread->detach();
2695
2696 {
2697 auto locker = holdLock(didStartLock);
2698 while (!didStart)
2699 didStartCondition.wait(didStartLock);
2700 }
2701
2702 return JSValue::encode(jsUndefined());
2703}
2704
2705EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec)
2706{
2707 VM& vm = exec->vm();
2708 auto scope = DECLARE_THROW_SCOPE(vm);
2709
2710 JSValue callback = exec->argument(0);
2711 CallData callData;
2712 CallType callType = getCallData(callback, callData);
2713 if (callType == CallType::None)
2714 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected callback"))));
2715
2716 RefPtr<Message> message;
2717 {
2718 ReleaseHeapAccessScope releaseAccess(vm.heap);
2719 message = Worker::current().dequeue();
2720 }
2721
2722 RefPtr<ArrayBuffer> nativeBuffer = ArrayBuffer::create(message->releaseContents());
2723 ArrayBufferSharingMode sharingMode = nativeBuffer->sharingMode();
2724 JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(sharingMode), WTFMove(nativeBuffer));
2725
2726 MarkedArgumentBuffer args;
2727 args.append(jsBuffer);
2728 args.append(jsNumber(message->index()));
2729 scope.release();
2730 return JSValue::encode(call(exec, callback, callType, callData, jsNull(), args));
2731}
2732
2733EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState* exec)
2734{
2735 VM& vm = exec->vm();
2736 auto scope = DECLARE_THROW_SCOPE(vm);
2737
2738 String report = exec->argument(0).toWTFString(exec);
2739 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2740
2741 Workers::singleton().report(report);
2742
2743 return JSValue::encode(jsUndefined());
2744}
2745
2746EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState* exec)
2747{
2748 VM& vm = exec->vm();
2749 auto scope = DECLARE_THROW_SCOPE(vm);
2750
2751 if (exec->argumentCount() >= 1) {
2752 Seconds seconds = Seconds::fromMilliseconds(exec->argument(0).toNumber(exec));
2753 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2754 sleep(seconds);
2755 }
2756 return JSValue::encode(jsUndefined());
2757}
2758
2759EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState* exec)
2760{
2761 VM& vm = exec->vm();
2762 auto scope = DECLARE_THROW_SCOPE(vm);
2763
2764 JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
2765 if (!jsBuffer || !jsBuffer->isShared())
2766 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected SharedArrayBuffer"))));
2767
2768 int32_t index = exec->argument(1).toInt32(exec);
2769 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2770
2771 Workers::singleton().broadcast(
2772 [&] (const AbstractLocker& locker, Worker& worker) {
2773 ArrayBuffer* nativeBuffer = jsBuffer->impl();
2774 ArrayBufferContents contents;
2775 nativeBuffer->transferTo(vm, contents); // "transferTo" means "share" if the buffer is shared.
2776 RefPtr<Message> message = adoptRef(new Message(WTFMove(contents), index));
2777 worker.enqueue(locker, message);
2778 });
2779
2780 return JSValue::encode(jsUndefined());
2781}
2782
2783EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState* exec)
2784{
2785 VM& vm = exec->vm();
2786
2787 String string = Workers::singleton().tryGetReport();
2788 if (!string)
2789 return JSValue::encode(jsNull());
2790
2791 return JSValue::encode(jsString(&vm, string));
2792}
2793
2794EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*)
2795{
2796 return JSValue::encode(jsUndefined());
2797}
2798
2799EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState* exec)
2800{
2801 VM& vm = exec->vm();
2802
2803 String string;
2804 {
2805 ReleaseHeapAccessScope releaseAccess(vm.heap);
2806 string = Workers::singleton().getReport();
2807 }
2808 if (!string)
2809 return JSValue::encode(jsNull());
2810
2811 return JSValue::encode(jsString(&vm, string));
2812}
2813
2814EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState* exec)
2815{
2816 VM& vm = exec->vm();
2817 return JSValue::encode(jsNumber(vm.heap.capacity()));
2818}
2819
2820EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState* exec)
2821{
2822 VM& vm = exec->vm();
2823 auto scope = DECLARE_THROW_SCOPE(vm);
2824
2825 vm.heap.releaseAccess();
2826 if (exec->argumentCount() >= 1) {
2827 double ms = exec->argument(0).toNumber(exec);
2828 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2829 sleep(Seconds::fromMilliseconds(ms));
2830 }
2831 vm.heap.acquireAccess();
2832 return JSValue::encode(jsUndefined());
2833}
2834
2835template<typename ValueType>
2836typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
2837
2838template<typename ValueType>
2839typename std::enable_if<std::is_fundamental<ValueType>::value>::type addOption(VM& vm, JSObject* optionsObject, Identifier identifier, ValueType value)
2840{
2841 optionsObject->putDirect(vm, identifier, JSValue(value));
2842}
2843
2844EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState* exec)
2845{
2846 VM& vm = exec->vm();
2847 JSObject* optionsObject = constructEmptyObject(exec);
2848#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
2849 addOption(vm, optionsObject, Identifier::fromString(exec, #name_), Options::name_());
2850 JSC_OPTIONS(FOR_EACH_OPTION)
2851#undef FOR_EACH_OPTION
2852 return JSValue::encode(optionsObject);
2853}
2854
2855EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
2856{
2857 if (exec->argumentCount() < 1)
2858 return JSValue::encode(jsUndefined());
2859
2860 CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
2861 if (!block)
2862 return JSValue::encode(jsNumber(0));
2863
2864 return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
2865}
2866
2867EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
2868{
2869 VM& vm = exec->vm();
2870 auto scope = DECLARE_THROW_SCOPE(vm);
2871
2872 if (exec->argumentCount() < 1)
2873 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Not enough arguments"))));
2874
2875 JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
2876 if (!buffer)
2877 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected an array buffer"))));
2878
2879 ArrayBufferContents dummyContents;
2880 buffer->impl()->transferTo(vm, dummyContents);
2881
2882 return JSValue::encode(jsUndefined());
2883}
2884
2885EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState* exec)
2886{
2887 VM& vm = exec->vm();
2888 vm.setFailNextNewCodeBlock();
2889 return JSValue::encode(jsUndefined());
2890}
2891
2892EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
2893{
2894 jscExit(EXIT_SUCCESS);
2895
2896#if COMPILER(MSVC)
2897 // Without this, Visual Studio will complain that this method does not return a value.
2898 return JSValue::encode(jsUndefined());
2899#endif
2900}
2901
2902EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*)
2903{
2904 CRASH();
2905}
2906
2907EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
2908EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
2909
2910EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
2911EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
2912EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
2913{
2914 for (size_t i = 0; i < exec->argumentCount(); ++i) {
2915 if (!exec->argument(i).isInt32())
2916 return JSValue::encode(jsBoolean(false));
2917 }
2918 return JSValue::encode(jsBoolean(true));
2919}
2920
2921EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
2922
2923EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
2924{
2925 return JSValue::encode(jsNumber(42));
2926}
2927
2928EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
2929{
2930 VM& vm = exec->vm();
2931 return JSValue::encode(Masquerader::create(vm, exec->lexicalGlobalObject()));
2932}
2933
2934EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
2935{
2936 JSValue value = exec->argument(0);
2937 if (value.isObject())
2938 return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
2939 return JSValue::encode(jsBoolean(false));
2940}
2941
2942EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
2943{
2944 VM& vm = exec->vm();
2945 vm.dumpTypeProfilerData();
2946 return JSValue::encode(jsUndefined());
2947}
2948
2949EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
2950{
2951 VM& vm = exec->vm();
2952 RELEASE_ASSERT(vm.typeProfiler());
2953 vm.typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
2954
2955 JSValue functionValue = exec->argument(0);
2956 RELEASE_ASSERT(functionValue.isFunction());
2957 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2958
2959 RELEASE_ASSERT(exec->argument(1).isString());
2960 String substring = asString(exec->argument(1))->value(exec);
2961 String sourceCodeText = executable->source().view().toString();
2962 unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
2963
2964 String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), vm);
2965 return JSValue::encode(JSONParse(exec, jsonString));
2966}
2967
2968EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
2969{
2970 VM& vm = exec->vm();
2971 RELEASE_ASSERT(vm.typeProfiler());
2972 vm.typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
2973
2974 JSValue functionValue = exec->argument(0);
2975 RELEASE_ASSERT(functionValue.isFunction());
2976 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2977
2978 unsigned offset = executable->typeProfilingStartOffset();
2979 String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), vm);
2980 return JSValue::encode(JSONParse(exec, jsonString));
2981}
2982
2983EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
2984{
2985 VM& vm = exec->vm();
2986 RELEASE_ASSERT(vm.controlFlowProfiler());
2987 vm.controlFlowProfiler()->dumpData();
2988 return JSValue::encode(jsUndefined());
2989}
2990
2991EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
2992{
2993 VM& vm = exec->vm();
2994 RELEASE_ASSERT(vm.controlFlowProfiler());
2995
2996 JSValue functionValue = exec->argument(0);
2997 RELEASE_ASSERT(functionValue.isFunction());
2998 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2999
3000 RELEASE_ASSERT(exec->argument(1).isString());
3001 String substring = asString(exec->argument(1))->value(exec);
3002 String sourceCodeText = executable->source().view().toString();
3003 RELEASE_ASSERT(sourceCodeText.contains(substring));
3004 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
3005
3006 bool hasExecuted = vm.controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), vm);
3007 return JSValue::encode(jsBoolean(hasExecuted));
3008}
3009
3010EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState* exec)
3011{
3012 VM& vm = exec->vm();
3013 RELEASE_ASSERT(vm.controlFlowProfiler());
3014
3015 JSValue functionValue = exec->argument(0);
3016 RELEASE_ASSERT(functionValue.isFunction());
3017 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
3018
3019 RELEASE_ASSERT(exec->argument(1).isString());
3020 String substring = asString(exec->argument(1))->value(exec);
3021 String sourceCodeText = executable->source().view().toString();
3022 RELEASE_ASSERT(sourceCodeText.contains(substring));
3023 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
3024
3025 size_t executionCount = vm.controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), vm);
3026 return JSValue::encode(JSValue(executionCount));
3027}
3028
3029EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
3030{
3031 Options::useExceptionFuzz() = true;
3032 return JSValue::encode(jsUndefined());
3033}
3034
3035EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
3036{
3037 VM& vm = exec->vm();
3038 vm.drainMicrotasks();
3039 return JSValue::encode(jsUndefined());
3040}
3041
3042EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*)
3043{
3044#if USE(JSVALUE64)
3045 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
3046#else
3047 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
3048#endif
3049}
3050
3051EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
3052{
3053 VM& vm = exec->vm();
3054 auto scope = DECLARE_THROW_SCOPE(vm);
3055
3056 String fileName = exec->argument(0).toWTFString(exec);
3057 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3058 Vector<char> script;
3059 if (!fetchScriptFromLocalFileSystem(fileName, script))
3060 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
3061
3062 JSInternalPromise* promise = loadAndEvaluateModule(exec, fileName);
3063 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3064
3065 JSValue error;
3066 JSFunction* errorHandler = JSNativeStdFunction::create(vm, exec->lexicalGlobalObject(), 1, String(), [&](ExecState* exec) {
3067 error = exec->argument(0);
3068 return JSValue::encode(jsUndefined());
3069 });
3070
3071 promise->then(exec, nullptr, errorHandler);
3072 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3073 vm.drainMicrotasks();
3074 if (error)
3075 return JSValue::encode(throwException(exec, scope, error));
3076 return JSValue::encode(jsUndefined());
3077}
3078
3079EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
3080{
3081 VM& vm = exec->vm();
3082 auto scope = DECLARE_THROW_SCOPE(vm);
3083
3084 if (exec->argumentCount() < 1 || !exec->argument(0).isString())
3085 return JSValue::encode(jsUndefined());
3086
3087 String functionText = asString(exec->argument(0))->value(exec);
3088 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3089
3090 const SourceCode& source = makeSource(functionText, { });
3091 JSFunction* func = JSFunction::create(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
3092
3093 return JSValue::encode(func);
3094}
3095
3096EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState* exec)
3097{
3098 VM& vm = exec->vm();
3099 return JSValue::encode(GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>()));
3100}
3101
3102EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
3103{
3104 VM& vm = exec->vm();
3105 auto scope = DECLARE_THROW_SCOPE(vm);
3106
3107 String source = exec->argument(0).toWTFString(exec);
3108 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3109
3110 StopWatch stopWatch;
3111 stopWatch.start();
3112
3113 ParserError error;
3114 bool validSyntax = checkModuleSyntax(exec, makeSource(source, { }, String(), TextPosition(), SourceProviderSourceType::Module), error);
3115 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3116 stopWatch.stop();
3117
3118 if (!validSyntax)
3119 throwException(exec, scope, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
3120 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
3121}
3122
3123EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*)
3124{
3125#if ENABLE(SAMPLING_PROFILER)
3126 return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
3127#else
3128 return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
3129#endif
3130}
3131
3132EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
3133{
3134 VM& vm = exec->vm();
3135 JSLockHolder lock(vm);
3136 auto scope = DECLARE_THROW_SCOPE(vm);
3137
3138 HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler());
3139 snapshotBuilder.buildSnapshot();
3140
3141 String jsonString = snapshotBuilder.json();
3142 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
3143 scope.releaseAssertNoException();
3144 return result;
3145}
3146
3147EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*)
3148{
3149 resetSuperSamplerState();
3150 return JSValue::encode(jsUndefined());
3151}
3152
3153EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState* exec)
3154{
3155 VM& vm = exec->vm();
3156 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
3157 if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0)))
3158 object->ensureArrayStorage(vm);
3159 }
3160 return JSValue::encode(jsUndefined());
3161}
3162
3163#if ENABLE(SAMPLING_PROFILER)
3164EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState* exec)
3165{
3166 VM& vm = exec->vm();
3167 SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
3168 samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
3169 samplingProfiler.start();
3170 return JSValue::encode(jsUndefined());
3171}
3172
3173EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec)
3174{
3175 VM& vm = exec->vm();
3176 auto scope = DECLARE_THROW_SCOPE(vm);
3177
3178 if (!vm.samplingProfiler())
3179 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Sampling profiler was never started"))));
3180
3181 String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
3182 EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
3183 scope.releaseAssertNoException();
3184 return result;
3185}
3186#endif // ENABLE(SAMPLING_PROFILER)
3187
3188EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*)
3189{
3190 return JSValue::encode(jsNumber(JSC::maxArguments));
3191}
3192
3193EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState* exec)
3194{
3195 VM& vm = exec->vm();
3196 auto scope = DECLARE_THROW_SCOPE(vm);
3197
3198 JSValue numberOfAsyncPasses = exec->argument(0);
3199 if (!numberOfAsyncPasses.isUInt32())
3200 return throwVMError(exec, scope, ASCIILiteral("Expected first argument to a uint32"));
3201
3202 asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32();
3203 return encodedJSUndefined();
3204}
3205
3206EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*)
3207{
3208 asyncTestPasses++;
3209 return encodedJSUndefined();
3210}
3211
3212#if ENABLE(WEBASSEMBLY)
3213
3214static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState* exec)
3215{
3216 VM& vm = exec->vm();
3217 auto scope = DECLARE_THROW_SCOPE(vm);
3218
3219 if (!Options::useWebAssembly())
3220 return throwVMTypeError(exec, scope, ASCIILiteral("WebAssemblyMemoryMode should only be called if the useWebAssembly option is set"));
3221
3222 if (JSObject* object = exec->argument(0).getObject()) {
3223 if (auto* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, object))
3224 return JSValue::encode(jsString(&vm, makeString(memory->memory().mode())));
3225 if (auto* instance = jsDynamicCast<JSWebAssemblyInstance*>(vm, object))
3226 return JSValue::encode(jsString(&vm, makeString(instance->memoryMode())));
3227 }
3228
3229 return throwVMTypeError(exec, scope, ASCIILiteral("WebAssemblyMemoryMode expects either a WebAssembly.Memory or WebAssembly.Instance"));
3230}
3231
3232#endif // ENABLE(WEBASSEBLY)
3233
3234// Use SEH for Release builds only to get rid of the crash report dialog
3235// (luckily the same tests fail in Release and Debug builds so far). Need to
3236// be in a separate main function because the jscmain function requires object
3237// unwinding.
3238
3239#if COMPILER(MSVC) && !defined(_DEBUG)
3240#define TRY __try {
3241#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
3242#else
3243#define TRY
3244#define EXCEPT(x)
3245#endif
3246
3247int jscmain(int argc, char** argv);
3248
3249static double s_desiredTimeout;
3250static double s_timeoutMultiplier = 1.0;
3251
3252static void startTimeoutThreadIfNeeded()
3253{
3254 if (char* timeoutString = getenv("JSCTEST_timeout")) {
3255 if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
3256 dataLog("WARNING: timeout string is malformed, got ", timeoutString,
3257 " but expected a number. Not using a timeout.\n");
3258 } else {
3259 Thread::create("jsc Timeout Thread", [] () {
3260 Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier);
3261 sleep(timeoutDuration);
3262 dataLog("Timed out after ", timeoutDuration, " seconds!\n");
3263 CRASH();
3264 });
3265 }
3266 }
3267}
3268
3269int main(int argc, char** argv)
3270{
3271#if PLATFORM(IOS) && CPU(ARM_THUMB2)
3272 // Enabled IEEE754 denormal support.
3273 fenv_t env;
3274 fegetenv( &env );
3275 env.__fpscr &= ~0x01000000u;
3276 fesetenv( &env );
3277#endif
3278
3279#if OS(WINDOWS)
3280 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
3281 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
3282 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
3283 ::SetErrorMode(0);
3284
3285#if defined(_DEBUG)
3286 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3287 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
3288 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3289 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
3290 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3291 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
3292#endif
3293
3294 timeBeginPeriod(1);
3295#endif
3296
3297#if PLATFORM(GTK)
3298 if (!setlocale(LC_ALL, ""))
3299 WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
3300#endif
3301
3302 // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
3303 // threading yet, since that would do somethings that we'd like to defer until after we
3304 // have a chance to parse options.
3305 WTF::initializeThreading();
3306
3307#if PLATFORM(IOS)
3308 Options::crashIfCantAllocateJITMemory() = true;
3309#endif
3310
3311 // We can't use destructors in the following code because it uses Windows
3312 // Structured Exception Handling
3313 int res = 0;
3314 TRY
3315 res = jscmain(argc, argv);
3316 EXCEPT(res = 3)
3317 finalizeStatsAtEndOfTesting();
3318
3319 jscExit(res);
3320}
3321
3322static void dumpException(GlobalObject* globalObject, JSValue exception)
3323{
3324 VM& vm = globalObject->vm();
3325 auto scope = DECLARE_CATCH_SCOPE(vm);
3326
3327#define CHECK_EXCEPTION() do { \
3328 if (scope.exception()) { \
3329 scope.clearException(); \
3330 return; \
3331 } \
3332 } while (false)
3333
3334 printf("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data());
3335
3336 Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
3337 CHECK_EXCEPTION();
3338 Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
3339 CHECK_EXCEPTION();
3340 Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
3341 CHECK_EXCEPTION();
3342 Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
3343 CHECK_EXCEPTION();
3344
3345 JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
3346 CHECK_EXCEPTION();
3347 JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
3348 CHECK_EXCEPTION();
3349 JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
3350 CHECK_EXCEPTION();
3351 JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
3352 CHECK_EXCEPTION();
3353
3354 if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
3355 && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
3356 printf(
3357 "at %s:%s\n",
3358 fileNameValue.toWTFString(globalObject->globalExec()).utf8().data(),
3359 lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
3360 }
3361
3362 if (!stackValue.isUndefinedOrNull()) {
3363 auto stackString = stackValue.toWTFString(globalObject->globalExec());
3364 if (stackString.length())
3365 printf("%s\n", stackString.utf8().data());
3366 }
3367
3368#undef CHECK_EXCEPTION
3369}
3370
3371static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, CommandLine& options)
3372{
3373 const String& expectedExceptionName = options.m_uncaughtExceptionName;
3374 auto scope = DECLARE_CATCH_SCOPE(vm);
3375 scope.clearException();
3376 if (!exception) {
3377 printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
3378 return false;
3379 }
3380
3381 ExecState* exec = globalObject->globalExec();
3382 JSValue exceptionClass = globalObject->get(exec, Identifier::fromString(exec, expectedExceptionName));
3383 if (!exceptionClass.isObject() || scope.exception()) {
3384 printf("Expected uncaught exception with name '%s' but given exception class is not defined\n", expectedExceptionName.utf8().data());
3385 return false;
3386 }
3387
3388 bool isInstanceOfExpectedException = jsCast<JSObject*>(exceptionClass)->hasInstance(exec, exception);
3389 if (scope.exception()) {
3390 printf("Expected uncaught exception with name '%s' but given exception class fails performing hasInstance\n", expectedExceptionName.utf8().data());
3391 return false;
3392 }
3393 if (isInstanceOfExpectedException) {
3394 if (options.m_alwaysDumpUncaughtException)
3395 dumpException(globalObject, exception);
3396 return true;
3397 }
3398
3399 printf("Expected uncaught exception with name '%s' but exception value is not instance of this exception class\n", expectedExceptionName.utf8().data());
3400 dumpException(globalObject, exception);
3401 return false;
3402}
3403
3404static void checkException(GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, CommandLine& options, bool& success)
3405{
3406 VM& vm = globalObject->vm();
3407
3408 if (options.m_treatWatchdogExceptionAsSuccess && value.inherits(vm, TerminatedExecutionError::info())) {
3409 ASSERT(hasException);
3410 return;
3411 }
3412
3413 if (!options.m_uncaughtExceptionName || !isLastFile) {
3414 success = success && !hasException;
3415 if (options.m_dump && !hasException)
3416 printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
3417 if (hasException)
3418 dumpException(globalObject, value);
3419 } else
3420 success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), options);
3421}
3422
3423static bool runWithOptions(GlobalObject* globalObject, CommandLine& options)
3424{
3425 Vector<Script>& scripts = options.m_scripts;
3426 String fileName;
3427 Vector<char> scriptBuffer;
3428
3429 if (options.m_dump)
3430 JSC::Options::dumpGeneratedBytecodes() = true;
3431
3432 VM& vm = globalObject->vm();
3433 auto scope = DECLARE_CATCH_SCOPE(vm);
3434 bool success = true;
3435
3436#if ENABLE(SAMPLING_FLAGS)
3437 SamplingFlags::start();
3438#endif
3439
3440 for (size_t i = 0; i < scripts.size(); i++) {
3441 JSInternalPromise* promise = nullptr;
3442 bool isModule = options.m_module || scripts[i].scriptType == Script::ScriptType::Module;
3443 if (scripts[i].codeSource == Script::CodeSource::File) {
3444 fileName = scripts[i].argument;
3445 if (scripts[i].strictMode == Script::StrictMode::Strict)
3446 scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
3447
3448 if (isModule) {
3449 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName);
3450 scope.releaseAssertNoException();
3451 } else {
3452 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer))
3453 return false; // fail early so we can catch missing files
3454 }
3455 } else {
3456 size_t commandLineLength = strlen(scripts[i].argument);
3457 scriptBuffer.resize(commandLineLength);
3458 std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
3459 fileName = ASCIILiteral("[Command Line]");
3460 }
3461
3462 bool isLastFile = i == scripts.size() - 1;
3463 if (isModule) {
3464 if (!promise)
3465 promise = loadAndEvaluateModule(globalObject->globalExec(), makeSource(stringFromUTF(scriptBuffer), SourceOrigin { absolutePath(fileName) }, fileName, TextPosition(), SourceProviderSourceType::Module));
3466 scope.clearException();
3467
3468 JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
3469 checkException(globalObject, isLastFile, false, exec->argument(0), options, success);
3470 return JSValue::encode(jsUndefined());
3471 });
3472
3473 JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
3474 checkException(globalObject, isLastFile, true, exec->argument(0), options, success);
3475 return JSValue::encode(jsUndefined());
3476 });
3477
3478 promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
3479 scope.releaseAssertNoException();
3480 vm.drainMicrotasks();
3481 } else {
3482 NakedPtr<Exception> evaluationException;
3483 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
3484 scope.assertNoException();
3485 if (evaluationException)
3486 returnValue = evaluationException->value();
3487 checkException(globalObject, isLastFile, evaluationException, returnValue, options, success);
3488 }
3489
3490 scriptBuffer.clear();
3491 scope.clearException();
3492 }
3493
3494#if ENABLE(REGEXP_TRACING)
3495 vm.dumpRegExpTrace();
3496#endif
3497 return success;
3498}
3499
3500#define RUNNING_FROM_XCODE 0
3501
3502static void runInteractive(GlobalObject* globalObject)
3503{
3504 VM& vm = globalObject->vm();
3505 auto scope = DECLARE_CATCH_SCOPE(vm);
3506
3507 std::optional<DirectoryName> directoryName = currentWorkingDirectory();
3508 if (!directoryName)
3509 return;
3510 SourceOrigin sourceOrigin(resolvePath(directoryName.value(), ModuleName("interpreter")));
3511
3512 bool shouldQuit = false;
3513 while (!shouldQuit) {
3514#if HAVE(READLINE) && !RUNNING_FROM_XCODE
3515 ParserError error;
3516 String source;
3517 do {
3518 error = ParserError();
3519 char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
3520 shouldQuit = !line;
3521 if (!line)
3522 break;
3523 source = source + line;
3524 source = source + '\n';
3525 checkSyntax(vm, makeSource(source, sourceOrigin), error);
3526 if (!line[0]) {
3527 free(line);
3528 break;
3529 }
3530 add_history(line);
3531 free(line);
3532 } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
3533
3534 if (error.isValid()) {
3535 printf("%s:%d\n", error.message().utf8().data(), error.line());
3536 continue;
3537 }
3538
3539
3540 NakedPtr<Exception> evaluationException;
3541 JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, sourceOrigin), JSValue(), evaluationException);
3542#else
3543 printf("%s", interactivePrompt);
3544 Vector<char, 256> line;
3545 int c;
3546 while ((c = getchar()) != EOF) {
3547 // FIXME: Should we also break on \r?
3548 if (c == '\n')
3549 break;
3550 line.append(c);
3551 }
3552 if (line.isEmpty())
3553 break;
3554
3555 NakedPtr<Exception> evaluationException;
3556 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, sourceOrigin, sourceOrigin.string()), JSValue(), evaluationException);
3557#endif
3558 if (evaluationException)
3559 printf("Exception: %s\n", evaluationException->value().toWTFString(globalObject->globalExec()).utf8().data());
3560 else
3561 printf("%s\n", returnValue.toWTFString(globalObject->globalExec()).utf8().data());
3562
3563 scope.clearException();
3564 vm.drainMicrotasks();
3565 }
3566 printf("\n");
3567}
3568
3569static NO_RETURN void printUsageStatement(bool help = false)
3570{
3571 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
3572 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
3573 fprintf(stderr, " -e Evaluate argument as script code\n");
3574 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
3575 fprintf(stderr, " -h|--help Prints this help message\n");
3576 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
3577 fprintf(stderr, " -m Execute as a module\n");
3578#if HAVE(SIGNAL_H)
3579 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
3580#endif
3581 fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
3582 fprintf(stderr, " -x Output exit code before terminating\n");
3583 fprintf(stderr, "\n");
3584 fprintf(stderr, " --sample Collects and outputs sampling profiler data\n");
3585 fprintf(stderr, " --test262-async Check that some script calls the print function with the string 'Test262:AsyncTestComplete'\n");
3586 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");
3587 fprintf(stderr, " --module-file=<file> Parse and evaluate the given file as module (this option may be passed more than once)\n");
3588 fprintf(stderr, " --exception=<name> Check the last script exits with an uncaught exception with the specified name\n");
3589 fprintf(stderr, " --watchdog-exception-ok Uncaught watchdog exceptions exit with success\n");
3590 fprintf(stderr, " --dumpException Dump uncaught exception text\n");
3591 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
3592 fprintf(stderr, " --dumpOptions Dumps all non-default JSC VM options before continuing\n");
3593 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
3594 fprintf(stderr, "\n");
3595
3596 jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
3597}
3598
3599void CommandLine::parseArguments(int argc, char** argv)
3600{
3601 Options::initialize();
3602
3603 if (Options::dumpOptions()) {
3604 printf("Command line:");
3605#if PLATFORM(COCOA)
3606 for (char** envp = *_NSGetEnviron(); *envp; envp++) {
3607 const char* env = *envp;
3608 if (!strncmp("JSC_", env, 4))
3609 printf(" %s", env);
3610 }
3611#endif // PLATFORM(COCOA)
3612 for (int i = 0; i < argc; ++i)
3613 printf(" %s", argv[i]);
3614 printf("\n");
3615 }
3616
3617 int i = 1;
3618 JSC::Options::DumpLevel dumpOptionsLevel = JSC::Options::DumpLevel::None;
3619 bool needToExit = false;
3620
3621 bool hasBadJSCOptions = false;
3622 for (; i < argc; ++i) {
3623 const char* arg = argv[i];
3624 if (!strcmp(arg, "-f")) {
3625 if (++i == argc)
3626 printUsageStatement();
3627 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
3628 continue;
3629 }
3630 if (!strcmp(arg, "-e")) {
3631 if (++i == argc)
3632 printUsageStatement();
3633 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::CommandLine, Script::ScriptType::Script, argv[i]));
3634 continue;
3635 }
3636 if (!strcmp(arg, "-i")) {
3637 m_interactive = true;
3638 continue;
3639 }
3640 if (!strcmp(arg, "-d")) {
3641 m_dump = true;
3642 continue;
3643 }
3644 if (!strcmp(arg, "-p")) {
3645 if (++i == argc)
3646 printUsageStatement();
3647 m_profile = true;
3648 m_profilerOutput = argv[i];
3649 continue;
3650 }
3651 if (!strcmp(arg, "-m")) {
3652 m_module = true;
3653 continue;
3654 }
3655 if (!strcmp(arg, "-s")) {
3656#if HAVE(SIGNAL_H)
3657 signal(SIGILL, _exit);
3658 signal(SIGFPE, _exit);
3659 signal(SIGBUS, _exit);
3660 signal(SIGSEGV, _exit);
3661#endif
3662 continue;
3663 }
3664 if (!strcmp(arg, "-x")) {
3665 m_exitCode = true;
3666 continue;
3667 }
3668 if (!strcmp(arg, "--")) {
3669 ++i;
3670 break;
3671 }
3672 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
3673 printUsageStatement(true);
3674
3675 if (!strcmp(arg, "--options")) {
3676 dumpOptionsLevel = JSC::Options::DumpLevel::Verbose;
3677 needToExit = true;
3678 continue;
3679 }
3680 if (!strcmp(arg, "--dumpOptions")) {
3681 dumpOptionsLevel = JSC::Options::DumpLevel::Overridden;
3682 continue;
3683 }
3684 if (!strcmp(arg, "--sample")) {
3685 JSC::Options::useSamplingProfiler() = true;
3686 JSC::Options::collectSamplingProfilerDataForJSCShell() = true;
3687 m_dumpSamplingProfilerData = true;
3688 continue;
3689 }
3690
3691 static const char* timeoutMultiplierOptStr = "--timeoutMultiplier=";
3692 static const unsigned timeoutMultiplierOptStrLength = strlen(timeoutMultiplierOptStr);
3693 if (!strncmp(arg, timeoutMultiplierOptStr, timeoutMultiplierOptStrLength)) {
3694 const char* valueStr = &arg[timeoutMultiplierOptStrLength];
3695 if (sscanf(valueStr, "%lf", &s_timeoutMultiplier) != 1)
3696 dataLog("WARNING: --timeoutMultiplier=", valueStr, " is invalid. Expects a numeric ratio.\n");
3697 continue;
3698 }
3699
3700 if (!strcmp(arg, "--test262-async")) {
3701 asyncTestExpectedPasses++;
3702 continue;
3703 }
3704
3705 if (!strcmp(arg, "--remote-debug")) {
3706 m_enableRemoteDebugging = true;
3707 continue;
3708 }
3709
3710 static const unsigned strictFileStrLength = strlen("--strict-file=");
3711 if (!strncmp(arg, "--strict-file=", strictFileStrLength)) {
3712 m_scripts.append(Script(Script::StrictMode::Strict, Script::CodeSource::File, Script::ScriptType::Script, argv[i] + strictFileStrLength));
3713 continue;
3714 }
3715
3716 static const unsigned moduleFileStrLength = strlen("--module-file=");
3717 if (!strncmp(arg, "--module-file=", moduleFileStrLength)) {
3718 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Module, argv[i] + moduleFileStrLength));
3719 continue;
3720 }
3721
3722 if (!strcmp(arg, "--dumpException")) {
3723 m_alwaysDumpUncaughtException = true;
3724 continue;
3725 }
3726
3727 static const unsigned exceptionStrLength = strlen("--exception=");
3728 if (!strncmp(arg, "--exception=", exceptionStrLength)) {
3729 m_uncaughtExceptionName = String(arg + exceptionStrLength);
3730 continue;
3731 }
3732
3733 if (!strcmp(arg, "--watchdog-exception-ok")) {
3734 m_treatWatchdogExceptionAsSuccess = true;
3735 continue;
3736 }
3737
3738 // See if the -- option is a JSC VM option.
3739 if (strstr(arg, "--") == arg) {
3740 if (!JSC::Options::setOption(&arg[2])) {
3741 hasBadJSCOptions = true;
3742 dataLog("ERROR: invalid option: ", arg, "\n");
3743 }
3744 continue;
3745 }
3746
3747 // This arg is not recognized by the VM nor by jsc. Pass it on to the
3748 // script.
3749 m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
3750 }
3751
3752 if (hasBadJSCOptions && JSC::Options::validateOptions())
3753 CRASH();
3754
3755 if (m_scripts.isEmpty())
3756 m_interactive = true;
3757
3758 for (; i < argc; ++i)
3759 m_arguments.append(argv[i]);
3760
3761 if (dumpOptionsLevel != JSC::Options::DumpLevel::None) {
3762 const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
3763 ? "Modified JSC runtime options:"
3764 : "All JSC runtime options:";
3765 JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
3766 }
3767 JSC::Options::ensureOptionsAreCoherent();
3768 if (needToExit)
3769 jscExit(EXIT_SUCCESS);
3770}
3771
3772template<typename Func>
3773int runJSC(CommandLine options, bool isWorker, const Func& func)
3774{
3775 Worker worker(Workers::singleton());
3776
3777 VM& vm = VM::create(LargeHeap).leakRef();
3778 int result;
3779 bool success;
3780 {
3781 JSLockHolder locker(vm);
3782
3783 if (options.m_profile && !vm.m_perBytecodeProfiler)
3784 vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm);
3785
3786 GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
3787 globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
3788 success = func(vm, globalObject);
3789 if (options.m_interactive && success)
3790 runInteractive(globalObject);
3791
3792 vm.drainMicrotasks();
3793 }
3794 vm.promiseDeferredTimer->runRunLoop();
3795
3796 result = success && (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3;
3797
3798 if (options.m_exitCode) {
3799 printf("jsc exiting %d", result);
3800 if (asyncTestExpectedPasses != asyncTestPasses)
3801 printf(" because expected: %d async test passes but got: %d async test passes", asyncTestExpectedPasses, asyncTestPasses);
3802 printf("\n");
3803 }
3804
3805 if (options.m_profile) {
3806 JSLockHolder locker(vm);
3807 if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
3808 fprintf(stderr, "could not save profiler output.\n");
3809 }
3810
3811#if ENABLE(JIT)
3812 {
3813 JSLockHolder locker(vm);
3814 if (Options::useExceptionFuzz())
3815 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
3816 bool fireAtEnabled =
3817 Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
3818 if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
3819 printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
3820 if (Options::useOSRExitFuzz()) {
3821 printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
3822 printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
3823 }
3824
3825
3826 auto compileTimeStats = JIT::compileTimeStats();
3827 Vector<CString> compileTimeKeys;
3828 for (auto& entry : compileTimeStats)
3829 compileTimeKeys.append(entry.key);
3830 std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
3831 for (CString key : compileTimeKeys)
3832 printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
3833 }
3834#endif
3835
3836 if (Options::gcAtEnd()) {
3837 // We need to hold the API lock to do a GC.
3838 JSLockHolder locker(&vm);
3839 vm.heap.collectNow(Sync, CollectionScope::Full);
3840 }
3841
3842 if (options.m_dumpSamplingProfilerData) {
3843#if ENABLE(SAMPLING_PROFILER)
3844 JSLockHolder locker(&vm);
3845 vm.samplingProfiler()->reportTopFunctions();
3846 vm.samplingProfiler()->reportTopBytecodes();
3847#else
3848 dataLog("Sampling profiler is not enabled on this platform\n");
3849#endif
3850 }
3851
3852 if (isWorker) {
3853 JSLockHolder locker(vm);
3854 // This is needed because we don't want the worker's main
3855 // thread to die before its compilation threads finish.
3856 vm.deref();
3857 }
3858
3859 return result;
3860}
3861
3862int jscmain(int argc, char** argv)
3863{
3864 // Need to override and enable restricted options before we start parsing options below.
3865 Options::enableRestrictedOptions(true);
3866
3867 // Note that the options parsing can affect VM creation, and thus
3868 // comes first.
3869 CommandLine options(argc, argv);
3870
3871 processConfigFile(Options::configFile(), "jsc");
3872
3873 // Initialize JSC before getting VM.
3874 WTF::initializeMainThread();
3875 JSC::initializeThreading();
3876 startTimeoutThreadIfNeeded();
3877#if ENABLE(WEBASSEMBLY)
3878 JSC::Wasm::enableFastMemory();
3879#endif
3880 Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled();
3881
3882 int result;
3883 result = runJSC(
3884 options, false,
3885 [&] (VM&, GlobalObject* globalObject) {
3886 return runWithOptions(globalObject, options);
3887 });
3888
3889 printSuperSamplerState();
3890
3891 return result;
3892}
3893
3894#if OS(WINDOWS)
3895extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
3896{
3897 return main(argc, const_cast<char**>(argv));
3898}
3899#endif
Note: See TracBrowser for help on using the repository browser.