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

Side by Side Diff: runtime/vm/code_generator.cc

Issue 10010029: When checking against non-parametrized types use a cache to hold result tuples (class, result). Tha… (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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/code_index_table.h" 7 #include "vm/code_index_table.h"
8 #include "vm/code_patcher.h" 8 #include "vm/code_patcher.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_api_impl.h" 10 #include "vm/dart_api_impl.h"
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 for (int i = 0; i < ctx.num_variables(); i++) { 299 for (int i = 0; i < ctx.num_variables(); i++) {
300 cloned_ctx.SetAt(i, Instance::Handle(ctx.At(i))); 300 cloned_ctx.SetAt(i, Instance::Handle(ctx.At(i)));
301 } 301 }
302 arguments.SetReturn(cloned_ctx); 302 arguments.SetReturn(cloned_ctx);
303 } 303 }
304 304
305 305
306 // Check that the given instance is an instance of the given type. 306 // Check that the given instance is an instance of the given type.
307 // Tested instance may not be null, because the null test is inlined. 307 // Tested instance may not be null, because the null test is inlined.
308 // Arg0: index of the token of the instanceof test (source location). 308 // Arg0: index of the token of the instanceof test (source location).
309 // Arg1: instance being checked. 309 // Arg1: node id of the instanceof node.
310 // Arg2: type. 310 // Arg2: instance being checked.
311 // Arg3: type arguments of the instantiator of the type. 311 // Arg3: type.
312 // Arg4: type arguments of the instantiator of the type.
312 // Return value: true or false, or may throw a type error in checked mode. 313 // Return value: true or false, or may throw a type error in checked mode.
313 DEFINE_RUNTIME_ENTRY(Instanceof, 4) { 314 DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
314 ASSERT(arguments.Count() == kInstanceofRuntimeEntry.argument_count()); 315 ASSERT(arguments.Count() == kInstanceofRuntimeEntry.argument_count());
315 // TODO(regis): Get the token index from the PcDesc (via DartFrame). 316 // TODO(regis): Get the token index from the PcDesc (via DartFrame).
316 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); 317 intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value();
317 const Instance& instance = Instance::CheckedHandle(arguments.At(1)); 318 intptr_t node_id = Smi::CheckedHandle(arguments.At(1)).Value();
318 const AbstractType& type = AbstractType::CheckedHandle(arguments.At(2)); 319 const Instance& instance = Instance::CheckedHandle(arguments.At(2));
320 const AbstractType& type = AbstractType::CheckedHandle(arguments.At(3));
319 const AbstractTypeArguments& type_instantiator = 321 const AbstractTypeArguments& type_instantiator =
320 AbstractTypeArguments::CheckedHandle(arguments.At(3)); 322 AbstractTypeArguments::CheckedHandle(arguments.At(4));
321 ASSERT(type.IsFinalized()); 323 ASSERT(type.IsFinalized());
322 Error& malformed_error = Error::Handle(); 324 Error& malformed_error = Error::Handle();
323 const Bool& result = Bool::Handle( 325 const Bool& result = Bool::Handle(
324 instance.IsInstanceOf(type, type_instantiator, &malformed_error) ? 326 instance.IsInstanceOf(type, type_instantiator, &malformed_error) ?
325 Bool::True() : Bool::False()); 327 Bool::True() : Bool::False());
326 if (FLAG_trace_type_checks) { 328 if (FLAG_trace_type_checks) {
327 const Type& instance_type = Type::Handle(instance.GetType()); 329 const Type& instance_type = Type::Handle(instance.GetType());
328 ASSERT(instance_type.IsInstantiated()); 330 ASSERT(instance_type.IsInstantiated());
329 if (type.IsInstantiated()) { 331 if (type.IsInstantiated()) {
330 OS::Print("InstanceOf: '%s' %s '%s'.\n", 332 OS::Print("InstanceOf: '%s' %s '%s'.\n",
(...skipping 20 matching lines...) Expand all
351 if (!result.value() && !malformed_error.IsNull()) { 353 if (!result.value() && !malformed_error.IsNull()) {
352 ASSERT(FLAG_enable_type_checks); 354 ASSERT(FLAG_enable_type_checks);
353 // Throw a dynamic type error only if the instanceof test fails. 355 // Throw a dynamic type error only if the instanceof test fails.
354 String& malformed_error_message = String::Handle( 356 String& malformed_error_message = String::Handle(
355 String::New(malformed_error.ToErrorCString())); 357 String::New(malformed_error.ToErrorCString()));
356 const String& no_name = String::Handle(String::NewSymbol("")); 358 const String& no_name = String::Handle(String::NewSymbol(""));
357 Exceptions::CreateAndThrowTypeError( 359 Exceptions::CreateAndThrowTypeError(
358 location, no_name, no_name, no_name, malformed_error_message); 360 location, no_name, no_name, no_name, malformed_error_message);
359 UNREACHABLE(); 361 UNREACHABLE();
360 } 362 }
363 // Update cache: add class of instance and result.
364 if (type.IsInstantiated() &&
365 !Class::Handle(type.type_class()).HasTypeArguments()) {
366 DartFrameIterator iterator;
367 DartFrame* caller_frame = iterator.NextFrame();
368 ASSERT(caller_frame != NULL);
369 const Code& code = Code::Handle(caller_frame->LookupDartCode());
370 ASSERT(!code.IsNull());
371 uword loc = code.GetTypeTestAtNodeId(node_id);
372 // TODO(srdjan): Check when 'loc' can be 0, once implemented everywhere.
373 if (loc != 0) {
374 // Found type test cache.
375 Array& value = Array::Handle(CodePatcher::GetTypeTestArray(loc));
376 const Class& instance_class = Class::Handle(instance.clazz());
377
378 #if defined(DEBUG)
379 // Check for duplicate entries.
380 Class& last_checked = Class::Handle();
381 for (intptr_t i = 0; i < value.Length(); i += 2) {
382 last_checked ^= value.At(i);
383 ASSERT(last_checked.raw() != instance_class.raw());
384 }
385 // Array must be null terminated.
386 ASSERT(last_checked.IsNull());
387 #endif
388
389 ASSERT(!value.IsNull());
390 intptr_t old_len = value.Length();
391 value = value.Grow(value, old_len + 2);
392 value.SetAt(old_len - 2, instance_class);
393 value.SetAt(old_len - 1, result);
394 CodePatcher::SetTypeTestArray(loc, value);
395 }
396 }
361 arguments.SetReturn(result); 397 arguments.SetReturn(result);
362 } 398 }
363 399
364 400
365 // For error reporting simplify type name, e.g, all integer types (Smi, Mint, 401 // For error reporting simplify type name, e.g, all integer types (Smi, Mint,
366 // Bigint) a re reported as 'int'. 402 // Bigint) a re reported as 'int'.
367 static RawString* GetSimpleTypeName(const Instance& value) { 403 static RawString* GetSimpleTypeName(const Instance& value) {
368 if (value.IsInteger()) { 404 if (value.IsInteger()) {
369 return String::NewSymbol("int"); 405 return String::NewSymbol("int");
370 } else { 406 } else {
(...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 } 1432 }
1397 } 1433 }
1398 } 1434 }
1399 // The cache is null terminated, therefore the loop above should never 1435 // The cache is null terminated, therefore the loop above should never
1400 // terminate by itself. 1436 // terminate by itself.
1401 UNREACHABLE(); 1437 UNREACHABLE();
1402 return Code::null(); 1438 return Code::null();
1403 } 1439 }
1404 1440
1405 } // namespace dart 1441 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698