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

Last change on this file since 171387 was 171387, checked in by Brent Fulgham, 11 years ago

Fix Windows (return a value!)

  • jsc.cpp:

(functionQuit): Satisfy compiler's need for
a return value.

  • Property svn:eol-style set to native
File size: 43.6 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012, 2013 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 "ButterflyInlines.h"
26#include "BytecodeGenerator.h"
27#include "Completion.h"
28#include "CopiedSpaceInlines.h"
29#include "ExceptionHelpers.h"
30#include "HeapStatistics.h"
31#include "InitializeThreading.h"
32#include "Interpreter.h"
33#include "JSArray.h"
34#include "JSArrayBuffer.h"
35#include "JSCInlines.h"
36#include "JSFunction.h"
37#include "JSLock.h"
38#include "JSProxy.h"
39#include "JSString.h"
40#include "ProfilerDatabase.h"
41#include "SamplingTool.h"
42#include "StackVisitor.h"
43#include "StructureInlines.h"
44#include "StructureRareDataInlines.h"
45#include "TestRunnerUtils.h"
46#include <math.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <thread>
51#include <wtf/CurrentTime.h>
52#include <wtf/MainThread.h>
53#include <wtf/StringPrintStream.h>
54#include <wtf/text/StringBuilder.h>
55
56#if !OS(WINDOWS)
57#include <unistd.h>
58#endif
59
60#if HAVE(READLINE)
61// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
62// We #define it to something else to avoid this conflict.
63#define Function ReadlineFunction
64#include <readline/history.h>
65#include <readline/readline.h>
66#undef Function
67#endif
68
69#if HAVE(SYS_TIME_H)
70#include <sys/time.h>
71#endif
72
73#if HAVE(SIGNAL_H)
74#include <signal.h>
75#endif
76
77#if COMPILER(MSVC) && !OS(WINCE)
78#include <crtdbg.h>
79#include <mmsystem.h>
80#include <windows.h>
81#endif
82
83#if PLATFORM(IOS) && CPU(ARM_THUMB2)
84#include <fenv.h>
85#include <arm/arch.h>
86#endif
87
88#if PLATFORM(EFL)
89#include <Ecore.h>
90#endif
91
92using namespace JSC;
93using namespace WTF;
94
95namespace {
96
97NO_RETURN_WITH_VALUE static void jscExit(int status)
98{
99#if ENABLE(DFG_JIT)
100 if (DFG::isCrashing()) {
101 for (;;) {
102#if OS(WINDOWS)
103 Sleep(1000);
104#else
105 pause();
106#endif
107 }
108 }
109#endif // ENABLE(DFG_JIT)
110 exit(status);
111}
112
113class Element;
114class ElementHandleOwner;
115class Masuqerader;
116class Root;
117
118class Element : public JSNonFinalObject {
119public:
120 Element(VM& vm, Structure* structure, Root* root)
121 : Base(vm, structure)
122 , m_root(root)
123 {
124 }
125
126 typedef JSNonFinalObject Base;
127 static const bool needsDestruction = false;
128
129 Root* root() const { return m_root; }
130 void setRoot(Root* root) { m_root = root; }
131
132 static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
133 {
134 Structure* structure = createStructure(vm, globalObject, jsNull());
135 Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure, root);
136 element->finishCreation(vm);
137 return element;
138 }
139
140 void finishCreation(VM&);
141
142 static ElementHandleOwner* handleOwner();
143
144 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
145 {
146 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
147 }
148
149 DECLARE_INFO;
150
151private:
152 Root* m_root;
153};
154
155class ElementHandleOwner : public WeakHandleOwner {
156public:
157 virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
158 {
159 Element* element = jsCast<Element*>(handle.slot()->asCell());
160 return visitor.containsOpaqueRoot(element->root());
161 }
162};
163
164class Masquerader : public JSNonFinalObject {
165public:
166 Masquerader(VM& vm, Structure* structure)
167 : Base(vm, structure)
168 {
169 }
170
171 typedef JSNonFinalObject Base;
172
173 static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
174 {
175 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll();
176 Structure* structure = createStructure(vm, globalObject, jsNull());
177 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
178 result->finishCreation(vm);
179 return result;
180 }
181
182 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
183 {
184 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
185 }
186
187 DECLARE_INFO;
188
189protected:
190 static const unsigned StructureFlags = JSC::MasqueradesAsUndefined | Base::StructureFlags;
191};
192
193class Root : public JSDestructibleObject {
194public:
195 Root(VM& vm, Structure* structure)
196 : Base(vm, structure)
197 {
198 }
199
200 Element* element()
201 {
202 return m_element.get();
203 }
204
205 void setElement(Element* element)
206 {
207 Weak<Element> newElement(element, Element::handleOwner());
208 m_element.swap(newElement);
209 }
210
211 static Root* create(VM& vm, JSGlobalObject* globalObject)
212 {
213 Structure* structure = createStructure(vm, globalObject, jsNull());
214 Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
215 root->finishCreation(vm);
216 return root;
217 }
218
219 typedef JSDestructibleObject Base;
220
221 DECLARE_INFO;
222 static const bool needsDestruction = true;
223
224 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
225 {
226 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
227 }
228
229 static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
230 {
231 Base::visitChildren(thisObject, visitor);
232 visitor.addOpaqueRoot(thisObject);
233 }
234
235private:
236 Weak<Element> m_element;
237};
238
239class ImpureGetter : public JSNonFinalObject {
240public:
241 ImpureGetter(VM& vm, Structure* structure)
242 : Base(vm, structure)
243 {
244 }
245
246 DECLARE_INFO;
247 typedef JSNonFinalObject Base;
248
249 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
250 {
251 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
252 }
253
254 static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
255 {
256 ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
257 getter->finishCreation(vm, delegate);
258 return getter;
259 }
260
261 void finishCreation(VM& vm, JSObject* delegate)
262 {
263 Base::finishCreation(vm);
264 if (delegate)
265 m_delegate.set(vm, this, delegate);
266 }
267
268 static const unsigned StructureFlags = JSC::HasImpureGetOwnPropertySlot | JSC::OverridesGetOwnPropertySlot | JSC::OverridesVisitChildren | Base::StructureFlags;
269
270 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
271 {
272 ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
273
274 if (thisObject->m_delegate && thisObject->m_delegate->getPropertySlot(exec, name, slot))
275 return true;
276
277 return Base::getOwnPropertySlot(object, exec, name, slot);
278 }
279
280 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
281 {
282 Base::visitChildren(cell, visitor);
283 ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
284 visitor.append(&thisObject->m_delegate);
285 }
286
287 void setDelegate(VM& vm, JSObject* delegate)
288 {
289 m_delegate.set(vm, this, delegate);
290 }
291
292private:
293 WriteBarrier<JSObject> m_delegate;
294};
295
296const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Element) };
297const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Masquerader) };
298const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Root) };
299const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ImpureGetter) };
300
301ElementHandleOwner* Element::handleOwner()
302{
303 static ElementHandleOwner* owner = 0;
304 if (!owner)
305 owner = new ElementHandleOwner();
306 return owner;
307}
308
309void Element::finishCreation(VM& vm)
310{
311 Base::finishCreation(vm);
312 m_root->setElement(this);
313}
314
315}
316
317static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
318
319static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
320static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
321static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
322
323static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
324static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
325static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
326static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
327static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
328static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
329static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
330static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
331static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
332static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
333static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
334static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
335static EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState*);
336#ifndef NDEBUG
337static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
338static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
339#endif
340static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
341static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
342static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
343static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
344static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
345static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
346static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
347static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
348static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
349static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
350static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
351static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
352static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
353static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
354static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
355static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
356static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
357static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
358static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
359static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
360
361#if ENABLE(SAMPLING_FLAGS)
362static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
363static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
364#endif
365
366struct Script {
367 bool isFile;
368 char* argument;
369
370 Script(bool isFile, char *argument)
371 : isFile(isFile)
372 , argument(argument)
373 {
374 }
375};
376
377class CommandLine {
378public:
379 CommandLine(int argc, char** argv)
380 : m_interactive(false)
381 , m_dump(false)
382 , m_exitCode(false)
383 , m_profile(false)
384 {
385 parseArguments(argc, argv);
386 }
387
388 bool m_interactive;
389 bool m_dump;
390 bool m_exitCode;
391 Vector<Script> m_scripts;
392 Vector<String> m_arguments;
393 bool m_profile;
394 String m_profilerOutput;
395
396 void parseArguments(int, char**);
397};
398
399static const char interactivePrompt[] = ">>> ";
400
401class StopWatch {
402public:
403 void start();
404 void stop();
405 long getElapsedMS(); // call stop() first
406
407private:
408 double m_startTime;
409 double m_stopTime;
410};
411
412void StopWatch::start()
413{
414 m_startTime = monotonicallyIncreasingTime();
415}
416
417void StopWatch::stop()
418{
419 m_stopTime = monotonicallyIncreasingTime();
420}
421
422long StopWatch::getElapsedMS()
423{
424 return static_cast<long>((m_stopTime - m_startTime) * 1000);
425}
426
427class GlobalObject : public JSGlobalObject {
428private:
429 GlobalObject(VM&, Structure*);
430
431public:
432 typedef JSGlobalObject Base;
433
434 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
435 {
436 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
437 object->finishCreation(vm, arguments);
438 vm.heap.addFinalizer(object, destroy);
439 return object;
440 }
441
442 static const bool needsDestruction = false;
443
444 DECLARE_INFO;
445 static const GlobalObjectMethodTable s_globalObjectMethodTable;
446
447 static Structure* createStructure(VM& vm, JSValue prototype)
448 {
449 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
450 }
451
452 static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return true; }
453
454protected:
455 void finishCreation(VM& vm, const Vector<String>& arguments)
456 {
457 Base::finishCreation(vm);
458
459 addFunction(vm, "debug", functionDebug, 1);
460 addFunction(vm, "describe", functionDescribe, 1);
461 addFunction(vm, "describeArray", functionDescribeArray, 1);
462 addFunction(vm, "print", functionPrint, 1);
463 addFunction(vm, "quit", functionQuit, 0);
464 addFunction(vm, "gc", functionGCAndSweep, 0);
465 addFunction(vm, "fullGC", functionFullGC, 0);
466 addFunction(vm, "edenGC", functionEdenGC, 0);
467 addFunction(vm, "deleteAllCompiledCode", functionDeleteAllCompiledCode, 0);
468#ifndef NDEBUG
469 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
470 addFunction(vm, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
471#endif
472 addFunction(vm, "version", functionVersion, 1);
473 addFunction(vm, "run", functionRun, 1);
474 addFunction(vm, "load", functionLoad, 1);
475 addFunction(vm, "readFile", functionReadFile, 1);
476 addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
477 addFunction(vm, "jscStack", functionJSCStack, 1);
478 addFunction(vm, "readline", functionReadline, 0);
479 addFunction(vm, "preciseTime", functionPreciseTime, 0);
480 addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
481 addFunction(vm, "noInline", functionNeverInlineFunction, 1);
482 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
483 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
484 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
485 addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
486#if ENABLE(SAMPLING_FLAGS)
487 addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
488 addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
489#endif
490 addConstructableFunction(vm, "Root", functionCreateRoot, 0);
491 addConstructableFunction(vm, "Element", functionCreateElement, 1);
492 addFunction(vm, "getElement", functionGetElement, 1);
493 addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
494
495 putDirectNativeFunction(vm, this, Identifier(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum | JSC::Function);
496 putDirectNativeFunction(vm, this, Identifier(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum | JSC::Function);
497 putDirectNativeFunction(vm, this, Identifier(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum | JSC::Function);
498 putDirectNativeFunction(vm, this, Identifier(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum | JSC::Function);
499 putDirectNativeFunction(vm, this, Identifier(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum | JSC::Function);
500
501 addFunction(vm, "effectful42", functionEffectful42, 0);
502 addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
503
504 addFunction(vm, "createProxy", functionCreateProxy, 1);
505
506 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
507 addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
508
509 JSArray* array = constructEmptyArray(globalExec(), 0);
510 for (size_t i = 0; i < arguments.size(); ++i)
511 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
512 putDirect(vm, Identifier(globalExec(), "arguments"), array);
513
514 putDirect(vm, Identifier(globalExec(), "console"), jsUndefined());
515 }
516
517 void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
518 {
519 Identifier identifier(&vm, name);
520 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
521 }
522
523 void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
524 {
525 Identifier identifier(&vm, name);
526 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
527 }
528};
529
530const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
531const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, 0, &shouldInterruptScriptBeforeTimeout };
532
533
534GlobalObject::GlobalObject(VM& vm, Structure* structure)
535 : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
536{
537}
538
539static inline String stringFromUTF(const char* utf8)
540{
541 // Find the the first non-ascii character, or nul.
542 const char* pos = utf8;
543 while (*pos > 0)
544 pos++;
545 size_t asciiLength = pos - utf8;
546
547 // Fast case - string is all ascii.
548 if (!*pos)
549 return String(utf8, asciiLength);
550
551 // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
552 ASSERT(*pos < 0);
553 ASSERT(strlen(utf8) == asciiLength + strlen(pos));
554 return String::fromUTF8WithLatin1Fallback(utf8, asciiLength + strlen(pos));
555}
556
557static inline SourceCode jscSource(const char* utf8, const String& filename)
558{
559 String str = stringFromUTF(utf8);
560 return makeSource(str, filename);
561}
562
563EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
564{
565 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
566 if (i)
567 putchar(' ');
568
569 printf("%s", exec->uncheckedArgument(i).toString(exec)->value(exec).utf8().data());
570 }
571
572 putchar('\n');
573 fflush(stdout);
574 return JSValue::encode(jsUndefined());
575}
576
577#ifndef NDEBUG
578EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
579{
580 if (!exec->callerFrame()->isVMEntrySentinel())
581 exec->vm().interpreter->dumpCallFrame(exec->callerFrame());
582 return JSValue::encode(jsUndefined());
583}
584#endif
585
586EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
587{
588 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
589 return JSValue::encode(jsUndefined());
590}
591
592EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
593{
594 if (exec->argumentCount() < 1)
595 return JSValue::encode(jsUndefined());
596 return JSValue::encode(jsString(exec, toString(exec->argument(0))));
597}
598
599EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
600{
601 if (exec->argumentCount() < 1)
602 return JSValue::encode(jsUndefined());
603 JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
604 if (!object)
605 return JSValue::encode(jsString(exec, "<not object>"));
606 return JSValue::encode(jsString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
607}
608
609class FunctionJSCStackFunctor {
610public:
611 FunctionJSCStackFunctor(StringBuilder& trace)
612 : m_trace(trace)
613 {
614 }
615
616 StackVisitor::Status operator()(StackVisitor& visitor)
617 {
618 m_trace.append(String::format(" %zu %s\n", visitor->index(), visitor->toString().utf8().data()));
619 return StackVisitor::Continue;
620 }
621
622private:
623 StringBuilder& m_trace;
624};
625
626EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
627{
628 StringBuilder trace;
629 trace.appendLiteral("--> Stack trace:\n");
630
631 FunctionJSCStackFunctor functor(trace);
632 exec->iterate(functor);
633 fprintf(stderr, "%s", trace.toString().utf8().data());
634 return JSValue::encode(jsUndefined());
635}
636
637EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
638{
639 JSLockHolder lock(exec);
640 return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
641}
642
643EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
644{
645 JSLockHolder lock(exec);
646 JSValue arg = exec->argument(0);
647 return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), arg.isNull() ? nullptr : jsCast<Root*>(exec->argument(0))));
648}
649
650EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
651{
652 JSLockHolder lock(exec);
653 Element* result = jsCast<Root*>(exec->argument(0).asCell())->element();
654 return JSValue::encode(result ? result : jsUndefined());
655}
656
657EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
658{
659 JSLockHolder lock(exec);
660 Element* element = jsCast<Element*>(exec->argument(0));
661 Root* root = jsCast<Root*>(exec->argument(1));
662 element->setRoot(root);
663 return JSValue::encode(jsUndefined());
664}
665
666EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
667{
668 JSLockHolder lock(exec);
669 JSValue target = exec->argument(0);
670 if (!target.isObject())
671 return JSValue::encode(jsUndefined());
672 JSObject* jsTarget = asObject(target.asCell());
673 Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->prototype());
674 JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
675 return JSValue::encode(proxy);
676}
677
678EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
679{
680 JSLockHolder lock(exec);
681 JSValue target = exec->argument(0);
682 JSObject* delegate = nullptr;
683 if (target.isObject())
684 delegate = asObject(target.asCell());
685 Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
686 ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
687 return JSValue::encode(result);
688}
689
690EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
691{
692 JSLockHolder lock(exec);
693 JSValue base = exec->argument(0);
694 if (!base.isObject())
695 return JSValue::encode(jsUndefined());
696 JSValue delegate = exec->argument(1);
697 if (!delegate.isObject())
698 return JSValue::encode(jsUndefined());
699 ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
700 impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
701 return JSValue::encode(jsUndefined());
702}
703
704EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
705{
706 JSLockHolder lock(exec);
707 exec->heap()->collectAllGarbage();
708 return JSValue::encode(jsUndefined());
709}
710
711EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
712{
713 JSLockHolder lock(exec);
714 exec->heap()->collect(FullCollection);
715 return JSValue::encode(jsUndefined());
716}
717
718EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
719{
720 JSLockHolder lock(exec);
721 exec->heap()->collect(EdenCollection);
722 return JSValue::encode(jsUndefined());
723}
724
725EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState* exec)
726{
727 JSLockHolder lock(exec);
728 exec->heap()->deleteAllCompiledCode();
729 return JSValue::encode(jsUndefined());
730}
731
732#ifndef NDEBUG
733EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
734{
735 JSLockHolder lock(exec);
736 exec->vm().releaseExecutableMemory();
737 return JSValue::encode(jsUndefined());
738}
739#endif
740
741EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
742{
743 // We need this function for compatibility with the Mozilla JS tests but for now
744 // we don't actually do any version-specific handling
745 return JSValue::encode(jsUndefined());
746}
747
748EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
749{
750 String fileName = exec->argument(0).toString(exec)->value(exec);
751 Vector<char> script;
752 if (!fillBufferWithContentsOfFile(fileName, script))
753 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
754
755 GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
756
757 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
758 for (unsigned i = 1; i < exec->argumentCount(); ++i)
759 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
760 globalObject->putDirect(
761 exec->vm(), Identifier(globalObject->globalExec(), "arguments"), array);
762
763 JSValue exception;
764 StopWatch stopWatch;
765 stopWatch.start();
766 evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &exception);
767 stopWatch.stop();
768
769 if (!!exception) {
770 exec->vm().throwException(globalObject->globalExec(), exception);
771 return JSValue::encode(jsUndefined());
772 }
773
774 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
775}
776
777EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
778{
779 String fileName = exec->argument(0).toString(exec)->value(exec);
780 Vector<char> script;
781 if (!fillBufferWithContentsOfFile(fileName, script))
782 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
783
784 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
785
786 JSValue evaluationException;
787 JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &evaluationException);
788 if (evaluationException)
789 exec->vm().throwException(exec, evaluationException);
790 return JSValue::encode(result);
791}
792
793EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
794{
795 String fileName = exec->argument(0).toString(exec)->value(exec);
796 Vector<char> script;
797 if (!fillBufferWithContentsOfFile(fileName, script))
798 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
799
800 return JSValue::encode(jsString(exec, stringFromUTF(script.data())));
801}
802
803EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
804{
805 String fileName = exec->argument(0).toString(exec)->value(exec);
806 Vector<char> script;
807 if (!fillBufferWithContentsOfFile(fileName, script))
808 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
809
810 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
811
812 StopWatch stopWatch;
813 stopWatch.start();
814
815 JSValue syntaxException;
816 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
817 stopWatch.stop();
818
819 if (!validSyntax)
820 exec->vm().throwException(exec, syntaxException);
821 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
822}
823
824#if ENABLE(SAMPLING_FLAGS)
825EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
826{
827 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
828 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
829 if ((flag >= 1) && (flag <= 32))
830 SamplingFlags::setFlag(flag);
831 }
832 return JSValue::encode(jsNull());
833}
834
835EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
836{
837 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
838 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
839 if ((flag >= 1) && (flag <= 32))
840 SamplingFlags::clearFlag(flag);
841 }
842 return JSValue::encode(jsNull());
843}
844#endif
845
846EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
847{
848 Vector<char, 256> line;
849 int c;
850 while ((c = getchar()) != EOF) {
851 // FIXME: Should we also break on \r?
852 if (c == '\n')
853 break;
854 line.append(c);
855 }
856 line.append('\0');
857 return JSValue::encode(jsString(exec, line.data()));
858}
859
860EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
861{
862 return JSValue::encode(jsNumber(currentTime()));
863}
864
865EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
866{
867 return JSValue::encode(setNeverInline(exec));
868}
869
870EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
871{
872 return JSValue::encode(optimizeNextInvocation(exec));
873}
874
875EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
876{
877 return JSValue::encode(numberOfDFGCompiles(exec));
878}
879
880EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
881{
882 if (exec->argumentCount() < 1)
883 return JSValue::encode(jsUndefined());
884
885 CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
886 if (!block)
887 return JSValue::encode(jsNumber(0));
888
889 return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
890}
891
892EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
893{
894 if (exec->argumentCount() < 1)
895 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Not enough arguments")));
896
897 JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
898 if (!buffer)
899 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Expected an array buffer")));
900
901 ArrayBufferContents dummyContents;
902 buffer->impl()->transfer(dummyContents);
903
904 return JSValue::encode(jsUndefined());
905}
906
907EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
908{
909 jscExit(EXIT_SUCCESS);
910
911#if COMPILER(MSVC)
912 // Without this, Visual Studio will complain that this method does not return a value.
913 return JSValue::encode(jsUndefined());
914#endif
915}
916
917EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
918EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
919
920EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
921EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
922
923EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
924
925EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
926{
927 return JSValue::encode(jsNumber(42));
928}
929
930EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
931{
932 return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
933}
934
935// Use SEH for Release builds only to get rid of the crash report dialog
936// (luckily the same tests fail in Release and Debug builds so far). Need to
937// be in a separate main function because the jscmain function requires object
938// unwinding.
939
940#if COMPILER(MSVC) && !defined(_DEBUG) && !OS(WINCE)
941#define TRY __try {
942#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
943#else
944#define TRY
945#define EXCEPT(x)
946#endif
947
948int jscmain(int argc, char** argv);
949
950static double s_desiredTimeout;
951
952static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
953{
954 auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
955 std::this_thread::sleep_for(timeout);
956
957 dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
958 CRASH();
959}
960
961int main(int argc, char** argv)
962{
963#if PLATFORM(IOS) && CPU(ARM_THUMB2)
964 // Enabled IEEE754 denormal support.
965 fenv_t env;
966 fegetenv( &env );
967 env.__fpscr &= ~0x01000000u;
968 fesetenv( &env );
969#endif
970
971#if OS(WINDOWS)
972#if !OS(WINCE)
973 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
974 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
975 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
976 ::SetErrorMode(0);
977
978#if defined(_DEBUG)
979 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
980 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
981 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
982 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
983 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
984 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
985#endif
986#endif
987
988 timeBeginPeriod(1);
989#endif
990
991#if PLATFORM(EFL)
992 ecore_init();
993#endif
994
995 // Initialize JSC before getting VM.
996#if ENABLE(SAMPLING_REGIONS)
997 WTF::initializeMainThread();
998#endif
999 JSC::initializeThreading();
1000
1001#if !OS(WINCE)
1002 if (char* timeoutString = getenv("JSC_timeout")) {
1003 if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1004 dataLog(
1005 "WARNING: timeout string is malformed, got ", timeoutString,
1006 " but expected a number. Not using a timeout.\n");
1007 } else
1008 createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1009 }
1010#endif
1011
1012#if PLATFORM(IOS)
1013 Options::crashIfCantAllocateJITMemory() = true;
1014#endif
1015
1016 // We can't use destructors in the following code because it uses Windows
1017 // Structured Exception Handling
1018 int res = 0;
1019 TRY
1020 res = jscmain(argc, argv);
1021 EXCEPT(res = 3)
1022 if (Options::logHeapStatisticsAtExit())
1023 HeapStatistics::reportSuccess();
1024
1025#if PLATFORM(EFL)
1026 ecore_shutdown();
1027#endif
1028
1029 jscExit(res);
1030}
1031
1032static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
1033{
1034 const char* script;
1035 String fileName;
1036 Vector<char> scriptBuffer;
1037
1038 if (dump)
1039 JSC::Options::dumpGeneratedBytecodes() = true;
1040
1041 VM& vm = globalObject->vm();
1042
1043#if ENABLE(SAMPLING_FLAGS)
1044 SamplingFlags::start();
1045#endif
1046
1047 bool success = true;
1048 for (size_t i = 0; i < scripts.size(); i++) {
1049 if (scripts[i].isFile) {
1050 fileName = scripts[i].argument;
1051 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
1052 return false; // fail early so we can catch missing files
1053 script = scriptBuffer.data();
1054 } else {
1055 script = scripts[i].argument;
1056 fileName = "[Command Line]";
1057 }
1058
1059 vm.startSampling();
1060
1061 JSValue evaluationException;
1062 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), &evaluationException);
1063 success = success && !evaluationException;
1064 if (dump && !evaluationException)
1065 printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1066 if (evaluationException) {
1067 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1068 Identifier stackID(globalObject->globalExec(), "stack");
1069 JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID);
1070 if (!stackValue.isUndefinedOrNull())
1071 printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1072 }
1073
1074 vm.stopSampling();
1075 globalObject->globalExec()->clearException();
1076 }
1077
1078#if ENABLE(SAMPLING_FLAGS)
1079 SamplingFlags::stop();
1080#endif
1081#if ENABLE(SAMPLING_REGIONS)
1082 SamplingRegion::dump();
1083#endif
1084 vm.dumpSampleData(globalObject->globalExec());
1085#if ENABLE(SAMPLING_COUNTERS)
1086 AbstractSamplingCounter::dump();
1087#endif
1088#if ENABLE(REGEXP_TRACING)
1089 vm.dumpRegExpTrace();
1090#endif
1091 return success;
1092}
1093
1094#define RUNNING_FROM_XCODE 0
1095
1096static void runInteractive(GlobalObject* globalObject)
1097{
1098 String interpreterName("Interpreter");
1099
1100 bool shouldQuit = false;
1101 while (!shouldQuit) {
1102#if HAVE(READLINE) && !RUNNING_FROM_XCODE
1103 ParserError error;
1104 String source;
1105 do {
1106 error = ParserError();
1107 char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
1108 shouldQuit = !line;
1109 if (!line)
1110 break;
1111 source = source + line;
1112 source = source + '\n';
1113 checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
1114 if (!line[0])
1115 break;
1116 add_history(line);
1117 } while (error.m_syntaxErrorType == ParserError::SyntaxErrorRecoverable);
1118
1119 if (error.m_type != ParserError::ErrorNone) {
1120 printf("%s:%d\n", error.m_message.utf8().data(), error.m_line);
1121 continue;
1122 }
1123
1124
1125 JSValue evaluationException;
1126 JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), &evaluationException);
1127#else
1128 printf("%s", interactivePrompt);
1129 Vector<char, 256> line;
1130 int c;
1131 while ((c = getchar()) != EOF) {
1132 // FIXME: Should we also break on \r?
1133 if (c == '\n')
1134 break;
1135 line.append(c);
1136 }
1137 if (line.isEmpty())
1138 break;
1139 line.append('\0');
1140
1141 JSValue evaluationException;
1142 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
1143#endif
1144 if (evaluationException)
1145 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1146 else
1147 printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1148
1149 globalObject->globalExec()->clearException();
1150 }
1151 printf("\n");
1152}
1153
1154static NO_RETURN void printUsageStatement(bool help = false)
1155{
1156 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
1157 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
1158 fprintf(stderr, " -e Evaluate argument as script code\n");
1159 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
1160 fprintf(stderr, " -h|--help Prints this help message\n");
1161 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
1162#if HAVE(SIGNAL_H)
1163 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
1164#endif
1165 fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
1166 fprintf(stderr, " -x Output exit code before terminating\n");
1167 fprintf(stderr, "\n");
1168 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
1169 fprintf(stderr, " --dumpOptions Dumps all JSC VM options before continuing\n");
1170 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
1171 fprintf(stderr, "\n");
1172
1173 jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
1174}
1175
1176void CommandLine::parseArguments(int argc, char** argv)
1177{
1178 int i = 1;
1179 bool needToDumpOptions = false;
1180 bool needToExit = false;
1181
1182 for (; i < argc; ++i) {
1183 const char* arg = argv[i];
1184 if (!strcmp(arg, "-f")) {
1185 if (++i == argc)
1186 printUsageStatement();
1187 m_scripts.append(Script(true, argv[i]));
1188 continue;
1189 }
1190 if (!strcmp(arg, "-e")) {
1191 if (++i == argc)
1192 printUsageStatement();
1193 m_scripts.append(Script(false, argv[i]));
1194 continue;
1195 }
1196 if (!strcmp(arg, "-i")) {
1197 m_interactive = true;
1198 continue;
1199 }
1200 if (!strcmp(arg, "-d")) {
1201 m_dump = true;
1202 continue;
1203 }
1204 if (!strcmp(arg, "-p")) {
1205 if (++i == argc)
1206 printUsageStatement();
1207 m_profile = true;
1208 m_profilerOutput = argv[i];
1209 continue;
1210 }
1211 if (!strcmp(arg, "-s")) {
1212#if HAVE(SIGNAL_H)
1213 signal(SIGILL, _exit);
1214 signal(SIGFPE, _exit);
1215 signal(SIGBUS, _exit);
1216 signal(SIGSEGV, _exit);
1217#endif
1218 continue;
1219 }
1220 if (!strcmp(arg, "-x")) {
1221 m_exitCode = true;
1222 continue;
1223 }
1224 if (!strcmp(arg, "--")) {
1225 ++i;
1226 break;
1227 }
1228 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
1229 printUsageStatement(true);
1230
1231 if (!strcmp(arg, "--options")) {
1232 needToDumpOptions = true;
1233 needToExit = true;
1234 continue;
1235 }
1236 if (!strcmp(arg, "--dumpOptions")) {
1237 needToDumpOptions = true;
1238 continue;
1239 }
1240
1241 // See if the -- option is a JSC VM option.
1242 // NOTE: At this point, we know that the arg starts with "--". Skip it.
1243 if (JSC::Options::setOption(&arg[2])) {
1244 // The arg was recognized as a VM option and has been parsed.
1245 continue; // Just continue with the next arg.
1246 }
1247
1248 // This arg is not recognized by the VM nor by jsc. Pass it on to the
1249 // script.
1250 m_scripts.append(Script(true, argv[i]));
1251 }
1252
1253 if (m_scripts.isEmpty())
1254 m_interactive = true;
1255
1256 for (; i < argc; ++i)
1257 m_arguments.append(argv[i]);
1258
1259 if (needToDumpOptions)
1260 JSC::Options::dumpAllOptions(stderr);
1261 if (needToExit)
1262 jscExit(EXIT_SUCCESS);
1263}
1264
1265int jscmain(int argc, char** argv)
1266{
1267 // Note that the options parsing can affect VM creation, and thus
1268 // comes first.
1269 CommandLine options(argc, argv);
1270 VM* vm = VM::create(LargeHeap).leakRef();
1271 int result;
1272 {
1273 JSLockHolder locker(vm);
1274
1275 if (options.m_profile && !vm->m_perBytecodeProfiler)
1276 vm->m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*vm));
1277
1278 GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
1279 bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump);
1280 if (options.m_interactive && success)
1281 runInteractive(globalObject);
1282
1283 result = success ? 0 : 3;
1284
1285 if (options.m_exitCode)
1286 printf("jsc exiting %d\n", result);
1287
1288 if (options.m_profile) {
1289 if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
1290 fprintf(stderr, "could not save profiler output.\n");
1291 }
1292
1293#if ENABLE(JIT)
1294 if (Options::enableExceptionFuzz())
1295 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
1296#endif
1297 }
1298
1299 return result;
1300}
1301
1302static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1303{
1304 FILE* f = fopen(fileName.utf8().data(), "r");
1305 if (!f) {
1306 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1307 return false;
1308 }
1309
1310 size_t bufferSize = 0;
1311 size_t bufferCapacity = 1024;
1312
1313 buffer.resize(bufferCapacity);
1314
1315 while (!feof(f) && !ferror(f)) {
1316 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
1317 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
1318 bufferCapacity *= 2;
1319 buffer.resize(bufferCapacity);
1320 }
1321 }
1322 fclose(f);
1323 buffer[bufferSize] = '\0';
1324
1325 if (buffer[0] == '#' && buffer[1] == '!')
1326 buffer[0] = buffer[1] = '/';
1327
1328 return true;
1329}
Note: See TracBrowser for help on using the repository browser.