| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 | 784 |
| 785 // Generate type check. | 785 // Generate type check. |
| 786 if (FLAG_enable_type_checks) { | 786 if (FLAG_enable_type_checks) { |
| 787 const RawFunction::Kind kind = parsed_function().function().kind(); | 787 const RawFunction::Kind kind = parsed_function().function().kind(); |
| 788 // Implicit getters do not need a type check at return. | 788 // Implicit getters do not need a type check at return. |
| 789 if ((kind != RawFunction::kImplicitGetter) && | 789 if ((kind != RawFunction::kImplicitGetter) && |
| 790 (kind != RawFunction::kConstImplicitGetter)) { | 790 (kind != RawFunction::kConstImplicitGetter)) { |
| 791 GenerateAssertAssignable( | 791 GenerateAssertAssignable( |
| 792 node->id(), | 792 node->id(), |
| 793 node->value()->token_index(), | 793 node->value()->token_index(), |
| 794 Type::ZoneHandle(parsed_function().function().result_type()), | 794 AbstractType::ZoneHandle(parsed_function().function().result_type()), |
| 795 String::ZoneHandle(String::NewSymbol("function result"))); | 795 String::ZoneHandle(String::NewSymbol("function result"))); |
| 796 } | 796 } |
| 797 } | 797 } |
| 798 GenerateReturnEpilog(); | 798 GenerateReturnEpilog(); |
| 799 } | 799 } |
| 800 | 800 |
| 801 | 801 |
| 802 void CodeGenerator::VisitLiteralNode(LiteralNode* node) { | 802 void CodeGenerator::VisitLiteralNode(LiteralNode* node) { |
| 803 if (!IsResultNeeded(node)) return; | 803 if (!IsResultNeeded(node)) return; |
| 804 const Object& literal = node->literal(); | 804 const Object& literal = node->literal(); |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 | 1026 |
| 1027 | 1027 |
| 1028 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) { | 1028 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) { |
| 1029 node->instance()->Visit(this); | 1029 node->instance()->Visit(this); |
| 1030 node->value()->Visit(this); | 1030 node->value()->Visit(this); |
| 1031 MarkDeoptPoint(node->id(), node->token_index()); | 1031 MarkDeoptPoint(node->id(), node->token_index()); |
| 1032 __ popl(EAX); // Value. | 1032 __ popl(EAX); // Value. |
| 1033 if (FLAG_enable_type_checks) { | 1033 if (FLAG_enable_type_checks) { |
| 1034 GenerateAssertAssignable(node->id(), | 1034 GenerateAssertAssignable(node->id(), |
| 1035 node->value()->token_index(), | 1035 node->value()->token_index(), |
| 1036 Type::ZoneHandle(node->field().type()), | 1036 AbstractType::ZoneHandle(node->field().type()), |
| 1037 String::ZoneHandle(node->field().name())); | 1037 String::ZoneHandle(node->field().name())); |
| 1038 } | 1038 } |
| 1039 __ popl(EDX); // Instance. | 1039 __ popl(EDX); // Instance. |
| 1040 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); | 1040 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); |
| 1041 if (IsResultNeeded(node)) { | 1041 if (IsResultNeeded(node)) { |
| 1042 // The result is the input value. | 1042 // The result is the input value. |
| 1043 __ pushl(EAX); | 1043 __ pushl(EAX); |
| 1044 } | 1044 } |
| 1045 } | 1045 } |
| 1046 | 1046 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1128 } | 1128 } |
| 1129 | 1129 |
| 1130 | 1130 |
| 1131 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { | 1131 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { |
| 1132 node->value()->Visit(this); | 1132 node->value()->Visit(this); |
| 1133 MarkDeoptPoint(node->id(), node->token_index()); | 1133 MarkDeoptPoint(node->id(), node->token_index()); |
| 1134 __ popl(EAX); // Value. | 1134 __ popl(EAX); // Value. |
| 1135 if (FLAG_enable_type_checks) { | 1135 if (FLAG_enable_type_checks) { |
| 1136 GenerateAssertAssignable(node->id(), | 1136 GenerateAssertAssignable(node->id(), |
| 1137 node->value()->token_index(), | 1137 node->value()->token_index(), |
| 1138 Type::ZoneHandle(node->field().type()), | 1138 AbstractType::ZoneHandle(node->field().type()), |
| 1139 String::ZoneHandle(node->field().name())); | 1139 String::ZoneHandle(node->field().name())); |
| 1140 } | 1140 } |
| 1141 __ LoadObject(EDX, node->field()); | 1141 __ LoadObject(EDX, node->field()); |
| 1142 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); | 1142 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); |
| 1143 if (IsResultNeeded(node)) { | 1143 if (IsResultNeeded(node)) { |
| 1144 // The result is the input value. | 1144 // The result is the input value. |
| 1145 __ pushl(EAX); | 1145 __ pushl(EAX); |
| 1146 } | 1146 } |
| 1147 } | 1147 } |
| 1148 | 1148 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1297 __ pushl(EAX); | 1297 __ pushl(EAX); |
| 1298 // It is not necessary to generate a type test of the assigned value here, | 1298 // It is not necessary to generate a type test of the assigned value here, |
| 1299 // because the setter will check the type of its incoming arguments. | 1299 // because the setter will check the type of its incoming arguments. |
| 1300 GenerateStaticSetterCall(node->token_index(), | 1300 GenerateStaticSetterCall(node->token_index(), |
| 1301 node->field_class(), | 1301 node->field_class(), |
| 1302 node->field_name()); | 1302 node->field_name()); |
| 1303 } else { | 1303 } else { |
| 1304 if (FLAG_enable_type_checks) { | 1304 if (FLAG_enable_type_checks) { |
| 1305 GenerateAssertAssignable(node->id(), | 1305 GenerateAssertAssignable(node->id(), |
| 1306 node->token_index(), | 1306 node->token_index(), |
| 1307 Type::ZoneHandle(node->field().type()), | 1307 AbstractType::ZoneHandle(node->field().type()), |
| 1308 String::ZoneHandle(node->field().name())); | 1308 String::ZoneHandle(node->field().name())); |
| 1309 } | 1309 } |
| 1310 __ LoadObject(EDX, node->field()); | 1310 __ LoadObject(EDX, node->field()); |
| 1311 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); | 1311 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); |
| 1312 } | 1312 } |
| 1313 } | 1313 } |
| 1314 | 1314 |
| 1315 | 1315 |
| 1316 void CodeGenerator::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { | 1316 void CodeGenerator::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { |
| 1317 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | 1317 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1359 // - NULL -> return false. | 1359 // - NULL -> return false. |
| 1360 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 1360 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 1361 // - Class equality (only if class is not parameterized). | 1361 // - Class equality (only if class is not parameterized). |
| 1362 // Inputs: | 1362 // Inputs: |
| 1363 // - EAX: object. | 1363 // - EAX: object. |
| 1364 // Destroys ECX. | 1364 // Destroys ECX. |
| 1365 // Returns: | 1365 // Returns: |
| 1366 // - true or false on stack. | 1366 // - true or false on stack. |
| 1367 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, | 1367 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, |
| 1368 intptr_t token_index, | 1368 intptr_t token_index, |
| 1369 const Type& type, | 1369 const AbstractType& type, |
| 1370 bool negate_result) { | 1370 bool negate_result) { |
| 1371 ASSERT(type.IsFinalized()); | 1371 ASSERT(type.IsFinalized()); |
| 1372 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1372 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 1373 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1373 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 1374 | 1374 |
| 1375 // All instances are of a subtype of the Object type. | 1375 // All instances are of a subtype of the Object type. |
| 1376 const Type& object_type = | 1376 const Type& object_type = |
| 1377 Type::Handle(Isolate::Current()->object_store()->object_type()); | 1377 Type::Handle(Isolate::Current()->object_store()->object_type()); |
| 1378 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { | 1378 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { |
| 1379 __ PushObject(negate_result ? bool_false : bool_true); | 1379 __ PushObject(negate_result ? bool_false : bool_true); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 // - NULL -> return NULL. | 1516 // - NULL -> return NULL. |
| 1517 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 1517 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 1518 // - Class equality (only if class is not parameterized). | 1518 // - Class equality (only if class is not parameterized). |
| 1519 // Inputs: | 1519 // Inputs: |
| 1520 // - EAX: object. | 1520 // - EAX: object. |
| 1521 // Destroys ECX and EDX. | 1521 // Destroys ECX and EDX. |
| 1522 // Returns: | 1522 // Returns: |
| 1523 // - object in EAX for successful assignable check (or throws TypeError). | 1523 // - object in EAX for successful assignable check (or throws TypeError). |
| 1524 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, | 1524 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, |
| 1525 intptr_t token_index, | 1525 intptr_t token_index, |
| 1526 const Type& dst_type, | 1526 const AbstractType& dst_type, |
| 1527 const String& dst_name) { | 1527 const String& dst_name) { |
| 1528 ASSERT(FLAG_enable_type_checks); | 1528 ASSERT(FLAG_enable_type_checks); |
| 1529 ASSERT(token_index >= 0); | 1529 ASSERT(token_index >= 0); |
| 1530 ASSERT(!dst_type.IsNull()); | 1530 ASSERT(!dst_type.IsNull()); |
| 1531 ASSERT(dst_type.IsFinalized()); | 1531 ASSERT(dst_type.IsFinalized()); |
| 1532 | 1532 |
| 1533 // Any expression is assignable to the Dynamic type and to the Object type. | 1533 // Any expression is assignable to the Dynamic type and to the Object type. |
| 1534 // Skip the test. | 1534 // Skip the test. |
| 1535 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { | 1535 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { |
| 1536 return; | 1536 return; |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2251 } | 2251 } |
| 2252 if (outer_function.IsFactory()) { | 2252 if (outer_function.IsFactory()) { |
| 2253 instantiator_class = outer_function.signature_class(); | 2253 instantiator_class = outer_function.signature_class(); |
| 2254 } else { | 2254 } else { |
| 2255 instantiator_class = outer_function.owner(); | 2255 instantiator_class = outer_function.owner(); |
| 2256 } | 2256 } |
| 2257 if (instantiator_class.NumTypeParameters() == 0) { | 2257 if (instantiator_class.NumTypeParameters() == 0) { |
| 2258 // The type arguments are compile time constants. | 2258 // The type arguments are compile time constants. |
| 2259 TypeArguments& type_arguments = TypeArguments::ZoneHandle(); | 2259 TypeArguments& type_arguments = TypeArguments::ZoneHandle(); |
| 2260 // TODO(regis): Temporary type should be allocated in new gen heap. | 2260 // TODO(regis): Temporary type should be allocated in new gen heap. |
| 2261 Type& type = Type::Handle( | 2261 AbstractType& type = AbstractType::Handle( |
| 2262 Type::NewParameterizedType(instantiator_class, type_arguments)); | 2262 Type::NewParameterizedType(instantiator_class, type_arguments)); |
| 2263 String& errmsg = String::Handle(); | 2263 String& errmsg = String::Handle(); |
| 2264 type = ClassFinalizer::FinalizeAndCanonicalizeType(type, &errmsg); | 2264 type = ClassFinalizer::FinalizeAndCanonicalizeType(type, &errmsg); |
| 2265 if (!errmsg.IsNull()) { | 2265 if (!errmsg.IsNull()) { |
| 2266 ErrorMsg(token_index, errmsg.ToCString()); | 2266 ErrorMsg(token_index, errmsg.ToCString()); |
| 2267 } | 2267 } |
| 2268 type_arguments = type.arguments(); | 2268 type_arguments = type.arguments(); |
| 2269 __ PushObject(type_arguments); | 2269 __ PushObject(type_arguments); |
| 2270 } else { | 2270 } else { |
| 2271 ASSERT(parsed_function().instantiator() != NULL); | 2271 ASSERT(parsed_function().instantiator() != NULL); |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2742 message_buffer, kMessageBufferSize, | 2742 message_buffer, kMessageBufferSize, |
| 2743 format, args); | 2743 format, args); |
| 2744 va_end(args); | 2744 va_end(args); |
| 2745 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); | 2745 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); |
| 2746 UNREACHABLE(); | 2746 UNREACHABLE(); |
| 2747 } | 2747 } |
| 2748 | 2748 |
| 2749 } // namespace dart | 2749 } // namespace dart |
| 2750 | 2750 |
| 2751 #endif // defined TARGET_ARCH_IA32 | 2751 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |