Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "config.h"
     30 #include "JSActivation.h"
     31 
     32 #include "Arguments.h"
     33 #include "Interpreter.h"
     34 #include "JSFunction.h"
     35 
     36 namespace JSC {
     37 
     38 ASSERT_CLASS_FITS_IN_CELL(JSActivation);
     39 
     40 const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
     41 
     42 JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable)
     43     : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers()))
     44 {
     45 }
     46 
     47 JSActivation::~JSActivation()
     48 {
     49     delete d();
     50 }
     51 
     52 void JSActivation::markChildren(MarkStack& markStack)
     53 {
     54     Base::markChildren(markStack);
     55 
     56     Register* registerArray = d()->registerArray.get();
     57     if (!registerArray)
     58         return;
     59 
     60     size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
     61 
     62     size_t count = numParametersMinusThis;
     63     markStack.appendValues(registerArray, count);
     64 
     65     size_t numVars = d()->functionExecutable->variableCount();
     66 
     67     // Skip the call frame, which sits between the parameters and vars.
     68     markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
     69 }
     70 
     71 bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
     72 {
     73     if (symbolTableGet(propertyName, slot))
     74         return true;
     75 
     76     if (JSValue* location = getDirectLocation(propertyName)) {
     77         slot.setValueSlot(location);
     78         return true;
     79     }
     80 
     81     // Only return the built-in arguments object if it wasn't overridden above.
     82     if (propertyName == exec->propertyNames().arguments) {
     83         slot.setCustom(this, getArgumentsGetter());
     84         return true;
     85     }
     86 
     87     // We don't call through to JSObject because there's no way to give an
     88     // activation object getter properties or a prototype.
     89     ASSERT(!hasGetterSetterProperties());
     90     ASSERT(prototype().isNull());
     91     return false;
     92 }
     93 
     94 void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
     95 {
     96     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     97 
     98     if (symbolTablePut(propertyName, value))
     99         return;
    100 
    101     // We don't call through to JSObject because __proto__ and getter/setter
    102     // properties are non-standard extensions that other implementations do not
    103     // expose in the activation object.
    104     ASSERT(!hasGetterSetterProperties());
    105     putDirect(propertyName, value, 0, true, slot);
    106 }
    107 
    108 // FIXME: Make this function honor ReadOnly (const) and DontEnum
    109 void JSActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
    110 {
    111     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
    112 
    113     if (symbolTablePutWithAttributes(propertyName, value, attributes))
    114         return;
    115 
    116     // We don't call through to JSObject because __proto__ and getter/setter
    117     // properties are non-standard extensions that other implementations do not
    118     // expose in the activation object.
    119     ASSERT(!hasGetterSetterProperties());
    120     PutPropertySlot slot;
    121     JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot);
    122 }
    123 
    124 bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
    125 {
    126     if (propertyName == exec->propertyNames().arguments)
    127         return false;
    128 
    129     return Base::deleteProperty(exec, propertyName);
    130 }
    131 
    132 JSObject* JSActivation::toThisObject(ExecState* exec) const
    133 {
    134     return exec->globalThisValue();
    135 }
    136 
    137 bool JSActivation::isDynamicScope() const
    138 {
    139     return d()->functionExecutable->usesEval();
    140 }
    141 
    142 JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
    143 {
    144     JSActivation* activation = asActivation(slot.slotBase());
    145 
    146     if (activation->d()->functionExecutable->usesArguments()) {
    147         PropertySlot slot;
    148         activation->symbolTableGet(exec->propertyNames().arguments, slot);
    149         return slot.getValue(exec, exec->propertyNames().arguments);
    150     }
    151 
    152     CallFrame* callFrame = CallFrame::create(activation->d()->registers);
    153     Arguments* arguments = callFrame->optionalCalleeArguments();
    154     if (!arguments) {
    155         arguments = new (callFrame) Arguments(callFrame);
    156         arguments->copyRegisters();
    157         callFrame->setCalleeArguments(arguments);
    158     }
    159     ASSERT(arguments->inherits(&Arguments::info));
    160 
    161     return arguments;
    162 }
    163 
    164 // These two functions serve the purpose of isolating the common case from a
    165 // PIC branch.
    166 
    167 PropertySlot::GetValueFunc JSActivation::getArgumentsGetter()
    168 {
    169     return argumentsGetter;
    170 }
    171 
    172 } // namespace JSC
    173