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 26 matching lines...) Expand all Loading... |
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 #define __ ACCESS_MASM(masm_) | 44 #define __ ACCESS_MASM(masm_) |
45 | 45 |
46 | 46 |
47 static unsigned GetPropertyId(Property* property) { | |
48 if (property->is_synthetic()) return AstNode::kNoNumber; | |
49 return property->id(); | |
50 } | |
51 | |
52 | |
53 class JumpPatchSite BASE_EMBEDDED { | 47 class JumpPatchSite BASE_EMBEDDED { |
54 public: | 48 public: |
55 explicit JumpPatchSite(MacroAssembler* masm) | 49 explicit JumpPatchSite(MacroAssembler* masm) |
56 : masm_(masm) { | 50 : masm_(masm) { |
57 #ifdef DEBUG | 51 #ifdef DEBUG |
58 info_emitted_ = false; | 52 info_emitted_ = false; |
59 #endif | 53 #endif |
60 } | 54 } |
61 | 55 |
62 ~JumpPatchSite() { | 56 ~JumpPatchSite() { |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 __ movq(rdx, rax); | 736 __ movq(rdx, rax); |
743 __ LoadRoot(rax, Heap::kTheHoleValueRootIndex); | 737 __ LoadRoot(rax, Heap::kTheHoleValueRootIndex); |
744 } | 738 } |
745 ASSERT(prop->key()->AsLiteral() != NULL && | 739 ASSERT(prop->key()->AsLiteral() != NULL && |
746 prop->key()->AsLiteral()->handle()->IsSmi()); | 740 prop->key()->AsLiteral()->handle()->IsSmi()); |
747 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 741 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
748 | 742 |
749 Handle<Code> ic = is_strict_mode() | 743 Handle<Code> ic = is_strict_mode() |
750 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 744 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
751 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 745 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
752 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 746 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
753 } | 747 } |
754 } | 748 } |
755 } | 749 } |
756 | 750 |
757 | 751 |
758 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 752 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
759 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 753 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
760 } | 754 } |
761 | 755 |
762 | 756 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 __ cmpq(rdx, rax); | 809 __ cmpq(rdx, rax); |
816 __ j(not_equal, &next_test); | 810 __ j(not_equal, &next_test); |
817 __ Drop(1); // Switch value is no longer needed. | 811 __ Drop(1); // Switch value is no longer needed. |
818 __ jmp(clause->body_target()); | 812 __ jmp(clause->body_target()); |
819 __ bind(&slow_case); | 813 __ bind(&slow_case); |
820 } | 814 } |
821 | 815 |
822 // Record position before stub call for type feedback. | 816 // Record position before stub call for type feedback. |
823 SetSourcePosition(clause->position()); | 817 SetSourcePosition(clause->position()); |
824 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 818 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
825 EmitCallIC(ic, &patch_site, clause->label()->id()); | 819 EmitCallIC(ic, &patch_site); |
826 | 820 |
827 __ testq(rax, rax); | 821 __ testq(rax, rax); |
828 __ j(not_equal, &next_test); | 822 __ j(not_equal, &next_test); |
829 __ Drop(1); // Switch value is no longer needed. | 823 __ Drop(1); // Switch value is no longer needed. |
830 __ jmp(clause->body_target()); | 824 __ jmp(clause->body_target()); |
831 } | 825 } |
832 | 826 |
833 // Discard the test value and jump to the default if present, otherwise to | 827 // Discard the test value and jump to the default if present, otherwise to |
834 // the end of the statement. | 828 // the end of the statement. |
835 __ bind(&next_test); | 829 __ bind(&next_test); |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 } | 1118 } |
1125 | 1119 |
1126 // All extension objects were empty and it is safe to use a global | 1120 // All extension objects were empty and it is safe to use a global |
1127 // load IC call. | 1121 // load IC call. |
1128 __ movq(rax, GlobalObjectOperand()); | 1122 __ movq(rax, GlobalObjectOperand()); |
1129 __ Move(rcx, slot->var()->name()); | 1123 __ Move(rcx, slot->var()->name()); |
1130 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1124 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1131 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1125 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
1132 ? RelocInfo::CODE_TARGET | 1126 ? RelocInfo::CODE_TARGET |
1133 : RelocInfo::CODE_TARGET_CONTEXT; | 1127 : RelocInfo::CODE_TARGET_CONTEXT; |
1134 EmitCallIC(ic, mode, AstNode::kNoNumber); | 1128 EmitCallIC(ic, mode); |
1135 } | 1129 } |
1136 | 1130 |
1137 | 1131 |
1138 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 1132 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
1139 Slot* slot, | 1133 Slot* slot, |
1140 Label* slow) { | 1134 Label* slow) { |
1141 ASSERT(slot->type() == Slot::CONTEXT); | 1135 ASSERT(slot->type() == Slot::CONTEXT); |
1142 Register context = rsi; | 1136 Register context = rsi; |
1143 Register temp = rbx; | 1137 Register temp = rbx; |
1144 | 1138 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 key_literal->handle()->IsSmi()) { | 1199 key_literal->handle()->IsSmi()) { |
1206 // Load arguments object if there are no eval-introduced | 1200 // Load arguments object if there are no eval-introduced |
1207 // variables. Then load the argument from the arguments | 1201 // variables. Then load the argument from the arguments |
1208 // object using keyed load. | 1202 // object using keyed load. |
1209 __ movq(rdx, | 1203 __ movq(rdx, |
1210 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1204 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
1211 slow)); | 1205 slow)); |
1212 __ Move(rax, key_literal->handle()); | 1206 __ Move(rax, key_literal->handle()); |
1213 Handle<Code> ic = | 1207 Handle<Code> ic = |
1214 isolate()->builtins()->KeyedLoadIC_Initialize(); | 1208 isolate()->builtins()->KeyedLoadIC_Initialize(); |
1215 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); | 1209 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1216 __ jmp(done); | 1210 __ jmp(done); |
1217 } | 1211 } |
1218 } | 1212 } |
1219 } | 1213 } |
1220 } | 1214 } |
1221 } | 1215 } |
1222 | 1216 |
1223 | 1217 |
1224 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1218 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
1225 // Four cases: non-this global variables, lookup slots, all other | 1219 // Four cases: non-this global variables, lookup slots, all other |
1226 // types of slots, and parameters that rewrite to explicit property | 1220 // types of slots, and parameters that rewrite to explicit property |
1227 // accesses on the arguments object. | 1221 // accesses on the arguments object. |
1228 Slot* slot = var->AsSlot(); | 1222 Slot* slot = var->AsSlot(); |
1229 Property* property = var->AsProperty(); | 1223 Property* property = var->AsProperty(); |
1230 | 1224 |
1231 if (var->is_global() && !var->is_this()) { | 1225 if (var->is_global() && !var->is_this()) { |
1232 Comment cmnt(masm_, "Global variable"); | 1226 Comment cmnt(masm_, "Global variable"); |
1233 // Use inline caching. Variable name is passed in rcx and the global | 1227 // Use inline caching. Variable name is passed in rcx and the global |
1234 // object on the stack. | 1228 // object on the stack. |
1235 __ Move(rcx, var->name()); | 1229 __ Move(rcx, var->name()); |
1236 __ movq(rax, GlobalObjectOperand()); | 1230 __ movq(rax, GlobalObjectOperand()); |
1237 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1231 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1238 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1232 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1239 context()->Plug(rax); | 1233 context()->Plug(rax); |
1240 | 1234 |
1241 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1235 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
1242 Label done, slow; | 1236 Label done, slow; |
1243 | 1237 |
1244 // Generate code for loading from variables potentially shadowed | 1238 // Generate code for loading from variables potentially shadowed |
1245 // by eval-introduced variables. | 1239 // by eval-introduced variables. |
1246 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1240 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
1247 | 1241 |
1248 __ bind(&slow); | 1242 __ bind(&slow); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1291 // Assert that the key is a smi. | 1285 // Assert that the key is a smi. |
1292 Literal* key_literal = property->key()->AsLiteral(); | 1286 Literal* key_literal = property->key()->AsLiteral(); |
1293 ASSERT_NOT_NULL(key_literal); | 1287 ASSERT_NOT_NULL(key_literal); |
1294 ASSERT(key_literal->handle()->IsSmi()); | 1288 ASSERT(key_literal->handle()->IsSmi()); |
1295 | 1289 |
1296 // Load the key. | 1290 // Load the key. |
1297 __ Move(rax, key_literal->handle()); | 1291 __ Move(rax, key_literal->handle()); |
1298 | 1292 |
1299 // Do a keyed property load. | 1293 // Do a keyed property load. |
1300 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1294 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1301 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); | 1295 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1302 context()->Plug(rax); | 1296 context()->Plug(rax); |
1303 } | 1297 } |
1304 } | 1298 } |
1305 | 1299 |
1306 | 1300 |
1307 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1301 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1308 Comment cmnt(masm_, "[ RegExpLiteral"); | 1302 Comment cmnt(masm_, "[ RegExpLiteral"); |
1309 Label materialized; | 1303 Label materialized; |
1310 // Registers will be used as follows: | 1304 // Registers will be used as follows: |
1311 // rdi = JS function. | 1305 // rdi = JS function. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1396 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1403 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1397 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
1404 // Fall through. | 1398 // Fall through. |
1405 case ObjectLiteral::Property::COMPUTED: | 1399 case ObjectLiteral::Property::COMPUTED: |
1406 if (key->handle()->IsSymbol()) { | 1400 if (key->handle()->IsSymbol()) { |
1407 VisitForAccumulatorValue(value); | 1401 VisitForAccumulatorValue(value); |
1408 __ Move(rcx, key->handle()); | 1402 __ Move(rcx, key->handle()); |
1409 __ movq(rdx, Operand(rsp, 0)); | 1403 __ movq(rdx, Operand(rsp, 0)); |
1410 if (property->emit_store()) { | 1404 if (property->emit_store()) { |
1411 Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize(); | 1405 Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize(); |
1412 EmitCallIC(ic, RelocInfo::CODE_TARGET, key->id()); | 1406 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1413 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1407 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1414 } | 1408 } |
1415 break; | 1409 break; |
1416 } | 1410 } |
1417 // Fall through. | 1411 // Fall through. |
1418 case ObjectLiteral::Property::PROTOTYPE: | 1412 case ObjectLiteral::Property::PROTOTYPE: |
1419 __ push(Operand(rsp, 0)); // Duplicate receiver. | 1413 __ push(Operand(rsp, 0)); // Duplicate receiver. |
1420 VisitForStackValue(key); | 1414 VisitForStackValue(key); |
1421 VisitForStackValue(value); | 1415 VisitForStackValue(value); |
1422 if (property->emit_store()) { | 1416 if (property->emit_store()) { |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 Token::Value op = expr->binary_op(); | 1599 Token::Value op = expr->binary_op(); |
1606 __ push(rax); // Left operand goes on the stack. | 1600 __ push(rax); // Left operand goes on the stack. |
1607 VisitForAccumulatorValue(expr->value()); | 1601 VisitForAccumulatorValue(expr->value()); |
1608 | 1602 |
1609 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1603 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
1610 ? OVERWRITE_RIGHT | 1604 ? OVERWRITE_RIGHT |
1611 : NO_OVERWRITE; | 1605 : NO_OVERWRITE; |
1612 SetSourcePosition(expr->position() + 1); | 1606 SetSourcePosition(expr->position() + 1); |
1613 AccumulatorValueContext context(this); | 1607 AccumulatorValueContext context(this); |
1614 if (ShouldInlineSmiCase(op)) { | 1608 if (ShouldInlineSmiCase(op)) { |
1615 EmitInlineSmiBinaryOp(expr->binary_operation(), | 1609 EmitInlineSmiBinaryOp(expr, |
1616 op, | 1610 op, |
1617 mode, | 1611 mode, |
1618 expr->target(), | 1612 expr->target(), |
1619 expr->value()); | 1613 expr->value()); |
1620 } else { | 1614 } else { |
1621 EmitBinaryOp(expr->binary_operation(), op, mode); | 1615 EmitBinaryOp(op, mode); |
1622 } | 1616 } |
1623 // Deoptimization point in case the binary operation may have side effects. | 1617 // Deoptimization point in case the binary operation may have side effects. |
1624 PrepareForBailout(expr->binary_operation(), TOS_REG); | 1618 PrepareForBailout(expr->binary_operation(), TOS_REG); |
1625 } else { | 1619 } else { |
1626 VisitForAccumulatorValue(expr->value()); | 1620 VisitForAccumulatorValue(expr->value()); |
1627 } | 1621 } |
1628 | 1622 |
1629 // Record source position before possible IC call. | 1623 // Record source position before possible IC call. |
1630 SetSourcePosition(expr->position()); | 1624 SetSourcePosition(expr->position()); |
1631 | 1625 |
(...skipping 13 matching lines...) Expand all Loading... |
1645 break; | 1639 break; |
1646 } | 1640 } |
1647 } | 1641 } |
1648 | 1642 |
1649 | 1643 |
1650 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1644 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1651 SetSourcePosition(prop->position()); | 1645 SetSourcePosition(prop->position()); |
1652 Literal* key = prop->key()->AsLiteral(); | 1646 Literal* key = prop->key()->AsLiteral(); |
1653 __ Move(rcx, key->handle()); | 1647 __ Move(rcx, key->handle()); |
1654 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1648 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1655 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 1649 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1656 } | 1650 } |
1657 | 1651 |
1658 | 1652 |
1659 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1653 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1660 SetSourcePosition(prop->position()); | 1654 SetSourcePosition(prop->position()); |
1661 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1655 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1662 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 1656 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1663 } | 1657 } |
1664 | 1658 |
1665 | 1659 |
1666 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1660 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
1667 Token::Value op, | 1661 Token::Value op, |
1668 OverwriteMode mode, | 1662 OverwriteMode mode, |
1669 Expression* left, | 1663 Expression* left, |
1670 Expression* right) { | 1664 Expression* right) { |
1671 // Do combined smi check of the operands. Left operand is on the | 1665 // Do combined smi check of the operands. Left operand is on the |
1672 // stack (popped into rdx). Right operand is in rax but moved into | 1666 // stack (popped into rdx). Right operand is in rax but moved into |
1673 // rcx to make the shifts easier. | 1667 // rcx to make the shifts easier. |
1674 NearLabel done, stub_call, smi_case; | 1668 NearLabel done, stub_call, smi_case; |
1675 __ pop(rdx); | 1669 __ pop(rdx); |
1676 __ movq(rcx, rax); | 1670 __ movq(rcx, rax); |
1677 __ or_(rax, rdx); | 1671 __ or_(rax, rdx); |
1678 JumpPatchSite patch_site(masm_); | 1672 JumpPatchSite patch_site(masm_); |
1679 patch_site.EmitJumpIfSmi(rax, &smi_case); | 1673 patch_site.EmitJumpIfSmi(rax, &smi_case); |
1680 | 1674 |
1681 __ bind(&stub_call); | 1675 __ bind(&stub_call); |
1682 __ movq(rax, rcx); | 1676 __ movq(rax, rcx); |
1683 TypeRecordingBinaryOpStub stub(op, mode); | 1677 TypeRecordingBinaryOpStub stub(op, mode); |
1684 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); | 1678 EmitCallIC(stub.GetCode(), &patch_site); |
1685 __ jmp(&done); | 1679 __ jmp(&done); |
1686 | 1680 |
1687 __ bind(&smi_case); | 1681 __ bind(&smi_case); |
1688 switch (op) { | 1682 switch (op) { |
1689 case Token::SAR: | 1683 case Token::SAR: |
1690 __ SmiShiftArithmeticRight(rax, rdx, rcx); | 1684 __ SmiShiftArithmeticRight(rax, rdx, rcx); |
1691 break; | 1685 break; |
1692 case Token::SHL: | 1686 case Token::SHL: |
1693 __ SmiShiftLeft(rax, rdx, rcx); | 1687 __ SmiShiftLeft(rax, rdx, rcx); |
1694 break; | 1688 break; |
(...skipping 21 matching lines...) Expand all Loading... |
1716 default: | 1710 default: |
1717 UNREACHABLE(); | 1711 UNREACHABLE(); |
1718 break; | 1712 break; |
1719 } | 1713 } |
1720 | 1714 |
1721 __ bind(&done); | 1715 __ bind(&done); |
1722 context()->Plug(rax); | 1716 context()->Plug(rax); |
1723 } | 1717 } |
1724 | 1718 |
1725 | 1719 |
1726 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1720 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1727 Token::Value op, | |
1728 OverwriteMode mode) { | 1721 OverwriteMode mode) { |
1729 __ pop(rdx); | 1722 __ pop(rdx); |
1730 TypeRecordingBinaryOpStub stub(op, mode); | 1723 TypeRecordingBinaryOpStub stub(op, mode); |
1731 // NULL signals no inlined smi code. | 1724 EmitCallIC(stub.GetCode(), NULL); // NULL signals no inlined smi code. |
1732 EmitCallIC(stub.GetCode(), NULL, expr->id()); | |
1733 context()->Plug(rax); | 1725 context()->Plug(rax); |
1734 } | 1726 } |
1735 | 1727 |
1736 | 1728 |
1737 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1729 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1738 // Invalid left-hand sides are rewritten to have a 'throw | 1730 // Invalid left-hand sides are rewritten to have a 'throw |
1739 // ReferenceError' on the left-hand side. | 1731 // ReferenceError' on the left-hand side. |
1740 if (!expr->IsValidLeftHandSide()) { | 1732 if (!expr->IsValidLeftHandSide()) { |
1741 VisitForEffect(expr); | 1733 VisitForEffect(expr); |
1742 return; | 1734 return; |
(...skipping 19 matching lines...) Expand all Loading... |
1762 } | 1754 } |
1763 case NAMED_PROPERTY: { | 1755 case NAMED_PROPERTY: { |
1764 __ push(rax); // Preserve value. | 1756 __ push(rax); // Preserve value. |
1765 VisitForAccumulatorValue(prop->obj()); | 1757 VisitForAccumulatorValue(prop->obj()); |
1766 __ movq(rdx, rax); | 1758 __ movq(rdx, rax); |
1767 __ pop(rax); // Restore value. | 1759 __ pop(rax); // Restore value. |
1768 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1760 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1769 Handle<Code> ic = is_strict_mode() | 1761 Handle<Code> ic = is_strict_mode() |
1770 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1762 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1771 : isolate()->builtins()->StoreIC_Initialize(); | 1763 : isolate()->builtins()->StoreIC_Initialize(); |
1772 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1764 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1773 break; | 1765 break; |
1774 } | 1766 } |
1775 case KEYED_PROPERTY: { | 1767 case KEYED_PROPERTY: { |
1776 __ push(rax); // Preserve value. | 1768 __ push(rax); // Preserve value. |
1777 if (prop->is_synthetic()) { | 1769 if (prop->is_synthetic()) { |
1778 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1770 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
1779 ASSERT(prop->key()->AsLiteral() != NULL); | 1771 ASSERT(prop->key()->AsLiteral() != NULL); |
1780 { AccumulatorValueContext for_object(this); | 1772 { AccumulatorValueContext for_object(this); |
1781 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 1773 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
1782 } | 1774 } |
1783 __ movq(rdx, rax); | 1775 __ movq(rdx, rax); |
1784 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1776 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1785 } else { | 1777 } else { |
1786 VisitForStackValue(prop->obj()); | 1778 VisitForStackValue(prop->obj()); |
1787 VisitForAccumulatorValue(prop->key()); | 1779 VisitForAccumulatorValue(prop->key()); |
1788 __ movq(rcx, rax); | 1780 __ movq(rcx, rax); |
1789 __ pop(rdx); | 1781 __ pop(rdx); |
1790 } | 1782 } |
1791 __ pop(rax); // Restore value. | 1783 __ pop(rax); // Restore value. |
1792 Handle<Code> ic = is_strict_mode() | 1784 Handle<Code> ic = is_strict_mode() |
1793 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1785 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
1794 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1786 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
1795 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1787 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1796 break; | 1788 break; |
1797 } | 1789 } |
1798 } | 1790 } |
1799 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1791 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1800 context()->Plug(rax); | 1792 context()->Plug(rax); |
1801 } | 1793 } |
1802 | 1794 |
1803 | 1795 |
1804 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1796 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1805 Token::Value op) { | 1797 Token::Value op) { |
1806 // Left-hand sides that rewrite to explicit property accesses do not reach | 1798 // Left-hand sides that rewrite to explicit property accesses do not reach |
1807 // here. | 1799 // here. |
1808 ASSERT(var != NULL); | 1800 ASSERT(var != NULL); |
1809 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1801 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1810 | 1802 |
1811 if (var->is_global()) { | 1803 if (var->is_global()) { |
1812 ASSERT(!var->is_this()); | 1804 ASSERT(!var->is_this()); |
1813 // Assignment to a global variable. Use inline caching for the | 1805 // Assignment to a global variable. Use inline caching for the |
1814 // assignment. Right-hand-side value is passed in rax, variable name in | 1806 // assignment. Right-hand-side value is passed in rax, variable name in |
1815 // rcx, and the global object on the stack. | 1807 // rcx, and the global object on the stack. |
1816 __ Move(rcx, var->name()); | 1808 __ Move(rcx, var->name()); |
1817 __ movq(rdx, GlobalObjectOperand()); | 1809 __ movq(rdx, GlobalObjectOperand()); |
1818 Handle<Code> ic = is_strict_mode() | 1810 Handle<Code> ic = is_strict_mode() |
1819 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1811 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1820 : isolate()->builtins()->StoreIC_Initialize(); | 1812 : isolate()->builtins()->StoreIC_Initialize(); |
1821 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1813 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1822 | 1814 |
1823 } else if (op == Token::INIT_CONST) { | 1815 } else if (op == Token::INIT_CONST) { |
1824 // Like var declarations, const declarations are hoisted to function | 1816 // Like var declarations, const declarations are hoisted to function |
1825 // scope. However, unlike var initializers, const initializers are able | 1817 // scope. However, unlike var initializers, const initializers are able |
1826 // to drill a hole to that function context, even from inside a 'with' | 1818 // to drill a hole to that function context, even from inside a 'with' |
1827 // context. We thus bypass the normal static scope lookup. | 1819 // context. We thus bypass the normal static scope lookup. |
1828 Slot* slot = var->AsSlot(); | 1820 Slot* slot = var->AsSlot(); |
1829 Label skip; | 1821 Label skip; |
1830 switch (slot->type()) { | 1822 switch (slot->type()) { |
1831 case Slot::PARAMETER: | 1823 case Slot::PARAMETER: |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1914 SetSourcePosition(expr->position()); | 1906 SetSourcePosition(expr->position()); |
1915 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1907 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1916 if (expr->ends_initialization_block()) { | 1908 if (expr->ends_initialization_block()) { |
1917 __ movq(rdx, Operand(rsp, 0)); | 1909 __ movq(rdx, Operand(rsp, 0)); |
1918 } else { | 1910 } else { |
1919 __ pop(rdx); | 1911 __ pop(rdx); |
1920 } | 1912 } |
1921 Handle<Code> ic = is_strict_mode() | 1913 Handle<Code> ic = is_strict_mode() |
1922 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1914 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1923 : isolate()->builtins()->StoreIC_Initialize(); | 1915 : isolate()->builtins()->StoreIC_Initialize(); |
1924 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 1916 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1925 | 1917 |
1926 // If the assignment ends an initialization block, revert to fast case. | 1918 // If the assignment ends an initialization block, revert to fast case. |
1927 if (expr->ends_initialization_block()) { | 1919 if (expr->ends_initialization_block()) { |
1928 __ push(rax); // Result of assignment, saved even if not needed. | 1920 __ push(rax); // Result of assignment, saved even if not needed. |
1929 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1921 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
1930 __ CallRuntime(Runtime::kToFastProperties, 1); | 1922 __ CallRuntime(Runtime::kToFastProperties, 1); |
1931 __ pop(rax); | 1923 __ pop(rax); |
1932 __ Drop(1); | 1924 __ Drop(1); |
1933 } | 1925 } |
1934 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 1926 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
(...skipping 19 matching lines...) Expand all Loading... |
1954 if (expr->ends_initialization_block()) { | 1946 if (expr->ends_initialization_block()) { |
1955 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. | 1947 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. |
1956 } else { | 1948 } else { |
1957 __ pop(rdx); | 1949 __ pop(rdx); |
1958 } | 1950 } |
1959 // Record source code position before IC call. | 1951 // Record source code position before IC call. |
1960 SetSourcePosition(expr->position()); | 1952 SetSourcePosition(expr->position()); |
1961 Handle<Code> ic = is_strict_mode() | 1953 Handle<Code> ic = is_strict_mode() |
1962 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1954 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
1963 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1955 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
1964 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 1956 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1965 | 1957 |
1966 // If the assignment ends an initialization block, revert to fast case. | 1958 // If the assignment ends an initialization block, revert to fast case. |
1967 if (expr->ends_initialization_block()) { | 1959 if (expr->ends_initialization_block()) { |
1968 __ pop(rdx); | 1960 __ pop(rdx); |
1969 __ push(rax); // Result of assignment, saved even if not needed. | 1961 __ push(rax); // Result of assignment, saved even if not needed. |
1970 __ push(rdx); | 1962 __ push(rdx); |
1971 __ CallRuntime(Runtime::kToFastProperties, 1); | 1963 __ CallRuntime(Runtime::kToFastProperties, 1); |
1972 __ pop(rax); | 1964 __ pop(rax); |
1973 } | 1965 } |
1974 | 1966 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2006 VisitForStackValue(args->at(i)); | 1998 VisitForStackValue(args->at(i)); |
2007 } | 1999 } |
2008 __ Move(rcx, name); | 2000 __ Move(rcx, name); |
2009 } | 2001 } |
2010 // Record source position for debugger. | 2002 // Record source position for debugger. |
2011 SetSourcePosition(expr->position()); | 2003 SetSourcePosition(expr->position()); |
2012 // Call the IC initialization code. | 2004 // Call the IC initialization code. |
2013 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2005 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2014 Handle<Code> ic = | 2006 Handle<Code> ic = |
2015 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); | 2007 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
2016 EmitCallIC(ic, mode, expr->id()); | 2008 EmitCallIC(ic, mode); |
2017 RecordJSReturnSite(expr); | 2009 RecordJSReturnSite(expr); |
2018 // Restore context register. | 2010 // Restore context register. |
2019 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2011 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2020 context()->Plug(rax); | 2012 context()->Plug(rax); |
2021 } | 2013 } |
2022 | 2014 |
2023 | 2015 |
2024 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2016 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2025 Expression* key, | 2017 Expression* key, |
2026 RelocInfo::Mode mode) { | 2018 RelocInfo::Mode mode) { |
(...skipping 14 matching lines...) Expand all Loading... |
2041 VisitForStackValue(args->at(i)); | 2033 VisitForStackValue(args->at(i)); |
2042 } | 2034 } |
2043 } | 2035 } |
2044 // Record source position for debugger. | 2036 // Record source position for debugger. |
2045 SetSourcePosition(expr->position()); | 2037 SetSourcePosition(expr->position()); |
2046 // Call the IC initialization code. | 2038 // Call the IC initialization code. |
2047 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2039 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2048 Handle<Code> ic = | 2040 Handle<Code> ic = |
2049 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); | 2041 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); |
2050 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. | 2042 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. |
2051 EmitCallIC(ic, mode, expr->id()); | 2043 EmitCallIC(ic, mode); |
2052 RecordJSReturnSite(expr); | 2044 RecordJSReturnSite(expr); |
2053 // Restore context register. | 2045 // Restore context register. |
2054 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2046 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2055 context()->DropAndPlug(1, rax); // Drop the key still on the stack. | 2047 context()->DropAndPlug(1, rax); // Drop the key still on the stack. |
2056 } | 2048 } |
2057 | 2049 |
2058 | 2050 |
2059 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2051 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
2060 // Code common for calls using the call stub. | 2052 // Code common for calls using the call stub. |
2061 ZoneList<Expression*>* args = expr->arguments(); | 2053 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2233 __ movq(rdx, operand); | 2225 __ movq(rdx, operand); |
2234 | 2226 |
2235 ASSERT(prop->key()->AsLiteral() != NULL); | 2227 ASSERT(prop->key()->AsLiteral() != NULL); |
2236 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2228 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
2237 __ Move(rax, prop->key()->AsLiteral()->handle()); | 2229 __ Move(rax, prop->key()->AsLiteral()->handle()); |
2238 | 2230 |
2239 // Record source code position for IC call. | 2231 // Record source code position for IC call. |
2240 SetSourcePosition(prop->position()); | 2232 SetSourcePosition(prop->position()); |
2241 | 2233 |
2242 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2234 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2243 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 2235 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
2244 // Push result (function). | 2236 // Push result (function). |
2245 __ push(rax); | 2237 __ push(rax); |
2246 // Push Global receiver. | 2238 // Push Global receiver. |
2247 __ movq(rcx, GlobalObjectOperand()); | 2239 __ movq(rcx, GlobalObjectOperand()); |
2248 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); | 2240 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
2249 EmitCallWithStub(expr); | 2241 EmitCallWithStub(expr); |
2250 } else { | 2242 } else { |
2251 { PreservePositionScope scope(masm()->positions_recorder()); | 2243 { PreservePositionScope scope(masm()->positions_recorder()); |
2252 VisitForStackValue(prop->obj()); | 2244 VisitForStackValue(prop->obj()); |
2253 } | 2245 } |
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3593 for (int i = 0; i < arg_count; i++) { | 3585 for (int i = 0; i < arg_count; i++) { |
3594 VisitForStackValue(args->at(i)); | 3586 VisitForStackValue(args->at(i)); |
3595 } | 3587 } |
3596 | 3588 |
3597 if (expr->is_jsruntime()) { | 3589 if (expr->is_jsruntime()) { |
3598 // Call the JS runtime function using a call IC. | 3590 // Call the JS runtime function using a call IC. |
3599 __ Move(rcx, expr->name()); | 3591 __ Move(rcx, expr->name()); |
3600 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 3592 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
3601 Handle<Code> ic = | 3593 Handle<Code> ic = |
3602 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); | 3594 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
3603 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 3595 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3604 // Restore context register. | 3596 // Restore context register. |
3605 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3597 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
3606 } else { | 3598 } else { |
3607 __ CallRuntime(expr->function(), arg_count); | 3599 __ CallRuntime(expr->function(), arg_count); |
3608 } | 3600 } |
3609 context()->Plug(rax); | 3601 context()->Plug(rax); |
3610 } | 3602 } |
3611 | 3603 |
3612 | 3604 |
3613 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3605 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3878 SetSourcePosition(expr->position()); | 3870 SetSourcePosition(expr->position()); |
3879 | 3871 |
3880 // Call stub for +1/-1. | 3872 // Call stub for +1/-1. |
3881 TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); | 3873 TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); |
3882 if (expr->op() == Token::INC) { | 3874 if (expr->op() == Token::INC) { |
3883 __ Move(rdx, Smi::FromInt(1)); | 3875 __ Move(rdx, Smi::FromInt(1)); |
3884 } else { | 3876 } else { |
3885 __ movq(rdx, rax); | 3877 __ movq(rdx, rax); |
3886 __ Move(rax, Smi::FromInt(1)); | 3878 __ Move(rax, Smi::FromInt(1)); |
3887 } | 3879 } |
3888 EmitCallIC(stub.GetCode(), &patch_site, expr->CountId()); | 3880 EmitCallIC(stub.GetCode(), &patch_site); |
3889 __ bind(&done); | 3881 __ bind(&done); |
3890 | 3882 |
3891 // Store the value returned in rax. | 3883 // Store the value returned in rax. |
3892 switch (assign_type) { | 3884 switch (assign_type) { |
3893 case VARIABLE: | 3885 case VARIABLE: |
3894 if (expr->is_postfix()) { | 3886 if (expr->is_postfix()) { |
3895 // Perform the assignment as if via '='. | 3887 // Perform the assignment as if via '='. |
3896 { EffectContext context(this); | 3888 { EffectContext context(this); |
3897 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3889 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3898 Token::ASSIGN); | 3890 Token::ASSIGN); |
(...skipping 12 matching lines...) Expand all Loading... |
3911 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3903 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3912 context()->Plug(rax); | 3904 context()->Plug(rax); |
3913 } | 3905 } |
3914 break; | 3906 break; |
3915 case NAMED_PROPERTY: { | 3907 case NAMED_PROPERTY: { |
3916 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3908 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
3917 __ pop(rdx); | 3909 __ pop(rdx); |
3918 Handle<Code> ic = is_strict_mode() | 3910 Handle<Code> ic = is_strict_mode() |
3919 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3911 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
3920 : isolate()->builtins()->StoreIC_Initialize(); | 3912 : isolate()->builtins()->StoreIC_Initialize(); |
3921 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 3913 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3922 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3914 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3923 if (expr->is_postfix()) { | 3915 if (expr->is_postfix()) { |
3924 if (!context()->IsEffect()) { | 3916 if (!context()->IsEffect()) { |
3925 context()->PlugTOS(); | 3917 context()->PlugTOS(); |
3926 } | 3918 } |
3927 } else { | 3919 } else { |
3928 context()->Plug(rax); | 3920 context()->Plug(rax); |
3929 } | 3921 } |
3930 break; | 3922 break; |
3931 } | 3923 } |
3932 case KEYED_PROPERTY: { | 3924 case KEYED_PROPERTY: { |
3933 __ pop(rcx); | 3925 __ pop(rcx); |
3934 __ pop(rdx); | 3926 __ pop(rdx); |
3935 Handle<Code> ic = is_strict_mode() | 3927 Handle<Code> ic = is_strict_mode() |
3936 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3928 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3937 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3929 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3938 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); | 3930 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3939 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3931 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3940 if (expr->is_postfix()) { | 3932 if (expr->is_postfix()) { |
3941 if (!context()->IsEffect()) { | 3933 if (!context()->IsEffect()) { |
3942 context()->PlugTOS(); | 3934 context()->PlugTOS(); |
3943 } | 3935 } |
3944 } else { | 3936 } else { |
3945 context()->Plug(rax); | 3937 context()->Plug(rax); |
3946 } | 3938 } |
3947 break; | 3939 break; |
3948 } | 3940 } |
3949 } | 3941 } |
3950 } | 3942 } |
3951 | 3943 |
3952 | 3944 |
3953 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 3945 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
3954 VariableProxy* proxy = expr->AsVariableProxy(); | 3946 VariableProxy* proxy = expr->AsVariableProxy(); |
3955 ASSERT(!context()->IsEffect()); | 3947 ASSERT(!context()->IsEffect()); |
3956 ASSERT(!context()->IsTest()); | 3948 ASSERT(!context()->IsTest()); |
3957 | 3949 |
3958 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3950 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
3959 Comment cmnt(masm_, "Global variable"); | 3951 Comment cmnt(masm_, "Global variable"); |
3960 __ Move(rcx, proxy->name()); | 3952 __ Move(rcx, proxy->name()); |
3961 __ movq(rax, GlobalObjectOperand()); | 3953 __ movq(rax, GlobalObjectOperand()); |
3962 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3954 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
3963 // Use a regular load, not a contextual load, to avoid a reference | 3955 // Use a regular load, not a contextual load, to avoid a reference |
3964 // error. | 3956 // error. |
3965 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 3957 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3966 PrepareForBailout(expr, TOS_REG); | 3958 PrepareForBailout(expr, TOS_REG); |
3967 context()->Plug(rax); | 3959 context()->Plug(rax); |
3968 } else if (proxy != NULL && | 3960 } else if (proxy != NULL && |
3969 proxy->var()->AsSlot() != NULL && | 3961 proxy->var()->AsSlot() != NULL && |
3970 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { | 3962 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
3971 Label done, slow; | 3963 Label done, slow; |
3972 | 3964 |
3973 // Generate code for loading from variables potentially shadowed | 3965 // Generate code for loading from variables potentially shadowed |
3974 // by eval-introduced variables. | 3966 // by eval-introduced variables. |
3975 Slot* slot = proxy->var()->AsSlot(); | 3967 Slot* slot = proxy->var()->AsSlot(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4153 __ or_(rcx, rax); | 4145 __ or_(rcx, rax); |
4154 patch_site.EmitJumpIfNotSmi(rcx, &slow_case); | 4146 patch_site.EmitJumpIfNotSmi(rcx, &slow_case); |
4155 __ cmpq(rdx, rax); | 4147 __ cmpq(rdx, rax); |
4156 Split(cc, if_true, if_false, NULL); | 4148 Split(cc, if_true, if_false, NULL); |
4157 __ bind(&slow_case); | 4149 __ bind(&slow_case); |
4158 } | 4150 } |
4159 | 4151 |
4160 // Record position and call the compare IC. | 4152 // Record position and call the compare IC. |
4161 SetSourcePosition(expr->position()); | 4153 SetSourcePosition(expr->position()); |
4162 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4154 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4163 EmitCallIC(ic, &patch_site, expr->id()); | 4155 EmitCallIC(ic, &patch_site); |
4164 | 4156 |
4165 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4157 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4166 __ testq(rax, rax); | 4158 __ testq(rax, rax); |
4167 Split(cc, if_true, if_false, fall_through); | 4159 Split(cc, if_true, if_false, fall_through); |
4168 } | 4160 } |
4169 } | 4161 } |
4170 | 4162 |
4171 // Convert the result of the comparison into one expected for this | 4163 // Convert the result of the comparison into one expected for this |
4172 // expression's context. | 4164 // expression's context. |
4173 context()->Plug(if_true, if_false); | 4165 context()->Plug(if_true, if_false); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4213 Register FullCodeGenerator::result_register() { | 4205 Register FullCodeGenerator::result_register() { |
4214 return rax; | 4206 return rax; |
4215 } | 4207 } |
4216 | 4208 |
4217 | 4209 |
4218 Register FullCodeGenerator::context_register() { | 4210 Register FullCodeGenerator::context_register() { |
4219 return rsi; | 4211 return rsi; |
4220 } | 4212 } |
4221 | 4213 |
4222 | 4214 |
4223 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | 4215 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
4224 RelocInfo::Mode mode, | |
4225 unsigned ast_id) { | |
4226 ASSERT(mode == RelocInfo::CODE_TARGET || | 4216 ASSERT(mode == RelocInfo::CODE_TARGET || |
4227 mode == RelocInfo::CODE_TARGET_CONTEXT); | 4217 mode == RelocInfo::CODE_TARGET_CONTEXT); |
4228 Counters* counters = isolate()->counters(); | 4218 Counters* counters = isolate()->counters(); |
4229 switch (ic->kind()) { | 4219 switch (ic->kind()) { |
4230 case Code::LOAD_IC: | 4220 case Code::LOAD_IC: |
4231 __ IncrementCounter(counters->named_load_full(), 1); | 4221 __ IncrementCounter(counters->named_load_full(), 1); |
4232 break; | 4222 break; |
4233 case Code::KEYED_LOAD_IC: | 4223 case Code::KEYED_LOAD_IC: |
4234 __ IncrementCounter(counters->keyed_load_full(), 1); | 4224 __ IncrementCounter(counters->keyed_load_full(), 1); |
4235 break; | 4225 break; |
4236 case Code::STORE_IC: | 4226 case Code::STORE_IC: |
4237 __ IncrementCounter(counters->named_store_full(), 1); | 4227 __ IncrementCounter(counters->named_store_full(), 1); |
4238 break; | 4228 break; |
4239 case Code::KEYED_STORE_IC: | 4229 case Code::KEYED_STORE_IC: |
4240 __ IncrementCounter(counters->keyed_store_full(), 1); | 4230 __ IncrementCounter(counters->keyed_store_full(), 1); |
4241 default: | 4231 default: |
4242 break; | 4232 break; |
4243 } | 4233 } |
4244 __ call(ic, mode, ast_id); | 4234 __ call(ic, mode); |
4245 } | 4235 } |
4246 | 4236 |
4247 | 4237 |
4248 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | 4238 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { |
4249 JumpPatchSite* patch_site, | |
4250 unsigned ast_id) { | |
4251 Counters* counters = isolate()->counters(); | 4239 Counters* counters = isolate()->counters(); |
4252 switch (ic->kind()) { | 4240 switch (ic->kind()) { |
4253 case Code::LOAD_IC: | 4241 case Code::LOAD_IC: |
4254 __ IncrementCounter(counters->named_load_full(), 1); | 4242 __ IncrementCounter(counters->named_load_full(), 1); |
4255 break; | 4243 break; |
4256 case Code::KEYED_LOAD_IC: | 4244 case Code::KEYED_LOAD_IC: |
4257 __ IncrementCounter(counters->keyed_load_full(), 1); | 4245 __ IncrementCounter(counters->keyed_load_full(), 1); |
4258 break; | 4246 break; |
4259 case Code::STORE_IC: | 4247 case Code::STORE_IC: |
4260 __ IncrementCounter(counters->named_store_full(), 1); | 4248 __ IncrementCounter(counters->named_store_full(), 1); |
4261 break; | 4249 break; |
4262 case Code::KEYED_STORE_IC: | 4250 case Code::KEYED_STORE_IC: |
4263 __ IncrementCounter(counters->keyed_store_full(), 1); | 4251 __ IncrementCounter(counters->keyed_store_full(), 1); |
4264 default: | 4252 default: |
4265 break; | 4253 break; |
4266 } | 4254 } |
4267 __ call(ic, RelocInfo::CODE_TARGET, ast_id); | 4255 __ call(ic, RelocInfo::CODE_TARGET); |
4268 if (patch_site != NULL && patch_site->is_bound()) { | 4256 if (patch_site != NULL && patch_site->is_bound()) { |
4269 patch_site->EmitPatchInfo(); | 4257 patch_site->EmitPatchInfo(); |
4270 } else { | 4258 } else { |
4271 __ nop(); // Signals no inlined code. | 4259 __ nop(); // Signals no inlined code. |
4272 } | 4260 } |
4273 } | 4261 } |
4274 | 4262 |
4275 | 4263 |
4276 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4264 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4277 ASSERT(IsAligned(frame_offset, kPointerSize)); | 4265 ASSERT(IsAligned(frame_offset, kPointerSize)); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4317 __ ret(0); | 4305 __ ret(0); |
4318 } | 4306 } |
4319 | 4307 |
4320 | 4308 |
4321 #undef __ | 4309 #undef __ |
4322 | 4310 |
4323 | 4311 |
4324 } } // namespace v8::internal | 4312 } } // namespace v8::internal |
4325 | 4313 |
4326 #endif // V8_TARGET_ARCH_X64 | 4314 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |