1 /* 2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 3 * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 4 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) 5 * Copyright (C) 2007 Maks Orlovich 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 * 22 */ 23 24 #ifndef Arguments_h 25 #define Arguments_h 26 27 #include "JSActivation.h" 28 #include "JSFunction.h" 29 #include "JSGlobalObject.h" 30 #include "Interpreter.h" 31 #include "ObjectConstructor.h" 32 #include "PrototypeFunction.h" 33 34 namespace JSC { 35 36 struct ArgumentsData : Noncopyable { 37 JSActivation* activation; 38 39 unsigned numParameters; 40 ptrdiff_t firstParameterIndex; 41 unsigned numArguments; 42 43 Register* registers; 44 OwnArrayPtr<Register> registerArray; 45 46 Register* extraArguments; 47 OwnArrayPtr<bool> deletedArguments; 48 Register extraArgumentsFixedBuffer[4]; 49 50 JSFunction* callee; 51 bool overrodeLength : 1; 52 bool overrodeCallee : 1; 53 }; 54 55 56 class Arguments : public JSObject { 57 public: 58 enum NoParametersType { NoParameters }; 59 60 Arguments(CallFrame*); 61 Arguments(CallFrame*, NoParametersType); 62 virtual ~Arguments(); 63 64 static const ClassInfo info; 65 66 virtual void markChildren(MarkStack&); 67 68 void fillArgList(ExecState*, MarkedArgumentBuffer&); 69 numProvidedArguments(ExecState * exec)70 uint32_t numProvidedArguments(ExecState* exec) const 71 { 72 if (UNLIKELY(d->overrodeLength)) 73 return get(exec, exec->propertyNames().length).toUInt32(exec); 74 return d->numArguments; 75 } 76 77 void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize); 78 void copyRegisters(); isTornOff()79 bool isTornOff() const { return d->registerArray; } setActivation(JSActivation * activation)80 void setActivation(JSActivation* activation) 81 { 82 d->activation = activation; 83 d->registers = &activation->registerAt(0); 84 } 85 createStructure(JSValue prototype)86 static PassRefPtr<Structure> createStructure(JSValue prototype) 87 { 88 return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 89 } 90 91 protected: 92 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; 93 94 private: 95 void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); 96 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); 97 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); 98 virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); 99 virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); 100 virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); 101 virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); 102 virtual bool deleteProperty(ExecState*, const Identifier& propertyName); 103 virtual bool deleteProperty(ExecState*, unsigned propertyName); 104 classInfo()105 virtual const ClassInfo* classInfo() const { return &info; } 106 107 void init(CallFrame*); 108 109 OwnPtr<ArgumentsData> d; 110 }; 111 112 Arguments* asArguments(JSValue); 113 asArguments(JSValue value)114 inline Arguments* asArguments(JSValue value) 115 { 116 ASSERT(asObject(value)->inherits(&Arguments::info)); 117 return static_cast<Arguments*>(asObject(value)); 118 } 119 getArgumentsData(CallFrame * callFrame,JSFunction * & function,ptrdiff_t & firstParameterIndex,Register * & argv,int & argc)120 ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc) 121 { 122 function = callFrame->callee(); 123 124 int numParameters = function->jsExecutable()->parameterCount(); 125 argc = callFrame->argumentCount(); 126 127 if (argc <= numParameters) 128 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters; 129 else 130 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc; 131 132 argc -= 1; // - 1 to skip "this" 133 firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters; 134 } 135 Arguments(CallFrame * callFrame)136 inline Arguments::Arguments(CallFrame* callFrame) 137 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) 138 , d(new ArgumentsData) 139 { 140 JSFunction* callee; 141 ptrdiff_t firstParameterIndex; 142 Register* argv; 143 int numArguments; 144 getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments); 145 146 d->numParameters = callee->jsExecutable()->parameterCount(); 147 d->firstParameterIndex = firstParameterIndex; 148 d->numArguments = numArguments; 149 150 d->activation = 0; 151 d->registers = callFrame->registers(); 152 153 Register* extraArguments; 154 if (d->numArguments <= d->numParameters) 155 extraArguments = 0; 156 else { 157 unsigned numExtraArguments = d->numArguments - d->numParameters; 158 if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register)) 159 extraArguments = new Register[numExtraArguments]; 160 else 161 extraArguments = d->extraArgumentsFixedBuffer; 162 for (unsigned i = 0; i < numExtraArguments; ++i) 163 extraArguments[i] = argv[d->numParameters + i]; 164 } 165 166 d->extraArguments = extraArguments; 167 168 d->callee = callee; 169 d->overrodeLength = false; 170 d->overrodeCallee = false; 171 } 172 Arguments(CallFrame * callFrame,NoParametersType)173 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) 174 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) 175 , d(new ArgumentsData) 176 { 177 ASSERT(!callFrame->callee()->jsExecutable()->parameterCount()); 178 179 unsigned numArguments = callFrame->argumentCount() - 1; 180 181 d->numParameters = 0; 182 d->numArguments = numArguments; 183 d->activation = 0; 184 185 Register* extraArguments; 186 if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register)) 187 extraArguments = new Register[numArguments]; 188 else 189 extraArguments = d->extraArgumentsFixedBuffer; 190 191 Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1; 192 for (unsigned i = 0; i < numArguments; ++i) 193 extraArguments[i] = argv[i]; 194 195 d->extraArguments = extraArguments; 196 197 d->callee = callFrame->callee(); 198 d->overrodeLength = false; 199 d->overrodeCallee = false; 200 } 201 copyRegisters()202 inline void Arguments::copyRegisters() 203 { 204 ASSERT(!isTornOff()); 205 206 if (!d->numParameters) 207 return; 208 209 int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize; 210 size_t registerArraySize = d->numParameters; 211 212 Register* registerArray = new Register[registerArraySize]; 213 memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register)); 214 d->registerArray.set(registerArray); 215 d->registers = registerArray + registerOffset; 216 } 217 218 // This JSActivation function is defined here so it can get at Arguments::setRegisters. copyRegisters(Arguments * arguments)219 inline void JSActivation::copyRegisters(Arguments* arguments) 220 { 221 ASSERT(!d()->registerArray); 222 223 size_t numParametersMinusThis = d()->functionExecutable->generatedBytecode().m_numParameters - 1; 224 size_t numVars = d()->functionExecutable->generatedBytecode().m_numVars; 225 size_t numLocals = numVars + numParametersMinusThis; 226 227 if (!numLocals) 228 return; 229 230 int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize; 231 size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize; 232 233 Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize); 234 setRegisters(registerArray + registerOffset, registerArray); 235 if (arguments && !arguments->isTornOff()) 236 static_cast<Arguments*>(arguments)->setActivation(this); 237 } 238 arguments()239 ALWAYS_INLINE Arguments* Register::arguments() const 240 { 241 if (jsValue() == JSValue()) 242 return 0; 243 return asArguments(jsValue()); 244 } 245 246 247 } // namespace JSC 248 249 #endif // Arguments_h 250