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

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

Issue 13483018: Introduces a second temporary register for MIPS assembler macros. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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 | « runtime/vm/constants_mips.h ('k') | runtime/vm/intermediate_language_mips.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 UNIMPLEMENTED(); 77 UNIMPLEMENTED();
78 return NULL; 78 return NULL;
79 } 79 }
80 80
81 81
82 void FlowGraphCompiler::CheckClassIds(Register class_id_reg, 82 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
83 const GrowableArray<intptr_t>& class_ids, 83 const GrowableArray<intptr_t>& class_ids,
84 Label* is_equal_lbl, 84 Label* is_equal_lbl,
85 Label* is_not_equal_lbl) { 85 Label* is_not_equal_lbl) {
86 for (intptr_t i = 0; i < class_ids.length(); i++) { 86 for (intptr_t i = 0; i < class_ids.length(); i++) {
87 __ LoadImmediate(TMP, class_ids[i]); 87 __ BranchEqual(class_id_reg, class_ids[i], is_equal_lbl);
88 __ beq(class_id_reg, TMP, is_equal_lbl);
89 } 88 }
90 __ b(is_not_equal_lbl); 89 __ b(is_not_equal_lbl);
91 } 90 }
92 91
93 92
94 // Testing against an instantiated type with no arguments, without 93 // Testing against an instantiated type with no arguments, without
95 // SubtypeTestCache. 94 // SubtypeTestCache.
96 // A0: instance being type checked (preserved). 95 // A0: instance being type checked (preserved).
97 // Clobbers: T0, T1, T2 96 // Clobbers: T0, T1, T2
98 // Returns true if there is a fallthrough. 97 // Returns true if there is a fallthrough.
(...skipping 15 matching lines...) Expand all
114 type_class, 113 type_class,
115 TypeArguments::Handle(), 114 TypeArguments::Handle(),
116 NULL)) { 115 NULL)) {
117 __ beq(T0, ZR, is_instance_lbl); 116 __ beq(T0, ZR, is_instance_lbl);
118 } else { 117 } else {
119 __ beq(T0, ZR, is_not_instance_lbl); 118 __ beq(T0, ZR, is_not_instance_lbl);
120 } 119 }
121 // Compare if the classes are equal. 120 // Compare if the classes are equal.
122 const Register kClassIdReg = T0; 121 const Register kClassIdReg = T0;
123 __ LoadClassId(kClassIdReg, kInstanceReg); 122 __ LoadClassId(kClassIdReg, kInstanceReg);
124 __ LoadImmediate(T1, type_class.id()); 123 __ BranchEqual(kClassIdReg, type_class.id(), is_instance_lbl);
125 __ beq(kClassIdReg, T1, is_instance_lbl); 124
126 // See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted 125 // See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted
127 // interfaces. 126 // interfaces.
128 // Bool interface can be implemented only by core class Bool. 127 // Bool interface can be implemented only by core class Bool.
129 if (type.IsBoolType()) { 128 if (type.IsBoolType()) {
130 __ LoadImmediate(T1, kBoolCid); 129 __ BranchEqual(kClassIdReg, kBoolCid, is_instance_lbl);
131 __ beq(kClassIdReg, T1, is_instance_lbl);
132 __ b(is_not_instance_lbl); 130 __ b(is_not_instance_lbl);
133 return false; 131 return false;
134 } 132 }
135 if (type.IsFunctionType()) { 133 if (type.IsFunctionType()) {
136 // Check if instance is a closure. 134 // Check if instance is a closure.
137 __ LoadClassById(T1, kClassIdReg); 135 __ LoadClassById(T1, kClassIdReg);
138 __ lw(T1, FieldAddress(T1, Class::signature_function_offset())); 136 __ lw(T1, FieldAddress(T1, Class::signature_function_offset()));
139 __ LoadImmediate(T2, reinterpret_cast<int32_t>(Object::null())); 137 __ BranchNotEqual(T1, reinterpret_cast<int32_t>(Object::null()),
140 __ bne(T1, T2, is_instance_lbl); 138 is_instance_lbl);
141 } 139 }
142 // Custom checking for numbers (Smi, Mint, Bigint and Double). 140 // Custom checking for numbers (Smi, Mint, Bigint and Double).
143 // Note that instance is not Smi (checked above). 141 // Note that instance is not Smi (checked above).
144 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) { 142 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
145 GenerateNumberTypeCheck( 143 GenerateNumberTypeCheck(
146 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl); 144 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
147 return false; 145 return false;
148 } 146 }
149 if (type.IsStringType()) { 147 if (type.IsStringType()) {
150 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); 148 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 } 195 }
198 if (TypeCheckAsClassEquality(type)) { 196 if (TypeCheckAsClassEquality(type)) {
199 const intptr_t type_cid = Class::Handle(type.type_class()).id(); 197 const intptr_t type_cid = Class::Handle(type.type_class()).id();
200 const Register kInstanceReg = A0; 198 const Register kInstanceReg = A0;
201 __ andi(T0, kInstanceReg, Immediate(kSmiTagMask)); 199 __ andi(T0, kInstanceReg, Immediate(kSmiTagMask));
202 if (type_cid == kSmiCid) { 200 if (type_cid == kSmiCid) {
203 __ beq(T0, ZR, is_instance_lbl); 201 __ beq(T0, ZR, is_instance_lbl);
204 } else { 202 } else {
205 __ beq(T0, ZR, is_not_instance_lbl); 203 __ beq(T0, ZR, is_not_instance_lbl);
206 __ LoadClassId(T0, kInstanceReg); 204 __ LoadClassId(T0, kInstanceReg);
207 __ LoadImmediate(T1, type_cid); 205 __ BranchEqual(T0, type_cid, is_instance_lbl);
208 __ beq(T0, T1, is_instance_lbl);
209 } 206 }
210 __ b(is_not_instance_lbl); 207 __ b(is_not_instance_lbl);
211 return SubtypeTestCache::null(); 208 return SubtypeTestCache::null();
212 } 209 }
213 if (type.IsInstantiated()) { 210 if (type.IsInstantiated()) {
214 const Class& type_class = Class::ZoneHandle(type.type_class()); 211 const Class& type_class = Class::ZoneHandle(type.type_class());
215 // A Smi object cannot be the instance of a parameterized class. 212 // A Smi object cannot be the instance of a parameterized class.
216 // A class equality check is only applicable with a dst type of a 213 // A class equality check is only applicable with a dst type of a
217 // non-parameterized class or with a raw dst type of a parameterized class. 214 // non-parameterized class or with a raw dst type of a parameterized class.
218 if (type_class.HasTypeArguments()) { 215 if (type_class.HasTypeArguments()) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 ASSERT(dst_type.IsFinalized()); 272 ASSERT(dst_type.IsFinalized());
276 // Assignable check is skipped in FlowGraphBuilder, not here. 273 // Assignable check is skipped in FlowGraphBuilder, not here.
277 ASSERT(dst_type.IsMalformed() || 274 ASSERT(dst_type.IsMalformed() ||
278 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 275 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
279 // Preserve instantiator and its type arguments. 276 // Preserve instantiator and its type arguments.
280 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 277 __ addiu(SP, SP, Immediate(-2 * kWordSize));
281 __ sw(A2, Address(SP, 1 * kWordSize)); 278 __ sw(A2, Address(SP, 1 * kWordSize));
282 __ sw(A1, Address(SP, 0 * kWordSize)); 279 __ sw(A1, Address(SP, 0 * kWordSize));
283 // A null object is always assignable and is returned as result. 280 // A null object is always assignable and is returned as result.
284 Label is_assignable, runtime_call; 281 Label is_assignable, runtime_call;
285 __ LoadImmediate(T0, reinterpret_cast<int32_t>(Object::null())); 282 __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable);
286 __ beq(A0, T0, &is_assignable);
287 283
288 if (!FLAG_eliminate_type_checks) { 284 if (!FLAG_eliminate_type_checks) {
289 // If type checks are not eliminated during the graph building then 285 // If type checks are not eliminated during the graph building then
290 // a transition sentinel can be seen here. 286 // a transition sentinel can be seen here.
291 __ LoadObject(T0, Object::transition_sentinel()); 287 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable);
292 __ beq(A0, T0, &is_assignable);
293 } 288 }
294 289
295 // Generate throw new TypeError() if the type is malformed. 290 // Generate throw new TypeError() if the type is malformed.
296 if (dst_type.IsMalformed()) { 291 if (dst_type.IsMalformed()) {
297 const Error& error = Error::Handle(dst_type.malformed_error()); 292 const Error& error = Error::Handle(dst_type.malformed_error());
298 const String& error_message = String::ZoneHandle( 293 const String& error_message = String::ZoneHandle(
299 Symbols::New(error.ToErrorCString())); 294 Symbols::New(error.ToErrorCString()));
300 __ PushObject(Object::ZoneHandle()); // Make room for the result. 295 __ PushObject(Object::ZoneHandle()); // Make room for the result.
301 __ Push(A0); // Push the source object. 296 __ Push(A0); // Push the source object.
302 __ PushObject(dst_name); // Push the name of the destination. 297 __ PushObject(dst_name); // Push the name of the destination.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 __ LoadObject(A0, test_cache); 332 __ LoadObject(A0, test_cache);
338 __ Push(A0); 333 __ Push(A0);
339 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs); 334 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs);
340 // Pop the parameters supplied to the runtime entry. The result of the 335 // Pop the parameters supplied to the runtime entry. The result of the
341 // type check runtime call is the checked value. 336 // type check runtime call is the checked value.
342 __ Drop(6); 337 __ Drop(6);
343 __ Pop(A0); 338 __ Pop(A0);
344 339
345 __ Bind(&is_assignable); 340 __ Bind(&is_assignable);
346 // Restore instantiator and its type arguments. 341 // Restore instantiator and its type arguments.
347 __ lw(A1, Address(SP, 0 * kWordSize)); 342 __ lw(A1, Address(SP, 0 * kWordSize));
348 __ lw(A2, Address(SP, 1 * kWordSize)); 343 __ lw(A2, Address(SP, 1 * kWordSize));
349 __ addiu(SP, SP, Immediate(2 * kWordSize)); 344 __ addiu(SP, SP, Immediate(2 * kWordSize));
350 } 345 }
351 346
352 347
353 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { 348 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
354 if (!is_optimizing()) { 349 if (!is_optimizing()) {
355 if (FLAG_enable_type_checks && instr->IsAssertAssignable()) { 350 if (FLAG_enable_type_checks && instr->IsAssertAssignable()) {
356 AssertAssignableInstr* assert = instr->AsAssertAssignable(); 351 AssertAssignableInstr* assert = instr->AsAssertAssignable();
357 AddCurrentDescriptor(PcDescriptors::kDeoptBefore, 352 AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
358 assert->deopt_id(), 353 assert->deopt_id(),
359 assert->token_pos()); 354 assert->token_pos());
(...skipping 27 matching lines...) Expand all
387 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex); 382 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex);
388 383
389 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, 384 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
390 // where num_pos_args is the number of positional arguments passed in. 385 // where num_pos_args is the number of positional arguments passed in.
391 const int min_num_pos_args = num_fixed_params; 386 const int min_num_pos_args = num_fixed_params;
392 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; 387 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
393 388
394 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); 389 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::positional_count_offset()));
395 // Check that min_num_pos_args <= num_pos_args. 390 // Check that min_num_pos_args <= num_pos_args.
396 Label wrong_num_arguments; 391 Label wrong_num_arguments;
397 __ addiu(T3, T2, Immediate(-Smi::RawValue(min_num_pos_args))); 392 __ BranchLess(T2, Smi::RawValue(min_num_pos_args), &wrong_num_arguments);
398 __ bltz(T3, &wrong_num_arguments);
399 393
400 // Check that num_pos_args <= max_num_pos_args. 394 // Check that num_pos_args <= max_num_pos_args.
401 __ addiu(T3, T2, Immediate(-Smi::RawValue(max_num_pos_args))); 395 __ BranchGreater(T2, Smi::RawValue(max_num_pos_args), &wrong_num_arguments);
402 __ bgtz(T3, &wrong_num_arguments);
403 396
404 // Copy positional arguments. 397 // Copy positional arguments.
405 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied 398 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied
406 // to fp[kFirstLocalSlotIndex - i]. 399 // to fp[kFirstLocalSlotIndex - i].
407 400
408 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 401 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
409 // Since T1 and T2 are Smi, use LSL 1 instead of LSL 2. 402 // Since T1 and T2 are Smi, use sll 1 instead of sll 2.
410 // Let T1 point to the last passed positional argument, i.e. to 403 // Let T1 point to the last passed positional argument, i.e. to
411 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)]. 404 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)].
412 __ subu(T1, T1, T2); 405 __ subu(T1, T1, T2);
413 __ sll(T1, T1, 1); 406 __ sll(T1, T1, 1);
414 __ addu(T1, FP, T1); 407 __ addu(T1, FP, T1);
415 __ addiu(T1, T1, Immediate(kLastParamSlotIndex * kWordSize)); 408 __ addiu(T1, T1, Immediate(kLastParamSlotIndex * kWordSize));
416 409
417 // Let T0 point to the last copied positional argument, i.e. to 410 // Let T0 point to the last copied positional argument, i.e. to
418 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. 411 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)].
419 __ addiu(T0, FP, Immediate((kFirstLocalSlotIndex + 1) * kWordSize)); 412 __ addiu(T0, FP, Immediate((kFirstLocalSlotIndex + 1) * kWordSize));
420 __ sll(T3, T2, 1); // T2 is a Smi. 413 __ sll(T3, T2, 1); // T2 is a Smi.
421 __ subu(T0, T0, T3); 414 __ subu(T0, T0, T3);
422 415
423 Label loop, loop_condition; 416 Label loop, loop_condition;
424 __ b(&loop_condition); 417 __ b(&loop_condition);
425 __ delay_slot()->SmiUntag(T2); 418 __ delay_slot()->SmiUntag(T2);
426 // We do not use the final allocation index of the variable here, i.e. 419 // We do not use the final allocation index of the variable here, i.e.
427 // scope->VariableAt(i)->index(), because captured variables still need 420 // scope->VariableAt(i)->index(), because captured variables still need
428 // to be copied to the context that is not yet allocated. 421 // to be copied to the context that is not yet allocated.
429 __ Bind(&loop); 422 __ Bind(&loop);
430 __ addu(T4, T1, T2); 423 __ addu(T4, T1, T2);
431 __ addu(T5, T0, T2); 424 __ addu(T5, T0, T2);
432 __ lw(TMP, Address(T4)); 425 __ lw(T3, Address(T4));
433 __ sw(TMP, Address(T5)); 426 __ sw(T3, Address(T5));
434 __ Bind(&loop_condition); 427 __ Bind(&loop_condition);
435 __ addiu(T2, T2, Immediate(-kWordSize)); 428 __ addiu(T2, T2, Immediate(-kWordSize));
436 __ bgez(T2, &loop); 429 __ bgez(T2, &loop);
437 430
438 // Copy or initialize optional named arguments. 431 // Copy or initialize optional named arguments.
439 Label all_arguments_processed; 432 Label all_arguments_processed;
440 if (num_opt_named_params > 0) { 433 if (num_opt_named_params > 0) {
441 // Start by alphabetically sorting the names of the optional parameters. 434 // Start by alphabetically sorting the names of the optional parameters.
442 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; 435 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
443 int* opt_param_position = new int[num_opt_named_params]; 436 int* opt_param_position = new int[num_opt_named_params];
(...skipping 24 matching lines...) Expand all
468 // Let T0 point to the entry of the first named argument. 461 // Let T0 point to the entry of the first named argument.
469 __ addiu(T0, S4, Immediate( 462 __ addiu(T0, S4, Immediate(
470 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag)); 463 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
471 for (int i = 0; i < num_opt_named_params; i++) { 464 for (int i = 0; i < num_opt_named_params; i++) {
472 Label load_default_value, assign_optional_parameter; 465 Label load_default_value, assign_optional_parameter;
473 const int param_pos = opt_param_position[i]; 466 const int param_pos = opt_param_position[i];
474 // Check if this named parameter was passed in. 467 // Check if this named parameter was passed in.
475 // Load T3 with the name of the argument. 468 // Load T3 with the name of the argument.
476 __ lw(T3, Address(T0, ArgumentsDescriptor::name_offset())); 469 __ lw(T3, Address(T0, ArgumentsDescriptor::name_offset()));
477 ASSERT(opt_param[i]->name().IsSymbol()); 470 ASSERT(opt_param[i]->name().IsSymbol());
478 __ LoadObject(T4, opt_param[i]->name()); 471 __ BranchNotEqual(T3, opt_param[i]->name(), &load_default_value);
479 __ bne(T3, T4, &load_default_value);
480 472
481 // Load T3 with passed-in argument at provided arg_pos, i.e. at 473 // Load T3 with passed-in argument at provided arg_pos, i.e. at
482 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos]. 474 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos].
483 __ lw(T3, Address(T0, ArgumentsDescriptor::position_offset())); 475 __ lw(T3, Address(T0, ArgumentsDescriptor::position_offset()));
484 // T3 is arg_pos as Smi. 476 // T3 is arg_pos as Smi.
485 // Point to next named entry. 477 // Point to next named entry.
486 __ addiu(T0, T0, Immediate(ArgumentsDescriptor::named_entry_size())); 478 __ addiu(T0, T0, Immediate(ArgumentsDescriptor::named_entry_size()));
487 __ subu(T3, ZR, T3); 479 __ subu(T3, ZR, T3);
488 __ sll(T3, T3, 1); 480 __ sll(T3, T3, 1);
489 __ addu(T3, T1, T3); 481 __ addu(T3, T1, T3);
(...skipping 11 matching lines...) Expand all
501 // We do not use the final allocation index of the variable here, i.e. 493 // We do not use the final allocation index of the variable here, i.e.
502 // scope->VariableAt(i)->index(), because captured variables still need 494 // scope->VariableAt(i)->index(), because captured variables still need
503 // to be copied to the context that is not yet allocated. 495 // to be copied to the context that is not yet allocated.
504 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos; 496 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
505 __ sw(T3, Address(FP, computed_param_pos * kWordSize)); 497 __ sw(T3, Address(FP, computed_param_pos * kWordSize));
506 } 498 }
507 delete[] opt_param; 499 delete[] opt_param;
508 delete[] opt_param_position; 500 delete[] opt_param_position;
509 // Check that T0 now points to the null terminator in the array descriptor. 501 // Check that T0 now points to the null terminator in the array descriptor.
510 __ lw(T3, Address(T0)); 502 __ lw(T3, Address(T0));
511 __ LoadImmediate(T4, reinterpret_cast<int32_t>(Object::null())); 503 __ BranchEqual(T3, reinterpret_cast<int32_t>(Object::null()),
512 __ beq(T3, T4, &all_arguments_processed); 504 &all_arguments_processed);
513 } else { 505 } else {
514 ASSERT(num_opt_pos_params > 0); 506 ASSERT(num_opt_pos_params > 0);
515 __ lw(T2, 507 __ lw(T2,
516 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); 508 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset()));
517 __ SmiUntag(T2); 509 __ SmiUntag(T2);
518 for (int i = 0; i < num_opt_pos_params; i++) { 510 for (int i = 0; i < num_opt_pos_params; i++) {
519 Label next_parameter; 511 Label next_parameter;
520 // Handle this optional positional parameter only if k or fewer positional 512 // Handle this optional positional parameter only if k or fewer positional
521 // arguments have been passed, where k is param_pos, the position of this 513 // arguments have been passed, where k is param_pos, the position of this
522 // optional parameter in the formal parameter list. 514 // optional parameter in the formal parameter list.
523 const int param_pos = num_fixed_params + i; 515 const int param_pos = num_fixed_params + i;
524 __ addiu(T3, T2, Immediate(-param_pos)); 516 __ BranchGreater(T2, param_pos, &next_parameter);
525 __ bgtz(T3, &next_parameter);
526 // Load T3 with default argument. 517 // Load T3 with default argument.
527 const Object& value = Object::ZoneHandle( 518 const Object& value = Object::ZoneHandle(
528 parsed_function().default_parameter_values().At(i)); 519 parsed_function().default_parameter_values().At(i));
529 __ LoadObject(T3, value); 520 __ LoadObject(T3, value);
530 // Assign T3 to fp[kFirstLocalSlotIndex - param_pos]. 521 // Assign T3 to fp[kFirstLocalSlotIndex - param_pos].
531 // We do not use the final allocation index of the variable here, i.e. 522 // We do not use the final allocation index of the variable here, i.e.
532 // scope->VariableAt(i)->index(), because captured variables still need 523 // scope->VariableAt(i)->index(), because captured variables still need
533 // to be copied to the context that is not yet allocated. 524 // to be copied to the context that is not yet allocated.
534 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos; 525 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
535 __ sw(T3, Address(FP, computed_param_pos * kWordSize)); 526 __ sw(T3, Address(FP, computed_param_pos * kWordSize));
536 __ Bind(&next_parameter); 527 __ Bind(&next_parameter);
537 } 528 }
538 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 529 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
539 __ SmiUntag(T1); 530 __ SmiUntag(T1);
540 // Check that T2 equals T1, i.e. no named arguments passed. 531 // Check that T2 equals T1, i.e. no named arguments passed.
541 __ beq(T2, T2, &all_arguments_processed); 532 __ beq(T2, T1, &all_arguments_processed);
542 } 533 }
543 534
544 __ Bind(&wrong_num_arguments); 535 __ Bind(&wrong_num_arguments);
545 if (StackSize() != 0) { 536 if (StackSize() != 0) {
546 // We need to unwind the space we reserved for locals and copied parameters. 537 // We need to unwind the space we reserved for locals and copied parameters.
547 // The NoSuchMethodFunction stub does not expect to see that area on the 538 // The NoSuchMethodFunction stub does not expect to see that area on the
548 // stack. 539 // stack.
549 __ addiu(SP, SP, Immediate(StackSize() * kWordSize)); 540 __ addiu(SP, SP, Immediate(StackSize() * kWordSize));
550 } 541 }
551 // The call below has an empty stackmap because we have just 542 // The call below has an empty stackmap because we have just
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 // Nullify originally passed arguments only after they have been copied and 574 // Nullify originally passed arguments only after they have been copied and
584 // checked, otherwise noSuchMethod would not see their original values. 575 // checked, otherwise noSuchMethod would not see their original values.
585 // This step can be skipped in case we decide that formal parameters are 576 // This step can be skipped in case we decide that formal parameters are
586 // implicitly final, since garbage collecting the unmodified value is not 577 // implicitly final, since garbage collecting the unmodified value is not
587 // an issue anymore. 578 // an issue anymore.
588 579
589 // S4 : arguments descriptor array. 580 // S4 : arguments descriptor array.
590 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 581 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
591 __ SmiUntag(T2); 582 __ SmiUntag(T2);
592 583
593 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); 584 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
594 Label null_args_loop, null_args_loop_condition; 585 Label null_args_loop, null_args_loop_condition;
595 __ b(&null_args_loop_condition); 586 __ b(&null_args_loop_condition);
596 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize)); 587 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize));
597 __ Bind(&null_args_loop); 588 __ Bind(&null_args_loop);
598 __ addu(T3, T1, T2); 589 __ addu(T3, T1, T2);
599 __ sw(TMP, Address(T3)); 590 __ sw(T0, Address(T3));
600 __ Bind(&null_args_loop_condition); 591 __ Bind(&null_args_loop_condition);
601 __ addiu(T2, T2, Immediate(-kWordSize)); 592 __ addiu(T2, T2, Immediate(-kWordSize));
602 __ bgez(T2, &null_args_loop); 593 __ bgez(T2, &null_args_loop);
603 } 594 }
604 595
605 596
606 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 597 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
607 UNIMPLEMENTED(); 598 UNIMPLEMENTED();
608 } 599 }
609 600
610 601
611 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 602 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
612 UNIMPLEMENTED(); 603 UNIMPLEMENTED();
613 } 604 }
614 605
615 606
616 void FlowGraphCompiler::EmitFrameEntry() { 607 void FlowGraphCompiler::EmitFrameEntry() {
617 const Function& function = parsed_function().function(); 608 const Function& function = parsed_function().function();
618 if (CanOptimizeFunction() && function.is_optimizable()) { 609 if (CanOptimizeFunction() && function.is_optimizable()) {
619 const bool can_optimize = !is_optimizing() || may_reoptimize(); 610 const bool can_optimize = !is_optimizing() || may_reoptimize();
620 const Register function_reg = T0; 611 const Register function_reg = T0;
621 if (can_optimize) { 612 if (can_optimize) {
622 Label next; 613 Label next;
623 // The pool pointer is not setup before entering the Dart frame. 614 // The pool pointer is not setup before entering the Dart frame.
624 615
625 __ mov(TMP, RA); // Save RA. 616 __ mov(TMP1, RA); // Save RA.
626 __ bal(&next); // Branch and link to next instruction to get PC in RA. 617 __ bal(&next); // Branch and link to next instruction to get PC in RA.
627 __ delay_slot()->mov(T2, RA); // Save PC of the following mov. 618 __ delay_slot()->mov(T2, RA); // Save PC of the following mov.
628 619
629 // Calculate offset of pool pointer from the PC. 620 // Calculate offset of pool pointer from the PC.
630 const intptr_t object_pool_pc_dist = 621 const intptr_t object_pool_pc_dist =
631 Instructions::HeaderSize() - Instructions::object_pool_offset() + 622 Instructions::HeaderSize() - Instructions::object_pool_offset() +
632 assembler()->CodeSize(); 623 assembler()->CodeSize();
633 624
634 __ Bind(&next); 625 __ Bind(&next);
635 __ mov(RA, TMP); // Restore RA. 626 __ mov(RA, TMP1); // Restore RA.
636 627
637 // Preserve PP of caller. 628 // Preserve PP of caller.
638 __ mov(T1, PP); 629 __ mov(T1, PP);
639 630
640 // Temporarily setup pool pointer for this dart function. 631 // Temporarily setup pool pointer for this dart function.
641 __ lw(PP, Address(T2, -object_pool_pc_dist)); 632 __ lw(PP, Address(T2, -object_pool_pc_dist));
642 633
643 // Load function object from object pool. 634 // Load function object from object pool.
644 __ LoadObject(function_reg, function); // Uses PP. 635 __ LoadObject(function_reg, function); // Uses PP.
645 636
(...skipping 13 matching lines...) Expand all
659 __ addiu(T1, T1, Immediate(1)); 650 __ addiu(T1, T1, Immediate(1));
660 __ sw(T1, FieldAddress(function_reg, 651 __ sw(T1, FieldAddress(function_reg,
661 Function::usage_counter_offset())); 652 Function::usage_counter_offset()));
662 } else { 653 } else {
663 __ lw(T1, FieldAddress(function_reg, 654 __ lw(T1, FieldAddress(function_reg,
664 Function::usage_counter_offset())); 655 Function::usage_counter_offset()));
665 } 656 }
666 657
667 // Skip Branch if T1 is less than the threshold. 658 // Skip Branch if T1 is less than the threshold.
668 Label dont_branch; 659 Label dont_branch;
669 __ LoadImmediate(T2, FLAG_optimization_counter_threshold); 660 __ BranchLess(T1, FLAG_optimization_counter_threshold, &dont_branch);
670 __ sltu(T2, T1, T2);
671 __ bgtz(T2, &dont_branch);
672 661
673 ASSERT(function_reg == T0); 662 ASSERT(function_reg == T0);
674 __ Branch(&StubCode::OptimizeFunctionLabel()); 663 __ Branch(&StubCode::OptimizeFunctionLabel());
675 664
676 __ Bind(&dont_branch); 665 __ Bind(&dont_branch);
677 } 666 }
678 } else { 667 } else {
679 AddCurrentDescriptor(PcDescriptors::kEntryPatch, 668 AddCurrentDescriptor(PcDescriptors::kEntryPatch,
680 Isolate::kNoDeoptId, 669 Isolate::kNoDeoptId,
681 0); // No token position. 670 0); // No token position.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 ASSERT(!parsed_function().function().HasOptionalParameters()); 711 ASSERT(!parsed_function().function().HasOptionalParameters());
723 const bool check_arguments = true; 712 const bool check_arguments = true;
724 #else 713 #else
725 const bool check_arguments = function.IsClosureFunction(); 714 const bool check_arguments = function.IsClosureFunction();
726 #endif 715 #endif
727 if (check_arguments) { 716 if (check_arguments) {
728 __ Comment("Check argument count"); 717 __ Comment("Check argument count");
729 // Check that exactly num_fixed arguments are passed in. 718 // Check that exactly num_fixed arguments are passed in.
730 Label correct_num_arguments, wrong_num_arguments; 719 Label correct_num_arguments, wrong_num_arguments;
731 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 720 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
732 __ LoadImmediate(T1, Smi::RawValue(num_fixed_params)); 721 __ BranchNotEqual(T0, Smi::RawValue(num_fixed_params),
733 __ bne(T0, T1, &wrong_num_arguments); 722 &wrong_num_arguments);
734 723
735 __ lw(T1, FieldAddress(S4, 724 __ lw(T1, FieldAddress(S4,
736 ArgumentsDescriptor::positional_count_offset())); 725 ArgumentsDescriptor::positional_count_offset()));
737 __ beq(T0, T1, &correct_num_arguments); 726 __ beq(T0, T1, &correct_num_arguments);
738 __ Bind(&wrong_num_arguments); 727 __ Bind(&wrong_num_arguments);
739 if (function.IsClosureFunction()) { 728 if (function.IsClosureFunction()) {
740 if (StackSize() != 0) { 729 if (StackSize() != 0) {
741 // We need to unwind the space we reserved for locals and copied 730 // We need to unwind the space we reserved for locals and copied
742 // parameters. The NoSuchMethodFunction stub does not expect to see 731 // parameters. The NoSuchMethodFunction stub does not expect to see
743 // that area on the stack. 732 // that area on the stack.
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 1096
1108 1097
1109 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 1098 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
1110 UNIMPLEMENTED(); 1099 UNIMPLEMENTED();
1111 } 1100 }
1112 1101
1113 1102
1114 } // namespace dart 1103 } // namespace dart
1115 1104
1116 #endif // defined TARGET_ARCH_MIPS 1105 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/constants_mips.h ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698