| OLD | NEW | 
|     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  Loading... | 
|    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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|  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 | 
| OLD | NEW |