| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 masm_(new MacroAssembler(NULL, buffer_size)), | 80 masm_(new MacroAssembler(NULL, buffer_size)), |
| 81 scope_(NULL), | 81 scope_(NULL), |
| 82 frame_(NULL), | 82 frame_(NULL), |
| 83 cc_reg_(al), | 83 cc_reg_(al), |
| 84 state_(NULL), | 84 state_(NULL), |
| 85 break_stack_height_(0), | 85 break_stack_height_(0), |
| 86 function_return_is_shadowed_(false) { | 86 function_return_is_shadowed_(false) { |
| 87 } | 87 } |
| 88 | 88 |
| 89 | 89 |
| 90 void CodeGenerator::SetFrame(VirtualFrame* new_frame) { |
| 91 frame_ = new_frame; |
| 92 } |
| 93 |
| 94 |
| 95 void CodeGenerator::DeleteFrame() { |
| 96 delete frame_; |
| 97 frame_ = NULL; |
| 98 } |
| 99 |
| 100 |
| 90 // Calling conventions: | 101 // Calling conventions: |
| 91 // r0: the number of arguments | 102 // r0: the number of arguments |
| 92 // fp: frame pointer | 103 // fp: frame pointer |
| 93 // sp: stack pointer | 104 // sp: stack pointer |
| 94 // pp: caller's parameter pointer | 105 // pp: caller's parameter pointer |
| 95 // cp: callee's context | 106 // cp: callee's context |
| 96 | 107 |
| 97 void CodeGenerator::GenCode(FunctionLiteral* fun) { | 108 void CodeGenerator::GenCode(FunctionLiteral* fun) { |
| 98 ZoneList<Statement*>* body = fun->body(); | 109 ZoneList<Statement*>* body = fun->body(); |
| 99 | 110 |
| 100 // Initialize state. | 111 // Initialize state. |
| 101 ASSERT(scope_ == NULL); | 112 ASSERT(scope_ == NULL); |
| 102 scope_ = fun->scope(); | 113 scope_ = fun->scope(); |
| 103 ASSERT(frame_ == NULL); | 114 ASSERT(frame_ == NULL); |
| 104 set_frame(new VirtualFrame(this)); | 115 frame_ = new VirtualFrame(this); |
| 105 cc_reg_ = al; | 116 cc_reg_ = al; |
| 106 function_return_.set_code_generator(this); | 117 function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL); |
| 107 function_return_is_shadowed_ = false; | 118 function_return_is_shadowed_ = false; |
| 108 { | 119 { |
| 109 CodeGenState state(this); | 120 CodeGenState state(this); |
| 110 | 121 |
| 111 // Entry | 122 // Entry |
| 112 // stack: function, receiver, arguments, return address | 123 // stack: function, receiver, arguments, return address |
| 113 // r0: number of arguments | 124 // r0: number of arguments |
| 114 // sp: stack pointer | 125 // sp: stack pointer |
| 115 // fp: frame pointer | 126 // fp: frame pointer |
| 116 // pp: caller's parameter pointer | 127 // pp: caller's parameter pointer |
| (...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 | 775 |
| 765 JumpTarget exit(this); | 776 JumpTarget exit(this); |
| 766 frame_->Pop(r0); | 777 frame_->Pop(r0); |
| 767 | 778 |
| 768 switch (op) { | 779 switch (op) { |
| 769 case Token::ADD: { | 780 case Token::ADD: { |
| 770 DeferredCode* deferred = | 781 DeferredCode* deferred = |
| 771 new DeferredInlinedSmiOperation(this, op, int_value, reversed); | 782 new DeferredInlinedSmiOperation(this, op, int_value, reversed); |
| 772 | 783 |
| 773 __ add(r0, r0, Operand(value), SetCC); | 784 __ add(r0, r0, Operand(value), SetCC); |
| 774 __ b(vs, deferred->enter()); | 785 deferred->enter()->Branch(vs); |
| 775 __ tst(r0, Operand(kSmiTagMask)); | 786 __ tst(r0, Operand(kSmiTagMask)); |
| 776 __ b(ne, deferred->enter()); | 787 deferred->enter()->Branch(ne); |
| 777 __ bind(deferred->exit()); | 788 deferred->exit()->Bind(); |
| 778 break; | 789 break; |
| 779 } | 790 } |
| 780 | 791 |
| 781 case Token::SUB: { | 792 case Token::SUB: { |
| 782 DeferredCode* deferred = | 793 DeferredCode* deferred = |
| 783 new DeferredInlinedSmiOperation(this, op, int_value, reversed); | 794 new DeferredInlinedSmiOperation(this, op, int_value, reversed); |
| 784 | 795 |
| 785 if (!reversed) { | 796 if (!reversed) { |
| 786 __ sub(r0, r0, Operand(value), SetCC); | 797 __ sub(r0, r0, Operand(value), SetCC); |
| 787 } else { | 798 } else { |
| 788 __ rsb(r0, r0, Operand(value), SetCC); | 799 __ rsb(r0, r0, Operand(value), SetCC); |
| 789 } | 800 } |
| 790 __ b(vs, deferred->enter()); | 801 deferred->enter()->Branch(vs); |
| 791 __ tst(r0, Operand(kSmiTagMask)); | 802 __ tst(r0, Operand(kSmiTagMask)); |
| 792 __ b(ne, deferred->enter()); | 803 deferred->enter()->Branch(ne); |
| 793 __ bind(deferred->exit()); | 804 deferred->exit()->Bind(); |
| 794 break; | 805 break; |
| 795 } | 806 } |
| 796 | 807 |
| 797 case Token::BIT_OR: | 808 case Token::BIT_OR: |
| 798 case Token::BIT_XOR: | 809 case Token::BIT_XOR: |
| 799 case Token::BIT_AND: { | 810 case Token::BIT_AND: { |
| 800 DeferredCode* deferred = | 811 DeferredCode* deferred = |
| 801 new DeferredInlinedSmiOperation(this, op, int_value, reversed); | 812 new DeferredInlinedSmiOperation(this, op, int_value, reversed); |
| 802 __ tst(r0, Operand(kSmiTagMask)); | 813 __ tst(r0, Operand(kSmiTagMask)); |
| 803 __ b(ne, deferred->enter()); | 814 deferred->enter()->Branch(ne); |
| 804 switch (op) { | 815 switch (op) { |
| 805 case Token::BIT_OR: __ orr(r0, r0, Operand(value)); break; | 816 case Token::BIT_OR: __ orr(r0, r0, Operand(value)); break; |
| 806 case Token::BIT_XOR: __ eor(r0, r0, Operand(value)); break; | 817 case Token::BIT_XOR: __ eor(r0, r0, Operand(value)); break; |
| 807 case Token::BIT_AND: __ and_(r0, r0, Operand(value)); break; | 818 case Token::BIT_AND: __ and_(r0, r0, Operand(value)); break; |
| 808 default: UNREACHABLE(); | 819 default: UNREACHABLE(); |
| 809 } | 820 } |
| 810 __ bind(deferred->exit()); | 821 deferred->exit()->Bind(); |
| 811 break; | 822 break; |
| 812 } | 823 } |
| 813 | 824 |
| 814 case Token::SHL: | 825 case Token::SHL: |
| 815 case Token::SHR: | 826 case Token::SHR: |
| 816 case Token::SAR: { | 827 case Token::SAR: { |
| 817 if (reversed) { | 828 if (reversed) { |
| 818 __ mov(ip, Operand(value)); | 829 __ mov(ip, Operand(value)); |
| 819 frame_->EmitPush(ip); | 830 frame_->EmitPush(ip); |
| 820 frame_->EmitPush(r0); | 831 frame_->EmitPush(r0); |
| 821 GenericBinaryOperation(op); | 832 GenericBinaryOperation(op); |
| 822 | 833 |
| 823 } else { | 834 } else { |
| 824 int shift_value = int_value & 0x1f; // least significant 5 bits | 835 int shift_value = int_value & 0x1f; // least significant 5 bits |
| 825 DeferredCode* deferred = | 836 DeferredCode* deferred = |
| 826 new DeferredInlinedSmiOperation(this, op, shift_value, false); | 837 new DeferredInlinedSmiOperation(this, op, shift_value, false); |
| 827 __ tst(r0, Operand(kSmiTagMask)); | 838 __ tst(r0, Operand(kSmiTagMask)); |
| 828 __ b(ne, deferred->enter()); | 839 deferred->enter()->Branch(ne); |
| 829 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags | 840 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags |
| 830 switch (op) { | 841 switch (op) { |
| 831 case Token::SHL: { | 842 case Token::SHL: { |
| 832 __ mov(r2, Operand(r2, LSL, shift_value)); | 843 __ mov(r2, Operand(r2, LSL, shift_value)); |
| 833 // check that the *unsigned* result fits in a smi | 844 // check that the *unsigned* result fits in a smi |
| 834 __ add(r3, r2, Operand(0x40000000), SetCC); | 845 __ add(r3, r2, Operand(0x40000000), SetCC); |
| 835 __ b(mi, deferred->enter()); | 846 deferred->enter()->Branch(mi); |
| 836 break; | 847 break; |
| 837 } | 848 } |
| 838 case Token::SHR: { | 849 case Token::SHR: { |
| 839 // LSR by immediate 0 means shifting 32 bits. | 850 // LSR by immediate 0 means shifting 32 bits. |
| 840 if (shift_value != 0) { | 851 if (shift_value != 0) { |
| 841 __ mov(r2, Operand(r2, LSR, shift_value)); | 852 __ mov(r2, Operand(r2, LSR, shift_value)); |
| 842 } | 853 } |
| 843 // check that the *unsigned* result fits in a smi | 854 // check that the *unsigned* result fits in a smi |
| 844 // neither of the two high-order bits can be set: | 855 // neither of the two high-order bits can be set: |
| 845 // - 0x80000000: high bit would be lost when smi tagging | 856 // - 0x80000000: high bit would be lost when smi tagging |
| 846 // - 0x40000000: this number would convert to negative when | 857 // - 0x40000000: this number would convert to negative when |
| 847 // smi tagging these two cases can only happen with shifts | 858 // smi tagging these two cases can only happen with shifts |
| 848 // by 0 or 1 when handed a valid smi | 859 // by 0 or 1 when handed a valid smi |
| 849 __ and_(r3, r2, Operand(0xc0000000), SetCC); | 860 __ and_(r3, r2, Operand(0xc0000000), SetCC); |
| 850 __ b(ne, deferred->enter()); | 861 deferred->enter()->Branch(ne); |
| 851 break; | 862 break; |
| 852 } | 863 } |
| 853 case Token::SAR: { | 864 case Token::SAR: { |
| 854 if (shift_value != 0) { | 865 if (shift_value != 0) { |
| 855 // ASR by immediate 0 means shifting 32 bits. | 866 // ASR by immediate 0 means shifting 32 bits. |
| 856 __ mov(r2, Operand(r2, ASR, shift_value)); | 867 __ mov(r2, Operand(r2, ASR, shift_value)); |
| 857 } | 868 } |
| 858 break; | 869 break; |
| 859 } | 870 } |
| 860 default: UNREACHABLE(); | 871 default: UNREACHABLE(); |
| 861 } | 872 } |
| 862 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); | 873 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); |
| 863 __ bind(deferred->exit()); | 874 deferred->exit()->Bind(); |
| 864 } | 875 } |
| 865 break; | 876 break; |
| 866 } | 877 } |
| 867 | 878 |
| 868 default: | 879 default: |
| 869 if (!reversed) { | 880 if (!reversed) { |
| 870 frame_->EmitPush(r0); | 881 frame_->EmitPush(r0); |
| 871 __ mov(r0, Operand(value)); | 882 __ mov(r0, Operand(value)); |
| 872 frame_->EmitPush(r0); | 883 frame_->EmitPush(r0); |
| 873 } else { | 884 } else { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 | 1015 |
| 1005 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 1016 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 1006 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { | 1017 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { |
| 1007 Visit(statements->at(i)); | 1018 Visit(statements->at(i)); |
| 1008 } | 1019 } |
| 1009 } | 1020 } |
| 1010 | 1021 |
| 1011 | 1022 |
| 1012 void CodeGenerator::VisitBlock(Block* node) { | 1023 void CodeGenerator::VisitBlock(Block* node) { |
| 1013 Comment cmnt(masm_, "[ Block"); | 1024 Comment cmnt(masm_, "[ Block"); |
| 1014 CodeForStatement(node); | 1025 CodeForStatementPosition(node); |
| 1015 node->set_break_stack_height(break_stack_height_); | 1026 node->set_break_stack_height(break_stack_height_); |
| 1016 node->break_target()->set_code_generator(this); | 1027 node->break_target()->Initialize(this); |
| 1017 VisitStatements(node->statements()); | 1028 VisitStatements(node->statements()); |
| 1018 if (node->break_target()->is_linked()) { | 1029 node->break_target()->Bind(); |
| 1019 node->break_target()->Bind(); | |
| 1020 } | |
| 1021 } | 1030 } |
| 1022 | 1031 |
| 1023 | 1032 |
| 1024 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1033 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 1025 __ mov(r0, Operand(pairs)); | 1034 __ mov(r0, Operand(pairs)); |
| 1026 frame_->EmitPush(r0); | 1035 frame_->EmitPush(r0); |
| 1027 frame_->EmitPush(cp); | 1036 frame_->EmitPush(cp); |
| 1028 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); | 1037 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); |
| 1029 frame_->EmitPush(r0); | 1038 frame_->EmitPush(r0); |
| 1030 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 1039 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); |
| 1031 // The result is discarded. | 1040 // The result is discarded. |
| 1032 } | 1041 } |
| 1033 | 1042 |
| 1034 | 1043 |
| 1035 void CodeGenerator::VisitDeclaration(Declaration* node) { | 1044 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 1036 Comment cmnt(masm_, "[ Declaration"); | 1045 Comment cmnt(masm_, "[ Declaration"); |
| 1037 CodeForStatement(node); | 1046 CodeForStatementPosition(node); |
| 1038 Variable* var = node->proxy()->var(); | 1047 Variable* var = node->proxy()->var(); |
| 1039 ASSERT(var != NULL); // must have been resolved | 1048 ASSERT(var != NULL); // must have been resolved |
| 1040 Slot* slot = var->slot(); | 1049 Slot* slot = var->slot(); |
| 1041 | 1050 |
| 1042 // If it was not possible to allocate the variable at compile time, | 1051 // If it was not possible to allocate the variable at compile time, |
| 1043 // we need to "declare" it at runtime to make sure it actually | 1052 // we need to "declare" it at runtime to make sure it actually |
| 1044 // exists in the local context. | 1053 // exists in the local context. |
| 1045 if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1054 if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 1046 // Variables with a "LOOKUP" slot were introduced as non-locals | 1055 // Variables with a "LOOKUP" slot were introduced as non-locals |
| 1047 // during variable resolution and must have mode DYNAMIC. | 1056 // during variable resolution and must have mode DYNAMIC. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1093 // safe to pop the value lying on top of the reference before unloading | 1102 // safe to pop the value lying on top of the reference before unloading |
| 1094 // the reference itself (which preserves the top of stack) because we | 1103 // the reference itself (which preserves the top of stack) because we |
| 1095 // know it is a zero-sized reference. | 1104 // know it is a zero-sized reference. |
| 1096 frame_->Drop(); | 1105 frame_->Drop(); |
| 1097 } | 1106 } |
| 1098 } | 1107 } |
| 1099 | 1108 |
| 1100 | 1109 |
| 1101 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1110 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
| 1102 Comment cmnt(masm_, "[ ExpressionStatement"); | 1111 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 1103 CodeForStatement(node); | 1112 CodeForStatementPosition(node); |
| 1104 Expression* expression = node->expression(); | 1113 Expression* expression = node->expression(); |
| 1105 expression->MarkAsStatement(); | 1114 expression->MarkAsStatement(); |
| 1106 Load(expression); | 1115 Load(expression); |
| 1107 frame_->Drop(); | 1116 frame_->Drop(); |
| 1108 } | 1117 } |
| 1109 | 1118 |
| 1110 | 1119 |
| 1111 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1120 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
| 1112 Comment cmnt(masm_, "// EmptyStatement"); | 1121 Comment cmnt(masm_, "// EmptyStatement"); |
| 1113 CodeForStatement(node); | 1122 CodeForStatementPosition(node); |
| 1114 // nothing to do | 1123 // nothing to do |
| 1115 } | 1124 } |
| 1116 | 1125 |
| 1117 | 1126 |
| 1118 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 1127 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
| 1119 Comment cmnt(masm_, "[ IfStatement"); | 1128 Comment cmnt(masm_, "[ IfStatement"); |
| 1120 // Generate different code depending on which parts of the if statement | 1129 // Generate different code depending on which parts of the if statement |
| 1121 // are present or not. | 1130 // are present or not. |
| 1122 bool has_then_stm = node->HasThenStatement(); | 1131 bool has_then_stm = node->HasThenStatement(); |
| 1123 bool has_else_stm = node->HasElseStatement(); | 1132 bool has_else_stm = node->HasElseStatement(); |
| 1124 | 1133 |
| 1125 CodeForStatement(node); | 1134 CodeForStatementPosition(node); |
| 1126 | 1135 |
| 1127 JumpTarget exit(this); | 1136 JumpTarget exit(this); |
| 1128 if (has_then_stm && has_else_stm) { | 1137 if (has_then_stm && has_else_stm) { |
| 1129 Comment cmnt(masm_, "[ IfThenElse"); | 1138 Comment cmnt(masm_, "[ IfThenElse"); |
| 1130 JumpTarget then(this); | 1139 JumpTarget then(this); |
| 1131 JumpTarget else_(this); | 1140 JumpTarget else_(this); |
| 1132 // if (cond) | 1141 // if (cond) |
| 1133 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); | 1142 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); |
| 1134 if (frame_ != NULL) { | 1143 if (frame_ != NULL) { |
| 1135 Branch(false, &else_); | 1144 Branch(false, &else_); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 | 1209 |
| 1201 | 1210 |
| 1202 void CodeGenerator::CleanStack(int num_bytes) { | 1211 void CodeGenerator::CleanStack(int num_bytes) { |
| 1203 ASSERT(num_bytes % kPointerSize == 0); | 1212 ASSERT(num_bytes % kPointerSize == 0); |
| 1204 frame_->Drop(num_bytes / kPointerSize); | 1213 frame_->Drop(num_bytes / kPointerSize); |
| 1205 } | 1214 } |
| 1206 | 1215 |
| 1207 | 1216 |
| 1208 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 1217 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { |
| 1209 Comment cmnt(masm_, "[ ContinueStatement"); | 1218 Comment cmnt(masm_, "[ ContinueStatement"); |
| 1210 CodeForStatement(node); | 1219 CodeForStatementPosition(node); |
| 1211 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1220 CleanStack(break_stack_height_ - node->target()->break_stack_height()); |
| 1212 node->target()->continue_target()->Jump(); | 1221 node->target()->continue_target()->Jump(); |
| 1213 } | 1222 } |
| 1214 | 1223 |
| 1215 | 1224 |
| 1216 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 1225 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
| 1217 Comment cmnt(masm_, "[ BreakStatement"); | 1226 Comment cmnt(masm_, "[ BreakStatement"); |
| 1218 CodeForStatement(node); | 1227 CodeForStatementPosition(node); |
| 1219 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1228 CleanStack(break_stack_height_ - node->target()->break_stack_height()); |
| 1220 node->target()->break_target()->Jump(); | 1229 node->target()->break_target()->Jump(); |
| 1221 } | 1230 } |
| 1222 | 1231 |
| 1223 | 1232 |
| 1224 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 1233 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
| 1225 Comment cmnt(masm_, "[ ReturnStatement"); | 1234 Comment cmnt(masm_, "[ ReturnStatement"); |
| 1226 CodeForStatement(node); | 1235 CodeForStatementPosition(node); |
| 1227 Load(node->expression()); | 1236 Load(node->expression()); |
| 1228 // Move the function result into r0. | 1237 // Move the function result into r0. |
| 1229 frame_->Pop(r0); | 1238 frame_->Pop(r0); |
| 1230 | 1239 |
| 1231 function_return_.Jump(); | 1240 function_return_.Jump(); |
| 1232 } | 1241 } |
| 1233 | 1242 |
| 1234 | 1243 |
| 1235 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1244 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
| 1236 Comment cmnt(masm_, "[ WithEnterStatement"); | 1245 Comment cmnt(masm_, "[ WithEnterStatement"); |
| 1237 CodeForStatement(node); | 1246 CodeForStatementPosition(node); |
| 1238 Load(node->expression()); | 1247 Load(node->expression()); |
| 1239 if (node->is_catch_block()) { | 1248 if (node->is_catch_block()) { |
| 1240 frame_->CallRuntime(Runtime::kPushCatchContext, 1); | 1249 frame_->CallRuntime(Runtime::kPushCatchContext, 1); |
| 1241 } else { | 1250 } else { |
| 1242 frame_->CallRuntime(Runtime::kPushContext, 1); | 1251 frame_->CallRuntime(Runtime::kPushContext, 1); |
| 1243 } | 1252 } |
| 1244 if (kDebug) { | 1253 if (kDebug) { |
| 1245 JumpTarget verified_true(this); | 1254 JumpTarget verified_true(this); |
| 1246 __ cmp(r0, Operand(cp)); | 1255 __ cmp(r0, Operand(cp)); |
| 1247 verified_true.Branch(eq); | 1256 verified_true.Branch(eq); |
| 1248 __ stop("PushContext: r0 is expected to be the same as cp"); | 1257 __ stop("PushContext: r0 is expected to be the same as cp"); |
| 1249 verified_true.Bind(); | 1258 verified_true.Bind(); |
| 1250 } | 1259 } |
| 1251 // Update context local. | 1260 // Update context local. |
| 1252 __ str(cp, frame_->Context()); | 1261 __ str(cp, frame_->Context()); |
| 1253 } | 1262 } |
| 1254 | 1263 |
| 1255 | 1264 |
| 1256 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 1265 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
| 1257 Comment cmnt(masm_, "[ WithExitStatement"); | 1266 Comment cmnt(masm_, "[ WithExitStatement"); |
| 1258 CodeForStatement(node); | 1267 CodeForStatementPosition(node); |
| 1259 // Pop context. | 1268 // Pop context. |
| 1260 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); | 1269 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); |
| 1261 // Update context local. | 1270 // Update context local. |
| 1262 __ str(cp, frame_->Context()); | 1271 __ str(cp, frame_->Context()); |
| 1263 } | 1272 } |
| 1264 | 1273 |
| 1265 | 1274 |
| 1266 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 1275 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { |
| 1267 return kFastSwitchMaxOverheadFactor; | 1276 return kFastSwitchMaxOverheadFactor; |
| 1268 } | 1277 } |
| 1269 | 1278 |
| 1270 int CodeGenerator::FastCaseSwitchMinCaseCount() { | 1279 int CodeGenerator::FastCaseSwitchMinCaseCount() { |
| 1271 return kFastSwitchMinCaseCount; | 1280 return kFastSwitchMinCaseCount; |
| 1272 } | 1281 } |
| 1273 | 1282 |
| 1274 | 1283 |
| 1275 void CodeGenerator::GenerateFastCaseSwitchJumpTable( | 1284 void CodeGenerator::GenerateFastCaseSwitchJumpTable( |
| 1276 SwitchStatement* node, | 1285 SwitchStatement* node, |
| 1277 int min_index, | 1286 int min_index, |
| 1278 int range, | 1287 int range, |
| 1279 JumpTarget* fail_label, | 1288 Label* default_label, |
| 1280 Vector<JumpTarget*> case_targets, | 1289 Vector<Label*> case_targets, |
| 1281 Vector<JumpTarget> case_labels) { | 1290 Vector<Label> case_labels) { |
| 1282 | 1291 |
| 1283 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); | 1292 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); |
| 1284 | 1293 |
| 1285 frame_->Pop(r0); | 1294 frame_->Pop(r0); |
| 1286 | 1295 |
| 1287 // Test for a Smi value in a HeapNumber. | 1296 // Test for a Smi value in a HeapNumber. |
| 1288 JumpTarget is_smi(this); | 1297 JumpTarget is_smi(this); |
| 1289 __ tst(r0, Operand(kSmiTagMask)); | 1298 __ tst(r0, Operand(kSmiTagMask)); |
| 1290 is_smi.Branch(eq); | 1299 is_smi.Branch(eq); |
| 1291 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag)); | 1300 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag)); |
| 1292 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag)); | 1301 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag)); |
| 1293 __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); | 1302 __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); |
| 1294 fail_label->Branch(ne); | 1303 __ b(ne, default_label); |
| 1295 frame_->EmitPush(r0); | 1304 frame_->EmitPush(r0); |
| 1296 frame_->CallRuntime(Runtime::kNumberToSmi, 1); | 1305 frame_->CallRuntime(Runtime::kNumberToSmi, 1); |
| 1297 is_smi.Bind(); | 1306 is_smi.Bind(); |
| 1298 | 1307 |
| 1299 if (min_index != 0) { | 1308 if (min_index != 0) { |
| 1300 // Small positive numbers can be immediate operands. | 1309 // Small positive numbers can be immediate operands. |
| 1301 if (min_index < 0) { | 1310 if (min_index < 0) { |
| 1302 // If min_index is Smi::kMinValue, -min_index is not a Smi. | 1311 // If min_index is Smi::kMinValue, -min_index is not a Smi. |
| 1303 if (Smi::IsValid(-min_index)) { | 1312 if (Smi::IsValid(-min_index)) { |
| 1304 __ add(r0, r0, Operand(Smi::FromInt(-min_index))); | 1313 __ add(r0, r0, Operand(Smi::FromInt(-min_index))); |
| 1305 } else { | 1314 } else { |
| 1306 __ add(r0, r0, Operand(Smi::FromInt(-min_index - 1))); | 1315 __ add(r0, r0, Operand(Smi::FromInt(-min_index - 1))); |
| 1307 __ add(r0, r0, Operand(Smi::FromInt(1))); | 1316 __ add(r0, r0, Operand(Smi::FromInt(1))); |
| 1308 } | 1317 } |
| 1309 } else { | 1318 } else { |
| 1310 __ sub(r0, r0, Operand(Smi::FromInt(min_index))); | 1319 __ sub(r0, r0, Operand(Smi::FromInt(min_index))); |
| 1311 } | 1320 } |
| 1312 } | 1321 } |
| 1313 __ tst(r0, Operand(0x80000000 | kSmiTagMask)); | 1322 __ tst(r0, Operand(0x80000000 | kSmiTagMask)); |
| 1314 fail_label->Branch(ne); | 1323 __ b(ne, default_label); |
| 1315 __ cmp(r0, Operand(Smi::FromInt(range))); | 1324 __ cmp(r0, Operand(Smi::FromInt(range))); |
| 1316 fail_label->Branch(ge); | 1325 __ b(ge, default_label); |
| 1317 __ SmiJumpTable(r0, case_targets); | 1326 __ SmiJumpTable(r0, case_targets); |
| 1318 | 1327 |
| 1319 JumpTarget table_start(this); | 1328 frame_->MakeMergable(); |
| 1320 table_start.Bind(); | 1329 VirtualFrame* start_frame = new VirtualFrame(frame_); |
| 1321 // Table containing branch operations. | 1330 // Table containing branch operations. |
| 1322 for (int i = 0; i < range; i++) { | 1331 for (int i = 0; i < range; i++) { |
| 1323 case_targets[i]->Jump(); | 1332 __ jmp(case_targets[i]); |
| 1324 frame_ = new VirtualFrame(table_start.expected_frame()); | |
| 1325 } | 1333 } |
| 1326 GenerateFastCaseSwitchCases(node, case_labels, &table_start); | 1334 GenerateFastCaseSwitchCases(node, case_labels, start_frame); |
| 1335 delete start_frame; |
| 1327 } | 1336 } |
| 1328 | 1337 |
| 1329 | 1338 |
| 1330 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 1339 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
| 1331 Comment cmnt(masm_, "[ SwitchStatement"); | 1340 Comment cmnt(masm_, "[ SwitchStatement"); |
| 1332 CodeForStatement(node); | 1341 CodeForStatementPosition(node); |
| 1333 node->set_break_stack_height(break_stack_height_); | 1342 node->set_break_stack_height(break_stack_height_); |
| 1334 node->break_target()->set_code_generator(this); | 1343 node->break_target()->Initialize(this); |
| 1335 | 1344 |
| 1336 Load(node->tag()); | 1345 Load(node->tag()); |
| 1337 | |
| 1338 if (TryGenerateFastCaseSwitchStatement(node)) { | 1346 if (TryGenerateFastCaseSwitchStatement(node)) { |
| 1339 return; | 1347 return; |
| 1340 } | 1348 } |
| 1341 | 1349 |
| 1342 JumpTarget next_test(this); | 1350 JumpTarget next_test(this); |
| 1343 JumpTarget fall_through(this); | 1351 JumpTarget fall_through(this); |
| 1344 JumpTarget default_entry(this); | 1352 JumpTarget default_entry(this); |
| 1345 JumpTarget default_exit(this); | 1353 JumpTarget default_exit(this); |
| 1346 ZoneList<CaseClause*>* cases = node->cases(); | 1354 ZoneList<CaseClause*>* cases = node->cases(); |
| 1347 int length = cases->length(); | 1355 int length = cases->length(); |
| 1348 CaseClause* default_clause = NULL; | 1356 CaseClause* default_clause = NULL; |
| 1349 | 1357 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1411 } | 1419 } |
| 1412 | 1420 |
| 1413 if (node->break_target()->is_linked()) { | 1421 if (node->break_target()->is_linked()) { |
| 1414 node->break_target()->Bind(); | 1422 node->break_target()->Bind(); |
| 1415 } | 1423 } |
| 1416 } | 1424 } |
| 1417 | 1425 |
| 1418 | 1426 |
| 1419 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1427 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { |
| 1420 Comment cmnt(masm_, "[ LoopStatement"); | 1428 Comment cmnt(masm_, "[ LoopStatement"); |
| 1421 CodeForStatement(node); | 1429 CodeForStatementPosition(node); |
| 1422 node->set_break_stack_height(break_stack_height_); | 1430 node->set_break_stack_height(break_stack_height_); |
| 1423 node->break_target()->set_code_generator(this); | 1431 node->break_target()->Initialize(this); |
| 1424 node->continue_target()->set_code_generator(this); | 1432 node->continue_target()->Initialize(this); |
| 1425 | 1433 |
| 1426 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a | 1434 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a |
| 1427 // known result for the test expression, with no side effects. | 1435 // known result for the test expression, with no side effects. |
| 1428 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1436 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; |
| 1429 if (node->cond() == NULL) { | 1437 if (node->cond() == NULL) { |
| 1430 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1438 ASSERT(node->type() == LoopStatement::FOR_LOOP); |
| 1431 info = ALWAYS_TRUE; | 1439 info = ALWAYS_TRUE; |
| 1432 } else { | 1440 } else { |
| 1433 Literal* lit = node->cond()->AsLiteral(); | 1441 Literal* lit = node->cond()->AsLiteral(); |
| 1434 if (lit != NULL) { | 1442 if (lit != NULL) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 } | 1573 } |
| 1566 } else { | 1574 } else { |
| 1567 // If there is an update statement and control flow can reach it | 1575 // If there is an update statement and control flow can reach it |
| 1568 // via falling out of the body of the loop or continuing, we | 1576 // via falling out of the body of the loop or continuing, we |
| 1569 // compile the update statement. | 1577 // compile the update statement. |
| 1570 if (frame_ != NULL || node->continue_target()->is_linked()) { | 1578 if (frame_ != NULL || node->continue_target()->is_linked()) { |
| 1571 node->continue_target()->Bind(); | 1579 node->continue_target()->Bind(); |
| 1572 // Record source position of the statement as this code which is | 1580 // Record source position of the statement as this code which is |
| 1573 // after the code for the body actually belongs to the loop | 1581 // after the code for the body actually belongs to the loop |
| 1574 // statement and not the body. | 1582 // statement and not the body. |
| 1575 CodeForStatement(node); | 1583 CodeForStatementPosition(node); |
| 1576 | 1584 |
| 1577 | |
| 1578 ASSERT(node->type() == LoopStatement::FOR_LOOP); | |
| 1579 Visit(node->next()); | 1585 Visit(node->next()); |
| 1580 loop.Jump(); | 1586 loop.Jump(); |
| 1581 } | 1587 } |
| 1582 } | 1588 } |
| 1583 } | 1589 } |
| 1584 break; | 1590 break; |
| 1585 } | 1591 } |
| 1586 } | 1592 } |
| 1587 | 1593 |
| 1588 if (node->break_target()->is_linked()) { | 1594 if (node->break_target()->is_linked()) { |
| 1589 node->break_target()->Bind(); | 1595 node->break_target()->Bind(); |
| 1590 } | 1596 } |
| 1591 } | 1597 } |
| 1592 | 1598 |
| 1593 | 1599 |
| 1594 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 1600 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
| 1595 Comment cmnt(masm_, "[ ForInStatement"); | 1601 Comment cmnt(masm_, "[ ForInStatement"); |
| 1596 CodeForStatement(node); | 1602 CodeForStatementPosition(node); |
| 1597 | 1603 |
| 1598 // We keep stuff on the stack while the body is executing. | 1604 // We keep stuff on the stack while the body is executing. |
| 1599 // Record it, so that a break/continue crossing this statement | 1605 // Record it, so that a break/continue crossing this statement |
| 1600 // can restore the stack. | 1606 // can restore the stack. |
| 1601 const int kForInStackSize = 5 * kPointerSize; | 1607 const int kForInStackSize = 5 * kPointerSize; |
| 1602 break_stack_height_ += kForInStackSize; | 1608 break_stack_height_ += kForInStackSize; |
| 1603 node->set_break_stack_height(break_stack_height_); | 1609 node->set_break_stack_height(break_stack_height_); |
| 1604 node->break_target()->set_code_generator(this); | 1610 node->break_target()->Initialize(this); |
| 1605 node->continue_target()->set_code_generator(this); | 1611 node->continue_target()->Initialize(this); |
| 1606 | 1612 |
| 1607 JumpTarget primitive(this); | 1613 JumpTarget primitive(this); |
| 1608 JumpTarget jsobject(this); | 1614 JumpTarget jsobject(this); |
| 1609 JumpTarget fixed_array(this); | 1615 JumpTarget fixed_array(this); |
| 1610 JumpTarget entry(this); | 1616 JumpTarget entry(this); |
| 1611 JumpTarget end_del_check(this); | 1617 JumpTarget end_del_check(this); |
| 1612 JumpTarget cleanup(this); | 1618 JumpTarget cleanup(this); |
| 1613 JumpTarget exit(this); | 1619 JumpTarget exit(this); |
| 1614 | 1620 |
| 1615 // Get the object to enumerate over (converted to JSObject). | 1621 // Get the object to enumerate over (converted to JSObject). |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 | 1781 |
| 1776 // Exit. | 1782 // Exit. |
| 1777 exit.Bind(); | 1783 exit.Bind(); |
| 1778 | 1784 |
| 1779 break_stack_height_ -= kForInStackSize; | 1785 break_stack_height_ -= kForInStackSize; |
| 1780 } | 1786 } |
| 1781 | 1787 |
| 1782 | 1788 |
| 1783 void CodeGenerator::VisitTryCatch(TryCatch* node) { | 1789 void CodeGenerator::VisitTryCatch(TryCatch* node) { |
| 1784 Comment cmnt(masm_, "[ TryCatch"); | 1790 Comment cmnt(masm_, "[ TryCatch"); |
| 1785 CodeForStatement(node); | 1791 CodeForStatementPosition(node); |
| 1786 | 1792 |
| 1787 JumpTarget try_block(this); | 1793 JumpTarget try_block(this); |
| 1788 JumpTarget exit(this); | 1794 JumpTarget exit(this); |
| 1789 | 1795 |
| 1790 try_block.Call(); | 1796 try_block.Call(); |
| 1791 // --- Catch block --- | 1797 // --- Catch block --- |
| 1792 frame_->EmitPush(r0); | 1798 frame_->EmitPush(r0); |
| 1793 | 1799 |
| 1794 // Store the caught exception in the catch variable. | 1800 // Store the caught exception in the catch variable. |
| 1795 { Reference ref(this, node->catch_var()); | 1801 { Reference ref(this, node->catch_var()); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1875 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1881 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1876 __ ldr(sp, MemOperand(r3)); | 1882 __ ldr(sp, MemOperand(r3)); |
| 1877 frame_->Forget(frame_->height() - handler_height); | 1883 frame_->Forget(frame_->height() - handler_height); |
| 1878 | 1884 |
| 1879 __ ldr(r1, frame_->ElementAt(kNextIndex)); | 1885 __ ldr(r1, frame_->ElementAt(kNextIndex)); |
| 1880 __ str(r1, MemOperand(r3)); | 1886 __ str(r1, MemOperand(r3)); |
| 1881 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1887 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
| 1882 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 1888 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
| 1883 // Code slot popped. | 1889 // Code slot popped. |
| 1884 frame_->Forget(1); | 1890 frame_->Forget(1); |
| 1885 shadows[i]->original_target()->Jump(); | 1891 shadows[i]->other_target()->Jump(); |
| 1886 } | 1892 } |
| 1887 } | 1893 } |
| 1888 | 1894 |
| 1889 exit.Bind(); | 1895 exit.Bind(); |
| 1890 } | 1896 } |
| 1891 | 1897 |
| 1892 | 1898 |
| 1893 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 1899 void CodeGenerator::VisitTryFinally(TryFinally* node) { |
| 1894 Comment cmnt(masm_, "[ TryFinally"); | 1900 Comment cmnt(masm_, "[ TryFinally"); |
| 1895 CodeForStatement(node); | 1901 CodeForStatementPosition(node); |
| 1896 | 1902 |
| 1897 // State: Used to keep track of reason for entering the finally | 1903 // State: Used to keep track of reason for entering the finally |
| 1898 // block. Should probably be extended to hold information for | 1904 // block. Should probably be extended to hold information for |
| 1899 // break/continue from within the try block. | 1905 // break/continue from within the try block. |
| 1900 enum { FALLING, THROWING, JUMPING }; | 1906 enum { FALLING, THROWING, JUMPING }; |
| 1901 | 1907 |
| 1902 JumpTarget unlink(this); | 1908 JumpTarget unlink(this); |
| 1903 JumpTarget try_block(this); | 1909 JumpTarget try_block(this); |
| 1904 JumpTarget finally_block(this); | 1910 JumpTarget finally_block(this); |
| 1905 | 1911 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1954 if (nof_unlinks > 0) { | 1960 if (nof_unlinks > 0) { |
| 1955 unlink.Jump(); | 1961 unlink.Jump(); |
| 1956 } | 1962 } |
| 1957 } | 1963 } |
| 1958 | 1964 |
| 1959 // Generate code to set the state for the (formerly) shadowing labels that | 1965 // Generate code to set the state for the (formerly) shadowing labels that |
| 1960 // have been jumped to. | 1966 // have been jumped to. |
| 1961 for (int i = 0; i <= nof_escapes; i++) { | 1967 for (int i = 0; i <= nof_escapes; i++) { |
| 1962 if (shadows[i]->is_linked()) { | 1968 if (shadows[i]->is_linked()) { |
| 1963 shadows[i]->Bind(); | 1969 shadows[i]->Bind(); |
| 1964 if (shadows[i]->original_target() == &function_return_) { | 1970 if (shadows[i]->other_target() == &function_return_) { |
| 1965 // If this label shadowed the function return, materialize the | 1971 // If this label shadowed the function return, materialize the |
| 1966 // return value on the stack. | 1972 // return value on the stack. |
| 1967 frame_->EmitPush(r0); | 1973 frame_->EmitPush(r0); |
| 1968 } else { | 1974 } else { |
| 1969 // Fake TOS for labels that shadowed breaks and continues. | 1975 // Fake TOS for labels that shadowed breaks and continues. |
| 1970 __ mov(r0, Operand(Factory::undefined_value())); | 1976 __ mov(r0, Operand(Factory::undefined_value())); |
| 1971 frame_->EmitPush(r0); | 1977 frame_->EmitPush(r0); |
| 1972 } | 1978 } |
| 1973 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); | 1979 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); |
| 1974 unlink.Jump(); | 1980 unlink.Jump(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2016 JumpTarget exit(this); | 2022 JumpTarget exit(this); |
| 2017 // Restore state and return value or faked TOS. | 2023 // Restore state and return value or faked TOS. |
| 2018 frame_->Pop(r2); | 2024 frame_->Pop(r2); |
| 2019 frame_->Pop(r0); | 2025 frame_->Pop(r0); |
| 2020 | 2026 |
| 2021 // Generate code to jump to the right destination for all used (formerly) | 2027 // Generate code to jump to the right destination for all used (formerly) |
| 2022 // shadowing labels. | 2028 // shadowing labels. |
| 2023 for (int i = 0; i <= nof_escapes; i++) { | 2029 for (int i = 0; i <= nof_escapes; i++) { |
| 2024 if (shadows[i]->is_bound()) { | 2030 if (shadows[i]->is_bound()) { |
| 2025 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); | 2031 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); |
| 2026 if (shadows[i]->original_target() != &function_return_) { | 2032 if (shadows[i]->other_target() != &function_return_) { |
| 2027 JumpTarget next(this); | 2033 JumpTarget next(this); |
| 2028 next.Branch(ne); | 2034 next.Branch(ne); |
| 2029 shadows[i]->original_target()->Jump(); | 2035 shadows[i]->other_target()->Jump(); |
| 2030 next.Bind(); | 2036 next.Bind(); |
| 2031 } else { | 2037 } else { |
| 2032 shadows[i]->original_target()->Branch(eq); | 2038 shadows[i]->other_target()->Branch(eq); |
| 2033 } | 2039 } |
| 2034 } | 2040 } |
| 2035 } | 2041 } |
| 2036 | 2042 |
| 2037 // Check if we need to rethrow the exception. | 2043 // Check if we need to rethrow the exception. |
| 2038 __ cmp(r2, Operand(Smi::FromInt(THROWING))); | 2044 __ cmp(r2, Operand(Smi::FromInt(THROWING))); |
| 2039 exit.Branch(ne); | 2045 exit.Branch(ne); |
| 2040 | 2046 |
| 2041 // Rethrow exception. | 2047 // Rethrow exception. |
| 2042 frame_->EmitPush(r0); | 2048 frame_->EmitPush(r0); |
| 2043 frame_->CallRuntime(Runtime::kReThrow, 1); | 2049 frame_->CallRuntime(Runtime::kReThrow, 1); |
| 2044 | 2050 |
| 2045 // Done. | 2051 // Done. |
| 2046 exit.Bind(); | 2052 exit.Bind(); |
| 2047 } | 2053 } |
| 2048 } | 2054 } |
| 2049 | 2055 |
| 2050 | 2056 |
| 2051 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 2057 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
| 2052 Comment cmnt(masm_, "[ DebuggerStatament"); | 2058 Comment cmnt(masm_, "[ DebuggerStatament"); |
| 2053 CodeForStatement(node); | 2059 CodeForStatementPosition(node); |
| 2054 frame_->CallRuntime(Runtime::kDebugBreak, 0); | 2060 frame_->CallRuntime(Runtime::kDebugBreak, 0); |
| 2055 // Ignore the return value. | 2061 // Ignore the return value. |
| 2056 } | 2062 } |
| 2057 | 2063 |
| 2058 | 2064 |
| 2059 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 2065 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { |
| 2060 ASSERT(boilerplate->IsBoilerplate()); | 2066 ASSERT(boilerplate->IsBoilerplate()); |
| 2061 | 2067 |
| 2062 // Push the boilerplate on the stack. | 2068 // Push the boilerplate on the stack. |
| 2063 __ mov(r0, Operand(boilerplate)); | 2069 __ mov(r0, Operand(boilerplate)); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2255 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); | 2261 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); |
| 2256 | 2262 |
| 2257 // Load the literal at the ast saved index. | 2263 // Load the literal at the ast saved index. |
| 2258 int literal_offset = | 2264 int literal_offset = |
| 2259 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; | 2265 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
| 2260 __ ldr(r2, FieldMemOperand(r1, literal_offset)); | 2266 __ ldr(r2, FieldMemOperand(r1, literal_offset)); |
| 2261 | 2267 |
| 2262 // Check whether we need to materialize the object literal boilerplate. | 2268 // Check whether we need to materialize the object literal boilerplate. |
| 2263 // If so, jump to the deferred code. | 2269 // If so, jump to the deferred code. |
| 2264 __ cmp(r2, Operand(Factory::undefined_value())); | 2270 __ cmp(r2, Operand(Factory::undefined_value())); |
| 2265 __ b(eq, deferred->enter()); | 2271 deferred->enter()->Branch(eq); |
| 2266 __ bind(deferred->exit()); | 2272 deferred->exit()->Bind(); |
| 2267 | 2273 |
| 2268 // Push the object literal boilerplate. | 2274 // Push the object literal boilerplate. |
| 2269 frame_->EmitPush(r2); | 2275 frame_->EmitPush(r2); |
| 2270 | 2276 |
| 2271 // Clone the boilerplate object. | 2277 // Clone the boilerplate object. |
| 2272 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); | 2278 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); |
| 2273 frame_->EmitPush(r0); // save the result | 2279 frame_->EmitPush(r0); // save the result |
| 2274 // r0: cloned object literal | 2280 // r0: cloned object literal |
| 2275 | 2281 |
| 2276 for (int i = 0; i < node->properties()->length(); i++) { | 2282 for (int i = 0; i < node->properties()->length(); i++) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2358 } | 2364 } |
| 2359 | 2365 |
| 2360 | 2366 |
| 2361 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { | 2367 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
| 2362 // Call runtime routine to allocate the catch extension object and | 2368 // Call runtime routine to allocate the catch extension object and |
| 2363 // assign the exception value to the catch variable. | 2369 // assign the exception value to the catch variable. |
| 2364 Comment cmnt(masm_, "[CatchExtensionObject "); | 2370 Comment cmnt(masm_, "[CatchExtensionObject "); |
| 2365 Load(node->key()); | 2371 Load(node->key()); |
| 2366 Load(node->value()); | 2372 Load(node->value()); |
| 2367 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 2373 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
| 2368 frame_->Push(r0); | 2374 frame_->EmitPush(r0); |
| 2369 } | 2375 } |
| 2370 | 2376 |
| 2371 | 2377 |
| 2372 void CodeGenerator::VisitAssignment(Assignment* node) { | 2378 void CodeGenerator::VisitAssignment(Assignment* node) { |
| 2373 Comment cmnt(masm_, "[ Assignment"); | 2379 Comment cmnt(masm_, "[ Assignment"); |
| 2374 CodeForStatement(node); | 2380 CodeForStatementPosition(node); |
| 2375 | 2381 |
| 2376 Reference target(this, node->target()); | 2382 Reference target(this, node->target()); |
| 2377 if (target.is_illegal()) { | 2383 if (target.is_illegal()) { |
| 2378 // Fool the virtual frame into thinking that we left the assignment's | 2384 // Fool the virtual frame into thinking that we left the assignment's |
| 2379 // value on the frame. | 2385 // value on the frame. |
| 2380 __ mov(r0, Operand(Smi::FromInt(0))); | 2386 __ mov(r0, Operand(Smi::FromInt(0))); |
| 2381 frame_->EmitPush(r0); | 2387 frame_->EmitPush(r0); |
| 2382 return; | 2388 return; |
| 2383 } | 2389 } |
| 2384 | 2390 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2437 Reference property(this, node); | 2443 Reference property(this, node); |
| 2438 property.GetValue(typeof_state()); | 2444 property.GetValue(typeof_state()); |
| 2439 } | 2445 } |
| 2440 | 2446 |
| 2441 | 2447 |
| 2442 void CodeGenerator::VisitCall(Call* node) { | 2448 void CodeGenerator::VisitCall(Call* node) { |
| 2443 Comment cmnt(masm_, "[ Call"); | 2449 Comment cmnt(masm_, "[ Call"); |
| 2444 | 2450 |
| 2445 ZoneList<Expression*>* args = node->arguments(); | 2451 ZoneList<Expression*>* args = node->arguments(); |
| 2446 | 2452 |
| 2447 CodeForStatement(node); | 2453 CodeForStatementPosition(node); |
| 2448 // Standard function call. | 2454 // Standard function call. |
| 2449 | 2455 |
| 2450 // Check if the function is a variable or a property. | 2456 // Check if the function is a variable or a property. |
| 2451 Expression* function = node->expression(); | 2457 Expression* function = node->expression(); |
| 2452 Variable* var = function->AsVariableProxy()->AsVariable(); | 2458 Variable* var = function->AsVariableProxy()->AsVariable(); |
| 2453 Property* property = function->AsProperty(); | 2459 Property* property = function->AsProperty(); |
| 2454 | 2460 |
| 2455 // ------------------------------------------------------------------------ | 2461 // ------------------------------------------------------------------------ |
| 2456 // Fast-case: Use inline caching. | 2462 // Fast-case: Use inline caching. |
| 2457 // --- | 2463 // --- |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2581 void CodeGenerator::VisitCallEval(CallEval* node) { | 2587 void CodeGenerator::VisitCallEval(CallEval* node) { |
| 2582 Comment cmnt(masm_, "[ CallEval"); | 2588 Comment cmnt(masm_, "[ CallEval"); |
| 2583 | 2589 |
| 2584 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve | 2590 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve |
| 2585 // the function we need to call and the receiver of the call. | 2591 // the function we need to call and the receiver of the call. |
| 2586 // Then we call the resolved function using the given arguments. | 2592 // Then we call the resolved function using the given arguments. |
| 2587 | 2593 |
| 2588 ZoneList<Expression*>* args = node->arguments(); | 2594 ZoneList<Expression*>* args = node->arguments(); |
| 2589 Expression* function = node->expression(); | 2595 Expression* function = node->expression(); |
| 2590 | 2596 |
| 2591 CodeForStatement(node); | 2597 CodeForStatementPosition(node); |
| 2592 | 2598 |
| 2593 // Prepare stack for call to resolved function. | 2599 // Prepare stack for call to resolved function. |
| 2594 Load(function); | 2600 Load(function); |
| 2595 __ mov(r2, Operand(Factory::undefined_value())); | 2601 __ mov(r2, Operand(Factory::undefined_value())); |
| 2596 __ push(r2); // Slot for receiver | 2602 __ push(r2); // Slot for receiver |
| 2597 for (int i = 0; i < args->length(); i++) { | 2603 for (int i = 0; i < args->length(); i++) { |
| 2598 Load(args->at(i)); | 2604 Load(args->at(i)); |
| 2599 } | 2605 } |
| 2600 | 2606 |
| 2601 // Prepare stack for call to ResolvePossiblyDirectEval. | 2607 // Prepare stack for call to ResolvePossiblyDirectEval. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2618 __ str(r1, MemOperand(sp, args->length() * kPointerSize)); | 2624 __ str(r1, MemOperand(sp, args->length() * kPointerSize)); |
| 2619 | 2625 |
| 2620 // Call the function. | 2626 // Call the function. |
| 2621 CodeForSourcePosition(node->position()); | 2627 CodeForSourcePosition(node->position()); |
| 2622 | 2628 |
| 2623 CallFunctionStub call_function(args->length()); | 2629 CallFunctionStub call_function(args->length()); |
| 2624 __ CallStub(&call_function); | 2630 __ CallStub(&call_function); |
| 2625 | 2631 |
| 2626 __ ldr(cp, frame_->Context()); | 2632 __ ldr(cp, frame_->Context()); |
| 2627 // Remove the function from the stack. | 2633 // Remove the function from the stack. |
| 2628 frame_->Pop(); | 2634 frame_->Drop(); |
| 2629 frame_->Push(r0); | 2635 frame_->EmitPush(r0); |
| 2630 } | 2636 } |
| 2631 | 2637 |
| 2632 | 2638 |
| 2633 void CodeGenerator::VisitCallNew(CallNew* node) { | 2639 void CodeGenerator::VisitCallNew(CallNew* node) { |
| 2634 Comment cmnt(masm_, "[ CallNew"); | 2640 Comment cmnt(masm_, "[ CallNew"); |
| 2635 CodeForStatement(node); | 2641 CodeForStatementPosition(node); |
| 2636 | 2642 |
| 2637 // According to ECMA-262, section 11.2.2, page 44, the function | 2643 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2638 // expression in new calls must be evaluated before the | 2644 // expression in new calls must be evaluated before the |
| 2639 // arguments. This is different from ordinary calls, where the | 2645 // arguments. This is different from ordinary calls, where the |
| 2640 // actual function to call is resolved after the arguments have been | 2646 // actual function to call is resolved after the arguments have been |
| 2641 // evaluated. | 2647 // evaluated. |
| 2642 | 2648 |
| 2643 // Compute function to call and use the global object as the | 2649 // Compute function to call and use the global object as the |
| 2644 // receiver. There is no need to use the global proxy here because | 2650 // receiver. There is no need to use the global proxy here because |
| 2645 // it will always be replaced with a newly allocated object. | 2651 // it will always be replaced with a newly allocated object. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2731 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. | 2737 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. |
| 2732 ASSERT_EQ(args->length(), 3); | 2738 ASSERT_EQ(args->length(), 3); |
| 2733 #ifdef ENABLE_LOGGING_AND_PROFILING | 2739 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 2734 if (ShouldGenerateLog(args->at(0))) { | 2740 if (ShouldGenerateLog(args->at(0))) { |
| 2735 Load(args->at(1)); | 2741 Load(args->at(1)); |
| 2736 Load(args->at(2)); | 2742 Load(args->at(2)); |
| 2737 __ CallRuntime(Runtime::kLog, 2); | 2743 __ CallRuntime(Runtime::kLog, 2); |
| 2738 } | 2744 } |
| 2739 #endif | 2745 #endif |
| 2740 __ mov(r0, Operand(Factory::undefined_value())); | 2746 __ mov(r0, Operand(Factory::undefined_value())); |
| 2741 frame_->Push(r0); | 2747 frame_->EmitPush(r0); |
| 2742 } | 2748 } |
| 2743 | 2749 |
| 2744 | 2750 |
| 2745 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 2751 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
| 2746 ASSERT(args->length() == 1); | 2752 ASSERT(args->length() == 1); |
| 2747 Load(args->at(0)); | 2753 Load(args->at(0)); |
| 2748 frame_->Pop(r0); | 2754 frame_->Pop(r0); |
| 2749 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); | 2755 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); |
| 2750 cc_reg_ = eq; | 2756 cc_reg_ = eq; |
| 2751 } | 2757 } |
| (...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3394 __ tst(r0, Operand(r0)); | 3400 __ tst(r0, Operand(r0)); |
| 3395 cc_reg_ = eq; | 3401 cc_reg_ = eq; |
| 3396 break; | 3402 break; |
| 3397 | 3403 |
| 3398 default: | 3404 default: |
| 3399 UNREACHABLE(); | 3405 UNREACHABLE(); |
| 3400 } | 3406 } |
| 3401 } | 3407 } |
| 3402 | 3408 |
| 3403 | 3409 |
| 3410 #ifdef DEBUG |
| 3411 bool CodeGenerator::HasValidEntryRegisters() { return true; } |
| 3412 #endif |
| 3413 |
| 3414 |
| 3404 bool CodeGenerator::IsActualFunctionReturn(JumpTarget* target) { | 3415 bool CodeGenerator::IsActualFunctionReturn(JumpTarget* target) { |
| 3405 return (target == &function_return_ && !function_return_is_shadowed_); | 3416 return (target == &function_return_ && !function_return_is_shadowed_); |
| 3406 } | 3417 } |
| 3407 | 3418 |
| 3408 | 3419 |
| 3409 #undef __ | 3420 #undef __ |
| 3410 #define __ masm-> | 3421 #define __ masm-> |
| 3411 | 3422 |
| 3412 Handle<String> Reference::GetName() { | 3423 Handle<String> Reference::GetName() { |
| 3413 ASSERT(type_ == NAMED); | 3424 ASSERT(type_ == NAMED); |
| (...skipping 1110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4524 __ mov(r2, Operand(0)); | 4535 __ mov(r2, Operand(0)); |
| 4525 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 4536 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
| 4526 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 4537 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
| 4527 RelocInfo::CODE_TARGET); | 4538 RelocInfo::CODE_TARGET); |
| 4528 } | 4539 } |
| 4529 | 4540 |
| 4530 | 4541 |
| 4531 #undef __ | 4542 #undef __ |
| 4532 | 4543 |
| 4533 } } // namespace v8::internal | 4544 } } // namespace v8::internal |
| OLD | NEW |