Ignore:
Timestamp:
Oct 1, 2008, 3:18:50 PM (17 years ago)
Author:
[email protected]
Message:

2008-10-01 Cameron Zwarich <[email protected]>

Reviewed by Darin Adler.

Bug 21123: using "arguments" in a function should not force creation of an activation object
<https://bugs.webkit.org/show_bug.cgi?id=21123>

Make the 'arguments' object not require a JSActivation. We store the
'arguments' object in the OptionalCalleeArguments call frame slot. We
need to be able to get the original 'arguments' object to tear it off
when returning from a function, but 'arguments' may be assigned to in a
number of ways.

Therefore, we use the OptionalCalleeArguments slot when we want to get
the original activation or we know that 'arguments' was not assigned a
different value. When 'arguments' may have been assigned a new value,
we use a new local variable that is initialized with 'arguments'. Since
a function parameter named 'arguments' may overwrite the value of
'arguments', we also need to be careful to look up 'arguments' in the
symbol table, so we get the parameter named 'arguments' instead of the
local variable that we have added for holding the 'arguments' object.

This is a 19.1% win on the V8 Raytrace benchmark using the SunSpider
harness, and a 20.7% win using the V8 harness. This amounts to a 6.5%
total speedup on the V8 benchmark suite using the V8 harness.

JavaScriptCore:

  • VM/CTI.cpp: (JSC::CTI::privateCompileMainPass):
  • VM/CodeBlock.h:
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::CodeGenerator):
  • VM/Machine.cpp: (JSC::Machine::unwindCallFrame): (JSC::Machine::privateExecute): (JSC::Machine::retrieveArguments): (JSC::Machine::cti_op_init_arguments): (JSC::Machine::cti_op_ret_activation_arguments):
  • VM/Machine.h:
  • VM/RegisterFile.h: (JSC::RegisterFile::):
  • kjs/Arguments.cpp: (JSC::Arguments::mark): (JSC::Arguments::fillArgList): (JSC::Arguments::getOwnPropertySlot): (JSC::Arguments::put):
  • kjs/Arguments.h: (JSC::Arguments::setRegisters): (JSC::Arguments::init): (JSC::Arguments::Arguments): (JSC::Arguments::copyRegisters): (JSC::JSActivation::copyRegisters):
  • kjs/JSActivation.cpp: (JSC::JSActivation::argumentsGetter):
  • kjs/JSActivation.h: (JSC::JSActivation::JSActivationData::JSActivationData):
  • kjs/grammar.y:
  • kjs/nodes.h: (JSC::ScopeNode::setUsesArguments):
  • masm/X86Assembler.h: (JSC::X86Assembler::): (JSC::X86Assembler::orl_mr):

LayoutTests:

  • fast/js/arguments-expected.txt:
  • fast/js/function-dot-arguments-expected.txt:
  • fast/js/resources/arguments.js:
  • fast/js/resources/function-dot-arguments.js:
File:
1 edited

Legend:

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

    r36821 r37160  
    3838const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
    3939
    40 struct ArgumentsData : Noncopyable {
    41     ArgumentsData(JSActivation* activation, unsigned numParameters, int firstParameterIndex, unsigned numArguments, JSFunction* callee)
    42         : activation(activation)
    43         , numParameters(numParameters)
    44         , firstParameterIndex(firstParameterIndex)
    45         , numArguments(numArguments)
    46         , extraArguments(0)
    47         , callee(callee)
    48         , overrodeLength(false)
    49         , overrodeCallee(false)
    50     {
    51     }
    52 
    53     JSActivation* activation;
    54 
    55     unsigned numParameters;
    56     int firstParameterIndex;
    57     unsigned numArguments;
    58     Register* extraArguments;
    59     OwnArrayPtr<bool> deletedArguments;
    60     Register extraArgumentsFixedBuffer[4];
    61 
    62     JSFunction* callee;
    63     bool overrodeLength : 1;
    64     bool overrodeCallee : 1;
    65 };
    66 
    67 // ECMA 10.1.8
    68 Arguments::Arguments(ExecState* exec, JSFunction* function, JSActivation* activation, int firstParameterIndex, Register* argv, int argc)
    69     : JSObject(exec->lexicalGlobalObject()->argumentsStructure())
    70     , d(new ArgumentsData(activation, function->numParameters(), firstParameterIndex, argc, function))
    71 {
    72     ASSERT(activation);
    73  
    74     if (d->numArguments > d->numParameters) {
    75         unsigned numExtraArguments = d->numArguments - d->numParameters;
    76         Register* extraArguments;
    77         if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
    78             extraArguments = new Register[numExtraArguments];
    79         else
    80             extraArguments = d->extraArgumentsFixedBuffer;
    81         for (unsigned i = 0; i < numExtraArguments; ++i)
    82             extraArguments[i] = argv[d->numParameters + i];
    83         d->extraArguments = extraArguments;
    84     }
    85 }
    86 
    8740Arguments::~Arguments()
    8841{
     
    9447{
    9548    JSObject::mark();
     49
     50    for (unsigned i = 0; i < d->numParameters; ++i) {
     51        if (!d->registers[i].marked())
     52            d->registers[i].mark();
     53    }
    9654
    9755    if (d->extraArguments) {
     
    10664        d->callee->mark();
    10765
    108     if (!d->activation->marked())
     66    if (d->activation && !d->activation->marked())
    10967        d->activation->mark();
    11068}
     
    11977
    12078        if (d->numParameters == d->numArguments) {
    121             args.initialize(&d->activation->registerAt(d->firstParameterIndex), d->numArguments);
     79            args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
    12280            return;
    12381        }
     
    12684        unsigned i = 0;
    12785        for (; i < parametersLength; ++i)
    128             args.append(d->activation->uncheckedSymbolTableGetValue(d->firstParameterIndex + i));
     86            args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
    12987        for (; i < d->numArguments; ++i)
    130             args.append(d->extraArguments[i - d->numParameters].getJSValue());
     88            args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
    13189        return;
    13290    }
     
    13694    for (; i < parametersLength; ++i) {
    13795        if (!d->deletedArguments[i])
    138             args.append(d->activation->uncheckedSymbolTableGetValue(d->firstParameterIndex + i));
     96            args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
    13997        else
    14098            args.append(get(exec, i));
     
    142100    for (; i < d->numArguments; ++i) {
    143101        if (!d->deletedArguments[i])
    144             args.append(d->extraArguments[i - d->numParameters].getJSValue());
     102            args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
    145103        else
    146104            args.append(get(exec, i));
     
    152110    if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
    153111        if (i < d->numParameters)
    154             d->activation->uncheckedSymbolTableGet(d->firstParameterIndex + i, slot);
    155         else
    156             slot.setValue(d->extraArguments[i - d->numParameters].getJSValue());
     112            slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
     113        else
     114            slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
    157115        return true;
    158116    }
     
    167125    if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
    168126        if (i < d->numParameters)
    169             d->activation->uncheckedSymbolTableGet(d->firstParameterIndex + i, slot);
    170         else
    171             slot.setValue(d->extraArguments[i - d->numParameters].getJSValue());
     127            slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
     128        else
     129            slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
    172130        return true;
    173131    }
     
    190148    if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
    191149        if (i < d->numParameters)
    192             d->activation->uncheckedSymbolTablePut(d->firstParameterIndex + i, value);
     150            d->registers[d->firstParameterIndex + i] = value;
    193151        else
    194152            d->extraArguments[i - d->numParameters] = value;
     
    205163    if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
    206164        if (i < d->numParameters)
    207             d->activation->uncheckedSymbolTablePut(d->firstParameterIndex + i, value);
     165            d->registers[d->firstParameterIndex + i] = value;
    208166        else
    209167            d->extraArguments[i - d->numParameters] = value;
Note: See TracChangeset for help on using the changeset viewer.