| OLD | NEW |
| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 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 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 } | 863 } |
| 864 | 864 |
| 865 | 865 |
| 866 void CodeGenerator::VisitArrayNode(ArrayNode* node) { | 866 void CodeGenerator::VisitArrayNode(ArrayNode* node) { |
| 867 // Evaluate the array elements. | 867 // Evaluate the array elements. |
| 868 for (int i = 0; i < node->length(); i++) { | 868 for (int i = 0; i < node->length(); i++) { |
| 869 AstNode* element = node->ElementAt(i); | 869 AstNode* element = node->ElementAt(i); |
| 870 element->Visit(this); | 870 element->Visit(this); |
| 871 } | 871 } |
| 872 | 872 |
| 873 const AbstractTypeArguments& element_type = node->type_arguments(); |
| 874 const bool instantiate_type_arguments = true; |
| 875 GenerateTypeArguments(node->id(), |
| 876 node->token_index(), |
| 877 element_type, |
| 878 instantiate_type_arguments); |
| 879 __ popq(RBX); |
| 880 __ movq(R10, Immediate(Smi::RawValue(node->length()))); |
| 881 |
| 873 // Allocate the array. | 882 // Allocate the array. |
| 874 // R10 : Array length as Smi. | 883 // R10 : Array length as Smi. |
| 875 // RBX : element type for the array. | 884 // RBX : element type for the array. |
| 876 __ movq(R10, Immediate(Smi::RawValue(node->length()))); | |
| 877 const AbstractTypeArguments& element_type = node->type_arguments(); | |
| 878 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | |
| 879 __ LoadObject(RBX, element_type); | |
| 880 GenerateCall(node->token_index(), | 885 GenerateCall(node->token_index(), |
| 881 &StubCode::AllocateArrayLabel(), | 886 &StubCode::AllocateArrayLabel(), |
| 882 PcDescriptors::kOther); | 887 PcDescriptors::kOther); |
| 883 | 888 |
| 884 // Pop the element values from the stack into the array. | 889 // Pop the element values from the stack into the array. |
| 885 __ leaq(RCX, FieldAddress(RAX, Array::data_offset())); | 890 __ leaq(RCX, FieldAddress(RAX, Array::data_offset())); |
| 886 for (int i = node->length() - 1; i >= 0; i--) { | 891 for (int i = node->length() - 1; i >= 0; i--) { |
| 887 __ popq(Address(RCX, i * kWordSize)); | 892 __ popq(Address(RCX, i * kWordSize)); |
| 888 } | 893 } |
| 889 | 894 |
| (...skipping 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 intptr_t type_arguments_instance_field_offset = | 2150 intptr_t type_arguments_instance_field_offset = |
| 2146 instantiator_class.type_arguments_instance_field_offset(); | 2151 instantiator_class.type_arguments_instance_field_offset(); |
| 2147 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | 2152 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| 2148 __ movq(RAX, FieldAddress(RAX, type_arguments_instance_field_offset)); | 2153 __ movq(RAX, FieldAddress(RAX, type_arguments_instance_field_offset)); |
| 2149 __ pushq(RAX); | 2154 __ pushq(RAX); |
| 2150 } | 2155 } |
| 2151 } | 2156 } |
| 2152 } | 2157 } |
| 2153 | 2158 |
| 2154 | 2159 |
| 2155 // Pushes the type arguments on the stack in preparation of a constructor or | 2160 // Pushes the type arguments on the stack in preparation of an allocation call. |
| 2156 // factory call. | 2161 // If instantiate_type_arguments is true, the instantiated type arguments |
| 2157 // For a factory call, instantiates (possibly requiring an additional run time | 2162 // are pushed on the stack (after an instantiation run time call, if necessary). |
| 2158 // call) and pushes the type argument vector that will be passed as implicit | 2163 // If instantiate_type_arguments is false, the (possibly uninstantiated) type |
| 2159 // first parameter to the factory. | 2164 // arguments are pushed on the stack, as well as the type arguments of the |
| 2160 // For a constructor call allocating an object of a parameterized class, pushes | 2165 // instantiator (or the special kNoInstantiator Smi marker, if the type |
| 2161 // the type arguments and the type arguments of the instantiator, without ever | 2166 // arguments are instantiated). |
| 2162 // generating an additional run time call. | 2167 void CodeGenerator::GenerateTypeArguments( |
| 2163 // Does nothing for a constructor call allocating an object of a non | 2168 intptr_t node_id, |
| 2164 // parameterized class. | 2169 intptr_t token_index, |
| 2165 // Note that a class without proper type parameters may still be parameterized, | 2170 const AbstractTypeArguments& type_arguments, |
| 2166 // e.g. class A extends Array<int>. | 2171 bool instantiate_type_arguments) { |
| 2167 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node, | |
| 2168 bool requires_type_arguments) { | |
| 2169 const Immediate raw_null = | 2172 const Immediate raw_null = |
| 2170 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2173 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2171 // Instantiate the type arguments if necessary. | 2174 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
| 2172 if (node->type_arguments().IsNull() || | 2175 // The type arguments are instantiated. |
| 2173 node->type_arguments().IsInstantiated()) { | 2176 __ PushObject(type_arguments); |
| 2174 if (requires_type_arguments) { | 2177 if (!instantiate_type_arguments) { |
| 2175 // A factory requires the type arguments as first parameter. | 2178 // The type arguments of the instantiator are not needed, since the |
| 2176 __ PushObject(node->type_arguments()); | 2179 // type arguments are instantiated. |
| 2177 if (!node->constructor().IsFactory()) { | 2180 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2178 // The non-factory allocator additionally requires the instantiator | |
| 2179 // type arguments which are not needed here, since the type arguments | |
| 2180 // are instantiated. | |
| 2181 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | |
| 2182 } | |
| 2183 } | 2181 } |
| 2184 } else { | 2182 } else { |
| 2185 // The type arguments are uninstantiated. | 2183 // The type arguments are uninstantiated. |
| 2186 ASSERT(requires_type_arguments); | 2184 GenerateInstantiatorTypeArguments(token_index); |
| 2187 GenerateInstantiatorTypeArguments(node->token_index()); | |
| 2188 __ popq(RAX); // Pop instantiator. | 2185 __ popq(RAX); // Pop instantiator. |
| 2189 // RAX is the instantiator AbstractTypeArguments object (or null). | 2186 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 2190 // If the instantiator is null and if the type argument vector | 2187 // If the instantiator is null and if the type argument vector |
| 2191 // instantiated from null becomes a vector of Dynamic, then use null as | 2188 // instantiated from null becomes a vector of Dynamic, then use null as |
| 2192 // the type arguments. | 2189 // the type arguments. |
| 2193 Label type_arguments_instantiated; | 2190 Label type_arguments_instantiated; |
| 2194 const intptr_t len = node->type_arguments().Length(); | 2191 const intptr_t len = type_arguments.Length(); |
| 2195 if (node->type_arguments().IsRawInstantiatedRaw(len)) { | 2192 if (type_arguments.IsRawInstantiatedRaw(len)) { |
| 2196 __ cmpq(RAX, raw_null); | 2193 __ cmpq(RAX, raw_null); |
| 2197 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2194 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2198 } | 2195 } |
| 2199 // Instantiate non-null type arguments. | 2196 // Instantiate non-null type arguments. |
| 2200 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2197 if (type_arguments.IsUninstantiatedIdentity()) { |
| 2201 // Check if the instantiator type argument vector is a TypeArguments of a | 2198 // Check if the instantiator type argument vector is a TypeArguments of a |
| 2202 // matching length and, if so, use it as the instantiated type_arguments. | 2199 // matching length and, if so, use it as the instantiated type_arguments. |
| 2203 // No need to check RAX for null (again), because a null instance will | 2200 // No need to check RAX for null (again), because a null instance will |
| 2204 // have the wrong class (Null instead of TypeArguments). | 2201 // have the wrong class (Null instead of TypeArguments). |
| 2205 Label type_arguments_uninstantiated; | 2202 Label type_arguments_uninstantiated; |
| 2206 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 2203 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 2207 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 2204 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 2208 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 2205 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 2209 Immediate arguments_length = | |
| 2210 Immediate(Smi::RawValue(node->type_arguments().Length())); | |
| 2211 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 2206 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 2212 arguments_length); | 2207 Immediate(Smi::RawValue(len))); |
| 2213 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2208 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2214 __ Bind(&type_arguments_uninstantiated); | 2209 __ Bind(&type_arguments_uninstantiated); |
| 2215 } | 2210 } |
| 2216 if (node->constructor().IsFactory()) { | 2211 if (instantiate_type_arguments) { |
| 2217 // A runtime call to instantiate the type arguments is required before | 2212 // A runtime call to instantiate the type arguments is required. |
| 2218 // calling the factory. | |
| 2219 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2213 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2220 __ PushObject(node->type_arguments()); | 2214 __ PushObject(type_arguments); |
| 2221 __ pushq(RAX); // Push instantiator type arguments. | 2215 __ pushq(RAX); // Push instantiator type arguments. |
| 2222 GenerateCallRuntime(node->id(), | 2216 GenerateCallRuntime(node_id, |
| 2223 node->token_index(), | 2217 token_index, |
| 2224 kInstantiateTypeArgumentsRuntimeEntry); | 2218 kInstantiateTypeArgumentsRuntimeEntry); |
| 2225 __ popq(RAX); // Pop instantiator type arguments. | 2219 __ popq(RAX); // Pop instantiator type arguments. |
| 2226 __ popq(RAX); // Pop uninstantiated type arguments. | 2220 __ popq(RAX); // Pop uninstantiated type arguments. |
| 2227 __ popq(RAX); // Pop instantiated type arguments. | 2221 __ popq(RAX); // Pop instantiated type arguments. |
| 2228 __ Bind(&type_arguments_instantiated); | 2222 __ Bind(&type_arguments_instantiated); |
| 2229 __ pushq(RAX); // Instantiated type arguments. | 2223 __ pushq(RAX); // Instantiated type arguments. |
| 2230 } else { | 2224 } else { |
| 2231 // In the non-factory case, we rely on the allocation stub to | 2225 // The allocation stub will instantiate the type arguments. |
| 2232 // instantiate the type arguments. | 2226 __ PushObject(type_arguments); |
| 2233 __ PushObject(node->type_arguments()); | |
| 2234 __ pushq(RAX); // Instantiator type arguments. | 2227 __ pushq(RAX); // Instantiator type arguments. |
| 2235 Label type_arguments_pushed; | 2228 Label type_arguments_pushed; |
| 2236 __ jmp(&type_arguments_pushed, Assembler::kNearJump); | 2229 __ jmp(&type_arguments_pushed, Assembler::kNearJump); |
| 2237 | 2230 |
| 2238 __ Bind(&type_arguments_instantiated); | 2231 __ Bind(&type_arguments_instantiated); |
| 2239 __ pushq(RAX); // Instantiated type arguments. | 2232 __ pushq(RAX); // Instantiated type arguments. |
| 2240 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 2233 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2241 __ Bind(&type_arguments_pushed); | 2234 __ Bind(&type_arguments_pushed); |
| 2242 } | 2235 } |
| 2243 } | 2236 } |
| 2244 } | 2237 } |
| 2245 | 2238 |
| 2246 | 2239 |
| 2247 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { | 2240 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2248 if (node->constructor().IsFactory()) { | 2241 if (node->constructor().IsFactory()) { |
| 2249 const bool requires_type_arguments = true; // Always first arg to factory. | 2242 const bool instantiate_type_arguments = true; // First argument to factory. |
| 2250 GenerateTypeArguments(node, requires_type_arguments); | 2243 GenerateTypeArguments(node->id(), |
| 2244 node->token_index(), |
| 2245 node->type_arguments(), |
| 2246 instantiate_type_arguments); |
| 2251 // The top of stack is an instantiated AbstractTypeArguments object | 2247 // The top of stack is an instantiated AbstractTypeArguments object |
| 2252 // (or null). | 2248 // (or null). |
| 2253 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 2249 int num_args = node->arguments()->length() + 1; // +1 to include type args. |
| 2254 node->arguments()->Visit(this); | 2250 node->arguments()->Visit(this); |
| 2255 // Call the factory. | 2251 // Call the factory. |
| 2256 __ LoadObject(RBX, node->constructor()); | 2252 __ LoadObject(RBX, node->constructor()); |
| 2257 __ LoadObject(R10, ArgumentsDescriptor(num_args, | 2253 __ LoadObject(R10, ArgumentsDescriptor(num_args, |
| 2258 node->arguments()->names())); | 2254 node->arguments()->names())); |
| 2259 GenerateCall(node->token_index(), | 2255 GenerateCall(node->token_index(), |
| 2260 &StubCode::CallStaticFunctionLabel(), | 2256 &StubCode::CallStaticFunctionLabel(), |
| 2261 PcDescriptors::kFuncCall); | 2257 PcDescriptors::kFuncCall); |
| 2262 // Factory constructor returns object in RAX. | 2258 // Factory constructor returns object in RAX. |
| 2263 __ addq(RSP, Immediate(num_args * kWordSize)); | 2259 __ addq(RSP, Immediate(num_args * kWordSize)); |
| 2264 if (IsResultNeeded(node)) { | 2260 if (IsResultNeeded(node)) { |
| 2265 __ pushq(RAX); | 2261 __ pushq(RAX); |
| 2266 } | 2262 } |
| 2267 return; | 2263 return; |
| 2268 } | 2264 } |
| 2269 | 2265 |
| 2270 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | 2266 const Class& cls = Class::ZoneHandle(node->constructor().owner()); |
| 2271 const bool requires_type_arguments = cls.HasTypeArguments(); | 2267 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 2272 GenerateTypeArguments(node, requires_type_arguments); | 2268 const bool instantiate_type_arguments = false; // Done in stub or runtime. |
| 2269 if (requires_type_arguments) { |
| 2270 GenerateTypeArguments(node->id(), |
| 2271 node->token_index(), |
| 2272 node->type_arguments(), |
| 2273 instantiate_type_arguments); |
| 2274 } |
| 2273 | 2275 |
| 2274 // If cls is parameterized, the type arguments and the instantiator's | 2276 // If cls is parameterized, the type arguments and the instantiator's |
| 2275 // type arguments are on the stack. | 2277 // type arguments are on the stack. |
| 2276 // In checked mode, if the type arguments are uninstantiated, they may need to | 2278 // In checked mode, if the type arguments are uninstantiated, they may need to |
| 2277 // be checked against declared bounds at run time. | 2279 // be checked against declared bounds at run time. |
| 2278 Error& malformed_error = Error::Handle(); | 2280 Error& malformed_error = Error::Handle(); |
| 2279 if (FLAG_enable_type_checks && | 2281 if (FLAG_enable_type_checks && |
| 2280 requires_type_arguments && | 2282 requires_type_arguments && |
| 2281 !node->type_arguments().IsNull() && | 2283 !node->type_arguments().IsNull() && |
| 2282 !node->type_arguments().IsInstantiated() && | 2284 !node->type_arguments().IsInstantiated() && |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2660 const Error& error = Error::Handle( | 2662 const Error& error = Error::Handle( |
| 2661 Parser::FormatError(script, token_index, "Error", format, args)); | 2663 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2662 va_end(args); | 2664 va_end(args); |
| 2663 Isolate::Current()->long_jump_base()->Jump(1, error); | 2665 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2664 UNREACHABLE(); | 2666 UNREACHABLE(); |
| 2665 } | 2667 } |
| 2666 | 2668 |
| 2667 } // namespace dart | 2669 } // namespace dart |
| 2668 | 2670 |
| 2669 #endif // defined TARGET_ARCH_X64 | 2671 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |