1 /* 2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 3 * Copyright (C) 2003, 2006, 2007, 2008 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 32 namespace JSC { 33 34 struct ArgumentsData : Noncopyable { 35 JSActivation* activation; 36 37 unsigned numParameters; 38 ptrdiff_t firstParameterIndex; 39 unsigned numArguments; 40 41 Register* registers; 42 OwnArrayPtr<Register> registerArray; 43 44 Register* extraArguments; 45 OwnArrayPtr<bool> deletedArguments; 46 Register extraArgumentsFixedBuffer[4]; 47 48 JSFunction* callee; 49 bool overrodeLength : 1; 50 bool overrodeCallee : 1; 51 }; 52 53 54 class Arguments : public JSObject { 55 public: 56 enum NoParametersType { NoParameters }; 57 58 Arguments(CallFrame*); 59 Arguments(CallFrame*, NoParametersType); 60 virtual ~Arguments(); 61 62 static const ClassInfo info; 63 64 virtual void mark(); 65 66 void fillArgList(ExecState*, ArgList&); 67 68 void copyRegisters(); isTornOff()69 bool isTornOff() const { return d->registerArray; } setActivation(JSActivation * activation)70 void setActivation(JSActivation* activation) 71 { 72 d->activation = activation; 73 d->registers = &activation->registerAt(0); 74 } 75 createStructure(JSValuePtr prototype)76 static PassRefPtr<Structure> createStructure(JSValuePtr prototype) 77 { 78 return Structure::create(prototype, TypeInfo(ObjectType)); 79 } 80 81 private: 82 void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); 83 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); 84 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); 85 virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); 86 virtual void put(ExecState*, unsigned propertyName, JSValuePtr, PutPropertySlot&); 87 virtual bool deleteProperty(ExecState*, const Identifier& propertyName); 88 virtual bool deleteProperty(ExecState*, unsigned propertyName); 89 classInfo()90 virtual const ClassInfo* classInfo() const { return &info; } 91 92 void init(CallFrame*); 93 94 OwnPtr<ArgumentsData> d; 95 }; 96 97 Arguments* asArguments(JSValuePtr); 98 asArguments(JSValuePtr value)99 inline Arguments* asArguments(JSValuePtr value) 100 { 101 ASSERT(asObject(value)->inherits(&Arguments::info)); 102 return static_cast<Arguments*>(asObject(value)); 103 } 104 getArgumentsData(CallFrame * callFrame,JSFunction * & function,ptrdiff_t & firstParameterIndex,Register * & argv,int & argc)105 ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc) 106 { 107 function = callFrame->callee(); 108 109 CodeBlock* codeBlock = &function->body()->generatedBytecode(); 110 int numParameters = codeBlock->m_numParameters; 111 argc = callFrame->argumentCount(); 112 113 if (argc <= numParameters) 114 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this" 115 else 116 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this" 117 118 argc -= 1; // - 1 to skip "this" 119 firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this" 120 } 121 Arguments(CallFrame * callFrame)122 inline Arguments::Arguments(CallFrame* callFrame) 123 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) 124 , d(new ArgumentsData) 125 { 126 JSFunction* callee; 127 ptrdiff_t firstParameterIndex; 128 Register* argv; 129 int numArguments; 130 getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments); 131 132 d->numParameters = callee->body()->parameterCount(); 133 d->firstParameterIndex = firstParameterIndex; 134 d->numArguments = numArguments; 135 136 d->activation = 0; 137 d->registers = callFrame->registers(); 138 139 Register* extraArguments; 140 if (d->numArguments <= d->numParameters) 141 extraArguments = 0; 142 else { 143 unsigned numExtraArguments = d->numArguments - d->numParameters; 144 if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register)) 145 extraArguments = new Register[numExtraArguments]; 146 else 147 extraArguments = d->extraArgumentsFixedBuffer; 148 for (unsigned i = 0; i < numExtraArguments; ++i) 149 extraArguments[i] = argv[d->numParameters + i]; 150 } 151 152 d->extraArguments = extraArguments; 153 154 d->callee = callee; 155 d->overrodeLength = false; 156 d->overrodeCallee = false; 157 } 158 Arguments(CallFrame * callFrame,NoParametersType)159 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) 160 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) 161 , d(new ArgumentsData) 162 { 163 ASSERT(!callFrame->callee()->body()->parameterCount()); 164 165 unsigned numArguments = callFrame->argumentCount() - 1; 166 167 d->numParameters = 0; 168 d->numArguments = numArguments; 169 d->activation = 0; 170 171 Register* extraArguments; 172 if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register)) 173 extraArguments = new Register[numArguments]; 174 else 175 extraArguments = d->extraArgumentsFixedBuffer; 176 177 Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1; 178 for (unsigned i = 0; i < numArguments; ++i) 179 extraArguments[i] = argv[i]; 180 181 d->extraArguments = extraArguments; 182 183 d->callee = callFrame->callee(); 184 d->overrodeLength = false; 185 d->overrodeCallee = false; 186 } 187 copyRegisters()188 inline void Arguments::copyRegisters() 189 { 190 ASSERT(!isTornOff()); 191 192 if (!d->numParameters) 193 return; 194 195 int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize; 196 size_t registerArraySize = d->numParameters; 197 198 Register* registerArray = new Register[registerArraySize]; 199 memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register)); 200 d->registerArray.set(registerArray); 201 d->registers = registerArray + registerOffset; 202 } 203 204 // This JSActivation function is defined here so it can get at Arguments::setRegisters. copyRegisters(Arguments * arguments)205 inline void JSActivation::copyRegisters(Arguments* arguments) 206 { 207 ASSERT(!d()->registerArray); 208 209 size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1; 210 size_t numVars = d()->functionBody->generatedBytecode().m_numVars; 211 size_t numLocals = numVars + numParametersMinusThis; 212 213 if (!numLocals) 214 return; 215 216 int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize; 217 size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize; 218 219 Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize); 220 setRegisters(registerArray + registerOffset, registerArray); 221 if (arguments && !arguments->isTornOff()) 222 static_cast<Arguments*>(arguments)->setActivation(this); 223 } 224 225 } // namespace JSC 226 227 #endif // Arguments_h 228