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

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

Enable JSC restricted options by default in the jsc shell.
https://bugs.webkit.org/show_bug.cgi?id=165615

Reviewed by Keith Miller.

The jsc shell is only used for debugging and development testing. We should
allow it to use restricted options like JSC_useDollarVM even for release builds.

  • jsc.cpp:

(jscmain):

  • runtime/Options.cpp:

(JSC::Options::enableRestrictedOptions):
(JSC::Options::isAvailable):
(JSC::allowRestrictedOptions): Deleted.

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