Chromium Code Reviews| 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 |