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

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

Issue 12473002: Complete implementation of bounds checking in the vm, by introducing a vm object (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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
« no previous file with comments | « runtime/vm/class_finalizer.cc ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/bigint_operations.h" 9 #include "vm/bigint_operations.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 ASSERT(arguments.ArgCount() == 174 ASSERT(arguments.ArgCount() ==
175 kAllocateObjectWithBoundsCheckRuntimeEntry.argument_count()); 175 kAllocateObjectWithBoundsCheckRuntimeEntry.argument_count());
176 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); 176 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
177 const Instance& instance = Instance::Handle(Instance::New(cls)); 177 const Instance& instance = Instance::Handle(Instance::New(cls));
178 arguments.SetReturn(instance); 178 arguments.SetReturn(instance);
179 ASSERT(cls.HasTypeArguments()); 179 ASSERT(cls.HasTypeArguments());
180 AbstractTypeArguments& type_arguments = 180 AbstractTypeArguments& type_arguments =
181 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 181 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
182 ASSERT(type_arguments.IsNull() || 182 ASSERT(type_arguments.IsNull() ||
183 (type_arguments.Length() == cls.NumTypeArguments())); 183 (type_arguments.Length() == cls.NumTypeArguments()));
184 AbstractTypeArguments& bounds_instantiator = AbstractTypeArguments::Handle();
185 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) { 184 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
186 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() == 185 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
187 StubCode::kNoInstantiator); 186 StubCode::kNoInstantiator);
188 } else { 187 } else {
189 ASSERT(!type_arguments.IsInstantiated()); 188 ASSERT(!type_arguments.IsInstantiated());
190 const AbstractTypeArguments& instantiator = 189 const AbstractTypeArguments& instantiator =
191 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2)); 190 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
192 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 191 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
192 Error& malformed_error = Error::Handle();
193 if (instantiator.IsNull()) { 193 if (instantiator.IsNull()) {
194 type_arguments = 194 type_arguments = type_arguments.InstantiateFrom(instantiator,
195 InstantiatedTypeArguments::New(type_arguments, instantiator); 195 &malformed_error);
196 } else if (instantiator.IsTypeArguments()) { 196 } else if (instantiator.IsTypeArguments()) {
197 // Code inlined in the caller should have optimized the case where the 197 // Code inlined in the caller should have optimized the case where the
198 // instantiator is a TypeArguments and can be used as type argument 198 // instantiator is a TypeArguments and can be used as type argument
199 // vector. 199 // vector.
200 ASSERT(!type_arguments.IsUninstantiatedIdentity() || 200 ASSERT(!type_arguments.IsUninstantiatedIdentity() ||
201 (instantiator.Length() != type_arguments.Length())); 201 (instantiator.Length() != type_arguments.Length()));
202 type_arguments = 202 type_arguments = type_arguments.InstantiateFrom(instantiator,
203 InstantiatedTypeArguments::New(type_arguments, instantiator); 203 &malformed_error);
204 } else { 204 } else {
205 // If possible, use the instantiator as the type argument vector. 205 // If possible, use the instantiator as the type argument vector.
206 if (type_arguments.IsUninstantiatedIdentity() && 206 if (type_arguments.IsUninstantiatedIdentity() &&
207 (instantiator.Length() == type_arguments.Length())) { 207 (instantiator.Length() == type_arguments.Length())) {
208 type_arguments = instantiator.raw(); 208 type_arguments = instantiator.raw();
209 } else { 209 } else {
210 type_arguments = 210 type_arguments = type_arguments.InstantiateFrom(instantiator,
211 InstantiatedTypeArguments::New(type_arguments, instantiator); 211 &malformed_error);
212 } 212 }
213 } 213 }
214 bounds_instantiator = instantiator.raw(); 214 if (!malformed_error.IsNull()) {
215 }
216 if (!type_arguments.IsNull()) {
217 ASSERT(type_arguments.IsInstantiated());
218 Error& malformed_error = Error::Handle();
219 if (!type_arguments.IsWithinBoundsOf(cls,
220 bounds_instantiator,
221 &malformed_error)) {
222 ASSERT(!malformed_error.IsNull());
223 // Throw a dynamic type error. 215 // Throw a dynamic type error.
224 const intptr_t location = GetCallerLocation(); 216 const intptr_t location = GetCallerLocation();
225 String& malformed_error_message = String::Handle( 217 String& malformed_error_message = String::Handle(
226 String::New(malformed_error.ToErrorCString())); 218 String::New(malformed_error.ToErrorCString()));
227 Exceptions::CreateAndThrowTypeError( 219 Exceptions::CreateAndThrowTypeError(
228 location, Symbols::Empty(), Symbols::Empty(), 220 location, Symbols::Empty(), Symbols::Empty(),
229 Symbols::Empty(), malformed_error_message); 221 Symbols::Empty(), malformed_error_message);
230 UNREACHABLE(); 222 UNREACHABLE();
231 } 223 }
232 } 224 }
225 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
233 instance.SetTypeArguments(type_arguments); 226 instance.SetTypeArguments(type_arguments);
234 } 227 }
235 228
236 229
237 // Instantiate type arguments. 230 // Instantiate type arguments.
238 // Arg0: uninstantiated type arguments. 231 // Arg0: uninstantiated type arguments.
239 // Arg1: instantiator type arguments. 232 // Arg1: instantiator type arguments.
240 // Return value: instantiated type arguments. 233 // Return value: instantiated type arguments.
241 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { 234 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
242 ASSERT(arguments.ArgCount() == 235 ASSERT(arguments.ArgCount() ==
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 OS::PrintErr("%s: '%s' %"Pd" %s '%s' %"Pd" (pc: %#"Px").\n", 359 OS::PrintErr("%s: '%s' %"Pd" %s '%s' %"Pd" (pc: %#"Px").\n",
367 message, 360 message,
368 String::Handle(instance_type.Name()).ToCString(), 361 String::Handle(instance_type.Name()).ToCString(),
369 Class::Handle(instance_type.type_class()).id(), 362 Class::Handle(instance_type.type_class()).id(),
370 (result.raw() == Bool::True().raw()) ? "is" : "is !", 363 (result.raw() == Bool::True().raw()) ? "is" : "is !",
371 String::Handle(type.Name()).ToCString(), 364 String::Handle(type.Name()).ToCString(),
372 Class::Handle(type.type_class()).id(), 365 Class::Handle(type.type_class()).id(),
373 caller_frame->pc()); 366 caller_frame->pc());
374 } else { 367 } else {
375 // Instantiate type before printing. 368 // Instantiate type before printing.
376 const AbstractType& instantiated_type = 369 Error& malformed_error = Error::Handle();
377 AbstractType::Handle(type.InstantiateFrom(instantiator_type_arguments)); 370 const AbstractType& instantiated_type = AbstractType::Handle(
371 type.InstantiateFrom(instantiator_type_arguments, &malformed_error));
378 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#"Px").\n", 372 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#"Px").\n",
379 message, 373 message,
380 String::Handle(instance_type.Name()).ToCString(), 374 String::Handle(instance_type.Name()).ToCString(),
381 (result.raw() == Bool::True().raw()) ? "is" : "is !", 375 (result.raw() == Bool::True().raw()) ? "is" : "is !",
382 String::Handle(instantiated_type.Name()).ToCString(), 376 String::Handle(instantiated_type.Name()).ToCString(),
383 String::Handle(type.Name()).ToCString(), 377 String::Handle(type.Name()).ToCString(),
384 caller_frame->pc()); 378 caller_frame->pc());
379 if (!malformed_error.IsNull()) {
380 OS::Print(" malformed error: %s\n", malformed_error.ToErrorCString());
381 }
385 } 382 }
386 const Function& function = Function::Handle( 383 const Function& function = Function::Handle(
387 caller_frame->LookupDartFunction()); 384 caller_frame->LookupDartFunction());
388 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); 385 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString());
389 } 386 }
390 387
391 388
392 // Converts InstantiatedTypeArguments to TypeArguments and stores it 389 // Converts InstantiatedTypeArguments to TypeArguments and stores it
393 // into the instance. The assembly code can handle only type arguments of 390 // into the instance. The assembly code can handle only type arguments of
394 // class TypeArguments. Because of the overhead, do it only when needed. 391 // class TypeArguments. Because of the overhead, do it only when needed.
(...skipping 11 matching lines...) Expand all
406 bool replaced = false; 403 bool replaced = false;
407 if (type_arguments.IsInstantiatedTypeArguments()) { 404 if (type_arguments.IsInstantiatedTypeArguments()) {
408 AbstractTypeArguments& uninstantiated = AbstractTypeArguments::Handle(); 405 AbstractTypeArguments& uninstantiated = AbstractTypeArguments::Handle();
409 AbstractTypeArguments& instantiator = AbstractTypeArguments::Handle(); 406 AbstractTypeArguments& instantiator = AbstractTypeArguments::Handle();
410 do { 407 do {
411 const InstantiatedTypeArguments& instantiated_type_arguments = 408 const InstantiatedTypeArguments& instantiated_type_arguments =
412 InstantiatedTypeArguments::Cast(type_arguments); 409 InstantiatedTypeArguments::Cast(type_arguments);
413 uninstantiated = 410 uninstantiated =
414 instantiated_type_arguments.uninstantiated_type_arguments(); 411 instantiated_type_arguments.uninstantiated_type_arguments();
415 instantiator = instantiated_type_arguments.instantiator_type_arguments(); 412 instantiator = instantiated_type_arguments.instantiator_type_arguments();
416 type_arguments = uninstantiated.InstantiateFrom(instantiator); 413 Error& malformed_error = Error::Handle();
414 type_arguments = uninstantiated.InstantiateFrom(instantiator,
415 &malformed_error);
416 ASSERT(malformed_error.IsNull()); // Malformed types are not optimized.
417 } while (type_arguments.IsInstantiatedTypeArguments()); 417 } while (type_arguments.IsInstantiatedTypeArguments());
418 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle(); 418 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
419 new_type_arguments = type_arguments.Canonicalize(); 419 new_type_arguments = type_arguments.Canonicalize();
420 instance.SetTypeArguments(new_type_arguments); 420 instance.SetTypeArguments(new_type_arguments);
421 replaced = true; 421 replaced = true;
422 } else if (!type_arguments.IsCanonical()) { 422 } else if (!type_arguments.IsCanonical()) {
423 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle(); 423 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
424 new_type_arguments = type_arguments.Canonicalize(); 424 new_type_arguments = type_arguments.Canonicalize();
425 instance.SetTypeArguments(new_type_arguments); 425 instance.SetTypeArguments(new_type_arguments);
426 replaced = true; 426 replaced = true;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 } 509 }
510 if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) { 510 if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) {
511 new_cache.AddCheck(instance_class.id(), 511 new_cache.AddCheck(instance_class.id(),
512 instance_type_arguments, 512 instance_type_arguments,
513 instantiator_type_arguments, 513 instantiator_type_arguments,
514 result); 514 result);
515 } 515 }
516 if (FLAG_trace_type_checks) { 516 if (FLAG_trace_type_checks) {
517 AbstractType& test_type = AbstractType::Handle(type.raw()); 517 AbstractType& test_type = AbstractType::Handle(type.raw());
518 if (!test_type.IsInstantiated()) { 518 if (!test_type.IsInstantiated()) {
519 test_type = type.InstantiateFrom(instantiator_type_arguments); 519 Error& malformed_error = Error::Handle();
520 test_type = type.InstantiateFrom(instantiator_type_arguments,
521 &malformed_error);
522 ASSERT(malformed_error.IsNull()); // Malformed types are not optimized.
520 } 523 }
521 OS::PrintErr(" Updated test cache %p ix: %"Pd" with (%"Pd", %p, %p, %s)\n" 524 OS::PrintErr(" Updated test cache %p ix: %"Pd" with (%"Pd", %p, %p, %s)\n"
522 " [%p %s %"Pd", %p %s]\n" 525 " [%p %s %"Pd", %p %s]\n"
523 " [%p %s %"Pd", %p %s] %s\n", 526 " [%p %s %"Pd", %p %s] %s\n",
524 new_cache.raw(), 527 new_cache.raw(),
525 len, 528 len,
526 instance_class.id(), 529 instance_class.id(),
527 530
528 instance_type_arguments.raw(), 531 instance_type_arguments.raw(),
529 instantiator_type_arguments.raw(), 532 instantiator_type_arguments.raw(),
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 } 627 }
625 if (!is_instance_of) { 628 if (!is_instance_of) {
626 // Throw a dynamic type error. 629 // Throw a dynamic type error.
627 const intptr_t location = GetCallerLocation(); 630 const intptr_t location = GetCallerLocation();
628 const AbstractType& src_type = AbstractType::Handle(src_instance.GetType()); 631 const AbstractType& src_type = AbstractType::Handle(src_instance.GetType());
629 const String& src_type_name = String::Handle(src_type.UserVisibleName()); 632 const String& src_type_name = String::Handle(src_type.UserVisibleName());
630 String& dst_type_name = String::Handle(); 633 String& dst_type_name = String::Handle();
631 if (!dst_type.IsInstantiated()) { 634 if (!dst_type.IsInstantiated()) {
632 // Instantiate dst_type before reporting the error. 635 // Instantiate dst_type before reporting the error.
633 const AbstractType& instantiated_dst_type = AbstractType::Handle( 636 const AbstractType& instantiated_dst_type = AbstractType::Handle(
634 dst_type.InstantiateFrom(instantiator_type_arguments)); 637 dst_type.InstantiateFrom(instantiator_type_arguments, NULL));
638 // Note that instantiated_dst_type may be malformed.
635 dst_type_name = instantiated_dst_type.UserVisibleName(); 639 dst_type_name = instantiated_dst_type.UserVisibleName();
636 } else { 640 } else {
637 dst_type_name = dst_type.UserVisibleName(); 641 dst_type_name = dst_type.UserVisibleName();
638 } 642 }
639 String& malformed_error_message = String::Handle(); 643 String& malformed_error_message = String::Handle();
640 if (!malformed_error.IsNull()) { 644 if (!malformed_error.IsNull()) {
641 ASSERT(FLAG_enable_type_checks); 645 ASSERT(FLAG_enable_type_checks);
642 malformed_error_message = String::New(malformed_error.ToErrorCString()); 646 malformed_error_message = String::New(malformed_error.ToErrorCString());
643 } 647 }
644 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, 648 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name,
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 if (right < 0) { 1727 if (right < 0) {
1724 remainder -= right; 1728 remainder -= right;
1725 } else { 1729 } else {
1726 remainder += right; 1730 remainder += right;
1727 } 1731 }
1728 } 1732 }
1729 return remainder; 1733 return remainder;
1730 } 1734 }
1731 1735
1732 } // namespace dart 1736 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.cc ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698