| 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 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 } else { | 704 } else { |
| 705 __ LoadObject(RAX, literal); | 705 __ LoadObject(RAX, literal); |
| 706 } | 706 } |
| 707 } else { | 707 } else { |
| 708 // Pop the previously evaluated result value into RAX. | 708 // Pop the previously evaluated result value into RAX. |
| 709 __ popq(RAX); | 709 __ popq(RAX); |
| 710 } | 710 } |
| 711 | 711 |
| 712 // Generate type check. | 712 // Generate type check. |
| 713 if (FLAG_enable_type_checks) { | 713 if (FLAG_enable_type_checks) { |
| 714 const RawFunction::Kind kind = parsed_function().function().kind(); | 714 const bool returns_null = node->value()->IsLiteralNode() && |
| 715 node->value()->AsLiteralNode()->literal().IsNull(); |
| 716 const RawFunction::Kind kind = parsed_function().function().kind(); |
| 715 // Implicit getters do not need a type check at return. | 717 // Implicit getters do not need a type check at return. |
| 716 if ((kind != RawFunction::kImplicitGetter) && | 718 if (!returns_null && |
| 719 (kind != RawFunction::kImplicitGetter) && |
| 717 (kind != RawFunction::kConstImplicitGetter)) { | 720 (kind != RawFunction::kConstImplicitGetter)) { |
| 718 GenerateAssertAssignable( | 721 GenerateAssertAssignable( |
| 719 node->id(), | 722 node->id(), |
| 720 node->value()->token_index(), | 723 node->value()->token_index(), |
| 721 AbstractType::ZoneHandle(parsed_function().function().result_type()), | 724 AbstractType::ZoneHandle(parsed_function().function().result_type()), |
| 722 String::ZoneHandle(String::NewSymbol("function result"))); | 725 String::ZoneHandle(String::NewSymbol("function result"))); |
| 723 } | 726 } |
| 724 } | 727 } |
| 725 GenerateReturnEpilog(node); | 728 GenerateReturnEpilog(node); |
| 726 } | 729 } |
| (...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 | 1322 |
| 1320 const Class& type_class = Class::ZoneHandle(type.type_class()); | 1323 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 1321 const bool requires_type_arguments = type_class.HasTypeArguments(); | 1324 const bool requires_type_arguments = type_class.HasTypeArguments(); |
| 1322 // A Smi object cannot be the instance of a parameterized class. | 1325 // A Smi object cannot be the instance of a parameterized class. |
| 1323 // A class equality check is only applicable with a dst type of a | 1326 // A class equality check is only applicable with a dst type of a |
| 1324 // non-parameterized class or with a raw dst type of a parameterized class. | 1327 // non-parameterized class or with a raw dst type of a parameterized class. |
| 1325 if (requires_type_arguments) { | 1328 if (requires_type_arguments) { |
| 1326 const AbstractTypeArguments& type_arguments = | 1329 const AbstractTypeArguments& type_arguments = |
| 1327 AbstractTypeArguments::Handle(type.arguments()); | 1330 AbstractTypeArguments::Handle(type.arguments()); |
| 1328 const bool is_raw_type = type_arguments.IsNull() || | 1331 const bool is_raw_type = type_arguments.IsNull() || |
| 1329 type_arguments.IsDynamicTypes(type_arguments.Length()); | 1332 type_arguments.IsRaw(type_arguments.Length()); |
| 1330 Label runtime_call; | 1333 Label runtime_call; |
| 1331 __ testq(RAX, Immediate(kSmiTagMask)); | 1334 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1332 __ j(ZERO, &runtime_call, Assembler::kNearJump); | 1335 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 1333 // Object not Smi. | 1336 // Object not Smi. |
| 1334 if (is_raw_type) { | 1337 if (is_raw_type) { |
| 1335 if (type.IsListInterface()) { | 1338 if (type.IsListInterface()) { |
| 1336 Label push_result; | 1339 Label push_result; |
| 1337 // TODO(srdjan) also accept List<Object>. | 1340 // TODO(srdjan) also accept List<Object>. |
| 1338 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1341 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1339 __ CompareObject(RCX, *CoreClass("ObjectArray")); | 1342 __ CompareObject(RCX, *CoreClass("ObjectArray")); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1498 if (dst_type.IsInstantiated()) { | 1501 if (dst_type.IsInstantiated()) { |
| 1499 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); | 1502 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); |
| 1500 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); | 1503 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); |
| 1501 // A Smi object cannot be the instance of a parameterized class. | 1504 // A Smi object cannot be the instance of a parameterized class. |
| 1502 // A class equality check is only applicable with a dst type of a | 1505 // A class equality check is only applicable with a dst type of a |
| 1503 // non-parameterized class or with a raw dst type of a parameterized class. | 1506 // non-parameterized class or with a raw dst type of a parameterized class. |
| 1504 if (dst_class_has_type_arguments) { | 1507 if (dst_class_has_type_arguments) { |
| 1505 const AbstractTypeArguments& dst_type_arguments = | 1508 const AbstractTypeArguments& dst_type_arguments = |
| 1506 AbstractTypeArguments::Handle(dst_type.arguments()); | 1509 AbstractTypeArguments::Handle(dst_type.arguments()); |
| 1507 const bool is_raw_dst_type = dst_type_arguments.IsNull() || | 1510 const bool is_raw_dst_type = dst_type_arguments.IsNull() || |
| 1508 dst_type_arguments.IsDynamicTypes(dst_type_arguments.Length()); | 1511 dst_type_arguments.IsRaw(dst_type_arguments.Length()); |
| 1509 if (is_raw_dst_type) { | 1512 if (is_raw_dst_type) { |
| 1510 // Dynamic type argument, check only classes. | 1513 // Dynamic type argument, check only classes. |
| 1511 if (dst_type.IsListInterface()) { | 1514 if (dst_type.IsListInterface()) { |
| 1512 // TODO(srdjan) also accept List<Object>. | 1515 // TODO(srdjan) also accept List<Object>. |
| 1513 __ testq(RAX, Immediate(kSmiTagMask)); | 1516 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1514 __ j(ZERO, &runtime_call); | 1517 __ j(ZERO, &runtime_call); |
| 1515 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1518 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1516 TestClassAndJump(*CoreClass("ObjectArray"), &done); | 1519 TestClassAndJump(*CoreClass("ObjectArray"), &done); |
| 1517 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done); | 1520 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done); |
| 1518 } else if (!dst_type_class.is_interface()) { | 1521 } else if (!dst_type_class.is_interface()) { |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2257 bool requires_type_arguments) { | 2260 bool requires_type_arguments) { |
| 2258 const Immediate raw_null = | 2261 const Immediate raw_null = |
| 2259 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2262 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2260 // Instantiate the type arguments if necessary. | 2263 // Instantiate the type arguments if necessary. |
| 2261 if (node->type_arguments().IsNull() || | 2264 if (node->type_arguments().IsNull() || |
| 2262 node->type_arguments().IsInstantiated()) { | 2265 node->type_arguments().IsInstantiated()) { |
| 2263 if (requires_type_arguments) { | 2266 if (requires_type_arguments) { |
| 2264 // A factory requires the type arguments as first parameter. | 2267 // A factory requires the type arguments as first parameter. |
| 2265 __ PushObject(node->type_arguments()); | 2268 __ PushObject(node->type_arguments()); |
| 2266 if (!node->constructor().IsFactory()) { | 2269 if (!node->constructor().IsFactory()) { |
| 2267 // The allocator additionally requires the instantiator type arguments. | 2270 // The non-factory allocator additionally requires the instantiator |
| 2268 __ pushq(raw_null); // Null instantiator. | 2271 // type arguments which are not needed here, since the type arguments |
| 2272 // are instantiated. |
| 2273 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2269 } | 2274 } |
| 2270 } | 2275 } |
| 2271 } else { | 2276 } else { |
| 2272 // The type arguments are uninstantiated. | 2277 // The type arguments are uninstantiated. |
| 2273 ASSERT(requires_type_arguments); | 2278 ASSERT(requires_type_arguments); |
| 2274 GenerateInstantiatorTypeArguments(node->token_index()); | 2279 GenerateInstantiatorTypeArguments(node->token_index()); |
| 2275 __ popq(RAX); // Pop instantiator. | 2280 __ popq(RAX); // Pop instantiator. |
| 2276 // RAX is the instantiator AbstractTypeArguments object (or null). | 2281 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 2277 // If RAX is null, no need to instantiate the type arguments, use null, and | 2282 // If the instantiator is null and if the type argument vector |
| 2278 // allocate an object of a raw type. | 2283 // instantiated from null becomes a vector of Dynamic, then use null as |
| 2279 Label type_arguments_instantiated, type_arguments_uninstantiated; | 2284 // the type arguments. |
| 2280 __ cmpq(RAX, raw_null); | 2285 Label type_arguments_instantiated; |
| 2281 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2286 const intptr_t len = node->type_arguments().Length(); |
| 2282 | 2287 if (node->type_arguments().IsRawInstantiatedRaw(len)) { |
| 2288 __ cmpq(RAX, raw_null); |
| 2289 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2290 } |
| 2283 // Instantiate non-null type arguments. | 2291 // Instantiate non-null type arguments. |
| 2284 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2292 if (node->type_arguments().IsUninstantiatedIdentity()) { |
| 2285 // Check if the instantiator type argument vector is a TypeArguments of a | 2293 // Check if the instantiator type argument vector is a TypeArguments of a |
| 2286 // matching length and, if so, use it as the instantiated type_arguments. | 2294 // matching length and, if so, use it as the instantiated type_arguments. |
| 2295 // No need to check RAX for null (again), because a null instance will |
| 2296 // have the wrong class (Null instead of TypeArguments). |
| 2297 Label type_arguments_uninstantiated; |
| 2287 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 2298 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 2288 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 2299 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 2289 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 2300 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 2290 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 2301 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 2291 Smi::New(node->type_arguments().Length()))); | 2302 Smi::New(node->type_arguments().Length()))); |
| 2292 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 2303 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 2293 arguments_length); | 2304 arguments_length); |
| 2294 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2305 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2306 __ Bind(&type_arguments_uninstantiated); |
| 2295 } | 2307 } |
| 2296 __ Bind(&type_arguments_uninstantiated); | |
| 2297 if (node->constructor().IsFactory()) { | 2308 if (node->constructor().IsFactory()) { |
| 2298 // A runtime call to instantiate the type arguments is required before | 2309 // A runtime call to instantiate the type arguments is required before |
| 2299 // calling the factory. | 2310 // calling the factory. |
| 2300 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2311 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2301 __ PushObject(node->type_arguments()); | 2312 __ PushObject(node->type_arguments()); |
| 2302 __ pushq(RAX); // Push instantiator type arguments. | 2313 __ pushq(RAX); // Push instantiator type arguments. |
| 2303 GenerateCallRuntime(node->id(), | 2314 GenerateCallRuntime(node->id(), |
| 2304 node->token_index(), | 2315 node->token_index(), |
| 2305 kInstantiateTypeArgumentsRuntimeEntry); | 2316 kInstantiateTypeArgumentsRuntimeEntry); |
| 2306 __ popq(RAX); // Pop instantiator type arguments. | 2317 __ popq(RAX); // Pop instantiator type arguments. |
| 2307 __ popq(RAX); // Pop uninstantiated type arguments. | 2318 __ popq(RAX); // Pop uninstantiated type arguments. |
| 2308 __ popq(RAX); // Pop instantiated type arguments. | 2319 __ popq(RAX); // Pop instantiated type arguments. |
| 2309 __ Bind(&type_arguments_instantiated); | 2320 __ Bind(&type_arguments_instantiated); |
| 2310 __ pushq(RAX); // Instantiated type arguments. | 2321 __ pushq(RAX); // Instantiated type arguments. |
| 2311 } else { | 2322 } else { |
| 2312 // In the non-factory case, we rely on the allocation stub to | 2323 // In the non-factory case, we rely on the allocation stub to |
| 2313 // instantiate the type arguments. | 2324 // instantiate the type arguments. |
| 2314 __ PushObject(node->type_arguments()); | 2325 __ PushObject(node->type_arguments()); |
| 2315 __ pushq(RAX); // Instantiator type arguments. | 2326 __ pushq(RAX); // Instantiator type arguments. |
| 2316 Label type_arguments_pushed; | 2327 Label type_arguments_pushed; |
| 2317 __ jmp(&type_arguments_pushed, Assembler::kNearJump); | 2328 __ jmp(&type_arguments_pushed, Assembler::kNearJump); |
| 2318 | 2329 |
| 2319 __ Bind(&type_arguments_instantiated); | 2330 __ Bind(&type_arguments_instantiated); |
| 2320 __ pushq(RAX); // Instantiated type arguments. | 2331 __ pushq(RAX); // Instantiated type arguments. |
| 2321 __ pushq(raw_null); // Null instantiator. | 2332 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2322 __ Bind(&type_arguments_pushed); | 2333 __ Bind(&type_arguments_pushed); |
| 2323 } | 2334 } |
| 2324 } | 2335 } |
| 2325 } | 2336 } |
| 2326 | 2337 |
| 2327 | 2338 |
| 2328 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { | 2339 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2329 if (node->constructor().IsFactory()) { | 2340 if (node->constructor().IsFactory()) { |
| 2330 const bool requires_type_arguments = true; // Always first arg to factory. | 2341 const bool requires_type_arguments = true; // Always first arg to factory. |
| 2331 GenerateTypeArguments(node, requires_type_arguments); | 2342 GenerateTypeArguments(node, requires_type_arguments); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2363 } | 2374 } |
| 2364 | 2375 |
| 2365 if (IsResultNeeded(node)) { | 2376 if (IsResultNeeded(node)) { |
| 2366 __ pushq(RAX); // Set up return value from allocate. | 2377 __ pushq(RAX); // Set up return value from allocate. |
| 2367 } | 2378 } |
| 2368 | 2379 |
| 2369 // First argument(this) for constructor call which follows. | 2380 // First argument(this) for constructor call which follows. |
| 2370 __ pushq(RAX); | 2381 __ pushq(RAX); |
| 2371 // Second argument is the implicit construction phase parameter. | 2382 // Second argument is the implicit construction phase parameter. |
| 2372 // Run both the constructor initializer list and the constructor body. | 2383 // Run both the constructor initializer list and the constructor body. |
| 2373 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 2384 __ pushq(Immediate(Smi::RawValue(Function::kCtorPhaseAll))); |
| 2374 | |
| 2375 | 2385 |
| 2376 // Now setup rest of the arguments for the constructor call. | 2386 // Now setup rest of the arguments for the constructor call. |
| 2377 node->arguments()->Visit(this); | 2387 node->arguments()->Visit(this); |
| 2378 | 2388 |
| 2379 // Call the constructor. | 2389 // Call the constructor. |
| 2380 // +2 to include implicit receiver and phase arguments. | 2390 // +2 to include implicit receiver and phase arguments. |
| 2381 int num_args = node->arguments()->length() + 2; | 2391 int num_args = node->arguments()->length() + 2; |
| 2382 __ LoadObject(RBX, node->constructor()); | 2392 __ LoadObject(RBX, node->constructor()); |
| 2383 __ LoadObject(R10, ArgumentsDescriptor(num_args, node->arguments()->names())); | 2393 __ LoadObject(R10, ArgumentsDescriptor(num_args, node->arguments()->names())); |
| 2384 GenerateCall(node->token_index(), | 2394 GenerateCall(node->token_index(), |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2705 const Error& error = Error::Handle( | 2715 const Error& error = Error::Handle( |
| 2706 Parser::FormatError(script, token_index, "Error", format, args)); | 2716 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2707 va_end(args); | 2717 va_end(args); |
| 2708 Isolate::Current()->long_jump_base()->Jump(1, error); | 2718 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2709 UNREACHABLE(); | 2719 UNREACHABLE(); |
| 2710 } | 2720 } |
| 2711 | 2721 |
| 2712 } // namespace dart | 2722 } // namespace dart |
| 2713 | 2723 |
| 2714 #endif // defined TARGET_ARCH_X64 | 2724 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |