| 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/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 if (num_opt_params == 0) { | 417 if (num_opt_params == 0) { |
| 418 __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params))); | 418 __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params))); |
| 419 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 419 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 420 } else { | 420 } else { |
| 421 __ subq(RAX, Immediate(Smi::RawValue(num_fixed_params))); | 421 __ subq(RAX, Immediate(Smi::RawValue(num_fixed_params))); |
| 422 __ cmpq(RAX, Immediate(Smi::RawValue(num_opt_params))); | 422 __ cmpq(RAX, Immediate(Smi::RawValue(num_opt_params))); |
| 423 __ j(BELOW_EQUAL, &argc_in_range, Assembler::kNearJump); | 423 __ j(BELOW_EQUAL, &argc_in_range, Assembler::kNearJump); |
| 424 } | 424 } |
| 425 if (function.IsClosureFunction()) { | 425 if (function.IsClosureFunction()) { |
| 426 GenerateCallRuntime(AstNode::kNoId, | 426 GenerateCallRuntime(AstNode::kNoId, |
| 427 function.token_index(), | 427 0, |
| 428 kClosureArgumentMismatchRuntimeEntry); | 428 kClosureArgumentMismatchRuntimeEntry); |
| 429 } else { | 429 } else { |
| 430 __ Stop("Wrong number of arguments"); | 430 __ Stop("Wrong number of arguments"); |
| 431 } | 431 } |
| 432 __ Bind(&argc_in_range); | 432 __ Bind(&argc_in_range); |
| 433 } | 433 } |
| 434 } else { | 434 } else { |
| 435 ASSERT(first_param_index == -1); | 435 ASSERT(first_param_index == -1); |
| 436 // Copy positional arguments. | 436 // Copy positional arguments. |
| 437 // Check that no fewer than num_fixed_params positional arguments are passed | 437 // Check that no fewer than num_fixed_params positional arguments are passed |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 delete[] opt_param; | 542 delete[] opt_param; |
| 543 delete[] opt_param_position; | 543 delete[] opt_param_position; |
| 544 // Check that RDI now points to the null terminator in the array descriptor. | 544 // Check that RDI now points to the null terminator in the array descriptor. |
| 545 Label all_arguments_processed; | 545 Label all_arguments_processed; |
| 546 __ cmpq(Address(RDI, 0), raw_null); | 546 __ cmpq(Address(RDI, 0), raw_null); |
| 547 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 547 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 548 | 548 |
| 549 __ Bind(&wrong_num_arguments); | 549 __ Bind(&wrong_num_arguments); |
| 550 if (function.IsClosureFunction()) { | 550 if (function.IsClosureFunction()) { |
| 551 GenerateCallRuntime(AstNode::kNoId, | 551 GenerateCallRuntime(AstNode::kNoId, |
| 552 function.token_index(), | 552 0, |
| 553 kClosureArgumentMismatchRuntimeEntry); | 553 kClosureArgumentMismatchRuntimeEntry); |
| 554 } else { | 554 } else { |
| 555 // Invoke noSuchMethod function. | 555 // Invoke noSuchMethod function. |
| 556 const int kNumArgsChecked = 1; | 556 const int kNumArgsChecked = 1; |
| 557 ICData& ic_data = ICData::ZoneHandle(); | 557 ICData& ic_data = ICData::ZoneHandle(); |
| 558 ic_data = ICData::New(parsed_function().function(), | 558 ic_data = ICData::New(parsed_function().function(), |
| 559 String::Handle(function.name()), | 559 String::Handle(function.name()), |
| 560 AstNode::kNoId, | 560 AstNode::kNoId, |
| 561 kNumArgsChecked); | 561 kNumArgsChecked); |
| 562 __ LoadObject(RBX, ic_data); | 562 __ LoadObject(RBX, ic_data); |
| 563 // RBP : points to previous frame pointer. | 563 // RBP : points to previous frame pointer. |
| 564 // RBP + 8 : points to return address. | 564 // RBP + 8 : points to return address. |
| 565 // RBP + 16 : address of last argument (arg n-1). | 565 // RBP + 16 : address of last argument (arg n-1). |
| 566 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). | 566 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 567 // RBX : ic-data. | 567 // RBX : ic-data. |
| 568 // R10 : arguments descriptor array. | 568 // R10 : arguments descriptor array. |
| 569 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 569 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 570 } | 570 } |
| 571 | 571 |
| 572 if (FLAG_trace_functions) { | 572 if (FLAG_trace_functions) { |
| 573 __ pushq(RAX); // Preserve result. | 573 __ pushq(RAX); // Preserve result. |
| 574 __ PushObject(function); | 574 __ PushObject(Function::ZoneHandle(function.raw())); |
| 575 GenerateCallRuntime(AstNode::kNoId, | 575 GenerateCallRuntime(AstNode::kNoId, |
| 576 0, | 576 0, |
| 577 kTraceFunctionExitRuntimeEntry); | 577 kTraceFunctionExitRuntimeEntry); |
| 578 __ popq(RAX); // Remove argument. | 578 __ popq(RAX); // Remove argument. |
| 579 __ popq(RAX); // Restore result. | 579 __ popq(RAX); // Restore result. |
| 580 } | 580 } |
| 581 __ LeaveFrame(); | 581 __ LeaveFrame(); |
| 582 __ ret(); | 582 __ ret(); |
| 583 | 583 |
| 584 __ Bind(&all_arguments_processed); | 584 __ Bind(&all_arguments_processed); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 612 } | 612 } |
| 613 __ movq(Address(RBP, index * kWordSize), RAX); | 613 __ movq(Address(RBP, index * kWordSize), RAX); |
| 614 } | 614 } |
| 615 | 615 |
| 616 // Generate stack overflow check. | 616 // Generate stack overflow check. |
| 617 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); | 617 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
| 618 __ cmpq(RSP, Address(TMP, 0)); | 618 __ cmpq(RSP, Address(TMP, 0)); |
| 619 Label no_stack_overflow; | 619 Label no_stack_overflow; |
| 620 __ j(ABOVE, &no_stack_overflow); | 620 __ j(ABOVE, &no_stack_overflow); |
| 621 GenerateCallRuntime(AstNode::kNoId, | 621 GenerateCallRuntime(AstNode::kNoId, |
| 622 function.token_index(), | 622 0, |
| 623 kStackOverflowRuntimeEntry); | 623 kStackOverflowRuntimeEntry); |
| 624 __ Bind(&no_stack_overflow); | 624 __ Bind(&no_stack_overflow); |
| 625 } | 625 } |
| 626 | 626 |
| 627 | 627 |
| 628 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { | 628 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { |
| 629 // Unchain the context(s) up to context level 0. | 629 // Unchain the context(s) up to context level 0. |
| 630 int context_level = state()->context_level(); | 630 int context_level = state()->context_level(); |
| 631 ASSERT(context_level >= 0); | 631 ASSERT(context_level >= 0); |
| 632 while (context_level-- > 0) { | 632 while (context_level-- > 0) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 __ nop(1); | 664 __ nop(1); |
| 665 __ nop(1); | 665 __ nop(1); |
| 666 __ nop(1); | 666 __ nop(1); |
| 667 __ nop(1); | 667 __ nop(1); |
| 668 __ nop(1); | 668 __ nop(1); |
| 669 __ nop(1); | 669 __ nop(1); |
| 670 AddCurrentDescriptor(PcDescriptors::kReturn, | 670 AddCurrentDescriptor(PcDescriptors::kReturn, |
| 671 node->id(), | 671 node->id(), |
| 672 node->token_index()); | 672 node->token_index()); |
| 673 | 673 |
| 674 | |
| 675 #ifdef DEBUG | 674 #ifdef DEBUG |
| 676 __ Bind(&wrong_stack); | 675 __ Bind(&wrong_stack); |
| 677 __ Stop("Exit stack size does not match the entry stack size."); | 676 __ Stop("Exit stack size does not match the entry stack size."); |
| 678 #endif // DEBUG. | 677 #endif // DEBUG. |
| 679 } | 678 } |
| 680 | 679 |
| 681 | 680 |
| 682 void CodeGenerator::VisitReturnNode(ReturnNode* node) { | 681 void CodeGenerator::VisitReturnNode(ReturnNode* node) { |
| 683 ASSERT(!IsResultNeeded(node)); | 682 ASSERT(!IsResultNeeded(node)); |
| 684 ASSERT(node->value() != NULL); | 683 ASSERT(node->value() != NULL); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 } | 789 } |
| 791 | 790 |
| 792 | 791 |
| 793 void CodeGenerator::VisitPrimaryNode(PrimaryNode* node) { | 792 void CodeGenerator::VisitPrimaryNode(PrimaryNode* node) { |
| 794 // PrimaryNodes are temporary during parsing. | 793 // PrimaryNodes are temporary during parsing. |
| 795 UNREACHABLE(); | 794 UNREACHABLE(); |
| 796 } | 795 } |
| 797 | 796 |
| 798 | 797 |
| 799 void CodeGenerator::VisitCloneContextNode(CloneContextNode *node) { | 798 void CodeGenerator::VisitCloneContextNode(CloneContextNode *node) { |
| 800 const Context& result = Context::ZoneHandle(); | 799 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 801 __ PushObject(result); | |
| 802 __ pushq(CTX); | 800 __ pushq(CTX); |
| 803 GenerateCallRuntime(node->id(), | 801 GenerateCallRuntime(node->id(), |
| 804 node->token_index(), kCloneContextRuntimeEntry); | 802 node->token_index(), kCloneContextRuntimeEntry); |
| 805 __ popq(RAX); | 803 __ popq(RAX); |
| 806 __ popq(CTX); // result: cloned context. Set as current context. | 804 __ popq(CTX); // result: cloned context. Set as current context. |
| 807 } | 805 } |
| 808 | 806 |
| 809 | 807 |
| 810 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { | 808 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { |
| 811 CodeGeneratorState codegen_state(this); | 809 CodeGeneratorState codegen_state(this); |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 // - Class equality (only if class is not parameterized). | 1291 // - Class equality (only if class is not parameterized). |
| 1294 // Inputs: | 1292 // Inputs: |
| 1295 // - RAX: object. | 1293 // - RAX: object. |
| 1296 // Destroys RCX. | 1294 // Destroys RCX. |
| 1297 // Returns: | 1295 // Returns: |
| 1298 // - true or false on stack. | 1296 // - true or false on stack. |
| 1299 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, | 1297 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, |
| 1300 intptr_t token_index, | 1298 intptr_t token_index, |
| 1301 const AbstractType& type, | 1299 const AbstractType& type, |
| 1302 bool negate_result) { | 1300 bool negate_result) { |
| 1303 ASSERT(type.IsFinalized()); | 1301 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 1304 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1302 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 1305 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1303 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 1306 | 1304 |
| 1307 // All instances are of a subtype of the Object type. | 1305 // All instances are of a subtype of the Object type. |
| 1308 const Type& object_type = | 1306 const Type& object_type = |
| 1309 Type::Handle(Isolate::Current()->object_store()->object_type()); | 1307 Type::Handle(Isolate::Current()->object_store()->object_type()); |
| 1310 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { | 1308 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { |
| 1311 __ PushObject(negate_result ? bool_false : bool_true); | 1309 __ PushObject(negate_result ? bool_false : bool_true); |
| 1312 return; | 1310 return; |
| 1313 } | 1311 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 Label runtime_call; | 1399 Label runtime_call; |
| 1402 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1400 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1403 __ CompareObject(RCX, *compare_class); | 1401 __ CompareObject(RCX, *compare_class); |
| 1404 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); | 1402 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); |
| 1405 __ PushObject(negate_result ? bool_false : bool_true); | 1403 __ PushObject(negate_result ? bool_false : bool_true); |
| 1406 __ jmp(&done, Assembler::kNearJump); | 1404 __ jmp(&done, Assembler::kNearJump); |
| 1407 __ Bind(&runtime_call); | 1405 __ Bind(&runtime_call); |
| 1408 } | 1406 } |
| 1409 } | 1407 } |
| 1410 } | 1408 } |
| 1411 const Object& result = Object::ZoneHandle(); | 1409 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1412 __ PushObject(result); // Make room for the result of the runtime call. | |
| 1413 __ pushq(RAX); // Push the instance. | 1410 __ pushq(RAX); // Push the instance. |
| 1414 __ PushObject(type); // Push the type. | 1411 __ PushObject(type); // Push the type. |
| 1415 if (!type.IsInstantiated()) { | 1412 if (!type.IsInstantiated()) { |
| 1416 GenerateInstantiatorTypeArguments(token_index); | 1413 GenerateInstantiatorTypeArguments(token_index); |
| 1417 } else { | 1414 } else { |
| 1418 __ pushq(raw_null); // Null instantiator. | 1415 __ pushq(raw_null); // Null instantiator. |
| 1419 } | 1416 } |
| 1420 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); | 1417 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); |
| 1421 // Pop the two parameters supplied to the runtime entry. The result of the | 1418 // Pop the two parameters supplied to the runtime entry. The result of the |
| 1422 // instanceof runtime call will be left as the result of the operation. | 1419 // instanceof runtime call will be left as the result of the operation. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1455 // - object in RAX for successful assignable check (or throws TypeError). | 1452 // - object in RAX for successful assignable check (or throws TypeError). |
| 1456 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, | 1453 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, |
| 1457 intptr_t token_index, | 1454 intptr_t token_index, |
| 1458 const AbstractType& dst_type, | 1455 const AbstractType& dst_type, |
| 1459 const String& dst_name) { | 1456 const String& dst_name) { |
| 1460 ASSERT(FLAG_enable_type_checks); | 1457 ASSERT(FLAG_enable_type_checks); |
| 1461 ASSERT(token_index >= 0); | 1458 ASSERT(token_index >= 0); |
| 1462 ASSERT(!dst_type.IsNull()); | 1459 ASSERT(!dst_type.IsNull()); |
| 1463 ASSERT(dst_type.IsFinalized()); | 1460 ASSERT(dst_type.IsFinalized()); |
| 1464 | 1461 |
| 1462 // Generate throw new TypeError() if the type is malformed. |
| 1463 if (dst_type.IsMalformed()) { |
| 1464 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 1465 const String& error_message = String::ZoneHandle( |
| 1466 String::NewSymbol(error.ToErrorCString())); |
| 1467 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1468 const Immediate location = |
| 1469 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); |
| 1470 __ pushq(location); // Push the source location. |
| 1471 __ pushq(RAX); // Push the source object. |
| 1472 __ PushObject(error_message); |
| 1473 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry); |
| 1474 // We should never return here. |
| 1475 __ int3(); |
| 1476 return; |
| 1477 } |
| 1478 |
| 1465 // Any expression is assignable to the Dynamic type and to the Object type. | 1479 // Any expression is assignable to the Dynamic type and to the Object type. |
| 1466 // Skip the test. | 1480 // Skip the test. |
| 1467 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { | 1481 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { |
| 1468 return; | 1482 return; |
| 1469 } | 1483 } |
| 1470 | 1484 |
| 1471 // It is a compile-time error to explicitly return a value (including null) | 1485 // It is a compile-time error to explicitly return a value (including null) |
| 1472 // from a void function. However, functions that do not explicitly return a | 1486 // from a void function. However, functions that do not explicitly return a |
| 1473 // value, implicitly return null. This includes void functions. Therefore, we | 1487 // value, implicitly return null. This includes void functions. Therefore, we |
| 1474 // skip the type test here and trust the parser to only return null in void | 1488 // skip the type test here and trust the parser to only return null in void |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1576 } else if (dst_type.IsFunctionInterface()) { | 1590 } else if (dst_type.IsFunctionInterface()) { |
| 1577 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1591 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1578 __ movq(RCX, FieldAddress(RCX, Class::signature_function_offset())); | 1592 __ movq(RCX, FieldAddress(RCX, Class::signature_function_offset())); |
| 1579 __ cmpq(RCX, raw_null); | 1593 __ cmpq(RCX, raw_null); |
| 1580 __ j(NOT_EQUAL, &done); | 1594 __ j(NOT_EQUAL, &done); |
| 1581 } | 1595 } |
| 1582 } | 1596 } |
| 1583 } | 1597 } |
| 1584 } | 1598 } |
| 1585 __ Bind(&runtime_call); | 1599 __ Bind(&runtime_call); |
| 1586 const Object& result = Object::ZoneHandle(); | 1600 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1587 __ PushObject(result); // Make room for the result of the runtime call. | |
| 1588 const Immediate location = | 1601 const Immediate location = |
| 1589 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 1602 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); |
| 1590 __ pushq(location); // Push the source location. | 1603 __ pushq(location); // Push the source location. |
| 1591 __ pushq(RAX); // Push the source object. | 1604 __ pushq(RAX); // Push the source object. |
| 1592 __ PushObject(dst_type); // Push the type of the destination. | 1605 __ PushObject(dst_type); // Push the type of the destination. |
| 1593 if (!dst_type.IsInstantiated()) { | 1606 if (!dst_type.IsInstantiated()) { |
| 1594 GenerateInstantiatorTypeArguments(token_index); | 1607 GenerateInstantiatorTypeArguments(token_index); |
| 1595 } else { | 1608 } else { |
| 1596 __ pushq(raw_null); // Null instantiator. | 1609 __ pushq(raw_null); // Null instantiator. |
| 1597 } | 1610 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 // This check should pass if the receiver's class implements the interface | 1656 // This check should pass if the receiver's class implements the interface |
| 1644 // 'bool'. Check only class 'Bool' since it is the only legal implementation | 1657 // 'bool'. Check only class 'Bool' since it is the only legal implementation |
| 1645 // of the interface 'bool'. | 1658 // of the interface 'bool'. |
| 1646 const Class& bool_class = | 1659 const Class& bool_class = |
| 1647 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); | 1660 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); |
| 1648 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1661 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1649 __ CompareObject(RCX, bool_class); | 1662 __ CompareObject(RCX, bool_class); |
| 1650 __ j(EQUAL, &done, Assembler::kNearJump); | 1663 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1651 | 1664 |
| 1652 __ Bind(&runtime_call); | 1665 __ Bind(&runtime_call); |
| 1653 const Object& result = Object::ZoneHandle(); | |
| 1654 __ PushObject(result); // Make room for the result of the runtime call. | |
| 1655 const Immediate location = | 1666 const Immediate location = |
| 1656 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 1667 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); |
| 1657 __ pushq(location); // Push the source location. | 1668 __ pushq(location); // Push the source location. |
| 1658 __ pushq(RAX); // Push the source object. | 1669 __ pushq(RAX); // Push the source object. |
| 1659 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); | 1670 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); |
| 1660 // Pop the parameters supplied to the runtime entry. The result of the | 1671 // We should never return here. |
| 1661 // type check runtime call is the checked value. | 1672 __ int3(); |
| 1662 __ addq(RSP, Immediate(3 * kWordSize)); | |
| 1663 | 1673 |
| 1664 __ Bind(&done); | 1674 __ Bind(&done); |
| 1665 } | 1675 } |
| 1666 | 1676 |
| 1667 | 1677 |
| 1668 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { | 1678 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { |
| 1669 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1679 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 1670 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1680 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 1671 node->left()->Visit(this); | 1681 node->left()->Visit(this); |
| 1672 | 1682 |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2091 // Could not concatenate at compile time, generate a call to | 2101 // Could not concatenate at compile time, generate a call to |
| 2092 // interpolation function. | 2102 // interpolation function. |
| 2093 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); | 2103 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); |
| 2094 interpol_arg->Add(node->values()); | 2104 interpol_arg->Add(node->values()); |
| 2095 node->values()->Visit(this); | 2105 node->values()->Visit(this); |
| 2096 __ LoadObject(RBX, interpol_func); | 2106 __ LoadObject(RBX, interpol_func); |
| 2097 __ LoadObject(R10, ArgumentsDescriptor(interpol_arg->length(), | 2107 __ LoadObject(R10, ArgumentsDescriptor(interpol_arg->length(), |
| 2098 interpol_arg->names())); | 2108 interpol_arg->names())); |
| 2099 GenerateCall(node->token_index(), | 2109 GenerateCall(node->token_index(), |
| 2100 &StubCode::CallStaticFunctionLabel(), | 2110 &StubCode::CallStaticFunctionLabel(), |
| 2101 PcDescriptors::kOther); | 2111 PcDescriptors::kFuncCall); |
| 2102 __ addq(RSP, Immediate(interpol_arg->length() * kWordSize)); | 2112 __ addq(RSP, Immediate(interpol_arg->length() * kWordSize)); |
| 2103 // Result is in RAX. | 2113 // Result is in RAX. |
| 2104 if (IsResultNeeded(node)) { | 2114 if (IsResultNeeded(node)) { |
| 2105 __ pushq(RAX); | 2115 __ pushq(RAX); |
| 2106 } | 2116 } |
| 2107 } | 2117 } |
| 2108 | 2118 |
| 2109 | 2119 |
| 2110 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { | 2120 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { |
| 2111 const int number_of_arguments = node->arguments()->length() + 1; | 2121 const int number_of_arguments = node->arguments()->length() + 1; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2178 // Pushes the type arguments of the instantiator on the stack. | 2188 // Pushes the type arguments of the instantiator on the stack. |
| 2179 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { | 2189 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { |
| 2180 const Class& instantiator_class = Class::Handle( | 2190 const Class& instantiator_class = Class::Handle( |
| 2181 parsed_function().function().owner()); | 2191 parsed_function().function().owner()); |
| 2182 if (instantiator_class.NumTypeParameters() == 0) { | 2192 if (instantiator_class.NumTypeParameters() == 0) { |
| 2183 // The type arguments are compile time constants. | 2193 // The type arguments are compile time constants. |
| 2184 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); | 2194 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); |
| 2185 // TODO(regis): Temporary type should be allocated in new gen heap. | 2195 // TODO(regis): Temporary type should be allocated in new gen heap. |
| 2186 Type& type = Type::Handle( | 2196 Type& type = Type::Handle( |
| 2187 Type::New(instantiator_class, type_arguments, token_index)); | 2197 Type::New(instantiator_class, type_arguments, token_index)); |
| 2188 type ^= ClassFinalizer::FinalizeType(instantiator_class, type); | 2198 type ^= ClassFinalizer::FinalizeType( |
| 2199 instantiator_class, type, ClassFinalizer::kFinalizeWellFormed); |
| 2189 type_arguments = type.arguments(); | 2200 type_arguments = type.arguments(); |
| 2190 __ PushObject(type_arguments); | 2201 __ PushObject(type_arguments); |
| 2191 } else { | 2202 } else { |
| 2192 ASSERT(parsed_function().instantiator() != NULL); | 2203 ASSERT(parsed_function().instantiator() != NULL); |
| 2193 parsed_function().instantiator()->Visit(this); | 2204 parsed_function().instantiator()->Visit(this); |
| 2194 Function& outer_function = | 2205 Function& outer_function = |
| 2195 Function::Handle(parsed_function().function().raw()); | 2206 Function::Handle(parsed_function().function().raw()); |
| 2196 while (outer_function.IsLocalFunction()) { | 2207 while (outer_function.IsLocalFunction()) { |
| 2197 outer_function = outer_function.parent_function(); | 2208 outer_function = outer_function.parent_function(); |
| 2198 } | 2209 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2261 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 2272 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 2262 Smi::New(node->type_arguments().Length()))); | 2273 Smi::New(node->type_arguments().Length()))); |
| 2263 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 2274 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 2264 arguments_length); | 2275 arguments_length); |
| 2265 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2276 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2266 } | 2277 } |
| 2267 __ Bind(&type_arguments_uninstantiated); | 2278 __ Bind(&type_arguments_uninstantiated); |
| 2268 if (node->constructor().IsFactory()) { | 2279 if (node->constructor().IsFactory()) { |
| 2269 // A runtime call to instantiate the type arguments is required before | 2280 // A runtime call to instantiate the type arguments is required before |
| 2270 // calling the factory. | 2281 // calling the factory. |
| 2271 const Object& result = Object::ZoneHandle(); | 2282 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2272 __ PushObject(result); // Make room for the result of the runtime call. | |
| 2273 __ PushObject(node->type_arguments()); | 2283 __ PushObject(node->type_arguments()); |
| 2274 __ pushq(RAX); // Push instantiator type arguments. | 2284 __ pushq(RAX); // Push instantiator type arguments. |
| 2275 GenerateCallRuntime(node->id(), | 2285 GenerateCallRuntime(node->id(), |
| 2276 node->token_index(), | 2286 node->token_index(), |
| 2277 kInstantiateTypeArgumentsRuntimeEntry); | 2287 kInstantiateTypeArgumentsRuntimeEntry); |
| 2278 __ popq(RAX); // Pop instantiator type arguments. | 2288 __ popq(RAX); // Pop instantiator type arguments. |
| 2279 __ popq(RAX); // Pop uninstantiated type arguments. | 2289 __ popq(RAX); // Pop uninstantiated type arguments. |
| 2280 __ popq(RAX); // Pop instantiated type arguments. | 2290 __ popq(RAX); // Pop instantiated type arguments. |
| 2281 __ Bind(&type_arguments_instantiated); | 2291 __ Bind(&type_arguments_instantiated); |
| 2282 __ pushq(RAX); // Instantiated type arguments. | 2292 __ pushq(RAX); // Instantiated type arguments. |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2596 } | 2606 } |
| 2597 | 2607 |
| 2598 // Generate code for the finally block if one exists. | 2608 // Generate code for the finally block if one exists. |
| 2599 if (node->finally_block() != NULL) { | 2609 if (node->finally_block() != NULL) { |
| 2600 node->finally_block()->Visit(this); | 2610 node->finally_block()->Visit(this); |
| 2601 } | 2611 } |
| 2602 } | 2612 } |
| 2603 | 2613 |
| 2604 | 2614 |
| 2605 void CodeGenerator::VisitThrowNode(ThrowNode* node) { | 2615 void CodeGenerator::VisitThrowNode(ThrowNode* node) { |
| 2606 const Object& result = Object::ZoneHandle(); | |
| 2607 node->exception()->Visit(this); | 2616 node->exception()->Visit(this); |
| 2608 __ popq(RAX); // Exception object is now in RAX. | 2617 // Exception object is on TOS. |
| 2609 if (node->stacktrace() != NULL) { | 2618 if (node->stacktrace() != NULL) { |
| 2610 __ PushObject(result); // Make room for the result of the runtime call. | |
| 2611 __ pushq(RAX); // Push the exception object. | |
| 2612 node->stacktrace()->Visit(this); | 2619 node->stacktrace()->Visit(this); |
| 2613 GenerateCallRuntime(node->id(), node->token_index(), kReThrowRuntimeEntry); | 2620 GenerateCallRuntime(node->id(), node->token_index(), kReThrowRuntimeEntry); |
| 2614 } else { | 2621 } else { |
| 2615 __ PushObject(result); // Make room for the result of the runtime call. | |
| 2616 __ pushq(RAX); // Push the exception object. | |
| 2617 GenerateCallRuntime(node->id(), node->token_index(), kThrowRuntimeEntry); | 2622 GenerateCallRuntime(node->id(), node->token_index(), kThrowRuntimeEntry); |
| 2618 } | 2623 } |
| 2619 // We should never return here. | 2624 // We should never return here. |
| 2620 __ int3(); | 2625 __ int3(); |
| 2621 } | 2626 } |
| 2622 | 2627 |
| 2623 | 2628 |
| 2624 void CodeGenerator::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 2629 void CodeGenerator::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
| 2625 int try_index = state()->try_index(); | 2630 int try_index = state()->try_index(); |
| 2626 if (try_index >= 0) { | 2631 if (try_index >= 0) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2684 const Error& error = Error::Handle( | 2689 const Error& error = Error::Handle( |
| 2685 Parser::FormatError(script, token_index, "Error", format, args)); | 2690 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2686 va_end(args); | 2691 va_end(args); |
| 2687 Isolate::Current()->long_jump_base()->Jump(1, error); | 2692 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2688 UNREACHABLE(); | 2693 UNREACHABLE(); |
| 2689 } | 2694 } |
| 2690 | 2695 |
| 2691 } // namespace dart | 2696 } // namespace dart |
| 2692 | 2697 |
| 2693 #endif // defined TARGET_ARCH_X64 | 2698 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |