| 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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 } | 191 } |
| 192 | 192 |
| 193 { Comment cmnt(masm_, "[ return <undefined>;"); | 193 { Comment cmnt(masm_, "[ return <undefined>;"); |
| 194 // Emit a 'return undefined' in case control fell off the end of the body. | 194 // Emit a 'return undefined' in case control fell off the end of the body. |
| 195 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 195 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 196 EmitReturnSequence(); | 196 EmitReturnSequence(); |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 | 199 |
| 200 | 200 |
| 201 void FullCodeGenerator::ClearAccumulator() { |
| 202 __ xor_(rax, rax); |
| 203 } |
| 204 |
| 205 |
| 201 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { | 206 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { |
| 202 Comment cmnt(masm_, "[ Stack check"); | 207 Comment cmnt(masm_, "[ Stack check"); |
| 203 NearLabel ok; | 208 NearLabel ok; |
| 204 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 209 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 205 __ j(above_equal, &ok); | 210 __ j(above_equal, &ok); |
| 206 StackCheckStub stub; | 211 StackCheckStub stub; |
| 207 __ CallStub(&stub); | 212 __ CallStub(&stub); |
| 208 __ bind(&ok); | 213 __ bind(&ok); |
| 209 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 214 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 210 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); | 215 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 838 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
| 834 __ SmiCompare(rax, Smi::FromInt(0)); | 839 __ SmiCompare(rax, Smi::FromInt(0)); |
| 835 __ j(equal, loop_statement.continue_target()); | 840 __ j(equal, loop_statement.continue_target()); |
| 836 __ movq(rbx, rax); | 841 __ movq(rbx, rax); |
| 837 | 842 |
| 838 // Update the 'each' property or variable from the possibly filtered | 843 // Update the 'each' property or variable from the possibly filtered |
| 839 // entry in register rbx. | 844 // entry in register rbx. |
| 840 __ bind(&update_each); | 845 __ bind(&update_each); |
| 841 __ movq(result_register(), rbx); | 846 __ movq(result_register(), rbx); |
| 842 // Perform the assignment as if via '='. | 847 // Perform the assignment as if via '='. |
| 843 EmitAssignment(stmt->each()); | 848 { EffectContext context(this); |
| 849 EmitAssignment(stmt->each(), stmt->AssignmentId()); |
| 850 } |
| 844 | 851 |
| 845 // Generate code for the body of the loop. | 852 // Generate code for the body of the loop. |
| 846 Visit(stmt->body()); | 853 Visit(stmt->body()); |
| 847 | 854 |
| 848 // Generate code for going to the next element by incrementing the | 855 // Generate code for going to the next element by incrementing the |
| 849 // index (smi) stored on top of the stack. | 856 // index (smi) stored on top of the stack. |
| 850 __ bind(loop_statement.continue_target()); | 857 __ bind(loop_statement.continue_target()); |
| 851 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); | 858 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); |
| 852 | 859 |
| 853 EmitStackCheck(stmt); | 860 EmitStackCheck(stmt); |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 } | 1422 } |
| 1416 | 1423 |
| 1417 // Record source position before possible IC call. | 1424 // Record source position before possible IC call. |
| 1418 SetSourcePosition(expr->position()); | 1425 SetSourcePosition(expr->position()); |
| 1419 | 1426 |
| 1420 // Store the value. | 1427 // Store the value. |
| 1421 switch (assign_type) { | 1428 switch (assign_type) { |
| 1422 case VARIABLE: | 1429 case VARIABLE: |
| 1423 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1430 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
| 1424 expr->op()); | 1431 expr->op()); |
| 1432 context()->Plug(rax); |
| 1425 break; | 1433 break; |
| 1426 case NAMED_PROPERTY: | 1434 case NAMED_PROPERTY: |
| 1427 EmitNamedPropertyAssignment(expr); | 1435 EmitNamedPropertyAssignment(expr); |
| 1428 break; | 1436 break; |
| 1429 case KEYED_PROPERTY: | 1437 case KEYED_PROPERTY: |
| 1430 EmitKeyedPropertyAssignment(expr); | 1438 EmitKeyedPropertyAssignment(expr); |
| 1431 break; | 1439 break; |
| 1432 } | 1440 } |
| 1433 } | 1441 } |
| 1434 | 1442 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1525 __ pop(rdx); | 1533 __ pop(rdx); |
| 1526 stub.GenerateCall(masm_, rdx, rax); | 1534 stub.GenerateCall(masm_, rdx, rax); |
| 1527 } else { | 1535 } else { |
| 1528 __ push(result_register()); | 1536 __ push(result_register()); |
| 1529 __ CallStub(&stub); | 1537 __ CallStub(&stub); |
| 1530 } | 1538 } |
| 1531 context()->Plug(rax); | 1539 context()->Plug(rax); |
| 1532 } | 1540 } |
| 1533 | 1541 |
| 1534 | 1542 |
| 1535 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1543 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { |
| 1536 // Invalid left-hand sides are rewritten to have a 'throw | 1544 // Invalid left-hand sides are rewritten to have a 'throw |
| 1537 // ReferenceError' on the left-hand side. | 1545 // ReferenceError' on the left-hand side. |
| 1538 if (!expr->IsValidLeftHandSide()) { | 1546 if (!expr->IsValidLeftHandSide()) { |
| 1539 VisitForEffect(expr); | 1547 VisitForEffect(expr); |
| 1540 return; | 1548 return; |
| 1541 } | 1549 } |
| 1542 | 1550 |
| 1543 // Left-hand side can only be a property, a global or a (parameter or local) | 1551 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1544 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1552 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 1545 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1553 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1575 VisitForAccumulatorValue(prop->key()); | 1583 VisitForAccumulatorValue(prop->key()); |
| 1576 __ movq(rcx, rax); | 1584 __ movq(rcx, rax); |
| 1577 __ pop(rdx); | 1585 __ pop(rdx); |
| 1578 __ pop(rax); | 1586 __ pop(rax); |
| 1579 Handle<Code> ic(isolate()->builtins()->builtin( | 1587 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1580 Builtins::KeyedStoreIC_Initialize)); | 1588 Builtins::KeyedStoreIC_Initialize)); |
| 1581 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1589 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1582 break; | 1590 break; |
| 1583 } | 1591 } |
| 1584 } | 1592 } |
| 1593 context()->Plug(rax); |
| 1585 } | 1594 } |
| 1586 | 1595 |
| 1587 | 1596 |
| 1588 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1597 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1589 Token::Value op) { | 1598 Token::Value op) { |
| 1590 // Left-hand sides that rewrite to explicit property accesses do not reach | 1599 // Left-hand sides that rewrite to explicit property accesses do not reach |
| 1591 // here. | 1600 // here. |
| 1592 ASSERT(var != NULL); | 1601 ASSERT(var != NULL); |
| 1593 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1602 ASSERT(var->is_global() || var->AsSlot() != NULL); |
| 1594 | 1603 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1648 if (op == Token::INIT_CONST) { | 1657 if (op == Token::INIT_CONST) { |
| 1649 // The runtime will ignore const redeclaration. | 1658 // The runtime will ignore const redeclaration. |
| 1650 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1659 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 1651 } else { | 1660 } else { |
| 1652 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1661 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
| 1653 } | 1662 } |
| 1654 break; | 1663 break; |
| 1655 } | 1664 } |
| 1656 __ bind(&done); | 1665 __ bind(&done); |
| 1657 } | 1666 } |
| 1658 | |
| 1659 context()->Plug(rax); | |
| 1660 } | 1667 } |
| 1661 | 1668 |
| 1662 | 1669 |
| 1663 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1670 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 1664 // Assignment to a property, using a named store IC. | 1671 // Assignment to a property, using a named store IC. |
| 1665 Property* prop = expr->target()->AsProperty(); | 1672 Property* prop = expr->target()->AsProperty(); |
| 1666 ASSERT(prop != NULL); | 1673 ASSERT(prop != NULL); |
| 1667 ASSERT(prop->key()->AsLiteral() != NULL); | 1674 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1668 | 1675 |
| 1669 // If the assignment starts a block of assignments to the same object, | 1676 // If the assignment starts a block of assignments to the same object, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1687 Handle<Code> ic(isolate()->builtins()->builtin( | 1694 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1688 Builtins::StoreIC_Initialize)); | 1695 Builtins::StoreIC_Initialize)); |
| 1689 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1696 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1690 | 1697 |
| 1691 // If the assignment ends an initialization block, revert to fast case. | 1698 // If the assignment ends an initialization block, revert to fast case. |
| 1692 if (expr->ends_initialization_block()) { | 1699 if (expr->ends_initialization_block()) { |
| 1693 __ push(rax); // Result of assignment, saved even if not needed. | 1700 __ push(rax); // Result of assignment, saved even if not needed. |
| 1694 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1701 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
| 1695 __ CallRuntime(Runtime::kToFastProperties, 1); | 1702 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1696 __ pop(rax); | 1703 __ pop(rax); |
| 1697 context()->DropAndPlug(1, rax); | 1704 __ Drop(1); |
| 1698 } else { | |
| 1699 context()->Plug(rax); | |
| 1700 } | 1705 } |
| 1706 context()->Plug(rax); |
| 1701 } | 1707 } |
| 1702 | 1708 |
| 1703 | 1709 |
| 1704 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1710 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1705 // Assignment to a property, using a keyed store IC. | 1711 // Assignment to a property, using a keyed store IC. |
| 1706 | 1712 |
| 1707 // If the assignment starts a block of assignments to the same object, | 1713 // If the assignment starts a block of assignments to the same object, |
| 1708 // change to slow case to avoid the quadratic behavior of repeatedly | 1714 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1709 // adding fast properties. | 1715 // adding fast properties. |
| 1710 if (expr->starts_initialization_block()) { | 1716 if (expr->starts_initialization_block()) { |
| (...skipping 1430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3141 __ bind(&done); | 3147 __ bind(&done); |
| 3142 | 3148 |
| 3143 // Store the value returned in rax. | 3149 // Store the value returned in rax. |
| 3144 switch (assign_type) { | 3150 switch (assign_type) { |
| 3145 case VARIABLE: | 3151 case VARIABLE: |
| 3146 if (expr->is_postfix()) { | 3152 if (expr->is_postfix()) { |
| 3147 // Perform the assignment as if via '='. | 3153 // Perform the assignment as if via '='. |
| 3148 { EffectContext context(this); | 3154 { EffectContext context(this); |
| 3149 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3155 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3150 Token::ASSIGN); | 3156 Token::ASSIGN); |
| 3157 context.Plug(rax); |
| 3151 } | 3158 } |
| 3152 // For all contexts except kEffect: We have the result on | 3159 // For all contexts except kEffect: We have the result on |
| 3153 // top of the stack. | 3160 // top of the stack. |
| 3154 if (!context()->IsEffect()) { | 3161 if (!context()->IsEffect()) { |
| 3155 context()->PlugTOS(); | 3162 context()->PlugTOS(); |
| 3156 } | 3163 } |
| 3157 } else { | 3164 } else { |
| 3158 // Perform the assignment as if via '='. | 3165 // Perform the assignment as if via '='. |
| 3159 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3166 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3160 Token::ASSIGN); | 3167 Token::ASSIGN); |
| 3168 context()->Plug(rax); |
| 3161 } | 3169 } |
| 3162 break; | 3170 break; |
| 3163 case NAMED_PROPERTY: { | 3171 case NAMED_PROPERTY: { |
| 3164 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3172 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
| 3165 __ pop(rdx); | 3173 __ pop(rdx); |
| 3166 Handle<Code> ic(isolate()->builtins()->builtin( | 3174 Handle<Code> ic(isolate()->builtins()->builtin( |
| 3167 Builtins::StoreIC_Initialize)); | 3175 Builtins::StoreIC_Initialize)); |
| 3168 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3176 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3169 if (expr->is_postfix()) { | 3177 if (expr->is_postfix()) { |
| 3170 if (!context()->IsEffect()) { | 3178 if (!context()->IsEffect()) { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3345 switch (op) { | 3353 switch (op) { |
| 3346 case Token::IN: | 3354 case Token::IN: |
| 3347 VisitForStackValue(expr->right()); | 3355 VisitForStackValue(expr->right()); |
| 3348 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 3356 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
| 3349 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 3357 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
| 3350 Split(equal, if_true, if_false, fall_through); | 3358 Split(equal, if_true, if_false, fall_through); |
| 3351 break; | 3359 break; |
| 3352 | 3360 |
| 3353 case Token::INSTANCEOF: { | 3361 case Token::INSTANCEOF: { |
| 3354 VisitForStackValue(expr->right()); | 3362 VisitForStackValue(expr->right()); |
| 3355 InstanceofStub stub; | 3363 InstanceofStub stub(InstanceofStub::kNoFlags); |
| 3356 __ CallStub(&stub); | 3364 __ CallStub(&stub); |
| 3357 __ testq(rax, rax); | 3365 __ testq(rax, rax); |
| 3358 // The stub returns 0 for true. | 3366 // The stub returns 0 for true. |
| 3359 Split(zero, if_true, if_false, fall_through); | 3367 Split(zero, if_true, if_false, fall_through); |
| 3360 break; | 3368 break; |
| 3361 } | 3369 } |
| 3362 | 3370 |
| 3363 default: { | 3371 default: { |
| 3364 VisitForAccumulatorValue(expr->right()); | 3372 VisitForAccumulatorValue(expr->right()); |
| 3365 Condition cc = no_condition; | 3373 Condition cc = no_condition; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3537 __ ret(0); | 3545 __ ret(0); |
| 3538 } | 3546 } |
| 3539 | 3547 |
| 3540 | 3548 |
| 3541 #undef __ | 3549 #undef __ |
| 3542 | 3550 |
| 3543 | 3551 |
| 3544 } } // namespace v8::internal | 3552 } } // namespace v8::internal |
| 3545 | 3553 |
| 3546 #endif // V8_TARGET_ARCH_X64 | 3554 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |