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

Last change on this file since 187890 was 187890, checked in by Yusuke Suzuki, 10 years ago

[ES6] Support Module Syntax
https://bugs.webkit.org/show_bug.cgi?id=147422

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch introduces ES6 Modules syntax parsing part.
In this patch, ASTBuilder just produces the corresponding nodes to the ES6 Modules syntax,
and this patch does not include the code generator part.

Modules require 2 phase parsing. In the first pass, we just analyze the dependent modules
and do not execute the body or construct the AST. And after analyzing all the dependent
modules, we will parse the dependent modules next.
After all analyzing part is done, we will start the second pass. In the second pass, we
will parse the module, produce the AST, and execute the body.
If we don't do so, we need to create all the ASTs in the module's dependent graph at first
because the given module can be executed after the all dependent modules are executed. It
means that we need to hold so many parser arenas. To avoid this, the first pass only extracts
the dependent modules' information.

In this patch, we don't add this analyzing part yet. This patch only implements the second pass.
This patch aims at just implementing the syntax parsing functionality correctly.
After this patch is landed, we will create the ModuleDependencyAnalyzer that inherits SyntaxChecker
to collect the dependent modules fast[1].

To test the parsing, we added the "checkModuleSyntax" function into jsc shell.
By using this, we can parse the given string as the module.

[1]: https://bugs.webkit.org/show_bug.cgi?id=147353

  • bytecompiler/NodesCodegen.cpp:

(JSC::ModuleProgramNode::emitBytecode):
(JSC::ImportDeclarationNode::emitBytecode):
(JSC::ExportAllDeclarationNode::emitBytecode):
(JSC::ExportDefaultDeclarationNode::emitBytecode):
(JSC::ExportLocalDeclarationNode::emitBytecode):
(JSC::ExportNamedDeclarationNode::emitBytecode):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionCheckModuleSyntax):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createModuleSpecifier):
(JSC::ASTBuilder::createImportSpecifier):
(JSC::ASTBuilder::createImportSpecifierList):
(JSC::ASTBuilder::appendImportSpecifier):
(JSC::ASTBuilder::createImportDeclaration):
(JSC::ASTBuilder::createExportAllDeclaration):
(JSC::ASTBuilder::createExportDefaultDeclaration):
(JSC::ASTBuilder::createExportLocalDeclaration):
(JSC::ASTBuilder::createExportNamedDeclaration):
(JSC::ASTBuilder::createExportSpecifier):
(JSC::ASTBuilder::createExportSpecifierList):
(JSC::ASTBuilder::appendExportSpecifier):

  • parser/Keywords.table:
  • parser/NodeConstructors.h:

(JSC::ModuleSpecifierNode::ModuleSpecifierNode):
(JSC::ImportSpecifierNode::ImportSpecifierNode):
(JSC::ImportDeclarationNode::ImportDeclarationNode):
(JSC::ExportAllDeclarationNode::ExportAllDeclarationNode):
(JSC::ExportDefaultDeclarationNode::ExportDefaultDeclarationNode):
(JSC::ExportLocalDeclarationNode::ExportLocalDeclarationNode):
(JSC::ExportNamedDeclarationNode::ExportNamedDeclarationNode):
(JSC::ExportSpecifierNode::ExportSpecifierNode):

  • parser/Nodes.cpp:

(JSC::ModuleProgramNode::ModuleProgramNode):

  • parser/Nodes.h:

(JSC::ModuleProgramNode::startColumn):
(JSC::ModuleProgramNode::endColumn):
(JSC::ModuleSpecifierNode::moduleName):
(JSC::ImportSpecifierNode::importedName):
(JSC::ImportSpecifierNode::localName):
(JSC::ImportSpecifierListNode::specifiers):
(JSC::ImportSpecifierListNode::append):
(JSC::ImportDeclarationNode::specifierList):
(JSC::ImportDeclarationNode::moduleSpecifier):
(JSC::ExportAllDeclarationNode::moduleSpecifier):
(JSC::ExportDefaultDeclarationNode::declaration):
(JSC::ExportLocalDeclarationNode::declaration):
(JSC::ExportSpecifierNode::exportedName):
(JSC::ExportSpecifierNode::localName):
(JSC::ExportSpecifierListNode::specifiers):
(JSC::ExportSpecifierListNode::append):
(JSC::ExportNamedDeclarationNode::specifierList):
(JSC::ExportNamedDeclarationNode::moduleSpecifier):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseModuleSourceElements):
(JSC::Parser<LexerType>::parseVariableDeclaration):
(JSC::Parser<LexerType>::parseVariableDeclarationList):
(JSC::Parser<LexerType>::createBindingPattern):
(JSC::Parser<LexerType>::tryParseDestructuringPatternExpression):
(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseForStatement):
(JSC::Parser<LexerType>::parseFormalParameters):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClassDeclaration):
(JSC::Parser<LexerType>::parseModuleSpecifier):
(JSC::Parser<LexerType>::parseImportClauseItem):
(JSC::Parser<LexerType>::parseImportDeclaration):
(JSC::Parser<LexerType>::parseExportSpecifier):
(JSC::Parser<LexerType>::parseExportDeclaration):
(JSC::Parser<LexerType>::parseMemberExpression):

  • parser/Parser.h:

(JSC::isIdentifierOrKeyword):
(JSC::ModuleScopeData::create):
(JSC::ModuleScopeData::exportedBindings):
(JSC::ModuleScopeData::exportName):
(JSC::ModuleScopeData::exportBinding):
(JSC::Scope::Scope):
(JSC::Scope::setIsModule):
(JSC::Scope::moduleScopeData):
(JSC::Parser::matchContextualKeyword):
(JSC::Parser::matchIdentifierOrKeyword):
(JSC::Parser::isofToken): Deleted.

  • parser/ParserModes.h:
  • parser/ParserTokens.h:
  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createModuleSpecifier):
(JSC::SyntaxChecker::createImportSpecifier):
(JSC::SyntaxChecker::createImportSpecifierList):
(JSC::SyntaxChecker::appendImportSpecifier):
(JSC::SyntaxChecker::createImportDeclaration):
(JSC::SyntaxChecker::createExportAllDeclaration):
(JSC::SyntaxChecker::createExportDefaultDeclaration):
(JSC::SyntaxChecker::createExportLocalDeclaration):
(JSC::SyntaxChecker::createExportNamedDeclaration):
(JSC::SyntaxChecker::createExportSpecifier):
(JSC::SyntaxChecker::createExportSpecifierList):
(JSC::SyntaxChecker::appendExportSpecifier):

  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers):

  • runtime/CommonIdentifiers.h:
  • runtime/Completion.cpp:

(JSC::checkModuleSyntax):

  • runtime/Completion.h:
  • tests/stress/modules-syntax-error-with-names.js: Added.

(shouldThrow):

  • tests/stress/modules-syntax-error.js: Added.

(shouldThrow):
(checkModuleSyntaxError.checkModuleSyntaxError.checkModuleSyntaxError):

  • tests/stress/modules-syntax.js: Added.

(prototype.checkModuleSyntax):
(checkModuleSyntax):

  • tests/stress/tagged-templates-syntax.js:

LayoutTests:

'export' and 'import' are changed from FutureReservedWord to Keyword in ES6.
http://www.ecma-international.org/ecma-262/6.0/#sec-keywords
And restrict 'super' use under the Script / Module contexts.

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