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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 if (strlen(FLAG_stop_at) > 0 && | 126 if (strlen(FLAG_stop_at) > 0 && |
127 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 127 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
128 __ int3(); | 128 __ int3(); |
129 } | 129 } |
130 #endif | 130 #endif |
131 | 131 |
132 // Strict mode functions and builtins need to replace the receiver | 132 // Strict mode functions and builtins need to replace the receiver |
133 // with undefined when called as functions (without an explicit | 133 // with undefined when called as functions (without an explicit |
134 // receiver object). rcx is zero for method calls and non-zero for | 134 // receiver object). rcx is zero for method calls and non-zero for |
135 // function calls. | 135 // function calls. |
136 if (info->is_strict_mode() || info->is_native()) { | 136 if (!info->is_classic_mode() || info->is_native()) { |
137 Label ok; | 137 Label ok; |
138 __ testq(rcx, rcx); | 138 __ testq(rcx, rcx); |
139 __ j(zero, &ok, Label::kNear); | 139 __ j(zero, &ok, Label::kNear); |
140 // +1 for return address. | 140 // +1 for return address. |
141 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; | 141 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; |
142 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 142 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
143 __ movq(Operand(rsp, receiver_offset), kScratchRegister); | 143 __ movq(Operand(rsp, receiver_offset), kScratchRegister); |
144 __ bind(&ok); | 144 __ bind(&ok); |
145 } | 145 } |
146 | 146 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 int offset = num_parameters * kPointerSize; | 220 int offset = num_parameters * kPointerSize; |
221 __ lea(rdx, | 221 __ lea(rdx, |
222 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); | 222 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); |
223 __ push(rdx); | 223 __ push(rdx); |
224 __ Push(Smi::FromInt(num_parameters)); | 224 __ Push(Smi::FromInt(num_parameters)); |
225 // Arguments to ArgumentsAccessStub: | 225 // Arguments to ArgumentsAccessStub: |
226 // function, receiver address, parameter count. | 226 // function, receiver address, parameter count. |
227 // The stub will rewrite receiver and parameter count if the previous | 227 // The stub will rewrite receiver and parameter count if the previous |
228 // stack frame was an arguments adapter frame. | 228 // stack frame was an arguments adapter frame. |
229 ArgumentsAccessStub stub( | 229 ArgumentsAccessStub stub( |
230 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT | 230 is_classic_mode() ? ArgumentsAccessStub::NEW_NON_STRICT_SLOW |
231 : ArgumentsAccessStub::NEW_NON_STRICT_SLOW); | 231 : ArgumentsAccessStub::NEW_STRICT); |
232 __ CallStub(&stub); | 232 __ CallStub(&stub); |
233 | 233 |
234 SetVar(arguments, rax, rbx, rdx); | 234 SetVar(arguments, rax, rbx, rdx); |
235 } | 235 } |
236 | 236 |
237 if (FLAG_trace) { | 237 if (FLAG_trace) { |
238 __ CallRuntime(Runtime::kTraceEnter, 0); | 238 __ CallRuntime(Runtime::kTraceEnter, 0); |
239 } | 239 } |
240 | 240 |
241 // Visit the declarations and body unless there is an illegal | 241 // Visit the declarations and body unless there is an illegal |
(...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1067 // space for nested functions that don't need literals cloning. If | 1067 // space for nested functions that don't need literals cloning. If |
1068 // we're running with the --always-opt or the --prepare-always-opt | 1068 // we're running with the --always-opt or the --prepare-always-opt |
1069 // flag, we need to use the runtime function so that the new function | 1069 // flag, we need to use the runtime function so that the new function |
1070 // we are creating here gets a chance to have its code optimized and | 1070 // we are creating here gets a chance to have its code optimized and |
1071 // doesn't just get a copy of the existing unoptimized code. | 1071 // doesn't just get a copy of the existing unoptimized code. |
1072 if (!FLAG_always_opt && | 1072 if (!FLAG_always_opt && |
1073 !FLAG_prepare_always_opt && | 1073 !FLAG_prepare_always_opt && |
1074 !pretenure && | 1074 !pretenure && |
1075 scope()->is_function_scope() && | 1075 scope()->is_function_scope() && |
1076 info->num_literals() == 0) { | 1076 info->num_literals() == 0) { |
1077 FastNewClosureStub stub(info->strict_mode_flag()); | 1077 FastNewClosureStub stub(info->language_mode()); |
1078 __ Push(info); | 1078 __ Push(info); |
1079 __ CallStub(&stub); | 1079 __ CallStub(&stub); |
1080 } else { | 1080 } else { |
1081 __ push(rsi); | 1081 __ push(rsi); |
1082 __ Push(info); | 1082 __ Push(info); |
1083 __ Push(pretenure | 1083 __ Push(pretenure |
1084 ? isolate()->factory()->true_value() | 1084 ? isolate()->factory()->true_value() |
1085 : isolate()->factory()->false_value()); | 1085 : isolate()->factory()->false_value()); |
1086 __ CallRuntime(Runtime::kNewClosure, 3); | 1086 __ CallRuntime(Runtime::kNewClosure, 3); |
1087 } | 1087 } |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 UNREACHABLE(); | 1417 UNREACHABLE(); |
1418 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1418 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1419 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1419 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
1420 // Fall through. | 1420 // Fall through. |
1421 case ObjectLiteral::Property::COMPUTED: | 1421 case ObjectLiteral::Property::COMPUTED: |
1422 if (key->handle()->IsSymbol()) { | 1422 if (key->handle()->IsSymbol()) { |
1423 if (property->emit_store()) { | 1423 if (property->emit_store()) { |
1424 VisitForAccumulatorValue(value); | 1424 VisitForAccumulatorValue(value); |
1425 __ Move(rcx, key->handle()); | 1425 __ Move(rcx, key->handle()); |
1426 __ movq(rdx, Operand(rsp, 0)); | 1426 __ movq(rdx, Operand(rsp, 0)); |
1427 Handle<Code> ic = is_strict_mode() | 1427 Handle<Code> ic = is_classic_mode() |
1428 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1428 ? isolate()->builtins()->StoreIC_Initialize() |
1429 : isolate()->builtins()->StoreIC_Initialize(); | 1429 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1430 __ call(ic, RelocInfo::CODE_TARGET, key->id()); | 1430 __ call(ic, RelocInfo::CODE_TARGET, key->id()); |
1431 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1431 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1432 } else { | 1432 } else { |
1433 VisitForEffect(value); | 1433 VisitForEffect(value); |
1434 } | 1434 } |
1435 break; | 1435 break; |
1436 } | 1436 } |
1437 // Fall through. | 1437 // Fall through. |
1438 case ObjectLiteral::Property::PROTOTYPE: | 1438 case ObjectLiteral::Property::PROTOTYPE: |
1439 __ push(Operand(rsp, 0)); // Duplicate receiver. | 1439 __ push(Operand(rsp, 0)); // Duplicate receiver. |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1776 EffectContext context(this); | 1776 EffectContext context(this); |
1777 EmitVariableAssignment(var, Token::ASSIGN); | 1777 EmitVariableAssignment(var, Token::ASSIGN); |
1778 break; | 1778 break; |
1779 } | 1779 } |
1780 case NAMED_PROPERTY: { | 1780 case NAMED_PROPERTY: { |
1781 __ push(rax); // Preserve value. | 1781 __ push(rax); // Preserve value. |
1782 VisitForAccumulatorValue(prop->obj()); | 1782 VisitForAccumulatorValue(prop->obj()); |
1783 __ movq(rdx, rax); | 1783 __ movq(rdx, rax); |
1784 __ pop(rax); // Restore value. | 1784 __ pop(rax); // Restore value. |
1785 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1785 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1786 Handle<Code> ic = is_strict_mode() | 1786 Handle<Code> ic = is_classic_mode() |
1787 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1787 ? isolate()->builtins()->StoreIC_Initialize() |
1788 : isolate()->builtins()->StoreIC_Initialize(); | 1788 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1789 __ call(ic); | 1789 __ call(ic); |
1790 break; | 1790 break; |
1791 } | 1791 } |
1792 case KEYED_PROPERTY: { | 1792 case KEYED_PROPERTY: { |
1793 __ push(rax); // Preserve value. | 1793 __ push(rax); // Preserve value. |
1794 VisitForStackValue(prop->obj()); | 1794 VisitForStackValue(prop->obj()); |
1795 VisitForAccumulatorValue(prop->key()); | 1795 VisitForAccumulatorValue(prop->key()); |
1796 __ movq(rcx, rax); | 1796 __ movq(rcx, rax); |
1797 __ pop(rdx); | 1797 __ pop(rdx); |
1798 __ pop(rax); // Restore value. | 1798 __ pop(rax); // Restore value. |
1799 Handle<Code> ic = is_strict_mode() | 1799 Handle<Code> ic = is_classic_mode() |
1800 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1800 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1801 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1801 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1802 __ call(ic); | 1802 __ call(ic); |
1803 break; | 1803 break; |
1804 } | 1804 } |
1805 } | 1805 } |
1806 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1806 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1807 context()->Plug(rax); | 1807 context()->Plug(rax); |
1808 } | 1808 } |
1809 | 1809 |
1810 | 1810 |
1811 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1811 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1812 Token::Value op) { | 1812 Token::Value op) { |
1813 if (var->IsUnallocated()) { | 1813 if (var->IsUnallocated()) { |
1814 // Global var, const, or let. | 1814 // Global var, const, or let. |
1815 __ Move(rcx, var->name()); | 1815 __ Move(rcx, var->name()); |
1816 __ movq(rdx, GlobalObjectOperand()); | 1816 __ movq(rdx, GlobalObjectOperand()); |
1817 Handle<Code> ic = is_strict_mode() | 1817 Handle<Code> ic = is_classic_mode() |
1818 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1818 ? isolate()->builtins()->StoreIC_Initialize() |
1819 : isolate()->builtins()->StoreIC_Initialize(); | 1819 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1820 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1820 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1821 } else if (op == Token::INIT_CONST) { | 1821 } else if (op == Token::INIT_CONST) { |
1822 // Const initializers need a write barrier. | 1822 // Const initializers need a write barrier. |
1823 ASSERT(!var->IsParameter()); // No const parameters. | 1823 ASSERT(!var->IsParameter()); // No const parameters. |
1824 if (var->IsStackLocal()) { | 1824 if (var->IsStackLocal()) { |
1825 Label skip; | 1825 Label skip; |
1826 __ movq(rdx, StackOperand(var)); | 1826 __ movq(rdx, StackOperand(var)); |
1827 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 1827 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
1828 __ j(not_equal, &skip); | 1828 __ j(not_equal, &skip); |
1829 __ movq(StackOperand(var), rax); | 1829 __ movq(StackOperand(var), rax); |
(...skipping 10 matching lines...) Expand all Loading... |
1840 __ Push(var->name()); | 1840 __ Push(var->name()); |
1841 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1841 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1842 } | 1842 } |
1843 | 1843 |
1844 } else if (var->mode() == LET && op != Token::INIT_LET) { | 1844 } else if (var->mode() == LET && op != Token::INIT_LET) { |
1845 // Non-initializing assignment to let variable needs a write barrier. | 1845 // Non-initializing assignment to let variable needs a write barrier. |
1846 if (var->IsLookupSlot()) { | 1846 if (var->IsLookupSlot()) { |
1847 __ push(rax); // Value. | 1847 __ push(rax); // Value. |
1848 __ push(rsi); // Context. | 1848 __ push(rsi); // Context. |
1849 __ Push(var->name()); | 1849 __ Push(var->name()); |
1850 __ Push(Smi::FromInt(strict_mode_flag())); | 1850 __ Push(Smi::FromInt(language_mode())); |
1851 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1851 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1852 } else { | 1852 } else { |
1853 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 1853 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
1854 Label assign; | 1854 Label assign; |
1855 MemOperand location = VarOperand(var, rcx); | 1855 MemOperand location = VarOperand(var, rcx); |
1856 __ movq(rdx, location); | 1856 __ movq(rdx, location); |
1857 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 1857 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
1858 __ j(not_equal, &assign, Label::kNear); | 1858 __ j(not_equal, &assign, Label::kNear); |
1859 __ Push(var->name()); | 1859 __ Push(var->name()); |
1860 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1860 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
(...skipping 22 matching lines...) Expand all Loading... |
1883 if (var->IsContextSlot()) { | 1883 if (var->IsContextSlot()) { |
1884 __ movq(rdx, rax); | 1884 __ movq(rdx, rax); |
1885 __ RecordWriteContextSlot( | 1885 __ RecordWriteContextSlot( |
1886 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); | 1886 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); |
1887 } | 1887 } |
1888 } else { | 1888 } else { |
1889 ASSERT(var->IsLookupSlot()); | 1889 ASSERT(var->IsLookupSlot()); |
1890 __ push(rax); // Value. | 1890 __ push(rax); // Value. |
1891 __ push(rsi); // Context. | 1891 __ push(rsi); // Context. |
1892 __ Push(var->name()); | 1892 __ Push(var->name()); |
1893 __ Push(Smi::FromInt(strict_mode_flag())); | 1893 __ Push(Smi::FromInt(language_mode())); |
1894 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1894 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1895 } | 1895 } |
1896 } | 1896 } |
1897 // Non-initializing assignments to consts are ignored. | 1897 // Non-initializing assignments to consts are ignored. |
1898 } | 1898 } |
1899 | 1899 |
1900 | 1900 |
1901 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1901 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1902 // Assignment to a property, using a named store IC. | 1902 // Assignment to a property, using a named store IC. |
1903 Property* prop = expr->target()->AsProperty(); | 1903 Property* prop = expr->target()->AsProperty(); |
(...skipping 11 matching lines...) Expand all Loading... |
1915 } | 1915 } |
1916 | 1916 |
1917 // Record source code position before IC call. | 1917 // Record source code position before IC call. |
1918 SetSourcePosition(expr->position()); | 1918 SetSourcePosition(expr->position()); |
1919 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1919 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1920 if (expr->ends_initialization_block()) { | 1920 if (expr->ends_initialization_block()) { |
1921 __ movq(rdx, Operand(rsp, 0)); | 1921 __ movq(rdx, Operand(rsp, 0)); |
1922 } else { | 1922 } else { |
1923 __ pop(rdx); | 1923 __ pop(rdx); |
1924 } | 1924 } |
1925 Handle<Code> ic = is_strict_mode() | 1925 Handle<Code> ic = is_classic_mode() |
1926 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1926 ? isolate()->builtins()->StoreIC_Initialize() |
1927 : isolate()->builtins()->StoreIC_Initialize(); | 1927 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1928 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 1928 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
1929 | 1929 |
1930 // If the assignment ends an initialization block, revert to fast case. | 1930 // If the assignment ends an initialization block, revert to fast case. |
1931 if (expr->ends_initialization_block()) { | 1931 if (expr->ends_initialization_block()) { |
1932 __ push(rax); // Result of assignment, saved even if not needed. | 1932 __ push(rax); // Result of assignment, saved even if not needed. |
1933 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1933 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
1934 __ CallRuntime(Runtime::kToFastProperties, 1); | 1934 __ CallRuntime(Runtime::kToFastProperties, 1); |
1935 __ pop(rax); | 1935 __ pop(rax); |
1936 __ Drop(1); | 1936 __ Drop(1); |
1937 } | 1937 } |
(...skipping 17 matching lines...) Expand all Loading... |
1955 } | 1955 } |
1956 | 1956 |
1957 __ pop(rcx); | 1957 __ pop(rcx); |
1958 if (expr->ends_initialization_block()) { | 1958 if (expr->ends_initialization_block()) { |
1959 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. | 1959 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. |
1960 } else { | 1960 } else { |
1961 __ pop(rdx); | 1961 __ pop(rdx); |
1962 } | 1962 } |
1963 // Record source code position before IC call. | 1963 // Record source code position before IC call. |
1964 SetSourcePosition(expr->position()); | 1964 SetSourcePosition(expr->position()); |
1965 Handle<Code> ic = is_strict_mode() | 1965 Handle<Code> ic = is_classic_mode() |
1966 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1966 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1967 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1967 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1968 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 1968 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
1969 | 1969 |
1970 // If the assignment ends an initialization block, revert to fast case. | 1970 // If the assignment ends an initialization block, revert to fast case. |
1971 if (expr->ends_initialization_block()) { | 1971 if (expr->ends_initialization_block()) { |
1972 __ pop(rdx); | 1972 __ pop(rdx); |
1973 __ push(rax); // Result of assignment, saved even if not needed. | 1973 __ push(rax); // Result of assignment, saved even if not needed. |
1974 __ push(rdx); | 1974 __ push(rdx); |
1975 __ CallRuntime(Runtime::kToFastProperties, 1); | 1975 __ CallRuntime(Runtime::kToFastProperties, 1); |
1976 __ pop(rax); | 1976 __ pop(rax); |
1977 } | 1977 } |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2083 // Push copy of the first argument or undefined if it doesn't exist. | 2083 // Push copy of the first argument or undefined if it doesn't exist. |
2084 if (arg_count > 0) { | 2084 if (arg_count > 0) { |
2085 __ push(Operand(rsp, arg_count * kPointerSize)); | 2085 __ push(Operand(rsp, arg_count * kPointerSize)); |
2086 } else { | 2086 } else { |
2087 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2087 __ PushRoot(Heap::kUndefinedValueRootIndex); |
2088 } | 2088 } |
2089 | 2089 |
2090 // Push the receiver of the enclosing function and do runtime call. | 2090 // Push the receiver of the enclosing function and do runtime call. |
2091 __ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize)); | 2091 __ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize)); |
2092 | 2092 |
2093 // Push the strict mode flag. In harmony mode every eval call | 2093 // Push the language mode. |
2094 // is a strict mode eval call. | 2094 __ Push(Smi::FromInt(language_mode())); |
2095 StrictModeFlag strict_mode = | |
2096 FLAG_harmony_scoping ? kStrictMode : strict_mode_flag(); | |
2097 __ Push(Smi::FromInt(strict_mode)); | |
2098 | 2095 |
2099 // Push the start position of the scope the calls resides in. | 2096 // Push the start position of the scope the calls resides in. |
2100 __ Push(Smi::FromInt(scope()->start_position())); | 2097 __ Push(Smi::FromInt(scope()->start_position())); |
2101 | 2098 |
| 2099 // Do the runtime call. |
2102 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2100 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
2103 } | 2101 } |
2104 | 2102 |
2105 | 2103 |
2106 void FullCodeGenerator::VisitCall(Call* expr) { | 2104 void FullCodeGenerator::VisitCall(Call* expr) { |
2107 #ifdef DEBUG | 2105 #ifdef DEBUG |
2108 // We want to verify that RecordJSReturnSite gets called on all paths | 2106 // We want to verify that RecordJSReturnSite gets called on all paths |
2109 // through this function. Avoid early returns. | 2107 // through this function. Avoid early returns. |
2110 expr->return_is_recorded_ = false; | 2108 expr->return_is_recorded_ = false; |
2111 #endif | 2109 #endif |
(...skipping 1518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3630 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3628 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
3631 switch (expr->op()) { | 3629 switch (expr->op()) { |
3632 case Token::DELETE: { | 3630 case Token::DELETE: { |
3633 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3631 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3634 Property* property = expr->expression()->AsProperty(); | 3632 Property* property = expr->expression()->AsProperty(); |
3635 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3633 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
3636 | 3634 |
3637 if (property != NULL) { | 3635 if (property != NULL) { |
3638 VisitForStackValue(property->obj()); | 3636 VisitForStackValue(property->obj()); |
3639 VisitForStackValue(property->key()); | 3637 VisitForStackValue(property->key()); |
3640 __ Push(Smi::FromInt(strict_mode_flag())); | 3638 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) |
| 3639 ? kNonStrictMode : kStrictMode; |
| 3640 __ Push(Smi::FromInt(strict_mode_flag)); |
3641 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3641 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3642 context()->Plug(rax); | 3642 context()->Plug(rax); |
3643 } else if (proxy != NULL) { | 3643 } else if (proxy != NULL) { |
3644 Variable* var = proxy->var(); | 3644 Variable* var = proxy->var(); |
3645 // Delete of an unqualified identifier is disallowed in strict mode | 3645 // Delete of an unqualified identifier is disallowed in strict mode |
3646 // but "delete this" is allowed. | 3646 // but "delete this" is allowed. |
3647 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); | 3647 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); |
3648 if (var->IsUnallocated()) { | 3648 if (var->IsUnallocated()) { |
3649 __ push(GlobalObjectOperand()); | 3649 __ push(GlobalObjectOperand()); |
3650 __ Push(var->name()); | 3650 __ Push(var->name()); |
3651 __ Push(Smi::FromInt(kNonStrictMode)); | 3651 __ Push(Smi::FromInt(kNonStrictMode)); |
3652 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3652 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3653 context()->Plug(rax); | 3653 context()->Plug(rax); |
3654 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3654 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
3655 // Result of deleting non-global variables is false. 'this' is | 3655 // Result of deleting non-global variables is false. 'this' is |
3656 // not really a variable, though we implement it as one. The | 3656 // not really a variable, though we implement it as one. The |
3657 // subexpression does not have side effects. | 3657 // subexpression does not have side effects. |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3918 // Perform the assignment as if via '='. | 3918 // Perform the assignment as if via '='. |
3919 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3919 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3920 Token::ASSIGN); | 3920 Token::ASSIGN); |
3921 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3921 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3922 context()->Plug(rax); | 3922 context()->Plug(rax); |
3923 } | 3923 } |
3924 break; | 3924 break; |
3925 case NAMED_PROPERTY: { | 3925 case NAMED_PROPERTY: { |
3926 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3926 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
3927 __ pop(rdx); | 3927 __ pop(rdx); |
3928 Handle<Code> ic = is_strict_mode() | 3928 Handle<Code> ic = is_classic_mode() |
3929 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3929 ? isolate()->builtins()->StoreIC_Initialize() |
3930 : isolate()->builtins()->StoreIC_Initialize(); | 3930 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
3931 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3931 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
3932 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3932 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3933 if (expr->is_postfix()) { | 3933 if (expr->is_postfix()) { |
3934 if (!context()->IsEffect()) { | 3934 if (!context()->IsEffect()) { |
3935 context()->PlugTOS(); | 3935 context()->PlugTOS(); |
3936 } | 3936 } |
3937 } else { | 3937 } else { |
3938 context()->Plug(rax); | 3938 context()->Plug(rax); |
3939 } | 3939 } |
3940 break; | 3940 break; |
3941 } | 3941 } |
3942 case KEYED_PROPERTY: { | 3942 case KEYED_PROPERTY: { |
3943 __ pop(rcx); | 3943 __ pop(rcx); |
3944 __ pop(rdx); | 3944 __ pop(rdx); |
3945 Handle<Code> ic = is_strict_mode() | 3945 Handle<Code> ic = is_classic_mode() |
3946 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3946 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
3947 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3947 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
3948 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3948 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
3949 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3949 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3950 if (expr->is_postfix()) { | 3950 if (expr->is_postfix()) { |
3951 if (!context()->IsEffect()) { | 3951 if (!context()->IsEffect()) { |
3952 context()->PlugTOS(); | 3952 context()->PlugTOS(); |
3953 } | 3953 } |
3954 } else { | 3954 } else { |
3955 context()->Plug(rax); | 3955 context()->Plug(rax); |
3956 } | 3956 } |
3957 break; | 3957 break; |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4307 *context_length = 0; | 4307 *context_length = 0; |
4308 return previous_; | 4308 return previous_; |
4309 } | 4309 } |
4310 | 4310 |
4311 | 4311 |
4312 #undef __ | 4312 #undef __ |
4313 | 4313 |
4314 } } // namespace v8::internal | 4314 } } // namespace v8::internal |
4315 | 4315 |
4316 #endif // V8_TARGET_ARCH_X64 | 4316 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |