| 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_strict_or_extended_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_strict_or_extended_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 |