From 6882a04fb36642862b11efe514251d32070c3d65 Mon Sep 17 00:00:00 2001 From: Konstantin Tokarev Date: Thu, 25 Aug 2016 19:20:41 +0300 Subject: Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443) Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev --- Source/JavaScriptCore/jsc.cpp | 1684 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 1478 insertions(+), 206 deletions(-) (limited to 'Source/JavaScriptCore/jsc.cpp') diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp index 4404faa9e..c672add34 100644 --- a/Source/JavaScriptCore/jsc.cpp +++ b/Source/JavaScriptCore/jsc.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2004-2008, 2012-2013, 2015 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,34 +22,53 @@ #include "config.h" -#include "APIShims.h" +#include "ArrayPrototype.h" #include "ButterflyInlines.h" #include "BytecodeGenerator.h" +#include "CodeBlock.h" #include "Completion.h" #include "CopiedSpaceInlines.h" +#include "DFGPlan.h" +#include "Disassembler.h" +#include "Exception.h" #include "ExceptionHelpers.h" #include "HeapStatistics.h" #include "InitializeThreading.h" #include "Interpreter.h" #include "JSArray.h" -#include "JSCTypedArrayStubs.h" +#include "JSArrayBuffer.h" +#include "JSCInlines.h" #include "JSFunction.h" +#include "JSInternalPromise.h" +#include "JSInternalPromiseDeferred.h" #include "JSLock.h" +#include "JSNativeStdFunction.h" +#include "JSONObject.h" #include "JSProxy.h" #include "JSString.h" -#include "Operations.h" +#include "JSWASMModule.h" +#include "ProfilerDatabase.h" +#include "SamplingProfiler.h" #include "SamplingTool.h" +#include "StackVisitor.h" +#include "StructureInlines.h" #include "StructureRareDataInlines.h" +#include "TestRunnerUtils.h" +#include "TypeProfilerLog.h" +#include "WASMModuleParser.h" #include #include #include #include +#include #include #include #include #include -#if !OS(WINDOWS) +#if OS(WINDOWS) +#include +#else #include #endif @@ -70,51 +89,485 @@ #include #endif -#if COMPILER(MSVC) && !OS(WINCE) +#if COMPILER(MSVC) #include #include #include #endif -#if PLATFORM(QT) -#include -#include -#endif - -#if PLATFORM(IOS) +#if PLATFORM(IOS) && CPU(ARM_THUMB2) #include #include #endif -#if PLATFORM(BLACKBERRY) -#include +#if PLATFORM(QT) +#include +#include #endif #if PLATFORM(EFL) #include #endif +#if !defined(PATH_MAX) +#define PATH_MAX 4096 +#endif + using namespace JSC; using namespace WTF; +namespace { + +NO_RETURN_WITH_VALUE static void jscExit(int status) +{ + waitForAsynchronousDisassembly(); + +#if ENABLE(DFG_JIT) + if (DFG::isCrashing()) { + for (;;) { +#if OS(WINDOWS) + Sleep(1000); +#else + pause(); +#endif + } + } +#endif // ENABLE(DFG_JIT) + exit(status); +} + +class Element; +class ElementHandleOwner; +class Masuqerader; +class Root; +class RuntimeArray; + +class Element : public JSNonFinalObject { +public: + Element(VM& vm, Structure* structure) + : Base(vm, structure) + { + } + + typedef JSNonFinalObject Base; + static const bool needsDestruction = false; + + Root* root() const { return m_root.get(); } + void setRoot(VM& vm, Root* root) { m_root.set(vm, this, 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); + element->finishCreation(vm, root); + return element; + } + + void finishCreation(VM&, Root*); + + static void visitChildren(JSCell* cell, SlotVisitor& visitor) + { + Element* thisObject = jsCast(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.append(&thisObject->m_root); + } + + 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: + WriteBarrier m_root; +}; + +class ElementHandleOwner : public WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(Handle handle, void*, SlotVisitor& visitor) override + { + 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 const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined; + + static Masquerader* create(VM& vm, JSGlobalObject* globalObject) + { + globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Masquerading object allocated"); + 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; +}; + +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 const unsigned StructureFlags = Base::StructureFlags | JSC::GetOwnPropertySlotIsImpure | JSC::OverridesGetOwnPropertySlot; + + 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 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 CustomGetter : public JSNonFinalObject { +public: + CustomGetter(VM& vm, Structure* structure) + : Base(vm, structure) + { + } + + DECLARE_INFO; + typedef JSNonFinalObject Base; + static const unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot; + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); + } + + static CustomGetter* create(VM& vm, Structure* structure) + { + CustomGetter* getter = new (NotNull, allocateCell(vm.heap, sizeof(CustomGetter))) CustomGetter(vm, structure); + getter->finishCreation(vm); + return getter; + } + + static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) + { + CustomGetter* thisObject = jsCast(object); + if (propertyName == PropertyName(Identifier::fromString(exec, "customGetter"))) { + slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->customGetter); + return true; + } + return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); + } + +private: + static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName) + { + CustomGetter* thisObject = jsDynamicCast(JSValue::decode(thisValue)); + if (!thisObject) + return throwVMTypeError(exec); + bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec); + if (shouldThrow) + return throwVMTypeError(exec); + return JSValue::encode(jsNumber(100)); + } +}; + +class RuntimeArray : public JSArray { +public: + typedef JSArray Base; + static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames; + + 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; + } + + Optional index = parseIndex(propertyName); + if (index && index.value() < thisObject->getLength()) { + slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()])); + 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(); + } + + 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)); + } + +private: + RuntimeArray(ExecState* exec, Structure* structure) + : JSArray(exec->vm(), structure, 0) + { + } + + static EncodedJSValue lengthGetter(ExecState* exec, 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, CREATE_METHOD_TABLE(Element) }; +const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, CREATE_METHOD_TABLE(Masquerader) }; +const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, CREATE_METHOD_TABLE(Root) }; +const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(ImpureGetter) }; +const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(CustomGetter) }; +const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) }; + +ElementHandleOwner* Element::handleOwner() +{ + static ElementHandleOwner* owner = 0; + if (!owner) + owner = new ElementHandleOwner(); + return owner; +} + +void Element::finishCreation(VM& vm, Root* root) +{ + Base::finishCreation(vm); + setRoot(vm, root); + 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 functionCreateCustomGetterObject(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 functionDescribe(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*); static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*); -static EncodedJSValue JSC_HOST_CALL functionGC(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 functionForceGCSlowPaths(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionAddressOf(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 functionNoDFG(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 EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*); static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*); +static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionAbort(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 functionIsInt32(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*); +#if ENABLE(WEBASSEMBLY) +static EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState*); +#endif +static EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*); +#if ENABLE(SAMPLING_PROFILER) +static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*); +#endif #if ENABLE(SAMPLING_FLAGS) static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*); @@ -135,20 +588,17 @@ struct Script { class CommandLine { public: CommandLine(int argc, char** argv) - : m_interactive(false) - , m_dump(false) - , m_exitCode(false) - , m_profile(false) { parseArguments(argc, argv); } - bool m_interactive; - bool m_dump; - bool m_exitCode; + bool m_interactive { false }; + bool m_dump { false }; + bool m_module { false }; + bool m_exitCode { false }; Vector