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

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

Issue 10280007: Check upper bounds of type arguments when allocating objects of a generic type (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 1165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 1176
1177 1177
1178 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { 1178 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) {
1179 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); 1179 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR));
1180 MarkDeoptPoint(node->id(), node->token_index()); 1180 MarkDeoptPoint(node->id(), node->token_index());
1181 GenerateLoadVariable(EAX, node->local()); 1181 GenerateLoadVariable(EAX, node->local());
1182 if (!node->prefix() && IsResultNeeded(node)) { 1182 if (!node->prefix() && IsResultNeeded(node)) {
1183 // Preserve as result. 1183 // Preserve as result.
1184 __ pushl(EAX); 1184 __ pushl(EAX);
1185 } 1185 }
1186 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1)));
1187 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; 1186 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-";
1188 __ pushl(EAX); 1187 __ pushl(EAX);
1189 __ pushl(value); 1188 __ pushl(Immediate(Smi::RawValue(1)));
1190 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name); 1189 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name);
1191 // result is in EAX. 1190 // result is in EAX.
1192 if (FLAG_enable_type_checks) { 1191 if (FLAG_enable_type_checks) {
1193 GenerateAssertAssignable(node->id(), 1192 GenerateAssertAssignable(node->id(),
1194 node->token_index(), 1193 node->token_index(),
1195 NULL, 1194 NULL,
1196 node->local().type(), 1195 node->local().type(),
1197 node->local().name()); 1196 node->local().name());
1198 } 1197 }
1199 GenerateStoreVariable(node->local(), EAX, EDX); 1198 GenerateStoreVariable(node->local(), EAX, EDX);
(...skipping 11 matching lines...) Expand all
1211 MarkDeoptPoint(node->getter_id(), node->token_index()); 1210 MarkDeoptPoint(node->getter_id(), node->token_index());
1212 GenerateInstanceGetterCall(node->getter_id(), 1211 GenerateInstanceGetterCall(node->getter_id(),
1213 node->token_index(), 1212 node->token_index(),
1214 node->field_name()); 1213 node->field_name());
1215 // result is in EAX. 1214 // result is in EAX.
1216 __ popl(EDX); // Get receiver. 1215 __ popl(EDX); // Get receiver.
1217 if (!node->prefix() && IsResultNeeded(node)) { 1216 if (!node->prefix() && IsResultNeeded(node)) {
1218 // Preserve as result. 1217 // Preserve as result.
1219 __ pushl(EAX); // Preserve value as result. 1218 __ pushl(EAX); // Preserve value as result.
1220 } 1219 }
1221 const Immediate one_value = Immediate(reinterpret_cast<int32_t>(Smi::New(1)));
1222 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; 1220 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-";
1223 // EAX: Value. 1221 // EAX: Value.
1224 // EDX: Receiver. 1222 // EDX: Receiver.
1225 __ pushl(EDX); // Preserve receiver. 1223 __ pushl(EDX); // Preserve receiver.
1226 __ pushl(EAX); // Left operand. 1224 __ pushl(EAX); // Left operand.
1227 __ pushl(one_value); // Right operand. 1225 __ pushl(Immediate(Smi::RawValue(1))); // Right operand.
1228 GenerateBinaryOperatorCall(node->operator_id(), 1226 GenerateBinaryOperatorCall(node->operator_id(),
1229 node->token_index(), 1227 node->token_index(),
1230 operator_name); 1228 operator_name);
1231 __ popl(EDX); // Restore receiver. 1229 __ popl(EDX); // Restore receiver.
1232 if (IsResultNeeded(node) && node->prefix()) { 1230 if (IsResultNeeded(node) && node->prefix()) {
1233 // Value stored into field is the result. 1231 // Value stored into field is the result.
1234 __ pushl(EAX); 1232 __ pushl(EAX);
1235 } 1233 }
1236 __ pushl(EDX); // Receiver. 1234 __ pushl(EDX); // Receiver.
1237 __ pushl(EAX); // Value. 1235 __ pushl(EAX); // Value.
(...skipping 16 matching lines...) Expand all
1254 GenerateLoadIndexed(node->load_id(), node->token_index()); 1252 GenerateLoadIndexed(node->load_id(), node->token_index());
1255 // Result is in EAX. 1253 // Result is in EAX.
1256 if (!node->prefix() && IsResultNeeded(node)) { 1254 if (!node->prefix() && IsResultNeeded(node)) {
1257 // Preserve EAX as result. 1255 // Preserve EAX as result.
1258 __ popl(EDX); // Preserved index -> EDX. 1256 __ popl(EDX); // Preserved index -> EDX.
1259 __ popl(ECX); // Preserved array -> ECX. 1257 __ popl(ECX); // Preserved array -> ECX.
1260 __ pushl(EAX); // Preserve original value from indexed load. 1258 __ pushl(EAX); // Preserve original value from indexed load.
1261 __ pushl(ECX); // Array. 1259 __ pushl(ECX); // Array.
1262 __ pushl(EDX); // Index. 1260 __ pushl(EDX); // Index.
1263 } 1261 }
1264 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1)));
1265 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; 1262 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-";
1266 __ pushl(EAX); // Left operand. 1263 __ pushl(EAX); // Left operand.
1267 __ pushl(value); // Right operand. 1264 __ pushl(Immediate(Smi::RawValue(1))); // Right operand.
1268 GenerateBinaryOperatorCall(node->operator_id(), 1265 GenerateBinaryOperatorCall(node->operator_id(),
1269 node->token_index(), 1266 node->token_index(),
1270 operator_name); 1267 operator_name);
1271 __ pushl(EAX); 1268 __ pushl(EAX);
1272 // TOS(0): value, TOS(1): index, TOS(2): array. 1269 // TOS(0): value, TOS(1): index, TOS(2): array.
1273 GenerateStoreIndexed(node->store_id(), 1270 GenerateStoreIndexed(node->store_id(),
1274 node->token_index(), 1271 node->token_index(),
1275 node->prefix() && IsResultNeeded(node)); 1272 node->prefix() && IsResultNeeded(node));
1276 } 1273 }
1277 1274
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 __ j(NOT_EQUAL, &non_null, Assembler::kNearJump); 1449 __ j(NOT_EQUAL, &non_null, Assembler::kNearJump);
1453 __ PushObject(negate_result ? bool_true : bool_false); 1450 __ PushObject(negate_result ? bool_true : bool_false);
1454 __ jmp(&done); 1451 __ jmp(&done);
1455 __ Bind(&non_null); 1452 __ Bind(&non_null);
1456 } 1453 }
1457 1454
1458 GenerateInlineInstanceof(node_id, token_index, type, 1455 GenerateInlineInstanceof(node_id, token_index, type,
1459 &is_instance_of, &is_not_instance_of); 1456 &is_instance_of, &is_not_instance_of);
1460 1457
1461 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1458 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1462 const Immediate location = 1459 const Immediate location = Immediate(Smi::RawValue(token_index));
1463 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); 1460 const Immediate node_id_as_smi = Immediate(Smi::RawValue(node_id));
1464 const Immediate node_id_as_smi =
1465 Immediate(reinterpret_cast<int32_t>(Smi::New(node_id)));
1466 __ pushl(location); // Push the source location. 1461 __ pushl(location); // Push the source location.
1467 __ pushl(node_id_as_smi); // node-id. 1462 __ pushl(node_id_as_smi); // node-id.
1468 __ pushl(EAX); // Push the instance. 1463 __ pushl(EAX); // Push the instance.
1469 __ PushObject(type); // Push the type. 1464 __ PushObject(type); // Push the type.
1470 if (!type.IsInstantiated()) { 1465 if (!type.IsInstantiated()) {
1471 GenerateInstantiatorTypeArguments(token_index); 1466 GenerateInstantiatorTypeArguments(token_index);
1472 } else { 1467 } else {
1473 __ pushl(raw_null); // Null instantiator. 1468 __ pushl(raw_null); // Null instantiator.
1474 } 1469 }
1475 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); 1470 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 Label done, runtime_call; 1812 Label done, runtime_call;
1818 __ cmpl(EAX, raw_null); 1813 __ cmpl(EAX, raw_null);
1819 __ j(EQUAL, &done); 1814 __ j(EQUAL, &done);
1820 1815
1821 // Generate throw new TypeError() if the type is malformed. 1816 // Generate throw new TypeError() if the type is malformed.
1822 if (dst_type.IsMalformed()) { 1817 if (dst_type.IsMalformed()) {
1823 const Error& error = Error::Handle(dst_type.malformed_error()); 1818 const Error& error = Error::Handle(dst_type.malformed_error());
1824 const String& error_message = String::ZoneHandle( 1819 const String& error_message = String::ZoneHandle(
1825 String::NewSymbol(error.ToErrorCString())); 1820 String::NewSymbol(error.ToErrorCString()));
1826 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1821 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1827 const Immediate location = 1822 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
1828 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1829 __ pushl(location); // Push the source location.
1830 __ pushl(EAX); // Push the source object. 1823 __ pushl(EAX); // Push the source object.
1831 __ PushObject(dst_name); // Push the name of the destination. 1824 __ PushObject(dst_name); // Push the name of the destination.
1832 __ PushObject(error_message); 1825 __ PushObject(error_message);
1833 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry); 1826 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1834 // We should never return here. 1827 // We should never return here.
1835 __ int3(); 1828 __ int3();
1836 1829
1837 __ Bind(&done); // For a null object. 1830 __ Bind(&done); // For a null object.
1838 return; 1831 return;
1839 } 1832 }
1840 1833
1841 GenerateInlineInstanceof(node_id, token_index, dst_type, 1834 GenerateInlineInstanceof(node_id, token_index, dst_type,
1842 &done, &runtime_call); 1835 &done, &runtime_call);
1843 1836
1844 __ Bind(&runtime_call); 1837 __ Bind(&runtime_call);
1845 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1838 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1846 const Immediate location = 1839 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
1847 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); 1840 __ pushl(Immediate(Smi::RawValue(node_id))); // node-id.
1848 const Immediate node_id_as_smi =
1849 Immediate(reinterpret_cast<int32_t>(Smi::New(node_id)));
1850 __ pushl(location); // Push the source location.
1851 __ pushl(node_id_as_smi); // node-id.
1852 __ pushl(EAX); // Push the source object. 1841 __ pushl(EAX); // Push the source object.
1853 __ PushObject(dst_type); // Push the type of the destination. 1842 __ PushObject(dst_type); // Push the type of the destination.
1854 if (dst_type.IsInstantiated()) { 1843 if (dst_type.IsInstantiated()) {
1855 __ pushl(raw_null); // Null instantiator. 1844 __ pushl(raw_null); // Null instantiator.
1856 } else { 1845 } else {
1857 GenerateInstantiatorTypeArguments(token_index); 1846 GenerateInstantiatorTypeArguments(token_index);
1858 } 1847 }
1859 __ PushObject(dst_name); // Push the name of the destination. 1848 __ PushObject(dst_name); // Push the name of the destination.
1860 GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry); 1849 GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry);
1861 // Pop the parameters supplied to the runtime entry. The result of the 1850 // Pop the parameters supplied to the runtime entry. The result of the
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 // This check should pass if the receiver's class implements the interface 1896 // This check should pass if the receiver's class implements the interface
1908 // 'bool'. Check only class 'Bool' since it is the only legal implementation 1897 // 'bool'. Check only class 'Bool' since it is the only legal implementation
1909 // of the interface 'bool'. 1898 // of the interface 'bool'.
1910 const Class& bool_class = 1899 const Class& bool_class =
1911 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); 1900 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class());
1912 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1901 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1913 __ CompareObject(ECX, bool_class); 1902 __ CompareObject(ECX, bool_class);
1914 __ j(EQUAL, &done, Assembler::kNearJump); 1903 __ j(EQUAL, &done, Assembler::kNearJump);
1915 1904
1916 __ Bind(&runtime_call); 1905 __ Bind(&runtime_call);
1917 const Immediate location = 1906 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
1918 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1919 __ pushl(location); // Push the source location.
1920 __ pushl(EAX); // Push the source object. 1907 __ pushl(EAX); // Push the source object.
1921 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); 1908 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry);
1922 // We should never return here. 1909 // We should never return here.
1923 __ int3(); 1910 __ int3();
1924 1911
1925 __ Bind(&done); 1912 __ Bind(&done);
1926 } 1913 }
1927 1914
1928 1915
1929 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { 1916 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) {
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after
2543 // Instantiate non-null type arguments. 2530 // Instantiate non-null type arguments.
2544 if (node->type_arguments().IsUninstantiatedIdentity()) { 2531 if (node->type_arguments().IsUninstantiatedIdentity()) {
2545 // Check if the instantiator type argument vector is a TypeArguments of a 2532 // Check if the instantiator type argument vector is a TypeArguments of a
2546 // matching length and, if so, use it as the instantiated type_arguments. 2533 // matching length and, if so, use it as the instantiated type_arguments.
2547 // No need to check RAX for null (again), because a null instance will 2534 // No need to check RAX for null (again), because a null instance will
2548 // have the wrong class (Null instead of TypeArguments). 2535 // have the wrong class (Null instead of TypeArguments).
2549 Label type_arguments_uninstantiated; 2536 Label type_arguments_uninstantiated;
2550 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); 2537 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class()));
2551 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); 2538 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset()));
2552 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 2539 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
2553 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( 2540 Immediate arguments_length =
2554 Smi::New(node->type_arguments().Length()))); 2541 Immediate(Smi::RawValue(node->type_arguments().Length()));
2555 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), 2542 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()),
2556 arguments_length); 2543 arguments_length);
2557 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2544 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2558 __ Bind(&type_arguments_uninstantiated); 2545 __ Bind(&type_arguments_uninstantiated);
2559 } 2546 }
2560 if (node->constructor().IsFactory()) { 2547 if (node->constructor().IsFactory()) {
2561 // A runtime call to instantiate the type arguments is required before 2548 // A runtime call to instantiate the type arguments is required before
2562 // calling the factory. 2549 // calling the factory.
2563 __ PushObject(Object::ZoneHandle()); // Make room for the result. 2550 __ PushObject(Object::ZoneHandle()); // Make room for the result.
2564 __ PushObject(node->type_arguments()); 2551 __ PushObject(node->type_arguments());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 } 2597 }
2611 return; 2598 return;
2612 } 2599 }
2613 2600
2614 const Class& cls = Class::ZoneHandle(node->constructor().owner()); 2601 const Class& cls = Class::ZoneHandle(node->constructor().owner());
2615 const bool requires_type_arguments = cls.HasTypeArguments(); 2602 const bool requires_type_arguments = cls.HasTypeArguments();
2616 GenerateTypeArguments(node, requires_type_arguments); 2603 GenerateTypeArguments(node, requires_type_arguments);
2617 2604
2618 // If cls is parameterized, the type arguments and the instantiator's 2605 // If cls is parameterized, the type arguments and the instantiator's
2619 // type arguments are on the stack. 2606 // type arguments are on the stack.
2620 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); 2607 // In checked mode, if the type arguments are uninstantiated, they may need to
2621 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); 2608 // be checked against declared bounds at run time.
2622 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); 2609 Error& malformed_error = Error::Handle();
2623 if (requires_type_arguments) { 2610 if (FLAG_enable_type_checks &&
2611 requires_type_arguments &&
2612 !node->type_arguments().IsNull() &&
2613 !node->type_arguments().IsInstantiated() &&
2614 !node->type_arguments().IsWithinBoundsOf(cls,
2615 node->type_arguments(),
2616 &malformed_error)) {
2617 // The uninstantiated type arguments cannot be verified to be within their
2618 // bounds at compile time, so verify them at runtime.
2619 // Although the type arguments may be uninstantiated at compile time, they
2620 // may represent the identity vector and may be replaced by the instantiated
2621 // type arguments of the instantiator at run time.
2622 __ popl(ECX); // Pop instantiator type arguments.
2623 __ popl(EAX); // Pop type arguments.
2624
2625 // Push the result place holder initialized to NULL.
2626 __ PushObject(Object::ZoneHandle());
2627 __ pushl(Immediate(Smi::RawValue(node->token_index())));
2628 __ PushObject(cls);
2629 __ pushl(EAX); // Push type arguments.
2630 __ pushl(ECX); // Push instantiator type arguments.
2631 GenerateCallRuntime(node->id(),
2632 node->token_index(),
2633 kAllocateObjectWithBoundsCheckRuntimeEntry);
2634 __ popl(ECX); // Pop instantiator type arguments.
2624 __ popl(ECX); // Pop type arguments. 2635 __ popl(ECX); // Pop type arguments.
2625 __ popl(ECX); // Pop instantiator type arguments. 2636 __ popl(ECX); // Pop class.
2637 __ popl(ECX); // Pop source location.
2638 __ popl(EAX); // Pop new instance.
2639 } else {
2640 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
2641 const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
2642 GenerateCall(node->token_index(), &label, PcDescriptors::kOther);
2643 if (requires_type_arguments) {
2644 __ popl(ECX); // Pop instantiator type arguments.
2645 __ popl(ECX); // Pop type arguments.
2646 }
2626 } 2647 }
2627 2648
2628 if (IsResultNeeded(node)) { 2649 if (IsResultNeeded(node)) {
2629 __ pushl(EAX); // Set up return value from allocate. 2650 __ pushl(EAX); // Set up return value from allocate.
2630 } 2651 }
2631 2652
2632 // First argument(this) for constructor call which follows. 2653 // First argument(this) for constructor call which follows.
2633 __ pushl(EAX); 2654 __ pushl(EAX);
2634 // Second argument is the implicit construction phase parameter. 2655 // Second argument is the implicit construction phase parameter.
2635 // Run both the constructor initializer list and the constructor body. 2656 // Run both the constructor initializer list and the constructor body.
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 const Error& error = Error::Handle( 2991 const Error& error = Error::Handle(
2971 Parser::FormatError(script, token_index, "Error", format, args)); 2992 Parser::FormatError(script, token_index, "Error", format, args));
2972 va_end(args); 2993 va_end(args);
2973 Isolate::Current()->long_jump_base()->Jump(1, error); 2994 Isolate::Current()->long_jump_base()->Jump(1, error);
2974 UNREACHABLE(); 2995 UNREACHABLE();
2975 } 2996 }
2976 2997
2977 } // namespace dart 2998 } // namespace dart
2978 2999
2979 #endif // defined TARGET_ARCH_IA32 3000 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698