Chromium Code Reviews| 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::kFirstStackSlotIndex * 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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1130 } | 1131 } |
| 1131 | 1132 |
| 1132 | 1133 |
| 1133 // Restore stack and initialize the two exception variables: | 1134 // Restore stack and initialize the two exception variables: |
| 1134 // exception and stack trace variables. | 1135 // exception and stack trace variables. |
| 1135 void FlowGraphCompiler::VisitCatchEntry(CatchEntryComp* comp) { | 1136 void FlowGraphCompiler::VisitCatchEntry(CatchEntryComp* comp) { |
| 1136 // Restore RSP from RBP as we are coming from a throw and the code for | 1137 // Restore RSP from RBP as we are coming from a throw and the code for |
| 1137 // popping arguments has not been run. | 1138 // popping arguments has not been run. |
| 1138 const intptr_t locals_space_size = StackSize() * kWordSize; | 1139 const intptr_t locals_space_size = StackSize() * kWordSize; |
| 1139 ASSERT(locals_space_size >= 0); | 1140 ASSERT(locals_space_size >= 0); |
| 1140 if (locals_space_size == 0) { | 1141 intptr_t offset_size = -locals_space_size + kLocalsOffsetFromFP; |
| 1141 __ movq(RSP, RBP); | 1142 __ leaq(RSP, Address(RBP, offset_size)); |
| 1142 } else { | |
| 1143 __ leaq(RSP, Address(RBP, -locals_space_size)); | |
| 1144 } | |
| 1145 | 1143 |
| 1146 ASSERT(!comp->exception_var().is_captured()); | 1144 ASSERT(!comp->exception_var().is_captured()); |
| 1147 ASSERT(!comp->stacktrace_var().is_captured()); | 1145 ASSERT(!comp->stacktrace_var().is_captured()); |
| 1148 __ movq(Address(RBP, comp->exception_var().index() * kWordSize), | 1146 __ movq(Address(RBP, comp->exception_var().index() * kWordSize), |
| 1149 kExceptionObjectReg); | 1147 kExceptionObjectReg); |
| 1150 __ movq(Address(RBP, comp->stacktrace_var().index() * kWordSize), | 1148 __ movq(Address(RBP, comp->stacktrace_var().index() * kWordSize), |
| 1151 kStackTraceObjectReg); | 1149 kStackTraceObjectReg); |
| 1152 } | 1150 } |
| 1153 | 1151 |
| 1154 | 1152 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1325 } | 1323 } |
| 1326 } | 1324 } |
| 1327 | 1325 |
| 1328 | 1326 |
| 1329 // Coped from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). | 1327 // Coped from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). |
| 1330 void FlowGraphCompiler::CopyParameters() { | 1328 void FlowGraphCompiler::CopyParameters() { |
| 1331 const Function& function = parsed_function_.function(); | 1329 const Function& function = parsed_function_.function(); |
| 1332 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 1330 LocalScope* scope = parsed_function_.node_sequence()->scope(); |
| 1333 const int num_fixed_params = function.num_fixed_parameters(); | 1331 const int num_fixed_params = function.num_fixed_parameters(); |
| 1334 const int num_opt_params = function.num_optional_parameters(); | 1332 const int num_opt_params = function.num_optional_parameters(); |
| 1335 ASSERT(parsed_function_.first_parameter_index() == -1); | 1333 ASSERT(parsed_function_.first_parameter_index() == |
| 1334 ParsedFunction::kFirstStackSlotIndex); | |
| 1336 // Copy positional arguments. | 1335 // Copy positional arguments. |
| 1337 // Check that no fewer than num_fixed_params positional arguments are passed | 1336 // Check that no fewer than num_fixed_params positional arguments are passed |
| 1338 // in and that no more than num_params arguments are passed in. | 1337 // in and that no more than num_params arguments are passed in. |
| 1339 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i]. | 1338 // Passed argument i at fp[1 + argc - i] |
| 1339 // copied to fp[ParsedFunction::kFirstStackSlotIndex - i]. | |
| 1340 const int num_params = num_fixed_params + num_opt_params; | 1340 const int num_params = num_fixed_params + num_opt_params; |
| 1341 | 1341 |
| 1342 // Total number of args is the first Smi in args descriptor array (R10). | 1342 // Total number of args is the first Smi in args descriptor array (R10). |
| 1343 __ movq(RBX, FieldAddress(R10, Array::data_offset())); | 1343 __ movq(RBX, FieldAddress(R10, Array::data_offset())); |
| 1344 // Check that num_args <= num_params. | 1344 // Check that num_args <= num_params. |
| 1345 Label wrong_num_arguments; | 1345 Label wrong_num_arguments; |
| 1346 __ cmpq(RBX, Immediate(Smi::RawValue(num_params))); | 1346 __ cmpq(RBX, Immediate(Smi::RawValue(num_params))); |
| 1347 __ j(GREATER, &wrong_num_arguments); | 1347 __ j(GREATER, &wrong_num_arguments); |
| 1348 // Number of positional args is the second Smi in descriptor array (R10). | 1348 // Number of positional args is the second Smi in descriptor array (R10). |
| 1349 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); | 1349 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); |
| 1350 // Check that num_pos_args >= num_fixed_params. | 1350 // Check that num_pos_args >= num_fixed_params. |
| 1351 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params))); | 1351 __ cmpq(RCX, Immediate(Smi::RawValue(num_fixed_params))); |
| 1352 __ j(LESS, &wrong_num_arguments); | 1352 __ j(LESS, &wrong_num_arguments); |
| 1353 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8. | 1353 // Since RBX and RCX are Smi, use TIMES_4 instead of TIMES_8. |
| 1354 // Let RBX point to the last passed positional argument, i.e. to | 1354 // Let RBX point to the last passed positional argument, i.e. to |
| 1355 // fp[1 + num_args - (num_pos_args - 1)]. | 1355 // fp[1 + num_args - (num_pos_args - 1)]. |
| 1356 __ subq(RBX, RCX); | 1356 __ subq(RBX, RCX); |
| 1357 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize)); | 1357 __ leaq(RBX, Address(RBP, RBX, TIMES_4, 2 * kWordSize)); |
| 1358 // Let RDI point to the last copied positional argument, i.e. to | 1358 // Let RDI point to the last copied positional argument, i.e. to |
| 1359 // fp[-1 - (num_pos_args - 1)]. | 1359 // fp[ParsedFunction::kFirstStackSlotIndex - (num_pos_args - 1)]. |
| 1360 __ SmiUntag(RCX); | 1360 __ SmiUntag(RCX); |
| 1361 __ movq(RAX, RCX); | 1361 __ movq(RAX, RCX); |
| 1362 __ negq(RAX); | 1362 __ negq(RAX); |
| 1363 __ leaq(RDI, Address(RBP, RAX, TIMES_8, 0)); | 1363 int index = ParsedFunction::kFirstStackSlotIndex + 1; |
|
regis
2012/05/14 17:33:10
const
siva
2012/05/15 23:52:39
Done.
| |
| 1364 // -num_pos_args is in RAX. | |
| 1365 // (ParsedFunction::kFirstStackSlotIndex + 1) is in index. | |
| 1366 __ leaq(RDI, Address(RBP, RAX, TIMES_8, (index * kWordSize))); | |
| 1364 Label loop, loop_condition; | 1367 Label loop, loop_condition; |
| 1365 __ jmp(&loop_condition, Assembler::kNearJump); | 1368 __ jmp(&loop_condition, Assembler::kNearJump); |
| 1366 // We do not use the final allocation index of the variable here, i.e. | 1369 // We do not use the final allocation index of the variable here, i.e. |
| 1367 // scope->VariableAt(i)->index(), because captured variables still need | 1370 // scope->VariableAt(i)->index(), because captured variables still need |
| 1368 // to be copied to the context that is not yet allocated. | 1371 // to be copied to the context that is not yet allocated. |
| 1369 const Address argument_addr(RBX, RCX, TIMES_8, 0); | 1372 const Address argument_addr(RBX, RCX, TIMES_8, 0); |
| 1370 const Address copy_addr(RDI, RCX, TIMES_8, 0); | 1373 const Address copy_addr(RDI, RCX, TIMES_8, 0); |
| 1371 __ Bind(&loop); | 1374 __ Bind(&loop); |
| 1372 __ movq(RAX, argument_addr); | 1375 __ movq(RAX, argument_addr); |
| 1373 __ movq(copy_addr, RAX); | 1376 __ movq(copy_addr, RAX); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1425 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. | 1428 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. |
| 1426 __ movq(RAX, argument_addr); | 1429 __ movq(RAX, argument_addr); |
| 1427 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | 1430 __ jmp(&assign_optional_parameter, Assembler::kNearJump); |
| 1428 __ Bind(&load_default_value); | 1431 __ Bind(&load_default_value); |
| 1429 // Load RAX with default argument at pos. | 1432 // Load RAX with default argument at pos. |
| 1430 const Object& value = Object::ZoneHandle( | 1433 const Object& value = Object::ZoneHandle( |
| 1431 parsed_function_.default_parameter_values().At( | 1434 parsed_function_.default_parameter_values().At( |
| 1432 param_pos - num_fixed_params)); | 1435 param_pos - num_fixed_params)); |
| 1433 __ LoadObject(RAX, value); | 1436 __ LoadObject(RAX, value); |
| 1434 __ Bind(&assign_optional_parameter); | 1437 __ Bind(&assign_optional_parameter); |
| 1435 // Assign RAX to fp[-1 - param_pos]. | 1438 // Assign RAX to fp[ParsedFunction::kFirstStackSlotIndex - param_pos]. |
| 1436 // We do not use the final allocation index of the variable here, i.e. | 1439 // We do not use the final allocation index of the variable here, i.e. |
| 1437 // scope->VariableAt(i)->index(), because captured variables still need | 1440 // scope->VariableAt(i)->index(), because captured variables still need |
| 1438 // to be copied to the context that is not yet allocated. | 1441 // to be copied to the context that is not yet allocated. |
| 1439 const Address param_addr(RBP, (-1 - param_pos) * kWordSize); | 1442 const Address param_addr( |
| 1443 RBP, (ParsedFunction::kFirstStackSlotIndex - param_pos) * kWordSize); | |
| 1440 __ movq(param_addr, RAX); | 1444 __ movq(param_addr, RAX); |
| 1441 __ Bind(&next_parameter); | 1445 __ Bind(&next_parameter); |
| 1442 } | 1446 } |
| 1443 delete[] opt_param; | 1447 delete[] opt_param; |
| 1444 delete[] opt_param_position; | 1448 delete[] opt_param_position; |
| 1445 // Check that RDI now points to the null terminator in the array descriptor. | 1449 // Check that RDI now points to the null terminator in the array descriptor. |
| 1446 const Immediate raw_null = | 1450 const Immediate raw_null = |
| 1447 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1451 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1448 Label all_arguments_processed; | 1452 Label all_arguments_processed; |
| 1449 __ cmpq(Address(RDI, 0), raw_null); | 1453 __ cmpq(Address(RDI, 0), raw_null); |
| 1450 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 1454 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 1451 | 1455 |
| 1452 __ Bind(&wrong_num_arguments); | 1456 __ Bind(&wrong_num_arguments); |
| 1457 if (StackSize() != 0) { | |
| 1458 // We need to unwind the space we reserved for locals/copied parms etc. | |
|
regis
2012/05/14 17:33:10
ditto
siva
2012/05/15 23:52:39
Yes, I incorporated your comment into the other CL
| |
| 1459 // as the NoSuchMethodFunction stub does not expect to see that area on | |
| 1460 // the stack. | |
| 1461 __ addq(RSP, Immediate(StackSize() * kWordSize)); | |
| 1462 } | |
| 1453 if (function.IsClosureFunction()) { | 1463 if (function.IsClosureFunction()) { |
| 1454 GenerateCallRuntime(AstNode::kNoId, | 1464 GenerateCallRuntime(AstNode::kNoId, |
| 1455 0, | 1465 0, |
| 1456 CatchClauseNode::kInvalidTryIndex, | 1466 CatchClauseNode::kInvalidTryIndex, |
| 1457 kClosureArgumentMismatchRuntimeEntry); | 1467 kClosureArgumentMismatchRuntimeEntry); |
| 1458 } else { | 1468 } else { |
| 1459 // Invoke noSuchMethod function. | 1469 // Invoke noSuchMethod function. |
| 1460 const int kNumArgsChecked = 1; | 1470 const int kNumArgsChecked = 1; |
| 1461 ICData& ic_data = ICData::ZoneHandle(); | 1471 ICData& ic_data = ICData::ZoneHandle(); |
| 1462 ic_data = ICData::New(parsed_function_.function(), | 1472 ic_data = ICData::New(parsed_function_.function(), |
| 1463 String::Handle(function.name()), | 1473 String::Handle(function.name()), |
| 1464 AstNode::kNoId, | 1474 AstNode::kNoId, |
| 1465 kNumArgsChecked); | 1475 kNumArgsChecked); |
| 1466 __ LoadObject(RBX, ic_data); | 1476 __ LoadObject(RBX, ic_data); |
| 1477 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. | |
| 1467 // RBP : points to previous frame pointer. | 1478 // RBP : points to previous frame pointer. |
| 1468 // RBP + 8 : points to return address. | 1479 // RBP + 8 : points to return address. |
| 1469 // RBP + 16 : address of last argument (arg n-1). | 1480 // RBP + 16 : address of last argument (arg n-1). |
| 1470 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). | 1481 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1471 // RBX : ic-data. | 1482 // RBX : ic-data. |
| 1472 // R10 : arguments descriptor array. | 1483 // R10 : arguments descriptor array. |
| 1473 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 1484 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1474 } | 1485 } |
| 1475 | 1486 |
| 1476 if (FLAG_trace_functions) { | 1487 if (FLAG_trace_functions) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1590 __ int3(); | 1601 __ int3(); |
| 1591 __ jmp(&StubCode::FixCallersTargetLabel()); | 1602 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 1592 return; | 1603 return; |
| 1593 } | 1604 } |
| 1594 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 1605 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 1595 const Function& function = parsed_function_.function(); | 1606 const Function& function = parsed_function_.function(); |
| 1596 | 1607 |
| 1597 const int parameter_count = function.num_fixed_parameters(); | 1608 const int parameter_count = function.num_fixed_parameters(); |
| 1598 const int num_copied_params = parsed_function_.copied_parameter_count(); | 1609 const int num_copied_params = parsed_function_.copied_parameter_count(); |
| 1599 const int local_count = parsed_function_.stack_local_count(); | 1610 const int local_count = parsed_function_.stack_local_count(); |
| 1600 __ EnterFrame(StackSize() * kWordSize); | 1611 AssemblerMacros::EnterDartFrame(assembler_, (StackSize() * kWordSize)); |
| 1601 | 1612 |
| 1602 // We check the number of passed arguments when we have to copy them due to | 1613 // We check the number of passed arguments when we have to copy them due to |
| 1603 // the presence of optional named parameters. | 1614 // the presence of optional named parameters. |
| 1604 // No such checking code is generated if only fixed parameters are declared, | 1615 // No such checking code is generated if only fixed parameters are declared, |
| 1605 // unless we are debug mode or unless we are compiling a closure. | 1616 // unless we are debug mode or unless we are compiling a closure. |
| 1606 if (num_copied_params == 0) { | 1617 if (num_copied_params == 0) { |
| 1607 #ifdef DEBUG | 1618 #ifdef DEBUG |
| 1608 const bool check_arguments = true; | 1619 const bool check_arguments = true; |
| 1609 #else | 1620 #else |
| 1610 const bool check_arguments = function.IsClosureFunction(); | 1621 const bool check_arguments = function.IsClosureFunction(); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1733 ASSERT(exception_handlers_list_ != NULL); | 1744 ASSERT(exception_handlers_list_ != NULL); |
| 1734 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1745 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 1735 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1746 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 1736 code.set_exception_handlers(handlers); | 1747 code.set_exception_handlers(handlers); |
| 1737 } | 1748 } |
| 1738 | 1749 |
| 1739 | 1750 |
| 1740 } // namespace dart | 1751 } // namespace dart |
| 1741 | 1752 |
| 1742 #endif // defined TARGET_ARCH_X64 | 1753 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |