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

Last change on this file since 128851 was 128851, checked in by Csaba Osztrogonác, 13 years ago

Unreviewed, rolling out r128826 and r128813.

Source/JavaScriptCore:

  • API/JSCallbackConstructor.cpp:

(JSC):
(JSC::JSCallbackConstructor::JSCallbackConstructor):

  • API/JSCallbackConstructor.h:

(JSCallbackConstructor):

  • API/JSCallbackObject.cpp:

(JSC):
(JSC::::createStructure):

  • API/JSCallbackObject.h:

(JSC::JSCallbackObject::create):
(JSCallbackObject):

  • API/JSClassRef.cpp:

(OpaqueJSClass::prototype):

  • API/JSObjectRef.cpp:

(JSObjectMake):
(JSObjectGetPrivate):
(JSObjectSetPrivate):
(JSObjectGetPrivateProperty):
(JSObjectSetPrivateProperty):
(JSObjectDeletePrivateProperty):

  • API/JSValueRef.cpp:

(JSValueIsObjectOfClass):

  • API/JSWeakObjectMapRefPrivate.cpp:
  • GNUmakefile.list.am:
  • JSCTypedArrayStubs.h:

(JSC):

(JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
(JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):

  • heap/Heap.cpp:

(JSC::Heap::isSafeToSweepStructures):
(JSC):

  • heap/Heap.h:

(JSC::Heap::allocatorForObjectWithDestructor):
(Heap):
(JSC::Heap::allocateWithDestructor):
(JSC::Heap::allocateStructure):
(JSC):

  • heap/IncrementalSweeper.cpp:

(JSC::IncrementalSweeper::IncrementalSweeper):
(JSC::IncrementalSweeper::sweepNextBlock):
(JSC::IncrementalSweeper::startSweeping):
(JSC::IncrementalSweeper::willFinishSweeping):
(JSC::IncrementalSweeper::structuresCanBeSwept):
(JSC):

  • heap/IncrementalSweeper.h:

(IncrementalSweeper):

  • heap/MarkedAllocator.cpp:

(JSC::MarkedAllocator::tryAllocateHelper):
(JSC::MarkedAllocator::allocateBlock):

  • heap/MarkedAllocator.h:

(JSC::MarkedAllocator::cellsNeedDestruction):
(JSC::MarkedAllocator::onlyContainsStructures):
(MarkedAllocator):
(JSC::MarkedAllocator::MarkedAllocator):
(JSC::MarkedAllocator::init):

  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::create):
(JSC::MarkedBlock::MarkedBlock):
(JSC):
(JSC::MarkedBlock::specializedSweep):
(JSC::MarkedBlock::sweep):
(JSC::MarkedBlock::sweepHelper):

  • heap/MarkedBlock.h:

(JSC):
(MarkedBlock):
(JSC::MarkedBlock::cellsNeedDestruction):
(JSC::MarkedBlock::onlyContainsStructures):

  • heap/MarkedSpace.cpp:

(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::resetAllocators):
(JSC::MarkedSpace::canonicalizeCellLivenessData):
(JSC::MarkedSpace::isPagedOut):
(JSC::MarkedSpace::freeBlock):

  • heap/MarkedSpace.h:

(MarkedSpace):
(Subspace):
(JSC::MarkedSpace::allocatorFor):
(JSC::MarkedSpace::destructorAllocatorFor):
(JSC::MarkedSpace::allocateWithDestructor):
(JSC::MarkedSpace::allocateStructure):
(JSC::MarkedSpace::forEachBlock):

  • heap/SlotVisitor.cpp:
  • jit/JIT.h:
  • jit/JITInlineMethods.h:

(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateJSFinalObject):
(JSC::JIT::emitAllocateJSArray):

  • jsc.cpp:

(GlobalObject::create):

  • runtime/Arguments.cpp:

(JSC):

  • runtime/Arguments.h:

(Arguments):
(JSC::Arguments::Arguments):

  • runtime/ErrorPrototype.cpp:

(JSC):

  • runtime/Executable.h:
  • runtime/InternalFunction.cpp:

(JSC):
(JSC::InternalFunction::InternalFunction):

  • runtime/InternalFunction.h:

(InternalFunction):

  • runtime/JSCell.h:

(JSC):
(JSC::allocateCell):

  • runtime/JSDestructibleObject.h: Removed.
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::reset):
(JSC):

  • runtime/JSGlobalObject.h:

(JSGlobalObject):
(JSC::JSGlobalObject::createRareDataIfNeeded):
(JSC::JSGlobalObject::create):

  • runtime/JSGlobalThis.h:

(JSGlobalThis):
(JSC::JSGlobalThis::JSGlobalThis):

  • runtime/JSPropertyNameIterator.h:
  • runtime/JSScope.cpp:

(JSC):

  • runtime/JSString.h:

(JSC):

  • runtime/JSWrapperObject.h:

(JSWrapperObject):
(JSC::JSWrapperObject::JSWrapperObject):

  • runtime/MathObject.cpp:

(JSC):

  • runtime/NameInstance.h:

(NameInstance):

  • runtime/RegExp.h:
  • runtime/RegExpObject.cpp:

(JSC):

  • runtime/SparseArrayValueMap.h:
  • runtime/Structure.h:

(JSC::Structure):
(JSC::JSCell::classInfo):
(JSC):

  • runtime/StructureChain.h:
  • runtime/SymbolTable.h:
  • testRegExp.cpp:

(GlobalObject::create):

Source/WebCore:

  • ForwardingHeaders/runtime/JSDestructibleObject.h: Removed.
  • bindings/js/JSDOMWrapper.h:

(WebCore::JSDOMWrapper::JSDOMWrapper):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHeader):

  • bridge/objc/objc_runtime.h:

(ObjcFallbackObjectImp):

  • bridge/objc/objc_runtime.mm:

(Bindings):
(JSC::Bindings::ObjcFallbackObjectImp::ObjcFallbackObjectImp):

  • bridge/runtime_array.cpp:

(JSC):
(JSC::RuntimeArray::destroy):

  • bridge/runtime_array.h:

(JSC::RuntimeArray::create):

  • bridge/runtime_object.cpp:

(Bindings):
(JSC::Bindings::RuntimeObject::RuntimeObject):

  • bridge/runtime_object.h:

(RuntimeObject):

Source/WebKit2:

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

(WebKit):
(WebKit::JSNPObject::JSNPObject):

  • WebProcess/Plugins/Netscape/JSNPObject.h:

(JSNPObject):

  • Property svn:eol-style set to native
File size: 25.5 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 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 "ButterflyInlineMethods.h"
26#include "BytecodeGenerator.h"
27#include "Completion.h"
28#include "CopiedSpaceInlineMethods.h"
29#include "ExceptionHelpers.h"
30#include "InitializeThreading.h"
31#include "Interpreter.h"
32#include "JSArray.h"
33#include "JSCTypedArrayStubs.h"
34#include "JSFunction.h"
35#include "JSLock.h"
36#include "JSString.h"
37#include "SamplingTool.h"
38#include <math.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <wtf/CurrentTime.h>
43#include <wtf/MainThread.h>
44#include <wtf/text/StringBuilder.h>
45
46#if !OS(WINDOWS)
47#include <unistd.h>
48#endif
49
50#if HAVE(READLINE)
51// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
52// We #define it to something else to avoid this conflict.
53#define Function ReadlineFunction
54#include <readline/history.h>
55#include <readline/readline.h>
56#undef Function
57#endif
58
59#if HAVE(SYS_TIME_H)
60#include <sys/time.h>
61#endif
62
63#if HAVE(SIGNAL_H)
64#include <signal.h>
65#endif
66
67#if COMPILER(MSVC) && !OS(WINCE)
68#include <crtdbg.h>
69#include <mmsystem.h>
70#include <windows.h>
71#endif
72
73#if PLATFORM(QT)
74#include <QCoreApplication>
75#include <QDateTime>
76#endif
77
78#if PLATFORM(IOS)
79#include <fenv.h>
80#include <arm/arch.h>
81#endif
82
83using namespace JSC;
84using namespace WTF;
85
86static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
87
88static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
89static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
90static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
91static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
92static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
93#ifndef NDEBUG
94static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
95static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
96#endif
97static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
98static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
99static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
100static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
101static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
102static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
103static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
104
105#if ENABLE(SAMPLING_FLAGS)
106static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
107static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
108#endif
109
110struct Script {
111 bool isFile;
112 char* argument;
113
114 Script(bool isFile, char *argument)
115 : isFile(isFile)
116 , argument(argument)
117 {
118 }
119};
120
121class CommandLine {
122public:
123 CommandLine(int argc, char** argv)
124 : m_interactive(false)
125 , m_dump(false)
126 , m_exitCode(false)
127 {
128 parseArguments(argc, argv);
129 }
130
131 bool m_interactive;
132 bool m_dump;
133 bool m_exitCode;
134 Vector<Script> m_scripts;
135 Vector<String> m_arguments;
136
137 void parseArguments(int, char**);
138};
139
140static const char interactivePrompt[] = "> ";
141
142class StopWatch {
143public:
144 void start();
145 void stop();
146 long getElapsedMS(); // call stop() first
147
148private:
149 double m_startTime;
150 double m_stopTime;
151};
152
153void StopWatch::start()
154{
155 m_startTime = currentTime();
156}
157
158void StopWatch::stop()
159{
160 m_stopTime = currentTime();
161}
162
163long StopWatch::getElapsedMS()
164{
165 return static_cast<long>((m_stopTime - m_startTime) * 1000);
166}
167
168class GlobalObject : public JSGlobalObject {
169private:
170 GlobalObject(JSGlobalData&, Structure*);
171
172public:
173 typedef JSGlobalObject Base;
174
175 static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<String>& arguments)
176 {
177 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure);
178 object->finishCreation(globalData, arguments);
179 return object;
180 }
181
182 static const ClassInfo s_info;
183 static const GlobalObjectMethodTable s_globalObjectMethodTable;
184
185 static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
186 {
187 return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
188 }
189
190 static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return true; }
191
192protected:
193 void finishCreation(JSGlobalData& globalData, const Vector<String>& arguments)
194 {
195 Base::finishCreation(globalData);
196
197 addFunction(globalData, "debug", functionDebug, 1);
198 addFunction(globalData, "describe", functionDescribe, 1);
199 addFunction(globalData, "print", functionPrint, 1);
200 addFunction(globalData, "quit", functionQuit, 0);
201 addFunction(globalData, "gc", functionGC, 0);
202#ifndef NDEBUG
203 addFunction(globalData, "dumpCallFrame", functionDumpCallFrame, 0);
204 addFunction(globalData, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
205#endif
206 addFunction(globalData, "version", functionVersion, 1);
207 addFunction(globalData, "run", functionRun, 1);
208 addFunction(globalData, "load", functionLoad, 1);
209 addFunction(globalData, "checkSyntax", functionCheckSyntax, 1);
210 addFunction(globalData, "jscStack", functionJSCStack, 1);
211 addFunction(globalData, "readline", functionReadline, 0);
212 addFunction(globalData, "preciseTime", functionPreciseTime, 0);
213#if ENABLE(SAMPLING_FLAGS)
214 addFunction(globalData, "setSamplingFlags", functionSetSamplingFlags, 1);
215 addFunction(globalData, "clearSamplingFlags", functionClearSamplingFlags, 1);
216#endif
217
218 addConstructableFunction(globalData, "Uint8Array", constructJSUint8Array, 1);
219 addConstructableFunction(globalData, "Uint8ClampedArray", constructJSUint8ClampedArray, 1);
220 addConstructableFunction(globalData, "Uint16Array", constructJSUint16Array, 1);
221 addConstructableFunction(globalData, "Uint32Array", constructJSUint32Array, 1);
222 addConstructableFunction(globalData, "Int8Array", constructJSInt8Array, 1);
223 addConstructableFunction(globalData, "Int16Array", constructJSInt16Array, 1);
224 addConstructableFunction(globalData, "Int32Array", constructJSInt32Array, 1);
225 addConstructableFunction(globalData, "Float32Array", constructJSFloat32Array, 1);
226 addConstructableFunction(globalData, "Float64Array", constructJSFloat64Array, 1);
227
228 JSArray* array = constructEmptyArray(globalExec());
229 for (size_t i = 0; i < arguments.size(); ++i)
230 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
231 putDirect(globalData, Identifier(globalExec(), "arguments"), array);
232 }
233
234 void addFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments)
235 {
236 Identifier identifier(globalExec(), name);
237 putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function));
238 }
239
240 void addConstructableFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments)
241 {
242 Identifier identifier(globalExec(), name);
243 putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function, NoIntrinsic, function));
244 }
245};
246COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
247ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
248
249const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
250const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled };
251
252
253GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure)
254 : JSGlobalObject(globalData, structure, &s_globalObjectMethodTable)
255{
256}
257
258static inline SourceCode jscSource(const char* utf8, const String& filename)
259{
260 // Find the the first non-ascii character, or nul.
261 const char* pos = utf8;
262 while (*pos > 0)
263 pos++;
264 size_t asciiLength = pos - utf8;
265
266 // Fast case - string is all ascii.
267 if (!*pos)
268 return makeSource(String(utf8, asciiLength), filename);
269
270 // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
271 ASSERT(*pos < 0);
272 ASSERT(strlen(utf8) == asciiLength + strlen(pos));
273 String source = String::fromUTF8WithLatin1Fallback(utf8, asciiLength + strlen(pos));
274 return makeSource(source.impl(), filename);
275}
276
277EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
278{
279 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
280 if (i)
281 putchar(' ');
282
283 printf("%s", exec->argument(i).toString(exec)->value(exec).utf8().data());
284 }
285
286 putchar('\n');
287 fflush(stdout);
288 return JSValue::encode(jsUndefined());
289}
290
291#ifndef NDEBUG
292EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
293{
294 if (!exec->callerFrame()->hasHostCallFrameFlag())
295 exec->globalData().interpreter->dumpCallFrame(exec->callerFrame());
296 return JSValue::encode(jsUndefined());
297}
298#endif
299
300EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
301{
302 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
303 return JSValue::encode(jsUndefined());
304}
305
306EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
307{
308 fprintf(stderr, "--> %s\n", exec->argument(0).description());
309 return JSValue::encode(jsUndefined());
310}
311
312EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
313{
314 StringBuilder trace;
315 trace.appendLiteral("--> Stack trace:\n");
316
317 Vector<StackFrame> stackTrace;
318 Interpreter::getStackTrace(&exec->globalData(), stackTrace);
319 int i = 0;
320
321 for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
322 StackFrame level = *iter;
323 trace.append(String::format(" %i %s\n", i, level.toString(exec).utf8().data()));
324 i++;
325 }
326 fprintf(stderr, "%s", trace.toString().utf8().data());
327 return JSValue::encode(jsUndefined());
328}
329
330EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
331{
332 JSLockHolder lock(exec);
333 exec->heap()->collectAllGarbage();
334 return JSValue::encode(jsUndefined());
335}
336
337#ifndef NDEBUG
338EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
339{
340 JSLockHolder lock(exec);
341 exec->globalData().releaseExecutableMemory();
342 return JSValue::encode(jsUndefined());
343}
344#endif
345
346EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
347{
348 // We need this function for compatibility with the Mozilla JS tests but for now
349 // we don't actually do any version-specific handling
350 return JSValue::encode(jsUndefined());
351}
352
353EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
354{
355 String fileName = exec->argument(0).toString(exec)->value(exec);
356 Vector<char> script;
357 if (!fillBufferWithContentsOfFile(fileName, script))
358 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
359
360 GlobalObject* globalObject = GlobalObject::create(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<String>());
361
362 JSValue exception;
363 StopWatch stopWatch;
364 stopWatch.start();
365 evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &exception);
366 stopWatch.stop();
367
368 if (!!exception) {
369 throwError(globalObject->globalExec(), exception);
370 return JSValue::encode(jsUndefined());
371 }
372
373 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
374}
375
376EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
377{
378 String fileName = exec->argument(0).toString(exec)->value(exec);
379 Vector<char> script;
380 if (!fillBufferWithContentsOfFile(fileName, script))
381 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
382
383 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
384
385 JSValue evaluationException;
386 JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &evaluationException);
387 if (evaluationException)
388 throwError(exec, evaluationException);
389 return JSValue::encode(result);
390}
391
392EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
393{
394 String fileName = exec->argument(0).toString(exec)->value(exec);
395 Vector<char> script;
396 if (!fillBufferWithContentsOfFile(fileName, script))
397 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
398
399 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
400
401 StopWatch stopWatch;
402 stopWatch.start();
403
404 JSValue syntaxException;
405 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
406 stopWatch.stop();
407
408 if (!validSyntax)
409 throwError(exec, syntaxException);
410 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
411}
412
413#if ENABLE(SAMPLING_FLAGS)
414EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
415{
416 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
417 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
418 if ((flag >= 1) && (flag <= 32))
419 SamplingFlags::setFlag(flag);
420 }
421 return JSValue::encode(jsNull());
422}
423
424EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
425{
426 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
427 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
428 if ((flag >= 1) && (flag <= 32))
429 SamplingFlags::clearFlag(flag);
430 }
431 return JSValue::encode(jsNull());
432}
433#endif
434
435EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
436{
437 Vector<char, 256> line;
438 int c;
439 while ((c = getchar()) != EOF) {
440 // FIXME: Should we also break on \r?
441 if (c == '\n')
442 break;
443 line.append(c);
444 }
445 line.append('\0');
446 return JSValue::encode(jsString(exec, line.data()));
447}
448
449EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
450{
451 return JSValue::encode(jsNumber(currentTime()));
452}
453
454EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
455{
456 exit(EXIT_SUCCESS);
457
458#if COMPILER(MSVC) && OS(WINCE)
459 // Without this, Visual Studio will complain that this method does not return a value.
460 return JSValue::encode(jsUndefined());
461#endif
462}
463
464// Use SEH for Release builds only to get rid of the crash report dialog
465// (luckily the same tests fail in Release and Debug builds so far). Need to
466// be in a separate main function because the jscmain function requires object
467// unwinding.
468
469#if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
470#define TRY __try {
471#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
472#else
473#define TRY
474#define EXCEPT(x)
475#endif
476
477int jscmain(int argc, char** argv);
478
479int main(int argc, char** argv)
480{
481#if PLATFORM(IOS)
482 // Enabled IEEE754 denormal support.
483 fenv_t env;
484 fegetenv( &env );
485 env.__fpscr &= ~0x01000000u;
486 fesetenv( &env );
487#endif
488
489#if OS(WINDOWS)
490#if !OS(WINCE)
491 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
492 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
493 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
494 ::SetErrorMode(0);
495#endif
496
497#if defined(_DEBUG)
498 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
499 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
500 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
501 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
502 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
503 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
504#endif
505
506 timeBeginPeriod(1);
507#endif
508
509#if PLATFORM(QT)
510 QCoreApplication app(argc, argv);
511#endif
512
513 // Initialize JSC before getting JSGlobalData.
514#if ENABLE(SAMPLING_REGIONS)
515 WTF::initializeMainThread();
516#endif
517 JSC::initializeThreading();
518
519 // We can't use destructors in the following code because it uses Windows
520 // Structured Exception Handling
521 int res = 0;
522 TRY
523 res = jscmain(argc, argv);
524 EXCEPT(res = 3)
525 return res;
526}
527
528static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
529{
530 const char* script;
531 String fileName;
532 Vector<char> scriptBuffer;
533
534 if (dump)
535 BytecodeGenerator::setDumpsGeneratedCode(true);
536
537 JSGlobalData& globalData = globalObject->globalData();
538
539#if ENABLE(SAMPLING_FLAGS)
540 SamplingFlags::start();
541#endif
542
543 bool success = true;
544 for (size_t i = 0; i < scripts.size(); i++) {
545 if (scripts[i].isFile) {
546 fileName = scripts[i].argument;
547 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
548 return false; // fail early so we can catch missing files
549 script = scriptBuffer.data();
550 } else {
551 script = scripts[i].argument;
552 fileName = "[Command Line]";
553 }
554
555 globalData.startSampling();
556
557 JSValue evaluationException;
558 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), &evaluationException);
559 success = success && !evaluationException;
560 if (dump && !evaluationException)
561 printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
562 if (evaluationException) {
563 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
564 Identifier stackID(globalObject->globalExec(), "stack");
565 JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID);
566 if (!stackValue.isUndefinedOrNull())
567 printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
568 }
569
570 globalData.stopSampling();
571 globalObject->globalExec()->clearException();
572 }
573
574#if ENABLE(SAMPLING_FLAGS)
575 SamplingFlags::stop();
576#endif
577#if ENABLE(SAMPLING_REGIONS)
578 SamplingRegion::dump();
579#endif
580 globalData.dumpSampleData(globalObject->globalExec());
581#if ENABLE(SAMPLING_COUNTERS)
582 AbstractSamplingCounter::dump();
583#endif
584#if ENABLE(REGEXP_TRACING)
585 globalData.dumpRegExpTrace();
586#endif
587 return success;
588}
589
590#define RUNNING_FROM_XCODE 0
591
592static void runInteractive(GlobalObject* globalObject)
593{
594 String interpreterName("Interpreter");
595
596 while (true) {
597#if HAVE(READLINE) && !RUNNING_FROM_XCODE
598 char* line = readline(interactivePrompt);
599 if (!line)
600 break;
601 if (line[0])
602 add_history(line);
603 JSValue evaluationException;
604 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, interpreterName), JSValue(), &evaluationException);
605 free(line);
606#else
607 printf("%s", interactivePrompt);
608 Vector<char, 256> line;
609 int c;
610 while ((c = getchar()) != EOF) {
611 // FIXME: Should we also break on \r?
612 if (c == '\n')
613 break;
614 line.append(c);
615 }
616 if (line.isEmpty())
617 break;
618 line.append('\0');
619
620 JSValue evaluationException;
621 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
622#endif
623 if (evaluationException)
624 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
625 else
626 printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
627
628 globalObject->globalExec()->clearException();
629 }
630 printf("\n");
631}
632
633static NO_RETURN void printUsageStatement(bool help = false)
634{
635 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
636 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
637 fprintf(stderr, " -e Evaluate argument as script code\n");
638 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
639 fprintf(stderr, " -h|--help Prints this help message\n");
640 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
641#if HAVE(SIGNAL_H)
642 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
643#endif
644 fprintf(stderr, " -x Output exit code before terminating\n");
645 fprintf(stderr, "\n");
646 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
647 fprintf(stderr, " --dumpOptions Dumps all JSC VM options before continuing\n");
648 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
649 fprintf(stderr, "\n");
650
651 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
652}
653
654void CommandLine::parseArguments(int argc, char** argv)
655{
656 int i = 1;
657 bool needToDumpOptions = false;
658 bool needToExit = false;
659
660 for (; i < argc; ++i) {
661 const char* arg = argv[i];
662 if (!strcmp(arg, "-f")) {
663 if (++i == argc)
664 printUsageStatement();
665 m_scripts.append(Script(true, argv[i]));
666 continue;
667 }
668 if (!strcmp(arg, "-e")) {
669 if (++i == argc)
670 printUsageStatement();
671 m_scripts.append(Script(false, argv[i]));
672 continue;
673 }
674 if (!strcmp(arg, "-i")) {
675 m_interactive = true;
676 continue;
677 }
678 if (!strcmp(arg, "-d")) {
679 m_dump = true;
680 continue;
681 }
682 if (!strcmp(arg, "-s")) {
683#if HAVE(SIGNAL_H)
684 signal(SIGILL, _exit);
685 signal(SIGFPE, _exit);
686 signal(SIGBUS, _exit);
687 signal(SIGSEGV, _exit);
688#endif
689 continue;
690 }
691 if (!strcmp(arg, "-x")) {
692 m_exitCode = true;
693 continue;
694 }
695 if (!strcmp(arg, "--")) {
696 ++i;
697 break;
698 }
699 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
700 printUsageStatement(true);
701
702 if (!strcmp(arg, "--options")) {
703 needToDumpOptions = true;
704 needToExit = true;
705 continue;
706 }
707 if (!strcmp(arg, "--dumpOptions")) {
708 needToDumpOptions = true;
709 continue;
710 }
711
712 // See if the -- option is a JSC VM option.
713 // NOTE: At this point, we know that the arg starts with "--". Skip it.
714 if (JSC::Options::setOption(&arg[2])) {
715 // The arg was recognized as a VM option and has been parsed.
716 continue; // Just continue with the next arg.
717 }
718
719 // This arg is not recognized by the VM nor by jsc. Pass it on to the
720 // script.
721 m_scripts.append(Script(true, argv[i]));
722 }
723
724 if (m_scripts.isEmpty())
725 m_interactive = true;
726
727 for (; i < argc; ++i)
728 m_arguments.append(argv[i]);
729
730 if (needToDumpOptions)
731 JSC::Options::dumpAllOptions(stderr);
732 if (needToExit)
733 exit(EXIT_SUCCESS);
734}
735
736int jscmain(int argc, char** argv)
737{
738 // Note that the options parsing can affect JSGlobalData creation, and thus
739 // comes first.
740 CommandLine options(argc, argv);
741 RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
742 JSLockHolder lock(globalData.get());
743 int result;
744
745 GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.m_arguments);
746 bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump);
747 if (options.m_interactive && success)
748 runInteractive(globalObject);
749
750 result = success ? 0 : 3;
751
752 if (options.m_exitCode)
753 printf("jsc exiting %d\n", result);
754
755 return result;
756}
757
758static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
759{
760 FILE* f = fopen(fileName.utf8().data(), "r");
761 if (!f) {
762 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
763 return false;
764 }
765
766 size_t bufferSize = 0;
767 size_t bufferCapacity = 1024;
768
769 buffer.resize(bufferCapacity);
770
771 while (!feof(f) && !ferror(f)) {
772 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
773 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
774 bufferCapacity *= 2;
775 buffer.resize(bufferCapacity);
776 }
777 }
778 fclose(f);
779 buffer[bufferSize] = '\0';
780
781 if (buffer[0] == '#' && buffer[1] == '!')
782 buffer[0] = buffer[1] = '/';
783
784 return true;
785}
Note: See TracBrowser for help on using the repository browser.