Changeset 102545 in webkit


Ignore:
Timestamp:
Dec 11, 2011 4:35:51 PM (12 years ago)
Author:
ggaren@apple.com
Message:

v8 benchmark takes 12-13 million function call slow paths due to extra arguments
https://bugs.webkit.org/show_bug.cgi?id=74244

Reviewed by Filip Pizlo.

.arguments function of order the Reversed

10% speedup on v8-raytrace, 1.7% speedup on v8 overall, neutral on Kraken
and SunSpider.

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::valueProfileForArgument): Clarified that the interface
to this function is an argument number.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitConstruct):
(JSC::BytecodeGenerator::isArgumentNumber): Switched to using CallFrame
helper functions for computing offsets for arguments, rather than doing
the math by hand.

Switched to iterating argument offsets backwards (--) instead of forwards (++).

  • bytecompiler/BytecodeGenerator.h:

(JSC::CallArguments::thisRegister):
(JSC::CallArguments::argumentRegister):
(JSC::CallArguments::registerOffset): Updated for arguments being reversed.

  • bytecompiler/NodesCodegen.cpp: Allocate arguments in reverse order.
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::getArgument):
(JSC::DFG::ByteCodeParser::setArgument):
(JSC::DFG::ByteCodeParser::flush):
(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::handleMinMax):
(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::processPhiStack): Use abstract argument indices
that just-in-time convert to bytecode operands (i.e., indexes in the register
file) through helper functions. This means only one piece of code needs
to know how arguments are laid out in the register file.

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump): Ditto.

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::valueProfileFor): Ditto.

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::compileFunction): The whole point of this patch:
Treat too many arguments as an arity match.

  • dfg/DFGOSRExit.h:

(JSC::DFG::OSRExit::variableForIndex):
(JSC::DFG::OSRExit::operandForIndex): Use helper functions, as above.

  • dfg/DFGOperands.h:

(JSC::DFG::operandToArgument):
(JSC::DFG::argumentToOperand): These are now the only two lines of code in
the DFG compiler that know how arguments are laid out in memory.

(JSC::DFG::Operands::operand):
(JSC::DFG::Operands::setOperand): Use helper functions, as above.

  • dfg/DFGOperations.cpp: The whole point of this patch:

Treat too many arguments as an arity match.

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::emitCall): Use helper functions, as above.

Also, don't tag the caller frame slot as a cell, because it's not a cell.

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::emitCall): Use helper functions, as above.

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compile): Use helper functions, as above.

(JSC::DFG::SpeculativeJIT::checkArgumentTypes): Use already-computed
argument virtual register instead of recomputing by hand.

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callFrameSlot):
(JSC::DFG::SpeculativeJIT::argumentSlot):
(JSC::DFG::SpeculativeJIT::callFrameTagSlot):
(JSC::DFG::SpeculativeJIT::callFramePayloadSlot):
(JSC::DFG::SpeculativeJIT::argumentTagSlot):
(JSC::DFG::SpeculativeJIT::argumentPayloadSlot): Added a few helper
functions for dealing with callee arguments specifically. These still
build on top of our other helper functions, and have no direct knowledge
of how arguments are laid out in the register file.

(JSC::DFG::SpeculativeJIT::resetCallArguments):
(JSC::DFG::SpeculativeJIT::addCallArgument): Renamed argumentIndex to
argumentOffset to match CallFrame naming.

(JSC::DFG::SpeculativeJIT::valueSourceReferenceForOperand): Use helper
functions, as above.

  • interpreter/CallFrame.h:

(JSC::ExecState::argumentOffset):
(JSC::ExecState::argumentOffsetIncludingThis):
(JSC::ExecState::argument):
(JSC::ExecState::setArgument):
(JSC::ExecState::thisArgumentOffset):
(JSC::ExecState::thisValue):
(JSC::ExecState::setThisValue):
(JSC::ExecState::offsetFor):
(JSC::ExecState::hostThisRegister):
(JSC::ExecState::hostThisValue): Added a bunch of helper functions for
computing where an argument is in the register file. Anything in the
runtime that needs to access arguments should use these helpers.

  • interpreter/CallFrameClosure.h:

(JSC::CallFrameClosure::setThis):
(JSC::CallFrameClosure::setArgument):
(JSC::CallFrameClosure::resetCallFrame): This stuff is a lot simpler, now
that too many arguments counts as an arity match and doesn't require
preserving two copies of our arguments.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::slideRegisterWindowForCall): Only need to do something
special if the caller provided too few arguments.

Key simplification: We never need to maintain two copies of our arguments
anymore.

(JSC::eval):
(JSC::loadVarargs): Use helper functions.

(JSC::Interpreter::unwindCallFrame): Updated for new interface.

(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall): Seriously, though: use helper
functions.

(JSC::Interpreter::privateExecute): No need to check for stack overflow
when calling host functions because they have zero callee registers.

(JSC::Interpreter::retrieveArguments): Explicitly tear off the arguments
object, since there's no special constructor for this anymore.

  • interpreter/Interpreter.h: Reduced the C++ re-entry depth because some

workers tests were hitting stack overflow in some of my testing. We should
make this test more exact in future.

  • interpreter/RegisterFile.h: Death to all runtime knowledge of argument

location that does not belong to the CallFrame class!

  • jit/JIT.cpp:

(JSC::JIT::privateCompile): I am a broken record and I use helper functions.

Also, the whole point of this patch: Treat too many arguments as an arity match.

  • jit/JITCall32_64.cpp:

(JSC::JIT::compileLoadVarargs):

  • jit/JITCall.cpp:

(JSC::JIT::compileLoadVarargs): Updated the argument copying math to use
helper functions, for backwards-correctness. Removed the condition
pertaining to declared argument count because, now that arguments are
always in just one place, this optimization is valid for all functions.
Standardized the if predicate for each line of the optimization. This might
fix a bug, but I couldn't get the bug to crash in practice.

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_create_arguments):
(JSC::JIT::emit_op_get_argument_by_val):
(JSC::JIT::emitSlow_op_get_argument_by_val):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_create_arguments):
(JSC::JIT::emit_op_get_argument_by_val):
(JSC::JIT::emitSlow_op_get_argument_by_val): Removed cti_op_create_arguments_no_params
optimization because it's no longer an optimization, now that arguments
are always contiguous in a known location.

Updated argument access opcode math for backwards-correctness.

  • jit/JITStubs.cpp:

(JSC::arityCheckFor): Updated just like slideRegisterWindowForCall. This
function is slightly different because it copies the call frame in
addition to the arguments. (In the Interpreter, the call frame is not
set up by this point.)

(JSC::lazyLinkFor): The whole point of this patch: Treat too many
arguments as an arity match.

(JSC::DEFINE_STUB_FUNCTION): Updated for new iterface to tearOff().

  • jit/JITStubs.h:
  • jit/SpecializedThunkJIT.h:

(JSC::SpecializedThunkJIT::loadDoubleArgument):
(JSC::SpecializedThunkJIT::loadCellArgument):
(JSC::SpecializedThunkJIT::loadInt32Argument): Use helper functions! They
build strong bones and teeth!

  • runtime/ArgList.cpp:

(JSC::ArgList::getSlice):
(JSC::MarkedArgumentBuffer::slowAppend):

  • runtime/ArgList.h:

(JSC::MarkedArgumentBuffer::MarkedArgumentBuffer):
(JSC::MarkedArgumentBuffer::~MarkedArgumentBuffer):
(JSC::MarkedArgumentBuffer::at):
(JSC::MarkedArgumentBuffer::clear):
(JSC::MarkedArgumentBuffer::append):
(JSC::MarkedArgumentBuffer::removeLast):
(JSC::MarkedArgumentBuffer::last):
(JSC::ArgList::ArgList):
(JSC::ArgList::at): Updated for backwards-correctness. WTF::Vector doesn't
play nice with backwards-ness, so I changed to using manual allocation.

Fixed a FIXME about not all values being marked in the case of out-of-line
arguments. I had to rewrite the loop anyway, and I didn't feel like
maintaining fidelity to its old bugs.

  • runtime/Arguments.cpp:

(JSC::Arguments::visitChildren):
(JSC::Arguments::copyToArguments):
(JSC::Arguments::fillArgList):
(JSC::Arguments::getOwnPropertySlotByIndex):
(JSC::Arguments::getOwnPropertySlot):
(JSC::Arguments::getOwnPropertyDescriptor):
(JSC::Arguments::putByIndex):
(JSC::Arguments::put):
(JSC::Arguments::tearOff):

  • runtime/Arguments.h:

(JSC::Arguments::create):
(JSC::Arguments::Arguments):
(JSC::Arguments::argument):
(JSC::Arguments::finishCreation): Secondary benefit of this patch: deleted
lots of tricky code designed to maintain two different copies of function
arguments. Now that arguments are always contiguous in one place in memory,
this complexity can go away.

Reduced down to one create function for the Arguments class, from three.

Moved tearOff() into an out-of-line function because it's huge.

Moved logic about whether to tear off eagerly into the Arguments class,
so we didn't have to duplicate it elsewhere.

  • runtime/JSActivation.cpp:

(JSC::JSActivation::JSActivation):
(JSC::JSActivation::visitChildren): Renamed m_numParametersMinusThis to
m_numCapturedArgs because if the value really were m_numParametersMinusThis
we would be marking too much. (We shouldn't mark 'this' because it can't
be captured.) Also, use helper functions.

  • runtime/JSActivation.h:

(JSC::JSActivation::tearOff): Use helper functions.

  • runtime/JSArray.cpp:

(JSC::JSArray::copyToArguments):

  • runtime/JSArray.h: Use helper functions, as above.
Location:
trunk/Source/JavaScriptCore
Files:
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r102534 r102545  
     12011-12-10  Geoffrey Garen  <ggaren@apple.com>
     2
     3        v8 benchmark takes 12-13 million function call slow paths due to extra arguments
     4        https://bugs.webkit.org/show_bug.cgi?id=74244
     5
     6        Reviewed by Filip Pizlo.
     7       
     8        .arguments function of order the Reversed
     9       
     10        10% speedup on v8-raytrace, 1.7% speedup on v8 overall, neutral on Kraken
     11        and SunSpider.
     12
     13        * bytecode/CodeBlock.h:
     14        (JSC::CodeBlock::valueProfileForArgument): Clarified that the interface
     15        to this function is an argument number.
     16
     17        * bytecompiler/BytecodeGenerator.cpp:
     18        (JSC::BytecodeGenerator::BytecodeGenerator):
     19        (JSC::BytecodeGenerator::emitCall):
     20        (JSC::BytecodeGenerator::emitConstruct):
     21        (JSC::BytecodeGenerator::isArgumentNumber): Switched to using CallFrame
     22        helper functions for computing offsets for arguments, rather than doing
     23        the math by hand.
     24       
     25        Switched to iterating argument offsets backwards (--) instead of forwards (++).
     26
     27        * bytecompiler/BytecodeGenerator.h:
     28        (JSC::CallArguments::thisRegister):
     29        (JSC::CallArguments::argumentRegister):
     30        (JSC::CallArguments::registerOffset): Updated for arguments being reversed.
     31
     32        * bytecompiler/NodesCodegen.cpp: Allocate arguments in reverse order.
     33
     34        * dfg/DFGByteCodeParser.cpp:
     35        (JSC::DFG::ByteCodeParser::getArgument):
     36        (JSC::DFG::ByteCodeParser::setArgument):
     37        (JSC::DFG::ByteCodeParser::flush):
     38        (JSC::DFG::ByteCodeParser::addCall):
     39        (JSC::DFG::ByteCodeParser::handleCall):
     40        (JSC::DFG::ByteCodeParser::handleInlining):
     41        (JSC::DFG::ByteCodeParser::handleMinMax):
     42        (JSC::DFG::ByteCodeParser::handleIntrinsic):
     43        (JSC::DFG::ByteCodeParser::parseBlock):
     44        (JSC::DFG::ByteCodeParser::processPhiStack): Use abstract argument indices
     45        that just-in-time convert to bytecode operands (i.e., indexes in the register
     46        file) through helper functions. This means only one piece of code needs
     47        to know how arguments are laid out in the register file.
     48
     49        * dfg/DFGGraph.cpp:
     50        (JSC::DFG::Graph::dump): Ditto.
     51
     52        * dfg/DFGGraph.h:
     53        (JSC::DFG::Graph::valueProfileFor): Ditto.
     54
     55        * dfg/DFGJITCompiler.cpp:
     56        (JSC::DFG::JITCompiler::compileFunction): The whole point of this patch:
     57        Treat too many arguments as an arity match.
     58
     59        * dfg/DFGOSRExit.h:
     60        (JSC::DFG::OSRExit::variableForIndex):
     61        (JSC::DFG::OSRExit::operandForIndex): Use helper functions, as above.
     62
     63        * dfg/DFGOperands.h:
     64        (JSC::DFG::operandToArgument):
     65        (JSC::DFG::argumentToOperand): These are now the only two lines of code in
     66        the DFG compiler that know how arguments are laid out in memory.
     67
     68        (JSC::DFG::Operands::operand):
     69        (JSC::DFG::Operands::setOperand): Use helper functions, as above.
     70
     71        * dfg/DFGOperations.cpp: The whole point of this patch:
     72        Treat too many arguments as an arity match.
     73
     74        * dfg/DFGSpeculativeJIT32_64.cpp:
     75        (JSC::DFG::SpeculativeJIT::emitCall): Use helper functions, as above.
     76       
     77        Also, don't tag the caller frame slot as a cell, because it's not a cell.
     78
     79        * dfg/DFGSpeculativeJIT64.cpp:
     80        (JSC::DFG::SpeculativeJIT::emitCall): Use helper functions, as above.
     81
     82        * dfg/DFGSpeculativeJIT.cpp:
     83        (JSC::DFG::SpeculativeJIT::compile): Use helper functions, as above.
     84
     85        (JSC::DFG::SpeculativeJIT::checkArgumentTypes): Use already-computed
     86        argument virtual register instead of recomputing by hand.
     87
     88        * dfg/DFGSpeculativeJIT.h:
     89        (JSC::DFG::SpeculativeJIT::callFrameSlot):
     90        (JSC::DFG::SpeculativeJIT::argumentSlot):
     91        (JSC::DFG::SpeculativeJIT::callFrameTagSlot):
     92        (JSC::DFG::SpeculativeJIT::callFramePayloadSlot):
     93        (JSC::DFG::SpeculativeJIT::argumentTagSlot):
     94        (JSC::DFG::SpeculativeJIT::argumentPayloadSlot): Added a few helper
     95        functions for dealing with callee arguments specifically. These still
     96        build on top of our other helper functions, and have no direct knowledge
     97        of how arguments are laid out in the register file.
     98
     99        (JSC::DFG::SpeculativeJIT::resetCallArguments):
     100        (JSC::DFG::SpeculativeJIT::addCallArgument): Renamed argumentIndex to
     101        argumentOffset to match CallFrame naming.
     102
     103        (JSC::DFG::SpeculativeJIT::valueSourceReferenceForOperand): Use helper
     104        functions, as above.
     105
     106        * interpreter/CallFrame.h:
     107        (JSC::ExecState::argumentOffset):
     108        (JSC::ExecState::argumentOffsetIncludingThis):
     109        (JSC::ExecState::argument):
     110        (JSC::ExecState::setArgument):
     111        (JSC::ExecState::thisArgumentOffset):
     112        (JSC::ExecState::thisValue):
     113        (JSC::ExecState::setThisValue):
     114        (JSC::ExecState::offsetFor):
     115        (JSC::ExecState::hostThisRegister):
     116        (JSC::ExecState::hostThisValue): Added a bunch of helper functions for
     117        computing where an argument is in the register file. Anything in the
     118        runtime that needs to access arguments should use these helpers.
     119
     120        * interpreter/CallFrameClosure.h:
     121        (JSC::CallFrameClosure::setThis):
     122        (JSC::CallFrameClosure::setArgument):
     123        (JSC::CallFrameClosure::resetCallFrame): This stuff is a lot simpler, now
     124        that too many arguments counts as an arity match and doesn't require
     125        preserving two copies of our arguments.
     126
     127        * interpreter/Interpreter.cpp:
     128        (JSC::Interpreter::slideRegisterWindowForCall): Only need to do something
     129        special if the caller provided too few arguments.
     130       
     131        Key simplification: We never need to maintain two copies of our arguments
     132        anymore.
     133
     134        (JSC::eval):
     135        (JSC::loadVarargs): Use helper functions.
     136
     137        (JSC::Interpreter::unwindCallFrame): Updated for new interface.
     138
     139        (JSC::Interpreter::execute):
     140        (JSC::Interpreter::executeCall):
     141        (JSC::Interpreter::executeConstruct):
     142        (JSC::Interpreter::prepareForRepeatCall): Seriously, though: use helper
     143        functions.
     144
     145        (JSC::Interpreter::privateExecute): No need to check for stack overflow
     146        when calling host functions because they have zero callee registers.
     147
     148        (JSC::Interpreter::retrieveArguments): Explicitly tear off the arguments
     149        object, since there's no special constructor for this anymore.
     150
     151        * interpreter/Interpreter.h: Reduced the C++ re-entry depth because some
     152        workers tests were hitting stack overflow in some of my testing. We should
     153        make this test more exact in future.
     154
     155        * interpreter/RegisterFile.h: Death to all runtime knowledge of argument
     156        location that does not belong to the CallFrame class!
     157
     158        * jit/JIT.cpp:
     159        (JSC::JIT::privateCompile): I am a broken record and I use helper functions.
     160       
     161        Also, the whole point of this patch: Treat too many arguments as an arity match.
     162
     163        * jit/JITCall32_64.cpp:
     164        (JSC::JIT::compileLoadVarargs):
     165        * jit/JITCall.cpp:
     166        (JSC::JIT::compileLoadVarargs): Updated the argument copying math to use
     167        helper functions, for backwards-correctness. Removed the condition
     168        pertaining to declared argument count because, now that arguments are
     169        always in just one place, this optimization is valid for all functions.
     170        Standardized the if predicate for each line of the optimization. This might
     171        fix a bug, but I couldn't get the bug to crash in practice.
     172
     173        * jit/JITOpcodes32_64.cpp:
     174        (JSC::JIT::emit_op_create_arguments):
     175        (JSC::JIT::emit_op_get_argument_by_val):
     176        (JSC::JIT::emitSlow_op_get_argument_by_val):
     177        * jit/JITOpcodes.cpp:
     178        (JSC::JIT::emit_op_create_arguments):
     179        (JSC::JIT::emit_op_get_argument_by_val):
     180        (JSC::JIT::emitSlow_op_get_argument_by_val): Removed cti_op_create_arguments_no_params
     181        optimization because it's no longer an optimization, now that arguments
     182        are always contiguous in a known location.
     183       
     184        Updated argument access opcode math for backwards-correctness.
     185
     186        * jit/JITStubs.cpp:
     187        (JSC::arityCheckFor): Updated just like slideRegisterWindowForCall. This
     188        function is slightly different because it copies the call frame in
     189        addition to the arguments. (In the Interpreter, the call frame is not
     190        set up by this point.)
     191
     192        (JSC::lazyLinkFor): The whole point of this patch: Treat too many
     193        arguments as an arity match.
     194
     195        (JSC::DEFINE_STUB_FUNCTION): Updated for new iterface to tearOff().
     196
     197        * jit/JITStubs.h:
     198        * jit/SpecializedThunkJIT.h:
     199        (JSC::SpecializedThunkJIT::loadDoubleArgument):
     200        (JSC::SpecializedThunkJIT::loadCellArgument):
     201        (JSC::SpecializedThunkJIT::loadInt32Argument): Use helper functions! They
     202        build strong bones and teeth!
     203
     204        * runtime/ArgList.cpp:
     205        (JSC::ArgList::getSlice):
     206        (JSC::MarkedArgumentBuffer::slowAppend):
     207        * runtime/ArgList.h:
     208        (JSC::MarkedArgumentBuffer::MarkedArgumentBuffer):
     209        (JSC::MarkedArgumentBuffer::~MarkedArgumentBuffer):
     210        (JSC::MarkedArgumentBuffer::at):
     211        (JSC::MarkedArgumentBuffer::clear):
     212        (JSC::MarkedArgumentBuffer::append):
     213        (JSC::MarkedArgumentBuffer::removeLast):
     214        (JSC::MarkedArgumentBuffer::last):
     215        (JSC::ArgList::ArgList):
     216        (JSC::ArgList::at): Updated for backwards-correctness. WTF::Vector doesn't
     217        play nice with backwards-ness, so I changed to using manual allocation.
     218       
     219        Fixed a FIXME about not all values being marked in the case of out-of-line
     220        arguments. I had to rewrite the loop anyway, and I didn't feel like
     221        maintaining fidelity to its old bugs.
     222
     223        * runtime/Arguments.cpp:
     224        (JSC::Arguments::visitChildren):
     225        (JSC::Arguments::copyToArguments):
     226        (JSC::Arguments::fillArgList):
     227        (JSC::Arguments::getOwnPropertySlotByIndex):
     228        (JSC::Arguments::getOwnPropertySlot):
     229        (JSC::Arguments::getOwnPropertyDescriptor):
     230        (JSC::Arguments::putByIndex):
     231        (JSC::Arguments::put):
     232        (JSC::Arguments::tearOff):
     233        * runtime/Arguments.h:
     234        (JSC::Arguments::create):
     235        (JSC::Arguments::Arguments):
     236        (JSC::Arguments::argument):
     237        (JSC::Arguments::finishCreation): Secondary benefit of this patch: deleted
     238        lots of tricky code designed to maintain two different copies of function
     239        arguments. Now that arguments are always contiguous in one place in memory,
     240        this complexity can go away.
     241       
     242        Reduced down to one create function for the Arguments class, from three.
     243
     244        Moved tearOff() into an out-of-line function because it's huge.
     245       
     246        Moved logic about whether to tear off eagerly into the Arguments class,
     247        so we didn't have to duplicate it elsewhere.
     248
     249        * runtime/JSActivation.cpp:
     250        (JSC::JSActivation::JSActivation):
     251        (JSC::JSActivation::visitChildren): Renamed m_numParametersMinusThis to
     252        m_numCapturedArgs because if the value really were m_numParametersMinusThis
     253        we would be marking too much. (We shouldn't mark 'this' because it can't
     254        be captured.) Also, use helper functions.
     255
     256        * runtime/JSActivation.h:
     257        (JSC::JSActivation::tearOff): Use helper functions.
     258
     259        * runtime/JSArray.cpp:
     260        (JSC::JSArray::copyToArguments):
     261        * runtime/JSArray.h: Use helper functions, as above.
     262
    12632011-12-10  Mark Hahnenberg  <mhahnenberg@apple.com>
    2264
     
    2035720619        (JSC::PredictionTracker::numberOfArguments):
    2035820620        (JSC::PredictionTracker::numberOfVariables):
    20359         (JSC::PredictionTracker::argumentIndexForOperand):
     20621        (JSC::PredictionTracker::argumentOffsetForOperand):
    2036020622        (JSC::PredictionTracker::predictArgument):
    2036120623        (JSC::PredictionTracker::predict):
     
    2209222354        (JSC::DFG::PredictionTracker::numberOfArguments):
    2209322355        (JSC::DFG::PredictionTracker::numberOfVariables):
    22094         (JSC::DFG::PredictionTracker::argumentIndexForOperand):
     22356        (JSC::DFG::PredictionTracker::argumentOffsetForOperand):
    2209522357        (JSC::DFG::PredictionTracker::predictArgument):
    2209622358        (JSC::DFG::PredictionTracker::predict):
  • trunk/Source/JavaScriptCore/Configurations/Base.xcconfig

    r99378 r102545  
    2525
    2626COMPILER_SPECIFIC_WARNING_CFLAGS = $(COMPILER_SPECIFIC_WARNING_CFLAGS_$(TARGET_GCC_VERSION));
    27 COMPILER_SPECIFIC_WARNING_CFLAGS_LLVM_COMPILER = -Wglobal-constructors -Wexit-time-destructors;
     27COMPILER_SPECIFIC_WARNING_CFLAGS_LLVM_COMPILER = ;
    2828
    2929CLANG_WARN_CXX0X_EXTENSIONS = NO;
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r102489 r102545  
    652652            return WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset);
    653653        }
    654         ValueProfile* valueProfileForArgument(int argumentIndex)
    655         {
    656             int index = argumentIndex;
    657             if (static_cast<unsigned>(index) >= m_valueProfiles.size())
     654        ValueProfile* valueProfileForArgument(int argument)
     655        {
     656            size_t index = argument;
     657            if (index >= m_valueProfiles.size())
    658658                return 0;
    659             ValueProfile* result = valueProfile(argumentIndex);
     659            ValueProfile* result = valueProfile(index);
    660660            if (result->m_bytecodeOffset != -1)
    661661                return 0;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r100879 r102545  
    203203    , m_scopeNode(programNode)
    204204    , m_codeBlock(codeBlock)
    205     , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
     205    , m_thisRegister(CallFrame::thisArgumentOffset())
    206206    , m_finallyDepth(0)
    207207    , m_dynamicScopeDepth(0)
     
    397397
    398398    FunctionParameters& parameters = *functionBody->parameters();
    399     size_t parameterCount = parameters.size();
    400     int nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
    401     m_parameters.grow(1 + parameterCount); // reserve space for "this"
     399    m_parameters.grow(parameters.size() + 1); // reserve space for "this"
    402400
    403401    // Add "this" as a parameter
    404     m_thisRegister.setIndex(nextParameterIndex);
     402    int nextParameterIndex = CallFrame::thisArgumentOffset();
     403    m_thisRegister.setIndex(nextParameterIndex--);
    405404    ++m_codeBlock->m_numParameters;
    406405   
    407     for (size_t i = 0; i < parameterCount; ++i)
    408         addParameter(parameters[i], ++nextParameterIndex);
     406    for (size_t i = 0; i < parameters.size(); ++i)
     407        addParameter(parameters[i], nextParameterIndex--);
    409408
    410409    preserveLastVar();
     
    436435    , m_scopeNode(evalNode)
    437436    , m_codeBlock(codeBlock)
    438     , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
     437    , m_thisRegister(CallFrame::thisArgumentOffset())
    439438    , m_finallyDepth(0)
    440439    , m_dynamicScopeDepth(0)
     
    18021801
    18031802    // Generate code for arguments.
    1804     unsigned argumentIndex = 0;
     1803    unsigned argument = 0;
    18051804    for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
    1806         emitNode(callArguments.argumentRegister(argumentIndex++), n);
     1805        emitNode(callArguments.argumentRegister(argument++), n);
    18071806
    18081807    // Reserve space for call frame.
     
    18211820    emitOpcode(opcodeID);
    18221821    instructions().append(func->index()); // func
    1823     instructions().append(callArguments.count()); // argCount
     1822    instructions().append(callArguments.argumentCountIncludingThis()); // argCount
    18241823    instructions().append(callArguments.registerOffset()); // registerOffset
    18251824    if (dst != ignoredResult()) {
     
    19011900
    19021901    // Generate code for arguments.
    1903     unsigned argumentIndex = 0;
     1902    unsigned argument = 0;
    19041903    if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
    19051904        for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
    1906             emitNode(callArguments.argumentRegister(argumentIndex++), n);
     1905            emitNode(callArguments.argumentRegister(argument++), n);
    19071906    }
    19081907
     
    19211920    emitOpcode(op_construct);
    19221921    instructions().append(func->index()); // func
    1923     instructions().append(callArguments.count()); // argCount
     1922    instructions().append(callArguments.argumentCountIncludingThis()); // argCount
    19241923    instructions().append(callArguments.registerOffset()); // registerOffset
    19251924    if (dst != ignoredResult()) {
     
    23632362    if (!registerID || registerID->index() >= 0)
    23642363         return 0;
    2365     return registerID->index() - m_thisRegister.index() - 1 == argumentNumber;
     2364    return registerID->index() == CallFrame::argumentOffset(argumentNumber);
    23662365}
    23672366
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r100879 r102545  
    5656        RegisterID* thisRegister() { return m_argv[0].get(); }
    5757        RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
    58         unsigned registerOffset() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize; }
    59         unsigned count() { return m_argv.size(); }
     58        unsigned registerOffset() { return m_argv.last()->index() + CallFrame::offsetFor(argumentCountIncludingThis()); }
     59        unsigned argumentCountIncludingThis() { return m_argv.size(); }
    6060        RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
    6161        ArgumentsNode* argumentsNode() { return m_argumentsNode; }
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r100879 r102545  
    320320        m_profileHookRegister = generator.newTemporary();
    321321
    322     newArgument(generator); // 'this' register.
    323     if (!argumentsNode)
    324         return;
    325     for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
    326         newArgument(generator);
     322    size_t argumentCountIncludingThis = 1; // 'this' register.
     323    if (argumentsNode) {
     324        for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
     325            ++argumentCountIncludingThis;
     326    }
     327
     328    m_argv.grow(argumentCountIncludingThis);
     329    for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
     330        m_argv[i] = generator.newTemporary();
     331        ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() + 1);
     332    }
    327333}
    328334
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r102489 r102545  
    7777
    7878    // Helper for min and max.
    79     bool handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg);
     79    bool handleMinMax(bool usesResult, int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis);
    8080   
    8181    // Handle calls. This resolves issues surrounding inlining and intrinsics.
    8282    void handleCall(Interpreter*, Instruction* currentInstruction, NodeType op, CodeSpecializationKind);
    8383    // Handle inlining. Return true if it succeeded, false if we need to plant a call.
    84     bool handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction*, int firstArg, int lastArg, unsigned nextOffset, CodeSpecializationKind);
     84    bool handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction*, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind);
    8585    // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
    86     bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int firstArg, int lastArg, PredictedType prediction);
     86    bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction);
    8787    // Prepare to parse a block.
    8888    void prepareToParseBlock();
     
    200200    NodeIndex getArgument(unsigned operand)
    201201    {
    202         unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
     202        unsigned argument = operandToArgument(operand);
    203203        ASSERT(argument < m_numArguments);
    204204
     
    249249    void setArgument(int operand, NodeIndex value)
    250250    {
    251         unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
     251        unsigned argument = operandToArgument(operand);
    252252        ASSERT(argument < m_numArguments);
    253253
     
    267267        int index;
    268268        if (operandIsArgument(operand)) {
    269             index = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
     269            index = operandToArgument(operand);
    270270            nodeIndex = m_currentBlock->variablesAtTail.argument(index);
    271271        } else {
     
    579579        addVarArgChild(get(currentInstruction[1].u.operand));
    580580        int argCount = currentInstruction[2].u.operand;
     581        if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
     582            m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
     583
    581584        int registerOffset = currentInstruction[3].u.operand;
    582         int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
    583         for (int argIdx = firstArg + (op == Construct ? 1 : 0); argIdx < firstArg + argCount; argIdx++)
    584             addVarArgChild(get(argIdx));
     585        int dummyThisArgument = op == Call ? 0 : 1;
     586        for (int i = 0 + dummyThisArgument; i < argCount; ++i)
     587            addVarArgChild(get(registerOffset + argumentToOperand(i)));
     588
    585589        NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
    586590        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
    587591            set(putInstruction[1].u.operand, call);
    588         if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
    589             m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
    590592        return call;
    591593    }
     
    896898        callType = UnknownFunction;
    897899    if (callType != UnknownFunction) {
    898         int argCount = currentInstruction[2].u.operand;
     900        int argumentCountIncludingThis = currentInstruction[2].u.operand;
    899901        int registerOffset = currentInstruction[3].u.operand;
    900         int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
    901         int lastArg = firstArg + argCount - 1;
    902                
     902
    903903        // Do we have a result?
    904904        bool usesResult = false;
     
    931931                addToGraph(CheckFunction, OpInfo(expectedFunction), callTarget);
    932932           
    933             if (handleIntrinsic(usesResult, resultOperand, intrinsic, firstArg, lastArg, prediction)) {
     933            if (handleIntrinsic(usesResult, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) {
    934934                if (!certainAboutExpectedFunction) {
    935935                    // Need to keep the call target alive for OSR. We could easily optimize this out if we wanted
     
    941941                return;
    942942            }
    943         } else if (handleInlining(usesResult, currentInstruction[1].u.operand, callTarget, resultOperand, certainAboutExpectedFunction, expectedFunction, firstArg, lastArg, nextOffset, kind))
     943        } else if (handleInlining(usesResult, currentInstruction[1].u.operand, callTarget, resultOperand, certainAboutExpectedFunction, expectedFunction, registerOffset, argumentCountIncludingThis, nextOffset, kind))
    944944            return;
    945945    }
     
    948948}
    949949
    950 bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction* expectedFunction, int firstArg, int lastArg, unsigned nextOffset, CodeSpecializationKind kind)
     950bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction* expectedFunction, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind)
    951951{
    952952    // First, the really simple checks: do we have an actual JS function?
     
    960960    // Does the number of arguments we're passing match the arity of the target? We could
    961961    // inline arity check failures, but for simplicity we currently don't.
    962     if (static_cast<int>(executable->parameterCount()) + 1 != lastArg - firstArg + 1)
     962    if (static_cast<int>(executable->parameterCount()) + 1 != argumentCountIncludingThis)
    963963        return false;
    964964   
     
    10011001    // FIXME: Don't flush constants!
    10021002   
    1003     for (int arg = firstArg + 1; arg <= lastArg; ++arg)
    1004         flush(arg);
    1005    
    1006     int inlineCallFrameStart = m_inlineStackTop->remapOperand(lastArg) + 1;
     1003    for (int i = 1; i < argumentCountIncludingThis; ++i)
     1004        flush(registerOffset + argumentToOperand(i));
     1005   
     1006    int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize;
    10071007   
    10081008    // Make sure that the area used by the call frame is reserved.
     
    11241124}
    11251125
    1126 bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg)
     1126bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis)
    11271127{
    11281128    if (!usesResult)
    11291129        return true;
    11301130
    1131     if (lastArg == firstArg) {
     1131    if (argumentCountIncludingThis == 1) { // Math.min()
    11321132        set(resultOperand, constantNaN());
    11331133        return true;
    11341134    }
    11351135     
    1136     if (lastArg == firstArg + 1) {
    1137         set(resultOperand, getToNumber(firstArg + 1));
     1136    if (argumentCountIncludingThis == 2) { // Math.min(x)
     1137        set(resultOperand, getToNumber(registerOffset + argumentToOperand(1)));
    11381138        return true;
    11391139    }
    11401140   
    1141     if (lastArg == firstArg + 2) {
    1142         set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), getToNumber(firstArg + 1), getToNumber(firstArg + 2)));
     1141    if (argumentCountIncludingThis == 3) { // Math.min(x, y)
     1142        set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), getToNumber(registerOffset + argumentToOperand(1)), getToNumber(registerOffset + argumentToOperand(2))));
    11431143        return true;
    11441144    }
     
    11481148}
    11491149
    1150 bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int firstArg, int lastArg, PredictedType prediction)
     1150// FIXME: We dead-code-eliminate unused Math intrinsics, but that's invalid because
     1151// they need to perform the ToNumber conversion, which can have side-effects.
     1152bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction)
    11511153{
    11521154    switch (intrinsic) {
     
    11581160        }
    11591161       
    1160         // We don't care about the this argument. If we don't have a first
    1161         // argument then make this JSConstant(NaN).
    1162         int absArg = firstArg + 1;
    1163         if (absArg > lastArg) {
     1162        if (argumentCountIncludingThis == 1) { // Math.abs()
    11641163            set(resultOperand, constantNaN());
    11651164            return true;
     
    11691168            return false;
    11701169
    1171         set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(absArg)));
     1170        set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(registerOffset + argumentToOperand(1))));
    11721171        return true;
    11731172    }
    1174        
     1173
    11751174    case MinIntrinsic:
    1176         return handleMinMax(usesResult, resultOperand, ArithMin, firstArg, lastArg);
     1175        return handleMinMax(usesResult, resultOperand, ArithMin, registerOffset, argumentCountIncludingThis);
    11771176       
    11781177    case MaxIntrinsic:
    1179         return handleMinMax(usesResult, resultOperand, ArithMax, firstArg, lastArg);
     1178        return handleMinMax(usesResult, resultOperand, ArithMax, registerOffset, argumentCountIncludingThis);
    11801179       
    11811180    case SqrtIntrinsic: {
     
    11831182            return true;
    11841183       
    1185         if (firstArg == lastArg) {
     1184        if (argumentCountIncludingThis == 1) { // Math.sqrt()
    11861185            set(resultOperand, constantNaN());
    11871186            return true;
     
    11911190            return false;
    11921191       
    1193         set(resultOperand, addToGraph(ArithSqrt, getToNumber(firstArg + 1)));
     1192        set(resultOperand, addToGraph(ArithSqrt, getToNumber(registerOffset + argumentToOperand(1))));
    11941193        return true;
    11951194    }
    11961195       
    11971196    case ArrayPushIntrinsic: {
    1198         if (firstArg + 1 != lastArg)
     1197        if (argumentCountIncludingThis != 2)
    11991198            return false;
    12001199       
    1201         NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(0), OpInfo(prediction), get(firstArg), get(firstArg + 1));
     1200        NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
    12021201        if (usesResult)
    12031202            set(resultOperand, arrayPush);
     
    12071206       
    12081207    case ArrayPopIntrinsic: {
    1209         if (firstArg != lastArg)
     1208        if (argumentCountIncludingThis != 1)
    12101209            return false;
    12111210       
    1212         NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get(firstArg));
     1211        NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)));
    12131212        if (usesResult)
    12141213            set(resultOperand, arrayPop);
     
    12171216
    12181217    case CharCodeAtIntrinsic: {
    1219         if (firstArg + 1 != lastArg)
     1218        if (argumentCountIncludingThis != 2)
    12201219            return false;
    1221         if (!(m_graph[get(firstArg)].prediction() & PredictString))
     1220
     1221        int thisOperand = registerOffset + argumentToOperand(0);
     1222        if (!(m_graph[get(thisOperand)].prediction() & PredictString))
    12221223            return false;
    12231224       
    1224         NodeIndex storage = addToGraph(GetIndexedPropertyStorage, get(firstArg), getToInt32(firstArg + 1));
    1225         NodeIndex charCode = addToGraph(StringCharCodeAt, get(firstArg), getToInt32(firstArg + 1), storage);
     1225        int indexOperand = registerOffset + argumentToOperand(1);
     1226        NodeIndex storage = addToGraph(GetIndexedPropertyStorage, get(thisOperand), getToInt32(indexOperand));
     1227        NodeIndex charCode = addToGraph(StringCharCodeAt, get(thisOperand), getToInt32(indexOperand), storage);
     1228
    12261229        if (usesResult)
    12271230            set(resultOperand, charCode);
     
    12301233
    12311234    case CharAtIntrinsic: {
    1232         if (firstArg + 1 != lastArg)
     1235        if (argumentCountIncludingThis != 2)
    12331236            return false;
    1234         if (!(m_graph[get(firstArg)].prediction() & PredictString))
     1237
     1238        int thisOperand = registerOffset + argumentToOperand(0);
     1239        if (!(m_graph[get(thisOperand)].prediction() & PredictString))
    12351240            return false;
    12361241
    1237         NodeIndex storage = addToGraph(GetIndexedPropertyStorage, get(firstArg), getToInt32(firstArg + 1));
    1238         NodeIndex charCode = addToGraph(StringCharAt, get(firstArg), getToInt32(firstArg + 1), storage);
     1242        int indexOperand = registerOffset + argumentToOperand(1);
     1243        NodeIndex storage = addToGraph(GetIndexedPropertyStorage, get(thisOperand), getToInt32(indexOperand));
     1244        NodeIndex charCode = addToGraph(StringCharAt, get(thisOperand), getToInt32(indexOperand), storage);
     1245
    12391246        if (usesResult)
    12401247            set(resultOperand, charCode);
     
    12681275        m_graph.m_arguments.resize(m_numArguments);
    12691276        for (unsigned argument = 0; argument < m_numArguments; ++argument) {
    1270             NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argument - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize)));
     1277            NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argumentToOperand(argument))));
    12711278            m_graph.m_arguments[argument] = setArgument;
    12721279            m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, setArgument);
     
    22082215#endif
    22092216
    2210                 valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? varNo - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize : varNo)));
     2217                valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? argumentToOperand(varNo) : static_cast<int>(varNo))));
    22112218                var = valueInPredecessor;
    22122219                if (stackType == ArgumentPhiStack)
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r100975 r102545  
    218218        int operand = variableAccessData->operand();
    219219        if (operandIsArgument(operand))
    220             printf("%sarg%u(%s)", hasPrinted ? ", " : "", operand - codeBlock->thisRegister(), nameOfVariableAccessData(variableAccessData));
     220            printf("%sarg%u(%s)", hasPrinted ? ", " : "", operandToArgument(operand), nameOfVariableAccessData(variableAccessData));
    221221        else
    222222            printf("%sr%u(%s)", hasPrinted ? ", " : "", operand, nameOfVariableAccessData(variableAccessData));
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r100315 r102545  
    198198            if (!operandIsArgument(node.local()))
    199199                return 0;
    200             int argument = node.local() + m_arguments.size() + RegisterFile::CallFrameHeaderSize;
     200            int argument = operandToArgument(node.local());
    201201            if (node.variableAccessData() != at(m_arguments[argument]).variableAccessData())
    202202                return 0;
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r101283 r102545  
    257257
    258258    load32(Address(GPRInfo::callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))), GPRInfo::regT1);
    259     branch32(Equal, GPRInfo::regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(fromArityCheck, this);
     259    branch32(AboveOrEqual, GPRInfo::regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(fromArityCheck, this);
    260260    move(stackPointerRegister, GPRInfo::argumentGPR0);
    261261    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h

    r99787 r102545  
    3535#include "DFGCorrectableJumpPoint.h"
    3636#include "DFGGPRInfo.h"
     37#include "DFGOperands.h"
    3738#include "MacroAssembler.h"
    3839#include "ValueProfile.h"
     
    113114        return index - m_arguments.size();
    114115    }
    115     int operandForArgument(int argument) const
    116     {
    117         return argument - m_arguments.size() - RegisterFile::CallFrameHeaderSize;
    118     }
    119116    int operandForIndex(int index) const
    120117    {
    121118        if (index < (int)m_arguments.size())
    122             return operandForArgument(index);
     119            return operandToArgument(index);
    123120        return index - m_arguments.size();
    124121    }
  • trunk/Source/JavaScriptCore/dfg/DFGOperands.h

    r100975 r102545  
    3131#if ENABLE(DFG_JIT)
    3232
     33#include "CallFrame.h"
    3334#include <wtf/Vector.h>
    3435
    3536namespace JSC { namespace DFG {
    3637
    37 // helper function to distinguish vars & temporaries from arguments.
     38// argument 0 is 'this'.
    3839inline bool operandIsArgument(int operand) { return operand < 0; }
     40inline int operandToArgument(int operand) { return -operand + CallFrame::thisArgumentOffset(); }
     41inline int argumentToOperand(int argument) { return -argument + CallFrame::thisArgumentOffset(); }
    3942
    4043template<typename T> struct OperandValueTraits;
     
    106109    {
    107110        if (operandIsArgument(operand)) {
    108             int argument = operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize;
     111            int argument = operandToArgument(operand);
    109112            return m_arguments[argument];
    110113        }
     
    118121    {
    119122        if (operandIsArgument(operand)) {
    120             int argument = operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize;
     123            int argument = operandToArgument(operand);
    121124            m_arguments[argument] = value;
    122125            return;
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r101298 r102545  
    659659        }
    660660        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
    661         if (execCallee->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
     661        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->m_numParameters))
     662            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
     663        else
    662664            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
    663         else
    664             codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
    665665    }
    666666    CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r102509 r102545  
    964964            case InlineStart: {
    965965                InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
    966                 unsigned argumentsStart = inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize - inlineCallFrame->arguments.size();
    967                 for (unsigned i = 0; i < inlineCallFrame->arguments.size(); ++i) {
    968                     ValueRecovery recovery = computeValueRecoveryFor(m_variables[argumentsStart + i]);
     966                int argumentCountIncludingThis = inlineCallFrame->arguments.size();
     967                for (int i = 0; i < argumentCountIncludingThis; ++i) {
     968                    ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
    969969                    // The recovery cannot point to registers, since the call frame reification isn't
    970970                    // as smart as OSR, so it can't handle that. The exception is the this argument,
     
    10211021       
    10221022#if DFG_ENABLE(VERBOSE_VALUE_RECOVERIES)
    1023         for (int operand = -m_arguments.size() - RegisterFile::CallFrameHeaderSize; operand < -RegisterFile::CallFrameHeaderSize; ++operand)
    1024             computeValueRecoveryFor(operand).dump(stderr);
     1023        for (size_t i = 0; i < m_arguments.size(); ++i)
     1024            computeValueRecoveryFor(argumentToOperand(i)).dump(stderr);
    10251025       
    10261026        fprintf(stderr, " : ");
     
    10551055   
    10561056    for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
    1057         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
    1058         PredictedType predictedType = at(m_jit.graph().m_arguments[i]).variableAccessData()->prediction();
     1057        VariableAccessData* variableAccessData = at(m_jit.graph().m_arguments[i]).variableAccessData();
     1058        VirtualRegister virtualRegister = variableAccessData->local();
     1059        PredictedType predictedType = variableAccessData->prediction();
    10591060#if USE(JSVALUE64)
    10601061        if (isInt32Prediction(predictedType))
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r102442 r102545  
    891891    void compileInstanceOf(Node&);
    892892   
    893     MacroAssembler::Address addressOfCallData(int idx)
    894     {
    895         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + idx) * static_cast<int>(sizeof(Register)));
     893    // Access to our fixed callee CallFrame.
     894    MacroAssembler::Address callFrameSlot(int slot)
     895    {
     896        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)));
     897    }
     898
     899    // Access to our fixed callee CallFrame.
     900    MacroAssembler::Address argumentSlot(int argument)
     901    {
     902        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)));
    896903    }
    897904
    898905#if USE(JSVALUE32_64)   
    899     MacroAssembler::Address tagOfCallData(int idx)
    900     {
    901         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + idx) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
    902     }
    903 
    904     MacroAssembler::Address payloadOfCallData(int idx)
    905     {
    906         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + idx) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     906    MacroAssembler::Address callFrameTagSlot(int slot)
     907    {
     908        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
     909    }
     910
     911    MacroAssembler::Address callFramePayloadSlot(int slot)
     912    {
     913        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     914    }
     915
     916    MacroAssembler::Address argumentTagSlot(int argument)
     917    {
     918        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
     919    }
     920
     921    MacroAssembler::Address argumentPayloadSlot(int argument)
     922    {
     923        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
    907924    }
    908925#endif
     
    10461063    // correct registers.
    10471064#if !NUMBER_OF_ARGUMENT_REGISTERS
    1048     unsigned m_callArgumentIndex;
    1049     void resetCallArguments() { m_callArgumentIndex = 0; }
     1065    unsigned m_callArgumentOffset;
     1066    void resetCallArguments() { m_callArgumentOffset = 0; }
    10501067
    10511068    // These methods are using internally to implement the callOperation methods.
    10521069    void addCallArgument(GPRReg value)
    10531070    {
    1054         m_jit.poke(value, m_callArgumentIndex++);
     1071        m_jit.poke(value, m_callArgumentOffset++);
    10551072    }
    10561073    void addCallArgument(TrustedImm32 imm)
    10571074    {
    1058         m_jit.poke(imm, m_callArgumentIndex++);
     1075        m_jit.poke(imm, m_callArgumentOffset++);
    10591076    }
    10601077    void addCallArgument(TrustedImmPtr pointer)
    10611078    {
    1062         m_jit.poke(pointer, m_callArgumentIndex++);
     1079        m_jit.poke(pointer, m_callArgumentOffset++);
    10631080    }
    10641081    void addCallArgument(FPRReg value)
    10651082    {
    1066         m_jit.storeDouble(value, JITCompiler::Address(JITCompiler::stackPointerRegister, m_callArgumentIndex * sizeof(void*)));
    1067         m_callArgumentIndex += sizeof(double) / sizeof(void*);
     1083        m_jit.storeDouble(value, JITCompiler::Address(JITCompiler::stackPointerRegister, m_callArgumentOffset * sizeof(void*)));
     1084        m_callArgumentOffset += sizeof(double) / sizeof(void*);
    10681085    }
    10691086
     
    20762093    {
    20772094        if (operandIsArgument(operand)) {
    2078             int argument = operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize;
     2095            int argument = operandToArgument(operand);
    20792096            return m_arguments[argument];
    20802097        }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r102442 r102545  
    12591259    use(calleeNodeIndex);
    12601260
    1261     // the call instruction's first child is either the function (normal call) or the
     1261    // The call instruction's first child is either the function (normal call) or the
    12621262    // receiver (method call). subsequent children are the arguments.
    1263     int numArgs = node.numChildren() - 1;
    1264 
    1265     // For constructors, the this argument is not passed but we have to make space
    1266     // for it.
    1267     int numPassedArgs = numArgs + dummyThisArgument;
    1268 
    1269     // amount of stuff (in units of sizeof(Register)) that we need to place at the
    1270     // top of the JS stack.
    1271     int callDataSize = 0;
    1272 
    1273     // first there are the arguments
    1274     callDataSize += numPassedArgs;
    1275 
    1276     // and then there is the call frame header
    1277     callDataSize += RegisterFile::CallFrameHeaderSize;
    1278 
    1279     m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), payloadOfCallData(RegisterFile::ArgumentCount));
    1280     m_jit.store32(MacroAssembler::TrustedImm32(JSValue::Int32Tag), tagOfCallData(RegisterFile::ArgumentCount));
    1281     m_jit.storePtr(GPRInfo::callFrameRegister, payloadOfCallData(RegisterFile::CallerFrame));
    1282     m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), tagOfCallData(RegisterFile::CallerFrame));
    1283 
    1284     for (int argIdx = 0; argIdx < numArgs; argIdx++) {
    1285         NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + argIdx];
     1263    int numPassedArgs = node.numChildren() - 1;
     1264
     1265    m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(RegisterFile::ArgumentCount));
     1266    m_jit.store32(MacroAssembler::TrustedImm32(JSValue::Int32Tag), callFrameTagSlot(RegisterFile::ArgumentCount));
     1267    m_jit.storePtr(GPRInfo::callFrameRegister, callFramePayloadSlot(RegisterFile::CallerFrame));
     1268    m_jit.store32(calleePayloadGPR, callFramePayloadSlot(RegisterFile::Callee));
     1269    m_jit.store32(calleeTagGPR, callFrameTagSlot(RegisterFile::Callee));
     1270
     1271    for (int i = 0; i < numPassedArgs; i++) {
     1272        NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i];
    12861273        JSValueOperand arg(this, argNodeIndex);
    12871274        GPRReg argTagGPR = arg.tagGPR();
     
    12891276        use(argNodeIndex);
    12901277
    1291         m_jit.store32(argTagGPR, tagOfCallData(-callDataSize + argIdx + dummyThisArgument));
    1292         m_jit.store32(argPayloadGPR, payloadOfCallData(-callDataSize + argIdx + dummyThisArgument));
    1293     }
    1294 
    1295     m_jit.store32(calleeTagGPR, tagOfCallData(RegisterFile::Callee));
    1296     m_jit.store32(calleePayloadGPR, payloadOfCallData(RegisterFile::Callee));
     1278        m_jit.store32(argTagGPR, argumentTagSlot(i + dummyThisArgument));
     1279        m_jit.store32(argPayloadGPR, argumentPayloadSlot(i + dummyThisArgument));
     1280    }
    12971281
    12981282    flushRegisters();
     
    13091293    slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, calleeTagGPR, TrustedImm32(JSValue::CellTag)));
    13101294    m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultPayloadGPR);
    1311     m_jit.storePtr(resultPayloadGPR, payloadOfCallData(RegisterFile::ScopeChain));
    1312     m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), tagOfCallData(RegisterFile::ScopeChain));
     1295    m_jit.storePtr(resultPayloadGPR, callFramePayloadSlot(RegisterFile::ScopeChain));
     1296    m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), callFrameTagSlot(RegisterFile::ScopeChain));
    13131297
    13141298    m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r102442 r102545  
    12181218    use(calleeNodeIndex);
    12191219   
    1220     // the call instruction's first child is either the function (normal call) or the
     1220    // The call instruction's first child is either the function (normal call) or the
    12211221    // receiver (method call). subsequent children are the arguments.
    1222     int numArgs = node.numChildren() - 1;
    1223    
    1224     int numPassedArgs = numArgs + dummyThisArgument;
    1225    
    1226     // amount of stuff (in units of sizeof(Register)) that we need to place at the
    1227     // top of the JS stack.
    1228     int callDataSize = 0;
    1229 
    1230     // first there are the arguments
    1231     callDataSize += numPassedArgs;
    1232    
    1233     // and then there is the call frame header
    1234     callDataSize += RegisterFile::CallFrameHeaderSize;
    1235    
    1236     m_jit.storePtr(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(numPassedArgs))), addressOfCallData(RegisterFile::ArgumentCount));
    1237     m_jit.storePtr(GPRInfo::callFrameRegister, addressOfCallData(RegisterFile::CallerFrame));
    1238    
    1239     for (int argIdx = 0; argIdx < numArgs; argIdx++) {
    1240         NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + argIdx];
     1222    int numPassedArgs = node.numChildren() - 1;
     1223   
     1224    m_jit.storePtr(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(numPassedArgs + dummyThisArgument))), callFrameSlot(RegisterFile::ArgumentCount));
     1225    m_jit.storePtr(GPRInfo::callFrameRegister, callFrameSlot(RegisterFile::CallerFrame));
     1226    m_jit.storePtr(calleeGPR, callFrameSlot(RegisterFile::Callee));
     1227   
     1228    for (int i = 0; i < numPassedArgs; i++) {
     1229        NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i];
    12411230        JSValueOperand arg(this, argNodeIndex);
    12421231        GPRReg argGPR = arg.gpr();
    12431232        use(argNodeIndex);
    12441233       
    1245         m_jit.storePtr(argGPR, addressOfCallData(-callDataSize + argIdx + dummyThisArgument));
    1246     }
    1247    
    1248     m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
    1249    
     1234        m_jit.storePtr(argGPR, argumentSlot(i + dummyThisArgument));
     1235    }
     1236
    12501237    flushRegisters();
    1251    
     1238
    12521239    GPRResult result(this);
    12531240    GPRReg resultGPR = result.gpr();
     
    12551242    JITCompiler::DataLabelPtr targetToCheck;
    12561243    JITCompiler::Jump slowPath;
    1257    
     1244
    12581245    slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
    12591246    m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
    1260     m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
     1247    m_jit.storePtr(resultGPR, callFrameSlot(RegisterFile::ScopeChain));
    12611248
    12621249    m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
  • trunk/Source/JavaScriptCore/interpreter/CallFrame.h

    r99148 r102545  
    144144
    145145        // Access to arguments.
    146         int hostThisRegister() { return -RegisterFile::CallFrameHeaderSize - argumentCountIncludingThis(); }
    147         JSValue hostThisValue() { return this[hostThisRegister()].jsValue(); }
    148146        size_t argumentCount() const { return argumentCountIncludingThis() - 1; }
    149147        size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].i(); }
    150         JSValue argument(int argumentNumber)
    151         {
    152             int argumentIndex = -RegisterFile::CallFrameHeaderSize - this[RegisterFile::ArgumentCount].i() + argumentNumber + 1;
    153             if (argumentIndex >= -RegisterFile::CallFrameHeaderSize)
    154                 return jsUndefined();
    155             return this[argumentIndex].jsValue();
    156         }
     148        static int argumentOffset(size_t argument) { return s_firstArgumentOffset - argument; }
     149        static int argumentOffsetIncludingThis(size_t argument) { return s_thisArgumentOffset - argument; }
     150
     151        JSValue argument(size_t argument)
     152        {
     153            if (argument >= argumentCount())
     154                 return jsUndefined();
     155            return this[argumentOffset(argument)].jsValue();
     156        }
     157        void setArgument(size_t argument, JSValue value)
     158        {
     159            this[argumentOffset(argument)] = value;
     160        }
     161
     162        static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); }
     163        JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); }
     164        void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; }
     165
     166        static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize; }
     167
     168        // FIXME: Remove these.
     169        int hostThisRegister() { return thisArgumentOffset(); }
     170        JSValue hostThisValue() { return thisValue(); }
    157171
    158172        static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
     
    183197    private:
    184198        static const intptr_t HostCallFrameFlag = 1;
     199        static const int s_thisArgumentOffset = -1 - RegisterFile::CallFrameHeaderSize;
     200        static const int s_firstArgumentOffset = s_thisArgumentOffset - 1;
     201
    185202#ifndef NDEBUG
    186203        RegisterFile* registerFile();
  • trunk/Source/JavaScriptCore/interpreter/CallFrameClosure.h

    r100540 r102545  
    4242    void setThis(JSValue value)
    4343    {
    44         newCallFrame[-RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis] = value;
    45         if (argumentCountIncludingThis > parameterCountIncludingThis)
    46             newCallFrame[-RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis - argumentCountIncludingThis] = value;
     44        newCallFrame->setThisValue(value);
    4745    }
    4846
    4947    void setArgument(int argument, JSValue value)
    5048    {
    51         if (argument + 1 < parameterCountIncludingThis)
    52             newCallFrame[argument + 1 - RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis] = value;
    53 
    54         if (argumentCountIncludingThis > parameterCountIncludingThis)
    55             newCallFrame[argument + 1 - RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis - argumentCountIncludingThis] = value;
     49        newCallFrame->setArgument(argument, value);
    5650    }
    5751
     
    6054        newCallFrame->setScopeChain(scopeChain);
    6155        for (int i = argumentCountIncludingThis; i < parameterCountIncludingThis; ++i)
    62             newCallFrame[i - RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis] = jsUndefined();
     56            newCallFrame->setArgument(i, jsUndefined());
    6357    }
    6458};
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r102194 r102545  
    368368#endif // ENABLE(INTERPRETER)
    369369
    370 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
     370ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argumentCountIncludingThis)
    371371{
    372     Register* r = callFrame->registers();
    373     Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
    374 
    375     if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
    376         if (UNLIKELY(!registerFile->grow(newEnd)))
    377             return 0;
    378         r += registerOffset;
    379     } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
    380         size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
    381         registerOffset += omittedArgCount;
    382         newEnd += omittedArgCount;
    383         if (!registerFile->grow(newEnd))
    384             return 0;
    385         r += registerOffset;
    386 
    387         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
    388         for (size_t i = 0; i < omittedArgCount; ++i)
    389             argv[i] = jsUndefined();
    390     } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
    391         size_t numParameters = newCodeBlock->m_numParameters;
    392         registerOffset += numParameters;
    393         newEnd += numParameters;
    394 
    395         if (!registerFile->grow(newEnd))
    396             return 0;
    397         r += registerOffset;
    398 
    399         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
    400         for (size_t i = 0; i < numParameters; ++i)
    401             argv[i + argc] = argv[i];
    402     }
    403 
    404     return CallFrame::create(r);
     372    // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
     373    if (!registerFile->grow(callFrame->registers() + registerOffset + newCodeBlock->m_numParameters + newCodeBlock->m_numCalleeRegisters))
     374        return 0;
     375
     376    if (argumentCountIncludingThis >= newCodeBlock->m_numParameters) {
     377        Register* newCallFrame = callFrame->registers() + registerOffset;
     378        return CallFrame::create(newCallFrame);
     379    }
     380
     381    // Too few arguments -- copy arguments, then fill in missing arguments with undefined.
     382    size_t delta = newCodeBlock->m_numParameters - argumentCountIncludingThis;
     383    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset + delta);
     384
     385    Register* dst = &newCallFrame->uncheckedR(CallFrame::thisArgumentOffset());
     386    Register* end = dst - argumentCountIncludingThis;
     387    for ( ; dst != end; --dst)
     388        *dst = *(dst - delta);
     389
     390    end -= delta;
     391    for ( ; dst != end; --dst)
     392        *dst = jsUndefined();
     393
     394    return newCallFrame;
    405395}
    406396
     
    464454    }
    465455
    466     JSValue thisValue = callerFrame->uncheckedR(callerCodeBlock->thisRegister()).jsValue();
     456    JSValue thisValue = callerFrame->thisValue();
    467457    ASSERT(isValidThisObject(thisValue, callFrame));
    468458    Interpreter* interpreter = callFrame->globalData().interpreter;
     
    480470        }
    481471
    482         unsigned parameterCount = callFrame->codeBlock()->m_numParameters;
    483         Register* src = callFrame->registers() - RegisterFile::CallFrameHeaderSize - parameterCount;
    484         if (argumentCountIncludingThis > parameterCount)
    485             src -= argumentCountIncludingThis;
    486         Register* dst = callFrame->registers() + firstFreeRegister;
    487         dst[0] = thisValue;
    488         for (unsigned i = 1; i < argumentCountIncludingThis; ++i)
    489             dst[i] = src[i];
    490 
    491472        newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
     473        newCallFrame->setThisValue(thisValue);
     474        for (size_t i = 0; i < callFrame->argumentCount(); ++i)
     475            newCallFrame->setArgument(i, callFrame->argument(i));
    492476        return newCallFrame;
    493477    }
     
    499483            return 0;
    500484        }
    501         Register* dst = callFrame->registers() + firstFreeRegister;
    502         dst[0] = thisValue;
    503 
    504485        newCallFrame->setArgumentCountIncludingThis(1);
     486        newCallFrame->setThisValue(thisValue);
    505487        return newCallFrame;
    506488    }
     
    519501            return 0;
    520502        }
    521         Register* dst = callFrame->registers() + firstFreeRegister;
    522         dst[0] = thisValue;
    523         argsObject->copyToRegisters(callFrame, &dst[1], argCount);
    524 
    525503        newCallFrame->setArgumentCountIncludingThis(argCount + 1);
     504        newCallFrame->setThisValue(thisValue);
     505        argsObject->copyToArguments(callFrame, newCallFrame, argCount);
    526506        return newCallFrame;
    527507    }
     
    535515            return 0;
    536516        }
    537         Register* dst = callFrame->registers() + firstFreeRegister;
    538         dst[0] = thisValue;
    539         array->copyToRegisters(callFrame, &dst[1], argCount);
    540 
    541517        newCallFrame->setArgumentCountIncludingThis(argCount + 1);
     518        newCallFrame->setThisValue(thisValue);
     519        array->copyToArguments(callFrame, newCallFrame, argCount);
    542520        return newCallFrame;
    543521    }
     
    550528        return 0;
    551529    }
    552     Register* dst = callFrame->registers() + firstFreeRegister;
    553     dst[0] = thisValue;
    554     for (unsigned i = 0; i < argCount; ++i) {
    555         dst[i + 1] = asObject(arguments)->get(callFrame, i);
     530    newCallFrame->setArgumentCountIncludingThis(argCount + 1);
     531    newCallFrame->setThisValue(thisValue);
     532    for (size_t i = 0; i < argCount; ++i) {
     533        newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i));
    556534        if (UNLIKELY(callFrame->globalData().exception))
    557535            return 0;
    558536    }
    559 
    560     newCallFrame->setArgumentCountIncludingThis(argCount + 1);
    561537    return newCallFrame;
    562538}
     
    701677    } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
    702678        if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
    703             asArguments(arguments)->tearOff(callFrame->globalData());
     679            asArguments(arguments)->tearOff(callFrame);
    704680    }
    705681
     
    986962    ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
    987963    newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0);
    988     newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
     964    newCallFrame->setThisValue(thisObj);
    989965    TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
    990966
     
    10311007    size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
    10321008
    1033     if (!m_registerFile.grow(oldEnd + registerOffset))
     1009    CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
     1010    if (!m_registerFile.grow(newCallFrame->registers()))
    10341011        return checkedReturn(throwStackOverflowError(callFrame));
    10351012
    1036     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    1037     size_t dst = 0;
    1038     newCallFrame->uncheckedR(0) = thisValue;
     1013    newCallFrame->setThisValue(thisValue);
    10391014    for (size_t i = 0; i < args.size(); ++i)
    1040         newCallFrame->uncheckedR(++dst) = args.at(i);
     1015        newCallFrame->setArgument(i, args.at(i));
    10411016
    10421017    if (callType == CallTypeJS) {
     
    10521027
    10531028        CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
    1054         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
     1029        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount);
    10551030        if (UNLIKELY(!newCallFrame)) {
    10561031            m_registerFile.shrink(oldEnd);
     
    10891064    ASSERT(callType == CallTypeHost);
    10901065    ScopeChainNode* scopeChain = callFrame->scopeChain();
    1091     newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
    10921066    newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
    10931067
     
    11321106        return checkedReturn(throwStackOverflowError(callFrame));
    11331107
    1134     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    1135     size_t dst = 0;
     1108    CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
     1109    newCallFrame->setThisValue(jsUndefined());
    11361110    for (size_t i = 0; i < args.size(); ++i)
    1137         newCallFrame->uncheckedR(++dst) = args.at(i);
     1111        newCallFrame->setArgument(i, args.at(i));
    11381112
    11391113    if (constructType == ConstructTypeJS) {
     
    11491123
    11501124        CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
    1151         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
     1125        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount);
    11521126        if (UNLIKELY(!newCallFrame)) {
    11531127            m_registerFile.shrink(oldEnd);
     
    11891163    ASSERT(constructType == ConstructTypeHost);
    11901164    ScopeChainNode* scopeChain = callFrame->scopeChain();
    1191     newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
    11921165    newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
    11931166
     
    12201193    ASSERT(!scopeChain->globalData->exception);
    12211194   
    1222     if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
    1223         if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
    1224             throwStackOverflowError(callFrame);
    1225             return CallFrameClosure();
    1226         }
    1227     }
    1228    
    1229     Register* oldEnd = m_registerFile.end();
    1230     if (!m_registerFile.grow(oldEnd + argumentCountIncludingThis)) {
     1195    if (callFrame->globalData().isCollectorBusy())
     1196        return CallFrameClosure();
     1197
     1198    if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
    12311199        throwStackOverflowError(callFrame);
    12321200        return CallFrameClosure();
    12331201    }
    12341202
    1235     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    1236     // We initialise |this| unnecessarily here for the sake of code clarity
    1237     size_t dst = 0;
    1238     for (int i = 0; i < argumentCountIncludingThis; ++i)
    1239         newCallFrame->uncheckedR(dst++) = jsUndefined();
    1240    
     1203    Register* oldEnd = m_registerFile.end();
     1204    size_t registerOffset = argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize;
     1205
     1206    CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
     1207    if (!m_registerFile.grow(newCallFrame->registers())) {
     1208        throwStackOverflowError(callFrame);
     1209        return CallFrameClosure();
     1210    }
     1211
    12411212    JSObject* error = functionExecutable->compileForCall(callFrame, scopeChain);
    12421213    if (error) {
     
    12471218    CodeBlock* codeBlock = &functionExecutable->generatedBytecodeForCall();
    12481219
    1249     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize, argumentCountIncludingThis);
     1220    newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, 0, argumentCountIncludingThis);
    12501221    if (UNLIKELY(!newCallFrame)) {
    12511222        throwStackOverflowError(callFrame);
     
    13681339    ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
    13691340    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0);
    1370     newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = thisValue;
     1341    newCallFrame->setThisValue(thisValue);
    13711342
    13721343    TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
     
    35113482        JSValue subscript = callFrame->r(property).jsValue();
    35123483        if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) {
    3513             unsigned arg = subscript.asUInt32() + 1;
    3514             unsigned numParameters = callFrame->codeBlock()->m_numParameters;
    3515             if (arg < numParameters)
    3516                 callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters);
    3517             else
    3518                 callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters - callFrame->argumentCount() - 1);
     3484            callFrame->uncheckedR(dst) = callFrame->argument(subscript.asUInt32());
    35193485            vPC += OPCODE_LENGTH(op_get_argument_by_val);
    35203486            NEXT_INSTRUCTION();
     
    43264292            ScopeChainNode* scopeChain = callFrame->scopeChain();
    43274293            CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
    4328             if (!registerFile->grow(newCallFrame->registers())) {
    4329                 exceptionValue = createStackOverflowError(callFrame);
    4330                 goto vm_throw;
    4331             }
    4332 
    43334294            newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
    43344295            JSValue returnValue;
     
    44534414        } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
    44544415            if (!codeBlock->isStrictMode())
    4455                 asArguments(argumentsValue)->tearOff(*globalData);
     4416                asArguments(argumentsValue)->tearOff(callFrame);
    44564417        }
    44574418
     
    44754436
    44764437        if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue())
    4477             asArguments(arguments)->tearOff(*globalData);
     4438            asArguments(arguments)->tearOff(callFrame);
    44784439
    44794440        vPC += OPCODE_LENGTH(op_tear_off_arguments);
     
    47284689            ScopeChainNode* scopeChain = callFrame->scopeChain();
    47294690            CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
    4730             if (!registerFile->grow(newCallFrame->registers())) {
    4731                 exceptionValue = createStackOverflowError(callFrame);
    4732                 goto vm_throw;
    4733             }
    47344691            newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, argCount, asObject(v));
    47354692
     
    51365093    }
    51375094
    5138     return Arguments::createAndTearOff(functionCallFrame->globalData(), functionCallFrame);
     5095    Arguments* arguments = Arguments::create(functionCallFrame->globalData(), functionCallFrame);
     5096    arguments->tearOff(functionCallFrame);
     5097    return JSValue(arguments);
    51395098}
    51405099
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r100540 r102545  
    8484    // We use a smaller reentrancy limit on iPhone because of the high amount of
    8585    // stack space required on the web thread.
    86     enum { MaxLargeThreadReentryDepth = 93, MaxSmallThreadReentryDepth = 32 };
     86    enum { MaxLargeThreadReentryDepth = 93, MaxSmallThreadReentryDepth = 16 };
    8787#else
    88     enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 32 };
     88    enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 16 };
    8989#endif // PLATFORM(IOS)
    9090
  • trunk/Source/JavaScriptCore/interpreter/RegisterFile.h

    r100556 r102545  
    5454            CodeBlock = -1,
    5555        };
    56 
    57         enum { ProgramCodeThisRegister = -CallFrameHeaderSize - 1 };
    5856
    5957        static const size_t defaultCapacity = 512 * 1024;
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r102489 r102545  
    558558        ASSERT(m_bytecodeOffset == (unsigned)-1);
    559559        if (shouldEmitProfiling()) {
    560             for (int argumentRegister = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters; argumentRegister < -RegisterFile::CallFrameHeaderSize; ++argumentRegister) {
     560            for (int argument = 0; argument < m_codeBlock->m_numParameters; ++argument) {
    561561                // If this is a constructor, then we want to put in a dummy profiling site (to
    562562                // keep things consistent) but we don't actually want to record the dummy value.
    563                 if (m_codeBlock->m_isConstructor
    564                     && argumentRegister == -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters)
     563                if (m_codeBlock->m_isConstructor && !argument)
    565564                    m_codeBlock->addValueProfile(-1);
    566565                else {
     566                    int offset = CallFrame::argumentOffsetIncludingThis(argument) * static_cast<int>(sizeof(Register));
    567567#if USE(JSVALUE64)
    568                     loadPtr(Address(callFrameRegister, argumentRegister * sizeof(Register)), regT0);
     568                    loadPtr(Address(callFrameRegister, offset), regT0);
    569569#elif USE(JSVALUE32_64)
    570                     load32(Address(callFrameRegister, argumentRegister * sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
    571                     load32(Address(callFrameRegister, argumentRegister * sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
     570                    load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
     571                    load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
    572572#endif
    573573                    emitValueProfilingSite(FirstProfilingSite);
     
    608608
    609609        load32(Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))), regT1);
    610         branch32(Equal, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this);
     610        branch32(AboveOrEqual, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this);
    611611
    612612        JITStubCall(this, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck).call(callFrameRegister);
  • trunk/Source/JavaScriptCore/jit/JITCall.cpp

    r100165 r102545  
    6565    JumpList slowCase;
    6666    JumpList end;
    67     if (m_codeBlock->usesArguments()
    68         && arguments == m_codeBlock->argumentsRegister()
    69         && m_codeBlock->m_numParameters == 1) {
     67    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) {
    7068        emitGetVirtualRegister(arguments, regT0);
    7169        slowCase.append(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
     
    8785        storePtr(regT2, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
    8886
    89         // Initialize 'this' and copy arguments.
     87        // Initialize 'this'.
     88        emitGetVirtualRegister(thisValue, regT2);
     89        storePtr(regT2, Address(regT1, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))));
     90
     91        // Copy arguments.
    9092        neg32(regT0);
    9193        signExtend32ToPtr(regT0, regT0);
    92         emitGetVirtualRegister(thisValue, regT2);
    93         storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
    9494        end.append(branchAddPtr(Zero, Imm32(1), regT0));
     95        // regT0: -argumentCount
    9596
    9697        Label copyLoop = label();
    97         loadPtr(BaseIndex(callFrameRegister, regT0, TimesEight, -((RegisterFile::CallFrameHeaderSize + 1) * static_cast<int>(sizeof(Register)))), regT2);
    98         storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
     98        loadPtr(BaseIndex(callFrameRegister, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT2);
     99        storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))));
    99100        branchAddPtr(NonZero, Imm32(1), regT0).linkTo(copyLoop, this);
    100101
     
    102103    }
    103104
    104     if (m_codeBlock->m_numParameters == 1)
     105    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
    105106        slowCase.link(this);
    106107
     
    111112    stubCall.call(regT1);
    112113
    113     if (m_codeBlock->m_numParameters == 1)
     114    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
    114115        end.link(this);
    115116}
  • trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp

    r100165 r102545  
    146146    JumpList slowCase;
    147147    JumpList end;
    148     if (m_codeBlock->usesArguments()
    149         && arguments == m_codeBlock->argumentsRegister()
    150         && m_codeBlock->m_numParameters == 1) {
     148    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) {
    151149        emitLoadTag(arguments, regT1);
    152150        slowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)));
     
    168166        store32(regT2, payloadFor(RegisterFile::ArgumentCount, regT3));
    169167
    170         // Initialize 'this' and copy arguments.
     168        // Initialize 'this'.
     169        emitLoad(thisValue, regT1, regT0);
     170        store32(regT0, Address(regT3, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
     171        store32(regT1, Address(regT3, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
     172
     173        // Copy arguments.
    171174        neg32(regT2);
    172         emitLoad(thisValue, regT1, regT0);
    173         store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
    174         store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
    175175        end.append(branchAdd32(Zero, Imm32(1), regT2));
     176        // regT2: -argumentCount;
    176177
    177178        Label copyLoop = label();
    178         load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) -((RegisterFile::CallFrameHeaderSize + 1) * static_cast<int>(sizeof(Register)))), regT0);
    179         load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) -((RegisterFile::CallFrameHeaderSize + 1) * static_cast<int>(sizeof(Register)))), regT1);
    180         store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
    181         store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
     179        load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))), regT0);
     180        load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))), regT1);
     181        store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
     182        store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
    182183        branchAdd32(NonZero, Imm32(1), regT2).linkTo(copyLoop, this);
    183184
     
    185186    }
    186187
    187     if (m_codeBlock->m_numParameters == 1)
     188    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
    188189        slowCase.link(this);
    189190
     
    194195    stubCall.call(regT3);
    195196
    196     if (m_codeBlock->m_numParameters == 1)
     197    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
    197198        end.link(this);
    198199}
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r100165 r102545  
    11851185
    11861186    Jump argsCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
    1187     if (m_codeBlock->m_numParameters == 1)
    1188         JITStubCall(this, cti_op_create_arguments_no_params).call();
    1189     else
    1190         JITStubCall(this, cti_op_create_arguments).call();
     1187    JITStubCall(this, cti_op_create_arguments).call();
    11911188    emitPutVirtualRegister(dst);
    11921189    emitPutVirtualRegister(unmodifiedArgumentsRegister(dst));
     
    14921489    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2);
    14931490    addSlowCase(branch32(AboveOrEqual, regT1, regT2));
    1494    
    1495     Jump skipOutofLineParams;
    1496     int numArgs = m_codeBlock->m_numParameters;
    1497     if (numArgs) {
    1498         Jump notInInPlaceArgs = branch32(AboveOrEqual, regT1, Imm32(numArgs));
    1499         addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0);
    1500         loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0);
    1501         skipOutofLineParams = jump();
    1502         notInInPlaceArgs.link(this);
    1503     }
    1504    
    1505     addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0);
    1506     mul32(TrustedImm32(sizeof(Register)), regT2, regT2);
    1507     subPtr(regT2, regT0);
    1508     loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0);
    1509     if (numArgs)
    1510         skipOutofLineParams.link(this);
     1491
     1492    neg32(regT1);
     1493    signExtend32ToPtr(regT1, regT1);
     1494    loadPtr(BaseIndex(callFrameRegister, regT1, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
    15111495    emitPutVirtualRegister(dst, regT0);
    15121496}
     
    15231507    linkSlowCase(iter);
    15241508    linkSlowCase(iter);
    1525     if (m_codeBlock->m_numParameters == 1)
    1526         JITStubCall(this, cti_op_create_arguments_no_params).call();
    1527     else
    1528         JITStubCall(this, cti_op_create_arguments).call();
     1509    JITStubCall(this, cti_op_create_arguments).call();
    15291510    emitPutVirtualRegister(arguments);
    15301511    emitPutVirtualRegister(unmodifiedArgumentsRegister(arguments));
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r100881 r102545  
    14631463    Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
    14641464
    1465     if (m_codeBlock->m_numParameters == 1)
    1466         JITStubCall(this, cti_op_create_arguments_no_params).call();
    1467     else
    1468         JITStubCall(this, cti_op_create_arguments).call();
    1469 
     1465    JITStubCall(this, cti_op_create_arguments).call();
    14701466    emitStore(dst, regT1, regT0);
    14711467    emitStore(unmodifiedArgumentsRegister(dst), regT1, regT0);
     
    16111607    addSlowCase(branch32(AboveOrEqual, regT2, regT3));
    16121608   
    1613     Jump skipOutofLineParams;
    1614     int numArgs = m_codeBlock->m_numParameters;
    1615     if (numArgs) {
    1616         Jump notInInPlaceArgs = branch32(AboveOrEqual, regT2, Imm32(numArgs));
    1617         addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1);
    1618         loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
    1619         loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
    1620         skipOutofLineParams = jump();
    1621         notInInPlaceArgs.link(this);
    1622     }
    1623 
    1624     addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1);
    1625     mul32(TrustedImm32(sizeof(Register)), regT3, regT3);
    1626     subPtr(regT3, regT1);
    1627     loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
    1628     loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
    1629     if (numArgs)
    1630         skipOutofLineParams.link(this);
     1609    neg32(regT2);
     1610    loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
     1611    loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT1);
    16311612    emitStore(dst, regT1, regT0);
    16321613}
     
    16431624    linkSlowCase(iter);
    16441625    linkSlowCase(iter);
    1645     if (m_codeBlock->m_numParameters == 1)
    1646         JITStubCall(this, cti_op_create_arguments_no_params).call();
    1647     else
    1648         JITStubCall(this, cti_op_create_arguments).call();
    1649    
     1626    JITStubCall(this, cti_op_create_arguments).call();
    16501627    emitStore(arguments, regT1, regT0);
    16511628    emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0);
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r102167 r102545  
    22022202}
    22032203
     2204static size_t debugCount[5];
     2205struct DebugCounter {
     2206    ~DebugCounter()
     2207    {
     2208        for (size_t i = 0; i < 5; ++i)
     2209            fprintf(stderr, "DebugCounter[%ld]: %ld\n", i, debugCount[i]);
     2210    }
     2211    void count(int delta) { ++debugCount[std::min(4, delta)]; }
     2212};
     2213
     2214DebugCounter debugCounter;
     2215
    22042216inline CallFrame* arityCheckFor(CallFrame* callFrame, RegisterFile* registerFile, CodeSpecializationKind kind)
    22052217{
     
    22072219    ASSERT(!callee->isHostFunction());
    22082220    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
    2209     int argCount = callFrame->argumentCountIncludingThis();
    2210     ReturnAddressPtr pc = callFrame->returnPC();
    2211 
    2212     ASSERT(argCount != newCodeBlock->m_numParameters);
    2213 
    2214     CallFrame* oldCallFrame = callFrame->callerFrame();
    2215 
    2216     Register* r;
    2217     if (argCount > newCodeBlock->m_numParameters) {
    2218         size_t numParameters = newCodeBlock->m_numParameters;
    2219         r = callFrame->registers() + numParameters;
    2220         Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
    2221         if (!registerFile->grow(newEnd))
    2222             return 0;
    2223 
    2224         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
    2225         for (size_t i = 0; i < numParameters; ++i)
    2226             argv[i + argCount] = argv[i];
    2227     } else {
    2228         size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
    2229         r = callFrame->registers() + omittedArgCount;
    2230         Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
    2231         if (!registerFile->grow(newEnd))
    2232             return 0;
    2233 
    2234         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
    2235         for (size_t i = 0; i < omittedArgCount; ++i)
    2236             argv[i] = jsUndefined();
    2237     }
    2238 
    2239     callFrame = CallFrame::create(r);
    2240     callFrame->setCallerFrame(oldCallFrame);
    2241     callFrame->setArgumentCountIncludingThis(argCount);
    2242     callFrame->setCallee(callee);
    2243     callFrame->setScopeChain(callee->scope());
    2244     callFrame->setReturnPC(pc.value());
    2245     callFrame->setCodeBlock(newCodeBlock);
    2246 
    2247     ASSERT((void*)callFrame <= registerFile->end());
    2248     return callFrame;
     2221    int argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
     2222
     2223    // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
     2224    if (!registerFile->grow(callFrame->registers() + newCodeBlock->m_numParameters + newCodeBlock->m_numCalleeRegisters))
     2225        return 0;
     2226
     2227    ASSERT(argumentCountIncludingThis < newCodeBlock->m_numParameters);
     2228
     2229    debugCounter.count(newCodeBlock->m_numParameters - argumentCountIncludingThis);
     2230
     2231    // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
     2232    size_t delta = newCodeBlock->m_numParameters - argumentCountIncludingThis;
     2233    Register* src = callFrame->registers();
     2234    Register* dst = callFrame->registers() + delta;
     2235
     2236    int i;
     2237    int end = -CallFrame::offsetFor(argumentCountIncludingThis);
     2238    for (i = -1; i >= end; --i)
     2239        dst[i] = src[i];
     2240
     2241    end -= delta;
     2242    for ( ; i >= end; --i)
     2243        dst[i] = jsUndefined();
     2244
     2245    CallFrame* newCallFrame = CallFrame::create(dst);
     2246    ASSERT((void*)newCallFrame <= registerFile->end());
     2247    return newCallFrame;
    22492248}
    22502249
     
    22922291            return 0;
    22932292        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
    2294         if (callFrame->argumentCountIncludingThis() != static_cast<size_t>(codeBlock->m_numParameters)
     2293        if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->m_numParameters)
    22952294            || callLinkInfo->callType == CallLinkInfo::CallVarargs)
    22962295            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
     
    23762375}
    23772376
    2378 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments_no_params)
    2379 {
    2380     STUB_INIT_STACK_FRAME(stackFrame);
    2381 
    2382     Arguments* arguments = Arguments::createNoParameters(*stackFrame.globalData, stackFrame.callFrame);
    2383     return JSValue::encode(JSValue(arguments));
    2384 }
    2385 
    23862377DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
    23872378{
    23882379    STUB_INIT_STACK_FRAME(stackFrame);
    23892380
    2390     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
     2381    CallFrame* callFrame = stackFrame.callFrame;
     2382    ASSERT(callFrame->codeBlock()->needsFullScopeChain());
    23912383    JSValue activationValue = stackFrame.args[0].jsValue();
    23922384    if (!activationValue) {
    23932385        if (JSValue v = stackFrame.args[1].jsValue()) {
    2394             if (!stackFrame.callFrame->codeBlock()->isStrictMode())
    2395                 asArguments(v)->tearOff(*stackFrame.globalData);
     2386            if (!callFrame->codeBlock()->isStrictMode())
     2387                asArguments(v)->tearOff(callFrame);
    23962388        }
    23972389        return;
     
    24072399    STUB_INIT_STACK_FRAME(stackFrame);
    24082400
    2409     ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain());
    2410     asArguments(stackFrame.args[0].jsValue())->tearOff(*stackFrame.globalData);
     2401    CallFrame* callFrame = stackFrame.callFrame;
     2402    ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
     2403    asArguments(stackFrame.args[0].jsValue())->tearOff(callFrame);
    24112404}
    24122405
  • trunk/Source/JavaScriptCore/jit/JITStubs.h

    r102167 r102545  
    327327    EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
    328328    EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
    329     EncodedJSValue JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
    330329    EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION);
    331330    EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION);
  • trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h

    r97872 r102545  
    4848        void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
    4949        {
    50             unsigned src = argumentToVirtualRegister(argument);
     50            unsigned src = CallFrame::argumentOffset(argument);
    5151            m_failures.append(emitLoadDouble(src, dst, scratch));
    5252        }
     
    5454        void loadCellArgument(int argument, RegisterID dst)
    5555        {
    56             unsigned src = argumentToVirtualRegister(argument);
     56            unsigned src = CallFrame::argumentOffset(argument);
    5757            m_failures.append(emitLoadJSCell(src, dst));
    5858        }
     
    6666        void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
    6767        {
    68             unsigned src = argumentToVirtualRegister(argument);
     68            unsigned src = CallFrame::argumentOffset(argument);
    6969            failTarget = emitLoadInt32(src, dst);
    7070        }
     
    150150
    151151    private:
    152         int argumentToVirtualRegister(unsigned argument)
    153         {
    154             return -static_cast<int>(RegisterFile::CallFrameHeaderSize + (m_expectedArgCount - argument));
    155         }
    156152
    157153        void tagReturnAsInt32()
  • trunk/Source/JavaScriptCore/runtime/ArgList.cpp

    r100516 r102545  
    3333void ArgList::getSlice(int startIndex, ArgList& result) const
    3434{
    35     if (startIndex <= 0 || static_cast<unsigned>(startIndex) >= m_argCount) {
     35    if (startIndex <= 0 || startIndex >= m_argCount) {
    3636        result = ArgList();
    3737        return;
    3838    }
    3939
    40     result.m_args = m_args + startIndex;
     40    result.m_args = m_args - startIndex;
    4141    result.m_argCount =  m_argCount - startIndex;
    4242}
     
    5353void MarkedArgumentBuffer::slowAppend(JSValue v)
    5454{
     55    int newCapacity = m_capacity * 4;
     56    EncodedJSValue* newBuffer = &(new EncodedJSValue[newCapacity])[newCapacity - 1];
     57    for (int i = 0; i < m_capacity; ++i)
     58        newBuffer[-i] = m_buffer[-i];
     59
     60    if (m_capacity != inlineCapacity)
     61        delete [] &m_buffer[-(m_capacity - 1)];
     62
     63    m_buffer = newBuffer;
     64    m_capacity = newCapacity;
     65
     66    m_buffer[-m_size] = JSValue::encode(v);
     67    ++m_size;
     68
     69    if (m_markSet)
     70        return;
     71
    5572    // As long as our size stays within our Vector's inline
    5673    // capacity, all our values are allocated on the stack, and
     
    5875    // our Vector's inline capacity, though, our values move to the
    5976    // heap, where they do need explicit marking.
    60     if (!m_markSet) {
    61         // FIXME: Even if v is not a JSCell*, if previous values in the buffer
    62         // are, then they won't be marked!
    63         if (Heap* heap = Heap::heap(v)) {
    64             ListSet& markSet = heap->markListSet();
    65             markSet.add(this);
    66             m_markSet = &markSet;
    67         }
     77    for (int i = 0; i < m_size; ++i) {
     78        Heap* heap = Heap::heap(JSValue::decode(m_buffer[-i]));
     79        if (!heap)
     80            continue;
     81
     82        m_markSet = &heap->markListSet();
     83        m_markSet->add(this);
     84        break;
    6885    }
    69 
    70     if (m_vector.size() < m_vector.capacity()) {
    71         m_vector.uncheckedAppend(v);
    72         return;
    73     }
    74 
    75     // 4x growth would be excessive for a normal vector, but it's OK for Lists
    76     // because they're short-lived.
    77     m_vector.reserveCapacity(m_vector.capacity() * 4);
    78    
    79     m_vector.uncheckedAppend(v);
    80     m_buffer = m_vector.data();
    8186}
    8287
  • trunk/Source/JavaScriptCore/runtime/ArgList.h

    r101604 r102545  
    3939
    4040    private:
    41         static const unsigned inlineCapacity = 8;
     41        static const size_t inlineCapacity = 8;
    4242        typedef Vector<Register, inlineCapacity> VectorType;
    4343        typedef HashSet<MarkedArgumentBuffer*> ListSet;
     
    4747        // FIXME: Remove all clients of this API, then remove this API.
    4848        MarkedArgumentBuffer()
    49             : m_isUsingInlineBuffer(true)
     49            : m_size(0)
     50            , m_capacity(inlineCapacity)
     51            , m_buffer(&m_inlineBuffer[m_capacity - 1])
    5052            , m_markSet(0)
    51 #ifndef NDEBUG
    52             , m_isReadOnly(false)
    53 #endif
    5453        {
    55             m_buffer = m_vector.data();
    56             m_size = 0;
    57         }
    58 
    59         // Constructor for a read-only list whose data has already been allocated elsewhere.
    60         MarkedArgumentBuffer(Register* buffer, size_t size)
    61             : m_buffer(buffer)
    62             , m_size(size)
    63             , m_isUsingInlineBuffer(true)
    64             , m_markSet(0)
    65 #ifndef NDEBUG
    66             , m_isReadOnly(true)
    67 #endif
    68         {
    69         }
    70 
    71         void initialize(WriteBarrier<Unknown>* buffer, size_t size)
    72         {
    73             ASSERT(!m_markSet);
    74             ASSERT(isEmpty());
    75 
    76             m_buffer = reinterpret_cast<Register*>(buffer);
    77             m_size = size;
    78 #ifndef NDEBUG
    79             m_isReadOnly = true;
    80 #endif
    8154        }
    8255
     
    8558            if (m_markSet)
    8659                m_markSet->remove(this);
     60
     61            if (m_capacity != inlineCapacity)
     62                delete [] &m_buffer[-(m_capacity - 1)];
    8763        }
    8864
     
    9066        bool isEmpty() const { return !m_size; }
    9167
    92         JSValue at(size_t i) const
     68        JSValue at(int i) const
    9369        {
    94             if (i < m_size)
    95                 return m_buffer[i].jsValue();
    96             return jsUndefined();
     70            if (i >= m_size)
     71                return jsUndefined();
     72
     73            return JSValue::decode(m_buffer[-i]);
    9774        }
    9875
    9976        void clear()
    10077        {
    101             m_vector.clear();
    102             m_buffer = 0;
    10378            m_size = 0;
    10479        }
     
    10681        void append(JSValue v)
    10782        {
    108             ASSERT(!m_isReadOnly);
     83            if (m_size >= m_capacity)
     84                return slowAppend(v);
    10985
    110             if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
    111                 m_vector.uncheckedAppend(v);
    112                 ++m_size;
    113             } else {
    114                 // Putting this case all in one function measurably improves
    115                 // the performance of the fast "just append to inline buffer" case.
    116                 slowAppend(v);
    117                 ++m_size;
    118                 m_isUsingInlineBuffer = false;
    119             }
     86            m_buffer[-m_size] = JSValue::encode(v);
     87            ++m_size;
    12088        }
    12189
     
    12492            ASSERT(m_size);
    12593            m_size--;
    126             m_vector.removeLast();
    12794        }
    12895
     
    13097        {
    13198            ASSERT(m_size);
    132             return m_buffer[m_size - 1].jsValue();
     99            return JSValue::decode(m_buffer[-(m_size - 1)]);
    133100        }
    134101       
     
    138105        void slowAppend(JSValue);
    139106       
    140         Register* m_buffer;
    141         size_t m_size;
    142         bool m_isUsingInlineBuffer;
    143 
    144         VectorType m_vector;
     107        int m_size;
     108        int m_capacity;
     109        EncodedJSValue m_inlineBuffer[inlineCapacity];
     110        EncodedJSValue* m_buffer;
    145111        ListSet* m_markSet;
    146 #ifndef NDEBUG
    147         bool m_isReadOnly;
    148 #endif
    149112
    150113    private:
     
    174137        {
    175138        }
    176        
     139
    177140        ArgList(ExecState* exec)
    178             : m_args(reinterpret_cast<JSValue*>(&exec[exec->hostThisRegister() + 1]))
     141            : m_args(reinterpret_cast<JSValue*>(&exec[CallFrame::argumentOffset(0)]))
    179142            , m_argCount(exec->argumentCount())
    180143        {
    181144        }
    182        
     145
    183146        ArgList(const MarkedArgumentBuffer& args)
    184147            : m_args(reinterpret_cast<JSValue*>(args.m_buffer))
     
    187150        }
    188151
    189         JSValue at(size_t idx) const
     152        JSValue at(int i) const
    190153        {
    191             if (idx < m_argCount)
    192                 return m_args[idx];
    193             return jsUndefined();
     154            if (i >= m_argCount)
     155                return jsUndefined();
     156            return m_args[-i];
    194157        }
    195158
     
    201164    private:
    202165        JSValue* m_args;
    203         size_t m_argCount;
     166        int m_argCount;
    204167    };
    205168
  • trunk/Source/JavaScriptCore/runtime/Arguments.cpp

    r100006 r102545  
    3838const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) };
    3939
    40 Arguments::~Arguments()
    41 {
    42     if (d->extraArguments != d->extraArgumentsFixedBuffer)
    43         delete [] d->extraArguments;
    44 }
    45 
    4640void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor)
    4741{
     
    5347
    5448    if (thisObject->d->registerArray)
    55         visitor.appendValues(thisObject->d->registerArray.get(), thisObject->d->numParameters);
    56 
    57     if (thisObject->d->extraArguments) {
    58         unsigned numExtraArguments = thisObject->d->numArguments - thisObject->d->numParameters;
    59         visitor.appendValues(thisObject->d->extraArguments, numExtraArguments);
    60     }
    61 
     49        visitor.appendValues(thisObject->d->registerArray.get(), thisObject->d->numArguments);
    6250    visitor.append(&thisObject->d->callee);
    63 
    6451    if (thisObject->d->activation)
    6552        visitor.append(&thisObject->d->activation);
    6653}
    6754
    68 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
    69 {
    70     if (UNLIKELY(d->overrodeLength)) {
    71         unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize);
    72         for (unsigned i = 0; i < length; i++)
    73             buffer[i] = get(exec, i);
    74         return;
    75     }
    76 
    77     if (LIKELY(!d->deletedArguments)) {
    78         unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
    79         unsigned i = 0;
    80         for (; i < parametersLength; ++i)
    81             buffer[i] = d->registers[d->firstParameterIndex + i].get();
    82         for (; i < d->numArguments; ++i)
    83             buffer[i] = d->extraArguments[i - d->numParameters].get();
    84         return;
    85     }
    86    
    87     unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
    88     unsigned i = 0;
    89     for (; i < parametersLength; ++i) {
    90         if (!d->deletedArguments[i])
    91             buffer[i] = d->registers[d->firstParameterIndex + i].get();
     55void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length)
     56{
     57    ASSERT(length == this->length(exec));
     58    for (size_t i = 0; i < length; ++i) {
     59        if (!d->deletedArguments || !d->deletedArguments[i])
     60            callFrame->setArgument(i, argument(i).get());
    9261        else
    93             buffer[i] = get(exec, i);
    94     }
    95     for (; i < d->numArguments; ++i) {
    96         if (!d->deletedArguments[i])
    97             buffer[i] = d->extraArguments[i - d->numParameters].get();
    98         else
    99             buffer[i] = get(exec, i);
     62            callFrame->setArgument(i, get(exec, i));
    10063    }
    10164}
     
    10366void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
    10467{
    105     if (UNLIKELY(d->overrodeLength)) {
    106         unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec);
    107         for (unsigned i = 0; i < length; i++)
    108             args.append(get(exec, i));
    109         return;
    110     }
    111 
    112     if (LIKELY(!d->deletedArguments)) {
    113         if (LIKELY(!d->numParameters)) {
    114             args.initialize(d->extraArguments, d->numArguments);
    115             return;
    116         }
    117 
    118         if (d->numParameters == d->numArguments) {
    119             args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
    120             return;
    121         }
    122 
    123         unsigned parametersLength = min(d->numParameters, d->numArguments);
    124         unsigned i = 0;
    125         for (; i < parametersLength; ++i)
    126             args.append(d->registers[d->firstParameterIndex + i].get());
    127         for (; i < d->numArguments; ++i)
    128             args.append(d->extraArguments[i - d->numParameters].get());
    129         return;
    130     }
    131 
    132     unsigned parametersLength = min(d->numParameters, d->numArguments);
    133     unsigned i = 0;
    134     for (; i < parametersLength; ++i) {
    135         if (!d->deletedArguments[i])
    136             args.append(d->registers[d->firstParameterIndex + i].get());
     68    uint32_t length = this->length(exec);
     69    for (size_t i = 0; i < length; ++i) {
     70        if (!d->deletedArguments || !d->deletedArguments[i])
     71            args.append(argument(i).get());
    13772        else
    13873            args.append(get(exec, i));
    13974    }
    140     for (; i < d->numArguments; ++i) {
    141         if (!d->deletedArguments[i])
    142             args.append(d->extraArguments[i - d->numParameters].get());
    143         else
    144             args.append(get(exec, i));
    145     }
    14675}
    14776
     
    15079    Arguments* thisObject = jsCast<Arguments*>(cell);
    15180    if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
    152         if (i < thisObject->d->numParameters) {
    153             slot.setValue(thisObject->d->registers[thisObject->d->firstParameterIndex + i].get());
    154         } else
    155             slot.setValue(thisObject->d->extraArguments[i - thisObject->d->numParameters].get());
     81        slot.setValue(thisObject->argument(i).get());
    15682        return true;
    15783    }
     
    190116    unsigned i = propertyName.toArrayIndex(isArrayIndex);
    191117    if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
    192         if (i < thisObject->d->numParameters) {
    193             slot.setValue(thisObject->d->registers[thisObject->d->firstParameterIndex + i].get());
    194         } else
    195             slot.setValue(thisObject->d->extraArguments[i - thisObject->d->numParameters].get());
     118        slot.setValue(thisObject->argument(i).get());
    196119        return true;
    197120    }
     
    222145    unsigned i = propertyName.toArrayIndex(isArrayIndex);
    223146    if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
    224         if (i < thisObject->d->numParameters) {
    225             descriptor.setDescriptor(thisObject->d->registers[thisObject->d->firstParameterIndex + i].get(), None);
    226         } else
    227             descriptor.setDescriptor(thisObject->d->extraArguments[i - thisObject->d->numParameters].get(), None);
     147        descriptor.setDescriptor(thisObject->argument(i).get(), None);
    228148        return true;
    229149    }
     
    265185{
    266186    Arguments* thisObject = jsCast<Arguments*>(cell);
    267     if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
    268         if (i < thisObject->d->numParameters)
    269             thisObject->d->registers[thisObject->d->firstParameterIndex + i].set(exec->globalData(), thisObject->d->activation ? static_cast<JSCell*>(thisObject->d->activation.get()) : cell, value);
    270         else
    271             thisObject->d->extraArguments[i - thisObject->d->numParameters].set(exec->globalData(), thisObject, value);
     187    if (i < static_cast<unsigned>(thisObject->d->numArguments) && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
     188        thisObject->argument(i).set(exec->globalData(), thisObject, value);
    272189        return;
    273190    }
     
    283200    unsigned i = propertyName.toArrayIndex(isArrayIndex);
    284201    if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
    285         if (i < thisObject->d->numParameters)
    286             thisObject->d->registers[thisObject->d->firstParameterIndex + i].set(exec->globalData(), thisObject->d->activation ? static_cast<JSCell*>(thisObject->d->activation.get()) : static_cast<JSCell*>(thisObject), value);
    287         else
    288             thisObject->d->extraArguments[i - thisObject->d->numParameters].set(exec->globalData(), thisObject, value);
     202        thisObject->argument(i).set(exec->globalData(), thisObject, value);
    289203        return;
    290204    }
     
    363277}
    364278
     279void Arguments::tearOff(CallFrame* callFrame)
     280{
     281    if (isTornOff())
     282        return;
     283
     284    if (!d->numArguments)
     285        return;
     286
     287    d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]);
     288    d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1);
     289
     290    if (!callFrame->isInlineCallFrame()) {
     291        for (size_t i = 0; i < d->numArguments; ++i)
     292            argument(i).set(callFrame->globalData(), this, callFrame->argument(i));
     293        return;
     294    }
     295
     296    InlineCallFrame* inlineCallFrame = callFrame->inlineCallFrame();
     297    for (size_t i = 0; i < d->numArguments; ++i) {
     298        ValueRecovery& recovery = inlineCallFrame->arguments[i + 1];
     299        // In the future we'll support displaced recoveries (indicating that the
     300        // argument was flushed to a different location), but for now we don't do
     301        // that so this code will fail if that were to happen. On the other hand,
     302        // it's much less likely that we'll support in-register recoveries since
     303        // this code does not (easily) have access to registers.
     304        JSValue value;
     305        Register* location = &callFrame->registers()[CallFrame::argumentOffset(i)];
     306        switch (recovery.technique()) {
     307        case AlreadyInRegisterFile:
     308            value = location->jsValue();
     309            break;
     310        case AlreadyInRegisterFileAsUnboxedInt32:
     311            value = jsNumber(location->unboxedInt32());
     312            break;
     313        case AlreadyInRegisterFileAsUnboxedCell:
     314            value = location->unboxedCell();
     315            break;
     316        case AlreadyInRegisterFileAsUnboxedBoolean:
     317            value = jsBoolean(location->unboxedBoolean());
     318            break;
     319        case Constant:
     320            value = recovery.constant();
     321            break;
     322        default:
     323            ASSERT_NOT_REACHED();
     324            break;
     325        }
     326        argument(i).set(callFrame->globalData(), this, value);
     327    }
     328}
     329
    365330} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/Arguments.h

    r100224 r102545  
    4040        WriteBarrier<JSActivation> activation;
    4141
    42         unsigned numParameters;
    43         ptrdiff_t firstParameterIndex;
    4442        unsigned numArguments;
    4543
     
    4745        OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
    4846
    49         WriteBarrier<Unknown>* extraArguments;
    5047        OwnArrayPtr<bool> deletedArguments;
    51         WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
    5248
    5349        WriteBarrier<JSFunction> callee;
     
    5652        bool overrodeCaller : 1;
    5753        bool isStrictMode : 1;
    58         bool isInlineFrame : 1; // If true, all arguments are in the extraArguments buffer.
    5954    };
    60 
    6155
    6256    class Arguments : public JSNonFinalObject {
     
    7064            return arguments;
    7165        }
    72        
    73         static Arguments* createAndTearOff(JSGlobalData& globalData, CallFrame* callFrame)
    74         {
    75             Arguments* arguments = new (allocateCell<Arguments>(globalData.heap)) Arguments(callFrame);
    76             arguments->finishCreationAndTearOff(callFrame);
    77             return arguments;
    78         }
    79        
    80         static Arguments* createNoParameters(JSGlobalData& globalData, CallFrame* callFrame)
    81         {
    82             Arguments* arguments = new (allocateCell<Arguments>(globalData.heap)) Arguments(callFrame, NoParameters);
    83             arguments->finishCreation(callFrame, NoParameters);
    84             return arguments;
    85         }
    8666
    87         // Use an enum because otherwise gcc insists on doing a memory
    88         // read.
    8967        enum { MaxArguments = 0x10000 };
    9068
     
    9674
    9775    public:
    98         virtual ~Arguments();
    99 
    10076        static const ClassInfo s_info;
    10177
     
    11187        }
    11288       
    113         void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
    114         void tearOff(JSGlobalData&);
     89        void copyToArguments(ExecState*, CallFrame*, uint32_t length);
     90        void tearOff(CallFrame*);
    11591        bool isTornOff() const { return d->registerArray; }
    11692        void didTearOffActivation(JSGlobalData& globalData, JSActivation* activation)
     
    130106        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
    131107
    132         void finishCreationButDontTearOff(CallFrame*);
    133108        void finishCreation(CallFrame*);
    134         void finishCreationAndTearOff(CallFrame*);
    135         void finishCreation(CallFrame*, NoParametersType);
    136109
    137110    private:
    138         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
    139111        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
    140112        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
     
    147119        void createStrictModeCallerIfNecessary(ExecState*);
    148120        void createStrictModeCalleeIfNecessary(ExecState*);
     121
     122        WriteBarrier<Unknown>& argument(size_t);
    149123
    150124        void init(CallFrame*);
     
    161135    }
    162136
    163     ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
    164     {
    165         function = asFunction(callFrame->callee());
    166 
    167         int numParameters = function->jsExecutable()->parameterCount();
    168         argc = callFrame->argumentCountIncludingThis();
    169        
    170         if (callFrame->isInlineCallFrame())
    171             ASSERT(argc == numParameters + 1);
    172 
    173         if (argc <= numParameters)
    174             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
    175         else
    176             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
    177 
    178         argc -= 1; // - 1 to skip "this"
    179         firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
    180     }
    181 
    182137    inline Arguments::Arguments(CallFrame* callFrame)
    183138        : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
     
    191146    {
    192147    }
    193    
    194     inline void Arguments::finishCreationButDontTearOff(CallFrame* callFrame)
     148
     149    inline WriteBarrier<Unknown>& Arguments::argument(size_t i)
     150    {
     151        return d->registers[CallFrame::argumentOffset(i)];
     152    }
     153
     154    inline void Arguments::finishCreation(CallFrame* callFrame)
    195155    {
    196156        Base::finishCreation(callFrame->globalData());
    197157        ASSERT(inherits(&s_info));
    198158
    199         JSFunction* callee;
    200         ptrdiff_t firstParameterIndex;
    201         Register* argv;
    202         int numArguments;
    203         getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
    204 
    205         d->numParameters = callee->jsExecutable()->parameterCount();
    206         d->firstParameterIndex = firstParameterIndex;
    207         d->numArguments = numArguments;
    208         d->isInlineFrame = false;
    209 
     159        JSFunction* callee = asFunction(callFrame->callee());
     160        d->numArguments = callFrame->argumentCount();
    210161        d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
    211 
    212         WriteBarrier<Unknown>* extraArguments;
    213         if (d->numArguments <= d->numParameters)
    214             extraArguments = 0;
    215         else {
    216             unsigned numExtraArguments = d->numArguments - d->numParameters;
    217             if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
    218                 extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
    219             else
    220                 extraArguments = d->extraArgumentsFixedBuffer;
    221             for (unsigned i = 0; i < numExtraArguments; ++i)
    222                 extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
    223         }
    224 
    225         d->extraArguments = extraArguments;
    226 
    227162        d->callee.set(callFrame->globalData(), this, callee);
    228163        d->overrodeLength = false;
     
    230165        d->overrodeCaller = false;
    231166        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
    232     }
    233167
    234     inline void Arguments::finishCreation(CallFrame* callFrame)
    235     {
    236         ASSERT(!callFrame->isInlineCallFrame());
    237         finishCreationButDontTearOff(callFrame);
    238         if (d->isStrictMode)
    239             tearOff(callFrame->globalData());
    240     }
    241 
    242     inline void Arguments::finishCreationAndTearOff(CallFrame* callFrame)
    243     {
    244         Base::finishCreation(callFrame->globalData());
    245         ASSERT(inherits(&s_info));
    246        
    247         JSFunction* callee;
    248 
    249         ptrdiff_t firstParameterIndex;
    250         Register* argv;
    251         int numArguments;
    252         getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
    253        
    254         d->numParameters = callee->jsExecutable()->parameterCount();
    255         d->firstParameterIndex = firstParameterIndex;
    256         d->numArguments = numArguments;
    257        
    258         if (d->numParameters) {
    259             int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
    260             size_t registerArraySize = d->numParameters;
    261            
    262             OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
    263             if (callFrame->isInlineCallFrame()) {
    264                 InlineCallFrame* inlineCallFrame = callFrame->inlineCallFrame();
    265                 for (size_t i = 0; i < registerArraySize; ++i) {
    266                     ValueRecovery& recovery = inlineCallFrame->arguments[i + 1];
    267                     // In the future we'll support displaced recoveries (indicating that the
    268                     // argument was flushed to a different location), but for now we don't do
    269                     // that so this code will fail if that were to happen. On the other hand,
    270                     // it's much less likely that we'll support in-register recoveries since
    271                     // this code does not (easily) have access to registers.
    272                     JSValue value;
    273                     Register* location = callFrame->registers() + i - registerOffset;
    274                     switch (recovery.technique()) {
    275                     case AlreadyInRegisterFile:
    276                         value = location->jsValue();
    277                         break;
    278                     case AlreadyInRegisterFileAsUnboxedInt32:
    279                         value = jsNumber(location->unboxedInt32());
    280                         break;
    281                     case AlreadyInRegisterFileAsUnboxedCell:
    282                         value = location->unboxedCell();
    283                         break;
    284                     case AlreadyInRegisterFileAsUnboxedBoolean:
    285                         value = jsBoolean(location->unboxedBoolean());
    286                         break;
    287                     case Constant:
    288                         value = recovery.constant();
    289                         break;
    290                     default:
    291                         ASSERT_NOT_REACHED();
    292                         break;
    293                     }
    294                     registerArray[i].set(callFrame->globalData(), this, value);
    295                 }
    296             } else {
    297                 for (size_t i = 0; i < registerArraySize; ++i)
    298                     registerArray[i].set(callFrame->globalData(), this, callFrame->registers()[i - registerOffset].jsValue());
    299             }
    300             d->registers = registerArray.get() + d->numParameters + RegisterFile::CallFrameHeaderSize;
    301             d->registerArray = registerArray.release();
    302         }
    303        
    304         WriteBarrier<Unknown>* extraArguments;
    305         if (callFrame->isInlineCallFrame())
    306             ASSERT(d->numArguments == d->numParameters);
    307         if (d->numArguments <= d->numParameters)
    308             extraArguments = 0;
    309         else {
    310             unsigned numExtraArguments = d->numArguments - d->numParameters;
    311             if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
    312                 extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
    313             else
    314                 extraArguments = d->extraArgumentsFixedBuffer;
    315             for (unsigned i = 0; i < numExtraArguments; ++i)
    316                 extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
    317         }
    318        
    319         d->extraArguments = extraArguments;
    320 
    321         d->callee.set(callFrame->globalData(), this, callee);
    322         d->overrodeLength = false;
    323         d->overrodeCallee = false;
    324         d->overrodeCaller = false;
    325         d->isInlineFrame = callFrame->isInlineCallFrame();
    326         d->isStrictMode = callFrame->codeBlock()->isStrictMode();
    327     }
    328 
    329     inline void Arguments::finishCreation(CallFrame* callFrame, NoParametersType)
    330     {
    331         ASSERT(!callFrame->isInlineCallFrame());
    332         Base::finishCreation(callFrame->globalData());
    333         ASSERT(inherits(&s_info));
    334         ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
    335 
    336         unsigned numArguments = callFrame->argumentCount();
    337 
    338         d->numParameters = 0;
    339         d->numArguments = numArguments;
    340         d->isInlineFrame = false;
    341 
    342         WriteBarrier<Unknown>* extraArguments;
    343         if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
    344             extraArguments = new WriteBarrier<Unknown>[numArguments];
    345         else
    346             extraArguments = d->extraArgumentsFixedBuffer;
    347 
    348         Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
    349         for (unsigned i = 0; i < numArguments; ++i)
    350             extraArguments[i].set(callFrame->globalData(), this, argv[i].jsValue());
    351 
    352         d->extraArguments = extraArguments;
    353 
    354         d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
    355         d->overrodeLength = false;
    356         d->overrodeCallee = false;
    357         d->overrodeCaller = false;
    358         d->isStrictMode = callFrame->codeBlock()->isStrictMode();
    359         if (d->isStrictMode)
    360             tearOff(callFrame->globalData());
    361     }
    362 
    363     inline void Arguments::tearOff(JSGlobalData& globalData)
    364     {
    365         ASSERT(!isTornOff());
    366 
    367         if (!d->numParameters)
    368             return;
    369 
    370         int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
    371         size_t registerArraySize = d->numParameters;
    372 
    373         OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
    374         for (size_t i = 0; i < registerArraySize; i++)
    375             registerArray[i].set(globalData, this, d->registers[i - registerOffset].get());
    376         d->registers = registerArray.get() + registerOffset;
    377         d->registerArray = registerArray.release();
     168        // The bytecode generator omits op_tear_off_activation in cases of no
     169        // declared parameters, so we need to tear off immediately.
     170        if (d->isStrictMode || !callee->jsExecutable()->parameterCount())
     171            tearOff(callFrame);
    378172    }
    379173
  • trunk/Source/JavaScriptCore/runtime/JSActivation.cpp

    r100672 r102545  
    3434#include "JSFunction.h"
    3535
     36using namespace std;
     37
    3638namespace JSC {
    3739
     
    4244JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)
    4345    : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers())
    44     , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount()))
     46    , m_numCapturedArgs(max(callFrame->argumentCount(), functionExecutable->parameterCount()))
    4547    , m_numCapturedVars(functionExecutable->capturedVariableCount())
    4648    , m_requiresDynamicChecks(functionExecutable->usesEval())
     
    7880        return;
    7981
    80     visitor.appendValues(registerArray, thisObject->m_numParametersMinusThis);
    81 
    82     // Skip the call frame, which sits between the parameters and vars.
    83     visitor.appendValues(registerArray + thisObject->m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, thisObject->m_numCapturedVars);
     82    visitor.appendValues(registerArray, thisObject->m_numCapturedArgs);
     83
     84    // Skip 'this' and call frame.
     85    visitor.appendValues(registerArray + CallFrame::offsetFor(thisObject->m_numCapturedArgs + 1), thisObject->m_numCapturedVars);
    8486}
    8587
  • trunk/Source/JavaScriptCore/runtime/JSActivation.h

    r100822 r102545  
    9090        NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
    9191
    92         int m_numParametersMinusThis;
     92        int m_numCapturedArgs;
    9393        int m_numCapturedVars : 31;
    9494        bool m_requiresDynamicChecks : 1;
     
    118118    {
    119119        ASSERT(!m_registerArray);
     120        ASSERT(m_numCapturedVars + m_numCapturedArgs);
    120121
    121         size_t numLocals = m_numCapturedVars + m_numParametersMinusThis;
     122        int registerOffset = CallFrame::offsetFor(m_numCapturedArgs + 1);
     123        size_t registerArraySize = registerOffset + m_numCapturedVars;
    122124
    123         if (!numLocals)
    124             return;
     125        OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
     126        WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
    125127
    126         int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
    127         size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
     128        // Copy all arguments that can be captured by name or by the arguments object.
     129        for (int i = 0; i < m_numCapturedArgs; ++i) {
     130            int index = CallFrame::argumentOffset(i);
     131            registers[index].set(globalData, this, m_registers[index].get());
     132        }
    128133
    129         OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1);
    130         WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
     134        // Skip 'this' and call frame.
     135
     136        // Copy all captured vars.
     137        for (int i = 0; i < m_numCapturedVars; ++i)
     138            registers[i].set(globalData, this, m_registers[i].get());
     139
    131140        setRegisters(registers, registerArray.release());
    132141    }
  • trunk/Source/JavaScriptCore/runtime/JSArray.cpp

    r101604 r102545  
    12661266}
    12671267
    1268 void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
    1269 {
    1270     ASSERT(m_storage->m_length >= maxSize);
    1271     UNUSED_PARAM(maxSize);
     1268void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length)
     1269{
     1270    ASSERT(length == this->length());
     1271    UNUSED_PARAM(length);
     1272    unsigned i = 0;
    12721273    WriteBarrier<Unknown>* vector = m_storage->m_vector;
    1273     unsigned vectorEnd = min(maxSize, m_vectorLength);
    1274     unsigned i = 0;
     1274    unsigned vectorEnd = min(length, m_vectorLength);
    12751275    for (; i < vectorEnd; ++i) {
    12761276        WriteBarrier<Unknown>& v = vector[i];
    12771277        if (!v)
    12781278            break;
    1279         buffer[i] = v.get();
    1280     }
    1281 
    1282     for (; i < maxSize; ++i)
    1283         buffer[i] = get(exec, i);
     1279        callFrame->setArgument(i, v.get());
     1280    }
     1281
     1282    for (; i < length; ++i)
     1283        callFrame->setArgument(i, get(exec, i));
    12841284}
    12851285
  • trunk/Source/JavaScriptCore/runtime/JSArray.h

    r100516 r102545  
    156156
    157157        void fillArgList(ExecState*, MarkedArgumentBuffer&);
    158         void copyToRegisters(ExecState*, Register*, uint32_t);
     158        void copyToArguments(ExecState*, CallFrame*, uint32_t length);
    159159
    160160        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
Note: See TracChangeset for help on using the changeset viewer.