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

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

Rename HighFidelityTypeProfiling variables for more clarity
https://bugs.webkit.org/show_bug.cgi?id=135899

Patch by Saam Barati <[email protected]> on 2014-08-20
Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Many names that are used in the type profiling infrastructure
prefix themselves with "HighFidelity" or include the words "high"
and/or "fidelity" in some way. But the words "high" and "fidelity" don't
add anything descriptive to the names surrounding type profiling.
So this patch removes all uses of "HighFidelity" and its variants.

Most renamings change "HighFidelity*" to "TypeProfiler*" or simply
drop the prefix "HighFidelity" all together. Now, almost all names
in relation to type profiling contain in them "TypeProfiler" or
"TypeProfiling" or some combination of the words "type" and "profile".

This patch also changes how we check if type profiling is enabled:
We no longer call vm::isProfilingTypesWithHighFidelity. We now just
check that vm::typeProfiler is not null.

This patch also changes all calls to TypeProfilerLog::processLogEntries
to use ASCIILiteral to form WTFStrings instead of vanilla C string literals.

  • CMakeLists.txt:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):

  • bytecode/TypeLocation.h:
  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedCodeBlock::typeProfilerExpressionInfoForBytecodeOffset):
(JSC::UnlinkedCodeBlock::addTypeProfilerExpressionInfo):
(JSC::UnlinkedCodeBlock::highFidelityTypeProfileExpressionInfoForBytecodeOffset): Deleted.
(JSC::UnlinkedCodeBlock::addHighFidelityTypeProfileExpressionInfo): Deleted.

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedFunctionExecutable::typeProfilingStartOffset):
(JSC::UnlinkedFunctionExecutable::typeProfilingEndOffset):
(JSC::UnlinkedFunctionExecutable::highFidelityTypeProfilingStartOffset): Deleted.
(JSC::UnlinkedFunctionExecutable::highFidelityTypeProfilingEndOffset): Deleted.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitMove):
(JSC::BytecodeGenerator::emitTypeProfilerExpressionInfo):
(JSC::BytecodeGenerator::emitProfileType):
(JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo): Deleted.
(JSC::BytecodeGenerator::emitProfileTypesWithHighFidelity): Deleted.

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::isProfilingTypesWithHighFidelity): Deleted.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ThisNode::emitBytecode):
(JSC::ResolveNode::emitBytecode):
(JSC::BracketAccessorNode::emitBytecode):
(JSC::DotAccessorNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::FunctionCallBracketNode::emitBytecode):
(JSC::FunctionCallDotNode::emitBytecode):
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
(JSC::PostfixNode::emitResolve):
(JSC::PostfixNode::emitBracket):
(JSC::PostfixNode::emitDot):
(JSC::PrefixNode::emitResolve):
(JSC::PrefixNode::emitBracket):
(JSC::PrefixNode::emitDot):
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::AssignDotNode::emitBytecode):
(JSC::ReadModifyDotNode::emitBytecode):
(JSC::AssignBracketNode::emitBytecode):
(JSC::ReadModifyBracketNode::emitBytecode):
(JSC::ConstDeclNode::emitCodeSingle):
(JSC::EmptyVarExpression::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::FunctionBodyNode::emitBytecode):

  • heap/Heap.cpp:

(JSC::Heap::collect):

  • inspector/agents/InspectorRuntimeAgent.cpp:

(Inspector::InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets):
(Inspector::recompileAllJSFunctionsForTypeProfiling):
(Inspector::InspectorRuntimeAgent::willDestroyFrontendAndBackend):
(Inspector::InspectorRuntimeAgent::enableTypeProfiler):
(Inspector::InspectorRuntimeAgent::disableTypeProfiler):
(Inspector::InspectorRuntimeAgent::setTypeProfilerEnabledState):
(Inspector::InspectorRuntimeAgent::enableHighFidelityTypeProfiling): Deleted.
(Inspector::InspectorRuntimeAgent::disableHighFidelityTypeProfiling): Deleted.
(Inspector::InspectorRuntimeAgent::setHighFidelityTypeProfilingEnabledState): Deleted.

  • inspector/agents/InspectorRuntimeAgent.h:
  • inspector/protocol/Runtime.json:
  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompile):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_profile_type):
(JSC::JIT::emit_op_profile_types_with_high_fidelity): Deleted.

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_profile_type):
(JSC::JIT::emit_op_profile_types_with_high_fidelity): Deleted.

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

(functionDumpTypesForAllVariables):

  • llint/LLIntSlowPaths.cpp:
  • llint/LowLevelInterpreter.asm:
  • runtime/CodeCache.cpp:

(JSC::CodeCache::getGlobalCodeBlock):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:
  • runtime/Executable.cpp:

(JSC::ScriptExecutable::ScriptExecutable):
(JSC::ProgramExecutable::ProgramExecutable):
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::ProgramExecutable::initializeGlobalProperties):

  • runtime/Executable.h:

(JSC::ScriptExecutable::typeProfilingStartOffset):
(JSC::ScriptExecutable::typeProfilingEndOffset):
(JSC::ScriptExecutable::highFidelityTypeProfilingStartOffset): Deleted.
(JSC::ScriptExecutable::highFidelityTypeProfilingEndOffset): Deleted.

  • runtime/HighFidelityLog.cpp: Removed.
  • runtime/HighFidelityLog.h: Removed.
  • runtime/HighFidelityTypeProfiler.cpp: Removed.
  • runtime/HighFidelityTypeProfiler.h: Removed.
  • runtime/Options.h:
  • runtime/SymbolTable.cpp:

(JSC::SymbolTable::prepareForTypeProfiling):
(JSC::SymbolTable::uniqueIDForVariable):
(JSC::SymbolTable::uniqueIDForRegister):
(JSC::SymbolTable::prepareForHighFidelityTypeProfiling): Deleted.

  • runtime/SymbolTable.h:
  • runtime/TypeProfiler.cpp: Added.

(JSC::TypeProfiler::logTypesForTypeLocation):
(JSC::TypeProfiler::insertNewLocation):
(JSC::TypeProfiler::getTypesForVariableAtOffsetForInspector):
(JSC::descriptorMatchesTypeLocation):
(JSC::TypeProfiler::findLocation):

  • runtime/TypeProfiler.h: Added.

(JSC::QueryKey::QueryKey):
(JSC::QueryKey::isHashTableDeletedValue):
(JSC::QueryKey::operator==):
(JSC::QueryKey::hash):
(JSC::QueryKeyHash::hash):
(JSC::QueryKeyHash::equal):
(JSC::TypeProfiler::functionHasExecutedCache):
(JSC::TypeProfiler::typeLocationCache):

  • runtime/TypeProfilerLog.cpp: Added.

(JSC::TypeProfilerLog::initializeLog):
(JSC::TypeProfilerLog::~TypeProfilerLog):
(JSC::TypeProfilerLog::processLogEntries):

  • runtime/TypeProfilerLog.h: Added.

(JSC::TypeProfilerLog::LogEntry::structureIDOffset):
(JSC::TypeProfilerLog::LogEntry::valueOffset):
(JSC::TypeProfilerLog::LogEntry::locationOffset):
(JSC::TypeProfilerLog::TypeProfilerLog):
(JSC::TypeProfilerLog::recordTypeInformationForLocation):
(JSC::TypeProfilerLog::logEndPtr):
(JSC::TypeProfilerLog::logStartOffset):
(JSC::TypeProfilerLog::currentLogEntryOffset):

  • runtime/VM.cpp:

(JSC::VM::VM):
(JSC::VM::enableTypeProfiler):
(JSC::VM::disableTypeProfiler):
(JSC::VM::dumpTypeProfilerData):
(JSC::VM::enableHighFidelityTypeProfiling): Deleted.
(JSC::VM::disableHighFidelityTypeProfiling): Deleted.
(JSC::VM::dumpHighFidelityProfilingTypes): Deleted.

  • runtime/VM.h:

(JSC::VM::typeProfilerLog):
(JSC::VM::typeProfiler):
(JSC::VM::isProfilingTypesWithHighFidelity): Deleted.
(JSC::VM::highFidelityLog): Deleted.
(JSC::VM::highFidelityTypeProfiler): Deleted.

Source/WebInspectorUI:

Change a reference in a comment to a JavaScriptCore file to its
newly renamed variant.

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