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