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

Unified Diff: runtime/vm/code_generator.cc

Issue 1418863003: Precompilation: Generate instance calls as IC calls that can switch to Megamoprhic calls. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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 | « no previous file | 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 bc33bca5998156f222e6cc78b0f023b858511200..9b3eb295c83059e52210650f7fca07def7f3d33b 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -61,6 +61,7 @@ DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
DECLARE_FLAG(int, deoptimization_counter_threshold);
DECLARE_FLAG(bool, trace_compiler);
DECLARE_FLAG(bool, warn_on_javascript_compatibility);
+DECLARE_FLAG(int, max_polymorphic_checks);
DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement.");
DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement.");
@@ -779,11 +780,9 @@ static bool ResolveCallThroughGetter(const Instance& receiver,
// Handle other invocations (implicit closures, noSuchMethod).
RawFunction* InlineCacheMissHelper(
const Instance& receiver,
- const ICData& ic_data) {
- const Array& args_descriptor = Array::Handle(ic_data.arguments_descriptor());
-
+ const Array& args_descriptor,
+ const String& target_name) {
const Class& receiver_class = Class::Handle(receiver.clazz());
- const String& target_name = String::Handle(ic_data.target_name());
Function& result = Function::Handle();
if (!ResolveCallThroughGetter(receiver,
@@ -828,7 +827,12 @@ static RawFunction* InlineCacheMissHandler(
String::Handle(ic_data.target_name()).ToCString(),
receiver.ToCString());
}
- target_function = InlineCacheMissHelper(receiver, ic_data);
+ const Array& args_descriptor =
+ Array::Handle(ic_data.arguments_descriptor());
+ const String& target_name = String::Handle(ic_data.target_name());
+ target_function = InlineCacheMissHelper(receiver,
+ args_descriptor,
+ target_name);
}
if (target_function.IsNull()) {
ASSERT(!FLAG_lazy_dispatchers);
@@ -1008,18 +1012,21 @@ DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) {
// Handle a miss of a megamorphic cache.
// Arg0: Receiver.
-// Arg1: ICData object.
+// Arg1: ICData or MegamorphicCache.
// Arg2: Arguments descriptor array.
-
// Returns: target function to call.
DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
- const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
- const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
- const Array& descriptor = Array::CheckedHandle(arguments.ArgAt(2));
- const String& name = String::Handle(ic_data.target_name());
- const MegamorphicCache& cache = MegamorphicCache::Handle(
- MegamorphicCacheTable::Lookup(isolate, name, descriptor));
- Class& cls = Class::Handle(receiver.clazz());
+ 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));
+ String& name = String::Handle(zone);
+ if (ic_data_or_cache.IsICData()) {
+ name = ICData::Cast(ic_data_or_cache).target_name();
+ } else {
+ ASSERT(ic_data_or_cache.IsMegamorphicCache());
+ name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
+ }
+ Class& cls = Class::Handle(zone, receiver.clazz());
ASSERT(!cls.IsNull());
if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) {
OS::PrintErr("Megamorphic IC miss, class=%s, function=%s\n",
@@ -1027,41 +1034,70 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
}
ArgumentsDescriptor args_desc(descriptor);
- Function& target_function = Function::Handle(
+ Function& target_function = Function::Handle(zone,
Resolver::ResolveDynamicForReceiverClass(cls,
name,
args_desc));
if (target_function.IsNull()) {
- target_function = InlineCacheMissHelper(receiver, ic_data);
+ target_function = InlineCacheMissHelper(receiver, descriptor, name);
}
if (target_function.IsNull()) {
ASSERT(!FLAG_lazy_dispatchers);
arguments.SetReturn(target_function);
return;
}
- // Insert function found into cache and return it.
- cache.EnsureCapacity();
- const Smi& class_id = Smi::Handle(Smi::New(cls.id()));
- cache.Insert(class_id, target_function);
+
+ 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));
+ 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);
+ }
+ } else {
+ const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache);
+ // Insert function found into cache and return it.
+ cache.EnsureCapacity();
+ const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id()));
+ cache.Insert(class_id, target_function);
+ }
arguments.SetReturn(target_function);
}
// Invoke appropriate noSuchMethod or closure from getter.
// Arg0: receiver
-// Arg1: IC data
+// Arg1: ICData or MegamorphicCache
// Arg2: arguments descriptor array
// Arg3: arguments array
DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
ASSERT(!FLAG_lazy_dispatchers);
- const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
- const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
- const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2));
- const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3));
- const String& target_name = String::Handle(ic_data.target_name());
+ const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+ const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1));
+ const Array& orig_arguments_desc =
+ Array::CheckedHandle(zone, arguments.ArgAt(2));
+ const Array& orig_arguments = Array::CheckedHandle(zone, arguments.ArgAt(3));
+ String& target_name = String::Handle(zone);
+ if (ic_data_or_cache.IsICData()) {
+ target_name = ICData::Cast(ic_data_or_cache).target_name();
+ } else {
+ ASSERT(ic_data_or_cache.IsMegamorphicCache());
+ target_name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
+ }
- Class& cls = Class::Handle(receiver.clazz());
- Function& function = Function::Handle();
+ Class& cls = Class::Handle(zone, receiver.clazz());
+ Function& function = Function::Handle(zone);
// Dart distinguishes getters and regular methods and allows their calls
// to mix with conversions, and its selectors are independent of arity. So do
@@ -1069,7 +1105,7 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
// need for conversion, or there really is no such method.
#define NO_SUCH_METHOD() \
- const Object& result = Object::Handle( \
+ const Object& result = Object::Handle(zone, \
DartEntry::InvokeNoSuchMethod(receiver, \
target_name, \
orig_arguments, \
@@ -1079,9 +1115,9 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
#define CLOSURIZE(some_function) \
const Function& closure_function = \
- Function::Handle(some_function.ImplicitClosureFunction()); \
+ Function::Handle(zone, some_function.ImplicitClosureFunction()); \
const Object& result = \
- Object::Handle(closure_function.ImplicitInstanceClosure(receiver)); \
+ Object::Handle(zone, closure_function.ImplicitInstanceClosure(receiver));\
arguments.SetReturn(result); \
const bool is_getter = Field::IsGetterName(target_name);
@@ -1091,7 +1127,7 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
// encountered first on the inheritance chain. Or,
// o#foo= (o.get:#set:foo) failed, closurize o.foo= if it exists.
String& field_name =
- String::Handle(Field::NameFromGetter(target_name));
+ String::Handle(zone, Field::NameFromGetter(target_name));
const bool is_extractor = field_name.CharAt(0) == '#';
if (is_extractor) {
@@ -1143,14 +1179,15 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
// call method and with lazy dispatchers the field-invocation-dispatcher
// would perform the closure call.
const Object& result =
- Object::Handle(DartEntry::InvokeClosure(orig_arguments,
- orig_arguments_desc));
+ Object::Handle(zone, DartEntry::InvokeClosure(orig_arguments,
+ orig_arguments_desc));
CheckResultError(result);
arguments.SetReturn(result);
return;
}
- const String& getter_name = String::Handle(Field::GetterName(target_name));
+ const String& getter_name =
+ String::Handle(zone, Field::GetterName(target_name));
while (!cls.IsNull()) {
function ^= cls.LookupDynamicFunction(target_name);
if (!function.IsNull()) {
@@ -1163,15 +1200,15 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
const Array& getter_arguments = Array::Handle(Array::New(1));
getter_arguments.SetAt(0, receiver);
const Object& getter_result =
- Object::Handle(DartEntry::InvokeFunction(function,
- getter_arguments));
+ Object::Handle(zone, DartEntry::InvokeFunction(function,
+ getter_arguments));
CheckResultError(getter_result);
ASSERT(getter_result.IsNull() || getter_result.IsInstance());
orig_arguments.SetAt(0, getter_result);
const Object& call_result =
- Object::Handle(DartEntry::InvokeClosure(orig_arguments,
- orig_arguments_desc));
+ Object::Handle(zone, DartEntry::InvokeClosure(orig_arguments,
+ orig_arguments_desc));
CheckResultError(call_result);
arguments.SetReturn(call_result);
return;
« no previous file with comments | « no previous file | runtime/vm/code_patcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698