source: webkit/trunk/Source/JavaScriptCore/jsc.cpp@ 188344

Last change on this file since 188344 was 188344, checked in by [email protected], 10 years ago

Roll out r188339, which broke the build.

Unreviewed.

  • jit/ExecutableAllocator.h:
  • jsc.cpp:

(GlobalObject::finishCreation):
(functionReleaseExecutableMemory):

  • runtime/VM.cpp:

(JSC::StackPreservingRecompiler::visit):
(JSC::StackPreservingRecompiler::operator()):
(JSC::VM::releaseExecutableMemory):
(JSC::releaseExecutableMemory):

  • runtime/VM.h:
  • runtime/Watchdog.cpp:

(JSC::Watchdog::setTimeLimit):

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