| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/locations.h" | 13 #include "vm/locations.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/parser.h" | 15 #include "vm/parser.h" |
| 16 #include "vm/simulator.h" |
| 16 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 17 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 18 | 19 |
| 19 #define __ compiler->assembler()-> | 20 #define __ compiler->assembler()-> |
| 20 | 21 |
| 21 namespace dart { | 22 namespace dart { |
| 22 | 23 |
| 23 DECLARE_FLAG(int, optimization_counter_threshold); | 24 DECLARE_FLAG(int, optimization_counter_threshold); |
| 24 DECLARE_FLAG(bool, propagate_ic_data); | 25 DECLARE_FLAG(bool, propagate_ic_data); |
| 25 | 26 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 188 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 188 summary->set_in(0, Location::RegisterLocation(A0)); // Value. | 189 summary->set_in(0, Location::RegisterLocation(A0)); // Value. |
| 189 summary->set_in(1, Location::RegisterLocation(A1)); // Instantiator. | 190 summary->set_in(1, Location::RegisterLocation(A1)); // Instantiator. |
| 190 summary->set_in(2, Location::RegisterLocation(A2)); // Type arguments. | 191 summary->set_in(2, Location::RegisterLocation(A2)); // Type arguments. |
| 191 summary->set_out(Location::RegisterLocation(A0)); | 192 summary->set_out(Location::RegisterLocation(A0)); |
| 192 return summary; | 193 return summary; |
| 193 } | 194 } |
| 194 | 195 |
| 195 | 196 |
| 196 LocationSummary* AssertBooleanInstr::MakeLocationSummary() const { | 197 LocationSummary* AssertBooleanInstr::MakeLocationSummary() const { |
| 197 UNIMPLEMENTED(); | 198 const intptr_t kNumInputs = 1; |
| 198 return NULL; | 199 const intptr_t kNumTemps = 0; |
| 200 LocationSummary* locs = |
| 201 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 202 locs->set_in(0, Location::RegisterLocation(A0)); |
| 203 locs->set_out(Location::RegisterLocation(A0)); |
| 204 return locs; |
| 205 } |
| 206 |
| 207 |
| 208 static void EmitAssertBoolean(Register reg, |
| 209 intptr_t token_pos, |
| 210 intptr_t deopt_id, |
| 211 LocationSummary* locs, |
| 212 FlowGraphCompiler* compiler) { |
| 213 // Check that the type of the value is allowed in conditional context. |
| 214 // Call the runtime if the object is not bool::true or bool::false. |
| 215 ASSERT(locs->always_calls()); |
| 216 Label done; |
| 217 __ BranchEqual(reg, Bool::True(), &done); |
| 218 __ BranchEqual(reg, Bool::False(), &done); |
| 219 |
| 220 __ Push(reg); // Push the source object. |
| 221 compiler->GenerateCallRuntime(token_pos, |
| 222 deopt_id, |
| 223 kConditionTypeErrorRuntimeEntry, |
| 224 locs); |
| 225 // We should never return here. |
| 226 __ break_(0); |
| 227 __ Bind(&done); |
| 199 } | 228 } |
| 200 | 229 |
| 201 | 230 |
| 202 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 231 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 203 UNIMPLEMENTED(); | 232 Register obj = locs()->in(0).reg(); |
| 233 Register result = locs()->out().reg(); |
| 234 |
| 235 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 236 ASSERT(obj == result); |
| 204 } | 237 } |
| 205 | 238 |
| 206 | 239 |
| 207 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { | 240 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { |
| 208 UNIMPLEMENTED(); | 241 UNIMPLEMENTED(); |
| 209 return NULL; | 242 return NULL; |
| 210 } | 243 } |
| 211 | 244 |
| 212 | 245 |
| 213 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 246 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 214 UNIMPLEMENTED(); | 247 UNIMPLEMENTED(); |
| 215 } | 248 } |
| 216 | 249 |
| 217 | 250 |
| 218 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { | 251 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { |
| 219 UNIMPLEMENTED(); | 252 const intptr_t kNumInputs = 2; |
| 220 return NULL; | 253 const bool is_checked_strict_equal = |
| 254 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 255 if (receiver_class_id() == kMintCid) { |
| 256 const intptr_t kNumTemps = 1; |
| 257 LocationSummary* locs = |
| 258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 259 locs->set_in(0, Location::RequiresFpuRegister()); |
| 260 locs->set_in(1, Location::RequiresFpuRegister()); |
| 261 locs->set_temp(0, Location::RequiresRegister()); |
| 262 locs->set_out(Location::RequiresRegister()); |
| 263 return locs; |
| 264 } |
| 265 if (receiver_class_id() == kDoubleCid) { |
| 266 const intptr_t kNumTemps = 0; |
| 267 LocationSummary* locs = |
| 268 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 269 locs->set_in(0, Location::RequiresFpuRegister()); |
| 270 locs->set_in(1, Location::RequiresFpuRegister()); |
| 271 locs->set_out(Location::RequiresRegister()); |
| 272 return locs; |
| 273 } |
| 274 if (receiver_class_id() == kSmiCid) { |
| 275 const intptr_t kNumTemps = 0; |
| 276 LocationSummary* locs = |
| 277 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 278 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 279 // Only one input can be a constant operand. The case of two constant |
| 280 // operands should be handled by constant propagation. |
| 281 locs->set_in(1, locs->in(0).IsConstant() |
| 282 ? Location::RequiresRegister() |
| 283 : Location::RegisterOrConstant(right())); |
| 284 locs->set_out(Location::RequiresRegister()); |
| 285 return locs; |
| 286 } |
| 287 if (is_checked_strict_equal) { |
| 288 const intptr_t kNumTemps = 1; |
| 289 LocationSummary* locs = |
| 290 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 291 locs->set_in(0, Location::RequiresRegister()); |
| 292 locs->set_in(1, Location::RequiresRegister()); |
| 293 locs->set_temp(0, Location::RequiresRegister()); |
| 294 locs->set_out(Location::RequiresRegister()); |
| 295 return locs; |
| 296 } |
| 297 if (IsPolymorphic()) { |
| 298 const intptr_t kNumTemps = 1; |
| 299 LocationSummary* locs = |
| 300 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 301 UNIMPLEMENTED(); // TODO(regis): Verify register allocation. |
| 302 return locs; |
| 303 } |
| 304 const intptr_t kNumTemps = 1; |
| 305 LocationSummary* locs = |
| 306 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 307 locs->set_in(0, Location::RegisterLocation(A1)); |
| 308 locs->set_in(1, Location::RegisterLocation(A0)); |
| 309 locs->set_temp(0, Location::RegisterLocation(T0)); |
| 310 locs->set_out(Location::RegisterLocation(V0)); |
| 311 return locs; |
| 312 } |
| 313 |
| 314 |
| 315 // A1: left. |
| 316 // A0: right. |
| 317 // Uses T0 to load ic_call_data. |
| 318 // Result in V0. |
| 319 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 320 intptr_t deopt_id, |
| 321 intptr_t token_pos, |
| 322 Token::Kind kind, |
| 323 LocationSummary* locs, |
| 324 const ICData& original_ic_data) { |
| 325 if (!compiler->is_optimizing()) { |
| 326 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 327 deopt_id, |
| 328 token_pos); |
| 329 } |
| 330 const int kNumberOfArguments = 2; |
| 331 const Array& kNoArgumentNames = Array::Handle(); |
| 332 const int kNumArgumentsChecked = 2; |
| 333 |
| 334 Label check_identity; |
| 335 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null())); |
| 336 __ beq(A1, TMP1, &check_identity); |
| 337 __ beq(A0, TMP1, &check_identity); |
| 338 |
| 339 ICData& equality_ic_data = ICData::ZoneHandle(); |
| 340 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
| 341 ASSERT(!original_ic_data.IsNull()); |
| 342 if (original_ic_data.NumberOfChecks() == 0) { |
| 343 // IC call for reoptimization populates original ICData. |
| 344 equality_ic_data = original_ic_data.raw(); |
| 345 } else { |
| 346 // Megamorphic call. |
| 347 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
| 348 } |
| 349 } else { |
| 350 equality_ic_data = ICData::New(compiler->parsed_function().function(), |
| 351 Symbols::EqualOperator(), |
| 352 deopt_id, |
| 353 kNumArgumentsChecked); |
| 354 } |
| 355 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 356 __ sw(A1, Address(SP, 1 * kWordSize)); |
| 357 __ sw(A0, Address(SP, 0 * kWordSize)); |
| 358 compiler->GenerateInstanceCall(deopt_id, |
| 359 token_pos, |
| 360 kNumberOfArguments, |
| 361 kNoArgumentNames, |
| 362 locs, |
| 363 equality_ic_data); |
| 364 Label check_ne; |
| 365 __ b(&check_ne); |
| 366 |
| 367 __ Bind(&check_identity); |
| 368 Label equality_done; |
| 369 if (compiler->is_optimizing()) { |
| 370 // No need to update IC data. |
| 371 Label is_true; |
| 372 __ beq(A1, A0, &is_true); |
| 373 __ LoadObject(V0, (kind == Token::kEQ) ? Bool::False() : Bool::True()); |
| 374 __ b(&equality_done); |
| 375 __ Bind(&is_true); |
| 376 __ LoadObject(V0, (kind == Token::kEQ) ? Bool::True() : Bool::False()); |
| 377 if (kind == Token::kNE) { |
| 378 // Skip not-equal result conversion. |
| 379 __ b(&equality_done); |
| 380 } |
| 381 } else { |
| 382 // Call stub, load IC data in register. The stub will update ICData if |
| 383 // necessary. |
| 384 Register ic_data_reg = locs->temp(0).reg(); |
| 385 ASSERT(ic_data_reg == T0); // Stub depends on it. |
| 386 __ LoadObject(ic_data_reg, equality_ic_data); |
| 387 // Pass left in A1 and right in A0. |
| 388 compiler->GenerateCall(token_pos, |
| 389 &StubCode::EqualityWithNullArgLabel(), |
| 390 PcDescriptors::kOther, |
| 391 locs); |
| 392 } |
| 393 __ Bind(&check_ne); |
| 394 if (kind == Token::kNE) { |
| 395 Label true_label, done; |
| 396 // Negate the condition: true label returns false and vice versa. |
| 397 __ BranchEqual(V0, Bool::True(), &true_label); |
| 398 __ LoadObject(V0, Bool::True()); |
| 399 __ b(&done); |
| 400 __ Bind(&true_label); |
| 401 __ LoadObject(V0, Bool::False()); |
| 402 __ Bind(&done); |
| 403 } |
| 404 __ Bind(&equality_done); |
| 405 } |
| 406 |
| 407 |
| 408 // Emit code when ICData's targets are all Object == (which is ===). |
| 409 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, |
| 410 const ICData& ic_data, |
| 411 const LocationSummary& locs, |
| 412 Token::Kind kind, |
| 413 BranchInstr* branch, |
| 414 intptr_t deopt_id) { |
| 415 UNIMPLEMENTED(); |
| 416 } |
| 417 |
| 418 |
| 419 // First test if receiver is NULL, in which case === is applied. |
| 420 // If type feedback was provided (lists of <class-id, target>), do a |
| 421 // type by type check (either === or static call to the operator. |
| 422 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 423 LocationSummary* locs, |
| 424 Token::Kind kind, |
| 425 BranchInstr* branch, |
| 426 const ICData& ic_data, |
| 427 intptr_t deopt_id, |
| 428 intptr_t token_pos) { |
| 429 UNIMPLEMENTED(); |
| 430 } |
| 431 |
| 432 |
| 433 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 434 const LocationSummary& locs, |
| 435 Token::Kind kind, |
| 436 BranchInstr* branch) { |
| 437 UNIMPLEMENTED(); |
| 438 } |
| 439 |
| 440 |
| 441 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 442 const LocationSummary& locs, |
| 443 Token::Kind kind, |
| 444 BranchInstr* branch) { |
| 445 UNIMPLEMENTED(); |
| 446 } |
| 447 |
| 448 |
| 449 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 450 const LocationSummary& locs, |
| 451 Token::Kind kind, |
| 452 BranchInstr* branch) { |
| 453 UNIMPLEMENTED(); |
| 221 } | 454 } |
| 222 | 455 |
| 223 | 456 |
| 224 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 457 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 225 UNIMPLEMENTED(); | 458 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 459 BranchInstr* kNoBranch = NULL; |
| 460 if (receiver_class_id() == kSmiCid) { |
| 461 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 462 return; |
| 463 } |
| 464 if (receiver_class_id() == kMintCid) { |
| 465 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch); |
| 466 return; |
| 467 } |
| 468 if (receiver_class_id() == kDoubleCid) { |
| 469 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 470 return; |
| 471 } |
| 472 const bool is_checked_strict_equal = |
| 473 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 474 if (is_checked_strict_equal) { |
| 475 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
| 476 deopt_id()); |
| 477 return; |
| 478 } |
| 479 if (IsPolymorphic()) { |
| 480 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), |
| 481 deopt_id(), token_pos()); |
| 482 return; |
| 483 } |
| 484 Register left = locs()->in(0).reg(); |
| 485 Register right = locs()->in(1).reg(); |
| 486 ASSERT(left == A1); |
| 487 ASSERT(right == A0); |
| 488 EmitEqualityAsInstanceCall(compiler, |
| 489 deopt_id(), |
| 490 token_pos(), |
| 491 kind(), |
| 492 locs(), |
| 493 *ic_data()); |
| 494 ASSERT(locs()->out().reg() == V0); |
| 226 } | 495 } |
| 227 | 496 |
| 228 | 497 |
| 229 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 498 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 230 BranchInstr* branch) { | 499 BranchInstr* branch) { |
| 231 UNIMPLEMENTED(); | 500 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 232 } | 501 if (receiver_class_id() == kSmiCid) { |
| 233 | 502 // Deoptimizes if both arguments not Smi. |
| 234 | 503 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 504 return; |
| 505 } |
| 506 if (receiver_class_id() == kMintCid) { |
| 507 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); |
| 508 return; |
| 509 } |
| 510 if (receiver_class_id() == kDoubleCid) { |
| 511 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 512 return; |
| 513 } |
| 514 const bool is_checked_strict_equal = |
| 515 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 516 if (is_checked_strict_equal) { |
| 517 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
| 518 deopt_id()); |
| 519 return; |
| 520 } |
| 521 if (IsPolymorphic()) { |
| 522 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), |
| 523 deopt_id(), token_pos()); |
| 524 return; |
| 525 } |
| 526 Register left = locs()->in(0).reg(); |
| 527 Register right = locs()->in(1).reg(); |
| 528 ASSERT(left == A1); |
| 529 ASSERT(right == A0); |
| 530 EmitEqualityAsInstanceCall(compiler, |
| 531 deopt_id(), |
| 532 token_pos(), |
| 533 Token::kEQ, // kNE reverse occurs at branch. |
| 534 locs(), |
| 535 *ic_data()); |
| 536 if (branch->is_checked()) { |
| 537 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); |
| 538 } |
| 539 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; |
| 540 __ CompareObject(CMPRES, V0, Bool::True()); |
| 541 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 542 } |
| 543 |
| 544 |
| 235 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 545 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 236 UNIMPLEMENTED(); | 546 UNIMPLEMENTED(); |
| 237 return NULL; | 547 return NULL; |
| 238 } | 548 } |
| 239 | 549 |
| 240 | 550 |
| 241 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 551 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 242 UNIMPLEMENTED(); | 552 UNIMPLEMENTED(); |
| 243 } | 553 } |
| 244 | 554 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 265 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 575 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 266 ASSERT(locs()->temp(0).reg() == A1); | 576 ASSERT(locs()->temp(0).reg() == A1); |
| 267 ASSERT(locs()->temp(1).reg() == A2); | 577 ASSERT(locs()->temp(1).reg() == A2); |
| 268 ASSERT(locs()->temp(2).reg() == T5); | 578 ASSERT(locs()->temp(2).reg() == T5); |
| 269 Register result = locs()->out().reg(); | 579 Register result = locs()->out().reg(); |
| 270 | 580 |
| 271 // Push the result place holder initialized to NULL. | 581 // Push the result place holder initialized to NULL. |
| 272 __ PushObject(Object::ZoneHandle()); | 582 __ PushObject(Object::ZoneHandle()); |
| 273 // Pass a pointer to the first argument in A2. | 583 // Pass a pointer to the first argument in A2. |
| 274 if (!function().HasOptionalParameters()) { | 584 if (!function().HasOptionalParameters()) { |
| 275 __ addiu(A2, FP, Immediate((kLastParamSlotIndex + | 585 __ AddImmediate(A2, FP, (kLastParamSlotIndex + |
| 276 function().NumParameters() - 1) * kWordSize)); | 586 function().NumParameters() - 1) * kWordSize); |
| 277 } else { | 587 } else { |
| 278 __ addiu(A2, FP, Immediate(kFirstLocalSlotIndex * kWordSize)); | 588 __ AddImmediate(A2, FP, kFirstLocalSlotIndex * kWordSize); |
| 279 } | 589 } |
| 280 // Compute the effective address. When running under the simulator, | 590 // Compute the effective address. When running under the simulator, |
| 281 // this is a redirection address that forces the simulator to call | 591 // this is a redirection address that forces the simulator to call |
| 282 // into the runtime system. | 592 // into the runtime system. |
| 283 uword entry = reinterpret_cast<uword>(native_c_function()); | 593 uword entry = reinterpret_cast<uword>(native_c_function()); |
| 284 #if defined(USING_SIMULATOR) | 594 #if defined(USING_SIMULATOR) |
| 285 entry = Simulator::RedirectExternalReference(entry, Simulator::kNativeCall); | 595 entry = Simulator::RedirectExternalReference(entry, Simulator::kNativeCall); |
| 286 #endif | 596 #endif |
| 287 __ LoadImmediate(T5, entry); | 597 __ LoadImmediate(T5, entry); |
| 288 __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function())); | 598 __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function())); |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 } | 1022 } |
| 713 | 1023 |
| 714 | 1024 |
| 715 LocationSummary* BranchInstr::MakeLocationSummary() const { | 1025 LocationSummary* BranchInstr::MakeLocationSummary() const { |
| 716 UNREACHABLE(); | 1026 UNREACHABLE(); |
| 717 return NULL; | 1027 return NULL; |
| 718 } | 1028 } |
| 719 | 1029 |
| 720 | 1030 |
| 721 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1031 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 722 UNIMPLEMENTED(); | 1032 comparison()->EmitBranchCode(compiler, this); |
| 723 } | 1033 } |
| 724 | 1034 |
| 725 | 1035 |
| 726 LocationSummary* CheckClassInstr::MakeLocationSummary() const { | 1036 LocationSummary* CheckClassInstr::MakeLocationSummary() const { |
| 727 UNIMPLEMENTED(); | 1037 UNIMPLEMENTED(); |
| 728 return NULL; | 1038 return NULL; |
| 729 } | 1039 } |
| 730 | 1040 |
| 731 | 1041 |
| 732 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1042 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 return NULL; | 1138 return NULL; |
| 829 } | 1139 } |
| 830 | 1140 |
| 831 | 1141 |
| 832 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1142 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 833 UNIMPLEMENTED(); | 1143 UNIMPLEMENTED(); |
| 834 } | 1144 } |
| 835 | 1145 |
| 836 | 1146 |
| 837 LocationSummary* GotoInstr::MakeLocationSummary() const { | 1147 LocationSummary* GotoInstr::MakeLocationSummary() const { |
| 838 UNIMPLEMENTED(); | 1148 return new LocationSummary(0, 0, LocationSummary::kNoCall); |
| 839 return NULL; | |
| 840 } | 1149 } |
| 841 | 1150 |
| 842 | 1151 |
| 843 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1152 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 844 UNIMPLEMENTED(); | 1153 // Add deoptimization descriptor for deoptimizing instructions |
| 1154 // that may be inserted before this instruction. |
| 1155 if (!compiler->is_optimizing()) { |
| 1156 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 1157 GetDeoptId(), |
| 1158 0); // No token position. |
| 1159 } |
| 1160 |
| 1161 if (HasParallelMove()) { |
| 1162 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 1163 } |
| 1164 |
| 1165 // We can fall through if the successor is the next block in the list. |
| 1166 // Otherwise, we need a jump. |
| 1167 if (!compiler->CanFallThroughTo(successor())) { |
| 1168 __ b(compiler->GetJumpLabel(successor())); |
| 1169 } |
| 1170 } |
| 1171 |
| 1172 |
| 1173 static Condition NegateCondition(Condition condition) { |
| 1174 switch (condition) { |
| 1175 case EQ: return NE; |
| 1176 case NE: return EQ; |
| 1177 default: |
| 1178 OS::Print("Error: Condition not recognized: %d\n", condition); |
| 1179 UNIMPLEMENTED(); |
| 1180 return EQ; |
| 1181 } |
| 845 } | 1182 } |
| 846 | 1183 |
| 847 | 1184 |
| 848 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, | 1185 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 849 bool value) { | 1186 bool value) { |
| 850 UNIMPLEMENTED(); | 1187 if (value && !compiler->CanFallThroughTo(true_successor())) { |
| 1188 __ b(compiler->GetJumpLabel(true_successor())); |
| 1189 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { |
| 1190 __ b(compiler->GetJumpLabel(false_successor())); |
| 1191 } |
| 851 } | 1192 } |
| 852 | 1193 |
| 853 | 1194 |
| 1195 // The comparison result is in CMPRES. |
| 854 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, | 1196 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 855 Condition true_condition) { | 1197 Condition true_condition) { |
| 856 UNIMPLEMENTED(); | 1198 if (compiler->CanFallThroughTo(false_successor())) { |
| 1199 // If the next block is the false successor we will fall through to it. |
| 1200 if (true_condition == EQ) { |
| 1201 __ beq(CMPRES, ZR, compiler->GetJumpLabel(true_successor())); |
| 1202 } else { |
| 1203 ASSERT(true_condition == NE); |
| 1204 __ bne(CMPRES, ZR, compiler->GetJumpLabel(true_successor())); |
| 1205 } |
| 1206 } else { |
| 1207 // If the next block is the true successor we negate comparison and fall |
| 1208 // through to it. |
| 1209 Condition false_condition = NegateCondition(true_condition); |
| 1210 if (false_condition == EQ) { |
| 1211 __ beq(CMPRES, ZR, compiler->GetJumpLabel(false_successor())); |
| 1212 } else { |
| 1213 ASSERT(false_condition == NE); |
| 1214 __ bne(CMPRES, ZR, compiler->GetJumpLabel(false_successor())); |
| 1215 } |
| 1216 // Fall through or jump to the true successor. |
| 1217 if (!compiler->CanFallThroughTo(true_successor())) { |
| 1218 __ b(compiler->GetJumpLabel(true_successor())); |
| 1219 } |
| 1220 } |
| 857 } | 1221 } |
| 858 | 1222 |
| 859 | 1223 |
| 860 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { | 1224 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 861 UNIMPLEMENTED(); | 1225 UNIMPLEMENTED(); |
| 862 return NULL; | 1226 return NULL; |
| 863 } | 1227 } |
| 864 | 1228 |
| 865 | 1229 |
| 866 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1230 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 867 UNIMPLEMENTED(); | 1231 UNIMPLEMENTED(); |
| 868 } | 1232 } |
| 869 | 1233 |
| 870 | 1234 |
| 871 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { | 1235 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 872 UNIMPLEMENTED(); | 1236 const intptr_t kNumInputs = 2; |
| 873 return NULL; | 1237 const intptr_t kNumTemps = 0; |
| 1238 LocationSummary* locs = |
| 1239 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1240 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 1241 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 1242 locs->set_out(Location::RequiresRegister()); |
| 1243 return locs; |
| 874 } | 1244 } |
| 875 | 1245 |
| 876 | 1246 |
| 1247 // Special code for numbers (compare values instead of references.) |
| 877 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1248 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 878 UNIMPLEMENTED(); | 1249 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 1250 Location left = locs()->in(0); |
| 1251 Location right = locs()->in(1); |
| 1252 if (left.IsConstant() && right.IsConstant()) { |
| 1253 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 1254 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 1255 left.constant().raw() == right.constant().raw() : |
| 1256 left.constant().raw() != right.constant().raw(); |
| 1257 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); |
| 1258 return; |
| 1259 } |
| 1260 if (left.IsConstant()) { |
| 1261 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 1262 left.constant(), |
| 1263 needs_number_check()); |
| 1264 } else if (right.IsConstant()) { |
| 1265 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 1266 right.constant(), |
| 1267 needs_number_check()); |
| 1268 } else { |
| 1269 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 1270 right.reg(), |
| 1271 needs_number_check()); |
| 1272 } |
| 1273 |
| 1274 Register result = locs()->out().reg(); |
| 1275 Label load_true, done; |
| 1276 if (kind() == Token::kEQ_STRICT) { |
| 1277 __ beq(CMPRES, ZR, &load_true); |
| 1278 } else { |
| 1279 ASSERT(kind() == Token::kNE_STRICT); |
| 1280 __ bne(CMPRES, ZR, &load_true); |
| 1281 } |
| 1282 __ LoadObject(result, Bool::False()); |
| 1283 __ b(&done); |
| 1284 __ Bind(&load_true); |
| 1285 __ LoadObject(result, Bool::True()); |
| 1286 __ Bind(&done); |
| 879 } | 1287 } |
| 880 | 1288 |
| 881 | 1289 |
| 882 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 1290 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 883 BranchInstr* branch) { | 1291 BranchInstr* branch) { |
| 884 UNIMPLEMENTED(); | 1292 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 1293 Location left = locs()->in(0); |
| 1294 Location right = locs()->in(1); |
| 1295 if (left.IsConstant() && right.IsConstant()) { |
| 1296 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 1297 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 1298 left.constant().raw() == right.constant().raw() : |
| 1299 left.constant().raw() != right.constant().raw(); |
| 1300 branch->EmitBranchOnValue(compiler, result); |
| 1301 return; |
| 1302 } |
| 1303 if (left.IsConstant()) { |
| 1304 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 1305 left.constant(), |
| 1306 needs_number_check()); |
| 1307 } else if (right.IsConstant()) { |
| 1308 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 1309 right.constant(), |
| 1310 needs_number_check()); |
| 1311 } else { |
| 1312 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 1313 right.reg(), |
| 1314 needs_number_check()); |
| 1315 } |
| 1316 |
| 1317 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; |
| 1318 branch->EmitBranchOnCondition(compiler, true_condition); |
| 885 } | 1319 } |
| 886 | 1320 |
| 887 | 1321 |
| 888 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1322 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 889 UNIMPLEMENTED(); | 1323 UNIMPLEMENTED(); |
| 890 } | 1324 } |
| 891 | 1325 |
| 892 | 1326 |
| 893 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 1327 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 894 UNIMPLEMENTED(); | 1328 UNIMPLEMENTED(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 917 return NULL; | 1351 return NULL; |
| 918 } | 1352 } |
| 919 | 1353 |
| 920 | 1354 |
| 921 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1355 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 922 UNIMPLEMENTED(); | 1356 UNIMPLEMENTED(); |
| 923 } | 1357 } |
| 924 | 1358 |
| 925 | 1359 |
| 926 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { | 1360 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 927 UNIMPLEMENTED(); | 1361 return MakeCallSummary(); |
| 928 return NULL; | |
| 929 } | 1362 } |
| 930 | 1363 |
| 931 | 1364 |
| 932 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1365 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 933 UNIMPLEMENTED(); | 1366 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 1367 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 1368 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 1369 compiler->GenerateCall(token_pos(), |
| 1370 &label, |
| 1371 PcDescriptors::kOther, |
| 1372 locs()); |
| 1373 __ Drop(ArgumentCount()); // Discard arguments. |
| 934 } | 1374 } |
| 935 | 1375 |
| 936 | 1376 |
| 937 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { | 1377 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 938 UNIMPLEMENTED(); | 1378 UNIMPLEMENTED(); |
| 939 return NULL; | 1379 return NULL; |
| 940 } | 1380 } |
| 941 | 1381 |
| 942 | 1382 |
| 943 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1383 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 944 UNIMPLEMENTED(); | 1384 UNIMPLEMENTED(); |
| 945 } | 1385 } |
| 946 | 1386 |
| 947 } // namespace dart | 1387 } // namespace dart |
| 948 | 1388 |
| 949 #endif // defined TARGET_ARCH_MIPS | 1389 #endif // defined TARGET_ARCH_MIPS |
| 950 | 1390 |
| OLD | NEW |