Chromium Code Reviews| Index: src/ia32/full-codegen-ia32.cc |
| =================================================================== |
| --- src/ia32/full-codegen-ia32.cc (revision 5966) |
| +++ src/ia32/full-codegen-ia32.cc (working copy) |
| @@ -41,6 +41,37 @@ |
| namespace v8 { |
| namespace internal { |
| + |
| +class JumpPatchSite BASE_EMBEDDED { |
| + public: |
| + JumpPatchSite(MacroAssembler* masm) : masm_(masm), info_emitted_(false) { } |
|
Vitaly Repeshko
2010/12/10 13:38:56
Missing "explicit".
fschneider
2010/12/10 14:32:17
Done.
|
| + |
| + ~JumpPatchSite() { |
| + ASSERT(patch_site_.is_bound() == info_emitted_); |
| + } |
| + |
| + void EmitJump(NearLabel* target) { |
| + ASSERT(!patch_site_.is_bound() && !info_emitted_); |
| + masm_->bind(&patch_site_); |
| + masm_->jmp(target); |
| + } |
| + |
| + void EmitPatchInfo() { |
| + int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); |
| + ASSERT(is_int8(delta_to_patch_site)); |
| + masm_->test(eax, Immediate(delta_to_patch_site)); |
| + info_emitted_ = true; |
| + } |
| + |
| + bool is_bound() { return patch_site_.is_bound(); } |
|
Vitaly Repeshko
2010/12/10 13:38:56
Can it be made const?
fschneider
2010/12/10 14:32:17
Done.
|
| + |
| + private: |
| + MacroAssembler* masm_; |
| + Label patch_site_; |
| + bool info_emitted_; |
|
Vitaly Repeshko
2010/12/10 13:38:56
Should probably be guarded by #ifdef DEBUG.
fschneider
2010/12/10 14:32:17
Done.
|
| +}; |
| + |
| + |
| #define __ ACCESS_MASM(masm_) |
| // Generate code for a JS function. On entry to the function the receiver |
| @@ -715,12 +746,13 @@ |
| // Perform the comparison as if via '==='. |
| __ mov(edx, Operand(esp, 0)); // Switch value. |
| bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); |
| + JumpPatchSite patch_site(masm_); |
| if (inline_smi_code) { |
| NearLabel slow_case; |
| __ mov(ecx, edx); |
| __ or_(ecx, Operand(eax)); |
| __ test(ecx, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &slow_case, not_taken); |
| + patch_site.EmitJump(&slow_case); |
| __ cmp(edx, Operand(eax)); |
| __ j(not_equal, &next_test); |
| __ Drop(1); // Switch value is no longer needed. |
| @@ -730,9 +762,8 @@ |
| // Record position before stub call for type feedback. |
| SetSourcePosition(clause->position()); |
| - |
| Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
| - __ call(ic, RelocInfo::CODE_TARGET); |
| + EmitCallIC(ic, &patch_site); |
| __ test(eax, Operand(eax)); |
| __ j(not_equal, &next_test); |
| @@ -1552,12 +1583,13 @@ |
| OverwriteMode mode, |
| bool left_is_constant_smi, |
| Smi* value) { |
| - NearLabel call_stub; |
| - Label done; |
| + NearLabel call_stub, done; |
| __ add(Operand(eax), Immediate(value)); |
| __ j(overflow, &call_stub); |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &done); |
| + JumpPatchSite patch_site(masm_); |
| + patch_site.EmitJump(&call_stub); |
| + __ jmp(&done); |
| // Undo the optimistic add operation and call the shared stub. |
| __ bind(&call_stub); |
| @@ -1570,7 +1602,8 @@ |
| __ mov(edx, eax); |
| __ mov(eax, Immediate(value)); |
| } |
| - __ CallStub(&stub); |
| + EmitCallIC(stub.GetCode(), &patch_site); |
| + |
| __ bind(&done); |
| context()->Plug(eax); |
| } |
| @@ -1580,7 +1613,7 @@ |
| OverwriteMode mode, |
| bool left_is_constant_smi, |
| Smi* value) { |
| - Label call_stub, done; |
| + NearLabel call_stub, done; |
| if (left_is_constant_smi) { |
| __ mov(ecx, eax); |
| __ mov(eax, Immediate(value)); |
| @@ -1590,7 +1623,9 @@ |
| } |
| __ j(overflow, &call_stub); |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &done); |
| + JumpPatchSite patch_site(masm_); |
| + patch_site.EmitJump(&call_stub); |
| + __ jmp(&done); |
| __ bind(&call_stub); |
| if (left_is_constant_smi) { |
| @@ -1603,7 +1638,8 @@ |
| } |
| Token::Value op = Token::SUB; |
| TypeRecordingBinaryOpStub stub(op, mode); |
| - __ CallStub(&stub); |
| + EmitCallIC(stub.GetCode(), &patch_site); |
| + |
| __ bind(&done); |
| context()->Plug(eax); |
| } |
| @@ -1613,20 +1649,15 @@ |
| Token::Value op, |
| OverwriteMode mode, |
| Smi* value) { |
| - Label call_stub, smi_case, done; |
| + NearLabel call_stub, done; |
| int shift_value = value->value() & 0x1f; |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &smi_case); |
| + // Patch site. |
| + JumpPatchSite patch_site(masm_); |
| + patch_site.EmitJump(&call_stub); |
| - __ bind(&call_stub); |
| - __ mov(edx, eax); |
| - __ mov(eax, Immediate(value)); |
| - TypeRecordingBinaryOpStub stub(op, mode); |
| - __ CallStub(&stub); |
| - __ jmp(&done); |
| - |
| - __ bind(&smi_case); |
| + // Smi case. |
| switch (op) { |
| case Token::SHL: |
| if (shift_value != 0) { |
| @@ -1665,7 +1696,15 @@ |
| default: |
| UNREACHABLE(); |
| } |
| + __ jmp(&done); |
| + // Call stub. |
| + __ bind(&call_stub); |
| + __ mov(edx, eax); |
| + __ mov(eax, Immediate(value)); |
| + TypeRecordingBinaryOpStub stub(op, mode); |
| + EmitCallIC(stub.GetCode(), &patch_site); |
| + |
| __ bind(&done); |
| context()->Plug(eax); |
| } |
| @@ -1675,18 +1714,14 @@ |
| Token::Value op, |
| OverwriteMode mode, |
| Smi* value) { |
| - Label smi_case, done; |
| + NearLabel call_stub, done; |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &smi_case); |
| + // Patch site. The first invocation of the stub will be patch the jmp with |
| + // the required conditional jump. |
| + JumpPatchSite patch_site(masm_); |
| + patch_site.EmitJump(&call_stub); |
| - // The order of the arguments does not matter for bit-ops with a |
| - // constant operand. |
| - __ mov(edx, Immediate(value)); |
| - TypeRecordingBinaryOpStub stub(op, mode); |
| - __ CallStub(&stub); |
| - __ jmp(&done); |
| - |
| - __ bind(&smi_case); |
| + // Smi case. |
| switch (op) { |
| case Token::BIT_OR: |
| __ or_(Operand(eax), Immediate(value)); |
| @@ -1700,7 +1735,15 @@ |
| default: |
| UNREACHABLE(); |
| } |
| + __ jmp(&done); |
| + // The order of the arguments does not matter for bit-ops with a |
| + // constant operand. |
| + __ bind(&call_stub); |
| + __ mov(edx, Immediate(value)); |
| + TypeRecordingBinaryOpStub stub(op, mode); |
| + EmitCallIC(stub.GetCode(), &patch_site); |
| + |
| __ bind(&done); |
| context()->Plug(eax); |
| } |
| @@ -1753,20 +1796,15 @@ |
| // Do combined smi check of the operands. Left operand is on the |
| // stack. Right operand is in eax. |
| - Label done, stub_call, smi_case; |
| + NearLabel done, stub_call; |
| __ pop(edx); |
| __ mov(ecx, eax); |
| __ or_(eax, Operand(edx)); |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &smi_case); |
| + JumpPatchSite patch_site(masm_); |
| + patch_site.EmitJump(&stub_call); |
| - __ bind(&stub_call); |
| - __ mov(eax, ecx); |
| - TypeRecordingBinaryOpStub stub(op, mode); |
| - __ CallStub(&stub); |
| - __ jmp(&done); |
| - |
| - __ bind(&smi_case); |
| + // Smi case. |
| __ mov(eax, edx); // Copy left operand in case of a stub call. |
| switch (op) { |
| @@ -1834,7 +1872,13 @@ |
| default: |
| UNREACHABLE(); |
| } |
| + __ jmp(&done); |
| + __ bind(&stub_call); |
| + __ mov(eax, ecx); |
| + TypeRecordingBinaryOpStub stub(op, mode); |
| + EmitCallIC(stub.GetCode(), &patch_site); |
| + |
| __ bind(&done); |
| context()->Plug(eax); |
| } |
| @@ -1845,6 +1889,7 @@ |
| __ pop(edx); |
| TypeRecordingBinaryOpStub stub(op, mode); |
| __ CallStub(&stub); |
|
Vitaly Repeshko
2010/12/10 13:38:56
How about making patch site an optional parameter
fschneider
2010/12/10 14:32:17
Done.
|
| + __ nop(); // Signals no inlined smi code. |
| context()->Plug(eax); |
| } |
| @@ -3709,6 +3754,7 @@ |
| // Inline smi case if we are in a loop. |
| NearLabel stub_call; |
| + JumpPatchSite patch_site(masm_); |
| Label done; |
| if (ShouldInlineSmiCase(expr->op())) { |
| if (expr->op() == Token::INC) { |
| @@ -3720,7 +3766,9 @@ |
| // We could eliminate this smi check if we split the code at |
| // the first smi check before calling ToNumber. |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &done); |
| + patch_site.EmitJump(&stub_call); |
| + __ jmp(&done); |
| + |
| __ bind(&stub_call); |
| // Call stub. Undo operation first. |
| if (expr->op() == Token::INC) { |
| @@ -3738,9 +3786,9 @@ |
| __ mov(eax, Immediate(Smi::FromInt(1))); |
| TypeRecordingBinaryOpStub stub(expr->binary_op(), |
| NO_OVERWRITE); |
| - __ CallStub(&stub); |
| + EmitCallIC(stub.GetCode(), &patch_site); |
| + |
| __ bind(&done); |
| - |
| // Store the value returned in eax. |
| switch (assign_type) { |
| case VARIABLE: |
| @@ -4005,21 +4053,23 @@ |
| } |
| bool inline_smi_code = ShouldInlineSmiCase(op); |
| + JumpPatchSite patch_site(masm_); |
| if (inline_smi_code) { |
| NearLabel slow_case; |
| __ mov(ecx, Operand(edx)); |
| __ or_(ecx, Operand(eax)); |
| __ test(ecx, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &slow_case, not_taken); |
| + patch_site.EmitJump(&slow_case); |
| __ cmp(edx, Operand(eax)); |
| Split(cc, if_true, if_false, NULL); |
| __ bind(&slow_case); |
| } |
| // Record position and call the compare IC. |
| + SetSourcePosition(expr->position()); |
| Handle<Code> ic = CompareIC::GetUninitialized(op); |
| - SetSourcePosition(expr->position()); |
| - __ call(ic, RelocInfo::CODE_TARGET); |
| + EmitCallIC(ic, &patch_site); |
| + |
| PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| __ test(eax, Operand(eax)); |
| Split(cc, if_true, if_false, fall_through); |
| @@ -4123,6 +4173,16 @@ |
| } |
| +void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { |
| + __ call(ic, RelocInfo::CODE_TARGET); |
| + if (patch_site->is_bound()) { |
| + patch_site->EmitPatchInfo(); |
| + } else { |
| + __ nop(); // Signals no inlined code. |
| + } |
| +} |
| + |
| + |
| void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| __ mov(Operand(ebp, frame_offset), value); |