| 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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 285 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 286 // - Class equality (only if class is not parameterized). | 286 // - Class equality (only if class is not parameterized). |
| 287 // Inputs: | 287 // Inputs: |
| 288 // - RAX: object. | 288 // - RAX: object. |
| 289 // - RDX: optional instantiator type arguments. | 289 // - RDX: optional instantiator type arguments. |
| 290 // Destroys RCX and RDX. | 290 // Destroys RCX and RDX. |
| 291 // Returns: | 291 // Returns: |
| 292 // - object in RAX for successful assignable check (or throws TypeError). | 292 // - object in RAX for successful assignable check (or throws TypeError). |
| 293 // Performance notes: positive checks must be quick, negative checks can be slow | 293 // Performance notes: positive checks must be quick, negative checks can be slow |
| 294 // as they throw an exception. | 294 // as they throw an exception. |
| 295 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t node_id, | 295 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid, |
| 296 intptr_t token_index, | 296 intptr_t token_index, |
| 297 intptr_t try_index, | 297 intptr_t try_index, |
| 298 const AbstractType& dst_type, | 298 const AbstractType& dst_type, |
| 299 const String& dst_name) { | 299 const String& dst_name) { |
| 300 ASSERT(FLAG_enable_type_checks); | 300 ASSERT(FLAG_enable_type_checks); |
| 301 ASSERT(token_index >= 0); | 301 ASSERT(token_index >= 0); |
| 302 ASSERT(!dst_type.IsNull()); | 302 ASSERT(!dst_type.IsNull()); |
| 303 ASSERT(dst_type.IsFinalized()); | 303 ASSERT(dst_type.IsFinalized()); |
| 304 ASSERT(dst_type.IsMalformed() || | 304 ASSERT(dst_type.IsMalformed() || |
| 305 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 305 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 317 const Error& error = Error::Handle(dst_type.malformed_error()); | 317 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 318 const String& error_message = String::ZoneHandle( | 318 const String& error_message = String::ZoneHandle( |
| 319 String::NewSymbol(error.ToErrorCString())); | 319 String::NewSymbol(error.ToErrorCString())); |
| 320 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 320 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 321 const Immediate location = | 321 const Immediate location = |
| 322 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 322 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); |
| 323 __ pushq(location); // Push the source location. | 323 __ pushq(location); // Push the source location. |
| 324 __ pushq(RAX); // Push the source object. | 324 __ pushq(RAX); // Push the source object. |
| 325 __ PushObject(dst_name); // Push the name of the destination. | 325 __ PushObject(dst_name); // Push the name of the destination. |
| 326 __ PushObject(error_message); | 326 __ PushObject(error_message); |
| 327 GenerateCallRuntime(node_id, | 327 GenerateCallRuntime(cid, |
| 328 token_index, | 328 token_index, |
| 329 try_index, | 329 try_index, |
| 330 kMalformedTypeErrorRuntimeEntry); | 330 kMalformedTypeErrorRuntimeEntry); |
| 331 // We should never return here. | 331 // We should never return here. |
| 332 __ int3(); | 332 __ int3(); |
| 333 | 333 |
| 334 __ Bind(&is_assignable); // For a null object. | 334 __ Bind(&is_assignable); // For a null object. |
| 335 return; | 335 return; |
| 336 } | 336 } |
| 337 | 337 |
| 338 // Generate inline type check, linking to runtime call if not assignable. | 338 // Generate inline type check, linking to runtime call if not assignable. |
| 339 GenerateInlineInstanceof(dst_type, &is_assignable, &runtime_call); | 339 GenerateInlineInstanceof(dst_type, &is_assignable, &runtime_call); |
| 340 | 340 |
| 341 __ Bind(&runtime_call); | 341 __ Bind(&runtime_call); |
| 342 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 342 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 343 const Immediate location = | 343 const Immediate location = |
| 344 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 344 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); |
| 345 const Immediate node_id_as_smi = | 345 const Immediate cid_as_smi = |
| 346 Immediate(reinterpret_cast<int64_t>(Smi::New(node_id))); | 346 Immediate(reinterpret_cast<int64_t>(Smi::New(cid))); |
| 347 __ pushq(location); // Push the source location. | 347 __ pushq(location); // Push the source location. |
| 348 __ pushq(node_id_as_smi); // node-id. | 348 __ pushq(cid_as_smi); // node-id. |
| 349 __ pushq(RAX); // Push the source object. | 349 __ pushq(RAX); // Push the source object. |
| 350 __ PushObject(dst_type); // Push the type of the destination. | 350 __ PushObject(dst_type); // Push the type of the destination. |
| 351 if (!dst_type.IsInstantiated()) { | 351 if (!dst_type.IsInstantiated()) { |
| 352 __ pushq(RDX); // Instantiator type arguments. | 352 __ pushq(RDX); // Instantiator type arguments. |
| 353 } else { | 353 } else { |
| 354 __ pushq(raw_null); // Null instantiator. | 354 __ pushq(raw_null); // Null instantiator. |
| 355 } | 355 } |
| 356 __ PushObject(dst_name); // Push the name of the destination. | 356 __ PushObject(dst_name); // Push the name of the destination. |
| 357 GenerateCallRuntime(node_id, | 357 GenerateCallRuntime(cid, |
| 358 token_index, | 358 token_index, |
| 359 try_index, | 359 try_index, |
| 360 kTypeCheckRuntimeEntry); | 360 kTypeCheckRuntimeEntry); |
| 361 // Pop the parameters supplied to the runtime entry. The result of the | 361 // Pop the parameters supplied to the runtime entry. The result of the |
| 362 // type check runtime call is the checked value. | 362 // type check runtime call is the checked value. |
| 363 __ addq(RSP, Immediate(6 * kWordSize)); | 363 __ addq(RSP, Immediate(6 * kWordSize)); |
| 364 __ popq(RAX); | 364 __ popq(RAX); |
| 365 | 365 |
| 366 __ Bind(&is_assignable); | 366 __ Bind(&is_assignable); |
| 367 } | 367 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 396 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { | 396 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { |
| 397 LoadValue(RAX, val); | 397 LoadValue(RAX, val); |
| 398 } | 398 } |
| 399 | 399 |
| 400 | 400 |
| 401 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { | 401 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { |
| 402 if (comp->instantiator_type_arguments() != NULL) { | 402 if (comp->instantiator_type_arguments() != NULL) { |
| 403 __ popq(RDX); | 403 __ popq(RDX); |
| 404 } | 404 } |
| 405 LoadValue(RAX, comp->value()); | 405 LoadValue(RAX, comp->value()); |
| 406 GenerateAssertAssignable(comp->node_id(), | 406 GenerateAssertAssignable(comp->cid(), |
| 407 comp->token_index(), | 407 comp->token_index(), |
| 408 comp->try_index(), | 408 comp->try_index(), |
| 409 comp->dst_type(), | 409 comp->dst_type(), |
| 410 comp->dst_name()); | 410 comp->dst_name()); |
| 411 } | 411 } |
| 412 | 412 |
| 413 | 413 |
| 414 void FlowGraphCompiler::VisitAssertBoolean(AssertBooleanComp* comp) { | 414 void FlowGraphCompiler::VisitAssertBoolean(AssertBooleanComp* comp) { |
| 415 LoadValue(RAX, comp->value()); | 415 LoadValue(RAX, comp->value()); |
| 416 // Check that the type of the value is allowed in conditional context. | 416 // Check that the type of the value is allowed in conditional context. |
| 417 // Call the runtime if the object is not bool::true or bool::false. | 417 // Call the runtime if the object is not bool::true or bool::false. |
| 418 Label done; | 418 Label done; |
| 419 __ CompareObject(RAX, Bool::ZoneHandle(Bool::True())); | 419 __ CompareObject(RAX, Bool::ZoneHandle(Bool::True())); |
| 420 __ j(EQUAL, &done, Assembler::kNearJump); | 420 __ j(EQUAL, &done, Assembler::kNearJump); |
| 421 __ CompareObject(RAX, Bool::ZoneHandle(Bool::False())); | 421 __ CompareObject(RAX, Bool::ZoneHandle(Bool::False())); |
| 422 __ j(EQUAL, &done, Assembler::kNearJump); | 422 __ j(EQUAL, &done, Assembler::kNearJump); |
| 423 | 423 |
| 424 const Immediate location = | 424 const Immediate location = |
| 425 Immediate(reinterpret_cast<int64_t>(Smi::New(comp->token_index()))); | 425 Immediate(reinterpret_cast<int64_t>(Smi::New(comp->token_index()))); |
| 426 __ pushq(location); // Push the source location. | 426 __ pushq(location); // Push the source location. |
| 427 __ pushq(RAX); // Push the source object. | 427 __ pushq(RAX); // Push the source object. |
| 428 GenerateCallRuntime(comp->node_id(), | 428 GenerateCallRuntime(comp->cid(), |
| 429 comp->token_index(), | 429 comp->token_index(), |
| 430 comp->try_index(), | 430 comp->try_index(), |
| 431 kConditionTypeErrorRuntimeEntry); | 431 kConditionTypeErrorRuntimeEntry); |
| 432 // We should never return here. | 432 // We should never return here. |
| 433 __ int3(); | 433 __ int3(); |
| 434 | 434 |
| 435 __ Bind(&done); | 435 __ Bind(&done); |
| 436 } | 436 } |
| 437 | 437 |
| 438 | 438 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 461 | 461 |
| 462 // Truee iff. the v2 is above v1 on stack, or one of them is constant. | 462 // Truee iff. the v2 is above v1 on stack, or one of them is constant. |
| 463 static bool VerifyValues(Value* v1, Value* v2) { | 463 static bool VerifyValues(Value* v1, Value* v2) { |
| 464 if (v1->IsTemp() && v2->IsTemp()) { | 464 if (v1->IsTemp() && v2->IsTemp()) { |
| 465 return (v1->AsTemp()->index() + 1) == v2->AsTemp()->index(); | 465 return (v1->AsTemp()->index() + 1) == v2->AsTemp()->index(); |
| 466 } | 466 } |
| 467 return true; | 467 return true; |
| 468 } | 468 } |
| 469 | 469 |
| 470 | 470 |
| 471 void FlowGraphCompiler::EmitInstanceCall(intptr_t node_id, | 471 void FlowGraphCompiler::EmitInstanceCall(intptr_t cid, |
| 472 intptr_t token_index, | 472 intptr_t token_index, |
| 473 intptr_t try_index, | 473 intptr_t try_index, |
| 474 const String& function_name, | 474 const String& function_name, |
| 475 intptr_t argument_count, | 475 intptr_t argument_count, |
| 476 const Array& argument_names, | 476 const Array& argument_names, |
| 477 intptr_t checked_argument_count) { | 477 intptr_t checked_argument_count) { |
| 478 ICData& ic_data = | 478 ICData& ic_data = |
| 479 ICData::ZoneHandle(ICData::New(parsed_function_.function(), | 479 ICData::ZoneHandle(ICData::New(parsed_function_.function(), |
| 480 function_name, | 480 function_name, |
| 481 node_id, | 481 cid, |
| 482 checked_argument_count)); | 482 checked_argument_count)); |
| 483 const Array& arguments_descriptor = | 483 const Array& arguments_descriptor = |
| 484 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); | 484 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| 485 __ LoadObject(RBX, ic_data); | 485 __ LoadObject(RBX, ic_data); |
| 486 __ LoadObject(R10, arguments_descriptor); | 486 __ LoadObject(R10, arguments_descriptor); |
| 487 | 487 |
| 488 uword label_address = 0; | 488 uword label_address = 0; |
| 489 switch (checked_argument_count) { | 489 switch (checked_argument_count) { |
| 490 case 1: | 490 case 1: |
| 491 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); | 491 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); |
| 492 break; | 492 break; |
| 493 case 2: | 493 case 2: |
| 494 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); | 494 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); |
| 495 break; | 495 break; |
| 496 default: | 496 default: |
| 497 UNIMPLEMENTED(); | 497 UNIMPLEMENTED(); |
| 498 } | 498 } |
| 499 ExternalLabel target_label("InlineCache", label_address); | 499 ExternalLabel target_label("InlineCache", label_address); |
| 500 __ call(&target_label); | 500 __ call(&target_label); |
| 501 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index, try_index); | 501 AddCurrentDescriptor(PcDescriptors::kIcCall, cid, token_index, try_index); |
| 502 __ addq(RSP, Immediate(argument_count * kWordSize)); | 502 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 503 } | 503 } |
| 504 | 504 |
| 505 | 505 |
| 506 void FlowGraphCompiler::EmitStaticCall(intptr_t token_index, | 506 void FlowGraphCompiler::EmitStaticCall(intptr_t token_index, |
| 507 intptr_t try_index, | 507 intptr_t try_index, |
| 508 const Function& function, | 508 const Function& function, |
| 509 intptr_t argument_count, | 509 intptr_t argument_count, |
| 510 const Array& argument_names) { | 510 const Array& argument_names) { |
| 511 const Array& arguments_descriptor = | 511 const Array& arguments_descriptor = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 comp->try_index(), | 547 comp->try_index(), |
| 548 &StubCode::CallClosureFunctionLabel(), | 548 &StubCode::CallClosureFunctionLabel(), |
| 549 PcDescriptors::kOther); | 549 PcDescriptors::kOther); |
| 550 __ addq(RSP, Immediate(argument_count * kWordSize)); | 550 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 551 __ popq(CTX); | 551 __ popq(CTX); |
| 552 } | 552 } |
| 553 | 553 |
| 554 | 554 |
| 555 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { | 555 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
| 556 ASSERT(VerifyCallComputation(comp)); | 556 ASSERT(VerifyCallComputation(comp)); |
| 557 EmitInstanceCall(comp->node_id(), | 557 EmitInstanceCall(comp->cid(), |
| 558 comp->token_index(), | 558 comp->token_index(), |
| 559 comp->try_index(), | 559 comp->try_index(), |
| 560 comp->function_name(), | 560 comp->function_name(), |
| 561 comp->ArgumentCount(), | 561 comp->ArgumentCount(), |
| 562 comp->argument_names(), | 562 comp->argument_names(), |
| 563 comp->checked_argument_count()); | 563 comp->checked_argument_count()); |
| 564 } | 564 } |
| 565 | 565 |
| 566 | 566 |
| 567 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { | 567 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 __ jmp(&done); | 604 __ jmp(&done); |
| 605 | 605 |
| 606 __ Bind(&non_null_compare); | 606 __ Bind(&non_null_compare); |
| 607 __ pushq(RAX); | 607 __ pushq(RAX); |
| 608 __ pushq(RDX); | 608 __ pushq(RDX); |
| 609 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 609 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 610 const int kNumberOfArguments = 2; | 610 const int kNumberOfArguments = 2; |
| 611 const Array& kNoArgumentNames = Array::Handle(); | 611 const Array& kNoArgumentNames = Array::Handle(); |
| 612 const int kNumArgumentsChecked = 1; | 612 const int kNumArgumentsChecked = 1; |
| 613 | 613 |
| 614 EmitInstanceCall(comp->node_id(), | 614 EmitInstanceCall(comp->cid(), |
| 615 comp->token_index(), | 615 comp->token_index(), |
| 616 comp->try_index(), | 616 comp->try_index(), |
| 617 operator_name, | 617 operator_name, |
| 618 kNumberOfArguments, | 618 kNumberOfArguments, |
| 619 kNoArgumentNames, | 619 kNoArgumentNames, |
| 620 kNumArgumentsChecked); | 620 kNumArgumentsChecked); |
| 621 __ Bind(&done); | 621 __ Bind(&done); |
| 622 } | 622 } |
| 623 | 623 |
| 624 | 624 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 731 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 731 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| 732 | 732 |
| 733 // Insert a copy of the third (last) argument under the arguments. | 733 // Insert a copy of the third (last) argument under the arguments. |
| 734 __ popq(RAX); // Value. | 734 __ popq(RAX); // Value. |
| 735 __ popq(RBX); // Index. | 735 __ popq(RBX); // Index. |
| 736 __ popq(RCX); // Receiver. | 736 __ popq(RCX); // Receiver. |
| 737 __ pushq(RAX); | 737 __ pushq(RAX); |
| 738 __ pushq(RCX); | 738 __ pushq(RCX); |
| 739 __ pushq(RBX); | 739 __ pushq(RBX); |
| 740 __ pushq(RAX); | 740 __ pushq(RAX); |
| 741 EmitInstanceCall(comp->node_id(), | 741 EmitInstanceCall(comp->cid(), |
| 742 comp->token_index(), | 742 comp->token_index(), |
| 743 comp->try_index(), | 743 comp->try_index(), |
| 744 function_name, | 744 function_name, |
| 745 3, | 745 3, |
| 746 Array::ZoneHandle(), | 746 Array::ZoneHandle(), |
| 747 1); | 747 1); |
| 748 __ popq(RAX); | 748 __ popq(RAX); |
| 749 } | 749 } |
| 750 | 750 |
| 751 | 751 |
| 752 void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { | 752 void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { |
| 753 // Preserve the second argument under the arguments as the result of the | 753 // Preserve the second argument under the arguments as the result of the |
| 754 // computation, then call the setter. | 754 // computation, then call the setter. |
| 755 const String& function_name = | 755 const String& function_name = |
| 756 String::ZoneHandle(Field::SetterSymbol(comp->field_name())); | 756 String::ZoneHandle(Field::SetterSymbol(comp->field_name())); |
| 757 | 757 |
| 758 // Insert a copy of the second (last) argument under the arguments. | 758 // Insert a copy of the second (last) argument under the arguments. |
| 759 __ popq(RAX); // Value. | 759 __ popq(RAX); // Value. |
| 760 __ popq(RBX); // Receiver. | 760 __ popq(RBX); // Receiver. |
| 761 __ pushq(RAX); | 761 __ pushq(RAX); |
| 762 __ pushq(RBX); | 762 __ pushq(RBX); |
| 763 __ pushq(RAX); | 763 __ pushq(RAX); |
| 764 EmitInstanceCall(comp->node_id(), | 764 EmitInstanceCall(comp->cid(), |
| 765 comp->token_index(), | 765 comp->token_index(), |
| 766 comp->try_index(), | 766 comp->try_index(), |
| 767 function_name, | 767 function_name, |
| 768 2, | 768 2, |
| 769 Array::ZoneHandle(), | 769 Array::ZoneHandle(), |
| 770 1); | 770 1); |
| 771 __ popq(RAX); | 771 __ popq(RAX); |
| 772 } | 772 } |
| 773 | 773 |
| 774 | 774 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 804 // Optimize instanceof type test by adding inlined tests for: | 804 // Optimize instanceof type test by adding inlined tests for: |
| 805 // - NULL -> return false. | 805 // - NULL -> return false. |
| 806 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 806 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 807 // - Class equality (only if class is not parameterized). | 807 // - Class equality (only if class is not parameterized). |
| 808 // Inputs: | 808 // Inputs: |
| 809 // - RAX: object. | 809 // - RAX: object. |
| 810 // - RDX: optional instantiator type arguments. | 810 // - RDX: optional instantiator type arguments. |
| 811 // Destroys RCX and RDX. | 811 // Destroys RCX and RDX. |
| 812 // Returns: | 812 // Returns: |
| 813 // - true or false in RAX. | 813 // - true or false in RAX. |
| 814 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id, | 814 void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid, |
| 815 intptr_t token_index, | 815 intptr_t token_index, |
| 816 intptr_t try_index, | 816 intptr_t try_index, |
| 817 const AbstractType& type, | 817 const AbstractType& type, |
| 818 bool negate_result) { | 818 bool negate_result) { |
| 819 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 819 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 820 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 820 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 821 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 821 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 822 | 822 |
| 823 const Immediate raw_null = | 823 const Immediate raw_null = |
| 824 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 824 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 837 __ j(EQUAL, &is_not_instance); | 837 __ j(EQUAL, &is_not_instance); |
| 838 } | 838 } |
| 839 | 839 |
| 840 // Generate inline instanceof test. | 840 // Generate inline instanceof test. |
| 841 GenerateInlineInstanceof(type, &is_instance, &is_not_instance); | 841 GenerateInlineInstanceof(type, &is_instance, &is_not_instance); |
| 842 | 842 |
| 843 // Generate runtime call. | 843 // Generate runtime call. |
| 844 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 844 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 845 const Immediate location = | 845 const Immediate location = |
| 846 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 846 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); |
| 847 const Immediate node_id_as_smi = | 847 const Immediate cid_as_smi = |
| 848 Immediate(reinterpret_cast<int64_t>(Smi::New(node_id))); | 848 Immediate(reinterpret_cast<int64_t>(Smi::New(cid))); |
| 849 __ pushq(location); // Push the source location. | 849 __ pushq(location); // Push the source location. |
| 850 __ pushq(node_id_as_smi); | 850 __ pushq(cid_as_smi); |
| 851 __ pushq(RAX); // Push the instance. | 851 __ pushq(RAX); // Push the instance. |
| 852 __ PushObject(type); // Push the type. | 852 __ PushObject(type); // Push the type. |
| 853 if (!type.IsInstantiated()) { | 853 if (!type.IsInstantiated()) { |
| 854 __ pushq(RDX); // Instantiator type arguments. | 854 __ pushq(RDX); // Instantiator type arguments. |
| 855 } else { | 855 } else { |
| 856 __ pushq(raw_null); // Null instantiator. | 856 __ pushq(raw_null); // Null instantiator. |
| 857 } | 857 } |
| 858 GenerateCallRuntime(node_id, token_index, try_index, kInstanceofRuntimeEntry); | 858 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry); |
| 859 // Pop the two parameters supplied to the runtime entry. The result of the | 859 // Pop the two parameters supplied to the runtime entry. The result of the |
| 860 // instanceof runtime call will be left as the result of the operation. | 860 // instanceof runtime call will be left as the result of the operation. |
| 861 __ addq(RSP, Immediate(5 * kWordSize)); | 861 __ addq(RSP, Immediate(5 * kWordSize)); |
| 862 Label done; | 862 Label done; |
| 863 if (negate_result) { | 863 if (negate_result) { |
| 864 __ popq(RDX); | 864 __ popq(RDX); |
| 865 __ LoadObject(RAX, bool_true); | 865 __ LoadObject(RAX, bool_true); |
| 866 __ cmpq(RDX, RAX); | 866 __ cmpq(RDX, RAX); |
| 867 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 867 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 868 __ LoadObject(RAX, bool_false); | 868 __ LoadObject(RAX, bool_false); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 879 __ LoadObject(RAX, negate_result ? bool_false : bool_true); | 879 __ LoadObject(RAX, negate_result ? bool_false : bool_true); |
| 880 __ Bind(&done); | 880 __ Bind(&done); |
| 881 } | 881 } |
| 882 | 882 |
| 883 | 883 |
| 884 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { | 884 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { |
| 885 if (comp->type_arguments() != NULL) { | 885 if (comp->type_arguments() != NULL) { |
| 886 __ popq(RDX); | 886 __ popq(RDX); |
| 887 } | 887 } |
| 888 LoadValue(RAX, comp->value()); | 888 LoadValue(RAX, comp->value()); |
| 889 GenerateInstanceOf(comp->node_id(), | 889 GenerateInstanceOf(comp->cid(), |
| 890 comp->token_index(), | 890 comp->token_index(), |
| 891 comp->try_index(), | 891 comp->try_index(), |
| 892 comp->type(), | 892 comp->type(), |
| 893 comp->negate_result()); | 893 comp->negate_result()); |
| 894 } | 894 } |
| 895 | 895 |
| 896 | 896 |
| 897 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { | 897 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { |
| 898 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); | 898 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); |
| 899 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 899 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 985 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 986 arguments_length); | 986 arguments_length); |
| 987 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 987 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 988 __ Bind(&type_arguments_uninstantiated); | 988 __ Bind(&type_arguments_uninstantiated); |
| 989 } | 989 } |
| 990 // A runtime call to instantiate the type arguments is required before | 990 // A runtime call to instantiate the type arguments is required before |
| 991 // calling the factory. | 991 // calling the factory. |
| 992 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 992 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 993 __ PushObject(comp->type_arguments()); | 993 __ PushObject(comp->type_arguments()); |
| 994 __ pushq(RAX); // Push instantiator type arguments. | 994 __ pushq(RAX); // Push instantiator type arguments. |
| 995 GenerateCallRuntime(comp->node_id(), | 995 GenerateCallRuntime(comp->cid(), |
| 996 comp->token_index(), | 996 comp->token_index(), |
| 997 comp->try_index(), | 997 comp->try_index(), |
| 998 kInstantiateTypeArgumentsRuntimeEntry); | 998 kInstantiateTypeArgumentsRuntimeEntry); |
| 999 __ popq(RAX); // Pop instantiator type arguments. | 999 __ popq(RAX); // Pop instantiator type arguments. |
| 1000 __ popq(RAX); // Pop uninstantiated type arguments. | 1000 __ popq(RAX); // Pop uninstantiated type arguments. |
| 1001 __ popq(RAX); // Pop instantiated type arguments. | 1001 __ popq(RAX); // Pop instantiated type arguments. |
| 1002 __ Bind(&type_arguments_instantiated); | 1002 __ Bind(&type_arguments_instantiated); |
| 1003 // RAX: Instantiated type arguments. | 1003 // RAX: Instantiated type arguments. |
| 1004 } | 1004 } |
| 1005 | 1005 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 CTX); | 1117 CTX); |
| 1118 // Set new context as current context. | 1118 // Set new context as current context. |
| 1119 __ movq(CTX, RAX); | 1119 __ movq(CTX, RAX); |
| 1120 } | 1120 } |
| 1121 | 1121 |
| 1122 | 1122 |
| 1123 void FlowGraphCompiler::VisitCloneContext(CloneContextComp* comp) { | 1123 void FlowGraphCompiler::VisitCloneContext(CloneContextComp* comp) { |
| 1124 __ popq(RAX); // Get context value from stack. | 1124 __ popq(RAX); // Get context value from stack. |
| 1125 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1125 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1126 __ pushq(RAX); | 1126 __ pushq(RAX); |
| 1127 GenerateCallRuntime(comp->node_id(), | 1127 GenerateCallRuntime(comp->cid(), |
| 1128 comp->token_index(), | 1128 comp->token_index(), |
| 1129 comp->try_index(), | 1129 comp->try_index(), |
| 1130 kCloneContextRuntimeEntry); | 1130 kCloneContextRuntimeEntry); |
| 1131 __ popq(RAX); // Remove argument. | 1131 __ popq(RAX); // Remove argument. |
| 1132 __ popq(RAX); // Get result (cloned context). | 1132 __ popq(RAX); // Get result (cloned context). |
| 1133 } | 1133 } |
| 1134 | 1134 |
| 1135 | 1135 |
| 1136 // Restore stack and initialize the two exception variables: | 1136 // Restore stack and initialize the two exception variables: |
| 1137 // exception and stack trace variables. | 1137 // exception and stack trace variables. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 // return pattern with a call to the debug stub. | 1249 // return pattern with a call to the debug stub. |
| 1250 __ nop(1); | 1250 __ nop(1); |
| 1251 __ nop(1); | 1251 __ nop(1); |
| 1252 __ nop(1); | 1252 __ nop(1); |
| 1253 __ nop(1); | 1253 __ nop(1); |
| 1254 __ nop(1); | 1254 __ nop(1); |
| 1255 __ nop(1); | 1255 __ nop(1); |
| 1256 __ nop(1); | 1256 __ nop(1); |
| 1257 __ nop(1); | 1257 __ nop(1); |
| 1258 AddCurrentDescriptor(PcDescriptors::kReturn, | 1258 AddCurrentDescriptor(PcDescriptors::kReturn, |
| 1259 instr->node_id(), | 1259 instr->cid(), |
| 1260 instr->token_index(), | 1260 instr->token_index(), |
| 1261 CatchClauseNode::kInvalidTryIndex); // try-index. | 1261 CatchClauseNode::kInvalidTryIndex); // try-index. |
| 1262 } | 1262 } |
| 1263 | 1263 |
| 1264 | 1264 |
| 1265 void FlowGraphCompiler::VisitThrow(ThrowInstr* instr) { | 1265 void FlowGraphCompiler::VisitThrow(ThrowInstr* instr) { |
| 1266 LoadValue(RAX, instr->exception()); | 1266 LoadValue(RAX, instr->exception()); |
| 1267 __ pushq(RAX); | 1267 __ pushq(RAX); |
| 1268 GenerateCallRuntime(instr->node_id(), | 1268 GenerateCallRuntime(instr->cid(), |
| 1269 instr->token_index(), | 1269 instr->token_index(), |
| 1270 instr->try_index(), | 1270 instr->try_index(), |
| 1271 kThrowRuntimeEntry); | 1271 kThrowRuntimeEntry); |
| 1272 __ int3(); | 1272 __ int3(); |
| 1273 } | 1273 } |
| 1274 | 1274 |
| 1275 | 1275 |
| 1276 void FlowGraphCompiler::VisitReThrow(ReThrowInstr* instr) { | 1276 void FlowGraphCompiler::VisitReThrow(ReThrowInstr* instr) { |
| 1277 LoadValue(RAX, instr->exception()); | 1277 LoadValue(RAX, instr->exception()); |
| 1278 __ pushq(RAX); | 1278 __ pushq(RAX); |
| 1279 LoadValue(RAX, instr->stack_trace()); | 1279 LoadValue(RAX, instr->stack_trace()); |
| 1280 __ pushq(RAX); | 1280 __ pushq(RAX); |
| 1281 GenerateCallRuntime(instr->node_id(), | 1281 GenerateCallRuntime(instr->cid(), |
| 1282 instr->token_index(), | 1282 instr->token_index(), |
| 1283 instr->try_index(), | 1283 instr->try_index(), |
| 1284 kReThrowRuntimeEntry); | 1284 kReThrowRuntimeEntry); |
| 1285 __ int3(); | 1285 __ int3(); |
| 1286 } | 1286 } |
| 1287 | 1287 |
| 1288 | 1288 |
| 1289 | 1289 |
| 1290 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { | 1290 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { |
| 1291 // Determine if the true branch is fall through (!negated) or the false | 1291 // Determine if the true branch is fall through (!negated) or the false |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1659 // Infrastructure copied from class CodeGenerator. | 1659 // Infrastructure copied from class CodeGenerator. |
| 1660 void FlowGraphCompiler::GenerateCall(intptr_t token_index, | 1660 void FlowGraphCompiler::GenerateCall(intptr_t token_index, |
| 1661 intptr_t try_index, | 1661 intptr_t try_index, |
| 1662 const ExternalLabel* label, | 1662 const ExternalLabel* label, |
| 1663 PcDescriptors::Kind kind) { | 1663 PcDescriptors::Kind kind) { |
| 1664 __ call(label); | 1664 __ call(label); |
| 1665 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); | 1665 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); |
| 1666 } | 1666 } |
| 1667 | 1667 |
| 1668 | 1668 |
| 1669 void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id, | 1669 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, |
| 1670 intptr_t token_index, | 1670 intptr_t token_index, |
| 1671 intptr_t try_index, | 1671 intptr_t try_index, |
| 1672 const RuntimeEntry& entry) { | 1672 const RuntimeEntry& entry) { |
| 1673 __ CallRuntime(entry); | 1673 __ CallRuntime(entry); |
| 1674 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index, try_index); | 1674 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); |
| 1675 } | 1675 } |
| 1676 | 1676 |
| 1677 | 1677 |
| 1678 // Uses current pc position and try-index. | 1678 // Uses current pc position and try-index. |
| 1679 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, | 1679 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, |
| 1680 intptr_t node_id, | 1680 intptr_t cid, |
| 1681 intptr_t token_index, | 1681 intptr_t token_index, |
| 1682 intptr_t try_index) { | 1682 intptr_t try_index) { |
| 1683 pc_descriptors_list_->AddDescriptor(kind, | 1683 pc_descriptors_list_->AddDescriptor(kind, |
| 1684 assembler_->CodeSize(), | 1684 assembler_->CodeSize(), |
| 1685 node_id, | 1685 cid, |
| 1686 token_index, | 1686 token_index, |
| 1687 try_index); | 1687 try_index); |
| 1688 } | 1688 } |
| 1689 | 1689 |
| 1690 | 1690 |
| 1691 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { | 1691 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { |
| 1692 ASSERT(pc_descriptors_list_ != NULL); | 1692 ASSERT(pc_descriptors_list_ != NULL); |
| 1693 const PcDescriptors& descriptors = PcDescriptors::Handle( | 1693 const PcDescriptors& descriptors = PcDescriptors::Handle( |
| 1694 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); | 1694 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); |
| 1695 descriptors.Verify(parsed_function_.function().is_optimizable()); | 1695 descriptors.Verify(parsed_function_.function().is_optimizable()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1714 ASSERT(exception_handlers_list_ != NULL); | 1714 ASSERT(exception_handlers_list_ != NULL); |
| 1715 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1715 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 1716 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1716 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 1717 code.set_exception_handlers(handlers); | 1717 code.set_exception_handlers(handlers); |
| 1718 } | 1718 } |
| 1719 | 1719 |
| 1720 | 1720 |
| 1721 } // namespace dart | 1721 } // namespace dart |
| 1722 | 1722 |
| 1723 #endif // defined TARGET_ARCH_X64 | 1723 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |