| OLD | NEW |
| 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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 frame_->CallRuntime(Runtime::kDebugTrace, 0); | 262 frame_->CallRuntime(Runtime::kDebugTrace, 0); |
| 263 // Ignore the return value. | 263 // Ignore the return value. |
| 264 } | 264 } |
| 265 #endif | 265 #endif |
| 266 VisitStatements(body); | 266 VisitStatements(body); |
| 267 | 267 |
| 268 // Generate a return statement if necessary. A NULL frame indicates | 268 // Generate a return statement if necessary. A NULL frame indicates |
| 269 // that control flow leaves the body on all paths and cannot fall | 269 // that control flow leaves the body on all paths and cannot fall |
| 270 // through. | 270 // through. |
| 271 if (frame_ != NULL) { | 271 if (frame_ != NULL) { |
| 272 frame_->SpillAll(); |
| 272 Literal undefined(Factory::undefined_value()); | 273 Literal undefined(Factory::undefined_value()); |
| 273 ReturnStatement statement(&undefined); | 274 ReturnStatement statement(&undefined); |
| 274 statement.set_statement_pos(fun->end_position()); | 275 statement.set_statement_pos(fun->end_position()); |
| 275 VisitReturnStatement(&statement); | 276 VisitReturnStatement(&statement); |
| 276 } | 277 } |
| 277 } | 278 } |
| 278 } | 279 } |
| 279 | 280 |
| 280 // Adjust for function-level loop nesting. | 281 // Adjust for function-level loop nesting. |
| 281 loop_nesting_ -= fun->loop_nesting(); | 282 loop_nesting_ -= fun->loop_nesting(); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 | 470 |
| 470 void CodeGenerator::LoadReference(Reference* ref) { | 471 void CodeGenerator::LoadReference(Reference* ref) { |
| 471 Comment cmnt(masm_, "[ LoadReference"); | 472 Comment cmnt(masm_, "[ LoadReference"); |
| 472 Expression* e = ref->expression(); | 473 Expression* e = ref->expression(); |
| 473 Property* property = e->AsProperty(); | 474 Property* property = e->AsProperty(); |
| 474 Variable* var = e->AsVariableProxy()->AsVariable(); | 475 Variable* var = e->AsVariableProxy()->AsVariable(); |
| 475 | 476 |
| 476 if (property != NULL) { | 477 if (property != NULL) { |
| 477 // The expression is either a property or a variable proxy that rewrites | 478 // The expression is either a property or a variable proxy that rewrites |
| 478 // to a property. | 479 // to a property. |
| 480 frame_->SpillAll(); |
| 479 Load(property->obj()); | 481 Load(property->obj()); |
| 480 frame_->SpillAll(); | 482 frame_->SpillAll(); |
| 481 // We use a named reference if the key is a literal symbol, unless it is | 483 // We use a named reference if the key is a literal symbol, unless it is |
| 482 // a string that can be legally parsed as an integer. This is because | 484 // a string that can be legally parsed as an integer. This is because |
| 483 // otherwise we will not get into the slow case code that handles [] on | 485 // otherwise we will not get into the slow case code that handles [] on |
| 484 // String objects. | 486 // String objects. |
| 485 Literal* literal = property->key()->AsLiteral(); | 487 Literal* literal = property->key()->AsLiteral(); |
| 486 uint32_t dummy; | 488 uint32_t dummy; |
| 487 if (literal != NULL && | 489 if (literal != NULL && |
| 488 literal->handle()->IsSymbol() && | 490 literal->handle()->IsSymbol() && |
| 489 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { | 491 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { |
| 490 ref->set_type(Reference::NAMED); | 492 ref->set_type(Reference::NAMED); |
| 491 } else { | 493 } else { |
| 492 Load(property->key()); | 494 Load(property->key()); |
| 493 frame_->SpillAll(); | 495 frame_->SpillAll(); |
| 494 ref->set_type(Reference::KEYED); | 496 ref->set_type(Reference::KEYED); |
| 495 } | 497 } |
| 496 } else if (var != NULL) { | 498 } else if (var != NULL) { |
| 497 // The expression is a variable proxy that does not rewrite to a | 499 // The expression is a variable proxy that does not rewrite to a |
| 498 // property. Global variables are treated as named property references. | 500 // property. Global variables are treated as named property references. |
| 499 if (var->is_global()) { | 501 if (var->is_global()) { |
| 502 frame_->SpillAll(); |
| 500 LoadGlobal(); | 503 LoadGlobal(); |
| 501 ref->set_type(Reference::NAMED); | 504 ref->set_type(Reference::NAMED); |
| 502 } else { | 505 } else { |
| 503 ASSERT(var->slot() != NULL); | 506 ASSERT(var->slot() != NULL); |
| 504 ref->set_type(Reference::SLOT); | 507 ref->set_type(Reference::SLOT); |
| 505 } | 508 } |
| 506 } else { | 509 } else { |
| 507 // Anything else is a runtime error. | 510 // Anything else is a runtime error. |
| 508 Load(e); | 511 Load(e); |
| 509 frame_->SpillAll(); | 512 frame_->SpillAll(); |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 | 1271 |
| 1269 | 1272 |
| 1270 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 1273 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 1271 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { | 1274 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { |
| 1272 Visit(statements->at(i)); | 1275 Visit(statements->at(i)); |
| 1273 } | 1276 } |
| 1274 } | 1277 } |
| 1275 | 1278 |
| 1276 | 1279 |
| 1277 void CodeGenerator::VisitBlock(Block* node) { | 1280 void CodeGenerator::VisitBlock(Block* node) { |
| 1278 frame_->SpillAll(); | |
| 1279 Comment cmnt(masm_, "[ Block"); | 1281 Comment cmnt(masm_, "[ Block"); |
| 1280 RecordStatementPosition(node); | 1282 RecordStatementPosition(node); |
| 1281 node->set_break_stack_height(break_stack_height_); | 1283 node->set_break_stack_height(break_stack_height_); |
| 1282 node->break_target()->set_code_generator(this); | 1284 node->break_target()->set_code_generator(this); |
| 1283 VisitStatements(node->statements()); | 1285 VisitStatements(node->statements()); |
| 1284 if (node->break_target()->is_linked()) { | 1286 if (node->break_target()->is_linked()) { |
| 1285 node->break_target()->Bind(); | 1287 node->break_target()->Bind(); |
| 1286 } | 1288 } |
| 1287 } | 1289 } |
| 1288 | 1290 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 | 1365 |
| 1364 | 1366 |
| 1365 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1367 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
| 1366 Comment cmnt(masm_, "[ ExpressionStatement"); | 1368 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 1367 RecordStatementPosition(node); | 1369 RecordStatementPosition(node); |
| 1368 Expression* expression = node->expression(); | 1370 Expression* expression = node->expression(); |
| 1369 expression->MarkAsStatement(); | 1371 expression->MarkAsStatement(); |
| 1370 Load(expression); | 1372 Load(expression); |
| 1371 // Remove the lingering expression result from the top of stack. | 1373 // Remove the lingering expression result from the top of stack. |
| 1372 frame_->Drop(); | 1374 frame_->Drop(); |
| 1373 // Rather than using SpillAll after all recursive calls to Visit over | |
| 1374 // statements, we spill here in the only statement type that uses the | |
| 1375 // virtual frame. This is temporary. | |
| 1376 frame_->SpillAll(); | |
| 1377 } | 1375 } |
| 1378 | 1376 |
| 1379 | 1377 |
| 1380 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1378 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
| 1381 frame_->SpillAll(); | 1379 frame_->SpillAll(); |
| 1382 Comment cmnt(masm_, "// EmptyStatement"); | 1380 Comment cmnt(masm_, "// EmptyStatement"); |
| 1383 // nothing to do | 1381 // nothing to do |
| 1384 } | 1382 } |
| 1385 | 1383 |
| 1386 | 1384 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1409 // If control flow can reach the then part via fall-through from the | 1407 // If control flow can reach the then part via fall-through from the |
| 1410 // test or a branch to the target, compile it. | 1408 // test or a branch to the target, compile it. |
| 1411 then.Bind(); | 1409 then.Bind(); |
| 1412 Visit(node->then_statement()); | 1410 Visit(node->then_statement()); |
| 1413 } | 1411 } |
| 1414 if (frame_ != NULL) { | 1412 if (frame_ != NULL) { |
| 1415 // A NULL frame here indicates that control did not fall out of the | 1413 // A NULL frame here indicates that control did not fall out of the |
| 1416 // then statement, it escaped on all branches. In that case, a jump | 1414 // then statement, it escaped on all branches. In that case, a jump |
| 1417 // to the exit label would be dead code (and impossible, because we | 1415 // to the exit label would be dead code (and impossible, because we |
| 1418 // don't have a current virtual frame to set at the exit label). | 1416 // don't have a current virtual frame to set at the exit label). |
| 1417 frame_->SpillAll(); |
| 1419 exit.Jump(); | 1418 exit.Jump(); |
| 1420 } | 1419 } |
| 1421 // else | 1420 // else |
| 1422 if (else_.is_linked()) { | 1421 if (else_.is_linked()) { |
| 1423 // Control flow for if-then-else does not fall-through to the else | 1422 // Control flow for if-then-else does not fall-through to the else |
| 1424 // part, it can only reach here via jump if at all. | 1423 // part, it can only reach here via jump if at all. |
| 1425 else_.Bind(); | 1424 else_.Bind(); |
| 1426 Visit(node->else_statement()); | 1425 Visit(node->else_statement()); |
| 1427 } | 1426 } |
| 1428 | 1427 |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1702 default_exit.Bind(); | 1701 default_exit.Bind(); |
| 1703 } else { | 1702 } else { |
| 1704 fall_through.Bind(); | 1703 fall_through.Bind(); |
| 1705 fall_through.Unuse(); | 1704 fall_through.Unuse(); |
| 1706 } | 1705 } |
| 1707 VisitStatements(clause->statements()); | 1706 VisitStatements(clause->statements()); |
| 1708 | 1707 |
| 1709 // If control flow can fall through from the body, jump to the next body | 1708 // If control flow can fall through from the body, jump to the next body |
| 1710 // or the end of the statement. | 1709 // or the end of the statement. |
| 1711 if (frame_ != NULL) { | 1710 if (frame_ != NULL) { |
| 1711 frame_->SpillAll(); |
| 1712 if (i < length - 1 && cases->at(i + 1)->is_default()) { | 1712 if (i < length - 1 && cases->at(i + 1)->is_default()) { |
| 1713 default_entry.Jump(); | 1713 default_entry.Jump(); |
| 1714 } else { | 1714 } else { |
| 1715 fall_through.Jump(); | 1715 fall_through.Jump(); |
| 1716 } | 1716 } |
| 1717 } | 1717 } |
| 1718 } | 1718 } |
| 1719 | 1719 |
| 1720 // The final "test" removes the switch value. | 1720 // The final "test" removes the switch value. |
| 1721 next_test.Bind(); | 1721 next_test.Bind(); |
| 1722 frame_->Drop(); | 1722 frame_->Drop(); |
| 1723 | 1723 |
| 1724 // If there is a default clause, compile it. | 1724 // If there is a default clause, compile it. |
| 1725 if (default_clause != NULL) { | 1725 if (default_clause != NULL) { |
| 1726 Comment cmnt(masm_, "[ Default clause"); | 1726 Comment cmnt(masm_, "[ Default clause"); |
| 1727 default_entry.Bind(); | 1727 default_entry.Bind(); |
| 1728 VisitStatements(default_clause->statements()); | 1728 VisitStatements(default_clause->statements()); |
| 1729 if (frame_ != NULL) { |
| 1730 frame_->SpillAll(); |
| 1731 } |
| 1729 // If control flow can fall out of the default and there is a case after | 1732 // If control flow can fall out of the default and there is a case after |
| 1730 // it, jump to that case's body. | 1733 // it, jump to that case's body. |
| 1731 if (frame_ != NULL && default_exit.is_bound()) { | 1734 if (frame_ != NULL && default_exit.is_bound()) { |
| 1732 default_exit.Jump(); | 1735 default_exit.Jump(); |
| 1733 } | 1736 } |
| 1734 } | 1737 } |
| 1735 | 1738 |
| 1736 if (fall_through.is_linked()) { | 1739 if (fall_through.is_linked()) { |
| 1737 fall_through.Bind(); | 1740 fall_through.Bind(); |
| 1738 } | 1741 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1776 if (info == ALWAYS_TRUE) { | 1779 if (info == ALWAYS_TRUE) { |
| 1777 node->continue_target()->Bind(); | 1780 node->continue_target()->Bind(); |
| 1778 } else if (info == ALWAYS_FALSE) { | 1781 } else if (info == ALWAYS_FALSE) { |
| 1779 // There is no need, we will never jump back. | 1782 // There is no need, we will never jump back. |
| 1780 } else { | 1783 } else { |
| 1781 ASSERT(info == DONT_KNOW); | 1784 ASSERT(info == DONT_KNOW); |
| 1782 body.Bind(); | 1785 body.Bind(); |
| 1783 } | 1786 } |
| 1784 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1787 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1785 Visit(node->body()); | 1788 Visit(node->body()); |
| 1789 if (frame_ != NULL) { |
| 1790 frame_->SpillAll(); |
| 1791 } |
| 1786 | 1792 |
| 1787 // Compile the "test". | 1793 // Compile the "test". |
| 1788 if (info == ALWAYS_TRUE) { | 1794 if (info == ALWAYS_TRUE) { |
| 1789 if (frame_ != NULL) { | 1795 if (frame_ != NULL) { |
| 1790 // If control flow can fall off the end of the body, jump back to | 1796 // If control flow can fall off the end of the body, jump back to |
| 1791 // the top. | 1797 // the top. |
| 1792 node->continue_target()->Jump(); | 1798 node->continue_target()->Jump(); |
| 1793 } | 1799 } |
| 1794 } else if (info == ALWAYS_FALSE) { | 1800 } else if (info == ALWAYS_FALSE) { |
| 1795 // If we have a continue in the body, we only have to bind its jump | 1801 // If we have a continue in the body, we only have to bind its jump |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 if (frame_ != NULL || body.is_linked()) { | 1846 if (frame_ != NULL || body.is_linked()) { |
| 1841 body.Bind(); | 1847 body.Bind(); |
| 1842 } | 1848 } |
| 1843 } | 1849 } |
| 1844 if (frame_ != NULL) { | 1850 if (frame_ != NULL) { |
| 1845 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1851 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1846 Visit(node->body()); | 1852 Visit(node->body()); |
| 1847 | 1853 |
| 1848 // If control flow can fall out of the body, jump back to the top. | 1854 // If control flow can fall out of the body, jump back to the top. |
| 1849 if (frame_ != NULL) { | 1855 if (frame_ != NULL) { |
| 1856 frame_->SpillAll(); |
| 1850 node->continue_target()->Jump(); | 1857 node->continue_target()->Jump(); |
| 1851 } | 1858 } |
| 1852 } | 1859 } |
| 1853 break; | 1860 break; |
| 1854 } | 1861 } |
| 1855 | 1862 |
| 1856 case LoopStatement::FOR_LOOP: { | 1863 case LoopStatement::FOR_LOOP: { |
| 1857 JumpTarget loop(this); | 1864 JumpTarget loop(this); |
| 1858 JumpTarget body(this); | 1865 JumpTarget body(this); |
| 1859 if (node->init() != NULL) { | 1866 if (node->init() != NULL) { |
| 1860 Visit(node->init()); | 1867 Visit(node->init()); |
| 1861 } | 1868 } |
| 1862 | 1869 |
| 1863 IncrementLoopNesting(); | 1870 IncrementLoopNesting(); |
| 1864 // There is no need to compile the test or body. | 1871 // There is no need to compile the test or body. |
| 1865 if (info == ALWAYS_FALSE) break; | 1872 if (info == ALWAYS_FALSE) break; |
| 1866 | 1873 |
| 1874 // TODO(): Could frame_ be NULL here? |
| 1875 frame_->SpillAll(); |
| 1867 // If there is no update statement, label the top of the loop with the | 1876 // If there is no update statement, label the top of the loop with the |
| 1868 // continue target, otherwise with the loop target. | 1877 // continue target, otherwise with the loop target. |
| 1869 if (node->next() == NULL) { | 1878 if (node->next() == NULL) { |
| 1870 node->continue_target()->Bind(); | 1879 node->continue_target()->Bind(); |
| 1871 } else { | 1880 } else { |
| 1872 loop.Bind(); | 1881 loop.Bind(); |
| 1873 } | 1882 } |
| 1874 | 1883 |
| 1875 // If the test is always true, there is no need to compile it. | 1884 // If the test is always true, there is no need to compile it. |
| 1876 if (info == DONT_KNOW) { | 1885 if (info == DONT_KNOW) { |
| 1877 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, | 1886 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, |
| 1878 &body, node->break_target(), true); | 1887 &body, node->break_target(), true); |
| 1879 if (frame_ != NULL) { | 1888 if (frame_ != NULL) { |
| 1880 Branch(false, node->break_target()); | 1889 Branch(false, node->break_target()); |
| 1881 } | 1890 } |
| 1882 if (frame_ != NULL || body.is_linked()) { | 1891 if (frame_ != NULL || body.is_linked()) { |
| 1883 body.Bind(); | 1892 body.Bind(); |
| 1884 } | 1893 } |
| 1885 } | 1894 } |
| 1886 | 1895 |
| 1887 if (frame_ != NULL) { | 1896 if (frame_ != NULL) { |
| 1888 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1897 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1889 Visit(node->body()); | 1898 Visit(node->body()); |
| 1899 if (frame_ != NULL) { |
| 1900 frame_->SpillAll(); |
| 1901 } |
| 1890 | 1902 |
| 1891 if (node->next() == NULL) { | 1903 if (node->next() == NULL) { |
| 1892 // If there is no update statement and control flow can fall out | 1904 // If there is no update statement and control flow can fall out |
| 1893 // of the loop, jump directly to the continue label. | 1905 // of the loop, jump directly to the continue label. |
| 1894 if (frame_ != NULL) { | 1906 if (frame_ != NULL) { |
| 1895 node->continue_target()->Jump(); | 1907 node->continue_target()->Jump(); |
| 1896 } | 1908 } |
| 1897 } else { | 1909 } else { |
| 1898 // If there is an update statement and control flow can reach it | 1910 // If there is an update statement and control flow can reach it |
| 1899 // via falling out of the body of the loop or continuing, we | 1911 // via falling out of the body of the loop or continuing, we |
| 1900 // compile the update statement. | 1912 // compile the update statement. |
| 1901 if (frame_ != NULL || node->continue_target()->is_linked()) { | 1913 if (frame_ != NULL || node->continue_target()->is_linked()) { |
| 1902 node->continue_target()->Bind(); | 1914 node->continue_target()->Bind(); |
| 1903 // Record source position of the statement as this code which is | 1915 // Record source position of the statement as this code which is |
| 1904 // after the code for the body actually belongs to the loop | 1916 // after the code for the body actually belongs to the loop |
| 1905 // statement and not the body. | 1917 // statement and not the body. |
| 1906 RecordStatementPosition(node); | 1918 RecordStatementPosition(node); |
| 1907 __ RecordPosition(node->statement_pos()); | 1919 __ RecordPosition(node->statement_pos()); |
| 1908 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1920 ASSERT(node->type() == LoopStatement::FOR_LOOP); |
| 1909 Visit(node->next()); | 1921 Visit(node->next()); |
| 1922 // TODO(): Can frame_ actually be NULL here? |
| 1923 if (frame_ != NULL) { |
| 1924 frame_->SpillAll(); |
| 1925 } |
| 1910 loop.Jump(); | 1926 loop.Jump(); |
| 1911 } | 1927 } |
| 1912 } | 1928 } |
| 1913 } | 1929 } |
| 1914 break; | 1930 break; |
| 1915 } | 1931 } |
| 1916 } | 1932 } |
| 1917 | 1933 |
| 1918 DecrementLoopNesting(); | 1934 DecrementLoopNesting(); |
| 1919 if (node->break_target()->is_linked()) { | 1935 if (node->break_target()->is_linked()) { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2082 } | 2098 } |
| 2083 } | 2099 } |
| 2084 } | 2100 } |
| 2085 // Discard the i'th entry pushed above or else the remainder of the | 2101 // Discard the i'th entry pushed above or else the remainder of the |
| 2086 // reference, whichever is currently on top of the stack. | 2102 // reference, whichever is currently on top of the stack. |
| 2087 frame_->Drop(); | 2103 frame_->Drop(); |
| 2088 | 2104 |
| 2089 // Body. | 2105 // Body. |
| 2090 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2106 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 2091 Visit(node->body()); | 2107 Visit(node->body()); |
| 2108 if (frame_ != NULL) { |
| 2109 frame_->SpillAll(); |
| 2110 } |
| 2092 | 2111 |
| 2093 // Next. | 2112 // Next. |
| 2094 node->continue_target()->Bind(); | 2113 node->continue_target()->Bind(); |
| 2095 frame_->EmitPop(eax); | 2114 frame_->EmitPop(eax); |
| 2096 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 2115 __ add(Operand(eax), Immediate(Smi::FromInt(1))); |
| 2097 frame_->EmitPush(eax); | 2116 frame_->EmitPush(eax); |
| 2098 entry.Jump(); | 2117 entry.Jump(); |
| 2099 | 2118 |
| 2100 // Cleanup. | 2119 // Cleanup. |
| 2101 cleanup.Bind(); | 2120 cleanup.Bind(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2127 // convenient property that it doesn't matter whether a value is | 2146 // convenient property that it doesn't matter whether a value is |
| 2128 // immediately on top of or underneath a zero-sized reference. | 2147 // immediately on top of or underneath a zero-sized reference. |
| 2129 ref.SetValue(NOT_CONST_INIT); | 2148 ref.SetValue(NOT_CONST_INIT); |
| 2130 } | 2149 } |
| 2131 | 2150 |
| 2132 // Remove the exception from the stack. | 2151 // Remove the exception from the stack. |
| 2133 frame_->Drop(); | 2152 frame_->Drop(); |
| 2134 | 2153 |
| 2135 VisitStatements(node->catch_block()->statements()); | 2154 VisitStatements(node->catch_block()->statements()); |
| 2136 if (frame_ != NULL) { | 2155 if (frame_ != NULL) { |
| 2156 frame_->SpillAll(); |
| 2137 exit.Jump(); | 2157 exit.Jump(); |
| 2138 } | 2158 } |
| 2139 | 2159 |
| 2140 | 2160 |
| 2141 // --- Try block --- | 2161 // --- Try block --- |
| 2142 try_block.Bind(); | 2162 try_block.Bind(); |
| 2143 | 2163 |
| 2144 frame_->PushTryHandler(TRY_CATCH_HANDLER); | 2164 frame_->PushTryHandler(TRY_CATCH_HANDLER); |
| 2145 int handler_height = frame_->height(); | 2165 int handler_height = frame_->height(); |
| 2146 | 2166 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2157 for (int i = 0; i < nof_escapes; i++) { | 2177 for (int i = 0; i < nof_escapes; i++) { |
| 2158 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2178 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2159 } | 2179 } |
| 2160 bool function_return_was_shadowed = function_return_is_shadowed_; | 2180 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2161 function_return_is_shadowed_ = true; | 2181 function_return_is_shadowed_ = true; |
| 2162 | 2182 |
| 2163 // Generate code for the statements in the try block. | 2183 // Generate code for the statements in the try block. |
| 2164 bool was_inside_try = is_inside_try_; | 2184 bool was_inside_try = is_inside_try_; |
| 2165 is_inside_try_ = true; | 2185 is_inside_try_ = true; |
| 2166 VisitStatements(node->try_block()->statements()); | 2186 VisitStatements(node->try_block()->statements()); |
| 2187 if (frame_ != NULL) { |
| 2188 frame_->SpillAll(); |
| 2189 } |
| 2167 is_inside_try_ = was_inside_try; | 2190 is_inside_try_ = was_inside_try; |
| 2168 | 2191 |
| 2169 // Stop the introduced shadowing and count the number of required unlinks. | 2192 // Stop the introduced shadowing and count the number of required unlinks. |
| 2170 // After shadowing stops, the original targets are unshadowed and the | 2193 // After shadowing stops, the original targets are unshadowed and the |
| 2171 // ShadowTargets represent the formerly shadowing targets. | 2194 // ShadowTargets represent the formerly shadowing targets. |
| 2172 int nof_unlinks = 0; | 2195 int nof_unlinks = 0; |
| 2173 for (int i = 0; i <= nof_escapes; i++) { | 2196 for (int i = 0; i <= nof_escapes; i++) { |
| 2174 shadows[i]->StopShadowing(); | 2197 shadows[i]->StopShadowing(); |
| 2175 if (shadows[i]->is_linked()) nof_unlinks++; | 2198 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2176 } | 2199 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2265 for (int i = 0; i < nof_escapes; i++) { | 2288 for (int i = 0; i < nof_escapes; i++) { |
| 2266 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2289 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2267 } | 2290 } |
| 2268 bool function_return_was_shadowed = function_return_is_shadowed_; | 2291 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2269 function_return_is_shadowed_ = true; | 2292 function_return_is_shadowed_ = true; |
| 2270 | 2293 |
| 2271 // Generate code for the statements in the try block. | 2294 // Generate code for the statements in the try block. |
| 2272 bool was_inside_try = is_inside_try_; | 2295 bool was_inside_try = is_inside_try_; |
| 2273 is_inside_try_ = true; | 2296 is_inside_try_ = true; |
| 2274 VisitStatements(node->try_block()->statements()); | 2297 VisitStatements(node->try_block()->statements()); |
| 2298 if (frame_ != NULL) { |
| 2299 frame_->SpillAll(); |
| 2300 } |
| 2275 is_inside_try_ = was_inside_try; | 2301 is_inside_try_ = was_inside_try; |
| 2276 | 2302 |
| 2277 // Stop the introduced shadowing and count the number of required unlinks. | 2303 // Stop the introduced shadowing and count the number of required unlinks. |
| 2278 // After shadowing stops, the original targets are unshadowed and the | 2304 // After shadowing stops, the original targets are unshadowed and the |
| 2279 // ShadowTargets represent the formerly shadowing targets. | 2305 // ShadowTargets represent the formerly shadowing targets. |
| 2280 int nof_unlinks = 0; | 2306 int nof_unlinks = 0; |
| 2281 for (int i = 0; i <= nof_escapes; i++) { | 2307 for (int i = 0; i <= nof_escapes; i++) { |
| 2282 shadows[i]->StopShadowing(); | 2308 shadows[i]->StopShadowing(); |
| 2283 if (shadows[i]->is_linked()) nof_unlinks++; | 2309 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2284 } | 2310 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2341 // that a break/continue crossing this statement can restore the | 2367 // that a break/continue crossing this statement can restore the |
| 2342 // stack. | 2368 // stack. |
| 2343 const int kFinallyStackSize = 2 * kPointerSize; | 2369 const int kFinallyStackSize = 2 * kPointerSize; |
| 2344 break_stack_height_ += kFinallyStackSize; | 2370 break_stack_height_ += kFinallyStackSize; |
| 2345 | 2371 |
| 2346 // Generate code for the statements in the finally block. | 2372 // Generate code for the statements in the finally block. |
| 2347 VisitStatements(node->finally_block()->statements()); | 2373 VisitStatements(node->finally_block()->statements()); |
| 2348 | 2374 |
| 2349 break_stack_height_ -= kFinallyStackSize; | 2375 break_stack_height_ -= kFinallyStackSize; |
| 2350 if (frame_ != NULL) { | 2376 if (frame_ != NULL) { |
| 2377 frame_->SpillAll(); |
| 2351 JumpTarget exit(this); | 2378 JumpTarget exit(this); |
| 2352 // Restore state and return value or faked TOS. | 2379 // Restore state and return value or faked TOS. |
| 2353 frame_->EmitPop(ecx); | 2380 frame_->EmitPop(ecx); |
| 2354 frame_->EmitPop(eax); | 2381 frame_->EmitPop(eax); |
| 2355 | 2382 |
| 2356 // Generate code to jump to the right destination for all used | 2383 // Generate code to jump to the right destination for all used |
| 2357 // (formerly) shadowing targets. | 2384 // (formerly) shadowing targets. |
| 2358 for (int i = 0; i <= nof_escapes; i++) { | 2385 for (int i = 0; i <= nof_escapes; i++) { |
| 2359 if (shadows[i]->is_bound()) { | 2386 if (shadows[i]->is_bound()) { |
| 2360 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); | 2387 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2845 | 2872 |
| 2846 | 2873 |
| 2847 bool CodeGenerator::IsInlineSmi(Literal* literal) { | 2874 bool CodeGenerator::IsInlineSmi(Literal* literal) { |
| 2848 if (literal == NULL || !literal->handle()->IsSmi()) return false; | 2875 if (literal == NULL || !literal->handle()->IsSmi()) return false; |
| 2849 int int_value = Smi::cast(*literal->handle())->value(); | 2876 int int_value = Smi::cast(*literal->handle())->value(); |
| 2850 return is_intn(int_value, kMaxSmiInlinedBits); | 2877 return is_intn(int_value, kMaxSmiInlinedBits); |
| 2851 } | 2878 } |
| 2852 | 2879 |
| 2853 | 2880 |
| 2854 void CodeGenerator::VisitAssignment(Assignment* node) { | 2881 void CodeGenerator::VisitAssignment(Assignment* node) { |
| 2855 frame_->SpillAll(); | |
| 2856 Comment cmnt(masm_, "[ Assignment"); | 2882 Comment cmnt(masm_, "[ Assignment"); |
| 2857 | 2883 |
| 2858 RecordStatementPosition(node); | 2884 RecordStatementPosition(node); |
| 2859 { Reference target(this, node->target()); | 2885 { Reference target(this, node->target()); |
| 2860 if (target.is_illegal()) { | 2886 if (target.is_illegal()) { |
| 2861 // Fool the virtual frame into thinking that we left the assignment's | 2887 // Fool the virtual frame into thinking that we left the assignment's |
| 2862 // value on the frame. | 2888 // value on the frame. |
| 2863 frame_->EmitPush(Immediate(Smi::FromInt(0))); | 2889 frame_->EmitPush(Immediate(Smi::FromInt(0))); |
| 2864 return; | 2890 return; |
| 2865 } | 2891 } |
| 2866 | 2892 |
| 2867 if (node->op() == Token::ASSIGN || | 2893 if (node->op() == Token::ASSIGN || |
| 2868 node->op() == Token::INIT_VAR || | 2894 node->op() == Token::INIT_VAR || |
| 2869 node->op() == Token::INIT_CONST) { | 2895 node->op() == Token::INIT_CONST) { |
| 2870 Load(node->value()); | 2896 Load(node->value()); |
| 2871 | 2897 |
| 2872 } else { | 2898 } else { |
| 2899 frame_->SpillAll(); |
| 2873 target.GetValue(NOT_INSIDE_TYPEOF); | 2900 target.GetValue(NOT_INSIDE_TYPEOF); |
| 2874 Literal* literal = node->value()->AsLiteral(); | 2901 Literal* literal = node->value()->AsLiteral(); |
| 2875 if (IsInlineSmi(literal)) { | 2902 if (IsInlineSmi(literal)) { |
| 2876 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, | 2903 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, |
| 2877 NO_OVERWRITE); | 2904 NO_OVERWRITE); |
| 2878 } else { | 2905 } else { |
| 2879 Load(node->value()); | 2906 Load(node->value()); |
| 2880 frame_->SpillAll(); | 2907 frame_->SpillAll(); |
| 2881 GenericBinaryOperation(node->binary_op(), node->type()); | 2908 GenericBinaryOperation(node->binary_op(), node->type()); |
| 2882 } | 2909 } |
| (...skipping 2604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5487 | 5514 |
| 5488 // Slow-case: Go through the JavaScript implementation. | 5515 // Slow-case: Go through the JavaScript implementation. |
| 5489 __ bind(&slow); | 5516 __ bind(&slow); |
| 5490 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5517 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 5491 } | 5518 } |
| 5492 | 5519 |
| 5493 | 5520 |
| 5494 #undef __ | 5521 #undef __ |
| 5495 | 5522 |
| 5496 } } // namespace v8::internal | 5523 } } // namespace v8::internal |
| OLD | NEW |