| 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 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 | 1116 |
| 1117 | 1117 |
| 1118 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { | 1118 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { |
| 1119 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | 1119 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); |
| 1120 MarkDeoptPoint(node->id(), node->token_index()); | 1120 MarkDeoptPoint(node->id(), node->token_index()); |
| 1121 GenerateLoadVariable(RAX, node->local()); | 1121 GenerateLoadVariable(RAX, node->local()); |
| 1122 if (!node->prefix() && IsResultNeeded(node)) { | 1122 if (!node->prefix() && IsResultNeeded(node)) { |
| 1123 // Preserve as result. | 1123 // Preserve as result. |
| 1124 __ pushq(RAX); | 1124 __ pushq(RAX); |
| 1125 } | 1125 } |
| 1126 const Immediate value = Immediate(reinterpret_cast<int64_t>(Smi::New(1))); | |
| 1127 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; | 1126 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; |
| 1128 __ pushq(RAX); | 1127 __ pushq(RAX); |
| 1129 __ pushq(value); | 1128 __ pushq(Immediate(Smi::RawValue(1))); |
| 1130 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name); | 1129 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name); |
| 1131 // result is in RAX. | 1130 // result is in RAX. |
| 1132 if (FLAG_enable_type_checks) { | 1131 if (FLAG_enable_type_checks) { |
| 1133 GenerateAssertAssignable(node->id(), | 1132 GenerateAssertAssignable(node->id(), |
| 1134 node->token_index(), | 1133 node->token_index(), |
| 1135 NULL, | 1134 NULL, |
| 1136 node->local().type(), | 1135 node->local().type(), |
| 1137 node->local().name()); | 1136 node->local().name()); |
| 1138 } | 1137 } |
| 1139 GenerateStoreVariable(node->local(), RAX, RDX); | 1138 GenerateStoreVariable(node->local(), RAX, RDX); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1151 MarkDeoptPoint(node->getter_id(), node->token_index()); | 1150 MarkDeoptPoint(node->getter_id(), node->token_index()); |
| 1152 GenerateInstanceGetterCall(node->getter_id(), | 1151 GenerateInstanceGetterCall(node->getter_id(), |
| 1153 node->token_index(), | 1152 node->token_index(), |
| 1154 node->field_name()); | 1153 node->field_name()); |
| 1155 // result is in RAX. | 1154 // result is in RAX. |
| 1156 __ popq(RDX); // Get receiver. | 1155 __ popq(RDX); // Get receiver. |
| 1157 if (!node->prefix() && IsResultNeeded(node)) { | 1156 if (!node->prefix() && IsResultNeeded(node)) { |
| 1158 // Preserve as result. | 1157 // Preserve as result. |
| 1159 __ pushq(RAX); // Preserve value as result. | 1158 __ pushq(RAX); // Preserve value as result. |
| 1160 } | 1159 } |
| 1161 const Immediate one_value = Immediate(reinterpret_cast<int64_t>(Smi::New(1))); | |
| 1162 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; | 1160 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; |
| 1163 // RAX: Value. | 1161 // RAX: Value. |
| 1164 // RDX: Receiver. | 1162 // RDX: Receiver. |
| 1165 __ pushq(RDX); // Preserve receiver. | 1163 __ pushq(RDX); // Preserve receiver. |
| 1166 __ pushq(RAX); // Left operand. | 1164 __ pushq(RAX); // Left operand. |
| 1167 __ pushq(one_value); // Right operand. | 1165 __ pushq(Immediate(Smi::RawValue(1))); // Right operand. |
| 1168 GenerateBinaryOperatorCall(node->operator_id(), | 1166 GenerateBinaryOperatorCall(node->operator_id(), |
| 1169 node->token_index(), | 1167 node->token_index(), |
| 1170 operator_name); | 1168 operator_name); |
| 1171 __ popq(RDX); // Restore receiver. | 1169 __ popq(RDX); // Restore receiver. |
| 1172 if (IsResultNeeded(node) && node->prefix()) { | 1170 if (IsResultNeeded(node) && node->prefix()) { |
| 1173 // Value stored into field is the result. | 1171 // Value stored into field is the result. |
| 1174 __ pushq(RAX); | 1172 __ pushq(RAX); |
| 1175 } | 1173 } |
| 1176 __ pushq(RDX); // Receiver. | 1174 __ pushq(RDX); // Receiver. |
| 1177 __ pushq(RAX); // Value. | 1175 __ pushq(RAX); // Value. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1194 GenerateLoadIndexed(node->load_id(), node->token_index()); | 1192 GenerateLoadIndexed(node->load_id(), node->token_index()); |
| 1195 // Result is in RAX. | 1193 // Result is in RAX. |
| 1196 if (!node->prefix() && IsResultNeeded(node)) { | 1194 if (!node->prefix() && IsResultNeeded(node)) { |
| 1197 // Preserve RAX as result. | 1195 // Preserve RAX as result. |
| 1198 __ popq(RDX); // Preserved index -> RDX. | 1196 __ popq(RDX); // Preserved index -> RDX. |
| 1199 __ popq(RCX); // Preserved array -> RCX. | 1197 __ popq(RCX); // Preserved array -> RCX. |
| 1200 __ pushq(RAX); // Preserve original value from indexed load. | 1198 __ pushq(RAX); // Preserve original value from indexed load. |
| 1201 __ pushq(RCX); // Array. | 1199 __ pushq(RCX); // Array. |
| 1202 __ pushq(RDX); // Index. | 1200 __ pushq(RDX); // Index. |
| 1203 } | 1201 } |
| 1204 const Immediate value = Immediate(reinterpret_cast<int64_t>(Smi::New(1))); | |
| 1205 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; | 1202 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; |
| 1206 __ pushq(RAX); // Left operand. | 1203 __ pushq(RAX); // Left operand. |
| 1207 __ pushq(value); // Right operand. | 1204 __ pushq(Immediate(Smi::RawValue(1))); // Right operand. |
| 1208 GenerateBinaryOperatorCall(node->operator_id(), | 1205 GenerateBinaryOperatorCall(node->operator_id(), |
| 1209 node->token_index(), | 1206 node->token_index(), |
| 1210 operator_name); | 1207 operator_name); |
| 1211 __ pushq(RAX); | 1208 __ pushq(RAX); |
| 1212 // TOS(0): value, TOS(1): index, TOS(2): array. | 1209 // TOS(0): value, TOS(1): index, TOS(2): array. |
| 1213 GenerateStoreIndexed(node->store_id(), | 1210 GenerateStoreIndexed(node->store_id(), |
| 1214 node->token_index(), | 1211 node->token_index(), |
| 1215 node->prefix() && IsResultNeeded(node)); | 1212 node->prefix() && IsResultNeeded(node)); |
| 1216 } | 1213 } |
| 1217 | 1214 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1375 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1372 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1376 __ CompareObject(RCX, *compare_class); | 1373 __ CompareObject(RCX, *compare_class); |
| 1377 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); | 1374 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); |
| 1378 __ PushObject(negate_result ? bool_false : bool_true); | 1375 __ PushObject(negate_result ? bool_false : bool_true); |
| 1379 __ jmp(&done, Assembler::kNearJump); | 1376 __ jmp(&done, Assembler::kNearJump); |
| 1380 __ Bind(&runtime_call); | 1377 __ Bind(&runtime_call); |
| 1381 } | 1378 } |
| 1382 } | 1379 } |
| 1383 } | 1380 } |
| 1384 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1381 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1385 const Immediate location = | 1382 const Immediate location = Immediate(Smi::RawValue(token_index)); |
| 1386 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 1383 const Immediate node_id_as_smi = Immediate(Smi::RawValue(node_id)); |
| 1387 const Immediate node_id_as_smi = | |
| 1388 Immediate(reinterpret_cast<int64_t>(Smi::New(node_id))); | |
| 1389 __ pushq(location); // Push the source location. | 1384 __ pushq(location); // Push the source location. |
| 1390 __ pushq(node_id_as_smi); | 1385 __ pushq(node_id_as_smi); |
| 1391 __ pushq(RAX); // Push the instance. | 1386 __ pushq(RAX); // Push the instance. |
| 1392 __ PushObject(type); // Push the type. | 1387 __ PushObject(type); // Push the type. |
| 1393 if (!type.IsInstantiated()) { | 1388 if (!type.IsInstantiated()) { |
| 1394 GenerateInstantiatorTypeArguments(token_index); | 1389 GenerateInstantiatorTypeArguments(token_index); |
| 1395 } else { | 1390 } else { |
| 1396 __ pushq(raw_null); // Null instantiator. | 1391 __ pushq(raw_null); // Null instantiator. |
| 1397 } | 1392 } |
| 1398 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); | 1393 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1486 Label done, runtime_call; | 1481 Label done, runtime_call; |
| 1487 __ cmpq(RAX, raw_null); | 1482 __ cmpq(RAX, raw_null); |
| 1488 __ j(EQUAL, &done); | 1483 __ j(EQUAL, &done); |
| 1489 | 1484 |
| 1490 // Generate throw new TypeError() if the type is malformed. | 1485 // Generate throw new TypeError() if the type is malformed. |
| 1491 if (dst_type.IsMalformed()) { | 1486 if (dst_type.IsMalformed()) { |
| 1492 const Error& error = Error::Handle(dst_type.malformed_error()); | 1487 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 1493 const String& error_message = String::ZoneHandle( | 1488 const String& error_message = String::ZoneHandle( |
| 1494 String::NewSymbol(error.ToErrorCString())); | 1489 String::NewSymbol(error.ToErrorCString())); |
| 1495 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1490 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1496 const Immediate location = | 1491 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location. |
| 1497 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | |
| 1498 __ pushq(location); // Push the source location. | |
| 1499 __ pushq(RAX); // Push the source object. | 1492 __ pushq(RAX); // Push the source object. |
| 1500 __ PushObject(dst_name); // Push the name of the destination. | 1493 __ PushObject(dst_name); // Push the name of the destination. |
| 1501 __ PushObject(error_message); | 1494 __ PushObject(error_message); |
| 1502 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry); | 1495 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry); |
| 1503 // We should never return here. | 1496 // We should never return here. |
| 1504 __ int3(); | 1497 __ int3(); |
| 1505 | 1498 |
| 1506 __ Bind(&done); // For a null object. | 1499 __ Bind(&done); // For a null object. |
| 1507 return; | 1500 return; |
| 1508 } | 1501 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1603 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1596 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1604 __ movq(RCX, FieldAddress(RCX, Class::signature_function_offset())); | 1597 __ movq(RCX, FieldAddress(RCX, Class::signature_function_offset())); |
| 1605 __ cmpq(RCX, raw_null); | 1598 __ cmpq(RCX, raw_null); |
| 1606 __ j(NOT_EQUAL, &done); | 1599 __ j(NOT_EQUAL, &done); |
| 1607 } | 1600 } |
| 1608 } | 1601 } |
| 1609 } | 1602 } |
| 1610 } | 1603 } |
| 1611 __ Bind(&runtime_call); | 1604 __ Bind(&runtime_call); |
| 1612 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1605 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1613 const Immediate location = | 1606 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location. |
| 1614 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 1607 __ pushq(Immediate(Smi::RawValue(node_id))); // node-id. |
| 1615 const Immediate node_id_as_smi = | |
| 1616 Immediate(reinterpret_cast<int64_t>(Smi::New(node_id))); | |
| 1617 __ pushq(location); // Push the source location. | |
| 1618 __ pushq(node_id_as_smi); // node-id. | |
| 1619 __ pushq(RAX); // Push the source object. | 1608 __ pushq(RAX); // Push the source object. |
| 1620 __ PushObject(dst_type); // Push the type of the destination. | 1609 __ PushObject(dst_type); // Push the type of the destination. |
| 1621 if (!dst_type.IsInstantiated()) { | 1610 if (!dst_type.IsInstantiated()) { |
| 1622 GenerateInstantiatorTypeArguments(token_index); | 1611 GenerateInstantiatorTypeArguments(token_index); |
| 1623 } else { | 1612 } else { |
| 1624 __ pushq(raw_null); // Null instantiator. | 1613 __ pushq(raw_null); // Null instantiator. |
| 1625 } | 1614 } |
| 1626 __ PushObject(dst_name); // Push the name of the destination. | 1615 __ PushObject(dst_name); // Push the name of the destination. |
| 1627 GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry); | 1616 GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry); |
| 1628 // Pop the parameters supplied to the runtime entry. The result of the | 1617 // Pop the parameters supplied to the runtime entry. The result of the |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1673 // This check should pass if the receiver's class implements the interface | 1662 // This check should pass if the receiver's class implements the interface |
| 1674 // 'bool'. Check only class 'Bool' since it is the only legal implementation | 1663 // 'bool'. Check only class 'Bool' since it is the only legal implementation |
| 1675 // of the interface 'bool'. | 1664 // of the interface 'bool'. |
| 1676 const Class& bool_class = | 1665 const Class& bool_class = |
| 1677 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); | 1666 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); |
| 1678 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 1667 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1679 __ CompareObject(RCX, bool_class); | 1668 __ CompareObject(RCX, bool_class); |
| 1680 __ j(EQUAL, &done, Assembler::kNearJump); | 1669 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1681 | 1670 |
| 1682 __ Bind(&runtime_call); | 1671 __ Bind(&runtime_call); |
| 1683 const Immediate location = | 1672 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location. |
| 1684 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | |
| 1685 __ pushq(location); // Push the source location. | |
| 1686 __ pushq(RAX); // Push the source object. | 1673 __ pushq(RAX); // Push the source object. |
| 1687 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); | 1674 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); |
| 1688 // We should never return here. | 1675 // We should never return here. |
| 1689 __ int3(); | 1676 __ int3(); |
| 1690 | 1677 |
| 1691 __ Bind(&done); | 1678 __ Bind(&done); |
| 1692 } | 1679 } |
| 1693 | 1680 |
| 1694 | 1681 |
| 1695 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { | 1682 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 // Instantiate non-null type arguments. | 2295 // Instantiate non-null type arguments. |
| 2309 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2296 if (node->type_arguments().IsUninstantiatedIdentity()) { |
| 2310 // Check if the instantiator type argument vector is a TypeArguments of a | 2297 // Check if the instantiator type argument vector is a TypeArguments of a |
| 2311 // matching length and, if so, use it as the instantiated type_arguments. | 2298 // matching length and, if so, use it as the instantiated type_arguments. |
| 2312 // No need to check RAX for null (again), because a null instance will | 2299 // No need to check RAX for null (again), because a null instance will |
| 2313 // have the wrong class (Null instead of TypeArguments). | 2300 // have the wrong class (Null instead of TypeArguments). |
| 2314 Label type_arguments_uninstantiated; | 2301 Label type_arguments_uninstantiated; |
| 2315 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 2302 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 2316 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 2303 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 2317 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 2304 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 2318 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 2305 Immediate arguments_length = |
| 2319 Smi::New(node->type_arguments().Length()))); | 2306 Immediate(Smi::RawValue(node->type_arguments().Length())); |
| 2320 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 2307 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 2321 arguments_length); | 2308 arguments_length); |
| 2322 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2309 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2323 __ Bind(&type_arguments_uninstantiated); | 2310 __ Bind(&type_arguments_uninstantiated); |
| 2324 } | 2311 } |
| 2325 if (node->constructor().IsFactory()) { | 2312 if (node->constructor().IsFactory()) { |
| 2326 // A runtime call to instantiate the type arguments is required before | 2313 // A runtime call to instantiate the type arguments is required before |
| 2327 // calling the factory. | 2314 // calling the factory. |
| 2328 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2315 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2329 __ PushObject(node->type_arguments()); | 2316 __ PushObject(node->type_arguments()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2375 } | 2362 } |
| 2376 return; | 2363 return; |
| 2377 } | 2364 } |
| 2378 | 2365 |
| 2379 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | 2366 const Class& cls = Class::ZoneHandle(node->constructor().owner()); |
| 2380 const bool requires_type_arguments = cls.HasTypeArguments(); | 2367 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 2381 GenerateTypeArguments(node, requires_type_arguments); | 2368 GenerateTypeArguments(node, requires_type_arguments); |
| 2382 | 2369 |
| 2383 // If cls is parameterized, the type arguments and the instantiator's | 2370 // If cls is parameterized, the type arguments and the instantiator's |
| 2384 // type arguments are on the stack. | 2371 // type arguments are on the stack. |
| 2385 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 2372 // In checked mode, if the type arguments are uninstantiated, they may need to |
| 2386 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 2373 // be checked against declared bounds at run time. |
| 2387 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); | 2374 Error& malformed_error = Error::Handle(); |
| 2388 if (requires_type_arguments) { | 2375 if (FLAG_enable_type_checks && |
| 2376 requires_type_arguments && |
| 2377 !node->type_arguments().IsNull() && |
| 2378 !node->type_arguments().IsInstantiated() && |
| 2379 !node->type_arguments().IsWithinBoundsOf(cls, |
| 2380 node->type_arguments(), |
| 2381 &malformed_error)) { |
| 2382 // The uninstantiated type arguments cannot be verified to be within their |
| 2383 // bounds at compile time, so verify them at runtime. |
| 2384 // Although the type arguments may be uninstantiated at compile time, they |
| 2385 // may represent the identity vector and may be replaced by the instantiated |
| 2386 // type arguments of the instantiator at run time. |
| 2387 __ popq(RCX); // Pop instantiator type arguments. |
| 2388 __ popq(RAX); // Pop type arguments. |
| 2389 |
| 2390 // Push the result place holder initialized to NULL. |
| 2391 __ PushObject(Object::ZoneHandle()); |
| 2392 __ pushq(Immediate(Smi::RawValue(node->token_index()))); |
| 2393 __ PushObject(cls); |
| 2394 __ pushq(RAX); // Push type arguments. |
| 2395 __ pushq(RCX); // Push instantiator type arguments. |
| 2396 GenerateCallRuntime(node->id(), |
| 2397 node->token_index(), |
| 2398 kAllocateObjectWithBoundsCheckRuntimeEntry); |
| 2399 __ popq(RCX); // Pop instantiator type arguments. |
| 2389 __ popq(RCX); // Pop type arguments. | 2400 __ popq(RCX); // Pop type arguments. |
| 2390 __ popq(RCX); // Pop instantiator type arguments. | 2401 __ popq(RCX); // Pop class. |
| 2402 __ popq(RCX); // Pop source location. |
| 2403 __ popq(RAX); // Pop new instance. |
| 2404 } else { |
| 2405 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 2406 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 2407 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); |
| 2408 if (requires_type_arguments) { |
| 2409 __ popq(RCX); // Pop instantiator type arguments. |
| 2410 __ popq(RCX); // Pop type arguments. |
| 2411 } |
| 2391 } | 2412 } |
| 2392 | 2413 |
| 2393 if (IsResultNeeded(node)) { | 2414 if (IsResultNeeded(node)) { |
| 2394 __ pushq(RAX); // Set up return value from allocate. | 2415 __ pushq(RAX); // Set up return value from allocate. |
| 2395 } | 2416 } |
| 2396 | 2417 |
| 2397 // First argument(this) for constructor call which follows. | 2418 // First argument(this) for constructor call which follows. |
| 2398 __ pushq(RAX); | 2419 __ pushq(RAX); |
| 2399 // Second argument is the implicit construction phase parameter. | 2420 // Second argument is the implicit construction phase parameter. |
| 2400 // Run both the constructor initializer list and the constructor body. | 2421 // Run both the constructor initializer list and the constructor body. |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2735 const Error& error = Error::Handle( | 2756 const Error& error = Error::Handle( |
| 2736 Parser::FormatError(script, token_index, "Error", format, args)); | 2757 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2737 va_end(args); | 2758 va_end(args); |
| 2738 Isolate::Current()->long_jump_base()->Jump(1, error); | 2759 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2739 UNREACHABLE(); | 2760 UNREACHABLE(); |
| 2740 } | 2761 } |
| 2741 | 2762 |
| 2742 } // namespace dart | 2763 } // namespace dart |
| 2743 | 2764 |
| 2744 #endif // defined TARGET_ARCH_X64 | 2765 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |