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 |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
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 #if defined(V8_TARGET_ARCH_X64) |
| 31 |
30 #include "codegen-inl.h" | 32 #include "codegen-inl.h" |
31 #include "register-allocator-inl.h" | 33 #include "register-allocator-inl.h" |
32 #include "scopes.h" | 34 #include "scopes.h" |
33 #include "virtual-frame-inl.h" | 35 #include "virtual-frame-inl.h" |
34 | 36 |
35 namespace v8 { | 37 namespace v8 { |
36 namespace internal { | 38 namespace internal { |
37 | 39 |
38 #define __ ACCESS_MASM(masm()) | 40 #define __ ACCESS_MASM(masm()) |
39 | 41 |
(...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 void VirtualFrame::DebugBreak() { | 1024 void VirtualFrame::DebugBreak() { |
1023 PrepareForCall(0, 0); | 1025 PrepareForCall(0, 0); |
1024 ASSERT(cgen()->HasValidEntryRegisters()); | 1026 ASSERT(cgen()->HasValidEntryRegisters()); |
1025 __ DebugBreak(); | 1027 __ DebugBreak(); |
1026 Result result = cgen()->allocator()->Allocate(rax); | 1028 Result result = cgen()->allocator()->Allocate(rax); |
1027 ASSERT(result.is_valid()); | 1029 ASSERT(result.is_valid()); |
1028 } | 1030 } |
1029 #endif | 1031 #endif |
1030 | 1032 |
1031 | 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 |
1032 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { | 1074 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { |
1033 // 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 |
1034 // 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 |
1035 // receiver. | 1077 // receiver. |
1036 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1078 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1037 Result name = Pop(); | 1079 Result name = Pop(); |
1038 PrepareForCall(1, 0); // One stack arg, not callee-dropped. | 1080 PrepareForCall(1, 0); // One stack arg, not callee-dropped. |
1039 name.ToRegister(rcx); | 1081 name.ToRegister(rcx); |
1040 name.Unuse(); | 1082 name.Unuse(); |
1041 return RawCallCodeObject(ic, mode); | 1083 return RawCallCodeObject(ic, mode); |
1042 } | 1084 } |
1043 | 1085 |
1044 | 1086 |
1045 Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { | 1087 Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { |
1046 // 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 |
1047 // the stack. It does not drop them. | 1089 // the stack. It does not drop them. |
1048 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1090 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1049 PrepareForCall(2, 0); // Two stack args, neither callee-dropped. | 1091 PrepareForCall(2, 0); // Two stack args, neither callee-dropped. |
1050 return RawCallCodeObject(ic, mode); | 1092 return RawCallCodeObject(ic, mode); |
1051 } | 1093 } |
1052 | 1094 |
1053 | 1095 |
1054 Result VirtualFrame::CallKeyedStoreIC() { | 1096 Result VirtualFrame::CallCommonStoreIC(Handle<Code> ic, |
1055 // Value, key, and receiver are on the top of the frame. The IC | 1097 Result* value, |
1056 // expects value in rax and key and receiver on the stack. It does | 1098 Result* key, |
1057 // not drop the key and receiver. | 1099 Result* receiver) { |
1058 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1100 // The IC expects value in rax, key in rcx, and receiver in rdx. |
1059 Result value = Pop(); | 1101 PrepareForCall(0, 0); |
1060 PrepareForCall(2, 0); // Two stack args, neither callee-dropped. | 1102 // If one of the three registers is free, or a value is already |
1061 value.ToRegister(rax); | 1103 // in the correct register, move the remaining two values using |
1062 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 |
1063 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); | 1142 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); |
1064 } | 1143 } |
1065 | 1144 |
1066 | 1145 |
1067 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, | 1146 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, |
1068 int arg_count, | 1147 int arg_count, |
1069 int loop_nesting) { | 1148 int loop_nesting) { |
1070 // 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 |
1071 // 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 |
1072 // on the stack, and drops them all. | 1151 // on the stack, and drops them all. |
(...skipping 26 matching lines...) Expand all Loading... |
1099 Result num_args = cgen()->allocator()->Allocate(rax); | 1178 Result num_args = cgen()->allocator()->Allocate(rax); |
1100 ASSERT(num_args.is_valid()); | 1179 ASSERT(num_args.is_valid()); |
1101 __ movq(num_args.reg(), Immediate(arg_count)); | 1180 __ movq(num_args.reg(), Immediate(arg_count)); |
1102 | 1181 |
1103 function.Unuse(); | 1182 function.Unuse(); |
1104 num_args.Unuse(); | 1183 num_args.Unuse(); |
1105 return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL); | 1184 return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL); |
1106 } | 1185 } |
1107 | 1186 |
1108 | 1187 |
1109 Result VirtualFrame::CallStoreIC() { | |
1110 // Name, value, and receiver are on top of the frame. The IC | |
1111 // expects name in rcx, value in rax, and receiver in edx. | |
1112 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | |
1113 Result name = Pop(); | |
1114 Result value = Pop(); | |
1115 Result receiver = Pop(); | |
1116 PrepareForCall(0, 0); | |
1117 | |
1118 // Optimized for case in which name is a constant value. | |
1119 if (name.is_register() && (name.reg().is(rdx) || name.reg().is(rax))) { | |
1120 if (!is_used(rcx)) { | |
1121 name.ToRegister(rcx); | |
1122 } else if (!is_used(rbx)) { | |
1123 name.ToRegister(rbx); | |
1124 } else { | |
1125 ASSERT(!is_used(rdi)); // Only three results are live, so rdi is free. | |
1126 name.ToRegister(rdi); | |
1127 } | |
1128 } | |
1129 // Now name is not in edx or eax, so we can fix them, then move name to ecx. | |
1130 if (value.is_register() && value.reg().is(rdx)) { | |
1131 if (receiver.is_register() && receiver.reg().is(rax)) { | |
1132 // Wrong registers. | |
1133 __ xchg(rax, rdx); | |
1134 } else { | |
1135 // Register rax is free for value, which frees rcx for receiver. | |
1136 value.ToRegister(rax); | |
1137 receiver.ToRegister(rdx); | |
1138 } | |
1139 } else { | |
1140 // Register rcx is free for receiver, which guarantees rax is free for | |
1141 // value. | |
1142 receiver.ToRegister(rdx); | |
1143 value.ToRegister(rax); | |
1144 } | |
1145 // Receiver and value are in the right place, so rcx is free for name. | |
1146 name.ToRegister(rcx); | |
1147 name.Unuse(); | |
1148 value.Unuse(); | |
1149 receiver.Unuse(); | |
1150 return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); | |
1151 } | |
1152 | |
1153 | |
1154 void VirtualFrame::PushTryHandler(HandlerType type) { | 1188 void VirtualFrame::PushTryHandler(HandlerType type) { |
1155 ASSERT(cgen()->HasValidEntryRegisters()); | 1189 ASSERT(cgen()->HasValidEntryRegisters()); |
1156 // Grow the expression stack by handler size less one (the return | 1190 // Grow the expression stack by handler size less one (the return |
1157 // address is already pushed by a call instruction). | 1191 // address is already pushed by a call instruction). |
1158 Adjust(kHandlerSize - 1); | 1192 Adjust(kHandlerSize - 1); |
1159 __ PushTryHandler(IN_JAVASCRIPT, type); | 1193 __ PushTryHandler(IN_JAVASCRIPT, type); |
1160 } | 1194 } |
1161 | 1195 |
1162 | 1196 |
1163 #undef __ | 1197 #undef __ |
1164 | 1198 |
1165 } } // namespace v8::internal | 1199 } } // namespace v8::internal |
| 1200 |
| 1201 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |