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 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 } | 1124 } |
1125 | 1125 |
1126 // All extension objects were empty and it is safe to use a global | 1126 // All extension objects were empty and it is safe to use a global |
1127 // load IC call. | 1127 // load IC call. |
1128 __ movq(rax, GlobalObjectOperand()); | 1128 __ movq(rax, GlobalObjectOperand()); |
1129 __ Move(rcx, slot->var()->name()); | 1129 __ Move(rcx, slot->var()->name()); |
1130 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1130 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1131 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1131 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
1132 ? RelocInfo::CODE_TARGET | 1132 ? RelocInfo::CODE_TARGET |
1133 : RelocInfo::CODE_TARGET_CONTEXT; | 1133 : RelocInfo::CODE_TARGET_CONTEXT; |
1134 EmitCallIC(ic, mode); | 1134 EmitCallIC(ic, mode, AstNode::kNoNumber); |
1135 } | 1135 } |
1136 | 1136 |
1137 | 1137 |
1138 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 1138 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
1139 Slot* slot, | 1139 Slot* slot, |
1140 Label* slow) { | 1140 Label* slow) { |
1141 ASSERT(slot->type() == Slot::CONTEXT); | 1141 ASSERT(slot->type() == Slot::CONTEXT); |
1142 Register context = rsi; | 1142 Register context = rsi; |
1143 Register temp = rbx; | 1143 Register temp = rbx; |
1144 | 1144 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 Slot* slot = var->AsSlot(); | 1228 Slot* slot = var->AsSlot(); |
1229 Property* property = var->AsProperty(); | 1229 Property* property = var->AsProperty(); |
1230 | 1230 |
1231 if (var->is_global() && !var->is_this()) { | 1231 if (var->is_global() && !var->is_this()) { |
1232 Comment cmnt(masm_, "Global variable"); | 1232 Comment cmnt(masm_, "Global variable"); |
1233 // Use inline caching. Variable name is passed in rcx and the global | 1233 // Use inline caching. Variable name is passed in rcx and the global |
1234 // object on the stack. | 1234 // object on the stack. |
1235 __ Move(rcx, var->name()); | 1235 __ Move(rcx, var->name()); |
1236 __ movq(rax, GlobalObjectOperand()); | 1236 __ movq(rax, GlobalObjectOperand()); |
1237 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1237 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1238 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1238 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); |
1239 context()->Plug(rax); | 1239 context()->Plug(rax); |
1240 | 1240 |
1241 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1241 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
1242 Label done, slow; | 1242 Label done, slow; |
1243 | 1243 |
1244 // Generate code for loading from variables potentially shadowed | 1244 // Generate code for loading from variables potentially shadowed |
1245 // by eval-introduced variables. | 1245 // by eval-introduced variables. |
1246 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1246 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
1247 | 1247 |
1248 __ bind(&slow); | 1248 __ bind(&slow); |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 } | 1762 } |
1763 case NAMED_PROPERTY: { | 1763 case NAMED_PROPERTY: { |
1764 __ push(rax); // Preserve value. | 1764 __ push(rax); // Preserve value. |
1765 VisitForAccumulatorValue(prop->obj()); | 1765 VisitForAccumulatorValue(prop->obj()); |
1766 __ movq(rdx, rax); | 1766 __ movq(rdx, rax); |
1767 __ pop(rax); // Restore value. | 1767 __ pop(rax); // Restore value. |
1768 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1768 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1769 Handle<Code> ic = is_strict_mode() | 1769 Handle<Code> ic = is_strict_mode() |
1770 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1770 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1771 : isolate()->builtins()->StoreIC_Initialize(); | 1771 : isolate()->builtins()->StoreIC_Initialize(); |
1772 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1772 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); |
1773 break; | 1773 break; |
1774 } | 1774 } |
1775 case KEYED_PROPERTY: { | 1775 case KEYED_PROPERTY: { |
1776 __ push(rax); // Preserve value. | 1776 __ push(rax); // Preserve value. |
1777 if (prop->is_synthetic()) { | 1777 if (prop->is_synthetic()) { |
1778 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1778 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
1779 ASSERT(prop->key()->AsLiteral() != NULL); | 1779 ASSERT(prop->key()->AsLiteral() != NULL); |
1780 { AccumulatorValueContext for_object(this); | 1780 { AccumulatorValueContext for_object(this); |
1781 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 1781 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
1782 } | 1782 } |
1783 __ movq(rdx, rax); | 1783 __ movq(rdx, rax); |
1784 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1784 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1785 } else { | 1785 } else { |
1786 VisitForStackValue(prop->obj()); | 1786 VisitForStackValue(prop->obj()); |
1787 VisitForAccumulatorValue(prop->key()); | 1787 VisitForAccumulatorValue(prop->key()); |
1788 __ movq(rcx, rax); | 1788 __ movq(rcx, rax); |
1789 __ pop(rdx); | 1789 __ pop(rdx); |
1790 } | 1790 } |
1791 __ pop(rax); // Restore value. | 1791 __ pop(rax); // Restore value. |
1792 Handle<Code> ic = is_strict_mode() | 1792 Handle<Code> ic = is_strict_mode() |
1793 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1793 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
1794 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1794 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
1795 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1795 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); |
1796 break; | 1796 break; |
1797 } | 1797 } |
1798 } | 1798 } |
1799 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1799 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1800 context()->Plug(rax); | 1800 context()->Plug(rax); |
1801 } | 1801 } |
1802 | 1802 |
1803 | 1803 |
1804 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1804 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1805 Token::Value op) { | 1805 Token::Value op) { |
1806 // Left-hand sides that rewrite to explicit property accesses do not reach | 1806 // Left-hand sides that rewrite to explicit property accesses do not reach |
1807 // here. | 1807 // here. |
1808 ASSERT(var != NULL); | 1808 ASSERT(var != NULL); |
1809 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1809 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1810 | 1810 |
1811 if (var->is_global()) { | 1811 if (var->is_global()) { |
1812 ASSERT(!var->is_this()); | 1812 ASSERT(!var->is_this()); |
1813 // Assignment to a global variable. Use inline caching for the | 1813 // Assignment to a global variable. Use inline caching for the |
1814 // assignment. Right-hand-side value is passed in rax, variable name in | 1814 // assignment. Right-hand-side value is passed in rax, variable name in |
1815 // rcx, and the global object on the stack. | 1815 // rcx, and the global object on the stack. |
1816 __ Move(rcx, var->name()); | 1816 __ Move(rcx, var->name()); |
1817 __ movq(rdx, GlobalObjectOperand()); | 1817 __ movq(rdx, GlobalObjectOperand()); |
1818 Handle<Code> ic = is_strict_mode() | 1818 Handle<Code> ic = is_strict_mode() |
1819 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1819 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1820 : isolate()->builtins()->StoreIC_Initialize(); | 1820 : isolate()->builtins()->StoreIC_Initialize(); |
1821 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1821 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); |
1822 | 1822 |
1823 } else if (op == Token::INIT_CONST) { | 1823 } else if (op == Token::INIT_CONST) { |
1824 // Like var declarations, const declarations are hoisted to function | 1824 // Like var declarations, const declarations are hoisted to function |
1825 // scope. However, unlike var initializers, const initializers are able | 1825 // scope. However, unlike var initializers, const initializers are able |
1826 // to drill a hole to that function context, even from inside a 'with' | 1826 // to drill a hole to that function context, even from inside a 'with' |
1827 // context. We thus bypass the normal static scope lookup. | 1827 // context. We thus bypass the normal static scope lookup. |
1828 Slot* slot = var->AsSlot(); | 1828 Slot* slot = var->AsSlot(); |
1829 Label skip; | 1829 Label skip; |
1830 switch (slot->type()) { | 1830 switch (slot->type()) { |
1831 case Slot::PARAMETER: | 1831 case Slot::PARAMETER: |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1914 SetSourcePosition(expr->position()); | 1914 SetSourcePosition(expr->position()); |
1915 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1915 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1916 if (expr->ends_initialization_block()) { | 1916 if (expr->ends_initialization_block()) { |
1917 __ movq(rdx, Operand(rsp, 0)); | 1917 __ movq(rdx, Operand(rsp, 0)); |
1918 } else { | 1918 } else { |
1919 __ pop(rdx); | 1919 __ pop(rdx); |
1920 } | 1920 } |
1921 Handle<Code> ic = is_strict_mode() | 1921 Handle<Code> ic = is_strict_mode() |
1922 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1922 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1923 : isolate()->builtins()->StoreIC_Initialize(); | 1923 : isolate()->builtins()->StoreIC_Initialize(); |
1924 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1924 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
1925 | 1925 |
1926 // If the assignment ends an initialization block, revert to fast case. | 1926 // If the assignment ends an initialization block, revert to fast case. |
1927 if (expr->ends_initialization_block()) { | 1927 if (expr->ends_initialization_block()) { |
1928 __ push(rax); // Result of assignment, saved even if not needed. | 1928 __ push(rax); // Result of assignment, saved even if not needed. |
1929 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1929 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
1930 __ CallRuntime(Runtime::kToFastProperties, 1); | 1930 __ CallRuntime(Runtime::kToFastProperties, 1); |
1931 __ pop(rax); | 1931 __ pop(rax); |
1932 __ Drop(1); | 1932 __ Drop(1); |
1933 } | 1933 } |
1934 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 1934 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
(...skipping 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3955 ASSERT(!context()->IsEffect()); | 3955 ASSERT(!context()->IsEffect()); |
3956 ASSERT(!context()->IsTest()); | 3956 ASSERT(!context()->IsTest()); |
3957 | 3957 |
3958 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3958 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
3959 Comment cmnt(masm_, "Global variable"); | 3959 Comment cmnt(masm_, "Global variable"); |
3960 __ Move(rcx, proxy->name()); | 3960 __ Move(rcx, proxy->name()); |
3961 __ movq(rax, GlobalObjectOperand()); | 3961 __ movq(rax, GlobalObjectOperand()); |
3962 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3962 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
3963 // Use a regular load, not a contextual load, to avoid a reference | 3963 // Use a regular load, not a contextual load, to avoid a reference |
3964 // error. | 3964 // error. |
3965 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3965 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); |
3966 PrepareForBailout(expr, TOS_REG); | 3966 PrepareForBailout(expr, TOS_REG); |
3967 context()->Plug(rax); | 3967 context()->Plug(rax); |
3968 } else if (proxy != NULL && | 3968 } else if (proxy != NULL && |
3969 proxy->var()->AsSlot() != NULL && | 3969 proxy->var()->AsSlot() != NULL && |
3970 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { | 3970 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
3971 Label done, slow; | 3971 Label done, slow; |
3972 | 3972 |
3973 // Generate code for loading from variables potentially shadowed | 3973 // Generate code for loading from variables potentially shadowed |
3974 // by eval-introduced variables. | 3974 // by eval-introduced variables. |
3975 Slot* slot = proxy->var()->AsSlot(); | 3975 Slot* slot = proxy->var()->AsSlot(); |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4317 __ ret(0); | 4317 __ ret(0); |
4318 } | 4318 } |
4319 | 4319 |
4320 | 4320 |
4321 #undef __ | 4321 #undef __ |
4322 | 4322 |
4323 | 4323 |
4324 } } // namespace v8::internal | 4324 } } // namespace v8::internal |
4325 | 4325 |
4326 #endif // V8_TARGET_ARCH_X64 | 4326 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |