Ignore:
Timestamp:
Jul 5, 2008, 4:19:36 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2008-07-05 Sam Weinig <[email protected]>

Rubber-stamped by Cameron Zwarich.

Split Arguments, IndexToNameMap, PrototypeFunction, GlobalEvalFunction and
the functions on the global object out of JSFunction.h/cpp.

  • GNUmakefile.am:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • VM/Machine.cpp:
  • kjs/AllInOneFile.cpp:
  • kjs/Arguments.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
  • kjs/Arguments.h: Copied from JavaScriptCore/kjs/JSFunction.h.
  • kjs/GlobalEvalFunction.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
  • kjs/GlobalEvalFunction.h: Copied from JavaScriptCore/kjs/JSFunction.h.
  • kjs/IndexToNameMap.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
  • kjs/IndexToNameMap.h: Copied from JavaScriptCore/kjs/JSFunction.h.
  • kjs/JSActivation.cpp:
  • kjs/JSFunction.cpp:
  • kjs/JSFunction.h:
  • kjs/JSGlobalObject.cpp:
  • kjs/JSGlobalObjectFunctions.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
  • kjs/JSGlobalObjectFunctions.h: Copied from JavaScriptCore/kjs/JSFunction.h. The functions on the global object should be in JSGlobalObject.cpp, but putting them there was a 0.5% regression.
  • kjs/PrototypeFunction.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
  • kjs/PrototypeFunction.h: Copied from JavaScriptCore/kjs/JSFunction.h.
  • kjs/Shell.cpp:
  • kjs/lexer.cpp:
  • kjs/ustring.cpp:

WebCore:

2008-07-05 Sam Weinig <[email protected]>

Rubber-stamped by Cameron Zwarich.

Split Arguments, IndexToNameMap, PrototypeFunction, GlobalEvalFunction and
the functions on the global object out of JSFunction.h/cpp.

  • ForwardingHeaders/kjs/PrototypeFunction.h: Added.
  • bindings/js/JSDOMBinding.cpp:
File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/JSGlobalObjectFunctions.cpp

    r35006 r35016  
    1 // -*- c-basic-offset: 2 -*-
    21/*
    32 *  Copyright (C) 1999-2002 Harri Porten ([email protected])
     
    2524
    2625#include "config.h"
    27 #include "JSFunction.h"
     26#include "JSGlobalObjectFunctions.h"
    2827
    2928#include "ExecState.h"
    30 #include "FunctionPrototype.h"
    31 #include "JSActivation.h"
     29#include "GlobalEvalFunction.h"
    3230#include "JSGlobalObject.h"
    3331#include "JSString.h"
    3432#include "Machine.h"
    35 #include "ObjectPrototype.h"
    3633#include "Parser.h"
    37 #include "PropertyNameArray.h"
    38 #include "ScopeChainMark.h"
    39 #include "debugger.h"
    4034#include "dtoa.h"
    4135#include "lexer.h"
    4236#include "nodes.h"
    43 #include "operations.h"
    4437#include <errno.h>
    45 #include <profiler/Profiler.h>
    4638#include <stdio.h>
    4739#include <stdlib.h>
     
    5648
    5749namespace KJS {
    58 
    59 // ----------------------------- JSFunction ----------------------------------
    60 
    61 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
    62 
    63 JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)
    64   : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)
    65   , body(b)
    66   , _scope(scopeChain)
    67 {
    68 }
    69 
    70 void JSFunction::mark()
    71 {
    72     InternalFunction::mark();
    73     body->mark();
    74     _scope.mark();
    75 }
    76 
    77 CallType JSFunction::getCallData(CallData& callData)
    78 {
    79     callData.js.functionBody = body.get();
    80     callData.js.scopeChain = _scope.node();
    81     return CallTypeJS;
    82 }
    83 
    84 JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)
    85 {
    86     return exec->machine()->execute(body.get(), exec, this, thisValue->toThisObject(exec), args, _scope.node(), exec->exceptionSlot());
    87 }
    88 
    89 JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
    90 {
    91     JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());
    92     return exec->machine()->retrieveArguments(exec, thisObj);
    93 }
    94 
    95 JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
    96 {
    97     JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());
    98     return exec->machine()->retrieveCaller(exec, thisObj);
    99 }
    100 
    101 JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
    102 {
    103     JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());
    104     return jsNumber(exec, thisObj->body->parameters().size());
    105 }
    106 
    107 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    108 {
    109     if (propertyName == exec->propertyNames().arguments) {
    110         slot.setCustom(this, argumentsGetter);
    111         return true;
    112     }
    113 
    114     if (propertyName == exec->propertyNames().length) {
    115         slot.setCustom(this, lengthGetter);
    116         return true;
    117     }
    118 
    119     if (propertyName == exec->propertyNames().caller) {
    120         slot.setCustom(this, callerGetter);
    121         return true;
    122     }
    123 
    124     return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);
    125 }
    126 
    127 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
    128 {
    129     if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
    130         return;
    131     InternalFunction::put(exec, propertyName, value);
    132 }
    133 
    134 bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)
    135 {
    136     if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
    137         return false;
    138     return InternalFunction::deleteProperty(exec, propertyName);
    139 }
    140 
    141 /* Returns the parameter name corresponding to the given index. eg:
    142  * function f1(x, y, z): getParameterName(0) --> x
    143  *
    144  * If a name appears more than once, only the last index at which
    145  * it appears associates with it. eg:
    146  * function f2(x, x): getParameterName(0) --> null
    147  */
    148 const Identifier& JSFunction::getParameterName(int index)
    149 {
    150     Vector<Identifier>& parameters = body->parameters();
    151 
    152     if (static_cast<size_t>(index) >= body->parameters().size())
    153         return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;
    154  
    155     const Identifier& name = parameters[index];
    156 
    157     // Are there any subsequent parameters with the same name?
    158     size_t size = parameters.size();
    159     for (size_t i = index + 1; i < size; ++i)
    160         if (parameters[i] == name)
    161             return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;
    162 
    163     return name;
    164 }
    165 
    166 // ECMA 13.2.2 [[Construct]]
    167 ConstructType JSFunction::getConstructData(ConstructData& constructData)
    168 {
    169     constructData.js.functionBody = body.get();
    170     constructData.js.scopeChain = _scope.node();
    171     return ConstructTypeJS;
    172 }
    173 
    174 JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
    175 {
    176     JSObject* proto;
    177     JSValue* p = get(exec, exec->propertyNames().prototype);
    178     if (p->isObject())
    179         proto = static_cast<JSObject*>(p);
    180     else
    181         proto = exec->lexicalGlobalObject()->objectPrototype();
    182 
    183     JSObject* thisObj = new (exec) JSObject(proto);
    184 
    185     JSValue* result = exec->machine()->execute(body.get(), exec, this, thisObj, args, _scope.node(), exec->exceptionSlot());
    186     if (exec->hadException() || !result->isObject())
    187         return thisObj;
    188     return static_cast<JSObject*>(result);
    189 }
    190 
    191 // ------------------------------ IndexToNameMap ---------------------------------
    192 
    193 // We map indexes in the arguments array to their corresponding argument names.
    194 // Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").
    195 
    196 // Once we have an argument name, we can get and set the argument's value in the
    197 // activation object.
    198 
    199 // We use Identifier::null to indicate that a given argument's value
    200 // isn't stored in the activation object.
    201 
    202 IndexToNameMap::IndexToNameMap(JSFunction* func, const ArgList& args)
    203 {
    204   _map = new Identifier[args.size()];
    205   this->size = args.size();
    206  
    207   unsigned i = 0;
    208   ArgList::const_iterator end = args.end();
    209   for (ArgList::const_iterator it = args.begin(); it != end; ++i, ++it)
    210     _map[i] = func->getParameterName(i); // null if there is no corresponding parameter
    211 }
    212 
    213 IndexToNameMap::~IndexToNameMap()
    214 {
    215   delete [] _map;
    216 }
    217 
    218 bool IndexToNameMap::isMapped(const Identifier& index) const
    219 {
    220   bool indexIsNumber;
    221   unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);
    222  
    223   if (!indexIsNumber)
    224     return false;
    225  
    226   if (indexAsNumber >= size)
    227     return false;
    228 
    229   if (_map[indexAsNumber].isNull())
    230     return false;
    231  
    232   return true;
    233 }
    234 
    235 void IndexToNameMap::unMap(ExecState* exec, const Identifier& index)
    236 {
    237   bool indexIsNumber;
    238   unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);
    239 
    240   ASSERT(indexIsNumber && indexAsNumber < size);
    241  
    242   _map[indexAsNumber] = exec->propertyNames().nullIdentifier;
    243 }
    244 
    245 Identifier& IndexToNameMap::operator[](const Identifier& index)
    246 {
    247   bool indexIsNumber;
    248   unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);
    249 
    250   ASSERT(indexIsNumber && indexAsNumber < size);
    251  
    252   return _map[indexAsNumber];
    253 }
    254 
    255 // ------------------------------ Arguments ---------------------------------
    256 
    257 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
    258 
    259 // ECMA 10.1.8
    260 Arguments::Arguments(ExecState* exec, JSFunction* func, const ArgList& args, JSActivation* act)
    261     : JSObject(exec->lexicalGlobalObject()->objectPrototype())
    262     , _activationObject(act)
    263     , indexToNameMap(func, args)
    264 {
    265     putDirect(exec->propertyNames().callee, func, DontEnum);
    266     putDirect(exec, exec->propertyNames().length, args.size(), DontEnum);
    267  
    268     int i = 0;
    269     ArgList::const_iterator end = args.end();
    270     for (ArgList::const_iterator it = args.begin(); it != end; ++it, ++i) {
    271         Identifier name = Identifier::from(exec, i);
    272         if (!indexToNameMap.isMapped(name))
    273             putDirect(name, *it, DontEnum);
    274     }
    275 }
    276 
    277 void Arguments::mark()
    278 {
    279   JSObject::mark();
    280   if (_activationObject && !_activationObject->marked())
    281     _activationObject->mark();
    282 }
    283 
    284 JSValue* Arguments::mappedIndexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
    285 {
    286   Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());
    287   return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);
    288 }
    289 
    290 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    291 {
    292   if (indexToNameMap.isMapped(propertyName)) {
    293     slot.setCustom(this, mappedIndexGetter);
    294     return true;
    295   }
    296 
    297   return JSObject::getOwnPropertySlot(exec, propertyName, slot);
    298 }
    299 
    300 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
    301 {
    302     if (indexToNameMap.isMapped(propertyName))
    303         _activationObject->put(exec, indexToNameMap[propertyName], value);
    304     else
    305         JSObject::put(exec, propertyName, value);
    306 }
    307 
    308 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
    309 {
    310   if (indexToNameMap.isMapped(propertyName)) {
    311     indexToNameMap.unMap(exec, propertyName);
    312     return true;
    313   } else {
    314     return JSObject::deleteProperty(exec, propertyName);
    315   }
    316 }
    317 
    318 // ------------------------------ Global Functions -----------------------------------
    31950
    32051static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape)
     
    682413#endif
    683414
    684 // ------------------------------ PrototypeFunction -------------------------------
    685 
    686 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function)
    687     : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)
    688     , m_function(function)
    689 {
    690     ASSERT_ARG(function, function);
    691     putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);
    692 }
    693 
    694 PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function)
    695     : InternalFunction(functionPrototype, name)
    696     , m_function(function)
    697 {
    698     ASSERT_ARG(function, function);
    699     putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);
    700 }
    701 
    702 CallType PrototypeFunction::getCallData(CallData& callData)
    703 {
    704     callData.native.function = m_function;
    705     return CallTypeNative;
    706 }
    707 
    708 // ------------------------------ PrototypeReflexiveFunction -------------------------------
    709 
    710 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
    711     : PrototypeFunction(exec, functionPrototype, len, name, function)
    712     , m_cachedGlobalObject(cachedGlobalObject)
    713 {
    714     ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
    715 }
    716 
    717 void GlobalEvalFunction::mark()
    718 {
    719     PrototypeFunction::mark();
    720     if (!m_cachedGlobalObject->marked())
    721         m_cachedGlobalObject->mark();
    722 }
    723 
    724415} // namespace KJS
Note: See TracChangeset for help on using the changeset viewer.