Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(397)

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 6580038: [Isolates] Merge from bleeding_edge, revisions 5934-6100. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 23 matching lines...) Expand all
34 #include "compiler.h" 34 #include "compiler.h"
35 #include "debug.h" 35 #include "debug.h"
36 #include "full-codegen.h" 36 #include "full-codegen.h"
37 #include "parser.h" 37 #include "parser.h"
38 #include "scopes.h" 38 #include "scopes.h"
39 #include "stub-cache.h" 39 #include "stub-cache.h"
40 40
41 namespace v8 { 41 namespace v8 {
42 namespace internal { 42 namespace internal {
43 43
44
44 #define __ ACCESS_MASM(masm_) 45 #define __ ACCESS_MASM(masm_)
45 46
47
48 class JumpPatchSite BASE_EMBEDDED {
49 public:
50 explicit JumpPatchSite(MacroAssembler* masm)
51 : masm_(masm) {
52 #ifdef DEBUG
53 info_emitted_ = false;
54 #endif
55 }
56
57 ~JumpPatchSite() {
58 ASSERT(patch_site_.is_bound() == info_emitted_);
59 }
60
61 void EmitJumpIfNotSmi(Register reg, NearLabel* target) {
62 __ test(reg, Immediate(kSmiTagMask));
63 EmitJump(not_carry, target); // Always taken before patched.
64 }
65
66 void EmitJumpIfSmi(Register reg, NearLabel* target) {
67 __ test(reg, Immediate(kSmiTagMask));
68 EmitJump(carry, target); // Never taken before patched.
69 }
70
71 void EmitPatchInfo() {
72 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
73 ASSERT(is_int8(delta_to_patch_site));
74 __ test(eax, Immediate(delta_to_patch_site));
75 #ifdef DEBUG
76 info_emitted_ = true;
77 #endif
78 }
79
80 bool is_bound() const { return patch_site_.is_bound(); }
81
82 private:
83 // jc will be patched with jz, jnc will become jnz.
84 void EmitJump(Condition cc, NearLabel* target) {
85 ASSERT(!patch_site_.is_bound() && !info_emitted_);
86 ASSERT(cc == carry || cc == not_carry);
87 __ bind(&patch_site_);
88 __ j(cc, target);
89 }
90
91 MacroAssembler* masm_;
92 Label patch_site_;
93 #ifdef DEBUG
94 bool info_emitted_;
95 #endif
96 };
97
98
46 // Generate code for a JS function. On entry to the function the receiver 99 // Generate code for a JS function. On entry to the function the receiver
47 // and arguments have been pushed on the stack left to right, with the 100 // and arguments have been pushed on the stack left to right, with the
48 // return address on top of them. The actual argument count matches the 101 // return address on top of them. The actual argument count matches the
49 // formal parameter count expected by the function. 102 // formal parameter count expected by the function.
50 // 103 //
51 // The live registers are: 104 // The live registers are:
52 // o edi: the JS function object being called (ie, ourselves) 105 // o edi: the JS function object being called (ie, ourselves)
53 // o esi: our context 106 // o esi: our context
54 // o ebp: our caller's frame pointer 107 // o ebp: our caller's frame pointer
55 // o esp: stack pointer (pointing to return address) 108 // o esp: stack pointer (pointing to return address)
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 } 244 }
192 245
193 { Comment cmnt(masm_, "[ return <undefined>;"); 246 { Comment cmnt(masm_, "[ return <undefined>;");
194 // Emit a 'return undefined' in case control fell off the end of the body. 247 // Emit a 'return undefined' in case control fell off the end of the body.
195 __ mov(eax, isolate()->factory()->undefined_value()); 248 __ mov(eax, isolate()->factory()->undefined_value());
196 EmitReturnSequence(); 249 EmitReturnSequence();
197 } 250 }
198 } 251 }
199 252
200 253
254 void FullCodeGenerator::ClearAccumulator() {
255 __ Set(eax, Immediate(Smi::FromInt(0)));
256 }
257
258
201 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { 259 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
202 Comment cmnt(masm_, "[ Stack check"); 260 Comment cmnt(masm_, "[ Stack check");
203 NearLabel ok; 261 NearLabel ok;
204 ExternalReference stack_limit = ExternalReference::address_of_stack_limit(); 262 ExternalReference stack_limit = ExternalReference::address_of_stack_limit();
205 __ cmp(esp, Operand::StaticVariable(stack_limit)); 263 __ cmp(esp, Operand::StaticVariable(stack_limit));
206 __ j(above_equal, &ok, taken); 264 __ j(above_equal, &ok, taken);
207 StackCheckStub stub; 265 StackCheckStub stub;
208 __ CallStub(&stub); 266 __ CallStub(&stub);
209 __ bind(&ok); 267 __ bind(&ok);
210 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 268 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 __ CallRuntime(Runtime::kDeclareGlobals, 3); 741 __ CallRuntime(Runtime::kDeclareGlobals, 3);
684 // Return value is ignored. 742 // Return value is ignored.
685 } 743 }
686 744
687 745
688 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 746 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
689 Comment cmnt(masm_, "[ SwitchStatement"); 747 Comment cmnt(masm_, "[ SwitchStatement");
690 Breakable nested_statement(this, stmt); 748 Breakable nested_statement(this, stmt);
691 SetStatementPosition(stmt); 749 SetStatementPosition(stmt);
692 750
693 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
694
695 // Keep the switch value on the stack until a case matches. 751 // Keep the switch value on the stack until a case matches.
696 VisitForStackValue(stmt->tag()); 752 VisitForStackValue(stmt->tag());
753 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
697 754
698 ZoneList<CaseClause*>* clauses = stmt->cases(); 755 ZoneList<CaseClause*>* clauses = stmt->cases();
699 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 756 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
700 757
701 Label next_test; // Recycled for each test. 758 Label next_test; // Recycled for each test.
702 // Compile all the tests with branches to their bodies. 759 // Compile all the tests with branches to their bodies.
703 for (int i = 0; i < clauses->length(); i++) { 760 for (int i = 0; i < clauses->length(); i++) {
704 CaseClause* clause = clauses->at(i); 761 CaseClause* clause = clauses->at(i);
705 // The default is not a test, but remember it as final fall through. 762 // The default is not a test, but remember it as final fall through.
706 if (clause->is_default()) { 763 if (clause->is_default()) {
707 default_clause = clause; 764 default_clause = clause;
708 continue; 765 continue;
709 } 766 }
710 767
711 Comment cmnt(masm_, "[ Case comparison"); 768 Comment cmnt(masm_, "[ Case comparison");
712 __ bind(&next_test); 769 __ bind(&next_test);
713 next_test.Unuse(); 770 next_test.Unuse();
714 771
715 // Compile the label expression. 772 // Compile the label expression.
716 VisitForAccumulatorValue(clause->label()); 773 VisitForAccumulatorValue(clause->label());
717 774
718 // Perform the comparison as if via '==='. 775 // Perform the comparison as if via '==='.
719 __ mov(edx, Operand(esp, 0)); // Switch value. 776 __ mov(edx, Operand(esp, 0)); // Switch value.
720 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 777 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
778 JumpPatchSite patch_site(masm_);
721 if (inline_smi_code) { 779 if (inline_smi_code) {
722 NearLabel slow_case; 780 NearLabel slow_case;
723 __ mov(ecx, edx); 781 __ mov(ecx, edx);
724 __ or_(ecx, Operand(eax)); 782 __ or_(ecx, Operand(eax));
725 __ test(ecx, Immediate(kSmiTagMask)); 783 patch_site.EmitJumpIfNotSmi(ecx, &slow_case);
726 __ j(not_zero, &slow_case, not_taken); 784
727 __ cmp(edx, Operand(eax)); 785 __ cmp(edx, Operand(eax));
728 __ j(not_equal, &next_test); 786 __ j(not_equal, &next_test);
729 __ Drop(1); // Switch value is no longer needed. 787 __ Drop(1); // Switch value is no longer needed.
730 __ jmp(clause->body_target()->entry_label()); 788 __ jmp(clause->body_target()->entry_label());
731 __ bind(&slow_case); 789 __ bind(&slow_case);
732 } 790 }
733 791
734 // Record position before stub call for type feedback. 792 // Record position before stub call for type feedback.
735 SetSourcePosition(clause->position()); 793 SetSourcePosition(clause->position());
736
737 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 794 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
738 __ call(ic, RelocInfo::CODE_TARGET); 795 EmitCallIC(ic, &patch_site);
739 796
740 __ test(eax, Operand(eax)); 797 __ test(eax, Operand(eax));
741 __ j(not_equal, &next_test); 798 __ j(not_equal, &next_test);
742 __ Drop(1); // Switch value is no longer needed. 799 __ Drop(1); // Switch value is no longer needed.
743 __ jmp(clause->body_target()->entry_label()); 800 __ jmp(clause->body_target()->entry_label());
744 } 801 }
745 802
746 // Discard the test value and jump to the default if present, otherwise to 803 // Discard the test value and jump to the default if present, otherwise to
747 // the end of the statement. 804 // the end of the statement.
748 __ bind(&next_test); 805 __ bind(&next_test);
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 965 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
909 __ test(eax, Operand(eax)); 966 __ test(eax, Operand(eax));
910 __ j(equal, loop_statement.continue_target()); 967 __ j(equal, loop_statement.continue_target());
911 __ mov(ebx, Operand(eax)); 968 __ mov(ebx, Operand(eax));
912 969
913 // Update the 'each' property or variable from the possibly filtered 970 // Update the 'each' property or variable from the possibly filtered
914 // entry in register ebx. 971 // entry in register ebx.
915 __ bind(&update_each); 972 __ bind(&update_each);
916 __ mov(result_register(), ebx); 973 __ mov(result_register(), ebx);
917 // Perform the assignment as if via '='. 974 // Perform the assignment as if via '='.
918 EmitAssignment(stmt->each()); 975 { EffectContext context(this);
976 EmitAssignment(stmt->each(), stmt->AssignmentId());
977 }
919 978
920 // Generate code for the body of the loop. 979 // Generate code for the body of the loop.
921 Visit(stmt->body()); 980 Visit(stmt->body());
922 981
923 // Generate code for going to the next element by incrementing the 982 // Generate code for going to the next element by incrementing the
924 // index (smi) stored on top of the stack. 983 // index (smi) stored on top of the stack.
925 __ bind(loop_statement.continue_target()); 984 __ bind(loop_statement.continue_target());
926 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); 985 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
927 986
928 EmitStackCheck(stmt); 987 EmitStackCheck(stmt);
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 break; 1540 break;
1482 case KEYED_PROPERTY: 1541 case KEYED_PROPERTY:
1483 EmitKeyedPropertyLoad(property); 1542 EmitKeyedPropertyLoad(property);
1484 break; 1543 break;
1485 } 1544 }
1486 } 1545 }
1487 1546
1488 // For property compound assignments we need another deoptimization 1547 // For property compound assignments we need another deoptimization
1489 // point after the property load. 1548 // point after the property load.
1490 if (property != NULL) { 1549 if (property != NULL) {
1491 PrepareForBailoutForId(expr->compound_bailout_id(), TOS_REG); 1550 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1492 } 1551 }
1493 1552
1494 Token::Value op = expr->binary_op(); 1553 Token::Value op = expr->binary_op();
1495 ConstantOperand constant = ShouldInlineSmiCase(op) 1554 ConstantOperand constant = ShouldInlineSmiCase(op)
1496 ? GetConstantOperand(op, expr->target(), expr->value()) 1555 ? GetConstantOperand(op, expr->target(), expr->value())
1497 : kNoConstants; 1556 : kNoConstants;
1498 ASSERT(constant == kRightConstant || constant == kNoConstants); 1557 ASSERT(constant == kRightConstant || constant == kNoConstants);
1499 if (constant == kNoConstants) { 1558 if (constant == kNoConstants) {
1500 __ push(eax); // Left operand goes on the stack. 1559 __ push(eax); // Left operand goes on the stack.
1501 VisitForAccumulatorValue(expr->value()); 1560 VisitForAccumulatorValue(expr->value());
(...skipping 22 matching lines...) Expand all
1524 } 1583 }
1525 1584
1526 // Record source position before possible IC call. 1585 // Record source position before possible IC call.
1527 SetSourcePosition(expr->position()); 1586 SetSourcePosition(expr->position());
1528 1587
1529 // Store the value. 1588 // Store the value.
1530 switch (assign_type) { 1589 switch (assign_type) {
1531 case VARIABLE: 1590 case VARIABLE:
1532 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1591 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1533 expr->op()); 1592 expr->op());
1593 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1594 context()->Plug(eax);
1534 break; 1595 break;
1535 case NAMED_PROPERTY: 1596 case NAMED_PROPERTY:
1536 EmitNamedPropertyAssignment(expr); 1597 EmitNamedPropertyAssignment(expr);
1537 break; 1598 break;
1538 case KEYED_PROPERTY: 1599 case KEYED_PROPERTY:
1539 EmitKeyedPropertyAssignment(expr); 1600 EmitKeyedPropertyAssignment(expr);
1540 break; 1601 break;
1541 } 1602 }
1542 } 1603 }
1543 1604
(...skipping 13 matching lines...) Expand all
1557 Handle<Code> ic(isolate()->builtins()->builtin( 1618 Handle<Code> ic(isolate()->builtins()->builtin(
1558 Builtins::KeyedLoadIC_Initialize)); 1619 Builtins::KeyedLoadIC_Initialize));
1559 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1620 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1560 } 1621 }
1561 1622
1562 1623
1563 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, 1624 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr,
1564 OverwriteMode mode, 1625 OverwriteMode mode,
1565 bool left_is_constant_smi, 1626 bool left_is_constant_smi,
1566 Smi* value) { 1627 Smi* value) {
1567 NearLabel call_stub; 1628 NearLabel call_stub, done;
1568 Label done;
1569 __ add(Operand(eax), Immediate(value)); 1629 __ add(Operand(eax), Immediate(value));
1570 __ j(overflow, &call_stub); 1630 __ j(overflow, &call_stub);
1571 __ test(eax, Immediate(kSmiTagMask)); 1631 JumpPatchSite patch_site(masm_);
1572 __ j(zero, &done); 1632 patch_site.EmitJumpIfSmi(eax, &done);
1573 1633
1574 // Undo the optimistic add operation and call the shared stub. 1634 // Undo the optimistic add operation and call the shared stub.
1575 __ bind(&call_stub); 1635 __ bind(&call_stub);
1576 __ sub(Operand(eax), Immediate(value)); 1636 __ sub(Operand(eax), Immediate(value));
1577 Token::Value op = Token::ADD; 1637 Token::Value op = Token::ADD;
1578 TypeRecordingBinaryOpStub stub(op, mode); 1638 TypeRecordingBinaryOpStub stub(op, mode);
1579 if (left_is_constant_smi) { 1639 if (left_is_constant_smi) {
1580 __ mov(edx, Immediate(value)); 1640 __ mov(edx, Immediate(value));
1581 } else { 1641 } else {
1582 __ mov(edx, eax); 1642 __ mov(edx, eax);
1583 __ mov(eax, Immediate(value)); 1643 __ mov(eax, Immediate(value));
1584 } 1644 }
1585 __ CallStub(&stub); 1645 EmitCallIC(stub.GetCode(), &patch_site);
1646
1586 __ bind(&done); 1647 __ bind(&done);
1587 context()->Plug(eax); 1648 context()->Plug(eax);
1588 } 1649 }
1589 1650
1590 1651
1591 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr, 1652 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr,
1592 OverwriteMode mode, 1653 OverwriteMode mode,
1593 bool left_is_constant_smi, 1654 bool left_is_constant_smi,
1594 Smi* value) { 1655 Smi* value) {
1595 Label call_stub, done; 1656 NearLabel call_stub, done;
1596 if (left_is_constant_smi) { 1657 if (left_is_constant_smi) {
1597 __ mov(ecx, eax); 1658 __ mov(ecx, eax);
1598 __ mov(eax, Immediate(value)); 1659 __ mov(eax, Immediate(value));
1599 __ sub(Operand(eax), ecx); 1660 __ sub(Operand(eax), ecx);
1600 } else { 1661 } else {
1601 __ sub(Operand(eax), Immediate(value)); 1662 __ sub(Operand(eax), Immediate(value));
1602 } 1663 }
1603 __ j(overflow, &call_stub); 1664 __ j(overflow, &call_stub);
1604 __ test(eax, Immediate(kSmiTagMask)); 1665 JumpPatchSite patch_site(masm_);
1605 __ j(zero, &done); 1666 patch_site.EmitJumpIfSmi(eax, &done);
1606 1667
1607 __ bind(&call_stub); 1668 __ bind(&call_stub);
1608 if (left_is_constant_smi) { 1669 if (left_is_constant_smi) {
1609 __ mov(edx, Immediate(value)); 1670 __ mov(edx, Immediate(value));
1610 __ mov(eax, ecx); 1671 __ mov(eax, ecx);
1611 } else { 1672 } else {
1612 __ add(Operand(eax), Immediate(value)); // Undo the subtraction. 1673 __ add(Operand(eax), Immediate(value)); // Undo the subtraction.
1613 __ mov(edx, eax); 1674 __ mov(edx, eax);
1614 __ mov(eax, Immediate(value)); 1675 __ mov(eax, Immediate(value));
1615 } 1676 }
1616 Token::Value op = Token::SUB; 1677 Token::Value op = Token::SUB;
1617 TypeRecordingBinaryOpStub stub(op, mode); 1678 TypeRecordingBinaryOpStub stub(op, mode);
1618 __ CallStub(&stub); 1679 EmitCallIC(stub.GetCode(), &patch_site);
1680
1619 __ bind(&done); 1681 __ bind(&done);
1620 context()->Plug(eax); 1682 context()->Plug(eax);
1621 } 1683 }
1622 1684
1623 1685
1624 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, 1686 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr,
1625 Token::Value op, 1687 Token::Value op,
1626 OverwriteMode mode, 1688 OverwriteMode mode,
1627 Smi* value) { 1689 Smi* value) {
1628 Label call_stub, smi_case, done; 1690 NearLabel call_stub, smi_case, done;
1629 int shift_value = value->value() & 0x1f; 1691 int shift_value = value->value() & 0x1f;
1630 1692
1631 __ test(eax, Immediate(kSmiTagMask)); 1693 JumpPatchSite patch_site(masm_);
1632 __ j(zero, &smi_case); 1694 patch_site.EmitJumpIfSmi(eax, &smi_case);
1633 1695
1696 // Call stub.
1634 __ bind(&call_stub); 1697 __ bind(&call_stub);
1635 __ mov(edx, eax); 1698 __ mov(edx, eax);
1636 __ mov(eax, Immediate(value)); 1699 __ mov(eax, Immediate(value));
1637 TypeRecordingBinaryOpStub stub(op, mode); 1700 TypeRecordingBinaryOpStub stub(op, mode);
1638 __ CallStub(&stub); 1701 EmitCallIC(stub.GetCode(), &patch_site);
1639 __ jmp(&done); 1702 __ jmp(&done);
1640 1703
1704 // Smi case.
1641 __ bind(&smi_case); 1705 __ bind(&smi_case);
1642 switch (op) { 1706 switch (op) {
1643 case Token::SHL: 1707 case Token::SHL:
1644 if (shift_value != 0) { 1708 if (shift_value != 0) {
1645 __ mov(edx, eax); 1709 __ mov(edx, eax);
1646 if (shift_value > 1) { 1710 if (shift_value > 1) {
1647 __ shl(edx, shift_value - 1); 1711 __ shl(edx, shift_value - 1);
1648 } 1712 }
1649 // Convert int result to smi, checking that it is in int range. 1713 // Convert int result to smi, checking that it is in int range.
1650 ASSERT(kSmiTagSize == 1); // Adjust code if not the case. 1714 ASSERT(kSmiTagSize == 1); // Adjust code if not the case.
(...skipping 29 matching lines...) Expand all
1680 1744
1681 __ bind(&done); 1745 __ bind(&done);
1682 context()->Plug(eax); 1746 context()->Plug(eax);
1683 } 1747 }
1684 1748
1685 1749
1686 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, 1750 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr,
1687 Token::Value op, 1751 Token::Value op,
1688 OverwriteMode mode, 1752 OverwriteMode mode,
1689 Smi* value) { 1753 Smi* value) {
1690 Label smi_case, done; 1754 NearLabel smi_case, done;
1691 __ test(eax, Immediate(kSmiTagMask)); 1755
1692 __ j(zero, &smi_case); 1756 JumpPatchSite patch_site(masm_);
1757 patch_site.EmitJumpIfSmi(eax, &smi_case);
1693 1758
1694 // The order of the arguments does not matter for bit-ops with a 1759 // The order of the arguments does not matter for bit-ops with a
1695 // constant operand. 1760 // constant operand.
1696 __ mov(edx, Immediate(value)); 1761 __ mov(edx, Immediate(value));
1697 TypeRecordingBinaryOpStub stub(op, mode); 1762 TypeRecordingBinaryOpStub stub(op, mode);
1698 __ CallStub(&stub); 1763 EmitCallIC(stub.GetCode(), &patch_site);
1699 __ jmp(&done); 1764 __ jmp(&done);
1700 1765
1766 // Smi case.
1701 __ bind(&smi_case); 1767 __ bind(&smi_case);
1702 switch (op) { 1768 switch (op) {
1703 case Token::BIT_OR: 1769 case Token::BIT_OR:
1704 __ or_(Operand(eax), Immediate(value)); 1770 __ or_(Operand(eax), Immediate(value));
1705 break; 1771 break;
1706 case Token::BIT_XOR: 1772 case Token::BIT_XOR:
1707 __ xor_(Operand(eax), Immediate(value)); 1773 __ xor_(Operand(eax), Immediate(value));
1708 break; 1774 break;
1709 case Token::BIT_AND: 1775 case Token::BIT_AND:
1710 __ and_(Operand(eax), Immediate(value)); 1776 __ and_(Operand(eax), Immediate(value));
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 EmitConstantSmiBinaryOp(expr, op, mode, false, value); 1824 EmitConstantSmiBinaryOp(expr, op, mode, false, value);
1759 return; 1825 return;
1760 } else if (constant == kLeftConstant) { 1826 } else if (constant == kLeftConstant) {
1761 Smi* value = Smi::cast(*left->AsLiteral()->handle()); 1827 Smi* value = Smi::cast(*left->AsLiteral()->handle());
1762 EmitConstantSmiBinaryOp(expr, op, mode, true, value); 1828 EmitConstantSmiBinaryOp(expr, op, mode, true, value);
1763 return; 1829 return;
1764 } 1830 }
1765 1831
1766 // Do combined smi check of the operands. Left operand is on the 1832 // Do combined smi check of the operands. Left operand is on the
1767 // stack. Right operand is in eax. 1833 // stack. Right operand is in eax.
1768 Label done, stub_call, smi_case; 1834 NearLabel done, smi_case, stub_call;
1769 __ pop(edx); 1835 __ pop(edx);
1770 __ mov(ecx, eax); 1836 __ mov(ecx, eax);
1771 __ or_(eax, Operand(edx)); 1837 __ or_(eax, Operand(edx));
1772 __ test(eax, Immediate(kSmiTagMask)); 1838 JumpPatchSite patch_site(masm_);
1773 __ j(zero, &smi_case); 1839 patch_site.EmitJumpIfSmi(eax, &smi_case);
1774 1840
1775 __ bind(&stub_call); 1841 __ bind(&stub_call);
1776 __ mov(eax, ecx); 1842 __ mov(eax, ecx);
1777 TypeRecordingBinaryOpStub stub(op, mode); 1843 TypeRecordingBinaryOpStub stub(op, mode);
1778 __ CallStub(&stub); 1844 EmitCallIC(stub.GetCode(), &patch_site);
1779 __ jmp(&done); 1845 __ jmp(&done);
1780 1846
1847 // Smi case.
1781 __ bind(&smi_case); 1848 __ bind(&smi_case);
1782 __ mov(eax, edx); // Copy left operand in case of a stub call. 1849 __ mov(eax, edx); // Copy left operand in case of a stub call.
1783 1850
1784 switch (op) { 1851 switch (op) {
1785 case Token::SAR: 1852 case Token::SAR:
1786 __ SmiUntag(eax); 1853 __ SmiUntag(eax);
1787 __ SmiUntag(ecx); 1854 __ SmiUntag(ecx);
1788 __ sar_cl(eax); // No checks of result necessary 1855 __ sar_cl(eax); // No checks of result necessary
1789 __ SmiTag(eax); 1856 __ SmiTag(eax);
1790 break; 1857 break;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1849 1916
1850 __ bind(&done); 1917 __ bind(&done);
1851 context()->Plug(eax); 1918 context()->Plug(eax);
1852 } 1919 }
1853 1920
1854 1921
1855 void FullCodeGenerator::EmitBinaryOp(Token::Value op, 1922 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
1856 OverwriteMode mode) { 1923 OverwriteMode mode) {
1857 __ pop(edx); 1924 __ pop(edx);
1858 TypeRecordingBinaryOpStub stub(op, mode); 1925 TypeRecordingBinaryOpStub stub(op, mode);
1859 __ CallStub(&stub); 1926 EmitCallIC(stub.GetCode(), NULL); // NULL signals no inlined smi code.
1860 context()->Plug(eax); 1927 context()->Plug(eax);
1861 } 1928 }
1862 1929
1863 1930
1864 void FullCodeGenerator::EmitAssignment(Expression* expr) { 1931 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1865 // Invalid left-hand sides are rewritten to have a 'throw 1932 // Invalid left-hand sides are rewritten to have a 'throw
1866 // ReferenceError' on the left-hand side. 1933 // ReferenceError' on the left-hand side.
1867 if (!expr->IsValidLeftHandSide()) { 1934 if (!expr->IsValidLeftHandSide()) {
1868 VisitForEffect(expr); 1935 VisitForEffect(expr);
1869 return; 1936 return;
1870 } 1937 }
1871 1938
1872 // Left-hand side can only be a property, a global or a (parameter or local) 1939 // Left-hand side can only be a property, a global or a (parameter or local)
1873 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1940 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1874 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1941 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
(...skipping 29 matching lines...) Expand all
1904 VisitForAccumulatorValue(prop->key()); 1971 VisitForAccumulatorValue(prop->key());
1905 __ mov(ecx, eax); 1972 __ mov(ecx, eax);
1906 __ pop(edx); 1973 __ pop(edx);
1907 __ pop(eax); // Restore value. 1974 __ pop(eax); // Restore value.
1908 Handle<Code> ic(isolate()->builtins()->builtin( 1975 Handle<Code> ic(isolate()->builtins()->builtin(
1909 Builtins::KeyedStoreIC_Initialize)); 1976 Builtins::KeyedStoreIC_Initialize));
1910 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1977 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1911 break; 1978 break;
1912 } 1979 }
1913 } 1980 }
1981 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1982 context()->Plug(eax);
1914 } 1983 }
1915 1984
1916 1985
1917 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1986 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1918 Token::Value op) { 1987 Token::Value op) {
1919 // Left-hand sides that rewrite to explicit property accesses do not reach 1988 // Left-hand sides that rewrite to explicit property accesses do not reach
1920 // here. 1989 // here.
1921 ASSERT(var != NULL); 1990 ASSERT(var != NULL);
1922 ASSERT(var->is_global() || var->AsSlot() != NULL); 1991 ASSERT(var->is_global() || var->AsSlot() != NULL);
1923 1992
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1977 if (op == Token::INIT_CONST) { 2046 if (op == Token::INIT_CONST) {
1978 // The runtime will ignore const redeclaration. 2047 // The runtime will ignore const redeclaration.
1979 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2048 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1980 } else { 2049 } else {
1981 __ CallRuntime(Runtime::kStoreContextSlot, 3); 2050 __ CallRuntime(Runtime::kStoreContextSlot, 3);
1982 } 2051 }
1983 break; 2052 break;
1984 } 2053 }
1985 __ bind(&done); 2054 __ bind(&done);
1986 } 2055 }
1987
1988 context()->Plug(eax);
1989 } 2056 }
1990 2057
1991 2058
1992 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2059 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1993 // Assignment to a property, using a named store IC. 2060 // Assignment to a property, using a named store IC.
1994 Property* prop = expr->target()->AsProperty(); 2061 Property* prop = expr->target()->AsProperty();
1995 ASSERT(prop != NULL); 2062 ASSERT(prop != NULL);
1996 ASSERT(prop->key()->AsLiteral() != NULL); 2063 ASSERT(prop->key()->AsLiteral() != NULL);
1997 2064
1998 // If the assignment starts a block of assignments to the same object, 2065 // If the assignment starts a block of assignments to the same object,
(...skipping 17 matching lines...) Expand all
2016 Handle<Code> ic(isolate()->builtins()->builtin( 2083 Handle<Code> ic(isolate()->builtins()->builtin(
2017 Builtins::StoreIC_Initialize)); 2084 Builtins::StoreIC_Initialize));
2018 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2085 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2019 2086
2020 // If the assignment ends an initialization block, revert to fast case. 2087 // If the assignment ends an initialization block, revert to fast case.
2021 if (expr->ends_initialization_block()) { 2088 if (expr->ends_initialization_block()) {
2022 __ push(eax); // Result of assignment, saved even if not needed. 2089 __ push(eax); // Result of assignment, saved even if not needed.
2023 __ push(Operand(esp, kPointerSize)); // Receiver is under value. 2090 __ push(Operand(esp, kPointerSize)); // Receiver is under value.
2024 __ CallRuntime(Runtime::kToFastProperties, 1); 2091 __ CallRuntime(Runtime::kToFastProperties, 1);
2025 __ pop(eax); 2092 __ pop(eax);
2026 context()->DropAndPlug(1, eax); 2093 __ Drop(1);
2027 } else {
2028 context()->Plug(eax);
2029 } 2094 }
2095 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2096 context()->Plug(eax);
2030 } 2097 }
2031 2098
2032 2099
2033 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2100 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2034 // Assignment to a property, using a keyed store IC. 2101 // Assignment to a property, using a keyed store IC.
2035 2102
2036 // If the assignment starts a block of assignments to the same object, 2103 // If the assignment starts a block of assignments to the same object,
2037 // change to slow case to avoid the quadratic behavior of repeatedly 2104 // change to slow case to avoid the quadratic behavior of repeatedly
2038 // adding fast properties. 2105 // adding fast properties.
2039 if (expr->starts_initialization_block()) { 2106 if (expr->starts_initialization_block()) {
(...skipping 18 matching lines...) Expand all
2058 2125
2059 // If the assignment ends an initialization block, revert to fast case. 2126 // If the assignment ends an initialization block, revert to fast case.
2060 if (expr->ends_initialization_block()) { 2127 if (expr->ends_initialization_block()) {
2061 __ pop(edx); 2128 __ pop(edx);
2062 __ push(eax); // Result of assignment, saved even if not needed. 2129 __ push(eax); // Result of assignment, saved even if not needed.
2063 __ push(edx); 2130 __ push(edx);
2064 __ CallRuntime(Runtime::kToFastProperties, 1); 2131 __ CallRuntime(Runtime::kToFastProperties, 1);
2065 __ pop(eax); 2132 __ pop(eax);
2066 } 2133 }
2067 2134
2135 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2068 context()->Plug(eax); 2136 context()->Plug(eax);
2069 } 2137 }
2070 2138
2071 2139
2072 void FullCodeGenerator::VisitProperty(Property* expr) { 2140 void FullCodeGenerator::VisitProperty(Property* expr) {
2073 Comment cmnt(masm_, "[ Property"); 2141 Comment cmnt(masm_, "[ Property");
2074 Expression* key = expr->key(); 2142 Expression* key = expr->key();
2075 2143
2076 if (key->IsPropertyName()) { 2144 if (key->IsPropertyName()) {
2077 VisitForAccumulatorValue(expr->obj()); 2145 VisitForAccumulatorValue(expr->obj());
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
3013 VisitForStackValue(args->at(1)); 3081 VisitForStackValue(args->at(1));
3014 3082
3015 StringCompareStub stub; 3083 StringCompareStub stub;
3016 __ CallStub(&stub); 3084 __ CallStub(&stub);
3017 context()->Plug(eax); 3085 context()->Plug(eax);
3018 } 3086 }
3019 3087
3020 3088
3021 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 3089 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
3022 // Load the argument on the stack and call the stub. 3090 // Load the argument on the stack and call the stub.
3023 TranscendentalCacheStub stub(TranscendentalCache::SIN); 3091 TranscendentalCacheStub stub(TranscendentalCache::SIN,
3092 TranscendentalCacheStub::TAGGED);
3024 ASSERT(args->length() == 1); 3093 ASSERT(args->length() == 1);
3025 VisitForStackValue(args->at(0)); 3094 VisitForStackValue(args->at(0));
3026 __ CallStub(&stub); 3095 __ CallStub(&stub);
3027 context()->Plug(eax); 3096 context()->Plug(eax);
3028 } 3097 }
3029 3098
3030 3099
3031 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 3100 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
3032 // Load the argument on the stack and call the stub. 3101 // Load the argument on the stack and call the stub.
3033 TranscendentalCacheStub stub(TranscendentalCache::COS); 3102 TranscendentalCacheStub stub(TranscendentalCache::COS,
3103 TranscendentalCacheStub::TAGGED);
3034 ASSERT(args->length() == 1); 3104 ASSERT(args->length() == 1);
3035 VisitForStackValue(args->at(0)); 3105 VisitForStackValue(args->at(0));
3036 __ CallStub(&stub); 3106 __ CallStub(&stub);
3037 context()->Plug(eax); 3107 context()->Plug(eax);
3038 } 3108 }
3039 3109
3040 3110
3041 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { 3111 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
3042 // Load the argument on the stack and call the stub. 3112 // Load the argument on the stack and call the stub.
3043 TranscendentalCacheStub stub(TranscendentalCache::LOG); 3113 TranscendentalCacheStub stub(TranscendentalCache::LOG,
3114 TranscendentalCacheStub::TAGGED);
3044 ASSERT(args->length() == 1); 3115 ASSERT(args->length() == 1);
3045 VisitForStackValue(args->at(0)); 3116 VisitForStackValue(args->at(0));
3046 __ CallStub(&stub); 3117 __ CallStub(&stub);
3047 context()->Plug(eax); 3118 context()->Plug(eax);
3048 } 3119 }
3049 3120
3050 3121
3051 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 3122 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
3052 // Load the argument on the stack and call the runtime function. 3123 // Load the argument on the stack and call the runtime function.
3053 ASSERT(args->length() == 1); 3124 ASSERT(args->length() == 1);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3117 __ j(not_equal, &slow_case); 3188 __ j(not_equal, &slow_case);
3118 3189
3119 // Check that both indices are smis. 3190 // Check that both indices are smis.
3120 __ mov(index_1, Operand(esp, 1 * kPointerSize)); 3191 __ mov(index_1, Operand(esp, 1 * kPointerSize));
3121 __ mov(index_2, Operand(esp, 0)); 3192 __ mov(index_2, Operand(esp, 0));
3122 __ mov(temp, index_1); 3193 __ mov(temp, index_1);
3123 __ or_(temp, Operand(index_2)); 3194 __ or_(temp, Operand(index_2));
3124 __ test(temp, Immediate(kSmiTagMask)); 3195 __ test(temp, Immediate(kSmiTagMask));
3125 __ j(not_zero, &slow_case); 3196 __ j(not_zero, &slow_case);
3126 3197
3198 // Check that both indices are valid.
3199 __ mov(temp, FieldOperand(object, JSArray::kLengthOffset));
3200 __ cmp(temp, Operand(index_1));
3201 __ j(below_equal, &slow_case);
3202 __ cmp(temp, Operand(index_2));
3203 __ j(below_equal, &slow_case);
3204
3127 // Bring addresses into index1 and index2. 3205 // Bring addresses into index1 and index2.
3128 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); 3206 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1));
3129 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2)); 3207 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2));
3130 3208
3131 // Swap elements. Use object and temp as scratch registers. 3209 // Swap elements. Use object and temp as scratch registers.
3132 __ mov(object, Operand(index_1, 0)); 3210 __ mov(object, Operand(index_1, 0));
3133 __ mov(temp, Operand(index_2, 0)); 3211 __ mov(temp, Operand(index_2, 0));
3134 __ mov(Operand(index_2, 0), object); 3212 __ mov(Operand(index_2, 0), object);
3135 __ mov(Operand(index_1, 0), temp); 3213 __ mov(Operand(index_1, 0), temp);
3136 3214
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
3724 __ mov(Operand(esp, kPointerSize), eax); 3802 __ mov(Operand(esp, kPointerSize), eax);
3725 break; 3803 break;
3726 case KEYED_PROPERTY: 3804 case KEYED_PROPERTY:
3727 __ mov(Operand(esp, 2 * kPointerSize), eax); 3805 __ mov(Operand(esp, 2 * kPointerSize), eax);
3728 break; 3806 break;
3729 } 3807 }
3730 } 3808 }
3731 } 3809 }
3732 3810
3733 // Inline smi case if we are in a loop. 3811 // Inline smi case if we are in a loop.
3734 NearLabel stub_call; 3812 NearLabel stub_call, done;
3735 Label done; 3813 JumpPatchSite patch_site(masm_);
3814
3736 if (ShouldInlineSmiCase(expr->op())) { 3815 if (ShouldInlineSmiCase(expr->op())) {
3737 if (expr->op() == Token::INC) { 3816 if (expr->op() == Token::INC) {
3738 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3817 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3739 } else { 3818 } else {
3740 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3819 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3741 } 3820 }
3742 __ j(overflow, &stub_call); 3821 __ j(overflow, &stub_call);
3743 // We could eliminate this smi check if we split the code at 3822 // We could eliminate this smi check if we split the code at
3744 // the first smi check before calling ToNumber. 3823 // the first smi check before calling ToNumber.
3745 __ test(eax, Immediate(kSmiTagMask)); 3824 patch_site.EmitJumpIfSmi(eax, &done);
3746 __ j(zero, &done); 3825
3747 __ bind(&stub_call); 3826 __ bind(&stub_call);
3748 // Call stub. Undo operation first. 3827 // Call stub. Undo operation first.
3749 if (expr->op() == Token::INC) { 3828 if (expr->op() == Token::INC) {
3750 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3829 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3751 } else { 3830 } else {
3752 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3831 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3753 } 3832 }
3754 } 3833 }
3755 3834
3756 // Record position before stub call. 3835 // Record position before stub call.
3757 SetSourcePosition(expr->position()); 3836 SetSourcePosition(expr->position());
3758 3837
3759 // Call stub for +1/-1. 3838 // Call stub for +1/-1.
3760 __ mov(edx, eax); 3839 __ mov(edx, eax);
3761 __ mov(eax, Immediate(Smi::FromInt(1))); 3840 __ mov(eax, Immediate(Smi::FromInt(1)));
3762 TypeRecordingBinaryOpStub stub(expr->binary_op(), 3841 TypeRecordingBinaryOpStub stub(expr->binary_op(),
3763 NO_OVERWRITE); 3842 NO_OVERWRITE);
3764 __ CallStub(&stub); 3843 EmitCallIC(stub.GetCode(), &patch_site);
3765 __ bind(&done); 3844 __ bind(&done);
3766 3845
3767 // Store the value returned in eax. 3846 // Store the value returned in eax.
3768 switch (assign_type) { 3847 switch (assign_type) {
3769 case VARIABLE: 3848 case VARIABLE:
3770 if (expr->is_postfix()) { 3849 if (expr->is_postfix()) {
3771 // Perform the assignment as if via '='. 3850 // Perform the assignment as if via '='.
3772 { EffectContext context(this); 3851 { EffectContext context(this);
3773 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3852 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3774 Token::ASSIGN); 3853 Token::ASSIGN);
3854 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3855 context.Plug(eax);
3775 } 3856 }
3776 // For all contexts except EffectContext We have the result on 3857 // For all contexts except EffectContext We have the result on
3777 // top of the stack. 3858 // top of the stack.
3778 if (!context()->IsEffect()) { 3859 if (!context()->IsEffect()) {
3779 context()->PlugTOS(); 3860 context()->PlugTOS();
3780 } 3861 }
3781 } else { 3862 } else {
3782 // Perform the assignment as if via '='. 3863 // Perform the assignment as if via '='.
3783 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3864 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3784 Token::ASSIGN); 3865 Token::ASSIGN);
3866 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3867 context()->Plug(eax);
3785 } 3868 }
3786 break; 3869 break;
3787 case NAMED_PROPERTY: { 3870 case NAMED_PROPERTY: {
3788 __ mov(ecx, prop->key()->AsLiteral()->handle()); 3871 __ mov(ecx, prop->key()->AsLiteral()->handle());
3789 __ pop(edx); 3872 __ pop(edx);
3790 Handle<Code> ic(isolate()->builtins()->builtin( 3873 Handle<Code> ic(isolate()->builtins()->builtin(
3791 Builtins::StoreIC_Initialize)); 3874 Builtins::StoreIC_Initialize));
3792 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3875 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3876 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3793 if (expr->is_postfix()) { 3877 if (expr->is_postfix()) {
3794 if (!context()->IsEffect()) { 3878 if (!context()->IsEffect()) {
3795 context()->PlugTOS(); 3879 context()->PlugTOS();
3796 } 3880 }
3797 } else { 3881 } else {
3798 context()->Plug(eax); 3882 context()->Plug(eax);
3799 } 3883 }
3800 break; 3884 break;
3801 } 3885 }
3802 case KEYED_PROPERTY: { 3886 case KEYED_PROPERTY: {
3803 __ pop(ecx); 3887 __ pop(ecx);
3804 __ pop(edx); 3888 __ pop(edx);
3805 Handle<Code> ic(isolate()->builtins()->builtin( 3889 Handle<Code> ic(isolate()->builtins()->builtin(
3806 Builtins::KeyedStoreIC_Initialize)); 3890 Builtins::KeyedStoreIC_Initialize));
3807 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3891 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3892 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3808 if (expr->is_postfix()) { 3893 if (expr->is_postfix()) {
3809 // Result is on the stack 3894 // Result is on the stack
3810 if (!context()->IsEffect()) { 3895 if (!context()->IsEffect()) {
3811 context()->PlugTOS(); 3896 context()->PlugTOS();
3812 } 3897 }
3813 } else { 3898 } else {
3814 context()->Plug(eax); 3899 context()->Plug(eax);
3815 } 3900 }
3816 break; 3901 break;
3817 } 3902 }
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
3976 case Token::IN: 4061 case Token::IN:
3977 VisitForStackValue(expr->right()); 4062 VisitForStackValue(expr->right());
3978 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4063 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3979 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 4064 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
3980 __ cmp(eax, isolate()->factory()->true_value()); 4065 __ cmp(eax, isolate()->factory()->true_value());
3981 Split(equal, if_true, if_false, fall_through); 4066 Split(equal, if_true, if_false, fall_through);
3982 break; 4067 break;
3983 4068
3984 case Token::INSTANCEOF: { 4069 case Token::INSTANCEOF: {
3985 VisitForStackValue(expr->right()); 4070 VisitForStackValue(expr->right());
3986 InstanceofStub stub; 4071 __ IncrementCounter(COUNTERS->instance_of_full(), 1);
4072 InstanceofStub stub(InstanceofStub::kNoFlags);
3987 __ CallStub(&stub); 4073 __ CallStub(&stub);
3988 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4074 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3989 __ test(eax, Operand(eax)); 4075 __ test(eax, Operand(eax));
3990 // The stub returns 0 for true. 4076 // The stub returns 0 for true.
3991 Split(zero, if_true, if_false, fall_through); 4077 Split(zero, if_true, if_false, fall_through);
3992 break; 4078 break;
3993 } 4079 }
3994 4080
3995 default: { 4081 default: {
3996 VisitForAccumulatorValue(expr->right()); 4082 VisitForAccumulatorValue(expr->right());
(...skipping 27 matching lines...) Expand all
4024 cc = greater_equal; 4110 cc = greater_equal;
4025 __ pop(edx); 4111 __ pop(edx);
4026 break; 4112 break;
4027 case Token::IN: 4113 case Token::IN:
4028 case Token::INSTANCEOF: 4114 case Token::INSTANCEOF:
4029 default: 4115 default:
4030 UNREACHABLE(); 4116 UNREACHABLE();
4031 } 4117 }
4032 4118
4033 bool inline_smi_code = ShouldInlineSmiCase(op); 4119 bool inline_smi_code = ShouldInlineSmiCase(op);
4120 JumpPatchSite patch_site(masm_);
4034 if (inline_smi_code) { 4121 if (inline_smi_code) {
4035 NearLabel slow_case; 4122 NearLabel slow_case;
4036 __ mov(ecx, Operand(edx)); 4123 __ mov(ecx, Operand(edx));
4037 __ or_(ecx, Operand(eax)); 4124 __ or_(ecx, Operand(eax));
4038 __ test(ecx, Immediate(kSmiTagMask)); 4125 patch_site.EmitJumpIfNotSmi(ecx, &slow_case);
4039 __ j(not_zero, &slow_case, not_taken);
4040 __ cmp(edx, Operand(eax)); 4126 __ cmp(edx, Operand(eax));
4041 Split(cc, if_true, if_false, NULL); 4127 Split(cc, if_true, if_false, NULL);
4042 __ bind(&slow_case); 4128 __ bind(&slow_case);
4043 } 4129 }
4044 4130
4045 // Record position and call the compare IC. 4131 // Record position and call the compare IC.
4132 SetSourcePosition(expr->position());
4046 Handle<Code> ic = CompareIC::GetUninitialized(op); 4133 Handle<Code> ic = CompareIC::GetUninitialized(op);
4047 SetSourcePosition(expr->position()); 4134 EmitCallIC(ic, &patch_site);
4048 __ call(ic, RelocInfo::CODE_TARGET); 4135
4049 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4136 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4050 __ test(eax, Operand(eax)); 4137 __ test(eax, Operand(eax));
4051 Split(cc, if_true, if_false, fall_through); 4138 Split(cc, if_true, if_false, fall_through);
4052 } 4139 }
4053 } 4140 }
4054 4141
4055 // Convert the result of the comparison into one expected for this 4142 // Convert the result of the comparison into one expected for this
4056 // expression's context. 4143 // expression's context.
4057 context()->Plug(if_true, if_false); 4144 context()->Plug(if_true, if_false);
4058 } 4145 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
4142 case Code::KEYED_STORE_IC: 4229 case Code::KEYED_STORE_IC:
4143 __ nop(); // Signals no inlined code. 4230 __ nop(); // Signals no inlined code.
4144 break; 4231 break;
4145 default: 4232 default:
4146 // Do nothing. 4233 // Do nothing.
4147 break; 4234 break;
4148 } 4235 }
4149 } 4236 }
4150 4237
4151 4238
4239 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
4240 __ call(ic, RelocInfo::CODE_TARGET);
4241 if (patch_site != NULL && patch_site->is_bound()) {
4242 patch_site->EmitPatchInfo();
4243 } else {
4244 __ nop(); // Signals no inlined code.
4245 }
4246 }
4247
4248
4152 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4249 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4153 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 4250 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4154 __ mov(Operand(ebp, frame_offset), value); 4251 __ mov(Operand(ebp, frame_offset), value);
4155 } 4252 }
4156 4253
4157 4254
4158 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4255 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4159 __ mov(dst, ContextOperand(esi, context_index)); 4256 __ mov(dst, ContextOperand(esi, context_index));
4160 } 4257 }
4161 4258
(...skipping 27 matching lines...) Expand all
4189 // And return. 4286 // And return.
4190 __ ret(0); 4287 __ ret(0);
4191 } 4288 }
4192 4289
4193 4290
4194 #undef __ 4291 #undef __
4195 4292
4196 } } // namespace v8::internal 4293 } } // namespace v8::internal
4197 4294
4198 #endif // V8_TARGET_ARCH_IA32 4295 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698