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

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

Turning on DUMP_PROPERTYMAP_STATS causes a build failure
https://bugs.webkit.org/show_bug.cgi?id=133673

Reviewed by Andreas Kling.

Source/JavaScriptCore:
Rewrote the property map statistics code because the old code wasn't building,
and it was also mixing numbers for lookups and insertions/removals.

New logging code records the number of calls to PropertyTable::find (finds) and
PropertyTable::get/PropertyTable::findWithString separately so that we can quantify
the number of probing during updates and lookups.

  • jsc.cpp:
  • runtime/PropertyMapHashTable.h:

(JSC::PropertyTable::find):
(JSC::PropertyTable::get):
(JSC::PropertyTable::findWithString):
(JSC::PropertyTable::add):
(JSC::PropertyTable::remove):
(JSC::PropertyTable::reinsert):
(JSC::PropertyTable::rehash):

  • runtime/Structure.cpp:

(JSC::PropertyMapStatisticsExitLogger::PropertyMapStatisticsExitLogger):
(JSC::PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger):

Source/WTF:
Added DEFINE_GLOBAL_FOR_LOGGING to allow running a destructor in logging code
that needs to be enabled in release builds (e.g. for JavaScriptCore).

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