| Index: runtime/vm/intermediate_language_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_ia32.cc (revision 13236)
|
| +++ runtime/vm/intermediate_language_ia32.cc (working copy)
|
| @@ -311,11 +311,12 @@
|
| locs->set_out(Location::RegisterLocation(EAX));
|
| return locs;
|
| }
|
| - const intptr_t kNumTemps = 0;
|
| + const intptr_t kNumTemps = 1;
|
| LocationSummary* locs =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
|
| - locs->set_in(0, Location::RegisterLocation(ECX));
|
| + locs->set_in(0, Location::RegisterLocation(EBX));
|
| locs->set_in(1, Location::RegisterLocation(EDX));
|
| + locs->set_temp(0, Location::RegisterLocation(ECX));
|
| locs->set_out(Location::RegisterLocation(EAX));
|
| return locs;
|
| }
|
| @@ -336,44 +337,38 @@
|
| const Array& kNoArgumentNames = Array::Handle();
|
| const int kNumArgumentsChecked = 2;
|
|
|
| - Label done, false_label, true_label;
|
| - Register left = locs->in(0).reg();
|
| - Register right = locs->in(1).reg();
|
| - __ popl(right);
|
| - __ popl(left);
|
| const Immediate raw_null =
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| - Label check_identity, instance_call;
|
| - __ cmpl(right, raw_null);
|
| + Label check_identity;
|
| + __ cmpl(Address(ESP, 0 * kWordSize), raw_null);
|
| __ j(EQUAL, &check_identity, Assembler::kNearJump);
|
| - __ cmpl(left, raw_null);
|
| - __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump);
|
| + __ cmpl(Address(ESP, 1 * kWordSize), raw_null);
|
| + __ j(EQUAL, &check_identity, Assembler::kNearJump);
|
|
|
| + const ICData& ic_data = compiler->GenerateInstanceCall(deopt_id,
|
| + token_pos,
|
| + operator_name,
|
| + kNumberOfArguments,
|
| + kNoArgumentNames,
|
| + kNumArgumentsChecked,
|
| + locs);
|
| + Label check_ne;
|
| + __ jmp(&check_ne);
|
| +
|
| __ Bind(&check_identity);
|
| - __ cmpl(left, right);
|
| - __ j(EQUAL, &true_label);
|
| - if (kind == Token::kEQ) {
|
| - __ LoadObject(EAX, compiler->bool_false());
|
| - __ jmp(&done);
|
| - __ Bind(&true_label);
|
| - __ LoadObject(EAX, compiler->bool_true());
|
| - __ jmp(&done);
|
| - } else {
|
| - ASSERT(kind == Token::kNE);
|
| - __ jmp(&false_label);
|
| - }
|
| -
|
| - __ Bind(&instance_call);
|
| - __ pushl(left);
|
| - __ pushl(right);
|
| - compiler->GenerateInstanceCall(deopt_id,
|
| - token_pos,
|
| - operator_name,
|
| - kNumberOfArguments,
|
| - kNoArgumentNames,
|
| - kNumArgumentsChecked,
|
| - locs);
|
| + // Call stub, load IC data in register. The stub will update ICData if
|
| + // necessary.
|
| + Register ic_data_reg = locs->temp(0).reg();
|
| + ASSERT(ic_data_reg == ECX); // Stub depends on it.
|
| + __ LoadObject(ic_data_reg, ic_data);
|
| + compiler->GenerateCall(token_pos,
|
| + &StubCode::EqualityWithNullArgLabel(),
|
| + PcDescriptors::kOther,
|
| + locs);
|
| + __ Drop(2);
|
| + __ Bind(&check_ne);
|
| if (kind == Token::kNE) {
|
| + Label false_label, true_label, done;
|
| // Negate the condition: true label returns false and vice versa.
|
| __ CompareObject(EAX, compiler->bool_true());
|
| __ j(EQUAL, &true_label, Assembler::kNearJump);
|
| @@ -382,8 +377,8 @@
|
| __ jmp(&done, Assembler::kNearJump);
|
| __ Bind(&true_label);
|
| __ LoadObject(EAX, compiler->bool_false());
|
| + __ Bind(&done);
|
| }
|
| - __ Bind(&done);
|
| }
|
|
|
|
|
| @@ -584,11 +579,21 @@
|
| Condition true_condition = TokenKindToSmiCondition(kind);
|
|
|
| if (left.IsConstant() && right.IsConstant()) {
|
| + bool result = false;
|
| + // One of them could be NULL (for equality only).
|
| + if (left.constant().IsNull() || right.constant().IsNull()) {
|
| + ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
|
| + result = left.constant().IsNull() && right.constant().IsNull();
|
| + if (kind == Token::kNE) {
|
| + result = !result;
|
| + }
|
| + } else {
|
| // TODO(vegorov): should be eliminated earlier by constant propagation.
|
| - const bool result = FlowGraphCompiler::EvaluateCondition(
|
| - true_condition,
|
| - Smi::Cast(left.constant()).Value(),
|
| - Smi::Cast(right.constant()).Value());
|
| + result = FlowGraphCompiler::EvaluateCondition(
|
| + true_condition,
|
| + Smi::Cast(left.constant()).Value(),
|
| + Smi::Cast(right.constant()).Value());
|
| + }
|
|
|
| if (branch != NULL) {
|
| branch->EmitBranchOnValue(compiler, result);
|
| @@ -2080,14 +2085,21 @@
|
| Register temp = locs()->temp(0).reg();
|
| Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
| kDeoptCheckClass);
|
| - ASSERT(unary_checks().GetReceiverClassIdAt(0) != kSmiCid);
|
| - __ testl(value, Immediate(kSmiTagMask));
|
| - __ j(ZERO, deopt);
|
| + Label is_ok;
|
| + intptr_t cix = 0;
|
| + if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
|
| + __ testl(value, Immediate(kSmiTagMask));
|
| + __ j(ZERO, &is_ok);
|
| + cix++; // Skip first check.
|
| + } else {
|
| + __ testl(value, Immediate(kSmiTagMask));
|
| + __ j(ZERO, deopt);
|
| + }
|
| __ LoadClassId(temp, value);
|
| - Label is_ok;
|
| const intptr_t num_checks = unary_checks().NumberOfChecks();
|
| const bool use_near_jump = num_checks < 5;
|
| - for (intptr_t i = 0; i < num_checks; i++) {
|
| + for (intptr_t i = cix; i < num_checks; i++) {
|
| + ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
|
| __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i)));
|
| if (i == (num_checks - 1)) {
|
| __ j(NOT_EQUAL, deopt);
|
|
|