Chromium Code Reviews| 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 159 | 159 |
| 160 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { | 160 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { |
| 161 if (is_optimizing()) return; | 161 if (is_optimizing()) return; |
| 162 Definition* defn = instr->AsDefinition(); | 162 Definition* defn = instr->AsDefinition(); |
| 163 if ((defn != NULL) && defn->is_used()) { | 163 if ((defn != NULL) && defn->is_used()) { |
| 164 __ Push(defn->locs()->out().reg()); | 164 __ Push(defn->locs()->out().reg()); |
| 165 } | 165 } |
| 166 } | 166 } |
| 167 | 167 |
| 168 | 168 |
| 169 // Input parameters: | |
| 170 // S4: arguments descriptor array. | |
| 169 void FlowGraphCompiler::CopyParameters() { | 171 void FlowGraphCompiler::CopyParameters() { |
| 170 UNIMPLEMENTED(); | 172 __ Comment("Copy parameters"); |
| 173 const Function& function = parsed_function().function(); | |
| 174 LocalScope* scope = parsed_function().node_sequence()->scope(); | |
| 175 const int num_fixed_params = function.num_fixed_parameters(); | |
| 176 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); | |
| 177 const int num_opt_named_params = function.NumOptionalNamedParameters(); | |
| 178 const int num_params = | |
| 179 num_fixed_params + num_opt_pos_params + num_opt_named_params; | |
| 180 ASSERT(function.NumParameters() == num_params); | |
| 181 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex); | |
| 182 | |
| 183 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, | |
| 184 // where num_pos_args is the number of positional arguments passed in. | |
| 185 const int min_num_pos_args = num_fixed_params; | |
| 186 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; | |
| 187 | |
| 188 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); | |
| 189 // Check that min_num_pos_args <= num_pos_args. | |
| 190 Label wrong_num_arguments; | |
| 191 __ addiu(T3, T2, Immediate(-Smi::RawValue(min_num_pos_args))); | |
| 192 __ bltz(T3, &wrong_num_arguments); | |
| 193 | |
| 194 // Check that num_pos_args <= max_num_pos_args. | |
| 195 __ addiu(T3, T2, Immediate(-Smi::RawValue(max_num_pos_args))); | |
| 196 __ bgtz(T3, &wrong_num_arguments); | |
| 197 | |
| 198 // Copy positional arguments. | |
| 199 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied | |
| 200 // to fp[kFirstLocalSlotIndex - i]. | |
| 201 | |
| 202 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | |
| 203 // Since T1 and T2 are Smi, use LSL 1 instead of LSL 2. | |
| 204 // Let T1 point to the last passed positional argument, i.e. to | |
| 205 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)]. | |
| 206 __ subu(T1, T1, T2); | |
| 207 __ sll(T1, T1, 1); | |
| 208 __ addu(T1, FP, T1); | |
| 209 __ addiu(T1, T1, Immediate(kLastParamSlotIndex * kWordSize)); | |
| 210 | |
| 211 // Let T0 point to the last copied positional argument, i.e. to | |
| 212 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. | |
| 213 __ addiu(T0, FP, Immediate((kFirstLocalSlotIndex + 1) * kWordSize)); | |
| 214 __ sll(T3, T2, 1); // T2 is a Smi. | |
| 215 __ subu(T0, T0, T3); | |
| 216 | |
| 217 Label loop, loop_condition; | |
| 218 __ b(&loop_condition); | |
| 219 __ delay_slot()->SmiUntag(T2); | |
| 220 // We do not use the final allocation index of the variable here, i.e. | |
| 221 // scope->VariableAt(i)->index(), because captured variables still need | |
| 222 // to be copied to the context that is not yet allocated. | |
| 223 __ Bind(&loop); | |
| 224 __ sll(T3, T2, 2); | |
| 225 __ addu(T4, T1, T3); | |
| 226 __ addu(T5, T0, T3); | |
| 227 __ lw(TMP, Address(T4)); | |
| 228 __ sw(TMP, Address(T5)); | |
| 229 __ Bind(&loop_condition); | |
| 230 __ addiu(T2, T2, Immediate(-1)); | |
|
regis
2013/04/03 21:12:39
You could spare the instruction sll(T3, T2, 2) by
zra
2013/04/03 21:41:00
Done.
| |
| 231 __ bgez(T2, &loop); | |
| 232 | |
| 233 // Copy or initialize optional named arguments. | |
| 234 Label all_arguments_processed; | |
| 235 if (num_opt_named_params > 0) { | |
| 236 // Start by alphabetically sorting the names of the optional parameters. | |
| 237 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; | |
| 238 int* opt_param_position = new int[num_opt_named_params]; | |
| 239 for (int pos = num_fixed_params; pos < num_params; pos++) { | |
| 240 LocalVariable* parameter = scope->VariableAt(pos); | |
| 241 const String& opt_param_name = parameter->name(); | |
| 242 int i = pos - num_fixed_params; | |
| 243 while (--i >= 0) { | |
| 244 LocalVariable* param_i = opt_param[i]; | |
| 245 const intptr_t result = opt_param_name.CompareTo(param_i->name()); | |
| 246 ASSERT(result != 0); | |
| 247 if (result > 0) break; | |
| 248 opt_param[i + 1] = opt_param[i]; | |
| 249 opt_param_position[i + 1] = opt_param_position[i]; | |
| 250 } | |
| 251 opt_param[i + 1] = parameter; | |
| 252 opt_param_position[i + 1] = pos; | |
| 253 } | |
| 254 // Generate code handling each optional parameter in alphabetical order. | |
| 255 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | |
| 256 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); | |
| 257 __ SmiUntag(T2); | |
| 258 // Let T1 point to the first passed argument, i.e. to | |
| 259 // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (T1) is Smi. | |
| 260 __ sll(T3, T1, 1); | |
| 261 __ addu(T1, FP, T3); | |
| 262 __ addiu(T1, T1, Immediate((kLastParamSlotIndex - 1) * kWordSize)); | |
| 263 // Let T0 point to the entry of the first named argument. | |
| 264 __ addiu(T0, S4, Immediate( | |
| 265 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag)); | |
| 266 for (int i = 0; i < num_opt_named_params; i++) { | |
| 267 Label load_default_value, assign_optional_parameter; | |
| 268 const int param_pos = opt_param_position[i]; | |
| 269 // Check if this named parameter was passed in. | |
| 270 // Load T3 with the name of the argument. | |
| 271 __ lw(T3, Address(T0, ArgumentsDescriptor::name_offset())); | |
| 272 ASSERT(opt_param[i]->name().IsSymbol()); | |
| 273 __ LoadObject(T4, opt_param[i]->name()); | |
| 274 __ bne(T3, T4, &load_default_value); | |
| 275 | |
| 276 // Load T3 with passed-in argument at provided arg_pos, i.e. at | |
| 277 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos]. | |
| 278 __ lw(T3, Address(T0, ArgumentsDescriptor::position_offset())); | |
| 279 // T3 is arg_pos as Smi. | |
| 280 // Point to next named entry. | |
| 281 __ addiu(T0, T0, Immediate(ArgumentsDescriptor::named_entry_size())); | |
| 282 __ subu(T3, ZR, T3); | |
| 283 __ sll(T3, T3, 1); | |
| 284 __ addu(T3, T1, T3); | |
| 285 __ b(&assign_optional_parameter); | |
| 286 __ delay_slot()->lw(T3, Address(T3)); | |
| 287 | |
| 288 __ Bind(&load_default_value); | |
| 289 // Load T3 with default argument. | |
| 290 const Object& value = Object::ZoneHandle( | |
| 291 parsed_function().default_parameter_values().At( | |
| 292 param_pos - num_fixed_params)); | |
| 293 __ LoadObject(T3, value); | |
| 294 __ Bind(&assign_optional_parameter); | |
| 295 // Assign T3 to fp[kFirstLocalSlotIndex - param_pos]. | |
| 296 // We do not use the final allocation index of the variable here, i.e. | |
| 297 // scope->VariableAt(i)->index(), because captured variables still need | |
| 298 // to be copied to the context that is not yet allocated. | |
| 299 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos; | |
| 300 __ sw(T3, Address(FP, computed_param_pos * kWordSize)); | |
| 301 } | |
| 302 delete[] opt_param; | |
| 303 delete[] opt_param_position; | |
| 304 // Check that T0 now points to the null terminator in the array descriptor. | |
| 305 __ lw(T3, Address(T0)); | |
| 306 __ LoadImmediate(T4, reinterpret_cast<int32_t>(Object::null())); | |
| 307 __ beq(T3, T4, &all_arguments_processed); | |
| 308 } else { | |
| 309 ASSERT(num_opt_pos_params > 0); | |
| 310 __ lw(T2, | |
| 311 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); | |
| 312 __ SmiUntag(T2); | |
| 313 for (int i = 0; i < num_opt_pos_params; i++) { | |
| 314 Label next_parameter; | |
| 315 // Handle this optional positional parameter only if k or fewer positional | |
| 316 // arguments have been passed, where k is param_pos, the position of this | |
| 317 // optional parameter in the formal parameter list. | |
| 318 const int param_pos = num_fixed_params + i; | |
| 319 __ addiu(T3, T2, Immediate(-param_pos)); | |
| 320 __ bgtz(T3, &next_parameter); | |
| 321 // Load T3 with default argument. | |
| 322 const Object& value = Object::ZoneHandle( | |
| 323 parsed_function().default_parameter_values().At(i)); | |
| 324 __ LoadObject(T3, value); | |
| 325 // Assign T3 to fp[kFirstLocalSlotIndex - param_pos]. | |
| 326 // We do not use the final allocation index of the variable here, i.e. | |
| 327 // scope->VariableAt(i)->index(), because captured variables still need | |
| 328 // to be copied to the context that is not yet allocated. | |
| 329 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos; | |
| 330 __ sw(T3, Address(FP, computed_param_pos * kWordSize)); | |
| 331 __ Bind(&next_parameter); | |
| 332 } | |
| 333 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | |
| 334 __ SmiUntag(T1); | |
| 335 // Check that T2 equals T1, i.e. no named arguments passed. | |
| 336 __ beq(T2, T2, &all_arguments_processed); | |
| 337 } | |
| 338 | |
| 339 __ Bind(&wrong_num_arguments); | |
| 340 if (StackSize() != 0) { | |
| 341 // We need to unwind the space we reserved for locals and copied parameters. | |
| 342 // The NoSuchMethodFunction stub does not expect to see that area on the | |
| 343 // stack. | |
| 344 __ addiu(SP, SP, Immediate(StackSize() * kWordSize)); | |
| 345 } | |
| 346 // The call below has an empty stackmap because we have just | |
| 347 // dropped the spill slots. | |
| 348 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | |
| 349 | |
| 350 // Invoke noSuchMethod function passing the original name of the function. | |
| 351 // If the function is a closure function, use "call" as the original name. | |
| 352 const String& name = String::Handle( | |
| 353 function.IsClosureFunction() ? Symbols::Call().raw() : function.name()); | |
| 354 const int kNumArgsChecked = 1; | |
| 355 const ICData& ic_data = ICData::ZoneHandle( | |
| 356 ICData::New(function, name, Isolate::kNoDeoptId, kNumArgsChecked)); | |
| 357 __ LoadObject(S5, ic_data); | |
| 358 // FP - 4 : saved PP, object pool pointer of caller. | |
| 359 // FP + 0 : previous frame pointer. | |
| 360 // FP + 4 : return address. | |
| 361 // FP + 8 : PC marker, for easy identification of RawInstruction obj. | |
| 362 // FP + 12: last argument (arg n-1). | |
| 363 // SP + 0 : saved PP. | |
| 364 // SP + 16 + 4*(n-1) : first argument (arg 0). | |
| 365 // S5 : ic-data. | |
| 366 // S4 : arguments descriptor array. | |
| 367 __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel()); | |
| 368 if (is_optimizing()) { | |
| 369 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | |
| 370 empty_stack_bitmap, | |
| 371 0); // No registers. | |
| 372 } | |
| 373 // The noSuchMethod call may return. | |
| 374 __ LeaveDartFrame(); | |
| 375 __ Ret(); | |
| 376 | |
| 377 __ Bind(&all_arguments_processed); | |
| 378 // Nullify originally passed arguments only after they have been copied and | |
| 379 // checked, otherwise noSuchMethod would not see their original values. | |
| 380 // This step can be skipped in case we decide that formal parameters are | |
| 381 // implicitly final, since garbage collecting the unmodified value is not | |
| 382 // an issue anymore. | |
| 383 | |
| 384 // S4 : arguments descriptor array. | |
| 385 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | |
| 386 __ SmiUntag(T2); | |
| 387 | |
| 388 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); | |
| 389 Label null_args_loop, null_args_loop_condition; | |
| 390 __ b(&null_args_loop_condition); | |
| 391 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize)); | |
| 392 __ Bind(&null_args_loop); | |
| 393 __ sll(T3, T2, 2); | |
| 394 __ addu(T3, T1, T3); | |
| 395 __ sw(TMP, Address(T3)); | |
| 396 __ Bind(&null_args_loop_condition); | |
| 397 __ addiu(T2, T2, Immediate(-1)); | |
|
regis
2013/04/03 21:12:39
You could spare the instruction sll(T3, T2, 2) by
zra
2013/04/03 21:41:00
Done.
| |
| 398 __ bgez(T2, &null_args_loop); | |
| 171 } | 399 } |
| 172 | 400 |
| 173 | 401 |
| 174 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { | 402 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { |
| 175 UNIMPLEMENTED(); | 403 UNIMPLEMENTED(); |
| 176 } | 404 } |
| 177 | 405 |
| 178 | 406 |
| 179 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { | 407 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { |
| 180 UNIMPLEMENTED(); | 408 UNIMPLEMENTED(); |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 453 } | 681 } |
| 454 | 682 |
| 455 | 683 |
| 456 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 684 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
| 457 const ICData& ic_data, | 685 const ICData& ic_data, |
| 458 const Array& arguments_descriptor, | 686 const Array& arguments_descriptor, |
| 459 intptr_t argument_count, | 687 intptr_t argument_count, |
| 460 intptr_t deopt_id, | 688 intptr_t deopt_id, |
| 461 intptr_t token_pos, | 689 intptr_t token_pos, |
| 462 LocationSummary* locs) { | 690 LocationSummary* locs) { |
| 463 UNIMPLEMENTED(); | 691 __ LoadObject(S4, arguments_descriptor); |
| 692 __ LoadObject(S5, ic_data); | |
| 693 GenerateDartCall(deopt_id, | |
| 694 token_pos, | |
| 695 target_label, | |
| 696 PcDescriptors::kIcCall, | |
| 697 locs); | |
| 698 __ Drop(argument_count); | |
| 464 } | 699 } |
| 465 | 700 |
| 466 | 701 |
| 467 void FlowGraphCompiler::EmitMegamorphicInstanceCall( | 702 void FlowGraphCompiler::EmitMegamorphicInstanceCall( |
| 468 const ICData& ic_data, | 703 const ICData& ic_data, |
| 469 const Array& arguments_descriptor, | 704 const Array& arguments_descriptor, |
| 470 intptr_t argument_count, | 705 intptr_t argument_count, |
| 471 intptr_t deopt_id, | 706 intptr_t deopt_id, |
| 472 intptr_t token_pos, | 707 intptr_t token_pos, |
| 473 LocationSummary* locs) { | 708 LocationSummary* locs) { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 668 | 903 |
| 669 | 904 |
| 670 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 905 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 671 UNIMPLEMENTED(); | 906 UNIMPLEMENTED(); |
| 672 } | 907 } |
| 673 | 908 |
| 674 | 909 |
| 675 } // namespace dart | 910 } // namespace dart |
| 676 | 911 |
| 677 #endif // defined TARGET_ARCH_MIPS | 912 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |