diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
| commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
| tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/runtime/Arguments.h | |
| parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
| download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz | |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/runtime/Arguments.h')
| -rw-r--r-- | Source/JavaScriptCore/runtime/Arguments.h | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h new file mode 100644 index 000000000..18f389171 --- /dev/null +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -0,0 +1,298 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) + * Copyright (C) 2007 Maks Orlovich + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Arguments_h +#define Arguments_h + +#include "CodeOrigin.h" +#include "JSActivation.h" +#include "JSDestructibleObject.h" +#include "JSFunction.h" +#include "JSGlobalObject.h" +#include "Interpreter.h" +#include "ObjectConstructor.h" +#include <wtf/StdLibExtras.h> + +namespace JSC { + +class Arguments : public JSDestructibleObject { + friend class JIT; + friend class JSArgumentsIterator; +public: + typedef JSDestructibleObject Base; + + static Arguments* create(VM& vm, CallFrame* callFrame) + { + Arguments* arguments = new (NotNull, allocateCell<Arguments>(vm.heap)) Arguments(callFrame); + arguments->finishCreation(callFrame); + return arguments; + } + + static Arguments* create(VM& vm, CallFrame* callFrame, InlineCallFrame* inlineCallFrame) + { + Arguments* arguments = new (NotNull, allocateCell<Arguments>(vm.heap)) Arguments(callFrame); + arguments->finishCreation(callFrame, inlineCallFrame); + return arguments; + } + + enum { MaxArguments = 0x10000 }; + +private: + enum NoParametersType { NoParameters }; + + Arguments(CallFrame*); + Arguments(CallFrame*, NoParametersType); + +public: + DECLARE_INFO; + + static void visitChildren(JSCell*, SlotVisitor&); + + void fillArgList(ExecState*, MarkedArgumentBuffer&); + + uint32_t length(ExecState* exec) const + { + if (UNLIKELY(m_overrodeLength)) + return get(exec, exec->propertyNames().length).toUInt32(exec); + return m_numArguments; + } + + void copyToArguments(ExecState*, CallFrame*, uint32_t length); + void tearOff(CallFrame*); + void tearOff(CallFrame*, InlineCallFrame*); + bool isTornOff() const { return m_registerArray.get(); } + void didTearOffActivation(ExecState*, JSActivation*); + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); + } + + static ptrdiff_t offsetOfNumArguments() { return OBJECT_OFFSETOF(Arguments, m_numArguments); } + static ptrdiff_t offsetOfRegisters() { return OBJECT_OFFSETOF(Arguments, m_registers); } + static ptrdiff_t offsetOfSlowArgumentData() { return OBJECT_OFFSETOF(Arguments, m_slowArgumentData); } + static ptrdiff_t offsetOfOverrodeLength() { return OBJECT_OFFSETOF(Arguments, m_overrodeLength); } + +protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + + void finishCreation(CallFrame*); + void finishCreation(CallFrame*, InlineCallFrame*); + +private: + static void destroy(JSCell*); + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); + static bool deleteProperty(JSCell*, ExecState*, PropertyName); + static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); + void createStrictModeCallerIfNecessary(ExecState*); + void createStrictModeCalleeIfNecessary(ExecState*); + + bool isArgument(size_t); + bool trySetArgument(VM&, size_t argument, JSValue); + JSValue tryGetArgument(size_t argument); + bool isDeletedArgument(size_t); + bool tryDeleteArgument(size_t); + WriteBarrierBase<Unknown>& argument(size_t); + void allocateSlowArguments(); + + void init(CallFrame*); + + WriteBarrier<JSActivation> m_activation; + + unsigned m_numArguments; + + // We make these full byte booleans to make them easy to test from the JIT, + // and because even if they were single-bit booleans we still wouldn't save + // any space. + bool m_overrodeLength; + bool m_overrodeCallee; + bool m_overrodeCaller; + bool m_isStrictMode; + + WriteBarrierBase<Unknown>* m_registers; + std::unique_ptr<WriteBarrier<Unknown>[]> m_registerArray; + + struct SlowArgumentData { + std::unique_ptr<SlowArgument[]> slowArguments; + int bytecodeToMachineCaptureOffset; // Add this if you have a bytecode offset into captured registers and you want the machine offset instead. Subtract if you want to do the opposite. + }; + + std::unique_ptr<SlowArgumentData> m_slowArgumentData; + + WriteBarrier<JSFunction> m_callee; +}; + +Arguments* asArguments(JSValue); + +inline Arguments* asArguments(JSValue value) +{ + ASSERT(asObject(value)->inherits(Arguments::info())); + return static_cast<Arguments*>(asObject(value)); +} + +inline Arguments::Arguments(CallFrame* callFrame) + : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) +{ +} + +inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) + : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) +{ +} + +inline void Arguments::allocateSlowArguments() +{ + if (m_slowArgumentData) + return; + m_slowArgumentData = std::make_unique<SlowArgumentData>(); + m_slowArgumentData->bytecodeToMachineCaptureOffset = 0; + m_slowArgumentData->slowArguments = std::make_unique<SlowArgument[]>(m_numArguments); + for (size_t i = 0; i < m_numArguments; ++i) { + ASSERT(m_slowArgumentData->slowArguments[i].status == SlowArgument::Normal); + m_slowArgumentData->slowArguments[i].index = CallFrame::argumentOffset(i); + } +} + +inline bool Arguments::tryDeleteArgument(size_t argument) +{ + if (!isArgument(argument)) + return false; + allocateSlowArguments(); + m_slowArgumentData->slowArguments[argument].status = SlowArgument::Deleted; + return true; +} + +inline bool Arguments::trySetArgument(VM& vm, size_t argument, JSValue value) +{ + if (!isArgument(argument)) + return false; + this->argument(argument).set(vm, this, value); + return true; +} + +inline JSValue Arguments::tryGetArgument(size_t argument) +{ + if (!isArgument(argument)) + return JSValue(); + return this->argument(argument).get(); +} + +inline bool Arguments::isDeletedArgument(size_t argument) +{ + if (argument >= m_numArguments) + return false; + if (!m_slowArgumentData) + return false; + if (m_slowArgumentData->slowArguments[argument].status != SlowArgument::Deleted) + return false; + return true; +} + +inline bool Arguments::isArgument(size_t argument) +{ + if (argument >= m_numArguments) + return false; + if (m_slowArgumentData && m_slowArgumentData->slowArguments[argument].status == SlowArgument::Deleted) + return false; + return true; +} + +inline WriteBarrierBase<Unknown>& Arguments::argument(size_t argument) +{ + ASSERT(isArgument(argument)); + if (!m_slowArgumentData) + return m_registers[CallFrame::argumentOffset(argument)]; + + int index = m_slowArgumentData->slowArguments[argument].index; + if (!m_activation || m_slowArgumentData->slowArguments[argument].status != SlowArgument::Captured) + return m_registers[index]; + + return m_activation->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset); +} + +inline void Arguments::finishCreation(CallFrame* callFrame) +{ + Base::finishCreation(callFrame->vm()); + ASSERT(inherits(info())); + + JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); + m_numArguments = callFrame->argumentCount(); + m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()); + m_callee.set(callFrame->vm(), this, callee); + m_overrodeLength = false; + m_overrodeCallee = false; + m_overrodeCaller = false; + m_isStrictMode = callFrame->codeBlock()->isStrictMode(); + + CodeBlock* codeBlock = callFrame->codeBlock(); + if (codeBlock->hasSlowArguments()) { + SymbolTable* symbolTable = codeBlock->symbolTable(); + const SlowArgument* slowArguments = codeBlock->machineSlowArguments(); + allocateSlowArguments(); + size_t count = std::min<unsigned>(m_numArguments, symbolTable->parameterCount()); + for (size_t i = 0; i < count; ++i) + m_slowArgumentData->slowArguments[i] = slowArguments[i]; + m_slowArgumentData->bytecodeToMachineCaptureOffset = + codeBlock->framePointerOffsetToGetActivationRegisters(); + } + + // The bytecode generator omits op_tear_off_activation in cases of no + // declared parameters, so we need to tear off immediately. + if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) + tearOff(callFrame); +} + +inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) +{ + Base::finishCreation(callFrame->vm()); + ASSERT(inherits(info())); + + JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame); + m_numArguments = inlineCallFrame->arguments.size() - 1; + + if (m_numArguments) { + int offsetForArgumentOne = inlineCallFrame->arguments[1].virtualRegister().offset(); + m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + offsetForArgumentOne - virtualRegisterForArgument(1).offset(); + } else + m_registers = 0; + m_callee.set(callFrame->vm(), this, callee); + m_overrodeLength = false; + m_overrodeCallee = false; + m_overrodeCaller = false; + m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode(); + ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)->slowArguments()); + + // The bytecode generator omits op_tear_off_activation in cases of no + // declared parameters, so we need to tear off immediately. + if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) + tearOff(callFrame, inlineCallFrame); +} + +} // namespace JSC + +#endif // Arguments_h |
