[WebAssembly] Parse wasm modules in a streaming fashion
[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         scope.release();
1156         return JSValue::encode(jsBoolean(false));
1157     }
1158     auto data = getWasmBufferFromValue(exec, exec->argument(0));
1159     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1160     scope.release();
1161     return JSValue::encode(jsNumber(static_cast<int32_t>(thisObject->streamingParser().addBytes(bitwise_cast<const uint8_t*>(data.first), data.second))));
1162 }
1163
1164 EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserFinalize(ExecState* exec)
1165 {
1166     VM& vm = exec->vm();
1167     auto* thisObject = jsDynamicCast<WasmStreamingParser*>(vm, exec->thisValue());
1168     if (!thisObject)
1169         return JSValue::encode(jsBoolean(false));
1170     return JSValue::encode(jsNumber(static_cast<int32_t>(thisObject->streamingParser().finalize())));
1171 }
1172
1173 #endif
1174
1175 } // namespace
1176
1177 namespace JSC {
1178
1179 const ClassInfo JSDollarVM::s_info = { "DollarVM", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVM) };
1180
1181 // Triggers a crash immediately.
1182 // Usage: $vm.crash()
1183 static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionCrash(ExecState*)
1184 {
1185     CRASH();
1186 }
1187
1188 // Executes a breakpoint instruction if the first argument is truthy or is unset.
1189 // Usage: $vm.breakpoint(<condition>)
1190 static EncodedJSValue JSC_HOST_CALL functionBreakpoint(ExecState* exec)
1191 {
1192     // Nothing should throw here but we might as well double check...
1193     VM& vm = exec->vm();
1194     auto scope = DECLARE_CATCH_SCOPE(vm);
1195     UNUSED_PARAM(scope);
1196     if (!exec->argumentCount() || exec->argument(0).toBoolean(exec))
1197         WTFBreakpointTrap();
1198
1199     return encodedJSUndefined();
1200 }
1201
1202 // Returns true if the current frame is a DFG frame.
1203 // Usage: isDFG = $vm.dfgTrue()
1204 static EncodedJSValue JSC_HOST_CALL functionDFGTrue(ExecState*)
1205 {
1206     return JSValue::encode(jsBoolean(false));
1207 }
1208
1209 // Returns true if the current frame is a FTL frame.
1210 // Usage: isFTL = $vm.ftlTrue()
1211 static EncodedJSValue JSC_HOST_CALL functionFTLTrue(ExecState*)
1212 {
1213     return JSValue::encode(jsBoolean(false));
1214 }
1215
1216 static EncodedJSValue JSC_HOST_CALL functionCpuMfence(ExecState*)
1217 {
1218 #if CPU(X86_64) && !OS(WINDOWS)
1219     asm volatile("mfence" ::: "memory");
1220 #endif
1221     return JSValue::encode(jsUndefined());
1222 }
1223
1224 static EncodedJSValue JSC_HOST_CALL functionCpuRdtsc(ExecState*)
1225 {
1226 #if CPU(X86_64) && !OS(WINDOWS)
1227     unsigned high;
1228     unsigned low;
1229     asm volatile ("rdtsc" : "=a"(low), "=d"(high));
1230     return JSValue::encode(jsNumber(low));
1231 #else
1232     return JSValue::encode(jsNumber(0));
1233 #endif
1234 }
1235
1236 static EncodedJSValue JSC_HOST_CALL functionCpuCpuid(ExecState*)
1237 {
1238 #if CPU(X86_64) && !OS(WINDOWS)
1239     WTF::x86_cpuid();
1240 #endif
1241     return JSValue::encode(jsUndefined());
1242 }
1243
1244 static EncodedJSValue JSC_HOST_CALL functionCpuPause(ExecState*)
1245 {
1246 #if CPU(X86_64) && !OS(WINDOWS)
1247     asm volatile ("pause" ::: "memory");
1248 #endif
1249     return JSValue::encode(jsUndefined());
1250 }
1251
1252 // This takes either a JSArrayBuffer, JSArrayBufferView*, or any other object as its first
1253 // argument. The second argument is expected to be an integer.
1254 //
1255 // If the first argument is a JSArrayBuffer, it'll clflush on that buffer
1256 // plus the second argument as a byte offset. It'll also flush on the object
1257 // itself so its length, etc, aren't in the cache.
1258 //
1259 // If the first argument is not a JSArrayBuffer, we load the butterfly
1260 // and clflush at the address of the butterfly.
1261 static EncodedJSValue JSC_HOST_CALL functionCpuClflush(ExecState* exec)
1262 {
1263 #if CPU(X86_64) && !OS(WINDOWS)
1264     VM& vm = exec->vm();
1265
1266     if (!exec->argument(1).isInt32())
1267         return JSValue::encode(jsBoolean(false));
1268
1269     auto clflush = [] (void* ptr) {
1270         char* ptrToFlush = static_cast<char*>(ptr);
1271         asm volatile ("clflush %0" :: "m"(*ptrToFlush) : "memory");
1272     };
1273
1274     Vector<void*> toFlush;
1275
1276     uint32_t offset = exec->argument(1).asUInt32();
1277
1278     if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(vm, exec->argument(0)))
1279         toFlush.append(bitwise_cast<char*>(view->vector()) + offset);
1280     else if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0))) {
1281         switch (object->indexingType()) {
1282         case ALL_INT32_INDEXING_TYPES:
1283         case ALL_CONTIGUOUS_INDEXING_TYPES:
1284         case ALL_DOUBLE_INDEXING_TYPES:
1285             toFlush.append(bitwise_cast<char*>(object->butterfly()) + Butterfly::offsetOfVectorLength());
1286             toFlush.append(bitwise_cast<char*>(object->butterfly()) + Butterfly::offsetOfPublicLength());
1287         }
1288     }
1289
1290     if (!toFlush.size())
1291         return JSValue::encode(jsBoolean(false));
1292
1293     for (void* ptr : toFlush)
1294         clflush(ptr);
1295     return JSValue::encode(jsBoolean(true));
1296 #else
1297     UNUSED_PARAM(exec);
1298     return JSValue::encode(jsBoolean(false));
1299 #endif
1300 }
1301
1302 class CallerFrameJITTypeFunctor {
1303 public:
1304     CallerFrameJITTypeFunctor()
1305         : m_currentFrame(0)
1306         , m_jitType(JITCode::None)
1307     {
1308     }
1309
1310     StackVisitor::Status operator()(StackVisitor& visitor) const
1311     {
1312         if (m_currentFrame++ > 1) {
1313             m_jitType = visitor->codeBlock()->jitType();
1314             return StackVisitor::Done;
1315         }
1316         return StackVisitor::Continue;
1317     }
1318     
1319     JITCode::JITType jitType() { return m_jitType; }
1320
1321 private:
1322     mutable unsigned m_currentFrame;
1323     mutable JITCode::JITType m_jitType;
1324 };
1325
1326 static FunctionExecutable* getExecutableForFunction(JSValue theFunctionValue)
1327 {
1328     if (!theFunctionValue.isCell())
1329         return nullptr;
1330     
1331     VM& vm = *theFunctionValue.asCell()->vm();
1332     JSFunction* theFunction = jsDynamicCast<JSFunction*>(vm, theFunctionValue);
1333     if (!theFunction)
1334         return nullptr;
1335     
1336     FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(vm,
1337         theFunction->executable());
1338
1339     return executable;
1340 }
1341
1342 // Returns true if the current frame is a LLInt frame.
1343 // Usage: isLLInt = $vm.llintTrue()
1344 static EncodedJSValue JSC_HOST_CALL functionLLintTrue(ExecState* exec)
1345 {
1346     if (!exec)
1347         return JSValue::encode(jsUndefined());
1348     CallerFrameJITTypeFunctor functor;
1349     exec->iterate(functor);
1350     return JSValue::encode(jsBoolean(functor.jitType() == JITCode::InterpreterThunk));
1351 }
1352
1353 // Returns true if the current frame is a baseline JIT frame.
1354 // Usage: isBaselineJIT = $vm.jitTrue()
1355 static EncodedJSValue JSC_HOST_CALL functionJITTrue(ExecState* exec)
1356 {
1357     if (!exec)
1358         return JSValue::encode(jsUndefined());
1359     CallerFrameJITTypeFunctor functor;
1360     exec->iterate(functor);
1361     return JSValue::encode(jsBoolean(functor.jitType() == JITCode::BaselineJIT));
1362 }
1363
1364 // Set that the argument function should not be inlined.
1365 // Usage:
1366 // function f() { };
1367 // $vm.noInline(f);
1368 static EncodedJSValue JSC_HOST_CALL functionNoInline(ExecState* exec)
1369 {
1370     if (exec->argumentCount() < 1)
1371         return JSValue::encode(jsUndefined());
1372     
1373     JSValue theFunctionValue = exec->uncheckedArgument(0);
1374
1375     if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue))
1376         executable->setNeverInline(true);
1377     
1378     return JSValue::encode(jsUndefined());
1379 }
1380
1381 // Runs a full GC synchronously.
1382 // Usage: $vm.gc()
1383 static EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
1384 {
1385     VMInspector::gc(exec);
1386     return JSValue::encode(jsUndefined());
1387 }
1388
1389 // Runs the edenGC synchronously.
1390 // Usage: $vm.edenGC()
1391 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1392 {
1393     VMInspector::edenGC(exec);
1394     return JSValue::encode(jsUndefined());
1395 }
1396
1397 // Gets a JSDollarVMCallFrame for a specified frame index.
1398 // Usage: var callFrame = $vm.callFrame(0) // frame 0 is the top frame.
1399 // Usage: var callFrame = $vm.callFrame() // implies frame 0 i.e. current frame.
1400 //
1401 // This gives you the ability to query the following:
1402 //    callFrame.valid; // false if we asked for a frame beyond the end of the stack, else true.
1403 //    callFrame.callee;
1404 //    callFrame.codeBlock;
1405 //    callFrame.unlinkedCodeBlock;
1406 //    callFrame.executable;
1407 //
1408 // Note: you cannot toString() a codeBlock, unlinkedCodeBlock, or executable because
1409 // there are internal objects and not a JS object. Hence, you cannot do string
1410 // concatenation with them.
1411 static EncodedJSValue JSC_HOST_CALL functionCallFrame(ExecState* exec)
1412 {
1413     unsigned frameNumber = 1;
1414     if (exec->argumentCount() >= 1) {
1415         JSValue value = exec->uncheckedArgument(0);
1416         if (!value.isUInt32())
1417             return JSValue::encode(jsUndefined());
1418
1419         // We need to inc the frame number because the caller would consider
1420         // its own frame as frame 0. Hence, we need discount the frame for this
1421         // function.
1422         frameNumber = value.asUInt32() + 1;
1423     }
1424
1425     return JSValue::encode(JSDollarVMCallFrame::create(exec, frameNumber));
1426 }
1427
1428 // Gets a token for the CodeBlock for a specified frame index.
1429 // Usage: codeBlockToken = $vm.codeBlockForFrame(0) // frame 0 is the top frame.
1430 // Usage: codeBlockToken = $vm.codeBlockForFrame() // implies frame 0 i.e. current frame.
1431 static EncodedJSValue JSC_HOST_CALL functionCodeBlockForFrame(ExecState* exec)
1432 {
1433     unsigned frameNumber = 1;
1434     if (exec->argumentCount() >= 1) {
1435         JSValue value = exec->uncheckedArgument(0);
1436         if (!value.isUInt32())
1437             return JSValue::encode(jsUndefined());
1438
1439         // We need to inc the frame number because the caller would consider
1440         // its own frame as frame 0. Hence, we need discount the frame for this
1441         // function.
1442         frameNumber = value.asUInt32() + 1;
1443     }
1444
1445     CodeBlock* codeBlock = VMInspector::codeBlockForFrame(exec, frameNumber);
1446     if (codeBlock)
1447         return JSValue::encode(codeBlock);
1448     return JSValue::encode(jsUndefined());
1449 }
1450
1451 static CodeBlock* codeBlockFromArg(ExecState* exec)
1452 {
1453     VM& vm = exec->vm();
1454     if (exec->argumentCount() < 1)
1455         return nullptr;
1456
1457     JSValue value = exec->uncheckedArgument(0);
1458     CodeBlock* candidateCodeBlock = nullptr;
1459     if (value.isCell()) {
1460         JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell());
1461         if (func) {
1462             if (func->isHostFunction())
1463                 candidateCodeBlock = nullptr;
1464             else
1465                 candidateCodeBlock = func->jsExecutable()->eitherCodeBlock();
1466         } else
1467             candidateCodeBlock = reinterpret_cast<CodeBlock*>(value.asCell());
1468     }
1469
1470     if (candidateCodeBlock && VMInspector::isValidCodeBlock(exec, candidateCodeBlock))
1471         return candidateCodeBlock;
1472
1473     if (candidateCodeBlock)
1474         dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n");
1475     else
1476         dataLog("Invalid codeBlock: ", value, "\n");
1477     return nullptr;
1478 }
1479
1480 // Usage: $vm.print("codeblock = ", $vm.codeBlockFor(functionObj))
1481 // Usage: $vm.print("codeblock = ", $vm.codeBlockFor(codeBlockToken))
1482 // Note: you cannot toString() a codeBlock because it's an internal object and not
1483 // a JS object. Hence, you cannot do string concatenation with it.
1484 static EncodedJSValue JSC_HOST_CALL functionCodeBlockFor(ExecState* exec)
1485 {
1486     CodeBlock* codeBlock = codeBlockFromArg(exec);
1487     WTF::StringPrintStream stream;
1488     if (codeBlock) {
1489         stream.print(*codeBlock);
1490         return JSValue::encode(jsString(exec, stream.toString()));
1491     }
1492     return JSValue::encode(jsUndefined());
1493 }
1494
1495 // Usage: $vm.dumpSourceFor(functionObj)
1496 // Usage: $vm.dumpSourceFor(codeBlockToken)
1497 static EncodedJSValue JSC_HOST_CALL functionDumpSourceFor(ExecState* exec)
1498 {
1499     CodeBlock* codeBlock = codeBlockFromArg(exec);
1500     if (codeBlock)
1501         codeBlock->dumpSource();
1502     return JSValue::encode(jsUndefined());
1503 }
1504
1505 // Usage: $vm.dumpBytecodeFor(functionObj)
1506 // Usage: $vm.dumpBytecodeFor(codeBlock)
1507 static EncodedJSValue JSC_HOST_CALL functionDumpBytecodeFor(ExecState* exec)
1508 {
1509     CodeBlock* codeBlock = codeBlockFromArg(exec);
1510     if (codeBlock)
1511         codeBlock->dumpBytecode();
1512     return JSValue::encode(jsUndefined());
1513 }
1514
1515 static EncodedJSValue doPrint(ExecState* exec, bool addLineFeed)
1516 {
1517     auto scope = DECLARE_THROW_SCOPE(exec->vm());
1518     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1519         JSValue arg = exec->uncheckedArgument(i);
1520         if (arg.isCell()
1521             && !arg.isObject()
1522             && !arg.isString()
1523             && !arg.isBigInt()) {
1524             dataLog(arg);
1525             continue;
1526         }
1527         String argStr = exec->uncheckedArgument(i).toWTFString(exec);
1528         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1529         dataLog(argStr);
1530     }
1531     if (addLineFeed)
1532         dataLog("\n");
1533     return JSValue::encode(jsUndefined());
1534 }
1535
1536 // Prints a series of comma separate strings without appending a newline.
1537 // Usage: $vm.dataLog(str1, str2, str3)
1538 static EncodedJSValue JSC_HOST_CALL functionDataLog(ExecState* exec)
1539 {
1540     const bool addLineFeed = false;
1541     return doPrint(exec, addLineFeed);
1542 }
1543
1544 // Prints a series of comma separate strings and appends a newline.
1545 // Usage: $vm.print(str1, str2, str3)
1546 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
1547 {
1548     const bool addLineFeed = true;
1549     return doPrint(exec, addLineFeed);
1550 }
1551
1552 // Dumps the current CallFrame.
1553 // Usage: $vm.dumpCallFrame()
1554 static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
1555 {
1556     // When the callers call this function, they are expecting to dump their
1557     // own frame. So skip 1 for this frame.
1558     VMInspector::dumpCallFrame(exec, 1);
1559     return JSValue::encode(jsUndefined());
1560 }
1561
1562 // Dumps the JS stack.
1563 // Usage: $vm.printStack()
1564 static EncodedJSValue JSC_HOST_CALL functionDumpStack(ExecState* exec)
1565 {
1566     // When the callers call this function, they are expecting to dump the
1567     // stack starting their own frame. So skip 1 for this frame.
1568     VMInspector::dumpStack(exec, 1);
1569     return JSValue::encode(jsUndefined());
1570 }
1571
1572 // Dumps the internal memory layout of a JSCell.
1573 // Usage: $vm.dumpCell(cell)
1574 static EncodedJSValue JSC_HOST_CALL functionDumpCell(ExecState* exec)
1575 {
1576     JSValue value = exec->argument(0);
1577     if (!value.isCell())
1578         return encodedJSUndefined();
1579     
1580     VMInspector::dumpCellMemory(value.asCell());
1581     return encodedJSUndefined();
1582 }
1583
1584 // Gets the dataLog dump of the indexingMode of the passed value.
1585 // Usage: $vm.print("indexingMode = " + $vm.indexingMode(jsValue))
1586 static EncodedJSValue JSC_HOST_CALL functionIndexingMode(ExecState* exec)
1587 {
1588     if (!exec->argument(0).isObject())
1589         return encodedJSUndefined();
1590
1591     WTF::StringPrintStream stream;
1592     stream.print(IndexingTypeDump(exec->uncheckedArgument(0).getObject()->indexingMode()));
1593     return JSValue::encode(jsString(exec, stream.toString()));
1594 }
1595
1596 static EncodedJSValue JSC_HOST_CALL functionInlineCapacity(ExecState* exec)
1597 {
1598     VM& vm = exec->vm();
1599     if (auto* object = jsDynamicCast<JSObject*>(vm, exec->argument(0)))
1600         return JSValue::encode(jsNumber(object->structure(vm)->inlineCapacity()));
1601
1602     return encodedJSUndefined();
1603 }
1604
1605 // Gets the dataLog dump of a given JS value as a string.
1606 // Usage: $vm.print("value = " + $vm.value(jsValue))
1607 static EncodedJSValue JSC_HOST_CALL functionValue(ExecState* exec)
1608 {
1609     WTF::StringPrintStream stream;
1610     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1611         if (i)
1612             stream.print(", ");
1613         stream.print(exec->uncheckedArgument(i));
1614     }
1615     
1616     return JSValue::encode(jsString(exec, stream.toString()));
1617 }
1618
1619 // Gets the pid of the current process.
1620 // Usage: $vm.print("pid = " + $vm.getpid())
1621 static EncodedJSValue JSC_HOST_CALL functionGetPID(ExecState*)
1622 {
1623     return JSValue::encode(jsNumber(getCurrentProcessID()));
1624 }
1625
1626 static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
1627 {
1628     VM& vm = exec->vm();
1629     JSLockHolder lock(vm);
1630     JSValue target = exec->argument(0);
1631     if (!target.isObject())
1632         return JSValue::encode(jsUndefined());
1633     JSObject* jsTarget = asObject(target.asCell());
1634     Structure* structure = JSProxy::createStructure(vm, exec->lexicalGlobalObject(), jsTarget->getPrototypeDirect(vm), ImpureProxyType);
1635     JSProxy* proxy = JSProxy::create(vm, structure, jsTarget);
1636     return JSValue::encode(proxy);
1637 }
1638
1639 static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
1640 {
1641     JSLockHolder lock(exec);
1642     RuntimeArray* array = RuntimeArray::create(exec);
1643     return JSValue::encode(array);
1644 }
1645
1646 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
1647 {
1648     VM& vm = exec->vm();
1649     JSLockHolder lock(vm);
1650     JSValue target = exec->argument(0);
1651     JSObject* delegate = nullptr;
1652     if (target.isObject())
1653         delegate = asObject(target.asCell());
1654     Structure* structure = ImpureGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1655     ImpureGetter* result = ImpureGetter::create(vm, structure, delegate);
1656     return JSValue::encode(result);
1657 }
1658
1659 static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState* exec)
1660 {
1661     VM& vm = exec->vm();
1662     JSLockHolder lock(vm);
1663     Structure* structure = CustomGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1664     CustomGetter* result = CustomGetter::create(vm, structure);
1665     return JSValue::encode(result);
1666 }
1667
1668 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState* exec)
1669 {
1670     VM& vm = exec->vm();
1671     JSLockHolder lock(vm);
1672     Structure* structure = DOMJITNode::createStructure(vm, exec->lexicalGlobalObject(), DOMJITGetter::create(vm, DOMJITGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull())));
1673     DOMJITNode* result = DOMJITNode::create(vm, structure);
1674     return JSValue::encode(result);
1675 }
1676
1677 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState* exec)
1678 {
1679     VM& vm = exec->vm();
1680     JSLockHolder lock(vm);
1681     Structure* structure = DOMJITGetter::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1682     DOMJITGetter* result = DOMJITGetter::create(vm, structure);
1683     return JSValue::encode(result);
1684 }
1685
1686 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState* exec)
1687 {
1688     VM& vm = exec->vm();
1689     JSLockHolder lock(vm);
1690     Structure* structure = DOMJITGetterComplex::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1691     DOMJITGetterComplex* result = DOMJITGetterComplex::create(vm, exec->lexicalGlobalObject(), structure);
1692     return JSValue::encode(result);
1693 }
1694
1695 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState* exec)
1696 {
1697     VM& vm = exec->vm();
1698     JSLockHolder lock(vm);
1699     Structure* structure = DOMJITFunctionObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1700     DOMJITFunctionObject* result = DOMJITFunctionObject::create(vm, exec->lexicalGlobalObject(), structure);
1701     return JSValue::encode(result);
1702 }
1703
1704 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITCheckSubClassObject(ExecState* exec)
1705 {
1706     VM& vm = exec->vm();
1707     JSLockHolder lock(vm);
1708     Structure* structure = DOMJITCheckSubClassObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1709     DOMJITCheckSubClassObject* result = DOMJITCheckSubClassObject::create(vm, exec->lexicalGlobalObject(), structure);
1710     return JSValue::encode(result);
1711 }
1712
1713 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterBaseJSObject(ExecState* exec)
1714 {
1715     VM& vm = exec->vm();
1716     JSLockHolder lock(vm);
1717     Structure* structure = DOMJITGetterBaseJSObject::createStructure(vm, exec->lexicalGlobalObject(), jsNull());
1718     DOMJITGetterBaseJSObject* result = DOMJITGetterBaseJSObject::create(vm, structure);
1719     return JSValue::encode(result);
1720 }
1721
1722 #if ENABLE(WEBASSEMBLY)
1723 static EncodedJSValue JSC_HOST_CALL functionCreateWasmStreamingParser(ExecState* exec)
1724 {
1725     VM& vm = exec->vm();
1726     JSLockHolder lock(vm);
1727     return JSValue::encode(WasmStreamingParser::create(vm, exec->lexicalGlobalObject()));
1728 }
1729 #endif
1730
1731 static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
1732 {
1733     VM& vm = exec->vm();
1734     JSLockHolder lock(vm);
1735     auto scope = DECLARE_THROW_SCOPE(vm);
1736
1737     JSValue base = exec->argument(0);
1738     if (!base.isObject())
1739         return JSValue::encode(jsUndefined());
1740     JSValue delegate = exec->argument(1);
1741     if (!delegate.isObject())
1742         return JSValue::encode(jsUndefined());
1743     ImpureGetter* impureGetter = jsDynamicCast<ImpureGetter*>(vm, asObject(base.asCell()));
1744     if (UNLIKELY(!impureGetter)) {
1745         throwTypeError(exec, scope, "argument is not an ImpureGetter"_s);
1746         return encodedJSValue();
1747     }
1748     impureGetter->setDelegate(vm, asObject(delegate.asCell()));
1749     return JSValue::encode(jsUndefined());
1750 }
1751
1752 static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
1753 {
1754     VM& vm = exec->vm();
1755     auto scope = DECLARE_THROW_SCOPE(vm);
1756
1757     if (exec->argumentCount() < 1 || !exec->argument(0).isString())
1758         return JSValue::encode(jsUndefined());
1759
1760     String functionText = asString(exec->argument(0))->value(exec);
1761     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1762
1763     const SourceCode& source = makeSource(functionText, { });
1764     JSFunction* func = JSFunction::create(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
1765
1766     return JSValue::encode(func);
1767 }
1768
1769 static EncodedJSValue JSC_HOST_CALL functionGetPrivateProperty(ExecState* exec)
1770 {
1771     VM& vm = exec->vm();
1772     auto scope = DECLARE_THROW_SCOPE(vm);
1773
1774     if (exec->argumentCount() < 2 || !exec->argument(1).isString())
1775         return encodedJSUndefined();
1776
1777     String str = asString(exec->argument(1))->value(exec);
1778
1779     const Identifier* ident = vm.propertyNames->lookUpPrivateName(Identifier::fromString(exec, str));
1780     if (!ident)
1781         return throwVMError(exec, scope, "Unknown private name.");
1782
1783     scope.release();
1784     return JSValue::encode(exec->argument(0).get(exec, *ident));
1785 }
1786
1787 static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
1788 {
1789     VM& vm = exec->vm();
1790     JSLockHolder lock(vm);
1791     return JSValue::encode(Root::create(vm, exec->lexicalGlobalObject()));
1792 }
1793
1794 static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
1795 {
1796     VM& vm = exec->vm();
1797     JSLockHolder lock(vm);
1798     auto scope = DECLARE_THROW_SCOPE(vm);
1799
1800     Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1801     if (!root)
1802         return JSValue::encode(throwException(exec, scope, createError(exec, "Cannot create Element without a Root."_s)));
1803     return JSValue::encode(Element::create(vm, exec->lexicalGlobalObject(), root));
1804 }
1805
1806 static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
1807 {
1808     VM& vm = exec->vm();
1809     JSLockHolder lock(vm);
1810     Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1811     if (!root)
1812         return JSValue::encode(jsUndefined());
1813     Element* result = root->element();
1814     return JSValue::encode(result ? result : jsUndefined());
1815 }
1816
1817 static EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState* exec)
1818 {
1819     VM& vm = exec->vm();
1820     JSLockHolder lock(vm);
1821     return JSValue::encode(SimpleObject::create(vm, exec->lexicalGlobalObject()));
1822 }
1823
1824 static EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState* exec)
1825 {
1826     VM& vm = exec->vm();
1827     JSLockHolder lock(vm);
1828     auto scope = DECLARE_THROW_SCOPE(vm);
1829
1830     SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
1831     if (UNLIKELY(!simpleObject)) {
1832         throwTypeError(exec, scope, "Invalid use of getHiddenValue test function"_s);
1833         return encodedJSValue();
1834     }
1835     return JSValue::encode(simpleObject->hiddenValue());
1836 }
1837
1838 static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState* exec)
1839 {
1840     VM& vm = exec->vm();
1841     JSLockHolder lock(vm);
1842     auto scope = DECLARE_THROW_SCOPE(vm);
1843
1844     SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
1845     if (UNLIKELY(!simpleObject)) {
1846         throwTypeError(exec, scope, "Invalid use of setHiddenValue test function"_s);
1847         return encodedJSValue();
1848     }
1849     JSValue value = exec->argument(1);
1850     simpleObject->setHiddenValue(vm, value);
1851     return JSValue::encode(jsUndefined());
1852 }
1853
1854 static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState* exec)
1855 {
1856     VM& vm = exec->vm();
1857     return JSValue::encode(vm.shadowChicken().functionsOnStack(exec));
1858 }
1859
1860 static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState* exec)
1861 {
1862     VM& vm = exec->vm();
1863     vm.setGlobalConstRedeclarationShouldThrow(false);
1864     return JSValue::encode(jsUndefined());
1865 }
1866
1867 static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
1868 {
1869     VM& vm = exec->vm();
1870     RELEASE_ASSERT(vm.typeProfiler());
1871     vm.typeProfilerLog()->processLogEntries("jsc Testing API: functionFindTypeForExpression"_s);
1872
1873     JSValue functionValue = exec->argument(0);
1874     RELEASE_ASSERT(functionValue.isFunction(vm));
1875     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1876
1877     RELEASE_ASSERT(exec->argument(1).isString());
1878     String substring = asString(exec->argument(1))->value(exec);
1879     String sourceCodeText = executable->source().view().toString();
1880     unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
1881     
1882     String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), vm);
1883     return JSValue::encode(JSONParse(exec, jsonString));
1884 }
1885
1886 static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
1887 {
1888     VM& vm = exec->vm();
1889     RELEASE_ASSERT(vm.typeProfiler());
1890     vm.typeProfilerLog()->processLogEntries("jsc Testing API: functionReturnTypeFor"_s);
1891
1892     JSValue functionValue = exec->argument(0);
1893     RELEASE_ASSERT(functionValue.isFunction(vm));
1894     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1895
1896     unsigned offset = executable->typeProfilingStartOffset();
1897     String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), vm);
1898     return JSValue::encode(JSONParse(exec, jsonString));
1899 }
1900
1901 static EncodedJSValue JSC_HOST_CALL functionFlattenDictionaryObject(ExecState* exec)
1902 {
1903     VM& vm = exec->vm();
1904     JSValue value = exec->argument(0);
1905     RELEASE_ASSERT(value.isObject() && value.getObject()->structure()->isDictionary());
1906     value.getObject()->flattenDictionaryObject(vm);
1907     return encodedJSUndefined();
1908 }
1909
1910 static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
1911 {
1912     VM& vm = exec->vm();
1913     RELEASE_ASSERT(vm.controlFlowProfiler());
1914     vm.controlFlowProfiler()->dumpData();
1915     return JSValue::encode(jsUndefined());
1916 }
1917
1918 static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
1919 {
1920     VM& vm = exec->vm();
1921     RELEASE_ASSERT(vm.controlFlowProfiler());
1922
1923     JSValue functionValue = exec->argument(0);
1924     RELEASE_ASSERT(functionValue.isFunction(vm));
1925     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1926
1927     RELEASE_ASSERT(exec->argument(1).isString());
1928     String substring = asString(exec->argument(1))->value(exec);
1929     String sourceCodeText = executable->source().view().toString();
1930     RELEASE_ASSERT(sourceCodeText.contains(substring));
1931     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1932     
1933     bool hasExecuted = vm.controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), vm);
1934     return JSValue::encode(jsBoolean(hasExecuted));
1935 }
1936
1937 static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState* exec)
1938 {
1939     VM& vm = exec->vm();
1940     RELEASE_ASSERT(vm.controlFlowProfiler());
1941
1942     JSValue functionValue = exec->argument(0);
1943     RELEASE_ASSERT(functionValue.isFunction(vm));
1944     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
1945
1946     RELEASE_ASSERT(exec->argument(1).isString());
1947     String substring = asString(exec->argument(1))->value(exec);
1948     String sourceCodeText = executable->source().view().toString();
1949     RELEASE_ASSERT(sourceCodeText.contains(substring));
1950     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1951     
1952     size_t executionCount = vm.controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), vm);
1953     return JSValue::encode(JSValue(executionCount));
1954 }
1955
1956 static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
1957 {
1958     Options::useExceptionFuzz() = true;
1959     return JSValue::encode(jsUndefined());
1960 }
1961
1962 static EncodedJSValue changeDebuggerModeWhenIdle(ExecState* exec, DebuggerMode mode)
1963 {
1964     bool newDebuggerMode = (mode == DebuggerOn);
1965     if (Options::forceDebuggerBytecodeGeneration() == newDebuggerMode)
1966         return JSValue::encode(jsUndefined());
1967
1968     VM* vm = &exec->vm();
1969     vm->whenIdle([=] () {
1970         Options::forceDebuggerBytecodeGeneration() = newDebuggerMode;
1971         vm->deleteAllCode(PreventCollectionAndDeleteAllCode);
1972     });
1973     return JSValue::encode(jsUndefined());
1974 }
1975
1976 static EncodedJSValue JSC_HOST_CALL functionEnableDebuggerModeWhenIdle(ExecState* exec)
1977 {
1978     return changeDebuggerModeWhenIdle(exec, DebuggerOn);
1979 }
1980
1981 static EncodedJSValue JSC_HOST_CALL functionDisableDebuggerModeWhenIdle(ExecState* exec)
1982 {
1983     return changeDebuggerModeWhenIdle(exec, DebuggerOff);
1984 }
1985
1986 static EncodedJSValue JSC_HOST_CALL functionGlobalObjectCount(ExecState* exec)
1987 {
1988     return JSValue::encode(jsNumber(exec->vm().heap.globalObjectCount()));
1989 }
1990
1991 static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState* exec)
1992 {
1993     JSValue value = exec->argument(0);
1994     RELEASE_ASSERT(value.isObject());
1995     JSGlobalObject* globalObject = jsCast<JSObject*>(value)->globalObject(exec->vm());
1996     RELEASE_ASSERT(globalObject);
1997     return JSValue::encode(globalObject);
1998 }
1999
2000 static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
2001 {
2002     JSValue value = exec->argument(0);
2003     if (!value.isObject())
2004         return JSValue::encode(jsUndefined());
2005
2006     JSValue property = exec->argument(1);
2007     if (!property.isString())
2008         return JSValue::encode(jsUndefined());
2009
2010     PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
2011     value.getPropertySlot(exec, asString(property)->toIdentifier(exec), slot);
2012
2013     JSValue result;
2014     if (slot.isCacheableGetter())
2015         result = slot.getterSetter();
2016     else
2017         result = jsNull();
2018
2019     return JSValue::encode(result);
2020 }
2021
2022 static EncodedJSValue JSC_HOST_CALL functionLoadGetterFromGetterSetter(ExecState* exec)
2023 {
2024     VM& vm = exec->vm();
2025     auto scope = DECLARE_THROW_SCOPE(vm);
2026
2027     GetterSetter* getterSetter = jsDynamicCast<GetterSetter*>(vm, exec->argument(0));
2028     if (UNLIKELY(!getterSetter)) {
2029         throwTypeError(exec, scope, "Invalid use of loadGetterFromGetterSetter test function: argument is not a GetterSetter"_s);
2030         return encodedJSValue();
2031     }
2032
2033     JSObject* getter = getterSetter->getter();
2034     RELEASE_ASSERT(getter);
2035     return JSValue::encode(getter);
2036 }
2037
2038 static EncodedJSValue JSC_HOST_CALL functionCreateCustomTestGetterSetter(ExecState* exec)
2039 {
2040     VM& vm = exec->vm();
2041     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2042     return JSValue::encode(JSTestCustomGetterSetter::create(vm, globalObject, JSTestCustomGetterSetter::createStructure(vm, globalObject)));
2043 }
2044
2045 static EncodedJSValue JSC_HOST_CALL functionDeltaBetweenButterflies(ExecState* exec)
2046 {
2047     VM& vm = exec->vm();
2048     JSObject* a = jsDynamicCast<JSObject*>(vm, exec->argument(0));
2049     JSObject* b = jsDynamicCast<JSObject*>(vm, exec->argument(1));
2050     if (!a || !b)
2051         return JSValue::encode(jsNumber(PNaN));
2052
2053     ptrdiff_t delta = bitwise_cast<char*>(a->butterfly()) - bitwise_cast<char*>(b->butterfly());
2054     if (delta < 0)
2055         return JSValue::encode(jsNumber(PNaN));
2056     if (delta > std::numeric_limits<int32_t>::max())
2057         return JSValue::encode(jsNumber(PNaN));
2058     return JSValue::encode(jsNumber(static_cast<int32_t>(delta)));
2059 }
2060
2061 static EncodedJSValue JSC_HOST_CALL functionTotalGCTime(ExecState* exec)
2062 {
2063     VM& vm = exec->vm();
2064     return JSValue::encode(jsNumber(vm.heap.totalGCTime().seconds()));
2065 }
2066
2067 void JSDollarVM::finishCreation(VM& vm)
2068 {
2069     Base::finishCreation(vm);
2070
2071     JSGlobalObject* globalObject = this->globalObject(vm);
2072
2073     auto addFunction = [&] (VM& vm, const char* name, NativeFunction function, unsigned arguments) {
2074         JSDollarVM::addFunction(vm, globalObject, name, function, arguments);
2075     };
2076     auto addConstructibleFunction = [&] (VM& vm, const char* name, NativeFunction function, unsigned arguments) {
2077         JSDollarVM::addConstructibleFunction(vm, globalObject, name, function, arguments);
2078     };
2079
2080     addFunction(vm, "abort", functionCrash, 0);
2081     addFunction(vm, "crash", functionCrash, 0);
2082     addFunction(vm, "breakpoint", functionBreakpoint, 0);
2083
2084     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
2085     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "ftlTrue"), 0, functionFTLTrue, FTLTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
2086
2087     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuMfence"), 0, functionCpuMfence, CPUMfenceIntrinsic, 0);
2088     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuRdtsc"), 0, functionCpuRdtsc, CPURdtscIntrinsic, 0);
2089     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuCpuid"), 0, functionCpuCpuid, CPUCpuidIntrinsic, 0);
2090     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuPause"), 0, functionCpuPause, CPUPauseIntrinsic, 0);
2091     addFunction(vm, "cpuClflush", functionCpuClflush, 2);
2092
2093     addFunction(vm, "llintTrue", functionLLintTrue, 0);
2094     addFunction(vm, "jitTrue", functionJITTrue, 0);
2095
2096     addFunction(vm, "noInline", functionNoInline, 1);
2097
2098     addFunction(vm, "gc", functionGC, 0);
2099     addFunction(vm, "edenGC", functionEdenGC, 0);
2100
2101     addFunction(vm, "callFrame", functionCallFrame, 1);
2102     addFunction(vm, "codeBlockFor", functionCodeBlockFor, 1);
2103     addFunction(vm, "codeBlockForFrame", functionCodeBlockForFrame, 1);
2104     addFunction(vm, "dumpSourceFor", functionDumpSourceFor, 1);
2105     addFunction(vm, "dumpBytecodeFor", functionDumpBytecodeFor, 1);
2106
2107     addFunction(vm, "dataLog", functionDataLog, 1);
2108     addFunction(vm, "print", functionPrint, 1);
2109     addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
2110     addFunction(vm, "dumpStack", functionDumpStack, 0);
2111
2112     addFunction(vm, "dumpCell", functionDumpCell, 1);
2113
2114     addFunction(vm, "indexingMode", functionIndexingMode, 1);
2115     addFunction(vm, "inlineCapacity", functionInlineCapacity, 1);
2116     addFunction(vm, "value", functionValue, 1);
2117     addFunction(vm, "getpid", functionGetPID, 0);
2118
2119     addFunction(vm, "createProxy", functionCreateProxy, 1);
2120     addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
2121
2122     addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
2123     addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
2124     addFunction(vm, "createDOMJITNodeObject", functionCreateDOMJITNodeObject, 0);
2125     addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0);
2126     addFunction(vm, "createDOMJITGetterComplexObject", functionCreateDOMJITGetterComplexObject, 0);
2127     addFunction(vm, "createDOMJITFunctionObject", functionCreateDOMJITFunctionObject, 0);
2128     addFunction(vm, "createDOMJITCheckSubClassObject", functionCreateDOMJITCheckSubClassObject, 0);
2129     addFunction(vm, "createDOMJITGetterBaseJSObject", functionCreateDOMJITGetterBaseJSObject, 0);
2130     addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
2131 #if ENABLE(WEBASSEMBLY)
2132     addFunction(vm, "createWasmStreamingParser", functionCreateWasmStreamingParser, 0);
2133 #endif
2134     addFunction(vm, "getPrivateProperty", functionGetPrivateProperty, 2);
2135     addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
2136
2137     addConstructibleFunction(vm, "Root", functionCreateRoot, 0);
2138     addConstructibleFunction(vm, "Element", functionCreateElement, 1);
2139     addFunction(vm, "getElement", functionGetElement, 1);
2140
2141     addConstructibleFunction(vm, "SimpleObject", functionCreateSimpleObject, 0);
2142     addFunction(vm, "getHiddenValue", functionGetHiddenValue, 1);
2143     addFunction(vm, "setHiddenValue", functionSetHiddenValue, 2);
2144
2145     addFunction(vm, "shadowChickenFunctionsOnStack", functionShadowChickenFunctionsOnStack, 0);
2146     addFunction(vm, "setGlobalConstRedeclarationShouldNotThrow", functionSetGlobalConstRedeclarationShouldNotThrow, 0);
2147
2148     addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
2149     addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
2150
2151     addFunction(vm, "flattenDictionaryObject", functionFlattenDictionaryObject, 1);
2152
2153     addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
2154     addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
2155     addFunction(vm, "basicBlockExecutionCount", functionBasicBlockExecutionCount, 2);
2156
2157     addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
2158
2159     addFunction(vm, "enableDebuggerModeWhenIdle", functionEnableDebuggerModeWhenIdle, 0);
2160     addFunction(vm, "disableDebuggerModeWhenIdle", functionDisableDebuggerModeWhenIdle, 0);
2161
2162     addFunction(vm, "globalObjectCount", functionGlobalObjectCount, 0);
2163     addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1);
2164
2165     addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
2166     addFunction(vm, "loadGetterFromGetterSetter", functionLoadGetterFromGetterSetter, 1);
2167     addFunction(vm, "createCustomTestGetterSetter", functionCreateCustomTestGetterSetter, 1);
2168
2169     addFunction(vm, "deltaBetweenButterflies", functionDeltaBetweenButterflies, 2);
2170     
2171     addFunction(vm, "totalGCTime", functionTotalGCTime, 0);
2172 }
2173
2174 void JSDollarVM::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
2175 {
2176     Identifier identifier = Identifier::fromString(&vm, name);
2177     putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function));
2178 }
2179
2180 void JSDollarVM::addConstructibleFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
2181 {
2182     Identifier identifier = Identifier::fromString(&vm, name);
2183     putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function, NoIntrinsic, function));
2184 }
2185
2186 } // namespace JSC