1/*
2 * Copyright (C) 2015-2019 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 "Debugger.h"
34#include "Error.h"
35#include "FrameTracers.h"
36#include "FunctionCodeBlock.h"
37#include "GetterSetter.h"
38#include "JSArray.h"
39#include "JSArrayBuffer.h"
40#include "JSCInlines.h"
41#include "JSFunction.h"
42#include "JSONObject.h"
43#include "JSProxy.h"
44#include "JSString.h"
45#include "Options.h"
46#include "Parser.h"
47#include "ProbeContext.h"
48#include "ShadowChicken.h"
49#include "Snippet.h"
50#include "SnippetParams.h"
51#include "TypeProfiler.h"
52#include "TypeProfilerLog.h"
53#include "VMInspector.h"
54#include "WasmCapabilities.h"
55#include <wtf/Atomics.h>
56#include <wtf/DataLog.h>
57#include <wtf/ProcessID.h>
58#include <wtf/StringPrintStream.h>
59
60#if ENABLE(WEBASSEMBLY)
61#include "JSWebAssemblyHelpers.h"
62#include "WasmStreamingParser.h"
63#endif
64
65using namespace JSC;
66
67IGNORE_WARNINGS_BEGIN("frame-address")
68
69extern "C" void ctiMasmProbeTrampoline();
70
71namespace JSC {
72
73// This class is only here as a simple way to grant JSDollarVM friend privileges
74// to all the classes that it needs special access to.
75class JSDollarVMHelper {
76public:
77 JSDollarVMHelper(VM& vm)
78 : m_vm(vm)
79 { }
80
81 void updateVMStackLimits() { return m_vm.updateStackLimits(); };
82
83private:
84 VM& m_vm;
85};
86
87} // namespace JSC
88
89namespace {
90
91// We must RELEASE_ASSERT(Options::useDollarVM()) in all JSDollarVM functions
92// that are non-trivial at an eye's glance. This includes (but is not limited to):
93// constructors
94// create() factory
95// createStructure() factory
96// finishCreation()
97// HOST_CALL or operation functions
98// Constructors and methods of utility and test classes
99// lambda functions
100//
101// The way to do this RELEASE_ASSERT is with the DollarVMAssertScope below.
102//
103// The only exception are some constexpr constructors used for instantiating
104// globals (since these must have trivial constructors) e.g. DOMJITAttribute.
105// Instead, these constructors should always be ALWAYS_INLINE.
106
107class JSDollarVMCallFrame : public JSDestructibleObject {
108 using Base = JSDestructibleObject;
109public:
110 JSDollarVMCallFrame(VM& vm, Structure* structure)
111 : Base(vm, structure)
112 {
113 DollarVMAssertScope assertScope;
114 }
115
116 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
117 {
118 DollarVMAssertScope assertScope;
119 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
120 }
121
122 static JSDollarVMCallFrame* create(JSGlobalObject* globalObject, CallFrame* callFrame, unsigned requestedFrameIndex)
123 {
124 DollarVMAssertScope assertScope;
125 VM& vm = globalObject->vm();
126 Structure* structure = createStructure(vm, globalObject, jsNull());
127 JSDollarVMCallFrame* frame = new (NotNull, allocateCell<JSDollarVMCallFrame>(vm.heap)) JSDollarVMCallFrame(vm, structure);
128 frame->finishCreation(vm, callFrame, requestedFrameIndex);
129 return frame;
130 }
131
132 void finishCreation(VM& vm, CallFrame* callFrame, unsigned requestedFrameIndex)
133 {
134 DollarVMAssertScope assertScope;
135 Base::finishCreation(vm);
136
137 auto addProperty = [&] (VM& vm, const char* name, JSValue value) {
138 DollarVMAssertScope assertScope;
139 JSDollarVMCallFrame::addProperty(vm, name, value);
140 };
141
142 unsigned frameIndex = 0;
143 bool isValid = false;
144 callFrame->iterate(vm, [&] (StackVisitor& visitor) {
145 DollarVMAssertScope assertScope;
146
147 if (frameIndex++ != requestedFrameIndex)
148 return StackVisitor::Continue;
149
150 addProperty(vm, "name", jsString(vm, visitor->functionName()));
151
152 if (visitor->callee().isCell())
153 addProperty(vm, "callee", visitor->callee().asCell());
154
155 CodeBlock* codeBlock = visitor->codeBlock();
156 if (codeBlock) {
157 addProperty(vm, "codeBlock", codeBlock);
158 addProperty(vm, "unlinkedCodeBlock", codeBlock->unlinkedCodeBlock());
159 addProperty(vm, "executable", codeBlock->ownerExecutable());
160 }
161 isValid = true;
162
163 return StackVisitor::Done;
164 });
165
166 addProperty(vm, "valid", jsBoolean(isValid));
167 }
168
169 DECLARE_INFO;
170
171private:
172 void addProperty(VM& vm, const char* name, JSValue value)
173 {
174 DollarVMAssertScope assertScope;
175 Identifier identifier = Identifier::fromString(vm, name);
176 putDirect(vm, identifier, value);
177 }
178};
179
180const ClassInfo JSDollarVMCallFrame::s_info = { "CallFrame", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVMCallFrame) };
181
182class ElementHandleOwner;
183class Root;
184
185class Element : public JSNonFinalObject {
186public:
187 Element(VM& vm, Structure* structure)
188 : Base(vm, structure)
189 {
190 DollarVMAssertScope assertScope;
191 }
192
193 typedef JSNonFinalObject Base;
194
195 Root* root() const { return m_root.get(); }
196 void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
197
198 static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
199 {
200 DollarVMAssertScope assertScope;
201 Structure* structure = createStructure(vm, globalObject, jsNull());
202 Element* element = new (NotNull, allocateCell<Element>(vm.heap)) Element(vm, structure);
203 element->finishCreation(vm, root);
204 return element;
205 }
206
207 void finishCreation(VM&, Root*);
208
209 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
210 {
211 DollarVMAssertScope assertScope;
212 Element* thisObject = jsCast<Element*>(cell);
213 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
214 Base::visitChildren(thisObject, visitor);
215 visitor.append(thisObject->m_root);
216 }
217
218 static ElementHandleOwner* handleOwner();
219
220 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
221 {
222 DollarVMAssertScope assertScope;
223 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
224 }
225
226 DECLARE_INFO;
227
228private:
229 WriteBarrier<Root> m_root;
230};
231
232class ElementHandleOwner : public WeakHandleOwner {
233 WTF_MAKE_FAST_ALLOCATED;
234public:
235 bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor, const char** reason) override
236 {
237 DollarVMAssertScope assertScope;
238 if (UNLIKELY(reason))
239 *reason = "JSC::Element is opaque root";
240 Element* element = jsCast<Element*>(handle.slot()->asCell());
241 return visitor.containsOpaqueRoot(element->root());
242 }
243};
244
245class Root : public JSDestructibleObject {
246public:
247 Root(VM& vm, Structure* structure)
248 : Base(vm, structure)
249 {
250 DollarVMAssertScope assertScope;
251 }
252
253 Element* element()
254 {
255 return m_element.get();
256 }
257
258 void setElement(Element* element)
259 {
260 DollarVMAssertScope assertScope;
261 Weak<Element> newElement(element, Element::handleOwner());
262 m_element.swap(newElement);
263 }
264
265 static Root* create(VM& vm, JSGlobalObject* globalObject)
266 {
267 DollarVMAssertScope assertScope;
268 Structure* structure = createStructure(vm, globalObject, jsNull());
269 Root* root = new (NotNull, allocateCell<Root>(vm.heap)) Root(vm, structure);
270 root->finishCreation(vm);
271 return root;
272 }
273
274 typedef JSDestructibleObject Base;
275
276 DECLARE_INFO;
277
278 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
279 {
280 DollarVMAssertScope assertScope;
281 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
282 }
283
284 static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
285 {
286 DollarVMAssertScope assertScope;
287 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
288 Base::visitChildren(thisObject, visitor);
289 visitor.addOpaqueRoot(thisObject);
290 }
291
292private:
293 Weak<Element> m_element;
294};
295
296class SimpleObject : public JSNonFinalObject {
297public:
298 SimpleObject(VM& vm, Structure* structure)
299 : Base(vm, structure)
300 {
301 DollarVMAssertScope assertScope;
302 }
303
304 typedef JSNonFinalObject Base;
305 static constexpr bool needsDestruction = false;
306
307 static SimpleObject* create(VM& vm, JSGlobalObject* globalObject)
308 {
309 DollarVMAssertScope assertScope;
310 Structure* structure = createStructure(vm, globalObject, jsNull());
311 SimpleObject* simpleObject = new (NotNull, allocateCell<SimpleObject>(vm.heap)) SimpleObject(vm, structure);
312 simpleObject->finishCreation(vm);
313 return simpleObject;
314 }
315
316 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
317 {
318 DollarVMAssertScope assertScope;
319 SimpleObject* thisObject = jsCast<SimpleObject*>(cell);
320 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
321 Base::visitChildren(thisObject, visitor);
322 visitor.append(thisObject->m_hiddenValue);
323 }
324
325 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
326 {
327 DollarVMAssertScope assertScope;
328 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
329 }
330
331 JSValue hiddenValue()
332 {
333 return m_hiddenValue.get();
334 }
335
336 void setHiddenValue(VM& vm, JSValue value)
337 {
338 ASSERT(value.isCell());
339 m_hiddenValue.set(vm, this, value);
340 }
341
342 DECLARE_INFO;
343
344private:
345 WriteBarrier<JSC::Unknown> m_hiddenValue;
346};
347
348class ImpureGetter : public JSNonFinalObject {
349public:
350 ImpureGetter(VM& vm, Structure* structure)
351 : Base(vm, structure)
352 {
353 DollarVMAssertScope assertScope;
354 }
355
356 DECLARE_INFO;
357 typedef JSNonFinalObject Base;
358 static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::GetOwnPropertySlotIsImpure | JSC::OverridesGetOwnPropertySlot;
359
360 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
361 {
362 DollarVMAssertScope assertScope;
363 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
364 }
365
366 static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
367 {
368 DollarVMAssertScope assertScope;
369 ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap)) ImpureGetter(vm, structure);
370 getter->finishCreation(vm, delegate);
371 return getter;
372 }
373
374 void finishCreation(VM& vm, JSObject* delegate)
375 {
376 DollarVMAssertScope assertScope;
377 Base::finishCreation(vm);
378 if (delegate)
379 m_delegate.set(vm, this, delegate);
380 }
381
382 static bool getOwnPropertySlot(JSObject* object, JSGlobalObject* globalObject, PropertyName name, PropertySlot& slot)
383 {
384 DollarVMAssertScope assertScope;
385 VM& vm = globalObject->vm();
386 auto scope = DECLARE_THROW_SCOPE(vm);
387 ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
388
389 if (thisObject->m_delegate) {
390 if (thisObject->m_delegate->getPropertySlot(globalObject, name, slot))
391 return true;
392 RETURN_IF_EXCEPTION(scope, false);
393 }
394
395 return Base::getOwnPropertySlot(object, globalObject, name, slot);
396 }
397
398 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
399 {
400 DollarVMAssertScope assertScope;
401 ASSERT_GC_OBJECT_INHERITS(cell, info());
402 Base::visitChildren(cell, visitor);
403 ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
404 visitor.append(thisObject->m_delegate);
405 }
406
407 void setDelegate(VM& vm, JSObject* delegate)
408 {
409 m_delegate.set(vm, this, delegate);
410 }
411
412private:
413 WriteBarrier<JSObject> m_delegate;
414};
415
416class CustomGetter : public JSNonFinalObject {
417public:
418 CustomGetter(VM& vm, Structure* structure)
419 : Base(vm, structure)
420 {
421 DollarVMAssertScope assertScope;
422 }
423
424 DECLARE_INFO;
425 typedef JSNonFinalObject Base;
426 static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot;
427
428 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
429 {
430 DollarVMAssertScope assertScope;
431 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
432 }
433
434 static CustomGetter* create(VM& vm, Structure* structure)
435 {
436 DollarVMAssertScope assertScope;
437 CustomGetter* getter = new (NotNull, allocateCell<CustomGetter>(vm.heap)) CustomGetter(vm, structure);
438 getter->finishCreation(vm);
439 return getter;
440 }
441
442 static bool getOwnPropertySlot(JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
443 {
444 DollarVMAssertScope assertScope;
445 VM& vm = globalObject->vm();
446 CustomGetter* thisObject = jsCast<CustomGetter*>(object);
447 if (propertyName == PropertyName(Identifier::fromString(vm, "customGetter"))) {
448 slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, thisObject->customGetter);
449 return true;
450 }
451
452 if (propertyName == PropertyName(Identifier::fromString(vm, "customGetterAccessor"))) {
453 slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | PropertyAttribute::CustomAccessor, thisObject->customGetterAcessor);
454 return true;
455 }
456
457 return JSObject::getOwnPropertySlot(thisObject, globalObject, propertyName, slot);
458 }
459
460private:
461 static EncodedJSValue customGetter(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)
462 {
463 DollarVMAssertScope assertScope;
464 VM& vm = globalObject->vm();
465 auto scope = DECLARE_THROW_SCOPE(vm);
466
467 CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(vm, JSValue::decode(thisValue));
468 if (!thisObject)
469 return throwVMTypeError(globalObject, scope);
470 bool shouldThrow = thisObject->get(globalObject, PropertyName(Identifier::fromString(vm, "shouldThrow"))).toBoolean(globalObject);
471 RETURN_IF_EXCEPTION(scope, encodedJSValue());
472 if (shouldThrow)
473 return throwVMTypeError(globalObject, scope);
474 return JSValue::encode(jsNumber(100));
475 }
476
477 static EncodedJSValue customGetterAcessor(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)
478 {
479 DollarVMAssertScope assertScope;
480 VM& vm = globalObject->vm();
481 auto scope = DECLARE_THROW_SCOPE(vm);
482
483 JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
484 if (!thisObject)
485 return throwVMTypeError(globalObject, scope);
486 bool shouldThrow = thisObject->get(globalObject, PropertyName(Identifier::fromString(vm, "shouldThrow"))).toBoolean(globalObject);
487 RETURN_IF_EXCEPTION(scope, encodedJSValue());
488 if (shouldThrow)
489 return throwVMTypeError(globalObject, scope);
490 return JSValue::encode(jsNumber(100));
491 }
492};
493
494class RuntimeArray : public JSArray {
495public:
496 typedef JSArray Base;
497 static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
498
499 static RuntimeArray* create(JSGlobalObject* globalObject, CallFrame* callFrame)
500 {
501 DollarVMAssertScope assertScope;
502 VM& vm = globalObject->vm();
503 Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
504 RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(vm.heap)) RuntimeArray(globalObject, structure);
505 runtimeArray->finishCreation(globalObject, callFrame);
506 vm.heap.addFinalizer(runtimeArray, destroy);
507 return runtimeArray;
508 }
509
510 ~RuntimeArray() { }
511
512 static void destroy(JSCell* cell)
513 {
514 DollarVMAssertScope assertScope;
515 static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
516 }
517
518 static constexpr bool needsDestruction = false;
519
520 static bool getOwnPropertySlot(JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
521 {
522 DollarVMAssertScope assertScope;
523 VM& vm = globalObject->vm();
524 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
525 if (propertyName == vm.propertyNames->length) {
526 slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, thisObject->lengthGetter);
527 return true;
528 }
529
530 Optional<uint32_t> index = parseIndex(propertyName);
531 if (index && index.value() < thisObject->getLength()) {
532 slot.setValue(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::DontEnum, jsNumber(thisObject->m_vector[index.value()]));
533 return true;
534 }
535
536 return JSObject::getOwnPropertySlot(thisObject, globalObject, propertyName, slot);
537 }
538
539 static bool getOwnPropertySlotByIndex(JSObject* object, JSGlobalObject* globalObject, unsigned index, PropertySlot& slot)
540 {
541 DollarVMAssertScope assertScope;
542 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
543 if (index < thisObject->getLength()) {
544 slot.setValue(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::DontEnum, jsNumber(thisObject->m_vector[index]));
545 return true;
546 }
547
548 return JSObject::getOwnPropertySlotByIndex(thisObject, globalObject, index, slot);
549 }
550
551 static NO_RETURN_DUE_TO_CRASH bool put(JSCell*, JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&)
552 {
553 RELEASE_ASSERT_NOT_REACHED();
554 }
555
556 static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName)
557 {
558 RELEASE_ASSERT_NOT_REACHED();
559 }
560
561 unsigned getLength() const { return m_vector.size(); }
562
563 DECLARE_INFO;
564
565 static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
566 {
567 DollarVMAssertScope assertScope;
568 return globalObject->arrayPrototype();
569 }
570
571 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
572 {
573 DollarVMAssertScope assertScope;
574 return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
575 }
576
577protected:
578 void finishCreation(JSGlobalObject* globalObject, CallFrame* callFrame)
579 {
580 DollarVMAssertScope assertScope;
581 VM& vm = globalObject->vm();
582 Base::finishCreation(vm);
583 ASSERT(inherits(vm, info()));
584
585 for (size_t i = 0; i < callFrame->argumentCount(); i++)
586 m_vector.append(callFrame->argument(i).toInt32(globalObject));
587 }
588
589private:
590 RuntimeArray(JSGlobalObject* globalObject, Structure* structure)
591 : JSArray(globalObject->vm(), structure, 0)
592 {
593 DollarVMAssertScope assertScope;
594 }
595
596 static EncodedJSValue lengthGetter(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)
597 {
598 DollarVMAssertScope assertScope;
599 VM& vm = globalObject->vm();
600 auto scope = DECLARE_THROW_SCOPE(vm);
601
602 RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(vm, JSValue::decode(thisValue));
603 if (!thisObject)
604 return throwVMTypeError(globalObject, scope);
605 return JSValue::encode(jsNumber(thisObject->getLength()));
606 }
607
608 Vector<int> m_vector;
609};
610
611static const struct CompactHashIndex staticCustomAccessorTableIndex[2] = {
612 { 0, -1 },
613 { -1, -1 },
614};
615
616static EncodedJSValue testStaticAccessorGetter(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)
617{
618 DollarVMAssertScope assertScope;
619 VM& vm = globalObject->vm();
620
621 JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
622 RELEASE_ASSERT(thisObject);
623
624 if (JSValue result = thisObject->getDirect(vm, PropertyName(Identifier::fromString(vm, "testField"))))
625 return JSValue::encode(result);
626 return JSValue::encode(jsUndefined());
627}
628
629static bool testStaticAccessorPutter(JSGlobalObject* globalObject, EncodedJSValue thisValue, EncodedJSValue value)
630{
631 DollarVMAssertScope assertScope;
632 VM& vm = globalObject->vm();
633
634 JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
635 RELEASE_ASSERT(thisObject);
636
637 return thisObject->putDirect(vm, PropertyName(Identifier::fromString(vm, "testField")), JSValue::decode(value));
638}
639
640static const struct HashTableValue staticCustomAccessorTableValues[1] = {
641 { "testStaticAccessor", static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(testStaticAccessorGetter), (intptr_t)static_cast<PutPropertySlot::PutValueFunc>(testStaticAccessorPutter) } },
642};
643
644static const struct HashTable staticCustomAccessorTable =
645 { 1, 1, true, nullptr, staticCustomAccessorTableValues, staticCustomAccessorTableIndex };
646
647class StaticCustomAccessor : public JSNonFinalObject {
648 using Base = JSNonFinalObject;
649public:
650 StaticCustomAccessor(VM& vm, Structure* structure)
651 : Base(vm, structure)
652 {
653 DollarVMAssertScope assertScope;
654 }
655
656 DECLARE_INFO;
657
658 static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable | OverridesGetOwnPropertySlot;
659
660 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
661 {
662 DollarVMAssertScope assertScope;
663 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
664 }
665
666 static StaticCustomAccessor* create(VM& vm, Structure* structure)
667 {
668 DollarVMAssertScope assertScope;
669 StaticCustomAccessor* accessor = new (NotNull, allocateCell<StaticCustomAccessor>(vm.heap)) StaticCustomAccessor(vm, structure);
670 accessor->finishCreation(vm);
671 return accessor;
672 }
673
674 static bool getOwnPropertySlot(JSObject* thisObject, JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
675 {
676 if (String(propertyName.uid()) == "thinAirCustomGetter") {
677 slot.setCacheableCustom(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | PropertyAttribute::CustomAccessor, testStaticAccessorGetter);
678 return true;
679 }
680 return JSNonFinalObject::getOwnPropertySlot(thisObject, globalObject, propertyName, slot);
681 }
682};
683
684class DOMJITNode : public JSNonFinalObject {
685public:
686 DOMJITNode(VM& vm, Structure* structure)
687 : Base(vm, structure)
688 {
689 DollarVMAssertScope assertScope;
690 }
691
692 DECLARE_INFO;
693 typedef JSNonFinalObject Base;
694 static constexpr unsigned StructureFlags = Base::StructureFlags;
695
696 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
697 {
698 DollarVMAssertScope assertScope;
699 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
700 }
701
702#if ENABLE(JIT)
703 static Ref<Snippet> checkSubClassSnippet()
704 {
705 DollarVMAssertScope assertScope;
706 Ref<Snippet> snippet = Snippet::create();
707 snippet->setGenerator([=] (CCallHelpers& jit, SnippetParams& params) {
708 DollarVMAssertScope assertScope;
709 CCallHelpers::JumpList failureCases;
710 failureCases.append(jit.branchIfNotType(params[0].gpr(), JSC::JSType(LastJSCObjectType + 1)));
711 return failureCases;
712 });
713 return snippet;
714 }
715#endif
716
717 static DOMJITNode* create(VM& vm, Structure* structure)
718 {
719 DollarVMAssertScope assertScope;
720 DOMJITNode* getter = new (NotNull, allocateCell<DOMJITNode>(vm.heap)) DOMJITNode(vm, structure);
721 getter->finishCreation(vm);
722 return getter;
723 }
724
725 int32_t value() const
726 {
727 return m_value;
728 }
729
730 static ptrdiff_t offsetOfValue() { return OBJECT_OFFSETOF(DOMJITNode, m_value); }
731
732private:
733 int32_t m_value { 42 };
734};
735
736class DOMJITGetter : public DOMJITNode {
737public:
738 DOMJITGetter(VM& vm, Structure* structure)
739 : Base(vm, structure)
740 {
741 DollarVMAssertScope assertScope;
742 }
743
744 DECLARE_INFO;
745 typedef DOMJITNode Base;
746 static constexpr unsigned StructureFlags = Base::StructureFlags;
747
748 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
749 {
750 DollarVMAssertScope assertScope;
751 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
752 }
753
754 static DOMJITGetter* create(VM& vm, Structure* structure)
755 {
756 DollarVMAssertScope assertScope;
757 DOMJITGetter* getter = new (NotNull, allocateCell<DOMJITGetter>(vm.heap)) DOMJITGetter(vm, structure);
758 getter->finishCreation(vm);
759 return getter;
760 }
761
762 class DOMJITAttribute : public DOMJIT::GetterSetter {
763 public:
764 ALWAYS_INLINE constexpr DOMJITAttribute()
765 : DOMJIT::GetterSetter(
766 DOMJITGetter::customGetter,
767#if ENABLE(JIT)
768 &callDOMGetter,
769#else
770 nullptr,
771#endif
772 SpecInt32Only)
773 {
774 }
775
776#if ENABLE(JIT)
777 static EncodedJSValue JIT_OPERATION slowCall(JSGlobalObject* globalObject, void* pointer)
778 {
779 DollarVMAssertScope assertScope;
780 VM& vm = globalObject->vm();
781 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
782 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
783 return JSValue::encode(jsNumber(static_cast<DOMJITGetter*>(pointer)->value()));
784 }
785
786 static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
787 {
788 DollarVMAssertScope assertScope;
789 Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
790 snippet->requireGlobalObject = true;
791 snippet->setGenerator([=] (CCallHelpers& jit, SnippetParams& params) {
792 DollarVMAssertScope assertScope;
793 JSValueRegs results = params[0].jsValueRegs();
794 GPRReg domGPR = params[1].gpr();
795 GPRReg globalObjectGPR = params[2].gpr();
796 params.addSlowPathCall(jit.jump(), jit, slowCall, results, globalObjectGPR, domGPR);
797 return CCallHelpers::JumpList();
798
799 });
800 return snippet;
801 }
802#endif
803 };
804
805private:
806 void finishCreation(VM&);
807
808 static EncodedJSValue customGetter(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)
809 {
810 DollarVMAssertScope assertScope;
811 VM& vm = globalObject->vm();
812 DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, JSValue::decode(thisValue));
813 ASSERT(thisObject);
814 return JSValue::encode(jsNumber(thisObject->value()));
815 }
816};
817
818static const DOMJITGetter::DOMJITAttribute DOMJITGetterDOMJIT;
819
820void DOMJITGetter::finishCreation(VM& vm)
821{
822 DollarVMAssertScope assertScope;
823 Base::finishCreation(vm);
824 const DOMJIT::GetterSetter* domJIT = &DOMJITGetterDOMJIT;
825 auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { DOMJITNode::info(), domJIT });
826 putDirectCustomAccessor(vm, Identifier::fromString(vm, "customGetter"), customGetterSetter, PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor);
827}
828
829
830class DOMJITGetterComplex : public DOMJITNode {
831public:
832 DOMJITGetterComplex(VM& vm, Structure* structure)
833 : Base(vm, structure)
834 {
835 DollarVMAssertScope assertScope;
836 }
837
838 DECLARE_INFO;
839 typedef DOMJITNode Base;
840 static constexpr unsigned StructureFlags = Base::StructureFlags;
841
842 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
843 {
844 DollarVMAssertScope assertScope;
845 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
846 }
847
848 static DOMJITGetterComplex* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
849 {
850 DollarVMAssertScope assertScope;
851 DOMJITGetterComplex* getter = new (NotNull, allocateCell<DOMJITGetterComplex>(vm.heap)) DOMJITGetterComplex(vm, structure);
852 getter->finishCreation(vm, globalObject);
853 return getter;
854 }
855
856 class DOMJITAttribute : public DOMJIT::GetterSetter {
857 public:
858 ALWAYS_INLINE constexpr DOMJITAttribute()
859 : DOMJIT::GetterSetter(
860 DOMJITGetterComplex::customGetter,
861#if ENABLE(JIT)
862 &callDOMGetter,
863#else
864 nullptr,
865#endif
866 SpecInt32Only)
867 {
868 }
869
870#if ENABLE(JIT)
871 static EncodedJSValue JIT_OPERATION slowCall(JSGlobalObject* globalObject, void* pointer)
872 {
873 DollarVMAssertScope assertScope;
874 VM& vm = globalObject->vm();
875 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
876 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
877 auto scope = DECLARE_THROW_SCOPE(vm);
878 auto* object = static_cast<DOMJITNode*>(pointer);
879 auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(vm, object);
880 if (domjitGetterComplex) {
881 if (domjitGetterComplex->m_enableException)
882 return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "DOMJITGetterComplex slow call exception"_s)));
883 }
884 return JSValue::encode(jsNumber(object->value()));
885 }
886
887 static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
888 {
889 DollarVMAssertScope assertScope;
890 Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
891 static_assert(GPRInfo::numberOfRegisters >= 4, "Number of registers should be larger or equal to 4.");
892 unsigned numGPScratchRegisters = GPRInfo::numberOfRegisters - 4;
893 snippet->numGPScratchRegisters = numGPScratchRegisters;
894 snippet->numFPScratchRegisters = 3;
895 snippet->requireGlobalObject = true;
896 snippet->setGenerator([=] (CCallHelpers& jit, SnippetParams& params) {
897 DollarVMAssertScope assertScope;
898 JSValueRegs results = params[0].jsValueRegs();
899 GPRReg domGPR = params[1].gpr();
900 GPRReg globalObjectGPR = params[2].gpr();
901 for (unsigned i = 0; i < numGPScratchRegisters; ++i)
902 jit.move(CCallHelpers::TrustedImm32(42), params.gpScratch(i));
903
904 params.addSlowPathCall(jit.jump(), jit, slowCall, results, globalObjectGPR, domGPR);
905 return CCallHelpers::JumpList();
906 });
907 return snippet;
908 }
909#endif
910 };
911
912private:
913 void finishCreation(VM&, JSGlobalObject*);
914
915 static EncodedJSValue JSC_HOST_CALL functionEnableException(JSGlobalObject* globalObject, CallFrame* callFrame)
916 {
917 DollarVMAssertScope assertScope;
918 VM& vm = globalObject->vm();
919 auto* object = jsDynamicCast<DOMJITGetterComplex*>(vm, callFrame->thisValue());
920 if (object)
921 object->m_enableException = true;
922 return JSValue::encode(jsUndefined());
923 }
924
925 static EncodedJSValue customGetter(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)
926 {
927 DollarVMAssertScope assertScope;
928 VM& vm = globalObject->vm();
929 auto scope = DECLARE_THROW_SCOPE(vm);
930
931 auto* thisObject = jsDynamicCast<DOMJITGetterComplex*>(vm, JSValue::decode(thisValue));
932 ASSERT(thisObject);
933 if (thisObject->m_enableException)
934 return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "DOMJITGetterComplex slow call exception"_s)));
935 return JSValue::encode(jsNumber(thisObject->value()));
936 }
937
938 bool m_enableException { false };
939};
940
941static const DOMJITGetterComplex::DOMJITAttribute DOMJITGetterComplexDOMJIT;
942
943void DOMJITGetterComplex::finishCreation(VM& vm, JSGlobalObject* globalObject)
944{
945 DollarVMAssertScope assertScope;
946 Base::finishCreation(vm);
947 const DOMJIT::GetterSetter* domJIT = &DOMJITGetterComplexDOMJIT;
948 auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { DOMJITGetterComplex::info(), domJIT });
949 putDirectCustomAccessor(vm, Identifier::fromString(vm, "customGetter"), customGetterSetter, PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor);
950 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "enableException"), 0, functionEnableException, NoIntrinsic, 0);
951}
952
953class DOMJITFunctionObject : public DOMJITNode {
954public:
955 DOMJITFunctionObject(VM& vm, Structure* structure)
956 : Base(vm, structure)
957 {
958 DollarVMAssertScope assertScope;
959 }
960
961 DECLARE_INFO;
962 typedef DOMJITNode Base;
963 static constexpr unsigned StructureFlags = Base::StructureFlags;
964
965 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
966 {
967 DollarVMAssertScope assertScope;
968 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
969 }
970
971 static DOMJITFunctionObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
972 {
973 DollarVMAssertScope assertScope;
974 DOMJITFunctionObject* object = new (NotNull, allocateCell<DOMJITFunctionObject>(vm.heap)) DOMJITFunctionObject(vm, structure);
975 object->finishCreation(vm, globalObject);
976 return object;
977 }
978
979 static EncodedJSValue JSC_HOST_CALL functionWithTypeCheck(JSGlobalObject* globalObject, CallFrame* callFrame)
980 {
981 DollarVMAssertScope assertScope;
982 VM& vm = globalObject->vm();
983 auto scope = DECLARE_THROW_SCOPE(vm);
984
985 DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, callFrame->thisValue());
986 if (!thisObject)
987 return throwVMTypeError(globalObject, scope);
988 return JSValue::encode(jsNumber(thisObject->value()));
989 }
990
991 static EncodedJSValue JIT_OPERATION functionWithoutTypeCheck(JSGlobalObject* globalObject, DOMJITNode* node)
992 {
993 DollarVMAssertScope assertScope;
994 VM& vm = globalObject->vm();
995 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
996 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
997 return JSValue::encode(jsNumber(node->value()));
998 }
999
1000#if ENABLE(JIT)
1001 static Ref<Snippet> checkSubClassSnippet()
1002 {
1003 DollarVMAssertScope assertScope;
1004 Ref<Snippet> snippet = Snippet::create();
1005 snippet->numFPScratchRegisters = 1;
1006 snippet->setGenerator([=] (CCallHelpers& jit, SnippetParams& params) {
1007 DollarVMAssertScope assertScope;
1008 static const double value = 42.0;
1009 CCallHelpers::JumpList failureCases;
1010 // May use scratch registers.
1011 jit.loadDouble(CCallHelpers::TrustedImmPtr(&value), params.fpScratch(0));
1012 failureCases.append(jit.branchIfNotType(params[0].gpr(), JSC::JSType(LastJSCObjectType + 1)));
1013 return failureCases;
1014 });
1015 return snippet;
1016 }
1017#endif
1018
1019private:
1020 void finishCreation(VM&, JSGlobalObject*);
1021};
1022
1023static const DOMJIT::Signature DOMJITFunctionObjectSignature(DOMJITFunctionObject::functionWithoutTypeCheck, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
1024
1025void DOMJITFunctionObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
1026{
1027 DollarVMAssertScope assertScope;
1028 Base::finishCreation(vm);
1029 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "func"), 0, functionWithTypeCheck, NoIntrinsic, &DOMJITFunctionObjectSignature, static_cast<unsigned>(PropertyAttribute::ReadOnly));
1030}
1031
1032class DOMJITCheckSubClassObject : public DOMJITNode {
1033public:
1034 DOMJITCheckSubClassObject(VM& vm, Structure* structure)
1035 : Base(vm, structure)
1036 {
1037 DollarVMAssertScope assertScope;
1038 }
1039
1040 DECLARE_INFO;
1041 typedef DOMJITNode Base;
1042 static constexpr unsigned StructureFlags = Base::StructureFlags;
1043
1044 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
1045 {
1046 DollarVMAssertScope assertScope;
1047 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
1048 }
1049
1050 static DOMJITCheckSubClassObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
1051 {
1052 DollarVMAssertScope assertScope;
1053 DOMJITCheckSubClassObject* object = new (NotNull, allocateCell<DOMJITCheckSubClassObject>(vm.heap)) DOMJITCheckSubClassObject(vm, structure);
1054 object->finishCreation(vm, globalObject);
1055 return object;
1056 }
1057
1058 static EncodedJSValue JSC_HOST_CALL functionWithTypeCheck(JSGlobalObject* globalObject, CallFrame* callFrame)
1059 {
1060 DollarVMAssertScope assertScope;
1061 VM& vm = globalObject->vm();
1062 auto scope = DECLARE_THROW_SCOPE(vm);
1063
1064 auto* thisObject = jsDynamicCast<DOMJITCheckSubClassObject*>(vm, callFrame->thisValue());
1065 if (!thisObject)
1066 return throwVMTypeError(globalObject, scope);
1067 return JSValue::encode(jsNumber(thisObject->value()));
1068 }
1069
1070 static EncodedJSValue JIT_OPERATION functionWithoutTypeCheck(JSGlobalObject* globalObject, DOMJITNode* node)
1071 {
1072 DollarVMAssertScope assertScope;
1073 VM& vm = globalObject->vm();
1074 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1075 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1076 return JSValue::encode(jsNumber(node->value()));
1077 }
1078
1079private:
1080 void finishCreation(VM&, JSGlobalObject*);
1081};
1082
1083static const DOMJIT::Signature DOMJITCheckSubClassObjectSignature(DOMJITCheckSubClassObject::functionWithoutTypeCheck, DOMJITCheckSubClassObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
1084
1085void DOMJITCheckSubClassObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
1086{
1087 DollarVMAssertScope assertScope;
1088 Base::finishCreation(vm);
1089 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "func"), 0, functionWithTypeCheck, NoIntrinsic, &DOMJITCheckSubClassObjectSignature, static_cast<unsigned>(PropertyAttribute::ReadOnly));
1090}
1091
1092class DOMJITGetterBaseJSObject : public DOMJITNode {
1093public:
1094 DOMJITGetterBaseJSObject(VM& vm, Structure* structure)
1095 : Base(vm, structure)
1096 {
1097 DollarVMAssertScope assertScope;
1098 }
1099
1100 DECLARE_INFO;
1101 using Base = DOMJITNode;
1102 static constexpr unsigned StructureFlags = Base::StructureFlags;
1103
1104 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
1105 {
1106 DollarVMAssertScope assertScope;
1107 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
1108 }
1109
1110 static DOMJITGetterBaseJSObject* create(VM& vm, Structure* structure)
1111 {
1112 DollarVMAssertScope assertScope;
1113 DOMJITGetterBaseJSObject* getter = new (NotNull, allocateCell<DOMJITGetterBaseJSObject>(vm.heap)) DOMJITGetterBaseJSObject(vm, structure);
1114 getter->finishCreation(vm);
1115 return getter;
1116 }
1117
1118 class DOMJITAttribute : public DOMJIT::GetterSetter {
1119 public:
1120 ALWAYS_INLINE constexpr DOMJITAttribute()
1121 : DOMJIT::GetterSetter(
1122 DOMJITGetterBaseJSObject::customGetter,
1123#if ENABLE(JIT)
1124 &callDOMGetter,
1125#else
1126 nullptr,
1127#endif
1128 SpecBytecodeTop)
1129 {
1130 }
1131
1132#if ENABLE(JIT)
1133 static EncodedJSValue JIT_OPERATION slowCall(JSGlobalObject* globalObject, void* pointer)
1134 {
1135 DollarVMAssertScope assertScope;
1136 VM& vm = globalObject->vm();
1137 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1138 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1139 JSObject* object = static_cast<JSObject*>(pointer);
1140 return JSValue::encode(object->getPrototypeDirect(vm));
1141 }
1142
1143 static Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter()
1144 {
1145 DollarVMAssertScope assertScope;
1146 Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
1147 snippet->requireGlobalObject = true;
1148 snippet->setGenerator([=] (CCallHelpers& jit, SnippetParams& params) {
1149 DollarVMAssertScope assertScope;
1150 JSValueRegs results = params[0].jsValueRegs();
1151 GPRReg domGPR = params[1].gpr();
1152 GPRReg globalObjectGPR = params[2].gpr();
1153 params.addSlowPathCall(jit.jump(), jit, slowCall, results, globalObjectGPR, domGPR);
1154 return CCallHelpers::JumpList();
1155
1156 });
1157 return snippet;
1158 }
1159#endif
1160 };
1161
1162private:
1163 void finishCreation(VM&);
1164
1165 static EncodedJSValue customGetter(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)
1166 {
1167 DollarVMAssertScope assertScope;
1168 VM& vm = globalObject->vm();
1169 JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
1170 RELEASE_ASSERT(thisObject);
1171 return JSValue::encode(thisObject->getPrototypeDirect(vm));
1172 }
1173};
1174
1175static const DOMJITGetterBaseJSObject::DOMJITAttribute DOMJITGetterBaseJSObjectDOMJIT;
1176
1177void DOMJITGetterBaseJSObject::finishCreation(VM& vm)
1178{
1179 DollarVMAssertScope assertScope;
1180 Base::finishCreation(vm);
1181 const DOMJIT::GetterSetter* domJIT = &DOMJITGetterBaseJSObjectDOMJIT;
1182 auto* customGetterSetter = DOMAttributeGetterSetter::create(vm, domJIT->getter(), nullptr, DOMAttributeAnnotation { JSObject::info(), domJIT });
1183 putDirectCustomAccessor(vm, Identifier::fromString(vm, "customGetter"), customGetterSetter, PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor);
1184}
1185
1186class Message : public ThreadSafeRefCounted<Message> {
1187public:
1188 Message(ArrayBufferContents&&, int32_t);
1189 ~Message();
1190
1191 ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
1192 int32_t index() const { return m_index; }
1193
1194private:
1195 ArrayBufferContents m_contents;
1196 int32_t m_index { 0 };
1197};
1198
1199class JSTestCustomGetterSetter : public JSNonFinalObject {
1200public:
1201 using Base = JSNonFinalObject;
1202 static constexpr unsigned StructureFlags = Base::StructureFlags;
1203
1204 JSTestCustomGetterSetter(VM& vm, Structure* structure)
1205 : Base(vm, structure)
1206 {
1207 DollarVMAssertScope assertScope;
1208 }
1209
1210 static JSTestCustomGetterSetter* create(VM& vm, JSGlobalObject*, Structure* structure)
1211 {
1212 DollarVMAssertScope assertScope;
1213 JSTestCustomGetterSetter* result = new (NotNull, allocateCell<JSTestCustomGetterSetter>(vm.heap)) JSTestCustomGetterSetter(vm, structure);
1214 result->finishCreation(vm);
1215 return result;
1216 }
1217
1218 void finishCreation(VM&);
1219
1220 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject)
1221 {
1222 DollarVMAssertScope assertScope;
1223 return Structure::create(vm, globalObject, globalObject->objectPrototype(), TypeInfo(ObjectType, StructureFlags), info());
1224 }
1225
1226 DECLARE_INFO;
1227};
1228
1229
1230static EncodedJSValue customGetAccessor(JSGlobalObject*, EncodedJSValue thisValue, PropertyName)
1231{
1232 // Passed |this|
1233 return thisValue;
1234}
1235
1236static EncodedJSValue customGetValue(JSGlobalObject* globalObject, EncodedJSValue slotValue, PropertyName)
1237{
1238 RELEASE_ASSERT(JSValue::decode(slotValue).inherits<JSTestCustomGetterSetter>(globalObject->vm()));
1239 // Passed property holder.
1240 return slotValue;
1241}
1242
1243static bool customSetAccessor(JSGlobalObject* globalObject, EncodedJSValue thisObject, EncodedJSValue encodedValue)
1244{
1245 DollarVMAssertScope assertScope;
1246 VM& vm = globalObject->vm();
1247
1248 JSValue value = JSValue::decode(encodedValue);
1249 RELEASE_ASSERT(value.isObject());
1250 JSObject* object = asObject(value);
1251 PutPropertySlot slot(object);
1252 object->put(object, globalObject, Identifier::fromString(vm, "result"), JSValue::decode(thisObject), slot);
1253
1254 return true;
1255}
1256
1257static bool customSetValue(JSGlobalObject* globalObject, EncodedJSValue slotValue, EncodedJSValue encodedValue)
1258{
1259 DollarVMAssertScope assertScope;
1260 VM& vm = globalObject->vm();
1261
1262 RELEASE_ASSERT(JSValue::decode(slotValue).inherits<JSTestCustomGetterSetter>(globalObject->vm()));
1263
1264 JSValue value = JSValue::decode(encodedValue);
1265 RELEASE_ASSERT(value.isObject());
1266 JSObject* object = asObject(value);
1267 PutPropertySlot slot(object);
1268 object->put(object, globalObject, Identifier::fromString(vm, "result"), JSValue::decode(slotValue), slot);
1269
1270 return true;
1271}
1272
1273void JSTestCustomGetterSetter::finishCreation(VM& vm)
1274{
1275 DollarVMAssertScope assertScope;
1276 Base::finishCreation(vm);
1277
1278 putDirectCustomAccessor(vm, Identifier::fromString(vm, "customValue"),
1279 CustomGetterSetter::create(vm, customGetValue, customSetValue), 0);
1280 putDirectCustomAccessor(vm, Identifier::fromString(vm, "customAccessor"),
1281 CustomGetterSetter::create(vm, customGetAccessor, customSetAccessor), static_cast<unsigned>(PropertyAttribute::CustomAccessor));
1282}
1283
1284const ClassInfo Element::s_info = { "Element", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Element) };
1285const ClassInfo Root::s_info = { "Root", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Root) };
1286const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(SimpleObject) };
1287const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ImpureGetter) };
1288const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(CustomGetter) };
1289const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RuntimeArray) };
1290#if ENABLE(JIT)
1291const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, &DOMJITNode::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITNode) };
1292#else
1293const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITNode) };
1294#endif
1295const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetter) };
1296const ClassInfo DOMJITGetterComplex::s_info = { "DOMJITGetterComplex", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetterComplex) };
1297const ClassInfo DOMJITGetterBaseJSObject::s_info = { "DOMJITGetterBaseJSObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetterBaseJSObject) };
1298#if ENABLE(JIT)
1299const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, &DOMJITFunctionObject::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
1300#else
1301const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
1302#endif
1303const ClassInfo DOMJITCheckSubClassObject::s_info = { "DOMJITCheckSubClassObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITCheckSubClassObject) };
1304const ClassInfo JSTestCustomGetterSetter::s_info = { "JSTestCustomGetterSetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestCustomGetterSetter) };
1305
1306const ClassInfo StaticCustomAccessor::s_info = { "StaticCustomAccessor", &Base::s_info, &staticCustomAccessorTable, nullptr, CREATE_METHOD_TABLE(StaticCustomAccessor) };
1307
1308ElementHandleOwner* Element::handleOwner()
1309{
1310 DollarVMAssertScope assertScope;
1311 static ElementHandleOwner* owner = 0;
1312 if (!owner)
1313 owner = new ElementHandleOwner();
1314 return owner;
1315}
1316
1317void Element::finishCreation(VM& vm, Root* root)
1318{
1319 DollarVMAssertScope assertScope;
1320 Base::finishCreation(vm);
1321 setRoot(vm, root);
1322 m_root->setElement(this);
1323}
1324
1325#if ENABLE(WEBASSEMBLY)
1326
1327static EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserAddBytes(JSGlobalObject*, CallFrame*);
1328static EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserFinalize(JSGlobalObject*, CallFrame*);
1329
1330class WasmStreamingParser : public JSDestructibleObject {
1331public:
1332 class Client final : public Wasm::StreamingParserClient {
1333 public:
1334 explicit Client(WasmStreamingParser* parser)
1335 : m_parser(parser)
1336 {
1337 }
1338
1339 bool didReceiveSectionData(Wasm::Section) override { return true; }
1340 bool didReceiveFunctionData(unsigned, const Wasm::FunctionData&) override { return true; }
1341 void didFinishParsing() override { }
1342
1343 WasmStreamingParser* m_parser;
1344 };
1345
1346 WasmStreamingParser(VM& vm, Structure* structure)
1347 : Base(vm, structure)
1348 , m_info(Wasm::ModuleInformation::create())
1349 , m_client(this)
1350 , m_streamingParser(m_info.get(), m_client)
1351 {
1352 DollarVMAssertScope assertScope;
1353 }
1354
1355 using Base = JSDestructibleObject;
1356
1357 static WasmStreamingParser* create(VM& vm, JSGlobalObject* globalObject)
1358 {
1359 DollarVMAssertScope assertScope;
1360 Structure* structure = createStructure(vm, globalObject, jsNull());
1361 WasmStreamingParser* result = new (NotNull, allocateCell<WasmStreamingParser>(vm.heap)) WasmStreamingParser(vm, structure);
1362 result->finishCreation(vm);
1363 return result;
1364 }
1365
1366 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
1367 {
1368 DollarVMAssertScope assertScope;
1369 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
1370 }
1371
1372 Wasm::StreamingParser& streamingParser() { return m_streamingParser; }
1373
1374 void finishCreation(VM& vm)
1375 {
1376 DollarVMAssertScope assertScope;
1377 Base::finishCreation(vm);
1378
1379 JSGlobalObject* globalObject = this->globalObject(vm);
1380 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "addBytes"), 0, functionWasmStreamingParserAddBytes, NoIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
1381 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "finalize"), 0, functionWasmStreamingParserFinalize, NoIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
1382 }
1383
1384 DECLARE_INFO;
1385
1386 Ref<Wasm::ModuleInformation> m_info;
1387 Client m_client;
1388 Wasm::StreamingParser m_streamingParser;
1389};
1390
1391const ClassInfo WasmStreamingParser::s_info = { "WasmStreamingParser", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(WasmStreamingParser) };
1392
1393EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserAddBytes(JSGlobalObject* globalObject, CallFrame* callFrame)
1394{
1395 DollarVMAssertScope assertScope;
1396 VM& vm = globalObject->vm();
1397 auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
1398
1399 auto* thisObject = jsDynamicCast<WasmStreamingParser*>(vm, callFrame->thisValue());
1400 if (!thisObject)
1401 RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(false)));
1402
1403 auto data = getWasmBufferFromValue(globalObject, callFrame->argument(0));
1404 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1405 RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(static_cast<int32_t>(thisObject->streamingParser().addBytes(bitwise_cast<const uint8_t*>(data.first), data.second)))));
1406}
1407
1408EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserFinalize(JSGlobalObject* globalObject, CallFrame* callFrame)
1409{
1410 DollarVMAssertScope assertScope;
1411 VM& vm = globalObject->vm();
1412 auto* thisObject = jsDynamicCast<WasmStreamingParser*>(vm, callFrame->thisValue());
1413 if (!thisObject)
1414 return JSValue::encode(jsBoolean(false));
1415 return JSValue::encode(jsNumber(static_cast<int32_t>(thisObject->streamingParser().finalize())));
1416}
1417
1418#endif
1419
1420} // namespace
1421
1422namespace JSC {
1423
1424const ClassInfo JSDollarVM::s_info = { "DollarVM", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDollarVM) };
1425
1426// Triggers a crash immediately.
1427// Usage: $vm.crash()
1428static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionCrash(JSGlobalObject*, CallFrame*)
1429{
1430 DollarVMAssertScope assertScope;
1431 CRASH();
1432}
1433
1434// Executes a breakpoint instruction if the first argument is truthy or is unset.
1435// Usage: $vm.breakpoint(<condition>)
1436static EncodedJSValue JSC_HOST_CALL functionBreakpoint(JSGlobalObject* globalObject, CallFrame* callFrame)
1437{
1438 DollarVMAssertScope assertScope;
1439 // Nothing should throw here but we might as well double check...
1440 VM& vm = globalObject->vm();
1441 auto scope = DECLARE_CATCH_SCOPE(vm);
1442 UNUSED_PARAM(scope);
1443 if (!callFrame->argumentCount() || callFrame->argument(0).toBoolean(globalObject))
1444 WTFBreakpointTrap();
1445
1446 return encodedJSUndefined();
1447}
1448
1449// Returns true if the current frame is a DFG frame.
1450// Usage: isDFG = $vm.dfgTrue()
1451static EncodedJSValue JSC_HOST_CALL functionDFGTrue(JSGlobalObject*, CallFrame*)
1452{
1453 DollarVMAssertScope assertScope;
1454 return JSValue::encode(jsBoolean(false));
1455}
1456
1457// Returns true if the current frame is a FTL frame.
1458// Usage: isFTL = $vm.ftlTrue()
1459static EncodedJSValue JSC_HOST_CALL functionFTLTrue(JSGlobalObject*, CallFrame*)
1460{
1461 DollarVMAssertScope assertScope;
1462 return JSValue::encode(jsBoolean(false));
1463}
1464
1465static EncodedJSValue JSC_HOST_CALL functionCpuMfence(JSGlobalObject*, CallFrame*)
1466{
1467 DollarVMAssertScope assertScope;
1468#if CPU(X86_64) && !OS(WINDOWS)
1469 asm volatile("mfence" ::: "memory");
1470#endif
1471 return JSValue::encode(jsUndefined());
1472}
1473
1474static EncodedJSValue JSC_HOST_CALL functionCpuRdtsc(JSGlobalObject*, CallFrame*)
1475{
1476 DollarVMAssertScope assertScope;
1477#if CPU(X86_64) && !OS(WINDOWS)
1478 unsigned high;
1479 unsigned low;
1480 asm volatile ("rdtsc" : "=a"(low), "=d"(high));
1481 return JSValue::encode(jsNumber(low));
1482#else
1483 return JSValue::encode(jsNumber(0));
1484#endif
1485}
1486
1487static EncodedJSValue JSC_HOST_CALL functionCpuCpuid(JSGlobalObject*, CallFrame*)
1488{
1489 DollarVMAssertScope assertScope;
1490#if CPU(X86_64) && !OS(WINDOWS)
1491 WTF::x86_cpuid();
1492#endif
1493 return JSValue::encode(jsUndefined());
1494}
1495
1496static EncodedJSValue JSC_HOST_CALL functionCpuPause(JSGlobalObject*, CallFrame*)
1497{
1498 DollarVMAssertScope assertScope;
1499#if CPU(X86_64) && !OS(WINDOWS)
1500 asm volatile ("pause" ::: "memory");
1501#endif
1502 return JSValue::encode(jsUndefined());
1503}
1504
1505// This takes either a JSArrayBuffer, JSArrayBufferView*, or any other object as its first
1506// argument. The second argument is expected to be an integer.
1507//
1508// If the first argument is a JSArrayBuffer, it'll clflush on that buffer
1509// plus the second argument as a byte offset. It'll also flush on the object
1510// itself so its length, etc, aren't in the cache.
1511//
1512// If the first argument is not a JSArrayBuffer, we load the butterfly
1513// and clflush at the address of the butterfly.
1514static EncodedJSValue JSC_HOST_CALL functionCpuClflush(JSGlobalObject* globalObject, CallFrame* callFrame)
1515{
1516 DollarVMAssertScope assertScope;
1517#if CPU(X86_64) && !OS(WINDOWS)
1518 VM& vm = globalObject->vm();
1519
1520 if (!callFrame->argument(1).isInt32())
1521 return JSValue::encode(jsBoolean(false));
1522
1523 auto clflush = [] (void* ptr) {
1524 DollarVMAssertScope assertScope;
1525 char* ptrToFlush = static_cast<char*>(ptr);
1526 asm volatile ("clflush %0" :: "m"(*ptrToFlush) : "memory");
1527 };
1528
1529 Vector<void*> toFlush;
1530
1531 uint32_t offset = callFrame->argument(1).asUInt32();
1532
1533 if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(vm, callFrame->argument(0)))
1534 toFlush.append(bitwise_cast<char*>(view->vector()) + offset);
1535 else if (JSObject* object = jsDynamicCast<JSObject*>(vm, callFrame->argument(0))) {
1536 switch (object->indexingType()) {
1537 case ALL_INT32_INDEXING_TYPES:
1538 case ALL_CONTIGUOUS_INDEXING_TYPES:
1539 case ALL_DOUBLE_INDEXING_TYPES:
1540 toFlush.append(bitwise_cast<char*>(object->butterfly()) + Butterfly::offsetOfVectorLength());
1541 toFlush.append(bitwise_cast<char*>(object->butterfly()) + Butterfly::offsetOfPublicLength());
1542 }
1543 }
1544
1545 if (!toFlush.size())
1546 return JSValue::encode(jsBoolean(false));
1547
1548 for (void* ptr : toFlush)
1549 clflush(ptr);
1550 return JSValue::encode(jsBoolean(true));
1551#else
1552 UNUSED_PARAM(globalObject);
1553 UNUSED_PARAM(callFrame);
1554 return JSValue::encode(jsBoolean(false));
1555#endif
1556}
1557
1558class CallerFrameJITTypeFunctor {
1559public:
1560 CallerFrameJITTypeFunctor()
1561 : m_currentFrame(0)
1562 , m_jitType(JITType::None)
1563 {
1564 DollarVMAssertScope assertScope;
1565 }
1566
1567 StackVisitor::Status operator()(StackVisitor& visitor) const
1568 {
1569 if (m_currentFrame++ > 1) {
1570 m_jitType = visitor->codeBlock()->jitType();
1571 return StackVisitor::Done;
1572 }
1573 return StackVisitor::Continue;
1574 }
1575
1576 JITType jitType() { return m_jitType; }
1577
1578private:
1579 mutable unsigned m_currentFrame;
1580 mutable JITType m_jitType;
1581};
1582
1583static FunctionExecutable* getExecutableForFunction(JSValue theFunctionValue)
1584{
1585 DollarVMAssertScope assertScope;
1586 if (!theFunctionValue.isCell())
1587 return nullptr;
1588
1589 VM& vm = theFunctionValue.asCell()->vm();
1590 JSFunction* theFunction = jsDynamicCast<JSFunction*>(vm, theFunctionValue);
1591 if (!theFunction)
1592 return nullptr;
1593
1594 FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(vm,
1595 theFunction->executable());
1596
1597 return executable;
1598}
1599
1600// Returns true if the current frame is a LLInt frame.
1601// Usage: isLLInt = $vm.llintTrue()
1602static EncodedJSValue JSC_HOST_CALL functionLLintTrue(JSGlobalObject* globalObject, CallFrame* callFrame)
1603{
1604 DollarVMAssertScope assertScope;
1605 VM& vm = globalObject->vm();
1606 if (!callFrame)
1607 return JSValue::encode(jsUndefined());
1608 CallerFrameJITTypeFunctor functor;
1609 callFrame->iterate(vm, functor);
1610 return JSValue::encode(jsBoolean(functor.jitType() == JITType::InterpreterThunk));
1611}
1612
1613// Returns true if the current frame is a baseline JIT frame.
1614// Usage: isBaselineJIT = $vm.jitTrue()
1615static EncodedJSValue JSC_HOST_CALL functionJITTrue(JSGlobalObject* globalObject, CallFrame* callFrame)
1616{
1617 DollarVMAssertScope assertScope;
1618 VM& vm = globalObject->vm();
1619 if (!callFrame)
1620 return JSValue::encode(jsUndefined());
1621 CallerFrameJITTypeFunctor functor;
1622 callFrame->iterate(vm, functor);
1623 return JSValue::encode(jsBoolean(functor.jitType() == JITType::BaselineJIT));
1624}
1625
1626// Set that the argument function should not be inlined.
1627// Usage:
1628// function f() { };
1629// $vm.noInline(f);
1630static EncodedJSValue JSC_HOST_CALL functionNoInline(JSGlobalObject*, CallFrame* callFrame)
1631{
1632 DollarVMAssertScope assertScope;
1633 if (callFrame->argumentCount() < 1)
1634 return JSValue::encode(jsUndefined());
1635
1636 JSValue theFunctionValue = callFrame->uncheckedArgument(0);
1637
1638 if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue))
1639 executable->setNeverInline(true);
1640
1641 return JSValue::encode(jsUndefined());
1642}
1643
1644// Runs a full GC synchronously.
1645// Usage: $vm.gc()
1646static EncodedJSValue JSC_HOST_CALL functionGC(JSGlobalObject* globalObject, CallFrame*)
1647{
1648 DollarVMAssertScope assertScope;
1649 VMInspector::gc(globalObject);
1650 return JSValue::encode(jsUndefined());
1651}
1652
1653// Runs the edenGC synchronously.
1654// Usage: $vm.edenGC()
1655static EncodedJSValue JSC_HOST_CALL functionEdenGC(JSGlobalObject* globalObject, CallFrame*)
1656{
1657 DollarVMAssertScope assertScope;
1658 VMInspector::edenGC(globalObject);
1659 return JSValue::encode(jsUndefined());
1660}
1661
1662// Dumps the hashes of all subspaces currently registered with the VM.
1663// Usage: $vm.dumpSubspaceHashes()
1664static EncodedJSValue JSC_HOST_CALL functionDumpSubspaceHashes(JSGlobalObject* globalObject, CallFrame*)
1665{
1666 DollarVMAssertScope assertScope;
1667 VM& vm = globalObject->vm();
1668 VMInspector::dumpSubspaceHashes(&vm);
1669 return JSValue::encode(jsUndefined());
1670}
1671
1672// Gets a JSDollarVMCallFrame for a specified frame index.
1673// Usage: var callFrame = $vm.callFrame(0) // frame 0 is the top frame.
1674// Usage: var callFrame = $vm.callFrame() // implies frame 0 i.e. current frame.
1675//
1676// This gives you the ability to query the following:
1677// callFrame.valid; // false if we asked for a frame beyond the end of the stack, else true.
1678// callFrame.callee;
1679// callFrame.codeBlock;
1680// callFrame.unlinkedCodeBlock;
1681// callFrame.executable;
1682//
1683// Note: you cannot toString() a codeBlock, unlinkedCodeBlock, or executable because
1684// there are internal objects and not a JS object. Hence, you cannot do string
1685// concatenation with them.
1686static EncodedJSValue JSC_HOST_CALL functionCallFrame(JSGlobalObject* globalObject, CallFrame* callFrame)
1687{
1688 DollarVMAssertScope assertScope;
1689 unsigned frameNumber = 1;
1690 if (callFrame->argumentCount() >= 1) {
1691 JSValue value = callFrame->uncheckedArgument(0);
1692 if (!value.isUInt32())
1693 return JSValue::encode(jsUndefined());
1694
1695 // We need to inc the frame number because the caller would consider
1696 // its own frame as frame 0. Hence, we need discount the frame for this
1697 // function.
1698 frameNumber = value.asUInt32() + 1;
1699 }
1700
1701 return JSValue::encode(JSDollarVMCallFrame::create(globalObject, callFrame, frameNumber));
1702}
1703
1704// Gets a token for the CodeBlock for a specified frame index.
1705// Usage: codeBlockToken = $vm.codeBlockForFrame(0) // frame 0 is the top frame.
1706// Usage: codeBlockToken = $vm.codeBlockForFrame() // implies frame 0 i.e. current frame.
1707static EncodedJSValue JSC_HOST_CALL functionCodeBlockForFrame(JSGlobalObject* globalObject, CallFrame* callFrame)
1708{
1709 DollarVMAssertScope assertScope;
1710 unsigned frameNumber = 1;
1711 if (callFrame->argumentCount() >= 1) {
1712 JSValue value = callFrame->uncheckedArgument(0);
1713 if (!value.isUInt32())
1714 return JSValue::encode(jsUndefined());
1715
1716 // We need to inc the frame number because the caller would consider
1717 // its own frame as frame 0. Hence, we need discount the frame for this
1718 // function.
1719 frameNumber = value.asUInt32() + 1;
1720 }
1721
1722 CodeBlock* codeBlock = VMInspector::codeBlockForFrame(globalObject, callFrame, frameNumber);
1723 if (codeBlock)
1724 return JSValue::encode(codeBlock);
1725 return JSValue::encode(jsUndefined());
1726}
1727
1728static CodeBlock* codeBlockFromArg(JSGlobalObject* globalObject, CallFrame* callFrame)
1729{
1730 DollarVMAssertScope assertScope;
1731 VM& vm = globalObject->vm();
1732 if (callFrame->argumentCount() < 1)
1733 return nullptr;
1734
1735 JSValue value = callFrame->uncheckedArgument(0);
1736 CodeBlock* candidateCodeBlock = nullptr;
1737 if (value.isCell()) {
1738 JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell());
1739 if (func) {
1740 if (func->isHostFunction())
1741 candidateCodeBlock = nullptr;
1742 else
1743 candidateCodeBlock = func->jsExecutable()->eitherCodeBlock();
1744 } else
1745 candidateCodeBlock = static_cast<CodeBlock*>(value.asCell());
1746 }
1747
1748 if (candidateCodeBlock && VMInspector::isValidCodeBlock(globalObject, candidateCodeBlock))
1749 return candidateCodeBlock;
1750
1751 if (candidateCodeBlock)
1752 dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n");
1753 else
1754 dataLog("Invalid codeBlock: ", value, "\n");
1755 return nullptr;
1756}
1757
1758// Usage: $vm.print("codeblock = ", $vm.codeBlockFor(functionObj))
1759// Usage: $vm.print("codeblock = ", $vm.codeBlockFor(codeBlockToken))
1760// Note: you cannot toString() a codeBlock because it's an internal object and not
1761// a JS object. Hence, you cannot do string concatenation with it.
1762static EncodedJSValue JSC_HOST_CALL functionCodeBlockFor(JSGlobalObject* globalObject, CallFrame* callFrame)
1763{
1764 DollarVMAssertScope assertScope;
1765 CodeBlock* codeBlock = codeBlockFromArg(globalObject, callFrame);
1766 WTF::StringPrintStream stream;
1767 if (codeBlock) {
1768 stream.print(*codeBlock);
1769 return JSValue::encode(jsString(globalObject->vm(), stream.toString()));
1770 }
1771 return JSValue::encode(jsUndefined());
1772}
1773
1774// Usage: $vm.dumpSourceFor(functionObj)
1775// Usage: $vm.dumpSourceFor(codeBlockToken)
1776static EncodedJSValue JSC_HOST_CALL functionDumpSourceFor(JSGlobalObject* globalObject, CallFrame* callFrame)
1777{
1778 DollarVMAssertScope assertScope;
1779 CodeBlock* codeBlock = codeBlockFromArg(globalObject, callFrame);
1780 if (codeBlock)
1781 codeBlock->dumpSource();
1782 return JSValue::encode(jsUndefined());
1783}
1784
1785// Usage: $vm.dumpBytecodeFor(functionObj)
1786// Usage: $vm.dumpBytecodeFor(codeBlock)
1787static EncodedJSValue JSC_HOST_CALL functionDumpBytecodeFor(JSGlobalObject* globalObject, CallFrame* callFrame)
1788{
1789 DollarVMAssertScope assertScope;
1790 CodeBlock* codeBlock = codeBlockFromArg(globalObject, callFrame);
1791 if (codeBlock)
1792 codeBlock->dumpBytecode();
1793 return JSValue::encode(jsUndefined());
1794}
1795
1796static EncodedJSValue doPrint(JSGlobalObject* globalObject, CallFrame* callFrame, bool addLineFeed)
1797{
1798 DollarVMAssertScope assertScope;
1799 auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
1800 for (unsigned i = 0; i < callFrame->argumentCount(); ++i) {
1801 JSValue arg = callFrame->uncheckedArgument(i);
1802 if (arg.isCell()
1803 && !arg.isObject()
1804 && !arg.isString()
1805 && !arg.isBigInt()) {
1806 dataLog(arg);
1807 continue;
1808 }
1809 String argStr = callFrame->uncheckedArgument(i).toWTFString(globalObject);
1810 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1811 dataLog(argStr);
1812 }
1813 if (addLineFeed)
1814 dataLog("\n");
1815 return JSValue::encode(jsUndefined());
1816}
1817
1818// Prints a series of comma separate strings without appending a newline.
1819// Usage: $vm.dataLog(str1, str2, str3)
1820static EncodedJSValue JSC_HOST_CALL functionDataLog(JSGlobalObject* globalObject, CallFrame* callFrame)
1821{
1822 DollarVMAssertScope assertScope;
1823 const bool addLineFeed = false;
1824 return doPrint(globalObject, callFrame, addLineFeed);
1825}
1826
1827// Prints a series of comma separate strings and appends a newline.
1828// Usage: $vm.print(str1, str2, str3)
1829static EncodedJSValue JSC_HOST_CALL functionPrint(JSGlobalObject* globalObject, CallFrame* callFrame)
1830{
1831 DollarVMAssertScope assertScope;
1832 const bool addLineFeed = true;
1833 return doPrint(globalObject, callFrame, addLineFeed);
1834}
1835
1836// Dumps the current CallFrame.
1837// Usage: $vm.dumpCallFrame()
1838static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(JSGlobalObject* globalObject, CallFrame* callFrame)
1839{
1840 DollarVMAssertScope assertScope;
1841 // When the callers call this function, they are expecting to dump their
1842 // own frame. So skip 1 for this frame.
1843 VMInspector::dumpCallFrame(globalObject, callFrame, 1);
1844 return JSValue::encode(jsUndefined());
1845}
1846
1847// Dumps the JS stack.
1848// Usage: $vm.printStack()
1849static EncodedJSValue JSC_HOST_CALL functionDumpStack(JSGlobalObject* globalObject, CallFrame* callFrame)
1850{
1851 DollarVMAssertScope assertScope;
1852 // When the callers call this function, they are expecting to dump the
1853 // stack starting their own frame. So skip 1 for this frame.
1854 VMInspector::dumpStack(globalObject, callFrame, 1);
1855 return JSValue::encode(jsUndefined());
1856}
1857
1858// Dumps the current CallFrame.
1859// Usage: $vm.dumpRegisters(N) // dump the registers of the Nth CallFrame.
1860// Usage: $vm.dumpRegisters() // dump the registers of the current CallFrame.
1861// FIXME: Currently, this function dumps the physical frame. We should make
1862// it dump the logical frame (i.e. be able to dump inlined frames as well).
1863static EncodedJSValue JSC_HOST_CALL functionDumpRegisters(JSGlobalObject* globalObject, CallFrame* callFrame)
1864{
1865 DollarVMAssertScope assertScope;
1866 VM& vm = globalObject->vm();
1867 unsigned requestedFrameIndex = 1;
1868 if (callFrame->argumentCount() >= 1) {
1869 JSValue value = callFrame->uncheckedArgument(0);
1870 if (!value.isUInt32())
1871 return JSValue::encode(jsUndefined());
1872
1873 // We need to inc the frame number because the caller would consider
1874 // its own frame as frame 0. Hence, we need discount the frame for this
1875 // function.
1876 requestedFrameIndex = value.asUInt32() + 1;
1877 }
1878
1879 unsigned frameIndex = 0;
1880 callFrame->iterate(vm, [&] (StackVisitor& visitor) {
1881 DollarVMAssertScope assertScope;
1882 if (frameIndex++ != requestedFrameIndex)
1883 return StackVisitor::Continue;
1884 VMInspector::dumpRegisters(visitor->callFrame());
1885 return StackVisitor::Done;
1886 });
1887
1888 return encodedJSUndefined();
1889}
1890
1891// Dumps the internal memory layout of a JSCell.
1892// Usage: $vm.dumpCell(cell)
1893static EncodedJSValue JSC_HOST_CALL functionDumpCell(JSGlobalObject*, CallFrame* callFrame)
1894{
1895 DollarVMAssertScope assertScope;
1896 JSValue value = callFrame->argument(0);
1897 if (!value.isCell())
1898 return encodedJSUndefined();
1899
1900 VMInspector::dumpCellMemory(value.asCell());
1901 return encodedJSUndefined();
1902}
1903
1904// Gets the dataLog dump of the indexingMode of the passed value.
1905// Usage: $vm.print("indexingMode = " + $vm.indexingMode(jsValue))
1906static EncodedJSValue JSC_HOST_CALL functionIndexingMode(JSGlobalObject* globalObject, CallFrame* callFrame)
1907{
1908 DollarVMAssertScope assertScope;
1909 if (!callFrame->argument(0).isObject())
1910 return encodedJSUndefined();
1911
1912 WTF::StringPrintStream stream;
1913 stream.print(IndexingTypeDump(callFrame->uncheckedArgument(0).getObject()->indexingMode()));
1914 return JSValue::encode(jsString(globalObject->vm(), stream.toString()));
1915}
1916
1917static EncodedJSValue JSC_HOST_CALL functionInlineCapacity(JSGlobalObject* globalObject, CallFrame* callFrame)
1918{
1919 DollarVMAssertScope assertScope;
1920 VM& vm = globalObject->vm();
1921 if (auto* object = jsDynamicCast<JSObject*>(vm, callFrame->argument(0)))
1922 return JSValue::encode(jsNumber(object->structure(vm)->inlineCapacity()));
1923
1924 return encodedJSUndefined();
1925}
1926
1927// Gets the dataLog dump of a given JS value as a string.
1928// Usage: $vm.print("value = " + $vm.value(jsValue))
1929static EncodedJSValue JSC_HOST_CALL functionValue(JSGlobalObject* globalObject, CallFrame* callFrame)
1930{
1931 DollarVMAssertScope assertScope;
1932 WTF::StringPrintStream stream;
1933 for (unsigned i = 0; i < callFrame->argumentCount(); ++i) {
1934 if (i)
1935 stream.print(", ");
1936 stream.print(callFrame->uncheckedArgument(i));
1937 }
1938
1939 return JSValue::encode(jsString(globalObject->vm(), stream.toString()));
1940}
1941
1942// Gets the pid of the current process.
1943// Usage: $vm.print("pid = " + $vm.getpid())
1944static EncodedJSValue JSC_HOST_CALL functionGetPID(JSGlobalObject*, CallFrame*)
1945{
1946 DollarVMAssertScope assertScope;
1947 return JSValue::encode(jsNumber(getCurrentProcessID()));
1948}
1949
1950// Make the globalObject have a bad time. Does nothing if the object is not a JSGlobalObject.
1951// Usage: $vm.haveABadTime(globalObject)
1952static EncodedJSValue JSC_HOST_CALL functionHaveABadTime(JSGlobalObject* globalObject, CallFrame* callFrame)
1953{
1954 DollarVMAssertScope assertScope;
1955 VM& vm = globalObject->vm();
1956 JSLockHolder lock(vm);
1957 JSValue objValue = callFrame->argument(0);
1958 if (!objValue.isObject())
1959 return JSValue::encode(jsBoolean(false));
1960
1961 JSObject* obj = asObject(objValue.asCell());
1962 JSGlobalObject* target = jsDynamicCast<JSGlobalObject*>(vm, obj);
1963 if (!target)
1964 JSValue::encode(jsBoolean(false));
1965
1966 target->haveABadTime(vm);
1967 return JSValue::encode(jsBoolean(true));
1968}
1969
1970// Checks if the object (or its global if the object is not a global) is having a bad time.
1971// Usage: $vm.isHavingABadTime(obj)
1972static EncodedJSValue JSC_HOST_CALL functionIsHavingABadTime(JSGlobalObject* globalObject, CallFrame* callFrame)
1973{
1974 DollarVMAssertScope assertScope;
1975 VM& vm = globalObject->vm();
1976 JSLockHolder lock(vm);
1977 JSValue objValue = callFrame->argument(0);
1978 if (!objValue.isObject())
1979 return JSValue::encode(jsUndefined());
1980
1981 JSObject* obj = asObject(objValue.asCell());
1982 JSGlobalObject* target = jsDynamicCast<JSGlobalObject*>(vm, obj);
1983 if (target)
1984 JSValue::encode(jsBoolean(target->isHavingABadTime()));
1985
1986 target= obj->globalObject();
1987 if (!target)
1988 return JSValue::encode(jsUndefined());
1989
1990 return JSValue::encode(jsBoolean(target->isHavingABadTime()));
1991}
1992
1993// Calls the specified test function after adjusting the stack to have the specified
1994// remaining size from the end of the physical stack.
1995// Usage: $vm.callWithStackSize(funcToCall, desiredStackSize)
1996//
1997// This function will only work in test configurations, specifically, only if JSC
1998// options are not frozen. For the jsc shell, the --disableOptionsFreezingForTesting
1999// argument needs to be passed in on the command line.
2000
2001#if ENABLE(MASM_PROBE)
2002static void callWithStackSizeProbeFunction(Probe::State* state)
2003{
2004 JSGlobalObject* globalObject = bitwise_cast<JSGlobalObject*>(state->arg);
2005 JSFunction* function = bitwise_cast<JSFunction*>(state->probeFunction);
2006 state->initializeStackFunction = nullptr;
2007 state->initializeStackArg = nullptr;
2008
2009 DollarVMAssertScope assertScope;
2010 VM& vm = globalObject->vm();
2011
2012 CallData callData;
2013 CallType callType = getCallData(vm, function, callData);
2014 MarkedArgumentBuffer args;
2015 call(globalObject, function, callType, callData, jsUndefined(), args);
2016}
2017#endif // ENABLE(MASM_PROBE)
2018
2019SUPPRESS_ASAN
2020static EncodedJSValue JSC_HOST_CALL functionCallWithStackSize(JSGlobalObject* globalObject, CallFrame* callFrame)
2021{
2022 DollarVMAssertScope assertScope;
2023 VM& vm = globalObject->vm();
2024 JSLockHolder lock(vm);
2025 auto throwScope = DECLARE_THROW_SCOPE(vm);
2026
2027#if OS(DARWIN) && CPU(X86_64)
2028 constexpr bool isSupportedByPlatform = true;
2029#else
2030 constexpr bool isSupportedByPlatform = false;
2031#endif
2032
2033 if (!isSupportedByPlatform)
2034 return throwVMError(globalObject, throwScope, "Not supported for this platform");
2035
2036#if ENABLE(MASM_PROBE)
2037 if (g_jscConfig.isPermanentlyFrozen || !g_jscConfig.disabledFreezingForTesting)
2038 return throwVMError(globalObject, throwScope, "Options are frozen");
2039
2040 if (callFrame->argumentCount() < 2)
2041 return throwVMError(globalObject, throwScope, "Invalid number of arguments");
2042 JSValue arg0 = callFrame->argument(0);
2043 JSValue arg1 = callFrame->argument(1);
2044 if (!arg0.isFunction(vm))
2045 return throwVMError(globalObject, throwScope, "arg0 should be a function");
2046 if (!arg1.isNumber())
2047 return throwVMError(globalObject, throwScope, "arg1 should be a number");
2048
2049 JSFunction* function = jsCast<JSFunction*>(arg0);
2050 size_t desiredStackSize = arg1.asNumber();
2051
2052 const StackBounds& bounds = Thread::current().stack();
2053 uint8_t* currentStackPosition = bitwise_cast<uint8_t*>(currentStackPointer());
2054 uint8_t* end = bitwise_cast<uint8_t*>(bounds.end());
2055 uint8_t* desiredStart = end + desiredStackSize;
2056 if (desiredStart >= currentStackPosition)
2057 return throwVMError(globalObject, throwScope, "Unable to setup desired stack size");
2058
2059 JSDollarVMHelper helper(vm);
2060
2061 unsigned originalMaxPerThreadStackUsage = Options::maxPerThreadStackUsage();
2062 void* originalVMSoftStackLimit = vm.softStackLimit();
2063 void* originalVMStackLimit = vm.stackLimit();
2064
2065 // This is a hack to make the VM think it's stack limits are near the end
2066 // of the physical stack.
2067 uint8_t* vmStackStart = bitwise_cast<uint8_t*>(vm.stackPointerAtVMEntry());
2068 uint8_t* vmStackEnd = vmStackStart - originalMaxPerThreadStackUsage;
2069 ptrdiff_t sizeDiff = vmStackEnd - end;
2070 RELEASE_ASSERT(sizeDiff >= 0);
2071 RELEASE_ASSERT(sizeDiff < UINT_MAX);
2072
2073 Options::maxPerThreadStackUsage() = originalMaxPerThreadStackUsage + sizeDiff;
2074 helper.updateVMStackLimits();
2075
2076#if OS(DARWIN) && CPU(X86_64)
2077 __asm__ volatile (
2078 "subq %[sizeDiff], %%rsp" "\n"
2079 "pushq %%rax" "\n"
2080 "pushq %%rcx" "\n"
2081 "pushq %%rdx" "\n"
2082 "pushq %%rbx" "\n"
2083 "callq *%%rax" "\n"
2084 "addq %[sizeDiff], %%rsp" "\n"
2085 :
2086 : "a" (ctiMasmProbeTrampoline)
2087 , "c" (callWithStackSizeProbeFunction)
2088 , "d" (function)
2089 , "b" (globalObject)
2090 , [sizeDiff] "rm" (sizeDiff)
2091 : "memory"
2092 );
2093#else
2094 UNUSED_PARAM(function);
2095#if !COMPILER(MSVC)
2096 UNUSED_PARAM(callWithStackSizeProbeFunction);
2097#endif
2098#endif // OS(DARWIN) && CPU(X86_64)
2099
2100 Options::maxPerThreadStackUsage() = originalMaxPerThreadStackUsage;
2101 helper.updateVMStackLimits();
2102 RELEASE_ASSERT(vm.softStackLimit() == originalVMSoftStackLimit);
2103 RELEASE_ASSERT(vm.stackLimit() == originalVMStackLimit);
2104
2105 throwScope.release();
2106 return encodedJSUndefined();
2107
2108#else // not ENABLE(MASM_PROBE)
2109 UNUSED_PARAM(callFrame);
2110 return throwVMError(globalObject, throwScope, "Not supported for this platform");
2111#endif // ENABLE(MASM_PROBE)
2112}
2113
2114// Creates a new global object.
2115// Usage: $vm.createGlobalObject()
2116static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(JSGlobalObject* globalObject, CallFrame*)
2117{
2118 DollarVMAssertScope assertScope;
2119 VM& vm = globalObject->vm();
2120 JSLockHolder lock(vm);
2121 return JSValue::encode(JSGlobalObject::create(vm, JSGlobalObject::createStructure(vm, jsNull())));
2122}
2123
2124static EncodedJSValue JSC_HOST_CALL functionCreateProxy(JSGlobalObject* globalObject, CallFrame* callFrame)
2125{
2126 DollarVMAssertScope assertScope;
2127 VM& vm = globalObject->vm();
2128 JSLockHolder lock(vm);
2129 JSValue target = callFrame->argument(0);
2130 if (!target.isObject())
2131 return JSValue::encode(jsUndefined());
2132 JSObject* jsTarget = asObject(target.asCell());
2133 Structure* structure = JSProxy::createStructure(vm, globalObject, jsTarget->getPrototypeDirect(vm), ImpureProxyType);
2134 JSProxy* proxy = JSProxy::create(vm, structure, jsTarget);
2135 return JSValue::encode(proxy);
2136}
2137
2138static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(JSGlobalObject* globalObject, CallFrame* callFrame)
2139{
2140 DollarVMAssertScope assertScope;
2141 JSLockHolder lock(globalObject);
2142 RuntimeArray* array = RuntimeArray::create(globalObject, callFrame);
2143 return JSValue::encode(array);
2144}
2145
2146static EncodedJSValue JSC_HOST_CALL functionCreateNullRopeString(JSGlobalObject* globalObject, CallFrame*)
2147{
2148 DollarVMAssertScope assertScope;
2149 VM& vm = globalObject->vm();
2150 JSLockHolder lock(vm);
2151 return JSValue::encode(JSRopeString::createNullForTesting(vm));
2152}
2153
2154static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(JSGlobalObject* globalObject, CallFrame* callFrame)
2155{
2156 DollarVMAssertScope assertScope;
2157 VM& vm = globalObject->vm();
2158 JSLockHolder lock(vm);
2159 JSValue target = callFrame->argument(0);
2160 JSObject* delegate = nullptr;
2161 if (target.isObject())
2162 delegate = asObject(target.asCell());
2163 Structure* structure = ImpureGetter::createStructure(vm, globalObject, jsNull());
2164 ImpureGetter* result = ImpureGetter::create(vm, structure, delegate);
2165 return JSValue::encode(result);
2166}
2167
2168static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(JSGlobalObject* globalObject, CallFrame*)
2169{
2170 DollarVMAssertScope assertScope;
2171 VM& vm = globalObject->vm();
2172 JSLockHolder lock(vm);
2173 Structure* structure = CustomGetter::createStructure(vm, globalObject, jsNull());
2174 CustomGetter* result = CustomGetter::create(vm, structure);
2175 return JSValue::encode(result);
2176}
2177
2178static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(JSGlobalObject* globalObject, CallFrame*)
2179{
2180 DollarVMAssertScope assertScope;
2181 VM& vm = globalObject->vm();
2182 JSLockHolder lock(vm);
2183 Structure* structure = DOMJITNode::createStructure(vm, globalObject, DOMJITGetter::create(vm, DOMJITGetter::createStructure(vm, globalObject, jsNull())));
2184 DOMJITNode* result = DOMJITNode::create(vm, structure);
2185 return JSValue::encode(result);
2186}
2187
2188static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(JSGlobalObject* globalObject, CallFrame*)
2189{
2190 DollarVMAssertScope assertScope;
2191 VM& vm = globalObject->vm();
2192 JSLockHolder lock(vm);
2193 Structure* structure = DOMJITGetter::createStructure(vm, globalObject, jsNull());
2194 DOMJITGetter* result = DOMJITGetter::create(vm, structure);
2195 return JSValue::encode(result);
2196}
2197
2198static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(JSGlobalObject* globalObject, CallFrame*)
2199{
2200 DollarVMAssertScope assertScope;
2201 VM& vm = globalObject->vm();
2202 JSLockHolder lock(vm);
2203 Structure* structure = DOMJITGetterComplex::createStructure(vm, globalObject, jsNull());
2204 DOMJITGetterComplex* result = DOMJITGetterComplex::create(vm, globalObject, structure);
2205 return JSValue::encode(result);
2206}
2207
2208static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(JSGlobalObject* globalObject, CallFrame*)
2209{
2210 DollarVMAssertScope assertScope;
2211 VM& vm = globalObject->vm();
2212 JSLockHolder lock(vm);
2213 Structure* structure = DOMJITFunctionObject::createStructure(vm, globalObject, jsNull());
2214 DOMJITFunctionObject* result = DOMJITFunctionObject::create(vm, globalObject, structure);
2215 return JSValue::encode(result);
2216}
2217
2218static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITCheckSubClassObject(JSGlobalObject* globalObject, CallFrame*)
2219{
2220 DollarVMAssertScope assertScope;
2221 VM& vm = globalObject->vm();
2222 JSLockHolder lock(vm);
2223 Structure* structure = DOMJITCheckSubClassObject::createStructure(vm, globalObject, jsNull());
2224 DOMJITCheckSubClassObject* result = DOMJITCheckSubClassObject::create(vm, globalObject, structure);
2225 return JSValue::encode(result);
2226}
2227
2228static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterBaseJSObject(JSGlobalObject* globalObject, CallFrame*)
2229{
2230 DollarVMAssertScope assertScope;
2231 VM& vm = globalObject->vm();
2232 JSLockHolder lock(vm);
2233 Structure* structure = DOMJITGetterBaseJSObject::createStructure(vm, globalObject, jsNull());
2234 DOMJITGetterBaseJSObject* result = DOMJITGetterBaseJSObject::create(vm, structure);
2235 return JSValue::encode(result);
2236}
2237
2238#if ENABLE(WEBASSEMBLY)
2239static EncodedJSValue JSC_HOST_CALL functionCreateWasmStreamingParser(JSGlobalObject* globalObject, CallFrame*)
2240{
2241 DollarVMAssertScope assertScope;
2242 VM& vm = globalObject->vm();
2243 JSLockHolder lock(vm);
2244 return JSValue::encode(WasmStreamingParser::create(vm, globalObject));
2245}
2246#endif
2247
2248static EncodedJSValue JSC_HOST_CALL functionCreateStaticCustomAccessor(JSGlobalObject* globalObject, CallFrame*)
2249{
2250 DollarVMAssertScope assertScope;
2251 VM& vm = globalObject->vm();
2252 JSLockHolder lock(vm);
2253 Structure* structure = StaticCustomAccessor::createStructure(vm, globalObject, jsNull());
2254 auto* result = StaticCustomAccessor::create(vm, structure);
2255 return JSValue::encode(result);
2256}
2257
2258static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(JSGlobalObject* globalObject, CallFrame* callFrame)
2259{
2260 DollarVMAssertScope assertScope;
2261 VM& vm = globalObject->vm();
2262 JSLockHolder lock(vm);
2263 auto scope = DECLARE_THROW_SCOPE(vm);
2264
2265 JSValue base = callFrame->argument(0);
2266 if (!base.isObject())
2267 return JSValue::encode(jsUndefined());
2268 JSValue delegate = callFrame->argument(1);
2269 if (!delegate.isObject())
2270 return JSValue::encode(jsUndefined());
2271 ImpureGetter* impureGetter = jsDynamicCast<ImpureGetter*>(vm, asObject(base.asCell()));
2272 if (UNLIKELY(!impureGetter)) {
2273 throwTypeError(globalObject, scope, "argument is not an ImpureGetter"_s);
2274 return encodedJSValue();
2275 }
2276 impureGetter->setDelegate(vm, asObject(delegate.asCell()));
2277 return JSValue::encode(jsUndefined());
2278}
2279
2280static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(JSGlobalObject* globalObject, CallFrame* callFrame)
2281{
2282 DollarVMAssertScope assertScope;
2283 VM& vm = globalObject->vm();
2284 auto scope = DECLARE_THROW_SCOPE(vm);
2285
2286 if (callFrame->argumentCount() < 1 || !callFrame->argument(0).isString())
2287 return JSValue::encode(jsUndefined());
2288
2289 String functionText = asString(callFrame->argument(0))->value(globalObject);
2290 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2291
2292 SourceCode source = makeSource(functionText, { });
2293 JSFunction* func = JSFunction::create(vm, createBuiltinExecutable(vm, source, Identifier::fromString(vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, nullptr, source), globalObject);
2294
2295 return JSValue::encode(func);
2296}
2297
2298static EncodedJSValue JSC_HOST_CALL functionGetPrivateProperty(JSGlobalObject* globalObject, CallFrame* callFrame)
2299{
2300 DollarVMAssertScope assertScope;
2301 VM& vm = globalObject->vm();
2302 auto scope = DECLARE_THROW_SCOPE(vm);
2303
2304 if (callFrame->argumentCount() < 2 || !callFrame->argument(1).isString())
2305 return encodedJSUndefined();
2306
2307 String str = asString(callFrame->argument(1))->value(globalObject);
2308
2309 SymbolImpl* symbol = vm.propertyNames->lookUpPrivateName(Identifier::fromString(vm, str));
2310 if (!symbol)
2311 return throwVMError(globalObject, scope, "Unknown private name.");
2312
2313 RELEASE_AND_RETURN(scope, JSValue::encode(callFrame->argument(0).get(globalObject, symbol)));
2314}
2315
2316static EncodedJSValue JSC_HOST_CALL functionCreateRoot(JSGlobalObject* globalObject, CallFrame*)
2317{
2318 DollarVMAssertScope assertScope;
2319 VM& vm = globalObject->vm();
2320 JSLockHolder lock(vm);
2321 return JSValue::encode(Root::create(vm, globalObject));
2322}
2323
2324static EncodedJSValue JSC_HOST_CALL functionCreateElement(JSGlobalObject* globalObject, CallFrame* callFrame)
2325{
2326 DollarVMAssertScope assertScope;
2327 VM& vm = globalObject->vm();
2328 JSLockHolder lock(vm);
2329 auto scope = DECLARE_THROW_SCOPE(vm);
2330
2331 Root* root = jsDynamicCast<Root*>(vm, callFrame->argument(0));
2332 if (!root)
2333 return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Cannot create Element without a Root."_s)));
2334 return JSValue::encode(Element::create(vm, globalObject, root));
2335}
2336
2337static EncodedJSValue JSC_HOST_CALL functionGetElement(JSGlobalObject* globalObject, CallFrame* callFrame)
2338{
2339 DollarVMAssertScope assertScope;
2340 VM& vm = globalObject->vm();
2341 JSLockHolder lock(vm);
2342 Root* root = jsDynamicCast<Root*>(vm, callFrame->argument(0));
2343 if (!root)
2344 return JSValue::encode(jsUndefined());
2345 Element* result = root->element();
2346 return JSValue::encode(result ? result : jsUndefined());
2347}
2348
2349static EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(JSGlobalObject* globalObject, CallFrame*)
2350{
2351 DollarVMAssertScope assertScope;
2352 VM& vm = globalObject->vm();
2353 JSLockHolder lock(vm);
2354 return JSValue::encode(SimpleObject::create(vm, globalObject));
2355}
2356
2357static EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(JSGlobalObject* globalObject, CallFrame* callFrame)
2358{
2359 DollarVMAssertScope assertScope;
2360 VM& vm = globalObject->vm();
2361 JSLockHolder lock(vm);
2362 auto scope = DECLARE_THROW_SCOPE(vm);
2363
2364 SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, callFrame->argument(0));
2365 if (UNLIKELY(!simpleObject)) {
2366 throwTypeError(globalObject, scope, "Invalid use of getHiddenValue test function"_s);
2367 return encodedJSValue();
2368 }
2369 return JSValue::encode(simpleObject->hiddenValue());
2370}
2371
2372static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(JSGlobalObject* globalObject, CallFrame* callFrame)
2373{
2374 DollarVMAssertScope assertScope;
2375 VM& vm = globalObject->vm();
2376 JSLockHolder lock(vm);
2377 auto scope = DECLARE_THROW_SCOPE(vm);
2378
2379 SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, callFrame->argument(0));
2380 if (UNLIKELY(!simpleObject)) {
2381 throwTypeError(globalObject, scope, "Invalid use of setHiddenValue test function"_s);
2382 return encodedJSValue();
2383 }
2384 JSValue value = callFrame->argument(1);
2385 simpleObject->setHiddenValue(vm, value);
2386 return JSValue::encode(jsUndefined());
2387}
2388
2389static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(JSGlobalObject* globalObject, CallFrame* callFrame)
2390{
2391 DollarVMAssertScope assertScope;
2392 VM& vm = globalObject->vm();
2393 auto scope = DECLARE_THROW_SCOPE(vm);
2394 if (auto* shadowChicken = vm.shadowChicken()) {
2395 scope.release();
2396 return JSValue::encode(shadowChicken->functionsOnStack(globalObject, callFrame));
2397 }
2398
2399 JSArray* result = constructEmptyArray(globalObject, 0);
2400 RETURN_IF_EXCEPTION(scope, { });
2401 StackVisitor::visit(callFrame, vm, [&] (StackVisitor& visitor) -> StackVisitor::Status {
2402 DollarVMAssertScope assertScope;
2403 if (visitor->isInlinedFrame())
2404 return StackVisitor::Continue;
2405 if (visitor->isWasmFrame())
2406 return StackVisitor::Continue;
2407 result->push(globalObject, jsCast<JSObject*>(visitor->callee().asCell()));
2408 scope.releaseAssertNoException(); // This function is only called from tests.
2409 return StackVisitor::Continue;
2410 });
2411 RETURN_IF_EXCEPTION(scope, { });
2412 return JSValue::encode(result);
2413}
2414
2415static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(JSGlobalObject* globalObject, CallFrame*)
2416{
2417 DollarVMAssertScope assertScope;
2418 VM& vm = globalObject->vm();
2419 vm.setGlobalConstRedeclarationShouldThrow(false);
2420 return JSValue::encode(jsUndefined());
2421}
2422
2423static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(JSGlobalObject* globalObject, CallFrame* callFrame)
2424{
2425 DollarVMAssertScope assertScope;
2426 VM& vm = globalObject->vm();
2427 RELEASE_ASSERT(vm.typeProfiler());
2428 vm.typeProfilerLog()->processLogEntries(vm, "jsc Testing API: functionFindTypeForExpression"_s);
2429
2430 JSValue functionValue = callFrame->argument(0);
2431 RELEASE_ASSERT(functionValue.isFunction(vm));
2432 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2433
2434 RELEASE_ASSERT(callFrame->argument(1).isString());
2435 String substring = asString(callFrame->argument(1))->value(globalObject);
2436 String sourceCodeText = executable->source().view().toString();
2437 unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
2438
2439 String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), vm);
2440 return JSValue::encode(JSONParse(globalObject, jsonString));
2441}
2442
2443static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(JSGlobalObject* globalObject, CallFrame* callFrame)
2444{
2445 DollarVMAssertScope assertScope;
2446 VM& vm = globalObject->vm();
2447 RELEASE_ASSERT(vm.typeProfiler());
2448 vm.typeProfilerLog()->processLogEntries(vm, "jsc Testing API: functionReturnTypeFor"_s);
2449
2450 JSValue functionValue = callFrame->argument(0);
2451 RELEASE_ASSERT(functionValue.isFunction(vm));
2452 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2453
2454 unsigned offset = executable->typeProfilingStartOffset(vm);
2455 String jsonString = vm.typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), vm);
2456 return JSValue::encode(JSONParse(globalObject, jsonString));
2457}
2458
2459static EncodedJSValue JSC_HOST_CALL functionFlattenDictionaryObject(JSGlobalObject* globalObject, CallFrame* callFrame)
2460{
2461 DollarVMAssertScope assertScope;
2462 VM& vm = globalObject->vm();
2463 JSValue value = callFrame->argument(0);
2464 RELEASE_ASSERT(value.isObject() && value.getObject()->structure()->isDictionary());
2465 value.getObject()->flattenDictionaryObject(vm);
2466 return encodedJSUndefined();
2467}
2468
2469static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(JSGlobalObject* globalObject, CallFrame*)
2470{
2471 DollarVMAssertScope assertScope;
2472 VM& vm = globalObject->vm();
2473 RELEASE_ASSERT(vm.controlFlowProfiler());
2474 vm.controlFlowProfiler()->dumpData();
2475 return JSValue::encode(jsUndefined());
2476}
2477
2478static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(JSGlobalObject* globalObject, CallFrame* callFrame)
2479{
2480 DollarVMAssertScope assertScope;
2481 VM& vm = globalObject->vm();
2482 RELEASE_ASSERT(vm.controlFlowProfiler());
2483
2484 JSValue functionValue = callFrame->argument(0);
2485 RELEASE_ASSERT(functionValue.isFunction(vm));
2486 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2487
2488 RELEASE_ASSERT(callFrame->argument(1).isString());
2489 String substring = asString(callFrame->argument(1))->value(globalObject);
2490 String sourceCodeText = executable->source().view().toString();
2491 RELEASE_ASSERT(sourceCodeText.contains(substring));
2492 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
2493
2494 bool hasExecuted = vm.controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), vm);
2495 return JSValue::encode(jsBoolean(hasExecuted));
2496}
2497
2498static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(JSGlobalObject* globalObject, CallFrame* callFrame)
2499{
2500 DollarVMAssertScope assertScope;
2501 VM& vm = globalObject->vm();
2502 RELEASE_ASSERT(vm.controlFlowProfiler());
2503
2504 JSValue functionValue = callFrame->argument(0);
2505 RELEASE_ASSERT(functionValue.isFunction(vm));
2506 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2507
2508 RELEASE_ASSERT(callFrame->argument(1).isString());
2509 String substring = asString(callFrame->argument(1))->value(globalObject);
2510 String sourceCodeText = executable->source().view().toString();
2511 RELEASE_ASSERT(sourceCodeText.contains(substring));
2512 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
2513
2514 size_t executionCount = vm.controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), vm);
2515 return JSValue::encode(JSValue(executionCount));
2516}
2517
2518static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(JSGlobalObject*, CallFrame*)
2519{
2520 DollarVMAssertScope assertScope;
2521 Options::useExceptionFuzz() = true;
2522 return JSValue::encode(jsUndefined());
2523}
2524
2525class DoNothingDebugger final : public Debugger {
2526 WTF_MAKE_NONCOPYABLE(DoNothingDebugger);
2527 WTF_MAKE_FAST_ALLOCATED;
2528public:
2529 DoNothingDebugger(VM& vm)
2530 : Debugger(vm)
2531 {
2532 DollarVMAssertScope assertScope;
2533 setSuppressAllPauses(true);
2534 }
2535
2536private:
2537 void sourceParsed(JSGlobalObject*, SourceProvider*, int, const WTF::String&) override
2538 {
2539 DollarVMAssertScope assertScope;
2540 }
2541};
2542
2543static EncodedJSValue changeDebuggerModeWhenIdle(JSGlobalObject* globalObject, OptionSet<CodeGenerationMode> codeGenerationMode)
2544{
2545 DollarVMAssertScope assertScope;
2546
2547 bool debuggerRequested = codeGenerationMode.contains(CodeGenerationMode::Debugger);
2548 if (debuggerRequested == globalObject->hasDebugger())
2549 return JSValue::encode(jsUndefined());
2550
2551 VM* vm = &globalObject->vm();
2552 vm->whenIdle([=] () {
2553 DollarVMAssertScope assertScope;
2554 if (debuggerRequested) {
2555 Debugger* debugger = new DoNothingDebugger(globalObject->vm());
2556 globalObject->setDebugger(debugger);
2557 debugger->activateBreakpoints(); // Also deletes all code.
2558 } else {
2559 Debugger* debugger = globalObject->debugger();
2560 debugger->deactivateBreakpoints(); // Also deletes all code.
2561 globalObject->setDebugger(nullptr);
2562 delete debugger;
2563 }
2564 });
2565 return JSValue::encode(jsUndefined());
2566}
2567
2568static EncodedJSValue JSC_HOST_CALL functionEnableDebuggerModeWhenIdle(JSGlobalObject* globalObject, CallFrame*)
2569{
2570 DollarVMAssertScope assertScope;
2571 return changeDebuggerModeWhenIdle(globalObject, { CodeGenerationMode::Debugger });
2572}
2573
2574static EncodedJSValue JSC_HOST_CALL functionDisableDebuggerModeWhenIdle(JSGlobalObject* globalObject, CallFrame*)
2575{
2576 DollarVMAssertScope assertScope;
2577 return changeDebuggerModeWhenIdle(globalObject, { });
2578}
2579
2580static EncodedJSValue JSC_HOST_CALL functionDeleteAllCodeWhenIdle(JSGlobalObject* globalObject, CallFrame*)
2581{
2582 DollarVMAssertScope assertScope;
2583 VM* vm = &globalObject->vm();
2584 vm->whenIdle([=] () {
2585 DollarVMAssertScope assertScope;
2586 vm->deleteAllCode(PreventCollectionAndDeleteAllCode);
2587 });
2588 return JSValue::encode(jsUndefined());
2589}
2590
2591static EncodedJSValue JSC_HOST_CALL functionGlobalObjectCount(JSGlobalObject* globalObject, CallFrame*)
2592{
2593 DollarVMAssertScope assertScope;
2594 return JSValue::encode(jsNumber(globalObject->vm().heap.globalObjectCount()));
2595}
2596
2597static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(JSGlobalObject* globalObject, CallFrame* callFrame)
2598{
2599 DollarVMAssertScope assertScope;
2600 JSValue value = callFrame->argument(0);
2601 RELEASE_ASSERT(value.isObject());
2602 JSGlobalObject* result = jsCast<JSObject*>(value)->globalObject(globalObject->vm());
2603 RELEASE_ASSERT(result);
2604 return JSValue::encode(result);
2605}
2606
2607static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(JSGlobalObject* globalObject, CallFrame* callFrame)
2608{
2609 DollarVMAssertScope assertScope;
2610 VM& vm = globalObject->vm();
2611 auto scope = DECLARE_THROW_SCOPE(vm);
2612
2613 JSValue value = callFrame->argument(0);
2614 if (!value.isObject())
2615 return JSValue::encode(jsUndefined());
2616
2617 JSValue property = callFrame->argument(1);
2618 if (!property.isString())
2619 return JSValue::encode(jsUndefined());
2620
2621 auto propertyName = asString(property)->toIdentifier(globalObject);
2622 RETURN_IF_EXCEPTION(scope, { });
2623
2624 PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
2625 value.getPropertySlot(globalObject, propertyName, slot);
2626 RETURN_IF_EXCEPTION(scope, { });
2627
2628 JSValue result;
2629 if (slot.isCacheableGetter())
2630 result = slot.getterSetter();
2631 else
2632 result = jsNull();
2633
2634 return JSValue::encode(result);
2635}
2636
2637static EncodedJSValue JSC_HOST_CALL functionLoadGetterFromGetterSetter(JSGlobalObject* globalObject, CallFrame* callFrame)
2638{
2639 DollarVMAssertScope assertScope;
2640 VM& vm = globalObject->vm();
2641 auto scope = DECLARE_THROW_SCOPE(vm);
2642
2643 GetterSetter* getterSetter = jsDynamicCast<GetterSetter*>(vm, callFrame->argument(0));
2644 if (UNLIKELY(!getterSetter)) {
2645 throwTypeError(globalObject, scope, "Invalid use of loadGetterFromGetterSetter test function: argument is not a GetterSetter"_s);
2646 return encodedJSValue();
2647 }
2648
2649 JSObject* getter = getterSetter->getter();
2650 RELEASE_ASSERT(getter);
2651 return JSValue::encode(getter);
2652}
2653
2654static EncodedJSValue JSC_HOST_CALL functionCreateCustomTestGetterSetter(JSGlobalObject* globalObject, CallFrame*)
2655{
2656 DollarVMAssertScope assertScope;
2657 VM& vm = globalObject->vm();
2658 return JSValue::encode(JSTestCustomGetterSetter::create(vm, globalObject, JSTestCustomGetterSetter::createStructure(vm, globalObject)));
2659}
2660
2661static EncodedJSValue JSC_HOST_CALL functionDeltaBetweenButterflies(JSGlobalObject* globalObject, CallFrame* callFrame)
2662{
2663 DollarVMAssertScope assertScope;
2664 VM& vm = globalObject->vm();
2665 JSObject* a = jsDynamicCast<JSObject*>(vm, callFrame->argument(0));
2666 JSObject* b = jsDynamicCast<JSObject*>(vm, callFrame->argument(1));
2667 if (!a || !b)
2668 return JSValue::encode(jsNumber(PNaN));
2669
2670 ptrdiff_t delta = bitwise_cast<char*>(a->butterfly()) - bitwise_cast<char*>(b->butterfly());
2671 if (delta < 0)
2672 return JSValue::encode(jsNumber(PNaN));
2673 if (delta > std::numeric_limits<int32_t>::max())
2674 return JSValue::encode(jsNumber(PNaN));
2675 return JSValue::encode(jsNumber(static_cast<int32_t>(delta)));
2676}
2677
2678static EncodedJSValue JSC_HOST_CALL functionTotalGCTime(JSGlobalObject* globalObject, CallFrame*)
2679{
2680 DollarVMAssertScope assertScope;
2681 VM& vm = globalObject->vm();
2682 return JSValue::encode(jsNumber(vm.heap.totalGCTime().seconds()));
2683}
2684
2685static EncodedJSValue JSC_HOST_CALL functionParseCount(JSGlobalObject*, CallFrame*)
2686{
2687 DollarVMAssertScope assertScope;
2688 return JSValue::encode(jsNumber(globalParseCount.load()));
2689}
2690
2691static EncodedJSValue JSC_HOST_CALL functionIsWasmSupported(JSGlobalObject*, CallFrame*)
2692{
2693 DollarVMAssertScope assertScope;
2694#if ENABLE(WEBASSEMBLY)
2695 return JSValue::encode(jsBoolean(Wasm::isSupported()));
2696#else
2697 return JSValue::encode(jsBoolean(false));
2698#endif
2699}
2700
2701static EncodedJSValue JSC_HOST_CALL functionMake16BitStringIfPossible(JSGlobalObject* globalObject, CallFrame* callFrame)
2702{
2703 DollarVMAssertScope assertScope;
2704 VM& vm = globalObject->vm();
2705 auto scope = DECLARE_THROW_SCOPE(vm);
2706 String string = callFrame->argument(0).toWTFString(globalObject);
2707 RETURN_IF_EXCEPTION(scope, { });
2708 if (!string.is8Bit())
2709 return JSValue::encode(jsString(vm, WTFMove(string)));
2710 Vector<UChar> buffer;
2711 buffer.resize(string.length());
2712 StringImpl::copyCharacters(buffer.data(), string.characters8(), string.length());
2713 return JSValue::encode(jsString(vm, String::adopt(WTFMove(buffer))));
2714}
2715
2716void JSDollarVM::finishCreation(VM& vm)
2717{
2718 DollarVMAssertScope assertScope;
2719 Base::finishCreation(vm);
2720
2721 JSGlobalObject* globalObject = this->globalObject(vm);
2722
2723 auto addFunction = [&] (VM& vm, const char* name, NativeFunction function, unsigned arguments) {
2724 DollarVMAssertScope assertScope;
2725 JSDollarVM::addFunction(vm, globalObject, name, function, arguments);
2726 };
2727 auto addConstructibleFunction = [&] (VM& vm, const char* name, NativeFunction function, unsigned arguments) {
2728 DollarVMAssertScope assertScope;
2729 JSDollarVM::addConstructibleFunction(vm, globalObject, name, function, arguments);
2730 };
2731
2732 addFunction(vm, "abort", functionCrash, 0);
2733 addFunction(vm, "crash", functionCrash, 0);
2734 addFunction(vm, "breakpoint", functionBreakpoint, 0);
2735
2736 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
2737 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "ftlTrue"), 0, functionFTLTrue, FTLTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
2738
2739 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "cpuMfence"), 0, functionCpuMfence, CPUMfenceIntrinsic, 0);
2740 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "cpuRdtsc"), 0, functionCpuRdtsc, CPURdtscIntrinsic, 0);
2741 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "cpuCpuid"), 0, functionCpuCpuid, CPUCpuidIntrinsic, 0);
2742 putDirectNativeFunction(vm, globalObject, Identifier::fromString(vm, "cpuPause"), 0, functionCpuPause, CPUPauseIntrinsic, 0);
2743 addFunction(vm, "cpuClflush", functionCpuClflush, 2);
2744
2745 addFunction(vm, "llintTrue", functionLLintTrue, 0);
2746 addFunction(vm, "jitTrue", functionJITTrue, 0);
2747
2748 addFunction(vm, "noInline", functionNoInline, 1);
2749
2750 addFunction(vm, "gc", functionGC, 0);
2751 addFunction(vm, "edenGC", functionEdenGC, 0);
2752 addFunction(vm, "dumpSubspaceHashes", functionDumpSubspaceHashes, 0);
2753
2754 addFunction(vm, "callFrame", functionCallFrame, 1);
2755 addFunction(vm, "codeBlockFor", functionCodeBlockFor, 1);
2756 addFunction(vm, "codeBlockForFrame", functionCodeBlockForFrame, 1);
2757 addFunction(vm, "dumpSourceFor", functionDumpSourceFor, 1);
2758 addFunction(vm, "dumpBytecodeFor", functionDumpBytecodeFor, 1);
2759
2760 addFunction(vm, "dataLog", functionDataLog, 1);
2761 addFunction(vm, "print", functionPrint, 1);
2762 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
2763 addFunction(vm, "dumpStack", functionDumpStack, 0);
2764 addFunction(vm, "dumpRegisters", functionDumpRegisters, 1);
2765
2766 addFunction(vm, "dumpCell", functionDumpCell, 1);
2767
2768 addFunction(vm, "indexingMode", functionIndexingMode, 1);
2769 addFunction(vm, "inlineCapacity", functionInlineCapacity, 1);
2770 addFunction(vm, "value", functionValue, 1);
2771 addFunction(vm, "getpid", functionGetPID, 0);
2772
2773 addFunction(vm, "haveABadTime", functionHaveABadTime, 1);
2774 addFunction(vm, "isHavingABadTime", functionIsHavingABadTime, 1);
2775
2776 addFunction(vm, "callWithStackSize", functionCallWithStackSize, 2);
2777
2778 addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
2779 addFunction(vm, "createProxy", functionCreateProxy, 1);
2780 addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
2781 addFunction(vm, "createNullRopeString", functionCreateNullRopeString, 0);
2782
2783 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
2784 addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
2785 addFunction(vm, "createDOMJITNodeObject", functionCreateDOMJITNodeObject, 0);
2786 addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0);
2787 addFunction(vm, "createDOMJITGetterComplexObject", functionCreateDOMJITGetterComplexObject, 0);
2788 addFunction(vm, "createDOMJITFunctionObject", functionCreateDOMJITFunctionObject, 0);
2789 addFunction(vm, "createDOMJITCheckSubClassObject", functionCreateDOMJITCheckSubClassObject, 0);
2790 addFunction(vm, "createDOMJITGetterBaseJSObject", functionCreateDOMJITGetterBaseJSObject, 0);
2791 addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
2792#if ENABLE(WEBASSEMBLY)
2793 addFunction(vm, "createWasmStreamingParser", functionCreateWasmStreamingParser, 0);
2794#endif
2795 addFunction(vm, "createStaticCustomAccessor", functionCreateStaticCustomAccessor, 0);
2796 addFunction(vm, "getPrivateProperty", functionGetPrivateProperty, 2);
2797 addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
2798
2799 addConstructibleFunction(vm, "Root", functionCreateRoot, 0);
2800 addConstructibleFunction(vm, "Element", functionCreateElement, 1);
2801 addFunction(vm, "getElement", functionGetElement, 1);
2802
2803 addConstructibleFunction(vm, "SimpleObject", functionCreateSimpleObject, 0);
2804 addFunction(vm, "getHiddenValue", functionGetHiddenValue, 1);
2805 addFunction(vm, "setHiddenValue", functionSetHiddenValue, 2);
2806
2807 addFunction(vm, "shadowChickenFunctionsOnStack", functionShadowChickenFunctionsOnStack, 0);
2808 addFunction(vm, "setGlobalConstRedeclarationShouldNotThrow", functionSetGlobalConstRedeclarationShouldNotThrow, 0);
2809
2810 addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
2811 addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
2812
2813 addFunction(vm, "flattenDictionaryObject", functionFlattenDictionaryObject, 1);
2814
2815 addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
2816 addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
2817 addFunction(vm, "basicBlockExecutionCount", functionBasicBlockExecutionCount, 2);
2818
2819 addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
2820
2821 addFunction(vm, "enableDebuggerModeWhenIdle", functionEnableDebuggerModeWhenIdle, 0);
2822 addFunction(vm, "disableDebuggerModeWhenIdle", functionDisableDebuggerModeWhenIdle, 0);
2823
2824 addFunction(vm, "deleteAllCodeWhenIdle", functionDeleteAllCodeWhenIdle, 0);
2825
2826 addFunction(vm, "globalObjectCount", functionGlobalObjectCount, 0);
2827 addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1);
2828
2829 addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
2830 addFunction(vm, "loadGetterFromGetterSetter", functionLoadGetterFromGetterSetter, 1);
2831 addFunction(vm, "createCustomTestGetterSetter", functionCreateCustomTestGetterSetter, 1);
2832
2833 addFunction(vm, "deltaBetweenButterflies", functionDeltaBetweenButterflies, 2);
2834
2835 addFunction(vm, "totalGCTime", functionTotalGCTime, 0);
2836
2837 addFunction(vm, "parseCount", functionParseCount, 0);
2838
2839 addFunction(vm, "isWasmSupported", functionIsWasmSupported, 0);
2840 addFunction(vm, "make16BitStringIfPossible", functionMake16BitStringIfPossible, 1);
2841}
2842
2843void JSDollarVM::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
2844{
2845 DollarVMAssertScope assertScope;
2846 Identifier identifier = Identifier::fromString(vm, name);
2847 putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function));
2848}
2849
2850void JSDollarVM::addConstructibleFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
2851{
2852 DollarVMAssertScope assertScope;
2853 Identifier identifier = Identifier::fromString(vm, name);
2854 putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function, NoIntrinsic, function));
2855}
2856
2857} // namespace JSC
2858
2859IGNORE_WARNINGS_END
2860