Chromium Code Reviews| 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 5140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5151 __ Drop(1); | 5151 __ Drop(1); |
| 5152 __ ret(2 * kPointerSize); | 5152 __ ret(2 * kPointerSize); |
| 5153 } | 5153 } |
| 5154 | 5154 |
| 5155 | 5155 |
| 5156 // Takes the input in 3 registers: address_ value_ and object_. A pointer to | 5156 // Takes the input in 3 registers: address_ value_ and object_. A pointer to |
| 5157 // the value has just been written into the object, now this stub makes sure | 5157 // the value has just been written into the object, now this stub makes sure |
| 5158 // we keep the GC informed. The word in the object where the value has been | 5158 // we keep the GC informed. The word in the object where the value has been |
| 5159 // written is in the address register. | 5159 // written is in the address register. |
| 5160 void RecordWriteStub::Generate(MacroAssembler* masm) { | 5160 void RecordWriteStub::Generate(MacroAssembler* masm) { |
| 5161 Label skip_non_incremental_part; | 5161 Label skip_to_incremental_noncompacting; |
| 5162 Label skip_to_incremental_compacting; | |
| 5162 | 5163 |
| 5163 // The first instruction is generated as a label so as to get the offset | 5164 // The first instruction is generated as a label so as to get the offset |
| 5164 // fixed up correctly by the bind(Label*) call. We patch it back and forth | 5165 // fixed up correctly by the bind(Label*) call. We patch it back and forth |
| 5165 // between a 2-byte compare instruction (a nop in this position) and the real | 5166 // between a 2-byte compare instruction (a nop in this position) and the real |
| 5166 // branch when we start and stop incremental heap marking. | 5167 // branch when we start and stop incremental heap marking. |
|
Erik Corry
2011/07/08 09:06:49
This comment does not mention compaction. I would
| |
| 5167 __ jmp(&skip_non_incremental_part, Label::kNear); | 5168 __ jmp(&skip_to_incremental_noncompacting, Label::kNear); |
| 5168 if (!masm->isolate()->heap()->incremental_marking()->IsMarking()) { | 5169 __ jmp(&skip_to_incremental_compacting, Label::kFar); |
| 5169 ASSERT(masm->byte_at(masm->pc_offset() - 2) == | |
| 5170 kSkipNonIncrementalPartInstruction); | |
| 5171 masm->set_byte_at(masm->pc_offset() - 2, kTwoByteNopInstruction); | |
| 5172 } | |
| 5173 | 5170 |
| 5174 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { | 5171 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { |
| 5175 __ RememberedSetHelper( | 5172 __ RememberedSetHelper( |
| 5176 address_, value_, save_fp_regs_mode_, MacroAssembler::kReturnAtEnd); | 5173 address_, value_, save_fp_regs_mode_, MacroAssembler::kReturnAtEnd); |
| 5177 } else { | 5174 } else { |
| 5178 __ ret(0); | 5175 __ ret(0); |
| 5179 } | 5176 } |
| 5180 | 5177 |
| 5181 __ bind(&skip_non_incremental_part); | 5178 __ bind(&skip_to_incremental_noncompacting); |
| 5182 GenerateIncremental(masm); | 5179 GenerateIncremental(masm, INCREMENTAL); |
| 5180 | |
| 5181 __ bind(&skip_to_incremental_compacting); | |
| 5182 GenerateIncremental(masm, INCREMENTAL_COMPACTION); | |
| 5183 | |
| 5184 // TODO(gc) ensure that GC can't happen after stub was generated by before | |
| 5185 // it was added to a stub cache. | |
|
Erik Corry
2011/07/08 09:06:49
This looks nasty. Please file a bug and put the b
| |
| 5186 IncrementalMarking* marking = masm->isolate()->heap()->incremental_marking(); | |
| 5187 if (!marking->IsMarking() || marking->IsCompacting()) { | |
| 5188 ASSERT(masm->byte_at(0) == kTwoByteJumpInstruction); | |
| 5189 masm->set_byte_at(0, kTwoByteNopInstruction); | |
| 5190 } | |
| 5191 | |
| 5192 if (!marking->IsMarking()) { | |
| 5193 ASSERT(masm->byte_at(2) == kFiveByteJumpInstruction); | |
| 5194 masm->set_byte_at(2, kFiveByteNopInstruction); | |
| 5195 } | |
| 5183 } | 5196 } |
| 5184 | 5197 |
| 5185 | 5198 |
| 5186 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm) { | 5199 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { |
| 5187 regs_.Save(masm); | 5200 regs_.Save(masm); |
| 5188 | 5201 |
| 5189 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { | 5202 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { |
| 5190 Label dont_need_remembered_set; | 5203 Label dont_need_remembered_set; |
| 5191 | 5204 |
| 5192 __ movq(regs_.scratch0(), Operand(regs_.address(), 0)); | 5205 __ movq(regs_.scratch0(), Operand(regs_.address(), 0)); |
| 5193 __ JumpIfNotInNewSpace(regs_.scratch0(), | 5206 __ JumpIfNotInNewSpace(regs_.scratch0(), |
| 5194 regs_.scratch0(), | 5207 regs_.scratch0(), |
| 5195 &dont_need_remembered_set); | 5208 &dont_need_remembered_set); |
| 5196 | 5209 |
| 5197 __ CheckPageFlag(regs_.object(), | 5210 __ CheckPageFlag(regs_.object(), |
| 5198 regs_.scratch0(), | 5211 regs_.scratch0(), |
| 5199 MemoryChunk::SCAN_ON_SCAVENGE, | 5212 MemoryChunk::SCAN_ON_SCAVENGE, |
| 5200 not_zero, | 5213 not_zero, |
| 5201 &dont_need_remembered_set); | 5214 &dont_need_remembered_set); |
| 5202 | 5215 |
| 5203 // First notify the incremental marker if necessary, then update the | 5216 // First notify the incremental marker if necessary, then update the |
| 5204 // remembered set. | 5217 // remembered set. |
| 5205 CheckNeedsToInformIncrementalMarker( | 5218 CheckNeedsToInformIncrementalMarker( |
| 5206 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker); | 5219 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); |
| 5207 InformIncrementalMarker(masm); | 5220 InformIncrementalMarker(masm, mode); |
| 5208 regs_.Restore(masm); | 5221 regs_.Restore(masm); |
| 5209 __ RememberedSetHelper( | 5222 __ RememberedSetHelper( |
| 5210 address_, value_, save_fp_regs_mode_, MacroAssembler::kReturnAtEnd); | 5223 address_, value_, save_fp_regs_mode_, MacroAssembler::kReturnAtEnd); |
| 5211 | 5224 |
| 5212 __ bind(&dont_need_remembered_set); | 5225 __ bind(&dont_need_remembered_set); |
| 5213 } | 5226 } |
| 5214 | 5227 |
| 5215 CheckNeedsToInformIncrementalMarker( | 5228 CheckNeedsToInformIncrementalMarker( |
| 5216 masm, kReturnOnNoNeedToInformIncrementalMarker); | 5229 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); |
| 5217 InformIncrementalMarker(masm); | 5230 InformIncrementalMarker(masm, mode); |
| 5218 regs_.Restore(masm); | 5231 regs_.Restore(masm); |
| 5219 __ ret(0); | 5232 __ ret(0); |
| 5220 } | 5233 } |
| 5221 | 5234 |
| 5222 | 5235 |
| 5223 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { | 5236 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) { |
| 5224 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 5237 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); |
| 5225 #ifdef _WIN64 | 5238 #ifdef _WIN64 |
| 5226 Register arg3 = r8; | 5239 Register arg3 = r8; |
| 5227 Register arg2 = rdx; | 5240 Register arg2 = rdx; |
| 5228 Register arg1 = rcx; | 5241 Register arg1 = rcx; |
| 5229 #else | 5242 #else |
| 5230 Register arg3 = rdx; | 5243 Register arg3 = rdx; |
| 5231 Register arg2 = rsi; | 5244 Register arg2 = rsi; |
| 5232 Register arg1 = rdi; | 5245 Register arg1 = rdi; |
| 5233 #endif | 5246 #endif |
| 5234 bool save_address = arg1.is(regs_.address()); | 5247 Register address = |
| 5235 if (save_address) { | 5248 arg1.is(regs_.address()) ? kScratchRegister : regs_.address(); |
| 5236 __ movq(arg3, regs_.address()); | 5249 ASSERT(!address.is(regs_.object())); |
| 5237 } | 5250 ASSERT(!address.is(arg1)); |
| 5251 __ Move(address, regs_.address()); | |
| 5238 __ Move(arg1, regs_.object()); | 5252 __ Move(arg1, regs_.object()); |
| 5239 if (save_address) { | 5253 if (mode == INCREMENTAL_COMPACTION) { |
| 5240 __ movq(arg2, Operand(arg3, 0)); | 5254 // TODO(gc) Can we just set address arg2 in the beginning? |
| 5255 __ Move(arg2, address); | |
| 5241 } else { | 5256 } else { |
| 5242 __ movq(arg2, Operand(regs_.address(), 0)); | 5257 ASSERT(mode == INCREMENTAL); |
| 5258 __ movq(arg2, Operand(address, 0)); | |
| 5243 } | 5259 } |
| 5244 __ LoadAddress(arg3, ExternalReference::isolate_address()); | 5260 __ LoadAddress(arg3, ExternalReference::isolate_address()); |
| 5245 // TODO(gc): Create a fast version of this C function that does not duplicate | 5261 // TODO(gc): Create a fast version of this C function that does not duplicate |
| 5246 // the checks done in the stub. | 5262 // the checks done in the stub. |
| 5247 int argument_count = 3; | 5263 int argument_count = 3; |
| 5248 __ PrepareCallCFunction(argument_count); | 5264 __ PrepareCallCFunction(argument_count); |
| 5249 __ CallCFunction( | 5265 if (mode == INCREMENTAL_COMPACTION) { |
| 5250 ExternalReference::incremental_marking_record_write_function( | 5266 __ CallCFunction( |
| 5251 masm->isolate()), | 5267 ExternalReference::incremental_evacuation_record_write_function( |
| 5252 argument_count); | 5268 masm->isolate()), |
| 5269 argument_count); | |
| 5270 } else { | |
| 5271 ASSERT(mode == INCREMENTAL); | |
| 5272 __ CallCFunction( | |
| 5273 ExternalReference::incremental_marking_record_write_function( | |
| 5274 masm->isolate()), | |
| 5275 argument_count); | |
| 5276 } | |
| 5253 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); | 5277 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); |
| 5254 } | 5278 } |
| 5255 | 5279 |
| 5256 | 5280 |
| 5257 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( | 5281 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( |
| 5258 MacroAssembler* masm, | 5282 MacroAssembler* masm, |
| 5259 RecordWriteStub::OnNoNeedToInformIncrementalMarker on_no_need) { | 5283 OnNoNeedToInformIncrementalMarker on_no_need, |
| 5284 Mode mode) { | |
| 5260 Label on_black; | 5285 Label on_black; |
| 5261 | 5286 |
| 5262 // Let's look at the color of the object: If it is not black we don't have | 5287 // Let's look at the color of the object: If it is not black we don't have |
| 5263 // to inform the incremental marker. | 5288 // to inform the incremental marker. |
| 5264 __ JumpIfBlack(regs_.object(), | 5289 __ JumpIfBlack(regs_.object(), |
| 5265 regs_.scratch0(), | 5290 regs_.scratch0(), |
| 5266 regs_.scratch1(), | 5291 regs_.scratch1(), |
| 5267 &on_black, | 5292 &on_black, |
| 5268 Label::kNear); | 5293 Label::kNear); |
| 5269 | 5294 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 5280 // TODO(gc): Add call to EnsureNotWhite here. | 5305 // TODO(gc): Add call to EnsureNotWhite here. |
| 5281 // Fall through when we need to inform the incremental marker. | 5306 // Fall through when we need to inform the incremental marker. |
| 5282 } | 5307 } |
| 5283 | 5308 |
| 5284 | 5309 |
| 5285 #undef __ | 5310 #undef __ |
| 5286 | 5311 |
| 5287 } } // namespace v8::internal | 5312 } } // namespace v8::internal |
| 5288 | 5313 |
| 5289 #endif // V8_TARGET_ARCH_X64 | 5314 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |