| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 allocator_(NULL), | 83 allocator_(NULL), |
| 84 cc_reg_(no_condition), | 84 cc_reg_(no_condition), |
| 85 state_(NULL), | 85 state_(NULL), |
| 86 is_inside_try_(false), | 86 is_inside_try_(false), |
| 87 break_stack_height_(0), | 87 break_stack_height_(0), |
| 88 loop_nesting_(0), | 88 loop_nesting_(0), |
| 89 function_return_is_shadowed_(false) { | 89 function_return_is_shadowed_(false) { |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 void CodeGenerator::SetFrame(VirtualFrame* frame) { |
| 94 if (frame_ != NULL) { |
| 95 frame_->DetachFromCodeGenerator(); |
| 96 } |
| 97 if (frame != NULL) { |
| 98 frame->AttachToCodeGenerator(); |
| 99 } |
| 100 frame_ = frame; |
| 101 } |
| 102 |
| 103 |
| 104 void CodeGenerator::DeleteFrame() { |
| 105 if (frame_ != NULL) { |
| 106 frame_->DetachFromCodeGenerator(); |
| 107 delete frame_; |
| 108 frame_ = NULL; |
| 109 } |
| 110 } |
| 111 |
| 112 |
| 93 // Calling conventions: | 113 // Calling conventions: |
| 94 // ebp: frame pointer | 114 // ebp: frame pointer |
| 95 // esp: stack pointer | 115 // esp: stack pointer |
| 96 // edi: caller's parameter pointer | 116 // edi: caller's parameter pointer |
| 97 // esi: callee's context | 117 // esi: callee's context |
| 98 | 118 |
| 99 void CodeGenerator::GenCode(FunctionLiteral* fun) { | 119 void CodeGenerator::GenCode(FunctionLiteral* fun) { |
| 100 // Record the position for debugging purposes. | 120 // Record the position for debugging purposes. |
| 101 __ RecordPosition(fun->start_position()); | 121 __ RecordPosition(fun->start_position()); |
| 102 | 122 |
| 103 ZoneList<Statement*>* body = fun->body(); | 123 ZoneList<Statement*>* body = fun->body(); |
| 104 | 124 |
| 105 // Initialize state. | 125 // Initialize state. |
| 106 ASSERT(scope_ == NULL); | 126 ASSERT(scope_ == NULL); |
| 107 scope_ = fun->scope(); | 127 scope_ = fun->scope(); |
| 108 ASSERT(frame_ == NULL); | |
| 109 set_frame(new VirtualFrame(this)); | |
| 110 ASSERT(allocator_ == NULL); | 128 ASSERT(allocator_ == NULL); |
| 111 RegisterAllocator register_allocator(this); | 129 RegisterAllocator register_allocator(this); |
| 112 allocator_ = ®ister_allocator; | 130 allocator_ = ®ister_allocator; |
| 131 ASSERT(frame_ == NULL); |
| 132 SetFrame(new VirtualFrame(this)); |
| 113 cc_reg_ = no_condition; | 133 cc_reg_ = no_condition; |
| 114 function_return_.set_code_generator(this); | 134 function_return_.set_code_generator(this); |
| 115 function_return_is_shadowed_ = false; | 135 function_return_is_shadowed_ = false; |
| 116 | 136 |
| 117 // Adjust for function-level loop nesting. | 137 // Adjust for function-level loop nesting. |
| 118 loop_nesting_ += fun->loop_nesting(); | 138 loop_nesting_ += fun->loop_nesting(); |
| 119 | 139 |
| 120 { | 140 { |
| 121 CodeGenState state(this); | 141 CodeGenState state(this); |
| 122 | 142 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 loop_nesting_ -= fun->loop_nesting(); | 301 loop_nesting_ -= fun->loop_nesting(); |
| 282 | 302 |
| 283 // Code generation state must be reset. | 303 // Code generation state must be reset. |
| 284 ASSERT(state_ == NULL); | 304 ASSERT(state_ == NULL); |
| 285 ASSERT(loop_nesting() == 0); | 305 ASSERT(loop_nesting() == 0); |
| 286 ASSERT(!function_return_is_shadowed_); | 306 ASSERT(!function_return_is_shadowed_); |
| 287 function_return_.Unuse(); | 307 function_return_.Unuse(); |
| 288 ASSERT(!has_cc()); | 308 ASSERT(!has_cc()); |
| 289 // There is no need to delete the register allocator, it is a | 309 // There is no need to delete the register allocator, it is a |
| 290 // stack-allocated local. | 310 // stack-allocated local. |
| 311 DeleteFrame(); |
| 291 allocator_ = NULL; | 312 allocator_ = NULL; |
| 292 delete_frame(); | |
| 293 scope_ = NULL; | 313 scope_ = NULL; |
| 294 } | 314 } |
| 295 | 315 |
| 296 | 316 |
| 297 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 317 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { |
| 298 // Currently, this assertion will fail if we try to assign to | 318 // Currently, this assertion will fail if we try to assign to |
| 299 // a constant variable that is constant because it is read-only | 319 // a constant variable that is constant because it is read-only |
| 300 // (such as the variable referring to a named function expression). | 320 // (such as the variable referring to a named function expression). |
| 301 // We need to implement assignments to read-only variables. | 321 // We need to implement assignments to read-only variables. |
| 302 // Ideally, we should do this during AST generation (by converting | 322 // Ideally, we should do this during AST generation (by converting |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 ref->set_type(Reference::NAMED); | 510 ref->set_type(Reference::NAMED); |
| 491 } else { | 511 } else { |
| 492 Load(property->key()); | 512 Load(property->key()); |
| 493 frame_->SpillAll(); | 513 frame_->SpillAll(); |
| 494 ref->set_type(Reference::KEYED); | 514 ref->set_type(Reference::KEYED); |
| 495 } | 515 } |
| 496 } else if (var != NULL) { | 516 } else if (var != NULL) { |
| 497 // The expression is a variable proxy that does not rewrite to a | 517 // The expression is a variable proxy that does not rewrite to a |
| 498 // property. Global variables are treated as named property references. | 518 // property. Global variables are treated as named property references. |
| 499 if (var->is_global()) { | 519 if (var->is_global()) { |
| 520 frame_->SpillAll(); |
| 500 LoadGlobal(); | 521 LoadGlobal(); |
| 501 ref->set_type(Reference::NAMED); | 522 ref->set_type(Reference::NAMED); |
| 502 } else { | 523 } else { |
| 503 ASSERT(var->slot() != NULL); | 524 ASSERT(var->slot() != NULL); |
| 504 ref->set_type(Reference::SLOT); | 525 ref->set_type(Reference::SLOT); |
| 505 } | 526 } |
| 506 } else { | 527 } else { |
| 507 // Anything else is a runtime error. | 528 // Anything else is a runtime error. |
| 508 Load(e); | 529 Load(e); |
| 509 frame_->SpillAll(); | 530 frame_->SpillAll(); |
| (...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 | 1275 |
| 1255 | 1276 |
| 1256 void CodeGenerator::CheckStack() { | 1277 void CodeGenerator::CheckStack() { |
| 1257 if (FLAG_check_stack) { | 1278 if (FLAG_check_stack) { |
| 1258 JumpTarget stack_is_ok(this); | 1279 JumpTarget stack_is_ok(this); |
| 1259 StackCheckStub stub; | 1280 StackCheckStub stub; |
| 1260 ExternalReference stack_guard_limit = | 1281 ExternalReference stack_guard_limit = |
| 1261 ExternalReference::address_of_stack_guard_limit(); | 1282 ExternalReference::address_of_stack_guard_limit(); |
| 1262 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); | 1283 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); |
| 1263 stack_is_ok.Branch(above_equal, taken); | 1284 stack_is_ok.Branch(above_equal, taken); |
| 1285 // The stack check can trigger the debugger. Before calling it, all |
| 1286 // values including constants must be spilled to the frame. |
| 1287 frame_->SpillAll(); |
| 1264 frame_->CallStub(&stub, 0); | 1288 frame_->CallStub(&stub, 0); |
| 1265 stack_is_ok.Bind(); | 1289 stack_is_ok.Bind(); |
| 1266 } | 1290 } |
| 1267 } | 1291 } |
| 1268 | 1292 |
| 1269 | 1293 |
| 1270 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 1294 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 1271 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { | 1295 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { |
| 1272 Visit(statements->at(i)); | 1296 Visit(statements->at(i)); |
| 1273 } | 1297 } |
| 1274 } | 1298 } |
| 1275 | 1299 |
| 1276 | 1300 |
| 1277 void CodeGenerator::VisitBlock(Block* node) { | 1301 void CodeGenerator::VisitBlock(Block* node) { |
| 1278 frame_->SpillAll(); | |
| 1279 Comment cmnt(masm_, "[ Block"); | 1302 Comment cmnt(masm_, "[ Block"); |
| 1280 RecordStatementPosition(node); | 1303 RecordStatementPosition(node); |
| 1281 node->set_break_stack_height(break_stack_height_); | 1304 node->set_break_stack_height(break_stack_height_); |
| 1282 node->break_target()->set_code_generator(this); | 1305 node->break_target()->set_code_generator(this); |
| 1283 VisitStatements(node->statements()); | 1306 VisitStatements(node->statements()); |
| 1284 if (node->break_target()->is_linked()) { | 1307 if (node->break_target()->is_linked()) { |
| 1285 node->break_target()->Bind(); | 1308 node->break_target()->Bind(); |
| 1286 } | 1309 } |
| 1287 } | 1310 } |
| 1288 | 1311 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 | 1386 |
| 1364 | 1387 |
| 1365 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1388 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
| 1366 Comment cmnt(masm_, "[ ExpressionStatement"); | 1389 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 1367 RecordStatementPosition(node); | 1390 RecordStatementPosition(node); |
| 1368 Expression* expression = node->expression(); | 1391 Expression* expression = node->expression(); |
| 1369 expression->MarkAsStatement(); | 1392 expression->MarkAsStatement(); |
| 1370 Load(expression); | 1393 Load(expression); |
| 1371 // Remove the lingering expression result from the top of stack. | 1394 // Remove the lingering expression result from the top of stack. |
| 1372 frame_->Drop(); | 1395 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 } | 1396 } |
| 1378 | 1397 |
| 1379 | 1398 |
| 1380 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1399 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
| 1381 frame_->SpillAll(); | 1400 frame_->SpillAll(); |
| 1382 Comment cmnt(masm_, "// EmptyStatement"); | 1401 Comment cmnt(masm_, "// EmptyStatement"); |
| 1383 // nothing to do | 1402 // nothing to do |
| 1384 } | 1403 } |
| 1385 | 1404 |
| 1386 | 1405 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1409 // If control flow can reach the then part via fall-through from the | 1428 // If control flow can reach the then part via fall-through from the |
| 1410 // test or a branch to the target, compile it. | 1429 // test or a branch to the target, compile it. |
| 1411 then.Bind(); | 1430 then.Bind(); |
| 1412 Visit(node->then_statement()); | 1431 Visit(node->then_statement()); |
| 1413 } | 1432 } |
| 1414 if (frame_ != NULL) { | 1433 if (frame_ != NULL) { |
| 1415 // A NULL frame here indicates that control did not fall out of the | 1434 // 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 | 1435 // 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 | 1436 // 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). | 1437 // don't have a current virtual frame to set at the exit label). |
| 1438 frame_->SpillAll(); |
| 1419 exit.Jump(); | 1439 exit.Jump(); |
| 1420 } | 1440 } |
| 1421 // else | 1441 // else |
| 1422 if (else_.is_linked()) { | 1442 if (else_.is_linked()) { |
| 1423 // Control flow for if-then-else does not fall-through to the else | 1443 // 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. | 1444 // part, it can only reach here via jump if at all. |
| 1425 else_.Bind(); | 1445 else_.Bind(); |
| 1426 Visit(node->else_statement()); | 1446 Visit(node->else_statement()); |
| 1427 } | 1447 } |
| 1428 | 1448 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1525 } | 1545 } |
| 1526 | 1546 |
| 1527 // Add a label for checking the size of the code used for returning. | 1547 // Add a label for checking the size of the code used for returning. |
| 1528 Label check_exit_codesize; | 1548 Label check_exit_codesize; |
| 1529 __ bind(&check_exit_codesize); | 1549 __ bind(&check_exit_codesize); |
| 1530 | 1550 |
| 1531 // Leave the frame and return popping the arguments and the | 1551 // Leave the frame and return popping the arguments and the |
| 1532 // receiver. | 1552 // receiver. |
| 1533 frame_->Exit(); | 1553 frame_->Exit(); |
| 1534 __ ret((scope_->num_parameters() + 1) * kPointerSize); | 1554 __ ret((scope_->num_parameters() + 1) * kPointerSize); |
| 1535 delete_frame(); | 1555 DeleteFrame(); |
| 1536 | 1556 |
| 1537 // Check that the size of the code used for returning matches what is | 1557 // Check that the size of the code used for returning matches what is |
| 1538 // expected by the debugger. | 1558 // expected by the debugger. |
| 1539 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, | 1559 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, |
| 1540 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); | 1560 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 1541 } | 1561 } |
| 1542 } | 1562 } |
| 1543 | 1563 |
| 1544 | 1564 |
| 1545 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1565 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1702 default_exit.Bind(); | 1722 default_exit.Bind(); |
| 1703 } else { | 1723 } else { |
| 1704 fall_through.Bind(); | 1724 fall_through.Bind(); |
| 1705 fall_through.Unuse(); | 1725 fall_through.Unuse(); |
| 1706 } | 1726 } |
| 1707 VisitStatements(clause->statements()); | 1727 VisitStatements(clause->statements()); |
| 1708 | 1728 |
| 1709 // If control flow can fall through from the body, jump to the next body | 1729 // If control flow can fall through from the body, jump to the next body |
| 1710 // or the end of the statement. | 1730 // or the end of the statement. |
| 1711 if (frame_ != NULL) { | 1731 if (frame_ != NULL) { |
| 1732 frame_->SpillAll(); |
| 1712 if (i < length - 1 && cases->at(i + 1)->is_default()) { | 1733 if (i < length - 1 && cases->at(i + 1)->is_default()) { |
| 1713 default_entry.Jump(); | 1734 default_entry.Jump(); |
| 1714 } else { | 1735 } else { |
| 1715 fall_through.Jump(); | 1736 fall_through.Jump(); |
| 1716 } | 1737 } |
| 1717 } | 1738 } |
| 1718 } | 1739 } |
| 1719 | 1740 |
| 1720 // The final "test" removes the switch value. | 1741 // The final "test" removes the switch value. |
| 1721 next_test.Bind(); | 1742 next_test.Bind(); |
| 1722 frame_->Drop(); | 1743 frame_->Drop(); |
| 1723 | 1744 |
| 1724 // If there is a default clause, compile it. | 1745 // If there is a default clause, compile it. |
| 1725 if (default_clause != NULL) { | 1746 if (default_clause != NULL) { |
| 1726 Comment cmnt(masm_, "[ Default clause"); | 1747 Comment cmnt(masm_, "[ Default clause"); |
| 1727 default_entry.Bind(); | 1748 default_entry.Bind(); |
| 1728 VisitStatements(default_clause->statements()); | 1749 VisitStatements(default_clause->statements()); |
| 1750 if (frame_ != NULL) { |
| 1751 frame_->SpillAll(); |
| 1752 } |
| 1729 // If control flow can fall out of the default and there is a case after | 1753 // If control flow can fall out of the default and there is a case after |
| 1730 // it, jump to that case's body. | 1754 // it, jump to that case's body. |
| 1731 if (frame_ != NULL && default_exit.is_bound()) { | 1755 if (frame_ != NULL && default_exit.is_bound()) { |
| 1732 default_exit.Jump(); | 1756 default_exit.Jump(); |
| 1733 } | 1757 } |
| 1734 } | 1758 } |
| 1735 | 1759 |
| 1736 if (fall_through.is_linked()) { | 1760 if (fall_through.is_linked()) { |
| 1737 fall_through.Bind(); | 1761 fall_through.Bind(); |
| 1738 } | 1762 } |
| 1739 | 1763 |
| 1740 if (node->break_target()->is_linked()) { | 1764 if (node->break_target()->is_linked()) { |
| 1741 node->break_target()->Bind(); | 1765 node->break_target()->Bind(); |
| 1742 } | 1766 } |
| 1743 } | 1767 } |
| 1744 | 1768 |
| 1745 | 1769 |
| 1746 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1770 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { |
| 1747 frame_->SpillAll(); | |
| 1748 Comment cmnt(masm_, "[ LoopStatement"); | 1771 Comment cmnt(masm_, "[ LoopStatement"); |
| 1749 RecordStatementPosition(node); | 1772 RecordStatementPosition(node); |
| 1750 node->set_break_stack_height(break_stack_height_); | 1773 node->set_break_stack_height(break_stack_height_); |
| 1751 node->break_target()->set_code_generator(this); | 1774 node->break_target()->set_code_generator(this); |
| 1752 node->continue_target()->set_code_generator(this); | 1775 node->continue_target()->set_code_generator(this); |
| 1753 | 1776 |
| 1754 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a | 1777 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a |
| 1755 // known result for the test expression, with no side effects. | 1778 // known result for the test expression, with no side effects. |
| 1756 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1779 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; |
| 1757 if (node->cond() == NULL) { | 1780 if (node->cond() == NULL) { |
| 1758 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1781 ASSERT(node->type() == LoopStatement::FOR_LOOP); |
| 1759 info = ALWAYS_TRUE; | 1782 info = ALWAYS_TRUE; |
| 1760 } else { | 1783 } else { |
| 1761 Literal* lit = node->cond()->AsLiteral(); | 1784 Literal* lit = node->cond()->AsLiteral(); |
| 1762 if (lit != NULL) { | 1785 if (lit != NULL) { |
| 1763 if (lit->IsTrue()) { | 1786 if (lit->IsTrue()) { |
| 1764 info = ALWAYS_TRUE; | 1787 info = ALWAYS_TRUE; |
| 1765 } else if (lit->IsFalse()) { | 1788 } else if (lit->IsFalse()) { |
| 1766 info = ALWAYS_FALSE; | 1789 info = ALWAYS_FALSE; |
| 1767 } | 1790 } |
| 1768 } | 1791 } |
| 1769 } | 1792 } |
| 1770 | 1793 |
| 1771 switch (node->type()) { | 1794 switch (node->type()) { |
| 1772 case LoopStatement::DO_LOOP: { | 1795 case LoopStatement::DO_LOOP: { |
| 1796 // The new code generator does not yet compile do loops. |
| 1797 frame_->SpillAll(); |
| 1773 JumpTarget body(this); | 1798 JumpTarget body(this); |
| 1774 IncrementLoopNesting(); | 1799 IncrementLoopNesting(); |
| 1775 // Label the body. | 1800 // Label the body. |
| 1776 if (info == ALWAYS_TRUE) { | 1801 if (info == ALWAYS_TRUE) { |
| 1777 node->continue_target()->Bind(); | 1802 node->continue_target()->Bind(); |
| 1778 } else if (info == ALWAYS_FALSE) { | 1803 } else if (info == ALWAYS_FALSE) { |
| 1779 // There is no need, we will never jump back. | 1804 // There is no need, we will never jump back. |
| 1780 } else { | 1805 } else { |
| 1781 ASSERT(info == DONT_KNOW); | 1806 ASSERT(info == DONT_KNOW); |
| 1782 body.Bind(); | 1807 body.Bind(); |
| 1783 } | 1808 } |
| 1784 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1809 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1785 Visit(node->body()); | 1810 Visit(node->body()); |
| 1811 if (frame_ != NULL) { |
| 1812 frame_->SpillAll(); |
| 1813 } |
| 1786 | 1814 |
| 1787 // Compile the "test". | 1815 // Compile the "test". |
| 1788 if (info == ALWAYS_TRUE) { | 1816 if (info == ALWAYS_TRUE) { |
| 1789 if (frame_ != NULL) { | 1817 if (frame_ != NULL) { |
| 1790 // If control flow can fall off the end of the body, jump back to | 1818 // If control flow can fall off the end of the body, jump back to |
| 1791 // the top. | 1819 // the top. |
| 1792 node->continue_target()->Jump(); | 1820 node->continue_target()->Jump(); |
| 1793 } | 1821 } |
| 1794 } else if (info == ALWAYS_FALSE) { | 1822 } else if (info == ALWAYS_FALSE) { |
| 1795 // If we have a continue in the body, we only have to bind its jump | 1823 // If we have a continue in the body, we only have to bind its jump |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1809 // A NULL frame here indicates that control flow did not fall | 1837 // A NULL frame here indicates that control flow did not fall |
| 1810 // out of the test expression. | 1838 // out of the test expression. |
| 1811 Branch(true, &body); | 1839 Branch(true, &body); |
| 1812 } | 1840 } |
| 1813 } | 1841 } |
| 1814 } | 1842 } |
| 1815 break; | 1843 break; |
| 1816 } | 1844 } |
| 1817 | 1845 |
| 1818 case LoopStatement::WHILE_LOOP: { | 1846 case LoopStatement::WHILE_LOOP: { |
| 1847 // The new code generator does not yet compile while loops. |
| 1848 frame_->SpillAll(); |
| 1819 JumpTarget body(this); | 1849 JumpTarget body(this); |
| 1820 IncrementLoopNesting(); | 1850 IncrementLoopNesting(); |
| 1821 // Generate the loop header. | 1851 // Generate the loop header. |
| 1822 if (info == ALWAYS_TRUE) { | 1852 if (info == ALWAYS_TRUE) { |
| 1823 // Merely label the body with the continue target. | 1853 // Merely label the body with the continue target. |
| 1824 node->continue_target()->Bind(); | 1854 node->continue_target()->Bind(); |
| 1825 } else if (info == ALWAYS_FALSE) { | 1855 } else if (info == ALWAYS_FALSE) { |
| 1826 // There is no need to even compile the test or body. | 1856 // There is no need to even compile the test or body. |
| 1827 break; | 1857 break; |
| 1828 } else { | 1858 } else { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1840 if (frame_ != NULL || body.is_linked()) { | 1870 if (frame_ != NULL || body.is_linked()) { |
| 1841 body.Bind(); | 1871 body.Bind(); |
| 1842 } | 1872 } |
| 1843 } | 1873 } |
| 1844 if (frame_ != NULL) { | 1874 if (frame_ != NULL) { |
| 1845 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1875 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1846 Visit(node->body()); | 1876 Visit(node->body()); |
| 1847 | 1877 |
| 1848 // If control flow can fall out of the body, jump back to the top. | 1878 // If control flow can fall out of the body, jump back to the top. |
| 1849 if (frame_ != NULL) { | 1879 if (frame_ != NULL) { |
| 1880 frame_->SpillAll(); |
| 1850 node->continue_target()->Jump(); | 1881 node->continue_target()->Jump(); |
| 1851 } | 1882 } |
| 1852 } | 1883 } |
| 1853 break; | 1884 break; |
| 1854 } | 1885 } |
| 1855 | 1886 |
| 1856 case LoopStatement::FOR_LOOP: { | 1887 case LoopStatement::FOR_LOOP: { |
| 1857 JumpTarget loop(this); | 1888 JumpTarget loop(this); |
| 1858 JumpTarget body(this); | 1889 JumpTarget body(this); |
| 1859 if (node->init() != NULL) { | 1890 if (node->init() != NULL) { |
| 1860 Visit(node->init()); | 1891 Visit(node->init()); |
| 1861 } | 1892 } |
| 1862 | 1893 |
| 1863 IncrementLoopNesting(); | 1894 IncrementLoopNesting(); |
| 1864 // There is no need to compile the test or body. | 1895 // There is no need to compile the test or body. |
| 1865 if (info == ALWAYS_FALSE) break; | 1896 if (info == ALWAYS_FALSE) break; |
| 1866 | 1897 |
| 1867 // If there is no update statement, label the top of the loop with the | 1898 // Label the top of the loop for the backward CFG edge. If there is |
| 1868 // continue target, otherwise with the loop target. | 1899 // no update expression label it with the continue target, otherwise |
| 1900 // with the loop target. |
| 1869 if (node->next() == NULL) { | 1901 if (node->next() == NULL) { |
| 1870 node->continue_target()->Bind(); | 1902 node->continue_target()->Bind(); |
| 1871 } else { | 1903 } else { |
| 1872 loop.Bind(); | 1904 loop.Bind(); |
| 1873 } | 1905 } |
| 1874 | 1906 |
| 1875 // If the test is always true, there is no need to compile it. | 1907 // If the test is always true, there is no need to compile it. |
| 1876 if (info == DONT_KNOW) { | 1908 if (info == DONT_KNOW) { |
| 1877 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, | 1909 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, |
| 1878 &body, node->break_target(), true); | 1910 &body, node->break_target(), true); |
| 1879 if (frame_ != NULL) { | 1911 if (frame_ != NULL) { |
| 1880 Branch(false, node->break_target()); | 1912 Branch(false, node->break_target()); |
| 1881 } | 1913 } |
| 1882 if (frame_ != NULL || body.is_linked()) { | 1914 if (frame_ != NULL || body.is_linked()) { |
| 1883 body.Bind(); | 1915 body.Bind(); |
| 1884 } | 1916 } |
| 1885 } | 1917 } |
| 1886 | 1918 |
| 1887 if (frame_ != NULL) { | 1919 if (frame_ != NULL) { |
| 1888 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1920 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1889 Visit(node->body()); | 1921 Visit(node->body()); |
| 1890 | 1922 |
| 1891 if (node->next() == NULL) { | 1923 if (node->next() == NULL) { |
| 1892 // If there is no update statement and control flow can fall out | 1924 // If there is no update statement and control flow can fall out |
| 1893 // of the loop, jump directly to the continue label. | 1925 // of the loop, jump to the continue label. |
| 1894 if (frame_ != NULL) { | 1926 if (frame_ != NULL) { |
| 1895 node->continue_target()->Jump(); | 1927 node->continue_target()->Jump(); |
| 1896 } | 1928 } |
| 1897 } else { | 1929 } else { |
| 1898 // If there is an update statement and control flow can reach it | 1930 // 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 | 1931 // via falling out of the body of the loop or continuing, we |
| 1900 // compile the update statement. | 1932 // compile the update statement. |
| 1901 if (frame_ != NULL || node->continue_target()->is_linked()) { | 1933 if (frame_ != NULL || node->continue_target()->is_linked()) { |
| 1902 node->continue_target()->Bind(); | 1934 node->continue_target()->Bind(); |
| 1903 // Record source position of the statement as this code which is | 1935 // Record source position of the statement as this code which is |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2082 } | 2114 } |
| 2083 } | 2115 } |
| 2084 } | 2116 } |
| 2085 // Discard the i'th entry pushed above or else the remainder of the | 2117 // Discard the i'th entry pushed above or else the remainder of the |
| 2086 // reference, whichever is currently on top of the stack. | 2118 // reference, whichever is currently on top of the stack. |
| 2087 frame_->Drop(); | 2119 frame_->Drop(); |
| 2088 | 2120 |
| 2089 // Body. | 2121 // Body. |
| 2090 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2122 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 2091 Visit(node->body()); | 2123 Visit(node->body()); |
| 2124 if (frame_ != NULL) { |
| 2125 frame_->SpillAll(); |
| 2126 } |
| 2092 | 2127 |
| 2093 // Next. | 2128 // Next. |
| 2094 node->continue_target()->Bind(); | 2129 node->continue_target()->Bind(); |
| 2095 frame_->EmitPop(eax); | 2130 frame_->EmitPop(eax); |
| 2096 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 2131 __ add(Operand(eax), Immediate(Smi::FromInt(1))); |
| 2097 frame_->EmitPush(eax); | 2132 frame_->EmitPush(eax); |
| 2098 entry.Jump(); | 2133 entry.Jump(); |
| 2099 | 2134 |
| 2100 // Cleanup. | 2135 // Cleanup. |
| 2101 cleanup.Bind(); | 2136 cleanup.Bind(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2127 // convenient property that it doesn't matter whether a value is | 2162 // convenient property that it doesn't matter whether a value is |
| 2128 // immediately on top of or underneath a zero-sized reference. | 2163 // immediately on top of or underneath a zero-sized reference. |
| 2129 ref.SetValue(NOT_CONST_INIT); | 2164 ref.SetValue(NOT_CONST_INIT); |
| 2130 } | 2165 } |
| 2131 | 2166 |
| 2132 // Remove the exception from the stack. | 2167 // Remove the exception from the stack. |
| 2133 frame_->Drop(); | 2168 frame_->Drop(); |
| 2134 | 2169 |
| 2135 VisitStatements(node->catch_block()->statements()); | 2170 VisitStatements(node->catch_block()->statements()); |
| 2136 if (frame_ != NULL) { | 2171 if (frame_ != NULL) { |
| 2172 frame_->SpillAll(); |
| 2137 exit.Jump(); | 2173 exit.Jump(); |
| 2138 } | 2174 } |
| 2139 | 2175 |
| 2140 | 2176 |
| 2141 // --- Try block --- | 2177 // --- Try block --- |
| 2142 try_block.Bind(); | 2178 try_block.Bind(); |
| 2143 | 2179 |
| 2144 frame_->PushTryHandler(TRY_CATCH_HANDLER); | 2180 frame_->PushTryHandler(TRY_CATCH_HANDLER); |
| 2145 int handler_height = frame_->height(); | 2181 int handler_height = frame_->height(); |
| 2146 | 2182 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2157 for (int i = 0; i < nof_escapes; i++) { | 2193 for (int i = 0; i < nof_escapes; i++) { |
| 2158 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2194 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2159 } | 2195 } |
| 2160 bool function_return_was_shadowed = function_return_is_shadowed_; | 2196 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2161 function_return_is_shadowed_ = true; | 2197 function_return_is_shadowed_ = true; |
| 2162 | 2198 |
| 2163 // Generate code for the statements in the try block. | 2199 // Generate code for the statements in the try block. |
| 2164 bool was_inside_try = is_inside_try_; | 2200 bool was_inside_try = is_inside_try_; |
| 2165 is_inside_try_ = true; | 2201 is_inside_try_ = true; |
| 2166 VisitStatements(node->try_block()->statements()); | 2202 VisitStatements(node->try_block()->statements()); |
| 2203 if (frame_ != NULL) { |
| 2204 frame_->SpillAll(); |
| 2205 } |
| 2167 is_inside_try_ = was_inside_try; | 2206 is_inside_try_ = was_inside_try; |
| 2168 | 2207 |
| 2169 // Stop the introduced shadowing and count the number of required unlinks. | 2208 // Stop the introduced shadowing and count the number of required unlinks. |
| 2170 // After shadowing stops, the original targets are unshadowed and the | 2209 // After shadowing stops, the original targets are unshadowed and the |
| 2171 // ShadowTargets represent the formerly shadowing targets. | 2210 // ShadowTargets represent the formerly shadowing targets. |
| 2172 int nof_unlinks = 0; | 2211 int nof_unlinks = 0; |
| 2173 for (int i = 0; i <= nof_escapes; i++) { | 2212 for (int i = 0; i <= nof_escapes; i++) { |
| 2174 shadows[i]->StopShadowing(); | 2213 shadows[i]->StopShadowing(); |
| 2175 if (shadows[i]->is_linked()) nof_unlinks++; | 2214 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2176 } | 2215 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2265 for (int i = 0; i < nof_escapes; i++) { | 2304 for (int i = 0; i < nof_escapes; i++) { |
| 2266 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2305 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2267 } | 2306 } |
| 2268 bool function_return_was_shadowed = function_return_is_shadowed_; | 2307 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2269 function_return_is_shadowed_ = true; | 2308 function_return_is_shadowed_ = true; |
| 2270 | 2309 |
| 2271 // Generate code for the statements in the try block. | 2310 // Generate code for the statements in the try block. |
| 2272 bool was_inside_try = is_inside_try_; | 2311 bool was_inside_try = is_inside_try_; |
| 2273 is_inside_try_ = true; | 2312 is_inside_try_ = true; |
| 2274 VisitStatements(node->try_block()->statements()); | 2313 VisitStatements(node->try_block()->statements()); |
| 2314 if (frame_ != NULL) { |
| 2315 frame_->SpillAll(); |
| 2316 } |
| 2275 is_inside_try_ = was_inside_try; | 2317 is_inside_try_ = was_inside_try; |
| 2276 | 2318 |
| 2277 // Stop the introduced shadowing and count the number of required unlinks. | 2319 // Stop the introduced shadowing and count the number of required unlinks. |
| 2278 // After shadowing stops, the original targets are unshadowed and the | 2320 // After shadowing stops, the original targets are unshadowed and the |
| 2279 // ShadowTargets represent the formerly shadowing targets. | 2321 // ShadowTargets represent the formerly shadowing targets. |
| 2280 int nof_unlinks = 0; | 2322 int nof_unlinks = 0; |
| 2281 for (int i = 0; i <= nof_escapes; i++) { | 2323 for (int i = 0; i <= nof_escapes; i++) { |
| 2282 shadows[i]->StopShadowing(); | 2324 shadows[i]->StopShadowing(); |
| 2283 if (shadows[i]->is_linked()) nof_unlinks++; | 2325 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2284 } | 2326 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2341 // that a break/continue crossing this statement can restore the | 2383 // that a break/continue crossing this statement can restore the |
| 2342 // stack. | 2384 // stack. |
| 2343 const int kFinallyStackSize = 2 * kPointerSize; | 2385 const int kFinallyStackSize = 2 * kPointerSize; |
| 2344 break_stack_height_ += kFinallyStackSize; | 2386 break_stack_height_ += kFinallyStackSize; |
| 2345 | 2387 |
| 2346 // Generate code for the statements in the finally block. | 2388 // Generate code for the statements in the finally block. |
| 2347 VisitStatements(node->finally_block()->statements()); | 2389 VisitStatements(node->finally_block()->statements()); |
| 2348 | 2390 |
| 2349 break_stack_height_ -= kFinallyStackSize; | 2391 break_stack_height_ -= kFinallyStackSize; |
| 2350 if (frame_ != NULL) { | 2392 if (frame_ != NULL) { |
| 2393 frame_->SpillAll(); |
| 2351 JumpTarget exit(this); | 2394 JumpTarget exit(this); |
| 2352 // Restore state and return value or faked TOS. | 2395 // Restore state and return value or faked TOS. |
| 2353 frame_->EmitPop(ecx); | 2396 frame_->EmitPop(ecx); |
| 2354 frame_->EmitPop(eax); | 2397 frame_->EmitPop(eax); |
| 2355 | 2398 |
| 2356 // Generate code to jump to the right destination for all used | 2399 // Generate code to jump to the right destination for all used |
| 2357 // (formerly) shadowing targets. | 2400 // (formerly) shadowing targets. |
| 2358 for (int i = 0; i <= nof_escapes; i++) { | 2401 for (int i = 0; i <= nof_escapes; i++) { |
| 2359 if (shadows[i]->is_bound()) { | 2402 if (shadows[i]->is_bound()) { |
| 2360 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); | 2403 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2845 | 2888 |
| 2846 | 2889 |
| 2847 bool CodeGenerator::IsInlineSmi(Literal* literal) { | 2890 bool CodeGenerator::IsInlineSmi(Literal* literal) { |
| 2848 if (literal == NULL || !literal->handle()->IsSmi()) return false; | 2891 if (literal == NULL || !literal->handle()->IsSmi()) return false; |
| 2849 int int_value = Smi::cast(*literal->handle())->value(); | 2892 int int_value = Smi::cast(*literal->handle())->value(); |
| 2850 return is_intn(int_value, kMaxSmiInlinedBits); | 2893 return is_intn(int_value, kMaxSmiInlinedBits); |
| 2851 } | 2894 } |
| 2852 | 2895 |
| 2853 | 2896 |
| 2854 void CodeGenerator::VisitAssignment(Assignment* node) { | 2897 void CodeGenerator::VisitAssignment(Assignment* node) { |
| 2855 frame_->SpillAll(); | |
| 2856 Comment cmnt(masm_, "[ Assignment"); | 2898 Comment cmnt(masm_, "[ Assignment"); |
| 2857 | 2899 |
| 2858 RecordStatementPosition(node); | 2900 RecordStatementPosition(node); |
| 2859 { Reference target(this, node->target()); | 2901 { Reference target(this, node->target()); |
| 2860 if (target.is_illegal()) { | 2902 if (target.is_illegal()) { |
| 2861 // Fool the virtual frame into thinking that we left the assignment's | 2903 // Fool the virtual frame into thinking that we left the assignment's |
| 2862 // value on the frame. | 2904 // value on the frame. |
| 2863 frame_->EmitPush(Immediate(Smi::FromInt(0))); | 2905 frame_->EmitPush(Immediate(Smi::FromInt(0))); |
| 2864 return; | 2906 return; |
| 2865 } | 2907 } |
| 2866 | 2908 |
| 2867 if (node->op() == Token::ASSIGN || | 2909 if (node->op() == Token::ASSIGN || |
| 2868 node->op() == Token::INIT_VAR || | 2910 node->op() == Token::INIT_VAR || |
| 2869 node->op() == Token::INIT_CONST) { | 2911 node->op() == Token::INIT_CONST) { |
| 2870 Load(node->value()); | 2912 Load(node->value()); |
| 2871 | 2913 |
| 2872 } else { | 2914 } else { |
| 2915 frame_->SpillAll(); |
| 2873 target.GetValue(NOT_INSIDE_TYPEOF); | 2916 target.GetValue(NOT_INSIDE_TYPEOF); |
| 2874 Literal* literal = node->value()->AsLiteral(); | 2917 Literal* literal = node->value()->AsLiteral(); |
| 2875 if (IsInlineSmi(literal)) { | 2918 if (IsInlineSmi(literal)) { |
| 2876 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, | 2919 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, |
| 2877 NO_OVERWRITE); | 2920 NO_OVERWRITE); |
| 2878 } else { | 2921 } else { |
| 2879 Load(node->value()); | 2922 Load(node->value()); |
| 2880 frame_->SpillAll(); | 2923 frame_->SpillAll(); |
| 2881 GenericBinaryOperation(node->binary_op(), node->type()); | 2924 GenericBinaryOperation(node->binary_op(), node->type()); |
| 2882 } | 2925 } |
| (...skipping 2604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5487 | 5530 |
| 5488 // Slow-case: Go through the JavaScript implementation. | 5531 // Slow-case: Go through the JavaScript implementation. |
| 5489 __ bind(&slow); | 5532 __ bind(&slow); |
| 5490 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5533 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 5491 } | 5534 } |
| 5492 | 5535 |
| 5493 | 5536 |
| 5494 #undef __ | 5537 #undef __ |
| 5495 | 5538 |
| 5496 } } // namespace v8::internal | 5539 } } // namespace v8::internal |
| OLD | NEW |