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_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 } | 285 } |
286 | 286 |
287 | 287 |
288 void MacroAssembler::RecordWriteField( | 288 void MacroAssembler::RecordWriteField( |
289 Register object, | 289 Register object, |
290 int offset, | 290 int offset, |
291 Register value, | 291 Register value, |
292 Register dst, | 292 Register dst, |
293 SaveFPRegsMode save_fp, | 293 SaveFPRegsMode save_fp, |
294 RememberedSetAction remembered_set_action, | 294 RememberedSetAction remembered_set_action, |
295 SmiCheck smi_check) { | 295 SmiCheck smi_check, |
| 296 PointersToHereCheck pointers_to_here_check_for_value) { |
296 // First, check if a write barrier is even needed. The tests below | 297 // First, check if a write barrier is even needed. The tests below |
297 // catch stores of Smis. | 298 // catch stores of Smis. |
298 Label done; | 299 Label done; |
299 | 300 |
300 // Skip barrier if writing a smi. | 301 // Skip barrier if writing a smi. |
301 if (smi_check == INLINE_SMI_CHECK) { | 302 if (smi_check == INLINE_SMI_CHECK) { |
302 JumpIfSmi(value, &done); | 303 JumpIfSmi(value, &done); |
303 } | 304 } |
304 | 305 |
305 // Although the object register is tagged, the offset is relative to the start | 306 // Although the object register is tagged, the offset is relative to the start |
306 // of the object, so so offset must be a multiple of kPointerSize. | 307 // of the object, so so offset must be a multiple of kPointerSize. |
307 ASSERT(IsAligned(offset, kPointerSize)); | 308 ASSERT(IsAligned(offset, kPointerSize)); |
308 | 309 |
309 leap(dst, FieldOperand(object, offset)); | 310 leap(dst, FieldOperand(object, offset)); |
310 if (emit_debug_code()) { | 311 if (emit_debug_code()) { |
311 Label ok; | 312 Label ok; |
312 testb(dst, Immediate((1 << kPointerSizeLog2) - 1)); | 313 testb(dst, Immediate((1 << kPointerSizeLog2) - 1)); |
313 j(zero, &ok, Label::kNear); | 314 j(zero, &ok, Label::kNear); |
314 int3(); | 315 int3(); |
315 bind(&ok); | 316 bind(&ok); |
316 } | 317 } |
317 | 318 |
318 RecordWrite( | 319 RecordWrite(object, dst, value, save_fp, remembered_set_action, |
319 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); | 320 OMIT_SMI_CHECK, pointers_to_here_check_for_value); |
320 | 321 |
321 bind(&done); | 322 bind(&done); |
322 | 323 |
323 // Clobber clobbered input registers when running with the debug-code flag | 324 // Clobber clobbered input registers when running with the debug-code flag |
324 // turned on to provoke errors. | 325 // turned on to provoke errors. |
325 if (emit_debug_code()) { | 326 if (emit_debug_code()) { |
326 Move(value, kZapValue, Assembler::RelocInfoNone()); | 327 Move(value, kZapValue, Assembler::RelocInfoNone()); |
327 Move(dst, kZapValue, Assembler::RelocInfoNone()); | 328 Move(dst, kZapValue, Assembler::RelocInfoNone()); |
328 } | 329 } |
329 } | 330 } |
330 | 331 |
331 | 332 |
332 void MacroAssembler::RecordWriteArray(Register object, | 333 void MacroAssembler::RecordWriteArray( |
333 Register value, | 334 Register object, |
334 Register index, | 335 Register value, |
335 SaveFPRegsMode save_fp, | 336 Register index, |
336 RememberedSetAction remembered_set_action, | 337 SaveFPRegsMode save_fp, |
337 SmiCheck smi_check) { | 338 RememberedSetAction remembered_set_action, |
| 339 SmiCheck smi_check, |
| 340 PointersToHereCheck pointers_to_here_check_for_value) { |
338 // First, check if a write barrier is even needed. The tests below | 341 // First, check if a write barrier is even needed. The tests below |
339 // catch stores of Smis. | 342 // catch stores of Smis. |
340 Label done; | 343 Label done; |
341 | 344 |
342 // Skip barrier if writing a smi. | 345 // Skip barrier if writing a smi. |
343 if (smi_check == INLINE_SMI_CHECK) { | 346 if (smi_check == INLINE_SMI_CHECK) { |
344 JumpIfSmi(value, &done); | 347 JumpIfSmi(value, &done); |
345 } | 348 } |
346 | 349 |
347 // Array access: calculate the destination address. Index is not a smi. | 350 // Array access: calculate the destination address. Index is not a smi. |
348 Register dst = index; | 351 Register dst = index; |
349 leap(dst, Operand(object, index, times_pointer_size, | 352 leap(dst, Operand(object, index, times_pointer_size, |
350 FixedArray::kHeaderSize - kHeapObjectTag)); | 353 FixedArray::kHeaderSize - kHeapObjectTag)); |
351 | 354 |
352 RecordWrite( | 355 RecordWrite(object, dst, value, save_fp, remembered_set_action, |
353 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); | 356 OMIT_SMI_CHECK, pointers_to_here_check_for_value); |
354 | 357 |
355 bind(&done); | 358 bind(&done); |
356 | 359 |
357 // Clobber clobbered input registers when running with the debug-code flag | 360 // Clobber clobbered input registers when running with the debug-code flag |
358 // turned on to provoke errors. | 361 // turned on to provoke errors. |
359 if (emit_debug_code()) { | 362 if (emit_debug_code()) { |
360 Move(value, kZapValue, Assembler::RelocInfoNone()); | 363 Move(value, kZapValue, Assembler::RelocInfoNone()); |
361 Move(index, kZapValue, Assembler::RelocInfoNone()); | 364 Move(index, kZapValue, Assembler::RelocInfoNone()); |
362 } | 365 } |
363 } | 366 } |
364 | 367 |
365 | 368 |
366 void MacroAssembler::RecordWrite(Register object, | 369 void MacroAssembler::RecordWriteForMap(Register object, |
367 Register address, | 370 Register map, |
368 Register value, | 371 Register dst, |
369 SaveFPRegsMode fp_mode, | 372 SaveFPRegsMode fp_mode) { |
370 RememberedSetAction remembered_set_action, | 373 ASSERT(!object.is(kScratchRegister)); |
371 SmiCheck smi_check) { | 374 ASSERT(!object.is(map)); |
| 375 ASSERT(!object.is(dst)); |
| 376 ASSERT(!map.is(dst)); |
| 377 AssertNotSmi(object); |
| 378 |
| 379 if (emit_debug_code()) { |
| 380 Label ok; |
| 381 if (map.is(kScratchRegister)) pushq(map); |
| 382 CompareMap(map, isolate()->factory()->meta_map()); |
| 383 if (map.is(kScratchRegister)) popq(map); |
| 384 j(equal, &ok, Label::kNear); |
| 385 int3(); |
| 386 bind(&ok); |
| 387 } |
| 388 |
| 389 if (!FLAG_incremental_marking) { |
| 390 return; |
| 391 } |
| 392 |
| 393 if (emit_debug_code()) { |
| 394 Label ok; |
| 395 if (map.is(kScratchRegister)) pushq(map); |
| 396 cmpp(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 397 if (map.is(kScratchRegister)) popq(map); |
| 398 j(equal, &ok, Label::kNear); |
| 399 int3(); |
| 400 bind(&ok); |
| 401 } |
| 402 |
| 403 // Compute the address. |
| 404 leap(dst, FieldOperand(object, HeapObject::kMapOffset)); |
| 405 |
| 406 // Count number of write barriers in generated code. |
| 407 isolate()->counters()->write_barriers_static()->Increment(); |
| 408 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); |
| 409 |
| 410 // First, check if a write barrier is even needed. The tests below |
| 411 // catch stores of smis and stores into the young generation. |
| 412 Label done; |
| 413 |
| 414 // A single check of the map's pages interesting flag suffices, since it is |
| 415 // only set during incremental collection, and then it's also guaranteed that |
| 416 // the from object's page's interesting flag is also set. This optimization |
| 417 // relies on the fact that maps can never be in new space. |
| 418 CheckPageFlag(map, |
| 419 map, // Used as scratch. |
| 420 MemoryChunk::kPointersToHereAreInterestingMask, |
| 421 zero, |
| 422 &done, |
| 423 Label::kNear); |
| 424 |
| 425 RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET, |
| 426 fp_mode); |
| 427 CallStub(&stub); |
| 428 |
| 429 bind(&done); |
| 430 |
| 431 // Clobber clobbered registers when running with the debug-code flag |
| 432 // turned on to provoke errors. |
| 433 if (emit_debug_code()) { |
| 434 Move(dst, kZapValue, Assembler::RelocInfoNone()); |
| 435 Move(map, kZapValue, Assembler::RelocInfoNone()); |
| 436 } |
| 437 } |
| 438 |
| 439 |
| 440 void MacroAssembler::RecordWrite( |
| 441 Register object, |
| 442 Register address, |
| 443 Register value, |
| 444 SaveFPRegsMode fp_mode, |
| 445 RememberedSetAction remembered_set_action, |
| 446 SmiCheck smi_check, |
| 447 PointersToHereCheck pointers_to_here_check_for_value) { |
372 ASSERT(!object.is(value)); | 448 ASSERT(!object.is(value)); |
373 ASSERT(!object.is(address)); | 449 ASSERT(!object.is(address)); |
374 ASSERT(!value.is(address)); | 450 ASSERT(!value.is(address)); |
375 AssertNotSmi(object); | 451 AssertNotSmi(object); |
376 | 452 |
377 if (remembered_set_action == OMIT_REMEMBERED_SET && | 453 if (remembered_set_action == OMIT_REMEMBERED_SET && |
378 !FLAG_incremental_marking) { | 454 !FLAG_incremental_marking) { |
379 return; | 455 return; |
380 } | 456 } |
381 | 457 |
(...skipping 11 matching lines...) Expand all Loading... |
393 | 469 |
394 // First, check if a write barrier is even needed. The tests below | 470 // First, check if a write barrier is even needed. The tests below |
395 // catch stores of smis and stores into the young generation. | 471 // catch stores of smis and stores into the young generation. |
396 Label done; | 472 Label done; |
397 | 473 |
398 if (smi_check == INLINE_SMI_CHECK) { | 474 if (smi_check == INLINE_SMI_CHECK) { |
399 // Skip barrier if writing a smi. | 475 // Skip barrier if writing a smi. |
400 JumpIfSmi(value, &done); | 476 JumpIfSmi(value, &done); |
401 } | 477 } |
402 | 478 |
403 CheckPageFlag(value, | 479 if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) { |
404 value, // Used as scratch. | 480 CheckPageFlag(value, |
405 MemoryChunk::kPointersToHereAreInterestingMask, | 481 value, // Used as scratch. |
406 zero, | 482 MemoryChunk::kPointersToHereAreInterestingMask, |
407 &done, | 483 zero, |
408 Label::kNear); | 484 &done, |
| 485 Label::kNear); |
| 486 } |
409 | 487 |
410 CheckPageFlag(object, | 488 CheckPageFlag(object, |
411 value, // Used as scratch. | 489 value, // Used as scratch. |
412 MemoryChunk::kPointersFromHereAreInterestingMask, | 490 MemoryChunk::kPointersFromHereAreInterestingMask, |
413 zero, | 491 zero, |
414 &done, | 492 &done, |
415 Label::kNear); | 493 Label::kNear); |
416 | 494 |
417 RecordWriteStub stub(isolate(), object, value, address, remembered_set_action, | 495 RecordWriteStub stub(isolate(), object, value, address, remembered_set_action, |
418 fp_mode); | 496 fp_mode); |
(...skipping 4758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5177 if (ms.shift() > 0) sarl(rdx, Immediate(ms.shift())); | 5255 if (ms.shift() > 0) sarl(rdx, Immediate(ms.shift())); |
5178 movl(rax, dividend); | 5256 movl(rax, dividend); |
5179 shrl(rax, Immediate(31)); | 5257 shrl(rax, Immediate(31)); |
5180 addl(rdx, rax); | 5258 addl(rdx, rax); |
5181 } | 5259 } |
5182 | 5260 |
5183 | 5261 |
5184 } } // namespace v8::internal | 5262 } } // namespace v8::internal |
5185 | 5263 |
5186 #endif // V8_TARGET_ARCH_X64 | 5264 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |