Chromium Code Reviews| Index: runtime/vm/intermediate_language_x64.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_x64.cc (revision 8949) |
| +++ runtime/vm/intermediate_language_x64.cc (working copy) |
| @@ -382,7 +382,6 @@ |
| } |
| - |
| // First test if receiver is NULL, in which case === is applied. |
| // If type feedback was provided (lists of <class-id, target>), do a |
| // type by type check (either === or static call to the operator. |
| @@ -1503,36 +1502,96 @@ |
| } |
| +static RawFunction* GetTargetForReceiverClassId(const ICData& ic_data, |
| + intptr_t receiver_class_id) { |
|
srdjan
2012/06/21 16:02:37
I could imagine that this could also live inside c
regis
2012/06/21 18:26:42
Good point. Done.
|
| + Function& target = Function::Handle(); |
| + for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| + GrowableArray<intptr_t> class_ids; |
| + ic_data.GetCheckAt(i, &class_ids, &target); |
| + if (class_ids[0] == receiver_class_id) { |
| + return target.raw(); |
| + } |
| + } |
| + UNREACHABLE(); |
| + return Function::null(); |
| +} |
| + |
| + |
| static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| - // receiver and a Smi argument. |
| + // receiver and a Mint or Smi argument. We fall back to the run time call if |
| + // both receiver and argument are Mint or if one of them is Mint and the other |
| + // is a negative Smi. |
| Register left = comp->locs()->in(0).reg(); |
| Register right = comp->locs()->in(1).reg(); |
| Register result = comp->locs()->out().reg(); |
| Register temp = comp->locs()->temp(0).reg(); |
| ASSERT(left == result); |
| + ASSERT(comp->op_kind() == Token::kBIT_AND); |
| Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| comp->instance_call()->token_index(), |
| comp->instance_call()->try_index(), |
| kDeoptMintBinaryOp, |
| temp, |
| right); |
| - __ testq(right, Immediate(kSmiTagMask)); // Argument must be Smi. |
| - __ j(NOT_ZERO, deopt); |
| - __ testq(left, Immediate(kSmiTagMask)); // Receiver can be Smi. |
| - Label two_smi; |
| - __ j(ZERO, &two_smi); |
| - __ CompareClassId(left, kMint); // Receiver must be Mint. |
| - __ j(NOT_EQUAL, deopt); |
| + Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| + __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| + __ j(NOT_ZERO, &non_smi); |
| + __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| + __ j(ZERO, &smi_smi); |
| + __ CompareClassId(right, kMint); // Is argument Mint? |
| + __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| + __ cmpq(left, Immediate(0)); |
| + __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| - ASSERT(comp->op_kind() == Token::kBIT_AND); |
| + // Positive Smi receiver, Mint argument. |
| + // Load lower argument Mint word, convert to Smi. It is OK to loose bits. |
| + __ movq(right, FieldAddress(right, Mint::value_offset())); |
| + __ SmiTag(right); |
| + __ andq(result, right); |
| + __ jmp(&done); |
| - // Load lower Mint word, convert to Smi. It is OK to loose bits. |
| - ASSERT(result == left); |
| + __ Bind(&non_smi); // Receiver is non-Smi. |
| + __ CompareClassId(left, kMint); // Is receiver Mint? |
| + __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. |
| + __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| + __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. |
| + __ cmpq(right, Immediate(0)); |
| + __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. |
| + |
| + // Mint receiver, positive Smi argument. |
| + // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
| __ movq(result, FieldAddress(left, Mint::value_offset())); |
| __ SmiTag(result); |
| - __ Bind(&two_smi); |
| + __ Bind(&smi_smi); |
| __ andq(result, right); |
| + __ jmp(&done); |
| + |
| + __ Bind(&smi_static_call); |
| + { |
| + Function& target = Function::ZoneHandle( |
| + GetTargetForReceiverClassId(*comp->ic_data(), kSmi)); |
| + compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| + comp->instance_call()->token_index(), |
| + comp->instance_call()->try_index(), |
| + target, |
| + comp->instance_call()->ArgumentCount(), |
| + comp->instance_call()->argument_names()); |
| + } |
| + __ jmp(&done); |
| + |
| + __ Bind(&mint_static_call); |
| + { |
| + Function& target = Function::ZoneHandle( |
| + GetTargetForReceiverClassId(*comp->ic_data(), kMint)); |
| + compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| + comp->instance_call()->token_index(), |
| + comp->instance_call()->try_index(), |
| + target, |
| + comp->instance_call()->ArgumentCount(), |
| + comp->instance_call()->argument_names()); |
| + } |
| + __ Bind(&done); |
| } |