| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 12 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
| 31 #include "register-allocator-inl.h" | 31 #include "register-allocator-inl.h" |
| 32 #include "scopes.h" | 32 #include "scopes.h" |
| 33 #include "virtual-frame-inl.h" |
| 33 | 34 |
| 34 namespace v8 { | 35 namespace v8 { |
| 35 namespace internal { | 36 namespace internal { |
| 36 | 37 |
| 37 #define __ ACCESS_MASM(masm()) | 38 #define __ ACCESS_MASM(masm()) |
| 38 | 39 |
| 39 // ------------------------------------------------------------------------- | |
| 40 // VirtualFrame implementation. | |
| 41 | |
| 42 // On entry to a function, the virtual frame already contains the receiver, | |
| 43 // the parameters, and a return address. All frame elements are in memory. | |
| 44 VirtualFrame::VirtualFrame() | |
| 45 : elements_(parameter_count() + local_count() + kPreallocatedElements), | |
| 46 stack_pointer_(parameter_count() + 1) { // 0-based index of TOS. | |
| 47 for (int i = 0; i <= stack_pointer_; i++) { | |
| 48 elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown)); | |
| 49 } | |
| 50 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { | |
| 51 register_locations_[i] = kIllegalIndex; | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 | |
| 56 void VirtualFrame::SyncElementBelowStackPointer(int index) { | 40 void VirtualFrame::SyncElementBelowStackPointer(int index) { |
| 57 // Emit code to write elements below the stack pointer to their | 41 // Emit code to write elements below the stack pointer to their |
| 58 // (already allocated) stack address. | 42 // (already allocated) stack address. |
| 59 ASSERT(index <= stack_pointer_); | 43 ASSERT(index <= stack_pointer_); |
| 60 FrameElement element = elements_[index]; | 44 FrameElement element = elements_[index]; |
| 61 ASSERT(!element.is_synced()); | 45 ASSERT(!element.is_synced()); |
| 62 switch (element.type()) { | 46 switch (element.type()) { |
| 63 case FrameElement::INVALID: | 47 case FrameElement::INVALID: |
| 64 break; | 48 break; |
| 65 | 49 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 | 155 |
| 172 void VirtualFrame::MakeMergable() { | 156 void VirtualFrame::MakeMergable() { |
| 173 for (int i = 0; i < element_count(); i++) { | 157 for (int i = 0; i < element_count(); i++) { |
| 174 FrameElement element = elements_[i]; | 158 FrameElement element = elements_[i]; |
| 175 | 159 |
| 176 // All number type information is reset to unknown for a mergable frame | 160 // All number type information is reset to unknown for a mergable frame |
| 177 // because of incoming back edges. | 161 // because of incoming back edges. |
| 178 if (element.is_constant() || element.is_copy()) { | 162 if (element.is_constant() || element.is_copy()) { |
| 179 if (element.is_synced()) { | 163 if (element.is_synced()) { |
| 180 // Just spill. | 164 // Just spill. |
| 181 elements_[i] = FrameElement::MemoryElement(NumberInfo::kUnknown); | 165 elements_[i] = FrameElement::MemoryElement(NumberInfo::Unknown()); |
| 182 } else { | 166 } else { |
| 183 // Allocate to a register. | 167 // Allocate to a register. |
| 184 FrameElement backing_element; // Invalid if not a copy. | 168 FrameElement backing_element; // Invalid if not a copy. |
| 185 if (element.is_copy()) { | 169 if (element.is_copy()) { |
| 186 backing_element = elements_[element.index()]; | 170 backing_element = elements_[element.index()]; |
| 187 } | 171 } |
| 188 Result fresh = cgen()->allocator()->Allocate(); | 172 Result fresh = cgen()->allocator()->Allocate(); |
| 189 ASSERT(fresh.is_valid()); // A register was spilled if all were in use. | 173 ASSERT(fresh.is_valid()); // A register was spilled if all were in use. |
| 190 elements_[i] = | 174 elements_[i] = |
| 191 FrameElement::RegisterElement(fresh.reg(), | 175 FrameElement::RegisterElement(fresh.reg(), |
| 192 FrameElement::NOT_SYNCED, | 176 FrameElement::NOT_SYNCED, |
| 193 NumberInfo::kUnknown); | 177 NumberInfo::Unknown()); |
| 194 Use(fresh.reg(), i); | 178 Use(fresh.reg(), i); |
| 195 | 179 |
| 196 // Emit a move. | 180 // Emit a move. |
| 197 if (element.is_constant()) { | 181 if (element.is_constant()) { |
| 198 if (cgen()->IsUnsafeSmi(element.handle())) { | 182 if (cgen()->IsUnsafeSmi(element.handle())) { |
| 199 cgen()->MoveUnsafeSmi(fresh.reg(), element.handle()); | 183 cgen()->MoveUnsafeSmi(fresh.reg(), element.handle()); |
| 200 } else { | 184 } else { |
| 201 __ Set(fresh.reg(), Immediate(element.handle())); | 185 __ Set(fresh.reg(), Immediate(element.handle())); |
| 202 } | 186 } |
| 203 } else { | 187 } else { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 216 } | 200 } |
| 217 } | 201 } |
| 218 } | 202 } |
| 219 // No need to set the copied flag --- there are no copies. | 203 // No need to set the copied flag --- there are no copies. |
| 220 } else { | 204 } else { |
| 221 // Clear the copy flag of non-constant, non-copy elements. | 205 // Clear the copy flag of non-constant, non-copy elements. |
| 222 // They cannot be copied because copies are not allowed. | 206 // They cannot be copied because copies are not allowed. |
| 223 // The copy flag is not relied on before the end of this loop, | 207 // The copy flag is not relied on before the end of this loop, |
| 224 // including when registers are spilled. | 208 // including when registers are spilled. |
| 225 elements_[i].clear_copied(); | 209 elements_[i].clear_copied(); |
| 226 elements_[i].set_number_info(NumberInfo::kUnknown); | 210 elements_[i].set_number_info(NumberInfo::Unknown()); |
| 227 } | 211 } |
| 228 } | 212 } |
| 229 } | 213 } |
| 230 | 214 |
| 231 | 215 |
| 232 void VirtualFrame::MergeTo(VirtualFrame* expected) { | 216 void VirtualFrame::MergeTo(VirtualFrame* expected) { |
| 233 Comment cmnt(masm(), "[ Merge frame"); | 217 Comment cmnt(masm(), "[ Merge frame"); |
| 234 // We should always be merging the code generator's current frame to an | 218 // We should always be merging the code generator's current frame to an |
| 235 // expected frame. | 219 // expected frame. |
| 236 ASSERT(cgen()->frame() == this); | 220 ASSERT(cgen()->frame() == this); |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, | 872 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, |
| 889 RelocInfo::Mode rmode) { | 873 RelocInfo::Mode rmode) { |
| 890 ASSERT(cgen()->HasValidEntryRegisters()); | 874 ASSERT(cgen()->HasValidEntryRegisters()); |
| 891 __ call(code, rmode); | 875 __ call(code, rmode); |
| 892 Result result = cgen()->allocator()->Allocate(eax); | 876 Result result = cgen()->allocator()->Allocate(eax); |
| 893 ASSERT(result.is_valid()); | 877 ASSERT(result.is_valid()); |
| 894 return result; | 878 return result; |
| 895 } | 879 } |
| 896 | 880 |
| 897 | 881 |
| 882 // This function assumes that the only results that could be in a_reg or b_reg |
| 883 // are a and b. Other results can be live, but must not be in a_reg or b_reg. |
| 884 void VirtualFrame::MoveResultsToRegisters(Result* a, |
| 885 Result* b, |
| 886 Register a_reg, |
| 887 Register b_reg) { |
| 888 if (a->is_register() && a->reg().is(a_reg)) { |
| 889 b->ToRegister(b_reg); |
| 890 } else if (!cgen()->allocator()->is_used(a_reg)) { |
| 891 a->ToRegister(a_reg); |
| 892 b->ToRegister(b_reg); |
| 893 } else if (cgen()->allocator()->is_used(b_reg)) { |
| 894 // a must be in b_reg, b in a_reg. |
| 895 __ xchg(a_reg, b_reg); |
| 896 // Results a and b will be invalidated, so it is ok if they are switched. |
| 897 } else { |
| 898 b->ToRegister(b_reg); |
| 899 a->ToRegister(a_reg); |
| 900 } |
| 901 a->Unuse(); |
| 902 b->Unuse(); |
| 903 } |
| 904 |
| 905 |
| 898 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { | 906 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { |
| 899 // Name and receiver are on the top of the frame. The IC expects | 907 // Name and receiver are on the top of the frame. The IC expects |
| 900 // name in ecx and receiver in eax. | 908 // name in ecx and receiver in eax. |
| 901 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | |
| 902 Result name = Pop(); | 909 Result name = Pop(); |
| 903 Result receiver = Pop(); | 910 Result receiver = Pop(); |
| 904 PrepareForCall(0, 0); // No stack arguments. | 911 PrepareForCall(0, 0); // No stack arguments. |
| 905 // Move results to the right registers: | 912 MoveResultsToRegisters(&name, &receiver, ecx, eax); |
| 906 if (name.is_register() && name.reg().is(eax)) { | 913 |
| 907 if (receiver.is_register() && receiver.reg().is(ecx)) { | 914 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 908 // Wrong registers. | |
| 909 __ xchg(eax, ecx); | |
| 910 } else { | |
| 911 // Register ecx is free for name, which frees eax for receiver. | |
| 912 name.ToRegister(ecx); | |
| 913 receiver.ToRegister(eax); | |
| 914 } | |
| 915 } else { | |
| 916 // Register eax is free for receiver, which frees ecx for name. | |
| 917 receiver.ToRegister(eax); | |
| 918 name.ToRegister(ecx); | |
| 919 } | |
| 920 name.Unuse(); | |
| 921 receiver.Unuse(); | |
| 922 return RawCallCodeObject(ic, mode); | 915 return RawCallCodeObject(ic, mode); |
| 923 } | 916 } |
| 924 | 917 |
| 925 | 918 |
| 926 Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { | 919 Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { |
| 927 // Key and receiver are on top of the frame. Put them in eax and edx. | 920 // Key and receiver are on top of the frame. Put them in eax and edx. |
| 928 Result key = Pop(); | 921 Result key = Pop(); |
| 929 Result receiver = Pop(); | 922 Result receiver = Pop(); |
| 930 PrepareForCall(0, 0); | 923 PrepareForCall(0, 0); |
| 931 | 924 MoveResultsToRegisters(&key, &receiver, eax, edx); |
| 932 if (!key.is_register() || !key.reg().is(edx)) { | |
| 933 // Register edx is available for receiver. | |
| 934 receiver.ToRegister(edx); | |
| 935 key.ToRegister(eax); | |
| 936 } else if (!receiver.is_register() || !receiver.reg().is(eax)) { | |
| 937 // Register eax is available for key. | |
| 938 key.ToRegister(eax); | |
| 939 receiver.ToRegister(edx); | |
| 940 } else { | |
| 941 __ xchg(edx, eax); | |
| 942 } | |
| 943 key.Unuse(); | |
| 944 receiver.Unuse(); | |
| 945 | 925 |
| 946 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 926 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 947 return RawCallCodeObject(ic, mode); | 927 return RawCallCodeObject(ic, mode); |
| 948 } | 928 } |
| 949 | 929 |
| 950 | 930 |
| 951 Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) { | 931 Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) { |
| 952 // Value and (if not contextual) receiver are on top of the frame. | 932 // Value and (if not contextual) receiver are on top of the frame. |
| 953 // The IC expects name in ecx, value in eax, and receiver in edx. | 933 // The IC expects name in ecx, value in eax, and receiver in edx. |
| 954 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 934 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 955 Result value = Pop(); | 935 Result value = Pop(); |
| 956 if (is_contextual) { | 936 if (is_contextual) { |
| 957 PrepareForCall(0, 0); | 937 PrepareForCall(0, 0); |
| 958 value.ToRegister(eax); | 938 value.ToRegister(eax); |
| 959 __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 939 __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 960 __ mov(ecx, name); | 940 value.Unuse(); |
| 961 } else { | 941 } else { |
| 962 Result receiver = Pop(); | 942 Result receiver = Pop(); |
| 963 PrepareForCall(0, 0); | 943 PrepareForCall(0, 0); |
| 964 | 944 MoveResultsToRegisters(&value, &receiver, eax, edx); |
| 965 if (value.is_register() && value.reg().is(edx)) { | |
| 966 if (receiver.is_register() && receiver.reg().is(eax)) { | |
| 967 // Wrong registers. | |
| 968 __ xchg(eax, edx); | |
| 969 } else { | |
| 970 // Register eax is free for value, which frees edx for receiver. | |
| 971 value.ToRegister(eax); | |
| 972 receiver.ToRegister(edx); | |
| 973 } | |
| 974 } else { | |
| 975 // Register edx is free for receiver, which guarantees eax is free for | |
| 976 // value. | |
| 977 receiver.ToRegister(edx); | |
| 978 value.ToRegister(eax); | |
| 979 } | |
| 980 } | 945 } |
| 981 __ mov(ecx, name); | 946 __ mov(ecx, name); |
| 982 value.Unuse(); | |
| 983 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); | 947 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); |
| 984 } | 948 } |
| 985 | 949 |
| 986 | 950 |
| 987 Result VirtualFrame::CallKeyedStoreIC() { | 951 Result VirtualFrame::CallKeyedStoreIC() { |
| 988 // Value, key, and receiver are on the top of the frame. The IC | 952 // Value, key, and receiver are on the top of the frame. The IC |
| 989 // expects value in eax and key and receiver on the stack. It does | 953 // expects value in eax, key in ecx, and receiver in edx. |
| 990 // not drop the key and receiver. | 954 Result value = Pop(); |
| 955 Result key = Pop(); |
| 956 Result receiver = Pop(); |
| 957 PrepareForCall(0, 0); |
| 958 if (!cgen()->allocator()->is_used(eax) || |
| 959 (value.is_register() && value.reg().is(eax))) { |
| 960 value.ToRegister(eax); // No effect if value is in eax already. |
| 961 MoveResultsToRegisters(&key, &receiver, ecx, edx); |
| 962 value.Unuse(); |
| 963 } else if (!cgen()->allocator()->is_used(ecx) || |
| 964 (key.is_register() && key.reg().is(ecx))) { |
| 965 // Receiver and/or key are in eax. |
| 966 key.ToRegister(ecx); |
| 967 MoveResultsToRegisters(&value, &receiver, eax, edx); |
| 968 key.Unuse(); |
| 969 } else if (!cgen()->allocator()->is_used(edx) || |
| 970 (receiver.is_register() && receiver.reg().is(edx))) { |
| 971 receiver.ToRegister(edx); |
| 972 MoveResultsToRegisters(&key, &value, ecx, eax); |
| 973 receiver.Unuse(); |
| 974 } else { |
| 975 // All three registers are used, and no value is in the correct place. |
| 976 // We have one of the two circular permutations of eax, ecx, edx. |
| 977 ASSERT(value.is_register()); |
| 978 if (value.reg().is(ecx)) { |
| 979 __ xchg(eax, edx); |
| 980 __ xchg(eax, ecx); |
| 981 } else { |
| 982 __ xchg(eax, ecx); |
| 983 __ xchg(eax, edx); |
| 984 } |
| 985 value.Unuse(); |
| 986 key.Unuse(); |
| 987 receiver.Unuse(); |
| 988 } |
| 989 |
| 991 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 990 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 992 Result value = Pop(); | |
| 993 PrepareForCall(2, 0); // Two stack args, neither callee-dropped. | |
| 994 value.ToRegister(eax); | |
| 995 value.Unuse(); | |
| 996 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); | 991 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); |
| 997 } | 992 } |
| 998 | 993 |
| 999 | 994 |
| 1000 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, | 995 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, |
| 1001 int arg_count, | 996 int arg_count, |
| 1002 int loop_nesting) { | 997 int loop_nesting) { |
| 1003 // Function name, arguments, and receiver are on top of the frame. | 998 // Function name, arguments, and receiver are on top of the frame. |
| 1004 // The IC expects the name in ecx and the rest on the stack and | 999 // The IC expects the name in ecx and the rest on the stack and |
| 1005 // drops them all. | 1000 // drops them all. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 } | 1055 } |
| 1061 } | 1056 } |
| 1062 | 1057 |
| 1063 | 1058 |
| 1064 Result VirtualFrame::Pop() { | 1059 Result VirtualFrame::Pop() { |
| 1065 FrameElement element = elements_.RemoveLast(); | 1060 FrameElement element = elements_.RemoveLast(); |
| 1066 int index = element_count(); | 1061 int index = element_count(); |
| 1067 ASSERT(element.is_valid()); | 1062 ASSERT(element.is_valid()); |
| 1068 | 1063 |
| 1069 // Get number type information of the result. | 1064 // Get number type information of the result. |
| 1070 NumberInfo::Type info; | 1065 NumberInfo info; |
| 1071 if (!element.is_copy()) { | 1066 if (!element.is_copy()) { |
| 1072 info = element.number_info(); | 1067 info = element.number_info(); |
| 1073 } else { | 1068 } else { |
| 1074 info = elements_[element.index()].number_info(); | 1069 info = elements_[element.index()].number_info(); |
| 1075 } | 1070 } |
| 1076 | 1071 |
| 1077 bool pop_needed = (stack_pointer_ == index); | 1072 bool pop_needed = (stack_pointer_ == index); |
| 1078 if (pop_needed) { | 1073 if (pop_needed) { |
| 1079 stack_pointer_--; | 1074 stack_pointer_--; |
| 1080 if (element.is_memory()) { | 1075 if (element.is_memory()) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1135 | 1130 |
| 1136 | 1131 |
| 1137 void VirtualFrame::EmitPop(Operand operand) { | 1132 void VirtualFrame::EmitPop(Operand operand) { |
| 1138 ASSERT(stack_pointer_ == element_count() - 1); | 1133 ASSERT(stack_pointer_ == element_count() - 1); |
| 1139 stack_pointer_--; | 1134 stack_pointer_--; |
| 1140 elements_.RemoveLast(); | 1135 elements_.RemoveLast(); |
| 1141 __ pop(operand); | 1136 __ pop(operand); |
| 1142 } | 1137 } |
| 1143 | 1138 |
| 1144 | 1139 |
| 1145 void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) { | 1140 void VirtualFrame::EmitPush(Register reg, NumberInfo info) { |
| 1146 ASSERT(stack_pointer_ == element_count() - 1); | 1141 ASSERT(stack_pointer_ == element_count() - 1); |
| 1147 elements_.Add(FrameElement::MemoryElement(info)); | 1142 elements_.Add(FrameElement::MemoryElement(info)); |
| 1148 stack_pointer_++; | 1143 stack_pointer_++; |
| 1149 __ push(reg); | 1144 __ push(reg); |
| 1150 } | 1145 } |
| 1151 | 1146 |
| 1152 | 1147 |
| 1153 void VirtualFrame::EmitPush(Operand operand, NumberInfo::Type info) { | 1148 void VirtualFrame::EmitPush(Operand operand, NumberInfo info) { |
| 1154 ASSERT(stack_pointer_ == element_count() - 1); | 1149 ASSERT(stack_pointer_ == element_count() - 1); |
| 1155 elements_.Add(FrameElement::MemoryElement(info)); | 1150 elements_.Add(FrameElement::MemoryElement(info)); |
| 1156 stack_pointer_++; | 1151 stack_pointer_++; |
| 1157 __ push(operand); | 1152 __ push(operand); |
| 1158 } | 1153 } |
| 1159 | 1154 |
| 1160 | 1155 |
| 1161 void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) { | 1156 void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) { |
| 1162 ASSERT(stack_pointer_ == element_count() - 1); | 1157 ASSERT(stack_pointer_ == element_count() - 1); |
| 1163 elements_.Add(FrameElement::MemoryElement(info)); | 1158 elements_.Add(FrameElement::MemoryElement(info)); |
| 1164 stack_pointer_++; | 1159 stack_pointer_++; |
| 1165 __ push(immediate); | 1160 __ push(immediate); |
| 1166 } | 1161 } |
| 1167 | 1162 |
| 1168 | 1163 |
| 1169 void VirtualFrame::Push(Expression* expr) { | 1164 void VirtualFrame::Push(Expression* expr) { |
| 1170 ASSERT(expr->IsTrivial()); | 1165 ASSERT(expr->IsTrivial()); |
| 1171 | 1166 |
| 1172 Literal* lit = expr->AsLiteral(); | 1167 Literal* lit = expr->AsLiteral(); |
| 1173 if (lit != NULL) { | 1168 if (lit != NULL) { |
| 1174 Push(lit->handle()); | 1169 Push(lit->handle()); |
| 1175 return; | 1170 return; |
| 1176 } | 1171 } |
| 1177 | 1172 |
| 1178 VariableProxy* proxy = expr->AsVariableProxy(); | 1173 VariableProxy* proxy = expr->AsVariableProxy(); |
| 1179 if (proxy != NULL && proxy->is_this()) { | 1174 if (proxy != NULL && proxy->is_this()) { |
| 1180 PushParameterAt(-1); | 1175 PushParameterAt(-1); |
| 1181 return; | 1176 return; |
| 1182 } | 1177 } |
| 1183 | 1178 |
| 1184 UNREACHABLE(); | 1179 UNREACHABLE(); |
| 1185 } | 1180 } |
| 1186 | 1181 |
| 1187 | 1182 |
| 1188 #undef __ | 1183 #undef __ |
| 1189 | 1184 |
| 1190 } } // namespace v8::internal | 1185 } } // namespace v8::internal |
| OLD | NEW |