| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 VisitForAccumulatorValue(function); | 749 VisitForAccumulatorValue(function); |
| 750 __ pop(edx); | 750 __ pop(edx); |
| 751 | 751 |
| 752 ASSERT(prop->key()->AsLiteral() != NULL && | 752 ASSERT(prop->key()->AsLiteral() != NULL && |
| 753 prop->key()->AsLiteral()->handle()->IsSmi()); | 753 prop->key()->AsLiteral()->handle()->IsSmi()); |
| 754 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 754 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
| 755 | 755 |
| 756 Handle<Code> ic = is_strict_mode() | 756 Handle<Code> ic = is_strict_mode() |
| 757 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 757 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 758 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 758 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 759 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 759 __ call(ic); |
| 760 } | 760 } |
| 761 } | 761 } |
| 762 } | 762 } |
| 763 | 763 |
| 764 | 764 |
| 765 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 765 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
| 766 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 766 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
| 767 } | 767 } |
| 768 | 768 |
| 769 | 769 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 __ cmp(edx, Operand(eax)); | 822 __ cmp(edx, Operand(eax)); |
| 823 __ j(not_equal, &next_test); | 823 __ j(not_equal, &next_test); |
| 824 __ Drop(1); // Switch value is no longer needed. | 824 __ Drop(1); // Switch value is no longer needed. |
| 825 __ jmp(clause->body_target()); | 825 __ jmp(clause->body_target()); |
| 826 __ bind(&slow_case); | 826 __ bind(&slow_case); |
| 827 } | 827 } |
| 828 | 828 |
| 829 // Record position before stub call for type feedback. | 829 // Record position before stub call for type feedback. |
| 830 SetSourcePosition(clause->position()); | 830 SetSourcePosition(clause->position()); |
| 831 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 831 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
| 832 EmitCallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 832 __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); |
| 833 patch_site.EmitPatchInfo(); | 833 patch_site.EmitPatchInfo(); |
| 834 __ test(eax, Operand(eax)); | 834 __ test(eax, Operand(eax)); |
| 835 __ j(not_equal, &next_test); | 835 __ j(not_equal, &next_test); |
| 836 __ Drop(1); // Switch value is no longer needed. | 836 __ Drop(1); // Switch value is no longer needed. |
| 837 __ jmp(clause->body_target()); | 837 __ jmp(clause->body_target()); |
| 838 } | 838 } |
| 839 | 839 |
| 840 // Discard the test value and jump to the default if present, otherwise to | 840 // Discard the test value and jump to the default if present, otherwise to |
| 841 // the end of the statement. | 841 // the end of the statement. |
| 842 __ bind(&next_test); | 842 __ bind(&next_test); |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 } | 1116 } |
| 1117 | 1117 |
| 1118 // All extension objects were empty and it is safe to use a global | 1118 // All extension objects were empty and it is safe to use a global |
| 1119 // load IC call. | 1119 // load IC call. |
| 1120 __ mov(eax, GlobalObjectOperand()); | 1120 __ mov(eax, GlobalObjectOperand()); |
| 1121 __ mov(ecx, slot->var()->name()); | 1121 __ mov(ecx, slot->var()->name()); |
| 1122 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1122 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 1123 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1123 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
| 1124 ? RelocInfo::CODE_TARGET | 1124 ? RelocInfo::CODE_TARGET |
| 1125 : RelocInfo::CODE_TARGET_CONTEXT; | 1125 : RelocInfo::CODE_TARGET_CONTEXT; |
| 1126 EmitCallIC(ic, mode, AstNode::kNoNumber); | 1126 __ call(ic, mode); |
| 1127 } | 1127 } |
| 1128 | 1128 |
| 1129 | 1129 |
| 1130 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 1130 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
| 1131 Slot* slot, | 1131 Slot* slot, |
| 1132 Label* slow) { | 1132 Label* slow) { |
| 1133 ASSERT(slot->type() == Slot::CONTEXT); | 1133 ASSERT(slot->type() == Slot::CONTEXT); |
| 1134 Register context = esi; | 1134 Register context = esi; |
| 1135 Register temp = ebx; | 1135 Register temp = ebx; |
| 1136 | 1136 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 key_literal->handle()->IsSmi()) { | 1196 key_literal->handle()->IsSmi()) { |
| 1197 // Load arguments object if there are no eval-introduced | 1197 // Load arguments object if there are no eval-introduced |
| 1198 // variables. Then load the argument from the arguments | 1198 // variables. Then load the argument from the arguments |
| 1199 // object using keyed load. | 1199 // object using keyed load. |
| 1200 __ mov(edx, | 1200 __ mov(edx, |
| 1201 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1201 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
| 1202 slow)); | 1202 slow)); |
| 1203 __ SafeSet(eax, Immediate(key_literal->handle())); | 1203 __ SafeSet(eax, Immediate(key_literal->handle())); |
| 1204 Handle<Code> ic = | 1204 Handle<Code> ic = |
| 1205 isolate()->builtins()->KeyedLoadIC_Initialize(); | 1205 isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 1206 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); | 1206 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); |
| 1207 __ jmp(done); | 1207 __ jmp(done); |
| 1208 } | 1208 } |
| 1209 } | 1209 } |
| 1210 } | 1210 } |
| 1211 } | 1211 } |
| 1212 } | 1212 } |
| 1213 | 1213 |
| 1214 | 1214 |
| 1215 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1215 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
| 1216 // Three cases: non-this global variables, lookup slots, and all other | 1216 // Three cases: non-this global variables, lookup slots, and all other |
| 1217 // types of slots. | 1217 // types of slots. |
| 1218 Slot* slot = var->AsSlot(); | 1218 Slot* slot = var->AsSlot(); |
| 1219 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); | 1219 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); |
| 1220 | 1220 |
| 1221 if (slot == NULL) { | 1221 if (slot == NULL) { |
| 1222 Comment cmnt(masm_, "Global variable"); | 1222 Comment cmnt(masm_, "Global variable"); |
| 1223 // Use inline caching. Variable name is passed in ecx and the global | 1223 // Use inline caching. Variable name is passed in ecx and the global |
| 1224 // object on the stack. | 1224 // object on the stack. |
| 1225 __ mov(eax, GlobalObjectOperand()); | 1225 __ mov(eax, GlobalObjectOperand()); |
| 1226 __ mov(ecx, var->name()); | 1226 __ mov(ecx, var->name()); |
| 1227 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1227 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 1228 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1228 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 1229 context()->Plug(eax); | 1229 context()->Plug(eax); |
| 1230 | 1230 |
| 1231 } else if (slot->type() == Slot::LOOKUP) { | 1231 } else if (slot->type() == Slot::LOOKUP) { |
| 1232 Label done, slow; | 1232 Label done, slow; |
| 1233 | 1233 |
| 1234 // Generate code for loading from variables potentially shadowed | 1234 // Generate code for loading from variables potentially shadowed |
| 1235 // by eval-introduced variables. | 1235 // by eval-introduced variables. |
| 1236 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1236 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1237 | 1237 |
| 1238 __ bind(&slow); | 1238 __ bind(&slow); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1364 // Fall through. | 1364 // Fall through. |
| 1365 case ObjectLiteral::Property::COMPUTED: | 1365 case ObjectLiteral::Property::COMPUTED: |
| 1366 if (key->handle()->IsSymbol()) { | 1366 if (key->handle()->IsSymbol()) { |
| 1367 if (property->emit_store()) { | 1367 if (property->emit_store()) { |
| 1368 VisitForAccumulatorValue(value); | 1368 VisitForAccumulatorValue(value); |
| 1369 __ mov(ecx, Immediate(key->handle())); | 1369 __ mov(ecx, Immediate(key->handle())); |
| 1370 __ mov(edx, Operand(esp, 0)); | 1370 __ mov(edx, Operand(esp, 0)); |
| 1371 Handle<Code> ic = is_strict_mode() | 1371 Handle<Code> ic = is_strict_mode() |
| 1372 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1372 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1373 : isolate()->builtins()->StoreIC_Initialize(); | 1373 : isolate()->builtins()->StoreIC_Initialize(); |
| 1374 EmitCallIC(ic, RelocInfo::CODE_TARGET, key->id()); | 1374 __ call(ic, RelocInfo::CODE_TARGET, key->id()); |
| 1375 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1375 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1376 } else { | 1376 } else { |
| 1377 VisitForEffect(value); | 1377 VisitForEffect(value); |
| 1378 } | 1378 } |
| 1379 break; | 1379 break; |
| 1380 } | 1380 } |
| 1381 // Fall through. | 1381 // Fall through. |
| 1382 case ObjectLiteral::Property::PROTOTYPE: | 1382 case ObjectLiteral::Property::PROTOTYPE: |
| 1383 __ push(Operand(esp, 0)); // Duplicate receiver. | 1383 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1384 VisitForStackValue(key); | 1384 VisitForStackValue(key); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 } | 1597 } |
| 1598 } | 1598 } |
| 1599 | 1599 |
| 1600 | 1600 |
| 1601 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1601 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1602 SetSourcePosition(prop->position()); | 1602 SetSourcePosition(prop->position()); |
| 1603 Literal* key = prop->key()->AsLiteral(); | 1603 Literal* key = prop->key()->AsLiteral(); |
| 1604 ASSERT(!key->handle()->IsSmi()); | 1604 ASSERT(!key->handle()->IsSmi()); |
| 1605 __ mov(ecx, Immediate(key->handle())); | 1605 __ mov(ecx, Immediate(key->handle())); |
| 1606 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1606 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 1607 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 1607 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 1608 } | 1608 } |
| 1609 | 1609 |
| 1610 | 1610 |
| 1611 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1611 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1612 SetSourcePosition(prop->position()); | 1612 SetSourcePosition(prop->position()); |
| 1613 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1613 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 1614 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 1614 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 1615 } | 1615 } |
| 1616 | 1616 |
| 1617 | 1617 |
| 1618 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1618 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 1619 Token::Value op, | 1619 Token::Value op, |
| 1620 OverwriteMode mode, | 1620 OverwriteMode mode, |
| 1621 Expression* left, | 1621 Expression* left, |
| 1622 Expression* right) { | 1622 Expression* right) { |
| 1623 // Do combined smi check of the operands. Left operand is on the | 1623 // Do combined smi check of the operands. Left operand is on the |
| 1624 // stack. Right operand is in eax. | 1624 // stack. Right operand is in eax. |
| 1625 Label smi_case, done, stub_call; | 1625 Label smi_case, done, stub_call; |
| 1626 __ pop(edx); | 1626 __ pop(edx); |
| 1627 __ mov(ecx, eax); | 1627 __ mov(ecx, eax); |
| 1628 __ or_(eax, Operand(edx)); | 1628 __ or_(eax, Operand(edx)); |
| 1629 JumpPatchSite patch_site(masm_); | 1629 JumpPatchSite patch_site(masm_); |
| 1630 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); | 1630 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
| 1631 | 1631 |
| 1632 __ bind(&stub_call); | 1632 __ bind(&stub_call); |
| 1633 __ mov(eax, ecx); | 1633 __ mov(eax, ecx); |
| 1634 BinaryOpStub stub(op, mode); | 1634 BinaryOpStub stub(op, mode); |
| 1635 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1635 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1636 patch_site.EmitPatchInfo(); | 1636 patch_site.EmitPatchInfo(); |
| 1637 __ jmp(&done, Label::kNear); | 1637 __ jmp(&done, Label::kNear); |
| 1638 | 1638 |
| 1639 // Smi case. | 1639 // Smi case. |
| 1640 __ bind(&smi_case); | 1640 __ bind(&smi_case); |
| 1641 __ mov(eax, edx); // Copy left operand in case of a stub call. | 1641 __ mov(eax, edx); // Copy left operand in case of a stub call. |
| 1642 | 1642 |
| 1643 switch (op) { | 1643 switch (op) { |
| 1644 case Token::SAR: | 1644 case Token::SAR: |
| 1645 __ SmiUntag(eax); | 1645 __ SmiUntag(eax); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 context()->Plug(eax); | 1710 context()->Plug(eax); |
| 1711 } | 1711 } |
| 1712 | 1712 |
| 1713 | 1713 |
| 1714 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1714 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 1715 Token::Value op, | 1715 Token::Value op, |
| 1716 OverwriteMode mode) { | 1716 OverwriteMode mode) { |
| 1717 __ pop(edx); | 1717 __ pop(edx); |
| 1718 BinaryOpStub stub(op, mode); | 1718 BinaryOpStub stub(op, mode); |
| 1719 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1719 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 1720 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1720 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1721 patch_site.EmitPatchInfo(); | 1721 patch_site.EmitPatchInfo(); |
| 1722 context()->Plug(eax); | 1722 context()->Plug(eax); |
| 1723 } | 1723 } |
| 1724 | 1724 |
| 1725 | 1725 |
| 1726 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1726 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
| 1727 // Invalid left-hand sides are rewritten to have a 'throw | 1727 // Invalid left-hand sides are rewritten to have a 'throw |
| 1728 // ReferenceError' on the left-hand side. | 1728 // ReferenceError' on the left-hand side. |
| 1729 if (!expr->IsValidLeftHandSide()) { | 1729 if (!expr->IsValidLeftHandSide()) { |
| 1730 VisitForEffect(expr); | 1730 VisitForEffect(expr); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1751 } | 1751 } |
| 1752 case NAMED_PROPERTY: { | 1752 case NAMED_PROPERTY: { |
| 1753 __ push(eax); // Preserve value. | 1753 __ push(eax); // Preserve value. |
| 1754 VisitForAccumulatorValue(prop->obj()); | 1754 VisitForAccumulatorValue(prop->obj()); |
| 1755 __ mov(edx, eax); | 1755 __ mov(edx, eax); |
| 1756 __ pop(eax); // Restore value. | 1756 __ pop(eax); // Restore value. |
| 1757 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1757 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1758 Handle<Code> ic = is_strict_mode() | 1758 Handle<Code> ic = is_strict_mode() |
| 1759 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1759 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1760 : isolate()->builtins()->StoreIC_Initialize(); | 1760 : isolate()->builtins()->StoreIC_Initialize(); |
| 1761 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1761 __ call(ic); |
| 1762 break; | 1762 break; |
| 1763 } | 1763 } |
| 1764 case KEYED_PROPERTY: { | 1764 case KEYED_PROPERTY: { |
| 1765 __ push(eax); // Preserve value. | 1765 __ push(eax); // Preserve value. |
| 1766 if (prop->is_synthetic()) { | 1766 if (prop->is_synthetic()) { |
| 1767 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1767 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 1768 ASSERT(prop->key()->AsLiteral() != NULL); | 1768 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1769 { AccumulatorValueContext for_object(this); | 1769 { AccumulatorValueContext for_object(this); |
| 1770 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 1770 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
| 1771 } | 1771 } |
| 1772 __ mov(edx, eax); | 1772 __ mov(edx, eax); |
| 1773 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 1773 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
| 1774 } else { | 1774 } else { |
| 1775 VisitForStackValue(prop->obj()); | 1775 VisitForStackValue(prop->obj()); |
| 1776 VisitForAccumulatorValue(prop->key()); | 1776 VisitForAccumulatorValue(prop->key()); |
| 1777 __ mov(ecx, eax); | 1777 __ mov(ecx, eax); |
| 1778 __ pop(edx); | 1778 __ pop(edx); |
| 1779 } | 1779 } |
| 1780 __ pop(eax); // Restore value. | 1780 __ pop(eax); // Restore value. |
| 1781 Handle<Code> ic = is_strict_mode() | 1781 Handle<Code> ic = is_strict_mode() |
| 1782 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1782 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 1783 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1783 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 1784 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1784 __ call(ic); |
| 1785 break; | 1785 break; |
| 1786 } | 1786 } |
| 1787 } | 1787 } |
| 1788 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1788 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
| 1789 context()->Plug(eax); | 1789 context()->Plug(eax); |
| 1790 } | 1790 } |
| 1791 | 1791 |
| 1792 | 1792 |
| 1793 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1793 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1794 Token::Value op) { | 1794 Token::Value op) { |
| 1795 ASSERT(var != NULL); | 1795 ASSERT(var != NULL); |
| 1796 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1796 ASSERT(var->is_global() || var->AsSlot() != NULL); |
| 1797 | 1797 |
| 1798 if (var->is_global()) { | 1798 if (var->is_global()) { |
| 1799 ASSERT(!var->is_this()); | 1799 ASSERT(!var->is_this()); |
| 1800 // Assignment to a global variable. Use inline caching for the | 1800 // Assignment to a global variable. Use inline caching for the |
| 1801 // assignment. Right-hand-side value is passed in eax, variable name in | 1801 // assignment. Right-hand-side value is passed in eax, variable name in |
| 1802 // ecx, and the global object on the stack. | 1802 // ecx, and the global object on the stack. |
| 1803 __ mov(ecx, var->name()); | 1803 __ mov(ecx, var->name()); |
| 1804 __ mov(edx, GlobalObjectOperand()); | 1804 __ mov(edx, GlobalObjectOperand()); |
| 1805 Handle<Code> ic = is_strict_mode() | 1805 Handle<Code> ic = is_strict_mode() |
| 1806 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1806 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1807 : isolate()->builtins()->StoreIC_Initialize(); | 1807 : isolate()->builtins()->StoreIC_Initialize(); |
| 1808 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1808 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 1809 | 1809 |
| 1810 } else if (op == Token::INIT_CONST) { | 1810 } else if (op == Token::INIT_CONST) { |
| 1811 // Like var declarations, const declarations are hoisted to function | 1811 // Like var declarations, const declarations are hoisted to function |
| 1812 // scope. However, unlike var initializers, const initializers are able | 1812 // scope. However, unlike var initializers, const initializers are able |
| 1813 // to drill a hole to that function context, even from inside a 'with' | 1813 // to drill a hole to that function context, even from inside a 'with' |
| 1814 // context. We thus bypass the normal static scope lookup. | 1814 // context. We thus bypass the normal static scope lookup. |
| 1815 Slot* slot = var->AsSlot(); | 1815 Slot* slot = var->AsSlot(); |
| 1816 Label skip; | 1816 Label skip; |
| 1817 switch (slot->type()) { | 1817 switch (slot->type()) { |
| 1818 case Slot::PARAMETER: | 1818 case Slot::PARAMETER: |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1891 SetSourcePosition(expr->position()); | 1891 SetSourcePosition(expr->position()); |
| 1892 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1892 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1893 if (expr->ends_initialization_block()) { | 1893 if (expr->ends_initialization_block()) { |
| 1894 __ mov(edx, Operand(esp, 0)); | 1894 __ mov(edx, Operand(esp, 0)); |
| 1895 } else { | 1895 } else { |
| 1896 __ pop(edx); | 1896 __ pop(edx); |
| 1897 } | 1897 } |
| 1898 Handle<Code> ic = is_strict_mode() | 1898 Handle<Code> ic = is_strict_mode() |
| 1899 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1899 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1900 : isolate()->builtins()->StoreIC_Initialize(); | 1900 : isolate()->builtins()->StoreIC_Initialize(); |
| 1901 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 1901 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 1902 | 1902 |
| 1903 // If the assignment ends an initialization block, revert to fast case. | 1903 // If the assignment ends an initialization block, revert to fast case. |
| 1904 if (expr->ends_initialization_block()) { | 1904 if (expr->ends_initialization_block()) { |
| 1905 __ push(eax); // Result of assignment, saved even if not needed. | 1905 __ push(eax); // Result of assignment, saved even if not needed. |
| 1906 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1906 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
| 1907 __ CallRuntime(Runtime::kToFastProperties, 1); | 1907 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1908 __ pop(eax); | 1908 __ pop(eax); |
| 1909 __ Drop(1); | 1909 __ Drop(1); |
| 1910 } | 1910 } |
| 1911 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 1911 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1931 if (expr->ends_initialization_block()) { | 1931 if (expr->ends_initialization_block()) { |
| 1932 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 1932 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
| 1933 } else { | 1933 } else { |
| 1934 __ pop(edx); | 1934 __ pop(edx); |
| 1935 } | 1935 } |
| 1936 // Record source code position before IC call. | 1936 // Record source code position before IC call. |
| 1937 SetSourcePosition(expr->position()); | 1937 SetSourcePosition(expr->position()); |
| 1938 Handle<Code> ic = is_strict_mode() | 1938 Handle<Code> ic = is_strict_mode() |
| 1939 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1939 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 1940 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1940 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 1941 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 1941 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 1942 | 1942 |
| 1943 // If the assignment ends an initialization block, revert to fast case. | 1943 // If the assignment ends an initialization block, revert to fast case. |
| 1944 if (expr->ends_initialization_block()) { | 1944 if (expr->ends_initialization_block()) { |
| 1945 __ pop(edx); | 1945 __ pop(edx); |
| 1946 __ push(eax); // Result of assignment, saved even if not needed. | 1946 __ push(eax); // Result of assignment, saved even if not needed. |
| 1947 __ push(edx); | 1947 __ push(edx); |
| 1948 __ CallRuntime(Runtime::kToFastProperties, 1); | 1948 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1949 __ pop(eax); | 1949 __ pop(eax); |
| 1950 } | 1950 } |
| 1951 | 1951 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1982 for (int i = 0; i < arg_count; i++) { | 1982 for (int i = 0; i < arg_count; i++) { |
| 1983 VisitForStackValue(args->at(i)); | 1983 VisitForStackValue(args->at(i)); |
| 1984 } | 1984 } |
| 1985 __ Set(ecx, Immediate(name)); | 1985 __ Set(ecx, Immediate(name)); |
| 1986 } | 1986 } |
| 1987 // Record source position of the IC call. | 1987 // Record source position of the IC call. |
| 1988 SetSourcePosition(expr->position()); | 1988 SetSourcePosition(expr->position()); |
| 1989 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1989 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1990 Handle<Code> ic = | 1990 Handle<Code> ic = |
| 1991 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); | 1991 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); |
| 1992 EmitCallIC(ic, mode, expr->id()); | 1992 __ call(ic, mode, expr->id()); |
| 1993 RecordJSReturnSite(expr); | 1993 RecordJSReturnSite(expr); |
| 1994 // Restore context register. | 1994 // Restore context register. |
| 1995 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1995 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1996 context()->Plug(eax); | 1996 context()->Plug(eax); |
| 1997 } | 1997 } |
| 1998 | 1998 |
| 1999 | 1999 |
| 2000 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2000 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2001 Expression* key) { | 2001 Expression* key) { |
| 2002 // Load the key. | 2002 // Load the key. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2015 for (int i = 0; i < arg_count; i++) { | 2015 for (int i = 0; i < arg_count; i++) { |
| 2016 VisitForStackValue(args->at(i)); | 2016 VisitForStackValue(args->at(i)); |
| 2017 } | 2017 } |
| 2018 } | 2018 } |
| 2019 // Record source position of the IC call. | 2019 // Record source position of the IC call. |
| 2020 SetSourcePosition(expr->position()); | 2020 SetSourcePosition(expr->position()); |
| 2021 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2021 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2022 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( | 2022 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( |
| 2023 arg_count, in_loop); | 2023 arg_count, in_loop); |
| 2024 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2024 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
| 2025 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 2025 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 2026 RecordJSReturnSite(expr); | 2026 RecordJSReturnSite(expr); |
| 2027 // Restore context register. | 2027 // Restore context register. |
| 2028 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2028 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2029 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2029 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
| 2030 } | 2030 } |
| 2031 | 2031 |
| 2032 | 2032 |
| 2033 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2033 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2034 // Code common for calls using the call stub. | 2034 // Code common for calls using the call stub. |
| 2035 ZoneList<Expression*>* args = expr->arguments(); | 2035 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 Literal* key = prop->key()->AsLiteral(); | 2191 Literal* key = prop->key()->AsLiteral(); |
| 2192 if (key != NULL && key->handle()->IsSymbol()) { | 2192 if (key != NULL && key->handle()->IsSymbol()) { |
| 2193 // Call to a named property, use call IC. | 2193 // Call to a named property, use call IC. |
| 2194 { PreservePositionScope scope(masm()->positions_recorder()); | 2194 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2195 VisitForStackValue(prop->obj()); | 2195 VisitForStackValue(prop->obj()); |
| 2196 } | 2196 } |
| 2197 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2197 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2198 } else { | 2198 } else { |
| 2199 // Call to a keyed property. | 2199 // Call to a keyed property. |
| 2200 // For a synthetic property use keyed load IC followed by function call, | 2200 // For a synthetic property use keyed load IC followed by function call, |
| 2201 // for a regular property use keyed EmitCallIC. | 2201 // for a regular property use EmitKeyedCallWithIC. |
| 2202 if (prop->is_synthetic()) { | 2202 if (prop->is_synthetic()) { |
| 2203 // Do not visit the object and key subexpressions (they are shared | 2203 // Do not visit the object and key subexpressions (they are shared |
| 2204 // by all occurrences of the same rewritten parameter). | 2204 // by all occurrences of the same rewritten parameter). |
| 2205 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 2205 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 2206 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); | 2206 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); |
| 2207 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); | 2207 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); |
| 2208 MemOperand operand = EmitSlotSearch(slot, edx); | 2208 MemOperand operand = EmitSlotSearch(slot, edx); |
| 2209 __ mov(edx, operand); | 2209 __ mov(edx, operand); |
| 2210 | 2210 |
| 2211 ASSERT(prop->key()->AsLiteral() != NULL); | 2211 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2212 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2212 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
| 2213 __ mov(eax, prop->key()->AsLiteral()->handle()); | 2213 __ mov(eax, prop->key()->AsLiteral()->handle()); |
| 2214 | 2214 |
| 2215 // Record source code position for IC call. | 2215 // Record source code position for IC call. |
| 2216 SetSourcePosition(prop->position()); | 2216 SetSourcePosition(prop->position()); |
| 2217 | 2217 |
| 2218 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2218 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2219 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 2219 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 2220 // Push result (function). | 2220 // Push result (function). |
| 2221 __ push(eax); | 2221 __ push(eax); |
| 2222 // Push Global receiver. | 2222 // Push Global receiver. |
| 2223 __ mov(ecx, GlobalObjectOperand()); | 2223 __ mov(ecx, GlobalObjectOperand()); |
| 2224 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 2224 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
| 2225 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2225 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2226 } else { | 2226 } else { |
| 2227 { PreservePositionScope scope(masm()->positions_recorder()); | 2227 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2228 VisitForStackValue(prop->obj()); | 2228 VisitForStackValue(prop->obj()); |
| 2229 } | 2229 } |
| (...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3555 VisitForStackValue(args->at(i)); | 3555 VisitForStackValue(args->at(i)); |
| 3556 } | 3556 } |
| 3557 | 3557 |
| 3558 if (expr->is_jsruntime()) { | 3558 if (expr->is_jsruntime()) { |
| 3559 // Call the JS runtime function via a call IC. | 3559 // Call the JS runtime function via a call IC. |
| 3560 __ Set(ecx, Immediate(expr->name())); | 3560 __ Set(ecx, Immediate(expr->name())); |
| 3561 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 3561 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 3562 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3562 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
| 3563 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( | 3563 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( |
| 3564 arg_count, in_loop, mode); | 3564 arg_count, in_loop, mode); |
| 3565 EmitCallIC(ic, mode, expr->id()); | 3565 __ call(ic, mode, expr->id()); |
| 3566 // Restore context register. | 3566 // Restore context register. |
| 3567 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3567 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3568 } else { | 3568 } else { |
| 3569 // Call the C runtime function. | 3569 // Call the C runtime function. |
| 3570 __ CallRuntime(expr->function(), arg_count); | 3570 __ CallRuntime(expr->function(), arg_count); |
| 3571 } | 3571 } |
| 3572 context()->Plug(eax); | 3572 context()->Plug(eax); |
| 3573 } | 3573 } |
| 3574 | 3574 |
| 3575 | 3575 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3694 // TODO(svenpanne): Allowing format strings in Comment would be nice here... | 3694 // TODO(svenpanne): Allowing format strings in Comment would be nice here... |
| 3695 Comment cmt(masm_, comment); | 3695 Comment cmt(masm_, comment); |
| 3696 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); | 3696 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
| 3697 UnaryOverwriteMode overwrite = | 3697 UnaryOverwriteMode overwrite = |
| 3698 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 3698 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
| 3699 UnaryOpStub stub(expr->op(), overwrite); | 3699 UnaryOpStub stub(expr->op(), overwrite); |
| 3700 // UnaryOpStub expects the argument to be in the | 3700 // UnaryOpStub expects the argument to be in the |
| 3701 // accumulator register eax. | 3701 // accumulator register eax. |
| 3702 VisitForAccumulatorValue(expr->expression()); | 3702 VisitForAccumulatorValue(expr->expression()); |
| 3703 SetSourcePosition(expr->position()); | 3703 SetSourcePosition(expr->position()); |
| 3704 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 3704 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 3705 context()->Plug(eax); | 3705 context()->Plug(eax); |
| 3706 } | 3706 } |
| 3707 | 3707 |
| 3708 | 3708 |
| 3709 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 3709 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 3710 Comment cmnt(masm_, "[ CountOperation"); | 3710 Comment cmnt(masm_, "[ CountOperation"); |
| 3711 SetSourcePosition(expr->position()); | 3711 SetSourcePosition(expr->position()); |
| 3712 | 3712 |
| 3713 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 3713 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
| 3714 // as the left-hand side. | 3714 // as the left-hand side. |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3814 } | 3814 } |
| 3815 } | 3815 } |
| 3816 | 3816 |
| 3817 // Record position before stub call. | 3817 // Record position before stub call. |
| 3818 SetSourcePosition(expr->position()); | 3818 SetSourcePosition(expr->position()); |
| 3819 | 3819 |
| 3820 // Call stub for +1/-1. | 3820 // Call stub for +1/-1. |
| 3821 __ mov(edx, eax); | 3821 __ mov(edx, eax); |
| 3822 __ mov(eax, Immediate(Smi::FromInt(1))); | 3822 __ mov(eax, Immediate(Smi::FromInt(1))); |
| 3823 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); | 3823 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); |
| 3824 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); | 3824 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); |
| 3825 patch_site.EmitPatchInfo(); | 3825 patch_site.EmitPatchInfo(); |
| 3826 __ bind(&done); | 3826 __ bind(&done); |
| 3827 | 3827 |
| 3828 // Store the value returned in eax. | 3828 // Store the value returned in eax. |
| 3829 switch (assign_type) { | 3829 switch (assign_type) { |
| 3830 case VARIABLE: | 3830 case VARIABLE: |
| 3831 if (expr->is_postfix()) { | 3831 if (expr->is_postfix()) { |
| 3832 // Perform the assignment as if via '='. | 3832 // Perform the assignment as if via '='. |
| 3833 { EffectContext context(this); | 3833 { EffectContext context(this); |
| 3834 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3834 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3848 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3848 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3849 context()->Plug(eax); | 3849 context()->Plug(eax); |
| 3850 } | 3850 } |
| 3851 break; | 3851 break; |
| 3852 case NAMED_PROPERTY: { | 3852 case NAMED_PROPERTY: { |
| 3853 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3853 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 3854 __ pop(edx); | 3854 __ pop(edx); |
| 3855 Handle<Code> ic = is_strict_mode() | 3855 Handle<Code> ic = is_strict_mode() |
| 3856 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3856 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 3857 : isolate()->builtins()->StoreIC_Initialize(); | 3857 : isolate()->builtins()->StoreIC_Initialize(); |
| 3858 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 3858 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3859 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3859 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3860 if (expr->is_postfix()) { | 3860 if (expr->is_postfix()) { |
| 3861 if (!context()->IsEffect()) { | 3861 if (!context()->IsEffect()) { |
| 3862 context()->PlugTOS(); | 3862 context()->PlugTOS(); |
| 3863 } | 3863 } |
| 3864 } else { | 3864 } else { |
| 3865 context()->Plug(eax); | 3865 context()->Plug(eax); |
| 3866 } | 3866 } |
| 3867 break; | 3867 break; |
| 3868 } | 3868 } |
| 3869 case KEYED_PROPERTY: { | 3869 case KEYED_PROPERTY: { |
| 3870 __ pop(ecx); | 3870 __ pop(ecx); |
| 3871 __ pop(edx); | 3871 __ pop(edx); |
| 3872 Handle<Code> ic = is_strict_mode() | 3872 Handle<Code> ic = is_strict_mode() |
| 3873 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3873 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3874 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3874 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3875 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 3875 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3876 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3876 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3877 if (expr->is_postfix()) { | 3877 if (expr->is_postfix()) { |
| 3878 // Result is on the stack | 3878 // Result is on the stack |
| 3879 if (!context()->IsEffect()) { | 3879 if (!context()->IsEffect()) { |
| 3880 context()->PlugTOS(); | 3880 context()->PlugTOS(); |
| 3881 } | 3881 } |
| 3882 } else { | 3882 } else { |
| 3883 context()->Plug(eax); | 3883 context()->Plug(eax); |
| 3884 } | 3884 } |
| 3885 break; | 3885 break; |
| 3886 } | 3886 } |
| 3887 } | 3887 } |
| 3888 } | 3888 } |
| 3889 | 3889 |
| 3890 | 3890 |
| 3891 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 3891 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 3892 VariableProxy* proxy = expr->AsVariableProxy(); | 3892 VariableProxy* proxy = expr->AsVariableProxy(); |
| 3893 ASSERT(!context()->IsEffect()); | 3893 ASSERT(!context()->IsEffect()); |
| 3894 ASSERT(!context()->IsTest()); | 3894 ASSERT(!context()->IsTest()); |
| 3895 | 3895 |
| 3896 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3896 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
| 3897 Comment cmnt(masm_, "Global variable"); | 3897 Comment cmnt(masm_, "Global variable"); |
| 3898 __ mov(eax, GlobalObjectOperand()); | 3898 __ mov(eax, GlobalObjectOperand()); |
| 3899 __ mov(ecx, Immediate(proxy->name())); | 3899 __ mov(ecx, Immediate(proxy->name())); |
| 3900 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3900 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 3901 // Use a regular load, not a contextual load, to avoid a reference | 3901 // Use a regular load, not a contextual load, to avoid a reference |
| 3902 // error. | 3902 // error. |
| 3903 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 3903 __ call(ic); |
| 3904 PrepareForBailout(expr, TOS_REG); | 3904 PrepareForBailout(expr, TOS_REG); |
| 3905 context()->Plug(eax); | 3905 context()->Plug(eax); |
| 3906 } else if (proxy != NULL && | 3906 } else if (proxy != NULL && |
| 3907 proxy->var()->AsSlot() != NULL && | 3907 proxy->var()->AsSlot() != NULL && |
| 3908 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { | 3908 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
| 3909 Label done, slow; | 3909 Label done, slow; |
| 3910 | 3910 |
| 3911 // Generate code for loading from variables potentially shadowed | 3911 // Generate code for loading from variables potentially shadowed |
| 3912 // by eval-introduced variables. | 3912 // by eval-introduced variables. |
| 3913 Slot* slot = proxy->var()->AsSlot(); | 3913 Slot* slot = proxy->var()->AsSlot(); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4088 __ or_(ecx, Operand(eax)); | 4088 __ or_(ecx, Operand(eax)); |
| 4089 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); | 4089 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
| 4090 __ cmp(edx, Operand(eax)); | 4090 __ cmp(edx, Operand(eax)); |
| 4091 Split(cc, if_true, if_false, NULL); | 4091 Split(cc, if_true, if_false, NULL); |
| 4092 __ bind(&slow_case); | 4092 __ bind(&slow_case); |
| 4093 } | 4093 } |
| 4094 | 4094 |
| 4095 // Record position and call the compare IC. | 4095 // Record position and call the compare IC. |
| 4096 SetSourcePosition(expr->position()); | 4096 SetSourcePosition(expr->position()); |
| 4097 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4097 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 4098 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 4098 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 4099 patch_site.EmitPatchInfo(); | 4099 patch_site.EmitPatchInfo(); |
| 4100 | 4100 |
| 4101 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4101 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 4102 __ test(eax, Operand(eax)); | 4102 __ test(eax, Operand(eax)); |
| 4103 Split(cc, if_true, if_false, fall_through); | 4103 Split(cc, if_true, if_false, fall_through); |
| 4104 } | 4104 } |
| 4105 } | 4105 } |
| 4106 | 4106 |
| 4107 // Convert the result of the comparison into one expected for this | 4107 // Convert the result of the comparison into one expected for this |
| 4108 // expression's context. | 4108 // expression's context. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4148 Register FullCodeGenerator::result_register() { | 4148 Register FullCodeGenerator::result_register() { |
| 4149 return eax; | 4149 return eax; |
| 4150 } | 4150 } |
| 4151 | 4151 |
| 4152 | 4152 |
| 4153 Register FullCodeGenerator::context_register() { | 4153 Register FullCodeGenerator::context_register() { |
| 4154 return esi; | 4154 return esi; |
| 4155 } | 4155 } |
| 4156 | 4156 |
| 4157 | 4157 |
| 4158 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | |
| 4159 RelocInfo::Mode mode, | |
| 4160 unsigned ast_id) { | |
| 4161 ASSERT(mode == RelocInfo::CODE_TARGET || | |
| 4162 mode == RelocInfo::CODE_TARGET_CONTEXT); | |
| 4163 __ call(ic, mode, ast_id); | |
| 4164 } | |
| 4165 | |
| 4166 | |
| 4167 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4158 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| 4168 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4159 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| 4169 __ mov(Operand(ebp, frame_offset), value); | 4160 __ mov(Operand(ebp, frame_offset), value); |
| 4170 } | 4161 } |
| 4171 | 4162 |
| 4172 | 4163 |
| 4173 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4164 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
| 4174 __ mov(dst, ContextOperand(esi, context_index)); | 4165 __ mov(dst, ContextOperand(esi, context_index)); |
| 4175 } | 4166 } |
| 4176 | 4167 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4223 // And return. | 4214 // And return. |
| 4224 __ ret(0); | 4215 __ ret(0); |
| 4225 } | 4216 } |
| 4226 | 4217 |
| 4227 | 4218 |
| 4228 #undef __ | 4219 #undef __ |
| 4229 | 4220 |
| 4230 } } // namespace v8::internal | 4221 } } // namespace v8::internal |
| 4231 | 4222 |
| 4232 #endif // V8_TARGET_ARCH_IA32 | 4223 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |