Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1071)

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 6664001: [Isolates] Merge (7083,7111] from bleeding_edge. (Closed)
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 2408 matching lines...) Expand 10 before | Expand all | Expand 10 after
2419 // rsp[16]: previous index 2419 // rsp[16]: previous index
2420 // rsp[24]: subject string 2420 // rsp[24]: subject string
2421 // rsp[32]: JSRegExp object 2421 // rsp[32]: JSRegExp object
2422 2422
2423 static const int kLastMatchInfoOffset = 1 * kPointerSize; 2423 static const int kLastMatchInfoOffset = 1 * kPointerSize;
2424 static const int kPreviousIndexOffset = 2 * kPointerSize; 2424 static const int kPreviousIndexOffset = 2 * kPointerSize;
2425 static const int kSubjectOffset = 3 * kPointerSize; 2425 static const int kSubjectOffset = 3 * kPointerSize;
2426 static const int kJSRegExpOffset = 4 * kPointerSize; 2426 static const int kJSRegExpOffset = 4 * kPointerSize;
2427 2427
2428 Label runtime; 2428 Label runtime;
2429
2430 // Ensure that a RegExp stack is allocated. 2429 // Ensure that a RegExp stack is allocated.
2431 ExternalReference address_of_regexp_stack_memory_address = 2430 ExternalReference address_of_regexp_stack_memory_address =
2432 ExternalReference::address_of_regexp_stack_memory_address(); 2431 ExternalReference::address_of_regexp_stack_memory_address();
2433 ExternalReference address_of_regexp_stack_memory_size = 2432 ExternalReference address_of_regexp_stack_memory_size =
2434 ExternalReference::address_of_regexp_stack_memory_size(); 2433 ExternalReference::address_of_regexp_stack_memory_size();
2435 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); 2434 __ movq(kScratchRegister, address_of_regexp_stack_memory_size);
2436 __ movq(kScratchRegister, Operand(kScratchRegister, 0)); 2435 __ movq(kScratchRegister, Operand(kScratchRegister, 0));
2437 __ testq(kScratchRegister, kScratchRegister); 2436 __ testq(kScratchRegister, kScratchRegister);
2438 __ j(zero, &runtime); 2437 __ j(zero, &runtime);
2439 2438
2440 2439
2441 // Check that the first argument is a JSRegExp object. 2440 // Check that the first argument is a JSRegExp object.
2442 __ movq(rax, Operand(rsp, kJSRegExpOffset)); 2441 __ movq(rax, Operand(rsp, kJSRegExpOffset));
2443 __ JumpIfSmi(rax, &runtime); 2442 __ JumpIfSmi(rax, &runtime);
2444 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); 2443 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
2445 __ j(not_equal, &runtime); 2444 __ j(not_equal, &runtime);
2446 // Check that the RegExp has been compiled (data contains a fixed array). 2445 // Check that the RegExp has been compiled (data contains a fixed array).
2447 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); 2446 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset));
2448 if (FLAG_debug_code) { 2447 if (FLAG_debug_code) {
2449 Condition is_smi = masm->CheckSmi(rcx); 2448 Condition is_smi = masm->CheckSmi(rax);
2450 __ Check(NegateCondition(is_smi), 2449 __ Check(NegateCondition(is_smi),
2451 "Unexpected type for RegExp data, FixedArray expected"); 2450 "Unexpected type for RegExp data, FixedArray expected");
2452 __ CmpObjectType(rcx, FIXED_ARRAY_TYPE, kScratchRegister); 2451 __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
2453 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); 2452 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
2454 } 2453 }
2455 2454
2456 // rcx: RegExp data (FixedArray) 2455 // rax: RegExp data (FixedArray)
2457 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 2456 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
2458 __ SmiToInteger32(rbx, FieldOperand(rcx, JSRegExp::kDataTagOffset)); 2457 __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset));
2459 __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP)); 2458 __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP));
2460 __ j(not_equal, &runtime); 2459 __ j(not_equal, &runtime);
2461 2460
2462 // rcx: RegExp data (FixedArray) 2461 // rax: RegExp data (FixedArray)
2463 // Check that the number of captures fit in the static offsets vector buffer. 2462 // Check that the number of captures fit in the static offsets vector buffer.
2464 __ SmiToInteger32(rdx, 2463 __ SmiToInteger32(rdx,
2465 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); 2464 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset));
2466 // Calculate number of capture registers (number_of_captures + 1) * 2. 2465 // Calculate number of capture registers (number_of_captures + 1) * 2.
2467 __ leal(rdx, Operand(rdx, rdx, times_1, 2)); 2466 __ leal(rdx, Operand(rdx, rdx, times_1, 2));
2468 // Check that the static offsets vector buffer is large enough. 2467 // Check that the static offsets vector buffer is large enough.
2469 __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize)); 2468 __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize));
2470 __ j(above, &runtime); 2469 __ j(above, &runtime);
2471 2470
2472 // rcx: RegExp data (FixedArray) 2471 // rax: RegExp data (FixedArray)
2473 // rdx: Number of capture registers 2472 // rdx: Number of capture registers
2474 // Check that the second argument is a string. 2473 // Check that the second argument is a string.
2475 __ movq(rdi, Operand(rsp, kSubjectOffset)); 2474 __ movq(rdi, Operand(rsp, kSubjectOffset));
2476 __ JumpIfSmi(rdi, &runtime); 2475 __ JumpIfSmi(rdi, &runtime);
2477 Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx); 2476 Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx);
2478 __ j(NegateCondition(is_string), &runtime); 2477 __ j(NegateCondition(is_string), &runtime);
2479 2478
2480 // rdi: Subject string. 2479 // rdi: Subject string.
2481 // rax: RegExp data (FixedArray). 2480 // rax: RegExp data (FixedArray).
2482 // rdx: Number of capture registers. 2481 // rdx: Number of capture registers.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2581 // rbx: previous index 2580 // rbx: previous index
2582 // rcx: encoding of subject string (1 if ascii 0 if two_byte); 2581 // rcx: encoding of subject string (1 if ascii 0 if two_byte);
2583 // r11: code 2582 // r11: code
2584 // All checks done. Now push arguments for native regexp code. 2583 // All checks done. Now push arguments for native regexp code.
2585 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1); 2584 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1);
2586 2585
2587 // Isolates: note we add an additional parameter here (isolate pointer). 2586 // Isolates: note we add an additional parameter here (isolate pointer).
2588 static const int kRegExpExecuteArguments = 8; 2587 static const int kRegExpExecuteArguments = 8;
2589 int argument_slots_on_stack = 2588 int argument_slots_on_stack =
2590 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); 2589 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
2591 __ EnterApiExitFrame(argument_slots_on_stack); // Clobbers rax! 2590 __ EnterApiExitFrame(argument_slots_on_stack);
2592 2591
2593 // Argument 8: Pass current isolate address. 2592 // Argument 8: Pass current isolate address.
2594 // __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), 2593 // __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
2595 // Immediate(ExternalReference::isolate_address())); 2594 // Immediate(ExternalReference::isolate_address()));
2596 __ movq(kScratchRegister, ExternalReference::isolate_address()); 2595 __ movq(kScratchRegister, ExternalReference::isolate_address());
2597 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), 2596 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
2598 kScratchRegister); 2597 kScratchRegister);
2599 2598
2600 // Argument 7: Indicate that this is a direct call from JavaScript. 2599 // Argument 7: Indicate that this is a direct call from JavaScript.
2601 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), 2600 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize),
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
3306 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); 3305 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi);
3307 __ Set(rax, argc_); 3306 __ Set(rax, argc_);
3308 __ Set(rbx, 0); 3307 __ Set(rbx, 0);
3309 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); 3308 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
3310 Handle<Code> adaptor(Isolate::Current()->builtins()->builtin( 3309 Handle<Code> adaptor(Isolate::Current()->builtins()->builtin(
3311 Builtins::ArgumentsAdaptorTrampoline)); 3310 Builtins::ArgumentsAdaptorTrampoline));
3312 __ Jump(adaptor, RelocInfo::CODE_TARGET); 3311 __ Jump(adaptor, RelocInfo::CODE_TARGET);
3313 } 3312 }
3314 3313
3315 3314
3315 bool CEntryStub::NeedsImmovableCode() {
3316 return false;
3317 }
3318
3319
3316 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 3320 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
3317 // Throw exception in eax. 3321 // Throw exception in eax.
3318 __ Throw(rax); 3322 __ Throw(rax);
3319 } 3323 }
3320 3324
3321 3325
3322 void CEntryStub::GenerateCore(MacroAssembler* masm, 3326 void CEntryStub::GenerateCore(MacroAssembler* masm,
3323 Label* throw_normal_exception, 3327 Label* throw_normal_exception,
3324 Label* throw_termination_exception, 3328 Label* throw_termination_exception,
3325 Label* throw_out_of_memory_exception, 3329 Label* throw_out_of_memory_exception,
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
3663 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers 3667 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers
3664 3668
3665 // Restore frame pointer and return. 3669 // Restore frame pointer and return.
3666 __ pop(rbp); 3670 __ pop(rbp);
3667 __ ret(0); 3671 __ ret(0);
3668 } 3672 }
3669 3673
3670 3674
3671 void InstanceofStub::Generate(MacroAssembler* masm) { 3675 void InstanceofStub::Generate(MacroAssembler* masm) {
3672 // Implements "value instanceof function" operator. 3676 // Implements "value instanceof function" operator.
3673 // Expected input state: 3677 // Expected input state with no inline cache:
3674 // rsp[0] : return address 3678 // rsp[0] : return address
3675 // rsp[1] : function pointer 3679 // rsp[1] : function pointer
3676 // rsp[2] : value 3680 // rsp[2] : value
3681 // Expected input state with an inline one-element cache:
3682 // rsp[0] : return address
3683 // rsp[1] : offset from return address to location of inline cache
3684 // rsp[2] : function pointer
3685 // rsp[3] : value
3677 // Returns a bitwise zero to indicate that the value 3686 // Returns a bitwise zero to indicate that the value
3678 // is and instance of the function and anything else to 3687 // is and instance of the function and anything else to
3679 // indicate that the value is not an instance. 3688 // indicate that the value is not an instance.
3680 3689
3681 // None of the flags are supported on X64. 3690 static const int kOffsetToMapCheckValue = 5;
3682 ASSERT(flags_ == kNoFlags); 3691 static const int kOffsetToResultValue = 21;
3692 // The last 4 bytes of the instruction sequence
3693 // movq(rax, FieldOperand(rdi, HeapObject::kMapOffset)
3694 // Move(kScratchRegister, Factory::the_hole_value)
3695 // in front of the hole value address.
3696 static const unsigned int kWordBeforeMapCheckValue = 0xBA49FF78;
3697 // The last 4 bytes of the instruction sequence
3698 // __ j(not_equal, &cache_miss);
3699 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
3700 // before the offset of the hole value in the root array.
3701 static const unsigned int kWordBeforeResultValue = 0x458B4909;
3702 // Only the inline check flag is supported on X64.
3703 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck());
3704 int extra_stack_space = HasCallSiteInlineCheck() ? kPointerSize : 0;
3683 3705
3684 // Get the object - go slow case if it's a smi. 3706 // Get the object - go slow case if it's a smi.
3685 Label slow; 3707 Label slow;
3686 __ movq(rax, Operand(rsp, 2 * kPointerSize)); 3708
3709 __ movq(rax, Operand(rsp, 2 * kPointerSize + extra_stack_space));
3687 __ JumpIfSmi(rax, &slow); 3710 __ JumpIfSmi(rax, &slow);
3688 3711
3689 // Check that the left hand is a JS object. Leave its map in rax. 3712 // Check that the left hand is a JS object. Leave its map in rax.
3690 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); 3713 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax);
3691 __ j(below, &slow); 3714 __ j(below, &slow);
3692 __ CmpInstanceType(rax, LAST_JS_OBJECT_TYPE); 3715 __ CmpInstanceType(rax, LAST_JS_OBJECT_TYPE);
3693 __ j(above, &slow); 3716 __ j(above, &slow);
3694 3717
3695 // Get the prototype of the function. 3718 // Get the prototype of the function.
3696 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); 3719 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space));
3697 // rdx is function, rax is map. 3720 // rdx is function, rax is map.
3698 3721
3699 // Look up the function and the map in the instanceof cache. 3722 // If there is a call site cache don't look in the global cache, but do the
3700 NearLabel miss; 3723 // real lookup and update the call site cache.
3701 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 3724 if (!HasCallSiteInlineCheck()) {
3702 __ j(not_equal, &miss); 3725 // Look up the function and the map in the instanceof cache.
3703 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); 3726 NearLabel miss;
3704 __ j(not_equal, &miss); 3727 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
3705 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3728 __ j(not_equal, &miss);
3706 __ ret(2 * kPointerSize); 3729 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
3730 __ j(not_equal, &miss);
3731 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
3732 __ ret(2 * kPointerSize);
3733 __ bind(&miss);
3734 }
3707 3735
3708 __ bind(&miss);
3709 __ TryGetFunctionPrototype(rdx, rbx, &slow); 3736 __ TryGetFunctionPrototype(rdx, rbx, &slow);
3710 3737
3711 // Check that the function prototype is a JS object. 3738 // Check that the function prototype is a JS object.
3712 __ JumpIfSmi(rbx, &slow); 3739 __ JumpIfSmi(rbx, &slow);
3713 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister); 3740 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister);
3714 __ j(below, &slow); 3741 __ j(below, &slow);
3715 __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE); 3742 __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE);
3716 __ j(above, &slow); 3743 __ j(above, &slow);
3717 3744
3718 // Register mapping: 3745 // Register mapping:
3719 // rax is object map. 3746 // rax is object map.
3720 // rdx is function. 3747 // rdx is function.
3721 // rbx is function prototype. 3748 // rbx is function prototype.
3722 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 3749 if (!HasCallSiteInlineCheck()) {
3723 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); 3750 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
3751 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
3752 } else {
3753 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
3754 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
3755 __ movq(Operand(kScratchRegister, kOffsetToMapCheckValue), rax);
3756 if (FLAG_debug_code) {
3757 __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
3758 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
3759 __ Assert(equal, "InstanceofStub unexpected call site cache.");
3760 }
3761 }
3724 3762
3725 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset)); 3763 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset));
3726 3764
3727 // Loop through the prototype chain looking for the function prototype. 3765 // Loop through the prototype chain looking for the function prototype.
3728 NearLabel loop, is_instance, is_not_instance; 3766 NearLabel loop, is_instance, is_not_instance;
3729 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); 3767 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex);
3730 __ bind(&loop); 3768 __ bind(&loop);
3731 __ cmpq(rcx, rbx); 3769 __ cmpq(rcx, rbx);
3732 __ j(equal, &is_instance); 3770 __ j(equal, &is_instance);
3733 __ cmpq(rcx, kScratchRegister); 3771 __ cmpq(rcx, kScratchRegister);
3734 // The code at is_not_instance assumes that kScratchRegister contains a 3772 // The code at is_not_instance assumes that kScratchRegister contains a
3735 // non-zero GCable value (the null object in this case). 3773 // non-zero GCable value (the null object in this case).
3736 __ j(equal, &is_not_instance); 3774 __ j(equal, &is_not_instance);
3737 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 3775 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3738 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); 3776 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
3739 __ jmp(&loop); 3777 __ jmp(&loop);
3740 3778
3741 __ bind(&is_instance); 3779 __ bind(&is_instance);
3742 __ xorl(rax, rax); 3780 if (!HasCallSiteInlineCheck()) {
3743 // Store bitwise zero in the cache. This is a Smi in GC terms. 3781 __ xorl(rax, rax);
3744 STATIC_ASSERT(kSmiTag == 0); 3782 // Store bitwise zero in the cache. This is a Smi in GC terms.
3745 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3783 STATIC_ASSERT(kSmiTag == 0);
3746 __ ret(2 * kPointerSize); 3784 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
3785 } else {
3786 // Store offset of true in the root array at the inline check site.
3787 ASSERT((Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias
3788 == 0xB0 - 0x100);
3789 __ movl(rax, Immediate(0xB0)); // TrueValue is at -10 * kPointerSize.
3790 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
3791 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
3792 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
3793 if (FLAG_debug_code) {
3794 __ movl(rax, Immediate(kWordBeforeResultValue));
3795 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
3796 __ Assert(equal, "InstanceofStub unexpected call site cache.");
3797 }
3798 __ xorl(rax, rax);
3799 }
3800 __ ret(2 * kPointerSize + extra_stack_space);
3747 3801
3748 __ bind(&is_not_instance); 3802 __ bind(&is_not_instance);
3749 // We have to store a non-zero value in the cache. 3803 if (!HasCallSiteInlineCheck()) {
3750 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); 3804 // We have to store a non-zero value in the cache.
3751 __ ret(2 * kPointerSize); 3805 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
3806 } else {
3807 // Store offset of false in the root array at the inline check site.
3808 ASSERT((Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias
3809 == 0xB8 - 0x100);
3810 __ movl(rax, Immediate(0xB8)); // FalseValue is at -9 * kPointerSize.
3811 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
3812 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
3813 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
3814 if (FLAG_debug_code) {
3815 __ movl(rax, Immediate(kWordBeforeResultValue));
3816 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
3817 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
3818 }
3819 }
3820 __ ret(2 * kPointerSize + extra_stack_space);
3752 3821
3753 // Slow-case: Go through the JavaScript implementation. 3822 // Slow-case: Go through the JavaScript implementation.
3754 __ bind(&slow); 3823 __ bind(&slow);
3824 if (HasCallSiteInlineCheck()) {
3825 // Remove extra value from the stack.
3826 __ pop(rcx);
3827 __ pop(rax);
3828 __ push(rcx);
3829 }
3755 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 3830 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
3756 } 3831 }
3757 3832
3758 3833
3759 // Passing arguments in registers is not supported. 3834 // Passing arguments in registers is not supported.
3760 Register InstanceofStub::left() { return no_reg; } 3835 Register InstanceofStub::left() { return no_reg; }
3761 3836
3762 3837
3763 Register InstanceofStub::right() { return no_reg; } 3838 Register InstanceofStub::right() { return no_reg; }
3764 3839
(...skipping 1250 matching lines...) Expand 10 before | Expand all | Expand 10 after
5015 __ pop(rcx); 5090 __ pop(rcx);
5016 __ pop(rax); 5091 __ pop(rax);
5017 __ pop(rdx); 5092 __ pop(rdx);
5018 __ push(rcx); 5093 __ push(rcx);
5019 5094
5020 // Do a tail call to the rewritten stub. 5095 // Do a tail call to the rewritten stub.
5021 __ jmp(rdi); 5096 __ jmp(rdi);
5022 } 5097 }
5023 5098
5024 5099
5025 void GenerateFastPixelArrayLoad(MacroAssembler* masm,
5026 Register receiver,
5027 Register key,
5028 Register elements,
5029 Register untagged_key,
5030 Register result,
5031 Label* not_pixel_array,
5032 Label* key_not_smi,
5033 Label* out_of_range) {
5034 // Register use:
5035 // receiver - holds the receiver and is unchanged.
5036 // key - holds the key and is unchanged (must be a smi).
5037 // elements - is set to the the receiver's element if
5038 // the receiver doesn't have a pixel array or the
5039 // key is not a smi, otherwise it's the elements'
5040 // external pointer.
5041 // untagged_key - is set to the untagged key
5042
5043 // Some callers already have verified that the key is a smi. key_not_smi is
5044 // set to NULL as a sentinel for that case. Otherwise, add an explicit check
5045 // to ensure the key is a smi must be added.
5046 if (key_not_smi != NULL) {
5047 __ JumpIfNotSmi(key, key_not_smi);
5048 } else {
5049 if (FLAG_debug_code) {
5050 __ AbortIfNotSmi(key);
5051 }
5052 }
5053 __ SmiToInteger32(untagged_key, key);
5054
5055 __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
5056 // By passing NULL as not_pixel_array, callers signal that they have already
5057 // verified that the receiver has pixel array elements.
5058 if (not_pixel_array != NULL) {
5059 __ CheckMap(elements, FACTORY->pixel_array_map(), not_pixel_array, true);
5060 } else {
5061 if (FLAG_debug_code) {
5062 // Map check should have already made sure that elements is a pixel array.
5063 __ Cmp(FieldOperand(elements, HeapObject::kMapOffset),
5064 FACTORY->pixel_array_map());
5065 __ Assert(equal, "Elements isn't a pixel array");
5066 }
5067 }
5068
5069 // Check that the smi is in range.
5070 __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
5071 __ j(above_equal, out_of_range); // unsigned check handles negative keys.
5072
5073 // Load and tag the element as a smi.
5074 __ movq(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset));
5075 __ movzxbq(result, Operand(elements, untagged_key, times_1, 0));
5076 __ Integer32ToSmi(result, result);
5077 __ ret(0);
5078 }
5079
5080
5081 // Stores an indexed element into a pixel array, clamping the stored value.
5082 void GenerateFastPixelArrayStore(MacroAssembler* masm,
5083 Register receiver,
5084 Register key,
5085 Register value,
5086 Register elements,
5087 Register scratch1,
5088 bool load_elements_from_receiver,
5089 bool key_is_untagged,
5090 Label* key_not_smi,
5091 Label* value_not_smi,
5092 Label* not_pixel_array,
5093 Label* out_of_range) {
5094 // Register use:
5095 // receiver - holds the receiver and is unchanged.
5096 // key - holds the key (must be a smi) and is unchanged.
5097 // value - holds the value (must be a smi) and is unchanged.
5098 // elements - holds the element object of the receiver on entry if
5099 // load_elements_from_receiver is false, otherwise used
5100 // internally to store the pixel arrays elements and
5101 // external array pointer.
5102 //
5103 Register external_pointer = elements;
5104 Register untagged_key = scratch1;
5105 Register untagged_value = receiver; // Only set once success guaranteed.
5106
5107 // Fetch the receiver's elements if the caller hasn't already done so.
5108 if (load_elements_from_receiver) {
5109 __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
5110 }
5111
5112 // By passing NULL as not_pixel_array, callers signal that they have already
5113 // verified that the receiver has pixel array elements.
5114 if (not_pixel_array != NULL) {
5115 __ CheckMap(elements, FACTORY->pixel_array_map(), not_pixel_array, true);
5116 } else {
5117 if (FLAG_debug_code) {
5118 // Map check should have already made sure that elements is a pixel array.
5119 __ Cmp(FieldOperand(elements, HeapObject::kMapOffset),
5120 FACTORY->pixel_array_map());
5121 __ Assert(equal, "Elements isn't a pixel array");
5122 }
5123 }
5124
5125 // Key must be a smi and it must be in range.
5126 if (key_is_untagged) {
5127 untagged_key = key;
5128 } else {
5129 // Some callers already have verified that the key is a smi. key_not_smi is
5130 // set to NULL as a sentinel for that case. Otherwise, add an explicit
5131 // check to ensure the key is a smi.
5132 if (key_not_smi != NULL) {
5133 __ JumpIfNotSmi(key, key_not_smi);
5134 } else {
5135 if (FLAG_debug_code) {
5136 __ AbortIfNotSmi(key);
5137 }
5138 }
5139 __ SmiToInteger32(untagged_key, key);
5140 }
5141 __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
5142 __ j(above_equal, out_of_range); // unsigned check handles negative keys.
5143
5144 // Value must be a smi.
5145 __ JumpIfNotSmi(value, value_not_smi);
5146 __ SmiToInteger32(untagged_value, value);
5147
5148 { // Clamp the value to [0..255].
5149 NearLabel done;
5150 __ testl(untagged_value, Immediate(0xFFFFFF00));
5151 __ j(zero, &done);
5152 __ setcc(negative, untagged_value); // 1 if negative, 0 if positive.
5153 __ decb(untagged_value); // 0 if negative, 255 if positive.
5154 __ bind(&done);
5155 }
5156
5157 __ movq(external_pointer,
5158 FieldOperand(elements, PixelArray::kExternalPointerOffset));
5159 __ movb(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
5160 __ ret(0); // Return value in eax.
5161 }
5162
5163 #undef __ 5100 #undef __
5164 5101
5165 } } // namespace v8::internal 5102 } } // namespace v8::internal
5166 5103
5167 #endif // V8_TARGET_ARCH_X64 5104 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698