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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 | 179 |
180 | 180 |
181 // Calling conventions: | 181 // Calling conventions: |
182 // ebp: frame pointer | 182 // ebp: frame pointer |
183 // esp: stack pointer | 183 // esp: stack pointer |
184 // edi: caller's parameter pointer | 184 // edi: caller's parameter pointer |
185 // esi: callee's context | 185 // esi: callee's context |
186 | 186 |
187 void CodeGenerator::GenCode(FunctionLiteral* fun) { | 187 void CodeGenerator::GenCode(FunctionLiteral* fun) { |
188 // Record the position for debugging purposes. | 188 // Record the position for debugging purposes. |
189 __ RecordPosition(fun->start_position()); | 189 CodeForSourcePosition(fun->start_position()); |
190 | 190 |
191 ZoneList<Statement*>* body = fun->body(); | 191 ZoneList<Statement*>* body = fun->body(); |
192 | 192 |
193 // Initialize state. | 193 // Initialize state. |
194 ASSERT(scope_ == NULL); | 194 ASSERT(scope_ == NULL); |
195 scope_ = fun->scope(); | 195 scope_ = fun->scope(); |
196 ASSERT(frame_ == NULL); | 196 ASSERT(frame_ == NULL); |
197 VirtualFrame virtual_frame(this); | 197 VirtualFrame virtual_frame(this); |
198 frame_ = &virtual_frame; | 198 frame_ = &virtual_frame; |
199 cc_reg_ = no_condition; | 199 cc_reg_ = no_condition; |
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1315 #endif | 1315 #endif |
1316 | 1316 |
1317 Major MajorKey() { return CallFunction; } | 1317 Major MajorKey() { return CallFunction; } |
1318 int MinorKey() { return argc_; } | 1318 int MinorKey() { return argc_; } |
1319 }; | 1319 }; |
1320 | 1320 |
1321 | 1321 |
1322 // Call the function just below TOS on the stack with the given | 1322 // Call the function just below TOS on the stack with the given |
1323 // arguments. The receiver is the TOS. | 1323 // arguments. The receiver is the TOS. |
1324 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 1324 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
1325 int position) { | 1325 int position) { |
1326 // Push the arguments ("left-to-right") on the stack. | 1326 // Push the arguments ("left-to-right") on the stack. |
1327 for (int i = 0; i < args->length(); i++) { | 1327 for (int i = 0; i < args->length(); i++) { |
1328 Load(args->at(i)); | 1328 Load(args->at(i)); |
1329 } | 1329 } |
1330 | 1330 |
1331 // Record the position for debugging purposes. | 1331 // Record the position for debugging purposes. |
1332 __ RecordPosition(position); | 1332 CodeForSourcePosition(position); |
1333 | 1333 |
1334 // Use the shared code stub to call the function. | 1334 // Use the shared code stub to call the function. |
1335 CallFunctionStub call_function(args->length()); | 1335 CallFunctionStub call_function(args->length()); |
1336 __ CallStub(&call_function); | 1336 __ CallStub(&call_function); |
1337 | 1337 |
1338 // Restore context and pop function from the stack. | 1338 // Restore context and pop function from the stack. |
1339 __ mov(esi, frame_->Context()); | 1339 __ mov(esi, frame_->Context()); |
1340 __ mov(frame_->Top(), eax); | 1340 __ mov(frame_->Top(), eax); |
1341 } | 1341 } |
1342 | 1342 |
(...skipping 15 matching lines...) Expand all Loading... |
1358 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); | 1358 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); |
1359 __ j(above_equal, &stack_is_ok, taken); | 1359 __ j(above_equal, &stack_is_ok, taken); |
1360 __ CallStub(&stub); | 1360 __ CallStub(&stub); |
1361 __ bind(&stack_is_ok); | 1361 __ bind(&stack_is_ok); |
1362 } | 1362 } |
1363 } | 1363 } |
1364 | 1364 |
1365 | 1365 |
1366 void CodeGenerator::VisitBlock(Block* node) { | 1366 void CodeGenerator::VisitBlock(Block* node) { |
1367 Comment cmnt(masm_, "[ Block"); | 1367 Comment cmnt(masm_, "[ Block"); |
1368 RecordStatementPosition(node); | 1368 CodeForStatement(node); |
1369 node->set_break_stack_height(break_stack_height_); | 1369 node->set_break_stack_height(break_stack_height_); |
1370 VisitStatements(node->statements()); | 1370 VisitStatements(node->statements()); |
1371 __ bind(node->break_target()); | 1371 __ bind(node->break_target()); |
1372 } | 1372 } |
1373 | 1373 |
1374 | 1374 |
1375 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1375 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
1376 frame_->Push(Immediate(pairs)); | 1376 frame_->Push(Immediate(pairs)); |
1377 frame_->Push(esi); | 1377 frame_->Push(esi); |
1378 frame_->Push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); | 1378 frame_->Push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); |
1379 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 1379 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
1380 // Return value is ignored. | 1380 // Return value is ignored. |
1381 } | 1381 } |
1382 | 1382 |
1383 | 1383 |
1384 void CodeGenerator::VisitDeclaration(Declaration* node) { | 1384 void CodeGenerator::VisitDeclaration(Declaration* node) { |
1385 Comment cmnt(masm_, "[ Declaration"); | 1385 Comment cmnt(masm_, "[ Declaration"); |
| 1386 CodeForStatement(node); |
1386 Variable* var = node->proxy()->var(); | 1387 Variable* var = node->proxy()->var(); |
1387 ASSERT(var != NULL); // must have been resolved | 1388 ASSERT(var != NULL); // must have been resolved |
1388 Slot* slot = var->slot(); | 1389 Slot* slot = var->slot(); |
1389 | 1390 |
1390 // If it was not possible to allocate the variable at compile time, | 1391 // If it was not possible to allocate the variable at compile time, |
1391 // we need to "declare" it at runtime to make sure it actually | 1392 // we need to "declare" it at runtime to make sure it actually |
1392 // exists in the local context. | 1393 // exists in the local context. |
1393 if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1394 if (slot != NULL && slot->type() == Slot::LOOKUP) { |
1394 // Variables with a "LOOKUP" slot were introduced as non-locals | 1395 // Variables with a "LOOKUP" slot were introduced as non-locals |
1395 // during variable resolution and must have mode DYNAMIC. | 1396 // during variable resolution and must have mode DYNAMIC. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 // safe to pop the value lying on top of the reference before unloading | 1438 // safe to pop the value lying on top of the reference before unloading |
1438 // the reference itself (which preserves the top of stack) because we | 1439 // the reference itself (which preserves the top of stack) because we |
1439 // know that it is a zero-sized reference. | 1440 // know that it is a zero-sized reference. |
1440 frame_->Pop(); | 1441 frame_->Pop(); |
1441 } | 1442 } |
1442 } | 1443 } |
1443 | 1444 |
1444 | 1445 |
1445 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1446 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
1446 Comment cmnt(masm_, "[ ExpressionStatement"); | 1447 Comment cmnt(masm_, "[ ExpressionStatement"); |
1447 RecordStatementPosition(node); | 1448 CodeForStatement(node); |
1448 Expression* expression = node->expression(); | 1449 Expression* expression = node->expression(); |
1449 expression->MarkAsStatement(); | 1450 expression->MarkAsStatement(); |
1450 Load(expression); | 1451 Load(expression); |
1451 // Remove the lingering expression result from the top of stack. | 1452 // Remove the lingering expression result from the top of stack. |
1452 frame_->Pop(); | 1453 frame_->Pop(); |
1453 } | 1454 } |
1454 | 1455 |
1455 | 1456 |
1456 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1457 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
1457 Comment cmnt(masm_, "// EmptyStatement"); | 1458 Comment cmnt(masm_, "// EmptyStatement"); |
| 1459 CodeForStatement(node); |
1458 // nothing to do | 1460 // nothing to do |
1459 } | 1461 } |
1460 | 1462 |
1461 | 1463 |
1462 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 1464 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
1463 Comment cmnt(masm_, "[ IfStatement"); | 1465 Comment cmnt(masm_, "[ IfStatement"); |
1464 // Generate different code depending on which | 1466 // Generate different code depending on which |
1465 // parts of the if statement are present or not. | 1467 // parts of the if statement are present or not. |
1466 bool has_then_stm = node->HasThenStatement(); | 1468 bool has_then_stm = node->HasThenStatement(); |
1467 bool has_else_stm = node->HasElseStatement(); | 1469 bool has_else_stm = node->HasElseStatement(); |
1468 | 1470 |
1469 RecordStatementPosition(node); | 1471 CodeForStatement(node); |
1470 Label exit; | 1472 Label exit; |
1471 if (has_then_stm && has_else_stm) { | 1473 if (has_then_stm && has_else_stm) { |
1472 Label then; | 1474 Label then; |
1473 Label else_; | 1475 Label else_; |
1474 // if (cond) | 1476 // if (cond) |
1475 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); | 1477 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); |
1476 Branch(false, &else_); | 1478 Branch(false, &else_); |
1477 // then | 1479 // then |
1478 __ bind(&then); | 1480 __ bind(&then); |
1479 Visit(node->then_statement()); | 1481 Visit(node->then_statement()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 | 1523 |
1522 | 1524 |
1523 void CodeGenerator::CleanStack(int num_bytes) { | 1525 void CodeGenerator::CleanStack(int num_bytes) { |
1524 ASSERT(num_bytes % kPointerSize == 0); | 1526 ASSERT(num_bytes % kPointerSize == 0); |
1525 frame_->Drop(num_bytes / kPointerSize); | 1527 frame_->Drop(num_bytes / kPointerSize); |
1526 } | 1528 } |
1527 | 1529 |
1528 | 1530 |
1529 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 1531 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { |
1530 Comment cmnt(masm_, "[ ContinueStatement"); | 1532 Comment cmnt(masm_, "[ ContinueStatement"); |
1531 RecordStatementPosition(node); | 1533 CodeForStatement(node); |
1532 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1534 CleanStack(break_stack_height_ - node->target()->break_stack_height()); |
1533 __ jmp(node->target()->continue_target()); | 1535 __ jmp(node->target()->continue_target()); |
1534 } | 1536 } |
1535 | 1537 |
1536 | 1538 |
1537 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 1539 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
1538 Comment cmnt(masm_, "[ BreakStatement"); | 1540 Comment cmnt(masm_, "[ BreakStatement"); |
1539 RecordStatementPosition(node); | 1541 CodeForStatement(node); |
1540 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1542 CleanStack(break_stack_height_ - node->target()->break_stack_height()); |
1541 __ jmp(node->target()->break_target()); | 1543 __ jmp(node->target()->break_target()); |
1542 } | 1544 } |
1543 | 1545 |
1544 | 1546 |
1545 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 1547 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
1546 Comment cmnt(masm_, "[ ReturnStatement"); | 1548 Comment cmnt(masm_, "[ ReturnStatement"); |
1547 RecordStatementPosition(node); | 1549 CodeForStatement(node); |
1548 Load(node->expression()); | 1550 Load(node->expression()); |
1549 | 1551 |
1550 // Move the function result into eax | 1552 // Move the function result into eax |
1551 frame_->Pop(eax); | 1553 frame_->Pop(eax); |
1552 | 1554 |
1553 // If we're inside a try statement or the return instruction | 1555 // If we're inside a try statement or the return instruction |
1554 // sequence has been generated, we just jump to that | 1556 // sequence has been generated, we just jump to that |
1555 // point. Otherwise, we generate the return instruction sequence and | 1557 // point. Otherwise, we generate the return instruction sequence and |
1556 // bind the function return label. | 1558 // bind the function return label. |
1557 if (is_inside_try_ || function_return_.is_bound()) { | 1559 if (is_inside_try_ || function_return_.is_bound()) { |
(...skipping 17 matching lines...) Expand all Loading... |
1575 // Check that the size of the code used for returning matches what is | 1577 // Check that the size of the code used for returning matches what is |
1576 // expected by the debugger. | 1578 // expected by the debugger. |
1577 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, | 1579 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, |
1578 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); | 1580 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); |
1579 } | 1581 } |
1580 } | 1582 } |
1581 | 1583 |
1582 | 1584 |
1583 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1585 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
1584 Comment cmnt(masm_, "[ WithEnterStatement"); | 1586 Comment cmnt(masm_, "[ WithEnterStatement"); |
1585 RecordStatementPosition(node); | 1587 CodeForStatement(node); |
1586 Load(node->expression()); | 1588 Load(node->expression()); |
1587 __ CallRuntime(Runtime::kPushContext, 1); | 1589 __ CallRuntime(Runtime::kPushContext, 1); |
1588 | 1590 |
1589 if (kDebug) { | 1591 if (kDebug) { |
1590 Label verified_true; | 1592 Label verified_true; |
1591 // Verify eax and esi are the same in debug mode | 1593 // Verify eax and esi are the same in debug mode |
1592 __ cmp(eax, Operand(esi)); | 1594 __ cmp(eax, Operand(esi)); |
1593 __ j(equal, &verified_true); | 1595 __ j(equal, &verified_true); |
1594 __ int3(); | 1596 __ int3(); |
1595 __ bind(&verified_true); | 1597 __ bind(&verified_true); |
1596 } | 1598 } |
1597 | 1599 |
1598 // Update context local. | 1600 // Update context local. |
1599 __ mov(frame_->Context(), esi); | 1601 __ mov(frame_->Context(), esi); |
1600 } | 1602 } |
1601 | 1603 |
1602 | 1604 |
1603 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 1605 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
1604 Comment cmnt(masm_, "[ WithExitStatement"); | 1606 Comment cmnt(masm_, "[ WithExitStatement"); |
| 1607 CodeForStatement(node); |
1605 // Pop context. | 1608 // Pop context. |
1606 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); | 1609 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); |
1607 // Update context local. | 1610 // Update context local. |
1608 __ mov(frame_->Context(), esi); | 1611 __ mov(frame_->Context(), esi); |
1609 } | 1612 } |
1610 | 1613 |
1611 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 1614 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { |
1612 return kFastSwitchMaxOverheadFactor; | 1615 return kFastSwitchMaxOverheadFactor; |
1613 } | 1616 } |
1614 | 1617 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 | 1680 |
1678 for (int i = 0, entry_pos = table_start.pos(); | 1681 for (int i = 0, entry_pos = table_start.pos(); |
1679 i < range; i++, entry_pos += sizeof(uint32_t)) { | 1682 i < range; i++, entry_pos += sizeof(uint32_t)) { |
1680 __ WriteInternalReference(entry_pos, *case_targets[i]); | 1683 __ WriteInternalReference(entry_pos, *case_targets[i]); |
1681 } | 1684 } |
1682 } | 1685 } |
1683 | 1686 |
1684 | 1687 |
1685 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 1688 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
1686 Comment cmnt(masm_, "[ SwitchStatement"); | 1689 Comment cmnt(masm_, "[ SwitchStatement"); |
1687 RecordStatementPosition(node); | 1690 CodeForStatement(node); |
1688 node->set_break_stack_height(break_stack_height_); | 1691 node->set_break_stack_height(break_stack_height_); |
1689 | 1692 |
1690 Load(node->tag()); | 1693 Load(node->tag()); |
1691 | 1694 |
1692 if (TryGenerateFastCaseSwitchStatement(node)) { | 1695 if (TryGenerateFastCaseSwitchStatement(node)) { |
1693 return; | 1696 return; |
1694 } | 1697 } |
1695 | 1698 |
1696 Label next, fall_through, default_case; | 1699 Label next, fall_through, default_case; |
1697 ZoneList<CaseClause*>* cases = node->cases(); | 1700 ZoneList<CaseClause*>* cases = node->cases(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1744 frame_->Pop(); | 1747 frame_->Pop(); |
1745 } | 1748 } |
1746 | 1749 |
1747 __ bind(&fall_through); | 1750 __ bind(&fall_through); |
1748 __ bind(node->break_target()); | 1751 __ bind(node->break_target()); |
1749 } | 1752 } |
1750 | 1753 |
1751 | 1754 |
1752 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1755 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { |
1753 Comment cmnt(masm_, "[ LoopStatement"); | 1756 Comment cmnt(masm_, "[ LoopStatement"); |
1754 RecordStatementPosition(node); | 1757 CodeForStatement(node); |
1755 node->set_break_stack_height(break_stack_height_); | 1758 node->set_break_stack_height(break_stack_height_); |
1756 | 1759 |
1757 // simple condition analysis | 1760 // simple condition analysis |
1758 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1761 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; |
1759 if (node->cond() == NULL) { | 1762 if (node->cond() == NULL) { |
1760 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1763 ASSERT(node->type() == LoopStatement::FOR_LOOP); |
1761 info = ALWAYS_TRUE; | 1764 info = ALWAYS_TRUE; |
1762 } else { | 1765 } else { |
1763 Literal* lit = node->cond()->AsLiteral(); | 1766 Literal* lit = node->cond()->AsLiteral(); |
1764 if (lit != NULL) { | 1767 if (lit != NULL) { |
(...skipping 22 matching lines...) Expand all Loading... |
1787 __ bind(&loop); | 1790 __ bind(&loop); |
1788 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1791 CheckStack(); // TODO(1222600): ignore if body contains calls. |
1789 Visit(node->body()); | 1792 Visit(node->body()); |
1790 | 1793 |
1791 // next | 1794 // next |
1792 __ bind(node->continue_target()); | 1795 __ bind(node->continue_target()); |
1793 if (node->next() != NULL) { | 1796 if (node->next() != NULL) { |
1794 // Record source position of the statement as this code which is after the | 1797 // Record source position of the statement as this code which is after the |
1795 // code for the body actually belongs to the loop statement and not the | 1798 // code for the body actually belongs to the loop statement and not the |
1796 // body. | 1799 // body. |
1797 RecordStatementPosition(node); | 1800 CodeForStatement(node); |
1798 __ RecordPosition(node->statement_pos()); | |
1799 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1801 ASSERT(node->type() == LoopStatement::FOR_LOOP); |
1800 Visit(node->next()); | 1802 Visit(node->next()); |
1801 } | 1803 } |
1802 | 1804 |
1803 // cond | 1805 // cond |
1804 __ bind(&entry); | 1806 __ bind(&entry); |
1805 switch (info) { | 1807 switch (info) { |
1806 case ALWAYS_TRUE: | 1808 case ALWAYS_TRUE: |
1807 __ jmp(&loop); | 1809 __ jmp(&loop); |
1808 break; | 1810 break; |
1809 case ALWAYS_FALSE: | 1811 case ALWAYS_FALSE: |
1810 break; | 1812 break; |
1811 case DONT_KNOW: | 1813 case DONT_KNOW: |
1812 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop, | 1814 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop, |
1813 node->break_target(), true); | 1815 node->break_target(), true); |
1814 Branch(true, &loop); | 1816 Branch(true, &loop); |
1815 break; | 1817 break; |
1816 } | 1818 } |
1817 | 1819 |
1818 DecrementLoopNesting(); | 1820 DecrementLoopNesting(); |
1819 | 1821 |
1820 // exit | 1822 // exit |
1821 __ bind(node->break_target()); | 1823 __ bind(node->break_target()); |
1822 } | 1824 } |
1823 | 1825 |
1824 | 1826 |
1825 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 1827 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
1826 Comment cmnt(masm_, "[ ForInStatement"); | 1828 Comment cmnt(masm_, "[ ForInStatement"); |
1827 RecordStatementPosition(node); | 1829 CodeForStatement(node); |
1828 | 1830 |
1829 // We keep stuff on the stack while the body is executing. | 1831 // We keep stuff on the stack while the body is executing. |
1830 // Record it, so that a break/continue crossing this statement | 1832 // Record it, so that a break/continue crossing this statement |
1831 // can restore the stack. | 1833 // can restore the stack. |
1832 const int kForInStackSize = 5 * kPointerSize; | 1834 const int kForInStackSize = 5 * kPointerSize; |
1833 break_stack_height_ += kForInStackSize; | 1835 break_stack_height_ += kForInStackSize; |
1834 node->set_break_stack_height(break_stack_height_); | 1836 node->set_break_stack_height(break_stack_height_); |
1835 | 1837 |
1836 Label loop, next, entry, cleanup, exit, primitive, jsobject; | 1838 Label loop, next, entry, cleanup, exit, primitive, jsobject; |
1837 Label end_del_check, fixed_array; | 1839 Label end_del_check, fixed_array; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2005 | 2007 |
2006 // Exit. | 2008 // Exit. |
2007 __ bind(&exit); | 2009 __ bind(&exit); |
2008 | 2010 |
2009 break_stack_height_ -= kForInStackSize; | 2011 break_stack_height_ -= kForInStackSize; |
2010 } | 2012 } |
2011 | 2013 |
2012 | 2014 |
2013 void CodeGenerator::VisitTryCatch(TryCatch* node) { | 2015 void CodeGenerator::VisitTryCatch(TryCatch* node) { |
2014 Comment cmnt(masm_, "[ TryCatch"); | 2016 Comment cmnt(masm_, "[ TryCatch"); |
| 2017 CodeForStatement(node); |
2015 | 2018 |
2016 Label try_block, exit; | 2019 Label try_block, exit; |
2017 | 2020 |
2018 __ call(&try_block); | 2021 __ call(&try_block); |
2019 // --- Catch block --- | 2022 // --- Catch block --- |
2020 frame_->Push(eax); | 2023 frame_->Push(eax); |
2021 | 2024 |
2022 // Store the caught exception in the catch variable. | 2025 // Store the caught exception in the catch variable. |
2023 { Reference ref(this, node->catch_var()); | 2026 { Reference ref(this, node->catch_var()); |
2024 ASSERT(ref.is_slot()); | 2027 ASSERT(ref.is_slot()); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2110 __ jmp(shadows[i]->original_label()); | 2113 __ jmp(shadows[i]->original_label()); |
2111 } | 2114 } |
2112 } | 2115 } |
2113 | 2116 |
2114 __ bind(&exit); | 2117 __ bind(&exit); |
2115 } | 2118 } |
2116 | 2119 |
2117 | 2120 |
2118 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 2121 void CodeGenerator::VisitTryFinally(TryFinally* node) { |
2119 Comment cmnt(masm_, "[ TryFinally"); | 2122 Comment cmnt(masm_, "[ TryFinally"); |
| 2123 CodeForStatement(node); |
2120 | 2124 |
2121 // State: Used to keep track of reason for entering the finally | 2125 // State: Used to keep track of reason for entering the finally |
2122 // block. Should probably be extended to hold information for | 2126 // block. Should probably be extended to hold information for |
2123 // break/continue from within the try block. | 2127 // break/continue from within the try block. |
2124 enum { FALLING, THROWING, JUMPING }; | 2128 enum { FALLING, THROWING, JUMPING }; |
2125 | 2129 |
2126 Label exit, unlink, try_block, finally_block; | 2130 Label exit, unlink, try_block, finally_block; |
2127 | 2131 |
2128 __ call(&try_block); | 2132 __ call(&try_block); |
2129 | 2133 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2247 frame_->Push(eax); // undo pop from above | 2251 frame_->Push(eax); // undo pop from above |
2248 __ CallRuntime(Runtime::kReThrow, 1); | 2252 __ CallRuntime(Runtime::kReThrow, 1); |
2249 | 2253 |
2250 // Done. | 2254 // Done. |
2251 __ bind(&exit); | 2255 __ bind(&exit); |
2252 } | 2256 } |
2253 | 2257 |
2254 | 2258 |
2255 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 2259 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
2256 Comment cmnt(masm_, "[ DebuggerStatement"); | 2260 Comment cmnt(masm_, "[ DebuggerStatement"); |
2257 RecordStatementPosition(node); | 2261 CodeForStatement(node); |
2258 __ CallRuntime(Runtime::kDebugBreak, 0); | 2262 __ CallRuntime(Runtime::kDebugBreak, 0); |
2259 // Ignore the return value. | 2263 // Ignore the return value. |
2260 } | 2264 } |
2261 | 2265 |
2262 | 2266 |
2263 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 2267 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { |
2264 ASSERT(boilerplate->IsBoilerplate()); | 2268 ASSERT(boilerplate->IsBoilerplate()); |
2265 | 2269 |
2266 // Push the boilerplate on the stack. | 2270 // Push the boilerplate on the stack. |
2267 frame_->Push(Immediate(boilerplate)); | 2271 frame_->Push(Immediate(boilerplate)); |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2603 | 2607 |
2604 bool CodeGenerator::IsInlineSmi(Literal* literal) { | 2608 bool CodeGenerator::IsInlineSmi(Literal* literal) { |
2605 if (literal == NULL || !literal->handle()->IsSmi()) return false; | 2609 if (literal == NULL || !literal->handle()->IsSmi()) return false; |
2606 int int_value = Smi::cast(*literal->handle())->value(); | 2610 int int_value = Smi::cast(*literal->handle())->value(); |
2607 return is_intn(int_value, kMaxSmiInlinedBits); | 2611 return is_intn(int_value, kMaxSmiInlinedBits); |
2608 } | 2612 } |
2609 | 2613 |
2610 | 2614 |
2611 void CodeGenerator::VisitAssignment(Assignment* node) { | 2615 void CodeGenerator::VisitAssignment(Assignment* node) { |
2612 Comment cmnt(masm_, "[ Assignment"); | 2616 Comment cmnt(masm_, "[ Assignment"); |
| 2617 CodeForStatement(node); |
2613 | 2618 |
2614 RecordStatementPosition(node); | |
2615 Reference target(this, node->target()); | 2619 Reference target(this, node->target()); |
2616 if (target.is_illegal()) return; | 2620 if (target.is_illegal()) return; |
2617 | 2621 |
2618 if (node->op() == Token::ASSIGN || | 2622 if (node->op() == Token::ASSIGN || |
2619 node->op() == Token::INIT_VAR || | 2623 node->op() == Token::INIT_VAR || |
2620 node->op() == Token::INIT_CONST) { | 2624 node->op() == Token::INIT_CONST) { |
2621 Load(node->value()); | 2625 Load(node->value()); |
2622 | 2626 |
2623 } else { | 2627 } else { |
2624 target.GetValue(NOT_INSIDE_TYPEOF); | 2628 target.GetValue(NOT_INSIDE_TYPEOF); |
2625 Literal* literal = node->value()->AsLiteral(); | 2629 Literal* literal = node->value()->AsLiteral(); |
2626 if (IsInlineSmi(literal)) { | 2630 if (IsInlineSmi(literal)) { |
2627 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, | 2631 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, |
2628 NO_OVERWRITE); | 2632 NO_OVERWRITE); |
2629 } else { | 2633 } else { |
2630 Load(node->value()); | 2634 Load(node->value()); |
2631 GenericBinaryOperation(node->binary_op(), node->type()); | 2635 GenericBinaryOperation(node->binary_op(), node->type()); |
2632 } | 2636 } |
2633 } | 2637 } |
2634 | 2638 |
2635 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | 2639 Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
2636 if (var != NULL && | 2640 if (var != NULL && |
2637 var->mode() == Variable::CONST && | 2641 var->mode() == Variable::CONST && |
2638 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { | 2642 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { |
2639 // Assignment ignored - leave the value on the stack. | 2643 // Assignment ignored - leave the value on the stack. |
2640 } else { | 2644 } else { |
2641 __ RecordPosition(node->position()); | 2645 CodeForSourcePosition(node->position()); |
2642 if (node->op() == Token::INIT_CONST) { | 2646 if (node->op() == Token::INIT_CONST) { |
2643 // Dynamic constant initializations must use the function context | 2647 // Dynamic constant initializations must use the function context |
2644 // and initialize the actual constant declared. Dynamic variable | 2648 // and initialize the actual constant declared. Dynamic variable |
2645 // initializations are simply assignments and use SetValue. | 2649 // initializations are simply assignments and use SetValue. |
2646 target.SetValue(CONST_INIT); | 2650 target.SetValue(CONST_INIT); |
2647 } else { | 2651 } else { |
2648 target.SetValue(NOT_CONST_INIT); | 2652 target.SetValue(NOT_CONST_INIT); |
2649 } | 2653 } |
2650 } | 2654 } |
2651 } | 2655 } |
2652 | 2656 |
2653 | 2657 |
2654 void CodeGenerator::VisitThrow(Throw* node) { | 2658 void CodeGenerator::VisitThrow(Throw* node) { |
2655 Comment cmnt(masm_, "[ Throw"); | 2659 Comment cmnt(masm_, "[ Throw"); |
| 2660 CodeForStatement(node); |
2656 | 2661 |
2657 Load(node->exception()); | 2662 Load(node->exception()); |
2658 __ RecordPosition(node->position()); | |
2659 __ CallRuntime(Runtime::kThrow, 1); | 2663 __ CallRuntime(Runtime::kThrow, 1); |
2660 frame_->Push(eax); | 2664 frame_->Push(eax); |
2661 } | 2665 } |
2662 | 2666 |
2663 | 2667 |
2664 void CodeGenerator::VisitProperty(Property* node) { | 2668 void CodeGenerator::VisitProperty(Property* node) { |
2665 Comment cmnt(masm_, "[ Property"); | 2669 Comment cmnt(masm_, "[ Property"); |
2666 | 2670 |
2667 Reference property(this, node); | 2671 Reference property(this, node); |
2668 property.GetValue(typeof_state()); | 2672 property.GetValue(typeof_state()); |
2669 } | 2673 } |
2670 | 2674 |
2671 | 2675 |
2672 void CodeGenerator::VisitCall(Call* node) { | 2676 void CodeGenerator::VisitCall(Call* node) { |
2673 Comment cmnt(masm_, "[ Call"); | 2677 Comment cmnt(masm_, "[ Call"); |
2674 | 2678 |
2675 ZoneList<Expression*>* args = node->arguments(); | 2679 ZoneList<Expression*>* args = node->arguments(); |
2676 | 2680 |
2677 RecordStatementPosition(node); | 2681 CodeForStatement(node); |
2678 | 2682 |
2679 // Check if the function is a variable or a property. | 2683 // Check if the function is a variable or a property. |
2680 Expression* function = node->expression(); | 2684 Expression* function = node->expression(); |
2681 Variable* var = function->AsVariableProxy()->AsVariable(); | 2685 Variable* var = function->AsVariableProxy()->AsVariable(); |
2682 Property* property = function->AsProperty(); | 2686 Property* property = function->AsProperty(); |
2683 | 2687 |
2684 // ------------------------------------------------------------------------ | 2688 // ------------------------------------------------------------------------ |
2685 // Fast-case: Use inline caching. | 2689 // Fast-case: Use inline caching. |
2686 // --- | 2690 // --- |
2687 // According to ECMA-262, section 11.2.3, page 44, the function to call | 2691 // According to ECMA-262, section 11.2.3, page 44, the function to call |
(...skipping 16 matching lines...) Expand all Loading... |
2704 LoadGlobal(); | 2708 LoadGlobal(); |
2705 // Load the arguments. | 2709 // Load the arguments. |
2706 for (int i = 0; i < args->length(); i++) { | 2710 for (int i = 0; i < args->length(); i++) { |
2707 Load(args->at(i)); | 2711 Load(args->at(i)); |
2708 } | 2712 } |
2709 | 2713 |
2710 // Setup the receiver register and call the IC initialization code. | 2714 // Setup the receiver register and call the IC initialization code. |
2711 Handle<Code> stub = (loop_nesting() > 0) | 2715 Handle<Code> stub = (loop_nesting() > 0) |
2712 ? ComputeCallInitializeInLoop(args->length()) | 2716 ? ComputeCallInitializeInLoop(args->length()) |
2713 : ComputeCallInitialize(args->length()); | 2717 : ComputeCallInitialize(args->length()); |
2714 __ RecordPosition(node->position()); | 2718 CodeForSourcePosition(node->position()); |
2715 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT); | 2719 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT); |
2716 __ mov(esi, frame_->Context()); | 2720 __ mov(esi, frame_->Context()); |
2717 | 2721 |
2718 // Overwrite the function on the stack with the result. | 2722 // Overwrite the function on the stack with the result. |
2719 __ mov(frame_->Top(), eax); | 2723 __ mov(frame_->Top(), eax); |
2720 | 2724 |
2721 } else if (var != NULL && var->slot() != NULL && | 2725 } else if (var != NULL && var->slot() != NULL && |
2722 var->slot()->type() == Slot::LOOKUP) { | 2726 var->slot()->type() == Slot::LOOKUP) { |
2723 // ---------------------------------- | 2727 // ---------------------------------- |
2724 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 2728 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj |
(...skipping 25 matching lines...) Expand all Loading... |
2750 frame_->Push(Immediate(literal->handle())); | 2754 frame_->Push(Immediate(literal->handle())); |
2751 Load(property->obj()); | 2755 Load(property->obj()); |
2752 | 2756 |
2753 // Load the arguments. | 2757 // Load the arguments. |
2754 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2758 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2755 | 2759 |
2756 // Call the IC initialization code. | 2760 // Call the IC initialization code. |
2757 Handle<Code> stub = (loop_nesting() > 0) | 2761 Handle<Code> stub = (loop_nesting() > 0) |
2758 ? ComputeCallInitializeInLoop(args->length()) | 2762 ? ComputeCallInitializeInLoop(args->length()) |
2759 : ComputeCallInitialize(args->length()); | 2763 : ComputeCallInitialize(args->length()); |
2760 __ RecordPosition(node->position()); | 2764 CodeForSourcePosition(node->position()); |
2761 __ call(stub, RelocInfo::CODE_TARGET); | 2765 __ call(stub, RelocInfo::CODE_TARGET); |
2762 __ mov(esi, frame_->Context()); | 2766 __ mov(esi, frame_->Context()); |
2763 | 2767 |
2764 // Overwrite the function on the stack with the result. | 2768 // Overwrite the function on the stack with the result. |
2765 __ mov(frame_->Top(), eax); | 2769 __ mov(frame_->Top(), eax); |
2766 | 2770 |
2767 } else { | 2771 } else { |
2768 // ------------------------------------------- | 2772 // ------------------------------------------- |
2769 // JavaScript example: 'array[index](1, 2, 3)' | 2773 // JavaScript example: 'array[index](1, 2, 3)' |
2770 // ------------------------------------------- | 2774 // ------------------------------------------- |
(...skipping 22 matching lines...) Expand all Loading... |
2793 LoadGlobalReceiver(eax); | 2797 LoadGlobalReceiver(eax); |
2794 | 2798 |
2795 // Call the function. | 2799 // Call the function. |
2796 CallWithArguments(args, node->position()); | 2800 CallWithArguments(args, node->position()); |
2797 } | 2801 } |
2798 } | 2802 } |
2799 | 2803 |
2800 | 2804 |
2801 void CodeGenerator::VisitCallNew(CallNew* node) { | 2805 void CodeGenerator::VisitCallNew(CallNew* node) { |
2802 Comment cmnt(masm_, "[ CallNew"); | 2806 Comment cmnt(masm_, "[ CallNew"); |
| 2807 CodeForStatement(node); |
2803 | 2808 |
2804 // According to ECMA-262, section 11.2.2, page 44, the function | 2809 // According to ECMA-262, section 11.2.2, page 44, the function |
2805 // expression in new calls must be evaluated before the | 2810 // expression in new calls must be evaluated before the |
2806 // arguments. This is different from ordinary calls, where the | 2811 // arguments. This is different from ordinary calls, where the |
2807 // actual function to call is resolved after the arguments have been | 2812 // actual function to call is resolved after the arguments have been |
2808 // evaluated. | 2813 // evaluated. |
2809 | 2814 |
2810 // Compute function to call and use the global object as the | 2815 // Compute function to call and use the global object as the |
2811 // receiver. There is no need to use the global proxy here because | 2816 // receiver. There is no need to use the global proxy here because |
2812 // it will always be replaced with a newly allocated object. | 2817 // it will always be replaced with a newly allocated object. |
2813 Load(node->expression()); | 2818 Load(node->expression()); |
2814 LoadGlobal(); | 2819 LoadGlobal(); |
2815 | 2820 |
2816 // Push the arguments ("left-to-right") on the stack. | 2821 // Push the arguments ("left-to-right") on the stack. |
2817 ZoneList<Expression*>* args = node->arguments(); | 2822 ZoneList<Expression*>* args = node->arguments(); |
2818 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2823 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2819 | 2824 |
2820 // Constructors are called with the number of arguments in register | 2825 // Constructors are called with the number of arguments in register |
2821 // eax for now. Another option would be to have separate construct | 2826 // eax for now. Another option would be to have separate construct |
2822 // call trampolines per different arguments counts encountered. | 2827 // call trampolines per different arguments counts encountered. |
2823 __ Set(eax, Immediate(args->length())); | 2828 __ Set(eax, Immediate(args->length())); |
2824 | 2829 |
2825 // Load the function into temporary function slot as per calling | 2830 // Load the function into temporary function slot as per calling |
2826 // convention. | 2831 // convention. |
2827 __ mov(edi, frame_->Element(args->length() + 1)); | 2832 __ mov(edi, frame_->Element(args->length() + 1)); |
2828 | 2833 |
2829 // Call the construct call builtin that handles allocation and | 2834 // Call the construct call builtin that handles allocation and |
2830 // constructor invocation. | 2835 // constructor invocation. |
2831 __ RecordPosition(node->position()); | 2836 CodeForSourcePosition(node->position()); |
2832 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 2837 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), |
2833 RelocInfo::CONSTRUCT_CALL); | 2838 RelocInfo::CONSTRUCT_CALL); |
2834 // Discard the function and "push" the newly created object. | 2839 // Discard the function and "push" the newly created object. |
2835 __ mov(frame_->Top(), eax); | 2840 __ mov(frame_->Top(), eax); |
2836 } | 2841 } |
2837 | 2842 |
2838 | 2843 |
2839 void CodeGenerator::VisitCallEval(CallEval* node) { | 2844 void CodeGenerator::VisitCallEval(CallEval* node) { |
2840 Comment cmnt(masm_, "[ CallEval"); | 2845 Comment cmnt(masm_, "[ CallEval"); |
2841 | 2846 |
2842 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve | 2847 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve |
2843 // the function we need to call and the receiver of the call. | 2848 // the function we need to call and the receiver of the call. |
2844 // Then we call the resolved function using the given arguments. | 2849 // Then we call the resolved function using the given arguments. |
2845 | 2850 |
2846 ZoneList<Expression*>* args = node->arguments(); | 2851 ZoneList<Expression*>* args = node->arguments(); |
2847 Expression* function = node->expression(); | 2852 Expression* function = node->expression(); |
2848 | 2853 |
2849 RecordStatementPosition(node); | 2854 CodeForStatement(node); |
2850 | 2855 |
2851 // Prepare stack for call to resolved function. | 2856 // Prepare stack for call to resolved function. |
2852 Load(function); | 2857 Load(function); |
2853 __ push(Immediate(Factory::undefined_value())); // Slot for receiver | 2858 __ push(Immediate(Factory::undefined_value())); // Slot for receiver |
2854 for (int i = 0; i < args->length(); i++) { | 2859 for (int i = 0; i < args->length(); i++) { |
2855 Load(args->at(i)); | 2860 Load(args->at(i)); |
2856 } | 2861 } |
2857 | 2862 |
2858 // Prepare stack for call to ResolvePossiblyDirectEval. | 2863 // Prepare stack for call to ResolvePossiblyDirectEval. |
2859 __ push(Operand(esp, args->length() * kPointerSize + kPointerSize)); | 2864 __ push(Operand(esp, args->length() * kPointerSize + kPointerSize)); |
2860 if (args->length() > 0) { | 2865 if (args->length() > 0) { |
2861 __ push(Operand(esp, args->length() * kPointerSize)); | 2866 __ push(Operand(esp, args->length() * kPointerSize)); |
2862 } else { | 2867 } else { |
2863 __ push(Immediate(Factory::undefined_value())); | 2868 __ push(Immediate(Factory::undefined_value())); |
2864 } | 2869 } |
2865 | 2870 |
2866 // Resolve the call. | 2871 // Resolve the call. |
2867 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); | 2872 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); |
2868 | 2873 |
2869 // Touch up stack with the right values for the function and the receiver. | 2874 // Touch up stack with the right values for the function and the receiver. |
2870 __ mov(edx, FieldOperand(eax, FixedArray::kHeaderSize)); | 2875 __ mov(edx, FieldOperand(eax, FixedArray::kHeaderSize)); |
2871 __ mov(Operand(esp, (args->length() + 1) * kPointerSize), edx); | 2876 __ mov(Operand(esp, (args->length() + 1) * kPointerSize), edx); |
2872 __ mov(edx, FieldOperand(eax, FixedArray::kHeaderSize + kPointerSize)); | 2877 __ mov(edx, FieldOperand(eax, FixedArray::kHeaderSize + kPointerSize)); |
2873 __ mov(Operand(esp, args->length() * kPointerSize), edx); | 2878 __ mov(Operand(esp, args->length() * kPointerSize), edx); |
2874 | 2879 |
2875 // Call the function. | 2880 // Call the function. |
2876 __ RecordPosition(node->position()); | 2881 CodeForSourcePosition(node->position()); |
2877 | 2882 |
2878 CallFunctionStub call_function(args->length()); | 2883 CallFunctionStub call_function(args->length()); |
2879 __ CallStub(&call_function); | 2884 __ CallStub(&call_function); |
2880 | 2885 |
2881 // Restore context and pop function from the stack. | 2886 // Restore context and pop function from the stack. |
2882 __ mov(esi, frame_->Context()); | 2887 __ mov(esi, frame_->Context()); |
2883 __ mov(frame_->Top(), eax); | 2888 __ mov(frame_->Top(), eax); |
2884 } | 2889 } |
2885 | 2890 |
2886 | 2891 |
(...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3764 SmiComparison(cc, right->AsLiteral()->handle(), strict); | 3769 SmiComparison(cc, right->AsLiteral()->handle(), strict); |
3765 return; | 3770 return; |
3766 } | 3771 } |
3767 | 3772 |
3768 Load(left); | 3773 Load(left); |
3769 Load(right); | 3774 Load(right); |
3770 Comparison(cc, strict); | 3775 Comparison(cc, strict); |
3771 } | 3776 } |
3772 | 3777 |
3773 | 3778 |
3774 void CodeGenerator::RecordStatementPosition(Node* node) { | |
3775 if (FLAG_debug_info) { | |
3776 int pos = node->statement_pos(); | |
3777 if (pos != RelocInfo::kNoPosition) { | |
3778 __ RecordStatementPosition(pos); | |
3779 } | |
3780 } | |
3781 } | |
3782 | |
3783 | |
3784 #undef __ | 3779 #undef __ |
3785 #define __ masm-> | 3780 #define __ masm-> |
3786 | 3781 |
3787 Handle<String> Reference::GetName() { | 3782 Handle<String> Reference::GetName() { |
3788 ASSERT(type_ == NAMED); | 3783 ASSERT(type_ == NAMED); |
3789 Property* property = expression_->AsProperty(); | 3784 Property* property = expression_->AsProperty(); |
3790 if (property == NULL) { | 3785 if (property == NULL) { |
3791 // Global variable reference treated as a named property reference. | 3786 // Global variable reference treated as a named property reference. |
3792 VariableProxy* proxy = expression_->AsVariableProxy(); | 3787 VariableProxy* proxy = expression_->AsVariableProxy(); |
3793 ASSERT(proxy->AsVariable() != NULL); | 3788 ASSERT(proxy->AsVariable() != NULL); |
3794 ASSERT(proxy->AsVariable()->is_global()); | 3789 ASSERT(proxy->AsVariable()->is_global()); |
3795 return proxy->name(); | 3790 return proxy->name(); |
3796 } else { | 3791 } else { |
3797 MacroAssembler* masm = cgen_->masm(); | |
3798 __ RecordPosition(property->position()); | |
3799 Literal* raw_name = property->key()->AsLiteral(); | 3792 Literal* raw_name = property->key()->AsLiteral(); |
3800 ASSERT(raw_name != NULL); | 3793 ASSERT(raw_name != NULL); |
3801 return Handle<String>(String::cast(*raw_name->handle())); | 3794 return Handle<String>(String::cast(*raw_name->handle())); |
3802 } | 3795 } |
3803 } | 3796 } |
3804 | 3797 |
3805 | 3798 |
3806 void Reference::GetValue(TypeofState typeof_state) { | 3799 void Reference::GetValue(TypeofState typeof_state) { |
3807 ASSERT(!is_illegal()); | 3800 ASSERT(!is_illegal()); |
3808 ASSERT(!cgen_->has_cc()); | 3801 ASSERT(!cgen_->has_cc()); |
(...skipping 30 matching lines...) Expand all Loading... |
3839 frame->Push(eax); // IC call leaves result in eax, push it out | 3832 frame->Push(eax); // IC call leaves result in eax, push it out |
3840 break; | 3833 break; |
3841 } | 3834 } |
3842 | 3835 |
3843 case KEYED: { | 3836 case KEYED: { |
3844 // TODO(1241834): Make sure that this it is safe to ignore the | 3837 // TODO(1241834): Make sure that this it is safe to ignore the |
3845 // distinction between expressions in a typeof and not in a typeof. | 3838 // distinction between expressions in a typeof and not in a typeof. |
3846 Comment cmnt(masm, "[ Load from keyed Property"); | 3839 Comment cmnt(masm, "[ Load from keyed Property"); |
3847 Property* property = expression_->AsProperty(); | 3840 Property* property = expression_->AsProperty(); |
3848 ASSERT(property != NULL); | 3841 ASSERT(property != NULL); |
3849 __ RecordPosition(property->position()); | |
3850 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 3842 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
3851 | 3843 |
3852 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 3844 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
3853 if (var != NULL) { | 3845 if (var != NULL) { |
3854 ASSERT(var->is_global()); | 3846 ASSERT(var->is_global()); |
3855 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 3847 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
3856 } else { | 3848 } else { |
3857 __ call(ic, RelocInfo::CODE_TARGET); | 3849 __ call(ic, RelocInfo::CODE_TARGET); |
3858 } | 3850 } |
3859 frame->Push(eax); // IC call leaves result in eax, push it out | 3851 frame->Push(eax); // IC call leaves result in eax, push it out |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3958 __ mov(ecx, name); | 3950 __ mov(ecx, name); |
3959 __ call(ic, RelocInfo::CODE_TARGET); | 3951 __ call(ic, RelocInfo::CODE_TARGET); |
3960 frame->Push(eax); // IC call leaves result in eax, push it out | 3952 frame->Push(eax); // IC call leaves result in eax, push it out |
3961 break; | 3953 break; |
3962 } | 3954 } |
3963 | 3955 |
3964 case KEYED: { | 3956 case KEYED: { |
3965 Comment cmnt(masm, "[ Store to keyed Property"); | 3957 Comment cmnt(masm, "[ Store to keyed Property"); |
3966 Property* property = expression_->AsProperty(); | 3958 Property* property = expression_->AsProperty(); |
3967 ASSERT(property != NULL); | 3959 ASSERT(property != NULL); |
3968 __ RecordPosition(property->position()); | |
3969 // Call IC code. | 3960 // Call IC code. |
3970 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 3961 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
3971 // TODO(1222589): Make the IC grab the values from the stack. | 3962 // TODO(1222589): Make the IC grab the values from the stack. |
3972 frame->Pop(eax); | 3963 frame->Pop(eax); |
3973 __ call(ic, RelocInfo::CODE_TARGET); | 3964 __ call(ic, RelocInfo::CODE_TARGET); |
3974 frame->Push(eax); // IC call leaves result in eax, push it out | 3965 frame->Push(eax); // IC call leaves result in eax, push it out |
3975 break; | 3966 break; |
3976 } | 3967 } |
3977 | 3968 |
3978 default: | 3969 default: |
(...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5199 | 5190 |
5200 // Slow-case: Go through the JavaScript implementation. | 5191 // Slow-case: Go through the JavaScript implementation. |
5201 __ bind(&slow); | 5192 __ bind(&slow); |
5202 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5193 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
5203 } | 5194 } |
5204 | 5195 |
5205 | 5196 |
5206 #undef __ | 5197 #undef __ |
5207 | 5198 |
5208 } } // namespace v8::internal | 5199 } } // namespace v8::internal |
OLD | NEW |