[JSC] Remove gcc warnings on mips and armv7
[WebKit-https.git] / Source / JavaScriptCore / tools / JSDollarVM.cpp
1 /*
2  * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSDollarVM.h"
28
29 #include "BuiltinExecutableCreator.h"
30 #include "CodeBlock.h"
31 #include "DOMAttributeGetterSetter.h"
32 #include "DOMJITGetterSetter.h"
33 #include "FrameTracers.h"
34 #include "FunctionCodeBlock.h"
35 #include "GetterSetter.h"
36 #include "JSArray.h"
37 #include "JSArrayBuffer.h"
38 #include "JSCInlines.h"
39 #include "JSFunction.h"
40 #include "JSONObject.h"
41 #include "JSProxy.h"
42 #include "JSString.h"
43 #include "ShadowChicken.h"
44 #include "Snippet.h"
45 #include "SnippetParams.h"
46 #include "TypeProfiler.h"
47 #include "TypeProfilerLog.h"
48 #include "VMInspector.h"
49 #include <wtf/Atomics.h>
50 #include <wtf/DataLog.h>
51 #include <wtf/ProcessID.h>
52 #include <wtf/StringPrintStream.h>
53
54 #if ENABLE(WEBASSEMBLY)
55 #include "JSWebAssemblyHelpers.h"
56 #include "WasmStreamingParser.h"
57 #endif
58
59 using namespace JSC;
60 using namespace WTF;
61
62 namespace {
63
64 class JSDollarVMCallFrame : public JSDestructibleObject {
65     using Base = JSDestructibleObject;
66 public:
67     JSDollarVMCallFrame(VM& vm, Structure* structure)
68         : Base(vm, structure)
69     { }
70
71     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
72     {
73         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
74     }
75
76     static JSDollarVMCallFrame* create(ExecState* exec, unsigned requestedFrameIndex)
77     {
78         VM& vm = exec->vm();
79         JSGlobalObject* globalObject = exec->lexicalGlobalObject();
80         Structure* structure = createStructure(vm, globalObject, jsNull());
81         JSDollarVMCallFrame* frame = new (NotNull, allocateCell<JSDollarVMCallFrame>(vm.heap, sizeof(JSDollarVMCallFrame))) JSDollarVMCallFrame(vm, structure);
82         frame->finishCreation(vm, exec, requestedFrameIndex);
83         return frame;
84     }
85
86     void finishCreation(VM& vm, CallFrame* frame, unsigned requestedFrameIndex)
87     {
88         Base::finishCreation(vm);
89
90         auto addProperty = [&] (VM& vm, const char* name, JSValue value) {
91             JSDollarVMCallFrame::addProperty(vm, name, value);
92         };
93
94         unsigned frameIndex = 0;
95         bool isValid = false;
96         frame->iterate([&] (StackVisitor& visitor) {
97
98             if (frameIndex++ != requestedFrameIndex)
99                 return StackVisitor::Continue;
100
101             addProperty(vm, "name", jsString(&vm, visitor->functionName()));
102
103             if (visitor->callee().isCell())
104                 addProperty(vm, "callee", visitor->callee().asCell());
105
106             CodeBlock* codeBlock = visitor->codeBlock();
107             if (codeBlock) {
108                 addProperty(vm, "codeBlock", codeBlock);
109                 addProperty(vm, "unlinkedCodeBlock", codeBlock->unlinkedCodeBlock());
110                 addProperty(vm, "executable", codeBlock->ownerExecutable());
111             }
112             isValid = true;
113
114             return StackVisitor::Done;
115         });
116
117         addProperty(vm, "valid", jsBoolean(isValid));
118     }
119
120     DECLARE_INFO;
121
122 private:
123     void addProperty(VM& vm, const char* name, JSValue value)
124     {
125         Identifier identifier = Identifier::fromString(&vm, name);
126         putDirect(vm, identifier, value);
127     }
128 };
129
130 const ClassInfo JSDollarVMCallFrame::s_info = { "CallFrame", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVMCallFrame) };
131
132 class ElementHandleOwner;
133 class Root;
134
135 class Element : public JSNonFinalObject {
136 public:
137     Element(VM& vm, Structure* structure)
138         : Base(vm, structure)
139     {
140     }
141
142     typedef JSNonFinalObject Base;
143
144     Root* root() const { return m_root.get(); }
145     void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
146
147     static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
148     {
149         Structure* structure = createStructure(vm, globalObject, jsNull());
150         Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
151         element->finishCreation(vm, root);
152         return element;
153     }
154
155     void finishCreation(VM&, Root*);
156
157     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
158     {
159         Element* thisObject = jsCast<Element*>(cell);
160         ASSERT_GC_OBJECT_INHERITS(thisObject, info());
161         Base::visitChildren(thisObject, visitor);
162         visitor.append(thisObject->m_root);
163     }
164
165     static ElementHandleOwner* handleOwner();
166
167     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
168     {
169         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
170     }
171
172     DECLARE_INFO;
173
174 private:
175     WriteBarrier<Root> m_root;
176 };
177
178 class ElementHandleOwner : public WeakHandleOwner {
179 public:
180     bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor, const char** reason) override
181     {
182         if (UNLIKELY(reason))
183             *reason = "JSC::Element is opaque root";
184         Element* element = jsCast<Element*>(handle.slot()->asCell());
185         return visitor.containsOpaqueRoot(element->root());
186     }
187 };
188
189 class Root : public JSDestructibleObject {
190 public:
191     Root(VM& vm, Structure* structure)
192         : Base(vm, structure)
193     {
194     }
195
196     Element* element()
197     {
198         return m_element.get();
199     }
200
201     void setElement(Element* element)
202     {
203         Weak<Element> newElement(element, Element::handleOwner());
204         m_element.swap(newElement);
205     }
206
207     static Root* create(VM& vm, JSGlobalObject* globalObject)
208     {
209         Structure* structure = createStructure(vm, globalObject, jsNull());
210         Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
211         root->finishCreation(vm);
212         return root;
213     }
214
215     typedef JSDestructibleObject Base;
216
217     DECLARE_INFO;
218
219     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
220     {
221         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
222     }
223
224     static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
225     {
226         Base::visitChildren(thisObject, visitor);
227         visitor.addOpaqueRoot(thisObject);
228     }
229
230 private:
231     Weak<Element> m_element;
232 };
233
234 class SimpleObject : public JSNonFinalObject {
235 public:
236     SimpleObject(VM& vm, Structure* structure)
237         : Base(vm, structure)
238     {
239     }
240
241     typedef JSNonFinalObject Base;
242     static const bool needsDestruction = false;
243
244     static SimpleObject* create(VM& vm, JSGlobalObject* globalObject)
245     {
246         Structure* structure = createStructure(vm, globalObject, jsNull());
247         SimpleObject* simpleObject = new (NotNull, allocateCell<SimpleObject>(vm.heap, sizeof(SimpleObject))) SimpleObject(vm, structure);
248         simpleObject->finishCreation(vm);
249         return simpleObject;
250     }
251
252     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
253     {
254         SimpleObject* thisObject = jsCast<SimpleObject*>(cell);
255         ASSERT_GC_OBJECT_INHERITS(thisObject, info());
256         Base::visitChildren(thisObject, visitor);
257         visitor.append(thisObject->m_hiddenValue);
258     }
259
260     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
261     {
262         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
263     }
264
265     JSValue hiddenValue()
266     {
267         return m_hiddenValue.get();
268     }
269
270     void setHiddenValue(VM& vm, JSValue value)
271     {
272         ASSERT(value.isCell());
273         m_hiddenValue.set(vm, this, value);
274     }
275
276     DECLARE_INFO;
277
278 private:
279     WriteBarrier<JSC::Unknown> m_hiddenValue;
280 };
281
282 class ImpureGetter : public JSNonFinalObject {
283 public:
284     ImpureGetter(VM& vm, Structure* structure)
285         : Base(vm, structure)
286     {
287     }
288
289     DECLARE_INFO;
290     typedef JSNonFinalObject Base;
291     static const unsigned StructureFlags = Base::StructureFlags | JSC::GetOwnPropertySlotIsImpure | JSC::OverridesGetOwnPropertySlot;
292
293     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
294     {
295         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
296     }
297
298     static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
299     {
300         ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
301         getter->finishCreation(vm, delegate);
302         return getter;
303     }
304
305     void finishCreation(VM& vm, JSObject* delegate)
306     {
307         Base::finishCreation(vm);
308         if (delegate)
309             m_delegate.set(vm, this, delegate);
310     }
311
312     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
313     {
314         VM& vm = exec->vm();
315         auto scope = DECLARE_THROW_SCOPE(vm);
316         ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
317         
318         if (thisObject->m_delegate) {
319             if (thisObject->m_delegate->getPropertySlot(exec, name, slot))
320                 return true;
321             RETURN_IF_EXCEPTION(scope, false);
322         }
323
324         return Base::getOwnPropertySlot(object, exec, name, slot);
325     }
326
327     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
328     {
329         Base::visitChildren(cell, visitor);
330         ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
331         visitor.append(thisObject->m_delegate);
332     }
333
334     void setDelegate(VM& vm, JSObject* delegate)
335     {
336         m_delegate.set(vm, this, delegate);
337     }
338
339 private:
340     WriteBarrier<JSObject> m_delegate;
341 };
342
343 class CustomGetter : public JSNonFinalObject {
344 public:
345     CustomGetter(VM& vm, Structure* structure)
346         : Base(vm, structure)
347     {
348     }
349
350     DECLARE_INFO;
351     typedef JSNonFinalObject Base;
352     static const unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot;
353
354     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
355     {
356         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
357     }
358
359     static CustomGetter* create(VM& vm, Structure* structure)
360     {
361         CustomGetter* getter = new (NotNull, allocateCell<CustomGetter>(vm.heap, sizeof(CustomGetter))) CustomGetter(vm, structure);
362         getter->finishCreation(vm);
363         return getter;
364     }
365
366     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
367     {
368         CustomGetter* thisObject = jsCast<CustomGetter*>(object);
369         if (propertyName == PropertyName(Identifier::fromString(exec, "customGetter"))) {
370             slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, thisObject->customGetter);
371             return true;
372         }
373         
374         if (propertyName == PropertyName(Identifier::fromString(exec, "customGetterAccessor"))) {
375             slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | PropertyAttribute::CustomAccessor, thisObject->customGetterAcessor);
376             return true;
377         }
378         
379         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
380     }
381
382 private:
383     static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
384     {
385         VM& vm = exec->vm();
386         auto scope = DECLARE_THROW_SCOPE(vm);
387
388         CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(vm, JSValue::decode(thisValue));
389         if (!thisObject)
390             return throwVMTypeError(exec, scope);
391         bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
392         RETURN_IF_EXCEPTION(scope, encodedJSValue());
393         if (shouldThrow)
394             return throwVMTypeError(exec, scope);
395         return JSValue::encode(jsNumber(100));
396     }
397     
398     static EncodedJSValue customGetterAcessor(ExecState* exec, EncodedJSValue thisValue, PropertyName)
399     {
400         VM& vm = exec->vm();
401         auto scope = DECLARE_THROW_SCOPE(vm);
402         
403         JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
404         if (!thisObject)
405             return throwVMTypeError(exec, scope);
406         bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
407         RETURN_IF_EXCEPTION(scope, encodedJSValue());
408         if (shouldThrow)
409             return throwVMTypeError(exec, scope);
410         return JSValue::encode(jsNumber(100));
411     }
412 };
413
414 class RuntimeArray : public JSArray {
415 public:
416     typedef JSArray Base;
417     static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
418
419     static RuntimeArray* create(ExecState* exec)
420     {
421         VM& vm = exec->vm();
422         JSGlobalObject* globalObject = exec->lexicalGlobalObject();
423         Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
424         RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(vm.heap)) RuntimeArray(exec, structure);
425         runtimeArray->finishCreation(exec);
426         vm.heap.addFinalizer(runtimeArray, destroy);
427         return runtimeArray;
428     }
429
430     ~RuntimeArray() { }
431
432     static void destroy(JSCell* cell)
433     {
434         static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
435     }
436
437     static const bool needsDestruction = false;
438
439     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
440     {
441         VM& vm = exec->vm();
442         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
443         if (propertyName == vm.propertyNames->length) {
444             slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, thisObject->lengthGetter);
445             return true;
446         }
447
448         std::optional<uint32_t> index = parseIndex(propertyName);
449         if (index && index.value() < thisObject->getLength()) {
450             slot.setValue(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::DontEnum, jsNumber(thisObject->m_vector[index.value()]));
451             return true;
452         }
453
454         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
455     }
456
457     static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
458     {
459         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
460         if (index < thisObject->getLength()) {
461             slot.setValue(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::DontEnum, jsNumber(thisObject->m_vector[index]));
462             return true;
463         }
464
465         return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
466     }
467
468     static NO_RETURN_DUE_TO_CRASH bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
469     {
470         RELEASE_ASSERT_NOT_REACHED();
471     }
472
473     static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
474     {
475         RELEASE_ASSERT_NOT_REACHED();
476     }
477
478     unsigned getLength() const { return m_vector.size(); }
479
480     DECLARE_INFO;
481
482     static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
483     {
484         return globalObject->arrayPrototype();
485     }
486
487     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
488     {
489         return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
490     }
491
492 protected:
493     void finishCreation(ExecState* exec)
494     {
495         VM& vm = exec->vm();
496         Base::finishCreation(vm);
497         ASSERT(inherits(vm, info()));
498
499         for (size_t i = 0; i < exec->argumentCount(); i++)
500             m_vector.append(exec->argument(i).toInt32(exec));
501     }
502
503 private:
504     RuntimeArray(ExecState* exec, Structure* structure)
505         : JSArray(exec->vm(), structure, 0)
506     {
507     }
508
509     static EncodedJSValue lengthGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
510     {
511         VM& vm = exec->vm();
512         auto scope = DECLARE_THROW_SCOPE(vm);
513
514         RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(vm, JSValue::decode(thisValue));
515         if (!thisObject)
516             return throwVMTypeError(exec, scope);
517         return JSValue::encode(jsNumber(thisObject->getLength()));
518     }
519
520     Vector<int> m_vector;
521 };
522
523 class DOMJITNode : public JSNonFinalObject {
524 public:
525     DOMJITNode(VM& vm, Structure* structure)
526         : Base(vm, structure)
527     {
528     }
529
530     DECLARE_INFO;
531     typedef JSNonFinalObject Base;
532     static const unsigned StructureFlags = Base::StructureFlags;
533
534     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
535     {
536         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
537     }
538
539 #if ENABLE(JIT)
540     static Ref<Snippet> checkSubClassSnippet()
541     {
542         Ref<Snippet> snippet = Snippet::create();
543         snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
544             CCallHelpers::JumpList failureCases;
545             failureCases.append(jit.branchIfNotType(params[0].gpr(), JSC::JSType(LastJSCObjectType + 1)));
546             return failureCases;
547         });
548         return snippet;
549     }
550 #endif
551
552     static DOMJITNode* create(VM& vm, Structure* structure)
553     {
554         DOMJITNode* getter = new (NotNull, allocateCell<DOMJITNode>(vm.heap, sizeof(DOMJITNode))) DOMJITNode(vm, structure);
555         getter->finishCreation(vm);
556         return getter;
557     }
558
559     int32_t value() const
560     {
561         return m_value;
562     }
563
564     static ptrdiff_t offsetOfValue() { return OBJECT_OFFSETOF(DOMJITNode, m_value); }
565
566 private:
567     int32_t m_value { 42 };
568 };
569
570 class DOMJITGetter : public DOMJITNode {
571 public:
572     DOMJITGetter(VM& vm, Structure* structure)
573         : Base(vm, structure)
574     {
575     }
576
577     DECLARE_INFO;
578     typedef DOMJITNode Base;
579     static const unsigned StructureFlags = Base::StructureFlags;
580
581     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
582     {
583         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
584     }
585
586     static DOMJITGetter* create(VM& vm, Structure* structure)
587     {
588         DOMJITGetter* getter = new (NotNull, allocateCell<DOMJITGetter>(vm.heap, sizeof(DOMJITGetter))) DOMJITGetter(vm, structure);
589         getter->finishCreation(vm);
590         return getter;
591     }
592
593     class DOMJITAttribute : public DOMJIT::GetterSetter {
594     public:
595         constexpr DOMJITAttribute()
596             : DOMJIT::GetterSetter(
597                 DOMJITGetter::customGetter,
598 #if ENABLE(JIT)
599                 &callDOMGetter,
600 #else
601                 nullptr,
602 #endif
603                 SpecInt32Only)
604         {
605         }
606
607 #if ENABLE(JIT)
608         static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
609         {
610             VM& vm = exec->vm();
611             NativeCallFrameTracer tracer(&vm, exec);
612             return JSValue::encode(jsNumber(static_cast<DOMJITGetter*>(pointer)->value()));
613         }
614
615         static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
616         {
617             Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
618             snippet->requireGlobalObject = false;
619             snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
620                 JSValueRegs results = params[0].jsValueRegs();
621                 GPRReg dom = params[1].gpr();
622                 params.addSlowPathCall(jit.jump(), jit, slowCall, results, dom);
623                 return CCallHelpers::JumpList();
624
625             });
626             return snippet;
627         }
628 #endif
629     };
630
631 private:
632     void finishCreation(VM&);
633
634     static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
635     {
636         VM& vm = exec->vm();
637         DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, JSValue::decode(thisValue));
638         ASSERT(thisObject);
639         return JSValue::encode(jsNumber(thisObject->value()));
640     }
641 };
642
643 static const DOMJITGetter::DOMJITAttribute DOMJITGetterDOMJIT;
644
645 void DOMJITGetter::finishCreation(VM& vm)
646 {
647     Base::finishCreation(vm);
648     const DOMJIT::GetterSetter* domJIT = &DOMJITGetterDOMJIT;
649     auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { DOMJITNode::info(), domJIT });
650     putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor);
651 }
652
653 class DOMJITGetterComplex : public DOMJITNode {
654 public:
655     DOMJITGetterComplex(VM& vm, Structure* structure)
656         : Base(vm, structure)
657     {
658     }
659
660     DECLARE_INFO;
661     typedef DOMJITNode Base;
662     static const unsigned StructureFlags = Base::StructureFlags;
663
664     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
665     {
666         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
667     }
668
669     static DOMJITGetterComplex* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
670     {
671         DOMJITGetterComplex* getter = new (NotNull, allocateCell<DOMJITGetterComplex>(vm.heap, sizeof(DOMJITGetterComplex))) DOMJITGetterComplex(vm, structure);
672         getter->finishCreation(vm, globalObject);
673         return getter;
674     }
675
676     class DOMJITAttribute : public DOMJIT::GetterSetter {
677     public:
678         constexpr DOMJITAttribute()
679             : DOMJIT::GetterSetter(
680                 DOMJITGetterComplex::customGetter,
681 #if ENABLE(JIT)
682                 &callDOMGetter,
683 #else
684                 nullptr,
685 #endif
686                 SpecInt32Only)
687         {
688         }
689
690 #if ENABLE(JIT)
691         static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
692         {
693             VM& vm = exec->vm();
694             NativeCallFrameTracer tracer(&vm, exec);
695             auto scope = DECLARE_THROW_SCOPE(vm);
696             auto* object = static_cast<DOMJITNode*>(pointer);
697             auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(vm, object);
698             if (domjitGetterComplex) {
699                 if (domjitGetterComplex->m_enableException)
700                     return JSValue::encode(throwException(exec, scope, createError(exec, "DOMJITGetterComplex slow call exception"_s)));
701             }
702             return JSValue::encode(jsNumber(object->value()));
703         }
704
705         static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
706         {
707             Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
708             static_assert(GPRInfo::numberOfRegisters >= 4, "Number of registers should be larger or equal to 4.");
709             unsigned numGPScratchRegisters = GPRInfo::numberOfRegisters - 4;
710             snippet->numGPScratchRegisters = numGPScratchRegisters;
711             snippet->numFPScratchRegisters = 3;
712             snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
713                 JSValueRegs results = params[0].jsValueRegs();
714                 GPRReg domGPR = params[1].gpr();
715                 for (unsigned i = 0; i < numGPScratchRegisters; ++i)
716                     jit.move(CCallHelpers::TrustedImm32(42), params.gpScratch(i));
717
718                 params.addSlowPathCall(jit.jump(), jit, slowCall, results, domGPR);
719                 return CCallHelpers::JumpList();
720             });
721             return snippet;
722         }
723 #endif
724     };
725
726 private:
727     void finishCreation(VM&, JSGlobalObject*);
728
729     static EncodedJSValue JSC_HOST_CALL functionEnableException(ExecState* exec)
730     {
731         VM& vm = exec->vm();
732         auto* object = jsDynamicCast<DOMJITGetterComplex*>(vm, exec->thisValue());
733         if (object)
734             object->m_enableException = true;
735         return JSValue::encode(jsUndefined());
736     }
737
738     static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
739     {
740         VM& vm = exec->vm();
741         auto scope = DECLARE_THROW_SCOPE(vm);
742
743         auto* thisObject = jsDynamicCast<DOMJITGetterComplex*>(vm, JSValue::decode(thisValue));
744         ASSERT(thisObject);
745         if (thisObject->m_enableException)
746             return JSValue::encode(throwException(exec, scope, createError(exec, "DOMJITGetterComplex slow call exception"_s)));
747         return JSValue::encode(jsNumber(thisObject->value()));
748     }
749
750     bool m_enableException { false };
751 };
752
753 static const DOMJITGetterComplex::DOMJITAttribute DOMJITGetterComplexDOMJIT;
754
755 void DOMJITGetterComplex::finishCreation(VM& vm, JSGlobalObject* globalObject)
756 {
757     Base::finishCreation(vm);
758     const DOMJIT::GetterSetter* domJIT = &DOMJITGetterComplexDOMJIT;
759     auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { DOMJITGetterComplex::info(), domJIT });
760     putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor);
761     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "enableException"), 0, functionEnableException, NoIntrinsic, 0);
762 }
763
764 class DOMJITFunctionObject : public DOMJITNode {
765 public:
766     DOMJITFunctionObject(VM& vm, Structure* structure)
767         : Base(vm, structure)
768     {
769     }
770
771     DECLARE_INFO;
772     typedef DOMJITNode Base;
773     static const unsigned StructureFlags = Base::StructureFlags;
774
775
776     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
777     {
778         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
779     }
780
781     static DOMJITFunctionObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
782     {
783         DOMJITFunctionObject* object = new (NotNull, allocateCell<DOMJITFunctionObject>(vm.heap, sizeof(DOMJITFunctionObject))) DOMJITFunctionObject(vm, structure);
784         object->finishCreation(vm, globalObject);
785         return object;
786     }
787
788     static EncodedJSValue JSC_HOST_CALL safeFunction(ExecState* exec)
789     {
790         VM& vm = exec->vm();
791         auto scope = DECLARE_THROW_SCOPE(vm);
792
793         DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, exec->thisValue());
794         if (!thisObject)
795             return throwVMTypeError(exec, scope);
796         return JSValue::encode(jsNumber(thisObject->value()));
797     }
798
799     static EncodedJSValue JIT_OPERATION unsafeFunction(ExecState* exec, DOMJITNode* node)
800     {
801         VM& vm = exec->vm();
802         NativeCallFrameTracer tracer(&vm, exec);
803         return JSValue::encode(jsNumber(node->value()));
804     }
805
806 #if ENABLE(JIT)
807     static Ref<Snippet> checkSubClassSnippet()
808     {
809         Ref<Snippet> snippet = Snippet::create();
810         snippet->numFPScratchRegisters = 1;
811         snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
812             static const double value = 42.0;
813             CCallHelpers::JumpList failureCases;
814             // May use scratch registers.
815             jit.loadDouble(CCallHelpers::TrustedImmPtr(&value), params.fpScratch(0));
816             failureCases.append(jit.branchIfNotType(params[0].gpr(), JSC::JSType(LastJSCObjectType + 1)));
817             return failureCases;
818         });
819         return snippet;
820     }
821 #endif
822
823 private:
824     void finishCreation(VM&, JSGlobalObject*);
825 };
826
827 static const DOMJIT::Signature DOMJITFunctionObjectSignature((uintptr_t)DOMJITFunctionObject::unsafeFunction, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
828
829 void DOMJITFunctionObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
830 {
831     Base::finishCreation(vm);
832     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, &DOMJITFunctionObjectSignature, static_cast<unsigned>(PropertyAttribute::ReadOnly));
833 }
834
835 class DOMJITCheckSubClassObject : public DOMJITNode {
836 public:
837     DOMJITCheckSubClassObject(VM& vm, Structure* structure)
838         : Base(vm, structure)
839     {
840     }
841
842     DECLARE_INFO;
843     typedef DOMJITNode Base;
844     static const unsigned StructureFlags = Base::StructureFlags;
845
846
847     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
848     {
849         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
850     }
851
852     static DOMJITCheckSubClassObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
853     {
854         DOMJITCheckSubClassObject* object = new (NotNull, allocateCell<DOMJITCheckSubClassObject>(vm.heap, sizeof(DOMJITCheckSubClassObject))) DOMJITCheckSubClassObject(vm, structure);
855         object->finishCreation(vm, globalObject);
856         return object;
857     }
858
859     static EncodedJSValue JSC_HOST_CALL safeFunction(ExecState* exec)
860     {
861         VM& vm = exec->vm();
862         auto scope = DECLARE_THROW_SCOPE(vm);
863
864         auto* thisObject = jsDynamicCast<DOMJITCheckSubClassObject*>(vm, exec->thisValue());
865         if (!thisObject)
866             return throwVMTypeError(exec, scope);
867         return JSValue::encode(jsNumber(thisObject->value()));
868     }
869
870     static EncodedJSValue JIT_OPERATION unsafeFunction(ExecState* exec, DOMJITNode* node)
871     {
872         VM& vm = exec->vm();
873         NativeCallFrameTracer tracer(&vm, exec);
874         return JSValue::encode(jsNumber(node->value()));
875     }
876
877 private:
878     void finishCreation(VM&, JSGlobalObject*);
879 };
880
881 static const DOMJIT::Signature DOMJITCheckSubClassObjectSignature((uintptr_t)DOMJITCheckSubClassObject::unsafeFunction, DOMJITCheckSubClassObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
882
883 void DOMJITCheckSubClassObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
884 {
885     Base::finishCreation(vm);
886     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, &DOMJITCheckSubClassObjectSignature, static_cast<unsigned>(PropertyAttribute::ReadOnly));
887 }
888
889 class DOMJITGetterBaseJSObject : public DOMJITNode {
890 public:
891     DOMJITGetterBaseJSObject(VM& vm, Structure* structure)
892         : Base(vm, structure)
893     {
894     }
895
896     DECLARE_INFO;
897     using Base = DOMJITNode;
898     static const unsigned StructureFlags = Base::StructureFlags;
899
900     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
901     {
902         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
903     }
904
905     static DOMJITGetterBaseJSObject* create(VM& vm, Structure* structure)
906     {
907         DOMJITGetterBaseJSObject* getter = new (NotNull, allocateCell<DOMJITGetterBaseJSObject>(vm.heap, sizeof(DOMJITGetterBaseJSObject))) DOMJITGetterBaseJSObject(vm, structure);
908         getter->finishCreation(vm);
909         return getter;
910     }
911
912     class DOMJITAttribute : public DOMJIT::GetterSetter {
913     public:
914         constexpr DOMJITAttribute()
915             : DOMJIT::GetterSetter(
916                 DOMJITGetterBaseJSObject::customGetter,
917 #if ENABLE(JIT)
918                 &callDOMGetter,
919 #else
920                 nullptr,
921 #endif
922                 SpecBytecodeTop)
923         {
924         }
925
926 #if ENABLE(JIT)
927         static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
928         {
929             VM& vm = exec->vm();
930             NativeCallFrameTracer tracer(&vm, exec);
931             JSObject* object = static_cast<JSObject*>(pointer);
932             return JSValue::encode(object->getPrototypeDirect(vm));
933         }
934
935         static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
936         {
937             Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
938             snippet->requireGlobalObject = false;
939             snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
940                 JSValueRegs results = params[0].jsValueRegs();
941                 GPRReg dom = params[1].gpr();
942                 params.addSlowPathCall(jit.jump(), jit, slowCall, results, dom);
943                 return CCallHelpers::JumpList();
944
945             });
946             return snippet;
947         }
948 #endif
949     };
950
951 private:
952     void finishCreation(VM&);
953
954     static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
955     {
956         VM& vm = exec->vm();
957         JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
958         RELEASE_ASSERT(thisObject);
959         return JSValue::encode(thisObject->getPrototypeDirect(vm));
960     }
961 };
962
963 static const DOMJITGetterBaseJSObject::DOMJITAttribute DOMJITGetterBaseJSObjectDOMJIT;
964
965 void DOMJITGetterBaseJSObject::finishCreation(VM& vm)
966 {
967     Base::finishCreation(vm);
968     const DOMJIT::GetterSetter* domJIT = &DOMJITGetterBaseJSObjectDOMJIT;
969     auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { JSObject::info(), domJIT });
970     putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor);
971 }
972
973 class Message : public ThreadSafeRefCounted<Message> {
974 public:
975     Message(ArrayBufferContents&&, int32_t);
976     ~Message();
977
978     ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
979     int32_t index() const { return m_index; }
980
981 private:
982     ArrayBufferContents m_contents;
983     int32_t m_index { 0 };
984 };
985
986 class JSTestCustomGetterSetter : public JSNonFinalObject {
987 public:
988     using Base = JSNonFinalObject;
989     static const unsigned StructureFlags = Base::StructureFlags;
990
991     JSTestCustomGetterSetter(VM& vm, Structure* structure)
992         : Base(vm, structure)
993     { }
994
995     static JSTestCustomGetterSetter* create(VM& vm, JSGlobalObject*, Structure* structure)
996     {
997         JSTestCustomGetterSetter* result = new (NotNull, allocateCell<JSTestCustomGetterSetter>(vm.heap, sizeof(JSTestCustomGetterSetter))) JSTestCustomGetterSetter(vm, structure);
998         result->finishCreation(vm);
999         return result;
1000     }
1001
1002     void finishCreation(VM&);
1003
1004     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject)
1005     {
1006         return Structure::create(vm, globalObject, globalObject->objectPrototype(), TypeInfo(ObjectType, StructureFlags), info());
1007     }
1008
1009     DECLARE_INFO;
1010 };
1011
1012
1013 static EncodedJSValue customGetAccessor(ExecState*, EncodedJSValue thisValue, PropertyName)
1014 {
1015     // Passed |this|
1016     return thisValue;
1017 }
1018
1019 static EncodedJSValue customGetValue(ExecState* exec, EncodedJSValue slotValue, PropertyName)
1020 {
1021     RELEASE_ASSERT(JSValue::decode(slotValue).inherits<JSTestCustomGetterSetter>(exec->vm()));
1022     // Passed property holder.
1023     return slotValue;
1024 }
1025
1026 static bool customSetAccessor(ExecState* exec, EncodedJSValue thisObject, EncodedJSValue encodedValue)
1027 {
1028     VM& vm = exec->vm();
1029
1030     JSValue value = JSValue::decode(encodedValue);
1031     RELEASE_ASSERT(value.isObject());
1032     JSObject* object = asObject(value);
1033     PutPropertySlot slot(object);
1034     object->put(object, exec, Identifier::fromString(&vm, "result"), JSValue::decode(thisObject), slot);
1035
1036     return true;
1037 }
1038
1039 static bool customSetValue(ExecState* exec, EncodedJSValue slotValue, EncodedJSValue encodedValue)
1040 {
1041     VM& vm = exec->vm();
1042
1043     RELEASE_ASSERT(JSValue::decode(slotValue).inherits<JSTestCustomGetterSetter>(exec->vm()));
1044
1045     JSValue value = JSValue::decode(encodedValue);
1046     RELEASE_ASSERT(value.isObject());
1047     JSObject* object = asObject(value);
1048     PutPropertySlot slot(object);
1049     object->put(object, exec, Identifier::fromString(&vm, "result"), JSValue::decode(slotValue), slot);
1050
1051     return true;
1052 }
1053
1054 void JSTestCustomGetterSetter::finishCreation(VM& vm)
1055 {
1056     Base::finishCreation(vm);
1057
1058     putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customValue"),
1059         CustomGetterSetter::create(vm, customGetValue, customSetValue), 0);
1060     putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customAccessor"),
1061         CustomGetterSetter::create(vm, customGetAccessor, customSetAccessor), static_cast<unsigned>(PropertyAttribute::CustomAccessor));
1062 }
1063
1064 const ClassInfo Element::s_info = { "Element", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Element) };
1065 const ClassInfo Root::s_info = { "Root", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Root) };
1066 const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(SimpleObject) };
1067 const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ImpureGetter) };
1068 const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(CustomGetter) };
1069 const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RuntimeArray) };
1070 #if ENABLE(JIT)
1071 const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, &DOMJITNode::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITNode) };
1072 #else
1073 const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITNode) };
1074 #endif
1075 const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetter) };
1076 const ClassInfo DOMJITGetterComplex::s_info = { "DOMJITGetterComplex", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetterComplex) };
1077 const ClassInfo DOMJITGetterBaseJSObject::s_info = { "DOMJITGetterBaseJSObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetterBaseJSObject) };
1078 #if ENABLE(JIT)
1079 const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, &DOMJITFunctionObject::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
1080 #else
1081 const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
1082 #endif
1083 const ClassInfo DOMJITCheckSubClassObject::s_info = { "DOMJITCheckSubClassObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITCheckSubClassObject) };
1084 const ClassInfo JSTestCustomGetterSetter::s_info = { "JSTestCustomGetterSetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestCustomGetterSetter) };
1085
1086 ElementHandleOwner* Element::handleOwner()
1087 {
1088     static ElementHandleOwner* owner = 0;
1089     if (!owner)
1090         owner = new ElementHandleOwner();
1091     return owner;
1092 }
1093
1094 void Element::finishCreation(VM& vm, Root* root)
1095 {
1096     Base::finishCreation(vm);
1097     setRoot(vm, root);
1098     m_root->setElement(this);
1099 }
1100
1101 #if ENABLE(WEBASSEMBLY)
1102
1103 static EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserAddBytes(ExecState*);
1104 static EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserFinalize(ExecState*);
1105
1106 class WasmStreamingParser : public JSDestructibleObject {
1107 public:
1108     WasmStreamingParser(VM& vm, Structure* structure)
1109         : Base(vm, structure)
1110         , m_info(Wasm::ModuleInformation::create())
1111         , m_streamingParser(m_info.get())
1112     {
1113     }
1114
1115     using Base = JSDestructibleObject;
1116
1117     static WasmStreamingParser* create(VM& vm, JSGlobalObject* globalObject)
1118     {
1119         Structure* structure = createStructure(vm, globalObject, jsNull());
1120         WasmStreamingParser* result = new (NotNull, allocateCell<WasmStreamingParser>(vm.heap, sizeof(WasmStreamingParser))) WasmStreamingParser(vm, structure);
1121         result->finishCreation(vm);
1122         return result;
1123     }
1124
1125     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
1126     {
1127         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
1128     }
1129
1130     Wasm::StreamingParser& streamingParser() { return m_streamingParser; }
1131
1132     void finishCreation(VM& vm)
1133     {
1134         Base::finishCreation(vm);
1135
1136         JSGlobalObject* globalObject = this->globalObject(vm);
1137         putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "addBytes"), 0, functionWasmStreamingParserAddBytes, NoIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
1138         putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "finalize"), 0, functionWasmStreamingParserFinalize, NoIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
1139     }
1140
1141     DECLARE_INFO;
1142
1143     Ref<Wasm::ModuleInformation> m_info;
1144     Wasm::StreamingParser m_streamingParser;
1145 };
1146
1147 const ClassInfo WasmStreamingParser::s_info = { "WasmStreamingParser", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(WasmStreamingParser) };
1148
1149 EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserAddBytes(ExecState* exec)
1150 {
1151     VM& vm = exec->vm();
1152     auto scope = DECLARE_THROW_SCOPE(exec->vm());
1153     auto* thisObject = jsDynamicCast<WasmStreamingParser*>(vm, exec->thisValue());
1154     if (!thisObject)
1155         RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(false)));
1156
1157     auto data = getWasmBufferFromValue(exec, exec->argument(0));
1158     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1159     RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(static_cast<int32_t>(thisObject->streamingParser().addBytes(bitwise_cast<const uint8_t*>(data.first), data.second)))));
1160 }
1161
1162 EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserFinalize(ExecState* exec)
1163 {
1164     VM& vm = exec->vm();
1165     auto* thisObject = jsDynamicCast<WasmStreamingParser*>(vm, exec->thisValue());
1166     if (!thisObject)
1167         return JSValue::encode(jsBoolean(false));
1168     return JSValue::encode(jsNumber(static_cast<int32_t>(thisObject->streamingParser().finalize())));
1169 }
1170
1171 #endif
1172
1173 } // namespace
1174
1175 namespace JSC {
1176
1177 const ClassInfo JSDollarVM::s_info = { "DollarVM", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVM) };
1178
1179 // Triggers a crash immediately.
1180 // Usage: $vm.crash()
1181 static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionCrash(ExecState*)
1182 {
1183     CRASH();
1184 }
1185
1186 // Executes a breakpoint instruction if the first argument is truthy or is unset.
1187 // Usage: $vm.breakpoint(<condition>)
1188 static EncodedJSValue JSC_HOST_CALL functionBreakpoint(ExecState* exec)
1189 {
1190     // Nothing should throw here but we might as well double check...
1191     VM& vm = exec->vm();
1192     auto scope = DECLARE_CATCH_SCOPE(vm);
1193     UNUSED_PARAM(scope);
1194     if (!exec->argumentCount() || exec->argument(0).toBoolean(exec))
1195         WTFBreakpointTrap();
1196
1197     return encodedJSUndefined();
1198 }
1199
1200 // Returns true if the current frame is a DFG frame.
1201 // Usage: isDFG = $vm.dfgTrue()
1202 static EncodedJSValue JSC_HOST_CALL functionDFGTrue(ExecState*)
1203 {
1204     return JSValue::encode(jsBoolean(false));
1205 }
1206
1207 // Returns true if the current frame is a FTL frame.
1208 // Usage: isFTL = $vm.ftlTrue()
1209 static EncodedJSValue JSC_HOST_CALL functionFTLTrue(ExecState*)
1210 {
1211     return JSValue::encode(jsBoolean(false));
1212 }
1213
1214 static EncodedJSValue JSC_HOST_CALL functionCpuMfence(ExecState*)
1215 {
1216 #if CPU(X86_64) && !OS(WINDOWS)
1217     asm volatile("mfence" ::: "memory");
1218 #endif
1219     return JSValue::encode(jsUndefined());
1220 }
1221
1222 static EncodedJSValue JSC_HOST_CALL functionCpuRdtsc(ExecState*)
1223 {
1224 #if CPU(X86_64) && !OS(WINDOWS)
1225     unsigned high;
1226     unsigned low;
1227     asm volatile ("rdtsc" : "=a"(low), "=d"(high));
1228     return JSValue::encode(jsNumber(low));
1229 #else
1230     return JSValue::encode(jsNumber(0));
1231 #endif
1232 }
1233
1234 static EncodedJSValue JSC_HOST_CALL functionCpuCpuid(ExecState*)
1235 {
1236 #if CPU(X86_64) && !OS(WINDOWS)
1237     WTF::x86_cpuid();
1238 #endif
1239     return JSValue::encode(jsUndefined());
1240 }
1241
1242 static EncodedJSValue JSC_HOST_CALL functionCpuPause(ExecState*)
1243 {
1244 #if CPU(X86_64) && !OS(WINDOWS)
1245     asm volatile ("pause" ::: "memory");
1246 #endif
1247     return JSValue::encode(jsUndefined());
1248 }
1249
1250 // This takes either a JSArrayBuffer, JSArrayBufferView*, or any other object as its first
1251 // argument. The second argument is expected to be an integer.
1252 //
1253 // If the first argument is a JSArrayBuffer, it'll clflush on that buffer
1254 // plus the second argument as a byte offset. It'll also flush on the object
1255 // itself so its length, etc, aren't in the cache.
1256 //
1257 // If the first argument is not a JSArrayBuffer, we load the butterfly
1258 // and clflush at the address of the butterfly.
1259 static EncodedJSValue JSC_HOST_CALL functionCpuClflush(ExecState* exec)
1260 {
1261 #if CPU(X86_64) && !OS(WINDOWS)
1262     VM& vm = exec->vm();
1263
1264     if (!exec->argument(1).isInt32())
1265         return JSValue::encode(jsBoolean(false));
1266
1267     auto clflush = [] (void* ptr) {
1268         char* ptrToFlush = static_cast<char*>(ptr);
1269         asm volatile ("clflush %0" :: "m"(*ptrToFlush) : "memory");
1270     };
1271
1272     Vector<void*> toFlush;
1273
1274     uint32_t offset = exec->argument(1).asUInt32();
1275
1276     if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(vm, exec->argument(0)))
1277         toFlush.append(bitwise_cast<char*>(view->vector()) + offset);
1278     else if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0))) {
1279         switch (object->indexingType()) {
1280         case ALL_INT32_INDEXING_TYPES:
1281         case ALL_CONTIGUOUS_INDEXING_TYPES:
1282         case ALL_DOUBLE_INDEXING_TYPES:
1283             toFlush.append(bitwise_cast<char*>(object->butterfly()) + Butterfly::offsetOfVectorLength());
1284             toFlush.append(bitwise_cast<char*>(object->butterfly()) + Butterfly::offsetOfPublicLength());
1285         }
1286     }
1287
1288     if (!toFlush.size())
1289         return JSValue::encode(jsBoolean(false));
1290
1291     for (void* ptr : toFlush)
1292         clflush(ptr);
1293     return JSValue::encode(jsBoolean(true));
1294 #else
1295     UNUSED_PARAM(exec);
1296     return JSValue::encode(jsBoolean(false));
1297 #endif
1298 }
1299
1300 class CallerFrameJITTypeFunctor {
1301 public:
1302     CallerFrameJITTypeFunctor()
1303         : m_currentFrame(0)
1304         , m_jitType(JITCode::None)
1305     {
1306     }
1307
1308     StackVisitor::Status operator()(StackVisitor& visitor) const
1309     {
1310         if (m_currentFrame++ > 1) {
1311             m_jitType = visitor->codeBlock()->jitType();
1312             return StackVisitor::Done;
1313         }
1314         return StackVisitor::Continue;
1315     }
1316     
1317     JITCode::JITType jitType() { return m_jitType; }
1318
1319 private:
1320     mutable unsigned m_currentFrame;
1321     mutable JITCode::JITType m_jitType;
1322 };
1323
1324 static FunctionExecutable* getExecutableForFunction(JSValue theFunctionValue)
1325 {
1326     if (!theFunctionValue.isCell())
1327         return nullptr;
1328     
1329     VM& vm = *theFunctionValue.asCell()->vm();
1330     JSFunction* theFunction = jsDynamicCast<JSFunction*>(vm, theFunctionValue);
1331     if (!theFunction)
1332         return nullptr;
1333     
1334     FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(vm,
1335         theFunction->executable());
1336
1337     return executable;
1338 }
1339
1340 // Returns true if the current frame is a LLInt frame.
1341 // Usage: isLLInt = $vm.llintTrue()
1342 static EncodedJSValue JSC_HOST_CALL functionLLintTrue(ExecState* exec)
1343 {
1344     if (!exec)
1345         return JSValue::encode(jsUndefined());
1346     CallerFrameJITTypeFunctor functor;
1347     exec->iterate(functor);
1348     return JSValue::encode(jsBoolean(functor.jitType() == JITCode::InterpreterThunk));
1349 }
1350
1351 // Returns true if the current frame is a baseline JIT frame.
1352 // Usage: isBaselineJIT = $vm.jitTrue()
1353 static EncodedJSValue JSC_HOST_CALL functionJITTrue(ExecState* exec)
1354 {
1355     if (!exec)
1356         return JSValue::encode(jsUndefined());
1357     CallerFrameJITTypeFunctor functor;
1358     exec->iterate(functor);
1359     return JSValue::encode(jsBoolean(functor.jitType() == JITCode::BaselineJIT));
1360 }
1361
1362 // Set that the argument function should not be inlined.
1363 // Usage:
1364 // function f() { };
1365 // $vm.noInline(f);
1366 static EncodedJSValue JSC_HOST_CALL functionNoInline(ExecState* exec)
1367 {
1368     if (exec->argumentCount() < 1)
1369         return JSValue::encode(jsUndefined());
1370     
1371     JSValue theFunctionValue = exec->uncheckedArgument(0);
1372
1373     if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue))
1374         executable->setNeverInline(true);
1375     
1376     return JSValue::encode(jsUndefined());
1377 }
1378
1379 // Runs a full GC synchronously.
1380 // Usage: $vm.gc()
1381 static EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
1382 {
1383     VMInspector::gc(exec);
1384     return JSValue::encode(jsUndefined());
1385 }
1386
1387 // Runs the edenGC synchronously.
1388 // Usage: $vm.edenGC()
1389 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1390 {
1391     VMInspector::edenGC(exec);
1392     return JSValue::encode(jsUndefined());
1393 }
1394
1395 // Gets a JSDollarVMCallFrame for a specified frame index.
1396 // Usage: var callFrame = $vm.callFrame(0) // frame 0 is the top frame.
1397 // Usage: var callFrame = $vm.callFrame() // implies frame 0 i.e. current frame.
1398 //
1399 // This gives you the ability to query the following:
1400 //    callFrame.valid; // false if we asked for a frame beyond the end of the stack, else true.
1401 //    callFrame.callee;
1402 //    callFrame.codeBlock;
1403 //    callFrame.unlinkedCodeBlock;
1404 //    callFrame.executable;
1405 //
1406 // Note: you cannot toString() a codeBlock, unlinkedCodeBlock, or executable because
1407 // there are internal objects and not a JS object. Hence, you cannot do string
1408 // concatenation with them.
1409 static EncodedJSValue JSC_HOST_CALL functionCallFrame(ExecState* exec)
1410 {
1411     unsigned frameNumber = 1;
1412     if (exec->argumentCount() >= 1) {
1413         JSValue value = exec->uncheckedArgument(0);
1414         if (!value.isUInt32())
1415             return JSValue::encode(jsUndefined());
1416
1417         // We need to inc the frame number because the caller would consider
1418         // its own frame as frame 0. Hence, we need discount the frame for this
1419         // function.
1420         frameNumber = value.asUInt32() + 1;
1421     }
1422
1423     return JSValue::encode(JSDollarVMCallFrame::create(exec, frameNumber));
1424 }
1425
1426 // Gets a token for the CodeBlock for a specified frame index.
1427 // Usage: codeBlockToken = $vm.codeBlockForFrame(0) // frame 0 is the top frame.
1428 // Usage: codeBlockToken = $vm.codeBlockForFrame() // implies frame 0 i.e. current frame.
1429 static EncodedJSValue JSC_HOST_CALL functionCodeBlockForFrame(ExecState* exec)
1430 {
1431     unsigned frameNumber = 1;
1432     if (exec->argumentCount() >= 1) {
1433         JSValue value = exec->uncheckedArgument(0);
1434         if (!value.isUInt32())
1435             return JSValue::encode(jsUndefined());
1436
1437         // We need to inc the frame number because the caller would consider
1438         // its own frame as frame 0. Hence, we need discount the frame for this
1439         // function.
1440         frameNumber = value.asUInt32() + 1;
1441     }
1442
1443     CodeBlock* codeBlock = VMInspector::codeBlockForFrame(exec, frameNumber);
1444     if (codeBlock)
1445         return JSValue::encode(codeBlock);
1446     return JSValue::encode(jsUndefined());
1447 }
1448
1449 static CodeBlock* codeBlockFromArg(ExecState* exec)
1450 {
1451     VM& vm = exec->vm();
1452     if (exec->argumentCount() < 1)
1453         return nullptr;
1454
1455     JSValue value = exec->uncheckedArgument(0);
1456     CodeBlock* candidateCodeBlock = nullptr;
1457     if (value.isCell()) {
1458         JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell());
1459         if (func) {
1460             if (func->isHostFunction())
1461                 candidateCodeBlock = nullptr;
1462             else
1463                 candidateCodeBlock = func->jsExecutable()->eitherCodeBlock();
1464         } else
1465             candidateCodeBlock = static_cast<CodeBlock*>(value.asCell());
1466     }
1467
1468     if (candidateCodeBlock && VMInspector::isValidCodeBlock(exec, candidateCodeBlock))
1469         return candidateCodeBlock;
1470
1471     if (candidateCodeBlock)
1472         dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n");
1473     else
1474         dataLog("Invalid codeBlock: ", value, "\n");
1475     return nullptr;
1476 }
1477
1478 // Usage: $vm.print("codeblock = ", $vm.codeBlockFor(functionObj))
1479 // Usage: $vm.print("codeblock = ", $vm.codeBlockFor(codeBlockToken))
1480 // Note: you cannot toString() a codeBlock because it's an internal object and not
1481 // a JS object. Hence, you cannot do string concatenation with it.
1482 static EncodedJSValue JSC_HOST_CALL functionCodeBlockFor(ExecState* exec)
1483 {
1484     CodeBlock* codeBlock = codeBlockFromArg(exec);
1485     WTF::StringPrintStream stream;
1486     if (codeBlock) {
1487         stream.print(*codeBlock);
1488         return JSValue::encode(jsString(exec, stream.toString()));
1489     }
1490     return JSValue::encode(jsUndefined());
1491 }
1492
1493 // Usage: $vm.dumpSourceFor(functionObj)
1494 // Usage: $vm.dumpSourceFor(codeBlockToken)
1495 static EncodedJSValue JSC_HOST_CALL functionDumpSourceFor(ExecState* exec)
1496 {
1497     CodeBlock* codeBlock = codeBlockFromArg(exec);
1498     if (codeBlock)
1499         codeBlock->dumpSource();
1500     return JSValue::encode(jsUndefined());
1501 }
1502
1503 // Usage: $vm.dumpBytecodeFor(functionObj)
1504 // Usage: $vm.dumpBytecodeFor(codeBlock)
1505 static EncodedJSValue JSC_HOST_CALL functionDumpBytecodeFor(ExecState* exec)
1506 {
1507     CodeBlock* codeBlock = codeBlockFromArg(exec);
1508     if (codeBlock)
1509         codeBlock->dumpBytecode();
1510     return JSValue::encode(jsUndefined());
1511 }
1512
1513 static EncodedJSValue doPrint(ExecState* exec, bool addLineFeed)
1514 {
1515     auto scope = DECLARE_THROW_SCOPE(exec->vm());
1516     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1517         JSValue arg = exec->uncheckedArgument(i);
1518         if (arg.isCell()
1519             && !arg.isObject()
1520             && !arg.isString()
1521             && !arg.isBigInt()) {
1522             dataLog(arg);
1523             continue;
1524         }
1525         String argStr = exec->uncheckedArgument(i).toWTFString(exec);
1526         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1527         dataLog(argStr);
1528     }
1529     if (addLineFeed)
1530         dataLog("\n");
1531     return JSValue::encode(jsUndefined());
1532 }
1533
1534 // Prints a series of comma separate strings without appending a newline.
1535 // Usage: $vm.dataLog(str1, str2, str3)
1536 static EncodedJSValue JSC_HOST_CALL functionDataLog(ExecState* exec)
1537 {
1538     const bool addLineFeed = false;
1539     return doPrint(exec, addLineFeed);
1540 }
1541
1542 // Prints a series of comma separate strings and appends a newline.
1543 // Usage: $vm.print(str1, str2, str3)
1544 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
1545 {
1546     const bool addLineFeed = true;
1547     return doPrint(exec, addLineFeed);
1548 }
1549
1550 // Dumps the current CallFrame.
1551 // Usage: $vm.dumpCallFrame()
1552 static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
1553 {
1554     // When the callers call this function, they are expecting to dump their
1555     // own frame. So skip 1 for this frame.
1556     VMInspector::dumpCallFrame(exec, 1);
1557     return JSValue::encode(jsUndefined());
1558 }
1559
1560 // Dumps the JS stack.
1561 // Usage: $vm.printStack()
1562 static EncodedJSValue JSC_HOST_CALL functionDumpStack(ExecState* exec)
1563 {
1564     // When the callers call this function, they are expecting to dump the
1565     // stack starting their own frame. So skip 1 for this frame.
1566     VMInspector::dumpStack(exec, 1);
1567     return JSValue::encode(jsUndefined());
1568 }
1569
1570 // Dumps the current CallFrame.
1571 // Usage: $vm.dumpRegisters(N) // dump the registers of the Nth CallFrame.
1572 // Usage: $vm.dumpRegisters() // dump the registers of the current CallFrame.
1573 // FIXME: Currently, this function dumps the physical frame. We should make
1574 // it dump the logical frame (i.e. be able to dump inlined frames as well).
1575 static EncodedJSValue JSC_HOST_CALL functionDumpRegisters(ExecState* exec)
1576 {
1577     unsigned requestedFrameIndex = 1;
1578     if (exec->argumentCount() >= 1) {
1579         JSValue value = exec->uncheckedArgument(0);
1580         if (!value.isUInt32())
1581             return JSValue::encode(jsUndefined());
1582
1583         // We need to inc the frame number because the caller would consider
1584         // its own frame as frame 0. Hence, we need discount the frame for this
1585         // function.
1586         requestedFrameIndex = value.asUInt32() + 1;
1587     }
1588
1589     unsigned frameIndex = 0;
1590     exec->iterate([&] (StackVisitor& visitor) {
1591         if (frameIndex++ != requestedFrameIndex)
1592             return StackVisitor::Continue;
1593         VMInspector::dumpRegisters(visitor->callFrame());
1594         return StackVisitor::Done;
1595     });
1596
1597     return encodedJSUndefined();
1598 }
1599
1600 // Dumps the internal memory layout of a JSCell.
1601 // Usage: $vm.dumpCell(cell)
1602 static EncodedJSValue JSC_HOST_CALL functionDumpCell(ExecState* exec)
1603 {
1604     JSValue value = exec->argument(0);
1605     if (!value.isCell())
1606         return encodedJSUndefined();
1607     
1608     VMInspector::dumpCellMemory(value.asCell());
1609     return encodedJSUndefined();
1610 }
1611
1612 // Gets the dataLog dump of the indexingMode of the passed value.
1613 // Usage: $vm.print("indexingMode = " + $vm.indexingMode(jsValue))
1614 static EncodedJSValue JSC_HOST_CALL functionIndexingMode(ExecState* exec)
1615 {
1616     if (!exec->argument(0).isObject())
1617         return encodedJSUndefined();
1618
1619     WTF::StringPrintStream stream;
1620     stream.print(IndexingTypeDump(exec->uncheckedArgument(0).getObject()->indexingMode()));
1621     return JSValue::encode(jsString(exec, stream.toString()));
1622 }
1623
1624 static EncodedJSValue JSC_HOST_CALL functionInlineCapacity(ExecState* exec)
1625 {
1626     VM& vm = exec->vm();
1627     if (auto* object = jsDynamicCast<JSObject*>(vm, exec->argument(0)))
1628         return JSValue::encode(jsNumber(object->structure(vm)->inlineCapacity()));
1629
1630     return encodedJSUndefined();
1631 }
1632
1633 // Gets the dataLog dump of a given JS value as a string.
1634 // Usage: $vm.print("value = " + $vm.value(jsValue))
1635 static EncodedJSValue JSC_HOST_CALL functionValue(ExecState* exec)
1636 {
1637     WTF::StringPrintStream stream;
1638     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1639         if (i)
1640             stream.print(", ");
1641         stream.print(exec->uncheckedArgument(i));
1642     }
1643     
1644     return JSValue::encode(jsString(exec, stream.toString()));
1645 }
1646
1647 // Gets the pid of the current process.
1648 // Usage: $vm.print("pid = " + $vm.getpid())
1649 static EncodedJSValue JSC_HOST_CALL functionGetPID(ExecState*)
1650 {
1651     return JSValue::encode(jsNumber(getCurrentProcessID()));
1652 }
1653
1654 static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
1655 {
1656     VM& vm = exec->vm();
1657     JSLockHolder lock(vm);
1658     JSValue target = exec->argument(0);
1659     if (!target.isObject())
1660         return JSValue::encode(jsUndefined());
1661     JSObject* jsTarget = asObject(target.asCell());
1662     Structure* structure = JSProxy::createStructure(vm, exec->lexicalGlobalObject(), jsTarget->getPrototypeDirect(vm), ImpureProxyType);
1663     JSProxy* proxy = JSProxy::create(vm, structure, jsTarget);
1664     return JSValue::encode(proxy);
1665 }
1666
1667 static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
1668 {
1669     JSLockHolder lock(exec);
1670     RuntimeArray* array = RuntimeArray::create(exec);
1671     return JSValue::encode(array);
1672 }
1673
1674 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
1675 {
1676     VM& vm = exec->vm();
1677     JSLockHolder lock(vm);
1678     JSValue target = exec->argument(0);
1679     JSObject* delegate = nullptr;
1680     if (target.isObject())
1681         delegate = asObject(target.asCell());
1682     Structure* structure = ImpureGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1683     ImpureGetter* result = ImpureGetter::create(vm, structure, delegate);
1684     return JSValue::encode(result);
1685 }
1686
1687 static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState* exec)
1688 {
1689     VM& vm = exec->vm();
1690     JSLockHolder lock(vm);
1691     Structure* structure = CustomGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1692     CustomGetter* result = CustomGetter::create(vm, structure);
1693     return JSValue::encode(result);
1694 }
1695
1696 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState* exec)
1697 {
1698     VM& vm = exec->vm();
1699     JSLockHolder lock(vm);
1700     Structure* structure = DOMJITNode::createStructure(vm, exec->lexicalGlobalObject(), DOMJITGetter::create(vm, DOMJITGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull())));
1701     DOMJITNode* result = DOMJITNode::create(vm, structure);
1702     return JSValue::encode(result);
1703 }
1704
1705 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState* exec)
1706 {
1707     VM& vm = exec->vm();
1708     JSLockHolder lock(vm);
1709     Structure* structure = DOMJITGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1710     DOMJITGetter* result = DOMJITGetter::create(vm, structure);
1711     return JSValue::encode(result);
1712 }
1713
1714 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState* exec)
1715 {
1716     VM& vm = exec->vm();
1717     JSLockHolder lock(vm);
1718     Structure* structure = DOMJITGetterComplex::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1719     DOMJITGetterComplex* result = DOMJITGetterComplex::create(vm, exec->lexicalGlobalObject(), structure);
1720     return JSValue::encode(result);
1721 }
1722
1723 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState* exec)
1724 {
1725     VM& vm = exec->vm();
1726     JSLockHolder lock(vm);
1727     Structure* structure = DOMJITFunctionObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1728     DOMJITFunctionObject* result = DOMJITFunctionObject::create(vm, exec->lexicalGlobalObject(), structure);
1729     return JSValue::encode(result);
1730 }
1731
1732 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITCheckSubClassObject(ExecState* exec)
1733 {
1734     VM& vm = exec->vm();
1735     JSLockHolder lock(vm);
1736     Structure* structure = DOMJITCheckSubClassObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1737     DOMJITCheckSubClassObject* result = DOMJITCheckSubClassObject::create(vm, exec->lexicalGlobalObject(), structure);
1738     return JSValue::encode(result);
1739 }
1740
1741 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterBaseJSObject(ExecState* exec)
1742 {
1743     VM& vm = exec->vm();
1744     JSLockHolder lock(vm);
1745     Structure* structure = DOMJITGetterBaseJSObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1746     DOMJITGetterBaseJSObject* result = DOMJITGetterBaseJSObject::create(vm, structure);
1747     return JSValue::encode(result);
1748 }
1749
1750 #if ENABLE(WEBASSEMBLY)
1751 static EncodedJSValue JSC_HOST_CALL functionCreateWasmStreamingParser(ExecState* exec)
1752 {
1753     VM& vm = exec->vm();
1754     JSLockHolder lock(vm);
1755     return JSValue::encode(WasmStreamingParser::create(vm, exec->lexicalGlobalObject()));
1756 }
1757 #endif
1758
1759 static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
1760 {
1761     VM& vm = exec->vm();
1762     JSLockHolder lock(vm);
1763     auto scope = DECLARE_THROW_SCOPE(vm);
1764
1765     JSValue base = exec->argument(0);
1766     if (!base.isObject())
1767         return JSValue::encode(jsUndefined());
1768     JSValue delegate = exec->argument(1);
1769     if (!delegate.isObject())
1770         return JSValue::encode(jsUndefined());
1771     ImpureGetter* impureGetter = jsDynamicCast<ImpureGetter*>(vm, asObject(base.asCell()));
1772     if (UNLIKELY(!impureGetter)) {
1773         throwTypeError(exec, scope, "argument is not an ImpureGetter"_s);
1774         return encodedJSValue();
1775     }
1776     impureGetter->setDelegate(vm, asObject(delegate.asCell()));
1777     return JSValue::encode(jsUndefined());
1778 }
1779
1780 static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
1781 {
1782     VM& vm = exec->vm();
1783     auto scope = DECLARE_THROW_SCOPE(vm);
1784
1785     if (exec->argumentCount() < 1 || !exec->argument(0).isString())
1786         return JSValue::encode(jsUndefined());
1787
1788     String functionText = asString(exec->argument(0))->value(exec);
1789     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1790
1791     const SourceCode& source = makeSource(functionText, { });
1792     JSFunction* func = JSFunction::create(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
1793
1794     return JSValue::encode(func);
1795 }
1796
1797 static EncodedJSValue JSC_HOST_CALL functionGetPrivateProperty(ExecState* exec)
1798 {
1799     VM& vm = exec->vm();
1800     auto scope = DECLARE_THROW_SCOPE(vm);
1801
1802     if (exec->argumentCount() < 2 || !exec->argument(1).isString())
1803         return encodedJSUndefined();
1804
1805     String str = asString(exec->argument(1))->value(exec);
1806
1807     const Identifier* ident = vm.propertyNames->lookUpPrivateName(Identifier::fromString(exec, str));
1808     if (!ident)
1809         return throwVMError(exec, scope, "Unknown private name.");
1810
1811     RELEASE_AND_RETURN(scope, JSValue::encode(exec->argument(0).get(exec, *ident)));
1812 }
1813
1814 static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
1815 {
1816     VM& vm = exec->vm();
1817     JSLockHolder lock(vm);
1818     return JSValue::encode(Root::create(vm, exec->lexicalGlobalObject()));
1819 }
1820
1821 static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
1822 {
1823     VM& vm = exec->vm();
1824     JSLockHolder lock(vm);
1825     auto scope = DECLARE_THROW_SCOPE(vm);
1826
1827     Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1828     if (!root)
1829         return JSValue::encode(throwException(exec, scope, createError(exec, "Cannot create Element without a Root."_s)));
1830     return JSValue::encode(Element::create(vm, exec->lexicalGlobalObject(), root));
1831 }
1832
1833 static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
1834 {
1835     VM& vm = exec->vm();
1836     JSLockHolder lock(vm);
1837     Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1838     if (!root)
1839         return JSValue::encode(jsUndefined());
1840     Element* result = root->element();
1841     return JSValue::encode(result ? result : jsUndefined());
1842 }
1843
1844 static EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState* exec)
1845 {
1846     VM& vm = exec->vm();
1847     JSLockHolder lock(vm);
1848     return JSValue::encode(SimpleObject::create(vm, exec->lexicalGlobalObject()));
1849 }
1850
1851 static EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState* exec)
1852 {
1853     VM& vm = exec->vm();
1854     JSLockHolder lock(vm);
1855     auto scope = DECLARE_THROW_SCOPE(vm);
1856
1857     SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
1858     if (UNLIKELY(!simpleObject)) {
1859         throwTypeError(exec, scope, "Invalid use of getHiddenValue test function"_s);
1860         return encodedJSValue();
1861     }
1862     return JSValue::encode(simpleObject->hiddenValue());
1863 }
1864
1865 static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState* exec)
1866 {
1867     VM& vm = exec->vm();
1868     JSLockHolder lock(vm);
1869     auto scope = DECLARE_THROW_SCOPE(vm);
1870
1871     SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
1872     if (UNLIKELY(!simpleObject)) {
1873         throwTypeError(exec, scope, "Invalid use of setHiddenValue test function"_s);
1874         return encodedJSValue();
1875     }
1876     JSValue value = exec->argument(1);
1877     simpleObject->setHiddenValue(vm, value);
1878     return JSValue::encode(jsUndefined());
1879 }
1880
1881 static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState* exec)
1882 {
1883     VM& vm = exec->vm();
1884     return JSValue::encode(vm.shadowChicken().functionsOnStack(exec));
1885 }
1886
1887 static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState* exec)
1888 {
1889     VM& vm = exec->vm();
1890     vm.setGlobalConstRedeclarationShouldThrow(false);
1891     return JSValue::encode(jsUndefined());
1892 }
1893
1894 static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
1895 {
1896     VM& vm = exec->vm();
1897     RELEASE_ASSERT(vm.typeProfiler());
1898     vm.typeProfilerLog()->processLogEntries("jsc Testing API: functionFindTypeForExpression"_s);
1899
1900     JSValue functionValue = exec->argument(0);
1901     RELEASE_ASSERT(functionValue.isFunction(vm));
1902     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1903
1904     RELEASE_ASSERT(exec->argument(1).isString());
1905     String substring = asString(exec->argument(1))->value(exec);
1906     String sourceCodeText = executable->source().view().toString();
1907     unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
1908     
1909     String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), vm);
1910     return JSValue::encode(JSONParse(exec, jsonString));
1911 }
1912
1913 static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
1914 {
1915     VM& vm = exec->vm();
1916     RELEASE_ASSERT(vm.typeProfiler());
1917     vm.typeProfilerLog()->processLogEntries("jsc Testing API: functionReturnTypeFor"_s);
1918
1919     JSValue functionValue = exec->argument(0);
1920     RELEASE_ASSERT(functionValue.isFunction(vm));
1921     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1922
1923     unsigned offset = executable->typeProfilingStartOffset();
1924     String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), vm);
1925     return JSValue::encode(JSONParse(exec, jsonString));
1926 }
1927
1928 static EncodedJSValue JSC_HOST_CALL functionFlattenDictionaryObject(ExecState* exec)
1929 {
1930     VM& vm = exec->vm();
1931     JSValue value = exec->argument(0);
1932     RELEASE_ASSERT(value.isObject() && value.getObject()->structure()->isDictionary());
1933     value.getObject()->flattenDictionaryObject(vm);
1934     return encodedJSUndefined();
1935 }
1936
1937 static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
1938 {
1939     VM& vm = exec->vm();
1940     RELEASE_ASSERT(vm.controlFlowProfiler());
1941     vm.controlFlowProfiler()->dumpData();
1942     return JSValue::encode(jsUndefined());
1943 }
1944
1945 static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
1946 {
1947     VM& vm = exec->vm();
1948     RELEASE_ASSERT(vm.controlFlowProfiler());
1949
1950     JSValue functionValue = exec->argument(0);
1951     RELEASE_ASSERT(functionValue.isFunction(vm));
1952     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1953
1954     RELEASE_ASSERT(exec->argument(1).isString());
1955     String substring = asString(exec->argument(1))->value(exec);
1956     String sourceCodeText = executable->source().view().toString();
1957     RELEASE_ASSERT(sourceCodeText.contains(substring));
1958     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1959     
1960     bool hasExecuted = vm.controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), vm);
1961     return JSValue::encode(jsBoolean(hasExecuted));
1962 }
1963
1964 static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState* exec)
1965 {
1966     VM& vm = exec->vm();
1967     RELEASE_ASSERT(vm.controlFlowProfiler());
1968
1969     JSValue functionValue = exec->argument(0);
1970     RELEASE_ASSERT(functionValue.isFunction(vm));
1971     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1972
1973     RELEASE_ASSERT(exec->argument(1).isString());
1974     String substring = asString(exec->argument(1))->value(exec);
1975     String sourceCodeText = executable->source().view().toString();
1976     RELEASE_ASSERT(sourceCodeText.contains(substring));
1977     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1978     
1979     size_t executionCount = vm.controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), vm);
1980     return JSValue::encode(JSValue(executionCount));
1981 }
1982
1983 static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
1984 {
1985     Options::useExceptionFuzz() = true;
1986     return JSValue::encode(jsUndefined());
1987 }
1988
1989 static EncodedJSValue changeDebuggerModeWhenIdle(ExecState* exec, DebuggerMode mode)
1990 {
1991     bool newDebuggerMode = (mode == DebuggerOn);
1992     if (Options::forceDebuggerBytecodeGeneration() == newDebuggerMode)
1993         return JSValue::encode(jsUndefined());
1994
1995     VM* vm = &exec->vm();
1996     vm->whenIdle([=] () {
1997         Options::forceDebuggerBytecodeGeneration() = newDebuggerMode;
1998         vm->deleteAllCode(PreventCollectionAndDeleteAllCode);
1999     });
2000     return JSValue::encode(jsUndefined());
2001 }
2002
2003 static EncodedJSValue JSC_HOST_CALL functionEnableDebuggerModeWhenIdle(ExecState* exec)
2004 {
2005     return changeDebuggerModeWhenIdle(exec, DebuggerOn);
2006 }
2007
2008 static EncodedJSValue JSC_HOST_CALL functionDisableDebuggerModeWhenIdle(ExecState* exec)
2009 {
2010     return changeDebuggerModeWhenIdle(exec, DebuggerOff);
2011 }
2012
2013 static EncodedJSValue JSC_HOST_CALL functionGlobalObjectCount(ExecState* exec)
2014 {
2015     return JSValue::encode(jsNumber(exec->vm().heap.globalObjectCount()));
2016 }
2017
2018 static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState* exec)
2019 {
2020     JSValue value = exec->argument(0);
2021     RELEASE_ASSERT(value.isObject());
2022     JSGlobalObject* globalObject = jsCast<JSObject*>(value)->globalObject(exec->vm());
2023     RELEASE_ASSERT(globalObject);
2024     return JSValue::encode(globalObject);
2025 }
2026
2027 static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
2028 {
2029     JSValue value = exec->argument(0);
2030     if (!value.isObject())
2031         return JSValue::encode(jsUndefined());
2032
2033     JSValue property = exec->argument(1);
2034     if (!property.isString())
2035         return JSValue::encode(jsUndefined());
2036
2037     PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
2038     value.getPropertySlot(exec, asString(property)->toIdentifier(exec), slot);
2039
2040     JSValue result;
2041     if (slot.isCacheableGetter())
2042         result = slot.getterSetter();
2043     else
2044         result = jsNull();
2045
2046     return JSValue::encode(result);
2047 }
2048
2049 static EncodedJSValue JSC_HOST_CALL functionLoadGetterFromGetterSetter(ExecState* exec)
2050 {
2051     VM& vm = exec->vm();
2052     auto scope = DECLARE_THROW_SCOPE(vm);
2053
2054     GetterSetter* getterSetter = jsDynamicCast<GetterSetter*>(vm, exec->argument(0));
2055     if (UNLIKELY(!getterSetter)) {
2056         throwTypeError(exec, scope, "Invalid use of loadGetterFromGetterSetter test function: argument is not a GetterSetter"_s);
2057         return encodedJSValue();
2058     }
2059
2060     JSObject* getter = getterSetter->getter();
2061     RELEASE_ASSERT(getter);
2062     return JSValue::encode(getter);
2063 }
2064
2065 static EncodedJSValue JSC_HOST_CALL functionCreateCustomTestGetterSetter(ExecState* exec)
2066 {
2067     VM& vm = exec->vm();
2068     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2069     return JSValue::encode(JSTestCustomGetterSetter::create(vm, globalObject, JSTestCustomGetterSetter::createStructure(vm, globalObject)));
2070 }
2071
2072 static EncodedJSValue JSC_HOST_CALL functionDeltaBetweenButterflies(ExecState* exec)
2073 {
2074     VM& vm = exec->vm();
2075     JSObject* a = jsDynamicCast<JSObject*>(vm, exec->argument(0));
2076     JSObject* b = jsDynamicCast<JSObject*>(vm, exec->argument(1));
2077     if (!a || !b)
2078         return JSValue::encode(jsNumber(PNaN));
2079
2080     ptrdiff_t delta = bitwise_cast<char*>(a->butterfly()) - bitwise_cast<char*>(b->butterfly());
2081     if (delta < 0)
2082         return JSValue::encode(jsNumber(PNaN));
2083     if (delta > std::numeric_limits<int32_t>::max())
2084         return JSValue::encode(jsNumber(PNaN));
2085     return JSValue::encode(jsNumber(static_cast<int32_t>(delta)));
2086 }
2087
2088 static EncodedJSValue JSC_HOST_CALL functionTotalGCTime(ExecState* exec)
2089 {
2090     VM& vm = exec->vm();
2091     return JSValue::encode(jsNumber(vm.heap.totalGCTime().seconds()));
2092 }
2093
2094 void JSDollarVM::finishCreation(VM& vm)
2095 {
2096     Base::finishCreation(vm);
2097
2098     JSGlobalObject* globalObject = this->globalObject(vm);
2099
2100     auto addFunction = [&] (VM& vm, const char* name, NativeFunction function, unsigned arguments) {
2101         JSDollarVM::addFunction(vm, globalObject, name, function, arguments);
2102     };
2103     auto addConstructibleFunction = [&] (VM& vm, const char* name, NativeFunction function, unsigned arguments) {
2104         JSDollarVM::addConstructibleFunction(vm, globalObject, name, function, arguments);
2105     };
2106
2107     addFunction(vm, "abort", functionCrash, 0);
2108     addFunction(vm, "crash", functionCrash, 0);
2109     addFunction(vm, "breakpoint", functionBreakpoint, 0);
2110
2111     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
2112     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "ftlTrue"), 0, functionFTLTrue, FTLTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
2113
2114     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuMfence"), 0, functionCpuMfence, CPUMfenceIntrinsic, 0);
2115     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuRdtsc"), 0, functionCpuRdtsc, CPURdtscIntrinsic, 0);
2116     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuCpuid"), 0, functionCpuCpuid, CPUCpuidIntrinsic, 0);
2117     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuPause"), 0, functionCpuPause, CPUPauseIntrinsic, 0);
2118     addFunction(vm, "cpuClflush", functionCpuClflush, 2);
2119
2120     addFunction(vm, "llintTrue", functionLLintTrue, 0);
2121     addFunction(vm, "jitTrue", functionJITTrue, 0);
2122
2123     addFunction(vm, "noInline", functionNoInline, 1);
2124
2125     addFunction(vm, "gc", functionGC, 0);
2126     addFunction(vm, "edenGC", functionEdenGC, 0);
2127
2128     addFunction(vm, "callFrame", functionCallFrame, 1);
2129     addFunction(vm, "codeBlockFor", functionCodeBlockFor, 1);
2130     addFunction(vm, "codeBlockForFrame", functionCodeBlockForFrame, 1);
2131     addFunction(vm, "dumpSourceFor", functionDumpSourceFor, 1);
2132     addFunction(vm, "dumpBytecodeFor", functionDumpBytecodeFor, 1);
2133
2134     addFunction(vm, "dataLog", functionDataLog, 1);
2135     addFunction(vm, "print", functionPrint, 1);
2136     addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
2137     addFunction(vm, "dumpStack", functionDumpStack, 0);
2138     addFunction(vm, "dumpRegisters", functionDumpRegisters, 1);
2139
2140     addFunction(vm, "dumpCell", functionDumpCell, 1);
2141
2142     addFunction(vm, "indexingMode", functionIndexingMode, 1);
2143     addFunction(vm, "inlineCapacity", functionInlineCapacity, 1);
2144     addFunction(vm, "value", functionValue, 1);
2145     addFunction(vm, "getpid", functionGetPID, 0);
2146
2147     addFunction(vm, "createProxy", functionCreateProxy, 1);
2148     addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
2149
2150     addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
2151     addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
2152     addFunction(vm, "createDOMJITNodeObject", functionCreateDOMJITNodeObject, 0);
2153     addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0);
2154     addFunction(vm, "createDOMJITGetterComplexObject", functionCreateDOMJITGetterComplexObject, 0);
2155     addFunction(vm, "createDOMJITFunctionObject", functionCreateDOMJITFunctionObject, 0);
2156     addFunction(vm, "createDOMJITCheckSubClassObject", functionCreateDOMJITCheckSubClassObject, 0);
2157     addFunction(vm, "createDOMJITGetterBaseJSObject", functionCreateDOMJITGetterBaseJSObject, 0);
2158     addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
2159 #if ENABLE(WEBASSEMBLY)
2160     addFunction(vm, "createWasmStreamingParser", functionCreateWasmStreamingParser, 0);
2161 #endif
2162     addFunction(vm, "getPrivateProperty", functionGetPrivateProperty, 2);
2163     addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
2164
2165     addConstructibleFunction(vm, "Root", functionCreateRoot, 0);
2166     addConstructibleFunction(vm, "Element", functionCreateElement, 1);
2167     addFunction(vm, "getElement", functionGetElement, 1);
2168
2169     addConstructibleFunction(vm, "SimpleObject", functionCreateSimpleObject, 0);
2170     addFunction(vm, "getHiddenValue", functionGetHiddenValue, 1);
2171     addFunction(vm, "setHiddenValue", functionSetHiddenValue, 2);
2172
2173     addFunction(vm, "shadowChickenFunctionsOnStack", functionShadowChickenFunctionsOnStack, 0);
2174     addFunction(vm, "setGlobalConstRedeclarationShouldNotThrow", functionSetGlobalConstRedeclarationShouldNotThrow, 0);
2175
2176     addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
2177     addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
2178
2179     addFunction(vm, "flattenDictionaryObject", functionFlattenDictionaryObject, 1);
2180
2181     addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
2182     addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
2183     addFunction(vm, "basicBlockExecutionCount", functionBasicBlockExecutionCount, 2);
2184
2185     addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
2186
2187     addFunction(vm, "enableDebuggerModeWhenIdle", functionEnableDebuggerModeWhenIdle, 0);
2188     addFunction(vm, "disableDebuggerModeWhenIdle", functionDisableDebuggerModeWhenIdle, 0);
2189
2190     addFunction(vm, "globalObjectCount", functionGlobalObjectCount, 0);
2191     addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1);
2192
2193     addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
2194     addFunction(vm, "loadGetterFromGetterSetter", functionLoadGetterFromGetterSetter, 1);
2195     addFunction(vm, "createCustomTestGetterSetter", functionCreateCustomTestGetterSetter, 1);
2196
2197     addFunction(vm, "deltaBetweenButterflies", functionDeltaBetweenButterflies, 2);
2198     
2199     addFunction(vm, "totalGCTime", functionTotalGCTime, 0);
2200 }
2201
2202 void JSDollarVM::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
2203 {
2204     Identifier identifier = Identifier::fromString(&vm, name);
2205     putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function));
2206 }
2207
2208 void JSDollarVM::addConstructibleFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
2209 {
2210     Identifier identifier = Identifier::fromString(&vm, name);
2211     putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function, NoIntrinsic, function));
2212 }
2213
2214 } // namespace JSC