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