| 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" |
| 11 #include "vm/ast_printer.h" | 11 #include "vm/ast_printer.h" |
| 12 #include "vm/class_finalizer.h" |
| 12 #include "vm/dart_entry.h" | 13 #include "vm/dart_entry.h" |
| 13 #include "vm/ic_data.h" | 14 #include "vm/ic_data.h" |
| 14 #include "vm/longjump.h" | 15 #include "vm/longjump.h" |
| 15 #include "vm/object.h" | 16 #include "vm/object.h" |
| 16 #include "vm/object_store.h" | 17 #include "vm/object_store.h" |
| 17 #include "vm/parser.h" | 18 #include "vm/parser.h" |
| 18 #include "vm/resolver.h" | 19 #include "vm/resolver.h" |
| 19 #include "vm/stub_code.h" | 20 #include "vm/stub_code.h" |
| 20 | 21 |
| 21 namespace dart { | 22 namespace dart { |
| (...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 node->receiver()->Visit(this); | 862 node->receiver()->Visit(this); |
| 862 } | 863 } |
| 863 } | 864 } |
| 864 // The function type of a closure may have type arguments. In that case, pass | 865 // The function type of a closure may have type arguments. In that case, pass |
| 865 // the type arguments of the instantiator. | 866 // the type arguments of the instantiator. |
| 866 const Class& cls = Class::Handle(function.signature_class()); | 867 const Class& cls = Class::Handle(function.signature_class()); |
| 867 ASSERT(!cls.IsNull()); | 868 ASSERT(!cls.IsNull()); |
| 868 const bool requires_type_arguments = cls.HasTypeArguments(); | 869 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 869 if (requires_type_arguments) { | 870 if (requires_type_arguments) { |
| 870 ASSERT(!function.IsImplicitStaticClosureFunction()); | 871 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 871 GenerateInstantiatorTypeArguments(); | 872 GenerateInstantiatorTypeArguments(node->token_index()); |
| 872 } | 873 } |
| 873 const Code& stub = Code::Handle( | 874 const Code& stub = Code::Handle( |
| 874 StubCode::GetAllocationStubForClosure(function)); | 875 StubCode::GetAllocationStubForClosure(function)); |
| 875 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 876 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 876 GenerateCall(node->token_index(), &label); | 877 GenerateCall(node->token_index(), &label); |
| 877 if (requires_type_arguments) { | 878 if (requires_type_arguments) { |
| 878 __ popl(ECX); // Pop type arguments. | 879 __ popl(ECX); // Pop type arguments. |
| 879 } | 880 } |
| 880 if (function.IsImplicitInstanceClosureFunction()) { | 881 if (function.IsImplicitInstanceClosureFunction()) { |
| 881 __ popl(ECX); // Pop receiver. | 882 __ popl(ECX); // Pop receiver. |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1420 __ jmp(&done, Assembler::kNearJump); | 1421 __ jmp(&done, Assembler::kNearJump); |
| 1421 __ Bind(&runtime_call); | 1422 __ Bind(&runtime_call); |
| 1422 } | 1423 } |
| 1423 } | 1424 } |
| 1424 } | 1425 } |
| 1425 const Object& result = Object::ZoneHandle(); | 1426 const Object& result = Object::ZoneHandle(); |
| 1426 __ PushObject(result); // Make room for the result of the runtime call. | 1427 __ PushObject(result); // Make room for the result of the runtime call. |
| 1427 __ pushl(EAX); // Push the instance. | 1428 __ pushl(EAX); // Push the instance. |
| 1428 __ PushObject(type); // Push the type. | 1429 __ PushObject(type); // Push the type. |
| 1429 if (!type.IsInstantiated()) { | 1430 if (!type.IsInstantiated()) { |
| 1430 GenerateInstantiatorTypeArguments(); | 1431 GenerateInstantiatorTypeArguments(token_index); |
| 1431 } else { | 1432 } else { |
| 1432 __ pushl(raw_null); // Null instantiator. | 1433 __ pushl(raw_null); // Null instantiator. |
| 1433 } | 1434 } |
| 1434 GenerateCallRuntime(token_index, kInstanceofRuntimeEntry); | 1435 GenerateCallRuntime(token_index, kInstanceofRuntimeEntry); |
| 1435 // Pop the two parameters supplied to the runtime entry. The result of the | 1436 // Pop the two parameters supplied to the runtime entry. The result of the |
| 1436 // instanceof runtime call will be left as the result of the operation. | 1437 // instanceof runtime call will be left as the result of the operation. |
| 1437 __ addl(ESP, Immediate(3 * kWordSize)); | 1438 __ addl(ESP, Immediate(3 * kWordSize)); |
| 1438 if (negate_result) { | 1439 if (negate_result) { |
| 1439 Label negate_done; | 1440 Label negate_done; |
| 1440 __ popl(EDX); | 1441 __ popl(EDX); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1577 } | 1578 } |
| 1578 __ Bind(&runtime_call); | 1579 __ Bind(&runtime_call); |
| 1579 const Object& result = Object::ZoneHandle(); | 1580 const Object& result = Object::ZoneHandle(); |
| 1580 __ PushObject(result); // Make room for the result of the runtime call. | 1581 __ PushObject(result); // Make room for the result of the runtime call. |
| 1581 const Immediate location = | 1582 const Immediate location = |
| 1582 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1583 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
| 1583 __ pushl(location); // Push the source location. | 1584 __ pushl(location); // Push the source location. |
| 1584 __ pushl(EAX); // Push the source object. | 1585 __ pushl(EAX); // Push the source object. |
| 1585 __ PushObject(dst_type); // Push the type of the destination. | 1586 __ PushObject(dst_type); // Push the type of the destination. |
| 1586 if (!dst_type.IsInstantiated()) { | 1587 if (!dst_type.IsInstantiated()) { |
| 1587 GenerateInstantiatorTypeArguments(); | 1588 GenerateInstantiatorTypeArguments(token_index); |
| 1588 } else { | 1589 } else { |
| 1589 __ pushl(raw_null); // Null instantiator. | 1590 __ pushl(raw_null); // Null instantiator. |
| 1590 } | 1591 } |
| 1591 __ PushObject(dst_name); // Push the name of the destination. | 1592 __ PushObject(dst_name); // Push the name of the destination. |
| 1592 GenerateCallRuntime(token_index, kTypeCheckRuntimeEntry); | 1593 GenerateCallRuntime(token_index, kTypeCheckRuntimeEntry); |
| 1593 // Pop the parameters supplied to the runtime entry. The result of the | 1594 // Pop the parameters supplied to the runtime entry. The result of the |
| 1594 // type check runtime call is the checked value. | 1595 // type check runtime call is the checked value. |
| 1595 __ addl(ESP, Immediate(5 * kWordSize)); | 1596 __ addl(ESP, Immediate(5 * kWordSize)); |
| 1596 __ popl(EAX); | 1597 __ popl(EAX); |
| 1597 | 1598 |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 // Restore the context. | 2160 // Restore the context. |
| 2160 __ popl(CTX); | 2161 __ popl(CTX); |
| 2161 // Result is in EAX. | 2162 // Result is in EAX. |
| 2162 if (IsResultNeeded(node)) { | 2163 if (IsResultNeeded(node)) { |
| 2163 __ pushl(EAX); | 2164 __ pushl(EAX); |
| 2164 } | 2165 } |
| 2165 } | 2166 } |
| 2166 | 2167 |
| 2167 | 2168 |
| 2168 // Pushes the type arguments of the instantiator on the stack. | 2169 // Pushes the type arguments of the instantiator on the stack. |
| 2169 void CodeGenerator::GenerateInstantiatorTypeArguments() { | 2170 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { |
| 2170 ASSERT(parsed_function().instantiator() != NULL); | 2171 const Class& instantiator_class = |
| 2171 parsed_function().instantiator()->Visit(this); | 2172 Class::Handle(parsed_function().function().owner()); |
| 2172 if (!parsed_function().function().IsInFactoryScope()) { | 2173 if (instantiator_class.NumTypeParameters() == 0) { |
| 2173 __ popl(EAX); // Pop instantiator. | 2174 // The type arguments are compile time constants. |
| 2174 const Class& instantiator_class = | 2175 TypeArguments& type_arguments = TypeArguments::ZoneHandle(); |
| 2175 Class::Handle(parsed_function().function().owner()); | 2176 const Type& type = Type::Handle( |
| 2176 // The instantiator is the receiver of the caller, which is not a factory. | 2177 Type::NewParameterizedType(instantiator_class, type_arguments)); |
| 2177 // The receiver cannot be null; extract its TypeArguments object. | 2178 const String& errmsg = String::Handle( |
| 2178 // Note that in the factory case, the instantiator is the first parameter | 2179 ClassFinalizer::FinalizeTypeWhileParsing(type)); |
| 2179 // of the factory, i.e. already a TypeArguments object. | 2180 if (!errmsg.IsNull()) { |
| 2180 intptr_t type_arguments_instance_field_offset = | 2181 ErrorMsg(token_index, errmsg.ToCString()); |
| 2181 instantiator_class.type_arguments_instance_field_offset(); | 2182 } |
| 2182 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | 2183 type_arguments = type.arguments(); |
| 2183 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); | 2184 __ PushObject(type_arguments); |
| 2184 __ pushl(EAX); | 2185 } else { |
| 2186 ASSERT(parsed_function().instantiator() != NULL); |
| 2187 parsed_function().instantiator()->Visit(this); |
| 2188 if (!parsed_function().function().IsInFactoryScope()) { |
| 2189 __ popl(EAX); // Pop instantiator. |
| 2190 // The instantiator is the receiver of the caller, which is not a factory. |
| 2191 // The receiver cannot be null; extract its TypeArguments object. |
| 2192 // Note that in the factory case, the instantiator is the first parameter |
| 2193 // of the factory, i.e. already a TypeArguments object. |
| 2194 intptr_t type_arguments_instance_field_offset = |
| 2195 instantiator_class.type_arguments_instance_field_offset(); |
| 2196 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| 2197 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); |
| 2198 __ pushl(EAX); |
| 2199 } |
| 2185 } | 2200 } |
| 2186 } | 2201 } |
| 2187 | 2202 |
| 2188 | 2203 |
| 2189 // Pushes the type arguments on the stack in preparation of a constructor or | 2204 // Pushes the type arguments on the stack in preparation of a constructor or |
| 2190 // factory call. | 2205 // factory call. |
| 2191 // For a factory call, instantiates (possibly requiring an additional run time | 2206 // For a factory call, instantiates (possibly requiring an additional run time |
| 2192 // call) and pushes the type argument vector that will be passed as implicit | 2207 // call) and pushes the type argument vector that will be passed as implicit |
| 2193 // first parameter to the factory. | 2208 // first parameter to the factory. |
| 2194 // For a constructor call allocating an object of a parameterized class, pushes | 2209 // For a constructor call allocating an object of a parameterized class, pushes |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2209 // A factory requires the type arguments as first parameter. | 2224 // A factory requires the type arguments as first parameter. |
| 2210 __ PushObject(node->type_arguments()); | 2225 __ PushObject(node->type_arguments()); |
| 2211 if (!node->constructor().IsFactory()) { | 2226 if (!node->constructor().IsFactory()) { |
| 2212 // The allocator additionally requires the instantiator type arguments. | 2227 // The allocator additionally requires the instantiator type arguments. |
| 2213 __ pushl(raw_null); // Null instantiator. | 2228 __ pushl(raw_null); // Null instantiator. |
| 2214 } | 2229 } |
| 2215 } | 2230 } |
| 2216 } else { | 2231 } else { |
| 2217 // The type arguments are uninstantiated. | 2232 // The type arguments are uninstantiated. |
| 2218 ASSERT(node->constructor().IsFactory() || requires_type_arguments); | 2233 ASSERT(node->constructor().IsFactory() || requires_type_arguments); |
| 2219 GenerateInstantiatorTypeArguments(); | 2234 GenerateInstantiatorTypeArguments(node->token_index()); |
| 2220 __ popl(EAX); // Pop instantiator. | 2235 __ popl(EAX); // Pop instantiator. |
| 2221 // EAX is the instantiator TypeArguments object (or null). | 2236 // EAX is the instantiator TypeArguments object (or null). |
| 2222 // If EAX is null, no need to instantiate the type arguments, use null, and | 2237 // If EAX is null, no need to instantiate the type arguments, use null, and |
| 2223 // allocate an object of a raw type. | 2238 // allocate an object of a raw type. |
| 2224 Label type_arguments_instantiated, type_arguments_uninstantiated; | 2239 Label type_arguments_instantiated, type_arguments_uninstantiated; |
| 2225 __ cmpl(EAX, raw_null); | 2240 __ cmpl(EAX, raw_null); |
| 2226 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2241 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2227 | 2242 |
| 2228 // Instantiate non-null type arguments. | 2243 // Instantiate non-null type arguments. |
| 2229 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2244 if (node->type_arguments().IsUninstantiatedIdentity()) { |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2626 const Class& cls = Class::Handle(parsed_function_.function().owner()); | 2641 const Class& cls = Class::Handle(parsed_function_.function().owner()); |
| 2627 const Script& script = Script::Handle(cls.script()); | 2642 const Script& script = Script::Handle(cls.script()); |
| 2628 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); | 2643 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); |
| 2629 Isolate::Current()->long_jump_base()->Jump(1, error_msg); | 2644 Isolate::Current()->long_jump_base()->Jump(1, error_msg); |
| 2630 UNREACHABLE(); | 2645 UNREACHABLE(); |
| 2631 } | 2646 } |
| 2632 | 2647 |
| 2633 } // namespace dart | 2648 } // namespace dart |
| 2634 | 2649 |
| 2635 #endif // defined TARGET_ARCH_IA32 | 2650 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |