| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_X64. | 
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) | 
| 7 | 7 | 
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" | 
| 9 | 9 | 
| 10 #include "lib/error.h" | 10 #include "lib/error.h" | 
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 100   __ nop(1); | 100   __ nop(1); | 
| 101   __ nop(1); | 101   __ nop(1); | 
| 102   __ nop(1); | 102   __ nop(1); | 
| 103   __ nop(1); | 103   __ nop(1); | 
| 104   __ nop(1); | 104   __ nop(1); | 
| 105   __ nop(1); | 105   __ nop(1); | 
| 106   __ nop(1); | 106   __ nop(1); | 
| 107   __ nop(1); | 107   __ nop(1); | 
| 108   compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 108   compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 
| 109                                  cid(), | 109                                  cid(), | 
| 110                                  token_index(), | 110                                  token_pos(), | 
| 111                                  CatchClauseNode::kInvalidTryIndex); | 111                                  CatchClauseNode::kInvalidTryIndex); | 
| 112 } | 112 } | 
| 113 | 113 | 
| 114 | 114 | 
| 115 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 115 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 
| 116   const intptr_t kNumInputs = 0; | 116   const intptr_t kNumInputs = 0; | 
| 117   const intptr_t kNumTemps = 1; | 117   const intptr_t kNumTemps = 1; | 
| 118   LocationSummary* result = new LocationSummary(kNumInputs, | 118   LocationSummary* result = new LocationSummary(kNumInputs, | 
| 119                                                 kNumTemps, | 119                                                 kNumTemps, | 
| 120                                                 LocationSummary::kCall); | 120                                                 LocationSummary::kCall); | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 179   Register result = locs()->out().reg(); | 179   Register result = locs()->out().reg(); | 
| 180 | 180 | 
| 181   // Check that the type of the value is allowed in conditional context. | 181   // Check that the type of the value is allowed in conditional context. | 
| 182   // Call the runtime if the object is not bool::true or bool::false. | 182   // Call the runtime if the object is not bool::true or bool::false. | 
| 183   Label done; | 183   Label done; | 
| 184   __ CompareObject(obj, compiler->bool_true()); | 184   __ CompareObject(obj, compiler->bool_true()); | 
| 185   __ j(EQUAL, &done, Assembler::kNearJump); | 185   __ j(EQUAL, &done, Assembler::kNearJump); | 
| 186   __ CompareObject(obj, compiler->bool_false()); | 186   __ CompareObject(obj, compiler->bool_false()); | 
| 187   __ j(EQUAL, &done, Assembler::kNearJump); | 187   __ j(EQUAL, &done, Assembler::kNearJump); | 
| 188 | 188 | 
| 189   __ pushq(Immediate(Smi::RawValue(token_index())));  // Source location. | 189   __ pushq(Immediate(Smi::RawValue(token_pos())));  // Source location. | 
| 190   __ pushq(obj);  // Push the source object. | 190   __ pushq(obj);  // Push the source object. | 
| 191   compiler->GenerateCallRuntime(cid(), | 191   compiler->GenerateCallRuntime(cid(), | 
| 192                                 token_index(), | 192                                 token_pos(), | 
| 193                                 try_index(), | 193                                 try_index(), | 
| 194                                 kConditionTypeErrorRuntimeEntry); | 194                                 kConditionTypeErrorRuntimeEntry); | 
| 195   // We should never return here. | 195   // We should never return here. | 
| 196   __ int3(); | 196   __ int3(); | 
| 197 | 197 | 
| 198   __ Bind(&done); | 198   __ Bind(&done); | 
| 199   ASSERT(obj == result); | 199   ASSERT(obj == result); | 
| 200 } | 200 } | 
| 201 | 201 | 
| 202 | 202 | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 249   return locs; | 249   return locs; | 
| 250 } | 250 } | 
| 251 | 251 | 
| 252 | 252 | 
| 253 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 253 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 
| 254                                    EqualityCompareComp* comp) { | 254                                    EqualityCompareComp* comp) { | 
| 255   Register left = comp->locs()->in(0).reg(); | 255   Register left = comp->locs()->in(0).reg(); | 
| 256   Register right = comp->locs()->in(1).reg(); | 256   Register right = comp->locs()->in(1).reg(); | 
| 257   Register temp = comp->locs()->temp(0).reg(); | 257   Register temp = comp->locs()->temp(0).reg(); | 
| 258   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 258   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 
| 259                                         comp->token_index(), | 259                                         comp->token_pos(), | 
| 260                                         comp->try_index(), | 260                                         comp->try_index(), | 
| 261                                         kDeoptSmiCompareSmis, | 261                                         kDeoptSmiCompareSmis, | 
| 262                                         left, | 262                                         left, | 
| 263                                         right); | 263                                         right); | 
| 264   // TODO(srdjan): Should we always include NULL test (common case)? | 264   // TODO(srdjan): Should we always include NULL test (common case)? | 
| 265   __ movq(temp, left); | 265   __ movq(temp, left); | 
| 266   __ orq(temp, right); | 266   __ orq(temp, right); | 
| 267   __ testq(temp, Immediate(kSmiTagMask)); | 267   __ testq(temp, Immediate(kSmiTagMask)); | 
| 268   __ j(NOT_ZERO, deopt); | 268   __ j(NOT_ZERO, deopt); | 
| 269   __ cmpq(left, right); | 269   __ cmpq(left, right); | 
| 270   if (comp->is_fused_with_branch()) { | 270   if (comp->is_fused_with_branch()) { | 
| 271     comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 271     comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 
| 272   } else { | 272   } else { | 
| 273     Register result = comp->locs()->out().reg(); | 273     Register result = comp->locs()->out().reg(); | 
| 274     Label load_true, done; | 274     Label load_true, done; | 
| 275     __ j(EQUAL, &load_true, Assembler::kNearJump); | 275     __ j(EQUAL, &load_true, Assembler::kNearJump); | 
| 276     __ LoadObject(result, compiler->bool_false()); | 276     __ LoadObject(result, compiler->bool_false()); | 
| 277     __ jmp(&done, Assembler::kNearJump); | 277     __ jmp(&done, Assembler::kNearJump); | 
| 278     __ Bind(&load_true); | 278     __ Bind(&load_true); | 
| 279     __ LoadObject(result, compiler->bool_true()); | 279     __ LoadObject(result, compiler->bool_true()); | 
| 280     __ Bind(&done); | 280     __ Bind(&done); | 
| 281   } | 281   } | 
| 282 } | 282 } | 
| 283 | 283 | 
| 284 | 284 | 
| 285 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 285 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 
| 286                                        EqualityCompareComp* comp) { | 286                                        EqualityCompareComp* comp) { | 
| 287   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 287   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 
| 288                                  comp->cid(), | 288                                  comp->cid(), | 
| 289                                  comp->token_index(), | 289                                  comp->token_pos(), | 
| 290                                  comp->try_index()); | 290                                  comp->try_index()); | 
| 291   const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 291   const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 
| 292   const int kNumberOfArguments = 2; | 292   const int kNumberOfArguments = 2; | 
| 293   const Array& kNoArgumentNames = Array::Handle(); | 293   const Array& kNoArgumentNames = Array::Handle(); | 
| 294   const int kNumArgumentsChecked = 2; | 294   const int kNumArgumentsChecked = 2; | 
| 295 | 295 | 
| 296   compiler->GenerateInstanceCall(comp->cid(), | 296   compiler->GenerateInstanceCall(comp->cid(), | 
| 297                                  comp->token_index(), | 297                                  comp->token_pos(), | 
| 298                                  comp->try_index(), | 298                                  comp->try_index(), | 
| 299                                  operator_name, | 299                                  operator_name, | 
| 300                                  kNumberOfArguments, | 300                                  kNumberOfArguments, | 
| 301                                  kNoArgumentNames, | 301                                  kNoArgumentNames, | 
| 302                                  kNumArgumentsChecked); | 302                                  kNumArgumentsChecked); | 
| 303   ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); | 303   ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); | 
| 304 | 304 | 
| 305   if (comp->is_fused_with_branch()) { | 305   if (comp->is_fused_with_branch()) { | 
| 306     __ CompareObject(RAX, compiler->bool_true()); | 306     __ CompareObject(RAX, compiler->bool_true()); | 
| 307     comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 307     comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 
| 308   } | 308   } | 
| 309 } | 309 } | 
| 310 | 310 | 
| 311 | 311 | 
| 312 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 312 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 
| 313                                           EqualityCompareComp* comp, | 313                                           EqualityCompareComp* comp, | 
| 314                                           Register left, | 314                                           Register left, | 
| 315                                           Register right) { | 315                                           Register right) { | 
| 316   ASSERT(comp->HasICData()); | 316   ASSERT(comp->HasICData()); | 
| 317   const ICData& ic_data = *comp->ic_data(); | 317   const ICData& ic_data = *comp->ic_data(); | 
| 318   ASSERT(ic_data.NumberOfChecks() > 0); | 318   ASSERT(ic_data.NumberOfChecks() > 0); | 
| 319   ASSERT(ic_data.num_args_tested() == 1); | 319   ASSERT(ic_data.num_args_tested() == 1); | 
| 320   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 320   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 
| 321                                         comp->token_index(), | 321                                         comp->token_pos(), | 
| 322                                         comp->try_index(), | 322                                         comp->try_index(), | 
| 323                                         kDeoptEquality); | 323                                         kDeoptEquality); | 
| 324   __ testq(left, Immediate(kSmiTagMask)); | 324   __ testq(left, Immediate(kSmiTagMask)); | 
| 325   Register temp = comp->locs()->temp(0).reg(); | 325   Register temp = comp->locs()->temp(0).reg(); | 
| 326   if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 326   if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 
| 327     Label done, load_class_id; | 327     Label done, load_class_id; | 
| 328     __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 328     __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 
| 329     __ movq(temp, Immediate(kSmi)); | 329     __ movq(temp, Immediate(kSmi)); | 
| 330     __ jmp(&done, Assembler::kNearJump); | 330     __ jmp(&done, Assembler::kNearJump); | 
| 331     __ Bind(&load_class_id); | 331     __ Bind(&load_class_id); | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 356         __ j(EQUAL, &load_true, Assembler::kNearJump); | 356         __ j(EQUAL, &load_true, Assembler::kNearJump); | 
| 357         __ LoadObject(result, compiler->bool_false()); | 357         __ LoadObject(result, compiler->bool_false()); | 
| 358         __ jmp(&done); | 358         __ jmp(&done); | 
| 359         __ Bind(&load_true); | 359         __ Bind(&load_true); | 
| 360         __ LoadObject(result, compiler->bool_true()); | 360         __ LoadObject(result, compiler->bool_true()); | 
| 361       } | 361       } | 
| 362     } else { | 362     } else { | 
| 363       const int kNumberOfArguments = 2; | 363       const int kNumberOfArguments = 2; | 
| 364       const Array& kNoArgumentNames = Array::Handle(); | 364       const Array& kNoArgumentNames = Array::Handle(); | 
| 365       compiler->GenerateStaticCall(comp->cid(), | 365       compiler->GenerateStaticCall(comp->cid(), | 
| 366                                    comp->token_index(), | 366                                    comp->token_pos(), | 
| 367                                    comp->try_index(), | 367                                    comp->try_index(), | 
| 368                                    target, | 368                                    target, | 
| 369                                    kNumberOfArguments, | 369                                    kNumberOfArguments, | 
| 370                                    kNoArgumentNames); | 370                                    kNoArgumentNames); | 
| 371       ASSERT(comp->is_fused_with_branch() || | 371       ASSERT(comp->is_fused_with_branch() || | 
| 372             (comp->locs()->out().reg() == RAX)); | 372             (comp->locs()->out().reg() == RAX)); | 
| 373       if (comp->is_fused_with_branch()) { | 373       if (comp->is_fused_with_branch()) { | 
| 374         __ CompareObject(RAX, compiler->bool_true()); | 374         __ CompareObject(RAX, compiler->bool_true()); | 
| 375         comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 375         comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 
| 376       } | 376       } | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 474   } | 474   } | 
| 475 } | 475 } | 
| 476 | 476 | 
| 477 | 477 | 
| 478 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, | 478 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, | 
| 479                                 RelationalOpComp* comp) { | 479                                 RelationalOpComp* comp) { | 
| 480   Register left = comp->locs()->in(0).reg(); | 480   Register left = comp->locs()->in(0).reg(); | 
| 481   Register right = comp->locs()->in(1).reg(); | 481   Register right = comp->locs()->in(1).reg(); | 
| 482   Register temp =  comp->locs()->temp(0).reg(); | 482   Register temp =  comp->locs()->temp(0).reg(); | 
| 483   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 483   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 
| 484                                         comp->token_index(), | 484                                         comp->token_pos(), | 
| 485                                         comp->try_index(), | 485                                         comp->try_index(), | 
| 486                                         kDeoptSmiCompareSmis, | 486                                         kDeoptSmiCompareSmis, | 
| 487                                         left, | 487                                         left, | 
| 488                                         right); | 488                                         right); | 
| 489   __ movq(temp, left); | 489   __ movq(temp, left); | 
| 490   __ orq(temp, right); | 490   __ orq(temp, right); | 
| 491   __ testq(temp, Immediate(kSmiTagMask)); | 491   __ testq(temp, Immediate(kSmiTagMask)); | 
| 492   __ j(NOT_ZERO, deopt); | 492   __ j(NOT_ZERO, deopt); | 
| 493 | 493 | 
| 494   Condition true_condition = TokenKindToSmiCondition(comp->kind()); | 494   Condition true_condition = TokenKindToSmiCondition(comp->kind()); | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
| 523 } | 523 } | 
| 524 | 524 | 
| 525 | 525 | 
| 526 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, | 526 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, | 
| 527                                    RelationalOpComp* comp) { | 527                                    RelationalOpComp* comp) { | 
| 528   Register left = comp->locs()->in(0).reg(); | 528   Register left = comp->locs()->in(0).reg(); | 
| 529   Register right = comp->locs()->in(1).reg(); | 529   Register right = comp->locs()->in(1).reg(); | 
| 530   // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 530   // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 
| 531   Register temp = comp->locs()->temp(0).reg(); | 531   Register temp = comp->locs()->temp(0).reg(); | 
| 532   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 532   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 
| 533                                         comp->token_index(), | 533                                         comp->token_pos(), | 
| 534                                         comp->try_index(), | 534                                         comp->try_index(), | 
| 535                                         kDeoptDoubleComparison, | 535                                         kDeoptDoubleComparison, | 
| 536                                         left, | 536                                         left, | 
| 537                                         right); | 537                                         right); | 
| 538   compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 538   compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 
| 539   compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 539   compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 
| 540 | 540 | 
| 541   Condition true_condition = TokenKindToDoubleCondition(comp->kind()); | 541   Condition true_condition = TokenKindToDoubleCondition(comp->kind()); | 
| 542   __ comisd(XMM0, XMM1); | 542   __ comisd(XMM0, XMM1); | 
| 543 | 543 | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 568     return; | 568     return; | 
| 569   } | 569   } | 
| 570   if (operands_class_id() == kDouble) { | 570   if (operands_class_id() == kDouble) { | 
| 571     EmitDoubleRelationalOp(compiler, this); | 571     EmitDoubleRelationalOp(compiler, this); | 
| 572     return; | 572     return; | 
| 573   } | 573   } | 
| 574   const String& function_name = | 574   const String& function_name = | 
| 575       String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 575       String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 
| 576   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 576   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 
| 577                                  cid(), | 577                                  cid(), | 
| 578                                  token_index(), | 578                                  token_pos(), | 
| 579                                  try_index()); | 579                                  try_index()); | 
| 580   const intptr_t kNumArguments = 2; | 580   const intptr_t kNumArguments = 2; | 
| 581   const intptr_t kNumArgsChecked = 2;  // Type-feedback. | 581   const intptr_t kNumArgsChecked = 2;  // Type-feedback. | 
| 582   compiler->GenerateInstanceCall(cid(), | 582   compiler->GenerateInstanceCall(cid(), | 
| 583                                  token_index(), | 583                                  token_pos(), | 
| 584                                  try_index(), | 584                                  try_index(), | 
| 585                                  function_name, | 585                                  function_name, | 
| 586                                  kNumArguments, | 586                                  kNumArguments, | 
| 587                                  Array::ZoneHandle(),  // No optional arguments. | 587                                  Array::ZoneHandle(),  // No optional arguments. | 
| 588                                  kNumArgsChecked); | 588                                  kNumArgsChecked); | 
| 589   ASSERT(locs()->out().reg() == RAX); | 589   ASSERT(locs()->out().reg() == RAX); | 
| 590 } | 590 } | 
| 591 | 591 | 
| 592 | 592 | 
| 593 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 593 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 618     arg_count += 1; | 618     arg_count += 1; | 
| 619   } | 619   } | 
| 620   if (!has_optional_parameters() && !is_native_instance_closure()) { | 620   if (!has_optional_parameters() && !is_native_instance_closure()) { | 
| 621     __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); | 621     __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); | 
| 622   } else { | 622   } else { | 
| 623     __ leaq(RAX, | 623     __ leaq(RAX, | 
| 624             Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 624             Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 
| 625   } | 625   } | 
| 626   __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 626   __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 
| 627   __ movq(R10, Immediate(arg_count)); | 627   __ movq(R10, Immediate(arg_count)); | 
| 628   compiler->GenerateCall(token_index(), | 628   compiler->GenerateCall(token_pos(), | 
| 629                          try_index(), | 629                          try_index(), | 
| 630                          &StubCode::CallNativeCFunctionLabel(), | 630                          &StubCode::CallNativeCFunctionLabel(), | 
| 631                          PcDescriptors::kOther); | 631                          PcDescriptors::kOther); | 
| 632   __ popq(result); | 632   __ popq(result); | 
| 633 } | 633 } | 
| 634 | 634 | 
| 635 | 635 | 
| 636 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 636 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 
| 637   const intptr_t kNumInputs = 2; | 637   const intptr_t kNumInputs = 2; | 
| 638   if (receiver_type() == kGrowableObjectArray) { | 638   if (receiver_type() == kGrowableObjectArray) { | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 649   } else { | 649   } else { | 
| 650     ASSERT(receiver_type() == kIllegalObjectKind); | 650     ASSERT(receiver_type() == kIllegalObjectKind); | 
| 651     return MakeCallSummary(); | 651     return MakeCallSummary(); | 
| 652   } | 652   } | 
| 653 } | 653 } | 
| 654 | 654 | 
| 655 | 655 | 
| 656 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 656 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 
| 657                                         LoadIndexedComp* comp) { | 657                                         LoadIndexedComp* comp) { | 
| 658   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 658   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 
| 659                                         comp->token_index(), | 659                                         comp->token_pos(), | 
| 660                                         comp->try_index(), | 660                                         comp->try_index(), | 
| 661                                         kDeoptLoadIndexedPolymorphic); | 661                                         kDeoptLoadIndexedPolymorphic); | 
| 662   if (comp->ic_data()->NumberOfChecks() == 0) { | 662   if (comp->ic_data()->NumberOfChecks() == 0) { | 
| 663     __ jmp(deopt); | 663     __ jmp(deopt); | 
| 664     return; | 664     return; | 
| 665   } | 665   } | 
| 666   ASSERT(comp->HasICData()); | 666   ASSERT(comp->HasICData()); | 
| 667   const ICData& ic_data = *comp->ic_data(); | 667   const ICData& ic_data = *comp->ic_data(); | 
| 668   ASSERT(ic_data.num_args_tested() == 1); | 668   ASSERT(ic_data.num_args_tested() == 1); | 
| 669   // No indexed access on Smi. | 669   // No indexed access on Smi. | 
| 670   ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 670   ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 
| 671   // Load receiver into RAX. | 671   // Load receiver into RAX. | 
| 672   const intptr_t kNumArguments = 2; | 672   const intptr_t kNumArguments = 2; | 
| 673   __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 673   __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 
| 674   __ testq(RAX, Immediate(kSmiTagMask)); | 674   __ testq(RAX, Immediate(kSmiTagMask)); | 
| 675   __ j(ZERO, deopt); | 675   __ j(ZERO, deopt); | 
| 676   Label done; | 676   Label done; | 
| 677   __ LoadClassId(RDI, RAX); | 677   __ LoadClassId(RDI, RAX); | 
| 678   compiler->EmitTestAndCall(ic_data, | 678   compiler->EmitTestAndCall(ic_data, | 
| 679                             RDI,  // Class id register. | 679                             RDI,  // Class id register. | 
| 680                             kNumArguments, | 680                             kNumArguments, | 
| 681                             Array::Handle(),  // No named arguments. | 681                             Array::Handle(),  // No named arguments. | 
| 682                             deopt, &done,  // Labels. | 682                             deopt, &done,  // Labels. | 
| 683                             comp->cid(), | 683                             comp->cid(), | 
| 684                             comp->token_index(), | 684                             comp->token_pos(), | 
| 685                             comp->try_index()); | 685                             comp->try_index()); | 
| 686   __ Bind(&done); | 686   __ Bind(&done); | 
| 687 } | 687 } | 
| 688 | 688 | 
| 689 | 689 | 
| 690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 691   if (receiver_type() == kIllegalObjectKind) { | 691   if (receiver_type() == kIllegalObjectKind) { | 
| 692     if (HasICData()) { | 692     if (HasICData()) { | 
| 693       EmitLoadIndexedPolymorphic(compiler, this); | 693       EmitLoadIndexedPolymorphic(compiler, this); | 
| 694     } else { | 694     } else { | 
| 695       compiler->EmitLoadIndexedGeneric(this); | 695       compiler->EmitLoadIndexedGeneric(this); | 
| 696     } | 696     } | 
| 697     ASSERT(locs()->out().reg() == RAX); | 697     ASSERT(locs()->out().reg() == RAX); | 
| 698     return; | 698     return; | 
| 699   } | 699   } | 
| 700 | 700 | 
| 701   Register receiver = locs()->in(0).reg(); | 701   Register receiver = locs()->in(0).reg(); | 
| 702   Register index = locs()->in(1).reg(); | 702   Register index = locs()->in(1).reg(); | 
| 703   Register result = locs()->out().reg(); | 703   Register result = locs()->out().reg(); | 
| 704 | 704 | 
| 705   const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 705   const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 
| 706       kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 706       kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 
| 707 | 707 | 
| 708   Label* deopt = compiler->AddDeoptStub(cid(), | 708   Label* deopt = compiler->AddDeoptStub(cid(), | 
| 709                                         token_index(), | 709                                         token_pos(), | 
| 710                                         try_index(), | 710                                         try_index(), | 
| 711                                         deopt_reason, | 711                                         deopt_reason, | 
| 712                                         receiver, | 712                                         receiver, | 
| 713                                         index); | 713                                         index); | 
| 714 | 714 | 
| 715   __ testq(receiver, Immediate(kSmiTagMask));  // Deoptimize if Smi. | 715   __ testq(receiver, Immediate(kSmiTagMask));  // Deoptimize if Smi. | 
| 716   __ j(ZERO, deopt); | 716   __ j(ZERO, deopt); | 
| 717   __ CompareClassId(receiver, receiver_type()); | 717   __ CompareClassId(receiver, receiver_type()); | 
| 718   __ j(NOT_EQUAL, deopt); | 718   __ j(NOT_EQUAL, deopt); | 
| 719 | 719 | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 770 } | 770 } | 
| 771 | 771 | 
| 772 | 772 | 
| 773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 
| 774                                     StoreIndexedComp* comp) { | 774                                     StoreIndexedComp* comp) { | 
| 775   const String& function_name = | 775   const String& function_name = | 
| 776       String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 776       String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 
| 777 | 777 | 
| 778   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 778   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 
| 779                                  comp->cid(), | 779                                  comp->cid(), | 
| 780                                  comp->token_index(), | 780                                  comp->token_pos(), | 
| 781                                  comp->try_index()); | 781                                  comp->try_index()); | 
| 782 | 782 | 
| 783   const intptr_t kNumArguments = 3; | 783   const intptr_t kNumArguments = 3; | 
| 784   const intptr_t kNumArgsChecked = 1;  // Type-feedback. | 784   const intptr_t kNumArgsChecked = 1;  // Type-feedback. | 
| 785   compiler->GenerateInstanceCall(comp->cid(), | 785   compiler->GenerateInstanceCall(comp->cid(), | 
| 786                                  comp->token_index(), | 786                                  comp->token_pos(), | 
| 787                                  comp->try_index(), | 787                                  comp->try_index(), | 
| 788                                  function_name, | 788                                  function_name, | 
| 789                                  kNumArguments, | 789                                  kNumArguments, | 
| 790                                  Array::ZoneHandle(),  // No named arguments. | 790                                  Array::ZoneHandle(),  // No named arguments. | 
| 791                                  kNumArgsChecked); | 791                                  kNumArgsChecked); | 
| 792 } | 792 } | 
| 793 | 793 | 
| 794 | 794 | 
| 795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 
| 796                                         StoreIndexedComp* comp) { | 796                                         StoreIndexedComp* comp) { | 
| 797   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 797   Label* deopt = compiler->AddDeoptStub(comp->cid(), | 
| 798                                         comp->token_index(), | 798                                         comp->token_pos(), | 
| 799                                         comp->try_index(), | 799                                         comp->try_index(), | 
| 800                                         kDeoptStoreIndexedPolymorphic); | 800                                         kDeoptStoreIndexedPolymorphic); | 
| 801   if (comp->ic_data()->NumberOfChecks() == 0) { | 801   if (comp->ic_data()->NumberOfChecks() == 0) { | 
| 802     __ jmp(deopt); | 802     __ jmp(deopt); | 
| 803     return; | 803     return; | 
| 804   } | 804   } | 
| 805   ASSERT(comp->HasICData()); | 805   ASSERT(comp->HasICData()); | 
| 806   const ICData& ic_data = *comp->ic_data(); | 806   const ICData& ic_data = *comp->ic_data(); | 
| 807   ASSERT(ic_data.num_args_tested() == 1); | 807   ASSERT(ic_data.num_args_tested() == 1); | 
| 808   // No indexed access on Smi. | 808   // No indexed access on Smi. | 
| 809   ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 809   ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 
| 810   // Load receiver into RAX. | 810   // Load receiver into RAX. | 
| 811   const intptr_t kNumArguments = 3; | 811   const intptr_t kNumArguments = 3; | 
| 812   __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 812   __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 
| 813   __ testq(RAX, Immediate(kSmiTagMask)); | 813   __ testq(RAX, Immediate(kSmiTagMask)); | 
| 814   __ j(ZERO, deopt); | 814   __ j(ZERO, deopt); | 
| 815   Label done; | 815   Label done; | 
| 816   __ LoadClassId(RDI, RAX); | 816   __ LoadClassId(RDI, RAX); | 
| 817   compiler->EmitTestAndCall(ic_data, | 817   compiler->EmitTestAndCall(ic_data, | 
| 818                             RDI,  // Class id register. | 818                             RDI,  // Class id register. | 
| 819                             kNumArguments, | 819                             kNumArguments, | 
| 820                             Array::Handle(),  // No named arguments. | 820                             Array::Handle(),  // No named arguments. | 
| 821                             deopt, &done,  // Labels. | 821                             deopt, &done,  // Labels. | 
| 822                             comp->cid(), | 822                             comp->cid(), | 
| 823                             comp->token_index(), | 823                             comp->token_pos(), | 
| 824                             comp->try_index()); | 824                             comp->try_index()); | 
| 825   __ Bind(&done); | 825   __ Bind(&done); | 
| 826 } | 826 } | 
| 827 | 827 | 
| 828 | 828 | 
| 829 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 829 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 830   if (receiver_type() == kIllegalObjectKind) { | 830   if (receiver_type() == kIllegalObjectKind) { | 
| 831     if (HasICData()) { | 831     if (HasICData()) { | 
| 832       EmitStoreIndexedPolymorphic(compiler, this); | 832       EmitStoreIndexedPolymorphic(compiler, this); | 
| 833     } else { | 833     } else { | 
| 834       EmitStoreIndexedGeneric(compiler, this); | 834       EmitStoreIndexedGeneric(compiler, this); | 
| 835     } | 835     } | 
| 836     return; | 836     return; | 
| 837   } | 837   } | 
| 838 | 838 | 
| 839   Register receiver = locs()->in(0).reg(); | 839   Register receiver = locs()->in(0).reg(); | 
| 840   Register index = locs()->in(1).reg(); | 840   Register index = locs()->in(1).reg(); | 
| 841   Register value = locs()->in(2).reg(); | 841   Register value = locs()->in(2).reg(); | 
| 842 | 842 | 
| 843   Label* deopt = compiler->AddDeoptStub(cid(), | 843   Label* deopt = compiler->AddDeoptStub(cid(), | 
| 844                                         token_index(), | 844                                         token_pos(), | 
| 845                                         try_index(), | 845                                         try_index(), | 
| 846                                         kDeoptStoreIndexed, | 846                                         kDeoptStoreIndexed, | 
| 847                                         receiver, | 847                                         receiver, | 
| 848                                         index, | 848                                         index, | 
| 849                                         value); | 849                                         value); | 
| 850 | 850 | 
| 851   __ testq(receiver, Immediate(kSmiTagMask));  // Deoptimize if Smi. | 851   __ testq(receiver, Immediate(kSmiTagMask));  // Deoptimize if Smi. | 
| 852   __ j(ZERO, deopt); | 852   __ j(ZERO, deopt); | 
| 853   __ CompareClassId(receiver, receiver_type()); | 853   __ CompareClassId(receiver, receiver_type()); | 
| 854   __ j(NOT_EQUAL, deopt); | 854   __ j(NOT_EQUAL, deopt); | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 893   return MakeCallSummary(); | 893   return MakeCallSummary(); | 
| 894 } | 894 } | 
| 895 | 895 | 
| 896 | 896 | 
| 897 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 897 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 898   const String& function_name = | 898   const String& function_name = | 
| 899       String::ZoneHandle(Field::SetterSymbol(field_name())); | 899       String::ZoneHandle(Field::SetterSymbol(field_name())); | 
| 900 | 900 | 
| 901   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 901   compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 
| 902                                  cid(), | 902                                  cid(), | 
| 903                                  token_index(), | 903                                  token_pos(), | 
| 904                                  try_index()); | 904                                  try_index()); | 
| 905   const intptr_t kArgumentCount = 2; | 905   const intptr_t kArgumentCount = 2; | 
| 906   const intptr_t kCheckedArgumentCount = 1; | 906   const intptr_t kCheckedArgumentCount = 1; | 
| 907   compiler->GenerateInstanceCall(cid(), | 907   compiler->GenerateInstanceCall(cid(), | 
| 908                                  token_index(), | 908                                  token_pos(), | 
| 909                                  try_index(), | 909                                  try_index(), | 
| 910                                  function_name, | 910                                  function_name, | 
| 911                                  kArgumentCount, | 911                                  kArgumentCount, | 
| 912                                  Array::ZoneHandle(), | 912                                  Array::ZoneHandle(), | 
| 913                                  kCheckedArgumentCount); | 913                                  kCheckedArgumentCount); | 
| 914 } | 914 } | 
| 915 | 915 | 
| 916 | 916 | 
| 917 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 917 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 
| 918   const intptr_t kNumInputs = 1; | 918   const intptr_t kNumInputs = 1; | 
| 919   return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 919   return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 
| 920 } | 920 } | 
| 921 | 921 | 
| 922 | 922 | 
| 923 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 923 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 924   Register value = locs()->in(0).reg(); | 924   Register value = locs()->in(0).reg(); | 
| 925   Register result = locs()->out().reg(); | 925   Register result = locs()->out().reg(); | 
| 926 | 926 | 
| 927   // Preserve the argument as the result of the computation, | 927   // Preserve the argument as the result of the computation, | 
| 928   // then call the setter. | 928   // then call the setter. | 
| 929 | 929 | 
| 930   // Duplicate the argument. | 930   // Duplicate the argument. | 
| 931   // TODO(fschneider): Avoid preserving the value if the result is not used. | 931   // TODO(fschneider): Avoid preserving the value if the result is not used. | 
| 932   __ pushq(value); | 932   __ pushq(value); | 
| 933   __ pushq(value); | 933   __ pushq(value); | 
| 934   compiler->GenerateStaticCall(cid(), | 934   compiler->GenerateStaticCall(cid(), | 
| 935                                token_index(), | 935                                token_pos(), | 
| 936                                try_index(), | 936                                try_index(), | 
| 937                                setter_function(), | 937                                setter_function(), | 
| 938                                1, | 938                                1, | 
| 939                                Array::ZoneHandle()); | 939                                Array::ZoneHandle()); | 
| 940   __ popq(result); | 940   __ popq(result); | 
| 941 } | 941 } | 
| 942 | 942 | 
| 943 | 943 | 
| 944 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 944 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 
| 945   // TODO(fschneider): For this instruction the input register may be | 945   // TODO(fschneider): For this instruction the input register may be | 
| 946   // reused for the result (but is not required to) because the input | 946   // reused for the result (but is not required to) because the input | 
| 947   // is not used after the result is defined.  We should consider adding | 947   // is not used after the result is defined.  We should consider adding | 
| 948   // this information to the input policy. | 948   // this information to the input policy. | 
| 949   return LocationSummary::Make(1, Location::RequiresRegister()); | 949   return LocationSummary::Make(1, Location::RequiresRegister()); | 
| 950 } | 950 } | 
| 951 | 951 | 
| 952 | 952 | 
| 953 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 953 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 954   Register instance_reg = locs()->in(0).reg(); | 954   Register instance_reg = locs()->in(0).reg(); | 
| 955   Register result_reg = locs()->out().reg(); | 955   Register result_reg = locs()->out().reg(); | 
| 956 | 956 | 
| 957   if (HasICData()) { | 957   if (HasICData()) { | 
| 958     ASSERT(original() != NULL); | 958     ASSERT(original() != NULL); | 
| 959     Label* deopt = compiler->AddDeoptStub(original()->cid(), | 959     Label* deopt = compiler->AddDeoptStub(original()->cid(), | 
| 960                                           original()->token_index(), | 960                                           original()->token_pos(), | 
| 961                                           original()->try_index(), | 961                                           original()->try_index(), | 
| 962                                           kDeoptInstanceGetterSameTarget, | 962                                           kDeoptInstanceGetterSameTarget, | 
| 963                                           instance_reg); | 963                                           instance_reg); | 
| 964     // Smis do not have instance fields (Smi class is always first). | 964     // Smis do not have instance fields (Smi class is always first). | 
| 965     // Use 'result' as temporary register. | 965     // Use 'result' as temporary register. | 
| 966     ASSERT(result_reg != instance_reg); | 966     ASSERT(result_reg != instance_reg); | 
| 967     ASSERT(ic_data() != NULL); | 967     ASSERT(ic_data() != NULL); | 
| 968     compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 968     compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 
| 969   } | 969   } | 
| 970   __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); | 970   __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 992   return summary; | 992   return summary; | 
| 993 } | 993 } | 
| 994 | 994 | 
| 995 | 995 | 
| 996 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 996 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 997   ASSERT(locs()->in(0).reg() == RAX);  // Value. | 997   ASSERT(locs()->in(0).reg() == RAX);  // Value. | 
| 998   ASSERT(locs()->in(1).reg() == RCX);  // Instantiator. | 998   ASSERT(locs()->in(1).reg() == RCX);  // Instantiator. | 
| 999   ASSERT(locs()->in(2).reg() == RDX);  // Instantiator type arguments. | 999   ASSERT(locs()->in(2).reg() == RDX);  // Instantiator type arguments. | 
| 1000 | 1000 | 
| 1001   compiler->GenerateInstanceOf(cid(), | 1001   compiler->GenerateInstanceOf(cid(), | 
| 1002                                token_index(), | 1002                                token_pos(), | 
| 1003                                try_index(), | 1003                                try_index(), | 
| 1004                                type(), | 1004                                type(), | 
| 1005                                negate_result()); | 1005                                negate_result()); | 
| 1006   ASSERT(locs()->out().reg() == RAX); | 1006   ASSERT(locs()->out().reg() == RAX); | 
| 1007 } | 1007 } | 
| 1008 | 1008 | 
| 1009 | 1009 | 
| 1010 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1010 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 
| 1011   // TODO(regis): The elements of the array could be considered as arguments to | 1011   // TODO(regis): The elements of the array could be considered as arguments to | 
| 1012   // CreateArrayComp, thereby making CreateArrayComp a call. | 1012   // CreateArrayComp, thereby making CreateArrayComp a call. | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 1025 | 1025 | 
| 1026 | 1026 | 
| 1027 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1027 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 1028   Register temp_reg = locs()->temp(0).reg(); | 1028   Register temp_reg = locs()->temp(0).reg(); | 
| 1029   Register result_reg = locs()->out().reg(); | 1029   Register result_reg = locs()->out().reg(); | 
| 1030 | 1030 | 
| 1031   // Allocate the array.  R10 = length, RBX = element type. | 1031   // Allocate the array.  R10 = length, RBX = element type. | 
| 1032   ASSERT(temp_reg == R10); | 1032   ASSERT(temp_reg == R10); | 
| 1033   ASSERT(locs()->in(0).reg() == RBX); | 1033   ASSERT(locs()->in(0).reg() == RBX); | 
| 1034   __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); | 1034   __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); | 
| 1035   compiler->GenerateCall(token_index(), | 1035   compiler->GenerateCall(token_pos(), | 
| 1036                          try_index(), | 1036                          try_index(), | 
| 1037                          &StubCode::AllocateArrayLabel(), | 1037                          &StubCode::AllocateArrayLabel(), | 
| 1038                          PcDescriptors::kOther); | 1038                          PcDescriptors::kOther); | 
| 1039   ASSERT(result_reg == RAX); | 1039   ASSERT(result_reg == RAX); | 
| 1040 | 1040 | 
| 1041   // Pop the element values from the stack into the array. | 1041   // Pop the element values from the stack into the array. | 
| 1042   __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 1042   __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 
| 1043   for (int i = ElementCount() - 1; i >= 0; --i) { | 1043   for (int i = ElementCount() - 1; i >= 0; --i) { | 
| 1044     ASSERT(ElementAt(i)->IsUse()); | 1044     ASSERT(ElementAt(i)->IsUse()); | 
| 1045     __ popq(Address(temp_reg, i * kWordSize)); | 1045     __ popq(Address(temp_reg, i * kWordSize)); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 1057 | 1057 | 
| 1058 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 1058 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 
| 1059     FlowGraphCompiler* compiler) { | 1059     FlowGraphCompiler* compiler) { | 
| 1060   const Class& cls = Class::ZoneHandle(constructor().owner()); | 1060   const Class& cls = Class::ZoneHandle(constructor().owner()); | 
| 1061   Register type_arguments = locs()->in(0).reg(); | 1061   Register type_arguments = locs()->in(0).reg(); | 
| 1062   Register instantiator_type_arguments = locs()->in(1).reg(); | 1062   Register instantiator_type_arguments = locs()->in(1).reg(); | 
| 1063   Register result = locs()->out().reg(); | 1063   Register result = locs()->out().reg(); | 
| 1064 | 1064 | 
| 1065   // Push the result place holder initialized to NULL. | 1065   // Push the result place holder initialized to NULL. | 
| 1066   __ PushObject(Object::ZoneHandle()); | 1066   __ PushObject(Object::ZoneHandle()); | 
| 1067   __ pushq(Immediate(Smi::RawValue(token_index()))); | 1067   __ pushq(Immediate(Smi::RawValue(token_pos()))); | 
| 1068   __ PushObject(cls); | 1068   __ PushObject(cls); | 
| 1069   __ pushq(type_arguments); | 1069   __ pushq(type_arguments); | 
| 1070   __ pushq(instantiator_type_arguments); | 1070   __ pushq(instantiator_type_arguments); | 
| 1071   compiler->GenerateCallRuntime(cid(), | 1071   compiler->GenerateCallRuntime(cid(), | 
| 1072                                 token_index(), | 1072                                 token_pos(), | 
| 1073                                 try_index(), | 1073                                 try_index(), | 
| 1074                                 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1074                                 kAllocateObjectWithBoundsCheckRuntimeEntry); | 
| 1075   // Pop instantiator type arguments, type arguments, class, and | 1075   // Pop instantiator type arguments, type arguments, class, and | 
| 1076   // source location. | 1076   // source location. | 
| 1077   __ Drop(4); | 1077   __ Drop(4); | 
| 1078   __ popq(result);  // Pop new instance. | 1078   __ popq(result);  // Pop new instance. | 
| 1079 } | 1079 } | 
| 1080 | 1080 | 
| 1081 | 1081 | 
| 1082 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1082 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 
| 1083   return LocationSummary::Make(1, Location::RequiresRegister()); | 1083   return LocationSummary::Make(1, Location::RequiresRegister()); | 
| 1084 } | 1084 } | 
| 1085 | 1085 | 
| 1086 | 1086 | 
| 1087 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1087 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 1088   Register instance_reg = locs()->in(0).reg(); | 1088   Register instance_reg = locs()->in(0).reg(); | 
| 1089   Register result_reg = locs()->out().reg(); | 1089   Register result_reg = locs()->out().reg(); | 
| 1090   if (HasICData()) { | 1090   if (HasICData()) { | 
| 1091     ASSERT(original() != NULL); | 1091     ASSERT(original() != NULL); | 
| 1092     Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1092     Label* deopt = compiler->AddDeoptStub(original()->cid(), | 
| 1093                                           original()->token_index(), | 1093                                           original()->token_pos(), | 
| 1094                                           original()->try_index(), | 1094                                           original()->try_index(), | 
| 1095                                           kDeoptInstanceGetterSameTarget, | 1095                                           kDeoptInstanceGetterSameTarget, | 
| 1096                                           instance_reg); | 1096                                           instance_reg); | 
| 1097     // Smis do not have instance fields (Smi class is always first). | 1097     // Smis do not have instance fields (Smi class is always first). | 
| 1098     // Use 'result' as temporary register. | 1098     // Use 'result' as temporary register. | 
| 1099     ASSERT(result_reg != instance_reg); | 1099     ASSERT(result_reg != instance_reg); | 
| 1100     ASSERT(ic_data() != NULL); | 1100     ASSERT(ic_data() != NULL); | 
| 1101     compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1101     compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 
| 1102   } | 1102   } | 
| 1103 | 1103 | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1148     __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1148     __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 
| 1149             Immediate(Smi::RawValue(len))); | 1149             Immediate(Smi::RawValue(len))); | 
| 1150     __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1150     __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 
| 1151     __ Bind(&type_arguments_uninstantiated); | 1151     __ Bind(&type_arguments_uninstantiated); | 
| 1152   } | 1152   } | 
| 1153   // A runtime call to instantiate the type arguments is required. | 1153   // A runtime call to instantiate the type arguments is required. | 
| 1154   __ PushObject(Object::ZoneHandle());  // Make room for the result. | 1154   __ PushObject(Object::ZoneHandle());  // Make room for the result. | 
| 1155   __ PushObject(type_arguments()); | 1155   __ PushObject(type_arguments()); | 
| 1156   __ pushq(instantiator_reg);  // Push instantiator type arguments. | 1156   __ pushq(instantiator_reg);  // Push instantiator type arguments. | 
| 1157   compiler->GenerateCallRuntime(cid(), | 1157   compiler->GenerateCallRuntime(cid(), | 
| 1158                                 token_index(), | 1158                                 token_pos(), | 
| 1159                                 try_index(), | 1159                                 try_index(), | 
| 1160                                 kInstantiateTypeArgumentsRuntimeEntry); | 1160                                 kInstantiateTypeArgumentsRuntimeEntry); | 
| 1161   __ Drop(2);  // Drop instantiator and uninstantiated type arguments. | 1161   __ Drop(2);  // Drop instantiator and uninstantiated type arguments. | 
| 1162   __ popq(result_reg);  // Pop instantiated type arguments. | 1162   __ popq(result_reg);  // Pop instantiated type arguments. | 
| 1163   __ Bind(&type_arguments_instantiated); | 1163   __ Bind(&type_arguments_instantiated); | 
| 1164   ASSERT(instantiator_reg == result_reg); | 1164   ASSERT(instantiator_reg == result_reg); | 
| 1165   // 'result_reg': Instantiated type arguments. | 1165   // 'result_reg': Instantiated type arguments. | 
| 1166 } | 1166 } | 
| 1167 | 1167 | 
| 1168 | 1168 | 
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1298 } | 1298 } | 
| 1299 | 1299 | 
| 1300 | 1300 | 
| 1301 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1301 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 1302   ASSERT(locs()->temp(0).reg() == R10); | 1302   ASSERT(locs()->temp(0).reg() == R10); | 
| 1303   ASSERT(locs()->out().reg() == RAX); | 1303   ASSERT(locs()->out().reg() == RAX); | 
| 1304 | 1304 | 
| 1305   __ movq(R10, Immediate(num_context_variables())); | 1305   __ movq(R10, Immediate(num_context_variables())); | 
| 1306   const ExternalLabel label("alloc_context", | 1306   const ExternalLabel label("alloc_context", | 
| 1307                             StubCode::AllocateContextEntryPoint()); | 1307                             StubCode::AllocateContextEntryPoint()); | 
| 1308   compiler->GenerateCall(token_index(), | 1308   compiler->GenerateCall(token_pos(), | 
| 1309                          try_index(), | 1309                          try_index(), | 
| 1310                          &label, | 1310                          &label, | 
| 1311                          PcDescriptors::kOther); | 1311                          PcDescriptors::kOther); | 
| 1312 } | 1312 } | 
| 1313 | 1313 | 
| 1314 | 1314 | 
| 1315 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1315 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 
| 1316   return LocationSummary::Make(1, | 1316   return LocationSummary::Make(1, | 
| 1317                                Location::RequiresRegister(), | 1317                                Location::RequiresRegister(), | 
| 1318                                LocationSummary::kCall); | 1318                                LocationSummary::kCall); | 
| 1319 } | 1319 } | 
| 1320 | 1320 | 
| 1321 | 1321 | 
| 1322 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1322 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 1323   Register context_value = locs()->in(0).reg(); | 1323   Register context_value = locs()->in(0).reg(); | 
| 1324   Register result = locs()->out().reg(); | 1324   Register result = locs()->out().reg(); | 
| 1325 | 1325 | 
| 1326   __ PushObject(Object::ZoneHandle());  // Make room for the result. | 1326   __ PushObject(Object::ZoneHandle());  // Make room for the result. | 
| 1327   __ pushq(context_value); | 1327   __ pushq(context_value); | 
| 1328   compiler->GenerateCallRuntime(cid(), | 1328   compiler->GenerateCallRuntime(cid(), | 
| 1329                                 token_index(), | 1329                                 token_pos(), | 
| 1330                                 try_index(), | 1330                                 try_index(), | 
| 1331                                 kCloneContextRuntimeEntry); | 1331                                 kCloneContextRuntimeEntry); | 
| 1332   __ popq(result);  // Remove argument. | 1332   __ popq(result);  // Remove argument. | 
| 1333   __ popq(result);  // Get result (cloned context). | 1333   __ popq(result);  // Get result (cloned context). | 
| 1334 } | 1334 } | 
| 1335 | 1335 | 
| 1336 | 1336 | 
| 1337 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1337 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 
| 1338   return LocationSummary::Make(0, Location::NoLocation()); | 1338   return LocationSummary::Make(0, Location::NoLocation()); | 
| 1339 } | 1339 } | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1372 | 1372 | 
| 1373 | 1373 | 
| 1374 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1374 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 1375   Register temp = locs()->temp(0).reg(); | 1375   Register temp = locs()->temp(0).reg(); | 
| 1376   // Generate stack overflow check. | 1376   // Generate stack overflow check. | 
| 1377   __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1377   __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 
| 1378   __ cmpq(RSP, Address(temp, 0)); | 1378   __ cmpq(RSP, Address(temp, 0)); | 
| 1379   Label no_stack_overflow; | 1379   Label no_stack_overflow; | 
| 1380   __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1380   __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 
| 1381   compiler->GenerateCallRuntime(cid(), | 1381   compiler->GenerateCallRuntime(cid(), | 
| 1382                                 token_index(), | 1382                                 token_pos(), | 
| 1383                                 try_index(), | 1383                                 try_index(), | 
| 1384                                 kStackOverflowRuntimeEntry); | 1384                                 kStackOverflowRuntimeEntry); | 
| 1385   __ Bind(&no_stack_overflow); | 1385   __ Bind(&no_stack_overflow); | 
| 1386 } | 1386 } | 
| 1387 | 1387 | 
| 1388 | 1388 | 
| 1389 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1389 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 
| 1390   const intptr_t kNumInputs = 2; | 1390   const intptr_t kNumInputs = 2; | 
| 1391 | 1391 | 
| 1392   if (operands_type() == kDoubleOperands) { | 1392   if (operands_type() == kDoubleOperands) { | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1448 } | 1448 } | 
| 1449 | 1449 | 
| 1450 | 1450 | 
| 1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 
| 1452   Register left = comp->locs()->in(0).reg(); | 1452   Register left = comp->locs()->in(0).reg(); | 
| 1453   Register right = comp->locs()->in(1).reg(); | 1453   Register right = comp->locs()->in(1).reg(); | 
| 1454   Register result = comp->locs()->out().reg(); | 1454   Register result = comp->locs()->out().reg(); | 
| 1455   Register temp = comp->locs()->temp(0).reg(); | 1455   Register temp = comp->locs()->temp(0).reg(); | 
| 1456   ASSERT(left == result); | 1456   ASSERT(left == result); | 
| 1457   Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1457   Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 
| 1458                                         comp->instance_call()->token_index(), | 1458                                         comp->instance_call()->token_pos(), | 
| 1459                                         comp->instance_call()->try_index(), | 1459                                         comp->instance_call()->try_index(), | 
| 1460                                         kDeoptSmiBinaryOp, | 1460                                         kDeoptSmiBinaryOp, | 
| 1461                                         temp, | 1461                                         temp, | 
| 1462                                         right); | 1462                                         right); | 
| 1463   // TODO(vegorov): for many binary operations this pattern can be rearranged | 1463   // TODO(vegorov): for many binary operations this pattern can be rearranged | 
| 1464   // to save one move. | 1464   // to save one move. | 
| 1465   __ movq(temp, left); | 1465   __ movq(temp, left); | 
| 1466   __ orq(left, right); | 1466   __ orq(left, right); | 
| 1467   __ testq(left, Immediate(kSmiTagMask)); | 1467   __ testq(left, Immediate(kSmiTagMask)); | 
| 1468   __ j(NOT_ZERO, deopt); | 1468   __ j(NOT_ZERO, deopt); | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1559       __ jmp(&done); | 1559       __ jmp(&done); | 
| 1560       { | 1560       { | 
| 1561         __ Bind(&call_method); | 1561         __ Bind(&call_method); | 
| 1562         Function& target = Function::ZoneHandle( | 1562         Function& target = Function::ZoneHandle( | 
| 1563             comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1563             comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 
| 1564         ASSERT(!target.IsNull()); | 1564         ASSERT(!target.IsNull()); | 
| 1565         const intptr_t kArgumentCount = 2; | 1565         const intptr_t kArgumentCount = 2; | 
| 1566         __ pushq(temp); | 1566         __ pushq(temp); | 
| 1567         __ pushq(right); | 1567         __ pushq(right); | 
| 1568         compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1568         compiler->GenerateStaticCall(comp->instance_call()->cid(), | 
| 1569                                      comp->instance_call()->token_index(), | 1569                                      comp->instance_call()->token_pos(), | 
| 1570                                      comp->instance_call()->try_index(), | 1570                                      comp->instance_call()->try_index(), | 
| 1571                                      target, | 1571                                      target, | 
| 1572                                      kArgumentCount, | 1572                                      kArgumentCount, | 
| 1573                                      Array::Handle());  // No argument names. | 1573                                      Array::Handle());  // No argument names. | 
| 1574         ASSERT(result == RAX); | 1574         ASSERT(result == RAX); | 
| 1575       } | 1575       } | 
| 1576       __ Bind(&done); | 1576       __ Bind(&done); | 
| 1577       break; | 1577       break; | 
| 1578     } | 1578     } | 
| 1579     case Token::kDIV: { | 1579     case Token::kDIV: { | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 1605   // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1605   // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 
| 1606   // receiver and a Mint or Smi argument. We fall back to the run time call if | 1606   // receiver and a Mint or Smi argument. We fall back to the run time call if | 
| 1607   // both receiver and argument are Mint or if one of them is Mint and the other | 1607   // both receiver and argument are Mint or if one of them is Mint and the other | 
| 1608   // is a negative Smi. | 1608   // is a negative Smi. | 
| 1609   Register left = comp->locs()->in(0).reg(); | 1609   Register left = comp->locs()->in(0).reg(); | 
| 1610   Register right = comp->locs()->in(1).reg(); | 1610   Register right = comp->locs()->in(1).reg(); | 
| 1611   Register result = comp->locs()->out().reg(); | 1611   Register result = comp->locs()->out().reg(); | 
| 1612   ASSERT(left == result); | 1612   ASSERT(left == result); | 
| 1613   ASSERT(comp->op_kind() == Token::kBIT_AND); | 1613   ASSERT(comp->op_kind() == Token::kBIT_AND); | 
| 1614   Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1614   Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 
| 1615                                         comp->instance_call()->token_index(), | 1615                                         comp->instance_call()->token_pos(), | 
| 1616                                         comp->instance_call()->try_index(), | 1616                                         comp->instance_call()->try_index(), | 
| 1617                                         kDeoptMintBinaryOp, | 1617                                         kDeoptMintBinaryOp, | 
| 1618                                         left, | 1618                                         left, | 
| 1619                                         right); | 1619                                         right); | 
| 1620   Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1620   Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 
| 1621   __ testq(left, Immediate(kSmiTagMask));  // Is receiver Smi? | 1621   __ testq(left, Immediate(kSmiTagMask));  // Is receiver Smi? | 
| 1622   __ j(NOT_ZERO, &non_smi); | 1622   __ j(NOT_ZERO, &non_smi); | 
| 1623   __ testq(right, Immediate(kSmiTagMask));  // Is argument Smi? | 1623   __ testq(right, Immediate(kSmiTagMask));  // Is argument Smi? | 
| 1624   __ j(ZERO, &smi_smi); | 1624   __ j(ZERO, &smi_smi); | 
| 1625   __ CompareClassId(right, kMint);  // Is argument Mint? | 1625   __ CompareClassId(right, kMint);  // Is argument Mint? | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 1653   __ Bind(&smi_static_call); | 1653   __ Bind(&smi_static_call); | 
| 1654   { | 1654   { | 
| 1655     Function& target = Function::ZoneHandle( | 1655     Function& target = Function::ZoneHandle( | 
| 1656         comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1656         comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 
| 1657     if (target.IsNull()) { | 1657     if (target.IsNull()) { | 
| 1658       __ jmp(deopt); | 1658       __ jmp(deopt); | 
| 1659     } else { | 1659     } else { | 
| 1660       __ pushq(left); | 1660       __ pushq(left); | 
| 1661       __ pushq(right); | 1661       __ pushq(right); | 
| 1662       compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1662       compiler->GenerateStaticCall(comp->instance_call()->cid(), | 
| 1663                                    comp->instance_call()->token_index(), | 1663                                    comp->instance_call()->token_pos(), | 
| 1664                                    comp->instance_call()->try_index(), | 1664                                    comp->instance_call()->try_index(), | 
| 1665                                    target, | 1665                                    target, | 
| 1666                                    comp->instance_call()->ArgumentCount(), | 1666                                    comp->instance_call()->ArgumentCount(), | 
| 1667                                    comp->instance_call()->argument_names()); | 1667                                    comp->instance_call()->argument_names()); | 
| 1668       ASSERT(result == RAX); | 1668       ASSERT(result == RAX); | 
| 1669       __ jmp(&done); | 1669       __ jmp(&done); | 
| 1670     } | 1670     } | 
| 1671   } | 1671   } | 
| 1672 | 1672 | 
| 1673   __ Bind(&mint_static_call); | 1673   __ Bind(&mint_static_call); | 
| 1674   { | 1674   { | 
| 1675     Function& target = Function::ZoneHandle( | 1675     Function& target = Function::ZoneHandle( | 
| 1676         comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1676         comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 
| 1677     if (target.IsNull()) { | 1677     if (target.IsNull()) { | 
| 1678       __ jmp(deopt); | 1678       __ jmp(deopt); | 
| 1679     } else { | 1679     } else { | 
| 1680       __ pushq(left); | 1680       __ pushq(left); | 
| 1681       __ pushq(right); | 1681       __ pushq(right); | 
| 1682       compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1682       compiler->GenerateStaticCall(comp->instance_call()->cid(), | 
| 1683                                    comp->instance_call()->token_index(), | 1683                                    comp->instance_call()->token_pos(), | 
| 1684                                    comp->instance_call()->try_index(), | 1684                                    comp->instance_call()->try_index(), | 
| 1685                                    target, | 1685                                    target, | 
| 1686                                    comp->instance_call()->ArgumentCount(), | 1686                                    comp->instance_call()->ArgumentCount(), | 
| 1687                                    comp->instance_call()->argument_names()); | 1687                                    comp->instance_call()->argument_names()); | 
| 1688       ASSERT(result == RAX); | 1688       ASSERT(result == RAX); | 
| 1689     } | 1689     } | 
| 1690   } | 1690   } | 
| 1691   __ Bind(&done); | 1691   __ Bind(&done); | 
| 1692 } | 1692 } | 
| 1693 | 1693 | 
| 1694 | 1694 | 
| 1695 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1695 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 
| 1696                                BinaryOpComp* comp) { | 1696                                BinaryOpComp* comp) { | 
| 1697   Register left = RBX; | 1697   Register left = RBX; | 
| 1698   Register right = RCX; | 1698   Register right = RCX; | 
| 1699   Register temp = RDX; | 1699   Register temp = RDX; | 
| 1700   Register result = comp->locs()->out().reg(); | 1700   Register result = comp->locs()->out().reg(); | 
| 1701 | 1701 | 
| 1702   const Class& double_class = compiler->double_class(); | 1702   const Class& double_class = compiler->double_class(); | 
| 1703   const Code& stub = | 1703   const Code& stub = | 
| 1704     Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1704     Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 
| 1705   const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1705   const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 
| 1706   compiler->GenerateCall(comp->instance_call()->token_index(), | 1706   compiler->GenerateCall(comp->instance_call()->token_pos(), | 
| 1707                          comp->instance_call()->try_index(), | 1707                          comp->instance_call()->try_index(), | 
| 1708                          &label, | 1708                          &label, | 
| 1709                          PcDescriptors::kOther); | 1709                          PcDescriptors::kOther); | 
| 1710   // Newly allocated object is now in the result register (RAX). | 1710   // Newly allocated object is now in the result register (RAX). | 
| 1711   ASSERT(result == RAX); | 1711   ASSERT(result == RAX); | 
| 1712   __ popq(right); | 1712   __ popq(right); | 
| 1713   __ popq(left); | 1713   __ popq(left); | 
| 1714 | 1714 | 
| 1715   Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1715   Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 
| 1716                                         comp->instance_call()->token_index(), | 1716                                         comp->instance_call()->token_pos(), | 
| 1717                                         comp->instance_call()->try_index(), | 1717                                         comp->instance_call()->try_index(), | 
| 1718                                         kDeoptDoubleBinaryOp, | 1718                                         kDeoptDoubleBinaryOp, | 
| 1719                                         left, | 1719                                         left, | 
| 1720                                         right); | 1720                                         right); | 
| 1721 | 1721 | 
| 1722   compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1722   compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 
| 1723   compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1723   compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 
| 1724 | 1724 | 
| 1725   switch (comp->op_kind()) { | 1725   switch (comp->op_kind()) { | 
| 1726     case Token::kADD: __ addsd(XMM0, XMM1); break; | 1726     case Token::kADD: __ addsd(XMM0, XMM1); break; | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1771   // TODO(srdjan): Implement for more checks. | 1771   // TODO(srdjan): Implement for more checks. | 
| 1772   ASSERT(ic_data.NumberOfChecks() == 1); | 1772   ASSERT(ic_data.NumberOfChecks() == 1); | 
| 1773   intptr_t test_class_id; | 1773   intptr_t test_class_id; | 
| 1774   Function& target = Function::Handle(); | 1774   Function& target = Function::Handle(); | 
| 1775   ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1775   ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 
| 1776 | 1776 | 
| 1777   Register value = locs()->in(0).reg(); | 1777   Register value = locs()->in(0).reg(); | 
| 1778   Register result = locs()->out().reg(); | 1778   Register result = locs()->out().reg(); | 
| 1779   ASSERT(value == result); | 1779   ASSERT(value == result); | 
| 1780   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1780   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 
| 1781                                         instance_call()->token_index(), | 1781                                         instance_call()->token_pos(), | 
| 1782                                         instance_call()->try_index(), | 1782                                         instance_call()->try_index(), | 
| 1783                                         kDeoptUnaryOp, | 1783                                         kDeoptUnaryOp, | 
| 1784                                         value); | 1784                                         value); | 
| 1785   if (test_class_id == kSmi) { | 1785   if (test_class_id == kSmi) { | 
| 1786     __ testq(value, Immediate(kSmiTagMask)); | 1786     __ testq(value, Immediate(kSmiTagMask)); | 
| 1787     __ j(NOT_ZERO, deopt); | 1787     __ j(NOT_ZERO, deopt); | 
| 1788     switch (op_kind()) { | 1788     switch (op_kind()) { | 
| 1789       case Token::kNEGATE: | 1789       case Token::kNEGATE: | 
| 1790         __ negq(value); | 1790         __ negq(value); | 
| 1791         __ j(OVERFLOW, deopt); | 1791         __ j(OVERFLOW, deopt); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1824   // TODO(srdjan): Implement for more checks. | 1824   // TODO(srdjan): Implement for more checks. | 
| 1825   ASSERT(ic_data.NumberOfChecks() == 1); | 1825   ASSERT(ic_data.NumberOfChecks() == 1); | 
| 1826   intptr_t test_class_id; | 1826   intptr_t test_class_id; | 
| 1827   Function& target = Function::Handle(); | 1827   Function& target = Function::Handle(); | 
| 1828   ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1828   ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 
| 1829 | 1829 | 
| 1830   Register value = locs()->in(0).reg(); | 1830   Register value = locs()->in(0).reg(); | 
| 1831   Register result = locs()->out().reg(); | 1831   Register result = locs()->out().reg(); | 
| 1832   ASSERT(value == result); | 1832   ASSERT(value == result); | 
| 1833   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1833   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 
| 1834                                         instance_call()->token_index(), | 1834                                         instance_call()->token_pos(), | 
| 1835                                         instance_call()->try_index(), | 1835                                         instance_call()->try_index(), | 
| 1836                                         kDeoptUnaryOp, | 1836                                         kDeoptUnaryOp, | 
| 1837                                         value); | 1837                                         value); | 
| 1838   if (test_class_id == kDouble) { | 1838   if (test_class_id == kDouble) { | 
| 1839     Register temp = locs()->temp(0).reg(); | 1839     Register temp = locs()->temp(0).reg(); | 
| 1840     __ testq(value, Immediate(kSmiTagMask)); | 1840     __ testq(value, Immediate(kSmiTagMask)); | 
| 1841     __ j(ZERO, deopt);  // Smi. | 1841     __ j(ZERO, deopt);  // Smi. | 
| 1842     __ CompareClassId(value, kDouble); | 1842     __ CompareClassId(value, kDouble); | 
| 1843     __ j(NOT_EQUAL, deopt); | 1843     __ j(NOT_EQUAL, deopt); | 
| 1844     // Allocate result object. | 1844     // Allocate result object. | 
| 1845     const Class& double_class = compiler->double_class(); | 1845     const Class& double_class = compiler->double_class(); | 
| 1846     const Code& stub = | 1846     const Code& stub = | 
| 1847         Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1847         Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 
| 1848     const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1848     const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 
| 1849     __ pushq(value); | 1849     __ pushq(value); | 
| 1850     compiler->GenerateCall(instance_call()->token_index(), | 1850     compiler->GenerateCall(instance_call()->token_pos(), | 
| 1851                            instance_call()->try_index(), | 1851                            instance_call()->try_index(), | 
| 1852                            &label, | 1852                            &label, | 
| 1853                            PcDescriptors::kOther); | 1853                            PcDescriptors::kOther); | 
| 1854     // Result is in RAX. | 1854     // Result is in RAX. | 
| 1855     ASSERT(result != temp); | 1855     ASSERT(result != temp); | 
| 1856     __ movq(result, RAX); | 1856     __ movq(result, RAX); | 
| 1857     __ popq(temp); | 1857     __ popq(temp); | 
| 1858     __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1858     __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 
| 1859     __ DoubleNegate(XMM0); | 1859     __ DoubleNegate(XMM0); | 
| 1860     __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1860     __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 1879 } | 1879 } | 
| 1880 | 1880 | 
| 1881 | 1881 | 
| 1882 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1882 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 1883   Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 1883   Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 
| 1884   Register result = locs()->out().reg(); | 1884   Register result = locs()->out().reg(); | 
| 1885 | 1885 | 
| 1886   const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1886   const DeoptReasonId deopt_reason = (from() == kDouble) ? | 
| 1887       kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1887       kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 
| 1888   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1888   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 
| 1889                                         instance_call()->token_index(), | 1889                                         instance_call()->token_pos(), | 
| 1890                                         instance_call()->try_index(), | 1890                                         instance_call()->try_index(), | 
| 1891                                         deopt_reason, | 1891                                         deopt_reason, | 
| 1892                                         value); | 1892                                         value); | 
| 1893 | 1893 | 
| 1894   if (from() == kDouble) { | 1894   if (from() == kDouble) { | 
| 1895     __ testq(value, Immediate(kSmiTagMask)); | 1895     __ testq(value, Immediate(kSmiTagMask)); | 
| 1896     __ j(ZERO, deopt);  // Deoptimize if Smi. | 1896     __ j(ZERO, deopt);  // Deoptimize if Smi. | 
| 1897     __ CompareClassId(value, kDouble); | 1897     __ CompareClassId(value, kDouble); | 
| 1898     __ j(NOT_EQUAL, deopt);  // Deoptimize if not Double. | 1898     __ j(NOT_EQUAL, deopt);  // Deoptimize if not Double. | 
| 1899     ASSERT(value == result); | 1899     ASSERT(value == result); | 
| 1900     return; | 1900     return; | 
| 1901   } | 1901   } | 
| 1902 | 1902 | 
| 1903   ASSERT(from() == kSmi); | 1903   ASSERT(from() == kSmi); | 
| 1904 | 1904 | 
| 1905   const Class& double_class = compiler->double_class(); | 1905   const Class& double_class = compiler->double_class(); | 
| 1906   const Code& stub = | 1906   const Code& stub = | 
| 1907     Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1907     Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 
| 1908   const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1908   const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 
| 1909 | 1909 | 
| 1910   // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1910   // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 
| 1911   compiler->GenerateCall(instance_call()->token_index(), | 1911   compiler->GenerateCall(instance_call()->token_pos(), | 
| 1912                          instance_call()->try_index(), | 1912                          instance_call()->try_index(), | 
| 1913                          &label, | 1913                          &label, | 
| 1914                          PcDescriptors::kOther); | 1914                          PcDescriptors::kOther); | 
| 1915   ASSERT(result == RAX); | 1915   ASSERT(result == RAX); | 
| 1916   __ popq(value); | 1916   __ popq(value); | 
| 1917 | 1917 | 
| 1918   __ testq(value, Immediate(kSmiTagMask)); | 1918   __ testq(value, Immediate(kSmiTagMask)); | 
| 1919   __ j(NOT_ZERO, deopt);  // Deoptimize if not Smi. | 1919   __ j(NOT_ZERO, deopt);  // Deoptimize if not Smi. | 
| 1920   __ SmiUntag(value); | 1920   __ SmiUntag(value); | 
| 1921   __ cvtsi2sd(XMM0, value); | 1921   __ cvtsi2sd(XMM0, value); | 
| 1922   __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1922   __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 
| 1923 } | 1923 } | 
| 1924 | 1924 | 
| 1925 | 1925 | 
| 1926 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1926 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 
| 1927   return MakeCallSummary(); | 1927   return MakeCallSummary(); | 
| 1928 } | 1928 } | 
| 1929 | 1929 | 
| 1930 | 1930 | 
| 1931 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1931 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| 1932   ASSERT(instance_call()->VerifyComputation()); | 1932   ASSERT(instance_call()->VerifyComputation()); | 
| 1933   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1933   Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 
| 1934                                         instance_call()->token_index(), | 1934                                         instance_call()->token_pos(), | 
| 1935                                         instance_call()->try_index(), | 1935                                         instance_call()->try_index(), | 
| 1936                                         kDeoptPolymorphicInstanceCallTestFail); | 1936                                         kDeoptPolymorphicInstanceCallTestFail); | 
| 1937   if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1937   if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 
| 1938     __ jmp(deopt); | 1938     __ jmp(deopt); | 
| 1939     return; | 1939     return; | 
| 1940   } | 1940   } | 
| 1941   ASSERT(HasICData()); | 1941   ASSERT(HasICData()); | 
| 1942   ASSERT(ic_data()->num_args_tested() == 1); | 1942   ASSERT(ic_data()->num_args_tested() == 1); | 
| 1943   Label handle_smi; | 1943   Label handle_smi; | 
| 1944   Label* is_smi_label = | 1944   Label* is_smi_label = | 
| 1945       ic_data()->GetReceiverClassIdAt(0) == kSmi ?  &handle_smi : deopt; | 1945       ic_data()->GetReceiverClassIdAt(0) == kSmi ?  &handle_smi : deopt; | 
| 1946 | 1946 | 
| 1947   // Load receiver into RAX. | 1947   // Load receiver into RAX. | 
| 1948   __ movq(RAX, | 1948   __ movq(RAX, | 
| 1949       Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1949       Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 
| 1950   __ testq(RAX, Immediate(kSmiTagMask)); | 1950   __ testq(RAX, Immediate(kSmiTagMask)); | 
| 1951   __ j(ZERO, is_smi_label); | 1951   __ j(ZERO, is_smi_label); | 
| 1952   Label done; | 1952   Label done; | 
| 1953   __ LoadClassId(RDI, RAX); | 1953   __ LoadClassId(RDI, RAX); | 
| 1954   compiler->EmitTestAndCall(*ic_data(), | 1954   compiler->EmitTestAndCall(*ic_data(), | 
| 1955                             RDI,  // Class id register. | 1955                             RDI,  // Class id register. | 
| 1956                             instance_call()->ArgumentCount(), | 1956                             instance_call()->ArgumentCount(), | 
| 1957                             instance_call()->argument_names(), | 1957                             instance_call()->argument_names(), | 
| 1958                             deopt, &done,  // Labels. | 1958                             deopt, &done,  // Labels. | 
| 1959                             instance_call()->cid(), | 1959                             instance_call()->cid(), | 
| 1960                             instance_call()->token_index(), | 1960                             instance_call()->token_pos(), | 
| 1961                             instance_call()->try_index()); | 1961                             instance_call()->try_index()); | 
| 1962   if (is_smi_label == &handle_smi) { | 1962   if (is_smi_label == &handle_smi) { | 
| 1963     __ Bind(&handle_smi); | 1963     __ Bind(&handle_smi); | 
| 1964     ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1964     ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 
| 1965     const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1965     const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 
| 1966     compiler->GenerateStaticCall(instance_call()->cid(), | 1966     compiler->GenerateStaticCall(instance_call()->cid(), | 
| 1967                                  instance_call()->token_index(), | 1967                                  instance_call()->token_pos(), | 
| 1968                                  instance_call()->try_index(), | 1968                                  instance_call()->try_index(), | 
| 1969                                  target, | 1969                                  target, | 
| 1970                                  instance_call()->ArgumentCount(), | 1970                                  instance_call()->ArgumentCount(), | 
| 1971                                  instance_call()->argument_names()); | 1971                                  instance_call()->argument_names()); | 
| 1972   } | 1972   } | 
| 1973   __ Bind(&done); | 1973   __ Bind(&done); | 
| 1974 } | 1974 } | 
| 1975 | 1975 | 
| 1976 }  // namespace dart | 1976 }  // namespace dart | 
| 1977 | 1977 | 
| 1978 #undef __ | 1978 #undef __ | 
| 1979 | 1979 | 
| 1980 #endif  // defined TARGET_ARCH_X64 | 1980 #endif  // defined TARGET_ARCH_X64 | 
| OLD | NEW | 
|---|