| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 __ ret(3 * kPointerSize); | 226 __ ret(3 * kPointerSize); |
| 227 | 227 |
| 228 __ bind(&slow_case); | 228 __ bind(&slow_case); |
| 229 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); | 229 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 // The stub expects its argument on the stack and returns its result in tos_: | 233 // The stub expects its argument on the stack and returns its result in tos_: |
| 234 // zero for false, and a non-zero value for true. | 234 // zero for false, and a non-zero value for true. |
| 235 void ToBooleanStub::Generate(MacroAssembler* masm) { | 235 void ToBooleanStub::Generate(MacroAssembler* masm) { |
| 236 // This stub overrides SometimesSetsUpAFrame() to return false. That means |
| 237 // we cannot call anything that could cause a GC from this stub. |
| 236 Label patch; | 238 Label patch; |
| 237 const Register argument = rax; | 239 const Register argument = rax; |
| 238 const Register map = rdx; | 240 const Register map = rdx; |
| 239 | 241 |
| 240 if (!types_.IsEmpty()) { | 242 if (!types_.IsEmpty()) { |
| 241 __ movq(argument, Operand(rsp, 1 * kPointerSize)); | 243 __ movq(argument, Operand(rsp, 1 * kPointerSize)); |
| 242 } | 244 } |
| 243 | 245 |
| 244 // undefined -> false | 246 // undefined -> false |
| 245 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); | 247 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 __ Set(tos_, 0); | 323 __ Set(tos_, 0); |
| 322 __ ret(1 * kPointerSize); | 324 __ ret(1 * kPointerSize); |
| 323 __ bind(¬_heap_number); | 325 __ bind(¬_heap_number); |
| 324 } | 326 } |
| 325 | 327 |
| 326 __ bind(&patch); | 328 __ bind(&patch); |
| 327 GenerateTypeTransition(masm); | 329 GenerateTypeTransition(masm); |
| 328 } | 330 } |
| 329 | 331 |
| 330 | 332 |
| 333 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 334 __ PushCallerSaved(save_doubles_); |
| 335 const int argument_count = 1; |
| 336 __ PrepareCallCFunction(argument_count); |
| 337 #ifdef _WIN64 |
| 338 __ LoadAddress(rcx, ExternalReference::isolate_address()); |
| 339 #else |
| 340 __ LoadAddress(rdi, ExternalReference::isolate_address()); |
| 341 #endif |
| 342 |
| 343 AllowExternalCallThatCantCauseGC scope(masm); |
| 344 __ CallCFunction( |
| 345 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
| 346 argument_count); |
| 347 __ PopCallerSaved(save_doubles_); |
| 348 __ ret(0); |
| 349 } |
| 350 |
| 351 |
| 331 void ToBooleanStub::CheckOddball(MacroAssembler* masm, | 352 void ToBooleanStub::CheckOddball(MacroAssembler* masm, |
| 332 Type type, | 353 Type type, |
| 333 Heap::RootListIndex value, | 354 Heap::RootListIndex value, |
| 334 bool result) { | 355 bool result) { |
| 335 const Register argument = rax; | 356 const Register argument = rax; |
| 336 if (types_.Contains(type)) { | 357 if (types_.Contains(type)) { |
| 337 // If we see an expected oddball, return its ToBoolean value tos_. | 358 // If we see an expected oddball, return its ToBoolean value tos_. |
| 338 Label different_value; | 359 Label different_value; |
| 339 __ CompareRoot(argument, value); | 360 __ CompareRoot(argument, value); |
| 340 __ j(not_equal, &different_value, Label::kNear); | 361 __ j(not_equal, &different_value, Label::kNear); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 __ shl(kScratchRegister, Immediate(63)); | 636 __ shl(kScratchRegister, Immediate(63)); |
| 616 __ xor_(FieldOperand(rax, HeapNumber::kValueOffset), kScratchRegister); | 637 __ xor_(FieldOperand(rax, HeapNumber::kValueOffset), kScratchRegister); |
| 617 } else { | 638 } else { |
| 618 // Allocate a heap number before calculating the answer, | 639 // Allocate a heap number before calculating the answer, |
| 619 // so we don't have an untagged double around during GC. | 640 // so we don't have an untagged double around during GC. |
| 620 Label slow_allocate_heapnumber, heapnumber_allocated; | 641 Label slow_allocate_heapnumber, heapnumber_allocated; |
| 621 __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber); | 642 __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber); |
| 622 __ jmp(&heapnumber_allocated); | 643 __ jmp(&heapnumber_allocated); |
| 623 | 644 |
| 624 __ bind(&slow_allocate_heapnumber); | 645 __ bind(&slow_allocate_heapnumber); |
| 625 __ EnterInternalFrame(); | 646 { |
| 626 __ push(rax); | 647 FrameScope scope(masm, StackFrame::INTERNAL); |
| 627 __ CallRuntime(Runtime::kNumberAlloc, 0); | 648 __ push(rax); |
| 628 __ movq(rcx, rax); | 649 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 629 __ pop(rax); | 650 __ movq(rcx, rax); |
| 630 __ LeaveInternalFrame(); | 651 __ pop(rax); |
| 652 } |
| 631 __ bind(&heapnumber_allocated); | 653 __ bind(&heapnumber_allocated); |
| 632 // rcx: allocated 'empty' number | 654 // rcx: allocated 'empty' number |
| 633 | 655 |
| 634 // Copy the double value to the new heap number, flipping the sign. | 656 // Copy the double value to the new heap number, flipping the sign. |
| 635 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); | 657 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 636 __ Set(kScratchRegister, 0x01); | 658 __ Set(kScratchRegister, 0x01); |
| 637 __ shl(kScratchRegister, Immediate(63)); | 659 __ shl(kScratchRegister, Immediate(63)); |
| 638 __ xor_(rdx, kScratchRegister); // Flip sign. | 660 __ xor_(rdx, kScratchRegister); // Flip sign. |
| 639 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); | 661 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); |
| 640 __ movq(rax, rcx); | 662 __ movq(rax, rcx); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 // operation result to the caller of the stub. | 766 // operation result to the caller of the stub. |
| 745 __ TailCallExternalReference( | 767 __ TailCallExternalReference( |
| 746 ExternalReference(IC_Utility(IC::kBinaryOp_Patch), | 768 ExternalReference(IC_Utility(IC::kBinaryOp_Patch), |
| 747 masm->isolate()), | 769 masm->isolate()), |
| 748 5, | 770 5, |
| 749 1); | 771 1); |
| 750 } | 772 } |
| 751 | 773 |
| 752 | 774 |
| 753 void BinaryOpStub::Generate(MacroAssembler* masm) { | 775 void BinaryOpStub::Generate(MacroAssembler* masm) { |
| 776 // Explicitly allow generation of nested stubs. It is safe here because |
| 777 // generation code does not use any raw pointers. |
| 778 AllowStubCallsScope allow_stub_calls(masm, true); |
| 779 |
| 754 switch (operands_type_) { | 780 switch (operands_type_) { |
| 755 case BinaryOpIC::UNINITIALIZED: | 781 case BinaryOpIC::UNINITIALIZED: |
| 756 GenerateTypeTransition(masm); | 782 GenerateTypeTransition(masm); |
| 757 break; | 783 break; |
| 758 case BinaryOpIC::SMI: | 784 case BinaryOpIC::SMI: |
| 759 GenerateSmiStub(masm); | 785 GenerateSmiStub(masm); |
| 760 break; | 786 break; |
| 761 case BinaryOpIC::INT32: | 787 case BinaryOpIC::INT32: |
| 762 UNREACHABLE(); | 788 UNREACHABLE(); |
| 763 // The int32 case is identical to the Smi case. We avoid creating this | 789 // The int32 case is identical to the Smi case. We avoid creating this |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1446 __ bind(&skip_cache); | 1472 __ bind(&skip_cache); |
| 1447 __ subq(rsp, Immediate(kDoubleSize)); | 1473 __ subq(rsp, Immediate(kDoubleSize)); |
| 1448 __ movsd(Operand(rsp, 0), xmm1); | 1474 __ movsd(Operand(rsp, 0), xmm1); |
| 1449 __ fld_d(Operand(rsp, 0)); | 1475 __ fld_d(Operand(rsp, 0)); |
| 1450 GenerateOperation(masm); | 1476 GenerateOperation(masm); |
| 1451 __ fstp_d(Operand(rsp, 0)); | 1477 __ fstp_d(Operand(rsp, 0)); |
| 1452 __ movsd(xmm1, Operand(rsp, 0)); | 1478 __ movsd(xmm1, Operand(rsp, 0)); |
| 1453 __ addq(rsp, Immediate(kDoubleSize)); | 1479 __ addq(rsp, Immediate(kDoubleSize)); |
| 1454 // We return the value in xmm1 without adding it to the cache, but | 1480 // We return the value in xmm1 without adding it to the cache, but |
| 1455 // we cause a scavenging GC so that future allocations will succeed. | 1481 // we cause a scavenging GC so that future allocations will succeed. |
| 1456 __ EnterInternalFrame(); | 1482 { |
| 1457 // Allocate an unused object bigger than a HeapNumber. | 1483 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1458 __ Push(Smi::FromInt(2 * kDoubleSize)); | 1484 // Allocate an unused object bigger than a HeapNumber. |
| 1459 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); | 1485 __ Push(Smi::FromInt(2 * kDoubleSize)); |
| 1460 __ LeaveInternalFrame(); | 1486 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); |
| 1487 } |
| 1461 __ Ret(); | 1488 __ Ret(); |
| 1462 } | 1489 } |
| 1463 | 1490 |
| 1464 // Call runtime, doing whatever allocation and cleanup is necessary. | 1491 // Call runtime, doing whatever allocation and cleanup is necessary. |
| 1465 if (tagged) { | 1492 if (tagged) { |
| 1466 __ bind(&runtime_call_clear_stack); | 1493 __ bind(&runtime_call_clear_stack); |
| 1467 __ fstp(0); | 1494 __ fstp(0); |
| 1468 __ bind(&runtime_call); | 1495 __ bind(&runtime_call); |
| 1469 __ TailCallExternalReference( | 1496 __ TailCallExternalReference( |
| 1470 ExternalReference(RuntimeFunction(), masm->isolate()), 1, 1); | 1497 ExternalReference(RuntimeFunction(), masm->isolate()), 1, 1); |
| 1471 } else { // UNTAGGED. | 1498 } else { // UNTAGGED. |
| 1472 __ bind(&runtime_call_clear_stack); | 1499 __ bind(&runtime_call_clear_stack); |
| 1473 __ bind(&runtime_call); | 1500 __ bind(&runtime_call); |
| 1474 __ AllocateHeapNumber(rax, rdi, &skip_cache); | 1501 __ AllocateHeapNumber(rax, rdi, &skip_cache); |
| 1475 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm1); | 1502 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm1); |
| 1476 __ EnterInternalFrame(); | 1503 { |
| 1477 __ push(rax); | 1504 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1478 __ CallRuntime(RuntimeFunction(), 1); | 1505 __ push(rax); |
| 1479 __ LeaveInternalFrame(); | 1506 __ CallRuntime(RuntimeFunction(), 1); |
| 1507 } |
| 1480 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | 1508 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 1481 __ Ret(); | 1509 __ Ret(); |
| 1482 } | 1510 } |
| 1483 } | 1511 } |
| 1484 | 1512 |
| 1485 | 1513 |
| 1486 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { | 1514 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { |
| 1487 switch (type_) { | 1515 switch (type_) { |
| 1488 // Add more cases when necessary. | 1516 // Add more cases when necessary. |
| 1489 case TranscendentalCache::SIN: return Runtime::kMath_sin; | 1517 case TranscendentalCache::SIN: return Runtime::kMath_sin; |
| (...skipping 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2663 | 2691 |
| 2664 // rbx: last_match_info backing store (FixedArray) | 2692 // rbx: last_match_info backing store (FixedArray) |
| 2665 // rdx: number of capture registers | 2693 // rdx: number of capture registers |
| 2666 // Store the capture count. | 2694 // Store the capture count. |
| 2667 __ Integer32ToSmi(kScratchRegister, rdx); | 2695 __ Integer32ToSmi(kScratchRegister, rdx); |
| 2668 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), | 2696 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), |
| 2669 kScratchRegister); | 2697 kScratchRegister); |
| 2670 // Store last subject and last input. | 2698 // Store last subject and last input. |
| 2671 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2699 __ movq(rax, Operand(rsp, kSubjectOffset)); |
| 2672 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); | 2700 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); |
| 2673 __ movq(rcx, rbx); | 2701 __ RecordWriteField(rbx, |
| 2674 __ RecordWrite(rcx, RegExpImpl::kLastSubjectOffset, rax, rdi); | 2702 RegExpImpl::kLastSubjectOffset, |
| 2703 rax, |
| 2704 rdi, |
| 2705 kDontSaveFPRegs); |
| 2675 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2706 __ movq(rax, Operand(rsp, kSubjectOffset)); |
| 2676 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); | 2707 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); |
| 2677 __ movq(rcx, rbx); | 2708 __ RecordWriteField(rbx, |
| 2678 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi); | 2709 RegExpImpl::kLastInputOffset, |
| 2710 rax, |
| 2711 rdi, |
| 2712 kDontSaveFPRegs); |
| 2679 | 2713 |
| 2680 // Get the static offsets vector filled by the native regexp code. | 2714 // Get the static offsets vector filled by the native regexp code. |
| 2681 __ LoadAddress(rcx, | 2715 __ LoadAddress(rcx, |
| 2682 ExternalReference::address_of_static_offsets_vector(isolate)); | 2716 ExternalReference::address_of_static_offsets_vector(isolate)); |
| 2683 | 2717 |
| 2684 // rbx: last_match_info backing store (FixedArray) | 2718 // rbx: last_match_info backing store (FixedArray) |
| 2685 // rcx: offsets vector | 2719 // rcx: offsets vector |
| 2686 // rdx: number of capture registers | 2720 // rdx: number of capture registers |
| 2687 Label next_capture, done; | 2721 Label next_capture, done; |
| 2688 // Capture register counter starts from number of capture registers and | 2722 // Capture register counter starts from number of capture registers and |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3224 __ testb(scratch, Immediate(kIsSymbolMask)); | 3258 __ testb(scratch, Immediate(kIsSymbolMask)); |
| 3225 __ j(zero, label); | 3259 __ j(zero, label); |
| 3226 } | 3260 } |
| 3227 | 3261 |
| 3228 | 3262 |
| 3229 void StackCheckStub::Generate(MacroAssembler* masm) { | 3263 void StackCheckStub::Generate(MacroAssembler* masm) { |
| 3230 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3264 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
| 3231 } | 3265 } |
| 3232 | 3266 |
| 3233 | 3267 |
| 3268 void CallFunctionStub::FinishCode(Code* code) { |
| 3269 code->set_has_function_cache(false); |
| 3270 } |
| 3271 |
| 3272 |
| 3273 void CallFunctionStub::Clear(Heap* heap, Address address) { |
| 3274 UNREACHABLE(); |
| 3275 } |
| 3276 |
| 3277 |
| 3278 Object* CallFunctionStub::GetCachedValue(Address address) { |
| 3279 UNREACHABLE(); |
| 3280 return NULL; |
| 3281 } |
| 3282 |
| 3283 |
| 3234 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3284 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3235 Label slow, non_function; | 3285 Label slow, non_function; |
| 3236 | 3286 |
| 3237 // The receiver might implicitly be the global object. This is | 3287 // The receiver might implicitly be the global object. This is |
| 3238 // indicated by passing the hole as the receiver to the call | 3288 // indicated by passing the hole as the receiver to the call |
| 3239 // function stub. | 3289 // function stub. |
| 3240 if (ReceiverMightBeImplicit()) { | 3290 if (ReceiverMightBeImplicit()) { |
| 3241 Label call; | 3291 Label call; |
| 3242 // Get the receiver from the stack. | 3292 // Get the receiver from the stack. |
| 3243 // +1 ~ return address | 3293 // +1 ~ return address |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3312 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); | 3362 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3313 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3363 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3314 } | 3364 } |
| 3315 | 3365 |
| 3316 | 3366 |
| 3317 bool CEntryStub::NeedsImmovableCode() { | 3367 bool CEntryStub::NeedsImmovableCode() { |
| 3318 return false; | 3368 return false; |
| 3319 } | 3369 } |
| 3320 | 3370 |
| 3321 | 3371 |
| 3372 bool CEntryStub::IsPregenerated() { |
| 3373 #ifdef _WIN64 |
| 3374 return result_size_ == 1; |
| 3375 #else |
| 3376 return true; |
| 3377 #endif |
| 3378 } |
| 3379 |
| 3380 |
| 3381 void CodeStub::GenerateStubsAheadOfTime() { |
| 3382 CEntryStub::GenerateAheadOfTime(); |
| 3383 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(); |
| 3384 // It is important that the store buffer overflow stubs are generated first. |
| 3385 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(); |
| 3386 } |
| 3387 |
| 3388 |
| 3389 void CodeStub::GenerateFPStubs() { |
| 3390 } |
| 3391 |
| 3392 |
| 3393 void CEntryStub::GenerateAheadOfTime() { |
| 3394 CEntryStub stub(1, kDontSaveFPRegs); |
| 3395 stub.GetCode()->set_is_pregenerated(true); |
| 3396 CEntryStub save_doubles(1, kSaveFPRegs); |
| 3397 save_doubles.GetCode()->set_is_pregenerated(true); |
| 3398 } |
| 3399 |
| 3400 |
| 3322 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 3401 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 3323 // Throw exception in eax. | 3402 // Throw exception in eax. |
| 3324 __ Throw(rax); | 3403 __ Throw(rax); |
| 3325 } | 3404 } |
| 3326 | 3405 |
| 3327 | 3406 |
| 3328 void CEntryStub::GenerateCore(MacroAssembler* masm, | 3407 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 3329 Label* throw_normal_exception, | 3408 Label* throw_normal_exception, |
| 3330 Label* throw_termination_exception, | 3409 Label* throw_termination_exception, |
| 3331 Label* throw_out_of_memory_exception, | 3410 Label* throw_out_of_memory_exception, |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3750 __ j(above, &slow); | 3829 __ j(above, &slow); |
| 3751 | 3830 |
| 3752 // Register mapping: | 3831 // Register mapping: |
| 3753 // rax is object map. | 3832 // rax is object map. |
| 3754 // rdx is function. | 3833 // rdx is function. |
| 3755 // rbx is function prototype. | 3834 // rbx is function prototype. |
| 3756 if (!HasCallSiteInlineCheck()) { | 3835 if (!HasCallSiteInlineCheck()) { |
| 3757 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); | 3836 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); |
| 3758 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); | 3837 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); |
| 3759 } else { | 3838 } else { |
| 3839 // Get return address and delta to inlined map check. |
| 3760 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); | 3840 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); |
| 3761 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 3841 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); |
| 3762 __ movq(Operand(kScratchRegister, kOffsetToMapCheckValue), rax); | 3842 __ movq(Operand(kScratchRegister, kOffsetToMapCheckValue), rax); |
| 3763 if (FLAG_debug_code) { | 3843 if (FLAG_debug_code) { |
| 3764 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); | 3844 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); |
| 3765 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); | 3845 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); |
| 3766 __ Assert(equal, "InstanceofStub unexpected call site cache (check)."); | 3846 __ Assert(equal, "InstanceofStub unexpected call site cache (check)."); |
| 3767 } | 3847 } |
| 3768 } | 3848 } |
| 3769 | 3849 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3784 __ jmp(&loop); | 3864 __ jmp(&loop); |
| 3785 | 3865 |
| 3786 __ bind(&is_instance); | 3866 __ bind(&is_instance); |
| 3787 if (!HasCallSiteInlineCheck()) { | 3867 if (!HasCallSiteInlineCheck()) { |
| 3788 __ xorl(rax, rax); | 3868 __ xorl(rax, rax); |
| 3789 // Store bitwise zero in the cache. This is a Smi in GC terms. | 3869 // Store bitwise zero in the cache. This is a Smi in GC terms. |
| 3790 STATIC_ASSERT(kSmiTag == 0); | 3870 STATIC_ASSERT(kSmiTag == 0); |
| 3791 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); | 3871 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); |
| 3792 } else { | 3872 } else { |
| 3793 // Store offset of true in the root array at the inline check site. | 3873 // Store offset of true in the root array at the inline check site. |
| 3794 ASSERT((Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias | 3874 int true_offset = 0x100 + |
| 3795 == 0xB0 - 0x100); | 3875 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
| 3796 __ movl(rax, Immediate(0xB0)); // TrueValue is at -10 * kPointerSize. | 3876 // Assert it is a 1-byte signed value. |
| 3877 ASSERT(true_offset >= 0 && true_offset < 0x100); |
| 3878 __ movl(rax, Immediate(true_offset)); |
| 3797 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); | 3879 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); |
| 3798 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 3880 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); |
| 3799 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 3881 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
| 3800 if (FLAG_debug_code) { | 3882 if (FLAG_debug_code) { |
| 3801 __ movl(rax, Immediate(kWordBeforeResultValue)); | 3883 __ movl(rax, Immediate(kWordBeforeResultValue)); |
| 3802 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 3884 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
| 3803 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)."); | 3885 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)."); |
| 3804 } | 3886 } |
| 3805 __ Set(rax, 0); | 3887 __ Set(rax, 0); |
| 3806 } | 3888 } |
| 3807 __ ret(2 * kPointerSize + extra_stack_space); | 3889 __ ret(2 * kPointerSize + extra_stack_space); |
| 3808 | 3890 |
| 3809 __ bind(&is_not_instance); | 3891 __ bind(&is_not_instance); |
| 3810 if (!HasCallSiteInlineCheck()) { | 3892 if (!HasCallSiteInlineCheck()) { |
| 3811 // We have to store a non-zero value in the cache. | 3893 // We have to store a non-zero value in the cache. |
| 3812 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); | 3894 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); |
| 3813 } else { | 3895 } else { |
| 3814 // Store offset of false in the root array at the inline check site. | 3896 // Store offset of false in the root array at the inline check site. |
| 3815 ASSERT((Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias | 3897 int false_offset = 0x100 + |
| 3816 == 0xB8 - 0x100); | 3898 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
| 3817 __ movl(rax, Immediate(0xB8)); // FalseValue is at -9 * kPointerSize. | 3899 // Assert it is a 1-byte signed value. |
| 3900 ASSERT(false_offset >= 0 && false_offset < 0x100); |
| 3901 __ movl(rax, Immediate(false_offset)); |
| 3818 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); | 3902 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); |
| 3819 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 3903 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); |
| 3820 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 3904 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
| 3821 if (FLAG_debug_code) { | 3905 if (FLAG_debug_code) { |
| 3822 __ movl(rax, Immediate(kWordBeforeResultValue)); | 3906 __ movl(rax, Immediate(kWordBeforeResultValue)); |
| 3823 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 3907 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
| 3824 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); | 3908 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); |
| 3825 } | 3909 } |
| 3826 } | 3910 } |
| 3827 __ ret(2 * kPointerSize + extra_stack_space); | 3911 __ ret(2 * kPointerSize + extra_stack_space); |
| (...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5264 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 5348 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
| 5265 // Save the registers. | 5349 // Save the registers. |
| 5266 __ pop(rcx); | 5350 __ pop(rcx); |
| 5267 __ push(rdx); | 5351 __ push(rdx); |
| 5268 __ push(rax); | 5352 __ push(rax); |
| 5269 __ push(rcx); | 5353 __ push(rcx); |
| 5270 | 5354 |
| 5271 // Call the runtime system in a fresh internal frame. | 5355 // Call the runtime system in a fresh internal frame. |
| 5272 ExternalReference miss = | 5356 ExternalReference miss = |
| 5273 ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate()); | 5357 ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate()); |
| 5274 __ EnterInternalFrame(); | 5358 { |
| 5275 __ push(rdx); | 5359 FrameScope scope(masm, StackFrame::INTERNAL); |
| 5276 __ push(rax); | 5360 __ push(rdx); |
| 5277 __ Push(Smi::FromInt(op_)); | 5361 __ push(rax); |
| 5278 __ CallExternalReference(miss, 3); | 5362 __ Push(Smi::FromInt(op_)); |
| 5279 __ LeaveInternalFrame(); | 5363 __ CallExternalReference(miss, 3); |
| 5364 } |
| 5280 | 5365 |
| 5281 // Compute the entry point of the rewritten stub. | 5366 // Compute the entry point of the rewritten stub. |
| 5282 __ lea(rdi, FieldOperand(rax, Code::kHeaderSize)); | 5367 __ lea(rdi, FieldOperand(rax, Code::kHeaderSize)); |
| 5283 | 5368 |
| 5284 // Restore registers. | 5369 // Restore registers. |
| 5285 __ pop(rcx); | 5370 __ pop(rcx); |
| 5286 __ pop(rax); | 5371 __ pop(rax); |
| 5287 __ pop(rdx); | 5372 __ pop(rdx); |
| 5288 __ push(rcx); | 5373 __ push(rcx); |
| 5289 | 5374 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5400 __ push(r0); | 5485 __ push(r0); |
| 5401 __ CallStub(&stub); | 5486 __ CallStub(&stub); |
| 5402 | 5487 |
| 5403 __ testq(r0, r0); | 5488 __ testq(r0, r0); |
| 5404 __ j(zero, miss); | 5489 __ j(zero, miss); |
| 5405 __ jmp(done); | 5490 __ jmp(done); |
| 5406 } | 5491 } |
| 5407 | 5492 |
| 5408 | 5493 |
| 5409 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { | 5494 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { |
| 5495 // This stub overrides SometimesSetsUpAFrame() to return false. That means |
| 5496 // we cannot call anything that could cause a GC from this stub. |
| 5410 // Stack frame on entry: | 5497 // Stack frame on entry: |
| 5411 // esp[0 * kPointerSize]: return address. | 5498 // esp[0 * kPointerSize]: return address. |
| 5412 // esp[1 * kPointerSize]: key's hash. | 5499 // esp[1 * kPointerSize]: key's hash. |
| 5413 // esp[2 * kPointerSize]: key. | 5500 // esp[2 * kPointerSize]: key. |
| 5414 // Registers: | 5501 // Registers: |
| 5415 // dictionary_: StringDictionary to probe. | 5502 // dictionary_: StringDictionary to probe. |
| 5416 // result_: used as scratch. | 5503 // result_: used as scratch. |
| 5417 // index_: will hold an index of entry if lookup is successful. | 5504 // index_: will hold an index of entry if lookup is successful. |
| 5418 // might alias with result_. | 5505 // might alias with result_. |
| 5419 // Returns: | 5506 // Returns: |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5485 __ Drop(1); | 5572 __ Drop(1); |
| 5486 __ ret(2 * kPointerSize); | 5573 __ ret(2 * kPointerSize); |
| 5487 | 5574 |
| 5488 __ bind(¬_in_dictionary); | 5575 __ bind(¬_in_dictionary); |
| 5489 __ movq(scratch, Immediate(0)); | 5576 __ movq(scratch, Immediate(0)); |
| 5490 __ Drop(1); | 5577 __ Drop(1); |
| 5491 __ ret(2 * kPointerSize); | 5578 __ ret(2 * kPointerSize); |
| 5492 } | 5579 } |
| 5493 | 5580 |
| 5494 | 5581 |
| 5582 struct AheadOfTimeWriteBarrierStubList { |
| 5583 Register object, value, address; |
| 5584 RememberedSetAction action; |
| 5585 }; |
| 5586 |
| 5587 |
| 5588 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
| 5589 // Used in RegExpExecStub. |
| 5590 { rbx, rax, rdi, EMIT_REMEMBERED_SET }, |
| 5591 // Used in CompileArrayPushCall. |
| 5592 { rbx, rcx, rdx, EMIT_REMEMBERED_SET }, |
| 5593 // Used in CompileStoreGlobal. |
| 5594 { rbx, rcx, rdx, OMIT_REMEMBERED_SET }, |
| 5595 // Used in StoreStubCompiler::CompileStoreField and |
| 5596 // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
| 5597 { rdx, rcx, rbx, EMIT_REMEMBERED_SET }, |
| 5598 // GenerateStoreField calls the stub with two different permutations of |
| 5599 // registers. This is the second. |
| 5600 { rbx, rcx, rdx, EMIT_REMEMBERED_SET }, |
| 5601 // StoreIC::GenerateNormal via GenerateDictionaryStore. |
| 5602 { rbx, r8, r9, EMIT_REMEMBERED_SET }, |
| 5603 // KeyedStoreIC::GenerateGeneric. |
| 5604 { rbx, rdx, rcx, EMIT_REMEMBERED_SET}, |
| 5605 // KeyedStoreStubCompiler::GenerateStoreFastElement. |
| 5606 { rdi, rdx, rcx, EMIT_REMEMBERED_SET}, |
| 5607 // Null termination. |
| 5608 { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} |
| 5609 }; |
| 5610 |
| 5611 |
| 5612 bool RecordWriteStub::IsPregenerated() { |
| 5613 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
| 5614 !entry->object.is(no_reg); |
| 5615 entry++) { |
| 5616 if (object_.is(entry->object) && |
| 5617 value_.is(entry->value) && |
| 5618 address_.is(entry->address) && |
| 5619 remembered_set_action_ == entry->action && |
| 5620 save_fp_regs_mode_ == kDontSaveFPRegs) { |
| 5621 return true; |
| 5622 } |
| 5623 } |
| 5624 return false; |
| 5625 } |
| 5626 |
| 5627 |
| 5628 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() { |
| 5629 StoreBufferOverflowStub stub1(kDontSaveFPRegs); |
| 5630 stub1.GetCode()->set_is_pregenerated(true); |
| 5631 StoreBufferOverflowStub stub2(kSaveFPRegs); |
| 5632 stub2.GetCode()->set_is_pregenerated(true); |
| 5633 } |
| 5634 |
| 5635 |
| 5636 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() { |
| 5637 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
| 5638 !entry->object.is(no_reg); |
| 5639 entry++) { |
| 5640 RecordWriteStub stub(entry->object, |
| 5641 entry->value, |
| 5642 entry->address, |
| 5643 entry->action, |
| 5644 kDontSaveFPRegs); |
| 5645 stub.GetCode()->set_is_pregenerated(true); |
| 5646 } |
| 5647 } |
| 5648 |
| 5649 |
| 5650 // Takes the input in 3 registers: address_ value_ and object_. A pointer to |
| 5651 // the value has just been written into the object, now this stub makes sure |
| 5652 // we keep the GC informed. The word in the object where the value has been |
| 5653 // written is in the address register. |
| 5654 void RecordWriteStub::Generate(MacroAssembler* masm) { |
| 5655 Label skip_to_incremental_noncompacting; |
| 5656 Label skip_to_incremental_compacting; |
| 5657 |
| 5658 // The first two instructions are generated with labels so as to get the |
| 5659 // offset fixed up correctly by the bind(Label*) call. We patch it back and |
| 5660 // forth between a compare instructions (a nop in this position) and the |
| 5661 // real branch when we start and stop incremental heap marking. |
| 5662 // See RecordWriteStub::Patch for details. |
| 5663 __ jmp(&skip_to_incremental_noncompacting, Label::kNear); |
| 5664 __ jmp(&skip_to_incremental_compacting, Label::kFar); |
| 5665 |
| 5666 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { |
| 5667 __ RememberedSetHelper(object_, |
| 5668 address_, |
| 5669 value_, |
| 5670 save_fp_regs_mode_, |
| 5671 MacroAssembler::kReturnAtEnd); |
| 5672 } else { |
| 5673 __ ret(0); |
| 5674 } |
| 5675 |
| 5676 __ bind(&skip_to_incremental_noncompacting); |
| 5677 GenerateIncremental(masm, INCREMENTAL); |
| 5678 |
| 5679 __ bind(&skip_to_incremental_compacting); |
| 5680 GenerateIncremental(masm, INCREMENTAL_COMPACTION); |
| 5681 |
| 5682 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. |
| 5683 // Will be checked in IncrementalMarking::ActivateGeneratedStub. |
| 5684 masm->set_byte_at(0, kTwoByteNopInstruction); |
| 5685 masm->set_byte_at(2, kFiveByteNopInstruction); |
| 5686 } |
| 5687 |
| 5688 |
| 5689 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { |
| 5690 regs_.Save(masm); |
| 5691 |
| 5692 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { |
| 5693 Label dont_need_remembered_set; |
| 5694 |
| 5695 __ movq(regs_.scratch0(), Operand(regs_.address(), 0)); |
| 5696 __ JumpIfNotInNewSpace(regs_.scratch0(), |
| 5697 regs_.scratch0(), |
| 5698 &dont_need_remembered_set); |
| 5699 |
| 5700 __ CheckPageFlag(regs_.object(), |
| 5701 regs_.scratch0(), |
| 5702 1 << MemoryChunk::SCAN_ON_SCAVENGE, |
| 5703 not_zero, |
| 5704 &dont_need_remembered_set); |
| 5705 |
| 5706 // First notify the incremental marker if necessary, then update the |
| 5707 // remembered set. |
| 5708 CheckNeedsToInformIncrementalMarker( |
| 5709 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); |
| 5710 InformIncrementalMarker(masm, mode); |
| 5711 regs_.Restore(masm); |
| 5712 __ RememberedSetHelper(object_, |
| 5713 address_, |
| 5714 value_, |
| 5715 save_fp_regs_mode_, |
| 5716 MacroAssembler::kReturnAtEnd); |
| 5717 |
| 5718 __ bind(&dont_need_remembered_set); |
| 5719 } |
| 5720 |
| 5721 CheckNeedsToInformIncrementalMarker( |
| 5722 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); |
| 5723 InformIncrementalMarker(masm, mode); |
| 5724 regs_.Restore(masm); |
| 5725 __ ret(0); |
| 5726 } |
| 5727 |
| 5728 |
| 5729 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) { |
| 5730 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); |
| 5731 #ifdef _WIN64 |
| 5732 Register arg3 = r8; |
| 5733 Register arg2 = rdx; |
| 5734 Register arg1 = rcx; |
| 5735 #else |
| 5736 Register arg3 = rdx; |
| 5737 Register arg2 = rsi; |
| 5738 Register arg1 = rdi; |
| 5739 #endif |
| 5740 Register address = |
| 5741 arg1.is(regs_.address()) ? kScratchRegister : regs_.address(); |
| 5742 ASSERT(!address.is(regs_.object())); |
| 5743 ASSERT(!address.is(arg1)); |
| 5744 __ Move(address, regs_.address()); |
| 5745 __ Move(arg1, regs_.object()); |
| 5746 if (mode == INCREMENTAL_COMPACTION) { |
| 5747 // TODO(gc) Can we just set address arg2 in the beginning? |
| 5748 __ Move(arg2, address); |
| 5749 } else { |
| 5750 ASSERT(mode == INCREMENTAL); |
| 5751 __ movq(arg2, Operand(address, 0)); |
| 5752 } |
| 5753 __ LoadAddress(arg3, ExternalReference::isolate_address()); |
| 5754 int argument_count = 3; |
| 5755 |
| 5756 AllowExternalCallThatCantCauseGC scope(masm); |
| 5757 __ PrepareCallCFunction(argument_count); |
| 5758 if (mode == INCREMENTAL_COMPACTION) { |
| 5759 __ CallCFunction( |
| 5760 ExternalReference::incremental_evacuation_record_write_function( |
| 5761 masm->isolate()), |
| 5762 argument_count); |
| 5763 } else { |
| 5764 ASSERT(mode == INCREMENTAL); |
| 5765 __ CallCFunction( |
| 5766 ExternalReference::incremental_marking_record_write_function( |
| 5767 masm->isolate()), |
| 5768 argument_count); |
| 5769 } |
| 5770 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); |
| 5771 } |
| 5772 |
| 5773 |
| 5774 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( |
| 5775 MacroAssembler* masm, |
| 5776 OnNoNeedToInformIncrementalMarker on_no_need, |
| 5777 Mode mode) { |
| 5778 Label on_black; |
| 5779 Label need_incremental; |
| 5780 Label need_incremental_pop_object; |
| 5781 |
| 5782 // Let's look at the color of the object: If it is not black we don't have |
| 5783 // to inform the incremental marker. |
| 5784 __ JumpIfBlack(regs_.object(), |
| 5785 regs_.scratch0(), |
| 5786 regs_.scratch1(), |
| 5787 &on_black, |
| 5788 Label::kNear); |
| 5789 |
| 5790 regs_.Restore(masm); |
| 5791 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { |
| 5792 __ RememberedSetHelper(object_, |
| 5793 address_, |
| 5794 value_, |
| 5795 save_fp_regs_mode_, |
| 5796 MacroAssembler::kReturnAtEnd); |
| 5797 } else { |
| 5798 __ ret(0); |
| 5799 } |
| 5800 |
| 5801 __ bind(&on_black); |
| 5802 |
| 5803 // Get the value from the slot. |
| 5804 __ movq(regs_.scratch0(), Operand(regs_.address(), 0)); |
| 5805 |
| 5806 if (mode == INCREMENTAL_COMPACTION) { |
| 5807 Label ensure_not_white; |
| 5808 |
| 5809 __ CheckPageFlag(regs_.scratch0(), // Contains value. |
| 5810 regs_.scratch1(), // Scratch. |
| 5811 MemoryChunk::kEvacuationCandidateMask, |
| 5812 zero, |
| 5813 &ensure_not_white, |
| 5814 Label::kNear); |
| 5815 |
| 5816 __ CheckPageFlag(regs_.object(), |
| 5817 regs_.scratch1(), // Scratch. |
| 5818 MemoryChunk::kSkipEvacuationSlotsRecordingMask, |
| 5819 zero, |
| 5820 &need_incremental); |
| 5821 |
| 5822 __ bind(&ensure_not_white); |
| 5823 } |
| 5824 |
| 5825 // We need an extra register for this, so we push the object register |
| 5826 // temporarily. |
| 5827 __ push(regs_.object()); |
| 5828 __ EnsureNotWhite(regs_.scratch0(), // The value. |
| 5829 regs_.scratch1(), // Scratch. |
| 5830 regs_.object(), // Scratch. |
| 5831 &need_incremental_pop_object, |
| 5832 Label::kNear); |
| 5833 __ pop(regs_.object()); |
| 5834 |
| 5835 regs_.Restore(masm); |
| 5836 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { |
| 5837 __ RememberedSetHelper(object_, |
| 5838 address_, |
| 5839 value_, |
| 5840 save_fp_regs_mode_, |
| 5841 MacroAssembler::kReturnAtEnd); |
| 5842 } else { |
| 5843 __ ret(0); |
| 5844 } |
| 5845 |
| 5846 __ bind(&need_incremental_pop_object); |
| 5847 __ pop(regs_.object()); |
| 5848 |
| 5849 __ bind(&need_incremental); |
| 5850 |
| 5851 // Fall through when we need to inform the incremental marker. |
| 5852 } |
| 5853 |
| 5854 |
| 5495 #undef __ | 5855 #undef __ |
| 5496 | 5856 |
| 5497 } } // namespace v8::internal | 5857 } } // namespace v8::internal |
| 5498 | 5858 |
| 5499 #endif // V8_TARGET_ARCH_X64 | 5859 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |