Ignore:
Timestamp:
Jan 11, 2008, 6:08:50 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

Reviewed by Maciej.

Optimized ActivationImp allocation, so that activation records are now
first allocated on an explicitly managed stack and only heap allocated
when necessary. Roughly a 5% improvement on SunSpider, and a larger
improvement on benchmarks that use more function calls.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • kjs/Activation.h: Added. (KJS::ActivationImp::ActivationData::ActivationData): (KJS::ActivationImp::ActivationImp): (KJS::ActivationImp::classInfo): (KJS::ActivationImp::isActivationObject): (KJS::ActivationImp::isOnStack): (KJS::ActivationImp::d): (KJS::StackActivation::StackActivation):
  • kjs/ExecState.cpp: (KJS::ExecState::ExecState): (KJS::ExecState::~ExecState):
  • kjs/ExecState.h: (KJS::ExecState::replaceScopeChainTop): (KJS::ExecState::setActivationObject): (KJS::ExecState::setLocalStorage):
  • kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::reset): (KJS::JSGlobalObject::pushActivation): (KJS::JSGlobalObject::checkActivationCount): (KJS::JSGlobalObject::popActivationHelper): (KJS::JSGlobalObject::popActivation): (KJS::JSGlobalObject::tearOffActivation):
  • kjs/JSGlobalObject.h:
  • kjs/JSVariableObject.h: (KJS::JSVariableObject::JSVariableObjectData::JSVariableObjectData): (KJS::JSVariableObject::JSVariableObject):
  • kjs/function.cpp: (KJS::FunctionImp::argumentsGetter): (KJS::ActivationImp::ActivationImp): (KJS::ActivationImp::~ActivationImp): (KJS::ActivationImp::init): (KJS::ActivationImp::getOwnPropertySlot): (KJS::ActivationImp::markHelper): (KJS::ActivationImp::mark): (KJS::ActivationImp::ActivationData::ActivationData): (KJS::GlobalFuncImp::callAsFunction):
  • kjs/function.h:
  • kjs/nodes.cpp: (KJS::PostIncResolveNode::evaluate): (KJS::PostDecResolveNode::evaluate): (KJS::PreIncResolveNode::evaluate): (KJS::PreDecResolveNode::evaluate): (KJS::ReadModifyResolveNode::evaluate): (KJS::AssignResolveNode::evaluate): (KJS::WithNode::execute): (KJS::TryNode::execute): (KJS::FunctionBodyNode::processDeclarations): (KJS::FuncExprNode::evaluate):
  • kjs/object.h:
  • kjs/scope_chain.h: (KJS::ScopeChain::replace):
  • kjs/scope_chain_mark.h: Added. (KJS::ScopeChain::mark):

WebCore:

Reviewed by Maciej.

Added a new forwarding header, because Activation.h has been separated
from function.h

  • ForwardingHeaders/kjs/Activation.h: Added.

LayoutTests:

Reviewed by Maciej.

Added a test case that came up when developing the ActivationImp tear-off.

  • fast/js/resources/vardecl-preserve-arguments.js:
  • fast/js/vardecl-preserve-arguments-expected.txt:
File:
1 edited

Legend:

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

    r29091 r29425  
    11/*
    22 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
     3 * Copyright (C) 2008 Cameron Zwarich ([email protected])
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3031#include "JSGlobalObject.h"
    3132
    32 #include "SavedBuiltins.h"
     33#include "Activation.h"
    3334#include "array_object.h"
    3435#include "bool_object.h"
     
    4142#include "object_object.h"
    4243#include "regexp_object.h"
     44#include "SavedBuiltins.h"
    4345#include "string_object.h"
    4446
     
    201203    ExecState* exec = &d()->globalExec;
    202204
     205    d()->activations = new ActivationStackNode;
     206    d()->activationCount = 0;
     207
    203208    // Prototypes
    204209    d()->functionPrototype = new FunctionPrototype(exec);
     
    495500}
    496501
     502ActivationImp* JSGlobalObject::pushActivation(ExecState* exec)
     503{
     504    if (d()->activationCount == activationStackNodeSize) {
     505        ActivationStackNode* newNode = new ActivationStackNode;
     506        newNode->prev = d()->activations;
     507        d()->activations = newNode;
     508        d()->activationCount = 0;
     509    }
     510   
     511    StackActivation* stackEntry = &d()->activations->data[d()->activationCount++];
     512    stackEntry->activationStorage.init(exec);
     513   
     514    return &(stackEntry->activationStorage);
     515}
     516
     517inline void JSGlobalObject::checkActivationCount()
     518{
     519    if (!d()->activationCount) {
     520        ActivationStackNode* prev = d()->activations->prev;
     521        delete d()->activations;
     522        d()->activations = prev;
     523        d()->activationCount = activationStackNodeSize;
     524    }
     525}
     526
     527void JSGlobalObject::popActivation()
     528{
     529    checkActivationCount();
     530    d()->activations->data[--d()->activationCount].activationDataStorage.localStorage.shrink(0);   
     531}
     532
     533void JSGlobalObject::tearOffActivation(ExecState* exec, bool leaveRelic)
     534{
     535    if (exec->codeType() == FunctionCode && static_cast<ActivationImp*>(exec->activationObject())->isOnStack()) {
     536        ActivationImp* oldActivation = static_cast<ActivationImp*>(exec->activationObject());
     537        ActivationImp* newActivation = new ActivationImp(*oldActivation->d(), leaveRelic);
     538       
     539        if (!leaveRelic) {
     540            checkActivationCount();
     541            d()->activationCount--;
     542        }
     543       
     544        oldActivation->d()->localStorage.shrink(0);
     545       
     546        exec->setActivationObject(newActivation);
     547        exec->setVariableObject(newActivation);
     548        exec->setLocalStorage(&(newActivation->localStorage()));
     549        exec->replaceScopeChainTop(newActivation);
     550    }
     551}
     552
    497553} // namespace KJS
Note: See TracChangeset for help on using the changeset viewer.