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

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

jsc.cpp is leaking memory allocated by readline in runInteractive
https://bugs.webkit.org/show_bug.cgi?id=163958

According to http://web.mit.edu/gnu/doc/html/rlman_2.html,
"The line readline returns is allocated with malloc ();
you should free () the line when you are done with it."
The memory allocated by readline is not being freed when it should.

Patch by Christopher Reid <[email protected]> on 2016-10-25
Reviewed by Mark Lam.

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