Changeset 42065 in webkit for trunk/JavaScriptCore
- Timestamp:
- Mar 27, 2009, 8:50:39 PM (16 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r42037 r42065 1 2009-03-27 Oliver Hunt <[email protected]> 2 3 Reviewed by Gavin Barraclough. 4 5 Improve performance of Function.prototype.call 6 <https://bugs.webkit.org/show_bug.cgi?id=24907> 7 8 Optimistically assume that expression.call(..) is going to be a call to 9 Function.prototype.call, and handle it specially to attempt to reduce the 10 degree of VM reentrancy. 11 12 When everything goes right this removes the vm reentry improving .call() 13 by around a factor of 10. 14 15 * JavaScriptCore.xcodeproj/project.pbxproj: 16 * bytecode/CodeBlock.cpp: 17 (JSC::CodeBlock::dump): 18 * bytecode/Opcode.h: 19 * bytecompiler/BytecodeGenerator.cpp: 20 (JSC::BytecodeGenerator::emitJumpIfNotFunctionCall): 21 * bytecompiler/BytecodeGenerator.h: 22 * interpreter/Interpreter.cpp: 23 (JSC::Interpreter::privateExecute): 24 * jit/JIT.cpp: 25 (JSC::JIT::privateCompileMainPass): 26 * parser/Grammar.y: 27 * parser/Nodes.cpp: 28 (JSC::CallFunctionCallDotNode::emitBytecode): 29 * parser/Nodes.h: 30 (JSC::CallFunctionCallDotNode::): 31 * runtime/FunctionPrototype.cpp: 32 (JSC::FunctionPrototype::addFunctionProperties): 33 * runtime/FunctionPrototype.h: 34 * runtime/JSGlobalObject.cpp: 35 (JSC::JSGlobalObject::reset): 36 (JSC::JSGlobalObject::mark): 37 * runtime/JSGlobalObject.h: 38 1 39 2009-03-27 Laszlo Gombos <[email protected]> 2 40 -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r40993 r42065 889 889 break; 890 890 } 891 case op_jn less: {891 case op_jneq_ptr: { 892 892 int r0 = (++it)->u.operand; 893 893 int r1 = (++it)->u.operand; 894 894 int offset = (++it)->u.operand; 895 printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); 895 printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); 896 break; 897 } 898 case op_jnless: { 899 int r0 = (++it)->u.operand; 900 JSValuePtr function = JSValuePtr((++it)->u.jsCell); 901 int offset = (++it)->u.operand; 902 printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), valueToSourceString(exec, function).ascii(), offset, locationForOffset(begin, it, offset)); 896 903 break; 897 904 } -
trunk/JavaScriptCore/bytecode/Opcode.h
r39752 r42065 126 126 macro(op_jeq_null, 3) \ 127 127 macro(op_jneq_null, 3) \ 128 macro(op_jneq_ptr, 4) \ 128 129 macro(op_jnless, 4) \ 129 130 macro(op_jmp_scopes, 3) \ -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r40993 r42065 692 692 emitOpcode(op_jfalse); 693 693 instructions().append(cond->index()); 694 instructions().append(target->offsetFrom(instructions().size())); 695 return target; 696 } 697 698 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target) 699 { 700 emitOpcode(op_jneq_ptr); 701 instructions().append(cond->index()); 702 instructions().append(m_scopeChain->globalObject()->d()->callFunction); 694 703 instructions().append(target->offsetFrom(instructions().size())); 695 704 return target; -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r41998 r42065 299 299 PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target); 300 300 PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target); 301 PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target); 301 302 PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth); 302 303 -
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r41999 r42065 2667 2667 NEXT_INSTRUCTION(); 2668 2668 } 2669 DEFINE_OPCODE(op_jneq_ptr) { 2670 /* jneq_ptr src(r) ptr(jsCell) target(offset) 2671 2672 Jumps to offset target from the current instruction, if the value r is equal 2673 to ptr, using pointer equality. 2674 */ 2675 int src = (++vPC)->u.operand; 2676 JSValuePtr ptr = JSValuePtr((++vPC)->u.jsCell); 2677 int target = (++vPC)->u.operand; 2678 JSValuePtr srcValue = callFrame[src].jsValue(callFrame); 2679 if (srcValue != ptr) { 2680 vPC += target; 2681 NEXT_INSTRUCTION(); 2682 } 2683 2684 ++vPC; 2685 NEXT_INSTRUCTION(); 2686 } 2669 2687 DEFINE_OPCODE(op_loop_if_less) { 2670 2688 /* loop_if_less src1(r) src2(r) target(offset) -
trunk/JavaScriptCore/jit/JIT.cpp
r41544 r42065 820 820 NEXT_OPCODE(op_jneq_null); 821 821 } 822 case op_jneq_ptr: { 823 unsigned src = currentInstruction[1].u.operand; 824 JSCell* ptr = currentInstruction[2].u.jsCell; 825 unsigned target = currentInstruction[3].u.operand; 826 827 emitGetVirtualRegister(src, regT0); 828 addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValuePtr::encode(JSValuePtr(ptr)))), target + 3); 829 830 RECORD_JUMP_TARGET(target + 3); 831 NEXT_OPCODE(op_jneq_ptr); 832 } 822 833 case op_post_inc: { 823 834 compileFastArith_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand); -
trunk/JavaScriptCore/parser/Grammar.y
r39554 r42065 1926 1926 ASSERT(func.m_node->isDotAccessorNode()); 1927 1927 DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node); 1928 FunctionCallDotNode* node = new FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot); 1928 FunctionCallDotNode* node; 1929 if (dot->identifier() == GLOBAL_DATA->propertyNames->call) 1930 node = new CallFunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot); 1931 else 1932 node = new FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot); 1929 1933 node->setSubexpressionInfo(dot->divot(), dot->endOffset()); 1930 1934 return createNodeInfo<ExpressionNode*>(node, features, numConstants); -
trunk/JavaScriptCore/parser/Nodes.cpp
r41806 r42065 693 693 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); 694 694 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 695 } 696 697 RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 698 { 699 RefPtr<Label> realCall = generator.newLabel(); 700 RefPtr<Label> end = generator.newLabel(); 701 RefPtr<RegisterID> base = generator.emitNode(m_base.get()); 702 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 703 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); 704 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); 705 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); 706 { 707 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); 708 RefPtr<RegisterID> thisRegister = generator.newTemporary(); 709 RefPtr<ArgumentListNode> oldList = m_args->m_listNode; 710 if (m_args->m_listNode && m_args->m_listNode->m_expr) { 711 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr.get()); 712 m_args->m_listNode = m_args->m_listNode->m_next; 713 } else { 714 generator.emitLoad(thisRegister.get(), jsNull()); 715 } 716 generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 717 generator.emitJump(end.get()); 718 m_args->m_listNode = oldList; 719 } 720 generator.emitLabel(realCall.get()); 721 { 722 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); 723 generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 724 } 725 generator.emitLabel(end.get()); 726 return finalDestination.get(); 695 727 } 696 728 -
trunk/JavaScriptCore/parser/Nodes.h
r41343 r42065 764 764 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; 765 765 766 pr ivate:766 protected: 767 767 RefPtr<ExpressionNode> m_base; 768 768 Identifier m_ident; 769 769 RefPtr<ArgumentsNode> m_args; 770 }; 771 772 class CallFunctionCallDotNode : public FunctionCallDotNode { 773 public: 774 CallFunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL 775 : FunctionCallDotNode(globalData, base, ident, args, divot, startOffset, endOffset) 776 { 777 } 778 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; 770 779 }; 771 780 -
trunk/JavaScriptCore/runtime/FunctionPrototype.cpp
r41168 r42065 44 44 } 45 45 46 void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure )46 void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure, PrototypeFunction** callFunction) 47 47 { 48 48 putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum); 49 49 putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply), DontEnum); 50 putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall), DontEnum); 50 *callFunction = new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall); 51 putDirectFunctionWithoutTransition(exec, *callFunction, DontEnum); 51 52 } 52 53 -
trunk/JavaScriptCore/runtime/FunctionPrototype.h
r39670 r42065 26 26 namespace JSC { 27 27 28 class PrototypeFunction; 29 28 30 class FunctionPrototype : public InternalFunction { 29 31 public: 30 32 FunctionPrototype(ExecState*, PassRefPtr<Structure>); 31 void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure );33 void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, PrototypeFunction** callFunction); 32 34 33 35 static PassRefPtr<Structure> createStructure(JSValuePtr proto) -
trunk/JavaScriptCore/runtime/JSGlobalObject.cpp
r41846 r42065 204 204 d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created. 205 205 d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype); 206 d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get()); 206 PrototypeFunction* callFunction = 0; 207 d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get(), &callFunction); 208 d()->callFunction = callFunction; 207 209 d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get()); 208 210 d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype); … … 371 373 372 374 markIfNeeded(d()->evalFunction); 375 markIfNeeded(d()->callFunction); 373 376 374 377 markIfNeeded(d()->objectPrototype); -
trunk/JavaScriptCore/runtime/JSGlobalObject.h
r41232 r42065 41 41 class NativeErrorConstructor; 42 42 class ProgramCodeBlock; 43 class PrototypeFunction; 43 44 class RegExpConstructor; 44 45 class RegExpPrototype; … … 105 106 106 107 GlobalEvalFunction* evalFunction; 108 PrototypeFunction* callFunction; 107 109 108 110 ObjectPrototype* objectPrototype;
Note:
See TracChangeset
for help on using the changeset viewer.