JavaScriptCore/runtime/Arguments.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
       
     3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
       
     4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
       
     5  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
       
     6  *  Copyright (C) 2007 Maks Orlovich
       
     7  *
       
     8  *  This library is free software; you can redistribute it and/or
       
     9  *  modify it under the terms of the GNU Library General Public
       
    10  *  License as published by the Free Software Foundation; either
       
    11  *  version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  *  This library is distributed in the hope that it will be useful,
       
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16  *  Library General Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU Library General Public License
       
    19  *  along with this library; see the file COPYING.LIB.  If not, write to
       
    20  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    21  *  Boston, MA 02110-1301, USA.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "config.h"
       
    26 #include "Arguments.h"
       
    27 
       
    28 #include "JSActivation.h"
       
    29 #include "JSFunction.h"
       
    30 #include "JSGlobalObject.h"
       
    31 
       
    32 using namespace std;
       
    33 
       
    34 namespace JSC {
       
    35 
       
    36 ASSERT_CLASS_FITS_IN_CELL(Arguments);
       
    37 
       
    38 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
       
    39 
       
    40 Arguments::~Arguments()
       
    41 {
       
    42     if (d->extraArguments != d->extraArgumentsFixedBuffer)
       
    43         delete [] d->extraArguments;
       
    44 }
       
    45 
       
    46 void Arguments::markChildren(MarkStack& markStack)
       
    47 {
       
    48     JSObject::markChildren(markStack);
       
    49 
       
    50     if (d->registerArray)
       
    51         markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters);
       
    52 
       
    53     if (d->extraArguments) {
       
    54         unsigned numExtraArguments = d->numArguments - d->numParameters;
       
    55         markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments);
       
    56     }
       
    57 
       
    58     markStack.append(d->callee);
       
    59 
       
    60     if (d->activation)
       
    61         markStack.append(d->activation);
       
    62 }
       
    63 
       
    64 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
       
    65 {
       
    66     if (UNLIKELY(d->overrodeLength)) {
       
    67         unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize);
       
    68         for (unsigned i = 0; i < length; i++)
       
    69             buffer[i] = get(exec, i);
       
    70         return;
       
    71     }
       
    72 
       
    73     if (LIKELY(!d->deletedArguments)) {
       
    74         unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
       
    75         unsigned i = 0;
       
    76         for (; i < parametersLength; ++i)
       
    77             buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
       
    78         for (; i < d->numArguments; ++i)
       
    79             buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
       
    80         return;
       
    81     }
       
    82     
       
    83     unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
       
    84     unsigned i = 0;
       
    85     for (; i < parametersLength; ++i) {
       
    86         if (!d->deletedArguments[i])
       
    87             buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
       
    88         else
       
    89             buffer[i] = get(exec, i);
       
    90     }
       
    91     for (; i < d->numArguments; ++i) {
       
    92         if (!d->deletedArguments[i])
       
    93             buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
       
    94         else
       
    95             buffer[i] = get(exec, i);
       
    96     }
       
    97 }
       
    98 
       
    99 void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
       
   100 {
       
   101     if (UNLIKELY(d->overrodeLength)) {
       
   102         unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); 
       
   103         for (unsigned i = 0; i < length; i++) 
       
   104             args.append(get(exec, i)); 
       
   105         return;
       
   106     }
       
   107 
       
   108     if (LIKELY(!d->deletedArguments)) {
       
   109         if (LIKELY(!d->numParameters)) {
       
   110             args.initialize(d->extraArguments, d->numArguments);
       
   111             return;
       
   112         }
       
   113 
       
   114         if (d->numParameters == d->numArguments) {
       
   115             args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
       
   116             return;
       
   117         }
       
   118 
       
   119         unsigned parametersLength = min(d->numParameters, d->numArguments);
       
   120         unsigned i = 0;
       
   121         for (; i < parametersLength; ++i)
       
   122             args.append(d->registers[d->firstParameterIndex + i].jsValue());
       
   123         for (; i < d->numArguments; ++i)
       
   124             args.append(d->extraArguments[i - d->numParameters].jsValue());
       
   125         return;
       
   126     }
       
   127 
       
   128     unsigned parametersLength = min(d->numParameters, d->numArguments);
       
   129     unsigned i = 0;
       
   130     for (; i < parametersLength; ++i) {
       
   131         if (!d->deletedArguments[i])
       
   132             args.append(d->registers[d->firstParameterIndex + i].jsValue());
       
   133         else
       
   134             args.append(get(exec, i));
       
   135     }
       
   136     for (; i < d->numArguments; ++i) {
       
   137         if (!d->deletedArguments[i])
       
   138             args.append(d->extraArguments[i - d->numParameters].jsValue());
       
   139         else
       
   140             args.append(get(exec, i));
       
   141     }
       
   142 }
       
   143 
       
   144 bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
       
   145 {
       
   146     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
       
   147         if (i < d->numParameters) {
       
   148             slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
       
   149         } else
       
   150             slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
       
   151         return true;
       
   152     }
       
   153 
       
   154     return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
       
   155 }
       
   156 
       
   157 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
       
   158 {
       
   159     bool isArrayIndex;
       
   160     unsigned i = propertyName.toArrayIndex(&isArrayIndex);
       
   161     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
       
   162         if (i < d->numParameters) {
       
   163             slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
       
   164         } else
       
   165             slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
       
   166         return true;
       
   167     }
       
   168 
       
   169     if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
       
   170         slot.setValue(jsNumber(exec, d->numArguments));
       
   171         return true;
       
   172     }
       
   173 
       
   174     if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
       
   175         slot.setValue(d->callee);
       
   176         return true;
       
   177     }
       
   178 
       
   179     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
       
   180 }
       
   181 
       
   182 bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
       
   183 {
       
   184     bool isArrayIndex;
       
   185     unsigned i = propertyName.toArrayIndex(&isArrayIndex);
       
   186     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
       
   187         if (i < d->numParameters) {
       
   188             descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum);
       
   189         } else
       
   190             descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum);
       
   191         return true;
       
   192     }
       
   193     
       
   194     if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
       
   195         descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum);
       
   196         return true;
       
   197     }
       
   198     
       
   199     if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
       
   200         descriptor.setDescriptor(d->callee, DontEnum);
       
   201         return true;
       
   202     }
       
   203     
       
   204     return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
       
   205 }
       
   206 
       
   207 void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
       
   208 {
       
   209     if (mode == IncludeDontEnumProperties) {
       
   210         for (unsigned i = 0; i < d->numArguments; ++i) {
       
   211             if (!d->deletedArguments || !d->deletedArguments[i])
       
   212                 propertyNames.add(Identifier(exec, UString::from(i)));
       
   213         }
       
   214         propertyNames.add(exec->propertyNames().callee);
       
   215         propertyNames.add(exec->propertyNames().length);
       
   216     }
       
   217     JSObject::getOwnPropertyNames(exec, propertyNames, mode);
       
   218 }
       
   219 
       
   220 void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
       
   221 {
       
   222     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
       
   223         if (i < d->numParameters)
       
   224             d->registers[d->firstParameterIndex + i] = JSValue(value);
       
   225         else
       
   226             d->extraArguments[i - d->numParameters] = JSValue(value);
       
   227         return;
       
   228     }
       
   229 
       
   230     JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
       
   231 }
       
   232 
       
   233 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
       
   234 {
       
   235     bool isArrayIndex;
       
   236     unsigned i = propertyName.toArrayIndex(&isArrayIndex);
       
   237     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
       
   238         if (i < d->numParameters)
       
   239             d->registers[d->firstParameterIndex + i] = JSValue(value);
       
   240         else
       
   241             d->extraArguments[i - d->numParameters] = JSValue(value);
       
   242         return;
       
   243     }
       
   244 
       
   245     if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
       
   246         d->overrodeLength = true;
       
   247         putDirect(propertyName, value, DontEnum);
       
   248         return;
       
   249     }
       
   250 
       
   251     if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
       
   252         d->overrodeCallee = true;
       
   253         putDirect(propertyName, value, DontEnum);
       
   254         return;
       
   255     }
       
   256 
       
   257     JSObject::put(exec, propertyName, value, slot);
       
   258 }
       
   259 
       
   260 bool Arguments::deleteProperty(ExecState* exec, unsigned i) 
       
   261 {
       
   262     if (i < d->numArguments) {
       
   263         if (!d->deletedArguments) {
       
   264             d->deletedArguments.set(new bool[d->numArguments]);
       
   265             memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
       
   266         }
       
   267         if (!d->deletedArguments[i]) {
       
   268             d->deletedArguments[i] = true;
       
   269             return true;
       
   270         }
       
   271     }
       
   272 
       
   273     return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
       
   274 }
       
   275 
       
   276 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) 
       
   277 {
       
   278     bool isArrayIndex;
       
   279     unsigned i = propertyName.toArrayIndex(&isArrayIndex);
       
   280     if (isArrayIndex && i < d->numArguments) {
       
   281         if (!d->deletedArguments) {
       
   282             d->deletedArguments.set(new bool[d->numArguments]);
       
   283             memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
       
   284         }
       
   285         if (!d->deletedArguments[i]) {
       
   286             d->deletedArguments[i] = true;
       
   287             return true;
       
   288         }
       
   289     }
       
   290 
       
   291     if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
       
   292         d->overrodeLength = true;
       
   293         return true;
       
   294     }
       
   295 
       
   296     if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
       
   297         d->overrodeCallee = true;
       
   298         return true;
       
   299     }
       
   300 
       
   301     return JSObject::deleteProperty(exec, propertyName);
       
   302 }
       
   303 
       
   304 } // namespace JSC