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

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

WebAssembly JS API: implement importing and defining Memory
https://bugs.webkit.org/show_bug.cgi?id=164134

Reviewed by Keith Miller.

JSTests:

  • wasm/Builder.js:

(const._importMemoryContinuation.section):
(const._importMemoryContinuation.assert):
(const._importMemoryContinuation):
(const._exportFunctionContinuation.const): Deleted.
(const._exportFunctionContinuation): Deleted.

  • wasm/Builder_WebAssemblyBinary.js:

(const.emitters.Import):

  • wasm/js-api/test_basic_api.js:

(const.c.in.constructorProperties.switch):

  • wasm/js-api/test_memory.js: Added.

(assert):
(binaryShouldNotParse):
(test):
(test.testMemImportError):

  • wasm/js-api/test_memory_constructor.js: Added.

(assert):
(throw.new.Error):
(testInvalidSize):
(assert.testInvalidInitial):
(testInvalidInitial.testInvalidMaximum):
(testInvalidInitial):
(testInvalidMaximum):

  • wasm/self-test/test_BuilderJSON.js:

Source/JavaScriptCore:

This patch implements the WebAssembly.Memory object. It refactors
the code to now associate a Memory with the instance instead of
the Module.

(functionTestWasmModuleFunctions):

  • runtime/VM.h:
  • shell/CMakeLists.txt:
  • testWasm.cpp: Removed.

This has bitrotted. I'm removing it.

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::sizeOfLoadOp):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):

  • wasm/WasmB3IRGenerator.h:
  • wasm/WasmFormat.cpp:

(JSC::Wasm::ModuleInformation::~ModuleInformation): Deleted.

  • wasm/WasmFormat.h:
  • wasm/WasmMemory.cpp:

(JSC::Wasm::Memory::Memory):

  • wasm/WasmMemory.h:

(JSC::Wasm::Memory::size):
(JSC::Wasm::Memory::initial):
(JSC::Wasm::Memory::maximum):
(JSC::Wasm::Memory::pinnedRegisters): Deleted.

  • wasm/WasmMemoryInformation.cpp: Added.

(JSC::Wasm::MemoryInformation::MemoryInformation):

  • wasm/WasmMemoryInformation.h: Added.

(JSC::Wasm::MemoryInformation::MemoryInformation):
(JSC::Wasm::MemoryInformation::pinnedRegisters):
(JSC::Wasm::MemoryInformation::initial):
(JSC::Wasm::MemoryInformation::maximum):
(JSC::Wasm::MemoryInformation::isImport):
(JSC::Wasm::MemoryInformation::operator bool):

  • wasm/WasmModuleParser.cpp:

(JSC::Wasm::ModuleParser::parseImport):
(JSC::Wasm::ModuleParser::parseMemoryHelper):
(JSC::Wasm::ModuleParser::parseMemory):
(JSC::Wasm::ModuleParser::parseExport):

  • wasm/WasmModuleParser.h:
  • wasm/WasmPageCount.h: Added. Implement a new way of describing Wasm

pages and then asking for how many bytes a quantity of pages is. This
class also makes it clear when we're talking about bytes or pages.

(JSC::Wasm::PageCount::PageCount):
(JSC::Wasm::PageCount::bytes):
(JSC::Wasm::PageCount::isValid):
(JSC::Wasm::PageCount::max):
(JSC::Wasm::PageCount::operator bool):
(JSC::Wasm::PageCount::operator<):
(JSC::Wasm::PageCount::operator>):
(JSC::Wasm::PageCount::operator>=):

  • wasm/WasmPlan.cpp:

(JSC::Wasm::Plan::run):

  • wasm/WasmPlan.h:

(JSC::Wasm::Plan::memory): Deleted.

  • wasm/WasmValidate.cpp:

(JSC::Wasm::Validate::hasMemory):
(JSC::Wasm::Validate::Validate):
(JSC::Wasm::validateFunction):

  • wasm/WasmValidate.h:
  • wasm/generateWasmValidateInlinesHeader.py:
  • wasm/js/JSWebAssemblyInstance.cpp:

(JSC::JSWebAssemblyInstance::visitChildren):

  • wasm/js/JSWebAssemblyInstance.h:

(JSC::JSWebAssemblyInstance::memory):
(JSC::JSWebAssemblyInstance::setMemory):
(JSC::JSWebAssemblyInstance::offsetOfImportFunctions):
(JSC::JSWebAssemblyInstance::allocationSize):

  • wasm/js/JSWebAssemblyMemory.cpp:

(JSC::JSWebAssemblyMemory::create):
(JSC::JSWebAssemblyMemory::JSWebAssemblyMemory):
(JSC::JSWebAssemblyMemory::buffer):
(JSC::JSWebAssemblyMemory::visitChildren):

  • wasm/js/JSWebAssemblyMemory.h:

(JSC::JSWebAssemblyMemory::memory):

  • wasm/js/WebAssemblyFunction.cpp:

(JSC::callWebAssemblyFunction):

  • wasm/js/WebAssemblyInstanceConstructor.cpp:

Handle importing and creating of memory according
to the spec. This also does the needed validation
of making sure the memory defined in the module
is compatible with the imported memory.

(JSC::constructJSWebAssemblyInstance):

  • wasm/js/WebAssemblyMemoryConstructor.cpp:

(JSC::constructJSWebAssemblyMemory):
(JSC::callJSWebAssemblyMemory):

  • wasm/js/WebAssemblyMemoryPrototype.cpp:

(JSC::webAssemblyMemoryProtoFuncBuffer):
(JSC::WebAssemblyMemoryPrototype::create):
(JSC::WebAssemblyMemoryPrototype::finishCreation):

  • wasm/js/WebAssemblyMemoryPrototype.h:
  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::finishCreation):
(JSC::WebAssemblyModuleRecord::link):

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