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_ARM | 7 #if V8_TARGET_ARCH_ARM |
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 __ push(descriptor->GetEnvironmentParameterRegister(i)); | 139 __ push(descriptor->GetEnvironmentParameterRegister(i)); |
140 } | 140 } |
141 ExternalReference miss = descriptor->miss_handler(); | 141 ExternalReference miss = descriptor->miss_handler(); |
142 __ CallExternalReference(miss, param_count); | 142 __ CallExternalReference(miss, param_count); |
143 } | 143 } |
144 | 144 |
145 __ Ret(); | 145 __ Ret(); |
146 } | 146 } |
147 | 147 |
148 | 148 |
149 // Takes a Smi and converts to an IEEE 64 bit floating point value in two | |
150 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and | |
151 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a | |
152 // scratch register. Destroys the source register. No GC occurs during this | |
153 // stub so you don't have to set up the frame. | |
154 class ConvertToDoubleStub : public PlatformCodeStub { | |
155 public: | |
156 ConvertToDoubleStub(Isolate* isolate, | |
157 Register result_reg_1, | |
158 Register result_reg_2, | |
159 Register source_reg, | |
160 Register scratch_reg) | |
161 : PlatformCodeStub(isolate), | |
162 result1_(result_reg_1), | |
163 result2_(result_reg_2), | |
164 source_(source_reg), | |
165 zeros_(scratch_reg) { } | |
166 | |
167 private: | |
168 Register result1_; | |
169 Register result2_; | |
170 Register source_; | |
171 Register zeros_; | |
172 | |
173 // Minor key encoding in 16 bits. | |
174 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; | |
175 class OpBits: public BitField<Token::Value, 2, 14> {}; | |
176 | |
177 Major MajorKey() const { return ConvertToDouble; } | |
178 uint32_t MinorKey() const { | |
179 // Encode the parameters in a unique 16 bit value. | |
180 return result1_.code() + | |
181 (result2_.code() << 4) + | |
182 (source_.code() << 8) + | |
183 (zeros_.code() << 12); | |
184 } | |
185 | |
186 void Generate(MacroAssembler* masm); | |
187 }; | |
188 | |
189 | |
190 void ConvertToDoubleStub::Generate(MacroAssembler* masm) { | |
191 Register exponent = result1_; | |
192 Register mantissa = result2_; | |
193 | |
194 Label not_special; | |
195 __ SmiUntag(source_); | |
196 // Move sign bit from source to destination. This works because the sign bit | |
197 // in the exponent word of the double has the same position and polarity as | |
198 // the 2's complement sign bit in a Smi. | |
199 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); | |
200 __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC); | |
201 // Subtract from 0 if source was negative. | |
202 __ rsb(source_, source_, Operand::Zero(), LeaveCC, ne); | |
203 | |
204 // We have -1, 0 or 1, which we treat specially. Register source_ contains | |
205 // absolute value: it is either equal to 1 (special case of -1 and 1), | |
206 // greater than 1 (not a special case) or less than 1 (special case of 0). | |
207 __ cmp(source_, Operand(1)); | |
208 __ b(gt, ¬_special); | |
209 | |
210 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). | |
211 const uint32_t exponent_word_for_1 = | |
212 HeapNumber::kExponentBias << HeapNumber::kExponentShift; | |
213 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq); | |
214 // 1, 0 and -1 all have 0 for the second word. | |
215 __ mov(mantissa, Operand::Zero()); | |
216 __ Ret(); | |
217 | |
218 __ bind(¬_special); | |
219 __ clz(zeros_, source_); | |
220 // Compute exponent and or it into the exponent register. | |
221 // We use mantissa as a scratch register here. Use a fudge factor to | |
222 // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts | |
223 // that fit in the ARM's constant field. | |
224 int fudge = 0x400; | |
225 __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias - fudge)); | |
226 __ add(mantissa, mantissa, Operand(fudge)); | |
227 __ orr(exponent, | |
228 exponent, | |
229 Operand(mantissa, LSL, HeapNumber::kExponentShift)); | |
230 // Shift up the source chopping the top bit off. | |
231 __ add(zeros_, zeros_, Operand(1)); | |
232 // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. | |
233 __ mov(source_, Operand(source_, LSL, zeros_)); | |
234 // Compute lower part of fraction (last 12 bits). | |
235 __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord)); | |
236 // And the top (top 20 bits). | |
237 __ orr(exponent, | |
238 exponent, | |
239 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); | |
240 __ Ret(); | |
241 } | |
242 | |
243 | |
244 void DoubleToIStub::Generate(MacroAssembler* masm) { | 149 void DoubleToIStub::Generate(MacroAssembler* masm) { |
245 Label out_of_range, only_low, negate, done; | 150 Label out_of_range, only_low, negate, done; |
246 Register input_reg = source(); | 151 Register input_reg = source(); |
247 Register result_reg = destination(); | 152 Register result_reg = destination(); |
248 DCHECK(is_truncating()); | 153 DCHECK(is_truncating()); |
249 | 154 |
250 int double_offset = offset(); | 155 int double_offset = offset(); |
251 // Account for saved regs if input is sp. | 156 // Account for saved regs if input is sp. |
252 if (input_reg.is(sp)) double_offset += 3 * kPointerSize; | 157 if (input_reg.is(sp)) double_offset += 3 * kPointerSize; |
253 | 158 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 } | 260 } |
356 | 261 |
357 | 262 |
358 // See comment for class. | 263 // See comment for class. |
359 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { | 264 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { |
360 Label max_negative_int; | 265 Label max_negative_int; |
361 // the_int_ has the answer which is a signed int32 but not a Smi. | 266 // the_int_ has the answer which is a signed int32 but not a Smi. |
362 // We test for the special value that has a different exponent. This test | 267 // We test for the special value that has a different exponent. This test |
363 // has the neat side effect of setting the flags according to the sign. | 268 // has the neat side effect of setting the flags according to the sign. |
364 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); | 269 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); |
365 __ cmp(the_int_, Operand(0x80000000u)); | 270 __ cmp(the_int(), Operand(0x80000000u)); |
366 __ b(eq, &max_negative_int); | 271 __ b(eq, &max_negative_int); |
367 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. | 272 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. |
368 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). | 273 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). |
369 uint32_t non_smi_exponent = | 274 uint32_t non_smi_exponent = |
370 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; | 275 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; |
371 __ mov(scratch_, Operand(non_smi_exponent)); | 276 __ mov(scratch(), Operand(non_smi_exponent)); |
372 // Set the sign bit in scratch_ if the value was negative. | 277 // Set the sign bit in scratch_ if the value was negative. |
373 __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs); | 278 __ orr(scratch(), scratch(), Operand(HeapNumber::kSignMask), LeaveCC, cs); |
374 // Subtract from 0 if the value was negative. | 279 // Subtract from 0 if the value was negative. |
375 __ rsb(the_int_, the_int_, Operand::Zero(), LeaveCC, cs); | 280 __ rsb(the_int(), the_int(), Operand::Zero(), LeaveCC, cs); |
376 // We should be masking the implict first digit of the mantissa away here, | 281 // We should be masking the implict first digit of the mantissa away here, |
377 // but it just ends up combining harmlessly with the last digit of the | 282 // but it just ends up combining harmlessly with the last digit of the |
378 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get | 283 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get |
379 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. | 284 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. |
380 DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); | 285 DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); |
381 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; | 286 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; |
382 __ orr(scratch_, scratch_, Operand(the_int_, LSR, shift_distance)); | 287 __ orr(scratch(), scratch(), Operand(the_int(), LSR, shift_distance)); |
383 __ str(scratch_, FieldMemOperand(the_heap_number_, | 288 __ str(scratch(), |
384 HeapNumber::kExponentOffset)); | 289 FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); |
385 __ mov(scratch_, Operand(the_int_, LSL, 32 - shift_distance)); | 290 __ mov(scratch(), Operand(the_int(), LSL, 32 - shift_distance)); |
386 __ str(scratch_, FieldMemOperand(the_heap_number_, | 291 __ str(scratch(), |
387 HeapNumber::kMantissaOffset)); | 292 FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); |
388 __ Ret(); | 293 __ Ret(); |
389 | 294 |
390 __ bind(&max_negative_int); | 295 __ bind(&max_negative_int); |
391 // The max negative int32 is stored as a positive number in the mantissa of | 296 // The max negative int32 is stored as a positive number in the mantissa of |
392 // a double because it uses a sign bit instead of using two's complement. | 297 // a double because it uses a sign bit instead of using two's complement. |
393 // The actual mantissa bits stored are all 0 because the implicit most | 298 // The actual mantissa bits stored are all 0 because the implicit most |
394 // significant 1 bit is not stored. | 299 // significant 1 bit is not stored. |
395 non_smi_exponent += 1 << HeapNumber::kExponentShift; | 300 non_smi_exponent += 1 << HeapNumber::kExponentShift; |
396 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); | 301 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); |
397 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); | 302 __ str(ip, FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); |
398 __ mov(ip, Operand::Zero()); | 303 __ mov(ip, Operand::Zero()); |
399 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); | 304 __ str(ip, FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); |
400 __ Ret(); | 305 __ Ret(); |
401 } | 306 } |
402 | 307 |
403 | 308 |
404 // Handle the case where the lhs and rhs are the same object. | 309 // Handle the case where the lhs and rhs are the same object. |
405 // Equality is almost reflexive (everything but NaN), so this is a test | 310 // Equality is almost reflexive (everything but NaN), so this is a test |
406 // for "identity and not NaN". | 311 // for "identity and not NaN". |
407 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 312 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
408 Label* slow, | 313 Label* slow, |
409 Condition cond) { | 314 Condition cond) { |
(...skipping 3591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4001 __ ldr(entry_key, FieldMemOperand(index, kElementsStartOffset)); | 3906 __ ldr(entry_key, FieldMemOperand(index, kElementsStartOffset)); |
4002 | 3907 |
4003 // Having undefined at this place means the name is not contained. | 3908 // Having undefined at this place means the name is not contained. |
4004 __ cmp(entry_key, Operand(undefined)); | 3909 __ cmp(entry_key, Operand(undefined)); |
4005 __ b(eq, ¬_in_dictionary); | 3910 __ b(eq, ¬_in_dictionary); |
4006 | 3911 |
4007 // Stop if found the property. | 3912 // Stop if found the property. |
4008 __ cmp(entry_key, Operand(key)); | 3913 __ cmp(entry_key, Operand(key)); |
4009 __ b(eq, &in_dictionary); | 3914 __ b(eq, &in_dictionary); |
4010 | 3915 |
4011 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 3916 if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { |
4012 // Check if the entry name is not a unique name. | 3917 // Check if the entry name is not a unique name. |
4013 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); | 3918 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); |
4014 __ ldrb(entry_key, | 3919 __ ldrb(entry_key, |
4015 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); | 3920 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); |
4016 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary); | 3921 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary); |
4017 } | 3922 } |
4018 } | 3923 } |
4019 | 3924 |
4020 __ bind(&maybe_in_dictionary); | 3925 __ bind(&maybe_in_dictionary); |
4021 // If we are doing negative lookup then probing failure should be | 3926 // If we are doing negative lookup then probing failure should be |
4022 // treated as a lookup success. For positive lookup probing failure | 3927 // treated as a lookup success. For positive lookup probing failure |
4023 // should be treated as lookup failure. | 3928 // should be treated as lookup failure. |
4024 if (mode_ == POSITIVE_LOOKUP) { | 3929 if (mode() == POSITIVE_LOOKUP) { |
4025 __ mov(result, Operand::Zero()); | 3930 __ mov(result, Operand::Zero()); |
4026 __ Ret(); | 3931 __ Ret(); |
4027 } | 3932 } |
4028 | 3933 |
4029 __ bind(&in_dictionary); | 3934 __ bind(&in_dictionary); |
4030 __ mov(result, Operand(1)); | 3935 __ mov(result, Operand(1)); |
4031 __ Ret(); | 3936 __ Ret(); |
4032 | 3937 |
4033 __ bind(¬_in_dictionary); | 3938 __ bind(¬_in_dictionary); |
4034 __ mov(result, Operand::Zero()); | 3939 __ mov(result, Operand::Zero()); |
(...skipping 25 matching lines...) Expand all Loading... |
4060 // real branch when we start and stop incremental heap marking. | 3965 // real branch when we start and stop incremental heap marking. |
4061 // See RecordWriteStub::Patch for details. | 3966 // See RecordWriteStub::Patch for details. |
4062 { | 3967 { |
4063 // Block literal pool emission, as the position of these two instructions | 3968 // Block literal pool emission, as the position of these two instructions |
4064 // is assumed by the patching code. | 3969 // is assumed by the patching code. |
4065 Assembler::BlockConstPoolScope block_const_pool(masm); | 3970 Assembler::BlockConstPoolScope block_const_pool(masm); |
4066 __ b(&skip_to_incremental_noncompacting); | 3971 __ b(&skip_to_incremental_noncompacting); |
4067 __ b(&skip_to_incremental_compacting); | 3972 __ b(&skip_to_incremental_compacting); |
4068 } | 3973 } |
4069 | 3974 |
4070 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { | 3975 if (remembered_set_action() == EMIT_REMEMBERED_SET) { |
4071 __ RememberedSetHelper(object_, | 3976 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), |
4072 address_, | |
4073 value_, | |
4074 save_fp_regs_mode_, | |
4075 MacroAssembler::kReturnAtEnd); | 3977 MacroAssembler::kReturnAtEnd); |
4076 } | 3978 } |
4077 __ Ret(); | 3979 __ Ret(); |
4078 | 3980 |
4079 __ bind(&skip_to_incremental_noncompacting); | 3981 __ bind(&skip_to_incremental_noncompacting); |
4080 GenerateIncremental(masm, INCREMENTAL); | 3982 GenerateIncremental(masm, INCREMENTAL); |
4081 | 3983 |
4082 __ bind(&skip_to_incremental_compacting); | 3984 __ bind(&skip_to_incremental_compacting); |
4083 GenerateIncremental(masm, INCREMENTAL_COMPACTION); | 3985 GenerateIncremental(masm, INCREMENTAL_COMPACTION); |
4084 | 3986 |
4085 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. | 3987 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. |
4086 // Will be checked in IncrementalMarking::ActivateGeneratedStub. | 3988 // Will be checked in IncrementalMarking::ActivateGeneratedStub. |
4087 DCHECK(Assembler::GetBranchOffset(masm->instr_at(0)) < (1 << 12)); | 3989 DCHECK(Assembler::GetBranchOffset(masm->instr_at(0)) < (1 << 12)); |
4088 DCHECK(Assembler::GetBranchOffset(masm->instr_at(4)) < (1 << 12)); | 3990 DCHECK(Assembler::GetBranchOffset(masm->instr_at(4)) < (1 << 12)); |
4089 PatchBranchIntoNop(masm, 0); | 3991 PatchBranchIntoNop(masm, 0); |
4090 PatchBranchIntoNop(masm, Assembler::kInstrSize); | 3992 PatchBranchIntoNop(masm, Assembler::kInstrSize); |
4091 } | 3993 } |
4092 | 3994 |
4093 | 3995 |
4094 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { | 3996 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { |
4095 regs_.Save(masm); | 3997 regs_.Save(masm); |
4096 | 3998 |
4097 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { | 3999 if (remembered_set_action() == EMIT_REMEMBERED_SET) { |
4098 Label dont_need_remembered_set; | 4000 Label dont_need_remembered_set; |
4099 | 4001 |
4100 __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); | 4002 __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); |
4101 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. | 4003 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. |
4102 regs_.scratch0(), | 4004 regs_.scratch0(), |
4103 &dont_need_remembered_set); | 4005 &dont_need_remembered_set); |
4104 | 4006 |
4105 __ CheckPageFlag(regs_.object(), | 4007 __ CheckPageFlag(regs_.object(), |
4106 regs_.scratch0(), | 4008 regs_.scratch0(), |
4107 1 << MemoryChunk::SCAN_ON_SCAVENGE, | 4009 1 << MemoryChunk::SCAN_ON_SCAVENGE, |
4108 ne, | 4010 ne, |
4109 &dont_need_remembered_set); | 4011 &dont_need_remembered_set); |
4110 | 4012 |
4111 // First notify the incremental marker if necessary, then update the | 4013 // First notify the incremental marker if necessary, then update the |
4112 // remembered set. | 4014 // remembered set. |
4113 CheckNeedsToInformIncrementalMarker( | 4015 CheckNeedsToInformIncrementalMarker( |
4114 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); | 4016 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); |
4115 InformIncrementalMarker(masm); | 4017 InformIncrementalMarker(masm); |
4116 regs_.Restore(masm); | 4018 regs_.Restore(masm); |
4117 __ RememberedSetHelper(object_, | 4019 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), |
4118 address_, | |
4119 value_, | |
4120 save_fp_regs_mode_, | |
4121 MacroAssembler::kReturnAtEnd); | 4020 MacroAssembler::kReturnAtEnd); |
4122 | 4021 |
4123 __ bind(&dont_need_remembered_set); | 4022 __ bind(&dont_need_remembered_set); |
4124 } | 4023 } |
4125 | 4024 |
4126 CheckNeedsToInformIncrementalMarker( | 4025 CheckNeedsToInformIncrementalMarker( |
4127 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); | 4026 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); |
4128 InformIncrementalMarker(masm); | 4027 InformIncrementalMarker(masm); |
4129 regs_.Restore(masm); | 4028 regs_.Restore(masm); |
4130 __ Ret(); | 4029 __ Ret(); |
4131 } | 4030 } |
4132 | 4031 |
4133 | 4032 |
4134 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { | 4033 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { |
4135 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 4034 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); |
4136 int argument_count = 3; | 4035 int argument_count = 3; |
4137 __ PrepareCallCFunction(argument_count, regs_.scratch0()); | 4036 __ PrepareCallCFunction(argument_count, regs_.scratch0()); |
4138 Register address = | 4037 Register address = |
4139 r0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); | 4038 r0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); |
4140 DCHECK(!address.is(regs_.object())); | 4039 DCHECK(!address.is(regs_.object())); |
4141 DCHECK(!address.is(r0)); | 4040 DCHECK(!address.is(r0)); |
4142 __ Move(address, regs_.address()); | 4041 __ Move(address, regs_.address()); |
4143 __ Move(r0, regs_.object()); | 4042 __ Move(r0, regs_.object()); |
4144 __ Move(r1, address); | 4043 __ Move(r1, address); |
4145 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); | 4044 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); |
4146 | 4045 |
4147 AllowExternalCallThatCantCauseGC scope(masm); | 4046 AllowExternalCallThatCantCauseGC scope(masm); |
4148 __ CallCFunction( | 4047 __ CallCFunction( |
4149 ExternalReference::incremental_marking_record_write_function(isolate()), | 4048 ExternalReference::incremental_marking_record_write_function(isolate()), |
4150 argument_count); | 4049 argument_count); |
4151 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); | 4050 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); |
4152 } | 4051 } |
4153 | 4052 |
4154 | 4053 |
4155 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( | 4054 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( |
4156 MacroAssembler* masm, | 4055 MacroAssembler* masm, |
4157 OnNoNeedToInformIncrementalMarker on_no_need, | 4056 OnNoNeedToInformIncrementalMarker on_no_need, |
4158 Mode mode) { | 4057 Mode mode) { |
4159 Label on_black; | 4058 Label on_black; |
4160 Label need_incremental; | 4059 Label need_incremental; |
4161 Label need_incremental_pop_scratch; | 4060 Label need_incremental_pop_scratch; |
4162 | 4061 |
4163 __ and_(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask)); | 4062 __ and_(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask)); |
4164 __ ldr(regs_.scratch1(), | 4063 __ ldr(regs_.scratch1(), |
4165 MemOperand(regs_.scratch0(), | 4064 MemOperand(regs_.scratch0(), |
4166 MemoryChunk::kWriteBarrierCounterOffset)); | 4065 MemoryChunk::kWriteBarrierCounterOffset)); |
4167 __ sub(regs_.scratch1(), regs_.scratch1(), Operand(1), SetCC); | 4066 __ sub(regs_.scratch1(), regs_.scratch1(), Operand(1), SetCC); |
4168 __ str(regs_.scratch1(), | 4067 __ str(regs_.scratch1(), |
4169 MemOperand(regs_.scratch0(), | 4068 MemOperand(regs_.scratch0(), |
4170 MemoryChunk::kWriteBarrierCounterOffset)); | 4069 MemoryChunk::kWriteBarrierCounterOffset)); |
4171 __ b(mi, &need_incremental); | 4070 __ b(mi, &need_incremental); |
4172 | 4071 |
4173 // Let's look at the color of the object: If it is not black we don't have | 4072 // Let's look at the color of the object: If it is not black we don't have |
4174 // to inform the incremental marker. | 4073 // to inform the incremental marker. |
4175 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); | 4074 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); |
4176 | 4075 |
4177 regs_.Restore(masm); | 4076 regs_.Restore(masm); |
4178 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { | 4077 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { |
4179 __ RememberedSetHelper(object_, | 4078 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), |
4180 address_, | |
4181 value_, | |
4182 save_fp_regs_mode_, | |
4183 MacroAssembler::kReturnAtEnd); | 4079 MacroAssembler::kReturnAtEnd); |
4184 } else { | 4080 } else { |
4185 __ Ret(); | 4081 __ Ret(); |
4186 } | 4082 } |
4187 | 4083 |
4188 __ bind(&on_black); | 4084 __ bind(&on_black); |
4189 | 4085 |
4190 // Get the value from the slot. | 4086 // Get the value from the slot. |
4191 __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); | 4087 __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); |
4192 | 4088 |
(...skipping 20 matching lines...) Expand all Loading... |
4213 __ Push(regs_.object(), regs_.address()); | 4109 __ Push(regs_.object(), regs_.address()); |
4214 __ EnsureNotWhite(regs_.scratch0(), // The value. | 4110 __ EnsureNotWhite(regs_.scratch0(), // The value. |
4215 regs_.scratch1(), // Scratch. | 4111 regs_.scratch1(), // Scratch. |
4216 regs_.object(), // Scratch. | 4112 regs_.object(), // Scratch. |
4217 regs_.address(), // Scratch. | 4113 regs_.address(), // Scratch. |
4218 &need_incremental_pop_scratch); | 4114 &need_incremental_pop_scratch); |
4219 __ Pop(regs_.object(), regs_.address()); | 4115 __ Pop(regs_.object(), regs_.address()); |
4220 | 4116 |
4221 regs_.Restore(masm); | 4117 regs_.Restore(masm); |
4222 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { | 4118 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { |
4223 __ RememberedSetHelper(object_, | 4119 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), |
4224 address_, | |
4225 value_, | |
4226 save_fp_regs_mode_, | |
4227 MacroAssembler::kReturnAtEnd); | 4120 MacroAssembler::kReturnAtEnd); |
4228 } else { | 4121 } else { |
4229 __ Ret(); | 4122 __ Ret(); |
4230 } | 4123 } |
4231 | 4124 |
4232 __ bind(&need_incremental_pop_scratch); | 4125 __ bind(&need_incremental_pop_scratch); |
4233 __ Pop(regs_.object(), regs_.address()); | 4126 __ Pop(regs_.object(), regs_.address()); |
4234 | 4127 |
4235 __ bind(&need_incremental); | 4128 __ bind(&need_incremental); |
4236 | 4129 |
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4834 MemOperand(fp, 6 * kPointerSize), | 4727 MemOperand(fp, 6 * kPointerSize), |
4835 NULL); | 4728 NULL); |
4836 } | 4729 } |
4837 | 4730 |
4838 | 4731 |
4839 #undef __ | 4732 #undef __ |
4840 | 4733 |
4841 } } // namespace v8::internal | 4734 } } // namespace v8::internal |
4842 | 4735 |
4843 #endif // V8_TARGET_ARCH_ARM | 4736 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |