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

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

Never include *Inlines.h files in interface headers, and never include *Inlines.h when you could include Operations.h instead
https://bugs.webkit.org/show_bug.cgi?id=128505

Reviewed by Mark Hahnenberg and Oliver Hunt.

  • API/JSContextRef.cpp:
  • assembler/LinkBuffer.cpp:
  • bytecode/ArrayProfile.cpp:
  • bytecode/BytecodeBasicBlock.cpp:
  • bytecode/BytecodeLivenessAnalysisInlines.h:
  • bytecode/CallLinkInfo.cpp:
  • bytecode/CodeBlock.cpp:
  • bytecode/CodeBlock.h:
  • bytecode/CodeBlockJettisoningWatchpoint.cpp:
  • bytecode/ExecutionCounter.cpp:
  • bytecode/MethodOfGettingAValueProfile.cpp:
  • bytecode/PreciseJumpTargets.cpp:
  • bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp:
  • bytecode/SamplingTool.cpp:
  • bytecode/SpecialPointer.cpp:
  • bytecode/StructureStubClearingWatchpoint.cpp:
  • debugger/DebuggerCallFrame.cpp:
  • dfg/DFGAbstractHeap.cpp:
  • dfg/DFGAbstractValue.cpp:
  • dfg/DFGArgumentsSimplificationPhase.cpp:
  • dfg/DFGArithMode.cpp:
  • dfg/DFGArrayMode.cpp:
  • dfg/DFGAtTailAbstractState.cpp:
  • dfg/DFGAvailability.cpp:
  • dfg/DFGBackwardsPropagationPhase.cpp:
  • dfg/DFGBasicBlock.cpp:
  • dfg/DFGBinarySwitch.cpp:
  • dfg/DFGBlockInsertionSet.cpp:
  • dfg/DFGByteCodeParser.cpp:
  • dfg/DFGCFAPhase.cpp:
  • dfg/DFGCFGSimplificationPhase.cpp:
  • dfg/DFGCPSRethreadingPhase.cpp:
  • dfg/DFGCSEPhase.cpp:
  • dfg/DFGCapabilities.cpp:
  • dfg/DFGClobberSet.cpp:
  • dfg/DFGClobberize.cpp:
  • dfg/DFGCommon.cpp:
  • dfg/DFGCommonData.cpp:
  • dfg/DFGCompilationKey.cpp:
  • dfg/DFGCompilationMode.cpp:
  • dfg/DFGConstantFoldingPhase.cpp:
  • dfg/DFGCriticalEdgeBreakingPhase.cpp:
  • dfg/DFGDCEPhase.cpp:
  • dfg/DFGDesiredIdentifiers.cpp:
  • dfg/DFGDesiredStructureChains.cpp:
  • dfg/DFGDesiredTransitions.cpp:
  • dfg/DFGDesiredWatchpoints.cpp:
  • dfg/DFGDisassembler.cpp:
  • dfg/DFGDisassembler.h:
  • dfg/DFGDominators.cpp:
  • dfg/DFGEdge.cpp:
  • dfg/DFGFailedFinalizer.cpp:
  • dfg/DFGFinalizer.cpp:
  • dfg/DFGFixupPhase.cpp:
  • dfg/DFGFlushFormat.cpp:
  • dfg/DFGFlushLivenessAnalysisPhase.cpp:
  • dfg/DFGFlushedAt.cpp:
  • dfg/DFGGraph.cpp:
  • dfg/DFGInPlaceAbstractState.cpp:
  • dfg/DFGInvalidationPointInjectionPhase.cpp:
  • dfg/DFGJITCode.cpp:
  • dfg/DFGJITCompiler.cpp:
  • dfg/DFGJITCompiler.h:
  • dfg/DFGJITFinalizer.cpp:
  • dfg/DFGJumpReplacement.cpp:
  • dfg/DFGLICMPhase.cpp:
  • dfg/DFGLazyJSValue.cpp:
  • dfg/DFGLivenessAnalysisPhase.cpp:
  • dfg/DFGLongLivedState.cpp:
  • dfg/DFGLoopPreHeaderCreationPhase.cpp:
  • dfg/DFGMinifiedNode.cpp:
  • dfg/DFGNaturalLoops.cpp:
  • dfg/DFGNode.cpp:
  • dfg/DFGNodeFlags.cpp:
  • dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
  • dfg/DFGOSREntry.cpp:
  • dfg/DFGOSREntrypointCreationPhase.cpp:
  • dfg/DFGOSRExit.cpp:
  • dfg/DFGOSRExitBase.cpp:
  • dfg/DFGOSRExitCompiler.cpp:
  • dfg/DFGOSRExitCompiler32_64.cpp:
  • dfg/DFGOSRExitCompiler64.cpp:
  • dfg/DFGOSRExitCompilerCommon.cpp:
  • dfg/DFGOSRExitJumpPlaceholder.cpp:
  • dfg/DFGOSRExitPreparation.cpp:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPhase.cpp:
  • dfg/DFGPlan.cpp:
  • dfg/DFGPredictionInjectionPhase.cpp:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGResurrectionForValidationPhase.cpp:
  • dfg/DFGSSAConversionPhase.cpp:
  • dfg/DFGSSALoweringPhase.cpp:
  • dfg/DFGSpeculativeJIT.cpp:
  • dfg/DFGSpeculativeJIT32_64.cpp:
  • dfg/DFGSpeculativeJIT64.cpp:
  • dfg/DFGStackLayoutPhase.cpp:
  • dfg/DFGStoreBarrierElisionPhase.cpp:
  • dfg/DFGStrengthReductionPhase.cpp:
  • dfg/DFGThunks.cpp:
  • dfg/DFGTierUpCheckInjectionPhase.cpp:
  • dfg/DFGToFTLDeferredCompilationCallback.cpp:
  • dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp:
  • dfg/DFGTypeCheckHoistingPhase.cpp:
  • dfg/DFGUnificationPhase.cpp:
  • dfg/DFGUseKind.cpp:
  • dfg/DFGValidate.cpp:
  • dfg/DFGValueSource.cpp:
  • dfg/DFGVariableAccessDataDump.cpp:
  • dfg/DFGVariableEvent.cpp:
  • dfg/DFGVariableEventStream.cpp:
  • dfg/DFGVirtualRegisterAllocationPhase.cpp:
  • dfg/DFGWatchpointCollectionPhase.cpp:
  • dfg/DFGWorklist.cpp:
  • disassembler/Disassembler.cpp:
  • ftl/FTLLink.cpp:
  • ftl/FTLOSRExitCompiler.cpp:
  • ftl/FTLSlowPathCall.cpp:
  • ftl/FTLThunks.cpp:

(JSC::FTL::slowPathCallThunkGenerator):

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