Changeset 68338 in webkit
- Timestamp:
- Sep 25, 2010 2:42:00 PM (14 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r68330 r68338 1 2010-09-25 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Cameron Zwarich. 4 5 Avoid constructing arguments object when accessing length and index properties 6 https://bugs.webkit.org/show_bug.cgi?id=46572 7 8 Add opcodes to read argument length and properties, and then implement them. 9 Much like other lazy opcodes these opcodes take a fast path when the arguments 10 object has not been instantiated, and fall back on generic access mechanisms 11 if they are acting on an instantiated object. 12 13 3% win on v8-earleyboyer, no change elsewhere. 14 15 * bytecode/CodeBlock.cpp: 16 (JSC::CodeBlock::dump): 17 * bytecode/Opcode.h: 18 * bytecompiler/BytecodeGenerator.cpp: 19 (JSC::BytecodeGenerator::emitGetArgumentsLength): 20 (JSC::BytecodeGenerator::emitGetArgumentByVal): 21 * bytecompiler/BytecodeGenerator.h: 22 * bytecompiler/NodesCodegen.cpp: 23 (JSC::BracketAccessorNode::emitBytecode): 24 (JSC::DotAccessorNode::emitBytecode): 25 * interpreter/Interpreter.cpp: 26 (JSC::Interpreter::privateExecute): 27 * jit/JIT.cpp: 28 (JSC::JIT::privateCompileMainPass): 29 (JSC::JIT::privateCompileSlowCases): 30 * jit/JIT.h: 31 * jit/JITOpcodes.cpp: 32 (JSC::JIT::emit_op_get_arguments_length): 33 (JSC::JIT::emitSlow_op_get_arguments_length): 34 (JSC::JIT::emit_op_get_argument_by_val): 35 (JSC::JIT::emitSlow_op_get_argument_by_val): 36 * jit/JITOpcodes32_64.cpp: 37 (JSC::JIT::emit_op_get_arguments_length): 38 (JSC::JIT::emitSlow_op_get_arguments_length): 39 (JSC::JIT::emit_op_get_argument_by_val): 40 (JSC::JIT::emitSlow_op_get_argument_by_val): 41 1 42 2010-09-25 Patrick Gansterer <paroga@webkit.org> 2 43 -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r68281 r68338 843 843 break; 844 844 } 845 case op_get_arguments_length: { 846 printUnaryOp(exec, location, it, "get_arguments_length"); 847 break; 848 } 845 849 case op_put_by_id: { 846 850 printPutByIdOp(exec, location, it, "put_by_id"); … … 889 893 int r2 = (++it)->u.operand; 890 894 printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 895 break; 896 } 897 case op_get_argument_by_val: { 898 int r0 = (++it)->u.operand; 899 int r1 = (++it)->u.operand; 900 int r2 = (++it)->u.operand; 901 printf("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 891 902 break; 892 903 } -
trunk/JavaScriptCore/bytecode/Opcode.h
r68281 r68338 121 121 macro(op_get_array_length, 8) \ 122 122 macro(op_get_string_length, 8) \ 123 macro(op_get_arguments_length, 4) \ 123 124 macro(op_put_by_id, 9) \ 124 125 macro(op_put_by_id_transition, 9) \ … … 127 128 macro(op_del_by_id, 4) \ 128 129 macro(op_get_by_val, 4) \ 130 macro(op_get_argument_by_val, 4) \ 129 131 macro(op_get_by_pname, 7) \ 130 132 macro(op_put_by_val, 4) \ -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r68281 r68338 1329 1329 } 1330 1330 1331 RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterID* base) 1332 { 1333 emitOpcode(op_get_arguments_length); 1334 instructions().append(dst->index()); 1335 ASSERT(base->index() == m_codeBlock->argumentsRegister()); 1336 instructions().append(base->index()); 1337 instructions().append(addConstant(propertyNames().arguments)); 1338 return dst; 1339 } 1340 1331 1341 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value) 1332 1342 { … … 1396 1406 } 1397 1407 1408 RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property) 1409 { 1410 emitOpcode(op_get_argument_by_val); 1411 instructions().append(dst->index()); 1412 ASSERT(base->index() == m_codeBlock->argumentsRegister()); 1413 instructions().append(base->index()); 1414 instructions().append(property->index()); 1415 return dst; 1416 } 1417 1398 1418 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property) 1399 1419 { -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r68281 r68338 335 335 336 336 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property); 337 RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base); 337 338 RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value); 338 339 RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value); 339 340 RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&); 340 341 RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property); 342 RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property); 341 343 RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value); 342 344 RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property); -
trunk/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r65593 r68338 291 291 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 292 292 { 293 if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())) { 294 RegisterID* property = generator.emitNode(m_subscript); 295 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 296 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property); 297 } 298 293 299 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); 294 300 RegisterID* property = generator.emitNode(m_subscript); … … 301 307 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 302 308 { 309 if (m_ident == generator.propertyNames().length) { 310 if (!m_base->isResolveNode()) 311 goto nonArgumentsPath; 312 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base); 313 if (!generator.willResolveToArguments(resolveNode->identifier())) 314 goto nonArgumentsPath; 315 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); 316 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments()); 317 } 318 319 nonArgumentsPath: 303 320 RegisterID* base = generator.emitNode(m_base); 304 321 generator.emitExpressionInfo(divot(), startOffset(), endOffset()); -
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r68281 r68338 3091 3091 vPC += OPCODE_LENGTH(op_get_by_pname); 3092 3092 NEXT_INSTRUCTION(); 3093 } 3094 DEFINE_OPCODE(op_get_arguments_length) { 3095 int dst = vPC[1].u.operand; 3096 int argumentsRegister = vPC[2].u.operand; 3097 int property = vPC[3].u.operand; 3098 JSValue arguments = callFrame->r(argumentsRegister).jsValue(); 3099 if (arguments) { 3100 Identifier& ident = codeBlock->identifier(property); 3101 PropertySlot slot(arguments); 3102 JSValue result = arguments.get(callFrame, ident, slot); 3103 CHECK_FOR_EXCEPTION(); 3104 callFrame->r(dst) = result; 3105 } else 3106 callFrame->r(dst) = jsNumber(callFrame, callFrame->argumentCount()); 3107 3108 vPC += OPCODE_LENGTH(op_get_arguments_length); 3109 NEXT_INSTRUCTION(); 3110 } 3111 DEFINE_OPCODE(op_get_argument_by_val) { 3112 int dst = vPC[1].u.operand; 3113 int argumentsRegister = vPC[2].u.operand; 3114 int property = vPC[3].u.operand; 3115 JSValue arguments = callFrame->r(argumentsRegister).jsValue(); 3116 JSValue subscript = callFrame->r(property).jsValue(); 3117 if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) { 3118 unsigned arg = subscript.asUInt32() + 1; 3119 unsigned numParameters = callFrame->codeBlock()->m_numParameters; 3120 if (arg < numParameters) 3121 callFrame->r(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters); 3122 else 3123 callFrame->r(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters - callFrame->argumentCount() - 1); 3124 vPC += OPCODE_LENGTH(op_get_argument_by_val); 3125 NEXT_INSTRUCTION(); 3126 } 3127 if (!arguments) { 3128 Arguments* arguments = new (globalData) Arguments(callFrame); 3129 callFrame->r(dst) = JSValue(arguments); 3130 callFrame->r(unmodifiedArgumentsRegister(dst)) = JSValue(arguments); 3131 } 3132 // fallthrough 3093 3133 } 3094 3134 DEFINE_OPCODE(op_get_by_val) { -
trunk/JavaScriptCore/jit/JIT.cpp
r68281 r68338 239 239 DEFINE_OP(op_eq_null) 240 240 DEFINE_OP(op_get_by_id) 241 DEFINE_OP(op_get_arguments_length) 241 242 DEFINE_OP(op_get_by_val) 243 DEFINE_OP(op_get_argument_by_val) 242 244 DEFINE_OP(op_get_by_pname) 243 245 DEFINE_OP(op_get_global_var) … … 400 402 DEFINE_SLOWCASE_OP(op_eq) 401 403 DEFINE_SLOWCASE_OP(op_get_by_id) 404 DEFINE_SLOWCASE_OP(op_get_arguments_length) 402 405 DEFINE_SLOWCASE_OP(op_get_by_val) 406 DEFINE_SLOWCASE_OP(op_get_argument_by_val) 403 407 DEFINE_SLOWCASE_OP(op_get_by_pname) 404 408 DEFINE_SLOWCASE_OP(op_instanceof) -
trunk/JavaScriptCore/jit/JIT.h
r68281 r68338 749 749 void emit_op_eq_null(Instruction*); 750 750 void emit_op_get_by_id(Instruction*); 751 void emit_op_get_arguments_length(Instruction*); 751 752 void emit_op_get_by_val(Instruction*); 753 void emit_op_get_argument_by_val(Instruction*); 752 754 void emit_op_get_by_pname(Instruction*); 753 755 void emit_op_get_global_var(Instruction*); … … 847 849 void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&); 848 850 void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&); 851 void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&); 849 852 void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); 853 void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); 850 854 void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&); 851 855 void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&); -
trunk/JavaScriptCore/jit/JITOpcodes.cpp
r68281 r68338 1471 1471 } 1472 1472 1473 void JIT::emit_op_get_arguments_length(Instruction* currentInstruction) 1474 { 1475 int dst = currentInstruction[1].u.operand; 1476 int argumentsRegister = currentInstruction[2].u.operand; 1477 addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister))); 1478 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); 1479 sub32(Imm32(1), regT0); 1480 emitFastArithReTagImmediate(regT0, regT0); 1481 emitPutVirtualRegister(dst, regT0); 1482 } 1483 1484 void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1485 { 1486 linkSlowCase(iter); 1487 unsigned dst = currentInstruction[1].u.operand; 1488 unsigned base = currentInstruction[2].u.operand; 1489 Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); 1490 1491 emitGetVirtualRegister(base, regT0); 1492 JITStubCall stubCall(this, cti_op_get_by_id_generic); 1493 stubCall.addArgument(regT0); 1494 stubCall.addArgument(ImmPtr(ident)); 1495 stubCall.call(dst); 1496 } 1497 1498 void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) 1499 { 1500 int dst = currentInstruction[1].u.operand; 1501 int argumentsRegister = currentInstruction[2].u.operand; 1502 int property = currentInstruction[3].u.operand; 1503 addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister))); 1504 emitGetVirtualRegister(property, regT1); 1505 addSlowCase(emitJumpIfNotImmediateInteger(regT1)); 1506 add32(Imm32(1), regT1); 1507 // regT1 now contains the integer index of the argument we want, including this 1508 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2); 1509 addSlowCase(branch32(AboveOrEqual, regT1, regT2)); 1510 1511 Jump skipOutofLineParams; 1512 int numArgs = m_codeBlock->m_numParameters; 1513 if (numArgs) { 1514 Jump notInInPlaceArgs = branch32(AboveOrEqual, regT1, Imm32(numArgs)); 1515 addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0); 1516 loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0); 1517 skipOutofLineParams = jump(); 1518 notInInPlaceArgs.link(this); 1519 } 1520 1521 addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0); 1522 mul32(Imm32(sizeof(Register)), regT2, regT2); 1523 subPtr(regT2, regT0); 1524 loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0); 1525 if (numArgs) 1526 skipOutofLineParams.link(this); 1527 emitPutVirtualRegister(dst, regT0); 1528 } 1529 1530 void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1531 { 1532 unsigned dst = currentInstruction[1].u.operand; 1533 unsigned arguments = currentInstruction[2].u.operand; 1534 unsigned property = currentInstruction[3].u.operand; 1535 1536 linkSlowCase(iter); 1537 Jump skipArgumentsCreation = jump(); 1538 1539 linkSlowCase(iter); 1540 linkSlowCase(iter); 1541 if (m_codeBlock->m_numParameters == 1) 1542 JITStubCall(this, cti_op_create_arguments_no_params).call(); 1543 else 1544 JITStubCall(this, cti_op_create_arguments).call(); 1545 emitPutVirtualRegister(dst); 1546 emitPutVirtualRegister(unmodifiedArgumentsRegister(dst)); 1547 1548 skipArgumentsCreation.link(this); 1549 JITStubCall stubCall(this, cti_op_get_by_val); 1550 stubCall.addArgument(arguments, regT2); 1551 stubCall.addArgument(property, regT2); 1552 stubCall.call(dst); 1553 } 1554 1473 1555 #endif // !USE(JSVALUE32_64) 1474 1556 -
trunk/JavaScriptCore/jit/JITOpcodes32_64.cpp
r68281 r68338 1563 1563 } 1564 1564 1565 void JIT::emit_op_get_arguments_length(Instruction* currentInstruction) 1566 { 1567 int dst = currentInstruction[1].u.operand; 1568 int argumentsRegister = currentInstruction[2].u.operand; 1569 addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), Imm32(JSValue::EmptyValueTag))); 1570 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); 1571 sub32(Imm32(1), regT0); 1572 emitStoreInt32(dst, regT0); 1573 } 1574 1575 void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1576 { 1577 linkSlowCase(iter); 1578 int dst = currentInstruction[1].u.operand; 1579 int base = currentInstruction[2].u.operand; 1580 int ident = currentInstruction[3].u.operand; 1581 1582 JITStubCall stubCall(this, cti_op_get_by_id_generic); 1583 stubCall.addArgument(base); 1584 stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident)))); 1585 stubCall.call(dst); 1586 } 1587 1588 void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) 1589 { 1590 int dst = currentInstruction[1].u.operand; 1591 int argumentsRegister = currentInstruction[2].u.operand; 1592 int property = currentInstruction[3].u.operand; 1593 addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), Imm32(JSValue::EmptyValueTag))); 1594 emitLoad(property, regT1, regT2); 1595 addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); 1596 add32(Imm32(1), regT2); 1597 // regT2 now contains the integer index of the argument we want, including this 1598 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT3); 1599 addSlowCase(branch32(AboveOrEqual, regT2, regT3)); 1600 1601 Jump skipOutofLineParams; 1602 int numArgs = m_codeBlock->m_numParameters; 1603 if (numArgs) { 1604 Jump notInInPlaceArgs = branch32(AboveOrEqual, regT2, Imm32(numArgs)); 1605 addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1); 1606 loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); 1607 loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); 1608 skipOutofLineParams = jump(); 1609 notInInPlaceArgs.link(this); 1610 } 1611 1612 addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1); 1613 mul32(Imm32(sizeof(Register)), regT3, regT3); 1614 subPtr(regT3, regT1); 1615 loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); 1616 loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); 1617 if (numArgs) 1618 skipOutofLineParams.link(this); 1619 emitStore(dst, regT1, regT0); 1620 } 1621 1622 void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1623 { 1624 unsigned dst = currentInstruction[1].u.operand; 1625 unsigned arguments = currentInstruction[2].u.operand; 1626 unsigned property = currentInstruction[3].u.operand; 1627 1628 linkSlowCase(iter); 1629 Jump skipArgumentsCreation = jump(); 1630 1631 linkSlowCase(iter); 1632 linkSlowCase(iter); 1633 if (m_codeBlock->m_numParameters == 1) 1634 JITStubCall(this, cti_op_create_arguments_no_params).call(); 1635 else 1636 JITStubCall(this, cti_op_create_arguments).call(); 1637 1638 emitStore(arguments, regT1, regT0); 1639 emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0); 1640 1641 skipArgumentsCreation.link(this); 1642 JITStubCall stubCall(this, cti_op_get_by_val); 1643 stubCall.addArgument(arguments); 1644 stubCall.addArgument(property); 1645 stubCall.call(dst); 1646 } 1647 1565 1648 } // namespace JSC 1566 1649
Note: See TracChangeset
for help on using the changeset viewer.