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