| 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 |