Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 5682010: Deoptimize to the proper target after assignment side effects. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge/build/ia32
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.cc ('k') | test/mjsunit/regress/regress-989.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | test/mjsunit/regress/regress-989.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698