Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(261)

Side by Side Diff: src/arm/codegen-arm.cc

Issue 2368001: Get rid of LoadAndSpill on ARM since Load() knows whether it is... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698