OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 static const Register kRootRegister = { 13 }; // r13 (callee save). | 55 static const Register kRootRegister = { 13 }; // r13 (callee save). |
56 // Value of smi in kSmiConstantRegister. | 56 // Value of smi in kSmiConstantRegister. |
57 static const int kSmiConstantRegisterValue = 1; | 57 static const int kSmiConstantRegisterValue = 1; |
58 // Actual value of root register is offset from the root array's start | 58 // Actual value of root register is offset from the root array's start |
59 // to take advantage of negitive 8-bit displacement values. | 59 // to take advantage of negitive 8-bit displacement values. |
60 static const int kRootRegisterBias = 128; | 60 static const int kRootRegisterBias = 128; |
61 | 61 |
62 // Convenience for platform-independent signatures. | 62 // Convenience for platform-independent signatures. |
63 typedef Operand MemOperand; | 63 typedef Operand MemOperand; |
64 | 64 |
| 65 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; |
| 66 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; |
| 67 |
| 68 bool AreAliased(Register r1, Register r2, Register r3, Register r4); |
| 69 |
65 // Forward declaration. | 70 // Forward declaration. |
66 class JumpTarget; | 71 class JumpTarget; |
67 | 72 |
68 struct SmiIndex { | 73 struct SmiIndex { |
69 SmiIndex(Register index_register, ScaleFactor scale) | 74 SmiIndex(Register index_register, ScaleFactor scale) |
70 : reg(index_register), | 75 : reg(index_register), |
71 scale(scale) {} | 76 scale(scale) {} |
72 Register reg; | 77 Register reg; |
73 ScaleFactor scale; | 78 ScaleFactor scale; |
74 }; | 79 }; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 // Load a root value where the index (or part of it) is variable. | 134 // Load a root value where the index (or part of it) is variable. |
130 // The variable_offset register is added to the fixed_offset value | 135 // The variable_offset register is added to the fixed_offset value |
131 // to get the index into the root-array. | 136 // to get the index into the root-array. |
132 void LoadRootIndexed(Register destination, | 137 void LoadRootIndexed(Register destination, |
133 Register variable_offset, | 138 Register variable_offset, |
134 int fixed_offset); | 139 int fixed_offset); |
135 void CompareRoot(Register with, Heap::RootListIndex index); | 140 void CompareRoot(Register with, Heap::RootListIndex index); |
136 void CompareRoot(const Operand& with, Heap::RootListIndex index); | 141 void CompareRoot(const Operand& with, Heap::RootListIndex index); |
137 void PushRoot(Heap::RootListIndex index); | 142 void PushRoot(Heap::RootListIndex index); |
138 | 143 |
139 // --------------------------------------------------------------------------- | 144 // These functions do not arrange the registers in any particular order so |
140 // GC Support | 145 // they are not useful for calls that can cause a GC. The caller can |
| 146 // exclude up to 3 registers that do not need to be saved and restored. |
| 147 void PushCallerSaved(SaveFPRegsMode fp_mode, |
| 148 Register exclusion1 = no_reg, |
| 149 Register exclusion2 = no_reg, |
| 150 Register exclusion3 = no_reg); |
| 151 void PopCallerSaved(SaveFPRegsMode fp_mode, |
| 152 Register exclusion1 = no_reg, |
| 153 Register exclusion2 = no_reg, |
| 154 Register exclusion3 = no_reg); |
141 | 155 |
142 // For page containing |object| mark region covering |addr| dirty. | 156 // --------------------------------------------------------------------------- |
143 // RecordWriteHelper only works if the object is not in new | 157 // GC Support |
144 // space. | |
145 void RecordWriteHelper(Register object, | |
146 Register addr, | |
147 Register scratch); | |
148 | 158 |
149 // Check if object is in new space. The condition cc can be equal or | |
150 // not_equal. If it is equal a jump will be done if the object is on new | |
151 // space. The register scratch can be object itself, but it will be clobbered. | |
152 void InNewSpace(Register object, | |
153 Register scratch, | |
154 Condition cc, | |
155 Label* branch, | |
156 Label::Distance near_jump = Label::kFar); | |
157 | 159 |
158 // For page containing |object| mark region covering [object+offset] | 160 enum RememberedSetFinalAction { |
159 // dirty. |object| is the object being stored into, |value| is the | 161 kReturnAtEnd, |
160 // object being stored. If |offset| is zero, then the |scratch| | 162 kFallThroughAtEnd |
161 // register contains the array index into the elements array | 163 }; |
162 // represented as an untagged 32-bit integer. All registers are | 164 |
163 // clobbered by the operation. RecordWrite filters out smis so it | 165 // Record in the remembered set the fact that we have a pointer to new space |
164 // does not update the write barrier if the value is a smi. | 166 // at the address pointed to by the addr register. Only works if addr is not |
165 void RecordWrite(Register object, | 167 // in new space. |
166 int offset, | 168 void RememberedSetHelper(Register addr, |
167 Register value, | 169 Register scratch, |
168 Register scratch); | 170 SaveFPRegsMode save_fp, |
| 171 RememberedSetFinalAction and_then); |
| 172 |
| 173 void CheckPageFlag(Register object, |
| 174 Register scratch, |
| 175 int mask, |
| 176 Condition cc, |
| 177 Label* condition_met, |
| 178 Label::Distance condition_met_distance = Label::kFar); |
| 179 |
| 180 // Check if object is in new space. Jumps if the object is not in new space. |
| 181 // The register scratch can be object itself, but it will be clobbered. |
| 182 void JumpIfNotInNewSpace(Register object, |
| 183 Register scratch, |
| 184 Label* branch, |
| 185 Label::Distance distance = Label::kFar) { |
| 186 InNewSpace(object, scratch, not_equal, branch, distance); |
| 187 } |
| 188 |
| 189 // Check if object is in new space. Jumps if the object is in new space. |
| 190 // The register scratch can be object itself, but it will be clobbered. |
| 191 void JumpIfInNewSpace(Register object, |
| 192 Register scratch, |
| 193 Label* branch, |
| 194 Label::Distance distance = Label::kFar) { |
| 195 InNewSpace(object, scratch, equal, branch, distance); |
| 196 } |
| 197 |
| 198 // Check if an object has the black incremental marking color. Also uses rcx! |
| 199 void JumpIfBlack(Register object, |
| 200 Register scratch0, |
| 201 Register scratch1, |
| 202 Label* on_black, |
| 203 Label::Distance on_black_distance = Label::kFar); |
| 204 |
| 205 // Detects conservatively whether an object is data-only, ie it does need to |
| 206 // be scanned by the garbage collector. |
| 207 void JumpIfDataObject(Register value, |
| 208 Register scratch, |
| 209 Label* not_data_object, |
| 210 Label::Distance not_data_object_distance); |
| 211 |
| 212 // Checks the color of an object. If the object is already grey or black |
| 213 // then we just fall through, since it is already live. If it is white and |
| 214 // we can determine that it doesn't need to be scanned, then we just mark it |
| 215 // black and fall through. For the rest we jump to the label so the |
| 216 // incremental marker can fix its assumptions. |
| 217 void EnsureNotWhite(Register object, |
| 218 Register scratch1, |
| 219 Register scratch2, |
| 220 Label* object_is_white_and_not_data, |
| 221 Label::Distance distance); |
| 222 |
| 223 // Notify the garbage collector that we wrote a pointer into an object. |
| 224 // |object| is the object being stored into, |value| is the object being |
| 225 // stored. value and scratch registers are clobbered by the operation. |
| 226 // The offset is the offset from the start of the object, not the offset from |
| 227 // the tagged HeapObject pointer. For use with FieldOperand(reg, off). |
| 228 void RecordWriteField( |
| 229 Register object, |
| 230 int offset, |
| 231 Register value, |
| 232 Register scratch, |
| 233 SaveFPRegsMode save_fp, |
| 234 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, |
| 235 SmiCheck smi_check = INLINE_SMI_CHECK); |
| 236 |
| 237 // As above, but the offset has the tag presubtracted. For use with |
| 238 // Operand(reg, off). |
| 239 void RecordWriteContextSlot( |
| 240 Register context, |
| 241 int offset, |
| 242 Register value, |
| 243 Register scratch, |
| 244 SaveFPRegsMode save_fp, |
| 245 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, |
| 246 SmiCheck smi_check = INLINE_SMI_CHECK) { |
| 247 RecordWriteField(context, |
| 248 offset + kHeapObjectTag, |
| 249 value, |
| 250 scratch, |
| 251 save_fp, |
| 252 remembered_set_action, |
| 253 smi_check); |
| 254 } |
| 255 |
| 256 // Notify the garbage collector that we wrote a pointer into a fixed array. |
| 257 // |array| is the array being stored into, |value| is the |
| 258 // object being stored. |index| is the array index represented as a |
| 259 // Smi. All registers are clobbered by the operation RecordWriteArray |
| 260 // filters out smis so it does not update the write barrier if the |
| 261 // value is a smi. |
| 262 void RecordWriteArray( |
| 263 Register array, |
| 264 Register value, |
| 265 Register index, |
| 266 SaveFPRegsMode save_fp, |
| 267 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, |
| 268 SmiCheck smi_check = INLINE_SMI_CHECK); |
169 | 269 |
170 // For page containing |object| mark region covering [address] | 270 // For page containing |object| mark region covering [address] |
171 // dirty. |object| is the object being stored into, |value| is the | 271 // dirty. |object| is the object being stored into, |value| is the |
172 // object being stored. All registers are clobbered by the | 272 // object being stored. All registers are clobbered by the |
173 // operation. RecordWrite filters out smis so it does not update | 273 // operation. RecordWrite filters out smis so it does not update |
174 // the write barrier if the value is a smi. | 274 // the write barrier if the value is a smi. |
175 void RecordWrite(Register object, | 275 void RecordWrite( |
176 Register address, | 276 Register object, |
177 Register value); | 277 Register address, |
178 | 278 Register value, |
179 // For page containing |object| mark region covering [object+offset] dirty. | 279 SaveFPRegsMode save_fp, |
180 // The value is known to not be a smi. | 280 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, |
181 // object is the object being stored into, value is the object being stored. | 281 SmiCheck smi_check = INLINE_SMI_CHECK); |
182 // If offset is zero, then the scratch register contains the array index into | |
183 // the elements array represented as an untagged 32-bit integer. | |
184 // All registers are clobbered by the operation. | |
185 void RecordWriteNonSmi(Register object, | |
186 int offset, | |
187 Register value, | |
188 Register scratch); | |
189 | 282 |
190 #ifdef ENABLE_DEBUGGER_SUPPORT | 283 #ifdef ENABLE_DEBUGGER_SUPPORT |
191 // --------------------------------------------------------------------------- | 284 // --------------------------------------------------------------------------- |
192 // Debugger Support | 285 // Debugger Support |
193 | 286 |
194 void DebugBreak(); | 287 void DebugBreak(); |
195 #endif | 288 #endif |
196 | 289 |
197 // Enter specific kind of exit frame; either in normal or | 290 // Enter specific kind of exit frame; either in normal or |
198 // debug mode. Expects the number of arguments in register rax and | 291 // debug mode. Expects the number of arguments in register rax and |
(...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1208 // If scratch is valid, it contains the address of the allocation top. | 1301 // If scratch is valid, it contains the address of the allocation top. |
1209 void UpdateAllocationTopHelper(Register result_end, Register scratch); | 1302 void UpdateAllocationTopHelper(Register result_end, Register scratch); |
1210 | 1303 |
1211 // Helper for PopHandleScope. Allowed to perform a GC and returns | 1304 // Helper for PopHandleScope. Allowed to perform a GC and returns |
1212 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and | 1305 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and |
1213 // possibly returns a failure object indicating an allocation failure. | 1306 // possibly returns a failure object indicating an allocation failure. |
1214 Object* PopHandleScopeHelper(Register saved, | 1307 Object* PopHandleScopeHelper(Register saved, |
1215 Register scratch, | 1308 Register scratch, |
1216 bool gc_allowed); | 1309 bool gc_allowed); |
1217 | 1310 |
| 1311 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. |
| 1312 void InNewSpace(Register object, |
| 1313 Register scratch, |
| 1314 Condition cc, |
| 1315 Label* branch, |
| 1316 Label::Distance distance = Label::kFar); |
| 1317 |
| 1318 // Helper for finding the mark bits for an address. Afterwards, the |
| 1319 // bitmap register points at the word with the mark bits and the mask |
| 1320 // the position of the first bit. Uses rcx as scratch and leaves addr_reg |
| 1321 // unchanged. |
| 1322 inline void GetMarkBits(Register addr_reg, |
| 1323 Register bitmap_reg, |
| 1324 Register mask_reg); |
1218 | 1325 |
1219 // Compute memory operands for safepoint stack slots. | 1326 // Compute memory operands for safepoint stack slots. |
1220 Operand SafepointRegisterSlot(Register reg); | 1327 Operand SafepointRegisterSlot(Register reg); |
1221 static int SafepointRegisterStackIndex(int reg_code) { | 1328 static int SafepointRegisterStackIndex(int reg_code) { |
1222 return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1; | 1329 return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1; |
1223 } | 1330 } |
1224 | 1331 |
1225 // Needs access to SafepointRegisterStackIndex for optimized frame | 1332 // Needs access to SafepointRegisterStackIndex for optimized frame |
1226 // traversal. | 1333 // traversal. |
1227 friend class OptimizedFrame; | 1334 friend class OptimizedFrame; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1305 masm->popfd(); \ | 1412 masm->popfd(); \ |
1306 } \ | 1413 } \ |
1307 masm-> | 1414 masm-> |
1308 #else | 1415 #else |
1309 #define ACCESS_MASM(masm) masm-> | 1416 #define ACCESS_MASM(masm) masm-> |
1310 #endif | 1417 #endif |
1311 | 1418 |
1312 } } // namespace v8::internal | 1419 } } // namespace v8::internal |
1313 | 1420 |
1314 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ | 1421 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ |
OLD | NEW |