| 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/opt_code_generator.h" | 8 #include "vm/opt_code_generator.h" |
| 9 | 9 |
| 10 #include "vm/assembler_macros.h" | 10 #include "vm/assembler_macros.h" |
| 11 #include "vm/ast_printer.h" | 11 #include "vm/ast_printer.h" |
| 12 #include "vm/intrinsifier.h" | |
| 13 #include "vm/object.h" | 12 #include "vm/object.h" |
| 14 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 15 #include "vm/resolver.h" | 14 #include "vm/resolver.h" |
| 16 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 17 | 16 |
| 18 namespace dart { | 17 namespace dart { |
| 19 | 18 |
| 20 #define __ assembler_-> | 19 #define __ assembler_-> |
| 21 | 20 |
| 22 DEFINE_FLAG(bool, trace_optimization, false, "Trace optimizations."); | 21 DEFINE_FLAG(bool, trace_optimization, false, "Trace optimizations."); |
| 23 DECLARE_FLAG(bool, enable_type_checks); | 22 DECLARE_FLAG(bool, enable_type_checks); |
| 24 DECLARE_FLAG(bool, intrinsify); | |
| 25 DECLARE_FLAG(bool, trace_functions); | |
| 26 | 23 |
| 27 | 24 |
| 28 // Property list to be used in CodeGenInfo. Each property has a setter | 25 // Property list to be used in CodeGenInfo. Each property has a setter |
| 29 // and a getter of specified type and name. | 26 // and a getter of specified type and name. |
| 30 // (name, type, default) | 27 // (name, type, default) |
| 31 #define PROPERTY_LIST(V) \ | 28 #define PROPERTY_LIST(V) \ |
| 32 V(is_temp, bool, false) \ | 29 V(is_temp, bool, false) \ |
| 33 V(allow_temp, bool, false) \ | 30 V(allow_temp, bool, false) \ |
| 34 V(true_label, Label*, NULL) \ | 31 V(true_label, Label*, NULL) \ |
| 35 V(false_label, Label*, NULL) \ | 32 V(false_label, Label*, NULL) \ |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 | 359 |
| 363 void OptimizingCodeGenerator::TraceNotOpt(AstNode* node, const char* message) { | 360 void OptimizingCodeGenerator::TraceNotOpt(AstNode* node, const char* message) { |
| 364 if (FLAG_trace_optimization) { | 361 if (FLAG_trace_optimization) { |
| 365 OS::Print("NOTOpt node ix: %d; %s: ", node->token_index(), message); | 362 OS::Print("NOTOpt node ix: %d; %s: ", node->token_index(), message); |
| 366 AstPrinter::PrintNode(node); | 363 AstPrinter::PrintNode(node); |
| 367 OS::Print("\n"); | 364 OS::Print("\n"); |
| 368 } | 365 } |
| 369 } | 366 } |
| 370 | 367 |
| 371 | 368 |
| 372 void OptimizingCodeGenerator::IntrinsifyGetter() { | |
| 373 // TOS: return address. | |
| 374 // +1 : receiver. | |
| 375 // Sequence node has one return node, its input is oad field node. | |
| 376 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | |
| 377 ASSERT(sequence_node.length() == 1); | |
| 378 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); | |
| 379 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); | |
| 380 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); | |
| 381 const LoadInstanceFieldNode& load_node = | |
| 382 *return_node.value()->AsLoadInstanceFieldNode(); | |
| 383 __ movl(EAX, Address(ESP, 1 * kWordSize)); | |
| 384 __ movl(EAX, FieldAddress(EAX, load_node.field().Offset())); | |
| 385 __ ret(); | |
| 386 } | |
| 387 | |
| 388 | |
| 389 void OptimizingCodeGenerator::IntrinsifySetter() { | |
| 390 // TOS: return address. | |
| 391 // +1 : value | |
| 392 // +2 : receiver. | |
| 393 // Sequence node has one store node and one return NULL node. | |
| 394 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | |
| 395 ASSERT(sequence_node.length() == 2); | |
| 396 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); | |
| 397 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); | |
| 398 const StoreInstanceFieldNode& store_node = | |
| 399 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); | |
| 400 __ movl(EAX, Address(ESP, 2 * kWordSize)); // Receiver. | |
| 401 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Value. | |
| 402 __ StoreIntoObject(EAX, FieldAddress(EAX, store_node.field().Offset()), EBX); | |
| 403 const Immediate raw_null = | |
| 404 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 405 __ movl(EAX, raw_null); | |
| 406 __ ret(); | |
| 407 } | |
| 408 | |
| 409 | |
| 410 bool OptimizingCodeGenerator::TryIntrinsify() { | |
| 411 if (FLAG_intrinsify && !FLAG_trace_functions) { | |
| 412 if ((parsed_function_.function().kind() == RawFunction::kImplicitGetter)) { | |
| 413 IntrinsifyGetter(); | |
| 414 return true; | |
| 415 } | |
| 416 if ((parsed_function_.function().kind() == RawFunction::kImplicitSetter)) { | |
| 417 IntrinsifySetter(); | |
| 418 return true; | |
| 419 } | |
| 420 } | |
| 421 // Even if an intrinsified version of the function was successfully | |
| 422 // generated, it may fall through to the non-intrinsified method body. | |
| 423 if (!FLAG_trace_functions) { | |
| 424 return Intrinsifier::Intrinsify(parsed_function().function(), assembler_); | |
| 425 } | |
| 426 return false; | |
| 427 } | |
| 428 | |
| 429 | |
| 430 // Check for stack overflow. | 369 // Check for stack overflow. |
| 431 // Note that first 5 bytes may be patched with a jump. | 370 // Note that first 5 bytes may be patched with a jump. |
| 432 // TODO(srdjan): Add check that no object is inlined in the first | 371 // TODO(srdjan): Add check that no object is inlined in the first |
| 433 // 5 bytes (length of a jump instruction). | 372 // 5 bytes (length of a jump instruction). |
| 434 void OptimizingCodeGenerator::GeneratePreEntryCode() { | 373 void OptimizingCodeGenerator::GeneratePreEntryCode() { |
| 435 } | 374 } |
| 436 | 375 |
| 437 | 376 |
| 438 void OptimizingCodeGenerator::CallDeoptimize(intptr_t node_id, | 377 void OptimizingCodeGenerator::CallDeoptimize(intptr_t node_id, |
| 439 intptr_t token_index) { | 378 intptr_t token_index) { |
| (...skipping 2721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3161 } | 3100 } |
| 3162 } | 3101 } |
| 3163 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 3102 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 3164 CodeGenerator::VisitUnaryOpNode(node); | 3103 CodeGenerator::VisitUnaryOpNode(node); |
| 3165 } | 3104 } |
| 3166 | 3105 |
| 3167 | 3106 |
| 3168 } // namespace dart | 3107 } // namespace dart |
| 3169 | 3108 |
| 3170 #endif // defined TARGET_ARCH_IA32 | 3109 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |