| 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/code_generator.h" | 5 #include "vm/code_generator.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
| 9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 | 670 |
| 671 // Result of an invoke may be an unhandled exception, in which case we | 671 // Result of an invoke may be an unhandled exception, in which case we |
| 672 // rethrow it. | 672 // rethrow it. |
| 673 static void CheckResultError(const Object& result) { | 673 static void CheckResultError(const Object& result) { |
| 674 if (result.IsError()) { | 674 if (result.IsError()) { |
| 675 Exceptions::PropagateError(Error::Cast(result)); | 675 Exceptions::PropagateError(Error::Cast(result)); |
| 676 } | 676 } |
| 677 } | 677 } |
| 678 | 678 |
| 679 | 679 |
| 680 #if !defined(TARGET_ARCH_DBC) |
| 680 // Gets called from debug stub when code reaches a breakpoint | 681 // Gets called from debug stub when code reaches a breakpoint |
| 681 // set on a runtime stub call. | 682 // set on a runtime stub call. |
| 682 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { | 683 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { |
| 683 if (!FLAG_support_debugger) { | 684 if (!FLAG_support_debugger) { |
| 684 UNREACHABLE(); | 685 UNREACHABLE(); |
| 685 return; | 686 return; |
| 686 } | 687 } |
| 687 DartFrameIterator iterator; | 688 DartFrameIterator iterator; |
| 688 StackFrame* caller_frame = iterator.NextFrame(); | 689 StackFrame* caller_frame = iterator.NextFrame(); |
| 689 ASSERT(caller_frame != NULL); | 690 ASSERT(caller_frame != NULL); |
| 690 const Code& orig_stub = Code::Handle( | 691 const Code& orig_stub = Code::Handle( |
| 691 isolate->debugger()->GetPatchedStubAddress(caller_frame->pc())); | 692 isolate->debugger()->GetPatchedStubAddress(caller_frame->pc())); |
| 692 const Error& error = Error::Handle(isolate->debugger()->SignalBpReached()); | 693 const Error& error = Error::Handle(isolate->debugger()->SignalBpReached()); |
| 693 if (!error.IsNull()) { | 694 if (!error.IsNull()) { |
| 694 Exceptions::PropagateError(error); | 695 Exceptions::PropagateError(error); |
| 695 UNREACHABLE(); | 696 UNREACHABLE(); |
| 696 } | 697 } |
| 697 arguments.SetReturn(orig_stub); | 698 arguments.SetReturn(orig_stub); |
| 698 } | 699 } |
| 700 #else |
| 701 // Gets called from the simulator when the breakpoint is reached. |
| 702 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { |
| 703 if (!FLAG_support_debugger) { |
| 704 UNREACHABLE(); |
| 705 return; |
| 706 } |
| 707 const Error& error = Error::Handle(isolate->debugger()->SignalBpReached()); |
| 708 if (!error.IsNull()) { |
| 709 Exceptions::PropagateError(error); |
| 710 UNREACHABLE(); |
| 711 } |
| 712 } |
| 713 #endif // !defined(TARGET_ARCH_DBC) |
| 699 | 714 |
| 700 | 715 |
| 701 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { | 716 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { |
| 702 if (!FLAG_support_debugger) { | 717 if (!FLAG_support_debugger) { |
| 703 UNREACHABLE(); | 718 UNREACHABLE(); |
| 704 return; | 719 return; |
| 705 } | 720 } |
| 706 const Error& error = | 721 const Error& error = |
| 707 Error::Handle(isolate->debugger()->DebuggerStepCallback()); | 722 Error::Handle(isolate->debugger()->DebuggerStepCallback()); |
| 708 if (!error.IsNull()) { | 723 if (!error.IsNull()) { |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 // Switch to megamorphic call. | 1031 // Switch to megamorphic call. |
| 1017 const MegamorphicCache& cache = MegamorphicCache::Handle(zone, | 1032 const MegamorphicCache& cache = MegamorphicCache::Handle(zone, |
| 1018 MegamorphicCacheTable::Lookup(isolate, name, descriptor)); | 1033 MegamorphicCacheTable::Lookup(isolate, name, descriptor)); |
| 1019 DartFrameIterator iterator; | 1034 DartFrameIterator iterator; |
| 1020 StackFrame* miss_function_frame = iterator.NextFrame(); | 1035 StackFrame* miss_function_frame = iterator.NextFrame(); |
| 1021 ASSERT(miss_function_frame->IsDartFrame()); | 1036 ASSERT(miss_function_frame->IsDartFrame()); |
| 1022 StackFrame* caller_frame = iterator.NextFrame(); | 1037 StackFrame* caller_frame = iterator.NextFrame(); |
| 1023 ASSERT(caller_frame->IsDartFrame()); | 1038 ASSERT(caller_frame->IsDartFrame()); |
| 1024 const Code& code = Code::Handle(zone, caller_frame->LookupDartCode()); | 1039 const Code& code = Code::Handle(zone, caller_frame->LookupDartCode()); |
| 1025 const Code& stub = | 1040 const Code& stub = |
| 1041 #if !defined(TARGET_ARCH_DBC) |
| 1026 Code::Handle(zone, StubCode::MegamorphicLookup_entry()->code()); | 1042 Code::Handle(zone, StubCode::MegamorphicLookup_entry()->code()); |
| 1043 #else |
| 1044 Code::Handle(); |
| 1045 UNREACHABLE(); |
| 1046 #endif |
| 1027 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), | 1047 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), |
| 1028 code, ic_data, cache, stub); | 1048 code, ic_data, cache, stub); |
| 1029 } | 1049 } |
| 1030 } else { | 1050 } else { |
| 1031 const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache); | 1051 const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache); |
| 1032 // Insert function found into cache and return it. | 1052 // Insert function found into cache and return it. |
| 1033 cache.EnsureCapacity(); | 1053 cache.EnsureCapacity(); |
| 1034 const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id())); | 1054 const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id())); |
| 1035 cache.Insert(class_id, target_function); | 1055 cache.Insert(class_id, target_function); |
| 1036 } | 1056 } |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 const Object& result = Object::Handle( | 1225 const Object& result = Object::Handle( |
| 1206 DartEntry::InvokeNoSuchMethod(receiver, | 1226 DartEntry::InvokeNoSuchMethod(receiver, |
| 1207 original_function_name, | 1227 original_function_name, |
| 1208 orig_arguments, | 1228 orig_arguments, |
| 1209 orig_arguments_desc)); | 1229 orig_arguments_desc)); |
| 1210 CheckResultError(result); | 1230 CheckResultError(result); |
| 1211 arguments.SetReturn(result); | 1231 arguments.SetReturn(result); |
| 1212 } | 1232 } |
| 1213 | 1233 |
| 1214 | 1234 |
| 1235 #if !defined(TARGET_ARCH_DBC) |
| 1215 static bool CanOptimizeFunction(const Function& function, Thread* thread) { | 1236 static bool CanOptimizeFunction(const Function& function, Thread* thread) { |
| 1216 if (FLAG_support_debugger) { | 1237 if (FLAG_support_debugger) { |
| 1217 Isolate* isolate = thread->isolate(); | 1238 Isolate* isolate = thread->isolate(); |
| 1218 if (isolate->debugger()->IsStepping() || | 1239 if (isolate->debugger()->IsStepping() || |
| 1219 isolate->debugger()->HasBreakpoint(function, thread->zone())) { | 1240 isolate->debugger()->HasBreakpoint(function, thread->zone())) { |
| 1220 // We cannot set breakpoints and single step in optimized code, | 1241 // We cannot set breakpoints and single step in optimized code, |
| 1221 // so do not optimize the function. | 1242 // so do not optimize the function. |
| 1222 function.set_usage_counter(0); | 1243 function.set_usage_counter(0); |
| 1223 return false; | 1244 return false; |
| 1224 } | 1245 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 // Huge methods (code size above --huge_method_cutoff_in_code_size) become | 1287 // Huge methods (code size above --huge_method_cutoff_in_code_size) become |
| 1267 // non-optimizable only after the code has been generated. | 1288 // non-optimizable only after the code has been generated. |
| 1268 if (FLAG_trace_failed_optimization_attempts) { | 1289 if (FLAG_trace_failed_optimization_attempts) { |
| 1269 THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString()); | 1290 THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString()); |
| 1270 } | 1291 } |
| 1271 function.set_usage_counter(INT_MIN); | 1292 function.set_usage_counter(INT_MIN); |
| 1272 return false; | 1293 return false; |
| 1273 } | 1294 } |
| 1274 return true; | 1295 return true; |
| 1275 } | 1296 } |
| 1297 #endif |
| 1276 | 1298 |
| 1277 | 1299 |
| 1278 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { | 1300 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
| 1279 #if defined(USING_SIMULATOR) | 1301 #if defined(TARGET_ARCH_DBC) |
| 1302 uword stack_pos = Simulator::Current()->sp(); |
| 1303 #elif defined(USING_SIMULATOR) |
| 1280 uword stack_pos = Simulator::Current()->get_register(SPREG); | 1304 uword stack_pos = Simulator::Current()->get_register(SPREG); |
| 1281 #else | 1305 #else |
| 1282 uword stack_pos = Isolate::GetCurrentStackPointer(); | 1306 uword stack_pos = Isolate::GetCurrentStackPointer(); |
| 1283 #endif | 1307 #endif |
| 1284 // Always clear the stack overflow flags. They are meant for this | 1308 // Always clear the stack overflow flags. They are meant for this |
| 1285 // particular stack overflow runtime call and are not meant to | 1309 // particular stack overflow runtime call and are not meant to |
| 1286 // persist. | 1310 // persist. |
| 1287 uword stack_overflow_flags = isolate->GetAndClearStackOverflowFlags(); | 1311 uword stack_overflow_flags = isolate->GetAndClearStackOverflowFlags(); |
| 1288 | 1312 |
| 1289 // If an interrupt happens at the same time as a stack overflow, we | 1313 // If an interrupt happens at the same time as a stack overflow, we |
| 1290 // process the stack overflow now and leave the interrupt for next | 1314 // process the stack overflow now and leave the interrupt for next |
| 1291 // time. | 1315 // time. |
| 1292 if (stack_pos < isolate->saved_stack_limit()) { | 1316 if (IsCalleeFrameOf(isolate->saved_stack_limit(), stack_pos)) { |
| 1293 // Use the preallocated stack overflow exception to avoid calling | 1317 // Use the preallocated stack overflow exception to avoid calling |
| 1294 // into dart code. | 1318 // into dart code. |
| 1295 const Instance& exception = | 1319 const Instance& exception = |
| 1296 Instance::Handle(isolate->object_store()->stack_overflow()); | 1320 Instance::Handle(isolate->object_store()->stack_overflow()); |
| 1297 Exceptions::Throw(thread, exception); | 1321 Exceptions::Throw(thread, exception); |
| 1298 UNREACHABLE(); | 1322 UNREACHABLE(); |
| 1299 } | 1323 } |
| 1300 | 1324 |
| 1301 // The following code is used to stress test deoptimization and | 1325 // The following code is used to stress test deoptimization and |
| 1302 // debugger stack tracing. | 1326 // debugger stack tracing. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1362 } | 1386 } |
| 1363 | 1387 |
| 1364 const Error& error = Error::Handle(isolate->HandleInterrupts()); | 1388 const Error& error = Error::Handle(isolate->HandleInterrupts()); |
| 1365 if (!error.IsNull()) { | 1389 if (!error.IsNull()) { |
| 1366 Exceptions::PropagateError(error); | 1390 Exceptions::PropagateError(error); |
| 1367 UNREACHABLE(); | 1391 UNREACHABLE(); |
| 1368 } | 1392 } |
| 1369 | 1393 |
| 1370 if ((stack_overflow_flags & Isolate::kOsrRequest) != 0) { | 1394 if ((stack_overflow_flags & Isolate::kOsrRequest) != 0) { |
| 1371 ASSERT(FLAG_use_osr); | 1395 ASSERT(FLAG_use_osr); |
| 1396 #if !defined(TARGET_ARCH_DBC) |
| 1372 DartFrameIterator iterator; | 1397 DartFrameIterator iterator; |
| 1373 StackFrame* frame = iterator.NextFrame(); | 1398 StackFrame* frame = iterator.NextFrame(); |
| 1374 ASSERT(frame != NULL); | 1399 ASSERT(frame != NULL); |
| 1375 const Code& code = Code::ZoneHandle(frame->LookupDartCode()); | 1400 const Code& code = Code::ZoneHandle(frame->LookupDartCode()); |
| 1376 ASSERT(!code.IsNull()); | 1401 ASSERT(!code.IsNull()); |
| 1377 const Function& function = Function::Handle(code.function()); | 1402 const Function& function = Function::Handle(code.function()); |
| 1378 ASSERT(!function.IsNull()); | 1403 ASSERT(!function.IsNull()); |
| 1379 // Since the code is referenced from the frame and the ZoneHandle, | 1404 // Since the code is referenced from the frame and the ZoneHandle, |
| 1380 // it cannot have been removed from the function. | 1405 // it cannot have been removed from the function. |
| 1381 ASSERT(function.HasCode()); | 1406 ASSERT(function.HasCode()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 if (optimized_code.raw() != original_code.raw()) { | 1439 if (optimized_code.raw() != original_code.raw()) { |
| 1415 // The OSR code does not work for calling the function, so restore the | 1440 // The OSR code does not work for calling the function, so restore the |
| 1416 // unoptimized code. Patch the stack frame to return into the OSR | 1441 // unoptimized code. Patch the stack frame to return into the OSR |
| 1417 // code. | 1442 // code. |
| 1418 uword optimized_entry = | 1443 uword optimized_entry = |
| 1419 Instructions::Handle(optimized_code.instructions()).EntryPoint(); | 1444 Instructions::Handle(optimized_code.instructions()).EntryPoint(); |
| 1420 function.AttachCode(original_code); | 1445 function.AttachCode(original_code); |
| 1421 frame->set_pc(optimized_entry); | 1446 frame->set_pc(optimized_entry); |
| 1422 frame->set_pc_marker(optimized_code.raw()); | 1447 frame->set_pc_marker(optimized_code.raw()); |
| 1423 } | 1448 } |
| 1449 #endif |
| 1424 } | 1450 } |
| 1425 } | 1451 } |
| 1426 | 1452 |
| 1427 | 1453 |
| 1428 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { | 1454 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { |
| 1429 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); | 1455 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); |
| 1430 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); | 1456 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); |
| 1431 DartFrameIterator iterator; | 1457 DartFrameIterator iterator; |
| 1432 StackFrame* frame = iterator.NextFrame(); | 1458 StackFrame* frame = iterator.NextFrame(); |
| 1433 ASSERT(frame != NULL); | 1459 ASSERT(frame != NULL); |
| 1434 OS::PrintErr("IC call @%#" Px ": ICData: %p cnt:%" Pd " nchecks: %" Pd | 1460 OS::PrintErr("IC call @%#" Px ": ICData: %p cnt:%" Pd " nchecks: %" Pd |
| 1435 " %s\n", | 1461 " %s\n", |
| 1436 frame->pc(), | 1462 frame->pc(), |
| 1437 ic_data.raw(), | 1463 ic_data.raw(), |
| 1438 function.usage_counter(), | 1464 function.usage_counter(), |
| 1439 ic_data.NumberOfChecks(), | 1465 ic_data.NumberOfChecks(), |
| 1440 function.ToFullyQualifiedCString()); | 1466 function.ToFullyQualifiedCString()); |
| 1441 } | 1467 } |
| 1442 | 1468 |
| 1443 | 1469 |
| 1444 // This is called from function that needs to be optimized. | 1470 // This is called from function that needs to be optimized. |
| 1445 // The requesting function can be already optimized (reoptimization). | 1471 // The requesting function can be already optimized (reoptimization). |
| 1446 // Returns the Code object where to continue execution. | 1472 // Returns the Code object where to continue execution. |
| 1447 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { | 1473 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { |
| 1448 #if !defined(DART_PRECOMPILED_RUNTIME) | 1474 #if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) |
| 1449 const Function& function = Function::CheckedHandle(zone, | 1475 const Function& function = Function::CheckedHandle(zone, |
| 1450 arguments.ArgAt(0)); | 1476 arguments.ArgAt(0)); |
| 1451 ASSERT(!function.IsNull()); | 1477 ASSERT(!function.IsNull()); |
| 1452 ASSERT(function.HasCode()); | 1478 ASSERT(function.HasCode()); |
| 1453 | 1479 |
| 1454 if (CanOptimizeFunction(function, thread)) { | 1480 if (CanOptimizeFunction(function, thread)) { |
| 1455 if (FLAG_background_compilation) { | 1481 if (FLAG_background_compilation) { |
| 1456 Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField()); | 1482 Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField()); |
| 1457 while (!field.IsNull()) { | 1483 while (!field.IsNull()) { |
| 1458 if (FLAG_trace_optimization || FLAG_trace_field_guards) { | 1484 if (FLAG_trace_optimization || FLAG_trace_field_guards) { |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1918 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
| 1893 const TypedData& new_data = | 1919 const TypedData& new_data = |
| 1894 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1920 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
| 1895 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1921 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
| 1896 typed_data_cell.SetAt(0, new_data); | 1922 typed_data_cell.SetAt(0, new_data); |
| 1897 arguments.SetReturn(new_data); | 1923 arguments.SetReturn(new_data); |
| 1898 } | 1924 } |
| 1899 | 1925 |
| 1900 | 1926 |
| 1901 } // namespace dart | 1927 } // namespace dart |
| OLD | NEW |