Ignore:
Timestamp:
Oct 26, 2007, 3:43:03 PM (18 years ago)
Author:
ggaren
Message:

Reviewed by Maciej Stachowiak.


Switched ActivationImp to using a symbol table. For now, though, all
clients take the slow path.


Net .6% speedup on SunSpider.


Slowdowns:

  • ActivationImp now mallocs in its constructor
  • Local variable hits use an extra level of indirection to retrieve data
  • Local variable misses do two lookups

Speedups:

  • Fast initialization of local variables upon function entry


  • kjs/function.cpp: (KJS::ActivationImp::ActivationImp): Malloc a private structure to hold data that won't fit in a JSCell. (KJS::ActivationImp::argumentsGetter): Use slow symbol table path for lookup. (KJS::ActivationImp::getOwnPropertySlot): ditto (KJS::ActivationImp::deleteProperty): ditto (KJS::ActivationImp::put): ditto (KJS::ActivationImp::createArgumentsObject): ditto

(KJS::ActivationImp::mark): Call JSObject::mark first so that one of
our properties doesn't try to recursively mark us. (This caused a crash
in earlier testing. Not sure why we haven't run into it before.)

  • kjs/nodes.cpp: Functions now build a symbol table the first time they're called. (KJS::VarDeclNode::evaluate): (KJS::FunctionBodyNode::FunctionBodyNode): (KJS::FunctionBodyNode::initializeSymbolTable): (KJS::FunctionBodyNode::processDeclarations): (KJS::FunctionBodyNode::processDeclarationsForFunctionCode): (KJS::FunctionBodyNode::processDeclarationsForProgramCode):
  • kjs/nodes.h: (KJS::FunctionBodyNode::symbolTable):
  • wtf/Forward.h: Added Vector.
File:
1 edited

Legend:

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

    r27100 r27126  
    391391const ClassInfo ActivationImp::info = {"Activation", 0, 0, 0};
    392392
    393 // ECMA 10.1.6
    394393ActivationImp::ActivationImp(FunctionImp* function, const List& arguments)
    395     : _function(function), _arguments(arguments), _argumentsObject(0)
    396 {
    397   // FIXME: Do we need to support enumerating the arguments property?
     394    : d(new ActivationImpPrivate(function, arguments))
     395    , symbolTable(&function->body->symbolTable())
     396{
    398397}
    399398
     
    401400{
    402401  ActivationImp* thisObj = static_cast<ActivationImp*>(slot.slotBase());
    403 
    404   // default: return builtin arguments array
    405   if (!thisObj->_argumentsObject)
     402  ActivationImpPrivate* d = thisObj->d.get();
     403 
     404  if (!d->argumentsObject)
    406405    thisObj->createArgumentsObject(exec);
    407406 
    408   return thisObj->_argumentsObject;
     407  return d->argumentsObject;
    409408}
    410409
     
    416415bool ActivationImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    417416{
    418     // do this first so property map arguments property wins over the below
    419     // we don't call JSObject because we won't have getter/setter properties
    420     // and we don't want to support __proto__
     417    // We don't call through to JSObject because there's no way to give an
     418    // acitvation object getter/setter properties, and exposing __proto__ in
     419    // the scope chain would be bizarre.
     420    ASSERT(!_prop.hasGetterSetterProperties());
     421
     422    size_t index;
     423    if (symbolTable->get(propertyName, index)) {
     424        slot.setValueSlot(this, &d->localStorage[index].value);
     425        return true;
     426    }
    421427
    422428    if (JSValue** location = getDirectLocation(propertyName)) {
     
    425431    }
    426432
     433    // Only return the built-in arguments object if it wasn't overridden above.
    427434    if (propertyName == exec->propertyNames().arguments) {
    428435        slot.setCustom(this, getArgumentsGetter());
     
    437444    if (propertyName == exec->propertyNames().arguments)
    438445        return false;
     446
     447    size_t index;
     448    if (symbolTable->get(propertyName, index))
     449        return false;
     450
    439451    return JSObject::deleteProperty(exec, propertyName);
    440452}
     
    442454void ActivationImp::put(ExecState*, const Identifier& propertyName, JSValue* value, int attr)
    443455{
    444   // There's no way that an activation object can have a prototype or getter/setter properties
     456  // There's no way that an activation object can have a prototype or getter/setter properties.
    445457  ASSERT(!_prop.hasGetterSetterProperties());
    446458  ASSERT(prototype() == jsNull());
    447459
     460  size_t index;
     461  if (symbolTable->get(propertyName, index)) {
     462    LocalStorageEntry& entry = d->localStorage[index];
     463    entry.value = value;
     464    entry.attributes = attr;
     465    return;
     466  }
     467
    448468  _prop.put(propertyName, value, attr, (attr == None || attr == DontDelete));
    449469}
     
    451471void ActivationImp::mark()
    452472{
    453     if (_function && !_function->marked())
    454         _function->mark();
    455     if (_argumentsObject && !_argumentsObject->marked())
    456         _argumentsObject->mark();
    457473    JSObject::mark();
     474
     475    if (!d->function->marked())
     476        d->function->mark();
     477
     478    size_t size = d->localStorage.size();
     479    for (size_t i = 0; i < size; ++i) {
     480        JSValue* value = d->localStorage[i].value;
     481        if (!value->marked())
     482            value->mark();
     483    }
     484
     485    if (d->argumentsObject && !d->argumentsObject->marked())
     486        d->argumentsObject->mark();
    458487}
    459488
    460489void ActivationImp::createArgumentsObject(ExecState* exec)
    461490{
    462   _argumentsObject = new Arguments(exec, _function, _arguments, const_cast<ActivationImp*>(this));
    463   // The arguments list is only needed to create the arguments object, so discard it now
    464   _arguments.reset();
     491  d->argumentsObject = new Arguments(exec, d->function, d->arguments, this);
     492
     493  // The arguments list is only needed to create the arguments object, so discard it now.
     494  // This prevents lists of Lists from building up, waiting to be garbage collected.
     495  d->arguments.reset();
    465496}
    466497
Note: See TracChangeset for help on using the changeset viewer.