Chromium Code Reviews| 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. |
|
Rico
2011/11/15 08:25:07
same comment as on arm,
Steven
2011/11/15 13:33:30
Done.
| |
| 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 |
| 2102 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2099 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2103 } | 2100 } |
| 2104 | 2101 |
| 2105 | 2102 |
| 2106 void FullCodeGenerator::VisitCall(Call* expr) { | 2103 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2107 #ifdef DEBUG | 2104 #ifdef DEBUG |
| (...skipping 1522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3630 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3627 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 3631 switch (expr->op()) { | 3628 switch (expr->op()) { |
| 3632 case Token::DELETE: { | 3629 case Token::DELETE: { |
| 3633 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3630 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 3634 Property* property = expr->expression()->AsProperty(); | 3631 Property* property = expr->expression()->AsProperty(); |
| 3635 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3632 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 3636 | 3633 |
| 3637 if (property != NULL) { | 3634 if (property != NULL) { |
| 3638 VisitForStackValue(property->obj()); | 3635 VisitForStackValue(property->obj()); |
| 3639 VisitForStackValue(property->key()); | 3636 VisitForStackValue(property->key()); |
| 3640 __ Push(Smi::FromInt(strict_mode_flag())); | 3637 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) |
| 3638 ? kNonStrictMode : kStrictMode; | |
| 3639 __ Push(Smi::FromInt(strict_mode_flag)); | |
| 3641 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3640 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 3642 context()->Plug(rax); | 3641 context()->Plug(rax); |
| 3643 } else if (proxy != NULL) { | 3642 } else if (proxy != NULL) { |
| 3644 Variable* var = proxy->var(); | 3643 Variable* var = proxy->var(); |
| 3645 // Delete of an unqualified identifier is disallowed in strict mode | 3644 // Delete of an unqualified identifier is disallowed in strict mode |
| 3646 // but "delete this" is allowed. | 3645 // but "delete this" is allowed. |
| 3647 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); | 3646 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); |
| 3648 if (var->IsUnallocated()) { | 3647 if (var->IsUnallocated()) { |
| 3649 __ push(GlobalObjectOperand()); | 3648 __ push(GlobalObjectOperand()); |
| 3650 __ Push(var->name()); | 3649 __ Push(var->name()); |
| 3651 __ Push(Smi::FromInt(kNonStrictMode)); | 3650 __ Push(Smi::FromInt(kNonStrictMode)); |
| 3652 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3651 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 3653 context()->Plug(rax); | 3652 context()->Plug(rax); |
| 3654 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3653 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 3655 // Result of deleting non-global variables is false. 'this' is | 3654 // Result of deleting non-global variables is false. 'this' is |
| 3656 // not really a variable, though we implement it as one. The | 3655 // not really a variable, though we implement it as one. The |
| 3657 // subexpression does not have side effects. | 3656 // 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 '='. | 3917 // Perform the assignment as if via '='. |
| 3919 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3918 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3920 Token::ASSIGN); | 3919 Token::ASSIGN); |
| 3921 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3920 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3922 context()->Plug(rax); | 3921 context()->Plug(rax); |
| 3923 } | 3922 } |
| 3924 break; | 3923 break; |
| 3925 case NAMED_PROPERTY: { | 3924 case NAMED_PROPERTY: { |
| 3926 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3925 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
| 3927 __ pop(rdx); | 3926 __ pop(rdx); |
| 3928 Handle<Code> ic = is_strict_mode() | 3927 Handle<Code> ic = is_classic_mode() |
| 3929 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3928 ? isolate()->builtins()->StoreIC_Initialize() |
| 3930 : isolate()->builtins()->StoreIC_Initialize(); | 3929 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
| 3931 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3930 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3932 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3931 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3933 if (expr->is_postfix()) { | 3932 if (expr->is_postfix()) { |
| 3934 if (!context()->IsEffect()) { | 3933 if (!context()->IsEffect()) { |
| 3935 context()->PlugTOS(); | 3934 context()->PlugTOS(); |
| 3936 } | 3935 } |
| 3937 } else { | 3936 } else { |
| 3938 context()->Plug(rax); | 3937 context()->Plug(rax); |
| 3939 } | 3938 } |
| 3940 break; | 3939 break; |
| 3941 } | 3940 } |
| 3942 case KEYED_PROPERTY: { | 3941 case KEYED_PROPERTY: { |
| 3943 __ pop(rcx); | 3942 __ pop(rcx); |
| 3944 __ pop(rdx); | 3943 __ pop(rdx); |
| 3945 Handle<Code> ic = is_strict_mode() | 3944 Handle<Code> ic = is_classic_mode() |
| 3946 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3945 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 3947 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3946 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 3948 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3947 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3949 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3948 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3950 if (expr->is_postfix()) { | 3949 if (expr->is_postfix()) { |
| 3951 if (!context()->IsEffect()) { | 3950 if (!context()->IsEffect()) { |
| 3952 context()->PlugTOS(); | 3951 context()->PlugTOS(); |
| 3953 } | 3952 } |
| 3954 } else { | 3953 } else { |
| 3955 context()->Plug(rax); | 3954 context()->Plug(rax); |
| 3956 } | 3955 } |
| 3957 break; | 3956 break; |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4307 *context_length = 0; | 4306 *context_length = 0; |
| 4308 return previous_; | 4307 return previous_; |
| 4309 } | 4308 } |
| 4310 | 4309 |
| 4311 | 4310 |
| 4312 #undef __ | 4311 #undef __ |
| 4313 | 4312 |
| 4314 } } // namespace v8::internal | 4313 } } // namespace v8::internal |
| 4315 | 4314 |
| 4316 #endif // V8_TARGET_ARCH_X64 | 4315 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |