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