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

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

The JITThunks class should be in its own file, and doing so should not break the build
https://bugs.webkit.org/show_bug.cgi?id=105696

Source/JavaScriptCore:

Rubber stamped by Sam Weinig and Geoffrey Garen.

This patch was supposed to just move JITThunks into its own file. But then I
realized that there is a horrible circular dependency chain between JSCell,
JSGlobalData, CallFrame, and Weak, which only works because of magical include
order in JITStubs.h, and the fact that JSGlobalData.h includes JITStubs.h
before it includes JSCell or JSValue.

I first tried to just get JITThunks.h to just magically do the same pointless
includes that JITStubs.h had, but then I decided to actually fix the underflying
problem, which was that JSCell needed CallFrame, CallFrame needed JSGlobalData,
JSGlobalData needed JITThunks, JITThunks needed Weak, and Weak needed JSCell.
Now, all of JSCell's outgoing dependencies are placed in JSCellInlines.h. This
also gave me an opportunity to move JSValue inline methods from JSCell.h into
JSValueInlines.h. But to make this really work, I needed to remove includes of
*Inlines.h from other headers (CodeBlock.h for example included JSValueInlines.h,
which defeats the whole entire purpose of having an Inlines.h file), and I needed
to add includes of *Inlines.h into a bunch of .cpp files. I did this mostly by
having .cpp files include Operations.h. In future, if you're adding a .cpp file
to JSC, you'll almost certainly have to include Operations.h unless you enjoy
link errors.

  • API/JSBase.cpp:
  • API/JSCallbackConstructor.cpp:
  • API/JSCallbackFunction.cpp:
  • API/JSCallbackObject.cpp:
  • API/JSClassRef.cpp:
  • API/JSContextRef.cpp:
  • API/JSObjectRef.cpp:
  • API/JSScriptRef.cpp:
  • API/JSWeakObjectMapRefPrivate.cpp:
  • JSCTypedArrayStubs.h:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/ArrayAllocationProfile.cpp:
  • bytecode/CodeBlock.cpp:
  • bytecode/GetByIdStatus.cpp:
  • bytecode/LazyOperandValueProfile.cpp:
  • bytecode/ResolveGlobalStatus.cpp:
  • bytecode/SpeculatedType.cpp:
  • bytecode/UnlinkedCodeBlock.cpp:
  • bytecompiler/BytecodeGenerator.cpp:
  • debugger/Debugger.cpp:
  • debugger/DebuggerActivation.cpp:
  • debugger/DebuggerCallFrame.cpp:
  • dfg/DFGArgumentsSimplificationPhase.cpp:
  • dfg/DFGArrayMode.cpp:
  • dfg/DFGByteCodeParser.cpp:
  • dfg/DFGConstantFoldingPhase.cpp:
  • dfg/DFGDriver.cpp:
  • dfg/DFGFixupPhase.cpp:
  • dfg/DFGGraph.cpp:
  • dfg/DFGJITCompiler.cpp:
  • dfg/DFGOSREntry.cpp:
  • dfg/DFGOSRExitCompiler.cpp:
  • dfg/DFGOSRExitCompiler32_64.cpp:
  • dfg/DFGOSRExitCompiler64.cpp:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
(DFG):
(JSC::DFG::SpeculativeJIT::silentSavePlanForFPR):
(JSC::DFG::SpeculativeJIT::silentSpill):
(JSC::DFG::SpeculativeJIT::silentFill):

  • dfg/DFGSpeculativeJIT.h:

(SpeculativeJIT):

  • dfg/DFGSpeculativeJIT32_64.cpp:
  • dfg/DFGSpeculativeJIT64.cpp:
  • dfg/DFGStructureCheckHoistingPhase.cpp:
  • dfg/DFGVariableEventStream.cpp:
  • heap/CopiedBlock.h:
  • heap/CopiedSpace.cpp:
  • heap/HandleSet.cpp:
  • heap/Heap.cpp:
  • heap/HeapStatistics.cpp:
  • heap/SlotVisitor.cpp:
  • heap/WeakBlock.cpp:
  • interpreter/CallFrame.cpp:
  • interpreter/CallFrame.h:
  • jit/ClosureCallStubRoutine.cpp:
  • jit/GCAwareJITStubRoutine.cpp:
  • jit/JIT.cpp:
  • jit/JITArithmetic.cpp:
  • jit/JITArithmetic32_64.cpp:
  • jit/JITCall.cpp:
  • jit/JITCall32_64.cpp:
  • jit/JITCode.h:
  • jit/JITExceptions.cpp:
  • jit/JITStubs.h:
  • jit/JITThunks.h:
  • jsc.cpp:
  • llint/LLIntExceptions.cpp:
  • profiler/LegacyProfiler.cpp:
  • profiler/ProfileGenerator.cpp:
  • profiler/ProfilerBytecode.cpp:
  • profiler/ProfilerBytecodeSequence.cpp:
  • profiler/ProfilerBytecodes.cpp:
  • profiler/ProfilerCompilation.cpp:
  • profiler/ProfilerCompiledBytecode.cpp:
  • profiler/ProfilerDatabase.cpp:
  • profiler/ProfilerOSRExit.cpp:
  • profiler/ProfilerOSRExitSite.cpp:
  • profiler/ProfilerOrigin.cpp:
  • profiler/ProfilerOriginStack.cpp:
  • profiler/ProfilerProfiledBytecodes.cpp:
  • runtime/ArgList.cpp:
  • runtime/Arguments.cpp:
  • runtime/ArrayConstructor.cpp:
  • runtime/BooleanConstructor.cpp:
  • runtime/BooleanObject.cpp:
  • runtime/BooleanPrototype.cpp:
  • runtime/CallData.cpp:
  • runtime/CodeCache.cpp:
  • runtime/Completion.cpp:
  • runtime/ConstructData.cpp:
  • runtime/DateConstructor.cpp:
  • runtime/DateInstance.cpp:
  • runtime/DatePrototype.cpp:
  • runtime/Error.cpp:
  • runtime/ErrorConstructor.cpp:
  • runtime/ErrorInstance.cpp:
  • runtime/ErrorPrototype.cpp:
  • runtime/ExceptionHelpers.cpp:
  • runtime/Executable.cpp:
  • runtime/FunctionConstructor.cpp:
  • runtime/FunctionPrototype.cpp:
  • runtime/GetterSetter.cpp:
  • runtime/Identifier.cpp:
  • runtime/InternalFunction.cpp:
  • runtime/JSActivation.cpp:
  • runtime/JSBoundFunction.cpp:
  • runtime/JSCell.cpp:
  • runtime/JSCell.h:

(JSC):

  • runtime/JSCellInlines.h: Added.

(JSC):
(JSC::JSCell::JSCell):
(JSC::JSCell::finishCreation):
(JSC::JSCell::structure):
(JSC::JSCell::visitChildren):
(JSC::allocateCell):
(JSC::isZapped):
(JSC::JSCell::isObject):
(JSC::JSCell::isString):
(JSC::JSCell::isGetterSetter):
(JSC::JSCell::isProxy):
(JSC::JSCell::isAPIValueWrapper):
(JSC::JSCell::setStructure):
(JSC::JSCell::methodTable):
(JSC::JSCell::inherits):
(JSC::JSCell::fastGetOwnPropertySlot):
(JSC::JSCell::fastGetOwnProperty):
(JSC::JSCell::toBoolean):

  • runtime/JSDateMath.cpp:
  • runtime/JSFunction.cpp:
  • runtime/JSFunction.h:

(JSC):

  • runtime/JSGlobalData.h:

(JSC):
(JSGlobalData):

  • runtime/JSGlobalObject.cpp:
  • runtime/JSGlobalObjectFunctions.cpp:
  • runtime/JSLock.cpp:
  • runtime/JSNameScope.cpp:
  • runtime/JSNotAnObject.cpp:
  • runtime/JSONObject.cpp:
  • runtime/JSObject.h:

(JSC):

  • runtime/JSProxy.cpp:
  • runtime/JSScope.cpp:
  • runtime/JSSegmentedVariableObject.cpp:
  • runtime/JSString.h:

(JSC):

  • runtime/JSStringJoiner.cpp:
  • runtime/JSSymbolTableObject.cpp:
  • runtime/JSValue.cpp:
  • runtime/JSValueInlines.h:

(JSC::JSValue::toInt32):
(JSC::JSValue::toUInt32):
(JSC):
(JSC::JSValue::isUInt32):
(JSC::JSValue::asUInt32):
(JSC::JSValue::asNumber):
(JSC::jsNaN):
(JSC::JSValue::JSValue):
(JSC::JSValue::encode):
(JSC::JSValue::decode):
(JSC::JSValue::operator bool):
(JSC::JSValue::operator==):
(JSC::JSValue::operator!=):
(JSC::JSValue::isEmpty):
(JSC::JSValue::isUndefined):
(JSC::JSValue::isNull):
(JSC::JSValue::isUndefinedOrNull):
(JSC::JSValue::isCell):
(JSC::JSValue::isInt32):
(JSC::JSValue::isDouble):
(JSC::JSValue::isTrue):
(JSC::JSValue::isFalse):
(JSC::JSValue::tag):
(JSC::JSValue::payload):
(JSC::JSValue::asInt32):
(JSC::JSValue::asDouble):
(JSC::JSValue::asCell):
(JSC::JSValue::isNumber):
(JSC::JSValue::isBoolean):
(JSC::JSValue::asBoolean):
(JSC::reinterpretDoubleToInt64):
(JSC::reinterpretInt64ToDouble):
(JSC::JSValue::isString):
(JSC::JSValue::isPrimitive):
(JSC::JSValue::isGetterSetter):
(JSC::JSValue::isObject):
(JSC::JSValue::getString):
(JSC::::getString):
(JSC::JSValue::getObject):
(JSC::JSValue::getUInt32):
(JSC::JSValue::toPrimitive):
(JSC::JSValue::getPrimitiveNumber):
(JSC::JSValue::toNumber):
(JSC::JSValue::toObject):
(JSC::JSValue::isFunction):
(JSC::JSValue::inherits):
(JSC::JSValue::toThisObject):
(JSC::JSValue::get):
(JSC::JSValue::put):
(JSC::JSValue::putByIndex):
(JSC::JSValue::structureOrUndefined):
(JSC::JSValue::equal):
(JSC::JSValue::equalSlowCaseInline):
(JSC::JSValue::strictEqualSlowCaseInline):
(JSC::JSValue::strictEqual):

  • runtime/JSVariableObject.cpp:
  • runtime/JSWithScope.cpp:
  • runtime/JSWrapperObject.cpp:
  • runtime/LiteralParser.cpp:
  • runtime/Lookup.cpp:
  • runtime/NameConstructor.cpp:
  • runtime/NameInstance.cpp:
  • runtime/NamePrototype.cpp:
  • runtime/NativeErrorConstructor.cpp:
  • runtime/NativeErrorPrototype.cpp:
  • runtime/NumberConstructor.cpp:
  • runtime/NumberObject.cpp:
  • runtime/ObjectConstructor.cpp:
  • runtime/ObjectPrototype.cpp:
  • runtime/Operations.h:

(JSC):

  • runtime/PropertySlot.cpp:
  • runtime/RegExp.cpp:
  • runtime/RegExpCache.cpp:
  • runtime/RegExpCachedResult.cpp:
  • runtime/RegExpConstructor.cpp:
  • runtime/RegExpMatchesArray.cpp:
  • runtime/RegExpObject.cpp:
  • runtime/RegExpPrototype.cpp:
  • runtime/SmallStrings.cpp:
  • runtime/SparseArrayValueMap.cpp:
  • runtime/StrictEvalActivation.cpp:
  • runtime/StringConstructor.cpp:
  • runtime/StringObject.cpp:
  • runtime/StringRecursionChecker.cpp:
  • runtime/Structure.h:

(JSC):

  • runtime/StructureChain.cpp:
  • runtime/TimeoutChecker.cpp:
  • testRegExp.cpp:

Source/WebCore:

Rubber stamped by Sam Weinig.

All .cpp files that use the JSC internal API must now transitively include
Operations.h, and none of the major JSC headers do it for you to avoid
circularity. WebCore doesn't have to worry about circularity with JSC, so
this changes all of the major WebCore JSC base headers to include
Operations.h.

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