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

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

Assertion failed under operationToLowerCase with a rope with zero length
https://bugs.webkit.org/show_bug.cgi?id=163314

Reviewed by Mark Lam.

JSTests:

  • stress/to-lower-case-intrinsic-on-empty-rope.js: Added.

(assert):
(returnRope.helper):
(returnRope):
(lower):

Source/JavaScriptCore:

There are some ways to get JSC to create empty rope strings. ToLowerCase
inside the DFG/FTL goes to the slow path when the argument is a rope.
operationToLowerCase was calling into a WTF string function that
assumed we are passing it a this value that has non-zero length.
However, we were calling it with a string that did have zero length.
To fix this, we make operationToLowerCase return the empty JSString
if it is going to make a string with zero length.

  • dfg/DFGOperations.cpp:
  • jsc.cpp:

(GlobalObject::finishCreation):
(functionIsRope):

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