| 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 |