Chromium Code Reviews| 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" |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 __ pushl(Address(EBP, variable.index() * kWordSize)); | 419 __ pushl(Address(EBP, variable.index() * kWordSize)); |
| 420 } | 420 } |
| 421 } | 421 } |
| 422 | 422 |
| 423 | 423 |
| 424 void CodeGenerator::GenerateInstanceCall( | 424 void CodeGenerator::GenerateInstanceCall( |
| 425 intptr_t node_id, | 425 intptr_t node_id, |
| 426 intptr_t token_index, | 426 intptr_t token_index, |
| 427 const String& function_name, | 427 const String& function_name, |
| 428 int num_arguments, | 428 int num_arguments, |
| 429 const Array& optional_arguments_names) { | 429 const Array& optional_arguments_names, |
| 430 intptr_t num_checks) { | |
| 431 ASSERT(num_checks > 0); // At least receiver check is necessary. | |
| 430 // Set up the function name and number of arguments (including the receiver) | 432 // Set up the function name and number of arguments (including the receiver) |
| 431 // to the InstanceCall stub which will resolve the correct entrypoint for | 433 // to the InstanceCall stub which will resolve the correct entrypoint for |
| 432 // the operator and call it. | 434 // the operator and call it. |
| 433 ICData ic_data(function_name, 1); | 435 ICData ic_data(function_name, num_checks); |
| 434 __ LoadObject(ECX, Array::ZoneHandle(ic_data.data())); | 436 __ LoadObject(ECX, Array::ZoneHandle(ic_data.data())); |
| 435 __ LoadObject(EDX, ArgumentsDescriptor(num_arguments, | 437 __ LoadObject(EDX, ArgumentsDescriptor(num_arguments, |
| 436 optional_arguments_names)); | 438 optional_arguments_names)); |
| 437 ExternalLabel target_label( | 439 uword label_address = 0; |
| 438 "InlineCache", StubCode::InlineCacheEntryPoint()); | 440 switch (num_checks) { |
| 441 case 1: | |
| 442 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); | |
| 443 break; | |
| 444 case 2: | |
| 445 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); | |
| 446 break; | |
| 447 default: | |
| 448 UNIMPLEMENTED(); | |
| 449 } | |
| 450 ExternalLabel target_label("InlineCache", label_address); | |
| 439 | 451 |
| 440 __ call(&target_label); | 452 __ call(&target_label); |
| 441 AddCurrentDescriptor(PcDescriptors::kIcCall, | 453 AddCurrentDescriptor(PcDescriptors::kIcCall, |
| 442 node_id, | 454 node_id, |
| 443 token_index); | 455 token_index); |
| 444 __ addl(ESP, Immediate(num_arguments * kWordSize)); | 456 __ addl(ESP, Immediate(num_arguments * kWordSize)); |
| 445 } | 457 } |
| 446 | 458 |
| 447 | 459 |
| 448 // Call to generate entry code: | 460 // Call to generate entry code: |
| (...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 intptr_t token_index) { | 1059 intptr_t token_index) { |
| 1048 // Invoke the [] operator on the receiver object with the index as argument. | 1060 // Invoke the [] operator on the receiver object with the index as argument. |
| 1049 const String& operator_name = | 1061 const String& operator_name = |
| 1050 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX))); | 1062 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX))); |
| 1051 const int kNumArguments = 2; // Receiver and index. | 1063 const int kNumArguments = 2; // Receiver and index. |
| 1052 const Array& kNoArgumentNames = Array::Handle(); | 1064 const Array& kNoArgumentNames = Array::Handle(); |
| 1053 GenerateInstanceCall(node_id, | 1065 GenerateInstanceCall(node_id, |
| 1054 token_index, | 1066 token_index, |
| 1055 operator_name, | 1067 operator_name, |
| 1056 kNumArguments, | 1068 kNumArguments, |
| 1057 kNoArgumentNames); | 1069 kNoArgumentNames, |
| 1070 1); | |
|
regis
2011/12/09 23:08:03
Declaring a constant as for kNumArguments and kNoA
srdjan
2011/12/12 17:19:33
Added const int kNumArgumentsChecked
| |
| 1058 } | 1071 } |
| 1059 | 1072 |
| 1060 | 1073 |
| 1061 void CodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) { | 1074 void CodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) { |
| 1062 node->array()->Visit(this); | 1075 node->array()->Visit(this); |
| 1063 // Now compute the index. | 1076 // Now compute the index. |
| 1064 node->index_expr()->Visit(this); | 1077 node->index_expr()->Visit(this); |
| 1065 MarkDeoptPoint(node->id(), node->token_index()); | 1078 MarkDeoptPoint(node->id(), node->token_index()); |
| 1066 GenerateLoadIndexed(node->id(), node->token_index()); | 1079 GenerateLoadIndexed(node->id(), node->token_index()); |
| 1067 // Result is in EAX. | 1080 // Result is in EAX. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1092 // Invoke the []= operator on the receiver object with index and | 1105 // Invoke the []= operator on the receiver object with index and |
| 1093 // value as arguments. | 1106 // value as arguments. |
| 1094 const String& operator_name = | 1107 const String& operator_name = |
| 1095 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 1108 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| 1096 const int kNumArguments = 3; // Receiver, index and value. | 1109 const int kNumArguments = 3; // Receiver, index and value. |
| 1097 const Array& kNoArgumentNames = Array::Handle(); | 1110 const Array& kNoArgumentNames = Array::Handle(); |
| 1098 GenerateInstanceCall(node_id, | 1111 GenerateInstanceCall(node_id, |
| 1099 token_index, | 1112 token_index, |
| 1100 operator_name, | 1113 operator_name, |
| 1101 kNumArguments, | 1114 kNumArguments, |
| 1102 kNoArgumentNames); | 1115 kNoArgumentNames, |
| 1116 1); | |
|
regis
2011/12/09 23:08:03
ditto and ditto for all other instances below.
srdjan
2011/12/12 17:19:33
Done.
| |
| 1103 } | 1117 } |
| 1104 | 1118 |
| 1105 | 1119 |
| 1106 void CodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { | 1120 void CodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { |
| 1107 // Compute the receiver object and pass as first argument to call. | 1121 // Compute the receiver object and pass as first argument to call. |
| 1108 node->array()->Visit(this); | 1122 node->array()->Visit(this); |
| 1109 // Now compute the index. | 1123 // Now compute the index. |
| 1110 node->index_expr()->Visit(this); | 1124 node->index_expr()->Visit(this); |
| 1111 // Finally compute the value to assign. | 1125 // Finally compute the value to assign. |
| 1112 node->value()->Visit(this); | 1126 node->value()->Visit(this); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1184 operator_name = String::NewSymbol(Token::Str(Token::kNEGATE)); | 1198 operator_name = String::NewSymbol(Token::Str(Token::kNEGATE)); |
| 1185 } else { | 1199 } else { |
| 1186 operator_name = String::NewSymbol(node->Name()); | 1200 operator_name = String::NewSymbol(node->Name()); |
| 1187 } | 1201 } |
| 1188 const int kNumberOfArguments = 1; | 1202 const int kNumberOfArguments = 1; |
| 1189 const Array& kNoArgumentNames = Array::Handle(); | 1203 const Array& kNoArgumentNames = Array::Handle(); |
| 1190 GenerateInstanceCall(node->id(), | 1204 GenerateInstanceCall(node->id(), |
| 1191 node->token_index(), | 1205 node->token_index(), |
| 1192 operator_name, | 1206 operator_name, |
| 1193 kNumberOfArguments, | 1207 kNumberOfArguments, |
| 1194 kNoArgumentNames); | 1208 kNoArgumentNames, |
| 1209 1); | |
| 1195 if (IsResultNeeded(node)) { | 1210 if (IsResultNeeded(node)) { |
| 1196 __ pushl(EAX); | 1211 __ pushl(EAX); |
| 1197 } | 1212 } |
| 1198 } | 1213 } |
| 1199 | 1214 |
| 1200 | 1215 |
| 1201 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { | 1216 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { |
| 1202 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | 1217 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); |
| 1203 MarkDeoptPoint(node->id(), node->token_index()); | 1218 MarkDeoptPoint(node->id(), node->token_index()); |
| 1204 GenerateLoadVariable(EAX, node->local()); | 1219 GenerateLoadVariable(EAX, node->local()); |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1811 __ Bind(&non_null_compare); | 1826 __ Bind(&non_null_compare); |
| 1812 } | 1827 } |
| 1813 // Do '==' first then negate if necessary, | 1828 // Do '==' first then negate if necessary, |
| 1814 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 1829 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 1815 const int kNumberOfArguments = 2; | 1830 const int kNumberOfArguments = 2; |
| 1816 const Array& kNoArgumentNames = Array::Handle(); | 1831 const Array& kNoArgumentNames = Array::Handle(); |
| 1817 GenerateInstanceCall(node->id(), | 1832 GenerateInstanceCall(node->id(), |
| 1818 node->token_index(), | 1833 node->token_index(), |
| 1819 operator_name, | 1834 operator_name, |
| 1820 kNumberOfArguments, | 1835 kNumberOfArguments, |
| 1821 kNoArgumentNames); | 1836 kNoArgumentNames, |
| 1837 1); | |
| 1822 | 1838 |
| 1823 // Result is in EAX. No need to negate if result is not needed. | 1839 // Result is in EAX. No need to negate if result is not needed. |
| 1824 if ((node->kind() == Token::kNE) && IsResultNeeded(node)) { | 1840 if ((node->kind() == Token::kNE) && IsResultNeeded(node)) { |
| 1825 // Negate result. | 1841 // Negate result. |
| 1826 Label load_true, done; | 1842 Label load_true, done; |
| 1827 __ LoadObject(EDX, bool_false); | 1843 __ LoadObject(EDX, bool_false); |
| 1828 __ cmpl(EAX, EDX); | 1844 __ cmpl(EAX, EDX); |
| 1829 __ j(EQUAL, &load_true, Assembler::kNearJump); | 1845 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 1830 __ movl(EAX, EDX); // false. | 1846 __ movl(EAX, EDX); // false. |
| 1831 __ jmp(&done, Assembler::kNearJump); | 1847 __ jmp(&done, Assembler::kNearJump); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2078 void CodeGenerator::GenerateBinaryOperatorCall(intptr_t node_id, | 2094 void CodeGenerator::GenerateBinaryOperatorCall(intptr_t node_id, |
| 2079 intptr_t token_index, | 2095 intptr_t token_index, |
| 2080 const char* name) { | 2096 const char* name) { |
| 2081 const String& operator_name = String::ZoneHandle(String::NewSymbol(name)); | 2097 const String& operator_name = String::ZoneHandle(String::NewSymbol(name)); |
| 2082 const int kNumberOfArguments = 2; | 2098 const int kNumberOfArguments = 2; |
| 2083 const Array& kNoArgumentNames = Array::Handle(); | 2099 const Array& kNoArgumentNames = Array::Handle(); |
| 2084 GenerateInstanceCall(node_id, | 2100 GenerateInstanceCall(node_id, |
| 2085 token_index, | 2101 token_index, |
| 2086 operator_name, | 2102 operator_name, |
| 2087 kNumberOfArguments, | 2103 kNumberOfArguments, |
| 2088 kNoArgumentNames); | 2104 kNoArgumentNames, |
| 2105 2); | |
| 2089 } | 2106 } |
| 2090 | 2107 |
| 2091 | 2108 |
| 2092 void CodeGenerator::VisitBinaryOpNode(BinaryOpNode* node) { | 2109 void CodeGenerator::VisitBinaryOpNode(BinaryOpNode* node) { |
| 2093 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 2110 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 2094 // Operators "&&" and "||" cannot be overloaded, therefore inline them | 2111 // Operators "&&" and "||" cannot be overloaded, therefore inline them |
| 2095 // instead of calling the operator. | 2112 // instead of calling the operator. |
| 2096 GenerateLogicalAndOrOp(node); | 2113 GenerateLogicalAndOrOp(node); |
| 2097 return; | 2114 return; |
| 2098 } | 2115 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2182 // Now compute rest of the arguments to the call. | 2199 // Now compute rest of the arguments to the call. |
| 2183 node->arguments()->Visit(this); | 2200 node->arguments()->Visit(this); |
| 2184 // Some method may be inlined using type feedback, therefore this may be a | 2201 // Some method may be inlined using type feedback, therefore this may be a |
| 2185 // deoptimization point. | 2202 // deoptimization point. |
| 2186 MarkDeoptPoint(node->id(), node->token_index()); | 2203 MarkDeoptPoint(node->id(), node->token_index()); |
| 2187 | 2204 |
| 2188 GenerateInstanceCall(node->id(), | 2205 GenerateInstanceCall(node->id(), |
| 2189 node->token_index(), | 2206 node->token_index(), |
| 2190 node->function_name(), | 2207 node->function_name(), |
| 2191 number_of_arguments, | 2208 number_of_arguments, |
| 2192 node->arguments()->names()); | 2209 node->arguments()->names(), |
| 2210 1); | |
| 2193 // Result is in EAX. | 2211 // Result is in EAX. |
| 2194 if (IsResultNeeded(node)) { | 2212 if (IsResultNeeded(node)) { |
| 2195 __ pushl(EAX); | 2213 __ pushl(EAX); |
| 2196 } | 2214 } |
| 2197 } | 2215 } |
| 2198 | 2216 |
| 2199 | 2217 |
| 2200 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { | 2218 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { |
| 2201 node->arguments()->Visit(this); | 2219 node->arguments()->Visit(this); |
| 2202 __ LoadObject(ECX, node->function()); | 2220 __ LoadObject(ECX, node->function()); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2436 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, | 2454 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, |
| 2437 intptr_t token_index, | 2455 intptr_t token_index, |
| 2438 const String& field_name) { | 2456 const String& field_name) { |
| 2439 const String& getter_name = String::ZoneHandle(Field::GetterName(field_name)); | 2457 const String& getter_name = String::ZoneHandle(Field::GetterName(field_name)); |
| 2440 const int kNumberOfArguments = 1; | 2458 const int kNumberOfArguments = 1; |
| 2441 const Array& kNoArgumentNames = Array::Handle(); | 2459 const Array& kNoArgumentNames = Array::Handle(); |
| 2442 GenerateInstanceCall(node_id, | 2460 GenerateInstanceCall(node_id, |
| 2443 token_index, | 2461 token_index, |
| 2444 getter_name, | 2462 getter_name, |
| 2445 kNumberOfArguments, | 2463 kNumberOfArguments, |
| 2446 kNoArgumentNames); | 2464 kNoArgumentNames, |
| 2465 1); | |
| 2447 } | 2466 } |
| 2448 | 2467 |
| 2449 | 2468 |
| 2450 // Call to the instance getter. | 2469 // Call to the instance getter. |
| 2451 void CodeGenerator::VisitInstanceGetterNode(InstanceGetterNode* node) { | 2470 void CodeGenerator::VisitInstanceGetterNode(InstanceGetterNode* node) { |
| 2452 node->receiver()->Visit(this); | 2471 node->receiver()->Visit(this); |
| 2453 MarkDeoptPoint(node->id(), node->token_index()); | 2472 MarkDeoptPoint(node->id(), node->token_index()); |
| 2454 GenerateInstanceGetterCall(node->id(), | 2473 GenerateInstanceGetterCall(node->id(), |
| 2455 node->token_index(), | 2474 node->token_index(), |
| 2456 node->field_name()); | 2475 node->field_name()); |
| 2457 if (IsResultNeeded(node)) { | 2476 if (IsResultNeeded(node)) { |
| 2458 __ pushl(EAX); | 2477 __ pushl(EAX); |
| 2459 } | 2478 } |
| 2460 } | 2479 } |
| 2461 | 2480 |
| 2462 | 2481 |
| 2463 // Expects receiver and value on stack. | 2482 // Expects receiver and value on stack. |
| 2464 void CodeGenerator::GenerateInstanceSetterCall(intptr_t node_id, | 2483 void CodeGenerator::GenerateInstanceSetterCall(intptr_t node_id, |
| 2465 intptr_t token_index, | 2484 intptr_t token_index, |
| 2466 const String& field_name) { | 2485 const String& field_name) { |
| 2467 const String& setter_name = String::ZoneHandle(Field::SetterName(field_name)); | 2486 const String& setter_name = String::ZoneHandle(Field::SetterName(field_name)); |
| 2468 const int kNumberOfArguments = 2; // receiver + value. | 2487 const int kNumberOfArguments = 2; // receiver + value. |
| 2469 const Array& kNoArgumentNames = Array::Handle(); | 2488 const Array& kNoArgumentNames = Array::Handle(); |
| 2470 GenerateInstanceCall(node_id, | 2489 GenerateInstanceCall(node_id, |
| 2471 token_index, | 2490 token_index, |
| 2472 setter_name, | 2491 setter_name, |
| 2473 kNumberOfArguments, | 2492 kNumberOfArguments, |
| 2474 kNoArgumentNames); | 2493 kNoArgumentNames, |
| 2494 1); | |
| 2475 } | 2495 } |
| 2476 | 2496 |
| 2477 | 2497 |
| 2478 // The call to the instance setter implements the assignment to a field. | 2498 // The call to the instance setter implements the assignment to a field. |
| 2479 // The result of the assignment to a field is the value being stored. | 2499 // The result of the assignment to a field is the value being stored. |
| 2480 void CodeGenerator::VisitInstanceSetterNode(InstanceSetterNode* node) { | 2500 void CodeGenerator::VisitInstanceSetterNode(InstanceSetterNode* node) { |
| 2481 // Compute the receiver object and pass it as first argument to call. | 2501 // Compute the receiver object and pass it as first argument to call. |
| 2482 node->receiver()->Visit(this); | 2502 node->receiver()->Visit(this); |
| 2483 node->value()->Visit(this); | 2503 node->value()->Visit(this); |
| 2484 MarkDeoptPoint(node->id(), node->token_index()); | 2504 MarkDeoptPoint(node->id(), node->token_index()); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2743 message_buffer, kMessageBufferSize, | 2763 message_buffer, kMessageBufferSize, |
| 2744 format, args); | 2764 format, args); |
| 2745 va_end(args); | 2765 va_end(args); |
| 2746 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); | 2766 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); |
| 2747 UNREACHABLE(); | 2767 UNREACHABLE(); |
| 2748 } | 2768 } |
| 2749 | 2769 |
| 2750 } // namespace dart | 2770 } // namespace dart |
| 2751 | 2771 |
| 2752 #endif // defined TARGET_ARCH_IA32 | 2772 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |