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

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
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_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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698