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). ecx is zero for method calls and non-zero for | 134 // receiver object). ecx 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 __ test(ecx, ecx); | 138 __ test(ecx, ecx); |
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 __ mov(ecx, Operand(esp, receiver_offset)); | 142 __ mov(ecx, Operand(esp, receiver_offset)); |
143 __ JumpIfSmi(ecx, &ok); | 143 __ JumpIfSmi(ecx, &ok); |
144 __ CmpObjectType(ecx, JS_GLOBAL_PROXY_TYPE, ecx); | 144 __ CmpObjectType(ecx, JS_GLOBAL_PROXY_TYPE, ecx); |
145 __ j(not_equal, &ok, Label::kNear); | 145 __ j(not_equal, &ok, Label::kNear); |
146 __ mov(Operand(esp, receiver_offset), | 146 __ mov(Operand(esp, receiver_offset), |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 int offset = num_parameters * kPointerSize; | 225 int offset = num_parameters * kPointerSize; |
226 __ lea(edx, | 226 __ lea(edx, |
227 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); | 227 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); |
228 __ push(edx); | 228 __ push(edx); |
229 __ SafePush(Immediate(Smi::FromInt(num_parameters))); | 229 __ SafePush(Immediate(Smi::FromInt(num_parameters))); |
230 // Arguments to ArgumentsAccessStub and/or New...: | 230 // Arguments to ArgumentsAccessStub and/or New...: |
231 // function, receiver address, parameter count. | 231 // function, receiver address, parameter count. |
232 // The stub will rewrite receiver and parameter count if the previous | 232 // The stub will rewrite receiver and parameter count if the previous |
233 // stack frame was an arguments adapter frame. | 233 // stack frame was an arguments adapter frame. |
234 ArgumentsAccessStub::Type type; | 234 ArgumentsAccessStub::Type type; |
235 if (is_strict_mode()) { | 235 if (!is_classic_mode()) { |
236 type = ArgumentsAccessStub::NEW_STRICT; | 236 type = ArgumentsAccessStub::NEW_STRICT; |
237 } else if (function()->has_duplicate_parameters()) { | 237 } else if (function()->has_duplicate_parameters()) { |
238 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 238 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; |
239 } else { | 239 } else { |
240 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 240 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; |
241 } | 241 } |
242 ArgumentsAccessStub stub(type); | 242 ArgumentsAccessStub stub(type); |
243 __ CallStub(&stub); | 243 __ CallStub(&stub); |
244 | 244 |
245 SetVar(arguments, eax, ebx, edx); | 245 SetVar(arguments, eax, ebx, edx); |
(...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 // space for nested functions that don't need literals cloning. If | 1064 // space for nested functions that don't need literals cloning. If |
1065 // we're running with the --always-opt or the --prepare-always-opt | 1065 // we're running with the --always-opt or the --prepare-always-opt |
1066 // flag, we need to use the runtime function so that the new function | 1066 // flag, we need to use the runtime function so that the new function |
1067 // we are creating here gets a chance to have its code optimized and | 1067 // we are creating here gets a chance to have its code optimized and |
1068 // doesn't just get a copy of the existing unoptimized code. | 1068 // doesn't just get a copy of the existing unoptimized code. |
1069 if (!FLAG_always_opt && | 1069 if (!FLAG_always_opt && |
1070 !FLAG_prepare_always_opt && | 1070 !FLAG_prepare_always_opt && |
1071 !pretenure && | 1071 !pretenure && |
1072 scope()->is_function_scope() && | 1072 scope()->is_function_scope() && |
1073 info->num_literals() == 0) { | 1073 info->num_literals() == 0) { |
1074 FastNewClosureStub stub(info->strict_mode_flag()); | 1074 FastNewClosureStub stub(info->language_mode()); |
1075 __ push(Immediate(info)); | 1075 __ push(Immediate(info)); |
1076 __ CallStub(&stub); | 1076 __ CallStub(&stub); |
1077 } else { | 1077 } else { |
1078 __ push(esi); | 1078 __ push(esi); |
1079 __ push(Immediate(info)); | 1079 __ push(Immediate(info)); |
1080 __ push(Immediate(pretenure | 1080 __ push(Immediate(pretenure |
1081 ? isolate()->factory()->true_value() | 1081 ? isolate()->factory()->true_value() |
1082 : isolate()->factory()->false_value())); | 1082 : isolate()->factory()->false_value())); |
1083 __ CallRuntime(Runtime::kNewClosure, 3); | 1083 __ CallRuntime(Runtime::kNewClosure, 3); |
1084 } | 1084 } |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 switch (property->kind()) { | 1413 switch (property->kind()) { |
1414 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1414 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1415 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1415 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
1416 // Fall through. | 1416 // Fall through. |
1417 case ObjectLiteral::Property::COMPUTED: | 1417 case ObjectLiteral::Property::COMPUTED: |
1418 if (key->handle()->IsSymbol()) { | 1418 if (key->handle()->IsSymbol()) { |
1419 if (property->emit_store()) { | 1419 if (property->emit_store()) { |
1420 VisitForAccumulatorValue(value); | 1420 VisitForAccumulatorValue(value); |
1421 __ mov(ecx, Immediate(key->handle())); | 1421 __ mov(ecx, Immediate(key->handle())); |
1422 __ mov(edx, Operand(esp, 0)); | 1422 __ mov(edx, Operand(esp, 0)); |
1423 Handle<Code> ic = is_strict_mode() | 1423 Handle<Code> ic = is_classic_mode() |
1424 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1424 ? isolate()->builtins()->StoreIC_Initialize() |
1425 : isolate()->builtins()->StoreIC_Initialize(); | 1425 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1426 __ call(ic, RelocInfo::CODE_TARGET, key->id()); | 1426 __ call(ic, RelocInfo::CODE_TARGET, key->id()); |
1427 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1427 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1428 } else { | 1428 } else { |
1429 VisitForEffect(value); | 1429 VisitForEffect(value); |
1430 } | 1430 } |
1431 break; | 1431 break; |
1432 } | 1432 } |
1433 // Fall through. | 1433 // Fall through. |
1434 case ObjectLiteral::Property::PROTOTYPE: | 1434 case ObjectLiteral::Property::PROTOTYPE: |
1435 __ push(Operand(esp, 0)); // Duplicate receiver. | 1435 __ push(Operand(esp, 0)); // Duplicate receiver. |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1811 EffectContext context(this); | 1811 EffectContext context(this); |
1812 EmitVariableAssignment(var, Token::ASSIGN); | 1812 EmitVariableAssignment(var, Token::ASSIGN); |
1813 break; | 1813 break; |
1814 } | 1814 } |
1815 case NAMED_PROPERTY: { | 1815 case NAMED_PROPERTY: { |
1816 __ push(eax); // Preserve value. | 1816 __ push(eax); // Preserve value. |
1817 VisitForAccumulatorValue(prop->obj()); | 1817 VisitForAccumulatorValue(prop->obj()); |
1818 __ mov(edx, eax); | 1818 __ mov(edx, eax); |
1819 __ pop(eax); // Restore value. | 1819 __ pop(eax); // Restore value. |
1820 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1820 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1821 Handle<Code> ic = is_strict_mode() | 1821 Handle<Code> ic = is_classic_mode() |
1822 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1822 ? isolate()->builtins()->StoreIC_Initialize() |
1823 : isolate()->builtins()->StoreIC_Initialize(); | 1823 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1824 __ call(ic); | 1824 __ call(ic); |
1825 break; | 1825 break; |
1826 } | 1826 } |
1827 case KEYED_PROPERTY: { | 1827 case KEYED_PROPERTY: { |
1828 __ push(eax); // Preserve value. | 1828 __ push(eax); // Preserve value. |
1829 VisitForStackValue(prop->obj()); | 1829 VisitForStackValue(prop->obj()); |
1830 VisitForAccumulatorValue(prop->key()); | 1830 VisitForAccumulatorValue(prop->key()); |
1831 __ mov(ecx, eax); | 1831 __ mov(ecx, eax); |
1832 __ pop(edx); | 1832 __ pop(edx); |
1833 __ pop(eax); // Restore value. | 1833 __ pop(eax); // Restore value. |
1834 Handle<Code> ic = is_strict_mode() | 1834 Handle<Code> ic = is_classic_mode() |
1835 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1835 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1836 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1836 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1837 __ call(ic); | 1837 __ call(ic); |
1838 break; | 1838 break; |
1839 } | 1839 } |
1840 } | 1840 } |
1841 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1841 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1842 context()->Plug(eax); | 1842 context()->Plug(eax); |
1843 } | 1843 } |
1844 | 1844 |
1845 | 1845 |
1846 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1846 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1847 Token::Value op) { | 1847 Token::Value op) { |
1848 if (var->IsUnallocated()) { | 1848 if (var->IsUnallocated()) { |
1849 // Global var, const, or let. | 1849 // Global var, const, or let. |
1850 __ mov(ecx, var->name()); | 1850 __ mov(ecx, var->name()); |
1851 __ mov(edx, GlobalObjectOperand()); | 1851 __ mov(edx, GlobalObjectOperand()); |
1852 Handle<Code> ic = is_strict_mode() | 1852 Handle<Code> ic = is_classic_mode() |
1853 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1853 ? isolate()->builtins()->StoreIC_Initialize() |
1854 : isolate()->builtins()->StoreIC_Initialize(); | 1854 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1855 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1855 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1856 | 1856 |
1857 } else if (op == Token::INIT_CONST) { | 1857 } else if (op == Token::INIT_CONST) { |
1858 // Const initializers need a write barrier. | 1858 // Const initializers need a write barrier. |
1859 ASSERT(!var->IsParameter()); // No const parameters. | 1859 ASSERT(!var->IsParameter()); // No const parameters. |
1860 if (var->IsStackLocal()) { | 1860 if (var->IsStackLocal()) { |
1861 Label skip; | 1861 Label skip; |
1862 __ mov(edx, StackOperand(var)); | 1862 __ mov(edx, StackOperand(var)); |
1863 __ cmp(edx, isolate()->factory()->the_hole_value()); | 1863 __ cmp(edx, isolate()->factory()->the_hole_value()); |
1864 __ j(not_equal, &skip); | 1864 __ j(not_equal, &skip); |
(...skipping 11 matching lines...) Expand all Loading... |
1876 __ push(Immediate(var->name())); | 1876 __ push(Immediate(var->name())); |
1877 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1877 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1878 } | 1878 } |
1879 | 1879 |
1880 } else if (var->mode() == LET && op != Token::INIT_LET) { | 1880 } else if (var->mode() == LET && op != Token::INIT_LET) { |
1881 // Non-initializing assignment to let variable needs a write barrier. | 1881 // Non-initializing assignment to let variable needs a write barrier. |
1882 if (var->IsLookupSlot()) { | 1882 if (var->IsLookupSlot()) { |
1883 __ push(eax); // Value. | 1883 __ push(eax); // Value. |
1884 __ push(esi); // Context. | 1884 __ push(esi); // Context. |
1885 __ push(Immediate(var->name())); | 1885 __ push(Immediate(var->name())); |
1886 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 1886 __ push(Immediate(Smi::FromInt(language_mode()))); |
1887 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1887 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1888 } else { | 1888 } else { |
1889 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 1889 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
1890 Label assign; | 1890 Label assign; |
1891 MemOperand location = VarOperand(var, ecx); | 1891 MemOperand location = VarOperand(var, ecx); |
1892 __ mov(edx, location); | 1892 __ mov(edx, location); |
1893 __ cmp(edx, isolate()->factory()->the_hole_value()); | 1893 __ cmp(edx, isolate()->factory()->the_hole_value()); |
1894 __ j(not_equal, &assign, Label::kNear); | 1894 __ j(not_equal, &assign, Label::kNear); |
1895 __ push(Immediate(var->name())); | 1895 __ push(Immediate(var->name())); |
1896 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1896 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
(...skipping 22 matching lines...) Expand all Loading... |
1919 if (var->IsContextSlot()) { | 1919 if (var->IsContextSlot()) { |
1920 __ mov(edx, eax); | 1920 __ mov(edx, eax); |
1921 int offset = Context::SlotOffset(var->index()); | 1921 int offset = Context::SlotOffset(var->index()); |
1922 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 1922 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
1923 } | 1923 } |
1924 } else { | 1924 } else { |
1925 ASSERT(var->IsLookupSlot()); | 1925 ASSERT(var->IsLookupSlot()); |
1926 __ push(eax); // Value. | 1926 __ push(eax); // Value. |
1927 __ push(esi); // Context. | 1927 __ push(esi); // Context. |
1928 __ push(Immediate(var->name())); | 1928 __ push(Immediate(var->name())); |
1929 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 1929 __ push(Immediate(Smi::FromInt(language_mode()))); |
1930 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1930 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1931 } | 1931 } |
1932 } | 1932 } |
1933 // Non-initializing assignments to consts are ignored. | 1933 // Non-initializing assignments to consts are ignored. |
1934 } | 1934 } |
1935 | 1935 |
1936 | 1936 |
1937 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1937 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1938 // Assignment to a property, using a named store IC. | 1938 // Assignment to a property, using a named store IC. |
1939 Property* prop = expr->target()->AsProperty(); | 1939 Property* prop = expr->target()->AsProperty(); |
(...skipping 11 matching lines...) Expand all Loading... |
1951 } | 1951 } |
1952 | 1952 |
1953 // Record source code position before IC call. | 1953 // Record source code position before IC call. |
1954 SetSourcePosition(expr->position()); | 1954 SetSourcePosition(expr->position()); |
1955 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1955 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1956 if (expr->ends_initialization_block()) { | 1956 if (expr->ends_initialization_block()) { |
1957 __ mov(edx, Operand(esp, 0)); | 1957 __ mov(edx, Operand(esp, 0)); |
1958 } else { | 1958 } else { |
1959 __ pop(edx); | 1959 __ pop(edx); |
1960 } | 1960 } |
1961 Handle<Code> ic = is_strict_mode() | 1961 Handle<Code> ic = is_classic_mode() |
1962 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1962 ? isolate()->builtins()->StoreIC_Initialize() |
1963 : isolate()->builtins()->StoreIC_Initialize(); | 1963 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1964 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 1964 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
1965 | 1965 |
1966 // If the assignment ends an initialization block, revert to fast case. | 1966 // If the assignment ends an initialization block, revert to fast case. |
1967 if (expr->ends_initialization_block()) { | 1967 if (expr->ends_initialization_block()) { |
1968 __ push(eax); // Result of assignment, saved even if not needed. | 1968 __ push(eax); // Result of assignment, saved even if not needed. |
1969 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1969 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
1970 __ CallRuntime(Runtime::kToFastProperties, 1); | 1970 __ CallRuntime(Runtime::kToFastProperties, 1); |
1971 __ pop(eax); | 1971 __ pop(eax); |
1972 __ Drop(1); | 1972 __ Drop(1); |
1973 } | 1973 } |
(...skipping 17 matching lines...) Expand all Loading... |
1991 } | 1991 } |
1992 | 1992 |
1993 __ pop(ecx); | 1993 __ pop(ecx); |
1994 if (expr->ends_initialization_block()) { | 1994 if (expr->ends_initialization_block()) { |
1995 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 1995 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
1996 } else { | 1996 } else { |
1997 __ pop(edx); | 1997 __ pop(edx); |
1998 } | 1998 } |
1999 // Record source code position before IC call. | 1999 // Record source code position before IC call. |
2000 SetSourcePosition(expr->position()); | 2000 SetSourcePosition(expr->position()); |
2001 Handle<Code> ic = is_strict_mode() | 2001 Handle<Code> ic = is_classic_mode() |
2002 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 2002 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2003 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 2003 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2004 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2004 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
2005 | 2005 |
2006 // If the assignment ends an initialization block, revert to fast case. | 2006 // If the assignment ends an initialization block, revert to fast case. |
2007 if (expr->ends_initialization_block()) { | 2007 if (expr->ends_initialization_block()) { |
2008 __ pop(edx); | 2008 __ pop(edx); |
2009 __ push(eax); // Result of assignment, saved even if not needed. | 2009 __ push(eax); // Result of assignment, saved even if not needed. |
2010 __ push(edx); | 2010 __ push(edx); |
2011 __ CallRuntime(Runtime::kToFastProperties, 1); | 2011 __ CallRuntime(Runtime::kToFastProperties, 1); |
2012 __ pop(eax); | 2012 __ pop(eax); |
2013 } | 2013 } |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2138 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2138 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
2139 // Push copy of the first argument or undefined if it doesn't exist. | 2139 // Push copy of the first argument or undefined if it doesn't exist. |
2140 if (arg_count > 0) { | 2140 if (arg_count > 0) { |
2141 __ push(Operand(esp, arg_count * kPointerSize)); | 2141 __ push(Operand(esp, arg_count * kPointerSize)); |
2142 } else { | 2142 } else { |
2143 __ push(Immediate(isolate()->factory()->undefined_value())); | 2143 __ push(Immediate(isolate()->factory()->undefined_value())); |
2144 } | 2144 } |
2145 | 2145 |
2146 // Push the receiver of the enclosing function. | 2146 // Push the receiver of the enclosing function. |
2147 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); | 2147 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); |
2148 | 2148 // Push the language mode. |
2149 // Push the strict mode flag. In harmony mode every eval call | 2149 __ push(Immediate(Smi::FromInt(language_mode()))); |
2150 // is a strict mode eval call. | |
2151 StrictModeFlag strict_mode = | |
2152 FLAG_harmony_scoping ? kStrictMode : strict_mode_flag(); | |
2153 __ push(Immediate(Smi::FromInt(strict_mode))); | |
2154 | 2150 |
2155 // Push the start position of the scope the calls resides in. | 2151 // Push the start position of the scope the calls resides in. |
2156 __ push(Immediate(Smi::FromInt(scope()->start_position()))); | 2152 __ push(Immediate(Smi::FromInt(scope()->start_position()))); |
2157 | 2153 |
| 2154 // Do the runtime call. |
2158 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2155 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
2159 } | 2156 } |
2160 | 2157 |
2161 | 2158 |
2162 void FullCodeGenerator::VisitCall(Call* expr) { | 2159 void FullCodeGenerator::VisitCall(Call* expr) { |
2163 #ifdef DEBUG | 2160 #ifdef DEBUG |
2164 // We want to verify that RecordJSReturnSite gets called on all paths | 2161 // We want to verify that RecordJSReturnSite gets called on all paths |
2165 // through this function. Avoid early returns. | 2162 // through this function. Avoid early returns. |
2166 expr->return_is_recorded_ = false; | 2163 expr->return_is_recorded_ = false; |
2167 #endif | 2164 #endif |
(...skipping 1504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3672 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3669 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
3673 switch (expr->op()) { | 3670 switch (expr->op()) { |
3674 case Token::DELETE: { | 3671 case Token::DELETE: { |
3675 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3672 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3676 Property* property = expr->expression()->AsProperty(); | 3673 Property* property = expr->expression()->AsProperty(); |
3677 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3674 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
3678 | 3675 |
3679 if (property != NULL) { | 3676 if (property != NULL) { |
3680 VisitForStackValue(property->obj()); | 3677 VisitForStackValue(property->obj()); |
3681 VisitForStackValue(property->key()); | 3678 VisitForStackValue(property->key()); |
3682 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 3679 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) |
| 3680 ? kNonStrictMode : kStrictMode; |
| 3681 __ push(Immediate(Smi::FromInt(strict_mode_flag))); |
3683 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3682 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3684 context()->Plug(eax); | 3683 context()->Plug(eax); |
3685 } else if (proxy != NULL) { | 3684 } else if (proxy != NULL) { |
3686 Variable* var = proxy->var(); | 3685 Variable* var = proxy->var(); |
3687 // Delete of an unqualified identifier is disallowed in strict mode | 3686 // Delete of an unqualified identifier is disallowed in strict mode |
3688 // but "delete this" is allowed. | 3687 // but "delete this" is allowed. |
3689 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); | 3688 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); |
3690 if (var->IsUnallocated()) { | 3689 if (var->IsUnallocated()) { |
3691 __ push(GlobalObjectOperand()); | 3690 __ push(GlobalObjectOperand()); |
3692 __ push(Immediate(var->name())); | 3691 __ push(Immediate(var->name())); |
3693 __ push(Immediate(Smi::FromInt(kNonStrictMode))); | 3692 __ push(Immediate(Smi::FromInt(kNonStrictMode))); |
3694 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3693 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3695 context()->Plug(eax); | 3694 context()->Plug(eax); |
3696 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3695 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
3697 // Result of deleting non-global variables is false. 'this' is | 3696 // Result of deleting non-global variables is false. 'this' is |
3698 // not really a variable, though we implement it as one. The | 3697 // not really a variable, though we implement it as one. The |
3699 // subexpression does not have side effects. | 3698 // subexpression does not have side effects. |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3958 // Perform the assignment as if via '='. | 3957 // Perform the assignment as if via '='. |
3959 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3958 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3960 Token::ASSIGN); | 3959 Token::ASSIGN); |
3961 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3960 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3962 context()->Plug(eax); | 3961 context()->Plug(eax); |
3963 } | 3962 } |
3964 break; | 3963 break; |
3965 case NAMED_PROPERTY: { | 3964 case NAMED_PROPERTY: { |
3966 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3965 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
3967 __ pop(edx); | 3966 __ pop(edx); |
3968 Handle<Code> ic = is_strict_mode() | 3967 Handle<Code> ic = is_classic_mode() |
3969 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3968 ? isolate()->builtins()->StoreIC_Initialize() |
3970 : isolate()->builtins()->StoreIC_Initialize(); | 3969 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
3971 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3970 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
3972 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3971 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3973 if (expr->is_postfix()) { | 3972 if (expr->is_postfix()) { |
3974 if (!context()->IsEffect()) { | 3973 if (!context()->IsEffect()) { |
3975 context()->PlugTOS(); | 3974 context()->PlugTOS(); |
3976 } | 3975 } |
3977 } else { | 3976 } else { |
3978 context()->Plug(eax); | 3977 context()->Plug(eax); |
3979 } | 3978 } |
3980 break; | 3979 break; |
3981 } | 3980 } |
3982 case KEYED_PROPERTY: { | 3981 case KEYED_PROPERTY: { |
3983 __ pop(ecx); | 3982 __ pop(ecx); |
3984 __ pop(edx); | 3983 __ pop(edx); |
3985 Handle<Code> ic = is_strict_mode() | 3984 Handle<Code> ic = is_classic_mode() |
3986 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3985 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
3987 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3986 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
3988 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 3987 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
3989 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3988 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3990 if (expr->is_postfix()) { | 3989 if (expr->is_postfix()) { |
3991 // Result is on the stack | 3990 // Result is on the stack |
3992 if (!context()->IsEffect()) { | 3991 if (!context()->IsEffect()) { |
3993 context()->PlugTOS(); | 3992 context()->PlugTOS(); |
3994 } | 3993 } |
3995 } else { | 3994 } else { |
3996 context()->Plug(eax); | 3995 context()->Plug(eax); |
3997 } | 3996 } |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4345 *context_length = 0; | 4344 *context_length = 0; |
4346 return previous_; | 4345 return previous_; |
4347 } | 4346 } |
4348 | 4347 |
4349 | 4348 |
4350 #undef __ | 4349 #undef __ |
4351 | 4350 |
4352 } } // namespace v8::internal | 4351 } } // namespace v8::internal |
4353 | 4352 |
4354 #endif // V8_TARGET_ARCH_IA32 | 4353 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |