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

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

Issue 17044: Experimental: begin using the register allocator for do and while... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 11 months 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 | « no previous file | src/jump-target-ia32.cc » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 1583 matching lines...) Expand 10 before | Expand all | Expand 10 after
1594 1594
1595 1595
1596 void CodeGenerator::CleanStack(int num_bytes) { 1596 void CodeGenerator::CleanStack(int num_bytes) {
1597 ASSERT(num_bytes % kPointerSize == 0); 1597 ASSERT(num_bytes % kPointerSize == 0);
1598 frame_->Drop(num_bytes / kPointerSize); 1598 frame_->Drop(num_bytes / kPointerSize);
1599 } 1599 }
1600 1600
1601 1601
1602 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1602 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1603 ASSERT(!in_spilled_code()); 1603 ASSERT(!in_spilled_code());
1604 VirtualFrame::SpilledScope spilled_scope(this);
1605 Comment cmnt(masm_, "[ ContinueStatement"); 1604 Comment cmnt(masm_, "[ ContinueStatement");
1606 CodeForStatement(node); 1605 CodeForStatement(node);
1607 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1606 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1608 node->target()->continue_target()->Jump(); 1607 node->target()->continue_target()->Jump();
1609 } 1608 }
1610 1609
1611 1610
1612 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1611 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1613 ASSERT(!in_spilled_code()); 1612 ASSERT(!in_spilled_code());
1614 VirtualFrame::SpilledScope spilled_scope(this);
1615 Comment cmnt(masm_, "[ BreakStatement"); 1613 Comment cmnt(masm_, "[ BreakStatement");
1616 CodeForStatement(node); 1614 CodeForStatement(node);
1617 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1615 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1618 node->target()->break_target()->Jump(); 1616 node->target()->break_target()->Jump();
1619 } 1617 }
1620 1618
1621 1619
1622 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1620 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1623 ASSERT(!in_spilled_code()); 1621 ASSERT(!in_spilled_code());
1624 VirtualFrame::SpilledScope spilled_scope(this); 1622 VirtualFrame::SpilledScope spilled_scope(this);
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 if (lit->IsTrue()) { 1884 if (lit->IsTrue()) {
1887 info = ALWAYS_TRUE; 1885 info = ALWAYS_TRUE;
1888 } else if (lit->IsFalse()) { 1886 } else if (lit->IsFalse()) {
1889 info = ALWAYS_FALSE; 1887 info = ALWAYS_FALSE;
1890 } 1888 }
1891 } 1889 }
1892 } 1890 }
1893 1891
1894 switch (node->type()) { 1892 switch (node->type()) {
1895 case LoopStatement::DO_LOOP: { 1893 case LoopStatement::DO_LOOP: {
1896 // The new code generator does not yet compile do loops.
1897 VirtualFrame::SpilledScope spilled_scope(this);
1898 JumpTarget body(this); 1894 JumpTarget body(this);
1899 IncrementLoopNesting(); 1895 IncrementLoopNesting();
1900 // Label the body. 1896
1897 // Label the top of the loop for the backward CFG edge. If the test
1898 // is always true we can use the continue target, and if the test is
1899 // always false there is no need.
1901 if (info == ALWAYS_TRUE) { 1900 if (info == ALWAYS_TRUE) {
1902 node->continue_target()->Bind(); 1901 node->continue_target()->Bind();
1903 } else if (info == ALWAYS_FALSE) { 1902 } else if (info == ALWAYS_FALSE) {
1904 // There is no need, we will never jump back. 1903 // There is no need, we will never jump back.
1905 } else { 1904 } else {
1906 ASSERT(info == DONT_KNOW); 1905 ASSERT(info == DONT_KNOW);
1907 body.Bind(); 1906 body.Bind();
1908 } 1907 }
1908
1909 CheckStack(); // TODO(1222600): ignore if body contains calls. 1909 CheckStack(); // TODO(1222600): ignore if body contains calls.
1910 VisitAndSpill(node->body()); 1910 Visit(node->body());
1911 1911
1912 // Compile the "test". 1912 // Compile the test.
1913 if (info == ALWAYS_TRUE) { 1913 if (info == ALWAYS_TRUE) {
1914 // If control flow can fall off the end of the body, jump back to
1915 // the top.
1914 if (has_valid_frame()) { 1916 if (has_valid_frame()) {
1915 // If control flow can fall off the end of the body, jump back to
1916 // the top.
1917 node->continue_target()->Jump(); 1917 node->continue_target()->Jump();
1918 } 1918 }
1919 } else if (info == ALWAYS_FALSE) { 1919 } else if (info == ALWAYS_FALSE) {
1920 // If we have a continue in the body, we only have to bind its jump 1920 // If we had a continue in the body we have to bind its jump target.
1921 // target.
1922 if (node->continue_target()->is_linked()) { 1921 if (node->continue_target()->is_linked()) {
1923 node->continue_target()->Bind(); 1922 node->continue_target()->Bind();
1924 } 1923 }
1925 } else { 1924 } else {
1926 ASSERT(info == DONT_KNOW); 1925 ASSERT(info == DONT_KNOW);
1927 // We have to compile the test expression if it can be reached by 1926 // We have to compile the test expression if it can be reached by
1928 // control flow falling out of the body or via continue. 1927 // control flow falling out of the body or via continue.
1929 if (has_valid_frame() || node->continue_target()->is_linked()) { 1928 if (node->continue_target()->is_linked()) {
1930 node->continue_target()->Bind(); 1929 node->continue_target()->Bind();
1931 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, 1930 }
1932 &body, node->break_target(), true); 1931 if (has_valid_frame()) {
1932 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
1933 &body, node->break_target(), true);
1933 // An invalid frame here indicates that control flow did not fall 1934 // An invalid frame here indicates that control flow did not fall
1934 // out of the test expression. 1935 // out of the test expression.
1935 if (has_valid_frame()) { 1936 if (has_valid_frame()) {
1936 Branch(true, &body); 1937 Branch(true, &body);
1937 } 1938 }
1938 } 1939 }
1939 } 1940 }
1940 break; 1941 break;
1941 } 1942 }
1942 1943
1943 case LoopStatement::WHILE_LOOP: { 1944 case LoopStatement::WHILE_LOOP: {
1944 // The new code generator does not yet compile while loops.
1945 VirtualFrame::SpilledScope spilled_scope(this);
1946 JumpTarget body(this);
1947 IncrementLoopNesting(); 1945 IncrementLoopNesting();
1948 // Generate the loop header. 1946
1949 if (info == ALWAYS_TRUE) { 1947 // If the test is never true and has no side effects there is no need
1950 // Merely label the body with the continue target. 1948 // to compile the test or body.
1951 node->continue_target()->Bind(); 1949 if (info == ALWAYS_FALSE) break;
1952 } else if (info == ALWAYS_FALSE) { 1950
1953 // There is no need to even compile the test or body. 1951 // Label the top of the loop with the continue target for the backward
1954 break; 1952 // CFG edge.
1955 } else { 1953 node->continue_target()->Bind();
1956 // Compile the test labeled with the continue target and label the 1954
1957 // body with the body target. 1955 // If the test is always true and has no side effects there is no need
1958 ASSERT(info == DONT_KNOW); 1956 // to compile it. We only compile the test when we do not know its
1959 node->continue_target()->Bind(); 1957 // outcome or it may have side effects.
1960 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, 1958 if (info == DONT_KNOW) {
1961 &body, node->break_target(), true); 1959 JumpTarget body(this);
1960 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
1961 &body, node->break_target(), true);
1962 // An invalid frame indicates that control did not fall out of the 1962 // An invalid frame indicates that control did not fall out of the
1963 // test expression. 1963 // test expression.
1964 if (has_valid_frame()) { 1964 if (has_valid_frame()) {
1965 Branch(false, node->break_target()); 1965 Branch(false, node->break_target());
1966 } 1966 }
1967 if (has_valid_frame() || body.is_linked()) { 1967 if (body.is_linked()) {
1968 body.Bind(); 1968 body.Bind();
1969 } 1969 }
1970 } 1970 }
1971
1971 if (has_valid_frame()) { 1972 if (has_valid_frame()) {
1972 CheckStack(); // TODO(1222600): ignore if body contains calls. 1973 CheckStack(); // TODO(1222600): ignore if body contains calls.
1973 VisitAndSpill(node->body()); 1974 Visit(node->body());
1974 1975
1975 // If control flow can fall out of the body, jump back to the top. 1976 // If control flow can fall out of the body, jump back to the top.
1976 if (has_valid_frame()) { 1977 if (has_valid_frame()) {
1977 node->continue_target()->Jump(); 1978 node->continue_target()->Jump();
1978 } 1979 }
1979 } 1980 }
1980 break; 1981 break;
1981 } 1982 }
1982 1983
1983 case LoopStatement::FOR_LOOP: { 1984 case LoopStatement::FOR_LOOP: {
1984 JumpTarget loop(this); 1985 JumpTarget loop(this);
1985 JumpTarget body(this);
1986 if (node->init() != NULL) { 1986 if (node->init() != NULL) {
1987 Visit(node->init()); 1987 Visit(node->init());
1988 } 1988 }
1989 1989
1990 IncrementLoopNesting(); 1990 IncrementLoopNesting();
1991 // There is no need to compile the test or body. 1991 // If the test is never true and has no side effects there is no need
1992 // to compile the test or body.
1992 if (info == ALWAYS_FALSE) break; 1993 if (info == ALWAYS_FALSE) break;
1993 1994
1994 // Label the top of the loop for the backward CFG edge. If there is 1995 // Label the top of the loop for the backward CFG edge. If there is
1995 // no update expression label it with the continue target, otherwise 1996 // no update expression we can use the continue target.
1996 // with the loop target.
1997 if (node->next() == NULL) { 1997 if (node->next() == NULL) {
1998 node->continue_target()->Bind(); 1998 node->continue_target()->Bind();
1999 } else { 1999 } else {
2000 loop.Bind(); 2000 loop.Bind();
2001 } 2001 }
2002 2002
2003 // If the test is always true, there is no need to compile it. 2003 // If the test is always true and has no side effects there is no need
2004 // to compile it. We only compile the test when we do not know its
2005 // outcome or it has side effects.
2004 if (info == DONT_KNOW) { 2006 if (info == DONT_KNOW) {
2007 JumpTarget body(this);
2005 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 2008 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
2006 &body, node->break_target(), true); 2009 &body, node->break_target(), true);
2007 if (has_valid_frame()) { 2010 if (has_valid_frame()) {
2008 Branch(false, node->break_target()); 2011 Branch(false, node->break_target());
2009 } 2012 }
2010 if (has_valid_frame() || body.is_linked()) { 2013 if (body.is_linked()) {
2011 body.Bind(); 2014 body.Bind();
2012 } 2015 }
2013 } 2016 }
2014 2017
2015 if (has_valid_frame()) { 2018 if (has_valid_frame()) {
2016 CheckStack(); // TODO(1222600): ignore if body contains calls. 2019 CheckStack(); // TODO(1222600): ignore if body contains calls.
2017 Visit(node->body()); 2020 Visit(node->body());
2018 2021
2019 if (node->next() == NULL) { 2022 if (node->next() == NULL) {
2020 // If there is no update statement and control flow can fall out 2023 // If there is no update statement and control flow can fall out
2021 // of the loop, jump to the continue label. 2024 // of the loop, jump to the continue label.
2022 if (has_valid_frame()) { 2025 if (has_valid_frame()) {
2023 node->continue_target()->Jump(); 2026 node->continue_target()->Jump();
2024 } 2027 }
2025 } else { 2028 } else {
2026 // If there is an update statement and control flow can reach it 2029 // If there is an update statement and control flow can reach it
2027 // via falling out of the body of the loop or continuing, we 2030 // via falling out of the body of the loop or continuing, we
2028 // compile the update statement. 2031 // compile the update statement.
2029 if (has_valid_frame() || node->continue_target()->is_linked()) { 2032 if (node->continue_target()->is_linked()) {
2030 node->continue_target()->Bind(); 2033 node->continue_target()->Bind();
2034 }
2035 if (has_valid_frame()) {
2031 // Record source position of the statement as this code which is 2036 // Record source position of the statement as this code which is
2032 // after the code for the body actually belongs to the loop 2037 // after the code for the body actually belongs to the loop
2033 // statement and not the body. 2038 // statement and not the body.
2034 CodeForStatement(node); 2039 CodeForStatement(node);
2035 ASSERT(node->type() == LoopStatement::FOR_LOOP); 2040 ASSERT(node->type() == LoopStatement::FOR_LOOP);
2036 Visit(node->next()); 2041 Visit(node->next());
2037 loop.Jump(); 2042 loop.Jump();
2038 } 2043 }
2039 } 2044 }
2040 } 2045 }
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
2325 if (nof_unlinks > 0) { 2330 if (nof_unlinks > 0) {
2326 exit.Jump(); 2331 exit.Jump();
2327 } 2332 }
2328 } 2333 }
2329 2334
2330 // Generate unlink code for the (formerly) shadowing targets that have been 2335 // Generate unlink code for the (formerly) shadowing targets that have been
2331 // jumped to. 2336 // jumped to.
2332 for (int i = 0; i <= nof_escapes; i++) { 2337 for (int i = 0; i <= nof_escapes; i++) {
2333 if (shadows[i]->is_linked()) { 2338 if (shadows[i]->is_linked()) {
2334 // Unlink from try chain; be careful not to destroy the TOS. 2339 // Unlink from try chain; be careful not to destroy the TOS.
2340 //
2341 // Because we can be jumping here (to spilled code) from unspilled
2342 // code, we need to reestablish a spilled frame at this block.
2335 shadows[i]->Bind(); 2343 shadows[i]->Bind();
2344 frame_->SpillAll();
2336 2345
2337 // Reload sp from the top handler, because some statements that we 2346 // Reload sp from the top handler, because some statements that we
2338 // break from (eg, for...in) may have left stuff on the stack. 2347 // break from (eg, for...in) may have left stuff on the stack.
2339 __ mov(edx, Operand::StaticVariable(handler_address)); 2348 __ mov(edx, Operand::StaticVariable(handler_address));
2340 const int kNextOffset = StackHandlerConstants::kNextOffset + 2349 const int kNextOffset = StackHandlerConstants::kNextOffset +
2341 StackHandlerConstants::kAddressDisplacement; 2350 StackHandlerConstants::kAddressDisplacement;
2342 __ lea(esp, Operand(edx, kNextOffset)); 2351 __ lea(esp, Operand(edx, kNextOffset));
2343 frame_->Forget(frame_->height() - handler_height); 2352 frame_->Forget(frame_->height() - handler_height);
2344 2353
2345 frame_->EmitPop(Operand::StaticVariable(handler_address)); 2354 frame_->EmitPop(Operand::StaticVariable(handler_address));
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2420 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); 2429 __ Set(ecx, Immediate(Smi::FromInt(FALLING)));
2421 if (nof_unlinks > 0) { 2430 if (nof_unlinks > 0) {
2422 unlink.Jump(); 2431 unlink.Jump();
2423 } 2432 }
2424 } 2433 }
2425 2434
2426 // Generate code to set the state for the (formerly) shadowing targets that 2435 // Generate code to set the state for the (formerly) shadowing targets that
2427 // have been jumped to. 2436 // have been jumped to.
2428 for (int i = 0; i <= nof_escapes; i++) { 2437 for (int i = 0; i <= nof_escapes; i++) {
2429 if (shadows[i]->is_linked()) { 2438 if (shadows[i]->is_linked()) {
2439 // Because we can be jumping here (to spilled code) from unspilled
2440 // code, we need to reestablish a spilled frame at this block.
2430 shadows[i]->Bind(); 2441 shadows[i]->Bind();
2442 frame_->SpillAll();
2431 if (shadows[i]->original_target() == &function_return_) { 2443 if (shadows[i]->original_target() == &function_return_) {
2432 // If this target shadowed the function return, materialize the 2444 // If this target shadowed the function return, materialize the
2433 // return value on the stack. 2445 // return value on the stack.
2434 frame_->EmitPush(eax); 2446 frame_->EmitPush(eax);
2435 } else { 2447 } else {
2436 // Fake TOS for targets that shadowed breaks and continues. 2448 // Fake TOS for targets that shadowed breaks and continues.
2437 frame_->EmitPush(Immediate(Factory::undefined_value())); 2449 frame_->EmitPush(Immediate(Factory::undefined_value()));
2438 } 2450 }
2439 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); 2451 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i)));
2440 unlink.Jump(); 2452 unlink.Jump();
(...skipping 3344 matching lines...) Expand 10 before | Expand all | Expand 10 after
5785 5797
5786 // Slow-case: Go through the JavaScript implementation. 5798 // Slow-case: Go through the JavaScript implementation.
5787 __ bind(&slow); 5799 __ bind(&slow);
5788 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5800 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5789 } 5801 }
5790 5802
5791 5803
5792 #undef __ 5804 #undef __
5793 5805
5794 } } // namespace v8::internal 5806 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/jump-target-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698