| 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 |