| Index: runtime/vm/intermediate_language_x64.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_x64.cc (revision 29797)
|
| +++ runtime/vm/intermediate_language_x64.cc (working copy)
|
| @@ -407,92 +407,11 @@
|
| locs->set_out(Location::RequiresRegister());
|
| return locs;
|
| }
|
| - if (IsCheckedStrictEqual()) {
|
| - const intptr_t kNumTemps = 1;
|
| - LocationSummary* locs =
|
| - new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - locs->set_in(0, Location::RequiresRegister());
|
| - locs->set_in(1, Location::RequiresRegister());
|
| - locs->set_temp(0, Location::RequiresRegister());
|
| - locs->set_out(Location::RequiresRegister());
|
| - return locs;
|
| - }
|
| - if (IsPolymorphic()) {
|
| - const intptr_t kNumTemps = 1;
|
| - LocationSummary* locs =
|
| - new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
|
| - locs->set_in(0, Location::RegisterLocation(RCX));
|
| - locs->set_in(1, Location::RegisterLocation(RDX));
|
| - locs->set_temp(0, Location::RegisterLocation(RBX));
|
| - locs->set_out(Location::RegisterLocation(RAX));
|
| - return locs;
|
| - }
|
| - const intptr_t kNumTemps = 1;
|
| - LocationSummary* locs =
|
| - new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
|
| - locs->set_in(0, Location::RegisterLocation(RCX));
|
| - locs->set_in(1, Location::RegisterLocation(RDX));
|
| - locs->set_temp(0, Location::RegisterLocation(RBX));
|
| - locs->set_out(Location::RegisterLocation(RAX));
|
| - return locs;
|
| + UNREACHABLE();
|
| + return NULL;
|
| }
|
|
|
|
|
| -static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
|
| - intptr_t deopt_id,
|
| - intptr_t token_pos,
|
| - Token::Kind kind,
|
| - LocationSummary* locs,
|
| - const ICData& original_ic_data) {
|
| - if (!compiler->is_optimizing()) {
|
| - compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
|
| - deopt_id,
|
| - token_pos);
|
| - }
|
| - const int kNumberOfArguments = 2;
|
| - const Array& kNoArgumentNames = Object::null_array();
|
| - const int kNumArgumentsChecked = 2;
|
| -
|
| - ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw());
|
| - if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
|
| - ASSERT(!original_ic_data.IsNull());
|
| - if (original_ic_data.NumberOfChecks() == 0) {
|
| - // IC call for reoptimization populates original ICData.
|
| - equality_ic_data = original_ic_data.raw();
|
| - } else {
|
| - // Megamorphic call.
|
| - equality_ic_data = original_ic_data.AsUnaryClassChecks();
|
| - }
|
| - } else {
|
| - const Array& arguments_descriptor =
|
| - Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments,
|
| - kNoArgumentNames));
|
| - equality_ic_data = ICData::New(compiler->parsed_function().function(),
|
| - Symbols::EqualOperator(),
|
| - arguments_descriptor,
|
| - deopt_id,
|
| - kNumArgumentsChecked);
|
| - }
|
| - compiler->GenerateInstanceCall(deopt_id,
|
| - token_pos,
|
| - kNumberOfArguments,
|
| - kNoArgumentNames,
|
| - locs,
|
| - equality_ic_data);
|
| - if (kind == Token::kNE) {
|
| - Label true_label, done;
|
| - // Negate the condition: true label returns false and vice versa.
|
| - __ CompareObject(RAX, Bool::True(), PP);
|
| - __ j(EQUAL, &true_label, Assembler::kNearJump);
|
| - __ LoadObject(RAX, Bool::True(), PP);
|
| - __ jmp(&done, Assembler::kNearJump);
|
| - __ Bind(&true_label);
|
| - __ LoadObject(RAX, Bool::False(), PP);
|
| - __ Bind(&done);
|
| - }
|
| -}
|
| -
|
| -
|
| static void LoadValueCid(FlowGraphCompiler* compiler,
|
| Register value_cid_reg,
|
| Register value_reg,
|
| @@ -512,164 +431,6 @@
|
| }
|
|
|
|
|
| -static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
|
| - const ICData& orig_ic_data,
|
| - LocationSummary* locs,
|
| - BranchInstr* branch,
|
| - Token::Kind kind,
|
| - intptr_t deopt_id,
|
| - intptr_t token_pos) {
|
| - ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
|
| - const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
|
| - ASSERT(ic_data.NumberOfChecks() > 0);
|
| - ASSERT(ic_data.num_args_tested() == 1);
|
| - Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
|
| - Register left = locs->in(0).reg();
|
| - Register right = locs->in(1).reg();
|
| - Register temp = locs->temp(0).reg();
|
| - LoadValueCid(compiler, temp, left,
|
| - (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
|
| - // 'temp' contains class-id of the left argument.
|
| - ObjectStore* object_store = Isolate::Current()->object_store();
|
| - Condition cond = TokenKindToSmiCondition(kind);
|
| - Label done;
|
| - const intptr_t len = ic_data.NumberOfChecks();
|
| - for (intptr_t i = 0; i < len; i++) {
|
| - // Assert that the Smi is at position 0, if at all.
|
| - ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0));
|
| - Label next_test;
|
| - __ CompareImmediate(temp, Immediate(ic_data.GetReceiverClassIdAt(i)), PP);
|
| - if (i < len - 1) {
|
| - __ j(NOT_EQUAL, &next_test);
|
| - } else {
|
| - __ j(NOT_EQUAL, deopt);
|
| - }
|
| - const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
|
| - if (target.Owner() == object_store->object_class()) {
|
| - // Object.== is same as ===.
|
| - __ Drop(2);
|
| - __ cmpq(left, right);
|
| - if (branch != NULL) {
|
| - branch->EmitBranchOnCondition(compiler, cond);
|
| - } else {
|
| - // This case should be rare.
|
| - Register result = locs->out().reg();
|
| - Label load_true;
|
| - __ j(cond, &load_true, Assembler::kNearJump);
|
| - __ LoadObject(result, Bool::False(), PP);
|
| - __ jmp(&done);
|
| - __ Bind(&load_true);
|
| - __ LoadObject(result, Bool::True(), PP);
|
| - }
|
| - } else {
|
| - const int kNumberOfArguments = 2;
|
| - const Array& kNoArgumentNames = Object::null_array();
|
| - compiler->GenerateStaticCall(deopt_id,
|
| - token_pos,
|
| - target,
|
| - kNumberOfArguments,
|
| - kNoArgumentNames,
|
| - locs);
|
| - if (branch == NULL) {
|
| - if (kind == Token::kNE) {
|
| - Label false_label;
|
| - __ CompareObject(RAX, Bool::True(), PP);
|
| - __ j(EQUAL, &false_label, Assembler::kNearJump);
|
| - __ LoadObject(RAX, Bool::True(), PP);
|
| - __ jmp(&done);
|
| - __ Bind(&false_label);
|
| - __ LoadObject(RAX, Bool::False(), PP);
|
| - }
|
| - } else {
|
| - if (branch->is_checked()) {
|
| - EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler);
|
| - }
|
| - __ CompareObject(RAX, Bool::True(), PP);
|
| - branch->EmitBranchOnCondition(compiler, cond);
|
| - }
|
| - }
|
| - if (i < len - 1) {
|
| - __ jmp(&done);
|
| - __ Bind(&next_test);
|
| - }
|
| - }
|
| - __ Bind(&done);
|
| -}
|
| -
|
| -
|
| -// Emit code when ICData's targets are all Object == (which is ===).
|
| -static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
|
| - const ICData& orig_ic_data,
|
| - const LocationSummary& locs,
|
| - Token::Kind kind,
|
| - BranchInstr* branch,
|
| - intptr_t deopt_id) {
|
| - ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
|
| - Register left = locs.in(0).reg();
|
| - Register right = locs.in(1).reg();
|
| - Register temp = locs.temp(0).reg();
|
| - Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
|
| - __ testq(left, Immediate(kSmiTagMask));
|
| - __ j(ZERO, deopt);
|
| - // 'left' is not Smi.
|
| -
|
| - Label identity_compare;
|
| - __ CompareObject(right, Object::null_object(), PP);
|
| - __ j(EQUAL, &identity_compare);
|
| - __ CompareObject(left, Object::null_object(), PP);
|
| - __ j(EQUAL, &identity_compare);
|
| -
|
| - __ LoadClassId(temp, left);
|
| - const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
|
| - const intptr_t len = ic_data.NumberOfChecks();
|
| - for (intptr_t i = 0; i < len; i++) {
|
| - __ CompareImmediate(temp, Immediate(ic_data.GetReceiverClassIdAt(i)), PP);
|
| - if (i == (len - 1)) {
|
| - __ j(NOT_EQUAL, deopt);
|
| - } else {
|
| - __ j(EQUAL, &identity_compare);
|
| - }
|
| - }
|
| - __ Bind(&identity_compare);
|
| - __ cmpq(left, right);
|
| - if (branch == NULL) {
|
| - Label done, is_equal;
|
| - Register result = locs.out().reg();
|
| - __ j(EQUAL, &is_equal, Assembler::kNearJump);
|
| - // Not equal.
|
| - __ LoadObject(result, Bool::Get(kind != Token::kEQ), PP);
|
| - __ jmp(&done, Assembler::kNearJump);
|
| - __ Bind(&is_equal);
|
| - __ LoadObject(result, Bool::Get(kind == Token::kEQ), PP);
|
| - __ Bind(&done);
|
| - } else {
|
| - Condition cond = TokenKindToSmiCondition(kind);
|
| - branch->EmitBranchOnCondition(compiler, cond);
|
| - }
|
| -}
|
| -
|
| -
|
| -// 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.
|
| -static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
|
| - LocationSummary* locs,
|
| - Token::Kind kind,
|
| - BranchInstr* branch,
|
| - const ICData& ic_data,
|
| - intptr_t deopt_id,
|
| - intptr_t token_pos) {
|
| - ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
|
| - ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
|
| - Register left = locs->in(0).reg();
|
| - Register right = locs->in(1).reg();
|
| - __ pushq(left);
|
| - __ pushq(right);
|
| - EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
|
| - deopt_id, token_pos);
|
| -}
|
| -
|
| -
|
| static Condition FlipCondition(Condition condition) {
|
| switch (condition) {
|
| case EQUAL: return EQUAL;
|
| @@ -771,27 +532,7 @@
|
| EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
|
| return;
|
| }
|
| - if (IsCheckedStrictEqual()) {
|
| - EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
|
| - deopt_id());
|
| - return;
|
| - }
|
| - if (IsPolymorphic()) {
|
| - EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(),
|
| - deopt_id(), token_pos());
|
| - return;
|
| - }
|
| - Register left = locs()->in(0).reg();
|
| - Register right = locs()->in(1).reg();
|
| - __ pushq(left);
|
| - __ pushq(right);
|
| - EmitEqualityAsInstanceCall(compiler,
|
| - deopt_id(),
|
| - token_pos(),
|
| - kind(),
|
| - locs(),
|
| - *ic_data());
|
| - ASSERT(locs()->out().reg() == RAX);
|
| + UNREACHABLE();
|
| }
|
|
|
|
|
| @@ -808,32 +549,7 @@
|
| EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
|
| return;
|
| }
|
| - if (IsCheckedStrictEqual()) {
|
| - EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
|
| - deopt_id());
|
| - return;
|
| - }
|
| - if (IsPolymorphic()) {
|
| - EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(),
|
| - deopt_id(), token_pos());
|
| - return;
|
| - }
|
| - Register left = locs()->in(0).reg();
|
| - Register right = locs()->in(1).reg();
|
| - __ pushq(left);
|
| - __ pushq(right);
|
| - EmitEqualityAsInstanceCall(compiler,
|
| - deopt_id(),
|
| - token_pos(),
|
| - Token::kEQ, // kNE reverse occurs at branch.
|
| - locs(),
|
| - *ic_data());
|
| - if (branch->is_checked()) {
|
| - EmitAssertBoolean(RAX, token_pos(), deopt_id(), locs(), compiler);
|
| - }
|
| - Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
|
| - __ CompareObject(RAX, Bool::True(), PP);
|
| - branch->EmitBranchOnCondition(compiler, branch_condition);
|
| + UNREACHABLE();
|
| }
|
|
|
|
|
|
|