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 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 944 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
945 __ test(eax, Operand(eax)); | 945 __ test(eax, Operand(eax)); |
946 __ j(equal, loop_statement.continue_target()); | 946 __ j(equal, loop_statement.continue_target()); |
947 __ mov(ebx, Operand(eax)); | 947 __ mov(ebx, Operand(eax)); |
948 | 948 |
949 // Update the 'each' property or variable from the possibly filtered | 949 // Update the 'each' property or variable from the possibly filtered |
950 // entry in register ebx. | 950 // entry in register ebx. |
951 __ bind(&update_each); | 951 __ bind(&update_each); |
952 __ mov(result_register(), ebx); | 952 __ mov(result_register(), ebx); |
953 // Perform the assignment as if via '='. | 953 // Perform the assignment as if via '='. |
954 EmitAssignment(stmt->each()); | 954 { EffectContext context(this); |
| 955 EmitAssignment(stmt->each(), stmt->AssignmentId()); |
| 956 } |
955 | 957 |
956 // Generate code for the body of the loop. | 958 // Generate code for the body of the loop. |
957 Visit(stmt->body()); | 959 Visit(stmt->body()); |
958 | 960 |
959 // Generate code for going to the next element by incrementing the | 961 // Generate code for going to the next element by incrementing the |
960 // index (smi) stored on top of the stack. | 962 // index (smi) stored on top of the stack. |
961 __ bind(loop_statement.continue_target()); | 963 __ bind(loop_statement.continue_target()); |
962 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); | 964 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); |
963 | 965 |
964 EmitStackCheck(stmt); | 966 EmitStackCheck(stmt); |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 break; | 1513 break; |
1512 case KEYED_PROPERTY: | 1514 case KEYED_PROPERTY: |
1513 EmitKeyedPropertyLoad(property); | 1515 EmitKeyedPropertyLoad(property); |
1514 break; | 1516 break; |
1515 } | 1517 } |
1516 } | 1518 } |
1517 | 1519 |
1518 // For property compound assignments we need another deoptimization | 1520 // For property compound assignments we need another deoptimization |
1519 // point after the property load. | 1521 // point after the property load. |
1520 if (property != NULL) { | 1522 if (property != NULL) { |
1521 PrepareForBailoutForId(expr->compound_bailout_id(), TOS_REG); | 1523 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
1522 } | 1524 } |
1523 | 1525 |
1524 Token::Value op = expr->binary_op(); | 1526 Token::Value op = expr->binary_op(); |
1525 ConstantOperand constant = ShouldInlineSmiCase(op) | 1527 ConstantOperand constant = ShouldInlineSmiCase(op) |
1526 ? GetConstantOperand(op, expr->target(), expr->value()) | 1528 ? GetConstantOperand(op, expr->target(), expr->value()) |
1527 : kNoConstants; | 1529 : kNoConstants; |
1528 ASSERT(constant == kRightConstant || constant == kNoConstants); | 1530 ASSERT(constant == kRightConstant || constant == kNoConstants); |
1529 if (constant == kNoConstants) { | 1531 if (constant == kNoConstants) { |
1530 __ push(eax); // Left operand goes on the stack. | 1532 __ push(eax); // Left operand goes on the stack. |
1531 VisitForAccumulatorValue(expr->value()); | 1533 VisitForAccumulatorValue(expr->value()); |
(...skipping 22 matching lines...) Expand all Loading... |
1554 } | 1556 } |
1555 | 1557 |
1556 // Record source position before possible IC call. | 1558 // Record source position before possible IC call. |
1557 SetSourcePosition(expr->position()); | 1559 SetSourcePosition(expr->position()); |
1558 | 1560 |
1559 // Store the value. | 1561 // Store the value. |
1560 switch (assign_type) { | 1562 switch (assign_type) { |
1561 case VARIABLE: | 1563 case VARIABLE: |
1562 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1564 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
1563 expr->op()); | 1565 expr->op()); |
| 1566 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 1567 context()->Plug(eax); |
1564 break; | 1568 break; |
1565 case NAMED_PROPERTY: | 1569 case NAMED_PROPERTY: |
1566 EmitNamedPropertyAssignment(expr); | 1570 EmitNamedPropertyAssignment(expr); |
1567 break; | 1571 break; |
1568 case KEYED_PROPERTY: | 1572 case KEYED_PROPERTY: |
1569 EmitKeyedPropertyAssignment(expr); | 1573 EmitKeyedPropertyAssignment(expr); |
1570 break; | 1574 break; |
1571 } | 1575 } |
1572 } | 1576 } |
1573 | 1577 |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 | 1899 |
1896 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1900 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1897 OverwriteMode mode) { | 1901 OverwriteMode mode) { |
1898 __ pop(edx); | 1902 __ pop(edx); |
1899 TypeRecordingBinaryOpStub stub(op, mode); | 1903 TypeRecordingBinaryOpStub stub(op, mode); |
1900 EmitCallIC(stub.GetCode(), NULL); // NULL signals no inlined smi code. | 1904 EmitCallIC(stub.GetCode(), NULL); // NULL signals no inlined smi code. |
1901 context()->Plug(eax); | 1905 context()->Plug(eax); |
1902 } | 1906 } |
1903 | 1907 |
1904 | 1908 |
1905 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1909 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1906 // Invalid left-hand sides are rewritten to have a 'throw | 1910 // Invalid left-hand sides are rewritten to have a 'throw |
1907 // ReferenceError' on the left-hand side. | 1911 // ReferenceError' on the left-hand side. |
1908 if (!expr->IsValidLeftHandSide()) { | 1912 if (!expr->IsValidLeftHandSide()) { |
1909 VisitForEffect(expr); | 1913 VisitForEffect(expr); |
1910 return; | 1914 return; |
1911 } | 1915 } |
1912 | 1916 |
1913 // Left-hand side can only be a property, a global or a (parameter or local) | 1917 // Left-hand side can only be a property, a global or a (parameter or local) |
1914 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1918 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1915 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1919 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
(...skipping 27 matching lines...) Expand all Loading... |
1943 VisitForStackValue(prop->obj()); | 1947 VisitForStackValue(prop->obj()); |
1944 VisitForAccumulatorValue(prop->key()); | 1948 VisitForAccumulatorValue(prop->key()); |
1945 __ mov(ecx, eax); | 1949 __ mov(ecx, eax); |
1946 __ pop(edx); | 1950 __ pop(edx); |
1947 __ pop(eax); // Restore value. | 1951 __ pop(eax); // Restore value. |
1948 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1952 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1949 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1953 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1950 break; | 1954 break; |
1951 } | 1955 } |
1952 } | 1956 } |
| 1957 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
| 1958 context()->Plug(eax); |
1953 } | 1959 } |
1954 | 1960 |
1955 | 1961 |
1956 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1962 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1957 Token::Value op) { | 1963 Token::Value op) { |
1958 // Left-hand sides that rewrite to explicit property accesses do not reach | 1964 // Left-hand sides that rewrite to explicit property accesses do not reach |
1959 // here. | 1965 // here. |
1960 ASSERT(var != NULL); | 1966 ASSERT(var != NULL); |
1961 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1967 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1962 | 1968 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2015 if (op == Token::INIT_CONST) { | 2021 if (op == Token::INIT_CONST) { |
2016 // The runtime will ignore const redeclaration. | 2022 // The runtime will ignore const redeclaration. |
2017 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2023 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
2018 } else { | 2024 } else { |
2019 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 2025 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
2020 } | 2026 } |
2021 break; | 2027 break; |
2022 } | 2028 } |
2023 __ bind(&done); | 2029 __ bind(&done); |
2024 } | 2030 } |
2025 | |
2026 context()->Plug(eax); | |
2027 } | 2031 } |
2028 | 2032 |
2029 | 2033 |
2030 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2034 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2031 // Assignment to a property, using a named store IC. | 2035 // Assignment to a property, using a named store IC. |
2032 Property* prop = expr->target()->AsProperty(); | 2036 Property* prop = expr->target()->AsProperty(); |
2033 ASSERT(prop != NULL); | 2037 ASSERT(prop != NULL); |
2034 ASSERT(prop->key()->AsLiteral() != NULL); | 2038 ASSERT(prop->key()->AsLiteral() != NULL); |
2035 | 2039 |
2036 // If the assignment starts a block of assignments to the same object, | 2040 // If the assignment starts a block of assignments to the same object, |
(...skipping 16 matching lines...) Expand all Loading... |
2053 } | 2057 } |
2054 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 2058 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
2055 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2059 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
2056 | 2060 |
2057 // If the assignment ends an initialization block, revert to fast case. | 2061 // If the assignment ends an initialization block, revert to fast case. |
2058 if (expr->ends_initialization_block()) { | 2062 if (expr->ends_initialization_block()) { |
2059 __ push(eax); // Result of assignment, saved even if not needed. | 2063 __ push(eax); // Result of assignment, saved even if not needed. |
2060 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 2064 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
2061 __ CallRuntime(Runtime::kToFastProperties, 1); | 2065 __ CallRuntime(Runtime::kToFastProperties, 1); |
2062 __ pop(eax); | 2066 __ pop(eax); |
2063 context()->DropAndPlug(1, eax); | 2067 __ Drop(1); |
2064 } else { | |
2065 context()->Plug(eax); | |
2066 } | 2068 } |
| 2069 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2070 context()->Plug(eax); |
2067 } | 2071 } |
2068 | 2072 |
2069 | 2073 |
2070 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2074 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2071 // Assignment to a property, using a keyed store IC. | 2075 // Assignment to a property, using a keyed store IC. |
2072 | 2076 |
2073 // If the assignment starts a block of assignments to the same object, | 2077 // If the assignment starts a block of assignments to the same object, |
2074 // change to slow case to avoid the quadratic behavior of repeatedly | 2078 // change to slow case to avoid the quadratic behavior of repeatedly |
2075 // adding fast properties. | 2079 // adding fast properties. |
2076 if (expr->starts_initialization_block()) { | 2080 if (expr->starts_initialization_block()) { |
(...skipping 17 matching lines...) Expand all Loading... |
2094 | 2098 |
2095 // If the assignment ends an initialization block, revert to fast case. | 2099 // If the assignment ends an initialization block, revert to fast case. |
2096 if (expr->ends_initialization_block()) { | 2100 if (expr->ends_initialization_block()) { |
2097 __ pop(edx); | 2101 __ pop(edx); |
2098 __ push(eax); // Result of assignment, saved even if not needed. | 2102 __ push(eax); // Result of assignment, saved even if not needed. |
2099 __ push(edx); | 2103 __ push(edx); |
2100 __ CallRuntime(Runtime::kToFastProperties, 1); | 2104 __ CallRuntime(Runtime::kToFastProperties, 1); |
2101 __ pop(eax); | 2105 __ pop(eax); |
2102 } | 2106 } |
2103 | 2107 |
| 2108 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2104 context()->Plug(eax); | 2109 context()->Plug(eax); |
2105 } | 2110 } |
2106 | 2111 |
2107 | 2112 |
2108 void FullCodeGenerator::VisitProperty(Property* expr) { | 2113 void FullCodeGenerator::VisitProperty(Property* expr) { |
2109 Comment cmnt(masm_, "[ Property"); | 2114 Comment cmnt(masm_, "[ Property"); |
2110 Expression* key = expr->key(); | 2115 Expression* key = expr->key(); |
2111 | 2116 |
2112 if (key->IsPropertyName()) { | 2117 if (key->IsPropertyName()) { |
2113 VisitForAccumulatorValue(expr->obj()); | 2118 VisitForAccumulatorValue(expr->obj()); |
(...skipping 1684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3798 | 3803 |
3799 __ bind(&done); | 3804 __ bind(&done); |
3800 // Store the value returned in eax. | 3805 // Store the value returned in eax. |
3801 switch (assign_type) { | 3806 switch (assign_type) { |
3802 case VARIABLE: | 3807 case VARIABLE: |
3803 if (expr->is_postfix()) { | 3808 if (expr->is_postfix()) { |
3804 // Perform the assignment as if via '='. | 3809 // Perform the assignment as if via '='. |
3805 { EffectContext context(this); | 3810 { EffectContext context(this); |
3806 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3811 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3807 Token::ASSIGN); | 3812 Token::ASSIGN); |
| 3813 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3814 context.Plug(eax); |
3808 } | 3815 } |
3809 // For all contexts except EffectContext We have the result on | 3816 // For all contexts except EffectContext We have the result on |
3810 // top of the stack. | 3817 // top of the stack. |
3811 if (!context()->IsEffect()) { | 3818 if (!context()->IsEffect()) { |
3812 context()->PlugTOS(); | 3819 context()->PlugTOS(); |
3813 } | 3820 } |
3814 } else { | 3821 } else { |
3815 // Perform the assignment as if via '='. | 3822 // Perform the assignment as if via '='. |
3816 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3823 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3817 Token::ASSIGN); | 3824 Token::ASSIGN); |
| 3825 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3826 context()->Plug(eax); |
3818 } | 3827 } |
3819 break; | 3828 break; |
3820 case NAMED_PROPERTY: { | 3829 case NAMED_PROPERTY: { |
3821 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3830 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
3822 __ pop(edx); | 3831 __ pop(edx); |
3823 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3832 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
3824 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3833 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3834 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3825 if (expr->is_postfix()) { | 3835 if (expr->is_postfix()) { |
3826 if (!context()->IsEffect()) { | 3836 if (!context()->IsEffect()) { |
3827 context()->PlugTOS(); | 3837 context()->PlugTOS(); |
3828 } | 3838 } |
3829 } else { | 3839 } else { |
3830 context()->Plug(eax); | 3840 context()->Plug(eax); |
3831 } | 3841 } |
3832 break; | 3842 break; |
3833 } | 3843 } |
3834 case KEYED_PROPERTY: { | 3844 case KEYED_PROPERTY: { |
3835 __ pop(ecx); | 3845 __ pop(ecx); |
3836 __ pop(edx); | 3846 __ pop(edx); |
3837 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 3847 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
3838 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3848 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3849 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3839 if (expr->is_postfix()) { | 3850 if (expr->is_postfix()) { |
3840 // Result is on the stack | 3851 // Result is on the stack |
3841 if (!context()->IsEffect()) { | 3852 if (!context()->IsEffect()) { |
3842 context()->PlugTOS(); | 3853 context()->PlugTOS(); |
3843 } | 3854 } |
3844 } else { | 3855 } else { |
3845 context()->Plug(eax); | 3856 context()->Plug(eax); |
3846 } | 3857 } |
3847 break; | 3858 break; |
3848 } | 3859 } |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4231 // And return. | 4242 // And return. |
4232 __ ret(0); | 4243 __ ret(0); |
4233 } | 4244 } |
4234 | 4245 |
4235 | 4246 |
4236 #undef __ | 4247 #undef __ |
4237 | 4248 |
4238 } } // namespace v8::internal | 4249 } } // namespace v8::internal |
4239 | 4250 |
4240 #endif // V8_TARGET_ARCH_IA32 | 4251 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |