Changeset 102545 in webkit
- Timestamp:
- Dec 11, 2011 4:35:51 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 38 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r102534 r102545 1 2011-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 1 263 2011-12-10 Mark Hahnenberg <mhahnenberg@apple.com> 2 264 … … 20357 20619 (JSC::PredictionTracker::numberOfArguments): 20358 20620 (JSC::PredictionTracker::numberOfVariables): 20359 (JSC::PredictionTracker::argument IndexForOperand):20621 (JSC::PredictionTracker::argumentOffsetForOperand): 20360 20622 (JSC::PredictionTracker::predictArgument): 20361 20623 (JSC::PredictionTracker::predict): … … 22092 22354 (JSC::DFG::PredictionTracker::numberOfArguments): 22093 22355 (JSC::DFG::PredictionTracker::numberOfVariables): 22094 (JSC::DFG::PredictionTracker::argument IndexForOperand):22356 (JSC::DFG::PredictionTracker::argumentOffsetForOperand): 22095 22357 (JSC::DFG::PredictionTracker::predictArgument): 22096 22358 (JSC::DFG::PredictionTracker::predict): -
trunk/Source/JavaScriptCore/Configurations/Base.xcconfig
r99378 r102545 25 25 26 26 COMPILER_SPECIFIC_WARNING_CFLAGS = $(COMPILER_SPECIFIC_WARNING_CFLAGS_$(TARGET_GCC_VERSION)); 27 COMPILER_SPECIFIC_WARNING_CFLAGS_LLVM_COMPILER = -Wglobal-constructors -Wexit-time-destructors;27 COMPILER_SPECIFIC_WARNING_CFLAGS_LLVM_COMPILER = ; 28 28 29 29 CLANG_WARN_CXX0X_EXTENSIONS = NO; -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r102489 r102545 652 652 return WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset); 653 653 } 654 ValueProfile* valueProfileForArgument(int argument Index)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()) 658 658 return 0; 659 ValueProfile* result = valueProfile( argumentIndex);659 ValueProfile* result = valueProfile(index); 660 660 if (result->m_bytecodeOffset != -1) 661 661 return 0; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r100879 r102545 203 203 , m_scopeNode(programNode) 204 204 , m_codeBlock(codeBlock) 205 , m_thisRegister( RegisterFile::ProgramCodeThisRegister)205 , m_thisRegister(CallFrame::thisArgumentOffset()) 206 206 , m_finallyDepth(0) 207 207 , m_dynamicScopeDepth(0) … … 397 397 398 398 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" 402 400 403 401 // Add "this" as a parameter 404 m_thisRegister.setIndex(nextParameterIndex); 402 int nextParameterIndex = CallFrame::thisArgumentOffset(); 403 m_thisRegister.setIndex(nextParameterIndex--); 405 404 ++m_codeBlock->m_numParameters; 406 405 407 for (size_t i = 0; i < parameter Count; ++i)408 addParameter(parameters[i], ++nextParameterIndex);406 for (size_t i = 0; i < parameters.size(); ++i) 407 addParameter(parameters[i], nextParameterIndex--); 409 408 410 409 preserveLastVar(); … … 436 435 , m_scopeNode(evalNode) 437 436 , m_codeBlock(codeBlock) 438 , m_thisRegister( RegisterFile::ProgramCodeThisRegister)437 , m_thisRegister(CallFrame::thisArgumentOffset()) 439 438 , m_finallyDepth(0) 440 439 , m_dynamicScopeDepth(0) … … 1802 1801 1803 1802 // Generate code for arguments. 1804 unsigned argument Index= 0;1803 unsigned argument = 0; 1805 1804 for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next) 1806 emitNode(callArguments.argumentRegister(argument Index++), n);1805 emitNode(callArguments.argumentRegister(argument++), n); 1807 1806 1808 1807 // Reserve space for call frame. … … 1821 1820 emitOpcode(opcodeID); 1822 1821 instructions().append(func->index()); // func 1823 instructions().append(callArguments. count()); // argCount1822 instructions().append(callArguments.argumentCountIncludingThis()); // argCount 1824 1823 instructions().append(callArguments.registerOffset()); // registerOffset 1825 1824 if (dst != ignoredResult()) { … … 1901 1900 1902 1901 // Generate code for arguments. 1903 unsigned argument Index= 0;1902 unsigned argument = 0; 1904 1903 if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) { 1905 1904 for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) 1906 emitNode(callArguments.argumentRegister(argument Index++), n);1905 emitNode(callArguments.argumentRegister(argument++), n); 1907 1906 } 1908 1907 … … 1921 1920 emitOpcode(op_construct); 1922 1921 instructions().append(func->index()); // func 1923 instructions().append(callArguments. count()); // argCount1922 instructions().append(callArguments.argumentCountIncludingThis()); // argCount 1924 1923 instructions().append(callArguments.registerOffset()); // registerOffset 1925 1924 if (dst != ignoredResult()) { … … 2363 2362 if (!registerID || registerID->index() >= 0) 2364 2363 return 0; 2365 return registerID->index() - m_thisRegister.index() - 1 == argumentNumber;2364 return registerID->index() == CallFrame::argumentOffset(argumentNumber); 2366 2365 } 2367 2366 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r100879 r102545 56 56 RegisterID* thisRegister() { return m_argv[0].get(); } 57 57 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(); } 60 60 RegisterID* profileHookRegister() { return m_profileHookRegister.get(); } 61 61 ArgumentsNode* argumentsNode() { return m_argumentsNode; } -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r100879 r102545 320 320 m_profileHookRegister = generator.newTemporary(); 321 321 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 } 327 333 } 328 334 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r102489 r102545 77 77 78 78 // 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); 80 80 81 81 // Handle calls. This resolves issues surrounding inlining and intrinsics. 82 82 void handleCall(Interpreter*, Instruction* currentInstruction, NodeType op, CodeSpecializationKind); 83 83 // 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); 85 85 // 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); 87 87 // Prepare to parse a block. 88 88 void prepareToParseBlock(); … … 200 200 NodeIndex getArgument(unsigned operand) 201 201 { 202 unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;202 unsigned argument = operandToArgument(operand); 203 203 ASSERT(argument < m_numArguments); 204 204 … … 249 249 void setArgument(int operand, NodeIndex value) 250 250 { 251 unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;251 unsigned argument = operandToArgument(operand); 252 252 ASSERT(argument < m_numArguments); 253 253 … … 267 267 int index; 268 268 if (operandIsArgument(operand)) { 269 index = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;269 index = operandToArgument(operand); 270 270 nodeIndex = m_currentBlock->variablesAtTail.argument(index); 271 271 } else { … … 579 579 addVarArgChild(get(currentInstruction[1].u.operand)); 580 580 int argCount = currentInstruction[2].u.operand; 581 if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots) 582 m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount; 583 581 584 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 585 589 NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction)); 586 590 if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) 587 591 set(putInstruction[1].u.operand, call); 588 if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)589 m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;590 592 return call; 591 593 } … … 896 898 callType = UnknownFunction; 897 899 if (callType != UnknownFunction) { 898 int arg Count= currentInstruction[2].u.operand;900 int argumentCountIncludingThis = currentInstruction[2].u.operand; 899 901 int registerOffset = currentInstruction[3].u.operand; 900 int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize; 901 int lastArg = firstArg + argCount - 1; 902 902 903 903 // Do we have a result? 904 904 bool usesResult = false; … … 931 931 addToGraph(CheckFunction, OpInfo(expectedFunction), callTarget); 932 932 933 if (handleIntrinsic(usesResult, resultOperand, intrinsic, firstArg, lastArg, prediction)) {933 if (handleIntrinsic(usesResult, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) { 934 934 if (!certainAboutExpectedFunction) { 935 935 // Need to keep the call target alive for OSR. We could easily optimize this out if we wanted … … 941 941 return; 942 942 } 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)) 944 944 return; 945 945 } … … 948 948 } 949 949 950 bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction* expectedFunction, int firstArg, int lastArg, unsigned nextOffset, CodeSpecializationKind kind)950 bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction* expectedFunction, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind) 951 951 { 952 952 // First, the really simple checks: do we have an actual JS function? … … 960 960 // Does the number of arguments we're passing match the arity of the target? We could 961 961 // 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) 963 963 return false; 964 964 … … 1001 1001 // FIXME: Don't flush constants! 1002 1002 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; 1007 1007 1008 1008 // Make sure that the area used by the call frame is reserved. … … 1124 1124 } 1125 1125 1126 bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg)1126 bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis) 1127 1127 { 1128 1128 if (!usesResult) 1129 1129 return true; 1130 1130 1131 if ( lastArg == firstArg) {1131 if (argumentCountIncludingThis == 1) { // Math.min() 1132 1132 set(resultOperand, constantNaN()); 1133 1133 return true; 1134 1134 } 1135 1135 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))); 1138 1138 return true; 1139 1139 } 1140 1140 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)))); 1143 1143 return true; 1144 1144 } … … 1148 1148 } 1149 1149 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. 1152 bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction) 1151 1153 { 1152 1154 switch (intrinsic) { … … 1158 1160 } 1159 1161 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() 1164 1163 set(resultOperand, constantNaN()); 1165 1164 return true; … … 1169 1168 return false; 1170 1169 1171 set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber( absArg)));1170 set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(registerOffset + argumentToOperand(1)))); 1172 1171 return true; 1173 1172 } 1174 1173 1175 1174 case MinIntrinsic: 1176 return handleMinMax(usesResult, resultOperand, ArithMin, firstArg, lastArg);1175 return handleMinMax(usesResult, resultOperand, ArithMin, registerOffset, argumentCountIncludingThis); 1177 1176 1178 1177 case MaxIntrinsic: 1179 return handleMinMax(usesResult, resultOperand, ArithMax, firstArg, lastArg);1178 return handleMinMax(usesResult, resultOperand, ArithMax, registerOffset, argumentCountIncludingThis); 1180 1179 1181 1180 case SqrtIntrinsic: { … … 1183 1182 return true; 1184 1183 1185 if ( firstArg == lastArg) {1184 if (argumentCountIncludingThis == 1) { // Math.sqrt() 1186 1185 set(resultOperand, constantNaN()); 1187 1186 return true; … … 1191 1190 return false; 1192 1191 1193 set(resultOperand, addToGraph(ArithSqrt, getToNumber( firstArg + 1)));1192 set(resultOperand, addToGraph(ArithSqrt, getToNumber(registerOffset + argumentToOperand(1)))); 1194 1193 return true; 1195 1194 } 1196 1195 1197 1196 case ArrayPushIntrinsic: { 1198 if ( firstArg + 1 != lastArg)1197 if (argumentCountIncludingThis != 2) 1199 1198 return false; 1200 1199 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))); 1202 1201 if (usesResult) 1203 1202 set(resultOperand, arrayPush); … … 1207 1206 1208 1207 case ArrayPopIntrinsic: { 1209 if ( firstArg != lastArg)1208 if (argumentCountIncludingThis != 1) 1210 1209 return false; 1211 1210 1212 NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get( firstArg));1211 NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0))); 1213 1212 if (usesResult) 1214 1213 set(resultOperand, arrayPop); … … 1217 1216 1218 1217 case CharCodeAtIntrinsic: { 1219 if ( firstArg + 1 != lastArg)1218 if (argumentCountIncludingThis != 2) 1220 1219 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)) 1222 1223 return false; 1223 1224 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 1226 1229 if (usesResult) 1227 1230 set(resultOperand, charCode); … … 1230 1233 1231 1234 case CharAtIntrinsic: { 1232 if ( firstArg + 1 != lastArg)1235 if (argumentCountIncludingThis != 2) 1233 1236 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)) 1235 1240 return false; 1236 1241 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 1239 1246 if (usesResult) 1240 1247 set(resultOperand, charCode); … … 1268 1275 m_graph.m_arguments.resize(m_numArguments); 1269 1276 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)))); 1271 1278 m_graph.m_arguments[argument] = setArgument; 1272 1279 m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, setArgument); … … 2208 2215 #endif 2209 2216 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)))); 2211 2218 var = valueInPredecessor; 2212 2219 if (stackType == ArgumentPhiStack) -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r100975 r102545 218 218 int operand = variableAccessData->operand(); 219 219 if (operandIsArgument(operand)) 220 printf("%sarg%u(%s)", hasPrinted ? ", " : "", operand - codeBlock->thisRegister(), nameOfVariableAccessData(variableAccessData));220 printf("%sarg%u(%s)", hasPrinted ? ", " : "", operandToArgument(operand), nameOfVariableAccessData(variableAccessData)); 221 221 else 222 222 printf("%sr%u(%s)", hasPrinted ? ", " : "", operand, nameOfVariableAccessData(variableAccessData)); -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r100315 r102545 198 198 if (!operandIsArgument(node.local())) 199 199 return 0; 200 int argument = node.local() + m_arguments.size() + RegisterFile::CallFrameHeaderSize;200 int argument = operandToArgument(node.local()); 201 201 if (node.variableAccessData() != at(m_arguments[argument]).variableAccessData()) 202 202 return 0; -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r101283 r102545 257 257 258 258 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); 260 260 move(stackPointerRegister, GPRInfo::argumentGPR0); 261 261 poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); -
trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h
r99787 r102545 35 35 #include "DFGCorrectableJumpPoint.h" 36 36 #include "DFGGPRInfo.h" 37 #include "DFGOperands.h" 37 38 #include "MacroAssembler.h" 38 39 #include "ValueProfile.h" … … 113 114 return index - m_arguments.size(); 114 115 } 115 int operandForArgument(int argument) const116 {117 return argument - m_arguments.size() - RegisterFile::CallFrameHeaderSize;118 }119 116 int operandForIndex(int index) const 120 117 { 121 118 if (index < (int)m_arguments.size()) 122 return operand ForArgument(index);119 return operandToArgument(index); 123 120 return index - m_arguments.size(); 124 121 } -
trunk/Source/JavaScriptCore/dfg/DFGOperands.h
r100975 r102545 31 31 #if ENABLE(DFG_JIT) 32 32 33 #include "CallFrame.h" 33 34 #include <wtf/Vector.h> 34 35 35 36 namespace JSC { namespace DFG { 36 37 37 // helper function to distinguish vars & temporaries from arguments.38 // argument 0 is 'this'. 38 39 inline bool operandIsArgument(int operand) { return operand < 0; } 40 inline int operandToArgument(int operand) { return -operand + CallFrame::thisArgumentOffset(); } 41 inline int argumentToOperand(int argument) { return -argument + CallFrame::thisArgumentOffset(); } 39 42 40 43 template<typename T> struct OperandValueTraits; … … 106 109 { 107 110 if (operandIsArgument(operand)) { 108 int argument = operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize;111 int argument = operandToArgument(operand); 109 112 return m_arguments[argument]; 110 113 } … … 118 121 { 119 122 if (operandIsArgument(operand)) { 120 int argument = operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize;123 int argument = operandToArgument(operand); 121 124 m_arguments[argument] = value; 122 125 return; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r101298 r102545 659 659 } 660 660 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 662 664 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall(); 663 else664 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);665 665 } 666 666 CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r102509 r102545 964 964 case InlineStart: { 965 965 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)]); 969 969 // The recovery cannot point to registers, since the call frame reification isn't 970 970 // as smart as OSR, so it can't handle that. The exception is the this argument, … … 1021 1021 1022 1022 #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); 1025 1025 1026 1026 fprintf(stderr, " : "); … … 1055 1055 1056 1056 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(); 1059 1060 #if USE(JSVALUE64) 1060 1061 if (isInt32Prediction(predictedType)) -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r102442 r102545 891 891 void compileInstanceOf(Node&); 892 892 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))); 896 903 } 897 904 898 905 #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)); 907 924 } 908 925 #endif … … 1046 1063 // correct registers. 1047 1064 #if !NUMBER_OF_ARGUMENT_REGISTERS 1048 unsigned m_callArgument Index;1049 void resetCallArguments() { m_callArgument Index= 0; }1065 unsigned m_callArgumentOffset; 1066 void resetCallArguments() { m_callArgumentOffset = 0; } 1050 1067 1051 1068 // These methods are using internally to implement the callOperation methods. 1052 1069 void addCallArgument(GPRReg value) 1053 1070 { 1054 m_jit.poke(value, m_callArgument Index++);1071 m_jit.poke(value, m_callArgumentOffset++); 1055 1072 } 1056 1073 void addCallArgument(TrustedImm32 imm) 1057 1074 { 1058 m_jit.poke(imm, m_callArgument Index++);1075 m_jit.poke(imm, m_callArgumentOffset++); 1059 1076 } 1060 1077 void addCallArgument(TrustedImmPtr pointer) 1061 1078 { 1062 m_jit.poke(pointer, m_callArgument Index++);1079 m_jit.poke(pointer, m_callArgumentOffset++); 1063 1080 } 1064 1081 void addCallArgument(FPRReg value) 1065 1082 { 1066 m_jit.storeDouble(value, JITCompiler::Address(JITCompiler::stackPointerRegister, m_callArgument Index* sizeof(void*)));1067 m_callArgument Index+= sizeof(double) / sizeof(void*);1083 m_jit.storeDouble(value, JITCompiler::Address(JITCompiler::stackPointerRegister, m_callArgumentOffset * sizeof(void*))); 1084 m_callArgumentOffset += sizeof(double) / sizeof(void*); 1068 1085 } 1069 1086 … … 2076 2093 { 2077 2094 if (operandIsArgument(operand)) { 2078 int argument = operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize;2095 int argument = operandToArgument(operand); 2079 2096 return m_arguments[argument]; 2080 2097 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r102442 r102545 1259 1259 use(calleeNodeIndex); 1260 1260 1261 // the call instruction's first child is either the function (normal call) or the1261 // The call instruction's first child is either the function (normal call) or the 1262 1262 // 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]; 1286 1273 JSValueOperand arg(this, argNodeIndex); 1287 1274 GPRReg argTagGPR = arg.tagGPR(); … … 1289 1276 use(argNodeIndex); 1290 1277 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 } 1297 1281 1298 1282 flushRegisters(); … … 1309 1293 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, calleeTagGPR, TrustedImm32(JSValue::CellTag))); 1310 1294 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)); 1313 1297 1314 1298 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r102442 r102545 1218 1218 use(calleeNodeIndex); 1219 1219 1220 // the call instruction's first child is either the function (normal call) or the1220 // The call instruction's first child is either the function (normal call) or the 1221 1221 // 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]; 1241 1230 JSValueOperand arg(this, argNodeIndex); 1242 1231 GPRReg argGPR = arg.gpr(); 1243 1232 use(argNodeIndex); 1244 1233 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 1250 1237 flushRegisters(); 1251 1238 1252 1239 GPRResult result(this); 1253 1240 GPRReg resultGPR = result.gpr(); … … 1255 1242 JITCompiler::DataLabelPtr targetToCheck; 1256 1243 JITCompiler::Jump slowPath; 1257 1244 1258 1245 slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue()))); 1259 1246 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)); 1261 1248 1262 1249 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); -
trunk/Source/JavaScriptCore/interpreter/CallFrame.h
r99148 r102545 144 144 145 145 // Access to arguments. 146 int hostThisRegister() { return -RegisterFile::CallFrameHeaderSize - argumentCountIncludingThis(); }147 JSValue hostThisValue() { return this[hostThisRegister()].jsValue(); }148 146 size_t argumentCount() const { return argumentCountIncludingThis() - 1; } 149 147 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(); } 157 171 158 172 static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); } … … 183 197 private: 184 198 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 185 202 #ifndef NDEBUG 186 203 RegisterFile* registerFile(); -
trunk/Source/JavaScriptCore/interpreter/CallFrameClosure.h
r100540 r102545 42 42 void setThis(JSValue value) 43 43 { 44 newCallFrame[-RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis] = value; 45 if (argumentCountIncludingThis > parameterCountIncludingThis) 46 newCallFrame[-RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis - argumentCountIncludingThis] = value; 44 newCallFrame->setThisValue(value); 47 45 } 48 46 49 47 void setArgument(int argument, JSValue value) 50 48 { 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); 56 50 } 57 51 … … 60 54 newCallFrame->setScopeChain(scopeChain); 61 55 for (int i = argumentCountIncludingThis; i < parameterCountIncludingThis; ++i) 62 newCallFrame [i - RegisterFile::CallFrameHeaderSize - parameterCountIncludingThis] = jsUndefined();56 newCallFrame->setArgument(i, jsUndefined()); 63 57 } 64 58 }; -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r102194 r102545 368 368 #endif // ENABLE(INTERPRETER) 369 369 370 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int arg c)370 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argumentCountIncludingThis) 371 371 { 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; 405 395 } 406 396 … … 464 454 } 465 455 466 JSValue thisValue = callerFrame-> uncheckedR(callerCodeBlock->thisRegister()).jsValue();456 JSValue thisValue = callerFrame->thisValue(); 467 457 ASSERT(isValidThisObject(thisValue, callFrame)); 468 458 Interpreter* interpreter = callFrame->globalData().interpreter; … … 480 470 } 481 471 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 491 472 newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis); 473 newCallFrame->setThisValue(thisValue); 474 for (size_t i = 0; i < callFrame->argumentCount(); ++i) 475 newCallFrame->setArgument(i, callFrame->argument(i)); 492 476 return newCallFrame; 493 477 } … … 499 483 return 0; 500 484 } 501 Register* dst = callFrame->registers() + firstFreeRegister;502 dst[0] = thisValue;503 504 485 newCallFrame->setArgumentCountIncludingThis(1); 486 newCallFrame->setThisValue(thisValue); 505 487 return newCallFrame; 506 488 } … … 519 501 return 0; 520 502 } 521 Register* dst = callFrame->registers() + firstFreeRegister;522 dst[0] = thisValue;523 argsObject->copyToRegisters(callFrame, &dst[1], argCount);524 525 503 newCallFrame->setArgumentCountIncludingThis(argCount + 1); 504 newCallFrame->setThisValue(thisValue); 505 argsObject->copyToArguments(callFrame, newCallFrame, argCount); 526 506 return newCallFrame; 527 507 } … … 535 515 return 0; 536 516 } 537 Register* dst = callFrame->registers() + firstFreeRegister;538 dst[0] = thisValue;539 array->copyToRegisters(callFrame, &dst[1], argCount);540 541 517 newCallFrame->setArgumentCountIncludingThis(argCount + 1); 518 newCallFrame->setThisValue(thisValue); 519 array->copyToArguments(callFrame, newCallFrame, argCount); 542 520 return newCallFrame; 543 521 } … … 550 528 return 0; 551 529 } 552 Register* dst = callFrame->registers() + firstFreeRegister;553 dst[0] = thisValue;554 for ( unsignedi = 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)); 556 534 if (UNLIKELY(callFrame->globalData().exception)) 557 535 return 0; 558 536 } 559 560 newCallFrame->setArgumentCountIncludingThis(argCount + 1);561 537 return newCallFrame; 562 538 } … … 701 677 } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) { 702 678 if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) 703 asArguments(arguments)->tearOff(callFrame ->globalData());679 asArguments(arguments)->tearOff(callFrame); 704 680 } 705 681 … … 986 962 ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'. 987 963 newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0); 988 newCallFrame-> uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);964 newCallFrame->setThisValue(thisObj); 989 965 TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame); 990 966 … … 1031 1007 size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize; 1032 1008 1033 if (!m_registerFile.grow(oldEnd + registerOffset)) 1009 CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset); 1010 if (!m_registerFile.grow(newCallFrame->registers())) 1034 1011 return checkedReturn(throwStackOverflowError(callFrame)); 1035 1012 1036 CallFrame* newCallFrame = CallFrame::create(oldEnd); 1037 size_t dst = 0; 1038 newCallFrame->uncheckedR(0) = thisValue; 1013 newCallFrame->setThisValue(thisValue); 1039 1014 for (size_t i = 0; i < args.size(); ++i) 1040 newCallFrame-> uncheckedR(++dst) = args.at(i);1015 newCallFrame->setArgument(i, args.at(i)); 1041 1016 1042 1017 if (callType == CallTypeJS) { … … 1052 1027 1053 1028 CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); 1054 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);1029 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount); 1055 1030 if (UNLIKELY(!newCallFrame)) { 1056 1031 m_registerFile.shrink(oldEnd); … … 1089 1064 ASSERT(callType == CallTypeHost); 1090 1065 ScopeChainNode* scopeChain = callFrame->scopeChain(); 1091 newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);1092 1066 newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function); 1093 1067 … … 1132 1106 return checkedReturn(throwStackOverflowError(callFrame)); 1133 1107 1134 CallFrame* newCallFrame = CallFrame::create(oldEnd );1135 size_t dst = 0;1108 CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset); 1109 newCallFrame->setThisValue(jsUndefined()); 1136 1110 for (size_t i = 0; i < args.size(); ++i) 1137 newCallFrame-> uncheckedR(++dst) = args.at(i);1111 newCallFrame->setArgument(i, args.at(i)); 1138 1112 1139 1113 if (constructType == ConstructTypeJS) { … … 1149 1123 1150 1124 CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct(); 1151 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);1125 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount); 1152 1126 if (UNLIKELY(!newCallFrame)) { 1153 1127 m_registerFile.shrink(oldEnd); … … 1189 1163 ASSERT(constructType == ConstructTypeHost); 1190 1164 ScopeChainNode* scopeChain = callFrame->scopeChain(); 1191 newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);1192 1165 newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor); 1193 1166 … … 1220 1193 ASSERT(!scopeChain->globalData->exception); 1221 1194 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) { 1231 1199 throwStackOverflowError(callFrame); 1232 1200 return CallFrameClosure(); 1233 1201 } 1234 1202 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 1241 1212 JSObject* error = functionExecutable->compileForCall(callFrame, scopeChain); 1242 1213 if (error) { … … 1247 1218 CodeBlock* codeBlock = &functionExecutable->generatedBytecodeForCall(); 1248 1219 1249 newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize, argumentCountIncludingThis);1220 newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, 0, argumentCountIncludingThis); 1250 1221 if (UNLIKELY(!newCallFrame)) { 1251 1222 throwStackOverflowError(callFrame); … … 1368 1339 ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'. 1369 1340 newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0); 1370 newCallFrame-> uncheckedR(newCallFrame->hostThisRegister()) = thisValue;1341 newCallFrame->setThisValue(thisValue); 1371 1342 1372 1343 TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame); … … 3511 3482 JSValue subscript = callFrame->r(property).jsValue(); 3512 3483 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()); 3519 3485 vPC += OPCODE_LENGTH(op_get_argument_by_val); 3520 3486 NEXT_INSTRUCTION(); … … 4326 4292 ScopeChainNode* scopeChain = callFrame->scopeChain(); 4327 4293 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); 4328 if (!registerFile->grow(newCallFrame->registers())) {4329 exceptionValue = createStackOverflowError(callFrame);4330 goto vm_throw;4331 }4332 4333 4294 newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v)); 4334 4295 JSValue returnValue; … … 4453 4414 } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) { 4454 4415 if (!codeBlock->isStrictMode()) 4455 asArguments(argumentsValue)->tearOff( *globalData);4416 asArguments(argumentsValue)->tearOff(callFrame); 4456 4417 } 4457 4418 … … 4475 4436 4476 4437 if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue()) 4477 asArguments(arguments)->tearOff( *globalData);4438 asArguments(arguments)->tearOff(callFrame); 4478 4439 4479 4440 vPC += OPCODE_LENGTH(op_tear_off_arguments); … … 4728 4689 ScopeChainNode* scopeChain = callFrame->scopeChain(); 4729 4690 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); 4730 if (!registerFile->grow(newCallFrame->registers())) {4731 exceptionValue = createStackOverflowError(callFrame);4732 goto vm_throw;4733 }4734 4691 newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, argCount, asObject(v)); 4735 4692 … … 5136 5093 } 5137 5094 5138 return Arguments::createAndTearOff(functionCallFrame->globalData(), functionCallFrame); 5095 Arguments* arguments = Arguments::create(functionCallFrame->globalData(), functionCallFrame); 5096 arguments->tearOff(functionCallFrame); 5097 return JSValue(arguments); 5139 5098 } 5140 5099 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.h
r100540 r102545 84 84 // We use a smaller reentrancy limit on iPhone because of the high amount of 85 85 // stack space required on the web thread. 86 enum { MaxLargeThreadReentryDepth = 93, MaxSmallThreadReentryDepth = 32};86 enum { MaxLargeThreadReentryDepth = 93, MaxSmallThreadReentryDepth = 16 }; 87 87 #else 88 enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 32};88 enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 16 }; 89 89 #endif // PLATFORM(IOS) 90 90 -
trunk/Source/JavaScriptCore/interpreter/RegisterFile.h
r100556 r102545 54 54 CodeBlock = -1, 55 55 }; 56 57 enum { ProgramCodeThisRegister = -CallFrameHeaderSize - 1 };58 56 59 57 static const size_t defaultCapacity = 512 * 1024; -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r102489 r102545 558 558 ASSERT(m_bytecodeOffset == (unsigned)-1); 559 559 if (shouldEmitProfiling()) { 560 for (int argument Register = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters; argumentRegister < -RegisterFile::CallFrameHeaderSize; ++argumentRegister) {560 for (int argument = 0; argument < m_codeBlock->m_numParameters; ++argument) { 561 561 // If this is a constructor, then we want to put in a dummy profiling site (to 562 562 // 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) 565 564 m_codeBlock->addValueProfile(-1); 566 565 else { 566 int offset = CallFrame::argumentOffsetIncludingThis(argument) * static_cast<int>(sizeof(Register)); 567 567 #if USE(JSVALUE64) 568 loadPtr(Address(callFrameRegister, argumentRegister * sizeof(Register)), regT0);568 loadPtr(Address(callFrameRegister, offset), regT0); 569 569 #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); 572 572 #endif 573 573 emitValueProfilingSite(FirstProfilingSite); … … 608 608 609 609 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); 611 611 612 612 JITStubCall(this, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck).call(callFrameRegister); -
trunk/Source/JavaScriptCore/jit/JITCall.cpp
r100165 r102545 65 65 JumpList slowCase; 66 66 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()) { 70 68 emitGetVirtualRegister(arguments, regT0); 71 69 slowCase.append(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue())))); … … 87 85 storePtr(regT2, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); 88 86 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. 90 92 neg32(regT0); 91 93 signExtend32ToPtr(regT0, regT0); 92 emitGetVirtualRegister(thisValue, regT2);93 storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));94 94 end.append(branchAddPtr(Zero, Imm32(1), regT0)); 95 // regT0: -argumentCount 95 96 96 97 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)))); 99 100 branchAddPtr(NonZero, Imm32(1), regT0).linkTo(copyLoop, this); 100 101 … … 102 103 } 103 104 104 if (m_codeBlock-> m_numParameters == 1)105 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) 105 106 slowCase.link(this); 106 107 … … 111 112 stubCall.call(regT1); 112 113 113 if (m_codeBlock-> m_numParameters == 1)114 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) 114 115 end.link(this); 115 116 } -
trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp
r100165 r102545 146 146 JumpList slowCase; 147 147 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()) { 151 149 emitLoadTag(arguments, regT1); 152 150 slowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag))); … … 168 166 store32(regT2, payloadFor(RegisterFile::ArgumentCount, regT3)); 169 167 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. 171 174 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)))));175 175 end.append(branchAdd32(Zero, Imm32(1), regT2)); 176 // regT2: -argumentCount; 176 177 177 178 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))))); 182 183 branchAdd32(NonZero, Imm32(1), regT2).linkTo(copyLoop, this); 183 184 … … 185 186 } 186 187 187 if (m_codeBlock-> m_numParameters == 1)188 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) 188 189 slowCase.link(this); 189 190 … … 194 195 stubCall.call(regT3); 195 196 196 if (m_codeBlock-> m_numParameters == 1)197 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) 197 198 end.link(this); 198 199 } -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r100165 r102545 1185 1185 1186 1186 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(); 1191 1188 emitPutVirtualRegister(dst); 1192 1189 emitPutVirtualRegister(unmodifiedArgumentsRegister(dst)); … … 1492 1489 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2); 1493 1490 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); 1511 1495 emitPutVirtualRegister(dst, regT0); 1512 1496 } … … 1523 1507 linkSlowCase(iter); 1524 1508 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(); 1529 1510 emitPutVirtualRegister(arguments); 1530 1511 emitPutVirtualRegister(unmodifiedArgumentsRegister(arguments)); -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r100881 r102545 1463 1463 Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag)); 1464 1464 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(); 1470 1466 emitStore(dst, regT1, regT0); 1471 1467 emitStore(unmodifiedArgumentsRegister(dst), regT1, regT0); … … 1611 1607 addSlowCase(branch32(AboveOrEqual, regT2, regT3)); 1612 1608 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); 1631 1612 emitStore(dst, regT1, regT0); 1632 1613 } … … 1643 1624 linkSlowCase(iter); 1644 1625 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(); 1650 1627 emitStore(arguments, regT1, regT0); 1651 1628 emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0); -
trunk/Source/JavaScriptCore/jit/JITStubs.cpp
r102167 r102545 2202 2202 } 2203 2203 2204 static size_t debugCount[5]; 2205 struct 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 2214 DebugCounter debugCounter; 2215 2204 2216 inline CallFrame* arityCheckFor(CallFrame* callFrame, RegisterFile* registerFile, CodeSpecializationKind kind) 2205 2217 { … … 2207 2219 ASSERT(!callee->isHostFunction()); 2208 2220 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; 2249 2248 } 2250 2249 … … 2292 2291 return 0; 2293 2292 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) 2295 2294 || callLinkInfo->callType == CallLinkInfo::CallVarargs) 2296 2295 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind); … … 2376 2375 } 2377 2376 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 2386 2377 DEFINE_STUB_FUNCTION(void, op_tear_off_activation) 2387 2378 { 2388 2379 STUB_INIT_STACK_FRAME(stackFrame); 2389 2380 2390 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain()); 2381 CallFrame* callFrame = stackFrame.callFrame; 2382 ASSERT(callFrame->codeBlock()->needsFullScopeChain()); 2391 2383 JSValue activationValue = stackFrame.args[0].jsValue(); 2392 2384 if (!activationValue) { 2393 2385 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); 2396 2388 } 2397 2389 return; … … 2407 2399 STUB_INIT_STACK_FRAME(stackFrame); 2408 2400 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); 2411 2404 } 2412 2405 -
trunk/Source/JavaScriptCore/jit/JITStubs.h
r102167 r102545 327 327 EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION); 328 328 EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION); 329 EncodedJSValue JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);330 329 EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION); 331 330 EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION); -
trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
r97872 r102545 48 48 void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch) 49 49 { 50 unsigned src = argumentToVirtualRegister(argument);50 unsigned src = CallFrame::argumentOffset(argument); 51 51 m_failures.append(emitLoadDouble(src, dst, scratch)); 52 52 } … … 54 54 void loadCellArgument(int argument, RegisterID dst) 55 55 { 56 unsigned src = argumentToVirtualRegister(argument);56 unsigned src = CallFrame::argumentOffset(argument); 57 57 m_failures.append(emitLoadJSCell(src, dst)); 58 58 } … … 66 66 void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget) 67 67 { 68 unsigned src = argumentToVirtualRegister(argument);68 unsigned src = CallFrame::argumentOffset(argument); 69 69 failTarget = emitLoadInt32(src, dst); 70 70 } … … 150 150 151 151 private: 152 int argumentToVirtualRegister(unsigned argument)153 {154 return -static_cast<int>(RegisterFile::CallFrameHeaderSize + (m_expectedArgCount - argument));155 }156 152 157 153 void tagReturnAsInt32() -
trunk/Source/JavaScriptCore/runtime/ArgList.cpp
r100516 r102545 33 33 void ArgList::getSlice(int startIndex, ArgList& result) const 34 34 { 35 if (startIndex <= 0 || sta tic_cast<unsigned>(startIndex)>= m_argCount) {35 if (startIndex <= 0 || startIndex >= m_argCount) { 36 36 result = ArgList(); 37 37 return; 38 38 } 39 39 40 result.m_args = m_args +startIndex;40 result.m_args = m_args - startIndex; 41 41 result.m_argCount = m_argCount - startIndex; 42 42 } … … 53 53 void MarkedArgumentBuffer::slowAppend(JSValue v) 54 54 { 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 55 72 // As long as our size stays within our Vector's inline 56 73 // capacity, all our values are allocated on the stack, and … … 58 75 // our Vector's inline capacity, though, our values move to the 59 76 // 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 buffer62 // 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; 68 85 } 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 Lists76 // 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();81 86 } 82 87 -
trunk/Source/JavaScriptCore/runtime/ArgList.h
r101604 r102545 39 39 40 40 private: 41 static const unsignedinlineCapacity = 8;41 static const size_t inlineCapacity = 8; 42 42 typedef Vector<Register, inlineCapacity> VectorType; 43 43 typedef HashSet<MarkedArgumentBuffer*> ListSet; … … 47 47 // FIXME: Remove all clients of this API, then remove this API. 48 48 MarkedArgumentBuffer() 49 : m_isUsingInlineBuffer(true) 49 : m_size(0) 50 , m_capacity(inlineCapacity) 51 , m_buffer(&m_inlineBuffer[m_capacity - 1]) 50 52 , m_markSet(0) 51 #ifndef NDEBUG52 , m_isReadOnly(false)53 #endif54 53 { 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 NDEBUG66 , m_isReadOnly(true)67 #endif68 {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 NDEBUG79 m_isReadOnly = true;80 #endif81 54 } 82 55 … … 85 58 if (m_markSet) 86 59 m_markSet->remove(this); 60 61 if (m_capacity != inlineCapacity) 62 delete [] &m_buffer[-(m_capacity - 1)]; 87 63 } 88 64 … … 90 66 bool isEmpty() const { return !m_size; } 91 67 92 JSValue at( size_t i) const68 JSValue at(int i) const 93 69 { 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]); 97 74 } 98 75 99 76 void clear() 100 77 { 101 m_vector.clear();102 m_buffer = 0;103 78 m_size = 0; 104 79 } … … 106 81 void append(JSValue v) 107 82 { 108 ASSERT(!m_isReadOnly); 83 if (m_size >= m_capacity) 84 return slowAppend(v); 109 85 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; 120 88 } 121 89 … … 124 92 ASSERT(m_size); 125 93 m_size--; 126 m_vector.removeLast();127 94 } 128 95 … … 130 97 { 131 98 ASSERT(m_size); 132 return m_buffer[m_size - 1].jsValue();99 return JSValue::decode(m_buffer[-(m_size - 1)]); 133 100 } 134 101 … … 138 105 void slowAppend(JSValue); 139 106 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; 145 111 ListSet* m_markSet; 146 #ifndef NDEBUG147 bool m_isReadOnly;148 #endif149 112 150 113 private: … … 174 137 { 175 138 } 176 139 177 140 ArgList(ExecState* exec) 178 : m_args(reinterpret_cast<JSValue*>(&exec[ exec->hostThisRegister() + 1]))141 : m_args(reinterpret_cast<JSValue*>(&exec[CallFrame::argumentOffset(0)])) 179 142 , m_argCount(exec->argumentCount()) 180 143 { 181 144 } 182 145 183 146 ArgList(const MarkedArgumentBuffer& args) 184 147 : m_args(reinterpret_cast<JSValue*>(args.m_buffer)) … … 187 150 } 188 151 189 JSValue at( size_t idx) const152 JSValue at(int i) const 190 153 { 191 if (i dx <m_argCount)192 return m_args[idx];193 return jsUndefined();154 if (i >= m_argCount) 155 return jsUndefined(); 156 return m_args[-i]; 194 157 } 195 158 … … 201 164 private: 202 165 JSValue* m_args; 203 size_t m_argCount;166 int m_argCount; 204 167 }; 205 168 -
trunk/Source/JavaScriptCore/runtime/Arguments.cpp
r100006 r102545 38 38 const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) }; 39 39 40 Arguments::~Arguments()41 {42 if (d->extraArguments != d->extraArgumentsFixedBuffer)43 delete [] d->extraArguments;44 }45 46 40 void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor) 47 41 { … … 53 47 54 48 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); 62 50 visitor.append(&thisObject->d->callee); 63 64 51 if (thisObject->d->activation) 65 52 visitor.append(&thisObject->d->activation); 66 53 } 67 54 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(); 55 void 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()); 92 61 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)); 100 63 } 101 64 } … … 103 66 void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) 104 67 { 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()); 137 72 else 138 73 args.append(get(exec, i)); 139 74 } 140 for (; i < d->numArguments; ++i) {141 if (!d->deletedArguments[i])142 args.append(d->extraArguments[i - d->numParameters].get());143 else144 args.append(get(exec, i));145 }146 75 } 147 76 … … 150 79 Arguments* thisObject = jsCast<Arguments*>(cell); 151 80 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()); 156 82 return true; 157 83 } … … 190 116 unsigned i = propertyName.toArrayIndex(isArrayIndex); 191 117 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()); 196 119 return true; 197 120 } … … 222 145 unsigned i = propertyName.toArrayIndex(isArrayIndex); 223 146 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); 228 148 return true; 229 149 } … … 265 185 { 266 186 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); 272 189 return; 273 190 } … … 283 200 unsigned i = propertyName.toArrayIndex(isArrayIndex); 284 201 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); 289 203 return; 290 204 } … … 363 277 } 364 278 279 void 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 365 330 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/Arguments.h
r100224 r102545 40 40 WriteBarrier<JSActivation> activation; 41 41 42 unsigned numParameters;43 ptrdiff_t firstParameterIndex;44 42 unsigned numArguments; 45 43 … … 47 45 OwnArrayPtr<WriteBarrier<Unknown> > registerArray; 48 46 49 WriteBarrier<Unknown>* extraArguments;50 47 OwnArrayPtr<bool> deletedArguments; 51 WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];52 48 53 49 WriteBarrier<JSFunction> callee; … … 56 52 bool overrodeCaller : 1; 57 53 bool isStrictMode : 1; 58 bool isInlineFrame : 1; // If true, all arguments are in the extraArguments buffer.59 54 }; 60 61 55 62 56 class Arguments : public JSNonFinalObject { … … 70 64 return arguments; 71 65 } 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 }86 66 87 // Use an enum because otherwise gcc insists on doing a memory88 // read.89 67 enum { MaxArguments = 0x10000 }; 90 68 … … 96 74 97 75 public: 98 virtual ~Arguments();99 100 76 static const ClassInfo s_info; 101 77 … … 111 87 } 112 88 113 void copyTo Registers(ExecState* exec, Register* buffer, uint32_t maxSize);114 void tearOff( JSGlobalData&);89 void copyToArguments(ExecState*, CallFrame*, uint32_t length); 90 void tearOff(CallFrame*); 115 91 bool isTornOff() const { return d->registerArray; } 116 92 void didTearOffActivation(JSGlobalData& globalData, JSActivation* activation) … … 130 106 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; 131 107 132 void finishCreationButDontTearOff(CallFrame*);133 108 void finishCreation(CallFrame*); 134 void finishCreationAndTearOff(CallFrame*);135 void finishCreation(CallFrame*, NoParametersType);136 109 137 110 private: 138 void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);139 111 static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); 140 112 static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); … … 147 119 void createStrictModeCallerIfNecessary(ExecState*); 148 120 void createStrictModeCalleeIfNecessary(ExecState*); 121 122 WriteBarrier<Unknown>& argument(size_t); 149 123 150 124 void init(CallFrame*); … … 161 135 } 162 136 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 else176 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;177 178 argc -= 1; // - 1 to skip "this"179 firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;180 }181 182 137 inline Arguments::Arguments(CallFrame* callFrame) 183 138 : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) … … 191 146 { 192 147 } 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) 195 155 { 196 156 Base::finishCreation(callFrame->globalData()); 197 157 ASSERT(inherits(&s_info)); 198 158 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(); 210 161 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 else220 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 227 162 d->callee.set(callFrame->globalData(), this, callee); 228 163 d->overrodeLength = false; … … 230 165 d->overrodeCaller = false; 231 166 d->isStrictMode = callFrame->codeBlock()->isStrictMode(); 232 }233 167 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); 378 172 } 379 173 -
trunk/Source/JavaScriptCore/runtime/JSActivation.cpp
r100672 r102545 34 34 #include "JSFunction.h" 35 35 36 using namespace std; 37 36 38 namespace JSC { 37 39 … … 42 44 JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable) 43 45 : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers()) 44 , m_num ParametersMinusThis(static_cast<int>(functionExecutable->parameterCount()))46 , m_numCapturedArgs(max(callFrame->argumentCount(), functionExecutable->parameterCount())) 45 47 , m_numCapturedVars(functionExecutable->capturedVariableCount()) 46 48 , m_requiresDynamicChecks(functionExecutable->usesEval()) … … 78 80 return; 79 81 80 visitor.appendValues(registerArray, thisObject->m_num ParametersMinusThis);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); 84 86 } 85 87 -
trunk/Source/JavaScriptCore/runtime/JSActivation.h
r100822 r102545 90 90 NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); 91 91 92 int m_num ParametersMinusThis;92 int m_numCapturedArgs; 93 93 int m_numCapturedVars : 31; 94 94 bool m_requiresDynamicChecks : 1; … … 118 118 { 119 119 ASSERT(!m_registerArray); 120 ASSERT(m_numCapturedVars + m_numCapturedArgs); 120 121 121 size_t numLocals = m_numCapturedVars + m_numParametersMinusThis; 122 int registerOffset = CallFrame::offsetFor(m_numCapturedArgs + 1); 123 size_t registerArraySize = registerOffset + m_numCapturedVars; 122 124 123 if (!numLocals)124 return;125 OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]); 126 WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset; 125 127 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 } 128 133 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 131 140 setRegisters(registers, registerArray.release()); 132 141 } -
trunk/Source/JavaScriptCore/runtime/JSArray.cpp
r101604 r102545 1266 1266 } 1267 1267 1268 void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) 1269 { 1270 ASSERT(m_storage->m_length >= maxSize); 1271 UNUSED_PARAM(maxSize); 1268 void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length) 1269 { 1270 ASSERT(length == this->length()); 1271 UNUSED_PARAM(length); 1272 unsigned i = 0; 1272 1273 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); 1275 1275 for (; i < vectorEnd; ++i) { 1276 1276 WriteBarrier<Unknown>& v = vector[i]; 1277 1277 if (!v) 1278 1278 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)); 1284 1284 } 1285 1285 -
trunk/Source/JavaScriptCore/runtime/JSArray.h
r100516 r102545 156 156 157 157 void fillArgList(ExecState*, MarkedArgumentBuffer&); 158 void copyTo Registers(ExecState*, Register*, uint32_t);158 void copyToArguments(ExecState*, CallFrame*, uint32_t length); 159 159 160 160 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
Note: See TracChangeset
for help on using the changeset viewer.