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_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 j(not_sign, &done, Label::kNear); | 308 j(not_sign, &done, Label::kNear); |
309 ExternalReference uint32_bias = | 309 ExternalReference uint32_bias = |
310 ExternalReference::address_of_uint32_bias(); | 310 ExternalReference::address_of_uint32_bias(); |
311 fld_d(Operand::StaticVariable(uint32_bias)); | 311 fld_d(Operand::StaticVariable(uint32_bias)); |
312 faddp(1); | 312 faddp(1); |
313 bind(&done); | 313 bind(&done); |
314 add(esp, Immediate(kPointerSize)); | 314 add(esp, Immediate(kPointerSize)); |
315 } | 315 } |
316 | 316 |
317 | 317 |
318 void MacroAssembler::RecordWriteArray(Register object, | 318 void MacroAssembler::RecordWriteArray( |
319 Register value, | 319 Register object, |
320 Register index, | 320 Register value, |
321 RememberedSetAction remembered_set_action, | 321 Register index, |
322 SmiCheck smi_check) { | 322 RememberedSetAction remembered_set_action, |
| 323 SmiCheck smi_check, |
| 324 PointersToHereCheck pointers_to_here_check_for_value) { |
323 // First, check if a write barrier is even needed. The tests below | 325 // First, check if a write barrier is even needed. The tests below |
324 // catch stores of Smis. | 326 // catch stores of Smis. |
325 Label done; | 327 Label done; |
326 | 328 |
327 // Skip barrier if writing a smi. | 329 // Skip barrier if writing a smi. |
328 if (smi_check == INLINE_SMI_CHECK) { | 330 if (smi_check == INLINE_SMI_CHECK) { |
329 ASSERT_EQ(0, kSmiTag); | 331 ASSERT_EQ(0, kSmiTag); |
330 test(value, Immediate(kSmiTagMask)); | 332 test(value, Immediate(kSmiTagMask)); |
331 j(zero, &done); | 333 j(zero, &done); |
332 } | 334 } |
333 | 335 |
334 // Array access: calculate the destination address in the same manner as | 336 // Array access: calculate the destination address in the same manner as |
335 // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset | 337 // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset |
336 // into an array of words. | 338 // into an array of words. |
337 Register dst = index; | 339 Register dst = index; |
338 lea(dst, Operand(object, index, times_half_pointer_size, | 340 lea(dst, Operand(object, index, times_half_pointer_size, |
339 FixedArray::kHeaderSize - kHeapObjectTag)); | 341 FixedArray::kHeaderSize - kHeapObjectTag)); |
340 | 342 |
341 RecordWrite( | 343 RecordWrite(object, dst, value, remembered_set_action, OMIT_SMI_CHECK, |
342 object, dst, value, remembered_set_action, OMIT_SMI_CHECK); | 344 pointers_to_here_check_for_value); |
343 | 345 |
344 bind(&done); | 346 bind(&done); |
345 | 347 |
346 // Clobber clobbered input registers when running with the debug-code flag | 348 // Clobber clobbered input registers when running with the debug-code flag |
347 // turned on to provoke errors. | 349 // turned on to provoke errors. |
348 if (emit_debug_code()) { | 350 if (emit_debug_code()) { |
349 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 351 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
350 mov(index, Immediate(BitCast<int32_t>(kZapValue))); | 352 mov(index, Immediate(BitCast<int32_t>(kZapValue))); |
351 } | 353 } |
352 } | 354 } |
353 | 355 |
354 | 356 |
355 void MacroAssembler::RecordWriteField( | 357 void MacroAssembler::RecordWriteField( |
356 Register object, | 358 Register object, |
357 int offset, | 359 int offset, |
358 Register value, | 360 Register value, |
359 Register dst, | 361 Register dst, |
360 RememberedSetAction remembered_set_action, | 362 RememberedSetAction remembered_set_action, |
361 SmiCheck smi_check) { | 363 SmiCheck smi_check, |
| 364 PointersToHereCheck pointers_to_here_check_for_value) { |
362 // First, check if a write barrier is even needed. The tests below | 365 // First, check if a write barrier is even needed. The tests below |
363 // catch stores of Smis. | 366 // catch stores of Smis. |
364 Label done; | 367 Label done; |
365 | 368 |
366 // Skip barrier if writing a smi. | 369 // Skip barrier if writing a smi. |
367 if (smi_check == INLINE_SMI_CHECK) { | 370 if (smi_check == INLINE_SMI_CHECK) { |
368 JumpIfSmi(value, &done, Label::kNear); | 371 JumpIfSmi(value, &done, Label::kNear); |
369 } | 372 } |
370 | 373 |
371 // Although the object register is tagged, the offset is relative to the start | 374 // Although the object register is tagged, the offset is relative to the start |
372 // of the object, so so offset must be a multiple of kPointerSize. | 375 // of the object, so so offset must be a multiple of kPointerSize. |
373 ASSERT(IsAligned(offset, kPointerSize)); | 376 ASSERT(IsAligned(offset, kPointerSize)); |
374 | 377 |
375 lea(dst, FieldOperand(object, offset)); | 378 lea(dst, FieldOperand(object, offset)); |
376 if (emit_debug_code()) { | 379 if (emit_debug_code()) { |
377 Label ok; | 380 Label ok; |
378 test_b(dst, (1 << kPointerSizeLog2) - 1); | 381 test_b(dst, (1 << kPointerSizeLog2) - 1); |
379 j(zero, &ok, Label::kNear); | 382 j(zero, &ok, Label::kNear); |
380 int3(); | 383 int3(); |
381 bind(&ok); | 384 bind(&ok); |
382 } | 385 } |
383 | 386 |
384 RecordWrite( | 387 RecordWrite(object, dst, value, remembered_set_action, OMIT_SMI_CHECK, |
385 object, dst, value, remembered_set_action, OMIT_SMI_CHECK); | 388 pointers_to_here_check_for_value); |
386 | 389 |
387 bind(&done); | 390 bind(&done); |
388 | 391 |
389 // Clobber clobbered input registers when running with the debug-code flag | 392 // Clobber clobbered input registers when running with the debug-code flag |
390 // turned on to provoke errors. | 393 // turned on to provoke errors. |
391 if (emit_debug_code()) { | 394 if (emit_debug_code()) { |
392 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 395 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
393 mov(dst, Immediate(BitCast<int32_t>(kZapValue))); | 396 mov(dst, Immediate(BitCast<int32_t>(kZapValue))); |
394 } | 397 } |
395 } | 398 } |
(...skipping 19 matching lines...) Expand all Loading... |
415 | 418 |
416 ASSERT(!object.is(value)); | 419 ASSERT(!object.is(value)); |
417 ASSERT(!object.is(address)); | 420 ASSERT(!object.is(address)); |
418 ASSERT(!value.is(address)); | 421 ASSERT(!value.is(address)); |
419 AssertNotSmi(object); | 422 AssertNotSmi(object); |
420 | 423 |
421 if (!FLAG_incremental_marking) { | 424 if (!FLAG_incremental_marking) { |
422 return; | 425 return; |
423 } | 426 } |
424 | 427 |
| 428 // Compute the address. |
| 429 lea(address, FieldOperand(object, HeapObject::kMapOffset)); |
| 430 |
425 // Count number of write barriers in generated code. | 431 // Count number of write barriers in generated code. |
426 isolate()->counters()->write_barriers_static()->Increment(); | 432 isolate()->counters()->write_barriers_static()->Increment(); |
427 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); | 433 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); |
428 | 434 |
429 // A single check of the map's pages interesting flag suffices, since it is | 435 // A single check of the map's pages interesting flag suffices, since it is |
430 // only set during incremental collection, and then it's also guaranteed that | 436 // only set during incremental collection, and then it's also guaranteed that |
431 // the from object's page's interesting flag is also set. This optimization | 437 // the from object's page's interesting flag is also set. This optimization |
432 // relies on the fact that maps can never be in new space. | 438 // relies on the fact that maps can never be in new space. |
433 ASSERT(!isolate()->heap()->InNewSpace(*map)); | 439 ASSERT(!isolate()->heap()->InNewSpace(*map)); |
434 CheckPageFlagForMap(map, | 440 CheckPageFlagForMap(map, |
435 MemoryChunk::kPointersToHereAreInterestingMask, | 441 MemoryChunk::kPointersToHereAreInterestingMask, |
436 zero, | 442 zero, |
437 &done, | 443 &done, |
438 Label::kNear); | 444 Label::kNear); |
439 | 445 |
440 // Delay the initialization of |address| and |value| for the stub until it's | |
441 // known that the will be needed. Up until this point their values are not | |
442 // needed since they are embedded in the operands of instructions that need | |
443 // them. | |
444 lea(address, FieldOperand(object, HeapObject::kMapOffset)); | |
445 mov(value, Immediate(map)); | |
446 RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET); | 446 RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET); |
447 CallStub(&stub); | 447 CallStub(&stub); |
448 | 448 |
449 bind(&done); | 449 bind(&done); |
450 | 450 |
451 // Clobber clobbered input registers when running with the debug-code flag | 451 // Clobber clobbered input registers when running with the debug-code flag |
452 // turned on to provoke errors. | 452 // turned on to provoke errors. |
453 if (emit_debug_code()) { | 453 if (emit_debug_code()) { |
454 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 454 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
455 mov(scratch1, Immediate(BitCast<int32_t>(kZapValue))); | 455 mov(scratch1, Immediate(BitCast<int32_t>(kZapValue))); |
456 mov(scratch2, Immediate(BitCast<int32_t>(kZapValue))); | 456 mov(scratch2, Immediate(BitCast<int32_t>(kZapValue))); |
457 } | 457 } |
458 } | 458 } |
459 | 459 |
460 | 460 |
461 void MacroAssembler::RecordWrite(Register object, | 461 void MacroAssembler::RecordWrite( |
462 Register address, | 462 Register object, |
463 Register value, | 463 Register address, |
464 RememberedSetAction remembered_set_action, | 464 Register value, |
465 SmiCheck smi_check) { | 465 RememberedSetAction remembered_set_action, |
| 466 SmiCheck smi_check, |
| 467 PointersToHereCheck pointers_to_here_check_for_value) { |
466 ASSERT(!object.is(value)); | 468 ASSERT(!object.is(value)); |
467 ASSERT(!object.is(address)); | 469 ASSERT(!object.is(address)); |
468 ASSERT(!value.is(address)); | 470 ASSERT(!value.is(address)); |
469 AssertNotSmi(object); | 471 AssertNotSmi(object); |
470 | 472 |
471 if (remembered_set_action == OMIT_REMEMBERED_SET && | 473 if (remembered_set_action == OMIT_REMEMBERED_SET && |
472 !FLAG_incremental_marking) { | 474 !FLAG_incremental_marking) { |
473 return; | 475 return; |
474 } | 476 } |
475 | 477 |
(...skipping 11 matching lines...) Expand all Loading... |
487 | 489 |
488 // First, check if a write barrier is even needed. The tests below | 490 // First, check if a write barrier is even needed. The tests below |
489 // catch stores of Smis and stores into young gen. | 491 // catch stores of Smis and stores into young gen. |
490 Label done; | 492 Label done; |
491 | 493 |
492 if (smi_check == INLINE_SMI_CHECK) { | 494 if (smi_check == INLINE_SMI_CHECK) { |
493 // Skip barrier if writing a smi. | 495 // Skip barrier if writing a smi. |
494 JumpIfSmi(value, &done, Label::kNear); | 496 JumpIfSmi(value, &done, Label::kNear); |
495 } | 497 } |
496 | 498 |
497 CheckPageFlag(value, | 499 if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) { |
498 value, // Used as scratch. | 500 CheckPageFlag(value, |
499 MemoryChunk::kPointersToHereAreInterestingMask, | 501 value, // Used as scratch. |
500 zero, | 502 MemoryChunk::kPointersToHereAreInterestingMask, |
501 &done, | 503 zero, |
502 Label::kNear); | 504 &done, |
| 505 Label::kNear); |
| 506 } |
503 CheckPageFlag(object, | 507 CheckPageFlag(object, |
504 value, // Used as scratch. | 508 value, // Used as scratch. |
505 MemoryChunk::kPointersFromHereAreInterestingMask, | 509 MemoryChunk::kPointersFromHereAreInterestingMask, |
506 zero, | 510 zero, |
507 &done, | 511 &done, |
508 Label::kNear); | 512 Label::kNear); |
509 | 513 |
510 RecordWriteStub stub(isolate(), object, value, address, | 514 RecordWriteStub stub(isolate(), object, value, address, |
511 remembered_set_action); | 515 remembered_set_action); |
512 CallStub(&stub); | 516 CallStub(&stub); |
(...skipping 2775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3288 if (ms.shift() > 0) sar(edx, ms.shift()); | 3292 if (ms.shift() > 0) sar(edx, ms.shift()); |
3289 mov(eax, dividend); | 3293 mov(eax, dividend); |
3290 shr(eax, 31); | 3294 shr(eax, 31); |
3291 add(edx, eax); | 3295 add(edx, eax); |
3292 } | 3296 } |
3293 | 3297 |
3294 | 3298 |
3295 } } // namespace v8::internal | 3299 } } // namespace v8::internal |
3296 | 3300 |
3297 #endif // V8_TARGET_ARCH_X87 | 3301 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |