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

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 6312193: Fixed a number of issues on x64 crankshaft port: (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address comments. Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/ic-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 25 matching lines...) Expand all
36 #include "full-codegen.h" 36 #include "full-codegen.h"
37 #include "parser.h" 37 #include "parser.h"
38 #include "scopes.h" 38 #include "scopes.h"
39 #include "stub-cache.h" 39 #include "stub-cache.h"
40 40
41 namespace v8 { 41 namespace v8 {
42 namespace internal { 42 namespace internal {
43 43
44 #define __ ACCESS_MASM(masm_) 44 #define __ ACCESS_MASM(masm_)
45 45
46
47 class JumpPatchSite BASE_EMBEDDED {
48 public:
49 explicit JumpPatchSite(MacroAssembler* masm)
50 : masm_(masm) {
51 #ifdef DEBUG
52 info_emitted_ = false;
53 #endif
54 }
55
56 ~JumpPatchSite() {
57 ASSERT(patch_site_.is_bound() == info_emitted_);
58 }
59
60 void EmitJumpIfNotSmi(Register reg, NearLabel* target) {
61 __ testb(reg, Immediate(kSmiTagMask));
62 EmitJump(not_carry, target); // Always taken before patched.
63 }
64
65 void EmitJumpIfSmi(Register reg, NearLabel* target) {
66 __ testb(reg, Immediate(kSmiTagMask));
67 EmitJump(carry, target); // Never taken before patched.
68 }
69
70 void EmitPatchInfo() {
71 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
72 ASSERT(is_int8(delta_to_patch_site));
73 __ testl(rax, Immediate(delta_to_patch_site));
74 #ifdef DEBUG
75 info_emitted_ = true;
76 #endif
77 }
78
79 bool is_bound() const { return patch_site_.is_bound(); }
80
81 private:
82 // jc will be patched with jz, jnc will become jnz.
83 void EmitJump(Condition cc, NearLabel* target) {
84 ASSERT(!patch_site_.is_bound() && !info_emitted_);
85 ASSERT(cc == carry || cc == not_carry);
86 __ bind(&patch_site_);
87 __ j(cc, target);
88 }
89
90 MacroAssembler* masm_;
91 Label patch_site_;
92 #ifdef DEBUG
93 bool info_emitted_;
94 #endif
95 };
96
97
46 // Generate code for a JS function. On entry to the function the receiver 98 // Generate code for a JS function. On entry to the function the receiver
47 // and arguments have been pushed on the stack left to right, with the 99 // and arguments have been pushed on the stack left to right, with the
48 // return address on top of them. The actual argument count matches the 100 // return address on top of them. The actual argument count matches the
49 // formal parameter count expected by the function. 101 // formal parameter count expected by the function.
50 // 102 //
51 // The live registers are: 103 // The live registers are:
52 // o rdi: the JS function object being called (ie, ourselves) 104 // o rdi: the JS function object being called (ie, ourselves)
53 // o rsi: our context 105 // o rsi: our context
54 // o rbp: our caller's frame pointer 106 // o rbp: our caller's frame pointer
55 // o rsp: stack pointer (pointing to return address) 107 // o rsp: stack pointer (pointing to return address)
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 Comment cmnt(masm_, "[ Case comparison"); 773 Comment cmnt(masm_, "[ Case comparison");
722 __ bind(&next_test); 774 __ bind(&next_test);
723 next_test.Unuse(); 775 next_test.Unuse();
724 776
725 // Compile the label expression. 777 // Compile the label expression.
726 VisitForAccumulatorValue(clause->label()); 778 VisitForAccumulatorValue(clause->label());
727 779
728 // Perform the comparison as if via '==='. 780 // Perform the comparison as if via '==='.
729 __ movq(rdx, Operand(rsp, 0)); // Switch value. 781 __ movq(rdx, Operand(rsp, 0)); // Switch value.
730 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 782 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
783 JumpPatchSite patch_site(masm_);
731 if (inline_smi_code) { 784 if (inline_smi_code) {
732 Label slow_case; 785 NearLabel slow_case;
733 __ JumpIfNotBothSmi(rdx, rax, &slow_case); 786 __ movq(rcx, rdx);
734 __ SmiCompare(rdx, rax); 787 __ or_(rcx, rax);
788 patch_site.EmitJumpIfNotSmi(rcx, &slow_case);
789
790 __ cmpq(rdx, rax);
735 __ j(not_equal, &next_test); 791 __ j(not_equal, &next_test);
736 __ Drop(1); // Switch value is no longer needed. 792 __ Drop(1); // Switch value is no longer needed.
737 __ jmp(clause->body_target()->entry_label()); 793 __ jmp(clause->body_target()->entry_label());
738 __ bind(&slow_case); 794 __ bind(&slow_case);
739 } 795 }
740 796
741 CompareFlags flags = inline_smi_code 797 // Record position before stub call for type feedback.
742 ? NO_SMI_COMPARE_IN_STUB 798 SetSourcePosition(clause->position());
743 : NO_COMPARE_FLAGS; 799 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
744 CompareStub stub(equal, true, flags); 800 EmitCallIC(ic, &patch_site);
745 __ CallStub(&stub); 801
746 __ testq(rax, rax); 802 __ testq(rax, rax);
747 __ j(not_equal, &next_test); 803 __ j(not_equal, &next_test);
748 __ Drop(1); // Switch value is no longer needed. 804 __ Drop(1); // Switch value is no longer needed.
749 __ jmp(clause->body_target()->entry_label()); 805 __ jmp(clause->body_target()->entry_label());
750 } 806 }
751 807
752 // Discard the test value and jump to the default if present, otherwise to 808 // Discard the test value and jump to the default if present, otherwise to
753 // the end of the statement. 809 // the end of the statement.
754 __ bind(&next_test); 810 __ bind(&next_test);
755 __ Drop(1); // Switch value is no longer needed. 811 __ Drop(1); // Switch value is no longer needed.
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 Token::Value op, 1571 Token::Value op,
1516 OverwriteMode mode, 1572 OverwriteMode mode,
1517 Expression* left, 1573 Expression* left,
1518 Expression* right, 1574 Expression* right,
1519 ConstantOperand constant) { 1575 ConstantOperand constant) {
1520 ASSERT(constant == kNoConstants); // Only handled case. 1576 ASSERT(constant == kNoConstants); // Only handled case.
1521 1577
1522 // Do combined smi check of the operands. Left operand is on the 1578 // Do combined smi check of the operands. Left operand is on the
1523 // stack (popped into rdx). Right operand is in rax but moved into 1579 // stack (popped into rdx). Right operand is in rax but moved into
1524 // rcx to make the shifts easier. 1580 // rcx to make the shifts easier.
1525 Label done, stub_call, smi_case; 1581 NearLabel done, stub_call, smi_case;
1526 __ pop(rdx); 1582 __ pop(rdx);
1527 __ movq(rcx, rax); 1583 __ movq(rcx, rax);
1528 Condition smi = masm()->CheckBothSmi(rdx, rax); 1584 __ or_(rax, rdx);
1529 __ j(smi, &smi_case); 1585 JumpPatchSite patch_site(masm_);
1586 patch_site.EmitJumpIfSmi(rax, &smi_case);
1530 1587
1531 __ bind(&stub_call); 1588 __ bind(&stub_call);
1589 __ movq(rax, rcx);
1532 TypeRecordingBinaryOpStub stub(op, mode); 1590 TypeRecordingBinaryOpStub stub(op, mode);
1533 __ movq(rax, rcx); 1591 EmitCallIC(stub.GetCode(), &patch_site);
1534 __ CallStub(&stub);
1535 __ jmp(&done); 1592 __ jmp(&done);
1536 1593
1537 __ bind(&smi_case); 1594 __ bind(&smi_case);
1538 switch (op) { 1595 switch (op) {
1539 case Token::SAR: 1596 case Token::SAR:
1540 __ SmiShiftArithmeticRight(rax, rdx, rcx); 1597 __ SmiShiftArithmeticRight(rax, rdx, rcx);
1541 break; 1598 break;
1542 case Token::SHL: 1599 case Token::SHL:
1543 __ SmiShiftLeft(rax, rdx, rcx); 1600 __ SmiShiftLeft(rax, rdx, rcx);
1544 break; 1601 break;
(...skipping 1645 matching lines...) Expand 10 before | Expand all | Expand 10 after
3190 __ movq(Operand(rsp, kPointerSize), rax); 3247 __ movq(Operand(rsp, kPointerSize), rax);
3191 break; 3248 break;
3192 case KEYED_PROPERTY: 3249 case KEYED_PROPERTY:
3193 __ movq(Operand(rsp, 2 * kPointerSize), rax); 3250 __ movq(Operand(rsp, 2 * kPointerSize), rax);
3194 break; 3251 break;
3195 } 3252 }
3196 } 3253 }
3197 } 3254 }
3198 3255
3199 // Inline smi case if we are in a loop. 3256 // Inline smi case if we are in a loop.
3200 Label stub_call, done; 3257 NearLabel stub_call, done;
3258 JumpPatchSite patch_site(masm_);
3259
3201 if (ShouldInlineSmiCase(expr->op())) { 3260 if (ShouldInlineSmiCase(expr->op())) {
3202 if (expr->op() == Token::INC) { 3261 if (expr->op() == Token::INC) {
3203 __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3262 __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3204 } else { 3263 } else {
3205 __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3264 __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3206 } 3265 }
3207 __ j(overflow, &stub_call); 3266 __ j(overflow, &stub_call);
3208 // We could eliminate this smi check if we split the code at 3267 // We could eliminate this smi check if we split the code at
3209 // the first smi check before calling ToNumber. 3268 // the first smi check before calling ToNumber.
3210 is_smi = masm_->CheckSmi(rax); 3269 patch_site.EmitJumpIfSmi(rax, &done);
3211 __ j(is_smi, &done);
3212 3270
3213 __ bind(&stub_call); 3271 __ bind(&stub_call);
3214 // Call stub. Undo operation first. 3272 // Call stub. Undo operation first.
3215 if (expr->op() == Token::INC) { 3273 if (expr->op() == Token::INC) {
3216 __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3274 __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3217 } else { 3275 } else {
3218 __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3276 __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3219 } 3277 }
3220 } 3278 }
3221 3279
3222 // Record position before stub call. 3280 // Record position before stub call.
3223 SetSourcePosition(expr->position()); 3281 SetSourcePosition(expr->position());
3224 3282
3225 // Call stub for +1/-1. 3283 // Call stub for +1/-1.
3226 TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); 3284 TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
3227 if (expr->op() == Token::INC) { 3285 if (expr->op() == Token::INC) {
3228 __ Move(rdx, Smi::FromInt(1)); 3286 __ Move(rdx, Smi::FromInt(1));
3229 } else { 3287 } else {
3230 __ movq(rdx, rax); 3288 __ movq(rdx, rax);
3231 __ Move(rax, Smi::FromInt(1)); 3289 __ Move(rax, Smi::FromInt(1));
3232 } 3290 }
3233 __ CallStub(&stub); 3291 EmitCallIC(stub.GetCode(), &patch_site);
3292 __ bind(&done);
3234 3293
3235 __ bind(&done);
3236 // Store the value returned in rax. 3294 // Store the value returned in rax.
3237 switch (assign_type) { 3295 switch (assign_type) {
3238 case VARIABLE: 3296 case VARIABLE:
3239 if (expr->is_postfix()) { 3297 if (expr->is_postfix()) {
3240 // Perform the assignment as if via '='. 3298 // Perform the assignment as if via '='.
3241 { EffectContext context(this); 3299 { EffectContext context(this);
3242 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3300 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3243 Token::ASSIGN); 3301 Token::ASSIGN);
3244 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3302 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3245 context.Plug(rax); 3303 context.Plug(rax);
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
3493 cc = greater_equal; 3551 cc = greater_equal;
3494 __ pop(rdx); 3552 __ pop(rdx);
3495 break; 3553 break;
3496 case Token::IN: 3554 case Token::IN:
3497 case Token::INSTANCEOF: 3555 case Token::INSTANCEOF:
3498 default: 3556 default:
3499 UNREACHABLE(); 3557 UNREACHABLE();
3500 } 3558 }
3501 3559
3502 bool inline_smi_code = ShouldInlineSmiCase(op); 3560 bool inline_smi_code = ShouldInlineSmiCase(op);
3561 JumpPatchSite patch_site(masm_);
3503 if (inline_smi_code) { 3562 if (inline_smi_code) {
3504 Label slow_case; 3563 NearLabel slow_case;
3505 __ JumpIfNotBothSmi(rax, rdx, &slow_case); 3564 __ movq(rcx, rdx);
3506 __ SmiCompare(rdx, rax); 3565 __ or_(rcx, rax);
3566 patch_site.EmitJumpIfNotSmi(rcx, &slow_case);
3567 __ cmpq(rdx, rax);
3507 Split(cc, if_true, if_false, NULL); 3568 Split(cc, if_true, if_false, NULL);
3508 __ bind(&slow_case); 3569 __ bind(&slow_case);
3509 } 3570 }
3510 3571
3511 CompareFlags flags = inline_smi_code 3572 // Record position and call the compare IC.
3512 ? NO_SMI_COMPARE_IN_STUB 3573 SetSourcePosition(expr->position());
3513 : NO_COMPARE_FLAGS; 3574 Handle<Code> ic = CompareIC::GetUninitialized(op);
3514 CompareStub stub(cc, strict, flags); 3575 EmitCallIC(ic, &patch_site);
3515 __ CallStub(&stub);
3516 3576
3517 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3577 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3518 __ testq(rax, rax); 3578 __ testq(rax, rax);
3519 Split(cc, if_true, if_false, fall_through); 3579 Split(cc, if_true, if_false, fall_through);
3520 } 3580 }
3521 } 3581 }
3522 3582
3523 // Convert the result of the comparison into one expected for this 3583 // Convert the result of the comparison into one expected for this
3524 // expression's context. 3584 // expression's context.
3525 context()->Plug(if_true, if_false); 3585 context()->Plug(if_true, if_false);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
3610 case Code::KEYED_STORE_IC: 3670 case Code::KEYED_STORE_IC:
3611 __ nop(); // Signals no inlined code. 3671 __ nop(); // Signals no inlined code.
3612 break; 3672 break;
3613 default: 3673 default:
3614 // Do nothing. 3674 // Do nothing.
3615 break; 3675 break;
3616 } 3676 }
3617 } 3677 }
3618 3678
3619 3679
3680 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
3681 __ call(ic, RelocInfo::CODE_TARGET);
3682 if (patch_site != NULL && patch_site->is_bound()) {
3683 patch_site->EmitPatchInfo();
3684 } else {
3685 __ nop(); // Signals no inlined code.
3686 }
3687 }
3688
3689
3620 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3690 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3621 ASSERT(IsAligned(frame_offset, kPointerSize)); 3691 ASSERT(IsAligned(frame_offset, kPointerSize));
3622 __ movq(Operand(rbp, frame_offset), value); 3692 __ movq(Operand(rbp, frame_offset), value);
3623 } 3693 }
3624 3694
3625 3695
3626 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3696 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3627 __ movq(dst, ContextOperand(rsi, context_index)); 3697 __ movq(dst, ContextOperand(rsi, context_index));
3628 } 3698 }
3629 3699
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3661 __ ret(0); 3731 __ ret(0);
3662 } 3732 }
3663 3733
3664 3734
3665 #undef __ 3735 #undef __
3666 3736
3667 3737
3668 } } // namespace v8::internal 3738 } } // namespace v8::internal
3669 3739
3670 #endif // V8_TARGET_ARCH_X64 3740 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698