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 |