| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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 "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 intptr_t slot_ix = 0; | 59 intptr_t slot_ix = 0; |
| 60 Environment* current = deopt_env_; | 60 Environment* current = deopt_env_; |
| 61 | 61 |
| 62 // Emit all kMaterializeObject instructions describing objects to be | 62 // Emit all kMaterializeObject instructions describing objects to be |
| 63 // materialized on the deoptimization as a prefix to the deoptimization info. | 63 // materialized on the deoptimization as a prefix to the deoptimization info. |
| 64 EmitMaterializations(deopt_env_, builder); | 64 EmitMaterializations(deopt_env_, builder); |
| 65 | 65 |
| 66 // The real frame starts here. | 66 // The real frame starts here. |
| 67 builder->MarkFrameStart(); | 67 builder->MarkFrameStart(); |
| 68 | 68 |
| 69 // Callee's PC marker is not used anymore. Pass Function::null() to set to 0. | 69 // Current PP, FP, and PC. |
| 70 builder->AddPp(current->function(), slot_ix++); |
| 70 builder->AddPcMarker(Function::Handle(), slot_ix++); | 71 builder->AddPcMarker(Function::Handle(), slot_ix++); |
| 71 | |
| 72 // Current FP and PC. | |
| 73 builder->AddCallerFp(slot_ix++); | 72 builder->AddCallerFp(slot_ix++); |
| 74 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); | 73 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); |
| 75 | 74 |
| 76 // Emit all values that are needed for materialization as a part of the | 75 // Emit all values that are needed for materialization as a part of the |
| 77 // expression stack for the bottom-most frame. This guarantees that GC | 76 // expression stack for the bottom-most frame. This guarantees that GC |
| 78 // will be able to find them during materialization. | 77 // will be able to find them during materialization. |
| 79 slot_ix = builder->EmitMaterializationArguments(slot_ix); | 78 slot_ix = builder->EmitMaterializationArguments(slot_ix); |
| 80 | 79 |
| 81 // For the innermost environment, set outgoing arguments and the locals. | 80 // For the innermost environment, set outgoing arguments and the locals. |
| 82 for (intptr_t i = current->Length() - 1; | 81 for (intptr_t i = current->Length() - 1; |
| 83 i >= current->fixed_parameter_count(); | 82 i >= current->fixed_parameter_count(); |
| 84 i--) { | 83 i--) { |
| 85 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); | 84 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); |
| 86 } | 85 } |
| 87 | 86 |
| 88 // Current PC marker and caller FP. | |
| 89 builder->AddPcMarker(current->function(), slot_ix++); | |
| 90 builder->AddCallerFp(slot_ix++); | |
| 91 | |
| 92 Environment* previous = current; | 87 Environment* previous = current; |
| 93 current = current->outer(); | 88 current = current->outer(); |
| 94 while (current != NULL) { | 89 while (current != NULL) { |
| 90 // PP, FP, and PC. |
| 91 builder->AddPp(current->function(), slot_ix++); |
| 92 builder->AddPcMarker(previous->function(), slot_ix++); |
| 93 builder->AddCallerFp(slot_ix++); |
| 94 |
| 95 // For any outer environment the deopt id is that of the call instruction | 95 // For any outer environment the deopt id is that of the call instruction |
| 96 // which is recorded in the outer environment. | 96 // which is recorded in the outer environment. |
| 97 builder->AddReturnAddress(current->function(), | 97 builder->AddReturnAddress(current->function(), |
| 98 Isolate::ToDeoptAfter(current->deopt_id()), | 98 Isolate::ToDeoptAfter(current->deopt_id()), |
| 99 slot_ix++); | 99 slot_ix++); |
| 100 | 100 |
| 101 // The values of outgoing arguments can be changed from the inlined call so | 101 // The values of outgoing arguments can be changed from the inlined call so |
| 102 // we must read them from the previous environment. | 102 // we must read them from the previous environment. |
| 103 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { | 103 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { |
| 104 builder->AddCopy(previous->ValueAt(i), | 104 builder->AddCopy(previous->ValueAt(i), |
| 105 previous->LocationAt(i), | 105 previous->LocationAt(i), |
| 106 slot_ix++); | 106 slot_ix++); |
| 107 } | 107 } |
| 108 | 108 |
| 109 // Set the locals, note that outgoing arguments are not in the environment. | 109 // Set the locals, note that outgoing arguments are not in the environment. |
| 110 for (intptr_t i = current->Length() - 1; | 110 for (intptr_t i = current->Length() - 1; |
| 111 i >= current->fixed_parameter_count(); | 111 i >= current->fixed_parameter_count(); |
| 112 i--) { | 112 i--) { |
| 113 builder->AddCopy(current->ValueAt(i), | 113 builder->AddCopy(current->ValueAt(i), |
| 114 current->LocationAt(i), | 114 current->LocationAt(i), |
| 115 slot_ix++); | 115 slot_ix++); |
| 116 } | 116 } |
| 117 | 117 |
| 118 // PC marker and caller FP. | |
| 119 builder->AddPcMarker(current->function(), slot_ix++); | |
| 120 builder->AddCallerFp(slot_ix++); | |
| 121 | |
| 122 // Iterate on the outer environment. | 118 // Iterate on the outer environment. |
| 123 previous = current; | 119 previous = current; |
| 124 current = current->outer(); | 120 current = current->outer(); |
| 125 } | 121 } |
| 126 // The previous pointer is now the outermost environment. | 122 // The previous pointer is now the outermost environment. |
| 127 ASSERT(previous != NULL); | 123 ASSERT(previous != NULL); |
| 128 | 124 |
| 129 // For the outermost environment, set caller PC. | 125 // For the outermost environment, set caller PC, caller PP, and caller FP. |
| 126 builder->AddCallerPp(slot_ix++); |
| 127 // PC marker. |
| 128 builder->AddPcMarker(previous->function(), slot_ix++); |
| 129 builder->AddCallerFp(slot_ix++); |
| 130 builder->AddCallerPc(slot_ix++); | 130 builder->AddCallerPc(slot_ix++); |
| 131 | 131 |
| 132 // For the outermost environment, set the incoming arguments. | 132 // For the outermost environment, set the incoming arguments. |
| 133 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { | 133 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { |
| 134 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); | 134 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); |
| 135 } | 135 } |
| 136 | 136 |
| 137 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo()); | 137 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo()); |
| 138 return deopt_info.raw(); | 138 return deopt_info.raw(); |
| 139 } | 139 } |
| 140 | 140 |
| 141 | |
| 142 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, | 141 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, |
| 143 intptr_t stub_ix) { | 142 intptr_t stub_ix) { |
| 144 // Calls do not need stubs, they share a deoptimization trampoline. | 143 // Calls do not need stubs, they share a deoptimization trampoline. |
| 145 ASSERT(reason() != kDeoptAtCall); | 144 ASSERT(reason() != kDeoptAtCall); |
| 146 Assembler* assem = compiler->assembler(); | 145 Assembler* assem = compiler->assembler(); |
| 147 #define __ assem-> | 146 #define __ assem-> |
| 148 __ Comment("Deopt stub for id %" Pd "", deopt_id()); | 147 __ Comment("Deopt stub for id %" Pd "", deopt_id()); |
| 149 __ Bind(entry_label()); | 148 __ Bind(entry_label()); |
| 150 if (FLAG_trap_on_deoptimization) __ int3(); | 149 if (FLAG_trap_on_deoptimization) __ int3(); |
| 151 | 150 |
| (...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 } | 1008 } |
| 1010 | 1009 |
| 1011 __ Bind(&wrong_num_arguments); | 1010 __ Bind(&wrong_num_arguments); |
| 1012 if (function.IsClosureFunction()) { | 1011 if (function.IsClosureFunction()) { |
| 1013 // Invoke noSuchMethod function passing "call" as the original name. | 1012 // Invoke noSuchMethod function passing "call" as the original name. |
| 1014 const int kNumArgsChecked = 1; | 1013 const int kNumArgsChecked = 1; |
| 1015 const ICData& ic_data = ICData::ZoneHandle( | 1014 const ICData& ic_data = ICData::ZoneHandle( |
| 1016 ICData::New(function, Symbols::Call(), Object::empty_array(), | 1015 ICData::New(function, Symbols::Call(), Object::empty_array(), |
| 1017 Isolate::kNoDeoptId, kNumArgsChecked)); | 1016 Isolate::kNoDeoptId, kNumArgsChecked)); |
| 1018 __ LoadObject(RBX, ic_data); | 1017 __ LoadObject(RBX, ic_data); |
| 1019 __ LeaveFrame(); // The arguments are still on the stack. | 1018 __ LeaveFrame(true); // The arguments are still on the stack. |
| 1020 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); | 1019 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1021 // The noSuchMethod call may return to the caller, but not here. | 1020 // The noSuchMethod call may return to the caller, but not here. |
| 1022 __ int3(); | 1021 __ int3(); |
| 1023 } else if (check_correct_named_args) { | 1022 } else if (check_correct_named_args) { |
| 1024 __ Stop("Wrong arguments"); | 1023 __ Stop("Wrong arguments"); |
| 1025 } | 1024 } |
| 1026 | 1025 |
| 1027 __ Bind(&all_arguments_processed); | 1026 __ Bind(&all_arguments_processed); |
| 1028 // Nullify originally passed arguments only after they have been copied and | 1027 // Nullify originally passed arguments only after they have been copied and |
| 1029 // checked, otherwise noSuchMethod would not see their original values. | 1028 // checked, otherwise noSuchMethod would not see their original values. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 __ ret(); | 1069 __ ret(); |
| 1071 } | 1070 } |
| 1072 | 1071 |
| 1073 | 1072 |
| 1074 void FlowGraphCompiler::EmitFrameEntry() { | 1073 void FlowGraphCompiler::EmitFrameEntry() { |
| 1075 const Function& function = parsed_function().function(); | 1074 const Function& function = parsed_function().function(); |
| 1076 if (CanOptimizeFunction() && | 1075 if (CanOptimizeFunction() && |
| 1077 function.is_optimizable() && | 1076 function.is_optimizable() && |
| 1078 (!is_optimizing() || may_reoptimize())) { | 1077 (!is_optimizing() || may_reoptimize())) { |
| 1079 const Register function_reg = RDI; | 1078 const Register function_reg = RDI; |
| 1079 |
| 1080 |
| 1081 // Temporarily load pool pointer. |
| 1082 __ pushq(PP); // Preserve PP of caller. |
| 1083 __ LoadPoolPointer(); |
| 1080 __ LoadObject(function_reg, function); | 1084 __ LoadObject(function_reg, function); |
| 1085 __ popq(PP); // Restore PP of caller. |
| 1086 |
| 1081 // Patch point is after the eventually inlined function object. | 1087 // Patch point is after the eventually inlined function object. |
| 1082 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1088 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1083 Isolate::kNoDeoptId, | 1089 Isolate::kNoDeoptId, |
| 1084 0); // No token position. | 1090 0); // No token position. |
| 1085 if (is_optimizing()) { | 1091 if (is_optimizing()) { |
| 1086 // Reoptimization of an optimized function is triggered by counting in | 1092 // Reoptimization of an optimized function is triggered by counting in |
| 1087 // IC stubs, but not at the entry of the function. | 1093 // IC stubs, but not at the entry of the function. |
| 1088 __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), | 1094 __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), |
| 1089 Immediate(FLAG_reoptimization_counter_threshold)); | 1095 Immediate(FLAG_reoptimization_counter_threshold)); |
| 1090 } else { | 1096 } else { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1163 // For closure functions, use "call" as the original name. | 1169 // For closure functions, use "call" as the original name. |
| 1164 const String& name = | 1170 const String& name = |
| 1165 String::Handle(function.IsClosureFunction() | 1171 String::Handle(function.IsClosureFunction() |
| 1166 ? Symbols::Call().raw() | 1172 ? Symbols::Call().raw() |
| 1167 : function.name()); | 1173 : function.name()); |
| 1168 const int kNumArgsChecked = 1; | 1174 const int kNumArgsChecked = 1; |
| 1169 const ICData& ic_data = ICData::ZoneHandle( | 1175 const ICData& ic_data = ICData::ZoneHandle( |
| 1170 ICData::New(function, name, Object::empty_array(), | 1176 ICData::New(function, name, Object::empty_array(), |
| 1171 Isolate::kNoDeoptId, kNumArgsChecked)); | 1177 Isolate::kNoDeoptId, kNumArgsChecked)); |
| 1172 __ LoadObject(RBX, ic_data); | 1178 __ LoadObject(RBX, ic_data); |
| 1173 __ LeaveFrame(); // The arguments are still on the stack. | 1179 __ LeaveFrame(true); // The arguments are still on the stack. |
| 1174 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); | 1180 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1175 // The noSuchMethod call may return to the caller, but not here. | 1181 // The noSuchMethod call may return to the caller, but not here. |
| 1176 __ int3(); | 1182 __ int3(); |
| 1177 } else { | 1183 } else { |
| 1178 __ Stop("Wrong number of arguments"); | 1184 __ Stop("Wrong number of arguments"); |
| 1179 } | 1185 } |
| 1180 __ Bind(&correct_num_arguments); | 1186 __ Bind(&correct_num_arguments); |
| 1181 } | 1187 } |
| 1182 } else if (!flow_graph().IsCompiledForOsr()) { | 1188 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1183 CopyParameters(); | 1189 CopyParameters(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1222 Isolate::kNoDeoptId, | 1228 Isolate::kNoDeoptId, |
| 1223 0); // No token position. | 1229 0); // No token position. |
| 1224 __ jmp(&StubCode::DeoptimizeLazyLabel()); | 1230 __ jmp(&StubCode::DeoptimizeLazyLabel()); |
| 1225 } | 1231 } |
| 1226 | 1232 |
| 1227 | 1233 |
| 1228 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1234 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 1229 const ExternalLabel* label, | 1235 const ExternalLabel* label, |
| 1230 PcDescriptors::Kind kind, | 1236 PcDescriptors::Kind kind, |
| 1231 LocationSummary* locs) { | 1237 LocationSummary* locs) { |
| 1232 __ call(label); | 1238 __ CallPatchable(label); |
| 1233 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1239 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
| 1234 RecordSafepoint(locs); | 1240 RecordSafepoint(locs); |
| 1235 } | 1241 } |
| 1236 | 1242 |
| 1237 | 1243 |
| 1238 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, | 1244 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, |
| 1239 intptr_t token_pos, | 1245 intptr_t token_pos, |
| 1240 const ExternalLabel* label, | 1246 const ExternalLabel* label, |
| 1241 PcDescriptors::Kind kind, | 1247 PcDescriptors::Kind kind, |
| 1242 LocationSummary* locs) { | 1248 LocationSummary* locs) { |
| 1243 __ call(label); | 1249 __ CallPatchable(label); |
| 1244 AddCurrentDescriptor(kind, deopt_id, token_pos); | 1250 AddCurrentDescriptor(kind, deopt_id, token_pos); |
| 1245 RecordSafepoint(locs); | 1251 RecordSafepoint(locs); |
| 1246 // Marks either the continuation point in unoptimized code or the | 1252 // Marks either the continuation point in unoptimized code or the |
| 1247 // deoptimization point in optimized code, after call. | 1253 // deoptimization point in optimized code, after call. |
| 1248 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1254 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
| 1249 if (is_optimizing()) { | 1255 if (is_optimizing()) { |
| 1250 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1256 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
| 1251 } else { | 1257 } else { |
| 1252 // Add deoptimization continuation point after the call and before the | 1258 // Add deoptimization continuation point after the call and before the |
| 1253 // arguments are removed. | 1259 // arguments are removed. |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1606 BranchInstr* branch) { | 1612 BranchInstr* branch) { |
| 1607 ASSERT(branch != NULL); | 1613 ASSERT(branch != NULL); |
| 1608 assembler()->comisd(left, right); | 1614 assembler()->comisd(left, right); |
| 1609 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? | 1615 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? |
| 1610 branch->true_successor() : branch->false_successor(); | 1616 branch->true_successor() : branch->false_successor(); |
| 1611 assembler()->j(PARITY_EVEN, GetJumpLabel(nan_result)); | 1617 assembler()->j(PARITY_EVEN, GetJumpLabel(nan_result)); |
| 1612 branch->EmitBranchOnCondition(this, true_condition); | 1618 branch->EmitBranchOnCondition(this, true_condition); |
| 1613 } | 1619 } |
| 1614 | 1620 |
| 1615 | 1621 |
| 1616 | |
| 1617 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, | 1622 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, |
| 1618 FpuRegister left, | 1623 FpuRegister left, |
| 1619 FpuRegister right, | 1624 FpuRegister right, |
| 1620 Register result) { | 1625 Register result) { |
| 1621 assembler()->comisd(left, right); | 1626 assembler()->comisd(left, right); |
| 1622 Label is_false, is_true, done; | 1627 Label is_false, is_true, done; |
| 1623 assembler()->j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN false; | 1628 assembler()->j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN false; |
| 1624 assembler()->j(true_condition, &is_true, Assembler::kNearJump); | 1629 assembler()->j(true_condition, &is_true, Assembler::kNearJump); |
| 1625 assembler()->Bind(&is_false); | 1630 assembler()->Bind(&is_false); |
| 1626 assembler()->LoadObject(result, Bool::False()); | 1631 assembler()->LoadObject(result, Bool::False()); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1889 __ movups(reg, Address(RSP, 0)); | 1894 __ movups(reg, Address(RSP, 0)); |
| 1890 __ addq(RSP, Immediate(kFpuRegisterSize)); | 1895 __ addq(RSP, Immediate(kFpuRegisterSize)); |
| 1891 } | 1896 } |
| 1892 | 1897 |
| 1893 | 1898 |
| 1894 #undef __ | 1899 #undef __ |
| 1895 | 1900 |
| 1896 } // namespace dart | 1901 } // namespace dart |
| 1897 | 1902 |
| 1898 #endif // defined TARGET_ARCH_X64 | 1903 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |