]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - jsc.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / jsc.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2004-2008, 2012-2013, 2015 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include "ArrayPrototype.h"
26#include "ButterflyInlines.h"
27#include "BytecodeGenerator.h"
28#include "CodeBlock.h"
29#include "Completion.h"
30#include "CopiedSpaceInlines.h"
31#include "Disassembler.h"
32#include "Exception.h"
33#include "ExceptionHelpers.h"
34#include "HeapStatistics.h"
35#include "InitializeThreading.h"
36#include "Interpreter.h"
37#include "JSArray.h"
38#include "JSArrayBuffer.h"
39#include "JSCInlines.h"
40#include "JSFunction.h"
41#include "JSLock.h"
42#include "JSONObject.h"
43#include "JSProxy.h"
44#include "JSString.h"
45#include "ProfilerDatabase.h"
46#include "SamplingTool.h"
47#include "StackVisitor.h"
48#include "StructureInlines.h"
49#include "StructureRareDataInlines.h"
50#include "TestRunnerUtils.h"
51#include "TypeProfilerLog.h"
52#include <math.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <thread>
57#include <wtf/CurrentTime.h>
58#include <wtf/MainThread.h>
59#include <wtf/StringPrintStream.h>
60#include <wtf/text/StringBuilder.h>
61
62#if !OS(WINDOWS)
63#include <unistd.h>
64#endif
65
66#if HAVE(READLINE)
67// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
68// We #define it to something else to avoid this conflict.
69#define Function ReadlineFunction
70#include <readline/history.h>
71#include <readline/readline.h>
72#undef Function
73#endif
74
75#if HAVE(SYS_TIME_H)
76#include <sys/time.h>
77#endif
78
79#if HAVE(SIGNAL_H)
80#include <signal.h>
81#endif
82
83#if COMPILER(MSVC)
84#include <crtdbg.h>
85#include <mmsystem.h>
86#include <windows.h>
87#endif
88
89#if PLATFORM(IOS) && CPU(ARM_THUMB2)
90#include <fenv.h>
91#include <arm/arch.h>
92#endif
93
94#if PLATFORM(EFL)
95#include <Ecore.h>
96#endif
97
98using namespace JSC;
99using namespace WTF;
100
101namespace JSC {
102WTF_IMPORT extern const struct HashTable globalObjectTable;
103}
104
105namespace {
106
107NO_RETURN_WITH_VALUE static void jscExit(int status)
108{
109 waitForAsynchronousDisassembly();
110
111#if ENABLE(DFG_JIT)
112 if (DFG::isCrashing()) {
113 for (;;) {
114#if OS(WINDOWS)
115 Sleep(1000);
116#else
117 pause();
118#endif
119 }
120 }
121#endif // ENABLE(DFG_JIT)
122 exit(status);
123}
124
125class Element;
126class ElementHandleOwner;
127class Masuqerader;
128class Root;
129class RuntimeArray;
130
131class Element : public JSNonFinalObject {
132public:
133 Element(VM& vm, Structure* structure)
134 : Base(vm, structure)
135 {
136 }
137
138 typedef JSNonFinalObject Base;
139 static const bool needsDestruction = false;
140
141 Root* root() const { return m_root.get(); }
142 void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
143
144 static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
145 {
146 Structure* structure = createStructure(vm, globalObject, jsNull());
147 Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
148 element->finishCreation(vm, root);
149 return element;
150 }
151
152 void finishCreation(VM&, Root*);
153
154 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
155 {
156 Element* thisObject = jsCast<Element*>(cell);
157 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
158 Base::visitChildren(thisObject, visitor);
159 visitor.append(&thisObject->m_root);
160 }
161
162 static ElementHandleOwner* handleOwner();
163
164 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
165 {
166 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
167 }
168
169 DECLARE_INFO;
170
171private:
172 WriteBarrier<Root> m_root;
173};
174
175class ElementHandleOwner : public WeakHandleOwner {
176public:
177 virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
178 {
179 Element* element = jsCast<Element*>(handle.slot()->asCell());
180 return visitor.containsOpaqueRoot(element->root());
181 }
182};
183
184class Masquerader : public JSNonFinalObject {
185public:
186 Masquerader(VM& vm, Structure* structure)
187 : Base(vm, structure)
188 {
189 }
190
191 typedef JSNonFinalObject Base;
192 static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
193
194 static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
195 {
196 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Masquerading object allocated");
197 Structure* structure = createStructure(vm, globalObject, jsNull());
198 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
199 result->finishCreation(vm);
200 return result;
201 }
202
203 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
204 {
205 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
206 }
207
208 DECLARE_INFO;
209};
210
211class Root : public JSDestructibleObject {
212public:
213 Root(VM& vm, Structure* structure)
214 : Base(vm, structure)
215 {
216 }
217
218 Element* element()
219 {
220 return m_element.get();
221 }
222
223 void setElement(Element* element)
224 {
225 Weak<Element> newElement(element, Element::handleOwner());
226 m_element.swap(newElement);
227 }
228
229 static Root* create(VM& vm, JSGlobalObject* globalObject)
230 {
231 Structure* structure = createStructure(vm, globalObject, jsNull());
232 Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
233 root->finishCreation(vm);
234 return root;
235 }
236
237 typedef JSDestructibleObject Base;
238
239 DECLARE_INFO;
240 static const bool needsDestruction = true;
241
242 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
243 {
244 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
245 }
246
247 static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
248 {
249 Base::visitChildren(thisObject, visitor);
250 visitor.addOpaqueRoot(thisObject);
251 }
252
253private:
254 Weak<Element> m_element;
255};
256
257class ImpureGetter : public JSNonFinalObject {
258public:
259 ImpureGetter(VM& vm, Structure* structure)
260 : Base(vm, structure)
261 {
262 }
263
264 DECLARE_INFO;
265 typedef JSNonFinalObject Base;
266 static const unsigned StructureFlags = Base::StructureFlags | JSC::HasImpureGetOwnPropertySlot | JSC::OverridesGetOwnPropertySlot;
267
268 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
269 {
270 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
271 }
272
273 static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
274 {
275 ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
276 getter->finishCreation(vm, delegate);
277 return getter;
278 }
279
280 void finishCreation(VM& vm, JSObject* delegate)
281 {
282 Base::finishCreation(vm);
283 if (delegate)
284 m_delegate.set(vm, this, delegate);
285 }
286
287 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
288 {
289 ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
290
291 if (thisObject->m_delegate && thisObject->m_delegate->getPropertySlot(exec, name, slot))
292 return true;
293
294 return Base::getOwnPropertySlot(object, exec, name, slot);
295 }
296
297 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
298 {
299 Base::visitChildren(cell, visitor);
300 ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
301 visitor.append(&thisObject->m_delegate);
302 }
303
304 void setDelegate(VM& vm, JSObject* delegate)
305 {
306 m_delegate.set(vm, this, delegate);
307 }
308
309private:
310 WriteBarrier<JSObject> m_delegate;
311};
312
313class RuntimeArray : public JSArray {
314public:
315 typedef JSArray Base;
316 static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
317
318 static RuntimeArray* create(ExecState* exec)
319 {
320 VM& vm = exec->vm();
321 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
322 Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
323 RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
324 runtimeArray->finishCreation(exec);
325 vm.heap.addFinalizer(runtimeArray, destroy);
326 return runtimeArray;
327 }
328
329 ~RuntimeArray() { }
330
331 static void destroy(JSCell* cell)
332 {
333 static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
334 }
335
336 static const bool needsDestruction = false;
337
338 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
339 {
340 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
341 if (propertyName == exec->propertyNames().length) {
342 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
343 return true;
344 }
345
346 Optional<uint32_t> index = parseIndex(propertyName);
347 if (index && index.value() < thisObject->getLength()) {
348 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()]));
349 return true;
350 }
351
352 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
353 }
354
355 static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
356 {
357 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
358 if (index < thisObject->getLength()) {
359 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
360 return true;
361 }
362
363 return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
364 }
365
366 static NO_RETURN_DUE_TO_CRASH void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
367 {
368 RELEASE_ASSERT_NOT_REACHED();
369 }
370
371 static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
372 {
373 RELEASE_ASSERT_NOT_REACHED();
374 }
375
376 unsigned getLength() const { return m_vector.size(); }
377
378 DECLARE_INFO;
379
380 static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
381 {
382 return globalObject->arrayPrototype();
383 }
384
385 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
386 {
387 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
388 }
389
390protected:
391 void finishCreation(ExecState* exec)
392 {
393 Base::finishCreation(exec->vm());
394 ASSERT(inherits(info()));
395
396 for (size_t i = 0; i < exec->argumentCount(); i++)
397 m_vector.append(exec->argument(i).toInt32(exec));
398 }
399
400private:
401 RuntimeArray(ExecState* exec, Structure* structure)
402 : JSArray(exec->vm(), structure, 0)
403 {
404 }
405
406 static EncodedJSValue lengthGetter(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName)
407 {
408 RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
409 if (!thisObject)
410 return throwVMTypeError(exec);
411 return JSValue::encode(jsNumber(thisObject->getLength()));
412 }
413
414 Vector<int> m_vector;
415};
416
417const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, CREATE_METHOD_TABLE(Element) };
418const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, CREATE_METHOD_TABLE(Masquerader) };
419const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, CREATE_METHOD_TABLE(Root) };
420const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(ImpureGetter) };
421const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) };
422
423ElementHandleOwner* Element::handleOwner()
424{
425 static ElementHandleOwner* owner = 0;
426 if (!owner)
427 owner = new ElementHandleOwner();
428 return owner;
429}
430
431void Element::finishCreation(VM& vm, Root* root)
432{
433 Base::finishCreation(vm);
434 setRoot(vm, root);
435 m_root->setElement(this);
436}
437
438}
439
440static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
441
442static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
443static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
444static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
445static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
446
447static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
448static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
449static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
450static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
451static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
452static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
453static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
454static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
455static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
456static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
457static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
458static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
459static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
460static EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState*);
461static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
462#ifndef NDEBUG
463static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
464static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
465#endif
466static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
467static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
468static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
469static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
470static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
471static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
472static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
473static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
474static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
475static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
476static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
477static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
478static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
479static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
480static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
481static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
482static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
483static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
484static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
485static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
486static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
487static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
488static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
489static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState*);
490static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*);
491static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
492static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
493static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
494
495#if ENABLE(SAMPLING_FLAGS)
496static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
497static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
498#endif
499
500struct Script {
501 bool isFile;
502 char* argument;
503
504 Script(bool isFile, char *argument)
505 : isFile(isFile)
506 , argument(argument)
507 {
508 }
509};
510
511class CommandLine {
512public:
513 CommandLine(int argc, char** argv)
514 : m_interactive(false)
515 , m_dump(false)
516 , m_exitCode(false)
517 , m_profile(false)
518 {
519 parseArguments(argc, argv);
520 }
521
522 bool m_interactive;
523 bool m_dump;
524 bool m_exitCode;
525 Vector<Script> m_scripts;
526 Vector<String> m_arguments;
527 bool m_profile;
528 String m_profilerOutput;
529
530 void parseArguments(int, char**);
531};
532
533static const char interactivePrompt[] = ">>> ";
534
535class StopWatch {
536public:
537 void start();
538 void stop();
539 long getElapsedMS(); // call stop() first
540
541private:
542 double m_startTime;
543 double m_stopTime;
544};
545
546void StopWatch::start()
547{
548 m_startTime = monotonicallyIncreasingTime();
549}
550
551void StopWatch::stop()
552{
553 m_stopTime = monotonicallyIncreasingTime();
554}
555
556long StopWatch::getElapsedMS()
557{
558 return static_cast<long>((m_stopTime - m_startTime) * 1000);
559}
560
561class GlobalObject : public JSGlobalObject {
562private:
563 GlobalObject(VM&, Structure*);
564
565public:
566 typedef JSGlobalObject Base;
567
568 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
569 {
570 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
571 object->finishCreation(vm, arguments);
572 vm.heap.addFinalizer(object, destroy);
573 return object;
574 }
575
576 static const bool needsDestruction = false;
577
578 DECLARE_INFO;
579 static const GlobalObjectMethodTable s_globalObjectMethodTable;
580
581 static Structure* createStructure(VM& vm, JSValue prototype)
582 {
583 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
584 }
585
586 static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
587
588protected:
589 void finishCreation(VM& vm, const Vector<String>& arguments)
590 {
591 Base::finishCreation(vm);
592
593 addFunction(vm, "debug", functionDebug, 1);
594 addFunction(vm, "describe", functionDescribe, 1);
595 addFunction(vm, "describeArray", functionDescribeArray, 1);
596 addFunction(vm, "print", functionPrint, 1);
597 addFunction(vm, "quit", functionQuit, 0);
598 addFunction(vm, "gc", functionGCAndSweep, 0);
599 addFunction(vm, "fullGC", functionFullGC, 0);
600 addFunction(vm, "edenGC", functionEdenGC, 0);
601 addFunction(vm, "gcHeapSize", functionHeapSize, 0);
602 addFunction(vm, "deleteAllCompiledCode", functionDeleteAllCompiledCode, 0);
603 addFunction(vm, "addressOf", functionAddressOf, 1);
604#ifndef NDEBUG
605 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
606 addFunction(vm, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
607#endif
608 addFunction(vm, "version", functionVersion, 1);
609 addFunction(vm, "run", functionRun, 1);
610 addFunction(vm, "load", functionLoad, 1);
611 addFunction(vm, "readFile", functionReadFile, 1);
612 addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
613 addFunction(vm, "jscStack", functionJSCStack, 1);
614 addFunction(vm, "readline", functionReadline, 0);
615 addFunction(vm, "preciseTime", functionPreciseTime, 0);
616 addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
617 addFunction(vm, "noInline", functionNeverInlineFunction, 1);
618 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
619 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
620 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
621 addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
622#if ENABLE(SAMPLING_FLAGS)
623 addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
624 addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
625#endif
626 addConstructableFunction(vm, "Root", functionCreateRoot, 0);
627 addConstructableFunction(vm, "Element", functionCreateElement, 1);
628 addFunction(vm, "getElement", functionGetElement, 1);
629 addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
630
631 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum | JSC::Function);
632 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum | JSC::Function);
633 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum | JSC::Function);
634 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum | JSC::Function);
635 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum | JSC::Function);
636 putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum | JSC::Function);
637
638 addFunction(vm, "effectful42", functionEffectful42, 0);
639 addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
640 addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
641
642 addFunction(vm, "createProxy", functionCreateProxy, 1);
643 addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
644
645 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
646 addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
647
648 addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
649 addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
650 addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
651
652 addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
653 addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
654
655 addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
656
657 JSArray* array = constructEmptyArray(globalExec(), 0);
658 for (size_t i = 0; i < arguments.size(); ++i)
659 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
660 putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
661
662 putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
663 }
664
665 void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
666 {
667 Identifier identifier = Identifier::fromString(&vm, name);
668 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
669 }
670
671 void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
672 {
673 Identifier identifier = Identifier::fromString(&vm, name);
674 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
675 }
676};
677
678const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, &globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
679const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout };
680
681
682GlobalObject::GlobalObject(VM& vm, Structure* structure)
683 : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
684{
685}
686
687static inline String stringFromUTF(const char* utf8)
688{
689 return String::fromUTF8WithLatin1Fallback(utf8, strlen(utf8));
690}
691
692static inline SourceCode jscSource(const char* utf8, const String& filename)
693{
694 String str = stringFromUTF(utf8);
695 return makeSource(str, filename);
696}
697
698EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
699{
700 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
701 if (i)
702 putchar(' ');
703
704 printf("%s", exec->uncheckedArgument(i).toString(exec)->view(exec).get().utf8().data());
705 }
706
707 putchar('\n');
708 fflush(stdout);
709 return JSValue::encode(jsUndefined());
710}
711
712#ifndef NDEBUG
713EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
714{
715 VMEntryFrame* topVMEntryFrame = exec->vm().topVMEntryFrame;
716 ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
717 if (callerFrame)
718 exec->vm().interpreter->dumpCallFrame(callerFrame);
719 return JSValue::encode(jsUndefined());
720}
721#endif
722
723EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
724{
725 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->view(exec).get().utf8().data());
726 return JSValue::encode(jsUndefined());
727}
728
729EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
730{
731 if (exec->argumentCount() < 1)
732 return JSValue::encode(jsUndefined());
733 return JSValue::encode(jsString(exec, toString(exec->argument(0))));
734}
735
736EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
737{
738 if (exec->argumentCount() < 1)
739 return JSValue::encode(jsUndefined());
740 JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
741 if (!object)
742 return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
743 return JSValue::encode(jsNontrivialString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
744}
745
746class FunctionJSCStackFunctor {
747public:
748 FunctionJSCStackFunctor(StringBuilder& trace)
749 : m_trace(trace)
750 {
751 }
752
753 StackVisitor::Status operator()(StackVisitor& visitor)
754 {
755 m_trace.append(String::format(" %zu %s\n", visitor->index(), visitor->toString().utf8().data()));
756 return StackVisitor::Continue;
757 }
758
759private:
760 StringBuilder& m_trace;
761};
762
763EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
764{
765 StringBuilder trace;
766 trace.appendLiteral("--> Stack trace:\n");
767
768 FunctionJSCStackFunctor functor(trace);
769 exec->iterate(functor);
770 fprintf(stderr, "%s", trace.toString().utf8().data());
771 return JSValue::encode(jsUndefined());
772}
773
774EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
775{
776 JSLockHolder lock(exec);
777 return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
778}
779
780EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
781{
782 JSLockHolder lock(exec);
783 JSValue arg = exec->argument(0);
784 return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), arg.isNull() ? nullptr : jsCast<Root*>(exec->argument(0))));
785}
786
787EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
788{
789 JSLockHolder lock(exec);
790 Element* result = jsCast<Root*>(exec->argument(0).asCell())->element();
791 return JSValue::encode(result ? result : jsUndefined());
792}
793
794EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
795{
796 JSLockHolder lock(exec);
797 Element* element = jsCast<Element*>(exec->argument(0));
798 Root* root = jsCast<Root*>(exec->argument(1));
799 element->setRoot(exec->vm(), root);
800 return JSValue::encode(jsUndefined());
801}
802
803EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
804{
805 JSLockHolder lock(exec);
806 JSValue target = exec->argument(0);
807 if (!target.isObject())
808 return JSValue::encode(jsUndefined());
809 JSObject* jsTarget = asObject(target.asCell());
810 Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->prototype());
811 JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
812 return JSValue::encode(proxy);
813}
814
815EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
816{
817 JSLockHolder lock(exec);
818 RuntimeArray* array = RuntimeArray::create(exec);
819 return JSValue::encode(array);
820}
821
822EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
823{
824 JSLockHolder lock(exec);
825 JSValue target = exec->argument(0);
826 JSObject* delegate = nullptr;
827 if (target.isObject())
828 delegate = asObject(target.asCell());
829 Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
830 ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
831 return JSValue::encode(result);
832}
833
834EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
835{
836 JSLockHolder lock(exec);
837 JSValue base = exec->argument(0);
838 if (!base.isObject())
839 return JSValue::encode(jsUndefined());
840 JSValue delegate = exec->argument(1);
841 if (!delegate.isObject())
842 return JSValue::encode(jsUndefined());
843 ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
844 impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
845 return JSValue::encode(jsUndefined());
846}
847
848EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
849{
850 JSLockHolder lock(exec);
851 exec->heap()->collectAllGarbage();
852 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
853}
854
855EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
856{
857 JSLockHolder lock(exec);
858 exec->heap()->collect(FullCollection);
859 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
860}
861
862EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
863{
864 JSLockHolder lock(exec);
865 exec->heap()->collect(EdenCollection);
866 return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
867}
868
869EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
870{
871 JSLockHolder lock(exec);
872 return JSValue::encode(jsNumber(exec->heap()->size()));
873}
874
875EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState* exec)
876{
877 JSLockHolder lock(exec);
878 exec->heap()->deleteAllCompiledCode();
879 return JSValue::encode(jsUndefined());
880}
881
882// This function is not generally very helpful in 64-bit code as the tag and payload
883// share a register. But in 32-bit JITed code the tag may not be checked if an
884// optimization removes type checking requirements, such as in ===.
885EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
886{
887 JSValue value = exec->argument(0);
888 if (!value.isCell())
889 return JSValue::encode(jsUndefined());
890 // Need to cast to uint64_t so bitwise_cast will play along.
891 uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
892 EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
893 return returnValue;
894}
895
896
897#ifndef NDEBUG
898EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
899{
900 JSLockHolder lock(exec);
901 exec->vm().releaseExecutableMemory();
902 return JSValue::encode(jsUndefined());
903}
904#endif
905
906EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
907{
908 // We need this function for compatibility with the Mozilla JS tests but for now
909 // we don't actually do any version-specific handling
910 return JSValue::encode(jsUndefined());
911}
912
913EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
914{
915 String fileName = exec->argument(0).toString(exec)->value(exec);
916 Vector<char> script;
917 if (!fillBufferWithContentsOfFile(fileName, script))
918 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
919
920 GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
921
922 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
923 for (unsigned i = 1; i < exec->argumentCount(); ++i)
924 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
925 globalObject->putDirect(
926 exec->vm(), Identifier::fromString(globalObject->globalExec(), "arguments"), array);
927
928 NakedPtr<Exception> exception;
929 StopWatch stopWatch;
930 stopWatch.start();
931 evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), exception);
932 stopWatch.stop();
933
934 if (exception) {
935 exec->vm().throwException(globalObject->globalExec(), exception);
936 return JSValue::encode(jsUndefined());
937 }
938
939 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
940}
941
942EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
943{
944 String fileName = exec->argument(0).toString(exec)->value(exec);
945 Vector<char> script;
946 if (!fillBufferWithContentsOfFile(fileName, script))
947 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
948
949 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
950
951 NakedPtr<Exception> evaluationException;
952 JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), evaluationException);
953 if (evaluationException)
954 exec->vm().throwException(exec, evaluationException);
955 return JSValue::encode(result);
956}
957
958EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
959{
960 String fileName = exec->argument(0).toString(exec)->value(exec);
961 Vector<char> script;
962 if (!fillBufferWithContentsOfFile(fileName, script))
963 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
964
965 return JSValue::encode(jsString(exec, stringFromUTF(script.data())));
966}
967
968EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
969{
970 String fileName = exec->argument(0).toString(exec)->value(exec);
971 Vector<char> script;
972 if (!fillBufferWithContentsOfFile(fileName, script))
973 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
974
975 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
976
977 StopWatch stopWatch;
978 stopWatch.start();
979
980 JSValue syntaxException;
981 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
982 stopWatch.stop();
983
984 if (!validSyntax)
985 exec->vm().throwException(exec, syntaxException);
986 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
987}
988
989#if ENABLE(SAMPLING_FLAGS)
990EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
991{
992 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
993 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
994 if ((flag >= 1) && (flag <= 32))
995 SamplingFlags::setFlag(flag);
996 }
997 return JSValue::encode(jsNull());
998}
999
1000EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
1001{
1002 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1003 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1004 if ((flag >= 1) && (flag <= 32))
1005 SamplingFlags::clearFlag(flag);
1006 }
1007 return JSValue::encode(jsNull());
1008}
1009#endif
1010
1011EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
1012{
1013 Vector<char, 256> line;
1014 int c;
1015 while ((c = getchar()) != EOF) {
1016 // FIXME: Should we also break on \r?
1017 if (c == '\n')
1018 break;
1019 line.append(c);
1020 }
1021 line.append('\0');
1022 return JSValue::encode(jsString(exec, line.data()));
1023}
1024
1025EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
1026{
1027 return JSValue::encode(jsNumber(currentTime()));
1028}
1029
1030EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
1031{
1032 return JSValue::encode(setNeverInline(exec));
1033}
1034
1035EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
1036{
1037 return JSValue::encode(optimizeNextInvocation(exec));
1038}
1039
1040EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1041{
1042 return JSValue::encode(numberOfDFGCompiles(exec));
1043}
1044
1045EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1046{
1047 if (exec->argumentCount() < 1)
1048 return JSValue::encode(jsUndefined());
1049
1050 CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1051 if (!block)
1052 return JSValue::encode(jsNumber(0));
1053
1054 return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1055}
1056
1057EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1058{
1059 if (exec->argumentCount() < 1)
1060 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Not enough arguments"))));
1061
1062 JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
1063 if (!buffer)
1064 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Expected an array buffer"))));
1065
1066 ArrayBufferContents dummyContents;
1067 buffer->impl()->transfer(dummyContents);
1068
1069 return JSValue::encode(jsUndefined());
1070}
1071
1072EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1073{
1074 jscExit(EXIT_SUCCESS);
1075
1076#if COMPILER(MSVC)
1077 // Without this, Visual Studio will complain that this method does not return a value.
1078 return JSValue::encode(jsUndefined());
1079#endif
1080}
1081
1082EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1083EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1084
1085EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1086EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1087EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
1088{
1089 for (size_t i = 0; i < exec->argumentCount(); ++i) {
1090 if (!exec->argument(i).isInt32())
1091 return JSValue::encode(jsBoolean(false));
1092 }
1093 return JSValue::encode(jsBoolean(true));
1094}
1095
1096EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
1097
1098EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
1099{
1100 return JSValue::encode(jsNumber(42));
1101}
1102
1103EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
1104{
1105 return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
1106}
1107
1108EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
1109{
1110 JSValue value = exec->argument(0);
1111 if (value.isObject())
1112 return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
1113 return JSValue::encode(jsBoolean(false));
1114}
1115
1116EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
1117{
1118 exec->vm().dumpTypeProfilerData();
1119 return JSValue::encode(jsUndefined());
1120}
1121
1122EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
1123{
1124 RELEASE_ASSERT(exec->vm().typeProfiler());
1125 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
1126
1127 JSValue functionValue = exec->argument(0);
1128 RELEASE_ASSERT(functionValue.isFunction());
1129 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1130
1131 RELEASE_ASSERT(exec->argument(1).isString());
1132 String substring = exec->argument(1).getString(exec);
1133 String sourceCodeText = executable->source().toString();
1134 unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
1135
1136 String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), exec->vm());
1137 return JSValue::encode(JSONParse(exec, jsonString));
1138}
1139
1140EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
1141{
1142 RELEASE_ASSERT(exec->vm().typeProfiler());
1143 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
1144
1145 JSValue functionValue = exec->argument(0);
1146 RELEASE_ASSERT(functionValue.isFunction());
1147 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1148
1149 unsigned offset = executable->source().startOffset();
1150 String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), exec->vm());
1151 return JSValue::encode(JSONParse(exec, jsonString));
1152}
1153
1154EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
1155{
1156 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1157 exec->vm().controlFlowProfiler()->dumpData();
1158 return JSValue::encode(jsUndefined());
1159}
1160
1161EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
1162{
1163 RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1164
1165 JSValue functionValue = exec->argument(0);
1166 RELEASE_ASSERT(functionValue.isFunction());
1167 FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1168
1169 RELEASE_ASSERT(exec->argument(1).isString());
1170 String substring = exec->argument(1).getString(exec);
1171 String sourceCodeText = executable->source().toString();
1172 RELEASE_ASSERT(sourceCodeText.contains(substring));
1173 int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1174
1175 bool hasExecuted = exec->vm().controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), exec->vm());
1176 return JSValue::encode(jsBoolean(hasExecuted));
1177}
1178
1179EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
1180{
1181 Options::enableExceptionFuzz() = true;
1182 return JSValue::encode(jsUndefined());
1183}
1184
1185// Use SEH for Release builds only to get rid of the crash report dialog
1186// (luckily the same tests fail in Release and Debug builds so far). Need to
1187// be in a separate main function because the jscmain function requires object
1188// unwinding.
1189
1190#if COMPILER(MSVC) && !defined(_DEBUG)
1191#define TRY __try {
1192#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1193#else
1194#define TRY
1195#define EXCEPT(x)
1196#endif
1197
1198int jscmain(int argc, char** argv);
1199
1200static double s_desiredTimeout;
1201
1202static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
1203{
1204 auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
1205 std::this_thread::sleep_for(timeout);
1206
1207 dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
1208 CRASH();
1209}
1210
1211int main(int argc, char** argv)
1212{
1213#if PLATFORM(IOS) && CPU(ARM_THUMB2)
1214 // Enabled IEEE754 denormal support.
1215 fenv_t env;
1216 fegetenv( &env );
1217 env.__fpscr &= ~0x01000000u;
1218 fesetenv( &env );
1219#endif
1220
1221#if OS(WINDOWS) && (defined(_M_X64) || defined(__x86_64__))
1222 // The VS2013 runtime has a bug where it mis-detects AVX-capable processors
1223 // if the feature has been disabled in firmware. This causes us to crash
1224 // in some of the math functions. For now, we disable those optimizations
1225 // because Microsoft is not going to fix the problem in VS2013.
1226 // FIXME: http://webkit.org/b/141449: Remove this workaround when we switch to VS2015+.
1227 _set_FMA3_enable(0);
1228
1229 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1230 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1231 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1232 ::SetErrorMode(0);
1233
1234#if defined(_DEBUG)
1235 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1236 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1237 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1238 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1239 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1240 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1241#endif
1242
1243 timeBeginPeriod(1);
1244#endif
1245
1246#if PLATFORM(EFL)
1247 ecore_init();
1248#endif
1249
1250 // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
1251 // threading yet, since that would do somethings that we'd like to defer until after we
1252 // have a chance to parse options.
1253 WTF::initializeThreading();
1254
1255 if (char* timeoutString = getenv("JSC_timeout")) {
1256 if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1257 dataLog(
1258 "WARNING: timeout string is malformed, got ", timeoutString,
1259 " but expected a number. Not using a timeout.\n");
1260 } else
1261 createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1262 }
1263
1264#if PLATFORM(IOS)
1265 Options::crashIfCantAllocateJITMemory() = true;
1266#endif
1267
1268 // We can't use destructors in the following code because it uses Windows
1269 // Structured Exception Handling
1270 int res = 0;
1271 TRY
1272 res = jscmain(argc, argv);
1273 EXCEPT(res = 3)
1274 if (Options::logHeapStatisticsAtExit())
1275 HeapStatistics::reportSuccess();
1276
1277#if PLATFORM(EFL)
1278 ecore_shutdown();
1279#endif
1280
1281 jscExit(res);
1282}
1283
1284static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
1285{
1286 const char* script;
1287 String fileName;
1288 Vector<char> scriptBuffer;
1289
1290 if (dump)
1291 JSC::Options::dumpGeneratedBytecodes() = true;
1292
1293 VM& vm = globalObject->vm();
1294
1295#if ENABLE(SAMPLING_FLAGS)
1296 SamplingFlags::start();
1297#endif
1298
1299 bool success = true;
1300 for (size_t i = 0; i < scripts.size(); i++) {
1301 if (scripts[i].isFile) {
1302 fileName = scripts[i].argument;
1303 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
1304 return false; // fail early so we can catch missing files
1305 script = scriptBuffer.data();
1306 } else {
1307 script = scripts[i].argument;
1308 fileName = ASCIILiteral("[Command Line]");
1309 }
1310
1311 vm.startSampling();
1312
1313 NakedPtr<Exception> evaluationException;
1314 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
1315 success = success && !evaluationException;
1316 if (dump && !evaluationException)
1317 printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1318 if (evaluationException) {
1319 printf("Exception: %s\n", evaluationException->value().toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1320 Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
1321 JSValue stackValue = evaluationException->value().get(globalObject->globalExec(), stackID);
1322 if (!stackValue.isUndefinedOrNull())
1323 printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1324 }
1325
1326 vm.stopSampling();
1327 globalObject->globalExec()->clearException();
1328 }
1329
1330#if ENABLE(SAMPLING_FLAGS)
1331 SamplingFlags::stop();
1332#endif
1333#if ENABLE(SAMPLING_REGIONS)
1334 SamplingRegion::dump();
1335#endif
1336 vm.dumpSampleData(globalObject->globalExec());
1337#if ENABLE(SAMPLING_COUNTERS)
1338 AbstractSamplingCounter::dump();
1339#endif
1340#if ENABLE(REGEXP_TRACING)
1341 vm.dumpRegExpTrace();
1342#endif
1343 return success;
1344}
1345
1346#define RUNNING_FROM_XCODE 0
1347
1348static void runInteractive(GlobalObject* globalObject)
1349{
1350 String interpreterName(ASCIILiteral("Interpreter"));
1351
1352 bool shouldQuit = false;
1353 while (!shouldQuit) {
1354#if HAVE(READLINE) && !RUNNING_FROM_XCODE
1355 ParserError error;
1356 String source;
1357 do {
1358 error = ParserError();
1359 char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
1360 shouldQuit = !line;
1361 if (!line)
1362 break;
1363 source = source + line;
1364 source = source + '\n';
1365 checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
1366 if (!line[0])
1367 break;
1368 add_history(line);
1369 } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
1370
1371 if (error.isValid()) {
1372 printf("%s:%d\n", error.message().utf8().data(), error.line());
1373 continue;
1374 }
1375
1376
1377 NakedPtr<Exception> evaluationException;
1378 JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), evaluationException);
1379#else
1380 printf("%s", interactivePrompt);
1381 Vector<char, 256> line;
1382 int c;
1383 while ((c = getchar()) != EOF) {
1384 // FIXME: Should we also break on \r?
1385 if (c == '\n')
1386 break;
1387 line.append(c);
1388 }
1389 if (line.isEmpty())
1390 break;
1391 line.append('\0');
1392
1393 NakedPtr<Exception> evaluationException;
1394 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), evaluationException);
1395#endif
1396 if (evaluationException)
1397 printf("Exception: %s\n", evaluationException->value().toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1398 else
1399 printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1400
1401 globalObject->globalExec()->clearException();
1402 }
1403 printf("\n");
1404}
1405
1406static NO_RETURN void printUsageStatement(bool help = false)
1407{
1408 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
1409 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
1410 fprintf(stderr, " -e Evaluate argument as script code\n");
1411 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
1412 fprintf(stderr, " -h|--help Prints this help message\n");
1413 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
1414#if HAVE(SIGNAL_H)
1415 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
1416#endif
1417 fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
1418 fprintf(stderr, " -x Output exit code before terminating\n");
1419 fprintf(stderr, "\n");
1420 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
1421 fprintf(stderr, " --dumpOptions Dumps all JSC VM options before continuing\n");
1422 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
1423 fprintf(stderr, "\n");
1424
1425 jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
1426}
1427
1428void CommandLine::parseArguments(int argc, char** argv)
1429{
1430 Options::initialize();
1431
1432 int i = 1;
1433 bool needToDumpOptions = false;
1434 bool needToExit = false;
1435
1436 for (; i < argc; ++i) {
1437 const char* arg = argv[i];
1438 if (!strcmp(arg, "-f")) {
1439 if (++i == argc)
1440 printUsageStatement();
1441 m_scripts.append(Script(true, argv[i]));
1442 continue;
1443 }
1444 if (!strcmp(arg, "-e")) {
1445 if (++i == argc)
1446 printUsageStatement();
1447 m_scripts.append(Script(false, argv[i]));
1448 continue;
1449 }
1450 if (!strcmp(arg, "-i")) {
1451 m_interactive = true;
1452 continue;
1453 }
1454 if (!strcmp(arg, "-d")) {
1455 m_dump = true;
1456 continue;
1457 }
1458 if (!strcmp(arg, "-p")) {
1459 if (++i == argc)
1460 printUsageStatement();
1461 m_profile = true;
1462 m_profilerOutput = argv[i];
1463 continue;
1464 }
1465 if (!strcmp(arg, "-s")) {
1466#if HAVE(SIGNAL_H)
1467 signal(SIGILL, _exit);
1468 signal(SIGFPE, _exit);
1469 signal(SIGBUS, _exit);
1470 signal(SIGSEGV, _exit);
1471#endif
1472 continue;
1473 }
1474 if (!strcmp(arg, "-x")) {
1475 m_exitCode = true;
1476 continue;
1477 }
1478 if (!strcmp(arg, "--")) {
1479 ++i;
1480 break;
1481 }
1482 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
1483 printUsageStatement(true);
1484
1485 if (!strcmp(arg, "--options")) {
1486 needToDumpOptions = true;
1487 needToExit = true;
1488 continue;
1489 }
1490 if (!strcmp(arg, "--dumpOptions")) {
1491 needToDumpOptions = true;
1492 continue;
1493 }
1494
1495 // See if the -- option is a JSC VM option.
1496 if (strstr(arg, "--") == arg && JSC::Options::setOption(&arg[2])) {
1497 // The arg was recognized as a VM option and has been parsed.
1498 continue; // Just continue with the next arg.
1499 }
1500
1501 // This arg is not recognized by the VM nor by jsc. Pass it on to the
1502 // script.
1503 m_scripts.append(Script(true, argv[i]));
1504 }
1505
1506 if (m_scripts.isEmpty())
1507 m_interactive = true;
1508
1509 for (; i < argc; ++i)
1510 m_arguments.append(argv[i]);
1511
1512 if (needToDumpOptions)
1513 JSC::Options::dumpAllOptions(JSC::Options::DumpLevel::Verbose, "All JSC runtime options:", stderr);
1514 JSC::Options::ensureOptionsAreCoherent();
1515 if (needToExit)
1516 jscExit(EXIT_SUCCESS);
1517}
1518
1519int jscmain(int argc, char** argv)
1520{
1521 // Note that the options parsing can affect VM creation, and thus
1522 // comes first.
1523 CommandLine options(argc, argv);
1524
1525 // Initialize JSC before getting VM.
1526#if ENABLE(SAMPLING_REGIONS)
1527 WTF::initializeMainThread();
1528#endif
1529 JSC::initializeThreading();
1530
1531 VM* vm = &VM::create(LargeHeap).leakRef();
1532 int result;
1533 {
1534 JSLockHolder locker(vm);
1535
1536 if (options.m_profile && !vm->m_perBytecodeProfiler)
1537 vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*vm);
1538
1539 GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
1540 bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump);
1541 if (options.m_interactive && success)
1542 runInteractive(globalObject);
1543
1544 result = success ? 0 : 3;
1545
1546 if (options.m_exitCode)
1547 printf("jsc exiting %d\n", result);
1548
1549 if (options.m_profile) {
1550 if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
1551 fprintf(stderr, "could not save profiler output.\n");
1552 }
1553
1554#if ENABLE(JIT)
1555 if (Options::enableExceptionFuzz())
1556 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
1557 bool fireAtEnabled =
1558 Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
1559 if (Options::enableExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
1560 printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
1561 if (Options::enableOSRExitFuzz()) {
1562 printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
1563 printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
1564 }
1565#endif
1566 }
1567
1568 return result;
1569}
1570
1571static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1572{
1573 FILE* f = fopen(fileName.utf8().data(), "r");
1574 if (!f) {
1575 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1576 return false;
1577 }
1578
1579 size_t bufferSize = 0;
1580 size_t bufferCapacity = 1024;
1581
1582 buffer.resize(bufferCapacity);
1583
1584 while (!feof(f) && !ferror(f)) {
1585 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
1586 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
1587 bufferCapacity *= 2;
1588 buffer.resize(bufferCapacity);
1589 }
1590 }
1591 fclose(f);
1592 buffer[bufferSize] = '\0';
1593
1594 if (buffer[0] == '#' && buffer[1] == '!')
1595 buffer[0] = buffer[1] = '/';
1596
1597 return true;
1598}
1599
1600#if OS(WINDOWS)
1601extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
1602{
1603 return main(argc, const_cast<char**>(argv));
1604}
1605#endif