X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..ef99ff287df9046eb88937225e0554eabb00e33c:/jsc.cpp?ds=sidebyside diff --git a/jsc.cpp b/jsc.cpp index 85ed56b..6ecd4f2 100644 --- a/jsc.cpp +++ b/jsc.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012, 2013 Apple Inc. All rights reserved. * Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com) * * This library is free software; you can redistribute it and/or @@ -22,28 +22,49 @@ #include "config.h" +#include "ArrayPrototype.h" +#include "ButterflyInlines.h" #include "BytecodeGenerator.h" #include "Completion.h" -#include "CurrentTime.h" +#include "CopiedSpaceInlines.h" #include "ExceptionHelpers.h" +#include "HeapStatistics.h" #include "InitializeThreading.h" +#include "Interpreter.h" #include "JSArray.h" +#include "JSArrayBuffer.h" +#include "JSCInlines.h" #include "JSFunction.h" #include "JSLock.h" +#include "JSProxy.h" #include "JSString.h" +#include "ProfilerDatabase.h" #include "SamplingTool.h" +#include "StackVisitor.h" +#include "StructureInlines.h" +#include "StructureRareDataInlines.h" +#include "TestRunnerUtils.h" #include #include #include #include +#include +#include +#include +#include +#include #if !OS(WINDOWS) #include #endif #if HAVE(READLINE) +// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h +// We #define it to something else to avoid this conflict. +#define Function ReadlineFunction #include #include +#undef Function #endif #if HAVE(SYS_TIME_H) @@ -60,29 +81,379 @@ #include #endif -#if PLATFORM(QT) -#include -#include +#if PLATFORM(IOS) && CPU(ARM_THUMB2) +#include +#include +#endif + +#if PLATFORM(EFL) +#include #endif using namespace JSC; using namespace WTF; -static void cleanupGlobalData(JSGlobalData*); -static bool fillBufferWithContentsOfFile(const UString& fileName, Vector& buffer); +namespace { + +class Element; +class ElementHandleOwner; +class Masuqerader; +class Root; +class RuntimeArray; + +class Element : public JSNonFinalObject { +public: + Element(VM& vm, Structure* structure, Root* root) + : Base(vm, structure) + , m_root(root) + { + } + + typedef JSNonFinalObject Base; + static const bool needsDestruction = false; + + Root* root() const { return m_root; } + void setRoot(Root* root) { m_root = root; } + + static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root) + { + Structure* structure = createStructure(vm, globalObject, jsNull()); + Element* element = new (NotNull, allocateCell(vm.heap, sizeof(Element))) Element(vm, structure, root); + element->finishCreation(vm); + return element; + } + + void finishCreation(VM&); + + static ElementHandleOwner* handleOwner(); + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); + } + DECLARE_INFO; + +private: + Root* m_root; +}; + +class ElementHandleOwner : public WeakHandleOwner { +public: + virtual bool isReachableFromOpaqueRoots(Handle handle, void*, SlotVisitor& visitor) + { + Element* element = jsCast(handle.slot()->asCell()); + return visitor.containsOpaqueRoot(element->root()); + } +}; + +class Masquerader : public JSNonFinalObject { +public: + Masquerader(VM& vm, Structure* structure) + : Base(vm, structure) + { + } + + typedef JSNonFinalObject Base; + + static Masquerader* create(VM& vm, JSGlobalObject* globalObject) + { + globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(); + Structure* structure = createStructure(vm, globalObject, jsNull()); + Masquerader* result = new (NotNull, allocateCell(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure); + result->finishCreation(vm); + return result; + } + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); + } + + DECLARE_INFO; + +protected: + static const unsigned StructureFlags = JSC::MasqueradesAsUndefined | Base::StructureFlags; +}; + +class Root : public JSDestructibleObject { +public: + Root(VM& vm, Structure* structure) + : Base(vm, structure) + { + } + + Element* element() + { + return m_element.get(); + } + + void setElement(Element* element) + { + Weak newElement(element, Element::handleOwner()); + m_element.swap(newElement); + } + + static Root* create(VM& vm, JSGlobalObject* globalObject) + { + Structure* structure = createStructure(vm, globalObject, jsNull()); + Root* root = new (NotNull, allocateCell(vm.heap, sizeof(Root))) Root(vm, structure); + root->finishCreation(vm); + return root; + } + + typedef JSDestructibleObject Base; + + DECLARE_INFO; + static const bool needsDestruction = true; + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); + } + + static void visitChildren(JSCell* thisObject, SlotVisitor& visitor) + { + Base::visitChildren(thisObject, visitor); + visitor.addOpaqueRoot(thisObject); + } + +private: + Weak m_element; +}; + +class ImpureGetter : public JSNonFinalObject { +public: + ImpureGetter(VM& vm, Structure* structure) + : Base(vm, structure) + { + } + + DECLARE_INFO; + typedef JSNonFinalObject Base; + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); + } + + static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate) + { + ImpureGetter* getter = new (NotNull, allocateCell(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure); + getter->finishCreation(vm, delegate); + return getter; + } + + void finishCreation(VM& vm, JSObject* delegate) + { + Base::finishCreation(vm); + if (delegate) + m_delegate.set(vm, this, delegate); + } + + static const unsigned StructureFlags = JSC::HasImpureGetOwnPropertySlot | JSC::OverridesGetOwnPropertySlot | JSC::OverridesVisitChildren | Base::StructureFlags; + + static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot) + { + ImpureGetter* thisObject = jsCast(object); + + if (thisObject->m_delegate && thisObject->m_delegate->getPropertySlot(exec, name, slot)) + return true; + + return Base::getOwnPropertySlot(object, exec, name, slot); + } + + static void visitChildren(JSCell* cell, SlotVisitor& visitor) + { + Base::visitChildren(cell, visitor); + ImpureGetter* thisObject = jsCast(cell); + visitor.append(&thisObject->m_delegate); + } + + void setDelegate(VM& vm, JSObject* delegate) + { + m_delegate.set(vm, this, delegate); + } + +private: + WriteBarrier m_delegate; +}; + +class RuntimeArray : public JSArray { +public: + typedef JSArray Base; + + static RuntimeArray* create(ExecState* exec) + { + VM& vm = exec->vm(); + JSGlobalObject* globalObject = exec->lexicalGlobalObject(); + Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject)); + RuntimeArray* runtimeArray = new (NotNull, allocateCell(*exec->heap())) RuntimeArray(exec, structure); + runtimeArray->finishCreation(exec); + vm.heap.addFinalizer(runtimeArray, destroy); + return runtimeArray; + } + + ~RuntimeArray() { } + + static void destroy(JSCell* cell) + { + static_cast(cell)->RuntimeArray::~RuntimeArray(); + } + + static const bool needsDestruction = false; + + static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) + { + RuntimeArray* thisObject = jsCast(object); + if (propertyName == exec->propertyNames().length) { + slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter); + return true; + } + + unsigned index = propertyName.asIndex(); + if (index < thisObject->getLength()) { + ASSERT(index != PropertyName::NotAnIndex); + slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index])); + return true; + } + + return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); + } + + static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot) + { + RuntimeArray* thisObject = jsCast(object); + if (index < thisObject->getLength()) { + slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index])); + return true; + } + + return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot); + } + + static NO_RETURN_DUE_TO_CRASH void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&) + { + RELEASE_ASSERT_NOT_REACHED(); + } + + static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName) + { + RELEASE_ASSERT_NOT_REACHED(); +#if !COMPILER(CLANG) + return true; +#endif + } + + unsigned getLength() const { return m_vector.size(); } + + DECLARE_INFO; + + static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject) + { + return globalObject->arrayPrototype(); + } + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass); + } + +protected: + void finishCreation(ExecState* exec) + { + Base::finishCreation(exec->vm()); + ASSERT(inherits(info())); + + for (size_t i = 0; i < exec->argumentCount(); i++) + m_vector.append(exec->argument(i).toInt32(exec)); + } + + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSArray::StructureFlags; + +private: + RuntimeArray(ExecState* exec, Structure* structure) + : JSArray(exec->vm(), structure, 0) + { + } + + static EncodedJSValue lengthGetter(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName) + { + RuntimeArray* thisObject = jsDynamicCast(JSValue::decode(thisValue)); + if (!thisObject) + return throwVMTypeError(exec); + return JSValue::encode(jsNumber(thisObject->getLength())); + } + + Vector m_vector; +}; + +const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Element) }; +const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Masquerader) }; +const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Root) }; +const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ImpureGetter) }; +const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(RuntimeArray) }; + +ElementHandleOwner* Element::handleOwner() +{ + static ElementHandleOwner* owner = 0; + if (!owner) + owner = new ElementHandleOwner(); + return owner; +} + +void Element::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + m_root->setElement(this); +} + +} + +static bool fillBufferWithContentsOfFile(const String& fileName, Vector& buffer); + +static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*); + +static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*); static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*); static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*); -static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState*); #ifndef NDEBUG static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*); #endif static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*); static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*); static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*); static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*); static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*); static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*); #if ENABLE(SAMPLING_FLAGS) static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*); @@ -100,21 +471,29 @@ struct Script { } }; -struct Options { - Options() - : interactive(false) - , dump(false) +class CommandLine { +public: + CommandLine(int argc, char** argv) + : m_interactive(false) + , m_dump(false) + , m_exitCode(false) + , m_profile(false) { + parseArguments(argc, argv); } - bool interactive; - bool dump; - Vector