| 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 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 } | 657 } |
| 658 | 658 |
| 659 | 659 |
| 660 void FlowGraphCompiler::VisitNativeCall(NativeCallComp* comp) { | 660 void FlowGraphCompiler::VisitNativeCall(NativeCallComp* comp) { |
| 661 // Push the result place holder initialized to NULL. | 661 // Push the result place holder initialized to NULL. |
| 662 __ PushObject(Object::ZoneHandle()); | 662 __ PushObject(Object::ZoneHandle()); |
| 663 // Pass a pointer to the first argument in RAX. | 663 // Pass a pointer to the first argument in RAX. |
| 664 if (!comp->has_optional_parameters()) { | 664 if (!comp->has_optional_parameters()) { |
| 665 __ leaq(RAX, Address(RBP, (1 + comp->argument_count()) * kWordSize)); | 665 __ leaq(RAX, Address(RBP, (1 + comp->argument_count()) * kWordSize)); |
| 666 } else { | 666 } else { |
| 667 __ leaq(RAX, Address(RBP, -1 * kWordSize)); | 667 __ leaq(RAX, |
| 668 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 668 } | 669 } |
| 669 __ movq(RBX, Immediate(reinterpret_cast<uword>(comp->native_c_function()))); | 670 __ movq(RBX, Immediate(reinterpret_cast<uword>(comp->native_c_function()))); |
| 670 __ movq(R10, Immediate(comp->argument_count())); | 671 __ movq(R10, Immediate(comp->argument_count())); |
| 671 GenerateCall(comp->token_index(), | 672 GenerateCall(comp->token_index(), |
| 672 comp->try_index(), | 673 comp->try_index(), |
| 673 &StubCode::CallNativeCFunctionLabel(), | 674 &StubCode::CallNativeCFunctionLabel(), |
| 674 PcDescriptors::kOther); | 675 PcDescriptors::kOther); |
| 675 __ popq(RAX); | 676 __ popq(RAX); |
| 676 } | 677 } |
| 677 | 678 |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 } | 1128 } |
| 1128 | 1129 |
| 1129 | 1130 |
| 1130 // Restore stack and initialize the two exception variables: | 1131 // Restore stack and initialize the two exception variables: |
| 1131 // exception and stack trace variables. | 1132 // exception and stack trace variables. |
| 1132 void FlowGraphCompiler::VisitCatchEntry(CatchEntryComp* comp) { | 1133 void FlowGraphCompiler::VisitCatchEntry(CatchEntryComp* comp) { |
| 1133 // Restore RSP from RBP as we are coming from a throw and the code for | 1134 // Restore RSP from RBP as we are coming from a throw and the code for |
| 1134 // popping arguments has not been run. | 1135 // popping arguments has not been run. |
| 1135 const intptr_t locals_space_size = StackSize() * kWordSize; | 1136 const intptr_t locals_space_size = StackSize() * kWordSize; |
| 1136 ASSERT(locals_space_size >= 0); | 1137 ASSERT(locals_space_size >= 0); |
| 1137 if (locals_space_size == 0) { | 1138 intptr_t offset_size = -locals_space_size + kLocalsOffsetFromFP; |
| 1138 __ movq(RSP, RBP); | 1139 __ leaq(RSP, Address(RBP, offset_size)); |
| 1139 } else { | |
| 1140 __ leaq(RSP, Address(RBP, -locals_space_size)); | |
| 1141 } | |
| 1142 | 1140 |
| 1143 ASSERT(!comp->exception_var().is_captured()); | 1141 ASSERT(!comp->exception_var().is_captured()); |
| 1144 ASSERT(!comp->stacktrace_var().is_captured()); | 1142 ASSERT(!comp->stacktrace_var().is_captured()); |
| 1145 __ movq(Address(RBP, comp->exception_var().index() * kWordSize), | 1143 __ movq(Address(RBP, comp->exception_var().index() * kWordSize), |
| 1146 kExceptionObjectReg); | 1144 kExceptionObjectReg); |
| 1147 __ movq(Address(RBP, comp->stacktrace_var().index() * kWordSize), | 1145 __ movq(Address(RBP, comp->stacktrace_var().index() * kWordSize), |
| 1148 kStackTraceObjectReg); | 1146 kStackTraceObjectReg); |
| 1149 } | 1147 } |
| 1150 | 1148 |
| 1151 | 1149 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 } | 1298 } |
| 1301 } | 1299 } |
| 1302 | 1300 |
| 1303 | 1301 |
| 1304 // Coped from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). | 1302 // Coped from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). |
| 1305 void FlowGraphCompiler::CopyParameters() { | 1303 void FlowGraphCompiler::CopyParameters() { |
| 1306 const Function& function = parsed_function_.function(); | 1304 const Function& function = parsed_function_.function(); |
| 1307 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 1305 LocalScope* scope = parsed_function_.node_sequence()->scope(); |
| 1308 const int num_fixed_params = function.num_fixed_parameters(); | 1306 const int num_fixed_params = function.num_fixed_parameters(); |
| 1309 const int num_opt_params = function.num_optional_parameters(); | 1307 const int num_opt_params = function.num_optional_parameters(); |
| 1310 ASSERT(parsed_function_.first_parameter_index() == -1); | 1308 ASSERT(parsed_function_.first_parameter_index() == |
| 1309 ParsedFunction::kFirstLocalSlotIndex); |
| 1311 // Copy positional arguments. | 1310 // Copy positional arguments. |
| 1312 // Check that no fewer than num_fixed_params positional arguments are passed | 1311 // Check that no fewer than num_fixed_params positional arguments are passed |
| 1313 // in and that no more than num_params arguments are passed in. | 1312 // in and that no more than num_params arguments are passed in. |
| 1314 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i]. | 1313 // Passed argument i at fp[1 + argc - i] |
| 1314 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. |
| 1315 const int num_params = num_fixed_params + num_opt_params; | 1315 const int num_params = num_fixed_params + num_opt_params; |
| 1316 | 1316 |
| 1317 // Total number of args is the first Smi in args descriptor array (R10). | 1317 // Total number of args is the first Smi in args descriptor array (R10). |
| 1318 __ movq(RBX, FieldAddress(R10, Array::data_offset())); | 1318 __ movq(RBX, FieldAddress(R10, Array::data_offset())); |
| 1319 // Check that num_args <= num_params. | 1319 // Check that num_args <= num_params. |
| 1320 Label wrong_num_arguments; | 1320 Label wrong_num_arguments; |
| 1321 __ cmpq(RBX, Immediate(Smi::RawValue(num_params))); | 1321 __ cmpq(RBX, Immediate(Smi::RawValue(num_params))); |
| 1322 __ j(GREATER, &wrong_num_arguments); | 1322 __ j(GREATER, &wrong_num_arguments); |
| 1323 // Number of positional args is the second Smi in descriptor array (R10). | 1323 // Number of positional args is the second Smi in descriptor array (R10). |
| 1324 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); | 1324 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); |
| 1325 // Check that num_pos_args >= num_fixed_params. | 1325 // Check that num_pos_args >= num_fixed_params. |
| 1326 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params))); | 1326 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params))); |
| 1327 __ j(LESS, &wrong_num_arguments); | 1327 __ j(LESS, &wrong_num_arguments); |
| 1328 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8. | 1328 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8. |
| 1329 // Let RBX point to the last passed positional argument, i.e. to | 1329 // Let RBX point to the last passed positional argument, i.e. to |
| 1330 // fp[1 + num_args - (num_pos_args - 1)]. | 1330 // fp[1 + num_args - (num_pos_args - 1)]. |
| 1331 __ subq(RBX, RCX); | 1331 __ subq(RBX, RCX); |
| 1332 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize)); | 1332 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize)); |
| 1333 // Let RDI point to the last copied positional argument, i.e. to | 1333 // Let RDI point to the last copied positional argument, i.e. to |
| 1334 // fp[-1 - (num_pos_args - 1)]. | 1334 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. |
| 1335 __ SmiUntag(RCX); | 1335 __ SmiUntag(RCX); |
| 1336 __ movq(RAX, RCX); | 1336 __ movq(RAX, RCX); |
| 1337 __ negq(RAX); | 1337 __ negq(RAX); |
| 1338 __ leaq(RDI, Address(RBP, RAX, TIMES_8, 0)); | 1338 const int index = ParsedFunction::kFirstLocalSlotIndex + 1; |
| 1339 // -num_pos_args is in RAX. |
| 1340 // (ParsedFunction::kFirstLocalSlotIndex + 1) is in index. |
| 1341 __ leaq(RDI, Address(RBP, RAX, TIMES_8, (index * kWordSize))); |
| 1339 Label loop, loop_condition; | 1342 Label loop, loop_condition; |
| 1340 __ jmp(&loop_condition, Assembler::kNearJump); | 1343 __ jmp(&loop_condition, Assembler::kNearJump); |
| 1341 // We do not use the final allocation index of the variable here, i.e. | 1344 // We do not use the final allocation index of the variable here, i.e. |
| 1342 // scope->VariableAt(i)->index(), because captured variables still need | 1345 // scope->VariableAt(i)->index(), because captured variables still need |
| 1343 // to be copied to the context that is not yet allocated. | 1346 // to be copied to the context that is not yet allocated. |
| 1344 const Address argument_addr(RBX, RCX, TIMES_8, 0); | 1347 const Address argument_addr(RBX, RCX, TIMES_8, 0); |
| 1345 const Address copy_addr(RDI, RCX, TIMES_8, 0); | 1348 const Address copy_addr(RDI, RCX, TIMES_8, 0); |
| 1346 __ Bind(&loop); | 1349 __ Bind(&loop); |
| 1347 __ movq(RAX, argument_addr); | 1350 __ movq(RAX, argument_addr); |
| 1348 __ movq(copy_addr, RAX); | 1351 __ movq(copy_addr, RAX); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. | 1403 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. |
| 1401 __ movq(RAX, argument_addr); | 1404 __ movq(RAX, argument_addr); |
| 1402 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | 1405 __ jmp(&assign_optional_parameter, Assembler::kNearJump); |
| 1403 __ Bind(&load_default_value); | 1406 __ Bind(&load_default_value); |
| 1404 // Load RAX with default argument at pos. | 1407 // Load RAX with default argument at pos. |
| 1405 const Object& value = Object::ZoneHandle( | 1408 const Object& value = Object::ZoneHandle( |
| 1406 parsed_function_.default_parameter_values().At( | 1409 parsed_function_.default_parameter_values().At( |
| 1407 param_pos - num_fixed_params)); | 1410 param_pos - num_fixed_params)); |
| 1408 __ LoadObject(RAX, value); | 1411 __ LoadObject(RAX, value); |
| 1409 __ Bind(&assign_optional_parameter); | 1412 __ Bind(&assign_optional_parameter); |
| 1410 // Assign RAX to fp[-1 - param_pos]. | 1413 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 1411 // We do not use the final allocation index of the variable here, i.e. | 1414 // We do not use the final allocation index of the variable here, i.e. |
| 1412 // scope->VariableAt(i)->index(), because captured variables still need | 1415 // scope->VariableAt(i)->index(), because captured variables still need |
| 1413 // to be copied to the context that is not yet allocated. | 1416 // to be copied to the context that is not yet allocated. |
| 1414 const Address param_addr(RBP, (-1 - param_pos) * kWordSize); | 1417 const Address param_addr( |
| 1418 RBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize); |
| 1415 __ movq(param_addr, RAX); | 1419 __ movq(param_addr, RAX); |
| 1416 __ Bind(&next_parameter); | 1420 __ Bind(&next_parameter); |
| 1417 } | 1421 } |
| 1418 delete[] opt_param; | 1422 delete[] opt_param; |
| 1419 delete[] opt_param_position; | 1423 delete[] opt_param_position; |
| 1420 // Check that RDI now points to the null terminator in the array descriptor. | 1424 // Check that RDI now points to the null terminator in the array descriptor. |
| 1421 const Immediate raw_null = | 1425 const Immediate raw_null = |
| 1422 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1426 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1423 Label all_arguments_processed; | 1427 Label all_arguments_processed; |
| 1424 __ cmpq(Address(RDI, 0), raw_null); | 1428 __ cmpq(Address(RDI, 0), raw_null); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1438 kClosureArgumentMismatchRuntimeEntry); | 1442 kClosureArgumentMismatchRuntimeEntry); |
| 1439 } else { | 1443 } else { |
| 1440 // Invoke noSuchMethod function. | 1444 // Invoke noSuchMethod function. |
| 1441 const int kNumArgsChecked = 1; | 1445 const int kNumArgsChecked = 1; |
| 1442 ICData& ic_data = ICData::ZoneHandle(); | 1446 ICData& ic_data = ICData::ZoneHandle(); |
| 1443 ic_data = ICData::New(parsed_function_.function(), | 1447 ic_data = ICData::New(parsed_function_.function(), |
| 1444 String::Handle(function.name()), | 1448 String::Handle(function.name()), |
| 1445 AstNode::kNoId, | 1449 AstNode::kNoId, |
| 1446 kNumArgsChecked); | 1450 kNumArgsChecked); |
| 1447 __ LoadObject(RBX, ic_data); | 1451 __ LoadObject(RBX, ic_data); |
| 1452 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. |
| 1448 // RBP : points to previous frame pointer. | 1453 // RBP : points to previous frame pointer. |
| 1449 // RBP + 8 : points to return address. | 1454 // RBP + 8 : points to return address. |
| 1450 // RBP + 16 : address of last argument (arg n-1). | 1455 // RBP + 16 : address of last argument (arg n-1). |
| 1451 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). | 1456 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1452 // RBX : ic-data. | 1457 // RBX : ic-data. |
| 1453 // R10 : arguments descriptor array. | 1458 // R10 : arguments descriptor array. |
| 1454 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 1459 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1455 } | 1460 } |
| 1456 | 1461 |
| 1457 if (FLAG_trace_functions) { | 1462 if (FLAG_trace_functions) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 __ int3(); | 1576 __ int3(); |
| 1572 __ jmp(&StubCode::FixCallersTargetLabel()); | 1577 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 1573 return; | 1578 return; |
| 1574 } | 1579 } |
| 1575 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 1580 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 1576 const Function& function = parsed_function_.function(); | 1581 const Function& function = parsed_function_.function(); |
| 1577 | 1582 |
| 1578 const int parameter_count = function.num_fixed_parameters(); | 1583 const int parameter_count = function.num_fixed_parameters(); |
| 1579 const int num_copied_params = parsed_function_.copied_parameter_count(); | 1584 const int num_copied_params = parsed_function_.copied_parameter_count(); |
| 1580 const int local_count = parsed_function_.stack_local_count(); | 1585 const int local_count = parsed_function_.stack_local_count(); |
| 1581 __ EnterFrame(StackSize() * kWordSize); | 1586 AssemblerMacros::EnterDartFrame(assembler_, (StackSize() * kWordSize)); |
| 1582 | 1587 |
| 1583 // We check the number of passed arguments when we have to copy them due to | 1588 // We check the number of passed arguments when we have to copy them due to |
| 1584 // the presence of optional named parameters. | 1589 // the presence of optional named parameters. |
| 1585 // No such checking code is generated if only fixed parameters are declared, | 1590 // No such checking code is generated if only fixed parameters are declared, |
| 1586 // unless we are debug mode or unless we are compiling a closure. | 1591 // unless we are debug mode or unless we are compiling a closure. |
| 1587 if (num_copied_params == 0) { | 1592 if (num_copied_params == 0) { |
| 1588 #ifdef DEBUG | 1593 #ifdef DEBUG |
| 1589 const bool check_arguments = true; | 1594 const bool check_arguments = true; |
| 1590 #else | 1595 #else |
| 1591 const bool check_arguments = function.IsClosureFunction(); | 1596 const bool check_arguments = function.IsClosureFunction(); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1714 ASSERT(exception_handlers_list_ != NULL); | 1719 ASSERT(exception_handlers_list_ != NULL); |
| 1715 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1720 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 1716 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1721 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 1717 code.set_exception_handlers(handlers); | 1722 code.set_exception_handlers(handlers); |
| 1718 } | 1723 } |
| 1719 | 1724 |
| 1720 | 1725 |
| 1721 } // namespace dart | 1726 } // namespace dart |
| 1722 | 1727 |
| 1723 #endif // defined TARGET_ARCH_X64 | 1728 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |