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