| 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_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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 DECLARE_FLAG(bool, compiler_stats); | 22 DECLARE_FLAG(bool, compiler_stats); |
| 23 DECLARE_FLAG(bool, enable_type_checks); | 23 DECLARE_FLAG(bool, enable_type_checks); |
| 24 DECLARE_FLAG(bool, intrinsify); | 24 DECLARE_FLAG(bool, intrinsify); |
| 25 DECLARE_FLAG(int, optimization_counter_threshold); | 25 DECLARE_FLAG(int, optimization_counter_threshold); |
| 26 DECLARE_FLAG(bool, print_ast); | 26 DECLARE_FLAG(bool, print_ast); |
| 27 DECLARE_FLAG(bool, print_scopes); | 27 DECLARE_FLAG(bool, print_scopes); |
| 28 DECLARE_FLAG(bool, report_usage_count); | 28 DECLARE_FLAG(bool, report_usage_count); |
| 29 DECLARE_FLAG(bool, trace_functions); | 29 DECLARE_FLAG(bool, trace_functions); |
| 30 | 30 |
| 31 | 31 |
| 32 class DeoptimizationStub : public ZoneAllocated { | 32 void DeoptimizationStub::GenerateCode(FlowGraphCompilerShared* compiler) { |
| 33 public: | |
| 34 DeoptimizationStub(intptr_t deopt_id, | |
| 35 intptr_t deopt_token_index, | |
| 36 intptr_t try_index, | |
| 37 DeoptReasonId reason) | |
| 38 : deopt_id_(deopt_id), | |
| 39 deopt_token_index_(deopt_token_index), | |
| 40 try_index_(try_index), | |
| 41 reason_(reason), | |
| 42 registers_(2), | |
| 43 entry_label_() {} | |
| 44 | |
| 45 void Push(Register reg) { registers_.Add(reg); } | |
| 46 Label* entry_label() { return &entry_label_; } | |
| 47 | |
| 48 void GenerateCode(FlowGraphCompiler* compiler); | |
| 49 | |
| 50 private: | |
| 51 const intptr_t deopt_id_; | |
| 52 const intptr_t deopt_token_index_; | |
| 53 const intptr_t try_index_; | |
| 54 const DeoptReasonId reason_; | |
| 55 GrowableArray<Register> registers_; | |
| 56 Label entry_label_; | |
| 57 | |
| 58 DISALLOW_COPY_AND_ASSIGN(DeoptimizationStub); | |
| 59 }; | |
| 60 | |
| 61 | |
| 62 void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) { | |
| 63 Assembler* assem = compiler->assembler(); | 33 Assembler* assem = compiler->assembler(); |
| 64 #define __ assem-> | 34 #define __ assem-> |
| 65 __ Comment("Deopt stub for id %d", deopt_id_); | 35 __ Comment("Deopt stub for id %d", deopt_id_); |
| 66 __ Bind(entry_label()); | 36 __ Bind(entry_label()); |
| 67 for (intptr_t i = 0; i < registers_.length(); i++) { | 37 for (intptr_t i = 0; i < registers_.length(); i++) { |
| 68 if (registers_[i] != kNoRegister) { | 38 if (registers_[i] != kNoRegister) { |
| 69 __ pushl(registers_[i]); | 39 __ pushl(registers_[i]); |
| 70 } | 40 } |
| 71 } | 41 } |
| 72 __ movl(EAX, Immediate(Smi::RawValue(reason_))); | 42 __ movl(EAX, Immediate(Smi::RawValue(reason_))); |
| 73 __ call(&StubCode::DeoptimizeLabel()); | 43 __ call(&StubCode::DeoptimizeLabel()); |
| 74 compiler->AddCurrentDescriptor(PcDescriptors::kOther, | 44 compiler->AddCurrentDescriptor(PcDescriptors::kOther, |
| 75 deopt_id_, | 45 deopt_id_, |
| 76 deopt_token_index_, | 46 deopt_token_index_, |
| 77 try_index_); | 47 try_index_); |
| 78 #undef __ | 48 #undef __ |
| 79 } | 49 } |
| 80 | 50 |
| 81 | 51 |
| 82 FlowGraphCompiler::FlowGraphCompiler( | 52 FlowGraphCompiler::FlowGraphCompiler( |
| 83 Assembler* assembler, | 53 Assembler* assembler, |
| 84 const ParsedFunction& parsed_function, | 54 const ParsedFunction& parsed_function, |
| 85 const GrowableArray<BlockEntryInstr*>& block_order, | 55 const GrowableArray<BlockEntryInstr*>& block_order, |
| 86 bool is_optimizing) | 56 bool is_optimizing) |
| 87 : FlowGraphVisitor(block_order), | 57 : FlowGraphCompilerShared(assembler, |
| 88 assembler_(assembler), | 58 parsed_function, |
| 89 parsed_function_(parsed_function), | 59 block_order, |
| 90 block_info_(block_order.length()), | 60 is_optimizing) {} |
| 91 current_block_(NULL), | |
| 92 pc_descriptors_list_(NULL), | |
| 93 stackmap_builder_(NULL), | |
| 94 exception_handlers_list_(NULL), | |
| 95 deopt_stubs_(), | |
| 96 is_optimizing_(is_optimizing) { | |
| 97 } | |
| 98 | 61 |
| 99 | 62 |
| 100 void FlowGraphCompiler::InitCompiler() { | 63 void FlowGraphCompiler::FinalizeComments(const Code& code) { |
| 101 pc_descriptors_list_ = new DescriptorList(); | 64 code.set_comments(assembler()->GetCodeComments()); |
| 102 exception_handlers_list_ = new ExceptionHandlerList(); | |
| 103 block_info_.Clear(); | |
| 104 for (int i = 0; i < block_order_.length(); ++i) { | |
| 105 block_info_.Add(new BlockInfo()); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 | |
| 110 FlowGraphCompiler::~FlowGraphCompiler() { | |
| 111 // BlockInfos are zone-allocated, so their destructors are not called. | |
| 112 // Verify the labels explicitly here. | |
| 113 for (int i = 0; i < block_info_.length(); ++i) { | |
| 114 ASSERT(!block_info_[i]->label.IsLinked()); | |
| 115 ASSERT(!block_info_[i]->label.HasNear()); | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 | |
| 120 intptr_t FlowGraphCompiler::StackSize() const { | |
| 121 return parsed_function_.stack_local_count() + | |
| 122 parsed_function_.copied_parameter_count(); | |
| 123 } | 65 } |
| 124 | 66 |
| 125 | 67 |
| 126 void FlowGraphCompiler::Bailout(const char* reason) { | 68 void FlowGraphCompiler::Bailout(const char* reason) { |
| 127 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; | 69 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; |
| 128 const char* function_name = parsed_function_.function().ToCString(); | 70 const char* function_name = parsed_function().function().ToCString(); |
| 129 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 71 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 130 char* chars = reinterpret_cast<char*>( | 72 char* chars = reinterpret_cast<char*>( |
| 131 Isolate::Current()->current_zone()->Allocate(len)); | 73 Isolate::Current()->current_zone()->Allocate(len)); |
| 132 OS::SNPrint(chars, len, kFormat, function_name, reason); | 74 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 133 const Error& error = Error::Handle( | 75 const Error& error = Error::Handle( |
| 134 LanguageError::New(String::Handle(String::New(chars)))); | 76 LanguageError::New(String::Handle(String::New(chars)))); |
| 135 Isolate::Current()->long_jump_base()->Jump(1, error); | 77 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 136 } | 78 } |
| 137 | 79 |
| 138 | 80 |
| 139 // Uses current pc position and try-index. | 81 #define __ assembler()-> |
| 140 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, | |
| 141 intptr_t cid, | |
| 142 intptr_t token_index, | |
| 143 intptr_t try_index) { | |
| 144 pc_descriptors_list_->AddDescriptor(kind, | |
| 145 assembler_->CodeSize(), | |
| 146 cid, | |
| 147 token_index, | |
| 148 try_index); | |
| 149 } | |
| 150 | |
| 151 #define __ assembler_-> | |
| 152 | 82 |
| 153 void FlowGraphCompiler::IntrinsifyGetter() { | 83 void FlowGraphCompiler::IntrinsifyGetter() { |
| 154 // TOS: return address. | 84 // TOS: return address. |
| 155 // +1 : receiver. | 85 // +1 : receiver. |
| 156 // Sequence node has one return node, its input is load field node. | 86 // Sequence node has one return node, its input is load field node. |
| 157 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | 87 const SequenceNode& sequence_node = *parsed_function().node_sequence(); |
| 158 ASSERT(sequence_node.length() == 1); | 88 ASSERT(sequence_node.length() == 1); |
| 159 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); | 89 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); |
| 160 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); | 90 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); |
| 161 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); | 91 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); |
| 162 const LoadInstanceFieldNode& load_node = | 92 const LoadInstanceFieldNode& load_node = |
| 163 *return_node.value()->AsLoadInstanceFieldNode(); | 93 *return_node.value()->AsLoadInstanceFieldNode(); |
| 164 __ movl(EAX, Address(ESP, 1 * kWordSize)); | 94 __ movl(EAX, Address(ESP, 1 * kWordSize)); |
| 165 __ movl(EAX, FieldAddress(EAX, load_node.field().Offset())); | 95 __ movl(EAX, FieldAddress(EAX, load_node.field().Offset())); |
| 166 __ ret(); | 96 __ ret(); |
| 167 } | 97 } |
| 168 | 98 |
| 169 | 99 |
| 170 void FlowGraphCompiler::IntrinsifySetter() { | 100 void FlowGraphCompiler::IntrinsifySetter() { |
| 171 // TOS: return address. | 101 // TOS: return address. |
| 172 // +1 : value | 102 // +1 : value |
| 173 // +2 : receiver. | 103 // +2 : receiver. |
| 174 // Sequence node has one store node and one return NULL node. | 104 // Sequence node has one store node and one return NULL node. |
| 175 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | 105 const SequenceNode& sequence_node = *parsed_function().node_sequence(); |
| 176 ASSERT(sequence_node.length() == 2); | 106 ASSERT(sequence_node.length() == 2); |
| 177 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); | 107 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); |
| 178 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); | 108 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); |
| 179 const StoreInstanceFieldNode& store_node = | 109 const StoreInstanceFieldNode& store_node = |
| 180 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); | 110 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); |
| 181 __ movl(EAX, Address(ESP, 2 * kWordSize)); // Receiver. | 111 __ movl(EAX, Address(ESP, 2 * kWordSize)); // Receiver. |
| 182 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Value. | 112 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Value. |
| 183 __ StoreIntoObject(EAX, FieldAddress(EAX, store_node.field().Offset()), EBX); | 113 __ StoreIntoObject(EAX, FieldAddress(EAX, store_node.field().Offset()), EBX); |
| 184 const Immediate raw_null = | 114 const Immediate raw_null = |
| 185 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 115 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 196 } | 126 } |
| 197 | 127 |
| 198 | 128 |
| 199 // Returns 'true' if code generation for this function is complete, i.e., | 129 // Returns 'true' if code generation for this function is complete, i.e., |
| 200 // no fall-through to regular code is needed. | 130 // no fall-through to regular code is needed. |
| 201 bool FlowGraphCompiler::TryIntrinsify() { | 131 bool FlowGraphCompiler::TryIntrinsify() { |
| 202 if (!CanOptimize()) return false; | 132 if (!CanOptimize()) return false; |
| 203 // Intrinsification skips arguments checks, therefore disable if in checked | 133 // Intrinsification skips arguments checks, therefore disable if in checked |
| 204 // mode. | 134 // mode. |
| 205 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) { | 135 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) { |
| 206 if ((parsed_function_.function().kind() == RawFunction::kImplicitGetter)) { | 136 if ((parsed_function().function().kind() == RawFunction::kImplicitGetter)) { |
| 207 IntrinsifyGetter(); | 137 IntrinsifyGetter(); |
| 208 return true; | 138 return true; |
| 209 } | 139 } |
| 210 if ((parsed_function_.function().kind() == RawFunction::kImplicitSetter)) { | 140 if ((parsed_function().function().kind() == RawFunction::kImplicitSetter)) { |
| 211 IntrinsifySetter(); | 141 IntrinsifySetter(); |
| 212 return true; | 142 return true; |
| 213 } | 143 } |
| 214 } | 144 } |
| 215 // Even if an intrinsified version of the function was successfully | 145 // Even if an intrinsified version of the function was successfully |
| 216 // generated, it may fall through to the non-intrinsified method body. | 146 // generated, it may fall through to the non-intrinsified method body. |
| 217 if (!FLAG_trace_functions) { | 147 if (!FLAG_trace_functions) { |
| 218 return Intrinsifier::Intrinsify(parsed_function_.function(), assembler_); | 148 return Intrinsifier::Intrinsify(parsed_function().function(), assembler()); |
| 219 } | 149 } |
| 220 return false; | 150 return false; |
| 221 } | 151 } |
| 222 | 152 |
| 223 | 153 |
| 224 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, | 154 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, |
| 225 intptr_t token_index, | 155 intptr_t token_index, |
| 226 intptr_t try_index, | 156 intptr_t try_index, |
| 227 const RuntimeEntry& entry) { | 157 const RuntimeEntry& entry) { |
| 228 __ CallRuntime(entry); | 158 __ CallRuntime(entry); |
| 229 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); | 159 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); |
| 230 } | 160 } |
| 231 | 161 |
| 232 | 162 |
| 233 void FlowGraphCompiler::CopyParameters() { | 163 void FlowGraphCompiler::CopyParameters() { |
| 234 const Function& function = parsed_function_.function(); | 164 const Function& function = parsed_function().function(); |
| 235 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 165 LocalScope* scope = parsed_function().node_sequence()->scope(); |
| 236 const int num_fixed_params = function.num_fixed_parameters(); | 166 const int num_fixed_params = function.num_fixed_parameters(); |
| 237 const int num_opt_params = function.num_optional_parameters(); | 167 const int num_opt_params = function.num_optional_parameters(); |
| 238 ASSERT(parsed_function_.first_parameter_index() == | 168 ASSERT(parsed_function().first_parameter_index() == |
| 239 ParsedFunction::kFirstLocalSlotIndex); | 169 ParsedFunction::kFirstLocalSlotIndex); |
| 240 // Copy positional arguments. | 170 // Copy positional arguments. |
| 241 // Check that no fewer than num_fixed_params positional arguments are passed | 171 // Check that no fewer than num_fixed_params positional arguments are passed |
| 242 // in and that no more than num_params arguments are passed in. | 172 // in and that no more than num_params arguments are passed in. |
| 243 // Passed argument i at fp[1 + argc - i] | 173 // Passed argument i at fp[1 + argc - i] |
| 244 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. | 174 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. |
| 245 const int num_params = num_fixed_params + num_opt_params; | 175 const int num_params = num_fixed_params + num_opt_params; |
| 246 | 176 |
| 247 // Total number of args is the first Smi in args descriptor array (EDX). | 177 // Total number of args is the first Smi in args descriptor array (EDX). |
| 248 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 178 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 // fp[1 + argc - arg_pos]. | 257 // fp[1 + argc - arg_pos]. |
| 328 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi. | 258 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi. |
| 329 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. | 259 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. |
| 330 __ negl(EAX); | 260 __ negl(EAX); |
| 331 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. | 261 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. |
| 332 __ movl(EAX, argument_addr); | 262 __ movl(EAX, argument_addr); |
| 333 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | 263 __ jmp(&assign_optional_parameter, Assembler::kNearJump); |
| 334 __ Bind(&load_default_value); | 264 __ Bind(&load_default_value); |
| 335 // Load EAX with default argument at pos. | 265 // Load EAX with default argument at pos. |
| 336 const Object& value = Object::ZoneHandle( | 266 const Object& value = Object::ZoneHandle( |
| 337 parsed_function_.default_parameter_values().At( | 267 parsed_function().default_parameter_values().At( |
| 338 param_pos - num_fixed_params)); | 268 param_pos - num_fixed_params)); |
| 339 __ LoadObject(EAX, value); | 269 __ LoadObject(EAX, value); |
| 340 __ Bind(&assign_optional_parameter); | 270 __ Bind(&assign_optional_parameter); |
| 341 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | 271 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 342 // We do not use the final allocation index of the variable here, i.e. | 272 // We do not use the final allocation index of the variable here, i.e. |
| 343 // scope->VariableAt(i)->index(), because captured variables still need | 273 // scope->VariableAt(i)->index(), because captured variables still need |
| 344 // to be copied to the context that is not yet allocated. | 274 // to be copied to the context that is not yet allocated. |
| 345 const Address param_addr( | 275 const Address param_addr( |
| 346 EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize); | 276 EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize); |
| 347 __ movl(param_addr, EAX); | 277 __ movl(param_addr, EAX); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 | 353 |
| 424 | 354 |
| 425 void FlowGraphCompiler::CompileGraph() { | 355 void FlowGraphCompiler::CompileGraph() { |
| 426 InitCompiler(); | 356 InitCompiler(); |
| 427 if (TryIntrinsify()) { | 357 if (TryIntrinsify()) { |
| 428 __ int3(); | 358 __ int3(); |
| 429 __ jmp(&StubCode::FixCallersTargetLabel()); | 359 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 430 return; | 360 return; |
| 431 } | 361 } |
| 432 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 362 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 433 const Function& function = parsed_function_.function(); | 363 const Function& function = parsed_function().function(); |
| 434 | 364 |
| 435 const int parameter_count = function.num_fixed_parameters(); | 365 const int parameter_count = function.num_fixed_parameters(); |
| 436 const int num_copied_params = parsed_function_.copied_parameter_count(); | 366 const int num_copied_params = parsed_function().copied_parameter_count(); |
| 437 const int local_count = parsed_function_.stack_local_count(); | 367 const int local_count = parsed_function().stack_local_count(); |
| 438 AssemblerMacros::EnterDartFrame(assembler_, (StackSize() * kWordSize)); | 368 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); |
| 439 // We check the number of passed arguments when we have to copy them due to | 369 // We check the number of passed arguments when we have to copy them due to |
| 440 // the presence of optional named parameters. | 370 // the presence of optional named parameters. |
| 441 // No such checking code is generated if only fixed parameters are declared, | 371 // No such checking code is generated if only fixed parameters are declared, |
| 442 // unless we are debug mode or unless we are compiling a closure. | 372 // unless we are debug mode or unless we are compiling a closure. |
| 443 if (num_copied_params == 0) { | 373 if (num_copied_params == 0) { |
| 444 #ifdef DEBUG | 374 #ifdef DEBUG |
| 445 const bool check_arguments = true; | 375 const bool check_arguments = true; |
| 446 #else | 376 #else |
| 447 const bool check_arguments = function.IsClosureFunction(); | 377 const bool check_arguments = function.IsClosureFunction(); |
| 448 #endif | 378 #endif |
| (...skipping 15 matching lines...) Expand all Loading... |
| 464 __ Bind(&argc_in_range); | 394 __ Bind(&argc_in_range); |
| 465 } | 395 } |
| 466 } else { | 396 } else { |
| 467 CopyParameters(); | 397 CopyParameters(); |
| 468 } | 398 } |
| 469 // Initialize (non-argument) stack allocated locals to null. | 399 // Initialize (non-argument) stack allocated locals to null. |
| 470 if (local_count > 0) { | 400 if (local_count > 0) { |
| 471 const Immediate raw_null = | 401 const Immediate raw_null = |
| 472 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 402 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 473 __ movl(EAX, raw_null); | 403 __ movl(EAX, raw_null); |
| 474 const int base = parsed_function_.first_stack_local_index(); | 404 const int base = parsed_function().first_stack_local_index(); |
| 475 for (int i = 0; i < local_count; ++i) { | 405 for (int i = 0; i < local_count; ++i) { |
| 476 // Subtract index i (locals lie at lower addresses than EBP). | 406 // Subtract index i (locals lie at lower addresses than EBP). |
| 477 __ movl(Address(EBP, (base - i) * kWordSize), EAX); | 407 __ movl(Address(EBP, (base - i) * kWordSize), EAX); |
| 478 } | 408 } |
| 479 } | 409 } |
| 480 | 410 |
| 481 // Generate stack overflow check. | 411 // Generate stack overflow check. |
| 482 __ cmpl(ESP, | 412 __ cmpl(ESP, |
| 483 Address::Absolute(Isolate::Current()->stack_limit_address())); | 413 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 484 Label no_stack_overflow; | 414 Label no_stack_overflow; |
| 485 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 415 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 486 GenerateCallRuntime(AstNode::kNoId, | 416 GenerateCallRuntime(AstNode::kNoId, |
| 487 function.token_index(), | 417 function.token_index(), |
| 488 CatchClauseNode::kInvalidTryIndex, | 418 CatchClauseNode::kInvalidTryIndex, |
| 489 kStackOverflowRuntimeEntry); | 419 kStackOverflowRuntimeEntry); |
| 490 __ Bind(&no_stack_overflow); | 420 __ Bind(&no_stack_overflow); |
| 491 | 421 |
| 492 if (FLAG_print_scopes) { | 422 if (FLAG_print_scopes) { |
| 493 // Print the function scope (again) after generating the prologue in order | 423 // Print the function scope (again) after generating the prologue in order |
| 494 // to see annotations such as allocation indices of locals. | 424 // to see annotations such as allocation indices of locals. |
| 495 if (FLAG_print_ast) { | 425 if (FLAG_print_ast) { |
| 496 // Second printing. | 426 // Second printing. |
| 497 OS::Print("Annotated "); | 427 OS::Print("Annotated "); |
| 498 } | 428 } |
| 499 AstPrinter::PrintFunctionScope(parsed_function_); | 429 AstPrinter::PrintFunctionScope(parsed_function()); |
| 500 } | 430 } |
| 501 | 431 |
| 502 VisitBlocks(); | 432 VisitBlocks(); |
| 503 | 433 |
| 504 __ int3(); | 434 __ int3(); |
| 505 GenerateDeferredCode(); | 435 GenerateDeferredCode(); |
| 506 // Emit function patching code. This will be swapped with the first 5 bytes | 436 // Emit function patching code. This will be swapped with the first 5 bytes |
| 507 // at entry point. | 437 // at entry point. |
| 508 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, | 438 pc_descriptors_list()->AddDescriptor(PcDescriptors::kPatchCode, |
| 509 assembler_->CodeSize(), | 439 assembler()->CodeSize(), |
| 510 AstNode::kNoId, | 440 AstNode::kNoId, |
| 511 0, | 441 0, |
| 512 -1); | 442 -1); |
| 513 __ jmp(&StubCode::FixCallersTargetLabel()); | 443 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 514 } | 444 } |
| 515 | 445 |
| 516 | 446 |
| 517 void FlowGraphCompiler::EmitInstanceCall(intptr_t cid, | 447 void FlowGraphCompiler::EmitInstanceCall(intptr_t cid, |
| 518 intptr_t token_index, | 448 intptr_t token_index, |
| 519 intptr_t try_index, | 449 intptr_t try_index, |
| 520 const String& function_name, | 450 const String& function_name, |
| 521 intptr_t argument_count, | 451 intptr_t argument_count, |
| 522 const Array& argument_names, | 452 const Array& argument_names, |
| 523 intptr_t checked_argument_count) { | 453 intptr_t checked_argument_count) { |
| 524 ICData& ic_data = ICData::ZoneHandle(ICData::New(parsed_function_.function(), | 454 ICData& ic_data = ICData::ZoneHandle(ICData::New(parsed_function().function(), |
| 525 function_name, | 455 function_name, |
| 526 cid, | 456 cid, |
| 527 checked_argument_count)); | 457 checked_argument_count)); |
| 528 const Array& arguments_descriptor = | 458 const Array& arguments_descriptor = |
| 529 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); | 459 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| 530 __ LoadObject(ECX, ic_data); | 460 __ LoadObject(ECX, ic_data); |
| 531 __ LoadObject(EDX, arguments_descriptor); | 461 __ LoadObject(EDX, arguments_descriptor); |
| 532 | 462 |
| 533 uword label_address = 0; | 463 uword label_address = 0; |
| 534 switch (checked_argument_count) { | 464 switch (checked_argument_count) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 | 498 |
| 569 void FlowGraphCompiler::GenerateCall(intptr_t token_index, | 499 void FlowGraphCompiler::GenerateCall(intptr_t token_index, |
| 570 intptr_t try_index, | 500 intptr_t try_index, |
| 571 const ExternalLabel* label, | 501 const ExternalLabel* label, |
| 572 PcDescriptors::Kind kind) { | 502 PcDescriptors::Kind kind) { |
| 573 __ call(label); | 503 __ call(label); |
| 574 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); | 504 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); |
| 575 } | 505 } |
| 576 | 506 |
| 577 | 507 |
| 578 void FlowGraphCompiler::GenerateDeferredCode() { | |
| 579 for (intptr_t i = 0; i < deopt_stubs_.length(); i++) { | |
| 580 deopt_stubs_[i]->GenerateCode(this); | |
| 581 } | |
| 582 } | |
| 583 | |
| 584 | |
| 585 void FlowGraphCompiler::EmitComment(Instruction* instr) { | 508 void FlowGraphCompiler::EmitComment(Instruction* instr) { |
| 586 char buffer[80]; | 509 char buffer[80]; |
| 587 BufferFormatter f(buffer, sizeof(buffer)); | 510 BufferFormatter f(buffer, sizeof(buffer)); |
| 588 instr->PrintTo(&f); | 511 instr->PrintTo(&f); |
| 589 __ Comment("@%d: %s", instr->cid(), buffer); | 512 __ Comment("@%d: %s", instr->cid(), buffer); |
| 590 } | 513 } |
| 591 | 514 |
| 592 | 515 |
| 593 void FlowGraphCompiler::BailoutOnInstruction(Instruction* instr) { | 516 void FlowGraphCompiler::BailoutOnInstruction(Instruction* instr) { |
| 594 char buffer[80]; | 517 char buffer[80]; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 607 // Load instruction inputs into allocated registers. | 530 // Load instruction inputs into allocated registers. |
| 608 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) { | 531 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) { |
| 609 Location loc = locs->in(i); | 532 Location loc = locs->in(i); |
| 610 ASSERT(loc.kind() == Location::kRegister); | 533 ASSERT(loc.kind() == Location::kRegister); |
| 611 __ popl(loc.reg()); | 534 __ popl(loc.reg()); |
| 612 } | 535 } |
| 613 } | 536 } |
| 614 | 537 |
| 615 | 538 |
| 616 void FlowGraphCompiler::VisitBlocks() { | 539 void FlowGraphCompiler::VisitBlocks() { |
| 617 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 540 for (intptr_t i = 0; i < block_order().length(); ++i) { |
| 618 __ Comment("B%d", i); | 541 __ Comment("B%d", i); |
| 619 // Compile the block entry. | 542 // Compile the block entry. |
| 620 current_block_ = block_order_[i]; | 543 set_current_block(block_order()[i]); |
| 621 Instruction* instr = current_block()->Accept(this); | 544 current_block()->PrepareEntry(this); |
| 545 Instruction* instr = current_block()->StraightLineSuccessor(); |
| 622 // Compile all successors until an exit, branch, or a block entry. | 546 // Compile all successors until an exit, branch, or a block entry. |
| 623 while ((instr != NULL) && !instr->IsBlockEntry()) { | 547 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 624 if (FLAG_code_comments) EmitComment(instr); | 548 if (FLAG_code_comments) EmitComment(instr); |
| 625 if (instr->locs() == NULL) { | 549 if (instr->locs() == NULL) { |
| 626 BailoutOnInstruction(instr); | 550 BailoutOnInstruction(instr); |
| 627 } else { | 551 } else { |
| 628 EmitInstructionPrologue(instr); | 552 EmitInstructionPrologue(instr); |
| 629 instr->EmitNativeCode(this); | 553 instr->EmitNativeCode(this); |
| 630 instr = instr->StraightLineSuccessor(); | 554 instr = instr->StraightLineSuccessor(); |
| 631 } | 555 } |
| 632 } | 556 } |
| 633 BlockEntryInstr* successor = | 557 BlockEntryInstr* successor = |
| 634 (instr == NULL) ? NULL : instr->AsBlockEntry(); | 558 (instr == NULL) ? NULL : instr->AsBlockEntry(); |
| 635 if (successor != NULL) { | 559 if (successor != NULL) { |
| 636 // Block ended with a "goto". We can fall through if it is the | 560 // Block ended with a "goto". We can fall through if it is the |
| 637 // next block in the list. Otherwise, we need a jump. | 561 // next block in the list. Otherwise, we need a jump. |
| 638 if ((i == block_order_.length() - 1) || | 562 if ((i == block_order().length() - 1) || |
| 639 (block_order_[i + 1] != successor)) { | 563 (block_order()[i + 1] != successor)) { |
| 640 __ jmp(&block_info_[successor->postorder_number()]->label); | 564 __ jmp(GetBlockLabel(successor)); |
| 641 } | 565 } |
| 642 } | 566 } |
| 643 } | 567 } |
| 644 } | 568 } |
| 645 | 569 |
| 646 | |
| 647 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { | |
| 648 ASSERT(pc_descriptors_list_ != NULL); | |
| 649 const PcDescriptors& descriptors = PcDescriptors::Handle( | |
| 650 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); | |
| 651 descriptors.Verify(parsed_function_.function().is_optimizable()); | |
| 652 code.set_pc_descriptors(descriptors); | |
| 653 } | |
| 654 | |
| 655 | |
| 656 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { | |
| 657 if (stackmap_builder_ == NULL) { | |
| 658 // The unoptimizing compiler has no stack maps. | |
| 659 code.set_stackmaps(Array::Handle()); | |
| 660 } else { | |
| 661 // Finalize the stack map array and add it to the code object. | |
| 662 code.set_stackmaps( | |
| 663 Array::Handle(stackmap_builder_->FinalizeStackmaps(code))); | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 | |
| 668 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { | |
| 669 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( | |
| 670 parsed_function_.node_sequence()->scope()->GetVarDescriptors()); | |
| 671 code.set_var_descriptors(var_descs); | |
| 672 } | |
| 673 | |
| 674 | |
| 675 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | |
| 676 ASSERT(exception_handlers_list_ != NULL); | |
| 677 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | |
| 678 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | |
| 679 code.set_exception_handlers(handlers); | |
| 680 } | |
| 681 | |
| 682 | |
| 683 void FlowGraphCompiler::FinalizeComments(const Code& code) { | |
| 684 code.set_comments(assembler_->GetCodeComments()); | |
| 685 } | |
| 686 | |
| 687 #undef __ | 570 #undef __ |
| 688 | 571 |
| 689 } // namespace dart | 572 } // namespace dart |
| 690 | 573 |
| 691 #endif // defined TARGET_ARCH_IA32 | 574 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |