| 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 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 // Evaluate the array elements. | 966 // Evaluate the array elements. |
| 967 for (int i = 0; i < node->length(); i++) { | 967 for (int i = 0; i < node->length(); i++) { |
| 968 AstNode* element = node->ElementAt(i); | 968 AstNode* element = node->ElementAt(i); |
| 969 element->Visit(this); | 969 element->Visit(this); |
| 970 } | 970 } |
| 971 | 971 |
| 972 // Allocate the array. | 972 // Allocate the array. |
| 973 // EDX : Array length as Smi. | 973 // EDX : Array length as Smi. |
| 974 // ECX : element type for the array. | 974 // ECX : element type for the array. |
| 975 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); | 975 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); |
| 976 const TypeArguments& element_type = node->type_arguments(); | 976 const AbstractTypeArguments& element_type = node->type_arguments(); |
| 977 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | 977 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); |
| 978 __ LoadObject(ECX, element_type); | 978 __ LoadObject(ECX, element_type); |
| 979 GenerateCall(node->token_index(), &StubCode::AllocateArrayLabel()); | 979 GenerateCall(node->token_index(), &StubCode::AllocateArrayLabel()); |
| 980 | 980 |
| 981 // Pop the element values from the stack into the array. | 981 // Pop the element values from the stack into the array. |
| 982 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 982 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
| 983 for (int i = node->length() - 1; i >= 0; i--) { | 983 for (int i = node->length() - 1; i >= 0; i--) { |
| 984 __ popl(Address(ECX, i * kWordSize)); | 984 __ popl(Address(ECX, i * kWordSize)); |
| 985 } | 985 } |
| 986 | 986 |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 __ jmp(&done, Assembler::kNearJump); | 1400 __ jmp(&done, Assembler::kNearJump); |
| 1401 | 1401 |
| 1402 __ Bind(&non_null); | 1402 __ Bind(&non_null); |
| 1403 | 1403 |
| 1404 const Class& type_class = Class::ZoneHandle(type.type_class()); | 1404 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 1405 const bool requires_type_arguments = type_class.HasTypeArguments(); | 1405 const bool requires_type_arguments = type_class.HasTypeArguments(); |
| 1406 // A Smi object cannot be the instance of a parameterized class. | 1406 // A Smi object cannot be the instance of a parameterized class. |
| 1407 // A class equality check is only applicable with a dst type of a | 1407 // A class equality check is only applicable with a dst type of a |
| 1408 // non-parameterized class or with a raw dst type of a parameterized class. | 1408 // non-parameterized class or with a raw dst type of a parameterized class. |
| 1409 if (requires_type_arguments) { | 1409 if (requires_type_arguments) { |
| 1410 const TypeArguments& type_arguments = | 1410 const AbstractTypeArguments& type_arguments = |
| 1411 TypeArguments::Handle(type.arguments()); | 1411 AbstractTypeArguments::Handle(type.arguments()); |
| 1412 const bool is_raw_type = type_arguments.IsNull() || | 1412 const bool is_raw_type = type_arguments.IsNull() || |
| 1413 type_arguments.IsDynamicTypes(type_arguments.Length()); | 1413 type_arguments.IsDynamicTypes(type_arguments.Length()); |
| 1414 Label runtime_call; | 1414 Label runtime_call; |
| 1415 __ testl(EAX, Immediate(kSmiTagMask)); | 1415 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1416 __ j(ZERO, &runtime_call, Assembler::kNearJump); | 1416 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 1417 // Object not Smi. | 1417 // Object not Smi. |
| 1418 if (is_raw_type) { | 1418 if (is_raw_type) { |
| 1419 if (type.IsListInterface()) { | 1419 if (type.IsListInterface()) { |
| 1420 Label push_result; | 1420 Label push_result; |
| 1421 // TODO(srdjan) also accept List<Object>. | 1421 // TODO(srdjan) also accept List<Object>. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1554 | 1554 |
| 1555 // If dst_type is instantiated and non-parameterized, we can inline code | 1555 // If dst_type is instantiated and non-parameterized, we can inline code |
| 1556 // checking whether the assigned instance is a Smi. | 1556 // checking whether the assigned instance is a Smi. |
| 1557 if (dst_type.IsInstantiated()) { | 1557 if (dst_type.IsInstantiated()) { |
| 1558 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); | 1558 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); |
| 1559 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); | 1559 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); |
| 1560 // A Smi object cannot be the instance of a parameterized class. | 1560 // A Smi object cannot be the instance of a parameterized class. |
| 1561 // A class equality check is only applicable with a dst type of a | 1561 // A class equality check is only applicable with a dst type of a |
| 1562 // non-parameterized class or with a raw dst type of a parameterized class. | 1562 // non-parameterized class or with a raw dst type of a parameterized class. |
| 1563 if (dst_class_has_type_arguments) { | 1563 if (dst_class_has_type_arguments) { |
| 1564 const TypeArguments& dst_type_arguments = | 1564 const AbstractTypeArguments& dst_type_arguments = |
| 1565 TypeArguments::Handle(dst_type.arguments()); | 1565 AbstractTypeArguments::Handle(dst_type.arguments()); |
| 1566 const bool is_raw_dst_type = dst_type_arguments.IsNull() || | 1566 const bool is_raw_dst_type = dst_type_arguments.IsNull() || |
| 1567 dst_type_arguments.IsDynamicTypes(dst_type_arguments.Length()); | 1567 dst_type_arguments.IsDynamicTypes(dst_type_arguments.Length()); |
| 1568 if (is_raw_dst_type) { | 1568 if (is_raw_dst_type) { |
| 1569 // Dynamic type argument, check only classes. | 1569 // Dynamic type argument, check only classes. |
| 1570 if (dst_type.IsListInterface()) { | 1570 if (dst_type.IsListInterface()) { |
| 1571 // TODO(srdjan) also accept List<Object>. | 1571 // TODO(srdjan) also accept List<Object>. |
| 1572 __ testl(EAX, Immediate(kSmiTagMask)); | 1572 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1573 __ j(ZERO, &runtime_call, Assembler::kNearJump); | 1573 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 1574 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1574 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1575 TestClassAndJump(*CoreClass("ObjectArray"), &done); | 1575 TestClassAndJump(*CoreClass("ObjectArray"), &done); |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2249 while (outer_function.IsLocalFunction()) { | 2249 while (outer_function.IsLocalFunction()) { |
| 2250 outer_function = outer_function.parent_function(); | 2250 outer_function = outer_function.parent_function(); |
| 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 AbstractTypeArguments& type_arguments = AbstractTypeArguments::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 Type& type = Type::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); |
| 2272 parsed_function().instantiator()->Visit(this); | 2272 parsed_function().instantiator()->Visit(this); |
| 2273 if (!outer_function.IsFactory()) { | 2273 if (!outer_function.IsFactory()) { |
| 2274 __ popl(EAX); // Pop instantiator. | 2274 __ popl(EAX); // Pop instantiator. |
| 2275 // The instantiator is the receiver of the caller, which is not a factory. | 2275 // The instantiator is the receiver of the caller, which is not a factory. |
| 2276 // The receiver cannot be null; extract its TypeArguments object. | 2276 // The receiver cannot be null; extract its AbstractTypeArguments object. |
| 2277 // Note that in the factory case, the instantiator is the first parameter | 2277 // Note that in the factory case, the instantiator is the first parameter |
| 2278 // of the factory, i.e. already a TypeArguments object. | 2278 // of the factory, i.e. already an AbstractTypeArguments object. |
| 2279 intptr_t type_arguments_instance_field_offset = | 2279 intptr_t type_arguments_instance_field_offset = |
| 2280 instantiator_class.type_arguments_instance_field_offset(); | 2280 instantiator_class.type_arguments_instance_field_offset(); |
| 2281 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | 2281 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| 2282 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); | 2282 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); |
| 2283 __ pushl(EAX); | 2283 __ pushl(EAX); |
| 2284 } | 2284 } |
| 2285 } | 2285 } |
| 2286 } | 2286 } |
| 2287 | 2287 |
| 2288 | 2288 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2311 if (!node->constructor().IsFactory()) { | 2311 if (!node->constructor().IsFactory()) { |
| 2312 // The allocator additionally requires the instantiator type arguments. | 2312 // The allocator additionally requires the instantiator type arguments. |
| 2313 __ pushl(raw_null); // Null instantiator. | 2313 __ pushl(raw_null); // Null instantiator. |
| 2314 } | 2314 } |
| 2315 } | 2315 } |
| 2316 } else { | 2316 } else { |
| 2317 // The type arguments are uninstantiated. | 2317 // The type arguments are uninstantiated. |
| 2318 ASSERT(requires_type_arguments); | 2318 ASSERT(requires_type_arguments); |
| 2319 GenerateInstantiatorTypeArguments(node->token_index()); | 2319 GenerateInstantiatorTypeArguments(node->token_index()); |
| 2320 __ popl(EAX); // Pop instantiator. | 2320 __ popl(EAX); // Pop instantiator. |
| 2321 // EAX is the instantiator TypeArguments object (or null). | 2321 // EAX is the instantiator AbstractTypeArguments object (or null). |
| 2322 // If EAX is null, no need to instantiate the type arguments, use null, and | 2322 // If EAX is null, no need to instantiate the type arguments, use null, and |
| 2323 // allocate an object of a raw type. | 2323 // allocate an object of a raw type. |
| 2324 Label type_arguments_instantiated, type_arguments_uninstantiated; | 2324 Label type_arguments_instantiated, type_arguments_uninstantiated; |
| 2325 __ cmpl(EAX, raw_null); | 2325 __ cmpl(EAX, raw_null); |
| 2326 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2326 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2327 | 2327 |
| 2328 // Instantiate non-null type arguments. | 2328 // Instantiate non-null type arguments. |
| 2329 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2329 if (node->type_arguments().IsUninstantiatedIdentity()) { |
| 2330 // Check if the instantiator type argument vector is a TypeArray of a | 2330 // Check if the instantiator type argument vector is a TypeArguments of a |
| 2331 // matching length and, if so, use it as the instantiated type_arguments. | 2331 // matching length and, if so, use it as the instantiated type_arguments. |
| 2332 __ LoadObject(ECX, Class::ZoneHandle(Object::type_array_class())); | 2332 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); |
| 2333 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); | 2333 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 2334 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 2334 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 2335 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( | 2335 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( |
| 2336 Smi::New(node->type_arguments().Length()))); | 2336 Smi::New(node->type_arguments().Length()))); |
| 2337 __ cmpl(FieldAddress(EAX, TypeArray::length_offset()), arguments_length); | 2337 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), |
| 2338 arguments_length); |
| 2338 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2339 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2339 } | 2340 } |
| 2340 __ Bind(&type_arguments_uninstantiated); | 2341 __ Bind(&type_arguments_uninstantiated); |
| 2341 if (node->constructor().IsFactory()) { | 2342 if (node->constructor().IsFactory()) { |
| 2342 // A runtime call to instantiate the type arguments is required before | 2343 // A runtime call to instantiate the type arguments is required before |
| 2343 // calling the factory. | 2344 // calling the factory. |
| 2344 const Object& result = Object::ZoneHandle(); | 2345 const Object& result = Object::ZoneHandle(); |
| 2345 __ PushObject(result); // Make room for the result of the runtime call. | 2346 __ PushObject(result); // Make room for the result of the runtime call. |
| 2346 __ PushObject(node->type_arguments()); | 2347 __ PushObject(node->type_arguments()); |
| 2347 __ pushl(EAX); // Push instantiator type arguments. | 2348 __ pushl(EAX); // Push instantiator type arguments. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2367 __ Bind(&type_arguments_pushed); | 2368 __ Bind(&type_arguments_pushed); |
| 2368 } | 2369 } |
| 2369 } | 2370 } |
| 2370 } | 2371 } |
| 2371 | 2372 |
| 2372 | 2373 |
| 2373 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { | 2374 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2374 if (node->constructor().IsFactory()) { | 2375 if (node->constructor().IsFactory()) { |
| 2375 const bool requires_type_arguments = true; // Always first arg to factory. | 2376 const bool requires_type_arguments = true; // Always first arg to factory. |
| 2376 GenerateTypeArguments(node, requires_type_arguments); | 2377 GenerateTypeArguments(node, requires_type_arguments); |
| 2377 // The top of stack is an instantiated TypeArguments object (or null). | 2378 // The top of stack is an instantiated AbstractTypeArguments object |
| 2379 // (or null). |
| 2378 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 2380 int num_args = node->arguments()->length() + 1; // +1 to include type args. |
| 2379 node->arguments()->Visit(this); | 2381 node->arguments()->Visit(this); |
| 2380 // Call the factory. | 2382 // Call the factory. |
| 2381 __ LoadObject(ECX, node->constructor()); | 2383 __ LoadObject(ECX, node->constructor()); |
| 2382 __ LoadObject(EDX, ArgumentsDescriptor(num_args, | 2384 __ LoadObject(EDX, ArgumentsDescriptor(num_args, |
| 2383 node->arguments()->names())); | 2385 node->arguments()->names())); |
| 2384 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2386 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); |
| 2385 // Factory constructor returns object in EAX. | 2387 // Factory constructor returns object in EAX. |
| 2386 __ addl(ESP, Immediate(num_args * kWordSize)); | 2388 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2387 if (IsResultNeeded(node)) { | 2389 if (IsResultNeeded(node)) { |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2742 message_buffer, kMessageBufferSize, | 2744 message_buffer, kMessageBufferSize, |
| 2743 format, args); | 2745 format, args); |
| 2744 va_end(args); | 2746 va_end(args); |
| 2745 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); | 2747 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); |
| 2746 UNREACHABLE(); | 2748 UNREACHABLE(); |
| 2747 } | 2749 } |
| 2748 | 2750 |
| 2749 } // namespace dart | 2751 } // namespace dart |
| 2750 | 2752 |
| 2751 #endif // defined TARGET_ARCH_IA32 | 2753 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |