OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
651 done.Branch(ne); | 651 done.Branch(ne); |
652 } | 652 } |
653 StoreToSlot(arguments->slot(), NOT_CONST_INIT); | 653 StoreToSlot(arguments->slot(), NOT_CONST_INIT); |
654 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); | 654 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); |
655 StoreToSlot(shadow->slot(), NOT_CONST_INIT); | 655 StoreToSlot(shadow->slot(), NOT_CONST_INIT); |
656 } | 656 } |
657 | 657 |
658 | 658 |
659 void CodeGenerator::LoadTypeofExpression(Expression* expr) { | 659 void CodeGenerator::LoadTypeofExpression(Expression* expr) { |
660 // Special handling of identifiers as subexpressions of typeof. | 660 // Special handling of identifiers as subexpressions of typeof. |
661 VirtualFrame::SpilledScope spilled_scope(frame_); | |
662 Variable* variable = expr->AsVariableProxy()->AsVariable(); | 661 Variable* variable = expr->AsVariableProxy()->AsVariable(); |
663 if (variable != NULL && !variable->is_this() && variable->is_global()) { | 662 if (variable != NULL && !variable->is_this() && variable->is_global()) { |
664 // For a global variable we build the property reference | 663 // For a global variable we build the property reference |
665 // <global>.<variable> and perform a (regular non-contextual) property | 664 // <global>.<variable> and perform a (regular non-contextual) property |
666 // load to make sure we do not get reference errors. | 665 // load to make sure we do not get reference errors. |
667 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 666 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
668 Literal key(variable->name()); | 667 Literal key(variable->name()); |
669 Property property(&global, &key, RelocInfo::kNoPosition); | 668 Property property(&global, &key, RelocInfo::kNoPosition); |
670 Reference ref(this, &property); | 669 Reference ref(this, &property); |
671 ref.GetValue(); | 670 ref.GetValue(); |
672 } else if (variable != NULL && variable->slot() != NULL) { | 671 } else if (variable != NULL && variable->slot() != NULL) { |
673 // For a variable that rewrites to a slot, we signal it is the immediate | 672 // For a variable that rewrites to a slot, we signal it is the immediate |
674 // subexpression of a typeof. | 673 // subexpression of a typeof. |
675 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 674 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); |
676 frame_->SpillAll(); | |
677 } else { | 675 } else { |
678 // Anything else can be handled normally. | 676 // Anything else can be handled normally. |
679 LoadAndSpill(expr); | 677 Load(expr); |
680 } | 678 } |
681 } | 679 } |
682 | 680 |
683 | 681 |
684 Reference::Reference(CodeGenerator* cgen, | 682 Reference::Reference(CodeGenerator* cgen, |
685 Expression* expression, | 683 Expression* expression, |
686 bool persist_after_get) | 684 bool persist_after_get) |
687 : cgen_(cgen), | 685 : cgen_(cgen), |
688 expression_(expression), | 686 expression_(expression), |
689 type_(ILLEGAL), | 687 type_(ILLEGAL), |
(...skipping 28 matching lines...) Expand all Loading... | |
718 // property. Global variables are treated as named property references. | 716 // property. Global variables are treated as named property references. |
719 if (var->is_global()) { | 717 if (var->is_global()) { |
720 LoadGlobal(); | 718 LoadGlobal(); |
721 ref->set_type(Reference::NAMED); | 719 ref->set_type(Reference::NAMED); |
722 } else { | 720 } else { |
723 ASSERT(var->slot() != NULL); | 721 ASSERT(var->slot() != NULL); |
724 ref->set_type(Reference::SLOT); | 722 ref->set_type(Reference::SLOT); |
725 } | 723 } |
726 } else { | 724 } else { |
727 // Anything else is a runtime error. | 725 // Anything else is a runtime error. |
728 VirtualFrame::SpilledScope spilled_scope(frame_); | 726 Load(e); |
729 LoadAndSpill(e); | |
730 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); | 727 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); |
731 } | 728 } |
732 } | 729 } |
733 | 730 |
734 | 731 |
735 void CodeGenerator::UnloadReference(Reference* ref) { | 732 void CodeGenerator::UnloadReference(Reference* ref) { |
736 int size = ref->size(); | 733 int size = ref->size(); |
737 ref->set_unloaded(); | 734 ref->set_unloaded(); |
738 if (size == 0) return; | 735 if (size == 0) return; |
739 | 736 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 case Token::DIV: | 846 case Token::DIV: |
850 case Token::MOD: | 847 case Token::MOD: |
851 case Token::BIT_OR: | 848 case Token::BIT_OR: |
852 case Token::BIT_AND: | 849 case Token::BIT_AND: |
853 case Token::BIT_XOR: | 850 case Token::BIT_XOR: |
854 case Token::SHL: | 851 case Token::SHL: |
855 case Token::SHR: | 852 case Token::SHR: |
856 case Token::SAR: { | 853 case Token::SAR: { |
857 Register rhs = frame_->PopToRegister(); | 854 Register rhs = frame_->PopToRegister(); |
858 Register lhs = frame_->PopToRegister(rhs); // Don't pop to rhs register. | 855 Register lhs = frame_->PopToRegister(rhs); // Don't pop to rhs register. |
859 { | 856 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs); |
860 VirtualFrame::SpilledScope spilled_scope(frame_); | 857 frame_->SpillAll(); |
861 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs); | 858 frame_->CallStub(&stub, 0); |
862 frame_->CallStub(&stub, 0); | |
863 } | |
864 frame_->EmitPush(r0); | 859 frame_->EmitPush(r0); |
865 break; | 860 break; |
866 } | 861 } |
867 | 862 |
868 case Token::COMMA: { | 863 case Token::COMMA: { |
869 Register scratch = frame_->PopToRegister(); | 864 Register scratch = frame_->PopToRegister(); |
870 // Simply discard left value. | 865 // Simply discard left value. |
871 frame_->Drop(); | 866 frame_->Drop(); |
872 frame_->EmitPush(scratch); | 867 frame_->EmitPush(scratch); |
873 break; | 868 break; |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1327 | 1322 |
1328 exit.Bind(); | 1323 exit.Bind(); |
1329 cc_reg_ = cc; | 1324 cc_reg_ = cc; |
1330 } | 1325 } |
1331 | 1326 |
1332 | 1327 |
1333 // Call the function on the stack with the given arguments. | 1328 // Call the function on the stack with the given arguments. |
1334 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 1329 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
1335 CallFunctionFlags flags, | 1330 CallFunctionFlags flags, |
1336 int position) { | 1331 int position) { |
1337 VirtualFrame::SpilledScope spilled_scope(frame_); | 1332 frame_->AssertIsSpilled(); |
1333 | |
1338 // Push the arguments ("left-to-right") on the stack. | 1334 // Push the arguments ("left-to-right") on the stack. |
1339 int arg_count = args->length(); | 1335 int arg_count = args->length(); |
1340 for (int i = 0; i < arg_count; i++) { | 1336 for (int i = 0; i < arg_count; i++) { |
1341 LoadAndSpill(args->at(i)); | 1337 Load(args->at(i)); |
1342 } | 1338 } |
1343 | 1339 |
1344 // Record the position for debugging purposes. | 1340 // Record the position for debugging purposes. |
1345 CodeForSourcePosition(position); | 1341 CodeForSourcePosition(position); |
1346 | 1342 |
1347 // Use the shared code stub to call the function. | 1343 // Use the shared code stub to call the function. |
1348 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 1344 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
1349 CallFunctionStub call_function(arg_count, in_loop, flags); | 1345 CallFunctionStub call_function(arg_count, in_loop, flags); |
1350 frame_->CallStub(&call_function, arg_count + 1); | 1346 frame_->CallStub(&call_function, arg_count + 1); |
1351 | 1347 |
(...skipping 15 matching lines...) Expand all Loading... | |
1367 // stack, as receiver and arguments, and calls x. | 1363 // stack, as receiver and arguments, and calls x. |
1368 // In the implementation comments, we call x the applicand | 1364 // In the implementation comments, we call x the applicand |
1369 // and y the receiver. | 1365 // and y the receiver. |
1370 VirtualFrame::SpilledScope spilled_scope(frame_); | 1366 VirtualFrame::SpilledScope spilled_scope(frame_); |
1371 | 1367 |
1372 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); | 1368 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); |
1373 ASSERT(arguments->IsArguments()); | 1369 ASSERT(arguments->IsArguments()); |
1374 | 1370 |
1375 // Load applicand.apply onto the stack. This will usually | 1371 // Load applicand.apply onto the stack. This will usually |
1376 // give us a megamorphic load site. Not super, but it works. | 1372 // give us a megamorphic load site. Not super, but it works. |
1377 LoadAndSpill(applicand); | 1373 Load(applicand); |
1378 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 1374 Handle<String> name = Factory::LookupAsciiSymbol("apply"); |
1379 frame_->Dup(); | 1375 frame_->Dup(); |
1380 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); | 1376 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); |
1381 frame_->EmitPush(r0); | 1377 frame_->EmitPush(r0); |
1382 | 1378 |
1383 // Load the receiver and the existing arguments object onto the | 1379 // Load the receiver and the existing arguments object onto the |
1384 // expression stack. Avoid allocating the arguments object here. | 1380 // expression stack. Avoid allocating the arguments object here. |
1385 LoadAndSpill(receiver); | 1381 Load(receiver); |
1386 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 1382 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); |
1387 | 1383 |
1388 // Emit the source position information after having loaded the | 1384 // Emit the source position information after having loaded the |
1389 // receiver and the arguments. | 1385 // receiver and the arguments. |
1390 CodeForSourcePosition(position); | 1386 CodeForSourcePosition(position); |
1391 // Contents of the stack at this point: | 1387 // Contents of the stack at this point: |
1392 // sp[0]: arguments object of the current function or the hole. | 1388 // sp[0]: arguments object of the current function or the hole. |
1393 // sp[1]: receiver | 1389 // sp[1]: receiver |
1394 // sp[2]: applicand.apply | 1390 // sp[2]: applicand.apply |
1395 // sp[3]: applicand. | 1391 // sp[3]: applicand. |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1667 frame_->Drop(); | 1663 frame_->Drop(); |
1668 } | 1664 } |
1669 ASSERT(frame_->height() == original_height); | 1665 ASSERT(frame_->height() == original_height); |
1670 } | 1666 } |
1671 | 1667 |
1672 | 1668 |
1673 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1669 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
1674 #ifdef DEBUG | 1670 #ifdef DEBUG |
1675 int original_height = frame_->height(); | 1671 int original_height = frame_->height(); |
1676 #endif | 1672 #endif |
1677 VirtualFrame::SpilledScope spilled_scope(frame_); | |
1678 Comment cmnt(masm_, "[ ExpressionStatement"); | 1673 Comment cmnt(masm_, "[ ExpressionStatement"); |
1679 CodeForStatementPosition(node); | 1674 CodeForStatementPosition(node); |
1680 Expression* expression = node->expression(); | 1675 Expression* expression = node->expression(); |
1681 expression->MarkAsStatement(); | 1676 expression->MarkAsStatement(); |
1682 LoadAndSpill(expression); | 1677 Load(expression); |
1683 frame_->Drop(); | 1678 frame_->Drop(); |
1684 ASSERT(frame_->height() == original_height); | 1679 ASSERT(frame_->height() == original_height); |
1685 } | 1680 } |
1686 | 1681 |
1687 | 1682 |
1688 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1683 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
1689 #ifdef DEBUG | 1684 #ifdef DEBUG |
1690 int original_height = frame_->height(); | 1685 int original_height = frame_->height(); |
1691 #endif | 1686 #endif |
1692 VirtualFrame::SpilledScope spilled_scope(frame_); | |
1693 Comment cmnt(masm_, "// EmptyStatement"); | 1687 Comment cmnt(masm_, "// EmptyStatement"); |
1694 CodeForStatementPosition(node); | 1688 CodeForStatementPosition(node); |
1695 // nothing to do | 1689 // nothing to do |
1696 ASSERT(frame_->height() == original_height); | 1690 ASSERT(frame_->height() == original_height); |
1697 } | 1691 } |
1698 | 1692 |
1699 | 1693 |
1700 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 1694 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
1701 #ifdef DEBUG | 1695 #ifdef DEBUG |
1702 int original_height = frame_->height(); | 1696 int original_height = frame_->height(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1800 CodeForStatementPosition(node); | 1794 CodeForStatementPosition(node); |
1801 node->target()->break_target()->Jump(); | 1795 node->target()->break_target()->Jump(); |
1802 } | 1796 } |
1803 | 1797 |
1804 | 1798 |
1805 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 1799 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
1806 VirtualFrame::SpilledScope spilled_scope(frame_); | 1800 VirtualFrame::SpilledScope spilled_scope(frame_); |
1807 Comment cmnt(masm_, "[ ReturnStatement"); | 1801 Comment cmnt(masm_, "[ ReturnStatement"); |
1808 | 1802 |
1809 CodeForStatementPosition(node); | 1803 CodeForStatementPosition(node); |
1810 LoadAndSpill(node->expression()); | 1804 Load(node->expression()); |
1811 if (function_return_is_shadowed_) { | 1805 if (function_return_is_shadowed_) { |
1812 frame_->EmitPop(r0); | 1806 frame_->EmitPop(r0); |
1813 function_return_.Jump(); | 1807 function_return_.Jump(); |
1814 } else { | 1808 } else { |
1815 // Pop the result from the frame and prepare the frame for | 1809 // Pop the result from the frame and prepare the frame for |
1816 // returning thus making it easier to merge. | 1810 // returning thus making it easier to merge. |
1817 frame_->EmitPop(r0); | 1811 frame_->EmitPop(r0); |
1818 frame_->PrepareForReturn(); | 1812 frame_->PrepareForReturn(); |
1819 | 1813 |
1820 function_return_.Jump(); | 1814 function_return_.Jump(); |
1821 } | 1815 } |
1822 } | 1816 } |
1823 | 1817 |
1824 | 1818 |
1825 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1819 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
1826 #ifdef DEBUG | 1820 #ifdef DEBUG |
1827 int original_height = frame_->height(); | 1821 int original_height = frame_->height(); |
1828 #endif | 1822 #endif |
1829 VirtualFrame::SpilledScope spilled_scope(frame_); | 1823 VirtualFrame::SpilledScope spilled_scope(frame_); |
1830 Comment cmnt(masm_, "[ WithEnterStatement"); | 1824 Comment cmnt(masm_, "[ WithEnterStatement"); |
1831 CodeForStatementPosition(node); | 1825 CodeForStatementPosition(node); |
1832 LoadAndSpill(node->expression()); | 1826 Load(node->expression()); |
1833 if (node->is_catch_block()) { | 1827 if (node->is_catch_block()) { |
1834 frame_->CallRuntime(Runtime::kPushCatchContext, 1); | 1828 frame_->CallRuntime(Runtime::kPushCatchContext, 1); |
1835 } else { | 1829 } else { |
1836 frame_->CallRuntime(Runtime::kPushContext, 1); | 1830 frame_->CallRuntime(Runtime::kPushContext, 1); |
1837 } | 1831 } |
1838 #ifdef DEBUG | 1832 #ifdef DEBUG |
1839 JumpTarget verified_true; | 1833 JumpTarget verified_true; |
1840 __ cmp(r0, cp); | 1834 __ cmp(r0, cp); |
1841 verified_true.Branch(eq); | 1835 verified_true.Branch(eq); |
1842 __ stop("PushContext: r0 is expected to be the same as cp"); | 1836 __ stop("PushContext: r0 is expected to be the same as cp"); |
(...skipping 22 matching lines...) Expand all Loading... | |
1865 | 1859 |
1866 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 1860 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
1867 #ifdef DEBUG | 1861 #ifdef DEBUG |
1868 int original_height = frame_->height(); | 1862 int original_height = frame_->height(); |
1869 #endif | 1863 #endif |
1870 VirtualFrame::SpilledScope spilled_scope(frame_); | 1864 VirtualFrame::SpilledScope spilled_scope(frame_); |
1871 Comment cmnt(masm_, "[ SwitchStatement"); | 1865 Comment cmnt(masm_, "[ SwitchStatement"); |
1872 CodeForStatementPosition(node); | 1866 CodeForStatementPosition(node); |
1873 node->break_target()->SetExpectedHeight(); | 1867 node->break_target()->SetExpectedHeight(); |
1874 | 1868 |
1875 LoadAndSpill(node->tag()); | 1869 Load(node->tag()); |
1876 | 1870 |
1877 JumpTarget next_test; | 1871 JumpTarget next_test; |
1878 JumpTarget fall_through; | 1872 JumpTarget fall_through; |
1879 JumpTarget default_entry; | 1873 JumpTarget default_entry; |
1880 JumpTarget default_exit(JumpTarget::BIDIRECTIONAL); | 1874 JumpTarget default_exit(JumpTarget::BIDIRECTIONAL); |
1881 ZoneList<CaseClause*>* cases = node->cases(); | 1875 ZoneList<CaseClause*>* cases = node->cases(); |
1882 int length = cases->length(); | 1876 int length = cases->length(); |
1883 CaseClause* default_clause = NULL; | 1877 CaseClause* default_clause = NULL; |
1884 | 1878 |
1885 for (int i = 0; i < length; i++) { | 1879 for (int i = 0; i < length; i++) { |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2164 CodeForStatementPosition(node); | 2158 CodeForStatementPosition(node); |
2165 | 2159 |
2166 JumpTarget primitive; | 2160 JumpTarget primitive; |
2167 JumpTarget jsobject; | 2161 JumpTarget jsobject; |
2168 JumpTarget fixed_array; | 2162 JumpTarget fixed_array; |
2169 JumpTarget entry(JumpTarget::BIDIRECTIONAL); | 2163 JumpTarget entry(JumpTarget::BIDIRECTIONAL); |
2170 JumpTarget end_del_check; | 2164 JumpTarget end_del_check; |
2171 JumpTarget exit; | 2165 JumpTarget exit; |
2172 | 2166 |
2173 // Get the object to enumerate over (converted to JSObject). | 2167 // Get the object to enumerate over (converted to JSObject). |
2174 LoadAndSpill(node->enumerable()); | 2168 Load(node->enumerable()); |
2175 | 2169 |
2176 // Both SpiderMonkey and kjs ignore null and undefined in contrast | 2170 // Both SpiderMonkey and kjs ignore null and undefined in contrast |
2177 // to the specification. 12.6.4 mandates a call to ToObject. | 2171 // to the specification. 12.6.4 mandates a call to ToObject. |
2178 frame_->EmitPop(r0); | 2172 frame_->EmitPop(r0); |
2179 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 2173 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
2180 __ cmp(r0, ip); | 2174 __ cmp(r0, ip); |
2181 exit.Branch(eq); | 2175 exit.Branch(eq); |
2182 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 2176 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
2183 __ cmp(r0, ip); | 2177 __ cmp(r0, ip); |
2184 exit.Branch(eq); | 2178 exit.Branch(eq); |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2689 exit.Bind(); | 2683 exit.Bind(); |
2690 } | 2684 } |
2691 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2685 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
2692 } | 2686 } |
2693 | 2687 |
2694 | 2688 |
2695 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 2689 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
2696 #ifdef DEBUG | 2690 #ifdef DEBUG |
2697 int original_height = frame_->height(); | 2691 int original_height = frame_->height(); |
2698 #endif | 2692 #endif |
2699 VirtualFrame::SpilledScope spilled_scope(frame_); | |
2700 Comment cmnt(masm_, "[ DebuggerStatament"); | 2693 Comment cmnt(masm_, "[ DebuggerStatament"); |
2701 CodeForStatementPosition(node); | 2694 CodeForStatementPosition(node); |
2702 #ifdef ENABLE_DEBUGGER_SUPPORT | 2695 #ifdef ENABLE_DEBUGGER_SUPPORT |
2703 frame_->DebugBreak(); | 2696 frame_->DebugBreak(); |
2704 #endif | 2697 #endif |
2705 // Ignore the return value. | 2698 // Ignore the return value. |
2706 ASSERT(frame_->height() == original_height); | 2699 ASSERT(frame_->height() == original_height); |
2707 } | 2700 } |
2708 | 2701 |
2709 | 2702 |
2710 void CodeGenerator::InstantiateFunction( | 2703 void CodeGenerator::InstantiateFunction( |
2711 Handle<SharedFunctionInfo> function_info) { | 2704 Handle<SharedFunctionInfo> function_info) { |
2712 VirtualFrame::SpilledScope spilled_scope(frame_); | |
2713 __ mov(r0, Operand(function_info)); | |
2714 // Use the fast case closure allocation code that allocates in new | 2705 // Use the fast case closure allocation code that allocates in new |
2715 // space for nested functions that don't need literals cloning. | 2706 // space for nested functions that don't need literals cloning. |
2716 if (scope()->is_function_scope() && function_info->num_literals() == 0) { | 2707 if (scope()->is_function_scope() && function_info->num_literals() == 0) { |
2717 FastNewClosureStub stub; | 2708 FastNewClosureStub stub; |
2718 frame_->EmitPush(r0); | 2709 frame_->EmitPush(Operand(function_info)); |
2710 frame_->SpillAll(); | |
2719 frame_->CallStub(&stub, 1); | 2711 frame_->CallStub(&stub, 1); |
2720 frame_->EmitPush(r0); | 2712 frame_->EmitPush(r0); |
2721 } else { | 2713 } else { |
2722 // Create a new closure. | 2714 // Create a new closure. |
2723 frame_->EmitPush(cp); | 2715 frame_->EmitPush(cp); |
2724 frame_->EmitPush(r0); | 2716 frame_->EmitPush(Operand(function_info)); |
2725 frame_->CallRuntime(Runtime::kNewClosure, 2); | 2717 frame_->CallRuntime(Runtime::kNewClosure, 2); |
2726 frame_->EmitPush(r0); | 2718 frame_->EmitPush(r0); |
2727 } | 2719 } |
2728 } | 2720 } |
2729 | 2721 |
2730 | 2722 |
2731 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 2723 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
2732 #ifdef DEBUG | 2724 #ifdef DEBUG |
2733 int original_height = frame_->height(); | 2725 int original_height = frame_->height(); |
2734 #endif | 2726 #endif |
(...skipping 30 matching lines...) Expand all Loading... | |
2765 VirtualFrame::SpilledScope spilled_scope(frame_); | 2757 VirtualFrame::SpilledScope spilled_scope(frame_); |
2766 Comment cmnt(masm_, "[ Conditional"); | 2758 Comment cmnt(masm_, "[ Conditional"); |
2767 JumpTarget then; | 2759 JumpTarget then; |
2768 JumpTarget else_; | 2760 JumpTarget else_; |
2769 LoadConditionAndSpill(node->condition(), &then, &else_, true); | 2761 LoadConditionAndSpill(node->condition(), &then, &else_, true); |
2770 if (has_valid_frame()) { | 2762 if (has_valid_frame()) { |
2771 Branch(false, &else_); | 2763 Branch(false, &else_); |
2772 } | 2764 } |
2773 if (has_valid_frame() || then.is_linked()) { | 2765 if (has_valid_frame() || then.is_linked()) { |
2774 then.Bind(); | 2766 then.Bind(); |
2775 LoadAndSpill(node->then_expression()); | 2767 Load(node->then_expression()); |
2776 } | 2768 } |
2777 if (else_.is_linked()) { | 2769 if (else_.is_linked()) { |
2778 JumpTarget exit; | 2770 JumpTarget exit; |
2779 if (has_valid_frame()) exit.Jump(); | 2771 if (has_valid_frame()) exit.Jump(); |
2780 else_.Bind(); | 2772 else_.Bind(); |
2781 LoadAndSpill(node->else_expression()); | 2773 Load(node->else_expression()); |
2782 if (exit.is_linked()) exit.Bind(); | 2774 if (exit.is_linked()) exit.Bind(); |
2783 } | 2775 } |
2784 ASSERT_EQ(original_height + 1, frame_->height()); | 2776 ASSERT_EQ(original_height + 1, frame_->height()); |
2785 } | 2777 } |
2786 | 2778 |
2787 | 2779 |
2788 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 2780 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
2789 if (slot->type() == Slot::LOOKUP) { | 2781 if (slot->type() == Slot::LOOKUP) { |
2790 ASSERT(slot->var()->is_dynamic()); | 2782 ASSERT(slot->var()->is_dynamic()); |
2791 | 2783 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3191 Expression* value = property->value(); | 3183 Expression* value = property->value(); |
3192 switch (property->kind()) { | 3184 switch (property->kind()) { |
3193 case ObjectLiteral::Property::CONSTANT: | 3185 case ObjectLiteral::Property::CONSTANT: |
3194 break; | 3186 break; |
3195 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 3187 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
3196 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 3188 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
3197 // else fall through | 3189 // else fall through |
3198 case ObjectLiteral::Property::COMPUTED: | 3190 case ObjectLiteral::Property::COMPUTED: |
3199 if (key->handle()->IsSymbol()) { | 3191 if (key->handle()->IsSymbol()) { |
3200 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3192 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
3201 LoadAndSpill(value); | 3193 Load(value); |
3202 frame_->EmitPop(r0); | 3194 frame_->EmitPop(r0); |
3203 __ mov(r2, Operand(key->handle())); | 3195 __ mov(r2, Operand(key->handle())); |
3204 __ ldr(r1, frame_->Top()); // Load the receiver. | 3196 __ ldr(r1, frame_->Top()); // Load the receiver. |
3205 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 3197 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
3206 break; | 3198 break; |
3207 } | 3199 } |
3208 // else fall through | 3200 // else fall through |
3209 case ObjectLiteral::Property::PROTOTYPE: { | 3201 case ObjectLiteral::Property::PROTOTYPE: { |
3210 __ ldr(r0, frame_->Top()); | 3202 __ ldr(r0, frame_->Top()); |
3211 frame_->EmitPush(r0); // dup the result | 3203 frame_->EmitPush(r0); // dup the result |
3212 LoadAndSpill(key); | 3204 Load(key); |
3213 LoadAndSpill(value); | 3205 Load(value); |
3214 frame_->CallRuntime(Runtime::kSetProperty, 3); | 3206 frame_->CallRuntime(Runtime::kSetProperty, 3); |
3215 break; | 3207 break; |
3216 } | 3208 } |
3217 case ObjectLiteral::Property::SETTER: { | 3209 case ObjectLiteral::Property::SETTER: { |
3218 __ ldr(r0, frame_->Top()); | 3210 __ ldr(r0, frame_->Top()); |
3219 frame_->EmitPush(r0); | 3211 frame_->EmitPush(r0); |
3220 LoadAndSpill(key); | 3212 Load(key); |
3221 __ mov(r0, Operand(Smi::FromInt(1))); | 3213 __ mov(r0, Operand(Smi::FromInt(1))); |
3222 frame_->EmitPush(r0); | 3214 frame_->EmitPush(r0); |
3223 LoadAndSpill(value); | 3215 Load(value); |
3224 frame_->CallRuntime(Runtime::kDefineAccessor, 4); | 3216 frame_->CallRuntime(Runtime::kDefineAccessor, 4); |
3225 break; | 3217 break; |
3226 } | 3218 } |
3227 case ObjectLiteral::Property::GETTER: { | 3219 case ObjectLiteral::Property::GETTER: { |
3228 __ ldr(r0, frame_->Top()); | 3220 __ ldr(r0, frame_->Top()); |
3229 frame_->EmitPush(r0); | 3221 frame_->EmitPush(r0); |
3230 LoadAndSpill(key); | 3222 Load(key); |
3231 __ mov(r0, Operand(Smi::FromInt(0))); | 3223 __ mov(r0, Operand(Smi::FromInt(0))); |
3232 frame_->EmitPush(r0); | 3224 frame_->EmitPush(r0); |
3233 LoadAndSpill(value); | 3225 Load(value); |
3234 frame_->CallRuntime(Runtime::kDefineAccessor, 4); | 3226 frame_->CallRuntime(Runtime::kDefineAccessor, 4); |
3235 break; | 3227 break; |
3236 } | 3228 } |
3237 } | 3229 } |
3238 } | 3230 } |
3239 ASSERT_EQ(original_height + 1, frame_->height()); | 3231 ASSERT_EQ(original_height + 1, frame_->height()); |
3240 } | 3232 } |
3241 | 3233 |
3242 | 3234 |
3243 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 3235 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
(...skipping 28 matching lines...) Expand all Loading... | |
3272 Expression* value = node->values()->at(i); | 3264 Expression* value = node->values()->at(i); |
3273 | 3265 |
3274 // If value is a literal the property value is already set in the | 3266 // If value is a literal the property value is already set in the |
3275 // boilerplate object. | 3267 // boilerplate object. |
3276 if (value->AsLiteral() != NULL) continue; | 3268 if (value->AsLiteral() != NULL) continue; |
3277 // If value is a materialized literal the property value is already set | 3269 // If value is a materialized literal the property value is already set |
3278 // in the boilerplate object if it is simple. | 3270 // in the boilerplate object if it is simple. |
3279 if (CompileTimeValue::IsCompileTimeValue(value)) continue; | 3271 if (CompileTimeValue::IsCompileTimeValue(value)) continue; |
3280 | 3272 |
3281 // The property must be set by generated code. | 3273 // The property must be set by generated code. |
3282 LoadAndSpill(value); | 3274 Load(value); |
3283 frame_->EmitPop(r0); | 3275 frame_->EmitPop(r0); |
3284 | 3276 |
3285 // Fetch the object literal. | 3277 // Fetch the object literal. |
3286 __ ldr(r1, frame_->Top()); | 3278 __ ldr(r1, frame_->Top()); |
3287 // Get the elements array. | 3279 // Get the elements array. |
3288 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 3280 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
3289 | 3281 |
3290 // Write to the indexed properties array. | 3282 // Write to the indexed properties array. |
3291 int offset = i * kPointerSize + FixedArray::kHeaderSize; | 3283 int offset = i * kPointerSize + FixedArray::kHeaderSize; |
3292 __ str(r0, FieldMemOperand(r1, offset)); | 3284 __ str(r0, FieldMemOperand(r1, offset)); |
3293 | 3285 |
3294 // Update the write barrier for the array address. | 3286 // Update the write barrier for the array address. |
3295 __ mov(r3, Operand(offset)); | 3287 __ mov(r3, Operand(offset)); |
3296 __ RecordWrite(r1, r3, r2); | 3288 __ RecordWrite(r1, r3, r2); |
3297 } | 3289 } |
3298 ASSERT_EQ(original_height + 1, frame_->height()); | 3290 ASSERT_EQ(original_height + 1, frame_->height()); |
3299 } | 3291 } |
3300 | 3292 |
3301 | 3293 |
3302 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { | 3294 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
3303 #ifdef DEBUG | 3295 #ifdef DEBUG |
3304 int original_height = frame_->height(); | 3296 int original_height = frame_->height(); |
3305 #endif | 3297 #endif |
3306 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3307 // Call runtime routine to allocate the catch extension object and | 3298 // Call runtime routine to allocate the catch extension object and |
3308 // assign the exception value to the catch variable. | 3299 // assign the exception value to the catch variable. |
3309 Comment cmnt(masm_, "[ CatchExtensionObject"); | 3300 Comment cmnt(masm_, "[ CatchExtensionObject"); |
3310 LoadAndSpill(node->key()); | 3301 Load(node->key()); |
3311 LoadAndSpill(node->value()); | 3302 Load(node->value()); |
3312 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 3303 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
3313 frame_->EmitPush(r0); | 3304 frame_->EmitPush(r0); |
3314 ASSERT_EQ(original_height + 1, frame_->height()); | 3305 ASSERT_EQ(original_height + 1, frame_->height()); |
3315 } | 3306 } |
3316 | 3307 |
3317 | 3308 |
3318 void CodeGenerator::EmitSlotAssignment(Assignment* node) { | 3309 void CodeGenerator::EmitSlotAssignment(Assignment* node) { |
3319 #ifdef DEBUG | 3310 #ifdef DEBUG |
3320 int original_height = frame_->height(); | 3311 int original_height = frame_->height(); |
3321 #endif | 3312 #endif |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3620 frame_->EmitPush(r0); | 3611 frame_->EmitPush(r0); |
3621 } | 3612 } |
3622 ASSERT_EQ(original_height + 1, frame_->height()); | 3613 ASSERT_EQ(original_height + 1, frame_->height()); |
3623 } | 3614 } |
3624 | 3615 |
3625 | 3616 |
3626 void CodeGenerator::VisitThrow(Throw* node) { | 3617 void CodeGenerator::VisitThrow(Throw* node) { |
3627 #ifdef DEBUG | 3618 #ifdef DEBUG |
3628 int original_height = frame_->height(); | 3619 int original_height = frame_->height(); |
3629 #endif | 3620 #endif |
3630 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3631 Comment cmnt(masm_, "[ Throw"); | 3621 Comment cmnt(masm_, "[ Throw"); |
3632 | 3622 |
3633 LoadAndSpill(node->exception()); | 3623 Load(node->exception()); |
3634 CodeForSourcePosition(node->position()); | 3624 CodeForSourcePosition(node->position()); |
3635 frame_->CallRuntime(Runtime::kThrow, 1); | 3625 frame_->CallRuntime(Runtime::kThrow, 1); |
3636 frame_->EmitPush(r0); | 3626 frame_->EmitPush(r0); |
3637 ASSERT_EQ(original_height + 1, frame_->height()); | 3627 ASSERT_EQ(original_height + 1, frame_->height()); |
3638 } | 3628 } |
3639 | 3629 |
3640 | 3630 |
3641 void CodeGenerator::VisitProperty(Property* node) { | 3631 void CodeGenerator::VisitProperty(Property* node) { |
3642 #ifdef DEBUG | 3632 #ifdef DEBUG |
3643 int original_height = frame_->height(); | 3633 int original_height = frame_->height(); |
3644 #endif | 3634 #endif |
3645 Comment cmnt(masm_, "[ Property"); | 3635 Comment cmnt(masm_, "[ Property"); |
3646 | 3636 |
3647 { Reference property(this, node); | 3637 { Reference property(this, node); |
3648 property.GetValue(); | 3638 property.GetValue(); |
3649 } | 3639 } |
3650 ASSERT_EQ(original_height + 1, frame_->height()); | 3640 ASSERT_EQ(original_height + 1, frame_->height()); |
3651 } | 3641 } |
3652 | 3642 |
3653 | 3643 |
3654 void CodeGenerator::VisitCall(Call* node) { | 3644 void CodeGenerator::VisitCall(Call* node) { |
3655 #ifdef DEBUG | 3645 #ifdef DEBUG |
3656 int original_height = frame_->height(); | 3646 int original_height = frame_->height(); |
3657 #endif | 3647 #endif |
3658 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3659 Comment cmnt(masm_, "[ Call"); | 3648 Comment cmnt(masm_, "[ Call"); |
3660 | 3649 |
3661 Expression* function = node->expression(); | 3650 Expression* function = node->expression(); |
3662 ZoneList<Expression*>* args = node->arguments(); | 3651 ZoneList<Expression*>* args = node->arguments(); |
3663 | 3652 |
3664 // Standard function call. | 3653 // Standard function call. |
3665 // Check if the function is a variable or a property. | 3654 // Check if the function is a variable or a property. |
3666 Variable* var = function->AsVariableProxy()->AsVariable(); | 3655 Variable* var = function->AsVariableProxy()->AsVariable(); |
3667 Property* property = function->AsProperty(); | 3656 Property* property = function->AsProperty(); |
3668 | 3657 |
3669 // ------------------------------------------------------------------------ | 3658 // ------------------------------------------------------------------------ |
3670 // Fast-case: Use inline caching. | 3659 // Fast-case: Use inline caching. |
3671 // --- | 3660 // --- |
3672 // According to ECMA-262, section 11.2.3, page 44, the function to call | 3661 // According to ECMA-262, section 11.2.3, page 44, the function to call |
3673 // must be resolved after the arguments have been evaluated. The IC code | 3662 // must be resolved after the arguments have been evaluated. The IC code |
3674 // automatically handles this by loading the arguments before the function | 3663 // automatically handles this by loading the arguments before the function |
3675 // is resolved in cache misses (this also holds for megamorphic calls). | 3664 // is resolved in cache misses (this also holds for megamorphic calls). |
3676 // ------------------------------------------------------------------------ | 3665 // ------------------------------------------------------------------------ |
3677 | 3666 |
3678 if (var != NULL && var->is_possibly_eval()) { | 3667 if (var != NULL && var->is_possibly_eval()) { |
3668 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3679 // ---------------------------------- | 3669 // ---------------------------------- |
3680 // JavaScript example: 'eval(arg)' // eval is not known to be shadowed | 3670 // JavaScript example: 'eval(arg)' // eval is not known to be shadowed |
3681 // ---------------------------------- | 3671 // ---------------------------------- |
3682 | 3672 |
3683 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 3673 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
3684 // resolve the function we need to call and the receiver of the | 3674 // resolve the function we need to call and the receiver of the |
3685 // call. Then we call the resolved function using the given | 3675 // call. Then we call the resolved function using the given |
3686 // arguments. | 3676 // arguments. |
3687 // Prepare stack for call to resolved function. | 3677 // Prepare stack for call to resolved function. |
3688 LoadAndSpill(function); | 3678 Load(function); |
3689 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 3679 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
3690 frame_->EmitPush(r2); // Slot for receiver | 3680 frame_->EmitPush(r2); // Slot for receiver |
3691 int arg_count = args->length(); | 3681 int arg_count = args->length(); |
3692 for (int i = 0; i < arg_count; i++) { | 3682 for (int i = 0; i < arg_count; i++) { |
3693 LoadAndSpill(args->at(i)); | 3683 Load(args->at(i)); |
3694 } | 3684 } |
3695 | 3685 |
3696 // Prepare stack for call to ResolvePossiblyDirectEval. | 3686 // Prepare stack for call to ResolvePossiblyDirectEval. |
3697 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize + kPointerSize)); | 3687 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize + kPointerSize)); |
3698 frame_->EmitPush(r1); | 3688 frame_->EmitPush(r1); |
3699 if (arg_count > 0) { | 3689 if (arg_count > 0) { |
3700 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 3690 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
3701 frame_->EmitPush(r1); | 3691 frame_->EmitPush(r1); |
3702 } else { | 3692 } else { |
3703 frame_->EmitPush(r2); | 3693 frame_->EmitPush(r2); |
(...skipping 27 matching lines...) Expand all Loading... | |
3731 // JavaScript example: 'foo(1, 2, 3)' // foo is global | 3721 // JavaScript example: 'foo(1, 2, 3)' // foo is global |
3732 // ---------------------------------- | 3722 // ---------------------------------- |
3733 // Pass the global object as the receiver and let the IC stub | 3723 // Pass the global object as the receiver and let the IC stub |
3734 // patch the stack to use the global proxy as 'this' in the | 3724 // patch the stack to use the global proxy as 'this' in the |
3735 // invoked function. | 3725 // invoked function. |
3736 LoadGlobal(); | 3726 LoadGlobal(); |
3737 | 3727 |
3738 // Load the arguments. | 3728 // Load the arguments. |
3739 int arg_count = args->length(); | 3729 int arg_count = args->length(); |
3740 for (int i = 0; i < arg_count; i++) { | 3730 for (int i = 0; i < arg_count; i++) { |
3741 LoadAndSpill(args->at(i)); | 3731 Load(args->at(i)); |
3742 } | 3732 } |
3743 | 3733 |
3734 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3744 // Setup the name register and call the IC initialization code. | 3735 // Setup the name register and call the IC initialization code. |
3745 __ mov(r2, Operand(var->name())); | 3736 __ mov(r2, Operand(var->name())); |
3746 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 3737 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
3747 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 3738 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
3748 CodeForSourcePosition(node->position()); | 3739 CodeForSourcePosition(node->position()); |
3749 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 3740 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
3750 arg_count + 1); | 3741 arg_count + 1); |
3751 __ ldr(cp, frame_->Context()); | 3742 __ ldr(cp, frame_->Context()); |
3752 frame_->EmitPush(r0); | 3743 frame_->EmitPush(r0); |
3753 | 3744 |
3754 } else if (var != NULL && var->slot() != NULL && | 3745 } else if (var != NULL && var->slot() != NULL && |
3755 var->slot()->type() == Slot::LOOKUP) { | 3746 var->slot()->type() == Slot::LOOKUP) { |
3747 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3756 // ---------------------------------- | 3748 // ---------------------------------- |
3757 // JavaScript examples: | 3749 // JavaScript examples: |
3758 // | 3750 // |
3759 // with (obj) foo(1, 2, 3) // foo may be in obj. | 3751 // with (obj) foo(1, 2, 3) // foo may be in obj. |
3760 // | 3752 // |
3761 // function f() {}; | 3753 // function f() {}; |
3762 // function g() { | 3754 // function g() { |
3763 // eval(...); | 3755 // eval(...); |
3764 // f(); // f could be in extension object. | 3756 // f(); // f could be in extension object. |
3765 // } | 3757 // } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3823 args->at(1)->AsVariableProxy() != NULL && | 3815 args->at(1)->AsVariableProxy() != NULL && |
3824 args->at(1)->AsVariableProxy()->IsArguments()) { | 3816 args->at(1)->AsVariableProxy()->IsArguments()) { |
3825 // Use the optimized Function.prototype.apply that avoids | 3817 // Use the optimized Function.prototype.apply that avoids |
3826 // allocating lazily allocated arguments objects. | 3818 // allocating lazily allocated arguments objects. |
3827 CallApplyLazy(property->obj(), | 3819 CallApplyLazy(property->obj(), |
3828 args->at(0), | 3820 args->at(0), |
3829 args->at(1)->AsVariableProxy(), | 3821 args->at(1)->AsVariableProxy(), |
3830 node->position()); | 3822 node->position()); |
3831 | 3823 |
3832 } else { | 3824 } else { |
3833 LoadAndSpill(property->obj()); // Receiver. | 3825 Load(property->obj()); // Receiver. |
3834 // Load the arguments. | 3826 // Load the arguments. |
3835 int arg_count = args->length(); | 3827 int arg_count = args->length(); |
3836 for (int i = 0; i < arg_count; i++) { | 3828 for (int i = 0; i < arg_count; i++) { |
3837 LoadAndSpill(args->at(i)); | 3829 Load(args->at(i)); |
3838 } | 3830 } |
3839 | 3831 |
3832 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3840 // Set the name register and call the IC initialization code. | 3833 // Set the name register and call the IC initialization code. |
3841 __ mov(r2, Operand(name)); | 3834 __ mov(r2, Operand(name)); |
3842 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 3835 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
3843 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 3836 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
3844 CodeForSourcePosition(node->position()); | 3837 CodeForSourcePosition(node->position()); |
3845 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 3838 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
3846 __ ldr(cp, frame_->Context()); | 3839 __ ldr(cp, frame_->Context()); |
3847 frame_->EmitPush(r0); | 3840 frame_->EmitPush(r0); |
3848 } | 3841 } |
3849 | 3842 |
3850 } else { | 3843 } else { |
3851 // ------------------------------------------- | 3844 // ------------------------------------------- |
3852 // JavaScript example: 'array[index](1, 2, 3)' | 3845 // JavaScript example: 'array[index](1, 2, 3)' |
3853 // ------------------------------------------- | 3846 // ------------------------------------------- |
3847 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3854 | 3848 |
3855 LoadAndSpill(property->obj()); | 3849 Load(property->obj()); |
3856 if (!property->is_synthetic()) { | 3850 if (!property->is_synthetic()) { |
3857 // Duplicate receiver for later use. | 3851 // Duplicate receiver for later use. |
3858 __ ldr(r0, MemOperand(sp, 0)); | 3852 __ ldr(r0, MemOperand(sp, 0)); |
3859 frame_->EmitPush(r0); | 3853 frame_->EmitPush(r0); |
3860 } | 3854 } |
3861 LoadAndSpill(property->key()); | 3855 Load(property->key()); |
3862 EmitKeyedLoad(); | 3856 EmitKeyedLoad(); |
3863 // Put the function below the receiver. | 3857 // Put the function below the receiver. |
3864 if (property->is_synthetic()) { | 3858 if (property->is_synthetic()) { |
3865 // Use the global receiver. | 3859 // Use the global receiver. |
3866 frame_->EmitPush(r0); // Function. | 3860 frame_->EmitPush(r0); // Function. |
3867 LoadGlobalReceiver(r0); | 3861 LoadGlobalReceiver(r0); |
3868 } else { | 3862 } else { |
3869 // Switch receiver and function. | 3863 // Switch receiver and function. |
3870 frame_->EmitPop(r1); // Receiver. | 3864 frame_->EmitPop(r1); // Receiver. |
3871 frame_->EmitPush(r0); // Function. | 3865 frame_->EmitPush(r0); // Function. |
3872 frame_->EmitPush(r1); // Receiver. | 3866 frame_->EmitPush(r1); // Receiver. |
3873 } | 3867 } |
3874 | 3868 |
3875 // Call the function. | 3869 // Call the function. |
3876 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); | 3870 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
3877 frame_->EmitPush(r0); | 3871 frame_->EmitPush(r0); |
3878 } | 3872 } |
3879 | 3873 |
3880 } else { | 3874 } else { |
3881 // ---------------------------------- | 3875 // ---------------------------------- |
3882 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 3876 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
3883 // ---------------------------------- | 3877 // ---------------------------------- |
3884 | 3878 |
3885 // Load the function. | 3879 // Load the function. |
3886 LoadAndSpill(function); | 3880 Load(function); |
3881 | |
3882 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3887 | 3883 |
3888 // Pass the global proxy as the receiver. | 3884 // Pass the global proxy as the receiver. |
3889 LoadGlobalReceiver(r0); | 3885 LoadGlobalReceiver(r0); |
3890 | 3886 |
3891 // Call the function. | 3887 // Call the function. |
3892 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); | 3888 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
3893 frame_->EmitPush(r0); | 3889 frame_->EmitPush(r0); |
3894 } | 3890 } |
3895 ASSERT_EQ(original_height + 1, frame_->height()); | 3891 ASSERT_EQ(original_height + 1, frame_->height()); |
3896 } | 3892 } |
3897 | 3893 |
3898 | 3894 |
3899 void CodeGenerator::VisitCallNew(CallNew* node) { | 3895 void CodeGenerator::VisitCallNew(CallNew* node) { |
3900 #ifdef DEBUG | 3896 #ifdef DEBUG |
3901 int original_height = frame_->height(); | 3897 int original_height = frame_->height(); |
3902 #endif | 3898 #endif |
3903 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3904 Comment cmnt(masm_, "[ CallNew"); | 3899 Comment cmnt(masm_, "[ CallNew"); |
3905 | 3900 |
3906 // According to ECMA-262, section 11.2.2, page 44, the function | 3901 // According to ECMA-262, section 11.2.2, page 44, the function |
3907 // expression in new calls must be evaluated before the | 3902 // expression in new calls must be evaluated before the |
3908 // arguments. This is different from ordinary calls, where the | 3903 // arguments. This is different from ordinary calls, where the |
3909 // actual function to call is resolved after the arguments have been | 3904 // actual function to call is resolved after the arguments have been |
3910 // evaluated. | 3905 // evaluated. |
3911 | 3906 |
3912 // Compute function to call and use the global object as the | 3907 // Compute function to call and use the global object as the |
3913 // receiver. There is no need to use the global proxy here because | 3908 // receiver. There is no need to use the global proxy here because |
3914 // it will always be replaced with a newly allocated object. | 3909 // it will always be replaced with a newly allocated object. |
3915 LoadAndSpill(node->expression()); | 3910 Load(node->expression()); |
3916 LoadGlobal(); | 3911 LoadGlobal(); |
3917 | 3912 |
3918 // Push the arguments ("left-to-right") on the stack. | 3913 // Push the arguments ("left-to-right") on the stack. |
3919 ZoneList<Expression*>* args = node->arguments(); | 3914 ZoneList<Expression*>* args = node->arguments(); |
3920 int arg_count = args->length(); | 3915 int arg_count = args->length(); |
3921 for (int i = 0; i < arg_count; i++) { | 3916 for (int i = 0; i < arg_count; i++) { |
3922 LoadAndSpill(args->at(i)); | 3917 Load(args->at(i)); |
3923 } | 3918 } |
3924 | 3919 |
3920 VirtualFrame::SpilledScope spilled_scope(frame_); | |
3921 | |
3925 // r0: the number of arguments. | 3922 // r0: the number of arguments. |
3926 __ mov(r0, Operand(arg_count)); | 3923 __ mov(r0, Operand(arg_count)); |
3927 // Load the function into r1 as per calling convention. | 3924 // Load the function into r1 as per calling convention. |
3928 __ ldr(r1, frame_->ElementAt(arg_count + 1)); | 3925 __ ldr(r1, frame_->ElementAt(arg_count + 1)); |
3929 | 3926 |
3930 // Call the construct call builtin that handles allocation and | 3927 // Call the construct call builtin that handles allocation and |
3931 // constructor invocation. | 3928 // constructor invocation. |
3932 CodeForSourcePosition(node->position()); | 3929 CodeForSourcePosition(node->position()); |
3933 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 3930 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); |
3934 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); | 3931 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); |
3935 | 3932 |
3936 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). | 3933 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). |
3937 __ str(r0, frame_->Top()); | 3934 __ str(r0, frame_->Top()); |
3938 ASSERT_EQ(original_height + 1, frame_->height()); | 3935 ASSERT_EQ(original_height + 1, frame_->height()); |
3939 } | 3936 } |
3940 | 3937 |
3941 | 3938 |
3942 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 3939 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
3943 VirtualFrame::SpilledScope spilled_scope(frame_); | 3940 VirtualFrame::SpilledScope spilled_scope(frame_); |
3944 ASSERT(args->length() == 1); | 3941 ASSERT(args->length() == 1); |
3945 JumpTarget leave, null, function, non_function_constructor; | 3942 JumpTarget leave, null, function, non_function_constructor; |
3946 | 3943 |
3947 // Load the object into r0. | 3944 // Load the object into r0. |
3948 LoadAndSpill(args->at(0)); | 3945 Load(args->at(0)); |
3949 frame_->EmitPop(r0); | 3946 frame_->EmitPop(r0); |
3950 | 3947 |
3951 // If the object is a smi, we return null. | 3948 // If the object is a smi, we return null. |
3952 __ tst(r0, Operand(kSmiTagMask)); | 3949 __ tst(r0, Operand(kSmiTagMask)); |
3953 null.Branch(eq); | 3950 null.Branch(eq); |
3954 | 3951 |
3955 // Check that the object is a JS object but take special care of JS | 3952 // Check that the object is a JS object but take special care of JS |
3956 // functions to make sure they have 'Function' as their class. | 3953 // functions to make sure they have 'Function' as their class. |
3957 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); | 3954 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); |
3958 null.Branch(lt); | 3955 null.Branch(lt); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3996 | 3993 |
3997 // All done. | 3994 // All done. |
3998 leave.Bind(); | 3995 leave.Bind(); |
3999 } | 3996 } |
4000 | 3997 |
4001 | 3998 |
4002 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 3999 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
4003 VirtualFrame::SpilledScope spilled_scope(frame_); | 4000 VirtualFrame::SpilledScope spilled_scope(frame_); |
4004 ASSERT(args->length() == 1); | 4001 ASSERT(args->length() == 1); |
4005 JumpTarget leave; | 4002 JumpTarget leave; |
4006 LoadAndSpill(args->at(0)); | 4003 Load(args->at(0)); |
4007 frame_->EmitPop(r0); // r0 contains object. | 4004 frame_->EmitPop(r0); // r0 contains object. |
4008 // if (object->IsSmi()) return the object. | 4005 // if (object->IsSmi()) return the object. |
4009 __ tst(r0, Operand(kSmiTagMask)); | 4006 __ tst(r0, Operand(kSmiTagMask)); |
4010 leave.Branch(eq); | 4007 leave.Branch(eq); |
4011 // It is a heap object - get map. If (!object->IsJSValue()) return the object. | 4008 // It is a heap object - get map. If (!object->IsJSValue()) return the object. |
4012 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); | 4009 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); |
4013 leave.Branch(ne); | 4010 leave.Branch(ne); |
4014 // Load the value. | 4011 // Load the value. |
4015 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); | 4012 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); |
4016 leave.Bind(); | 4013 leave.Bind(); |
4017 frame_->EmitPush(r0); | 4014 frame_->EmitPush(r0); |
4018 } | 4015 } |
4019 | 4016 |
4020 | 4017 |
4021 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { | 4018 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { |
4022 VirtualFrame::SpilledScope spilled_scope(frame_); | 4019 VirtualFrame::SpilledScope spilled_scope(frame_); |
4023 ASSERT(args->length() == 2); | 4020 ASSERT(args->length() == 2); |
4024 JumpTarget leave; | 4021 JumpTarget leave; |
4025 LoadAndSpill(args->at(0)); // Load the object. | 4022 Load(args->at(0)); // Load the object. |
4026 LoadAndSpill(args->at(1)); // Load the value. | 4023 Load(args->at(1)); // Load the value. |
4027 frame_->EmitPop(r0); // r0 contains value | 4024 frame_->EmitPop(r0); // r0 contains value |
4028 frame_->EmitPop(r1); // r1 contains object | 4025 frame_->EmitPop(r1); // r1 contains object |
4029 // if (object->IsSmi()) return object. | 4026 // if (object->IsSmi()) return object. |
4030 __ tst(r1, Operand(kSmiTagMask)); | 4027 __ tst(r1, Operand(kSmiTagMask)); |
4031 leave.Branch(eq); | 4028 leave.Branch(eq); |
4032 // It is a heap object - get map. If (!object->IsJSValue()) return the object. | 4029 // It is a heap object - get map. If (!object->IsJSValue()) return the object. |
4033 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); | 4030 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); |
4034 leave.Branch(ne); | 4031 leave.Branch(ne); |
4035 // Store the value. | 4032 // Store the value. |
4036 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); | 4033 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
(...skipping 14 matching lines...) Expand all Loading... | |
4051 cc_reg_ = eq; | 4048 cc_reg_ = eq; |
4052 } | 4049 } |
4053 | 4050 |
4054 | 4051 |
4055 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { | 4052 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { |
4056 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. | 4053 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. |
4057 ASSERT_EQ(args->length(), 3); | 4054 ASSERT_EQ(args->length(), 3); |
4058 #ifdef ENABLE_LOGGING_AND_PROFILING | 4055 #ifdef ENABLE_LOGGING_AND_PROFILING |
4059 if (ShouldGenerateLog(args->at(0))) { | 4056 if (ShouldGenerateLog(args->at(0))) { |
4060 Load(args->at(1)); | 4057 Load(args->at(1)); |
4061 Load(args->at(2)); | 4058 Load(args->at(2)); |
Søren Thygesen Gjesse
2010/05/28 10:15:47
Isn't SpillAll/AssertIsSpilled needed here? (I don
Erik Corry
2010/05/28 11:24:12
Well spotted! I think the real problem here is th
| |
4062 frame_->SpillAll(); | |
4063 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4064 __ CallRuntime(Runtime::kLog, 2); | 4059 __ CallRuntime(Runtime::kLog, 2); |
4065 } | 4060 } |
4066 #endif | 4061 #endif |
4067 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); | 4062 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); |
4068 } | 4063 } |
4069 | 4064 |
4070 | 4065 |
4071 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 4066 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
4072 ASSERT(args->length() == 1); | 4067 ASSERT(args->length() == 1); |
4073 Load(args->at(0)); | 4068 Load(args->at(0)); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4143 }; | 4138 }; |
4144 | 4139 |
4145 | 4140 |
4146 // This generates code that performs a String.prototype.charCodeAt() call | 4141 // This generates code that performs a String.prototype.charCodeAt() call |
4147 // or returns a smi in order to trigger conversion. | 4142 // or returns a smi in order to trigger conversion. |
4148 void CodeGenerator::GenerateStringCharCodeAt(ZoneList<Expression*>* args) { | 4143 void CodeGenerator::GenerateStringCharCodeAt(ZoneList<Expression*>* args) { |
4149 VirtualFrame::SpilledScope spilled_scope(frame_); | 4144 VirtualFrame::SpilledScope spilled_scope(frame_); |
4150 Comment(masm_, "[ GenerateStringCharCodeAt"); | 4145 Comment(masm_, "[ GenerateStringCharCodeAt"); |
4151 ASSERT(args->length() == 2); | 4146 ASSERT(args->length() == 2); |
4152 | 4147 |
4153 LoadAndSpill(args->at(0)); | 4148 Load(args->at(0)); |
4154 LoadAndSpill(args->at(1)); | 4149 Load(args->at(1)); |
4155 | 4150 |
4156 Register index = r1; | 4151 Register index = r1; |
4157 Register object = r2; | 4152 Register object = r2; |
4158 | 4153 |
4159 frame_->EmitPop(r1); | 4154 frame_->EmitPop(r1); |
4160 frame_->EmitPop(r2); | 4155 frame_->EmitPop(r2); |
4161 | 4156 |
4162 // We need two extra registers. | 4157 // We need two extra registers. |
4163 Register scratch = r3; | 4158 Register scratch = r3; |
4164 Register result = r0; | 4159 Register result = r0; |
(...skipping 28 matching lines...) Expand all Loading... | |
4193 StringCharFromCodeGenerator char_from_code_generator_; | 4188 StringCharFromCodeGenerator char_from_code_generator_; |
4194 }; | 4189 }; |
4195 | 4190 |
4196 | 4191 |
4197 // Generates code for creating a one-char string from a char code. | 4192 // Generates code for creating a one-char string from a char code. |
4198 void CodeGenerator::GenerateStringCharFromCode(ZoneList<Expression*>* args) { | 4193 void CodeGenerator::GenerateStringCharFromCode(ZoneList<Expression*>* args) { |
4199 VirtualFrame::SpilledScope spilled_scope(frame_); | 4194 VirtualFrame::SpilledScope spilled_scope(frame_); |
4200 Comment(masm_, "[ GenerateStringCharFromCode"); | 4195 Comment(masm_, "[ GenerateStringCharFromCode"); |
4201 ASSERT(args->length() == 1); | 4196 ASSERT(args->length() == 1); |
4202 | 4197 |
4203 LoadAndSpill(args->at(0)); | 4198 Load(args->at(0)); |
4204 | 4199 |
4205 Register code = r1; | 4200 Register code = r1; |
4206 Register result = r0; | 4201 Register result = r0; |
4207 | 4202 |
4208 frame_->EmitPop(code); | 4203 frame_->EmitPop(code); |
4209 | 4204 |
4210 DeferredStringCharFromCode* deferred = new DeferredStringCharFromCode( | 4205 DeferredStringCharFromCode* deferred = new DeferredStringCharFromCode( |
4211 code, result); | 4206 code, result); |
4212 deferred->fast_case_generator()->GenerateFast(masm_); | 4207 deferred->fast_case_generator()->GenerateFast(masm_); |
4213 deferred->BindExit(); | 4208 deferred->BindExit(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4264 }; | 4259 }; |
4265 | 4260 |
4266 | 4261 |
4267 // This generates code that performs a String.prototype.charAt() call | 4262 // This generates code that performs a String.prototype.charAt() call |
4268 // or returns a smi in order to trigger conversion. | 4263 // or returns a smi in order to trigger conversion. |
4269 void CodeGenerator::GenerateStringCharAt(ZoneList<Expression*>* args) { | 4264 void CodeGenerator::GenerateStringCharAt(ZoneList<Expression*>* args) { |
4270 VirtualFrame::SpilledScope spilled_scope(frame_); | 4265 VirtualFrame::SpilledScope spilled_scope(frame_); |
4271 Comment(masm_, "[ GenerateStringCharAt"); | 4266 Comment(masm_, "[ GenerateStringCharAt"); |
4272 ASSERT(args->length() == 2); | 4267 ASSERT(args->length() == 2); |
4273 | 4268 |
4274 LoadAndSpill(args->at(0)); | 4269 Load(args->at(0)); |
4275 LoadAndSpill(args->at(1)); | 4270 Load(args->at(1)); |
4276 | 4271 |
4277 Register index = r1; | 4272 Register index = r1; |
4278 Register object = r2; | 4273 Register object = r2; |
4279 | 4274 |
4280 frame_->EmitPop(r1); | 4275 frame_->EmitPop(r1); |
4281 frame_->EmitPop(r2); | 4276 frame_->EmitPop(r2); |
4282 | 4277 |
4283 // We need three extra registers. | 4278 // We need three extra registers. |
4284 Register scratch1 = r3; | 4279 Register scratch1 = r3; |
4285 Register scratch2 = r4; | 4280 Register scratch2 = r4; |
4286 Register result = r0; | 4281 Register result = r0; |
4287 | 4282 |
4288 DeferredStringCharAt* deferred = | 4283 DeferredStringCharAt* deferred = |
4289 new DeferredStringCharAt(object, | 4284 new DeferredStringCharAt(object, |
4290 index, | 4285 index, |
4291 scratch1, | 4286 scratch1, |
4292 scratch2, | 4287 scratch2, |
4293 result); | 4288 result); |
4294 deferred->fast_case_generator()->GenerateFast(masm_); | 4289 deferred->fast_case_generator()->GenerateFast(masm_); |
4295 deferred->BindExit(); | 4290 deferred->BindExit(); |
4296 frame_->EmitPush(result); | 4291 frame_->EmitPush(result); |
4297 } | 4292 } |
4298 | 4293 |
4299 | 4294 |
4300 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | 4295 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { |
4301 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4302 ASSERT(args->length() == 1); | 4296 ASSERT(args->length() == 1); |
4303 LoadAndSpill(args->at(0)); | 4297 Load(args->at(0)); |
4304 JumpTarget answer; | 4298 JumpTarget answer; |
4305 // We need the CC bits to come out as not_equal in the case where the | 4299 // We need the CC bits to come out as not_equal in the case where the |
4306 // object is a smi. This can't be done with the usual test opcode so | 4300 // object is a smi. This can't be done with the usual test opcode so |
4307 // we use XOR to get the right CC bits. | 4301 // we use XOR to get the right CC bits. |
4308 frame_->EmitPop(r0); | 4302 Register possible_array = frame_->PopToRegister(); |
4309 __ and_(r1, r0, Operand(kSmiTagMask)); | 4303 Register scratch = VirtualFrame::scratch0(); |
4310 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); | 4304 __ and_(scratch, possible_array, Operand(kSmiTagMask)); |
4305 __ eor(scratch, scratch, Operand(kSmiTagMask), SetCC); | |
4311 answer.Branch(ne); | 4306 answer.Branch(ne); |
4312 // It is a heap object - get the map. Check if the object is a JS array. | 4307 // It is a heap object - get the map. Check if the object is a JS array. |
4313 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 4308 __ CompareObjectType(possible_array, scratch, scratch, JS_ARRAY_TYPE); |
4314 answer.Bind(); | 4309 answer.Bind(); |
4315 cc_reg_ = eq; | 4310 cc_reg_ = eq; |
4316 } | 4311 } |
4317 | 4312 |
4318 | 4313 |
4319 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { | 4314 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { |
4320 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4321 ASSERT(args->length() == 1); | 4315 ASSERT(args->length() == 1); |
4322 LoadAndSpill(args->at(0)); | 4316 Load(args->at(0)); |
4323 JumpTarget answer; | 4317 JumpTarget answer; |
4324 // We need the CC bits to come out as not_equal in the case where the | 4318 // We need the CC bits to come out as not_equal in the case where the |
4325 // object is a smi. This can't be done with the usual test opcode so | 4319 // object is a smi. This can't be done with the usual test opcode so |
4326 // we use XOR to get the right CC bits. | 4320 // we use XOR to get the right CC bits. |
4327 frame_->EmitPop(r0); | 4321 Register possible_regexp = frame_->PopToRegister(); |
4328 __ and_(r1, r0, Operand(kSmiTagMask)); | 4322 Register scratch = VirtualFrame::scratch0(); |
4329 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); | 4323 __ and_(scratch, possible_regexp, Operand(kSmiTagMask)); |
4324 __ eor(scratch, scratch, Operand(kSmiTagMask), SetCC); | |
4330 answer.Branch(ne); | 4325 answer.Branch(ne); |
4331 // It is a heap object - get the map. Check if the object is a regexp. | 4326 // It is a heap object - get the map. Check if the object is a regexp. |
4332 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); | 4327 __ CompareObjectType(possible_regexp, scratch, scratch, JS_REGEXP_TYPE); |
4333 answer.Bind(); | 4328 answer.Bind(); |
4334 cc_reg_ = eq; | 4329 cc_reg_ = eq; |
4335 } | 4330 } |
4336 | 4331 |
4337 | 4332 |
4338 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { | 4333 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { |
4339 // This generates a fast version of: | 4334 // This generates a fast version of: |
4340 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp') | 4335 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp') |
4341 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4342 ASSERT(args->length() == 1); | 4336 ASSERT(args->length() == 1); |
4343 LoadAndSpill(args->at(0)); | 4337 Load(args->at(0)); |
4344 frame_->EmitPop(r1); | 4338 Register possible_object = frame_->PopToRegister(); |
4345 __ tst(r1, Operand(kSmiTagMask)); | 4339 __ tst(possible_object, Operand(kSmiTagMask)); |
4346 false_target()->Branch(eq); | 4340 false_target()->Branch(eq); |
4347 | 4341 |
4348 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 4342 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
4349 __ cmp(r1, ip); | 4343 __ cmp(possible_object, ip); |
4350 true_target()->Branch(eq); | 4344 true_target()->Branch(eq); |
4351 | 4345 |
4352 Register map_reg = r2; | 4346 Register map_reg = VirtualFrame::scratch0(); |
4353 __ ldr(map_reg, FieldMemOperand(r1, HeapObject::kMapOffset)); | 4347 __ ldr(map_reg, FieldMemOperand(possible_object, HeapObject::kMapOffset)); |
4354 // Undetectable objects behave like undefined when tested with typeof. | 4348 // Undetectable objects behave like undefined when tested with typeof. |
4355 __ ldrb(r1, FieldMemOperand(map_reg, Map::kBitFieldOffset)); | 4349 __ ldrb(possible_object, FieldMemOperand(map_reg, Map::kBitFieldOffset)); |
4356 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4350 __ tst(possible_object, Operand(1 << Map::kIsUndetectable)); |
4357 false_target()->Branch(ne); | 4351 false_target()->Branch(ne); |
4358 | 4352 |
4359 __ ldrb(r1, FieldMemOperand(map_reg, Map::kInstanceTypeOffset)); | 4353 __ ldrb(possible_object, FieldMemOperand(map_reg, Map::kInstanceTypeOffset)); |
4360 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); | 4354 __ cmp(possible_object, Operand(FIRST_JS_OBJECT_TYPE)); |
4361 false_target()->Branch(lt); | 4355 false_target()->Branch(lt); |
4362 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); | 4356 __ cmp(possible_object, Operand(LAST_JS_OBJECT_TYPE)); |
4363 cc_reg_ = le; | 4357 cc_reg_ = le; |
4364 } | 4358 } |
4365 | 4359 |
4366 | 4360 |
4367 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { | 4361 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { |
4368 // This generates a fast version of: | 4362 // This generates a fast version of: |
4369 // (%_ClassOf(arg) === 'Function') | 4363 // (%_ClassOf(arg) === 'Function') |
4370 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4371 ASSERT(args->length() == 1); | 4364 ASSERT(args->length() == 1); |
4372 LoadAndSpill(args->at(0)); | 4365 Load(args->at(0)); |
4373 frame_->EmitPop(r0); | 4366 Register possible_function = frame_->PopToRegister(); |
4374 __ tst(r0, Operand(kSmiTagMask)); | 4367 __ tst(possible_function, Operand(kSmiTagMask)); |
4375 false_target()->Branch(eq); | 4368 false_target()->Branch(eq); |
4376 Register map_reg = r2; | 4369 Register map_reg = VirtualFrame::scratch0(); |
4377 __ CompareObjectType(r0, map_reg, r1, JS_FUNCTION_TYPE); | 4370 Register scratch = VirtualFrame::scratch1(); |
4371 __ CompareObjectType(possible_function, map_reg, scratch, JS_FUNCTION_TYPE); | |
4378 cc_reg_ = eq; | 4372 cc_reg_ = eq; |
4379 } | 4373 } |
4380 | 4374 |
4381 | 4375 |
4382 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { | 4376 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { |
4383 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4384 ASSERT(args->length() == 1); | 4377 ASSERT(args->length() == 1); |
4385 LoadAndSpill(args->at(0)); | 4378 Load(args->at(0)); |
4386 frame_->EmitPop(r0); | 4379 Register possible_undetectable = frame_->PopToRegister(); |
4387 __ tst(r0, Operand(kSmiTagMask)); | 4380 __ tst(possible_undetectable, Operand(kSmiTagMask)); |
4388 false_target()->Branch(eq); | 4381 false_target()->Branch(eq); |
4389 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4382 Register scratch = VirtualFrame::scratch0(); |
4390 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 4383 __ ldr(scratch, |
4391 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4384 FieldMemOperand(possible_undetectable, HeapObject::kMapOffset)); |
4385 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | |
4386 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); | |
4392 cc_reg_ = ne; | 4387 cc_reg_ = ne; |
4393 } | 4388 } |
4394 | 4389 |
4395 | 4390 |
4396 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { | 4391 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { |
4397 ASSERT(args->length() == 0); | 4392 ASSERT(args->length() == 0); |
4398 | 4393 |
4399 Register scratch0 = VirtualFrame::scratch0(); | 4394 Register scratch0 = VirtualFrame::scratch0(); |
4400 Register scratch1 = VirtualFrame::scratch1(); | 4395 Register scratch1 = VirtualFrame::scratch1(); |
4401 // Get the frame pointer for the calling frame. | 4396 // Get the frame pointer for the calling frame. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4442 frame_->EmitPush(tos); | 4437 frame_->EmitPush(tos); |
4443 } | 4438 } |
4444 | 4439 |
4445 | 4440 |
4446 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { | 4441 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { |
4447 VirtualFrame::SpilledScope spilled_scope(frame_); | 4442 VirtualFrame::SpilledScope spilled_scope(frame_); |
4448 ASSERT(args->length() == 1); | 4443 ASSERT(args->length() == 1); |
4449 | 4444 |
4450 // Satisfy contract with ArgumentsAccessStub: | 4445 // Satisfy contract with ArgumentsAccessStub: |
4451 // Load the key into r1 and the formal parameters count into r0. | 4446 // Load the key into r1 and the formal parameters count into r0. |
4452 LoadAndSpill(args->at(0)); | 4447 Load(args->at(0)); |
4453 frame_->EmitPop(r1); | 4448 frame_->EmitPop(r1); |
4454 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); | 4449 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); |
4455 | 4450 |
4456 // Call the shared stub to get to arguments[key]. | 4451 // Call the shared stub to get to arguments[key]. |
4457 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 4452 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
4458 frame_->CallStub(&stub, 0); | 4453 frame_->CallStub(&stub, 0); |
4459 frame_->EmitPush(r0); | 4454 frame_->EmitPush(r0); |
4460 } | 4455 } |
4461 | 4456 |
4462 | 4457 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4514 } | 4509 } |
4515 | 4510 |
4516 | 4511 |
4517 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { | 4512 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { |
4518 ASSERT_EQ(2, args->length()); | 4513 ASSERT_EQ(2, args->length()); |
4519 | 4514 |
4520 Load(args->at(0)); | 4515 Load(args->at(0)); |
4521 Load(args->at(1)); | 4516 Load(args->at(1)); |
4522 | 4517 |
4523 StringAddStub stub(NO_STRING_ADD_FLAGS); | 4518 StringAddStub stub(NO_STRING_ADD_FLAGS); |
4519 frame_->SpillAll(); | |
Søren Thygesen Gjesse
2010/05/28 10:15:47
How about moving the SpillAll to CallStub?
Erik Corry
2010/05/28 11:24:12
CallStub is common for the light targets and I wan
| |
4524 frame_->CallStub(&stub, 2); | 4520 frame_->CallStub(&stub, 2); |
4525 frame_->EmitPush(r0); | 4521 frame_->EmitPush(r0); |
4526 } | 4522 } |
4527 | 4523 |
4528 | 4524 |
4529 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { | 4525 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { |
4530 ASSERT_EQ(3, args->length()); | 4526 ASSERT_EQ(3, args->length()); |
4531 | 4527 |
4532 Load(args->at(0)); | 4528 Load(args->at(0)); |
4533 Load(args->at(1)); | 4529 Load(args->at(1)); |
4534 Load(args->at(2)); | 4530 Load(args->at(2)); |
4535 | 4531 |
4536 SubStringStub stub; | 4532 SubStringStub stub; |
4533 frame_->SpillAll(); | |
4537 frame_->CallStub(&stub, 3); | 4534 frame_->CallStub(&stub, 3); |
4538 frame_->EmitPush(r0); | 4535 frame_->EmitPush(r0); |
4539 } | 4536 } |
4540 | 4537 |
4541 | 4538 |
4542 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { | 4539 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { |
4543 ASSERT_EQ(2, args->length()); | 4540 ASSERT_EQ(2, args->length()); |
4544 | 4541 |
4545 Load(args->at(0)); | 4542 Load(args->at(0)); |
4546 Load(args->at(1)); | 4543 Load(args->at(1)); |
4547 | 4544 |
4548 StringCompareStub stub; | 4545 StringCompareStub stub; |
4546 frame_->SpillAll(); | |
4549 frame_->CallStub(&stub, 2); | 4547 frame_->CallStub(&stub, 2); |
4550 frame_->EmitPush(r0); | 4548 frame_->EmitPush(r0); |
4551 } | 4549 } |
4552 | 4550 |
4553 | 4551 |
4554 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { | 4552 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
4555 ASSERT_EQ(4, args->length()); | 4553 ASSERT_EQ(4, args->length()); |
4556 | 4554 |
4557 Load(args->at(0)); | 4555 Load(args->at(0)); |
4558 Load(args->at(1)); | 4556 Load(args->at(1)); |
4559 Load(args->at(2)); | 4557 Load(args->at(2)); |
4560 Load(args->at(3)); | 4558 Load(args->at(3)); |
4561 RegExpExecStub stub; | 4559 RegExpExecStub stub; |
4560 frame_->SpillAll(); | |
4562 frame_->CallStub(&stub, 4); | 4561 frame_->CallStub(&stub, 4); |
4563 frame_->EmitPush(r0); | 4562 frame_->EmitPush(r0); |
4564 } | 4563 } |
4565 | 4564 |
4566 | 4565 |
4567 void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) { | 4566 void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) { |
4568 // No stub. This code only occurs a few times in regexp.js. | 4567 // No stub. This code only occurs a few times in regexp.js. |
4569 const int kMaxInlineLength = 100; | 4568 const int kMaxInlineLength = 100; |
4570 ASSERT_EQ(3, args->length()); | 4569 ASSERT_EQ(3, args->length()); |
4571 Load(args->at(0)); // Size of array, smi. | 4570 Load(args->at(0)); // Size of array, smi. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4686 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { | 4685 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { |
4687 ASSERT_EQ(2, args->length()); | 4686 ASSERT_EQ(2, args->length()); |
4688 | 4687 |
4689 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 4688 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
4690 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 4689 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
4691 | 4690 |
4692 Handle<FixedArray> jsfunction_result_caches( | 4691 Handle<FixedArray> jsfunction_result_caches( |
4693 Top::global_context()->jsfunction_result_caches()); | 4692 Top::global_context()->jsfunction_result_caches()); |
4694 if (jsfunction_result_caches->length() <= cache_id) { | 4693 if (jsfunction_result_caches->length() <= cache_id) { |
4695 __ Abort("Attempt to use undefined cache."); | 4694 __ Abort("Attempt to use undefined cache."); |
4696 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 4695 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); |
4697 frame_->EmitPush(r0); | |
4698 return; | 4696 return; |
4699 } | 4697 } |
4700 | 4698 |
4701 Load(args->at(1)); | 4699 Load(args->at(1)); |
4700 | |
4701 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4702 | |
4702 frame_->EmitPop(r2); | 4703 frame_->EmitPop(r2); |
4703 | 4704 |
4704 __ ldr(r1, ContextOperand(cp, Context::GLOBAL_INDEX)); | 4705 __ ldr(r1, ContextOperand(cp, Context::GLOBAL_INDEX)); |
4705 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset)); | 4706 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset)); |
4706 __ ldr(r1, ContextOperand(r1, Context::JSFUNCTION_RESULT_CACHES_INDEX)); | 4707 __ ldr(r1, ContextOperand(r1, Context::JSFUNCTION_RESULT_CACHES_INDEX)); |
4707 __ ldr(r1, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(cache_id))); | 4708 __ ldr(r1, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(cache_id))); |
4708 | 4709 |
4709 DeferredSearchCache* deferred = new DeferredSearchCache(r0, r1, r2); | 4710 DeferredSearchCache* deferred = new DeferredSearchCache(r0, r1, r2); |
4710 | 4711 |
4711 const int kFingerOffset = | 4712 const int kFingerOffset = |
(...skipping 15 matching lines...) Expand all Loading... | |
4727 } | 4728 } |
4728 | 4729 |
4729 | 4730 |
4730 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { | 4731 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { |
4731 ASSERT_EQ(args->length(), 1); | 4732 ASSERT_EQ(args->length(), 1); |
4732 | 4733 |
4733 // Load the argument on the stack and jump to the runtime. | 4734 // Load the argument on the stack and jump to the runtime. |
4734 Load(args->at(0)); | 4735 Load(args->at(0)); |
4735 | 4736 |
4736 NumberToStringStub stub; | 4737 NumberToStringStub stub; |
4738 frame_->SpillAll(); | |
4737 frame_->CallStub(&stub, 1); | 4739 frame_->CallStub(&stub, 1); |
4738 frame_->EmitPush(r0); | 4740 frame_->EmitPush(r0); |
4739 } | 4741 } |
4740 | 4742 |
4741 | 4743 |
4742 class DeferredSwapElements: public DeferredCode { | 4744 class DeferredSwapElements: public DeferredCode { |
4743 public: | 4745 public: |
4744 DeferredSwapElements(Register object, Register index1, Register index2) | 4746 DeferredSwapElements(Register object, Register index1, Register index2) |
4745 : object_(object), index1_(index1), index2_(index2) { | 4747 : object_(object), index1_(index1), index2_(index2) { |
4746 set_comment("[ DeferredSwapElements"); | 4748 set_comment("[ DeferredSwapElements"); |
(...skipping 16 matching lines...) Expand all Loading... | |
4763 | 4765 |
4764 void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) { | 4766 void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) { |
4765 Comment cmnt(masm_, "[ GenerateSwapElements"); | 4767 Comment cmnt(masm_, "[ GenerateSwapElements"); |
4766 | 4768 |
4767 ASSERT_EQ(3, args->length()); | 4769 ASSERT_EQ(3, args->length()); |
4768 | 4770 |
4769 Load(args->at(0)); | 4771 Load(args->at(0)); |
4770 Load(args->at(1)); | 4772 Load(args->at(1)); |
4771 Load(args->at(2)); | 4773 Load(args->at(2)); |
4772 | 4774 |
4775 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4776 | |
4773 Register index2 = r2; | 4777 Register index2 = r2; |
4774 Register index1 = r1; | 4778 Register index1 = r1; |
4775 Register object = r0; | 4779 Register object = r0; |
4776 Register tmp1 = r3; | 4780 Register tmp1 = r3; |
4777 Register tmp2 = r4; | 4781 Register tmp2 = r4; |
4778 | 4782 |
4779 frame_->EmitPop(index2); | 4783 frame_->EmitPop(index2); |
4780 frame_->EmitPop(index1); | 4784 frame_->EmitPop(index1); |
4781 frame_->EmitPop(object); | 4785 frame_->EmitPop(object); |
4782 | 4786 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4887 Register rhs = frame_->PopToRegister(lhs); | 4891 Register rhs = frame_->PopToRegister(lhs); |
4888 __ cmp(lhs, rhs); | 4892 __ cmp(lhs, rhs); |
4889 cc_reg_ = eq; | 4893 cc_reg_ = eq; |
4890 } | 4894 } |
4891 | 4895 |
4892 | 4896 |
4893 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 4897 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
4894 #ifdef DEBUG | 4898 #ifdef DEBUG |
4895 int original_height = frame_->height(); | 4899 int original_height = frame_->height(); |
4896 #endif | 4900 #endif |
4897 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4898 if (CheckForInlineRuntimeCall(node)) { | 4901 if (CheckForInlineRuntimeCall(node)) { |
4899 ASSERT((has_cc() && frame_->height() == original_height) || | 4902 ASSERT((has_cc() && frame_->height() == original_height) || |
4900 (!has_cc() && frame_->height() == original_height + 1)); | 4903 (!has_cc() && frame_->height() == original_height + 1)); |
4901 return; | 4904 return; |
4902 } | 4905 } |
4903 | 4906 |
4904 ZoneList<Expression*>* args = node->arguments(); | 4907 ZoneList<Expression*>* args = node->arguments(); |
4905 Comment cmnt(masm_, "[ CallRuntime"); | 4908 Comment cmnt(masm_, "[ CallRuntime"); |
4906 Runtime::Function* function = node->function(); | 4909 Runtime::Function* function = node->function(); |
4907 | 4910 |
4908 if (function == NULL) { | 4911 if (function == NULL) { |
4909 // Prepare stack for calling JS runtime function. | 4912 // Prepare stack for calling JS runtime function. |
4910 // Push the builtins object found in the current global object. | 4913 // Push the builtins object found in the current global object. |
4911 __ ldr(r1, GlobalObject()); | 4914 Register scratch = VirtualFrame::scratch0(); |
4912 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); | 4915 __ ldr(scratch, GlobalObject()); |
4913 frame_->EmitPush(r0); | 4916 Register builtins = frame_->GetTOSRegister(); |
4917 __ ldr(builtins, FieldMemOperand(scratch, GlobalObject::kBuiltinsOffset)); | |
4918 frame_->EmitPush(builtins); | |
4914 } | 4919 } |
4915 | 4920 |
4916 // Push the arguments ("left-to-right"). | 4921 // Push the arguments ("left-to-right"). |
4917 int arg_count = args->length(); | 4922 int arg_count = args->length(); |
4918 for (int i = 0; i < arg_count; i++) { | 4923 for (int i = 0; i < arg_count; i++) { |
4919 LoadAndSpill(args->at(i)); | 4924 Load(args->at(i)); |
4920 } | 4925 } |
4921 | 4926 |
4927 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4928 | |
4922 if (function == NULL) { | 4929 if (function == NULL) { |
4923 // Call the JS runtime function. | 4930 // Call the JS runtime function. |
4924 __ mov(r2, Operand(node->name())); | 4931 __ mov(r2, Operand(node->name())); |
4925 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 4932 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
4926 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 4933 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
4927 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 4934 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
4928 __ ldr(cp, frame_->Context()); | 4935 __ ldr(cp, frame_->Context()); |
4929 frame_->EmitPush(r0); | 4936 frame_->EmitPush(r0); |
4930 } else { | 4937 } else { |
4931 // Call the C runtime function. | 4938 // Call the C runtime function. |
(...skipping 19 matching lines...) Expand all Loading... | |
4951 true_target(), | 4958 true_target(), |
4952 true); | 4959 true); |
4953 // LoadCondition may (and usually does) leave a test and branch to | 4960 // LoadCondition may (and usually does) leave a test and branch to |
4954 // be emitted by the caller. In that case, negate the condition. | 4961 // be emitted by the caller. In that case, negate the condition. |
4955 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); | 4962 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); |
4956 | 4963 |
4957 } else if (op == Token::DELETE) { | 4964 } else if (op == Token::DELETE) { |
4958 Property* property = node->expression()->AsProperty(); | 4965 Property* property = node->expression()->AsProperty(); |
4959 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 4966 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
4960 if (property != NULL) { | 4967 if (property != NULL) { |
4961 LoadAndSpill(property->obj()); | 4968 Load(property->obj()); |
4962 LoadAndSpill(property->key()); | 4969 Load(property->key()); |
4963 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | 4970 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); |
4971 frame_->EmitPush(r0); | |
4964 | 4972 |
4965 } else if (variable != NULL) { | 4973 } else if (variable != NULL) { |
4966 Slot* slot = variable->slot(); | 4974 Slot* slot = variable->slot(); |
4967 if (variable->is_global()) { | 4975 if (variable->is_global()) { |
4968 LoadGlobal(); | 4976 LoadGlobal(); |
4969 __ mov(r0, Operand(variable->name())); | 4977 frame_->EmitPush(Operand(variable->name())); |
4978 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | |
4970 frame_->EmitPush(r0); | 4979 frame_->EmitPush(r0); |
4971 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | |
4972 | 4980 |
4973 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 4981 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
4974 // lookup the context holding the named variable | 4982 // lookup the context holding the named variable |
4975 frame_->EmitPush(cp); | 4983 frame_->EmitPush(cp); |
4976 __ mov(r0, Operand(variable->name())); | 4984 frame_->EmitPush(Operand(variable->name())); |
4977 frame_->EmitPush(r0); | |
4978 frame_->CallRuntime(Runtime::kLookupContext, 2); | 4985 frame_->CallRuntime(Runtime::kLookupContext, 2); |
4979 // r0: context | 4986 // r0: context |
4980 frame_->EmitPush(r0); | 4987 frame_->EmitPush(r0); |
4981 __ mov(r0, Operand(variable->name())); | 4988 frame_->EmitPush(Operand(variable->name())); |
4989 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | |
4982 frame_->EmitPush(r0); | 4990 frame_->EmitPush(r0); |
4983 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | |
4984 | 4991 |
4985 } else { | 4992 } else { |
4986 // Default: Result of deleting non-global, not dynamically | 4993 // Default: Result of deleting non-global, not dynamically |
4987 // introduced variables is false. | 4994 // introduced variables is false. |
4988 __ LoadRoot(r0, Heap::kFalseValueRootIndex); | 4995 frame_->EmitPushRoot(Heap::kFalseValueRootIndex); |
4989 } | 4996 } |
4990 | 4997 |
4991 } else { | 4998 } else { |
4992 // Default: Result of deleting expressions is true. | 4999 // Default: Result of deleting expressions is true. |
4993 LoadAndSpill(node->expression()); // may have side-effects | 5000 Load(node->expression()); // may have side-effects |
4994 frame_->Drop(); | 5001 frame_->Drop(); |
4995 __ LoadRoot(r0, Heap::kTrueValueRootIndex); | 5002 frame_->EmitPushRoot(Heap::kTrueValueRootIndex); |
4996 } | 5003 } |
4997 frame_->EmitPush(r0); | |
4998 | 5004 |
4999 } else if (op == Token::TYPEOF) { | 5005 } else if (op == Token::TYPEOF) { |
5000 // Special case for loading the typeof expression; see comment on | 5006 // Special case for loading the typeof expression; see comment on |
5001 // LoadTypeofExpression(). | 5007 // LoadTypeofExpression(). |
5002 LoadTypeofExpression(node->expression()); | 5008 LoadTypeofExpression(node->expression()); |
5003 frame_->CallRuntime(Runtime::kTypeof, 1); | 5009 frame_->CallRuntime(Runtime::kTypeof, 1); |
5004 frame_->EmitPush(r0); // r0 has result | 5010 frame_->EmitPush(r0); // r0 has result |
5005 | 5011 |
5006 } else { | 5012 } else { |
5007 bool overwrite = | 5013 bool overwrite = |
5008 (node->expression()->AsBinaryOperation() != NULL && | 5014 (node->expression()->AsBinaryOperation() != NULL && |
5009 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5015 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5010 LoadAndSpill(node->expression()); | 5016 Load(node->expression()); |
5011 frame_->EmitPop(r0); | |
5012 switch (op) { | 5017 switch (op) { |
5013 case Token::NOT: | 5018 case Token::NOT: |
5014 case Token::DELETE: | 5019 case Token::DELETE: |
5015 case Token::TYPEOF: | 5020 case Token::TYPEOF: |
5016 UNREACHABLE(); // handled above | 5021 UNREACHABLE(); // handled above |
5017 break; | 5022 break; |
5018 | 5023 |
5019 case Token::SUB: { | 5024 case Token::SUB: { |
5025 VirtualFrame::SpilledScope spilled(frame_); | |
5026 frame_->EmitPop(r0); | |
5020 GenericUnaryOpStub stub(Token::SUB, overwrite); | 5027 GenericUnaryOpStub stub(Token::SUB, overwrite); |
5021 frame_->CallStub(&stub, 0); | 5028 frame_->CallStub(&stub, 0); |
5029 frame_->EmitPush(r0); // r0 has result | |
5022 break; | 5030 break; |
5023 } | 5031 } |
5024 | 5032 |
5025 case Token::BIT_NOT: { | 5033 case Token::BIT_NOT: { |
5026 // smi check | 5034 // smi check |
5035 VirtualFrame::SpilledScope spilled(frame_); | |
5036 frame_->EmitPop(r0); | |
5027 JumpTarget smi_label; | 5037 JumpTarget smi_label; |
5028 JumpTarget continue_label; | 5038 JumpTarget continue_label; |
5029 __ tst(r0, Operand(kSmiTagMask)); | 5039 __ tst(r0, Operand(kSmiTagMask)); |
5030 smi_label.Branch(eq); | 5040 smi_label.Branch(eq); |
5031 | 5041 |
5032 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); | 5042 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
5033 frame_->CallStub(&stub, 0); | 5043 frame_->CallStub(&stub, 0); |
5034 continue_label.Jump(); | 5044 continue_label.Jump(); |
5035 | 5045 |
5036 smi_label.Bind(); | 5046 smi_label.Bind(); |
5037 __ mvn(r0, Operand(r0)); | 5047 __ mvn(r0, Operand(r0)); |
5038 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag | 5048 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag |
5039 continue_label.Bind(); | 5049 continue_label.Bind(); |
5050 frame_->EmitPush(r0); // r0 has result | |
5040 break; | 5051 break; |
5041 } | 5052 } |
5042 | 5053 |
5043 case Token::VOID: | 5054 case Token::VOID: |
5044 // since the stack top is cached in r0, popping and then | 5055 frame_->Drop(); |
5045 // pushing a value can be done by just writing to r0. | 5056 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); |
5046 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | |
5047 break; | 5057 break; |
5048 | 5058 |
5049 case Token::ADD: { | 5059 case Token::ADD: { |
5060 VirtualFrame::SpilledScope spilled(frame_); | |
5061 frame_->EmitPop(r0); | |
5050 // Smi check. | 5062 // Smi check. |
5051 JumpTarget continue_label; | 5063 JumpTarget continue_label; |
5052 __ tst(r0, Operand(kSmiTagMask)); | 5064 __ tst(r0, Operand(kSmiTagMask)); |
5053 continue_label.Branch(eq); | 5065 continue_label.Branch(eq); |
5054 frame_->EmitPush(r0); | 5066 frame_->EmitPush(r0); |
5055 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); | 5067 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); |
5056 continue_label.Bind(); | 5068 continue_label.Bind(); |
5069 frame_->EmitPush(r0); // r0 has result | |
5057 break; | 5070 break; |
5058 } | 5071 } |
5059 default: | 5072 default: |
5060 UNREACHABLE(); | 5073 UNREACHABLE(); |
5061 } | 5074 } |
5062 frame_->EmitPush(r0); // r0 has result | |
5063 } | 5075 } |
5064 ASSERT(!has_valid_frame() || | 5076 ASSERT(!has_valid_frame() || |
5065 (has_cc() && frame_->height() == original_height) || | 5077 (has_cc() && frame_->height() == original_height) || |
5066 (!has_cc() && frame_->height() == original_height + 1)); | 5078 (!has_cc() && frame_->height() == original_height + 1)); |
5067 } | 5079 } |
5068 | 5080 |
5069 | 5081 |
5070 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 5082 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
5071 #ifdef DEBUG | 5083 #ifdef DEBUG |
5072 int original_height = frame_->height(); | 5084 int original_height = frame_->height(); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5202 // section 9.2, page 30. | 5214 // section 9.2, page 30. |
5203 ToBoolean(&pop_and_continue, &exit); | 5215 ToBoolean(&pop_and_continue, &exit); |
5204 Branch(false, &exit); | 5216 Branch(false, &exit); |
5205 | 5217 |
5206 // Pop the result of evaluating the first part. | 5218 // Pop the result of evaluating the first part. |
5207 pop_and_continue.Bind(); | 5219 pop_and_continue.Bind(); |
5208 frame_->Pop(); | 5220 frame_->Pop(); |
5209 | 5221 |
5210 // Evaluate right side expression. | 5222 // Evaluate right side expression. |
5211 is_true.Bind(); | 5223 is_true.Bind(); |
5212 LoadAndSpill(node->right()); | 5224 Load(node->right()); |
5213 | 5225 |
5214 // Exit (always with a materialized value). | 5226 // Exit (always with a materialized value). |
5215 exit.Bind(); | 5227 exit.Bind(); |
5216 } else if (has_cc() || is_true.is_linked()) { | 5228 } else if (has_cc() || is_true.is_linked()) { |
5217 // The left-hand side is either (a) partially compiled to | 5229 // The left-hand side is either (a) partially compiled to |
5218 // control flow with a final branch left to emit or (b) fully | 5230 // control flow with a final branch left to emit or (b) fully |
5219 // compiled to control flow and possibly true. | 5231 // compiled to control flow and possibly true. |
5220 if (has_cc()) { | 5232 if (has_cc()) { |
5221 Branch(false, false_target()); | 5233 Branch(false, false_target()); |
5222 } | 5234 } |
(...skipping 25 matching lines...) Expand all Loading... | |
5248 // section 9.2, page 30. | 5260 // section 9.2, page 30. |
5249 ToBoolean(&exit, &pop_and_continue); | 5261 ToBoolean(&exit, &pop_and_continue); |
5250 Branch(true, &exit); | 5262 Branch(true, &exit); |
5251 | 5263 |
5252 // Pop the result of evaluating the first part. | 5264 // Pop the result of evaluating the first part. |
5253 pop_and_continue.Bind(); | 5265 pop_and_continue.Bind(); |
5254 frame_->Pop(); | 5266 frame_->Pop(); |
5255 | 5267 |
5256 // Evaluate right side expression. | 5268 // Evaluate right side expression. |
5257 is_false.Bind(); | 5269 is_false.Bind(); |
5258 LoadAndSpill(node->right()); | 5270 Load(node->right()); |
5259 | 5271 |
5260 // Exit (always with a materialized value). | 5272 // Exit (always with a materialized value). |
5261 exit.Bind(); | 5273 exit.Bind(); |
5262 } else if (has_cc() || is_false.is_linked()) { | 5274 } else if (has_cc() || is_false.is_linked()) { |
5263 // The left-hand side is either (a) partially compiled to | 5275 // The left-hand side is either (a) partially compiled to |
5264 // control flow with a final branch left to emit or (b) fully | 5276 // control flow with a final branch left to emit or (b) fully |
5265 // compiled to control flow and possibly false. | 5277 // compiled to control flow and possibly false. |
5266 if (has_cc()) { | 5278 if (has_cc()) { |
5267 Branch(true, true_target()); | 5279 Branch(true, true_target()); |
5268 } | 5280 } |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5530 case Token::GTE: | 5542 case Token::GTE: |
5531 Comparison(ge, left, right); | 5543 Comparison(ge, left, right); |
5532 break; | 5544 break; |
5533 | 5545 |
5534 case Token::EQ_STRICT: | 5546 case Token::EQ_STRICT: |
5535 Comparison(eq, left, right, true); | 5547 Comparison(eq, left, right, true); |
5536 break; | 5548 break; |
5537 | 5549 |
5538 case Token::IN: { | 5550 case Token::IN: { |
5539 VirtualFrame::SpilledScope scope(frame_); | 5551 VirtualFrame::SpilledScope scope(frame_); |
5540 LoadAndSpill(left); | 5552 Load(left); |
5541 LoadAndSpill(right); | 5553 Load(right); |
5542 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); | 5554 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); |
5543 frame_->EmitPush(r0); | 5555 frame_->EmitPush(r0); |
5544 break; | 5556 break; |
5545 } | 5557 } |
5546 | 5558 |
5547 case Token::INSTANCEOF: { | 5559 case Token::INSTANCEOF: { |
5548 VirtualFrame::SpilledScope scope(frame_); | 5560 VirtualFrame::SpilledScope scope(frame_); |
5549 LoadAndSpill(left); | 5561 Load(left); |
5550 LoadAndSpill(right); | 5562 Load(right); |
5551 InstanceofStub stub; | 5563 InstanceofStub stub; |
5552 frame_->CallStub(&stub, 2); | 5564 frame_->CallStub(&stub, 2); |
5553 // At this point if instanceof succeeded then r0 == 0. | 5565 // At this point if instanceof succeeded then r0 == 0. |
5554 __ tst(r0, Operand(r0)); | 5566 __ tst(r0, Operand(r0)); |
5555 cc_reg_ = eq; | 5567 cc_reg_ = eq; |
5556 break; | 5568 break; |
5557 } | 5569 } |
5558 | 5570 |
5559 default: | 5571 default: |
5560 UNREACHABLE(); | 5572 UNREACHABLE(); |
(...skipping 4709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10270 __ bind(&string_add_runtime); | 10282 __ bind(&string_add_runtime); |
10271 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10283 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10272 } | 10284 } |
10273 | 10285 |
10274 | 10286 |
10275 #undef __ | 10287 #undef __ |
10276 | 10288 |
10277 } } // namespace v8::internal | 10289 } } // namespace v8::internal |
10278 | 10290 |
10279 #endif // V8_TARGET_ARCH_ARM | 10291 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |