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

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

Unreviewed, rolling out r178751.
https://bugs.webkit.org/show_bug.cgi?id=140694

Caused 32-bit JSC test failures (Requested by JoePeck on
#webkit).

Reverted changeset:

"put_by_val_direct need to check the property is index or not
for using putDirect / putDirectIndex"
https://bugs.webkit.org/show_bug.cgi?id=140426
http://trac.webkit.org/changeset/178751

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