Changeset 37324 in webkit for trunk/JavaScriptCore
- Timestamp:
- Oct 5, 2008, 11:00:58 PM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r37323 r37324 1 2008-10-05 Cameron Zwarich <[email protected]> 2 3 Reviewed by Oliver Hunt. 4 5 Bug 21364: Remove the branch in op_ret for OptionalCalleeActivation and OptionalCalleeArguments 6 <https://bugs.webkit.org/show_bug.cgi?id=21364> 7 8 Use information from the parser to detect whether an activation is 9 needed or 'arguments' is used, and emit explicit instructions to tear 10 them off before op_ret. This allows a branch to be removed from op_ret 11 and simplifies some other code. This does cause a small change in the 12 behaviour of 'f.arguments'; it is no longer live when 'arguments' is not 13 mentioned in the lexical scope of the function. 14 15 It should now be easy to remove the OptionaCalleeActivation slot in the 16 call frame, but this will be done in a later patch. 17 18 * VM/CTI.cpp: 19 (JSC::CTI::privateCompileMainPass): 20 * VM/CodeBlock.cpp: 21 (JSC::CodeBlock::dump): 22 * VM/CodeGenerator.cpp: 23 (JSC::CodeGenerator::emitReturn): 24 * VM/CodeGenerator.h: 25 * VM/Machine.cpp: 26 (JSC::Machine::unwindCallFrame): 27 (JSC::Machine::privateExecute): 28 (JSC::Machine::retrieveArguments): 29 (JSC::Machine::cti_op_create_arguments): 30 (JSC::Machine::cti_op_tear_off_activation): 31 (JSC::Machine::cti_op_tear_off_arguments): 32 * VM/Machine.h: 33 * VM/Opcode.h: 34 * kjs/Arguments.cpp: 35 (JSC::Arguments::mark): 36 * kjs/Arguments.h: 37 (JSC::Arguments::isTornOff): 38 (JSC::Arguments::Arguments): 39 (JSC::Arguments::copyRegisters): 40 (JSC::JSActivation::copyRegisters): 41 * kjs/JSActivation.cpp: 42 (JSC::JSActivation::argumentsGetter): 43 * kjs/JSActivation.h: 44 1 45 2008-10-05 Maciej Stachowiak <[email protected]> 2 46 -
trunk/JavaScriptCore/VM/CTI.cpp
r37297 r37324 1171 1171 break; 1172 1172 } 1173 case op_tear_off_activation: { 1174 emitCall(i, Machine::cti_op_tear_off_activation); 1175 i += 1; 1176 break; 1177 } 1178 case op_tear_off_arguments: { 1179 emitCall(i, Machine::cti_op_tear_off_arguments); 1180 i += 1; 1181 break; 1182 } 1173 1183 case op_ret: { 1174 // If there is an activation or an 'arguments' object, we tear it1175 // off by jumping to the hook below.1176 m_jit.movl_mr(RegisterFile::OptionalCalleeActivation * static_cast<int>(sizeof(Register)), X86::edi, X86::eax);1177 m_jit.orl_mr(RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register)), X86::edi, X86::eax);1178 m_jit.cmpl_i32r(0, X86::eax);1179 X86Assembler::JmpSrc activation = m_jit.emitUnlinkedJne();1180 X86Assembler::JmpDst activated = m_jit.label();1181 1182 1184 // Check for a profiler - if there is one, jump to the hook below. 1183 1185 emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax); … … 1203 1205 m_jit.pushl_r(X86::edx); 1204 1206 m_jit.ret(); 1205 1206 // Activation and 'arguments' hook1207 m_jit.link(activation, m_jit.label());1208 emitCall(i, Machine::cti_op_ret_activation_arguments);1209 m_jit.link(m_jit.emitUnlinkedJmp(), activated);1210 1207 1211 1208 // Profiling hook -
trunk/JavaScriptCore/VM/CodeBlock.cpp
r37294 r37324 810 810 break; 811 811 } 812 case op_tear_off_activation: { 813 int r0 = (++it)->u.operand; 814 printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str()); 815 break; 816 } 817 case op_tear_off_arguments: { 818 int r0 = (++it)->u.operand; 819 printf("[%4d] tear_off_arguments\t %s\n", location, registerName(r0).c_str()); 820 break; 821 } 812 822 case op_ret: { 813 823 int r0 = (++it)->u.operand; -
trunk/JavaScriptCore/VM/CodeGenerator.cpp
r37320 r37324 1159 1159 } 1160 1160 1161 RegisterID* CodeGenerator::emitReturn(RegisterID* src) 1162 { 1163 if (m_codeBlock->needsFullScopeChain) 1164 emitOpcode(op_tear_off_activation); 1165 else if (m_codeBlock->usesArguments) 1166 emitOpcode(op_tear_off_arguments); 1167 1168 return emitUnaryNoDstOp(op_ret, src); 1169 } 1170 1161 1171 RegisterID* CodeGenerator::emitUnaryNoDstOp(OpcodeID opcode, RegisterID* src) 1162 1172 { -
trunk/JavaScriptCore/VM/CodeGenerator.h
r37050 r37324 278 278 RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); 279 279 280 RegisterID* emitReturn(RegisterID* src) { return emitUnaryNoDstOp(op_ret, src); }280 RegisterID* emitReturn(RegisterID* src); 281 281 RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); } 282 282 -
trunk/JavaScriptCore/VM/Machine.cpp
r37323 r37324 782 782 if (JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].getJSValue())) { 783 783 ASSERT(activation->isObject(&JSActivation::info)); 784 activation->copyRegisters(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 784 Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 785 ASSERT(!arguments || arguments->isObject(&Arguments::info)); 786 activation->copyRegisters(arguments); 785 787 } else if (Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue())) { 786 788 ASSERT(arguments->isObject(&Arguments::info)); 787 arguments->copyRegisters(); 789 if (!arguments->isTornOff()) 790 arguments->copyRegisters(); 788 791 } 789 792 … … 3352 3355 goto vm_throw; 3353 3356 } 3357 BEGIN_OPCODE(op_tear_off_activation) { 3358 JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].getJSValue()); 3359 ASSERT(codeBlock(r)->needsFullScopeChain); 3360 ASSERT(activation->isObject(&JSActivation::info)); 3361 3362 Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 3363 ASSERT(!arguments || arguments->isObject(&Arguments::info)); 3364 activation->copyRegisters(arguments); 3365 3366 ++vPC; 3367 NEXT_OPCODE; 3368 } 3369 BEGIN_OPCODE(op_tear_off_arguments) { 3370 Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 3371 ASSERT(codeBlock(r)->usesArguments && !codeBlock(r)->needsFullScopeChain); 3372 ASSERT(arguments->isObject(&Arguments::info)); 3373 3374 arguments->copyRegisters(); 3375 3376 ++vPC; 3377 NEXT_OPCODE; 3378 } 3354 3379 BEGIN_OPCODE(op_ret) { 3355 3380 /* ret result(r) … … 3364 3389 int result = (++vPC)->u.operand; 3365 3390 3366 // If this call frame created an activation or an 'arguments' object, tear it off.3367 if (JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].getJSValue())) {3368 ASSERT(!codeBlock(r)->needsFullScopeChain || scopeChain(r)->object == activation);3369 ASSERT(activation->isObject(&JSActivation::info));3370 activation->copyRegisters(r[RegisterFile::OptionalCalleeArguments].getJSValue());3371 } else if (Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue())) {3372 ASSERT(arguments->isObject(&Arguments::info));3373 arguments->copyRegisters();3374 }3375 3376 3391 if (*enabledProfilerReference) 3377 3392 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(r[RegisterFile::Callee].jsValue(exec))); … … 3466 3481 */ 3467 3482 3468 JSValue* activation = r[RegisterFile::OptionalCalleeActivation].getJSValue(); 3469 Arguments* arguments; 3470 if (activation) { 3471 ASSERT(activation->isObject(&JSActivation::info)); 3472 arguments = new (globalData) Arguments(exec, static_cast<JSActivation*>(activation)); 3473 } else 3474 arguments = new (globalData) Arguments(exec, r); 3483 Arguments* arguments = new (globalData) Arguments(exec, r); 3475 3484 r[RegisterFile::OptionalCalleeArguments] = arguments; 3476 3485 r[RegisterFile::ArgumentsRegister] = arguments; … … 3908 3917 return jsNull(); 3909 3918 3910 JSValue* arguments;3911 3919 CodeBlock* codeBlock = Machine::codeBlock(r); 3912 3920 if (codeBlock->usesArguments) { … … 3914 3922 SymbolTable& symbolTable = static_cast<FunctionBodyNode*>(codeBlock->ownerNode)->symbolTable(); 3915 3923 int argumentsIndex = symbolTable.get(exec->propertyNames().arguments.ustring().rep()).getIndex(); 3916 arguments = r[argumentsIndex].jsValue(exec); 3917 } else { 3918 arguments = r[RegisterFile::OptionalCalleeArguments].getJSValue(); 3919 if (!arguments) { 3920 JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].getJSValue()); 3921 if (activation) 3922 arguments = new (exec) Arguments(exec, activation); 3923 else 3924 arguments = new (exec) Arguments(exec, r); 3925 r[RegisterFile::OptionalCalleeArguments] = arguments; 3926 } 3927 ASSERT(arguments->isObject(&Arguments::info)); 3928 } 3924 return r[argumentsIndex].jsValue(exec); 3925 } 3926 3927 Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 3928 if (!arguments) { 3929 arguments = new (exec) Arguments(exec, r); 3930 arguments->copyRegisters(); 3931 r[RegisterFile::OptionalCalleeArguments] = arguments; 3932 } 3933 ASSERT(arguments->isObject(&Arguments::info)); 3929 3934 3930 3935 return arguments; … … 4654 4659 Register* r = ARG_r; 4655 4660 4656 JSValue* activation = r[RegisterFile::OptionalCalleeActivation].getJSValue(); 4657 Arguments* arguments; 4658 if (activation) { 4659 ASSERT(activation->isObject(&JSActivation::info)); 4660 arguments = new (ARG_globalData) Arguments(exec, static_cast<JSActivation*>(activation)); 4661 } else 4662 arguments = new (ARG_globalData) Arguments(exec, r); 4661 Arguments* arguments = new (ARG_globalData) Arguments(exec, r); 4663 4662 r[RegisterFile::OptionalCalleeArguments] = arguments; 4664 4663 r[RegisterFile::ArgumentsRegister] = arguments; 4665 4664 } 4666 4665 4667 void Machine::cti_op_ ret_activation_arguments(CTI_ARGS)4666 void Machine::cti_op_tear_off_activation(CTI_ARGS) 4668 4667 { 4669 4668 Register* r = ARG_r; 4670 4669 4671 // If this call frame created an activation or an 'arguments' object, tear it off. 4672 if (JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].getJSValue())) { 4673 ASSERT(!codeBlock(r)->needsFullScopeChain || scopeChain(r)->object == activation); 4674 ASSERT(activation->isObject(&JSActivation::info)); 4675 activation->copyRegisters(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 4676 } else if (Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue())) { 4677 ASSERT(arguments->isObject(&Arguments::info)); 4678 arguments->copyRegisters(); 4679 } 4670 JSActivation* activation = static_cast<JSActivation*>(r[RegisterFile::OptionalCalleeActivation].getJSValue()); 4671 ASSERT(codeBlock(r)->needsFullScopeChain); 4672 ASSERT(activation->isObject(&JSActivation::info)); 4673 4674 Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 4675 ASSERT(!arguments || arguments->isObject(&Arguments::info)); 4676 activation->copyRegisters(arguments); 4677 } 4678 4679 void Machine::cti_op_tear_off_arguments(CTI_ARGS) 4680 { 4681 Register* r = ARG_r; 4682 4683 Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue()); 4684 ASSERT(codeBlock(r)->usesArguments && !codeBlock(r)->needsFullScopeChain); 4685 ASSERT(arguments->isObject(&Arguments::info)); 4686 4687 arguments->copyRegisters(); 4680 4688 } 4681 4689 -
trunk/JavaScriptCore/VM/Machine.h
r37323 r37324 165 165 static JSValue* SFX_CALL cti_op_call_NotJSFunction(CTI_ARGS); 166 166 static void SFX_CALL cti_op_create_arguments(CTI_ARGS); 167 static void SFX_CALL cti_op_ret_activation_arguments(CTI_ARGS); 167 static void SFX_CALL cti_op_tear_off_activation(CTI_ARGS); 168 static void SFX_CALL cti_op_tear_off_arguments(CTI_ARGS); 168 169 static void SFX_CALL cti_op_ret_profiler(CTI_ARGS); 169 170 static void SFX_CALL cti_op_ret_scopeChain(CTI_ARGS); -
trunk/JavaScriptCore/VM/Opcode.h
r37294 r37324 138 138 macro(op_call) \ 139 139 macro(op_call_eval) \ 140 macro(op_tear_off_activation) \ 141 macro(op_tear_off_arguments) \ 140 142 macro(op_ret) \ 141 143 \ -
trunk/JavaScriptCore/kjs/Arguments.cpp
r37268 r37324 65 65 if (!d->callee->marked()) 66 66 d->callee->mark(); 67 68 if (d->activation && !d->activation->marked())69 d->activation->mark();70 67 } 71 68 -
trunk/JavaScriptCore/kjs/Arguments.h
r37268 r37324 33 33 34 34 struct ArgumentsData : Noncopyable { 35 JSActivation* activation;36 37 35 unsigned numParameters; 38 36 ptrdiff_t firstParameterIndex; … … 55 53 public: 56 54 Arguments(ExecState*, Register* callFrame); 57 Arguments(ExecState*, JSActivation*);58 55 virtual ~Arguments(); 59 56 … … 65 62 66 63 void copyRegisters(); 64 bool isTornOff() const { return d->registerArray; } 67 65 void setRegisters(Register* registers) { d->registers = registers; } 68 66 … … 82 80 }; 83 81 84 inline void Arguments::init(ExecState* exec, Register* callFrame) 82 inline Arguments::Arguments(ExecState* exec, Register* callFrame) 83 : JSObject(exec->lexicalGlobalObject()->argumentsStructure()) 84 , d(new ArgumentsData) 85 85 { 86 86 JSFunction* callee; … … 116 116 } 117 117 118 inline Arguments::Arguments(ExecState* exec, Register* callFrame)119 : JSObject(exec->lexicalGlobalObject()->argumentsStructure())120 , d(new ArgumentsData)121 {122 d->activation = 0;123 init(exec, callFrame);124 }125 126 inline Arguments::Arguments(ExecState* exec, JSActivation* activation)127 : JSObject(exec->lexicalGlobalObject()->argumentsStructure())128 , d(new ArgumentsData)129 {130 ASSERT(activation);131 d->activation = activation;132 init(exec, &activation->registerAt(0));133 }134 135 118 inline void Arguments::copyRegisters() 136 119 { 137 ASSERT(!d->activation); 138 ASSERT(!d->registerArray); 120 ASSERT(!isTornOff()); 139 121 140 122 if (!d->numParameters) … … 151 133 152 134 // This JSActivation function is defined here so it can get at Arguments::setRegisters. 153 inline void JSActivation::copyRegisters( JSValue* arguments)135 inline void JSActivation::copyRegisters(Arguments* arguments) 154 136 { 155 137 ASSERT(!d()->registerArray); … … 167 149 Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize); 168 150 setRegisters(registerArray + registerOffset, registerArray); 169 if (arguments) { 170 ASSERT(arguments->isObject(&Arguments::info)); 151 if (arguments && !arguments->isTornOff()) 171 152 static_cast<Arguments*>(arguments)->setRegisters(registerArray + registerOffset); 172 }173 153 } 174 154 -
trunk/JavaScriptCore/kjs/JSActivation.cpp
r37285 r37324 156 156 JSActivation* thisObj = static_cast<JSActivation*>(slot.slotBase()); 157 157 158 JSValue* arguments;159 158 if (thisObj->d()->functionBody->usesArguments()) { 160 159 PropertySlot slot; 161 160 thisObj->symbolTableGet(exec->propertyNames().arguments, slot); 162 arguments = slot.getValue(exec, exec->propertyNames().arguments); 163 } else { 164 arguments = thisObj->d()->registers[RegisterFile::OptionalCalleeArguments].getJSValue(); 165 if (!arguments) { 166 arguments = new (exec) Arguments(exec, thisObj); 167 thisObj->d()->registers[RegisterFile::OptionalCalleeArguments] = arguments; 168 } 169 ASSERT(arguments->isObject(&Arguments::info)); 161 return slot.getValue(exec, exec->propertyNames().arguments); 170 162 } 163 164 Arguments* arguments = static_cast<Arguments*>(thisObj->d()->registers[RegisterFile::OptionalCalleeArguments].getJSValue()); 165 if (!arguments) { 166 arguments = new (exec) Arguments(exec, &thisObj->registerAt(0)); 167 arguments->copyRegisters(); 168 thisObj->d()->registers[RegisterFile::OptionalCalleeArguments] = arguments; 169 } 170 ASSERT(arguments->isObject(&Arguments::info)); 171 171 172 172 return arguments; -
trunk/JavaScriptCore/kjs/JSActivation.h
r37285 r37324 60 60 virtual JSObject* toThisObject(ExecState*) const; 61 61 62 void copyRegisters( JSValue* arguments);62 void copyRegisters(Arguments* arguments); 63 63 64 64 virtual const ClassInfo* classInfo() const { return &info; }
Note:
See TracChangeset
for help on using the changeset viewer.