OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 MemOperand(sp, (param_count-1-i) * kPointerSize)); | 136 MemOperand(sp, (param_count-1-i) * kPointerSize)); |
137 } | 137 } |
138 ExternalReference miss = descriptor->miss_handler(); | 138 ExternalReference miss = descriptor->miss_handler(); |
139 __ CallExternalReference(miss, param_count); | 139 __ CallExternalReference(miss, param_count); |
140 } | 140 } |
141 | 141 |
142 __ Ret(); | 142 __ Ret(); |
143 } | 143 } |
144 | 144 |
145 | 145 |
146 // Takes a Smi and converts to an IEEE 64 bit floating point value in two | |
147 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and | |
148 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a | |
149 // scratch register. Destroys the source register. No GC occurs during this | |
150 // stub so you don't have to set up the frame. | |
151 class ConvertToDoubleStub : public PlatformCodeStub { | |
152 public: | |
153 ConvertToDoubleStub(Isolate* isolate, | |
154 Register result_reg_1, | |
155 Register result_reg_2, | |
156 Register source_reg, | |
157 Register scratch_reg) | |
158 : PlatformCodeStub(isolate), | |
159 result1_(result_reg_1), | |
160 result2_(result_reg_2), | |
161 source_(source_reg), | |
162 zeros_(scratch_reg) { } | |
163 | |
164 private: | |
165 Register result1_; | |
166 Register result2_; | |
167 Register source_; | |
168 Register zeros_; | |
169 | |
170 // Minor key encoding in 16 bits. | |
171 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; | |
172 class OpBits: public BitField<Token::Value, 2, 14> {}; | |
173 | |
174 Major MajorKey() const { return ConvertToDouble; } | |
175 uint32_t MinorKey() const { | |
176 // Encode the parameters in a unique 16 bit value. | |
177 return result1_.code() + | |
178 (result2_.code() << 4) + | |
179 (source_.code() << 8) + | |
180 (zeros_.code() << 12); | |
181 } | |
182 | |
183 void Generate(MacroAssembler* masm); | |
184 }; | |
185 | |
186 | |
187 void ConvertToDoubleStub::Generate(MacroAssembler* masm) { | |
188 #ifndef BIG_ENDIAN_FLOATING_POINT | |
189 Register exponent = result1_; | |
190 Register mantissa = result2_; | |
191 #else | |
192 Register exponent = result2_; | |
193 Register mantissa = result1_; | |
194 #endif | |
195 Label not_special; | |
196 // Convert from Smi to integer. | |
197 __ SmiUntag(source_); | |
198 // Move sign bit from source to destination. This works because the sign bit | |
199 // in the exponent word of the double has the same position and polarity as | |
200 // the 2's complement sign bit in a Smi. | |
201 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); | |
202 __ And(exponent, source_, Operand(HeapNumber::kSignMask)); | |
203 // Subtract from 0 if source was negative. | |
204 __ subu(at, zero_reg, source_); | |
205 __ Movn(source_, at, exponent); | |
206 | |
207 // We have -1, 0 or 1, which we treat specially. Register source_ contains | |
208 // absolute value: it is either equal to 1 (special case of -1 and 1), | |
209 // greater than 1 (not a special case) or less than 1 (special case of 0). | |
210 __ Branch(¬_special, gt, source_, Operand(1)); | |
211 | |
212 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). | |
213 const uint32_t exponent_word_for_1 = | |
214 HeapNumber::kExponentBias << HeapNumber::kExponentShift; | |
215 // Safe to use 'at' as dest reg here. | |
216 __ Or(at, exponent, Operand(exponent_word_for_1)); | |
217 __ Movn(exponent, at, source_); // Write exp when source not 0. | |
218 // 1, 0 and -1 all have 0 for the second word. | |
219 __ Ret(USE_DELAY_SLOT); | |
220 __ mov(mantissa, zero_reg); | |
221 | |
222 __ bind(¬_special); | |
223 // Count leading zeros. | |
224 // Gets the wrong answer for 0, but we already checked for that case above. | |
225 __ Clz(zeros_, source_); | |
226 // Compute exponent and or it into the exponent register. | |
227 // We use mantissa as a scratch register here. | |
228 __ li(mantissa, Operand(31 + HeapNumber::kExponentBias)); | |
229 __ subu(mantissa, mantissa, zeros_); | |
230 __ sll(mantissa, mantissa, HeapNumber::kExponentShift); | |
231 __ Or(exponent, exponent, mantissa); | |
232 | |
233 // Shift up the source chopping the top bit off. | |
234 __ Addu(zeros_, zeros_, Operand(1)); | |
235 // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. | |
236 __ sllv(source_, source_, zeros_); | |
237 // Compute lower part of fraction (last 12 bits). | |
238 __ sll(mantissa, source_, HeapNumber::kMantissaBitsInTopWord); | |
239 // And the top (top 20 bits). | |
240 __ srl(source_, source_, 32 - HeapNumber::kMantissaBitsInTopWord); | |
241 | |
242 __ Ret(USE_DELAY_SLOT); | |
243 __ or_(exponent, exponent, source_); | |
244 } | |
245 | |
246 | |
247 void DoubleToIStub::Generate(MacroAssembler* masm) { | 146 void DoubleToIStub::Generate(MacroAssembler* masm) { |
248 Label out_of_range, only_low, negate, done; | 147 Label out_of_range, only_low, negate, done; |
249 Register input_reg = source(); | 148 Register input_reg = source(); |
250 Register result_reg = destination(); | 149 Register result_reg = destination(); |
251 | 150 |
252 int double_offset = offset(); | 151 int double_offset = offset(); |
253 // Account for saved regs if input is sp. | 152 // Account for saved regs if input is sp. |
254 if (input_reg.is(sp)) double_offset += 3 * kPointerSize; | 153 if (input_reg.is(sp)) double_offset += 3 * kPointerSize; |
255 | 154 |
256 Register scratch = | 155 Register scratch = |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 } | 289 } |
391 | 290 |
392 | 291 |
393 // See comment for class, this does NOT work for int32's that are in Smi range. | 292 // See comment for class, this does NOT work for int32's that are in Smi range. |
394 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { | 293 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { |
395 Label max_negative_int; | 294 Label max_negative_int; |
396 // the_int_ has the answer which is a signed int32 but not a Smi. | 295 // the_int_ has the answer which is a signed int32 but not a Smi. |
397 // We test for the special value that has a different exponent. | 296 // We test for the special value that has a different exponent. |
398 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); | 297 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); |
399 // Test sign, and save for later conditionals. | 298 // Test sign, and save for later conditionals. |
400 __ And(sign_, the_int_, Operand(0x80000000u)); | 299 __ And(sign(), the_int(), Operand(0x80000000u)); |
401 __ Branch(&max_negative_int, eq, the_int_, Operand(0x80000000u)); | 300 __ Branch(&max_negative_int, eq, the_int(), Operand(0x80000000u)); |
402 | 301 |
403 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. | 302 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. |
404 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). | 303 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). |
405 uint32_t non_smi_exponent = | 304 uint32_t non_smi_exponent = |
406 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; | 305 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; |
407 __ li(scratch_, Operand(non_smi_exponent)); | 306 __ li(scratch(), Operand(non_smi_exponent)); |
408 // Set the sign bit in scratch_ if the value was negative. | 307 // Set the sign bit in scratch_ if the value was negative. |
409 __ or_(scratch_, scratch_, sign_); | 308 __ or_(scratch(), scratch(), sign()); |
410 // Subtract from 0 if the value was negative. | 309 // Subtract from 0 if the value was negative. |
411 __ subu(at, zero_reg, the_int_); | 310 __ subu(at, zero_reg, the_int()); |
412 __ Movn(the_int_, at, sign_); | 311 __ Movn(the_int(), at, sign()); |
413 // We should be masking the implict first digit of the mantissa away here, | 312 // We should be masking the implict first digit of the mantissa away here, |
414 // but it just ends up combining harmlessly with the last digit of the | 313 // but it just ends up combining harmlessly with the last digit of the |
415 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get | 314 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get |
416 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. | 315 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. |
417 DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); | 316 DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); |
418 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; | 317 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; |
419 __ srl(at, the_int_, shift_distance); | 318 __ srl(at, the_int(), shift_distance); |
420 __ or_(scratch_, scratch_, at); | 319 __ or_(scratch(), scratch(), at); |
421 __ sw(scratch_, FieldMemOperand(the_heap_number_, | 320 __ sw(scratch(), FieldMemOperand(the_heap_number(), |
422 HeapNumber::kExponentOffset)); | 321 HeapNumber::kExponentOffset)); |
423 __ sll(scratch_, the_int_, 32 - shift_distance); | 322 __ sll(scratch(), the_int(), 32 - shift_distance); |
424 __ Ret(USE_DELAY_SLOT); | 323 __ Ret(USE_DELAY_SLOT); |
425 __ sw(scratch_, FieldMemOperand(the_heap_number_, | 324 __ sw(scratch(), FieldMemOperand(the_heap_number(), |
426 HeapNumber::kMantissaOffset)); | 325 HeapNumber::kMantissaOffset)); |
427 | 326 |
428 __ bind(&max_negative_int); | 327 __ bind(&max_negative_int); |
429 // The max negative int32 is stored as a positive number in the mantissa of | 328 // The max negative int32 is stored as a positive number in the mantissa of |
430 // a double because it uses a sign bit instead of using two's complement. | 329 // a double because it uses a sign bit instead of using two's complement. |
431 // The actual mantissa bits stored are all 0 because the implicit most | 330 // The actual mantissa bits stored are all 0 because the implicit most |
432 // significant 1 bit is not stored. | 331 // significant 1 bit is not stored. |
433 non_smi_exponent += 1 << HeapNumber::kExponentShift; | 332 non_smi_exponent += 1 << HeapNumber::kExponentShift; |
434 __ li(scratch_, Operand(HeapNumber::kSignMask | non_smi_exponent)); | 333 __ li(scratch(), Operand(HeapNumber::kSignMask | non_smi_exponent)); |
435 __ sw(scratch_, | 334 __ sw(scratch(), |
436 FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); | 335 FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); |
437 __ mov(scratch_, zero_reg); | 336 __ mov(scratch(), zero_reg); |
438 __ Ret(USE_DELAY_SLOT); | 337 __ Ret(USE_DELAY_SLOT); |
439 __ sw(scratch_, | 338 __ sw(scratch(), |
440 FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); | 339 FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); |
441 } | 340 } |
442 | 341 |
443 | 342 |
444 // Handle the case where the lhs and rhs are the same object. | 343 // Handle the case where the lhs and rhs are the same object. |
445 // Equality is almost reflexive (everything but NaN), so this is a test | 344 // Equality is almost reflexive (everything but NaN), so this is a test |
446 // for "identity and not NaN". | 345 // for "identity and not NaN". |
447 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 346 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
448 Label* slow, | 347 Label* slow, |
449 Condition cc) { | 348 Condition cc) { |
450 Label not_identical; | 349 Label not_identical; |
(...skipping 3806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4257 __ dsll(index, index, kPointerSizeLog2); | 4156 __ dsll(index, index, kPointerSizeLog2); |
4258 __ Daddu(index, index, dictionary); | 4157 __ Daddu(index, index, dictionary); |
4259 __ ld(entry_key, FieldMemOperand(index, kElementsStartOffset)); | 4158 __ ld(entry_key, FieldMemOperand(index, kElementsStartOffset)); |
4260 | 4159 |
4261 // Having undefined at this place means the name is not contained. | 4160 // Having undefined at this place means the name is not contained. |
4262 __ Branch(¬_in_dictionary, eq, entry_key, Operand(undefined)); | 4161 __ Branch(¬_in_dictionary, eq, entry_key, Operand(undefined)); |
4263 | 4162 |
4264 // Stop if found the property. | 4163 // Stop if found the property. |
4265 __ Branch(&in_dictionary, eq, entry_key, Operand(key)); | 4164 __ Branch(&in_dictionary, eq, entry_key, Operand(key)); |
4266 | 4165 |
4267 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 4166 if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { |
4268 // Check if the entry name is not a unique name. | 4167 // Check if the entry name is not a unique name. |
4269 __ ld(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); | 4168 __ ld(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); |
4270 __ lbu(entry_key, | 4169 __ lbu(entry_key, |
4271 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); | 4170 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); |
4272 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary); | 4171 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary); |
4273 } | 4172 } |
4274 } | 4173 } |
4275 | 4174 |
4276 __ bind(&maybe_in_dictionary); | 4175 __ bind(&maybe_in_dictionary); |
4277 // If we are doing negative lookup then probing failure should be | 4176 // If we are doing negative lookup then probing failure should be |
4278 // treated as a lookup success. For positive lookup probing failure | 4177 // treated as a lookup success. For positive lookup probing failure |
4279 // should be treated as lookup failure. | 4178 // should be treated as lookup failure. |
4280 if (mode_ == POSITIVE_LOOKUP) { | 4179 if (mode() == POSITIVE_LOOKUP) { |
4281 __ Ret(USE_DELAY_SLOT); | 4180 __ Ret(USE_DELAY_SLOT); |
4282 __ mov(result, zero_reg); | 4181 __ mov(result, zero_reg); |
4283 } | 4182 } |
4284 | 4183 |
4285 __ bind(&in_dictionary); | 4184 __ bind(&in_dictionary); |
4286 __ Ret(USE_DELAY_SLOT); | 4185 __ Ret(USE_DELAY_SLOT); |
4287 __ li(result, 1); | 4186 __ li(result, 1); |
4288 | 4187 |
4289 __ bind(¬_in_dictionary); | 4188 __ bind(¬_in_dictionary); |
4290 __ Ret(USE_DELAY_SLOT); | 4189 __ Ret(USE_DELAY_SLOT); |
(...skipping 23 matching lines...) Expand all Loading... |
4314 // get the offset fixed up correctly by the bind(Label*) call. We patch it | 4213 // get the offset fixed up correctly by the bind(Label*) call. We patch it |
4315 // back and forth between a "bne zero_reg, zero_reg, ..." (a nop in this | 4214 // back and forth between a "bne zero_reg, zero_reg, ..." (a nop in this |
4316 // position) and the "beq zero_reg, zero_reg, ..." when we start and stop | 4215 // position) and the "beq zero_reg, zero_reg, ..." when we start and stop |
4317 // incremental heap marking. | 4216 // incremental heap marking. |
4318 // See RecordWriteStub::Patch for details. | 4217 // See RecordWriteStub::Patch for details. |
4319 __ beq(zero_reg, zero_reg, &skip_to_incremental_noncompacting); | 4218 __ beq(zero_reg, zero_reg, &skip_to_incremental_noncompacting); |
4320 __ nop(); | 4219 __ nop(); |
4321 __ beq(zero_reg, zero_reg, &skip_to_incremental_compacting); | 4220 __ beq(zero_reg, zero_reg, &skip_to_incremental_compacting); |
4322 __ nop(); | 4221 __ nop(); |
4323 | 4222 |
4324 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { | 4223 if (remembered_set_action() == EMIT_REMEMBERED_SET) { |
4325 __ RememberedSetHelper(object_, | 4224 __ RememberedSetHelper(object(), |
4326 address_, | 4225 address(), |
4327 value_, | 4226 value(), |
4328 save_fp_regs_mode_, | 4227 save_fp_regs_mode(), |
4329 MacroAssembler::kReturnAtEnd); | 4228 MacroAssembler::kReturnAtEnd); |
4330 } | 4229 } |
4331 __ Ret(); | 4230 __ Ret(); |
4332 | 4231 |
4333 __ bind(&skip_to_incremental_noncompacting); | 4232 __ bind(&skip_to_incremental_noncompacting); |
4334 GenerateIncremental(masm, INCREMENTAL); | 4233 GenerateIncremental(masm, INCREMENTAL); |
4335 | 4234 |
4336 __ bind(&skip_to_incremental_compacting); | 4235 __ bind(&skip_to_incremental_compacting); |
4337 GenerateIncremental(masm, INCREMENTAL_COMPACTION); | 4236 GenerateIncremental(masm, INCREMENTAL_COMPACTION); |
4338 | 4237 |
4339 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. | 4238 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. |
4340 // Will be checked in IncrementalMarking::ActivateGeneratedStub. | 4239 // Will be checked in IncrementalMarking::ActivateGeneratedStub. |
4341 | 4240 |
4342 PatchBranchIntoNop(masm, 0); | 4241 PatchBranchIntoNop(masm, 0); |
4343 PatchBranchIntoNop(masm, 2 * Assembler::kInstrSize); | 4242 PatchBranchIntoNop(masm, 2 * Assembler::kInstrSize); |
4344 } | 4243 } |
4345 | 4244 |
4346 | 4245 |
4347 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { | 4246 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { |
4348 regs_.Save(masm); | 4247 regs_.Save(masm); |
4349 | 4248 |
4350 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { | 4249 if (remembered_set_action() == EMIT_REMEMBERED_SET) { |
4351 Label dont_need_remembered_set; | 4250 Label dont_need_remembered_set; |
4352 | 4251 |
4353 __ ld(regs_.scratch0(), MemOperand(regs_.address(), 0)); | 4252 __ ld(regs_.scratch0(), MemOperand(regs_.address(), 0)); |
4354 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. | 4253 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. |
4355 regs_.scratch0(), | 4254 regs_.scratch0(), |
4356 &dont_need_remembered_set); | 4255 &dont_need_remembered_set); |
4357 | 4256 |
4358 __ CheckPageFlag(regs_.object(), | 4257 __ CheckPageFlag(regs_.object(), |
4359 regs_.scratch0(), | 4258 regs_.scratch0(), |
4360 1 << MemoryChunk::SCAN_ON_SCAVENGE, | 4259 1 << MemoryChunk::SCAN_ON_SCAVENGE, |
4361 ne, | 4260 ne, |
4362 &dont_need_remembered_set); | 4261 &dont_need_remembered_set); |
4363 | 4262 |
4364 // First notify the incremental marker if necessary, then update the | 4263 // First notify the incremental marker if necessary, then update the |
4365 // remembered set. | 4264 // remembered set. |
4366 CheckNeedsToInformIncrementalMarker( | 4265 CheckNeedsToInformIncrementalMarker( |
4367 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); | 4266 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); |
4368 InformIncrementalMarker(masm); | 4267 InformIncrementalMarker(masm); |
4369 regs_.Restore(masm); | 4268 regs_.Restore(masm); |
4370 __ RememberedSetHelper(object_, | 4269 __ RememberedSetHelper(object(), |
4371 address_, | 4270 address(), |
4372 value_, | 4271 value(), |
4373 save_fp_regs_mode_, | 4272 save_fp_regs_mode(), |
4374 MacroAssembler::kReturnAtEnd); | 4273 MacroAssembler::kReturnAtEnd); |
4375 | 4274 |
4376 __ bind(&dont_need_remembered_set); | 4275 __ bind(&dont_need_remembered_set); |
4377 } | 4276 } |
4378 | 4277 |
4379 CheckNeedsToInformIncrementalMarker( | 4278 CheckNeedsToInformIncrementalMarker( |
4380 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); | 4279 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); |
4381 InformIncrementalMarker(masm); | 4280 InformIncrementalMarker(masm); |
4382 regs_.Restore(masm); | 4281 regs_.Restore(masm); |
4383 __ Ret(); | 4282 __ Ret(); |
4384 } | 4283 } |
4385 | 4284 |
4386 | 4285 |
4387 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { | 4286 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { |
4388 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 4287 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); |
4389 int argument_count = 3; | 4288 int argument_count = 3; |
4390 __ PrepareCallCFunction(argument_count, regs_.scratch0()); | 4289 __ PrepareCallCFunction(argument_count, regs_.scratch0()); |
4391 Register address = | 4290 Register address = |
4392 a0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); | 4291 a0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); |
4393 DCHECK(!address.is(regs_.object())); | 4292 DCHECK(!address.is(regs_.object())); |
4394 DCHECK(!address.is(a0)); | 4293 DCHECK(!address.is(a0)); |
4395 __ Move(address, regs_.address()); | 4294 __ Move(address, regs_.address()); |
4396 __ Move(a0, regs_.object()); | 4295 __ Move(a0, regs_.object()); |
4397 __ Move(a1, address); | 4296 __ Move(a1, address); |
4398 __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); | 4297 __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); |
4399 | 4298 |
4400 AllowExternalCallThatCantCauseGC scope(masm); | 4299 AllowExternalCallThatCantCauseGC scope(masm); |
4401 __ CallCFunction( | 4300 __ CallCFunction( |
4402 ExternalReference::incremental_marking_record_write_function(isolate()), | 4301 ExternalReference::incremental_marking_record_write_function(isolate()), |
4403 argument_count); | 4302 argument_count); |
4404 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); | 4303 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); |
4405 } | 4304 } |
4406 | 4305 |
4407 | 4306 |
4408 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( | 4307 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( |
4409 MacroAssembler* masm, | 4308 MacroAssembler* masm, |
4410 OnNoNeedToInformIncrementalMarker on_no_need, | 4309 OnNoNeedToInformIncrementalMarker on_no_need, |
4411 Mode mode) { | 4310 Mode mode) { |
4412 Label on_black; | 4311 Label on_black; |
4413 Label need_incremental; | 4312 Label need_incremental; |
4414 Label need_incremental_pop_scratch; | 4313 Label need_incremental_pop_scratch; |
4415 | 4314 |
4416 __ And(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask)); | 4315 __ And(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask)); |
4417 __ ld(regs_.scratch1(), | 4316 __ ld(regs_.scratch1(), |
4418 MemOperand(regs_.scratch0(), | 4317 MemOperand(regs_.scratch0(), |
4419 MemoryChunk::kWriteBarrierCounterOffset)); | 4318 MemoryChunk::kWriteBarrierCounterOffset)); |
4420 __ Dsubu(regs_.scratch1(), regs_.scratch1(), Operand(1)); | 4319 __ Dsubu(regs_.scratch1(), regs_.scratch1(), Operand(1)); |
4421 __ sd(regs_.scratch1(), | 4320 __ sd(regs_.scratch1(), |
4422 MemOperand(regs_.scratch0(), | 4321 MemOperand(regs_.scratch0(), |
4423 MemoryChunk::kWriteBarrierCounterOffset)); | 4322 MemoryChunk::kWriteBarrierCounterOffset)); |
4424 __ Branch(&need_incremental, lt, regs_.scratch1(), Operand(zero_reg)); | 4323 __ Branch(&need_incremental, lt, regs_.scratch1(), Operand(zero_reg)); |
4425 | 4324 |
4426 // Let's look at the color of the object: If it is not black we don't have | 4325 // Let's look at the color of the object: If it is not black we don't have |
4427 // to inform the incremental marker. | 4326 // to inform the incremental marker. |
4428 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); | 4327 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); |
4429 | 4328 |
4430 regs_.Restore(masm); | 4329 regs_.Restore(masm); |
4431 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { | 4330 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { |
4432 __ RememberedSetHelper(object_, | 4331 __ RememberedSetHelper(object(), |
4433 address_, | 4332 address(), |
4434 value_, | 4333 value(), |
4435 save_fp_regs_mode_, | 4334 save_fp_regs_mode(), |
4436 MacroAssembler::kReturnAtEnd); | 4335 MacroAssembler::kReturnAtEnd); |
4437 } else { | 4336 } else { |
4438 __ Ret(); | 4337 __ Ret(); |
4439 } | 4338 } |
4440 | 4339 |
4441 __ bind(&on_black); | 4340 __ bind(&on_black); |
4442 | 4341 |
4443 // Get the value from the slot. | 4342 // Get the value from the slot. |
4444 __ ld(regs_.scratch0(), MemOperand(regs_.address(), 0)); | 4343 __ ld(regs_.scratch0(), MemOperand(regs_.address(), 0)); |
4445 | 4344 |
(...skipping 20 matching lines...) Expand all Loading... |
4466 __ Push(regs_.object(), regs_.address()); | 4365 __ Push(regs_.object(), regs_.address()); |
4467 __ EnsureNotWhite(regs_.scratch0(), // The value. | 4366 __ EnsureNotWhite(regs_.scratch0(), // The value. |
4468 regs_.scratch1(), // Scratch. | 4367 regs_.scratch1(), // Scratch. |
4469 regs_.object(), // Scratch. | 4368 regs_.object(), // Scratch. |
4470 regs_.address(), // Scratch. | 4369 regs_.address(), // Scratch. |
4471 &need_incremental_pop_scratch); | 4370 &need_incremental_pop_scratch); |
4472 __ Pop(regs_.object(), regs_.address()); | 4371 __ Pop(regs_.object(), regs_.address()); |
4473 | 4372 |
4474 regs_.Restore(masm); | 4373 regs_.Restore(masm); |
4475 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { | 4374 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { |
4476 __ RememberedSetHelper(object_, | 4375 __ RememberedSetHelper(object(), |
4477 address_, | 4376 address(), |
4478 value_, | 4377 value(), |
4479 save_fp_regs_mode_, | 4378 save_fp_regs_mode(), |
4480 MacroAssembler::kReturnAtEnd); | 4379 MacroAssembler::kReturnAtEnd); |
4481 } else { | 4380 } else { |
4482 __ Ret(); | 4381 __ Ret(); |
4483 } | 4382 } |
4484 | 4383 |
4485 __ bind(&need_incremental_pop_scratch); | 4384 __ bind(&need_incremental_pop_scratch); |
4486 __ Pop(regs_.object(), regs_.address()); | 4385 __ Pop(regs_.object(), regs_.address()); |
4487 | 4386 |
4488 __ bind(&need_incremental); | 4387 __ bind(&need_incremental); |
4489 | 4388 |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5077 MemOperand(fp, 6 * kPointerSize), | 4976 MemOperand(fp, 6 * kPointerSize), |
5078 NULL); | 4977 NULL); |
5079 } | 4978 } |
5080 | 4979 |
5081 | 4980 |
5082 #undef __ | 4981 #undef __ |
5083 | 4982 |
5084 } } // namespace v8::internal | 4983 } } // namespace v8::internal |
5085 | 4984 |
5086 #endif // V8_TARGET_ARCH_MIPS64 | 4985 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |