| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 832 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
| 833 __ SmiCompare(rax, Smi::FromInt(0)); | 833 __ SmiCompare(rax, Smi::FromInt(0)); |
| 834 __ j(equal, loop_statement.continue_target()); | 834 __ j(equal, loop_statement.continue_target()); |
| 835 __ movq(rbx, rax); | 835 __ movq(rbx, rax); |
| 836 | 836 |
| 837 // Update the 'each' property or variable from the possibly filtered | 837 // Update the 'each' property or variable from the possibly filtered |
| 838 // entry in register rbx. | 838 // entry in register rbx. |
| 839 __ bind(&update_each); | 839 __ bind(&update_each); |
| 840 __ movq(result_register(), rbx); | 840 __ movq(result_register(), rbx); |
| 841 // Perform the assignment as if via '='. | 841 // Perform the assignment as if via '='. |
| 842 EmitAssignment(stmt->each()); | 842 { EffectContext context(this); |
| 843 EmitAssignment(stmt->each(), stmt->AssignmentId()); |
| 844 } |
| 843 | 845 |
| 844 // Generate code for the body of the loop. | 846 // Generate code for the body of the loop. |
| 845 Visit(stmt->body()); | 847 Visit(stmt->body()); |
| 846 | 848 |
| 847 // Generate code for going to the next element by incrementing the | 849 // Generate code for going to the next element by incrementing the |
| 848 // index (smi) stored on top of the stack. | 850 // index (smi) stored on top of the stack. |
| 849 __ bind(loop_statement.continue_target()); | 851 __ bind(loop_statement.continue_target()); |
| 850 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); | 852 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); |
| 851 | 853 |
| 852 EmitStackCheck(stmt); | 854 EmitStackCheck(stmt); |
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 __ pop(rdx); | 1516 __ pop(rdx); |
| 1515 stub.GenerateCall(masm_, rdx, rax); | 1517 stub.GenerateCall(masm_, rdx, rax); |
| 1516 } else { | 1518 } else { |
| 1517 __ push(result_register()); | 1519 __ push(result_register()); |
| 1518 __ CallStub(&stub); | 1520 __ CallStub(&stub); |
| 1519 } | 1521 } |
| 1520 context()->Plug(rax); | 1522 context()->Plug(rax); |
| 1521 } | 1523 } |
| 1522 | 1524 |
| 1523 | 1525 |
| 1524 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1526 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { |
| 1525 // Invalid left-hand sides are rewritten to have a 'throw | 1527 // Invalid left-hand sides are rewritten to have a 'throw |
| 1526 // ReferenceError' on the left-hand side. | 1528 // ReferenceError' on the left-hand side. |
| 1527 if (!expr->IsValidLeftHandSide()) { | 1529 if (!expr->IsValidLeftHandSide()) { |
| 1528 VisitForEffect(expr); | 1530 VisitForEffect(expr); |
| 1529 return; | 1531 return; |
| 1530 } | 1532 } |
| 1531 | 1533 |
| 1532 // Left-hand side can only be a property, a global or a (parameter or local) | 1534 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1533 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1535 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 1534 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1536 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1562 VisitForStackValue(prop->obj()); | 1564 VisitForStackValue(prop->obj()); |
| 1563 VisitForAccumulatorValue(prop->key()); | 1565 VisitForAccumulatorValue(prop->key()); |
| 1564 __ movq(rcx, rax); | 1566 __ movq(rcx, rax); |
| 1565 __ pop(rdx); | 1567 __ pop(rdx); |
| 1566 __ pop(rax); | 1568 __ pop(rax); |
| 1567 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1569 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1568 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1570 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1569 break; | 1571 break; |
| 1570 } | 1572 } |
| 1571 } | 1573 } |
| 1574 context()->Plug(rax); |
| 1572 } | 1575 } |
| 1573 | 1576 |
| 1574 | 1577 |
| 1575 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1578 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1576 Token::Value op) { | 1579 Token::Value op) { |
| 1577 // Left-hand sides that rewrite to explicit property accesses do not reach | 1580 // Left-hand sides that rewrite to explicit property accesses do not reach |
| 1578 // here. | 1581 // here. |
| 1579 ASSERT(var != NULL); | 1582 ASSERT(var != NULL); |
| 1580 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1583 ASSERT(var->is_global() || var->AsSlot() != NULL); |
| 1581 | 1584 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 if (op == Token::INIT_CONST) { | 1637 if (op == Token::INIT_CONST) { |
| 1635 // The runtime will ignore const redeclaration. | 1638 // The runtime will ignore const redeclaration. |
| 1636 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1639 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 1637 } else { | 1640 } else { |
| 1638 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1641 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
| 1639 } | 1642 } |
| 1640 break; | 1643 break; |
| 1641 } | 1644 } |
| 1642 __ bind(&done); | 1645 __ bind(&done); |
| 1643 } | 1646 } |
| 1644 | |
| 1645 context()->Plug(rax); | |
| 1646 } | 1647 } |
| 1647 | 1648 |
| 1648 | 1649 |
| 1649 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1650 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 1650 // Assignment to a property, using a named store IC. | 1651 // Assignment to a property, using a named store IC. |
| 1651 Property* prop = expr->target()->AsProperty(); | 1652 Property* prop = expr->target()->AsProperty(); |
| 1652 ASSERT(prop != NULL); | 1653 ASSERT(prop != NULL); |
| 1653 ASSERT(prop->key()->AsLiteral() != NULL); | 1654 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1654 | 1655 |
| 1655 // If the assignment starts a block of assignments to the same object, | 1656 // If the assignment starts a block of assignments to the same object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1672 } | 1673 } |
| 1673 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1674 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1674 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1675 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1675 | 1676 |
| 1676 // If the assignment ends an initialization block, revert to fast case. | 1677 // If the assignment ends an initialization block, revert to fast case. |
| 1677 if (expr->ends_initialization_block()) { | 1678 if (expr->ends_initialization_block()) { |
| 1678 __ push(rax); // Result of assignment, saved even if not needed. | 1679 __ push(rax); // Result of assignment, saved even if not needed. |
| 1679 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1680 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
| 1680 __ CallRuntime(Runtime::kToFastProperties, 1); | 1681 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1681 __ pop(rax); | 1682 __ pop(rax); |
| 1682 context()->DropAndPlug(1, rax); | 1683 __ Drop(1); |
| 1683 } else { | |
| 1684 context()->Plug(rax); | |
| 1685 } | 1684 } |
| 1685 context()->Plug(rax); |
| 1686 } | 1686 } |
| 1687 | 1687 |
| 1688 | 1688 |
| 1689 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1689 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1690 // Assignment to a property, using a keyed store IC. | 1690 // Assignment to a property, using a keyed store IC. |
| 1691 | 1691 |
| 1692 // If the assignment starts a block of assignments to the same object, | 1692 // If the assignment starts a block of assignments to the same object, |
| 1693 // change to slow case to avoid the quadratic behavior of repeatedly | 1693 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1694 // adding fast properties. | 1694 // adding fast properties. |
| 1695 if (expr->starts_initialization_block()) { | 1695 if (expr->starts_initialization_block()) { |
| (...skipping 1424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3120 __ bind(&done); | 3120 __ bind(&done); |
| 3121 | 3121 |
| 3122 // Store the value returned in rax. | 3122 // Store the value returned in rax. |
| 3123 switch (assign_type) { | 3123 switch (assign_type) { |
| 3124 case VARIABLE: | 3124 case VARIABLE: |
| 3125 if (expr->is_postfix()) { | 3125 if (expr->is_postfix()) { |
| 3126 // Perform the assignment as if via '='. | 3126 // Perform the assignment as if via '='. |
| 3127 { EffectContext context(this); | 3127 { EffectContext context(this); |
| 3128 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3128 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3129 Token::ASSIGN); | 3129 Token::ASSIGN); |
| 3130 context.Plug(rax); |
| 3130 } | 3131 } |
| 3131 // For all contexts except kEffect: We have the result on | 3132 // For all contexts except kEffect: We have the result on |
| 3132 // top of the stack. | 3133 // top of the stack. |
| 3133 if (!context()->IsEffect()) { | 3134 if (!context()->IsEffect()) { |
| 3134 context()->PlugTOS(); | 3135 context()->PlugTOS(); |
| 3135 } | 3136 } |
| 3136 } else { | 3137 } else { |
| 3137 // Perform the assignment as if via '='. | 3138 // Perform the assignment as if via '='. |
| 3138 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3139 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3139 Token::ASSIGN); | 3140 Token::ASSIGN); |
| 3141 context()->Plug(rax); |
| 3140 } | 3142 } |
| 3141 break; | 3143 break; |
| 3142 case NAMED_PROPERTY: { | 3144 case NAMED_PROPERTY: { |
| 3143 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3145 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
| 3144 __ pop(rdx); | 3146 __ pop(rdx); |
| 3145 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3147 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 3146 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3148 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3147 if (expr->is_postfix()) { | 3149 if (expr->is_postfix()) { |
| 3148 if (!context()->IsEffect()) { | 3150 if (!context()->IsEffect()) { |
| 3149 context()->PlugTOS(); | 3151 context()->PlugTOS(); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3513 __ ret(0); | 3515 __ ret(0); |
| 3514 } | 3516 } |
| 3515 | 3517 |
| 3516 | 3518 |
| 3517 #undef __ | 3519 #undef __ |
| 3518 | 3520 |
| 3519 | 3521 |
| 3520 } } // namespace v8::internal | 3522 } } // namespace v8::internal |
| 3521 | 3523 |
| 3522 #endif // V8_TARGET_ARCH_X64 | 3524 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |