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

Unified Diff: runtime/vm/code_generator.cc

Issue 10352012: Using SubtypeTestCache object instead of an array, that way we do not need to patch and can communi… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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
Index: runtime/vm/code_generator.cc
===================================================================
--- runtime/vm/code_generator.cc (revision 7292)
+++ runtime/vm/code_generator.cc (working copy)
@@ -451,105 +451,69 @@
const Instance& instance,
const AbstractType& type,
const AbstractTypeArguments& type_instantiator,
- const Bool& result) {
+ const Bool& result,
+ const SubtypeTestCache& new_cache) {
// Since the test is expensive, don't do it unless necessary.
// The list of disallowed cases will decrease as they are implemented in
// inlined assembly.
- if (!type.IsInstantiated()) return;
- if (Class::Handle(type.type_class()).HasTypeArguments()) {
- const AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::Handle(type.arguments());
- const bool is_raw_type = type_arguments.IsNull() ||
- type_arguments.IsRaw(type_arguments.Length());
- if (!is_raw_type) {
- // We cannot inline tests for instances with more than one type argument
- // or if its class has not been resolved (malformed type).
- if (type_arguments.Length() != 1) {
- // We can handle only one argument so far.
- return;
- }
- const AbstractType& tp_argument =
- AbstractType::ZoneHandle(type_arguments.TypeAt(0));
- if (!tp_argument.IsType()) {
- // E.g, it is TypeParameter.
- return;
- }
- ASSERT(tp_argument.HasResolvedTypeClass());
- }
- }
+ if (new_cache.IsNull()) return;
AbstractTypeArguments& instance_type_arguments =
AbstractTypeArguments::Handle();
const Class& instance_class = Class::Handle(instance.clazz());
AbstractTypeArguments& original_instance_type_arguments =
AbstractTypeArguments::Handle();
if (instance_class.HasTypeArguments()) {
+ // Canonicalize type arguments.
original_instance_type_arguments = instance.GetTypeArguments();
OptimizeTypeArguments(instance);
instance_type_arguments = instance.GetTypeArguments();
}
- DartFrameIterator iterator;
- StackFrame* caller_frame = iterator.NextFrame();
- ASSERT(caller_frame != NULL);
- const Code& code = Code::Handle(caller_frame->LookupDartCode());
- ASSERT(!code.IsNull());
- uword loc = code.GetTypeTestAtNodeId(node_id);
- if (loc != 0) {
- // Found type test cache.
- Array& cache = Array::Handle(CodePatcher::GetTypeTestArray(loc));
- // TODO(srdjan): Prevent type test cache from growing too much, it has been
- // observed to grow to 100 elements.
- // Don't enter duplicate entries.
- // TODO(srdjan): Check instantiator type arguments as well.
- Object& last_instance_class = Object::Handle();
- Object& last_instance_type_arguments = Object::Handle();
- // Check for duplicate entries (can happen if we optimized type arguments
- // above).
- for (intptr_t i = 0; i < cache.Length();
- i += SubTypeTestCache::kNumEntries) {
- last_instance_class = cache.At(i + SubTypeTestCache::kInstanceClass);
- last_instance_type_arguments =
- cache.At(i + SubTypeTestCache::kInstanceTypeArguments);
- if ((last_instance_class.raw() == instance_class.raw()) &&
- (last_instance_type_arguments.raw() ==
- instance_type_arguments.raw())) {
- if (FLAG_trace_type_checks &&
- (original_instance_type_arguments.raw() ==
- instance_type_arguments.raw())) {
+ Class& last_instance_class = Class::Handle();
+ AbstractTypeArguments& last_instance_type_arguments =
+ AbstractTypeArguments::Handle();
+ AbstractTypeArguments& last_instantiator_type_arguments =
+ AbstractTypeArguments::Handle();
+ Bool& last_result = Bool::Handle();
+ intptr_t len = new_cache.NumberOfChecks();
+ for (intptr_t i = 0; i < len; ++i) {
+ new_cache.GetCheck(i, &last_instance_class,
+ &last_instance_type_arguments,
regis 2012/05/03 20:59:11 Interesting indentation
srdjan 2012/05/03 21:51:08 Made it conventional.
+ &last_instantiator_type_arguments,
+ &last_result);
+ if ((last_instance_class.raw() == instance_class.raw()) &&
+ (last_instance_type_arguments.raw() ==
+ instance_type_arguments.raw())) {
+ if (FLAG_trace_type_checks) {
+ if (original_instance_type_arguments.raw() ==
+ instance_type_arguments.raw()) {
PrintTypeCheck("WARNING duplicate cache entry", instance, type,
type_instantiator, result);
}
- return;
}
+ // A duplicate entry found, likely because the instance type arguments
+ // were not cacnonicalized before.
+ return;
}
-
- // Array must be null terminated.
- ASSERT(last_instance_class.IsNull());
- ASSERT(!cache.IsNull());
- // Cache is null terminate, i.e., the last entry contains all null elements.
- intptr_t old_len = cache.Length();
- cache = cache.Grow(cache, old_len + SubTypeTestCache::kNumEntries);
- intptr_t last_start = old_len - SubTypeTestCache::kNumEntries;
- cache.SetAt(last_start + SubTypeTestCache::kInstanceClass, instance_class);
- cache.SetAt(last_start + SubTypeTestCache::kInstanceTypeArguments,
- instance_type_arguments);
- // TODO(srdjan): Store instantiator arguments instead of null.
- cache.SetAt(last_start + SubTypeTestCache::kInstantiatorTypeArguments,
- AbstractTypeArguments::Handle());
- cache.SetAt(last_start + SubTypeTestCache::kTestResult , result);
- if (FLAG_trace_type_checks) {
- OS::Print(" Updated test cache: [0x%x %s, 0x%x %s]\n"
- " [0x%x %s] %s\n",
- instance_class.raw(),
- instance_class.ToCString(),
- instance_type_arguments.raw(),
- instance_type_arguments.ToCString(),
- type.type_class(),
- Class::Handle(type.type_class()).ToCString(),
- result.ToCString());
- }
- CodePatcher::SetTypeTestArray(loc, cache);
}
+ new_cache.AddCheck(instance_class,
+ instance_type_arguments,
+ AbstractTypeArguments::Handle(),
+ result);
+ if (FLAG_trace_type_checks) {
+ OS::Print(" Updated test cache 0x%x ix:%d:\n"
+ " [0x%x %s, 0x%x %s]\n"
+ " [0x%x %s] %s\n",
+ new_cache.raw(),
regis 2012/05/03 20:59:11 indentation
regis 2012/05/03 20:59:11 indentation
srdjan 2012/05/03 21:51:08 Done.
srdjan 2012/05/03 21:51:08 Done.
+ len,
+ instance_class.raw(),
+ instance_class.ToCString(),
+ instance_type_arguments.raw(),
+ instance_type_arguments.ToCString(),
+ type.type_class(),
+ Class::Handle(type.type_class()).ToCString(),
+ result.ToCString());
+ }
}
@@ -560,8 +524,9 @@
// Arg2: instance being checked.
// Arg3: type.
// Arg4: type arguments of the instantiator of the type.
+// Arg5: SubtypeTestCache.
// Return value: true or false, or may throw a type error in checked mode.
-DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
+DEFINE_RUNTIME_ENTRY(Instanceof, 6) {
ASSERT(arguments.Count() == kInstanceofRuntimeEntry.argument_count());
// TODO(regis): Get the token index from the PcDesc (via DartFrame).
intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value();
@@ -570,6 +535,8 @@
const AbstractType& type = AbstractType::CheckedHandle(arguments.At(3));
const AbstractTypeArguments& type_instantiator =
AbstractTypeArguments::CheckedHandle(arguments.At(4));
+ const SubtypeTestCache& cache =
+ SubtypeTestCache::CheckedHandle(arguments.At(5));
ASSERT(type.IsFinalized());
Error& malformed_error = Error::Handle();
const Bool& result = Bool::Handle(
@@ -587,7 +554,8 @@
location, no_name, no_name, no_name, malformed_error_message);
UNREACHABLE();
}
- UpdateTypeTestCache(node_id, instance, type, type_instantiator, result);
+ UpdateTypeTestCache(
+ node_id, instance, type, type_instantiator, result, cache);
arguments.SetReturn(result);
}
@@ -607,12 +575,13 @@
// can therefore be assigned.
// Arg0: index of the token of the assignment (source location).
// Arg1: node-id of the assignemnt.
-// Arg1: instance being assigned.
-// Arg2: type being assigned to.
-// Arg3: type arguments of the instantiator of the type being assigned to.
-// Arg4: name of variable being assigned to.
+// Arg2: instance being assigned.
+// Arg3: type being assigned to.
+// Arg4: type arguments of the instantiator of the type being assigned to.
+// Arg5: name of variable being assigned to.
+// Arg6: SubtypeTestCache.
// Return value: instance if a subtype, otherwise throw a TypeError.
-DEFINE_RUNTIME_ENTRY(TypeCheck, 6) {
+DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
ASSERT(arguments.Count() == kTypeCheckRuntimeEntry.argument_count());
// TODO(regis): Get the token index from the PcDesc (via DartFrame).
intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value();
@@ -622,6 +591,8 @@
const AbstractTypeArguments& dst_type_instantiator =
AbstractTypeArguments::CheckedHandle(arguments.At(4));
const String& dst_name = String::CheckedHandle(arguments.At(5));
+ const SubtypeTestCache& cache =
+ SubtypeTestCache::CheckedHandle(arguments.At(6));
ASSERT(!dst_type.IsDynamicType()); // No need to check assignment.
ASSERT(!dst_type.IsMalformed()); // Already checked in code generator.
ASSERT(!src_instance.IsNull()); // Already checked in inlined code.
@@ -655,7 +626,7 @@
UNREACHABLE();
}
UpdateTypeTestCache(node_id, src_instance, dst_type, dst_type_instantiator,
- Bool::ZoneHandle(Bool::True()));
+ Bool::ZoneHandle(Bool::True()), cache);
arguments.SetReturn(src_instance);
}

Powered by Google App Engine
This is Rietveld 408576698