Index: src/arm/ic-arm.cc |
=================================================================== |
--- src/arm/ic-arm.cc (revision 6683) |
+++ src/arm/ic-arm.cc (working copy) |
@@ -1700,11 +1700,78 @@ |
Token::Name(op_)); |
} |
#endif |
+ |
+ // Activate inlined smi code. |
+ if (previous_state == UNINITIALIZED) { |
+ PatchInlinedSmiCode(address()); |
+ } |
} |
void PatchInlinedSmiCode(Address address) { |
- // Currently there is no smi inlining in the ARM full code generator. |
+ Address cmp_instruction_address = |
+ address + Assembler::kCallTargetAddressOffset; |
+ |
+ // If the instruction following the call is not a cmp rx, #yyy, nothing |
+ // was inlined. |
+ Instr instr = Assembler::instr_at(cmp_instruction_address); |
+ if (!Assembler::IsCmpImmediate(instr)) { |
+ return; |
+ } |
+ |
+ // The delta to the start of the map check instruction and the |
+ // condition code uses at the patched jump. |
+ int delta = Assembler::GetCmpImmediateRawImmediate(instr); |
+ delta += |
+ Assembler::GetCmpImmediateRegister(instr).code() * kOff12Mask; |
+ // If the delta is 0 the instruction is cmp r0, #0 which also signals that |
+ // nothing was inlined. |
+ if (delta == 0) { |
+ return; |
+ } |
+ |
+#ifdef DEBUG |
+ if (FLAG_trace_ic) { |
+ PrintF("[ patching ic at %p, cmp=%p, delta=%d\n", |
+ address, cmp_instruction_address, delta); |
+ } |
+#endif |
+ |
+ Address patch_address = |
+ cmp_instruction_address - delta * Instruction::kInstrSize; |
+ Instr instr_at_patch = Assembler::instr_at(patch_address); |
+ Instr branch_instr = |
+ Assembler::instr_at(patch_address + Instruction::kInstrSize); |
+ ASSERT(Assembler::IsCmpRegister(instr_at_patch)); |
+ ASSERT_EQ(Assembler::GetRn(instr_at_patch).code(), |
+ Assembler::GetRm(instr_at_patch).code()); |
+ ASSERT(Assembler::IsBranch(branch_instr)); |
+ if (Assembler::GetCondition(branch_instr) == eq) { |
+ // This is patching a "jump if not smi" site to be active. |
+ // Changing |
+ // cmp rx, rx |
+ // b eq, <target> |
+ // to |
+ // tst rx, #kSmiTagMask |
+ // b ne, <target> |
+ CodePatcher patcher(patch_address, 2); |
+ Register reg = Assembler::GetRn(instr_at_patch); |
+ patcher.masm()->tst(reg, Operand(kSmiTagMask)); |
+ patcher.EmitCondition(ne); |
+ } else { |
+ ASSERT(Assembler::GetCondition(branch_instr) == ne); |
+ // This is patching a "jump if smi" site to be active. |
+ // Changing |
+ // cmp rx, rx |
+ // b ne, <target> |
+ // to |
+ // tst rx, #kSmiTagMask |
+ // b eq, <target> |
+ CodePatcher patcher(patch_address, 2); |
+ Register reg = Assembler::GetRn(instr_at_patch); |
+ patcher.masm()->tst(reg, Operand(kSmiTagMask)); |
+ patcher.EmitCondition(eq); |
+ } |
} |