OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 void VirtualFrame::DebugBreak() { | 1024 void VirtualFrame::DebugBreak() { |
1025 PrepareForCall(0, 0); | 1025 PrepareForCall(0, 0); |
1026 ASSERT(cgen()->HasValidEntryRegisters()); | 1026 ASSERT(cgen()->HasValidEntryRegisters()); |
1027 __ DebugBreak(); | 1027 __ DebugBreak(); |
1028 Result result = cgen()->allocator()->Allocate(rax); | 1028 Result result = cgen()->allocator()->Allocate(rax); |
1029 ASSERT(result.is_valid()); | 1029 ASSERT(result.is_valid()); |
1030 } | 1030 } |
1031 #endif | 1031 #endif |
1032 | 1032 |
1033 | 1033 |
| 1034 // This function assumes that the only results that could be in a_reg or b_reg |
| 1035 // are a and b. Other results can be live, but must not be in a_reg or b_reg. |
| 1036 void VirtualFrame::MoveResultsToRegisters(Result* a, |
| 1037 Result* b, |
| 1038 Register a_reg, |
| 1039 Register b_reg) { |
| 1040 ASSERT(!a_reg.is(b_reg)); |
| 1041 // Assert that cgen()->allocator()->count(a_reg) is accounted for by a and b. |
| 1042 ASSERT(cgen()->allocator()->count(a_reg) <= 2); |
| 1043 ASSERT(cgen()->allocator()->count(a_reg) != 2 || a->reg().is(a_reg)); |
| 1044 ASSERT(cgen()->allocator()->count(a_reg) != 2 || b->reg().is(a_reg)); |
| 1045 ASSERT(cgen()->allocator()->count(a_reg) != 1 || |
| 1046 (a->is_register() && a->reg().is(a_reg)) || |
| 1047 (b->is_register() && b->reg().is(a_reg))); |
| 1048 // Assert that cgen()->allocator()->count(b_reg) is accounted for by a and b. |
| 1049 ASSERT(cgen()->allocator()->count(b_reg) <= 2); |
| 1050 ASSERT(cgen()->allocator()->count(b_reg) != 2 || a->reg().is(b_reg)); |
| 1051 ASSERT(cgen()->allocator()->count(b_reg) != 2 || b->reg().is(b_reg)); |
| 1052 ASSERT(cgen()->allocator()->count(b_reg) != 1 || |
| 1053 (a->is_register() && a->reg().is(b_reg)) || |
| 1054 (b->is_register() && b->reg().is(b_reg))); |
| 1055 |
| 1056 if (a->is_register() && a->reg().is(a_reg)) { |
| 1057 b->ToRegister(b_reg); |
| 1058 } else if (!cgen()->allocator()->is_used(a_reg)) { |
| 1059 a->ToRegister(a_reg); |
| 1060 b->ToRegister(b_reg); |
| 1061 } else if (cgen()->allocator()->is_used(b_reg)) { |
| 1062 // a must be in b_reg, b in a_reg. |
| 1063 __ xchg(a_reg, b_reg); |
| 1064 // Results a and b will be invalidated, so it is ok if they are switched. |
| 1065 } else { |
| 1066 b->ToRegister(b_reg); |
| 1067 a->ToRegister(a_reg); |
| 1068 } |
| 1069 a->Unuse(); |
| 1070 b->Unuse(); |
| 1071 } |
| 1072 |
| 1073 |
1034 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { | 1074 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { |
1035 // Name and receiver are on the top of the frame. The IC expects | 1075 // Name and receiver are on the top of the frame. The IC expects |
1036 // name in rcx and receiver on the stack. It does not drop the | 1076 // name in rcx and receiver on the stack. It does not drop the |
1037 // receiver. | 1077 // receiver. |
1038 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1078 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1039 Result name = Pop(); | 1079 Result name = Pop(); |
1040 PrepareForCall(1, 0); // One stack arg, not callee-dropped. | 1080 PrepareForCall(1, 0); // One stack arg, not callee-dropped. |
1041 name.ToRegister(rcx); | 1081 name.ToRegister(rcx); |
1042 name.Unuse(); | 1082 name.Unuse(); |
1043 return RawCallCodeObject(ic, mode); | 1083 return RawCallCodeObject(ic, mode); |
1044 } | 1084 } |
1045 | 1085 |
1046 | 1086 |
1047 Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { | 1087 Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { |
1048 // Key and receiver are on top of the frame. The IC expects them on | 1088 // Key and receiver are on top of the frame. The IC expects them on |
1049 // the stack. It does not drop them. | 1089 // the stack. It does not drop them. |
1050 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1090 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1051 PrepareForCall(2, 0); // Two stack args, neither callee-dropped. | 1091 PrepareForCall(2, 0); // Two stack args, neither callee-dropped. |
1052 return RawCallCodeObject(ic, mode); | 1092 return RawCallCodeObject(ic, mode); |
1053 } | 1093 } |
1054 | 1094 |
1055 | 1095 |
1056 Result VirtualFrame::CallKeyedStoreIC() { | 1096 Result VirtualFrame::CallCommonStoreIC(Handle<Code> ic, |
1057 // Value, key, and receiver are on the top of the frame. The IC | 1097 Result* value, |
1058 // expects value in rax and key and receiver on the stack. It does | 1098 Result* key, |
1059 // not drop the key and receiver. | 1099 Result* receiver) { |
1060 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1100 // The IC expects value in rax, key in rcx, and receiver in rdx. |
1061 Result value = Pop(); | 1101 PrepareForCall(0, 0); |
1062 PrepareForCall(2, 0); // Two stack args, neither callee-dropped. | 1102 // If one of the three registers is free, or a value is already |
1063 value.ToRegister(rax); | 1103 // in the correct register, move the remaining two values using |
1064 value.Unuse(); | 1104 // MoveResultsToRegisters(). |
| 1105 if (!cgen()->allocator()->is_used(rax) || |
| 1106 (value->is_register() && value->reg().is(rax))) { |
| 1107 if (!cgen()->allocator()->is_used(rax)) { |
| 1108 value->ToRegister(rax); |
| 1109 } |
| 1110 MoveResultsToRegisters(key, receiver, rcx, rdx); |
| 1111 value->Unuse(); |
| 1112 } else if (!cgen()->allocator()->is_used(rcx) || |
| 1113 (key->is_register() && key->reg().is(rcx))) { |
| 1114 if (!cgen()->allocator()->is_used(rcx)) { |
| 1115 key->ToRegister(rcx); |
| 1116 } |
| 1117 MoveResultsToRegisters(value, receiver, rax, rdx); |
| 1118 key->Unuse(); |
| 1119 } else if (!cgen()->allocator()->is_used(rdx) || |
| 1120 (receiver->is_register() && receiver->reg().is(rdx))) { |
| 1121 if (!cgen()->allocator()->is_used(rdx)) { |
| 1122 receiver->ToRegister(rdx); |
| 1123 } |
| 1124 MoveResultsToRegisters(key, value, rcx, rax); |
| 1125 receiver->Unuse(); |
| 1126 } else { |
| 1127 // Otherwise, no register is free, and no value is in the correct place. |
| 1128 // We have one of the two circular permutations of eax, ecx, edx. |
| 1129 ASSERT(value->is_register()); |
| 1130 if (value->reg().is(rcx)) { |
| 1131 __ xchg(rax, rdx); |
| 1132 __ xchg(rax, rcx); |
| 1133 } else { |
| 1134 __ xchg(rax, rcx); |
| 1135 __ xchg(rax, rdx); |
| 1136 } |
| 1137 value->Unuse(); |
| 1138 key->Unuse(); |
| 1139 receiver->Unuse(); |
| 1140 } |
| 1141 |
1065 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); | 1142 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); |
1066 } | 1143 } |
1067 | 1144 |
1068 | 1145 |
1069 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, | 1146 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, |
1070 int arg_count, | 1147 int arg_count, |
1071 int loop_nesting) { | 1148 int loop_nesting) { |
1072 // Function name, arguments, and receiver are found on top of the frame | 1149 // Function name, arguments, and receiver are found on top of the frame |
1073 // and dropped by the call. The IC expects the name in rcx and the rest | 1150 // and dropped by the call. The IC expects the name in rcx and the rest |
1074 // on the stack, and drops them all. | 1151 // on the stack, and drops them all. |
(...skipping 26 matching lines...) Expand all Loading... |
1101 Result num_args = cgen()->allocator()->Allocate(rax); | 1178 Result num_args = cgen()->allocator()->Allocate(rax); |
1102 ASSERT(num_args.is_valid()); | 1179 ASSERT(num_args.is_valid()); |
1103 __ movq(num_args.reg(), Immediate(arg_count)); | 1180 __ movq(num_args.reg(), Immediate(arg_count)); |
1104 | 1181 |
1105 function.Unuse(); | 1182 function.Unuse(); |
1106 num_args.Unuse(); | 1183 num_args.Unuse(); |
1107 return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL); | 1184 return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL); |
1108 } | 1185 } |
1109 | 1186 |
1110 | 1187 |
1111 Result VirtualFrame::CallStoreIC() { | |
1112 // Name, value, and receiver are on top of the frame. The IC | |
1113 // expects name in rcx, value in rax, and receiver in edx. | |
1114 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | |
1115 Result name = Pop(); | |
1116 Result value = Pop(); | |
1117 Result receiver = Pop(); | |
1118 PrepareForCall(0, 0); | |
1119 | |
1120 // Optimized for case in which name is a constant value. | |
1121 if (name.is_register() && (name.reg().is(rdx) || name.reg().is(rax))) { | |
1122 if (!is_used(rcx)) { | |
1123 name.ToRegister(rcx); | |
1124 } else if (!is_used(rbx)) { | |
1125 name.ToRegister(rbx); | |
1126 } else { | |
1127 ASSERT(!is_used(rdi)); // Only three results are live, so rdi is free. | |
1128 name.ToRegister(rdi); | |
1129 } | |
1130 } | |
1131 // Now name is not in edx or eax, so we can fix them, then move name to ecx. | |
1132 if (value.is_register() && value.reg().is(rdx)) { | |
1133 if (receiver.is_register() && receiver.reg().is(rax)) { | |
1134 // Wrong registers. | |
1135 __ xchg(rax, rdx); | |
1136 } else { | |
1137 // Register rax is free for value, which frees rcx for receiver. | |
1138 value.ToRegister(rax); | |
1139 receiver.ToRegister(rdx); | |
1140 } | |
1141 } else { | |
1142 // Register rcx is free for receiver, which guarantees rax is free for | |
1143 // value. | |
1144 receiver.ToRegister(rdx); | |
1145 value.ToRegister(rax); | |
1146 } | |
1147 // Receiver and value are in the right place, so rcx is free for name. | |
1148 name.ToRegister(rcx); | |
1149 name.Unuse(); | |
1150 value.Unuse(); | |
1151 receiver.Unuse(); | |
1152 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); | |
1153 } | |
1154 | |
1155 | |
1156 void VirtualFrame::PushTryHandler(HandlerType type) { | 1188 void VirtualFrame::PushTryHandler(HandlerType type) { |
1157 ASSERT(cgen()->HasValidEntryRegisters()); | 1189 ASSERT(cgen()->HasValidEntryRegisters()); |
1158 // Grow the expression stack by handler size less one (the return | 1190 // Grow the expression stack by handler size less one (the return |
1159 // address is already pushed by a call instruction). | 1191 // address is already pushed by a call instruction). |
1160 Adjust(kHandlerSize - 1); | 1192 Adjust(kHandlerSize - 1); |
1161 __ PushTryHandler(IN_JAVASCRIPT, type); | 1193 __ PushTryHandler(IN_JAVASCRIPT, type); |
1162 } | 1194 } |
1163 | 1195 |
1164 | 1196 |
1165 #undef __ | 1197 #undef __ |
1166 | 1198 |
1167 } } // namespace v8::internal | 1199 } } // namespace v8::internal |
1168 | 1200 |
1169 #endif // V8_TARGET_ARCH_X64 | 1201 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |