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 { EffectContext context(this); | 842 EmitAssignment(stmt->each()); |
843 EmitAssignment(stmt->each(), stmt->AssignmentId()); | |
844 } | |
845 | 843 |
846 // Generate code for the body of the loop. | 844 // Generate code for the body of the loop. |
847 Visit(stmt->body()); | 845 Visit(stmt->body()); |
848 | 846 |
849 // Generate code for going to the next element by incrementing the | 847 // Generate code for going to the next element by incrementing the |
850 // index (smi) stored on top of the stack. | 848 // index (smi) stored on top of the stack. |
851 __ bind(loop_statement.continue_target()); | 849 __ bind(loop_statement.continue_target()); |
852 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); | 850 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); |
853 | 851 |
854 EmitStackCheck(stmt); | 852 EmitStackCheck(stmt); |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 } | 1406 } |
1409 | 1407 |
1410 // Record source position before possible IC call. | 1408 // Record source position before possible IC call. |
1411 SetSourcePosition(expr->position()); | 1409 SetSourcePosition(expr->position()); |
1412 | 1410 |
1413 // Store the value. | 1411 // Store the value. |
1414 switch (assign_type) { | 1412 switch (assign_type) { |
1415 case VARIABLE: | 1413 case VARIABLE: |
1416 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1414 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
1417 expr->op()); | 1415 expr->op()); |
1418 context()->Plug(rax); | |
1419 break; | 1416 break; |
1420 case NAMED_PROPERTY: | 1417 case NAMED_PROPERTY: |
1421 EmitNamedPropertyAssignment(expr); | 1418 EmitNamedPropertyAssignment(expr); |
1422 break; | 1419 break; |
1423 case KEYED_PROPERTY: | 1420 case KEYED_PROPERTY: |
1424 EmitKeyedPropertyAssignment(expr); | 1421 EmitKeyedPropertyAssignment(expr); |
1425 break; | 1422 break; |
1426 } | 1423 } |
1427 } | 1424 } |
1428 | 1425 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 __ pop(rdx); | 1514 __ pop(rdx); |
1518 stub.GenerateCall(masm_, rdx, rax); | 1515 stub.GenerateCall(masm_, rdx, rax); |
1519 } else { | 1516 } else { |
1520 __ push(result_register()); | 1517 __ push(result_register()); |
1521 __ CallStub(&stub); | 1518 __ CallStub(&stub); |
1522 } | 1519 } |
1523 context()->Plug(rax); | 1520 context()->Plug(rax); |
1524 } | 1521 } |
1525 | 1522 |
1526 | 1523 |
1527 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { | 1524 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
1528 // Invalid left-hand sides are rewritten to have a 'throw | 1525 // Invalid left-hand sides are rewritten to have a 'throw |
1529 // ReferenceError' on the left-hand side. | 1526 // ReferenceError' on the left-hand side. |
1530 if (!expr->IsValidLeftHandSide()) { | 1527 if (!expr->IsValidLeftHandSide()) { |
1531 VisitForEffect(expr); | 1528 VisitForEffect(expr); |
1532 return; | 1529 return; |
1533 } | 1530 } |
1534 | 1531 |
1535 // Left-hand side can only be a property, a global or a (parameter or local) | 1532 // Left-hand side can only be a property, a global or a (parameter or local) |
1536 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1533 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1537 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1534 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
(...skipping 27 matching lines...) Expand all Loading... |
1565 VisitForStackValue(prop->obj()); | 1562 VisitForStackValue(prop->obj()); |
1566 VisitForAccumulatorValue(prop->key()); | 1563 VisitForAccumulatorValue(prop->key()); |
1567 __ movq(rcx, rax); | 1564 __ movq(rcx, rax); |
1568 __ pop(rdx); | 1565 __ pop(rdx); |
1569 __ pop(rax); | 1566 __ pop(rax); |
1570 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1567 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1571 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1568 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1572 break; | 1569 break; |
1573 } | 1570 } |
1574 } | 1571 } |
1575 context()->Plug(rax); | |
1576 } | 1572 } |
1577 | 1573 |
1578 | 1574 |
1579 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1575 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1580 Token::Value op) { | 1576 Token::Value op) { |
1581 // Left-hand sides that rewrite to explicit property accesses do not reach | 1577 // Left-hand sides that rewrite to explicit property accesses do not reach |
1582 // here. | 1578 // here. |
1583 ASSERT(var != NULL); | 1579 ASSERT(var != NULL); |
1584 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1580 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1585 | 1581 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1638 if (op == Token::INIT_CONST) { | 1634 if (op == Token::INIT_CONST) { |
1639 // The runtime will ignore const redeclaration. | 1635 // The runtime will ignore const redeclaration. |
1640 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1636 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1641 } else { | 1637 } else { |
1642 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1638 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
1643 } | 1639 } |
1644 break; | 1640 break; |
1645 } | 1641 } |
1646 __ bind(&done); | 1642 __ bind(&done); |
1647 } | 1643 } |
| 1644 |
| 1645 context()->Plug(rax); |
1648 } | 1646 } |
1649 | 1647 |
1650 | 1648 |
1651 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1649 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1652 // Assignment to a property, using a named store IC. | 1650 // Assignment to a property, using a named store IC. |
1653 Property* prop = expr->target()->AsProperty(); | 1651 Property* prop = expr->target()->AsProperty(); |
1654 ASSERT(prop != NULL); | 1652 ASSERT(prop != NULL); |
1655 ASSERT(prop->key()->AsLiteral() != NULL); | 1653 ASSERT(prop->key()->AsLiteral() != NULL); |
1656 | 1654 |
1657 // If the assignment starts a block of assignments to the same object, | 1655 // If the assignment starts a block of assignments to the same object, |
(...skipping 16 matching lines...) Expand all Loading... |
1674 } | 1672 } |
1675 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1673 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1676 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1674 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1677 | 1675 |
1678 // If the assignment ends an initialization block, revert to fast case. | 1676 // If the assignment ends an initialization block, revert to fast case. |
1679 if (expr->ends_initialization_block()) { | 1677 if (expr->ends_initialization_block()) { |
1680 __ push(rax); // Result of assignment, saved even if not needed. | 1678 __ push(rax); // Result of assignment, saved even if not needed. |
1681 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1679 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
1682 __ CallRuntime(Runtime::kToFastProperties, 1); | 1680 __ CallRuntime(Runtime::kToFastProperties, 1); |
1683 __ pop(rax); | 1681 __ pop(rax); |
1684 __ Drop(1); | 1682 context()->DropAndPlug(1, rax); |
| 1683 } else { |
| 1684 context()->Plug(rax); |
1685 } | 1685 } |
1686 context()->Plug(rax); | |
1687 } | 1686 } |
1688 | 1687 |
1689 | 1688 |
1690 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1689 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1691 // Assignment to a property, using a keyed store IC. | 1690 // Assignment to a property, using a keyed store IC. |
1692 | 1691 |
1693 // 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, |
1694 // change to slow case to avoid the quadratic behavior of repeatedly | 1693 // change to slow case to avoid the quadratic behavior of repeatedly |
1695 // adding fast properties. | 1694 // adding fast properties. |
1696 if (expr->starts_initialization_block()) { | 1695 if (expr->starts_initialization_block()) { |
(...skipping 1424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3121 __ bind(&done); | 3120 __ bind(&done); |
3122 | 3121 |
3123 // Store the value returned in rax. | 3122 // Store the value returned in rax. |
3124 switch (assign_type) { | 3123 switch (assign_type) { |
3125 case VARIABLE: | 3124 case VARIABLE: |
3126 if (expr->is_postfix()) { | 3125 if (expr->is_postfix()) { |
3127 // Perform the assignment as if via '='. | 3126 // Perform the assignment as if via '='. |
3128 { EffectContext context(this); | 3127 { EffectContext context(this); |
3129 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3128 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3130 Token::ASSIGN); | 3129 Token::ASSIGN); |
3131 context.Plug(rax); | |
3132 } | 3130 } |
3133 // For all contexts except kEffect: We have the result on | 3131 // For all contexts except kEffect: We have the result on |
3134 // top of the stack. | 3132 // top of the stack. |
3135 if (!context()->IsEffect()) { | 3133 if (!context()->IsEffect()) { |
3136 context()->PlugTOS(); | 3134 context()->PlugTOS(); |
3137 } | 3135 } |
3138 } else { | 3136 } else { |
3139 // Perform the assignment as if via '='. | 3137 // Perform the assignment as if via '='. |
3140 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3138 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3141 Token::ASSIGN); | 3139 Token::ASSIGN); |
3142 context()->Plug(rax); | |
3143 } | 3140 } |
3144 break; | 3141 break; |
3145 case NAMED_PROPERTY: { | 3142 case NAMED_PROPERTY: { |
3146 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3143 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
3147 __ pop(rdx); | 3144 __ pop(rdx); |
3148 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3145 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
3149 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3146 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3150 if (expr->is_postfix()) { | 3147 if (expr->is_postfix()) { |
3151 if (!context()->IsEffect()) { | 3148 if (!context()->IsEffect()) { |
3152 context()->PlugTOS(); | 3149 context()->PlugTOS(); |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3516 __ ret(0); | 3513 __ ret(0); |
3517 } | 3514 } |
3518 | 3515 |
3519 | 3516 |
3520 #undef __ | 3517 #undef __ |
3521 | 3518 |
3522 | 3519 |
3523 } } // namespace v8::internal | 3520 } } // namespace v8::internal |
3524 | 3521 |
3525 #endif // V8_TARGET_ARCH_X64 | 3522 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |