| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 904 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
| 905 __ test(eax, Operand(eax)); | 905 __ test(eax, Operand(eax)); |
| 906 __ j(equal, loop_statement.continue_target()); | 906 __ j(equal, loop_statement.continue_target()); |
| 907 __ mov(ebx, Operand(eax)); | 907 __ mov(ebx, Operand(eax)); |
| 908 | 908 |
| 909 // Update the 'each' property or variable from the possibly filtered | 909 // Update the 'each' property or variable from the possibly filtered |
| 910 // entry in register ebx. | 910 // entry in register ebx. |
| 911 __ bind(&update_each); | 911 __ bind(&update_each); |
| 912 __ mov(result_register(), ebx); | 912 __ mov(result_register(), ebx); |
| 913 // Perform the assignment as if via '='. | 913 // Perform the assignment as if via '='. |
| 914 { EffectContext context(this); | 914 EmitAssignment(stmt->each()); |
| 915 EmitAssignment(stmt->each(), stmt->AssignmentId()); | |
| 916 } | |
| 917 | 915 |
| 918 // Generate code for the body of the loop. | 916 // Generate code for the body of the loop. |
| 919 Visit(stmt->body()); | 917 Visit(stmt->body()); |
| 920 | 918 |
| 921 // Generate code for going to the next element by incrementing the | 919 // Generate code for going to the next element by incrementing the |
| 922 // index (smi) stored on top of the stack. | 920 // index (smi) stored on top of the stack. |
| 923 __ bind(loop_statement.continue_target()); | 921 __ bind(loop_statement.continue_target()); |
| 924 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); | 922 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); |
| 925 | 923 |
| 926 EmitStackCheck(stmt); | 924 EmitStackCheck(stmt); |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1473 break; | 1471 break; |
| 1474 case KEYED_PROPERTY: | 1472 case KEYED_PROPERTY: |
| 1475 EmitKeyedPropertyLoad(property); | 1473 EmitKeyedPropertyLoad(property); |
| 1476 break; | 1474 break; |
| 1477 } | 1475 } |
| 1478 } | 1476 } |
| 1479 | 1477 |
| 1480 // For property compound assignments we need another deoptimization | 1478 // For property compound assignments we need another deoptimization |
| 1481 // point after the property load. | 1479 // point after the property load. |
| 1482 if (property != NULL) { | 1480 if (property != NULL) { |
| 1483 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | 1481 PrepareForBailoutForId(expr->compound_bailout_id(), TOS_REG); |
| 1484 } | 1482 } |
| 1485 | 1483 |
| 1486 Token::Value op = expr->binary_op(); | 1484 Token::Value op = expr->binary_op(); |
| 1487 ConstantOperand constant = ShouldInlineSmiCase(op) | 1485 ConstantOperand constant = ShouldInlineSmiCase(op) |
| 1488 ? GetConstantOperand(op, expr->target(), expr->value()) | 1486 ? GetConstantOperand(op, expr->target(), expr->value()) |
| 1489 : kNoConstants; | 1487 : kNoConstants; |
| 1490 ASSERT(constant == kRightConstant || constant == kNoConstants); | 1488 ASSERT(constant == kRightConstant || constant == kNoConstants); |
| 1491 if (constant == kNoConstants) { | 1489 if (constant == kNoConstants) { |
| 1492 __ push(eax); // Left operand goes on the stack. | 1490 __ push(eax); // Left operand goes on the stack. |
| 1493 VisitForAccumulatorValue(expr->value()); | 1491 VisitForAccumulatorValue(expr->value()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1516 } | 1514 } |
| 1517 | 1515 |
| 1518 // Record source position before possible IC call. | 1516 // Record source position before possible IC call. |
| 1519 SetSourcePosition(expr->position()); | 1517 SetSourcePosition(expr->position()); |
| 1520 | 1518 |
| 1521 // Store the value. | 1519 // Store the value. |
| 1522 switch (assign_type) { | 1520 switch (assign_type) { |
| 1523 case VARIABLE: | 1521 case VARIABLE: |
| 1524 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1522 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
| 1525 expr->op()); | 1523 expr->op()); |
| 1526 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | |
| 1527 context()->Plug(eax); | |
| 1528 break; | 1524 break; |
| 1529 case NAMED_PROPERTY: | 1525 case NAMED_PROPERTY: |
| 1530 EmitNamedPropertyAssignment(expr); | 1526 EmitNamedPropertyAssignment(expr); |
| 1531 break; | 1527 break; |
| 1532 case KEYED_PROPERTY: | 1528 case KEYED_PROPERTY: |
| 1533 EmitKeyedPropertyAssignment(expr); | 1529 EmitKeyedPropertyAssignment(expr); |
| 1534 break; | 1530 break; |
| 1535 } | 1531 } |
| 1536 } | 1532 } |
| 1537 | 1533 |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1846 | 1842 |
| 1847 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1843 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
| 1848 OverwriteMode mode) { | 1844 OverwriteMode mode) { |
| 1849 __ pop(edx); | 1845 __ pop(edx); |
| 1850 TypeRecordingBinaryOpStub stub(op, mode); | 1846 TypeRecordingBinaryOpStub stub(op, mode); |
| 1851 __ CallStub(&stub); | 1847 __ CallStub(&stub); |
| 1852 context()->Plug(eax); | 1848 context()->Plug(eax); |
| 1853 } | 1849 } |
| 1854 | 1850 |
| 1855 | 1851 |
| 1856 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1852 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 1857 // Invalid left-hand sides are rewritten to have a 'throw | 1853 // Invalid left-hand sides are rewritten to have a 'throw |
| 1858 // ReferenceError' on the left-hand side. | 1854 // ReferenceError' on the left-hand side. |
| 1859 if (!expr->IsValidLeftHandSide()) { | 1855 if (!expr->IsValidLeftHandSide()) { |
| 1860 VisitForEffect(expr); | 1856 VisitForEffect(expr); |
| 1861 return; | 1857 return; |
| 1862 } | 1858 } |
| 1863 | 1859 |
| 1864 // Left-hand side can only be a property, a global or a (parameter or local) | 1860 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1865 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1861 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 1866 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1862 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1894 VisitForStackValue(prop->obj()); | 1890 VisitForStackValue(prop->obj()); |
| 1895 VisitForAccumulatorValue(prop->key()); | 1891 VisitForAccumulatorValue(prop->key()); |
| 1896 __ mov(ecx, eax); | 1892 __ mov(ecx, eax); |
| 1897 __ pop(edx); | 1893 __ pop(edx); |
| 1898 __ pop(eax); // Restore value. | 1894 __ pop(eax); // Restore value. |
| 1899 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1895 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1900 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1896 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1901 break; | 1897 break; |
| 1902 } | 1898 } |
| 1903 } | 1899 } |
| 1904 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | |
| 1905 context()->Plug(eax); | |
| 1906 } | 1900 } |
| 1907 | 1901 |
| 1908 | 1902 |
| 1909 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1903 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1910 Token::Value op) { | 1904 Token::Value op) { |
| 1911 // Left-hand sides that rewrite to explicit property accesses do not reach | 1905 // Left-hand sides that rewrite to explicit property accesses do not reach |
| 1912 // here. | 1906 // here. |
| 1913 ASSERT(var != NULL); | 1907 ASSERT(var != NULL); |
| 1914 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1908 ASSERT(var->is_global() || var->AsSlot() != NULL); |
| 1915 | 1909 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1968 if (op == Token::INIT_CONST) { | 1962 if (op == Token::INIT_CONST) { |
| 1969 // The runtime will ignore const redeclaration. | 1963 // The runtime will ignore const redeclaration. |
| 1970 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1964 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 1971 } else { | 1965 } else { |
| 1972 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1966 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
| 1973 } | 1967 } |
| 1974 break; | 1968 break; |
| 1975 } | 1969 } |
| 1976 __ bind(&done); | 1970 __ bind(&done); |
| 1977 } | 1971 } |
| 1972 |
| 1973 context()->Plug(eax); |
| 1978 } | 1974 } |
| 1979 | 1975 |
| 1980 | 1976 |
| 1981 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1977 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 1982 // Assignment to a property, using a named store IC. | 1978 // Assignment to a property, using a named store IC. |
| 1983 Property* prop = expr->target()->AsProperty(); | 1979 Property* prop = expr->target()->AsProperty(); |
| 1984 ASSERT(prop != NULL); | 1980 ASSERT(prop != NULL); |
| 1985 ASSERT(prop->key()->AsLiteral() != NULL); | 1981 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1986 | 1982 |
| 1987 // If the assignment starts a block of assignments to the same object, | 1983 // If the assignment starts a block of assignments to the same object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2004 } | 2000 } |
| 2005 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 2001 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 2006 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2002 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 2007 | 2003 |
| 2008 // If the assignment ends an initialization block, revert to fast case. | 2004 // If the assignment ends an initialization block, revert to fast case. |
| 2009 if (expr->ends_initialization_block()) { | 2005 if (expr->ends_initialization_block()) { |
| 2010 __ push(eax); // Result of assignment, saved even if not needed. | 2006 __ push(eax); // Result of assignment, saved even if not needed. |
| 2011 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 2007 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
| 2012 __ CallRuntime(Runtime::kToFastProperties, 1); | 2008 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2013 __ pop(eax); | 2009 __ pop(eax); |
| 2014 __ Drop(1); | 2010 context()->DropAndPlug(1, eax); |
| 2011 } else { |
| 2012 context()->Plug(eax); |
| 2015 } | 2013 } |
| 2016 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | |
| 2017 context()->Plug(eax); | |
| 2018 } | 2014 } |
| 2019 | 2015 |
| 2020 | 2016 |
| 2021 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2017 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2022 // Assignment to a property, using a keyed store IC. | 2018 // Assignment to a property, using a keyed store IC. |
| 2023 | 2019 |
| 2024 // If the assignment starts a block of assignments to the same object, | 2020 // If the assignment starts a block of assignments to the same object, |
| 2025 // change to slow case to avoid the quadratic behavior of repeatedly | 2021 // change to slow case to avoid the quadratic behavior of repeatedly |
| 2026 // adding fast properties. | 2022 // adding fast properties. |
| 2027 if (expr->starts_initialization_block()) { | 2023 if (expr->starts_initialization_block()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2045 | 2041 |
| 2046 // If the assignment ends an initialization block, revert to fast case. | 2042 // If the assignment ends an initialization block, revert to fast case. |
| 2047 if (expr->ends_initialization_block()) { | 2043 if (expr->ends_initialization_block()) { |
| 2048 __ pop(edx); | 2044 __ pop(edx); |
| 2049 __ push(eax); // Result of assignment, saved even if not needed. | 2045 __ push(eax); // Result of assignment, saved even if not needed. |
| 2050 __ push(edx); | 2046 __ push(edx); |
| 2051 __ CallRuntime(Runtime::kToFastProperties, 1); | 2047 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2052 __ pop(eax); | 2048 __ pop(eax); |
| 2053 } | 2049 } |
| 2054 | 2050 |
| 2055 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | |
| 2056 context()->Plug(eax); | 2051 context()->Plug(eax); |
| 2057 } | 2052 } |
| 2058 | 2053 |
| 2059 | 2054 |
| 2060 void FullCodeGenerator::VisitProperty(Property* expr) { | 2055 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2061 Comment cmnt(masm_, "[ Property"); | 2056 Comment cmnt(masm_, "[ Property"); |
| 2062 Expression* key = expr->key(); | 2057 Expression* key = expr->key(); |
| 2063 | 2058 |
| 2064 if (key->IsPropertyName()) { | 2059 if (key->IsPropertyName()) { |
| 2065 VisitForAccumulatorValue(expr->obj()); | 2060 VisitForAccumulatorValue(expr->obj()); |
| (...skipping 1681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3747 __ bind(&done); | 3742 __ bind(&done); |
| 3748 | 3743 |
| 3749 // Store the value returned in eax. | 3744 // Store the value returned in eax. |
| 3750 switch (assign_type) { | 3745 switch (assign_type) { |
| 3751 case VARIABLE: | 3746 case VARIABLE: |
| 3752 if (expr->is_postfix()) { | 3747 if (expr->is_postfix()) { |
| 3753 // Perform the assignment as if via '='. | 3748 // Perform the assignment as if via '='. |
| 3754 { EffectContext context(this); | 3749 { EffectContext context(this); |
| 3755 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3750 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3756 Token::ASSIGN); | 3751 Token::ASSIGN); |
| 3757 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | |
| 3758 context.Plug(eax); | |
| 3759 } | 3752 } |
| 3760 // For all contexts except EffectContext We have the result on | 3753 // For all contexts except EffectContext We have the result on |
| 3761 // top of the stack. | 3754 // top of the stack. |
| 3762 if (!context()->IsEffect()) { | 3755 if (!context()->IsEffect()) { |
| 3763 context()->PlugTOS(); | 3756 context()->PlugTOS(); |
| 3764 } | 3757 } |
| 3765 } else { | 3758 } else { |
| 3766 // Perform the assignment as if via '='. | 3759 // Perform the assignment as if via '='. |
| 3767 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3760 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3768 Token::ASSIGN); | 3761 Token::ASSIGN); |
| 3769 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | |
| 3770 context()->Plug(eax); | |
| 3771 } | 3762 } |
| 3772 break; | 3763 break; |
| 3773 case NAMED_PROPERTY: { | 3764 case NAMED_PROPERTY: { |
| 3774 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3765 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 3775 __ pop(edx); | 3766 __ pop(edx); |
| 3776 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3767 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 3777 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3768 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3778 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | |
| 3779 if (expr->is_postfix()) { | 3769 if (expr->is_postfix()) { |
| 3780 if (!context()->IsEffect()) { | 3770 if (!context()->IsEffect()) { |
| 3781 context()->PlugTOS(); | 3771 context()->PlugTOS(); |
| 3782 } | 3772 } |
| 3783 } else { | 3773 } else { |
| 3784 context()->Plug(eax); | 3774 context()->Plug(eax); |
| 3785 } | 3775 } |
| 3786 break; | 3776 break; |
| 3787 } | 3777 } |
| 3788 case KEYED_PROPERTY: { | 3778 case KEYED_PROPERTY: { |
| 3789 __ pop(ecx); | 3779 __ pop(ecx); |
| 3790 __ pop(edx); | 3780 __ pop(edx); |
| 3791 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 3781 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 3792 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3782 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3793 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | |
| 3794 if (expr->is_postfix()) { | 3783 if (expr->is_postfix()) { |
| 3795 // Result is on the stack | 3784 // Result is on the stack |
| 3796 if (!context()->IsEffect()) { | 3785 if (!context()->IsEffect()) { |
| 3797 context()->PlugTOS(); | 3786 context()->PlugTOS(); |
| 3798 } | 3787 } |
| 3799 } else { | 3788 } else { |
| 3800 context()->Plug(eax); | 3789 context()->Plug(eax); |
| 3801 } | 3790 } |
| 3802 break; | 3791 break; |
| 3803 } | 3792 } |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4174 // And return. | 4163 // And return. |
| 4175 __ ret(0); | 4164 __ ret(0); |
| 4176 } | 4165 } |
| 4177 | 4166 |
| 4178 | 4167 |
| 4179 #undef __ | 4168 #undef __ |
| 4180 | 4169 |
| 4181 } } // namespace v8::internal | 4170 } } // namespace v8::internal |
| 4182 | 4171 |
| 4183 #endif // V8_TARGET_ARCH_IA32 | 4172 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |