Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Unified Diff: runtime/vm/code_generator.cc

Issue 2226893002: Optimize AOT's switchable calls for the monomorphic case. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: sync Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/clustered_snapshot.cc ('k') | runtime/vm/code_patcher.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator.cc
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index bc9689c2fe3bb0ad5daa9d5785f86ac52aa31c43..ca1ba0bd52d019871ef330fb12e04197e41ccf63 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -671,7 +671,7 @@ DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) {
" to '%s' new entry point %#" Px " (%s)\n",
caller_frame->pc(),
target_function.ToFullyQualifiedCString(),
- target_code.EntryPoint(),
+ target_code.UncheckedEntryPoint(),
target_code.is_optimized() ? "optimized" : "unoptimized");
}
arguments.SetReturn(target_code);
@@ -1028,12 +1028,88 @@ DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) {
// Handle a miss of a megamorphic cache.
// Arg0: Receiver.
+// Returns: the ICData used to continue with a polymorphic call.
+DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) {
+#if defined(TARGET_ARCH_DBC)
+ // DBC does not use switchable calls.
+ UNREACHABLE();
+#else
+ const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+
+ DartFrameIterator iterator;
+ StackFrame* caller_frame = iterator.NextFrame();
+ ASSERT(caller_frame->IsDartFrame());
+ const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
+ const Function& caller_function =
+ Function::Handle(zone, caller_frame->LookupDartFunction());
+
+ Smi& old_expected_cid = Smi::Handle(zone);
+ old_expected_cid ^= CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(),
+ caller_code);
+ const Code& old_target_code =
+ Code::Handle(CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(),
+ caller_code));
+ Function& old_target = Function::Handle(zone);
+ old_target ^= old_target_code.owner();
+
+ // We lost the original ICData when we patched to the monomorphic case.
+ const String& name = String::Handle(zone, old_target.name());
+ ASSERT(!old_target.HasOptionalParameters());
+ const Array& descriptor = Array::Handle(zone,
+ ArgumentsDescriptor::New(old_target.num_fixed_parameters()));
+ const ICData& ic_data =
+ ICData::Handle(zone, ICData::New(caller_function,
+ name,
+ descriptor,
+ Thread::kNoDeoptId,
+ 1, /* args_tested */
+ false /* static_call */));
+
+ // Add the first target.
+ ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target);
+
+ // Maybe add the new target.
+ Class& cls = Class::Handle(zone, receiver.clazz());
+ ArgumentsDescriptor args_desc(descriptor);
+ Function& target_function = Function::Handle(zone,
+ Resolver::ResolveDynamicForReceiverClass(cls,
+ name,
+ args_desc));
+ if (target_function.IsNull()) {
+ target_function = InlineCacheMissHelper(receiver, descriptor, name);
+ }
+ if (target_function.IsNull()) {
+ ASSERT(!FLAG_lazy_dispatchers);
+ } else {
+ ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
+ }
+
+ // Patch to call through stub.
+ const Code& stub =
+ Code::Handle(zone, StubCode::ICLookupThroughCode_entry()->code());
+ ASSERT(!Isolate::Current()->compilation_allowed());
+ CodePatcher::PatchSwitchableCallAt(caller_frame->pc(),
+ caller_code,
+ ic_data,
+ stub);
+
+ // Return the ICData. The miss stub will jump to continue in the IC lookup
+ // stub.
+ arguments.SetReturn(ic_data);
+#endif // !defined(TARGET_ARCH_DBC)
+}
+
+
+// Handle a miss of a megamorphic cache.
+// Arg0: Receiver.
// Arg1: ICData or MegamorphicCache.
// Arg2: Arguments descriptor array.
// Returns: target function to call.
DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
-// DBC does not use megamorphic calls right now.
-#if !defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_DBC)
+ // DBC does not use megamorphic calls right now.
+ UNREACHABLE();
+#else
const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1));
const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(2));
@@ -1067,21 +1143,58 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
if (ic_data_or_cache.IsICData()) {
const ICData& ic_data = ICData::Cast(ic_data_or_cache);
- ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
- if (ic_data.NumberOfChecks() > FLAG_max_polymorphic_checks) {
- // Switch to megamorphic call.
- const MegamorphicCache& cache = MegamorphicCache::Handle(zone,
- MegamorphicCacheTable::Lookup(isolate, name, descriptor));
+
+ if ((ic_data.NumberOfChecks() == 0) &&
+ !target_function.HasOptionalParameters() &&
+ !Isolate::Current()->compilation_allowed()) {
+ // This call site is unlinked: transition to a monomorphic direct call.
+ // Note we cannot do this if the target has optional parameters because
+ // the monomorphic direct call does not load the arguments descriptor.
+ // We cannot do this if we are still in the middle of precompiling because
+ // the monomorphic case hides an live instance selector from the
+ // treeshaker.
+
+ if (!target_function.HasCode()) {
+ const Error& error =
+ Error::Handle(Compiler::CompileFunction(thread, target_function));
+ if (!error.IsNull()) {
+ Exceptions::PropagateError(error);
+ }
+ }
+
DartFrameIterator iterator;
StackFrame* miss_function_frame = iterator.NextFrame();
ASSERT(miss_function_frame->IsDartFrame());
StackFrame* caller_frame = iterator.NextFrame();
ASSERT(caller_frame->IsDartFrame());
- const Code& code = Code::Handle(zone, caller_frame->LookupDartCode());
- const Code& stub =
- Code::Handle(zone, StubCode::MegamorphicLookup_entry()->code());
- CodePatcher::PatchSwitchableCallAt(caller_frame->pc(),
- code, ic_data, cache, stub);
+ const Code& caller_code =
+ Code::Handle(zone, caller_frame->LookupDartCode());
+ const Code& target_code =
+ Code::Handle(zone, target_function.CurrentCode());
+ const Smi& expected_cid =
+ Smi::Handle(zone, Smi::New(receiver.GetClassId()));
+
+ CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
+ expected_cid, target_code);
+ } else {
+ ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
+ if (ic_data.NumberOfChecks() > FLAG_max_polymorphic_checks) {
+ // Switch to megamorphic call.
+ const MegamorphicCache& cache = MegamorphicCache::Handle(zone,
+ MegamorphicCacheTable::Lookup(isolate, name, descriptor));
+ DartFrameIterator iterator;
+ StackFrame* miss_function_frame = iterator.NextFrame();
+ ASSERT(miss_function_frame->IsDartFrame());
+ StackFrame* caller_frame = iterator.NextFrame();
+ ASSERT(caller_frame->IsDartFrame());
+ const Code& caller_code =
+ Code::Handle(zone, caller_frame->LookupDartCode());
+ const Code& stub =
+ Code::Handle(zone, StubCode::MegamorphicLookup_entry()->code());
+
+ CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
+ cache, stub);
+ }
}
} else {
const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache);
@@ -1091,8 +1204,6 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
cache.Insert(class_id, target_function);
}
arguments.SetReturn(target_function);
-#else
- UNREACHABLE();
#endif // !defined(TARGET_ARCH_DBC)
}
@@ -1461,7 +1572,7 @@ DEFINE_RUNTIME_ENTRY(StackOverflow, 0) {
// unoptimized code. Patch the stack frame to return into the OSR
// code.
uword optimized_entry =
- Instructions::Handle(optimized_code.instructions()).EntryPoint();
+ Instructions::UncheckedEntryPoint(optimized_code.instructions());
function.AttachCode(original_code);
frame->set_pc(optimized_entry);
frame->set_pc_marker(optimized_code.raw());
@@ -1596,7 +1707,7 @@ DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) {
"target '%s' -> %#" Px "\n",
frame->pc(),
target_function.ToFullyQualifiedCString(),
- current_target_code.EntryPoint());
+ current_target_code.UncheckedEntryPoint());
}
arguments.SetReturn(current_target_code);
}
@@ -1638,7 +1749,7 @@ DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) {
" -> %#" Px "\n",
frame->pc(),
alloc_class.ToCString(),
- alloc_stub.EntryPoint());
+ alloc_stub.UncheckedEntryPoint());
}
arguments.SetReturn(alloc_stub);
#else
@@ -1690,7 +1801,7 @@ void DeoptimizeAt(const Code& optimized_code, uword pc) {
const Instructions& instrs =
Instructions::Handle(zone, optimized_code.instructions());
{
- WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+ WritableInstructionsScope writable(instrs.PayloadStart(), instrs.size());
CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump);
}
if (FLAG_trace_patching) {
« no previous file with comments | « runtime/vm/clustered_snapshot.cc ('k') | runtime/vm/code_patcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698