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

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

JavaScriptCore: Use ASCIILiteral where possible
https://bugs.webkit.org/show_bug.cgi?id=136179

Patch by Joseph Pecoraro <Joseph Pecoraro> on 2014-08-29
Reviewed by Michael Saboff.

Source/JavaScriptCore:

General string / character related changes. Use ASCIILiteral where
possible, jsNontrivialString where possible, and replace string
literals with character literals in some places.

No new tests, no changes to functionality.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::nameForRegister):

  • bytecompiler/NodesCodegen.cpp:

(JSC::PostfixNode::emitBytecode):
(JSC::PrefixNode::emitBytecode):
(JSC::AssignErrorNode::emitBytecode):
(JSC::ForInNode::emitMultiLoopBytecode):
(JSC::ForOfNode::emitBytecode):
(JSC::ObjectPatternNode::toString):

  • dfg/DFGFunctionWhitelist.cpp:

(JSC::DFG::FunctionWhitelist::contains):

  • dfg/DFGOperations.cpp:

(JSC::DFG::newTypedArrayWithSize):
(JSC::DFG::newTypedArrayWithOneArgument):

  • inspector/ConsoleMessage.cpp:

(Inspector::ConsoleMessage::addToFrontend):

  • inspector/InspectorBackendDispatcher.cpp:

(Inspector::InspectorBackendDispatcher::dispatch):

  • inspector/ScriptCallStackFactory.cpp:

(Inspector::extractSourceInformationFromException):

  • inspector/scripts/codegen/generator_templates.py:
  • interpreter/StackVisitor.cpp:

(JSC::StackVisitor::Frame::functionName):
(JSC::StackVisitor::Frame::sourceURL):

  • jit/JITOperations.cpp:
  • jsc.cpp:

(functionDescribeArray):
(functionRun):
(functionLoad):
(functionReadFile):
(functionCheckSyntax):
(functionTransferArrayBuffer):
(runWithScripts):
(runInteractive):

  • parser/Lexer.cpp:

(JSC::Lexer<T>::invalidCharacterMessage):
(JSC::Lexer<T>::parseString):
(JSC::Lexer<T>::parseStringSlowCase):
(JSC::Lexer<T>::lex):

  • profiler/Profile.cpp:

(JSC::Profile::Profile):

  • runtime/Arguments.cpp:

(JSC::argumentsFuncIterator):

  • runtime/ArrayPrototype.cpp:

(JSC::performSlowSort):
(JSC::arrayProtoFuncSort):

  • runtime/ExceptionHelpers.cpp:

(JSC::createError):
(JSC::createInvalidParameterError):
(JSC::createNotAConstructorError):
(JSC::createNotAFunctionError):
(JSC::createNotAnObjectError):
(JSC::createErrorForInvalidGlobalAssignment):

  • runtime/FunctionPrototype.cpp:

(JSC::insertSemicolonIfNeeded):

  • runtime/JSArray.cpp:

(JSC::JSArray::defineOwnProperty):
(JSC::JSArray::pop):
(JSC::JSArray::push):

  • runtime/JSArrayBufferConstructor.cpp:

(JSC::JSArrayBufferConstructor::finishCreation):

  • runtime/JSArrayBufferPrototype.cpp:

(JSC::arrayBufferProtoFuncSlice):

  • runtime/JSDataView.cpp:

(JSC::JSDataView::create):

  • runtime/JSDataViewPrototype.cpp:

(JSC::getData):
(JSC::setData):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::reset):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncProtoSetter):

  • runtime/JSPromiseConstructor.cpp:

(JSC::JSPromiseConstructor::finishCreation):

  • runtime/LiteralParser.cpp:

(JSC::LiteralParser<CharType>::Lexer::lex):
(JSC::LiteralParser<CharType>::Lexer::lexString):
(JSC::LiteralParser<CharType>::parse):

  • runtime/LiteralParser.h:

(JSC::LiteralParser::getErrorMessage):

  • runtime/TypeSet.cpp:

(JSC::TypeSet::seenTypes):
(JSC::TypeSet::displayName):
(JSC::TypeSet::allPrimitiveTypeNames):
(JSC::StructureShape::propertyHash):
(JSC::StructureShape::stringRepresentation):

Source/WTF:

  • wtf/text/WTFString.cpp:

(asciiDebug):

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