Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(263)

Side by Side Diff: vm/code_generator_ia32.cc

Issue 8827015: Implement two-argument check inline cache. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « vm/code_generator_ia32.h ('k') | vm/code_patcher_ia32_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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_args_checked) {
431 ASSERT(num_args_checked > 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_args_checked);
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_args_checked) {
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 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 1055
1044 1056
1045 // Expects array and index on stack and returns result in EAX. 1057 // Expects array and index on stack and returns result in EAX.
1046 void CodeGenerator::GenerateLoadIndexed(intptr_t node_id, 1058 void CodeGenerator::GenerateLoadIndexed(intptr_t node_id,
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();
1065 const int kNumArgumentsChecked = 1;
1053 GenerateInstanceCall(node_id, 1066 GenerateInstanceCall(node_id,
1054 token_index, 1067 token_index,
1055 operator_name, 1068 operator_name,
1056 kNumArguments, 1069 kNumArguments,
1057 kNoArgumentNames); 1070 kNoArgumentNames,
1071 kNumArgumentsChecked);
1058 } 1072 }
1059 1073
1060 1074
1061 void CodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) { 1075 void CodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) {
1062 node->array()->Visit(this); 1076 node->array()->Visit(this);
1063 // Now compute the index. 1077 // Now compute the index.
1064 node->index_expr()->Visit(this); 1078 node->index_expr()->Visit(this);
1065 MarkDeoptPoint(node->id(), node->token_index()); 1079 MarkDeoptPoint(node->id(), node->token_index());
1066 GenerateLoadIndexed(node->id(), node->token_index()); 1080 GenerateLoadIndexed(node->id(), node->token_index());
1067 // Result is in EAX. 1081 // Result is in EAX.
(...skipping 20 matching lines...) Expand all
1088 __ pushl(ECX); // Restore arguments. 1102 __ pushl(ECX); // Restore arguments.
1089 __ pushl(EDX); 1103 __ pushl(EDX);
1090 __ pushl(EAX); 1104 __ pushl(EAX);
1091 } 1105 }
1092 // Invoke the []= operator on the receiver object with index and 1106 // Invoke the []= operator on the receiver object with index and
1093 // value as arguments. 1107 // value as arguments.
1094 const String& operator_name = 1108 const String& operator_name =
1095 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); 1109 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX)));
1096 const int kNumArguments = 3; // Receiver, index and value. 1110 const int kNumArguments = 3; // Receiver, index and value.
1097 const Array& kNoArgumentNames = Array::Handle(); 1111 const Array& kNoArgumentNames = Array::Handle();
1112 const int kNumArgumentsChecked = 1;
1098 GenerateInstanceCall(node_id, 1113 GenerateInstanceCall(node_id,
1099 token_index, 1114 token_index,
1100 operator_name, 1115 operator_name,
1101 kNumArguments, 1116 kNumArguments,
1102 kNoArgumentNames); 1117 kNoArgumentNames,
1118 kNumArgumentsChecked);
1103 } 1119 }
1104 1120
1105 1121
1106 void CodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { 1122 void CodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) {
1107 // Compute the receiver object and pass as first argument to call. 1123 // Compute the receiver object and pass as first argument to call.
1108 node->array()->Visit(this); 1124 node->array()->Visit(this);
1109 // Now compute the index. 1125 // Now compute the index.
1110 node->index_expr()->Visit(this); 1126 node->index_expr()->Visit(this);
1111 // Finally compute the value to assign. 1127 // Finally compute the value to assign.
1112 node->value()->Visit(this); 1128 node->value()->Visit(this);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 } 1196 }
1181 MarkDeoptPoint(node->id(), node->token_index()); 1197 MarkDeoptPoint(node->id(), node->token_index());
1182 String& operator_name = String::ZoneHandle(); 1198 String& operator_name = String::ZoneHandle();
1183 if (node->kind() == Token::kSUB) { 1199 if (node->kind() == Token::kSUB) {
1184 operator_name = String::NewSymbol(Token::Str(Token::kNEGATE)); 1200 operator_name = String::NewSymbol(Token::Str(Token::kNEGATE));
1185 } else { 1201 } else {
1186 operator_name = String::NewSymbol(node->Name()); 1202 operator_name = String::NewSymbol(node->Name());
1187 } 1203 }
1188 const int kNumberOfArguments = 1; 1204 const int kNumberOfArguments = 1;
1189 const Array& kNoArgumentNames = Array::Handle(); 1205 const Array& kNoArgumentNames = Array::Handle();
1206 const int kNumArgumentsChecked = 1;
1190 GenerateInstanceCall(node->id(), 1207 GenerateInstanceCall(node->id(),
1191 node->token_index(), 1208 node->token_index(),
1192 operator_name, 1209 operator_name,
1193 kNumberOfArguments, 1210 kNumberOfArguments,
1194 kNoArgumentNames); 1211 kNoArgumentNames,
1212 kNumArgumentsChecked);
1195 if (IsResultNeeded(node)) { 1213 if (IsResultNeeded(node)) {
1196 __ pushl(EAX); 1214 __ pushl(EAX);
1197 } 1215 }
1198 } 1216 }
1199 1217
1200 1218
1201 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { 1219 void CodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) {
1202 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); 1220 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR));
1203 MarkDeoptPoint(node->id(), node->token_index()); 1221 MarkDeoptPoint(node->id(), node->token_index());
1204 GenerateLoadVariable(EAX, node->local()); 1222 GenerateLoadVariable(EAX, node->local());
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 __ jmp(&null_done, Assembler::kNearJump); 1825 __ jmp(&null_done, Assembler::kNearJump);
1808 __ Bind(&load_true); 1826 __ Bind(&load_true);
1809 __ LoadObject(EAX, bool_true); 1827 __ LoadObject(EAX, bool_true);
1810 __ jmp(&null_done, Assembler::kNearJump); 1828 __ jmp(&null_done, Assembler::kNearJump);
1811 __ Bind(&non_null_compare); 1829 __ Bind(&non_null_compare);
1812 } 1830 }
1813 // Do '==' first then negate if necessary, 1831 // Do '==' first then negate if necessary,
1814 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); 1832 const String& operator_name = String::ZoneHandle(String::NewSymbol("=="));
1815 const int kNumberOfArguments = 2; 1833 const int kNumberOfArguments = 2;
1816 const Array& kNoArgumentNames = Array::Handle(); 1834 const Array& kNoArgumentNames = Array::Handle();
1835 const int kNumArgumentsChecked = 1;
1817 GenerateInstanceCall(node->id(), 1836 GenerateInstanceCall(node->id(),
1818 node->token_index(), 1837 node->token_index(),
1819 operator_name, 1838 operator_name,
1820 kNumberOfArguments, 1839 kNumberOfArguments,
1821 kNoArgumentNames); 1840 kNoArgumentNames,
1841 kNumArgumentsChecked);
1822 1842
1823 // Result is in EAX. No need to negate if result is not needed. 1843 // Result is in EAX. No need to negate if result is not needed.
1824 if ((node->kind() == Token::kNE) && IsResultNeeded(node)) { 1844 if ((node->kind() == Token::kNE) && IsResultNeeded(node)) {
1825 // Negate result. 1845 // Negate result.
1826 Label load_true, done; 1846 Label load_true, done;
1827 __ LoadObject(EDX, bool_false); 1847 __ LoadObject(EDX, bool_false);
1828 __ cmpl(EAX, EDX); 1848 __ cmpl(EAX, EDX);
1829 __ j(EQUAL, &load_true, Assembler::kNearJump); 1849 __ j(EQUAL, &load_true, Assembler::kNearJump);
1830 __ movl(EAX, EDX); // false. 1850 __ movl(EAX, EDX); // false.
1831 __ jmp(&done, Assembler::kNearJump); 1851 __ jmp(&done, Assembler::kNearJump);
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
2074 2094
2075 2095
2076 // Expect receiver(left operand) and right operand on stack. 2096 // Expect receiver(left operand) and right operand on stack.
2077 // Return result in EAX. 2097 // Return result in EAX.
2078 void CodeGenerator::GenerateBinaryOperatorCall(intptr_t node_id, 2098 void CodeGenerator::GenerateBinaryOperatorCall(intptr_t node_id,
2079 intptr_t token_index, 2099 intptr_t token_index,
2080 const char* name) { 2100 const char* name) {
2081 const String& operator_name = String::ZoneHandle(String::NewSymbol(name)); 2101 const String& operator_name = String::ZoneHandle(String::NewSymbol(name));
2082 const int kNumberOfArguments = 2; 2102 const int kNumberOfArguments = 2;
2083 const Array& kNoArgumentNames = Array::Handle(); 2103 const Array& kNoArgumentNames = Array::Handle();
2104 const int kNumArgumentsChecked = 2;
2084 GenerateInstanceCall(node_id, 2105 GenerateInstanceCall(node_id,
2085 token_index, 2106 token_index,
2086 operator_name, 2107 operator_name,
2087 kNumberOfArguments, 2108 kNumberOfArguments,
2088 kNoArgumentNames); 2109 kNoArgumentNames,
2110 kNumArgumentsChecked);
2089 } 2111 }
2090 2112
2091 2113
2092 void CodeGenerator::VisitBinaryOpNode(BinaryOpNode* node) { 2114 void CodeGenerator::VisitBinaryOpNode(BinaryOpNode* node) {
2093 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { 2115 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
2094 // Operators "&&" and "||" cannot be overloaded, therefore inline them 2116 // Operators "&&" and "||" cannot be overloaded, therefore inline them
2095 // instead of calling the operator. 2117 // instead of calling the operator.
2096 GenerateLogicalAndOrOp(node); 2118 GenerateLogicalAndOrOp(node);
2097 return; 2119 return;
2098 } 2120 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2177 2199
2178 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { 2200 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) {
2179 const int number_of_arguments = node->arguments()->length() + 1; 2201 const int number_of_arguments = node->arguments()->length() + 1;
2180 // Compute the receiver object and pass it as first argument to call. 2202 // Compute the receiver object and pass it as first argument to call.
2181 node->receiver()->Visit(this); 2203 node->receiver()->Visit(this);
2182 // Now compute rest of the arguments to the call. 2204 // Now compute rest of the arguments to the call.
2183 node->arguments()->Visit(this); 2205 node->arguments()->Visit(this);
2184 // Some method may be inlined using type feedback, therefore this may be a 2206 // Some method may be inlined using type feedback, therefore this may be a
2185 // deoptimization point. 2207 // deoptimization point.
2186 MarkDeoptPoint(node->id(), node->token_index()); 2208 MarkDeoptPoint(node->id(), node->token_index());
2187 2209 const int kNumArgumentsChecked = 1;
2188 GenerateInstanceCall(node->id(), 2210 GenerateInstanceCall(node->id(),
2189 node->token_index(), 2211 node->token_index(),
2190 node->function_name(), 2212 node->function_name(),
2191 number_of_arguments, 2213 number_of_arguments,
2192 node->arguments()->names()); 2214 node->arguments()->names(),
2215 kNumArgumentsChecked);
2193 // Result is in EAX. 2216 // Result is in EAX.
2194 if (IsResultNeeded(node)) { 2217 if (IsResultNeeded(node)) {
2195 __ pushl(EAX); 2218 __ pushl(EAX);
2196 } 2219 }
2197 } 2220 }
2198 2221
2199 2222
2200 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { 2223 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) {
2201 node->arguments()->Visit(this); 2224 node->arguments()->Visit(this);
2202 __ LoadObject(ECX, node->function()); 2225 __ LoadObject(ECX, node->function());
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
2432 } 2455 }
2433 2456
2434 2457
2435 // Expects receiver on stack, returns result in EAX.. 2458 // Expects receiver on stack, returns result in EAX..
2436 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, 2459 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id,
2437 intptr_t token_index, 2460 intptr_t token_index,
2438 const String& field_name) { 2461 const String& field_name) {
2439 const String& getter_name = String::ZoneHandle(Field::GetterName(field_name)); 2462 const String& getter_name = String::ZoneHandle(Field::GetterName(field_name));
2440 const int kNumberOfArguments = 1; 2463 const int kNumberOfArguments = 1;
2441 const Array& kNoArgumentNames = Array::Handle(); 2464 const Array& kNoArgumentNames = Array::Handle();
2465 const int kNumArgumentsChecked = 1;
2442 GenerateInstanceCall(node_id, 2466 GenerateInstanceCall(node_id,
2443 token_index, 2467 token_index,
2444 getter_name, 2468 getter_name,
2445 kNumberOfArguments, 2469 kNumberOfArguments,
2446 kNoArgumentNames); 2470 kNoArgumentNames,
2471 kNumArgumentsChecked);
2447 } 2472 }
2448 2473
2449 2474
2450 // Call to the instance getter. 2475 // Call to the instance getter.
2451 void CodeGenerator::VisitInstanceGetterNode(InstanceGetterNode* node) { 2476 void CodeGenerator::VisitInstanceGetterNode(InstanceGetterNode* node) {
2452 node->receiver()->Visit(this); 2477 node->receiver()->Visit(this);
2453 MarkDeoptPoint(node->id(), node->token_index()); 2478 MarkDeoptPoint(node->id(), node->token_index());
2454 GenerateInstanceGetterCall(node->id(), 2479 GenerateInstanceGetterCall(node->id(),
2455 node->token_index(), 2480 node->token_index(),
2456 node->field_name()); 2481 node->field_name());
2457 if (IsResultNeeded(node)) { 2482 if (IsResultNeeded(node)) {
2458 __ pushl(EAX); 2483 __ pushl(EAX);
2459 } 2484 }
2460 } 2485 }
2461 2486
2462 2487
2463 // Expects receiver and value on stack. 2488 // Expects receiver and value on stack.
2464 void CodeGenerator::GenerateInstanceSetterCall(intptr_t node_id, 2489 void CodeGenerator::GenerateInstanceSetterCall(intptr_t node_id,
2465 intptr_t token_index, 2490 intptr_t token_index,
2466 const String& field_name) { 2491 const String& field_name) {
2467 const String& setter_name = String::ZoneHandle(Field::SetterName(field_name)); 2492 const String& setter_name = String::ZoneHandle(Field::SetterName(field_name));
2468 const int kNumberOfArguments = 2; // receiver + value. 2493 const int kNumberOfArguments = 2; // receiver + value.
2469 const Array& kNoArgumentNames = Array::Handle(); 2494 const Array& kNoArgumentNames = Array::Handle();
2495 const int kNumArgumentsChecked = 1;
2470 GenerateInstanceCall(node_id, 2496 GenerateInstanceCall(node_id,
2471 token_index, 2497 token_index,
2472 setter_name, 2498 setter_name,
2473 kNumberOfArguments, 2499 kNumberOfArguments,
2474 kNoArgumentNames); 2500 kNoArgumentNames,
2501 kNumArgumentsChecked);
2475 } 2502 }
2476 2503
2477 2504
2478 // The call to the instance setter implements the assignment to a field. 2505 // 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. 2506 // The result of the assignment to a field is the value being stored.
2480 void CodeGenerator::VisitInstanceSetterNode(InstanceSetterNode* node) { 2507 void CodeGenerator::VisitInstanceSetterNode(InstanceSetterNode* node) {
2481 // Compute the receiver object and pass it as first argument to call. 2508 // Compute the receiver object and pass it as first argument to call.
2482 node->receiver()->Visit(this); 2509 node->receiver()->Visit(this);
2483 node->value()->Visit(this); 2510 node->value()->Visit(this);
2484 MarkDeoptPoint(node->id(), node->token_index()); 2511 MarkDeoptPoint(node->id(), node->token_index());
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
2743 message_buffer, kMessageBufferSize, 2770 message_buffer, kMessageBufferSize,
2744 format, args); 2771 format, args);
2745 va_end(args); 2772 va_end(args);
2746 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); 2773 Isolate::Current()->long_jump_base()->Jump(1, message_buffer);
2747 UNREACHABLE(); 2774 UNREACHABLE();
2748 } 2775 }
2749 2776
2750 } // namespace dart 2777 } // namespace dart
2751 2778
2752 #endif // defined TARGET_ARCH_IA32 2779 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « vm/code_generator_ia32.h ('k') | vm/code_patcher_ia32_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698