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

Side by Side Diff: runtime/vm/flow_graph_compiler_ia32.cc

Issue 10451109: Port CopyParameters() to new ia32 compiler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months 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 | « no previous file | runtime/vm/flow_graph_compiler_x64.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) 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 DISALLOW_COPY_AND_ASSIGN(DeoptimizationStub); 58 DISALLOW_COPY_AND_ASSIGN(DeoptimizationStub);
59 }; 59 };
60 60
61 61
62 void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) { 62 void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) {
63 Assembler* assem = compiler->assembler(); 63 Assembler* assem = compiler->assembler();
64 #define __ assem-> 64 #define __ assem->
65 __ Comment("Deopt stub for id %d", deopt_id_); 65 __ Comment("Deopt stub for id %d", deopt_id_);
66 __ Bind(entry_label()); 66 __ Bind(entry_label());
67 for (intptr_t i = 0; i < registers_.length(); i++) { 67 for (intptr_t i = 0; i < registers_.length(); i++) {
68 __ pushl(registers_[i]); 68 if (registers_[i] != kNoRegister) {
69 __ pushl(registers_[i]);
70 }
69 } 71 }
70 __ movl(EAX, Immediate(Smi::RawValue(reason_))); 72 __ movl(EAX, Immediate(Smi::RawValue(reason_)));
71 __ call(&StubCode::DeoptimizeLabel()); 73 __ call(&StubCode::DeoptimizeLabel());
72 compiler->AddCurrentDescriptor(PcDescriptors::kOther, 74 compiler->AddCurrentDescriptor(PcDescriptors::kOther,
73 deopt_id_, 75 deopt_id_,
74 deopt_token_index_, 76 deopt_token_index_,
75 try_index_); 77 try_index_);
76 #undef __ 78 #undef __
77 } 79 }
78 80
79 81
80 FlowGraphCompiler::FlowGraphCompiler( 82 FlowGraphCompiler::FlowGraphCompiler(
81 Assembler* assembler, 83 Assembler* assembler,
82 const ParsedFunction& parsed_function, 84 const ParsedFunction& parsed_function,
83 const GrowableArray<BlockEntryInstr*>& block_order, 85 const GrowableArray<BlockEntryInstr*>& block_order,
84 bool is_optimizing) 86 bool is_optimizing)
85 : FlowGraphVisitor(block_order), 87 : FlowGraphVisitor(block_order),
86 assembler_(assembler), 88 assembler_(assembler),
87 parsed_function_(parsed_function), 89 parsed_function_(parsed_function),
88 block_info_(block_order.length()), 90 block_info_(block_order.length()),
89 current_block_(NULL), 91 current_block_(NULL),
90 pc_descriptors_list_(NULL), 92 pc_descriptors_list_(NULL),
91 stackmap_builder_(NULL), 93 stackmap_builder_(NULL),
92 exception_handlers_list_(NULL), 94 exception_handlers_list_(NULL),
93 deopt_stubs_(), 95 deopt_stubs_(),
94 is_optimizing_(is_optimizing) { 96 is_optimizing_(is_optimizing) {
95 } 97 }
96 98
97 99
100 void FlowGraphCompiler::InitCompiler() {
101 pc_descriptors_list_ = new DescriptorList();
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
98 FlowGraphCompiler::~FlowGraphCompiler() { 110 FlowGraphCompiler::~FlowGraphCompiler() {
99 // BlockInfos are zone-allocated, so their destructors are not called. 111 // BlockInfos are zone-allocated, so their destructors are not called.
100 // Verify the labels explicitly here. 112 // Verify the labels explicitly here.
101 for (int i = 0; i < block_info_.length(); ++i) { 113 for (int i = 0; i < block_info_.length(); ++i) {
102 ASSERT(!block_info_[i]->label.IsLinked()); 114 ASSERT(!block_info_[i]->label.IsLinked());
103 ASSERT(!block_info_[i]->label.HasNear()); 115 ASSERT(!block_info_[i]->label.HasNear());
104 } 116 }
105 } 117 }
106 118
107 119
108 void FlowGraphCompiler::InitCompiler() { 120 intptr_t FlowGraphCompiler::StackSize() const {
109 pc_descriptors_list_ = new DescriptorList(); 121 return parsed_function_.stack_local_count() +
110 exception_handlers_list_ = new ExceptionHandlerList(); 122 parsed_function_.copied_parameter_count();
111 block_info_.Clear();
112 for (int i = 0; i < block_order_.length(); ++i) {
113 block_info_.Add(new BlockInfo());
114 }
115 } 123 }
116 124
117 125
118 void FlowGraphCompiler::Bailout(const char* reason) { 126 void FlowGraphCompiler::Bailout(const char* reason) {
119 const char* kFormat = "FlowGraphCompiler Bailout: %s."; 127 const char* kFormat = "FlowGraphCompiler Bailout: %s %s.";
120 intptr_t len = OS::SNPrint(NULL, 0, kFormat, reason) + 1; 128 const char* function_name = parsed_function_.function().ToCString();
129 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
121 char* chars = reinterpret_cast<char*>( 130 char* chars = reinterpret_cast<char*>(
122 Isolate::Current()->current_zone()->Allocate(len)); 131 Isolate::Current()->current_zone()->Allocate(len));
123 OS::SNPrint(chars, len, kFormat, reason); 132 OS::SNPrint(chars, len, kFormat, function_name, reason);
124 const Error& error = Error::Handle( 133 const Error& error = Error::Handle(
125 LanguageError::New(String::Handle(String::New(chars)))); 134 LanguageError::New(String::Handle(String::New(chars))));
126 Isolate::Current()->long_jump_base()->Jump(1, error); 135 Isolate::Current()->long_jump_base()->Jump(1, error);
127 } 136 }
128 137
129 138
130 // Uses current pc position and try-index. 139 // Uses current pc position and try-index.
131 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, 140 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind,
132 intptr_t cid, 141 intptr_t cid,
133 intptr_t token_index, 142 intptr_t token_index,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 __ movl(EAX, Address(ESP, 2 * kWordSize)); // Receiver. 181 __ movl(EAX, Address(ESP, 2 * kWordSize)); // Receiver.
173 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Value. 182 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Value.
174 __ StoreIntoObject(EAX, FieldAddress(EAX, store_node.field().Offset()), EBX); 183 __ StoreIntoObject(EAX, FieldAddress(EAX, store_node.field().Offset()), EBX);
175 const Immediate raw_null = 184 const Immediate raw_null =
176 Immediate(reinterpret_cast<intptr_t>(Object::null())); 185 Immediate(reinterpret_cast<intptr_t>(Object::null()));
177 __ movl(EAX, raw_null); 186 __ movl(EAX, raw_null);
178 __ ret(); 187 __ ret();
179 } 188 }
180 189
181 190
182 intptr_t FlowGraphCompiler::StackSize() const {
183 return parsed_function_.stack_local_count() +
184 parsed_function_.copied_parameter_count();
185 }
186
187
188 bool FlowGraphCompiler::CanOptimize() { 191 bool FlowGraphCompiler::CanOptimize() {
189 return 192 return
190 !FLAG_report_usage_count && 193 !FLAG_report_usage_count &&
191 (FLAG_optimization_counter_threshold >= 0) && 194 (FLAG_optimization_counter_threshold >= 0) &&
192 !Isolate::Current()->debugger()->IsActive(); 195 !Isolate::Current()->debugger()->IsActive();
193 } 196 }
194 197
195 198
196 // Returns 'true' if code generation for this function is complete, i.e., 199 // Returns 'true' if code generation for this function is complete, i.e.,
197 // no fall-through to regular code is needed. 200 // no fall-through to regular code is needed.
(...skipping 23 matching lines...) Expand all
221 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, 224 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid,
222 intptr_t token_index, 225 intptr_t token_index,
223 intptr_t try_index, 226 intptr_t try_index,
224 const RuntimeEntry& entry) { 227 const RuntimeEntry& entry) {
225 __ CallRuntime(entry); 228 __ CallRuntime(entry);
226 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); 229 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index);
227 } 230 }
228 231
229 232
230 void FlowGraphCompiler::CopyParameters() { 233 void FlowGraphCompiler::CopyParameters() {
231 Bailout("Copy Parameters"); 234 const Function& function = parsed_function_.function();
235 LocalScope* scope = parsed_function_.node_sequence()->scope();
236 const int num_fixed_params = function.num_fixed_parameters();
237 const int num_opt_params = function.num_optional_parameters();
238 ASSERT(parsed_function_.first_parameter_index() ==
239 ParsedFunction::kFirstLocalSlotIndex);
240 // Copy positional arguments.
241 // 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.
243 // Passed argument i at fp[1 + argc - i]
244 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i].
245 const int num_params = num_fixed_params + num_opt_params;
246
247 // Total number of args is the first Smi in args descriptor array (EDX).
248 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
249 // Check that num_args <= num_params.
250 Label wrong_num_arguments;
251 __ cmpl(EBX, Immediate(Smi::RawValue(num_params)));
252 __ j(GREATER, &wrong_num_arguments);
253 // Number of positional args is the second Smi in descriptor array (EDX).
254 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
255 // Check that num_pos_args >= num_fixed_params.
256 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params)));
257 __ j(LESS, &wrong_num_arguments);
258 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4.
259 // Let EBX point to the last passed positional argument, i.e. to
260 // fp[1 + num_args - (num_pos_args - 1)].
261 __ subl(EBX, ECX);
262 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize));
263 // Let EDI point to the last copied positional argument, i.e. to
264 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)].
265 const int index = ParsedFunction::kFirstLocalSlotIndex + 1;
266 __ leal(EDI, Address(EBP, (index * kWordSize)));
267 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling.
268 __ subl(EDI, ECX);
269 __ SmiUntag(ECX);
270 Label loop, loop_condition;
271 __ jmp(&loop_condition, Assembler::kNearJump);
272 // We do not use the final allocation index of the variable here, i.e.
273 // scope->VariableAt(i)->index(), because captured variables still need
274 // to be copied to the context that is not yet allocated.
275 const Address argument_addr(EBX, ECX, TIMES_4, 0);
276 const Address copy_addr(EDI, ECX, TIMES_4, 0);
277 __ Bind(&loop);
278 __ movl(EAX, argument_addr);
279 __ movl(copy_addr, EAX);
280 __ Bind(&loop_condition);
281 __ decl(ECX);
282 __ j(POSITIVE, &loop, Assembler::kNearJump);
283
284 // Copy or initialize optional named arguments.
285 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments.
286 // Start by alphabetically sorting the names of the optional parameters.
287 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
288 int* opt_param_position = new int[num_opt_params];
289 for (int pos = num_fixed_params; pos < num_params; pos++) {
290 LocalVariable* parameter = scope->VariableAt(pos);
291 const String& opt_param_name = parameter->name();
292 int i = pos - num_fixed_params;
293 while (--i >= 0) {
294 LocalVariable* param_i = opt_param[i];
295 const intptr_t result = opt_param_name.CompareTo(param_i->name());
296 ASSERT(result != 0);
297 if (result > 0) break;
298 opt_param[i + 1] = opt_param[i];
299 opt_param_position[i + 1] = opt_param_position[i];
300 }
301 opt_param[i + 1] = parameter;
302 opt_param_position[i + 1] = pos;
303 }
304 // Generate code handling each optional parameter in alphabetical order.
305 // Total number of args is the first Smi in args descriptor array (EDX).
306 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
307 // Number of positional args is the second Smi in descriptor array (EDX).
308 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
309 __ SmiUntag(ECX);
310 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
311 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi.
312 // Let EDI point to the name/pos pair of the first named argument.
313 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
314 for (int i = 0; i < num_opt_params; i++) {
315 // Handle this optional parameter only if k or fewer positional arguments
316 // have been passed, where k is the position of this optional parameter in
317 // the formal parameter list.
318 Label load_default_value, assign_optional_parameter, next_parameter;
319 const int param_pos = opt_param_position[i];
320 __ cmpl(ECX, Immediate(param_pos));
321 __ j(GREATER, &next_parameter, Assembler::kNearJump);
322 // Check if this named parameter was passed in.
323 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
324 __ CompareObject(EAX, opt_param[i]->name());
325 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
326 // Load EAX with passed-in argument at provided arg_pos, i.e. at
327 // fp[1 + argc - arg_pos].
328 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
329 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
330 __ negl(EAX);
331 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
332 __ movl(EAX, argument_addr);
333 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
334 __ Bind(&load_default_value);
335 // Load EAX with default argument at pos.
336 const Object& value = Object::ZoneHandle(
337 parsed_function_.default_parameter_values().At(
338 param_pos - num_fixed_params));
339 __ LoadObject(EAX, value);
340 __ Bind(&assign_optional_parameter);
341 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
342 // We do not use the final allocation index of the variable here, i.e.
343 // scope->VariableAt(i)->index(), because captured variables still need
344 // to be copied to the context that is not yet allocated.
345 const Address param_addr(
346 EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize);
347 __ movl(param_addr, EAX);
348 __ Bind(&next_parameter);
349 }
350 delete[] opt_param;
351 delete[] opt_param_position;
352 // Check that EDI now points to the null terminator in the array descriptor.
353 const Immediate raw_null =
354 Immediate(reinterpret_cast<intptr_t>(Object::null()));
355 Label all_arguments_processed;
356 __ cmpl(Address(EDI, 0), raw_null);
357 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
358
359 __ Bind(&wrong_num_arguments);
360 if (StackSize() != 0) {
361 // We need to unwind the space we reserved for locals and copied parameters.
362 // The NoSuchMethodFunction stub does not expect to see that area on the
363 // stack.
364 __ addl(ESP, Immediate(StackSize() * kWordSize));
365 }
366 if (function.IsClosureFunction()) {
367 GenerateCallRuntime(AstNode::kNoId,
368 0,
369 CatchClauseNode::kInvalidTryIndex,
370 kClosureArgumentMismatchRuntimeEntry);
371 } else {
372 // Invoke noSuchMethod function.
373 const int kNumArgsChecked = 1;
374 ICData& ic_data = ICData::ZoneHandle();
375 ic_data = ICData::New(function,
376 String::Handle(function.name()),
377 AstNode::kNoId,
378 kNumArgsChecked);
379 __ LoadObject(ECX, ic_data);
380 // EBP - 4 : PC marker, allows easy identification of RawInstruction obj.
381 // EBP : points to previous frame pointer.
382 // EBP + 4 : points to return address.
383 // EBP + 8 : address of last argument (arg n-1).
384 // ESP + 8 + 4*(n-1) : address of first argument (arg 0).
385 // ECX : ic-data.
386 // EDX : arguments descriptor array.
387 __ call(&StubCode::CallNoSuchMethodFunctionLabel());
388 }
389
390 if (FLAG_trace_functions) {
391 __ pushl(EAX); // Preserve result.
392 __ PushObject(Function::ZoneHandle(function.raw()));
393 GenerateCallRuntime(AstNode::kNoId,
394 0,
395 CatchClauseNode::kInvalidTryIndex,
396 kTraceFunctionExitRuntimeEntry);
397 __ popl(EAX); // Remove argument.
398 __ popl(EAX); // Restore result.
399 }
400 __ LeaveFrame();
401 __ ret();
402
403 __ Bind(&all_arguments_processed);
404 // Nullify originally passed arguments only after they have been copied and
405 // checked, otherwise noSuchMethod would not see their original values.
406 // This step can be skipped in case we decide that formal parameters are
407 // implicitly final, since garbage collecting the unmodified value is not
408 // an issue anymore.
409
410 // EDX : arguments descriptor array.
411 // Total number of args is the first Smi in args descriptor array (EDX).
412 __ movl(ECX, FieldAddress(EDX, Array::data_offset()));
413 __ SmiUntag(ECX);
414 Label null_args_loop, null_args_loop_condition;
415 __ jmp(&null_args_loop_condition, Assembler::kNearJump);
416 const Address original_argument_addr(EBP, ECX, TIMES_4, 2 * kWordSize);
417 __ Bind(&null_args_loop);
418 __ movl(original_argument_addr, raw_null);
419 __ Bind(&null_args_loop_condition);
420 __ decl(ECX);
421 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump);
232 } 422 }
233 423
234 424
235 void FlowGraphCompiler::CompileGraph() { 425 void FlowGraphCompiler::CompileGraph() {
236 InitCompiler(); 426 InitCompiler();
237 if (TryIntrinsify()) { 427 if (TryIntrinsify()) {
238 __ int3(); 428 __ int3();
239 __ jmp(&StubCode::FixCallersTargetLabel()); 429 __ jmp(&StubCode::FixCallersTargetLabel());
240 return; 430 return;
241 } 431 }
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 682
493 void FlowGraphCompiler::FinalizeComments(const Code& code) { 683 void FlowGraphCompiler::FinalizeComments(const Code& code) {
494 code.set_comments(assembler_->GetCodeComments()); 684 code.set_comments(assembler_->GetCodeComments());
495 } 685 }
496 686
497 #undef __ 687 #undef __
498 688
499 } // namespace dart 689 } // namespace dart
500 690
501 #endif // defined TARGET_ARCH_IA32 691 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698