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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 if (strlen(FLAG_stop_at) > 0 && | 124 if (strlen(FLAG_stop_at) > 0 && |
125 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 125 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
126 __ int3(); | 126 __ int3(); |
127 } | 127 } |
128 #endif | 128 #endif |
129 | 129 |
130 // Strict mode functions and builtins need to replace the receiver | 130 // Strict mode functions and builtins need to replace the receiver |
131 // with undefined when called as functions (without an explicit | 131 // with undefined when called as functions (without an explicit |
132 // receiver object). ecx is zero for method calls and non-zero for | 132 // receiver object). ecx is zero for method calls and non-zero for |
133 // function calls. | 133 // function calls. |
134 if (info->is_strict_mode() || info->is_native()) { | 134 if (!info->is_classic_mode() || info->is_native()) { |
135 Label ok; | 135 Label ok; |
136 __ test(ecx, ecx); | 136 __ test(ecx, ecx); |
137 __ j(zero, &ok, Label::kNear); | 137 __ j(zero, &ok, Label::kNear); |
138 // +1 for return address. | 138 // +1 for return address. |
139 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; | 139 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; |
140 __ mov(Operand(esp, receiver_offset), | 140 __ mov(Operand(esp, receiver_offset), |
141 Immediate(isolate()->factory()->undefined_value())); | 141 Immediate(isolate()->factory()->undefined_value())); |
142 __ bind(&ok); | 142 __ bind(&ok); |
143 } | 143 } |
144 | 144 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 int offset = num_parameters * kPointerSize; | 219 int offset = num_parameters * kPointerSize; |
220 __ lea(edx, | 220 __ lea(edx, |
221 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); | 221 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); |
222 __ push(edx); | 222 __ push(edx); |
223 __ SafePush(Immediate(Smi::FromInt(num_parameters))); | 223 __ SafePush(Immediate(Smi::FromInt(num_parameters))); |
224 // Arguments to ArgumentsAccessStub and/or New...: | 224 // Arguments to ArgumentsAccessStub and/or New...: |
225 // function, receiver address, parameter count. | 225 // function, receiver address, parameter count. |
226 // The stub will rewrite receiver and parameter count if the previous | 226 // The stub will rewrite receiver and parameter count if the previous |
227 // stack frame was an arguments adapter frame. | 227 // stack frame was an arguments adapter frame. |
228 ArgumentsAccessStub::Type type; | 228 ArgumentsAccessStub::Type type; |
229 if (is_strict_mode()) { | 229 if (!is_classic_mode()) { |
230 type = ArgumentsAccessStub::NEW_STRICT; | 230 type = ArgumentsAccessStub::NEW_STRICT; |
231 } else if (function()->has_duplicate_parameters()) { | 231 } else if (function()->has_duplicate_parameters()) { |
232 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 232 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; |
233 } else { | 233 } else { |
234 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 234 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; |
235 } | 235 } |
236 ArgumentsAccessStub stub(type); | 236 ArgumentsAccessStub stub(type); |
237 __ CallStub(&stub); | 237 __ CallStub(&stub); |
238 | 238 |
239 SetVar(arguments, eax, ebx, edx); | 239 SetVar(arguments, eax, ebx, edx); |
(...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 // space for nested functions that don't need literals cloning. If | 1058 // space for nested functions that don't need literals cloning. If |
1059 // we're running with the --always-opt or the --prepare-always-opt | 1059 // we're running with the --always-opt or the --prepare-always-opt |
1060 // flag, we need to use the runtime function so that the new function | 1060 // flag, we need to use the runtime function so that the new function |
1061 // we are creating here gets a chance to have its code optimized and | 1061 // we are creating here gets a chance to have its code optimized and |
1062 // doesn't just get a copy of the existing unoptimized code. | 1062 // doesn't just get a copy of the existing unoptimized code. |
1063 if (!FLAG_always_opt && | 1063 if (!FLAG_always_opt && |
1064 !FLAG_prepare_always_opt && | 1064 !FLAG_prepare_always_opt && |
1065 !pretenure && | 1065 !pretenure && |
1066 scope()->is_function_scope() && | 1066 scope()->is_function_scope() && |
1067 info->num_literals() == 0) { | 1067 info->num_literals() == 0) { |
1068 FastNewClosureStub stub(info->strict_mode_flag()); | 1068 FastNewClosureStub stub(info->language_mode()); |
1069 __ push(Immediate(info)); | 1069 __ push(Immediate(info)); |
1070 __ CallStub(&stub); | 1070 __ CallStub(&stub); |
1071 } else { | 1071 } else { |
1072 __ push(esi); | 1072 __ push(esi); |
1073 __ push(Immediate(info)); | 1073 __ push(Immediate(info)); |
1074 __ push(Immediate(pretenure | 1074 __ push(Immediate(pretenure |
1075 ? isolate()->factory()->true_value() | 1075 ? isolate()->factory()->true_value() |
1076 : isolate()->factory()->false_value())); | 1076 : isolate()->factory()->false_value())); |
1077 __ CallRuntime(Runtime::kNewClosure, 3); | 1077 __ CallRuntime(Runtime::kNewClosure, 3); |
1078 } | 1078 } |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 switch (property->kind()) { | 1403 switch (property->kind()) { |
1404 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1404 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1405 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1405 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
1406 // Fall through. | 1406 // Fall through. |
1407 case ObjectLiteral::Property::COMPUTED: | 1407 case ObjectLiteral::Property::COMPUTED: |
1408 if (key->handle()->IsSymbol()) { | 1408 if (key->handle()->IsSymbol()) { |
1409 if (property->emit_store()) { | 1409 if (property->emit_store()) { |
1410 VisitForAccumulatorValue(value); | 1410 VisitForAccumulatorValue(value); |
1411 __ mov(ecx, Immediate(key->handle())); | 1411 __ mov(ecx, Immediate(key->handle())); |
1412 __ mov(edx, Operand(esp, 0)); | 1412 __ mov(edx, Operand(esp, 0)); |
1413 Handle<Code> ic = is_strict_mode() | 1413 Handle<Code> ic = is_classic_mode() |
1414 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1414 ? isolate()->builtins()->StoreIC_Initialize() |
1415 : isolate()->builtins()->StoreIC_Initialize(); | 1415 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1416 __ call(ic, RelocInfo::CODE_TARGET, key->id()); | 1416 __ call(ic, RelocInfo::CODE_TARGET, key->id()); |
1417 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1417 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1418 } else { | 1418 } else { |
1419 VisitForEffect(value); | 1419 VisitForEffect(value); |
1420 } | 1420 } |
1421 break; | 1421 break; |
1422 } | 1422 } |
1423 // Fall through. | 1423 // Fall through. |
1424 case ObjectLiteral::Property::PROTOTYPE: | 1424 case ObjectLiteral::Property::PROTOTYPE: |
1425 __ push(Operand(esp, 0)); // Duplicate receiver. | 1425 __ push(Operand(esp, 0)); // Duplicate receiver. |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1801 EffectContext context(this); | 1801 EffectContext context(this); |
1802 EmitVariableAssignment(var, Token::ASSIGN); | 1802 EmitVariableAssignment(var, Token::ASSIGN); |
1803 break; | 1803 break; |
1804 } | 1804 } |
1805 case NAMED_PROPERTY: { | 1805 case NAMED_PROPERTY: { |
1806 __ push(eax); // Preserve value. | 1806 __ push(eax); // Preserve value. |
1807 VisitForAccumulatorValue(prop->obj()); | 1807 VisitForAccumulatorValue(prop->obj()); |
1808 __ mov(edx, eax); | 1808 __ mov(edx, eax); |
1809 __ pop(eax); // Restore value. | 1809 __ pop(eax); // Restore value. |
1810 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1810 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1811 Handle<Code> ic = is_strict_mode() | 1811 Handle<Code> ic = is_classic_mode() |
1812 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1812 ? isolate()->builtins()->StoreIC_Initialize() |
1813 : isolate()->builtins()->StoreIC_Initialize(); | 1813 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1814 __ call(ic); | 1814 __ call(ic); |
1815 break; | 1815 break; |
1816 } | 1816 } |
1817 case KEYED_PROPERTY: { | 1817 case KEYED_PROPERTY: { |
1818 __ push(eax); // Preserve value. | 1818 __ push(eax); // Preserve value. |
1819 VisitForStackValue(prop->obj()); | 1819 VisitForStackValue(prop->obj()); |
1820 VisitForAccumulatorValue(prop->key()); | 1820 VisitForAccumulatorValue(prop->key()); |
1821 __ mov(ecx, eax); | 1821 __ mov(ecx, eax); |
1822 __ pop(edx); | 1822 __ pop(edx); |
1823 __ pop(eax); // Restore value. | 1823 __ pop(eax); // Restore value. |
1824 Handle<Code> ic = is_strict_mode() | 1824 Handle<Code> ic = is_classic_mode() |
1825 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1825 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1826 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1826 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1827 __ call(ic); | 1827 __ call(ic); |
1828 break; | 1828 break; |
1829 } | 1829 } |
1830 } | 1830 } |
1831 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1831 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1832 context()->Plug(eax); | 1832 context()->Plug(eax); |
1833 } | 1833 } |
1834 | 1834 |
1835 | 1835 |
1836 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1836 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1837 Token::Value op) { | 1837 Token::Value op) { |
1838 if (var->IsUnallocated()) { | 1838 if (var->IsUnallocated()) { |
1839 // Global var, const, or let. | 1839 // Global var, const, or let. |
1840 __ mov(ecx, var->name()); | 1840 __ mov(ecx, var->name()); |
1841 __ mov(edx, GlobalObjectOperand()); | 1841 __ mov(edx, GlobalObjectOperand()); |
1842 Handle<Code> ic = is_strict_mode() | 1842 Handle<Code> ic = is_classic_mode() |
1843 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1843 ? isolate()->builtins()->StoreIC_Initialize() |
1844 : isolate()->builtins()->StoreIC_Initialize(); | 1844 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1845 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1845 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1846 | 1846 |
1847 } else if (op == Token::INIT_CONST) { | 1847 } else if (op == Token::INIT_CONST) { |
1848 // Const initializers need a write barrier. | 1848 // Const initializers need a write barrier. |
1849 ASSERT(!var->IsParameter()); // No const parameters. | 1849 ASSERT(!var->IsParameter()); // No const parameters. |
1850 if (var->IsStackLocal()) { | 1850 if (var->IsStackLocal()) { |
1851 Label skip; | 1851 Label skip; |
1852 __ mov(edx, StackOperand(var)); | 1852 __ mov(edx, StackOperand(var)); |
1853 __ cmp(edx, isolate()->factory()->the_hole_value()); | 1853 __ cmp(edx, isolate()->factory()->the_hole_value()); |
1854 __ j(not_equal, &skip); | 1854 __ j(not_equal, &skip); |
(...skipping 11 matching lines...) Expand all Loading... |
1866 __ push(Immediate(var->name())); | 1866 __ push(Immediate(var->name())); |
1867 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1867 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1868 } | 1868 } |
1869 | 1869 |
1870 } else if (var->mode() == LET && op != Token::INIT_LET) { | 1870 } else if (var->mode() == LET && op != Token::INIT_LET) { |
1871 // Non-initializing assignment to let variable needs a write barrier. | 1871 // Non-initializing assignment to let variable needs a write barrier. |
1872 if (var->IsLookupSlot()) { | 1872 if (var->IsLookupSlot()) { |
1873 __ push(eax); // Value. | 1873 __ push(eax); // Value. |
1874 __ push(esi); // Context. | 1874 __ push(esi); // Context. |
1875 __ push(Immediate(var->name())); | 1875 __ push(Immediate(var->name())); |
1876 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 1876 __ push(Immediate(Smi::FromInt(language_mode()))); |
1877 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1877 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1878 } else { | 1878 } else { |
1879 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 1879 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
1880 Label assign; | 1880 Label assign; |
1881 MemOperand location = VarOperand(var, ecx); | 1881 MemOperand location = VarOperand(var, ecx); |
1882 __ mov(edx, location); | 1882 __ mov(edx, location); |
1883 __ cmp(edx, isolate()->factory()->the_hole_value()); | 1883 __ cmp(edx, isolate()->factory()->the_hole_value()); |
1884 __ j(not_equal, &assign, Label::kNear); | 1884 __ j(not_equal, &assign, Label::kNear); |
1885 __ push(Immediate(var->name())); | 1885 __ push(Immediate(var->name())); |
1886 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1886 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
(...skipping 22 matching lines...) Expand all Loading... |
1909 if (var->IsContextSlot()) { | 1909 if (var->IsContextSlot()) { |
1910 __ mov(edx, eax); | 1910 __ mov(edx, eax); |
1911 int offset = Context::SlotOffset(var->index()); | 1911 int offset = Context::SlotOffset(var->index()); |
1912 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 1912 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
1913 } | 1913 } |
1914 } else { | 1914 } else { |
1915 ASSERT(var->IsLookupSlot()); | 1915 ASSERT(var->IsLookupSlot()); |
1916 __ push(eax); // Value. | 1916 __ push(eax); // Value. |
1917 __ push(esi); // Context. | 1917 __ push(esi); // Context. |
1918 __ push(Immediate(var->name())); | 1918 __ push(Immediate(var->name())); |
1919 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 1919 __ push(Immediate(Smi::FromInt(language_mode()))); |
1920 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1920 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1921 } | 1921 } |
1922 } | 1922 } |
1923 // Non-initializing assignments to consts are ignored. | 1923 // Non-initializing assignments to consts are ignored. |
1924 } | 1924 } |
1925 | 1925 |
1926 | 1926 |
1927 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1927 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1928 // Assignment to a property, using a named store IC. | 1928 // Assignment to a property, using a named store IC. |
1929 Property* prop = expr->target()->AsProperty(); | 1929 Property* prop = expr->target()->AsProperty(); |
(...skipping 11 matching lines...) Expand all Loading... |
1941 } | 1941 } |
1942 | 1942 |
1943 // Record source code position before IC call. | 1943 // Record source code position before IC call. |
1944 SetSourcePosition(expr->position()); | 1944 SetSourcePosition(expr->position()); |
1945 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1945 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1946 if (expr->ends_initialization_block()) { | 1946 if (expr->ends_initialization_block()) { |
1947 __ mov(edx, Operand(esp, 0)); | 1947 __ mov(edx, Operand(esp, 0)); |
1948 } else { | 1948 } else { |
1949 __ pop(edx); | 1949 __ pop(edx); |
1950 } | 1950 } |
1951 Handle<Code> ic = is_strict_mode() | 1951 Handle<Code> ic = is_classic_mode() |
1952 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1952 ? isolate()->builtins()->StoreIC_Initialize() |
1953 : isolate()->builtins()->StoreIC_Initialize(); | 1953 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1954 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 1954 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
1955 | 1955 |
1956 // If the assignment ends an initialization block, revert to fast case. | 1956 // If the assignment ends an initialization block, revert to fast case. |
1957 if (expr->ends_initialization_block()) { | 1957 if (expr->ends_initialization_block()) { |
1958 __ push(eax); // Result of assignment, saved even if not needed. | 1958 __ push(eax); // Result of assignment, saved even if not needed. |
1959 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1959 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
1960 __ CallRuntime(Runtime::kToFastProperties, 1); | 1960 __ CallRuntime(Runtime::kToFastProperties, 1); |
1961 __ pop(eax); | 1961 __ pop(eax); |
1962 __ Drop(1); | 1962 __ Drop(1); |
1963 } | 1963 } |
(...skipping 17 matching lines...) Expand all Loading... |
1981 } | 1981 } |
1982 | 1982 |
1983 __ pop(ecx); | 1983 __ pop(ecx); |
1984 if (expr->ends_initialization_block()) { | 1984 if (expr->ends_initialization_block()) { |
1985 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 1985 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
1986 } else { | 1986 } else { |
1987 __ pop(edx); | 1987 __ pop(edx); |
1988 } | 1988 } |
1989 // Record source code position before IC call. | 1989 // Record source code position before IC call. |
1990 SetSourcePosition(expr->position()); | 1990 SetSourcePosition(expr->position()); |
1991 Handle<Code> ic = is_strict_mode() | 1991 Handle<Code> ic = is_classic_mode() |
1992 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1992 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1993 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1993 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1994 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 1994 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
1995 | 1995 |
1996 // If the assignment ends an initialization block, revert to fast case. | 1996 // If the assignment ends an initialization block, revert to fast case. |
1997 if (expr->ends_initialization_block()) { | 1997 if (expr->ends_initialization_block()) { |
1998 __ pop(edx); | 1998 __ pop(edx); |
1999 __ push(eax); // Result of assignment, saved even if not needed. | 1999 __ push(eax); // Result of assignment, saved even if not needed. |
2000 __ push(edx); | 2000 __ push(edx); |
2001 __ CallRuntime(Runtime::kToFastProperties, 1); | 2001 __ CallRuntime(Runtime::kToFastProperties, 1); |
2002 __ pop(eax); | 2002 __ pop(eax); |
2003 } | 2003 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2127 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2127 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
2128 // Push copy of the first argument or undefined if it doesn't exist. | 2128 // Push copy of the first argument or undefined if it doesn't exist. |
2129 if (arg_count > 0) { | 2129 if (arg_count > 0) { |
2130 __ push(Operand(esp, arg_count * kPointerSize)); | 2130 __ push(Operand(esp, arg_count * kPointerSize)); |
2131 } else { | 2131 } else { |
2132 __ push(Immediate(isolate()->factory()->undefined_value())); | 2132 __ push(Immediate(isolate()->factory()->undefined_value())); |
2133 } | 2133 } |
2134 | 2134 |
2135 // Push the receiver of the enclosing function. | 2135 // Push the receiver of the enclosing function. |
2136 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); | 2136 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); |
2137 | 2137 // Push the language mode. |
2138 // Push the strict mode flag. In harmony mode every eval call | 2138 __ push(Immediate(Smi::FromInt(language_mode()))); |
2139 // is a strict mode eval call. | |
2140 StrictModeFlag strict_mode = | |
2141 FLAG_harmony_scoping ? kStrictMode : strict_mode_flag(); | |
2142 __ push(Immediate(Smi::FromInt(strict_mode))); | |
2143 | 2139 |
2144 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); | 2140 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); |
2145 } | 2141 } |
2146 | 2142 |
2147 | 2143 |
2148 void FullCodeGenerator::VisitCall(Call* expr) { | 2144 void FullCodeGenerator::VisitCall(Call* expr) { |
2149 #ifdef DEBUG | 2145 #ifdef DEBUG |
2150 // We want to verify that RecordJSReturnSite gets called on all paths | 2146 // We want to verify that RecordJSReturnSite gets called on all paths |
2151 // through this function. Avoid early returns. | 2147 // through this function. Avoid early returns. |
2152 expr->return_is_recorded_ = false; | 2148 expr->return_is_recorded_ = false; |
(...skipping 1496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3649 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3645 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
3650 switch (expr->op()) { | 3646 switch (expr->op()) { |
3651 case Token::DELETE: { | 3647 case Token::DELETE: { |
3652 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3648 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3653 Property* property = expr->expression()->AsProperty(); | 3649 Property* property = expr->expression()->AsProperty(); |
3654 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3650 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
3655 | 3651 |
3656 if (property != NULL) { | 3652 if (property != NULL) { |
3657 VisitForStackValue(property->obj()); | 3653 VisitForStackValue(property->obj()); |
3658 VisitForStackValue(property->key()); | 3654 VisitForStackValue(property->key()); |
3659 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 3655 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) |
| 3656 ? kNonStrictMode : kStrictMode; |
| 3657 __ push(Immediate(Smi::FromInt(strict_mode_flag))); |
3660 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3658 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3661 context()->Plug(eax); | 3659 context()->Plug(eax); |
3662 } else if (proxy != NULL) { | 3660 } else if (proxy != NULL) { |
3663 Variable* var = proxy->var(); | 3661 Variable* var = proxy->var(); |
3664 // Delete of an unqualified identifier is disallowed in strict mode | 3662 // Delete of an unqualified identifier is disallowed in strict mode |
3665 // but "delete this" is allowed. | 3663 // but "delete this" is allowed. |
3666 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); | 3664 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); |
3667 if (var->IsUnallocated()) { | 3665 if (var->IsUnallocated()) { |
3668 __ push(GlobalObjectOperand()); | 3666 __ push(GlobalObjectOperand()); |
3669 __ push(Immediate(var->name())); | 3667 __ push(Immediate(var->name())); |
3670 __ push(Immediate(Smi::FromInt(kNonStrictMode))); | 3668 __ push(Immediate(Smi::FromInt(kNonStrictMode))); |
3671 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3669 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3672 context()->Plug(eax); | 3670 context()->Plug(eax); |
3673 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3671 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
3674 // Result of deleting non-global variables is false. 'this' is | 3672 // Result of deleting non-global variables is false. 'this' is |
3675 // not really a variable, though we implement it as one. The | 3673 // not really a variable, though we implement it as one. The |
3676 // subexpression does not have side effects. | 3674 // subexpression does not have side effects. |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3935 // Perform the assignment as if via '='. | 3933 // Perform the assignment as if via '='. |
3936 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3934 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3937 Token::ASSIGN); | 3935 Token::ASSIGN); |
3938 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3936 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3939 context()->Plug(eax); | 3937 context()->Plug(eax); |
3940 } | 3938 } |
3941 break; | 3939 break; |
3942 case NAMED_PROPERTY: { | 3940 case NAMED_PROPERTY: { |
3943 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3941 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
3944 __ pop(edx); | 3942 __ pop(edx); |
3945 Handle<Code> ic = is_strict_mode() | 3943 Handle<Code> ic = is_classic_mode() |
3946 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3944 ? isolate()->builtins()->StoreIC_Initialize() |
3947 : isolate()->builtins()->StoreIC_Initialize(); | 3945 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
3948 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3946 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
3949 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3947 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3950 if (expr->is_postfix()) { | 3948 if (expr->is_postfix()) { |
3951 if (!context()->IsEffect()) { | 3949 if (!context()->IsEffect()) { |
3952 context()->PlugTOS(); | 3950 context()->PlugTOS(); |
3953 } | 3951 } |
3954 } else { | 3952 } else { |
3955 context()->Plug(eax); | 3953 context()->Plug(eax); |
3956 } | 3954 } |
3957 break; | 3955 break; |
3958 } | 3956 } |
3959 case KEYED_PROPERTY: { | 3957 case KEYED_PROPERTY: { |
3960 __ pop(ecx); | 3958 __ pop(ecx); |
3961 __ pop(edx); | 3959 __ pop(edx); |
3962 Handle<Code> ic = is_strict_mode() | 3960 Handle<Code> ic = is_classic_mode() |
3963 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3961 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
3964 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3962 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
3965 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3963 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
3966 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3964 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3967 if (expr->is_postfix()) { | 3965 if (expr->is_postfix()) { |
3968 // Result is on the stack | 3966 // Result is on the stack |
3969 if (!context()->IsEffect()) { | 3967 if (!context()->IsEffect()) { |
3970 context()->PlugTOS(); | 3968 context()->PlugTOS(); |
3971 } | 3969 } |
3972 } else { | 3970 } else { |
3973 context()->Plug(eax); | 3971 context()->Plug(eax); |
3974 } | 3972 } |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4322 *context_length = 0; | 4320 *context_length = 0; |
4323 return previous_; | 4321 return previous_; |
4324 } | 4322 } |
4325 | 4323 |
4326 | 4324 |
4327 #undef __ | 4325 #undef __ |
4328 | 4326 |
4329 } } // namespace v8::internal | 4327 } } // namespace v8::internal |
4330 | 4328 |
4331 #endif // V8_TARGET_ARCH_IA32 | 4329 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |